]> git.mxchange.org Git - friendica.git/commitdiff
Merge pull request #11003 from annando/fix-api
authorHypolite Petovan <hypolite@mrpetovan.com>
Sun, 21 Nov 2021 12:55:25 +0000 (07:55 -0500)
committerGitHub <noreply@github.com>
Sun, 21 Nov 2021 12:55:25 +0000 (07:55 -0500)
Fix legacy API

include/api.php
src/Module/Api/ApiResponse.php
src/Module/Api/Friendica/Index.php
src/Module/BaseApi.php
tests/datasets/api.fixture.php
tests/legacy/ApiTest.php
tests/src/Module/Api/ApiResponseTest.php

index d1ff1458ed06f1cc64e49476d21c159f8ea17289..5d6fb2add03420551baa2645f16edd76a46e8054 100644 (file)
@@ -221,101 +221,11 @@ function api_call(App $a, App\Arguments $args = null)
                Logger::warning(API_LOG_PREFIX . 'not implemented', ['module' => 'api', 'action' => 'call', 'query' => DI::args()->getQueryString()]);
                throw new NotFoundException();
        } catch (HTTPException $e) {
+               Logger::notice(API_LOG_PREFIX . 'got exception', ['module' => 'api', 'action' => 'call', 'query' => DI::args()->getQueryString(), 'error' => $e]);
                DI::apiResponse()->error($e->getCode(), $e->getDescription(), $e->getMessage(), $type);
        }
 }
 
-/**
- * Set values for RSS template
- *
- * @param array $arr       Array to be passed to template
- * @param array $user_info User info
- * @return array
- * @throws BadRequestException
- * @throws ImagickException
- * @throws InternalServerErrorException
- * @throws UnauthorizedException
- * @todo  find proper type-hints
- */
-function api_rss_extra($arr, $user_info)
-{
-       if (is_null($user_info)) {
-               $uid = BaseApi::getCurrentUserID();
-               if (empty($uid)) {
-                       throw new ForbiddenException();
-               }
-
-               $user_info = DI::twitterUser()->createFromUserId($uid)->toArray();
-       }
-
-       $arr['$user'] = $user_info;
-       $arr['$rss'] = [
-               'alternate'    => $user_info['url'],
-               'self'         => DI::baseUrl() . "/" . DI::args()->getQueryString(),
-               'base'         => DI::baseUrl(),
-               'updated'      => DateTimeFormat::utc(null, DateTimeFormat::API),
-               'atom_updated' => DateTimeFormat::utcNow(DateTimeFormat::ATOM),
-               'language'     => $user_info['lang'],
-               'logo'         => DI::baseUrl() . "/images/friendica-32.png",
-       ];
-
-       return $arr;
-}
-
-
-/**
- * Unique contact to contact url.
- *
- * @param int $id Contact id
- * @return bool|string
- *                Contact url or False if contact id is unknown
- * @throws Exception
- */
-function api_unique_id_to_nurl($id)
-{
-       $r = DBA::selectFirst('contact', ['nurl'], ['id' => $id]);
-
-       if (DBA::isResult($r)) {
-               return $r["nurl"];
-       } else {
-               return false;
-       }
-}
-
-/**
- * return api-formatted array for item's author and owner
- *
- * @param App   $a    App
- * @param array $item item from db
- * @return array(array:author, array:owner)
- * @throws BadRequestException
- * @throws ImagickException
- * @throws InternalServerErrorException
- * @throws UnauthorizedException
- */
-function api_item_get_user(App $a, $item)
-{
-       if (empty($item['author-id'])) {
-               $item['author-id'] = Contact::getPublicIdByUserId(BaseApi::getCurrentUserID());
-       }
-       $status_user = DI::twitterUser()->createFromContactId($item['author-id'], BaseApi::getCurrentUserID())->toArray();
-
-       $author_user = $status_user;
-
-       $status_user["protected"] = isset($item['private']) && ($item['private'] == Item::PRIVATE);
-
-       if (($item['thr-parent'] ?? '') == ($item['uri'] ?? '')) {
-               if (empty($item['owner-id'])) {
-                       $item['owner-id'] = Contact::getPublicIdByUserId(BaseApi::getCurrentUserID());
-               }
-               $owner_user = DI::twitterUser()->createFromContactId($item['owner-id'], BaseApi::getCurrentUserID())->toArray();
-       } else {
-               $owner_user = $author_user;
-       }
-
-       return ([$status_user, $author_user, $owner_user]);
-}
-
 /**
  * TWITTER API
  */
@@ -337,6 +247,7 @@ function api_item_get_user(App $a, $item)
 function api_account_verify_credentials($type)
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
+       $uid = BaseApi::getCurrentUserID();
 
        unset($_REQUEST['user_id']);
        unset($_GET['user_id']);
@@ -346,7 +257,7 @@ function api_account_verify_credentials($type)
 
        $skip_status = $_REQUEST['skip_status'] ?? false;
 
-       $user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
+       $user_info = DI::twitterUser()->createFromUserId($uid, $skip_status)->toArray();
 
        // "verified" isn't used here in the standard
        unset($user_info["verified"]);
@@ -360,8 +271,8 @@ function api_account_verify_credentials($type)
        }
 
        // "uid" and "self" are only needed for some internal stuff, so remove it from here
-       unset($user_info["uid"]);
-       unset($user_info["self"]);
+       unset($user_info['uid']);
+       unset($user_info['self']);
 
        return DI::apiResponse()->formatData("user", $type, ['user' => $user_info]);
 }
@@ -400,17 +311,14 @@ function requestdata($k)
  */
 function api_statuses_mediap($type)
 {
-       $a = DI::app();
-
        BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
+       $uid = BaseApi::getCurrentUserID();
 
-       $user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
+       $a = DI::app();
 
-       $_REQUEST['profile_uid'] = BaseApi::getCurrentUserID();
+       $_REQUEST['profile_uid'] = $uid;
        $_REQUEST['api_source'] = true;
        $txt = requestdata('status') ?? '';
-       /// @TODO old-lost code?
-       //$txt = urldecode(requestdata('status'));
 
        if ((strpos($txt, '<') !== false) || (strpos($txt, '>') !== false)) {
                $txt = HTML::toBBCodeVideo($txt);
@@ -421,8 +329,6 @@ function api_statuses_mediap($type)
        }
        $txt = HTML::toBBCode($txt);
 
-       DI::args()->getArgv()[1] = $user_info['screen_name']; //should be set to username?
-
        $picture = wall_upload_post($a, false);
 
        // now that we have the img url in bbcode we can add it to the status and insert the wall item.
@@ -452,9 +358,10 @@ api_register_func('api/statuses/mediap', 'api_statuses_mediap', true, API_METHOD
  */
 function api_statuses_update($type)
 {
-       $a = DI::app();
-
        BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
+       $uid = BaseApi::getCurrentUserID();
+
+       $a = DI::app();
 
        // convert $_POST array items to the form we use for web posts.
        if (requestdata('htmlstatus')) {
@@ -492,7 +399,7 @@ function api_statuses_update($type)
        if (requestdata('lat') && requestdata('long')) {
                $_REQUEST['coord'] = sprintf("%s %s", requestdata('lat'), requestdata('long'));
        }
-       $_REQUEST['profile_uid'] = BaseApi::getCurrentUserID();
+       $_REQUEST['profile_uid'] = $uid;
 
        if (!$parent) {
                // Check for throttling (maximum posts per day, week and month)
@@ -500,11 +407,11 @@ function api_statuses_update($type)
                if ($throttle_day > 0) {
                        $datefrom = date(DateTimeFormat::MYSQL, time() - 24*60*60);
 
-                       $condition = ["`gravity` = ? AND `uid` = ? AND `wall` AND `received` > ?", GRAVITY_PARENT, BaseApi::getCurrentUserID(), $datefrom];
+                       $condition = ["`gravity` = ? AND `uid` = ? AND `wall` AND `received` > ?", GRAVITY_PARENT, $uid, $datefrom];
                        $posts_day = Post::count($condition);
 
                        if ($posts_day > $throttle_day) {
-                               logger::info('Daily posting limit reached for user '.BaseApi::getCurrentUserID());
+                               logger::info('Daily posting limit reached for user ' . $uid);
                                // die(api_error($type, DI::l10n()->t("Daily posting limit of %d posts reached. The post was rejected.", $throttle_day));
                                throw new TooManyRequestsException(DI::l10n()->tt("Daily posting limit of %d post reached. The post was rejected.", "Daily posting limit of %d posts reached. The post was rejected.", $throttle_day));
                        }
@@ -514,11 +421,11 @@ function api_statuses_update($type)
                if ($throttle_week > 0) {
                        $datefrom = date(DateTimeFormat::MYSQL, time() - 24*60*60*7);
 
-                       $condition = ["`gravity` = ? AND `uid` = ? AND `wall` AND `received` > ?", GRAVITY_PARENT, BaseApi::getCurrentUserID(), $datefrom];
+                       $condition = ["`gravity` = ? AND `uid` = ? AND `wall` AND `received` > ?", GRAVITY_PARENT, $uid, $datefrom];
                        $posts_week = Post::count($condition);
 
                        if ($posts_week > $throttle_week) {
-                               logger::info('Weekly posting limit reached for user '.BaseApi::getCurrentUserID());
+                               logger::info('Weekly posting limit reached for user ' . $uid);
                                // die(api_error($type, DI::l10n()->t("Weekly posting limit of %d posts reached. The post was rejected.", $throttle_week)));
                                throw new TooManyRequestsException(DI::l10n()->tt("Weekly posting limit of %d post reached. The post was rejected.", "Weekly posting limit of %d posts reached. The post was rejected.", $throttle_week));
                        }
@@ -528,11 +435,11 @@ function api_statuses_update($type)
                if ($throttle_month > 0) {
                        $datefrom = date(DateTimeFormat::MYSQL, time() - 24*60*60*30);
 
-                       $condition = ["`gravity` = ? AND `uid` = ? AND `wall` AND `received` > ?", GRAVITY_PARENT, BaseApi::getCurrentUserID(), $datefrom];
+                       $condition = ["`gravity` = ? AND `uid` = ? AND `wall` AND `received` > ?", GRAVITY_PARENT, $uid, $datefrom];
                        $posts_month = Post::count($condition);
 
                        if ($posts_month > $throttle_month) {
-                               logger::info('Monthly posting limit reached for user '.BaseApi::getCurrentUserID());
+                               logger::info('Monthly posting limit reached for user ' . $uid);
                                // die(api_error($type, DI::l10n()->t("Monthly posting limit of %d posts reached. The post was rejected.", $throttle_month));
                                throw new TooManyRequestsException(DI::l10n()->t("Monthly posting limit of %d post reached. The post was rejected.", "Monthly posting limit of %d posts reached. The post was rejected.", $throttle_month));
                        }
@@ -557,7 +464,7 @@ function api_statuses_update($type)
                        $media = DBA::toArray(DBA::p("SELECT `resource-id`, `scale`, `nickname`, `type`, `desc`, `filename`, `datasize`, `width`, `height` FROM `photo`
                                        INNER JOIN `user` ON `user`.`uid` = `photo`.`uid` WHERE `resource-id` IN
                                                (SELECT `resource-id` FROM `photo` WHERE `id` = ?) AND `photo`.`uid` = ?
-                                       ORDER BY `photo`.`width` DESC LIMIT 2", $id, BaseApi::getCurrentUserID()));
+                                       ORDER BY `photo`.`width` DESC LIMIT 2", $id, $uid));
 
                        if (!empty($media)) {
                                $ressources[] = $media[0]['resource-id'];
@@ -605,7 +512,7 @@ function api_statuses_update($type)
        if (!empty($ressources) && !empty($item_id)) {
                $item = Post::selectFirst(['uri-id', 'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid'], ['id' => $item_id]);
                foreach ($ressources as $ressource) {
-                       Photo::setPermissionForRessource($ressource, BaseApi::getCurrentUserID(), $item['allow_cid'], $item['allow_gid'], $item['deny_cid'], $item['deny_gid']);
+                       Photo::setPermissionForRessource($ressource, $uid, $item['allow_cid'], $item['allow_gid'], $item['deny_cid'], $item['deny_gid']);
                }
        }
 
@@ -630,8 +537,6 @@ api_register_func('api/statuses/update_with_media', 'api_statuses_update', true,
  */
 function api_media_upload()
 {
-       $a = DI::app();
-
        BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
 
        if (empty($_FILES['media'])) {
@@ -639,7 +544,7 @@ function api_media_upload()
                throw new BadRequestException("No media.");
        }
 
-       $media = wall_upload_post($a, false);
+       $media = wall_upload_post(DI::app(), false);
        if (!$media) {
                // Output error
                throw new InternalServerErrorException();
@@ -681,6 +586,7 @@ api_register_func('api/media/upload', 'api_media_upload', true, API_METHOD_POST)
 function api_media_metadata_create($type)
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
+       $uid = BaseApi::getCurrentUserID();
 
        $postdata = Network::postdata();
 
@@ -703,7 +609,7 @@ function api_media_metadata_create($type)
 
        Logger::info('Updating metadata', ['media_id' => $data['media_id']]);
 
-       $condition =  ['id' => $data['media_id'], 'uid' => BaseApi::getCurrentUserID()];
+       $condition = ['id' => $data['media_id'], 'uid' => $uid];
        $photo = DBA::selectFirst('photo', ['resource-id'], $condition);
        if (!DBA::isResult($photo)) {
                throw new BadRequestException("Metadata not found.");
@@ -787,8 +693,9 @@ function api_get_item(array $condition)
 function api_users_show($type)
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
+       $uid = BaseApi::getCurrentUserID();
 
-       $user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
+       $user_info = DI::twitterUser()->createFromUserId($uid)->toArray();
 
        $item = api_get_last_status($user_info['pid'], $user_info['uid']);
        if (!empty($item)) {
@@ -820,6 +727,9 @@ api_register_func('api/externalprofile/show', 'api_users_show');
  */
 function api_users_search($type)
 {
+       BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
+       $uid = BaseApi::getCurrentUserID();
+
        $userlist = [];
 
        if (!empty($_GET['q'])) {
@@ -837,7 +747,7 @@ function api_users_search($type)
                if (DBA::isResult($contacts)) {
                        $k = 0;
                        foreach ($contacts as $contact) {
-                               $user_info = DI::twitterUser()->createFromContactId($contact['id'], BaseApi::getCurrentUserID())->toArray();
+                               $user_info = DI::twitterUser()->createFromContactId($contact['id'], $uid)->toArray();
 
                                if ($type == 'xml') {
                                        $userlist[$k++ . ':user'] = $user_info;
@@ -875,15 +785,15 @@ api_register_func('api/users/search', 'api_users_search');
  */
 function api_users_lookup($type)
 {
+       BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
+       $uid = BaseApi::getCurrentUserID();
+
        $users = [];
 
        if (!empty($_REQUEST['user_id'])) {
-               foreach (explode(',', $_REQUEST['user_id']) as $id) {
-                       if (!empty($id)) {
-                               $cid = BaseApi::getContactIDForSearchterm($id);
-                               if (!empty($cid)) {
-                                       $users[] = DI::twitterUser()->createFromContactId($cid, BaseApi::getCurrentUserID())->toArray();
-                               }
+               foreach (explode(',', $_REQUEST['user_id']) as $cid) {
+                       if (!empty($cid) && is_numeric($cid)) {
+                               $users[] = DI::twitterUser()->createFromContactId((int)$cid, $uid)->toArray();
                        }
                }
        }
@@ -915,8 +825,7 @@ api_register_func('api/users/lookup', 'api_users_lookup', true);
 function api_search($type)
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
-
-       $user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
+       $uid = BaseApi::getCurrentUserID();
 
        if (empty($_REQUEST['q'])) {
                throw new BadRequestException('q parameter is required.');
@@ -943,7 +852,7 @@ function api_search($type)
        $params = ['order' => ['id' => true], 'limit' => [$start, $count]];
        if (preg_match('/^#(\w+)$/', $searchTerm, $matches) === 1 && isset($matches[1])) {
                $searchTerm = $matches[1];
-               $condition = ["`iid` > ? AND `name` = ? AND (NOT `private` OR (`private` AND `uid` = ?))", $since_id, $searchTerm, BaseApi::getCurrentUserID()];
+               $condition = ["`iid` > ? AND `name` = ? AND (NOT `private` OR (`private` AND `uid` = ?))", $since_id, $searchTerm, $uid];
                $tags = DBA::select('tag-search-view', ['uri-id'], $condition);
                $uriids = [];
                while ($tag = DBA::fetch($tags)) {
@@ -966,7 +875,7 @@ function api_search($type)
                        " . ($exclude_replies ? " AND `gravity` = " . GRAVITY_PARENT : ' ') . "
                        AND (`uid` = 0 OR (`uid` = ? AND NOT `global`))
                        AND `body` LIKE CONCAT('%',?,'%')",
-                       $since_id, BaseApi::getCurrentUserID(), $_REQUEST['q']];
+                       $since_id, $uid, $_REQUEST['q']];
                if ($max_id > 0) {
                        $condition[0] .= ' AND `id` <= ?';
                        $condition[] = $max_id;
@@ -976,7 +885,7 @@ function api_search($type)
        $statuses = [];
 
        if (parse_url($searchTerm, PHP_URL_SCHEME) != '') {
-               $id = Item::fetchByLink($searchTerm, BaseApi::getCurrentUserID());
+               $id = Item::fetchByLink($searchTerm, $uid);
                if (!$id) {
                        // Public post
                        $id = Item::fetchByLink($searchTerm);
@@ -987,11 +896,15 @@ function api_search($type)
                }
        }
 
-       $statuses = $statuses ?: Post::selectForUser(BaseApi::getCurrentUserID(), [], $condition, $params);
+       $statuses = $statuses ?: Post::selectForUser($uid, [], $condition, $params);
 
-       $data['status'] = api_format_items(Post::toArray($statuses), $user_info);
+       $ret = [];
+       while ($status = DBA::fetch($statuses)) {
+               $ret[] = api_format_item($status, $type);
+       }
+       DBA::close($statuses);
 
-       bindComments($data['status']);
+       $data['status'] = $ret;
 
        return DI::apiResponse()->formatData('statuses', $type, $data);
 }
@@ -1019,8 +932,7 @@ api_register_func('api/search', 'api_search', true);
 function api_statuses_home_timeline($type)
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
-
-       $user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
+       $uid = BaseApi::getCurrentUserID();
 
        unset($_REQUEST['user_id']);
        unset($_GET['user_id']);
@@ -1041,7 +953,7 @@ function api_statuses_home_timeline($type)
        $start = max(0, ($page - 1) * $count);
 
        $condition = ["`uid` = ? AND `gravity` IN (?, ?) AND `id` > ?",
-               BaseApi::getCurrentUserID(), GRAVITY_PARENT, GRAVITY_COMMENT, $since_id];
+               $uid, GRAVITY_PARENT, GRAVITY_COMMENT, $since_id];
 
        if ($max_id > 0) {
                $condition[0] .= " AND `id` <= ?";
@@ -1057,17 +969,15 @@ function api_statuses_home_timeline($type)
        }
 
        $params = ['order' => ['id' => true], 'limit' => [$start, $count]];
-       $statuses = Post::selectForUser(BaseApi::getCurrentUserID(), [], $condition, $params);
+       $statuses = Post::selectForUser($uid, [], $condition, $params);
 
-       $items = Post::toArray($statuses);
-
-       $ret = api_format_items($items, $user_info, false, $type);
-
-       // Set all posts from the query above to seen
+       $ret = [];
        $idarray = [];
-       foreach ($items as $item) {
-               $idarray[] = intval($item["id"]);
+       while ($status = DBA::fetch($statuses)) {
+               $ret[] = api_format_item($status, $type);
+               $idarray[] = intval($status['id']);
        }
+       DBA::close($statuses);
 
        if (!empty($idarray)) {
                $unseen = Post::exists(['unseen' => true, 'id' => $idarray]);
@@ -1076,18 +986,7 @@ function api_statuses_home_timeline($type)
                }
        }
 
-       bindComments($ret);
-
-       $data = ['status' => $ret];
-       switch ($type) {
-               case "atom":
-                       break;
-               case "rss":
-                       $data = api_rss_extra($data, $user_info);
-                       break;
-       }
-
-       return DI::apiResponse()->formatData("statuses", $type, $data);
+       return DI::apiResponse()->formatData("statuses", $type, ['status' => $ret], Contact::getPublicIdByUserId($uid));
 }
 
 
@@ -1110,8 +1009,7 @@ api_register_func('api/statuses/friends_timeline', 'api_statuses_home_timeline',
 function api_statuses_public_timeline($type)
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
-
-       $user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
+       $uid = BaseApi::getCurrentUserID();
 
        // get last network messages
 
@@ -1135,9 +1033,7 @@ function api_statuses_public_timeline($type)
                }
 
                $params = ['order' => ['id' => true], 'limit' => [$start, $count]];
-               $statuses = Post::selectForUser(BaseApi::getCurrentUserID(), [], $condition, $params);
-
-               $r = Post::toArray($statuses);
+               $statuses = Post::selectForUser($uid, [], $condition, $params);
        } else {
                $condition = ["`gravity` IN (?, ?) AND `id` > ? AND `private` = ? AND `wall` AND `origin` AND NOT `author-hidden`",
                        GRAVITY_PARENT, GRAVITY_COMMENT, $since_id, Item::PUBLIC];
@@ -1152,25 +1048,16 @@ function api_statuses_public_timeline($type)
                }
 
                $params = ['order' => ['id' => true], 'limit' => [$start, $count]];
-               $statuses = Post::selectForUser(BaseApi::getCurrentUserID(), [], $condition, $params);
-
-               $r = Post::toArray($statuses);
+               $statuses = Post::selectForUser($uid, [], $condition, $params);
        }
 
-       $ret = api_format_items($r, $user_info, false, $type);
-
-       bindComments($ret);
-
-       $data = ['status' => $ret];
-       switch ($type) {
-               case "atom":
-                       break;
-               case "rss":
-                       $data = api_rss_extra($data, $user_info);
-                       break;
+       $ret = [];
+       while ($status = DBA::fetch($statuses)) {
+               $ret[] = api_format_item($status, $type);
        }
+       DBA::close($statuses);
 
-       return DI::apiResponse()->formatData("statuses", $type, $data);
+       return DI::apiResponse()->formatData("statuses", $type, ['status' => $ret], Contact::getPublicIdByUserId($uid));
 }
 
 /// @TODO move to top of file or somewhere better
@@ -1190,11 +1077,10 @@ api_register_func('api/statuses/public_timeline', 'api_statuses_public_timeline'
 function api_statuses_networkpublic_timeline($type)
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
+       $uid = BaseApi::getCurrentUserID();
 
-       $user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
-
-       $since_id        = $_REQUEST['since_id'] ?? 0;
-       $max_id          = $_REQUEST['max_id'] ?? 0;
+       $since_id = $_REQUEST['since_id'] ?? 0;
+       $max_id   = $_REQUEST['max_id'] ?? 0;
 
        // pagination
        $count = $_REQUEST['count'] ?? 20;
@@ -1211,22 +1097,15 @@ function api_statuses_networkpublic_timeline($type)
        }
 
        $params = ['order' => ['id' => true], 'limit' => [$start, $count]];
-       $statuses = Post::toArray(Post::selectForUser(BaseApi::getCurrentUserID(), Item::DISPLAY_FIELDLIST, $condition, $params));
-
-       $ret = api_format_items($statuses, $user_info, false, $type);
-
-       bindComments($ret);
+       $statuses = Post::selectForUser($uid, Item::DISPLAY_FIELDLIST, $condition, $params);
 
-       $data = ['status' => $ret];
-       switch ($type) {
-               case "atom":
-                       break;
-               case "rss":
-                       $data = api_rss_extra($data, $user_info);
-                       break;
+       $ret = [];
+       while ($status = DBA::fetch($statuses)) {
+               $ret[] = api_format_item($status, $type);
        }
+       DBA::close($statuses);
 
-       return DI::apiResponse()->formatData("statuses", $type, $data);
+       return DI::apiResponse()->formatData("statuses", $type, ['status' => $ret], Contact::getPublicIdByUserId($uid));
 }
 
 /// @TODO move to top of file or somewhere better
@@ -1248,8 +1127,7 @@ api_register_func('api/statuses/networkpublic_timeline', 'api_statuses_networkpu
 function api_statuses_show($type)
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
-
-       $user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
+       $uid = BaseApi::getCurrentUserID();
 
        // params
        $id = intval(DI::args()->getArgv()[3] ?? 0);
@@ -1273,7 +1151,7 @@ function api_statuses_show($type)
                throw new BadRequestException(sprintf("There is no status with the id %d", $id));
        }
 
-       $item = Post::selectFirst(['id'], ['uri-id' => $uri_item['uri-id'], 'uid' => [0, BaseApi::getCurrentUserID()]], ['order' => ['uid' => true]]);
+       $item = Post::selectFirst(['id'], ['uri-id' => $uri_item['uri-id'], 'uid' => [0, $uid]], ['order' => ['uid' => true]]);
        if (!DBA::isResult($item)) {
                throw new BadRequestException(sprintf("There is no status with the uri-id %d for the given user.", $uri_item['uri-id']));
        }
@@ -1288,14 +1166,18 @@ function api_statuses_show($type)
                $params = [];
        }
 
-       $statuses = Post::selectForUser(BaseApi::getCurrentUserID(), [], $condition, $params);
+       $statuses = Post::selectForUser($uid, [], $condition, $params);
 
        /// @TODO How about copying this to above methods which don't check $r ?
        if (!DBA::isResult($statuses)) {
                throw new BadRequestException(sprintf("There is no status or conversation with the id %d.", $id));
        }
 
-       $ret = api_format_items(Post::toArray($statuses), $user_info, false, $type);
+       $ret = [];
+       while ($status = DBA::fetch($statuses)) {
+               $ret[] = api_format_item($status, $type);
+       }
+       DBA::close($statuses);
 
        if ($conversation) {
                $data = ['status' => $ret];
@@ -1324,8 +1206,7 @@ api_register_func('api/statuses/show', 'api_statuses_show', true);
 function api_conversation_show($type)
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
-
-       $user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
+       $uid = BaseApi::getCurrentUserID();
 
        // params
        $id       = intval(DI::args()->getArgv()[3]           ?? 0);
@@ -1353,7 +1234,7 @@ function api_conversation_show($type)
                throw new BadRequestException("There is no status with the id $id.");
        }
 
-       $parent = Post::selectFirst(['id'], ['uri-id' => $item['parent-uri-id'], 'uid' => [0, BaseApi::getCurrentUserID()]], ['order' => ['uid' => true]]);
+       $parent = Post::selectFirst(['id'], ['uri-id' => $item['parent-uri-id'], 'uid' => [0, $uid]], ['order' => ['uid' => true]]);
        if (!DBA::isResult($parent)) {
                throw new BadRequestException("There is no status with this id.");
        }
@@ -1361,7 +1242,7 @@ function api_conversation_show($type)
        $id = $parent['id'];
 
        $condition = ["`parent` = ? AND `uid` IN (0, ?) AND `gravity` IN (?, ?) AND `id` > ?",
-               $id, BaseApi::getCurrentUserID(), GRAVITY_PARENT, GRAVITY_COMMENT, $since_id];
+               $id, $uid, GRAVITY_PARENT, GRAVITY_COMMENT, $since_id];
 
        if ($max_id > 0) {
                $condition[0] .= " AND `id` <= ?";
@@ -1369,13 +1250,17 @@ function api_conversation_show($type)
        }
 
        $params = ['order' => ['id' => true], 'limit' => [$start, $count]];
-       $statuses = Post::selectForUser(BaseApi::getCurrentUserID(), [], $condition, $params);
+       $statuses = Post::selectForUser($uid, [], $condition, $params);
 
        if (!DBA::isResult($statuses)) {
                throw new BadRequestException("There is no status with id $id.");
        }
 
-       $ret = api_format_items(Post::toArray($statuses), $user_info, false, $type);
+       $ret = [];
+       while ($status = DBA::fetch($statuses)) {
+               $ret[] = api_format_item($status, $type);
+       }
+       DBA::close($statuses);
 
        $data = ['status' => $ret];
        return DI::apiResponse()->formatData("statuses", $type, $data);
@@ -1400,9 +1285,8 @@ api_register_func('api/statusnet/conversation', 'api_conversation_show', true);
  */
 function api_statuses_repeat($type)
 {
-       $a = DI::app();
-
        BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
+       $uid = BaseApi::getCurrentUserID();
 
        // params
        $id = intval(DI::args()->getArgv()[3] ?? 0);
@@ -1423,7 +1307,7 @@ function api_statuses_repeat($type)
 
        if (DBA::isResult($item) && !empty($item['body'])) {
                if (in_array($item['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::TWITTER])) {
-                       if (!Item::performActivity($id, 'announce', BaseApi::getCurrentUserID())) {
+                       if (!Item::performActivity($id, 'announce', $uid)) {
                                throw new InternalServerErrorException();
                        }
 
@@ -1443,14 +1327,14 @@ function api_statuses_repeat($type)
                                $post .= "[/share]";
                        }
                        $_REQUEST['body'] = $post;
-                       $_REQUEST['profile_uid'] = BaseApi::getCurrentUserID();
+                       $_REQUEST['profile_uid'] = $uid;
                        $_REQUEST['api_source'] = true;
 
                        if (empty($_REQUEST['source'])) {
                                $_REQUEST['source'] = api_source();
                        }
 
-                       $item_id = item_post($a);
+                       $item_id = item_post(DI::app());
                }
        } else {
                throw new ForbiddenException();
@@ -1479,6 +1363,7 @@ api_register_func('api/statuses/retweet', 'api_statuses_repeat', true, API_METHO
 function api_statuses_destroy($type)
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
+       $uid = BaseApi::getCurrentUserID();
 
        // params
        $id = intval(DI::args()->getArgv()[3] ?? 0);
@@ -1496,7 +1381,7 @@ function api_statuses_destroy($type)
 
        $ret = api_statuses_show($type);
 
-       Item::deleteForUser(['id' => $id], BaseApi::getCurrentUserID());
+       Item::deleteForUser(['id' => $id], $uid);
 
        return $ret;
 }
@@ -1520,8 +1405,7 @@ api_register_func('api/statuses/destroy', 'api_statuses_destroy', true, API_METH
 function api_statuses_mentions($type)
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
-
-       $user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
+       $uid = BaseApi::getCurrentUserID();
 
        unset($_REQUEST['user_id']);
        unset($_GET['user_id']);
@@ -1545,11 +1429,11 @@ function api_statuses_mentions($type)
 
        $condition = [
                GRAVITY_PARENT, GRAVITY_COMMENT,
-               BaseApi::getCurrentUserID(),
+               $uid,
                Post\UserNotification::TYPE_EXPLICIT_TAGGED | Post\UserNotification::TYPE_IMPLICIT_TAGGED |
                Post\UserNotification::TYPE_THREAD_COMMENT | Post\UserNotification::TYPE_DIRECT_COMMENT |
                Post\UserNotification::TYPE_DIRECT_THREAD_COMMENT,
-               BaseApi::getCurrentUserID(), $since_id,
+               $uid, $since_id,
        ];
 
        if ($max_id > 0) {
@@ -1560,20 +1444,15 @@ function api_statuses_mentions($type)
        array_unshift($condition, $query);
 
        $params = ['order' => ['id' => true], 'limit' => [$start, $count]];
-       $statuses = Post::selectForUser(BaseApi::getCurrentUserID(), [], $condition, $params);
-
-       $ret = api_format_items(Post::toArray($statuses), $user_info, false, $type);
+       $statuses = Post::selectForUser($uid, [], $condition, $params);
 
-       $data = ['status' => $ret];
-       switch ($type) {
-               case "atom":
-                       break;
-               case "rss":
-                       $data = api_rss_extra($data, $user_info);
-                       break;
+       $ret = [];
+       while ($status = DBA::fetch($statuses)) {
+               $ret[] = api_format_item($status, $type);
        }
+       DBA::close($statuses);
 
-       return DI::apiResponse()->formatData("statuses", $type, $data);
+       return DI::apiResponse()->formatData("statuses", $type, ['status' => $ret], Contact::getPublicIdByUserId($uid));
 }
 
 /// @TODO move to top of file or somewhere better
@@ -1595,11 +1474,11 @@ api_register_func('api/statuses/replies', 'api_statuses_mentions', true);
 function api_statuses_user_timeline($type)
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
+       $uid = BaseApi::getCurrentUserID();
 
-       $user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
-
-       Logger::info('api_statuses_user_timeline', ['api_user' => BaseApi::getCurrentUserID(), 'user_info' => $user_info, '_REQUEST' => $_REQUEST]);
+       Logger::info('api_statuses_user_timeline', ['api_user' => $uid, '_REQUEST' => $_REQUEST]);
 
+       $cid             = BaseApi::getContactIDForSearchterm($_REQUEST['screen_name'] ?? '', $_REQUEST['user_id'] ?? 0, $uid);
        $since_id        = $_REQUEST['since_id'] ?? 0;
        $max_id          = $_REQUEST['max_id'] ?? 0;
        $exclude_replies = !empty($_REQUEST['exclude_replies']);
@@ -1611,12 +1490,8 @@ function api_statuses_user_timeline($type)
 
        $start = max(0, ($page - 1) * $count);
 
-       $condition = ["`uid` = ? AND `gravity` IN (?, ?) AND `id` > ? AND `contact-id` = ?",
-               BaseApi::getCurrentUserID(), GRAVITY_PARENT, GRAVITY_COMMENT, $since_id, $user_info['cid']];
-
-       if ($user_info['self'] == 1) {
-               $condition[0] .= ' AND `wall` ';
-       }
+       $condition = ["(`uid` = ? OR (`uid` = ? AND NOT `global`)) AND `gravity` IN (?, ?) AND `id` > ? AND `author-id` = ?",
+               0, $uid, GRAVITY_PARENT, GRAVITY_COMMENT, $since_id, $cid];
 
        if ($exclude_replies) {
                $condition[0] .= ' AND `gravity` = ?';
@@ -1633,22 +1508,15 @@ function api_statuses_user_timeline($type)
                $condition[] = $max_id;
        }
        $params = ['order' => ['id' => true], 'limit' => [$start, $count]];
-       $statuses = Post::selectForUser(BaseApi::getCurrentUserID(), [], $condition, $params);
+       $statuses = Post::selectForUser($uid, [], $condition, $params);
 
-       $ret = api_format_items(Post::toArray($statuses), $user_info, true, $type);
-
-       bindComments($ret);
-
-       $data = ['status' => $ret];
-       switch ($type) {
-               case "atom":
-                       break;
-               case "rss":
-                       $data = api_rss_extra($data, $user_info);
-                       break;
+       $ret = [];
+       while ($status = DBA::fetch($statuses)) {
+               $ret[] = api_format_item($status, $type);
        }
+       DBA::close($statuses);
 
-       return DI::apiResponse()->formatData("statuses", $type, $data);
+       return DI::apiResponse()->formatData("statuses", $type, ['status' => $ret], Contact::getPublicIdByUserId($uid));
 }
 
 /// @TODO move to top of file or somewhere better
@@ -1671,6 +1539,7 @@ api_register_func('api/statuses/user_timeline', 'api_statuses_user_timeline', tr
 function api_favorites_create_destroy($type)
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
+       $uid = BaseApi::getCurrentUserID();
 
        // for versioned api.
        /// @TODO We need a better global soluton
@@ -1689,7 +1558,7 @@ function api_favorites_create_destroy($type)
                $itemid = intval($_REQUEST['id'] ?? 0);
        }
 
-       $item = Post::selectFirstForUser(BaseApi::getCurrentUserID(), [], ['id' => $itemid, 'uid' => BaseApi::getCurrentUserID()]);
+       $item = Post::selectFirstForUser($uid, [], ['id' => $itemid, 'uid' => $uid]);
 
        if (!DBA::isResult($item)) {
                throw new BadRequestException("Invalid item.");
@@ -1712,20 +1581,9 @@ function api_favorites_create_destroy($type)
                throw new InternalServerErrorException("DB error");
        }
 
-       $user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
-       $rets = api_format_items([$item], $user_info, false, $type);
-       $ret = $rets[0];
+       $ret = api_format_item($item, $type);
 
-       $data = ['status' => $ret];
-       switch ($type) {
-               case "atom":
-                       break;
-               case "rss":
-                       $data = api_rss_extra($data, $user_info);
-                       break;
-       }
-
-       return DI::apiResponse()->formatData("status", $type, $data);
+       return DI::apiResponse()->formatData("status", $type, ['status' => $ret], Contact::getPublicIdByUserId($uid));
 }
 
 /// @TODO move to top of file or somewhere better
@@ -1747,51 +1605,39 @@ api_register_func('api/favorites/destroy', 'api_favorites_create_destroy', true,
 function api_favorites($type)
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
-
-       $user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
+       $uid = BaseApi::getCurrentUserID();
 
        // in friendica starred item are private
        // return favorites only for self
-       Logger::info(API_LOG_PREFIX . 'for {self}', ['module' => 'api', 'action' => 'favorites', 'self' => $user_info['self']]);
-
-       if ($user_info['self'] == 0) {
-               $ret = [];
-       } else {
-               // params
-               $since_id = $_REQUEST['since_id'] ?? 0;
-               $max_id = $_REQUEST['max_id'] ?? 0;
-               $count = $_GET['count'] ?? 20;
-               $page = $_REQUEST['page'] ?? 1;
-
-               $start = max(0, ($page - 1) * $count);
+       Logger::info(API_LOG_PREFIX . 'for {self}', ['module' => 'api', 'action' => 'favorites']);
 
-               $condition = ["`uid` = ? AND `gravity` IN (?, ?) AND `id` > ? AND `starred`",
-                       BaseApi::getCurrentUserID(), GRAVITY_PARENT, GRAVITY_COMMENT, $since_id];
+       // params
+       $since_id = $_REQUEST['since_id'] ?? 0;
+       $max_id = $_REQUEST['max_id'] ?? 0;
+       $count = $_GET['count'] ?? 20;
+       $page = $_REQUEST['page'] ?? 1;
 
-               $params = ['order' => ['id' => true], 'limit' => [$start, $count]];
+       $start = max(0, ($page - 1) * $count);
 
-               if ($max_id > 0) {
-                       $condition[0] .= " AND `id` <= ?";
-                       $condition[] = $max_id;
-               }
+       $condition = ["`uid` = ? AND `gravity` IN (?, ?) AND `id` > ? AND `starred`",
+               $uid, GRAVITY_PARENT, GRAVITY_COMMENT, $since_id];
 
-               $statuses = Post::selectForUser(BaseApi::getCurrentUserID(), [], $condition, $params);
+       $params = ['order' => ['id' => true], 'limit' => [$start, $count]];
 
-               $ret = api_format_items(Post::toArray($statuses), $user_info, false, $type);
+       if ($max_id > 0) {
+               $condition[0] .= " AND `id` <= ?";
+               $condition[] = $max_id;
        }
 
-       bindComments($ret);
+       $statuses = Post::selectForUser($uid, [], $condition, $params);
 
-       $data = ['status' => $ret];
-       switch ($type) {
-               case "atom":
-                       break;
-               case "rss":
-                       $data = api_rss_extra($data, $user_info);
-                       break;
+       $ret = [];
+       while ($status = DBA::fetch($statuses)) {
+               $ret[] = api_format_item($status, $type);
        }
+       DBA::close($statuses);
 
-       return DI::apiResponse()->formatData("statuses", $type, $data);
+       return DI::apiResponse()->formatData("statuses", $type, ['status' => $ret], Contact::getPublicIdByUserId($uid));
 }
 
 /// @TODO move to top of file or somewhere better
@@ -2230,7 +2076,7 @@ function api_format_items_activities($item, $type = "json")
                //builtin_activity_puller($i, $activities);
 
                // get user data and add it to the array of the activity
-               $user = DI::twitterUser()->createFromContactId($parent_item['author-id'], BaseApi::getCurrentUserID())->toArray();
+               $user = DI::twitterUser()->createFromContactId($parent_item['author-id'], $item['uid'])->toArray();
                switch ($parent_item['verb']) {
                        case Activity::LIKE:
                                $activities['like'][] = $user;
@@ -2274,45 +2120,6 @@ function api_format_items_activities($item, $type = "json")
        return $activities;
 }
 
-/**
- * format items to be returned by api
- *
- * @param array  $items       array of items
- * @param array  $user_info
- * @param bool   $filter_user filter items by $user_info
- * @param string $type        Return type (atom, rss, xml, json)
- * @return array
- * @throws BadRequestException
- * @throws ImagickException
- * @throws InternalServerErrorException
- * @throws UnauthorizedException
- */
-function api_format_items($items, $user_info, $filter_user = false, $type = "json")
-{
-       $a = DI::app();
-
-       $ret = [];
-
-       if (empty($items)) {
-               return $ret;
-       }
-
-       foreach ((array)$items as $item) {
-               [$status_user, $author_user, $owner_user] = api_item_get_user($a, $item);
-
-               // Look if the posts are matching if they should be filtered by user id
-               if ($filter_user && ($status_user["id"] != $user_info["id"])) {
-                       continue;
-               }
-
-               $status = api_format_item($item, $type, $status_user, $author_user, $owner_user);
-
-               $ret[] = $status;
-       }
-
-       return $ret;
-}
-
 /**
  * @param array  $item       Item record
  * @param string $type       Return format (atom, rss, xml, json)
@@ -2325,13 +2132,10 @@ function api_format_items($items, $user_info, $filter_user = false, $type = "jso
  * @throws InternalServerErrorException
  * @throws UnauthorizedException
  */
-function api_format_item($item, $type = "json", $status_user = null, $author_user = null, $owner_user = null)
+function api_format_item($item, $type = "json")
 {
-       $a = DI::app();
-
-       if (empty($status_user) || empty($author_user) || empty($owner_user)) {
-               [$status_user, $author_user, $owner_user] = api_item_get_user($a, $item);
-       }
+       $author_user = DI::twitterUser()->createFromContactId($item['author-id'], $item['uid'])->toArray();
+       $owner_user = DI::twitterUser()->createFromContactId($item['owner-id'], $item['uid'])->toArray();
 
        DI::contentItem()->localize($item);
 
@@ -2359,7 +2163,7 @@ function api_format_item($item, $type = "json", $status_user = null, $author_use
                'in_reply_to_screen_name' => $in_reply_to['screen_name'],
                $geo => null,
                'favorited' => $item['starred'] ? true : false,
-               'user' =>  $status_user,
+               'user' =>  $author_user,
                'friendica_author' => $author_user,
                'friendica_owner' => $owner_user,
                'friendica_private' => $item['private'] == Item::PRIVATE,
@@ -2369,7 +2173,8 @@ function api_format_item($item, $type = "json", $status_user = null, $author_use
                'external_url' => DI::baseUrl() . "/display/" . $item['guid'],
                'friendica_activities' => api_format_items_activities($item, $type),
                'friendica_title' => $item['title'],
-               'friendica_html' => BBCode::convertForUriId($item['uri-id'], $item['body'], BBCode::EXTERNAL)
+               'friendica_html' => BBCode::convertForUriId($item['uri-id'], $item['body'], BBCode::EXTERNAL),
+               'friendica_comments' => Post::countPosts(['thr-parent-id' => $item['uri-id'], 'deleted' => false, 'gravity' => GRAVITY_COMMENT])
        ];
 
        if (count($converted["attachments"]) > 0) {
@@ -2394,7 +2199,7 @@ function api_format_item($item, $type = "json", $status_user = null, $author_use
                if (!empty($announce)) {
                        $retweeted_item = $item;
                        $item = $announce;
-                       $status['friendica_owner'] = DI::twitterUser()->createFromContactId($announce['author-id'], BaseApi::getCurrentUserID())->toArray();
+                       $status['friendica_owner'] = DI::twitterUser()->createFromContactId($announce['author-id'], $item['uid'])->toArray();
                }
        }
 
@@ -2413,7 +2218,7 @@ function api_format_item($item, $type = "json", $status_user = null, $author_use
                        $quoted_status['text'] = $conv_quoted['text'];
                        $quoted_status['statusnet_html'] = $conv_quoted['html'];
                        try {
-                               $quoted_status["user"] = DI::twitterUser()->createFromContactId($quoted_item['author-id'], BaseApi::getCurrentUserID())->toArray();
+                               $quoted_status["user"] = DI::twitterUser()->createFromContactId($quoted_item['author-id'], $item['uid'])->toArray();
                        } catch (BadRequestException $e) {
                                // user not found. should be found?
                                /// @todo check if the user should be always found
@@ -2435,7 +2240,7 @@ function api_format_item($item, $type = "json", $status_user = null, $author_use
                unset($retweeted_status['statusnet_conversation_id']);
                $status['user'] = $status['friendica_owner'];
                try {
-                       $retweeted_status["user"] = DI::twitterUser()->createFromContactId($retweeted_item['author-id'], BaseApi::getCurrentUserID())->toArray();
+                       $retweeted_status["user"] = DI::twitterUser()->createFromContactId($retweeted_item['author-id'], $item['uid'])->toArray();
                } catch (BadRequestException $e) {
                        // user not found. should be found?
                        /// @todo check if the user should be always found
@@ -2464,8 +2269,8 @@ function api_format_item($item, $type = "json", $status_user = null, $author_use
        }
 
        // "uid" and "self" are only needed for some internal stuff, so remove it from here
-       unset($status["user"]["uid"]);
-       unset($status["user"]["self"]);
+       unset($status["user"]['uid']);
+       unset($status["user"]['self']);
 
        if ($item["coord"] != "") {
                $coords = explode(' ', $item["coord"]);
@@ -2518,10 +2323,10 @@ api_register_func('api/lists/subscriptions', 'api_lists_list', true);
 function api_lists_ownerships($type)
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
+       $uid = BaseApi::getCurrentUserID();
 
        // params
-       $user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
-       $uid = $user_info['uid'];
+       $user_info = DI::twitterUser()->createFromUserId($uid)->toArray();
 
        $groups = DBA::select('group', [], ['deleted' => 0, 'uid' => $uid]);
 
@@ -2563,8 +2368,7 @@ api_register_func('api/lists/ownerships', 'api_lists_ownerships', true);
 function api_lists_statuses($type)
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
-
-       $user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
+       $uid = BaseApi::getCurrentUserID();
 
        unset($_REQUEST['user_id']);
        unset($_GET['user_id']);
@@ -2588,7 +2392,7 @@ function api_lists_statuses($type)
 
        $groups = DBA::selectToArray('group_member', ['contact-id'], ['gid' => 1]);
        $gids = array_column($groups, 'contact-id');
-       $condition = ['uid' => BaseApi::getCurrentUserID(), 'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT], 'group-id' => $gids];
+       $condition = ['uid' => $uid, 'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT], 'group-id' => $gids];
        $condition = DBA::mergeConditions($condition, ["`id` > ?", $since_id]);
 
        if ($max_id > 0) {
@@ -2605,20 +2409,15 @@ function api_lists_statuses($type)
        }
 
        $params = ['order' => ['id' => true], 'limit' => [$start, $count]];
-       $statuses = Post::selectForUser(BaseApi::getCurrentUserID(), [], $condition, $params);
-
-       $items = api_format_items(Post::toArray($statuses), $user_info, false, $type);
+       $statuses = Post::selectForUser($uid, [], $condition, $params);
 
-       $data = ['status' => $items];
-       switch ($type) {
-               case "atom":
-                       break;
-               case "rss":
-                       $data = api_rss_extra($data, $user_info);
-                       break;
+       $items = [];
+       while ($status = DBA::fetch($statuses)) {
+               $items[] = api_format_item($status, $type);
        }
+       DBA::close($statuses);
 
-       return DI::apiResponse()->formatData("statuses", $type, $data);
+       return DI::apiResponse()->formatData("statuses", $type, ['status' => $items], Contact::getPublicIdByUserId($uid));
 }
 
 /// @TODO move to top of file or somewhere better
@@ -2641,6 +2440,7 @@ api_register_func('api/lists/statuses', 'api_lists_statuses', true);
 function api_statuses_f($qtype)
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
+       $uid = BaseApi::getCurrentUserID();
 
        // pagination
        $count = $_GET['count'] ?? 20;
@@ -2648,7 +2448,7 @@ function api_statuses_f($qtype)
 
        $start = max(0, ($page - 1) * $count);
 
-       $user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
+       $user_info = DI::twitterUser()->createFromUserId($uid)->toArray();
 
        if (!empty($_GET['cursor']) && $_GET['cursor'] == 'undefined') {
                /* this is to stop Hotot to load friends multiple times
@@ -2668,11 +2468,6 @@ function api_statuses_f($qtype)
                $sql_extra = sprintf(" AND ( `rel` = %d OR `rel` = %d ) ", intval(Contact::FOLLOWER), intval(Contact::FRIEND));
        }
 
-       // friends and followers only for self
-       if ($user_info['self'] == 0) {
-               $sql_extra = " AND false ";
-       }
-
        if ($qtype == 'blocks') {
                $sql_filter = 'AND `blocked` AND NOT `pending`';
        } elseif ($qtype == 'incoming') {
@@ -2691,17 +2486,17 @@ function api_statuses_f($qtype)
                $sql_extra
                ORDER BY `nick`
                LIMIT ?, ?",
-               BaseApi::getCurrentUserID(),
+               $uid,
                $start,
                $count
        ));
 
        $ret = [];
        foreach ($r as $cid) {
-               $user = DI::twitterUser()->createFromContactId($cid['id'], BaseApi::getCurrentUserID())->toArray();
+               $user = DI::twitterUser()->createFromContactId($cid['id'], $uid)->toArray();
                // "uid" and "self" are only needed for some internal stuff, so remove it from here
-               unset($user["uid"]);
-               unset($user["self"]);
+               unset($user['uid']);
+               unset($user['self']);
 
                if ($user) {
                        $ret[] = $user;
@@ -2823,7 +2618,6 @@ api_register_func('api/friendships/incoming', 'api_friendships_incoming', true);
 function api_direct_messages_new($type)
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
-
        $uid = BaseApi::getCurrentUserID();
 
        if (empty($_POST["text"]) || empty($_POST['screen_name']) && empty($_POST['user_id'])) {
@@ -2832,29 +2626,14 @@ function api_direct_messages_new($type)
 
        $sender = DI::twitterUser()->createFromUserId($uid)->toArray();
 
-       $recipient = null;
-       if (!empty($_POST['screen_name'])) {
-               $contacts = Contact::selectToArray(['id', 'nurl', 'network'], ['uid' => BaseApi::getCurrentUserID(), 'nick' => $_POST['screen_name']]);
-               if (DBA::isResult($contacts)) {
-                       // Selecting the id by priority, friendica first
-                       api_best_nickname($contacts);
-
-                       $recipient = DI::twitterUser()->createFromContactId($contacts[0]['id'], $uid)->toArray();
-               }
-       } else {
-               $cid = BaseApi::getContactIDForSearchterm($_POST['user_id']);
-               if (!empty($cid)) {
-                       $recipient = DI::twitterUser()->createFromContactId($cid, $uid)->toArray();
-               }
-       }
-
-       if (empty($recipient)) {
+       $cid = BaseApi::getContactIDForSearchterm($_POST['screen_name'] ?? '', $_POST['user_id'] ?? 0, $uid);
+       if (empty($cid)) {
                throw new NotFoundException('Recipient not found');
        }
 
        $replyto = '';
        if (!empty($_REQUEST['replyto'])) {
-               $mail = DBA::selectFirst('mail', ['parent-uri', 'title'], ['uid' => BaseApi::getCurrentUserID(), 'id' => $_REQUEST['replyto']]);
+               $mail    = DBA::selectFirst('mail', ['parent-uri', 'title'], ['uid' => $uid, 'id' => $_REQUEST['replyto']]);
                $replyto = $mail['parent-uri'];
                $sub     = $mail['title'];
        } else {
@@ -2865,26 +2644,18 @@ function api_direct_messages_new($type)
                }
        }
 
-       $id = Mail::send($recipient['cid'], $_POST['text'], $sub, $replyto);
+       $cdata = Contact::getPublicAndUserContactID($cid, $uid);
+
+       $id = Mail::send($cdata['user'], $_POST['text'], $sub, $replyto);
 
        if ($id > -1) {
                $mail = DBA::selectFirst('mail', [], ['id' => $id]);
-               $ret = api_format_messages($mail, $recipient, $sender);
+               $ret = api_format_messages($mail, DI::twitterUser()->createFromContactId($cid, $uid)->toArray(), $sender);
        } else {
                $ret = ["error" => $id];
        }
 
-       $data = ['direct_message'=>$ret];
-
-       switch ($type) {
-               case "atom":
-                       break;
-               case "rss":
-                       $data = api_rss_extra($data, $sender);
-                       break;
-       }
-
-       return DI::apiResponse()->formatData("direct-messages", $type, $data);
+       return DI::apiResponse()->formatData("direct-messages", $type, ['direct_message' => $ret], Contact::getPublicIdByUserId($uid));
 }
 
 /// @TODO move to top of file or somewhere better
@@ -2905,9 +2676,8 @@ api_register_func('api/direct_messages/new', 'api_direct_messages_new', true, AP
 function api_direct_messages_destroy($type)
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
+       $uid = BaseApi::getCurrentUserID();
 
-       // params
-       $user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
        //required
        $id = $_REQUEST['id'] ?? 0;
        // optional
@@ -2915,7 +2685,6 @@ function api_direct_messages_destroy($type)
        $verbose = (!empty($_GET['friendica_verbose']) ? strtolower($_GET['friendica_verbose']) : "false");
        /// @todo optional parameter 'include_entities' from Twitter API not yet implemented
 
-       $uid = $user_info['uid'];
        // error if no id or parenturi specified (for clients posting parent-uri as well)
        if ($verbose == "true" && ($id == 0 || $parenturi == "")) {
                $answer = ['result' => 'error', 'message' => 'message id or parenturi not specified'];
@@ -3053,6 +2822,7 @@ api_register_func('api/friendships/destroy', 'api_friendships_destroy', true, AP
 function api_direct_messages_box($type, $box, $verbose)
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
+       $uid = BaseApi::getCurrentUserID();
 
        // params
        $count = $_GET['count'] ?? 20;
@@ -3071,7 +2841,7 @@ function api_direct_messages_box($type, $box, $verbose)
        unset($_REQUEST['screen_name']);
        unset($_GET['screen_name']);
 
-       $user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
+       $user_info = DI::twitterUser()->createFromUserId($uid)->toArray();
 
        $profile_url = $user_info["url"];
 
@@ -3103,7 +2873,7 @@ function api_direct_messages_box($type, $box, $verbose)
 
        $r = DBA::toArray(DBA::p(
                "SELECT `mail`.*, `contact`.`nurl` AS `contact-url` FROM `mail`,`contact` WHERE `mail`.`contact-id` = `contact`.`id` AND `mail`.`uid` = ? AND $sql_extra AND `mail`.`id` > ? ORDER BY `mail`.`id` DESC LIMIT ?,?",
-               BaseApi::getCurrentUserID(),
+               $uid,
                $since_id,
                $start,
                $count
@@ -3117,9 +2887,9 @@ function api_direct_messages_box($type, $box, $verbose)
        foreach ($r as $item) {
                if ($box == "inbox" || $item['from-url'] != $profile_url) {
                        $recipient = $user_info;
-                       $sender = DI::twitterUser()->createFromContactId($item['contact-id'], BaseApi::getCurrentUserID())->toArray();
+                       $sender = DI::twitterUser()->createFromContactId($item['contact-id'], $uid)->toArray();
                } elseif ($box == "sentbox" || $item['from-url'] == $profile_url) {
-                       $recipient = DI::twitterUser()->createFromContactId($item['contact-id'], BaseApi::getCurrentUserID())->toArray();
+                       $recipient = DI::twitterUser()->createFromContactId($item['contact-id'], $uid)->toArray();
                        $sender = $user_info;
                }
 
@@ -3128,17 +2898,7 @@ function api_direct_messages_box($type, $box, $verbose)
                }
        }
 
-
-       $data = ['direct_message' => $ret];
-       switch ($type) {
-               case "atom":
-                       break;
-               case "rss":
-                       $data = api_rss_extra($data, $user_info);
-                       break;
-       }
-
-       return DI::apiResponse()->formatData("direct-messages", $type, $data);
+       return DI::apiResponse()->formatData("direct-messages", $type, ['direct_message' => $ret], Contact::getPublicIdByUserId($uid));
 }
 
 /**
@@ -3218,12 +2978,13 @@ api_register_func('api/direct_messages', 'api_direct_messages_inbox', true);
 function api_fr_photos_list($type)
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
+       $uid = BaseApi::getCurrentUserID();
 
        $r = DBA::toArray(DBA::p(
                "SELECT `resource-id`, MAX(scale) AS `scale`, `album`, `filename`, `type`, MAX(`created`) AS `created`,
                MAX(`edited`) AS `edited`, MAX(`desc`) AS `desc` FROM `photo`
                WHERE `uid` = ? AND NOT `photo-type` IN (?, ?) GROUP BY `resource-id`, `album`, `filename`, `type`",
-               BaseApi::getCurrentUserID(), Photo::CONTACT_AVATAR, Photo::CONTACT_BANNER
+               $uid, Photo::CONTACT_AVATAR, Photo::CONTACT_BANNER
        ));
        $typetoext = [
                'image/jpeg' => 'jpg',
@@ -3268,6 +3029,7 @@ function api_fr_photos_list($type)
 function api_fr_photo_create_update($type)
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
+       $uid = BaseApi::getCurrentUserID();
 
        // input params
        $photo_id  = $_REQUEST['photo_id']  ?? null;
@@ -3301,24 +3063,24 @@ function api_fr_photo_create_update($type)
                $mode = "update";
 
                // check if photo is existing in databasei
-               if (!Photo::exists(['resource-id' => $photo_id, 'uid' => BaseApi::getCurrentUserID(), 'album' => $album])) {
+               if (!Photo::exists(['resource-id' => $photo_id, 'uid' => $uid, 'album' => $album])) {
                        throw new BadRequestException("photo not available");
                }
        }
 
        // checks on acl strings provided by clients
        $acl_input_error = false;
-       $acl_input_error |= check_acl_input($allow_cid);
-       $acl_input_error |= check_acl_input($deny_cid);
-       $acl_input_error |= check_acl_input($allow_gid);
-       $acl_input_error |= check_acl_input($deny_gid);
+       $acl_input_error |= check_acl_input($allow_cid, $uid);
+       $acl_input_error |= check_acl_input($deny_cid, $uid);
+       $acl_input_error |= check_acl_input($allow_gid, $uid);
+       $acl_input_error |= check_acl_input($deny_gid, $uid);
        if ($acl_input_error) {
                throw new BadRequestException("acl data invalid");
        }
        // now let's upload the new media in create-mode
        if ($mode == "create") {
                $media = $_FILES['media'];
-               $data = save_media_to_database("photo", $media, $type, $album, trim($allow_cid), trim($deny_cid), trim($allow_gid), trim($deny_gid), $desc, Photo::DEFAULT, $visibility);
+               $data = save_media_to_database("photo", $media, $type, $album, trim($allow_cid), trim($deny_cid), trim($allow_gid), trim($deny_gid), $desc, Photo::DEFAULT, $visibility, null, $uid);
 
                // return success of updating or error message
                if (!is_null($data)) {
@@ -3363,7 +3125,7 @@ function api_fr_photo_create_update($type)
                $result = false;
                if (count($updated_fields) > 0) {
                        $nothingtodo = false;
-                       $result = Photo::update($updated_fields, ['uid' => BaseApi::getCurrentUserID(), 'resource-id' => $photo_id, 'album' => $album]);
+                       $result = Photo::update($updated_fields, ['uid' => $uid, 'resource-id' => $photo_id, 'album' => $album]);
                } else {
                        $nothingtodo = true;
                }
@@ -3371,7 +3133,7 @@ function api_fr_photo_create_update($type)
                if (!empty($_FILES['media'])) {
                        $nothingtodo = false;
                        $media = $_FILES['media'];
-                       $data = save_media_to_database("photo", $media, $type, $album, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $desc, Photo::DEFAULT, $visibility, $photo_id);
+                       $data = save_media_to_database("photo", $media, $type, $album, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $desc, Photo::DEFAULT, $visibility, $photo_id, $uid);
                        if (!is_null($data)) {
                                return DI::apiResponse()->formatData("photo_update", $type, $data);
                        }
@@ -3436,6 +3198,7 @@ function api_fr_photo_detail($type)
 function api_account_update_profile_image($type)
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
+       $uid = BaseApi::getCurrentUserID();
 
        // input params
        $profile_id = $_REQUEST['profile_id'] ?? 0;
@@ -3447,7 +3210,7 @@ function api_account_update_profile_image($type)
 
        // check if specified profile id is valid
        if ($profile_id != 0) {
-               $profile = DBA::selectFirst('profile', ['is-default'], ['uid' => BaseApi::getCurrentUserID(), 'id' => $profile_id]);
+               $profile = DBA::selectFirst('profile', ['is-default'], ['uid' => $uid, 'id' => $profile_id]);
                // error message if specified profile id is not in database
                if (!DBA::isResult($profile)) {
                        throw new BadRequestException("profile_id not available");
@@ -3465,7 +3228,7 @@ function api_account_update_profile_image($type)
                $media = $_FILES['media'];
        }
        // save new profile image
-       $data = save_media_to_database("profileimage", $media, $type, DI::l10n()->t(Photo::PROFILE_PHOTOS), "", "", "", "", "", Photo::USER_AVATAR);
+       $data = save_media_to_database("profileimage", $media, $type, DI::l10n()->t(Photo::PROFILE_PHOTOS), "", "", "", "", "", Photo::USER_AVATAR, false, null, $uid);
 
        // get filetype
        if (is_array($media['type'])) {
@@ -3483,18 +3246,18 @@ function api_account_update_profile_image($type)
 
        // change specified profile or all profiles to the new resource-id
        if ($is_default_profile) {
-               $condition = ["`profile` AND `resource-id` != ? AND `uid` = ?", $data['photo']['id'], BaseApi::getCurrentUserID()];
+               $condition = ["`profile` AND `resource-id` != ? AND `uid` = ?", $data['photo']['id'], $uid];
                Photo::update(['profile' => false, 'photo-type' => Photo::DEFAULT], $condition);
        } else {
                $fields = ['photo' => DI::baseUrl() . '/photo/' . $data['photo']['id'] . '-4.' . $fileext,
                        'thumb' => DI::baseUrl() . '/photo/' . $data['photo']['id'] . '-5.' . $fileext];
-               DBA::update('profile', $fields, ['id' => $_REQUEST['profile'], 'uid' => BaseApi::getCurrentUserID()]);
+               DBA::update('profile', $fields, ['id' => $_REQUEST['profile'], 'uid' => $uid]);
        }
 
-       Contact::updateSelfFromUserID(BaseApi::getCurrentUserID(), true);
+       Contact::updateSelfFromUserID($uid, true);
 
        // Update global directory in background
-       Profile::publishUpdate(BaseApi::getCurrentUserID());
+       Profile::publishUpdate($uid);
 
        // output for client
        if ($data) {
@@ -3527,25 +3290,24 @@ api_register_func('api/account/update_profile_image', 'api_account_update_profil
 function api_account_update_profile($type)
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
+       $uid = BaseApi::getCurrentUserID();
 
-       $local_user = BaseApi::getCurrentUserID();
-
-       $api_user = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
+       $api_user = DI::twitterUser()->createFromUserId($uid)->toArray();
 
        if (!empty($_POST['name'])) {
-               DBA::update('profile', ['name' => $_POST['name']], ['uid' => $local_user]);
-               DBA::update('user', ['username' => $_POST['name']], ['uid' => $local_user]);
-               Contact::update(['name' => $_POST['name']], ['uid' => $local_user, 'self' => 1]);
+               DBA::update('profile', ['name' => $_POST['name']], ['uid' => $uid]);
+               DBA::update('user', ['username' => $_POST['name']], ['uid' => $uid]);
+               Contact::update(['name' => $_POST['name']], ['uid' => $uid, 'self' => 1]);
                Contact::update(['name' => $_POST['name']], ['id' => $api_user['id']]);
        }
 
        if (isset($_POST['description'])) {
-               DBA::update('profile', ['about' => $_POST['description']], ['uid' => $local_user]);
-               Contact::update(['about' => $_POST['description']], ['uid' => $local_user, 'self' => 1]);
+               DBA::update('profile', ['about' => $_POST['description']], ['uid' => $uid]);
+               Contact::update(['about' => $_POST['description']], ['uid' => $uid, 'self' => 1]);
                Contact::update(['about' => $_POST['description']], ['id' => $api_user['id']]);
        }
 
-       Profile::publishUpdate($local_user);
+       Profile::publishUpdate($uid);
 
        return api_account_verify_credentials($type);
 }
@@ -3556,10 +3318,11 @@ api_register_func('api/account/update_profile', 'api_account_update_profile', tr
 /**
  *
  * @param string $acl_string
+ * @param int    $uid
  * @return bool
  * @throws Exception
  */
-function check_acl_input($acl_string)
+function check_acl_input($acl_string, $uid)
 {
        if (empty($acl_string)) {
                return false;
@@ -3575,7 +3338,7 @@ function check_acl_input($acl_string)
        foreach ($cid_array as $cid) {
                $cid = str_replace("<", "", $cid);
                $cid = str_replace(">", "", $cid);
-               $condition = ['id' => $cid, 'uid' => BaseApi::getCurrentUserID()];
+               $condition = ['id' => $cid, 'uid' => $uid];
                $contact_not_found |= !DBA::exists('contact', $condition);
        }
        return $contact_not_found;
@@ -3594,6 +3357,7 @@ function check_acl_input($acl_string)
  * @param integer $phototype
  * @param boolean $visibility
  * @param string  $photo_id
+ * @param int     $uid
  * @return array
  * @throws BadRequestException
  * @throws ForbiddenException
@@ -3602,7 +3366,7 @@ function check_acl_input($acl_string)
  * @throws NotFoundException
  * @throws UnauthorizedException
  */
-function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $desc, $phototype = 0, $visibility = false, $photo_id = null)
+function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $desc, $phototype, $visibility, $photo_id, $uid)
 {
        $visitor   = 0;
        $src = "";
@@ -3677,13 +3441,13 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $
                // upload normal image (scales 0, 1, 2)
                logger::info("photo upload: starting new photo upload");
 
-               $r = Photo::store($Image, BaseApi::getCurrentUserID(), $visitor, $resource_id, $filename, $album, 0, Photo::DEFAULT, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc);
+               $r = Photo::store($Image, $uid, $visitor, $resource_id, $filename, $album, 0, Photo::DEFAULT, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc);
                if (!$r) {
                        logger::notice("photo upload: image upload with scale 0 (original size) failed");
                }
                if ($width > 640 || $height > 640) {
                        $Image->scaleDown(640);
-                       $r = Photo::store($Image, BaseApi::getCurrentUserID(), $visitor, $resource_id, $filename, $album, 1, Photo::DEFAULT, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc);
+                       $r = Photo::store($Image, $uid, $visitor, $resource_id, $filename, $album, 1, Photo::DEFAULT, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc);
                        if (!$r) {
                                logger::notice("photo upload: image upload with scale 1 (640x640) failed");
                        }
@@ -3691,7 +3455,7 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $
 
                if ($width > 320 || $height > 320) {
                        $Image->scaleDown(320);
-                       $r = Photo::store($Image, BaseApi::getCurrentUserID(), $visitor, $resource_id, $filename, $album, 2, Photo::DEFAULT, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc);
+                       $r = Photo::store($Image, $uid, $visitor, $resource_id, $filename, $album, 2, Photo::DEFAULT, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc);
                        if (!$r) {
                                logger::notice("photo upload: image upload with scale 2 (320x320) failed");
                        }
@@ -3703,7 +3467,7 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $
 
                if ($width > 300 || $height > 300) {
                        $Image->scaleDown(300);
-                       $r = Photo::store($Image, BaseApi::getCurrentUserID(), $visitor, $resource_id, $filename, $album, 4, $phototype, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc);
+                       $r = Photo::store($Image, $uid, $visitor, $resource_id, $filename, $album, 4, $phototype, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc);
                        if (!$r) {
                                logger::notice("photo upload: profile image upload with scale 4 (300x300) failed");
                        }
@@ -3711,7 +3475,7 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $
 
                if ($width > 80 || $height > 80) {
                        $Image->scaleDown(80);
-                       $r = Photo::store($Image, BaseApi::getCurrentUserID(), $visitor, $resource_id, $filename, $album, 5, $phototype, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc);
+                       $r = Photo::store($Image, $uid, $visitor, $resource_id, $filename, $album, 5, $phototype, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc);
                        if (!$r) {
                                logger::notice("photo upload: profile image upload with scale 5 (80x80) failed");
                        }
@@ -3719,7 +3483,7 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $
 
                if ($width > 48 || $height > 48) {
                        $Image->scaleDown(48);
-                       $r = Photo::store($Image, BaseApi::getCurrentUserID(), $visitor, $resource_id, $filename, $album, 6, $phototype, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc);
+                       $r = Photo::store($Image, $uid, $visitor, $resource_id, $filename, $album, 6, $phototype, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc);
                        if (!$r) {
                                logger::notice("photo upload: profile image upload with scale 6 (48x48) failed");
                        }
@@ -3731,7 +3495,7 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $
        if (!empty($r)) {
                // create entry in 'item'-table on new uploads to enable users to comment/like/dislike the photo
                if ($photo_id == null && $mediatype == "photo") {
-                       post_photo_item($resource_id, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $filetype, $visibility);
+                       post_photo_item($resource_id, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $filetype, $visibility, $uid);
                }
                // on success return image data in json/xml format (like /api/friendica/photo does when no scale is given)
                return prepare_photo_data($type, false, $resource_id);
@@ -3749,17 +3513,18 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $
  * @param string  $deny_gid
  * @param string  $filetype
  * @param boolean $visibility
+ * @param int     $uid
  * @throws InternalServerErrorException
  */
-function post_photo_item($hash, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $filetype, $visibility = false)
+function post_photo_item($hash, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $filetype, $visibility, $uid)
 {
        // get data about the api authenticated user
-       $uri = Item::newURI(intval(BaseApi::getCurrentUserID()));
-       $owner_record = DBA::selectFirst('contact', [], ['uid' => BaseApi::getCurrentUserID(), 'self' => true]);
+       $uri = Item::newURI(intval($uid));
+       $owner_record = DBA::selectFirst('contact', [], ['uid' => $uid, 'self' => true]);
 
        $arr = [];
        $arr['guid']          = System::createUUID();
-       $arr['uid']           = intval(BaseApi::getCurrentUserID());
+       $arr['uid']           = intval($uid);
        $arr['uri']           = $uri;
        $arr['type']          = 'photo';
        $arr['wall']          = 1;
@@ -3811,8 +3576,7 @@ function post_photo_item($hash, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $f
 function prepare_photo_data($type, $scale, $photo_id)
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
-
-       $user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
+       $uid = BaseApi::getCurrentUserID();
 
        $scale_sql = ($scale === false ? "" : sprintf("AND scale=%d", intval($scale)));
        $data_sql = ($scale === false ? "" : "data, ");
@@ -3826,7 +3590,7 @@ function prepare_photo_data($type, $scale, $photo_id)
                        FROM `photo` WHERE `uid` = ? AND `resource-id` = ? $scale_sql GROUP BY
                                   `resource-id`, `created`, `edited`, `title`, `desc`, `album`, `filename`,
                                   `type`, `height`, `width`, `datasize`, `profile`, `allow_cid`, `deny_cid`, `allow_gid`, `deny_gid`",
-               BaseApi::getCurrentUserID(),
+               $uid,
                $photo_id
        ));
 
@@ -3869,7 +3633,7 @@ function prepare_photo_data($type, $scale, $photo_id)
        }
 
        // retrieve item element for getting activities (like, dislike etc.) related to photo
-       $condition = ['uid' => BaseApi::getCurrentUserID(), 'resource-id' => $photo_id];
+       $condition = ['uid' => $uid, 'resource-id' => $photo_id];
        $item = Post::selectFirst(['id', 'uid', 'uri', 'parent', 'allow_cid', 'deny_cid', 'allow_gid', 'deny_gid'], $condition);
        if (!DBA::isResult($item)) {
                throw new NotFoundException('Photo-related item not found.');
@@ -3879,12 +3643,17 @@ function prepare_photo_data($type, $scale, $photo_id)
 
        // retrieve comments on photo
        $condition = ["`parent` = ? AND `uid` = ? AND `gravity` IN (?, ?)",
-               $item['parent'], BaseApi::getCurrentUserID(), GRAVITY_PARENT, GRAVITY_COMMENT];
+               $item['parent'], $uid, GRAVITY_PARENT, GRAVITY_COMMENT];
 
-       $statuses = Post::selectForUser(BaseApi::getCurrentUserID(), [], $condition);
+       $statuses = Post::selectForUser($uid, [], $condition);
 
        // prepare output of comments
-       $commentData = api_format_items(Post::toArray($statuses), $user_info, false, $type);
+       $commentData = [];
+       while ($status = DBA::fetch($statuses)) {
+               $commentData[] = api_format_item($status, $type);
+       }
+       DBA::close($statuses);
+
        $comments = [];
        if ($type == "xml") {
                $k = 0;
@@ -3958,7 +3727,7 @@ function api_in_reply_to($item)
        $in_reply_to['user_id_str'] = null;
        $in_reply_to['screen_name'] = null;
 
-       if (($item['thr-parent'] != $item['uri']) && ($item['gravity'] != GRAVITY_PARENT)) {
+       if (!empty($item['thr-parent']) && ($item['thr-parent'] != $item['uri']) && ($item['gravity'] != GRAVITY_PARENT)) {
                $parent = Post::selectFirst(['id'], ['uid' => $item['uid'], 'uri' => $item['thr-parent']]);
                if (DBA::isResult($parent)) {
                        $in_reply_to['status_id'] = intval($parent['id']);
@@ -4019,74 +3788,6 @@ function api_clean_plain_items($text)
        return $text;
 }
 
-/**
- *
- * @param array $contacts
- *
- * @return void
- */
-function api_best_nickname(&$contacts)
-{
-       $best_contact = [];
-
-       if (count($contacts) == 0) {
-               return;
-       }
-
-       foreach ($contacts as $contact) {
-               if ($contact["network"] == "") {
-                       $contact["network"] = "dfrn";
-                       $best_contact = [$contact];
-               }
-       }
-
-       if (sizeof($best_contact) == 0) {
-               foreach ($contacts as $contact) {
-                       if ($contact["network"] == "dfrn") {
-                               $best_contact = [$contact];
-                       }
-               }
-       }
-
-       if (sizeof($best_contact) == 0) {
-               foreach ($contacts as $contact) {
-                       if ($contact["network"] == "dspr") {
-                               $best_contact = [$contact];
-                       }
-               }
-       }
-
-       if (sizeof($best_contact) == 0) {
-               foreach ($contacts as $contact) {
-                       if ($contact["network"] == "stat") {
-                               $best_contact = [$contact];
-                       }
-               }
-       }
-
-       if (sizeof($best_contact) == 0) {
-               foreach ($contacts as $contact) {
-                       if ($contact["network"] == "pump") {
-                               $best_contact = [$contact];
-                       }
-               }
-       }
-
-       if (sizeof($best_contact) == 0) {
-               foreach ($contacts as $contact) {
-                       if ($contact["network"] == "twit") {
-                               $best_contact = [$contact];
-                       }
-               }
-       }
-
-       if (sizeof($best_contact) == 1) {
-               $contacts = $best_contact;
-       } else {
-               $contacts = [$contacts[0]];
-       }
-}
-
 /**
  * Return all or a specified group of the user with the containing contacts.
  *
@@ -4102,11 +3803,10 @@ function api_best_nickname(&$contacts)
 function api_friendica_group_show($type)
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
+       $uid = BaseApi::getCurrentUserID();
 
        // params
-       $user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
        $gid = $_REQUEST['gid'] ?? 0;
-       $uid = $user_info['uid'];
 
        // get data of the specified group id or all groups if not specified
        if ($gid != 0) {
@@ -4130,13 +3830,13 @@ function api_friendica_group_show($type)
                        $user_element = "users";
                        $k = 0;
                        foreach ($members as $member) {
-                               $user = DI::twitterUser()->createFromContactId($member['contact-id'], BaseApi::getCurrentUserID())->toArray();
+                               $user = DI::twitterUser()->createFromContactId($member['contact-id'], $uid)->toArray();
                                $users[$k++.":user"] = $user;
                        }
                } else {
                        $user_element = "user";
                        foreach ($members as $member) {
-                               $user = DI::twitterUser()->createFromContactId($member['contact-id'], BaseApi::getCurrentUserID())->toArray();
+                               $user = DI::twitterUser()->createFromContactId($member['contact-id'], $uid)->toArray();
                                $users[] = $user;
                        }
                }
@@ -4163,11 +3863,10 @@ api_register_func('api/friendica/group_show', 'api_friendica_group_show', true);
 function api_lists_destroy($type)
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
+       $uid = BaseApi::getCurrentUserID();
 
        // params
-       $user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
        $gid = $_REQUEST['list_id'] ?? 0;
-       $uid = $user_info['uid'];
 
        // error if no gid specified
        if ($gid == 0) {
@@ -4186,7 +3885,7 @@ function api_lists_destroy($type)
                        'name' => $group['name'],
                        'id' => intval($gid),
                        'id_str' => (string) $gid,
-                       'user' => $user_info
+                       'user' => DI::twitterUser()->createFromUserId($uid)->toArray()
                ];
 
                return DI::apiResponse()->formatData("lists", $type, ['lists' => $list]);
@@ -4264,11 +3963,10 @@ function group_create($name, $uid, $users = [])
 function api_friendica_group_create($type)
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
+       $uid = BaseApi::getCurrentUserID();
 
        // params
-       $user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
        $name = $_REQUEST['name'] ?? '';
-       $uid = $user_info['uid'];
        $json = json_decode($_POST['json'], true);
        $users = $json['user'];
 
@@ -4295,11 +3993,10 @@ api_register_func('api/friendica/group_create', 'api_friendica_group_create', tr
 function api_lists_create($type)
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
+       $uid = BaseApi::getCurrentUserID();
 
        // params
-       $user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
        $name = $_REQUEST['name'] ?? '';
-       $uid = $user_info['uid'];
 
        $success = group_create($name, $uid);
        if ($success['success']) {
@@ -4307,7 +4004,7 @@ function api_lists_create($type)
                        'name' => $success['name'],
                        'id' => intval($success['gid']),
                        'id_str' => (string) $success['gid'],
-                       'user' => $user_info
+                       'user' => DI::twitterUser()->createFromUserId($uid)->toArray()
                ];
 
                return DI::apiResponse()->formatData("lists", $type, ['lists' => $grp]);
@@ -4331,10 +4028,9 @@ api_register_func('api/lists/create', 'api_lists_create', true, API_METHOD_POST)
 function api_friendica_group_update($type)
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
+       $uid = BaseApi::getCurrentUserID();
 
        // params
-       $user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
-       $uid = $user_info['uid'];
        $gid = $_REQUEST['gid'] ?? 0;
        $name = $_REQUEST['name'] ?? '';
        $json = json_decode($_POST['json'], true);
@@ -4401,12 +4097,11 @@ api_register_func('api/friendica/group_update', 'api_friendica_group_update', tr
 function api_lists_update($type)
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
+       $uid = BaseApi::getCurrentUserID();
 
        // params
-       $user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
        $gid = $_REQUEST['list_id'] ?? 0;
        $name = $_REQUEST['name'] ?? '';
-       $uid = $user_info['uid'];
 
        // error if no gid specified
        if ($gid == 0) {
@@ -4425,7 +4120,7 @@ function api_lists_update($type)
                        'name' => $name,
                        'id' => intval($gid),
                        'id_str' => (string) $gid,
-                       'user' => $user_info
+                       'user' => DI::twitterUser()->createFromUserId($uid)->toArray()
                ];
 
                return DI::apiResponse()->formatData("lists", $type, ['lists' => $list]);
@@ -4450,8 +4145,7 @@ api_register_func('api/lists/update', 'api_lists_update', true, API_METHOD_POST)
 function api_friendica_notification_seen($type)
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
-
-       $user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
+       $uid = BaseApi::getCurrentUserID();
 
        if (DI::args()->getArgc() !== 4) {
                throw new BadRequestException('Invalid argument count');
@@ -4461,7 +4155,7 @@ function api_friendica_notification_seen($type)
 
        try {
                $Notify = DI::notify()->selectOneById($id);
-               if ($Notify->uid !== BaseApi::getCurrentUserID()) {
+               if ($Notify->uid !== $uid) {
                        throw new NotFoundException();
                }
 
@@ -4473,10 +4167,10 @@ function api_friendica_notification_seen($type)
                DI::notify()->save($Notify);
 
                if ($Notify->otype === Notification\ObjectType::ITEM) {
-                       $item = Post::selectFirstForUser(BaseApi::getCurrentUserID(), [], ['id' => $Notify->iid, 'uid' => BaseApi::getCurrentUserID()]);
+                       $item = Post::selectFirstForUser($uid, [], ['id' => $Notify->iid, 'uid' => $uid]);
                        if (DBA::isResult($item)) {
                                // we found the item, return it to the user
-                               $ret  = api_format_items([$item], $user_info, false, $type);
+                               $ret = [api_format_item($item, $type)];
                                $data = ['status' => $ret];
                                return DI::apiResponse()->formatData('status', $type, $data);
                        }
@@ -4511,11 +4205,11 @@ api_register_func('api/friendica/notification/seen', 'api_friendica_notification
 function api_friendica_direct_messages_search($type, $box = "")
 {
        BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
+       $uid = BaseApi::getCurrentUserID();
 
        // params
-       $user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
+       $user_info = DI::twitterUser()->createFromUserId($uid)->toArray();
        $searchstring = $_REQUEST['searchstring'] ?? '';
-       $uid = $user_info['uid'];
 
        // error if no searchstring specified
        if ($searchstring == "") {
@@ -4542,9 +4236,9 @@ function api_friendica_direct_messages_search($type, $box = "")
                foreach ($r as $item) {
                        if ($box == "inbox" || $item['from-url'] != $profile_url) {
                                $recipient = $user_info;
-                               $sender = DI::twitterUser()->createFromContactId($item['contact-id'], BaseApi::getCurrentUserID())->toArray();
+                               $sender = DI::twitterUser()->createFromContactId($item['contact-id'], $uid)->toArray();
                        } elseif ($box == "sentbox" || $item['from-url'] == $profile_url) {
-                               $recipient = DI::twitterUser()->createFromContactId($item['contact-id'], BaseApi::getCurrentUserID())->toArray();
+                               $recipient = DI::twitterUser()->createFromContactId($item['contact-id'], $uid)->toArray();
                                $sender = $user_info;
                        }
 
@@ -4560,81 +4254,3 @@ function api_friendica_direct_messages_search($type, $box = "")
 
 /// @TODO move to top of file or somewhere better
 api_register_func('api/friendica/direct_messages_search', 'api_friendica_direct_messages_search', true);
-
-/*
- * Number of comments
- *
- * Bind comment numbers(friendica_comments: Int) on each statuses page of *_timeline / favorites / search
- *
- * @param object $data [Status, Status]
- *
- * @return void
- */
-function bindComments(&$data)
-{
-       if (count($data) == 0) {
-               return;
-       }
-
-       $ids = [];
-       $comments = [];
-       foreach ($data as $item) {
-               $ids[] = $item['id'];
-       }
-
-       $idStr = DBA::escape(implode(', ', $ids));
-       $sql = "SELECT `parent`, COUNT(*) as comments FROM `post-user-view` WHERE `parent` IN ($idStr) AND `deleted` = ? AND `gravity`= ? GROUP BY `parent`";
-       $items = DBA::p($sql, 0, GRAVITY_COMMENT);
-       $itemsData = DBA::toArray($items);
-
-       foreach ($itemsData as $item) {
-               $comments[$item['parent']] = $item['comments'];
-       }
-
-       foreach ($data as $idx => $item) {
-               $id = $item['id'];
-               $data[$idx]['friendica_comments'] = isset($comments[$id]) ? $comments[$id] : 0;
-       }
-}
-
-/*
-@TODO Maybe open to implement?
-To.Do:
-       [pagename] => api/1.1/statuses/lookup.json
-       [id] => 605138389168451584
-       [include_cards] => true
-       [cards_platform] => Android-12
-       [include_entities] => true
-       [include_my_retweet] => 1
-       [include_rts] => 1
-       [include_reply_count] => true
-       [include_descendent_reply_count] => true
-(?)
-
-
-Not implemented by now:
-statuses/retweets_of_me
-friendships/create
-friendships/destroy
-friendships/exists
-friendships/show
-account/update_location
-account/update_profile_background_image
-blocks/create
-blocks/destroy
-friendica/profile/update
-friendica/profile/create
-friendica/profile/delete
-
-Not implemented in status.net:
-statuses/retweeted_to_me
-statuses/retweeted_by_me
-direct_messages/destroy
-account/end_session
-account/update_delivery_device
-notifications/follow
-notifications/leave
-blocks/exists
-blocks/blocking
-lists
-*/
index 9521e2270a6e2938ac875fc70ee4313b717f51ce..b2d17f7fb20106728db0864df7bcde5e7dfee1a5 100644 (file)
@@ -3,11 +3,14 @@
 namespace Friendica\Module\Api;
 
 use Friendica\App\Arguments;
+use Friendica\App\BaseURL;
 use Friendica\Core\L10n;
 use Friendica\Util\Arrays;
+use Friendica\Util\DateTimeFormat;
 use Friendica\Util\HTTPInputData;
 use Friendica\Util\XML;
 use Psr\Log\LoggerInterface;
+use Friendica\Factory\Api\Twitter\User as TwitterUser;
 
 /**
  * This class is used to format and return API responses
@@ -26,11 +29,13 @@ class ApiResponse
         * @param Arguments       $args
         * @param LoggerInterface $logger
         */
-       public function __construct(L10n $l10n, Arguments $args, LoggerInterface $logger)
+       public function __construct(L10n $l10n, Arguments $args, LoggerInterface $logger, BaseURL $baseurl, TwitterUser $twitteruser)
        {
-               $this->l10n   = $l10n;
-               $this->args   = $args;
-               $this->logger = $logger;
+               $this->l10n        = $l10n;
+               $this->args        = $args;
+               $this->logger      = $logger;
+               $this->baseurl     = $baseurl;
+               $this->twitterUser = $twitteruser;
        }
 
        /**
@@ -102,20 +107,51 @@ class ApiResponse
                return XML::fromArray($data3, $xml, false, $namespaces);
        }
 
+       /**
+        * Set values for RSS template
+        *
+        * @param array $arr Array to be passed to template
+        * @param int   $cid Contact ID of template
+        * @return array
+        */
+       private function addRSSValues(array $arr, int $cid)
+       {
+               if (empty($cid)) {
+                       return $arr;
+               }
+
+               $user_info = $this->twitterUser->createFromContactId($cid)->toArray();
+
+               $arr['$user'] = $user_info;
+               $arr['$rss'] = [
+                       'alternate'    => $user_info['url'],
+                       'self'         => $this->baseurl . '/' . $this->args->getQueryString(),
+                       'base'         => $this->baseurl,
+                       'updated'      => DateTimeFormat::utc(null, DateTimeFormat::API),
+                       'atom_updated' => DateTimeFormat::utcNow(DateTimeFormat::ATOM),
+                       'language'     => $user_info['lang'],
+                       'logo'         => $this->baseurl . '/images/friendica-32.png',
+               ];
+
+               return $arr;
+       }
+
        /**
         * Formats the data according to the data type
         *
         * @param string $root_element Name of the root element
         * @param string $type         Return type (atom, rss, xml, json)
         * @param array  $data         JSON style array
+        * @param int    $cid          ID of the contact for RSS
         *
         * @return array|string (string|array) XML data or JSON data
         */
-       public function formatData(string $root_element, string $type, array $data)
+       public function formatData(string $root_element, string $type, array $data, int $cid = 0)
        {
                switch ($type) {
-                       case 'atom':
                        case 'rss':
+                               $data = $this->addRSSValues($data, $cid);
+                       case 'atom':
                        case 'xml':
                                return $this->createXML($data, $root_element);
                        case 'json':
index dbe45f545fdd06c040397f62c609154437310dec..5806f2e4810adc78d4a69d7d3aff04d200f65165 100644 (file)
@@ -23,6 +23,7 @@ namespace Friendica\Module\Api\Friendica;
 
 use Friendica\DI;
 use Friendica\Module\BaseApi;
+require_once __DIR__ . '/../../../../include/api.php';
 
 /**
  * api/friendica
index 2e8e1d15b83402709c6bb7b079a30f90380feef6..eaefdd0bdf917b94f6f2e1b4e90aaa7b90418470 100644 (file)
@@ -27,6 +27,7 @@ use Friendica\Core\System;
 use Friendica\DI;
 use Friendica\Model\Contact;
 use Friendica\Model\Post;
+use Friendica\Model\User;
 use Friendica\Network\HTTPException;
 use Friendica\Security\BasicAuth;
 use Friendica\Security\OAuth;
@@ -292,12 +293,23 @@ class BaseApi extends BaseModule
                }
        }
 
-       public static function getContactIDForSearchterm($searchterm)
+       public static function getContactIDForSearchterm(string $screen_name, int $cid, int $uid)
        {
-               if (intval($searchterm) == 0) {
-                       $cid = Contact::getIdForURL($searchterm, 0, false);
+               if (!empty($cid)) {
+                       return $cid;
+               }
+
+               if (strpos($screen_name, '@') !== false) {
+                       $cid = Contact::getIdForURL($screen_name, 0, false);
                } else {
-                       $cid = intval($searchterm);
+                       $user = User::getByNickname($screen_name, ['uid']);
+                       if (!empty($user['uid'])) {
+                               $cid = Contact::getPublicIdByUserId($user['uid']);
+                       }
+               }
+
+               if (empty($cid) && ($uid != 0)) {
+                       $cid = Contact::getPublicIdByUserId($uid);
                }
 
                return $cid;
index 6743dbf112519f19cd7ce2475ce3774baefd7d16..9e0174c029009cf0d29cf2b7107567ff6a1ffa2d 100644 (file)
@@ -303,6 +303,7 @@ return [
                        'causer-id'     => 42,
                        'vid'           => 8,
                        'private'       => Item::PUBLIC,
+                       'global'        => true,
                        'visible'       => 1,
                        'deleted'       => 0,
                ],
@@ -317,6 +318,7 @@ return [
                        'causer-id'     => 42,
                        'vid'           => 8,
                        'private'       => Item::PUBLIC,
+                       'global'        => true,
                        'visible'       => 1,
                        'deleted'       => 0,
                ],
@@ -331,6 +333,7 @@ return [
                        'causer-id'     => 43,
                        'vid'           => 8,
                        'private'       => Item::PUBLIC,
+                       'global'        => true,
                        'visible'       => 1,
                        'deleted'       => 0,
                ],
@@ -345,6 +348,7 @@ return [
                        'causer-id'     => 44,
                        'vid'           => 8,
                        'private'       => Item::PUBLIC,
+                       'global'        => true,
                        'visible'       => 1,
                        'deleted'       => 0,
                ],
@@ -359,6 +363,7 @@ return [
                        'causer-id'     => 42,
                        'vid'           => 8,
                        'private'       => Item::PUBLIC,
+                       'global'        => true,
                        'visible'       => 1,
                        'deleted'       => 0,
                ],
@@ -373,6 +378,7 @@ return [
                        'causer-id'     => 44,
                        'vid'           => 8,
                        'private'       => Item::PUBLIC,
+                       'global'        => true,
                        'visible'       => 1,
                        'deleted'       => 0,
                ],
@@ -392,6 +398,7 @@ return [
                        'parent-uri-id' => 1,
                        'thr-parent-id' => 1,
                        'private'       => Item::PUBLIC,
+                       'global'        => true,
                        'gravity'       => GRAVITY_PARENT,
                        'network'       => Protocol::DFRN,
                        'wall'          => 1,
@@ -413,6 +420,7 @@ return [
                        'causer-id'     => 42,
                        'vid'           => 8,
                        'private'       => Item::PUBLIC,
+                       'global'        => true,
                        'visible'       => 1,
                        'deleted'       => 0,
                        'wall'          => 1,
@@ -433,6 +441,7 @@ return [
                        'causer-id'     => 43,
                        'vid'           => 8,
                        'private'       => Item::PUBLIC,
+                       'global'        => true,
                        'visible'       => 1,
                        'deleted'       => 0,
                        'wall'          => 1,
@@ -453,6 +462,7 @@ return [
                        'causer-id'     => 44,
                        'vid'           => 8,
                        'private'       => Item::PUBLIC,
+                       'global'        => true,
                        'visible'       => 1,
                        'deleted'       => 0,
                        'wall'          => 1,
@@ -473,6 +483,7 @@ return [
                        'causer-id'     => 42,
                        'vid'           => 8,
                        'private'       => Item::PUBLIC,
+                       'global'        => true,
                        'visible'       => 1,
                        'deleted'       => 0,
                        'wall'          => 1,
@@ -493,6 +504,7 @@ return [
                        'causer-id'     => 44,
                        'vid'           => 8,
                        'private'       => Item::PUBLIC,
+                       'global'        => true,
                        'visible'       => 1,
                        'deleted'       => 0,
                        'wall'          => 1,
@@ -513,6 +525,7 @@ return [
                        'causer-id'     => 42,
                        'vid'           => 8,
                        'private'       => Item::PUBLIC,
+                       'global'        => true,
                        'visible'       => 1,
                        'deleted'       => 0,
                        'wall'          => 0,
@@ -533,6 +546,7 @@ return [
                        'causer-id'     => 42,
                        'vid'           => 8,
                        'private'       => Item::PUBLIC,
+                       'global'        => true,
                        'visible'       => 1,
                        'deleted'       => 0,
                        'wall'          => 0,
@@ -553,6 +567,7 @@ return [
                        'causer-id'     => 43,
                        'vid'           => 8,
                        'private'       => Item::PUBLIC,
+                       'global'        => true,
                        'visible'       => 1,
                        'deleted'       => 0,
                        'wall'          => 0,
@@ -573,6 +588,7 @@ return [
                        'causer-id'     => 44,
                        'vid'           => 8,
                        'private'       => Item::PUBLIC,
+                       'global'        => true,
                        'visible'       => 1,
                        'deleted'       => 0,
                        'wall'          => 0,
@@ -593,6 +609,7 @@ return [
                        'causer-id'     => 42,
                        'vid'           => 8,
                        'private'       => Item::PUBLIC,
+                       'global'        => true,
                        'visible'       => 1,
                        'deleted'       => 0,
                        'wall'          => 0,
@@ -611,6 +628,7 @@ return [
                        'parent-uri-id' => 6,
                        'thr-parent-id' => 6,
                        'private'       => Item::PUBLIC,
+                       'global'        => true,
                        'gravity'       => GRAVITY_PARENT,
                        'network'       => Protocol::DFRN,
                        'origin'        => 0,
index 13509bf3434aac3f7d111c12ad1dbbdababb6aa2..cc89dc0f8dcf08bcdab0a21aab3a24b89a48ffe7 100644 (file)
@@ -10,6 +10,7 @@ use Friendica\Core\Config\Capability\IManageConfigValues;
 use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues;
 use Friendica\Core\Protocol;
 use Friendica\DI;
+use Friendica\Model\Post;
 use Friendica\Module\Api\ApiResponse;
 use Friendica\Module\BaseApi;
 use Friendica\Network\HTTPException;
@@ -555,6 +556,7 @@ class ApiTest extends FixtureTest
         */
        public function testApiRssExtra()
        {
+               /*
                $user_info = ['url' => 'user_url', 'lang' => 'en'];
                $result    = api_rss_extra([], $user_info);
                self::assertEquals($user_info, $result['$user']);
@@ -565,6 +567,7 @@ class ApiTest extends FixtureTest
                self::assertArrayHasKey('atom_updated', $result['$rss']);
                self::assertArrayHasKey('language', $result['$rss']);
                self::assertArrayHasKey('logo', $result['$rss']);
+               */
        }
 
        /**
@@ -574,6 +577,7 @@ class ApiTest extends FixtureTest
         */
        public function testApiRssExtraWithoutUserInfo()
        {
+               /*
                $result = api_rss_extra([], null);
                self::assertIsArray($result['$user']);
                self::assertArrayHasKey('alternate', $result['$rss']);
@@ -583,26 +587,7 @@ class ApiTest extends FixtureTest
                self::assertArrayHasKey('atom_updated', $result['$rss']);
                self::assertArrayHasKey('language', $result['$rss']);
                self::assertArrayHasKey('logo', $result['$rss']);
-       }
-
-       /**
-        * Test the api_unique_id_to_nurl() function.
-        *
-        * @return void
-        */
-       public function testApiUniqueIdToNurl()
-       {
-               self::assertFalse(api_unique_id_to_nurl($this->wrongUserId));
-       }
-
-       /**
-        * Test the api_unique_id_to_nurl() function with a correct ID.
-        *
-        * @return void
-        */
-       public function testApiUniqueIdToNurlWithCorrectId()
-       {
-               self::assertEquals($this->otherUser['nurl'], api_unique_id_to_nurl($this->otherUser['id']));
+               */
        }
 
        /**
@@ -763,29 +748,6 @@ class ApiTest extends FixtureTest
                self::assertSelfUser(DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray());
        }
 
-       /**
-        * Test the api_item_get_user() function.
-        *
-        * @return void
-        */
-       public function testApiItemGetUser()
-       {
-               $users = api_item_get_user($this->app, []);
-               self::assertSelfUser($users[0]);
-       }
-
-       /**
-        * Test the api_item_get_user() function with a different item parent.
-        *
-        * @return void
-        */
-       public function testApiItemGetUserWithDifferentParent()
-       {
-               $users = api_item_get_user($this->app, ['thr-parent' => 'item_parent', 'uri' => 'item_uri']);
-               self::assertSelfUser($users[0]);
-               self::assertEquals($users[0], $users[1]);
-       }
-
        /**
         * Test the Arrays::walkRecursive() function.
         *
@@ -1790,10 +1752,12 @@ class ApiTest extends FixtureTest
         */
        public function testApiStatusesUserTimeline()
        {
+               $_REQUEST['user_id']         = 42;
                $_REQUEST['max_id']          = 10;
                $_REQUEST['exclude_replies'] = true;
-               $_REQUEST['conversation_id'] = 1;
-               $result                      = api_statuses_user_timeline('json');
+               $_REQUEST['conversation_id'] = 7;
+
+               $result = api_statuses_user_timeline('json');
                self::assertNotEmpty($result['status']);
                foreach ($result['status'] as $status) {
                        self::assertStatus($status);
@@ -1807,8 +1771,10 @@ class ApiTest extends FixtureTest
         */
        public function testApiStatusesUserTimelineWithNegativePage()
        {
-               $_REQUEST['page'] = -2;
-               $result           = api_statuses_user_timeline('json');
+               $_REQUEST['user_id'] = 42;
+               $_REQUEST['page']    = -2;
+
+               $result = api_statuses_user_timeline('json');
                self::assertNotEmpty($result['status']);
                foreach ($result['status'] as $status) {
                        self::assertStatus($status);
@@ -2262,21 +2228,9 @@ class ApiTest extends FixtureTest
         */
        public function testApiFormatItems()
        {
-               $items  = [
-                       [
-                               'item_network'   => 'item_network',
-                               'source'         => 'web',
-                               'coord'          => '5 7',
-                               'body'           => '',
-                               'verb'           => '',
-                               'author-id'      => 43,
-                               'author-network' => Protocol::DFRN,
-                               'author-link'    => 'http://localhost/profile/othercontact',
-                               'plink'          => '',
-                       ]
-               ];
-               $result = api_format_items($items, ['id' => 0], true);
-               foreach ($result as $status) {
+               $items = Post::selectToArray([], ['uid' => 42]);
+               foreach ($items as $item) {
+                       $status = api_format_item($item);
                        self::assertStatus($status);
                }
        }
@@ -2287,19 +2241,9 @@ class ApiTest extends FixtureTest
         */
        public function testApiFormatItemsWithXml()
        {
-               $items  = [
-                       [
-                               'coord'          => '5 7',
-                               'body'           => '',
-                               'verb'           => '',
-                               'author-id'      => 43,
-                               'author-network' => Protocol::DFRN,
-                               'author-link'    => 'http://localhost/profile/othercontact',
-                               'plink'          => '',
-                       ]
-               ];
-               $result = api_format_items($items, ['id' => 0], true, 'xml');
-               foreach ($result as $status) {
+               $items = Post::selectToArray([], ['uid' => 42]);
+               foreach ($items as $item) {
+                       $status = api_format_item($item, 'xml');
                        self::assertStatus($status);
                }
        }
@@ -2602,9 +2546,9 @@ class ApiTest extends FixtureTest
        public function testApiDirectMessagesNewWithScreenName()
        {
                $this->app->setLoggedInUserNickname($this->selfUser['nick']);
-               $_POST['text']        = 'message_text';
-               $_POST['screen_name'] = $this->friendUser['nick'];
-               $result               = api_direct_messages_new('json');
+               $_POST['text']    = 'message_text';
+               $_POST['user_id'] = $this->friendUser['id'];
+               $result           = api_direct_messages_new('json');
                self::assertStringContainsString('message_text', $result['direct_message']['text']);
                self::assertEquals('selfcontact', $result['direct_message']['sender_screen_name']);
                self::assertEquals(1, $result['direct_message']['friendica_seen']);
@@ -2618,10 +2562,10 @@ class ApiTest extends FixtureTest
        public function testApiDirectMessagesNewWithTitle()
        {
                $this->app->setLoggedInUserNickname($this->selfUser['nick']);
-               $_POST['text']        = 'message_text';
-               $_POST['screen_name'] = $this->friendUser['nick'];
-               $_REQUEST['title']    = 'message_title';
-               $result               = api_direct_messages_new('json');
+               $_POST['text']     = 'message_text';
+               $_POST['user_id']  = $this->friendUser['id'];
+               $_REQUEST['title'] = 'message_title';
+               $result            = api_direct_messages_new('json');
                self::assertStringContainsString('message_text', $result['direct_message']['text']);
                self::assertStringContainsString('message_title', $result['direct_message']['text']);
                self::assertEquals('selfcontact', $result['direct_message']['sender_screen_name']);
@@ -2636,9 +2580,9 @@ class ApiTest extends FixtureTest
        public function testApiDirectMessagesNewWithRss()
        {
                $this->app->setLoggedInUserNickname($this->selfUser['nick']);
-               $_POST['text']        = 'message_text';
-               $_POST['screen_name'] = $this->friendUser['nick'];
-               $result               = api_direct_messages_new('rss');
+               $_POST['text']    = 'message_text';
+               $_POST['user_id'] = $this->friendUser['id'];
+               $result           = api_direct_messages_new('rss');
                self::assertXml($result, 'direct-messages');
        }
 
@@ -3068,7 +3012,7 @@ class ApiTest extends FixtureTest
         */
        public function testCheckAclInput()
        {
-               $result = check_acl_input('<aclstring>');
+               $result = check_acl_input('<aclstring>', BaseApi::getCurrentUserID());
                // Where does this result come from?
                self::assertEquals(1, $result);
        }
@@ -3080,7 +3024,7 @@ class ApiTest extends FixtureTest
         */
        public function testCheckAclInputWithEmptyAclString()
        {
-               $result = check_acl_input(' ');
+               $result = check_acl_input(' ', BaseApi::getCurrentUserID());
                self::assertFalse($result);
        }
 
@@ -3161,18 +3105,6 @@ class ApiTest extends FixtureTest
                self::assertEquals('some_text [url="some_url"]"some_url"[/url]', $result);
        }
 
-       /**
-        * Test the api_best_nickname() function.
-        *
-        * @return void
-        */
-       public function testApiBestNickname()
-       {
-               $contacts = [];
-               $result   = api_best_nickname($contacts);
-               self::assertNull($result);
-       }
-
        /**
         * Test the api_best_nickname() function with contacts.
         *
index b6f5826214fcd63ffc1406eec78b6d1cb01da440..524c9ebd17f15fa3e911e17cac07a7af1ccacbd4 100644 (file)
@@ -3,7 +3,9 @@
 namespace Friendica\Test\src\Module\Api;
 
 use Friendica\App\Arguments;
+use Friendica\App\BaseURL;
 use Friendica\Core\L10n;
+use Friendica\Factory\Api\Twitter\User;
 use Friendica\Test\MockedTest;
 use Friendica\Test\Util\ApiResponseDouble;
 use Psr\Log\NullLogger;
@@ -22,8 +24,10 @@ class ApiResponseTest extends MockedTest
                $l10n = \Mockery::mock(L10n::class);
                $args = \Mockery::mock(Arguments::class);
                $args->shouldReceive('getQueryString')->andReturn('');
+               $baseUrl     = \Mockery::mock(BaseURL::class);
+               $twitterUser = \Mockery::mock(User::class);
 
-               $response = new ApiResponseDouble($l10n, $args, new NullLogger());
+               $response = new ApiResponseDouble($l10n, $args, new NullLogger(), $baseUrl, $twitterUser);
                $response->error(200, 'OK', 'error_message', 'json');
 
                self::assertEquals('{"error":"error_message","code":"200 OK","request":""}', ApiResponseDouble::getOutput());
@@ -34,8 +38,10 @@ class ApiResponseTest extends MockedTest
                $l10n = \Mockery::mock(L10n::class);
                $args = \Mockery::mock(Arguments::class);
                $args->shouldReceive('getQueryString')->andReturn('');
+               $baseUrl     = \Mockery::mock(BaseURL::class);
+               $twitterUser = \Mockery::mock(User::class);
 
-               $response = new ApiResponseDouble($l10n, $args, new NullLogger());
+               $response = new ApiResponseDouble($l10n, $args, new NullLogger(), $baseUrl, $twitterUser);
                $response->error(200, 'OK', 'error_message', 'xml');
 
                self::assertEquals('<?xml version="1.0"?>' . "\n" .
@@ -54,8 +60,10 @@ class ApiResponseTest extends MockedTest
                $l10n = \Mockery::mock(L10n::class);
                $args = \Mockery::mock(Arguments::class);
                $args->shouldReceive('getQueryString')->andReturn('');
+               $baseUrl     = \Mockery::mock(BaseURL::class);
+               $twitterUser = \Mockery::mock(User::class);
 
-               $response = new ApiResponseDouble($l10n, $args, new NullLogger());
+               $response = new ApiResponseDouble($l10n, $args, new NullLogger(), $baseUrl, $twitterUser);
                $response->error(200, 'OK', 'error_message', 'rss');
 
                self::assertEquals(
@@ -75,8 +83,10 @@ class ApiResponseTest extends MockedTest
                $l10n = \Mockery::mock(L10n::class);
                $args = \Mockery::mock(Arguments::class);
                $args->shouldReceive('getQueryString')->andReturn('');
+               $baseUrl     = \Mockery::mock(BaseURL::class);
+               $twitterUser = \Mockery::mock(User::class);
 
-               $response = new ApiResponseDouble($l10n, $args, new NullLogger());
+               $response = new ApiResponseDouble($l10n, $args, new NullLogger(), $baseUrl, $twitterUser);
                $response->error(200, 'OK', 'error_message', 'atom');
 
                self::assertEquals(
@@ -99,8 +109,10 @@ class ApiResponseTest extends MockedTest
                });
                $args = \Mockery::mock(Arguments::class);
                $args->shouldReceive('getQueryString')->andReturn('');
+               $baseUrl     = \Mockery::mock(BaseURL::class);
+               $twitterUser = \Mockery::mock(User::class);
 
-               $response = new ApiResponseDouble($l10n, $args, new NullLogger());
+               $response = new ApiResponseDouble($l10n, $args, new NullLogger(), $baseUrl, $twitterUser);
                $response->unsupported();
 
                self::assertEquals('{"error":"API endpoint %s %s is not implemented","error_description":"The API endpoint is currently not implemented but might be in the future."}', ApiResponseDouble::getOutput());