]> git.mxchange.org Git - friendica.git/blobdiff - include/api.php
[WIP] Rewrite to Proxy class: (#5507)
[friendica.git] / include / api.php
index 00c2173c38b1b8f4c4297047928e1b8396447f42..4fbbc37779ecf0f5d177268e62ec98f1c521194e 100644 (file)
@@ -16,9 +16,10 @@ use Friendica\Core\Config;
 use Friendica\Core\L10n;
 use Friendica\Core\NotificationsManager;
 use Friendica\Core\PConfig;
+use Friendica\Core\Protocol;
 use Friendica\Core\System;
 use Friendica\Core\Worker;
-use Friendica\Database\DBM;
+use Friendica\Database\DBA;
 use Friendica\Model\Contact;
 use Friendica\Model\Group;
 use Friendica\Model\Item;
@@ -39,6 +40,7 @@ use Friendica\Object\Image;
 use Friendica\Protocol\Diaspora;
 use Friendica\Util\DateTimeFormat;
 use Friendica\Util\Network;
+use Friendica\Util\Proxy as ProxyUtils;
 use Friendica\Util\XML;
 
 require_once 'include/conversation.php';
@@ -46,7 +48,6 @@ require_once 'mod/share.php';
 require_once 'mod/item.php';
 require_once 'include/security.php';
 require_once 'mod/wall_upload.php';
-require_once 'mod/proxy.php';
 
 define('API_METHOD_ANY', '*');
 define('API_METHOD_GET', 'GET');
@@ -90,11 +91,15 @@ function api_source()
        }
 
        // Support for known clients that doesn't send a source name
-       if (strpos($_SERVER['HTTP_USER_AGENT'], "Twidere") !== false) {
-               return "Twidere";
-       }
+       if (!empty($_SERVER['HTTP_USER_AGENT'])) {
+               if(strpos($_SERVER['HTTP_USER_AGENT'], "Twidere") !== false) {
+                       return "Twidere";
+               }
 
-       logger("Unrecognized user-agent ".$_SERVER['HTTP_USER_AGENT'], LOGGER_DEBUG);
+               logger("Unrecognized user-agent ".$_SERVER['HTTP_USER_AGENT'], LOGGER_DEBUG);
+       } else {
+               logger("Empty user-agent", LOGGER_DEBUG);
+       }
 
        return "api";
 }
@@ -164,7 +169,8 @@ function api_login(App $a)
        $oauth1 = new FKOAuth1();
        // login with oauth
        try {
-               list($consumer, $token) = $oauth1->verify_request(OAuthRequest::from_request());
+               $request = OAuthRequest::from_request();
+               list($consumer, $token) = $oauth1->verify_request($request);
                if (!is_null($token)) {
                        $oauth1->loginUser($token->uid);
                        Addon::callHooks('logged_in', $a->user);
@@ -193,8 +199,8 @@ function api_login(App $a)
                throw new UnauthorizedException("This API requires login");
        }
 
-       $user = $_SERVER['PHP_AUTH_USER'];
-       $password = $_SERVER['PHP_AUTH_PW'];
+       $user = defaults($_SERVER, 'PHP_AUTH_USER', '');
+       $password = defaults($_SERVER, 'PHP_AUTH_PW', '');
 
        // allow "user@server" login (but ignore 'server' part)
        $at = strstr($user, "@", true);
@@ -224,11 +230,11 @@ function api_login(App $a)
        } else {
                $user_id = User::authenticate(trim($user), trim($password));
                if ($user_id !== false) {
-                       $record = dba::selectFirst('user', [], ['uid' => $user_id]);
+                       $record = DBA::selectFirst('user', [], ['uid' => $user_id]);
                }
        }
 
-       if (!DBM::is_result($record)) {
+       if (!DBA::isResult($record)) {
                logger('API_login failure: ' . print_r($_SERVER, true), LOGGER_DEBUG);
                header('WWW-Authenticate: Basic realm="Friendica"');
                //header('HTTP/1.0 401 Unauthorized');
@@ -258,7 +264,7 @@ function api_check_method($method)
        if ($method == "*") {
                return true;
        }
-       return (strpos($method, $_SERVER['REQUEST_METHOD']) !== false);
+       return (stripos($method, defaults($_SERVER, 'REQUEST_METHOD', 'GET')) !== false);
 }
 
 /**
@@ -298,7 +304,7 @@ function api_call(App $a)
                                //unset($_SERVER['PHP_AUTH_USER']);
 
                                /// @TODO should be "true ==[=] $info['auth']", if you miss only one = character, you assign a variable (only with ==). Let's make all this even.
-                               if ($info['auth'] === true && api_user() === false) {
+                               if (!empty($info['auth']) && api_user() === false) {
                                        api_login($a);
                                }
 
@@ -475,7 +481,7 @@ function api_rss_extra(App $a, $arr, $user_info)
                'base'         => System::baseUrl(),
                'updated'      => api_date(null),
                'atom_updated' => DateTimeFormat::utcNow(DateTimeFormat::ATOM),
-               'language'     => $user_info['language'],
+               'language'     => $user_info['lang'],
                'logo'         => System::baseUrl() . "/images/friendica-32.png",
        ];
 
@@ -492,9 +498,9 @@ function api_rss_extra(App $a, $arr, $user_info)
  */
 function api_unique_id_to_nurl($id)
 {
-       $r = dba::selectFirst('contact', ['nurl'], ['id' => $id]);
+       $r = DBA::selectFirst('contact', ['nurl'], ['id' => $id]);
 
-       if (DBM::is_result($r)) {
+       if (DBA::isResult($r)) {
                return $r["nurl"];
        } else {
                return false;
@@ -519,7 +525,7 @@ function api_get_user(App $a, $contact_id = null)
 
        // Searching for contact URL
        if (!is_null($contact_id) && (intval($contact_id) == 0)) {
-               $user = dbesc(normalise_link($contact_id));
+               $user = DBA::escape(normalise_link($contact_id));
                $url = $user;
                $extra_query = "AND `contact`.`nurl` = '%s' ";
                if (api_user() !== false) {
@@ -529,7 +535,7 @@ function api_get_user(App $a, $contact_id = null)
 
        // Searching for contact id with uid = 0
        if (!is_null($contact_id) && (intval($contact_id) != 0)) {
-               $user = dbesc(api_unique_id_to_nurl(intval($contact_id)));
+               $user = DBA::escape(api_unique_id_to_nurl(intval($contact_id)));
 
                if ($user == "") {
                        throw new BadRequestException("User ID ".$contact_id." not found.");
@@ -543,7 +549,7 @@ function api_get_user(App $a, $contact_id = null)
        }
 
        if (is_null($user) && x($_GET, 'user_id')) {
-               $user = dbesc(api_unique_id_to_nurl($_GET['user_id']));
+               $user = DBA::escape(api_unique_id_to_nurl($_GET['user_id']));
 
                if ($user == "") {
                        throw new BadRequestException("User ID ".$_GET['user_id']." not found.");
@@ -556,7 +562,7 @@ function api_get_user(App $a, $contact_id = null)
                }
        }
        if (is_null($user) && x($_GET, 'screen_name')) {
-               $user = dbesc($_GET['screen_name']);
+               $user = DBA::escape($_GET['screen_name']);
                $extra_query = "AND `contact`.`nick` = '%s' ";
                if (api_user() !== false) {
                        $extra_query .= "AND `contact`.`uid`=".intval(api_user());
@@ -564,18 +570,21 @@ function api_get_user(App $a, $contact_id = null)
        }
 
        if (is_null($user) && x($_GET, 'profileurl')) {
-               $user = dbesc(normalise_link($_GET['profileurl']));
+               $user = DBA::escape(normalise_link($_GET['profileurl']));
                $extra_query = "AND `contact`.`nurl` = '%s' ";
                if (api_user() !== false) {
                        $extra_query .= "AND `contact`.`uid`=".intval(api_user());
                }
        }
 
+       // $called_api is the API path exploded on / and is expected to have at least 2 elements
        if (is_null($user) && ($a->argc > (count($called_api) - 1)) && (count($called_api) > 0)) {
                $argid = count($called_api);
-               list($user, $null) = explode(".", $a->argv[$argid]);
+               if (!empty($a->argv[$argid])) {
+                       list($user, $null) = explode(".", $a->argv[$argid]);
+               }
                if (is_numeric($user)) {
-                       $user = dbesc(api_unique_id_to_nurl(intval($user)));
+                       $user = DBA::escape(api_unique_id_to_nurl(intval($user)));
 
                        if ($user != "") {
                                $url = $user;
@@ -585,7 +594,7 @@ function api_get_user(App $a, $contact_id = null)
                                }
                        }
                } else {
-                       $user = dbesc($user);
+                       $user = DBA::escape($user);
                        $extra_query = "AND `contact`.`nick` = '%s' ";
                        if (api_user() !== false) {
                                $extra_query .= "AND `contact`.`uid`=" . intval(api_user());
@@ -621,14 +630,14 @@ function api_get_user(App $a, $contact_id = null)
        }
 
        // if the contact wasn't found, fetch it from the contacts with uid = 0
-       if (!DBM::is_result($uinfo)) {
+       if (!DBA::isResult($uinfo)) {
                $r = [];
 
                if ($url != "") {
-                       $r = q("SELECT * FROM `contact` WHERE `uid` = 0 AND `nurl` = '%s' LIMIT 1", dbesc(normalise_link($url)));
+                       $r = q("SELECT * FROM `contact` WHERE `uid` = 0 AND `nurl` = '%s' LIMIT 1", DBA::escape(normalise_link($url)));
                }
 
-               if (DBM::is_result($r)) {
+               if (DBA::isResult($r)) {
                        $network_name = ContactSelector::networkToName($r[0]['network'], $r[0]['url']);
 
                        // If no nick where given, extract it from the address
@@ -686,61 +695,10 @@ function api_get_user(App $a, $contact_id = null)
                        $uinfo[0]['network'] = NETWORK_DFRN;
                }
 
-               $usr = dba::selectFirst('user', ['default-location'], ['uid' => api_user()]);
-               $profile = dba::selectFirst('profile', ['about'], ['uid' => api_user(), 'is-default' => true]);
-
-               /// @TODO old-lost code? (twice)
-               // Counting is deactivated by now, due to performance issues
-               // count public wall messages
-               //$r = q("SELECT COUNT(*) as `count` FROM `item` WHERE `uid` = %d AND `wall`",
-               //              intval($uinfo[0]['uid'])
-               //);
-               //$countitms = $r[0]['count'];
-               $countitms = 0;
-       } else {
-               // Counting is deactivated by now, due to performance issues
-               //$r = q("SELECT count(*) as `count` FROM `item`
-               //              WHERE  `contact-id` = %d",
-               //              intval($uinfo[0]['id'])
-               //);
-               //$countitms = $r[0]['count'];
-               $countitms = 0;
-       }
-
-               /// @TODO old-lost code? (twice)
-               /*
-               // Counting is deactivated by now, due to performance issues
-               // count friends
-               $r = q("SELECT count(*) as `count` FROM `contact`
-                               WHERE  `uid` = %d AND `rel` IN ( %d, %d )
-                               AND `self`=0 AND NOT `blocked` AND NOT `pending` AND `hidden`=0",
-                               intval($uinfo[0]['uid']),
-                               intval(CONTACT_IS_SHARING),
-                               intval(CONTACT_IS_FRIEND)
-               );
-               $countfriends = $r[0]['count'];
-
-               $r = q("SELECT count(*) as `count` FROM `contact`
-                               WHERE  `uid` = %d AND `rel` IN ( %d, %d )
-                               AND `self`=0 AND NOT `blocked` AND NOT `pending` AND `hidden`=0",
-                               intval($uinfo[0]['uid']),
-                               intval(CONTACT_IS_FOLLOWER),
-                               intval(CONTACT_IS_FRIEND)
-               );
-               $countfollowers = $r[0]['count'];
-
-               $r = q("SELECT count(*) as `count` FROM item where starred = 1 and uid = %d and deleted = 0",
-                       intval($uinfo[0]['uid'])
-               );
-               $starred = $r[0]['count'];
-
-
-               if (! $uinfo[0]['self']) {
-                       $countfriends = 0;
-                       $countfollowers = 0;
-                       $starred = 0;
-               }
-               */
+               $usr = DBA::selectFirst('user', ['default-location'], ['uid' => api_user()]);
+               $profile = DBA::selectFirst('profile', ['about'], ['uid' => api_user(), 'is-default' => true]);
+       }
+       $countitems = 0;
        $countfriends = 0;
        $countfollowers = 0;
        $starred = 0;
@@ -790,12 +748,12 @@ function api_get_user(App $a, $contact_id = null)
                'time_zone' => 'UTC',
                'geo_enabled' => false,
                'verified' => true,
-               'statuses_count' => intval($countitms),
+               'statuses_count' => intval($countitems),
                'lang' => '',
                'contributors_enabled' => false,
                'is_translator' => false,
                'is_translation_enabled' => false,
-               'following' => (($uinfo[0]['rel'] == CONTACT_IS_FOLLOWER) || ($uinfo[0]['rel'] == CONTACT_IS_FRIEND)),
+               'following' => (($uinfo[0]['rel'] == Contact::FOLLOWER) || ($uinfo[0]['rel'] == Contact::FRIEND)),
                'follow_request_sent' => false,
                'statusnet_blocking' => false,
                'notifications' => false,
@@ -811,9 +769,10 @@ function api_get_user(App $a, $contact_id = null)
 
        // If this is a local user and it uses Frio, we can get its color preferences.
        if ($ret['self']) {
-               $theme_info = dba::selectFirst('user', ['theme'], ['uid' => $ret['uid']]);
+               $theme_info = DBA::selectFirst('user', ['theme'], ['uid' => $ret['uid']]);
                if ($theme_info['theme'] === 'frio') {
                        $schema = PConfig::get($ret['uid'], 'frio', 'schema');
+
                        if ($schema && ($schema != '---')) {
                                if (file_exists('view/theme/frio/schema/'.$schema.'.php')) {
                                        $schemefile = 'view/theme/frio/schema/'.$schema.'.php';
@@ -824,13 +783,13 @@ function api_get_user(App $a, $contact_id = null)
                                $link_color = PConfig::get($ret['uid'], 'frio', 'link_color');
                                $bgcolor = PConfig::get($ret['uid'], 'frio', 'background_color');
                        }
-                       if (!$nav_bg) {
+                       if (empty($nav_bg)) {
                                $nav_bg = "#708fa0";
                        }
-                       if (!$link_color) {
+                       if (empty($link_color)) {
                                $link_color = "#6fdbe8";
                        }
-                       if (!$bgcolor) {
+                       if (empty($bgcolor)) {
                                $bgcolor = "#ededed";
                        }
 
@@ -852,12 +811,12 @@ function api_get_user(App $a, $contact_id = null)
  */
 function api_item_get_user(App $a, $item)
 {
-       $status_user = api_get_user($a, $item["author-id"]);
+       $status_user = api_get_user($a, defaults($item, 'author-id', null));
 
-       $status_user["protected"] = $item["private"];
+       $status_user["protected"] = defaults($item, 'private', 0);
 
-       if ($item['thr-parent'] == $item['uri']) {
-               $owner_user = api_get_user($a, $item["owner-id"]);
+       if (defaults($item, 'thr-parent', '') == defaults($item, 'uri', '')) {
+               $owner_user = api_get_user($a, defaults($item, 'author-id', null));
        } else {
                $owner_user = $status_user;
        }
@@ -931,7 +890,6 @@ function api_create_xml(array $data, $root_element)
 {
        $childname = key($data);
        $data2 = array_pop($data);
-       $key = key($data2);
 
        $namespaces = ["" => "http://api.twitter.com",
                                "statusnet" => "http://status.net/schema/api/1/",
@@ -944,18 +902,19 @@ function api_create_xml(array $data, $root_element)
        }
 
        if (is_array($data2)) {
+               $key = key($data2);
                api_walk_recursive($data2, "api_reformat_xml");
-       }
 
-       if ($key == "0") {
-               $data4 = [];
-               $i = 1;
+               if ($key == "0") {
+                       $data4 = [];
+                       $i = 1;
 
-               foreach ($data2 as $item) {
-                       $data4[$i++ . ":" . $childname] = $item;
-               }
+                       foreach ($data2 as $item) {
+                               $data4[$i++ . ":" . $childname] = $item;
+                       }
 
-               $data2 = $data4;
+                       $data2 = $data4;
+               }
        }
 
        $data3 = [$root_element => $data2];
@@ -1076,7 +1035,6 @@ function api_statuses_mediap($type)
        }
        $user_info = api_get_user($a);
 
-       $_REQUEST['type'] = 'wall';
        $_REQUEST['profile_uid'] = api_user();
        $_REQUEST['api_source'] = true;
        $txt = requestdata('status');
@@ -1165,26 +1123,14 @@ function api_statuses_update($type)
        }
        $_REQUEST['profile_uid'] = api_user();
 
-       if ($parent) {
-               $_REQUEST['type'] = 'net-comment';
-       } else {
+       if (!$parent) {
                // Check for throttling (maximum posts per day, week and month)
                $throttle_day = Config::get('system', 'throttle_limit_day');
                if ($throttle_day > 0) {
                        $datefrom = date(DateTimeFormat::MYSQL, time() - 24*60*60);
 
-                       $r = q(
-                               "SELECT COUNT(*) AS `posts_day` FROM `item` WHERE `uid`=%d AND `wall`
-                               AND `created` > '%s' AND `id` = `parent`",
-                               intval(api_user()),
-                               dbesc($datefrom)
-                       );
-
-                       if (DBM::is_result($r)) {
-                               $posts_day = $r[0]["posts_day"];
-                       } else {
-                               $posts_day = 0;
-                       }
+                       $condition = ["`uid` = ? AND `wall` AND `created` > ? AND `id` = `parent`", api_user(), $datefrom];
+                       $posts_day = DBA::count('item', $condition);
 
                        if ($posts_day > $throttle_day) {
                                logger('Daily posting limit reached for user '.api_user(), LOGGER_DEBUG);
@@ -1197,18 +1143,8 @@ function api_statuses_update($type)
                if ($throttle_week > 0) {
                        $datefrom = date(DateTimeFormat::MYSQL, time() - 24*60*60*7);
 
-                       $r = q(
-                               "SELECT COUNT(*) AS `posts_week` FROM `item` WHERE `uid`=%d AND `wall`
-                               AND `created` > '%s' AND `id` = `parent`",
-                               intval(api_user()),
-                               dbesc($datefrom)
-                       );
-
-                       if (DBM::is_result($r)) {
-                               $posts_week = $r[0]["posts_week"];
-                       } else {
-                               $posts_week = 0;
-                       }
+                       $condition = ["`uid` = ? AND `wall` AND `created` > ? AND `id` = `parent`", api_user(), $datefrom];
+                       $posts_week = DBA::count('item', $condition);
 
                        if ($posts_week > $throttle_week) {
                                logger('Weekly posting limit reached for user '.api_user(), LOGGER_DEBUG);
@@ -1221,18 +1157,8 @@ function api_statuses_update($type)
                if ($throttle_month > 0) {
                        $datefrom = date(DateTimeFormat::MYSQL, time() - 24*60*60*30);
 
-                       $r = q(
-                               "SELECT COUNT(*) AS `posts_month` FROM `item` WHERE `uid`=%d AND `wall`
-                               AND `created` > '%s' AND `id` = `parent`",
-                               intval(api_user()),
-                               dbesc($datefrom)
-                       );
-
-                       if (DBM::is_result($r)) {
-                               $posts_month = $r[0]["posts_month"];
-                       } else {
-                               $posts_month = 0;
-                       }
+                       $condition = ["`uid` = ? AND `wall` AND `created` > ? AND `id` = `parent`", api_user(), $datefrom];
+                       $posts_month = DBA::count('item', $condition);
 
                        if ($posts_month > $throttle_month) {
                                logger('Monthly posting limit reached for user '.api_user(), LOGGER_DEBUG);
@@ -1240,8 +1166,6 @@ function api_statuses_update($type)
                                throw new TooManyRequestsException(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));
                        }
                }
-
-               $_REQUEST['type'] = 'wall';
        }
 
        if (x($_FILES, 'media')) {
@@ -1259,7 +1183,7 @@ function api_statuses_update($type)
                        intval(requestdata('media_ids')),
                        api_user()
                );
-               if (DBM::is_result($r)) {
+               if (DBA::isResult($r)) {
                        $phototypes = Image::supportedTypes();
                        $ext = $phototypes[$r[0]['type']];
                        $_REQUEST['body'] .= "\n\n" . '[url=' . System::baseUrl() . '/photos/' . $r[0]['nickname'] . '/image/' . $r[0]['resource-id'] . ']';
@@ -1351,11 +1275,11 @@ function api_status_show($type)
        }
 
        // get last public wall message
-       $condition = ["`owner-id` = ? AND `uid` = ? AND `type` != 'activity' ".$privacy_sql,
-               $user_info['pid'], api_user()];
-       $lastwall = dba::selectFirst('item', [], $condition, ['order' => ['id' => true]]);
+       $condition = ['owner-id' => $user_info['pid'], 'uid' => api_user(),
+               'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT]];
+       $lastwall = Item::selectFirst(Item::ITEM_FIELDLIST, $condition, ['order' => ['id' => true]]);
 
-       if (DBM::is_result($lastwall)) {
+       if (DBA::isResult($lastwall)) {
                $in_reply_to = api_in_reply_to($lastwall);
 
                $converted = api_convert_item($lastwall);
@@ -1380,19 +1304,19 @@ function api_status_show($type)
                        'in_reply_to_screen_name' => $in_reply_to['screen_name'],
                        'user' => $user_info,
                        $geo => null,
-                       'coordinates' => "",
-                       'place' => "",
-                       'contributors' => "",
+                       'coordinates' => '',
+                       'place' => '',
+                       'contributors' => '',
                        'is_quote_status' => false,
                        'retweet_count' => 0,
                        'favorite_count' => 0,
                        'favorited' => $lastwall['starred'] ? true : false,
                        'retweeted' => false,
                        'possibly_sensitive' => false,
-                       'lang' => "",
+                       'lang' => '',
                        'statusnet_html' => $converted["html"],
                        'statusnet_conversation_id' => $lastwall['parent'],
-                       'external_url' => System::baseUrl() . "/display/" . $lastwall['guid'],
+                       'external_url' => System::baseUrl() . '/display/' . $lastwall['guid'],
                ];
 
                if (count($converted["attachments"]) > 0) {
@@ -1436,11 +1360,11 @@ function api_users_show($type)
 
        $user_info = api_get_user($a);
 
-       $condition = ["`owner-id` = ? AND `uid` = ? AND `verb` = ? AND `type` != 'activity' AND NOT `private`",
-               $user_info['pid'], api_user(), ACTIVITY_POST];
-       $lastwall = dba::selectFirst('item', [], $condition, ['order' => ['id' => true]]);
+       $condition = ['owner-id' => $user_info['pid'], 'uid' => api_user(),
+               'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT], 'private' => false];
+       $lastwall = Item::selectFirst(Item::ITEM_FIELDLIST, $condition, ['order' => ['id' => true]]);
 
-       if (DBM::is_result($lastwall)) {
+       if (DBA::isResult($lastwall)) {
                $in_reply_to = api_in_reply_to($lastwall);
 
                $converted = api_convert_item($lastwall);
@@ -1513,13 +1437,13 @@ function api_users_search($type)
        $userlist = [];
 
        if (x($_GET, 'q')) {
-               $r = q("SELECT id FROM `contact` WHERE `uid` = 0 AND `name` = '%s'", dbesc($_GET["q"]));
+               $r = q("SELECT id FROM `contact` WHERE `uid` = 0 AND `name` = '%s'", DBA::escape($_GET["q"]));
 
-               if (!DBM::is_result($r)) {
-                       $r = q("SELECT `id` FROM `contact` WHERE `uid` = 0 AND `nick` = '%s'", dbesc($_GET["q"]));
+               if (!DBA::isResult($r)) {
+                       $r = q("SELECT `id` FROM `contact` WHERE `uid` = 0 AND `nick` = '%s'", DBA::escape($_GET["q"]));
                }
 
-               if (DBM::is_result($r)) {
+               if (DBA::isResult($r)) {
                        $k = 0;
                        foreach ($r as $user) {
                                $user_info = api_get_user($a, $user["id"]);
@@ -1558,7 +1482,7 @@ function api_users_lookup($type)
 {
        $users = [];
 
-       if (x($_REQUEST['user_id'])) {
+       if (!empty($_REQUEST['user_id'])) {
                foreach (explode(',', $_REQUEST['user_id']) as $id) {
                        if (!empty($id)) {
                                $users[] = api_get_user(get_app(), $id);
@@ -1615,10 +1539,10 @@ function api_search($type)
 
        $start = $page * $count;
 
-       $condition = ["`verb` = ? AND `item`.`id` > ?
+       $condition = ["`gravity` IN (?, ?) AND `item`.`id` > ?
                AND (`item`.`uid` = 0 OR (`item`.`uid` = ? AND NOT `item`.`global`))
                AND `item`.`body` LIKE CONCAT('%',?,'%')",
-               ACTIVITY_POST, $since_id, api_user(), $_REQUEST['q']];
+               GRAVITY_PARENT, GRAVITY_COMMENT, $since_id, api_user(), $_REQUEST['q']];
 
        if ($max_id > 0) {
                $condition[0] .= " AND `item`.`id` <= ?";
@@ -1626,9 +1550,9 @@ function api_search($type)
        }
 
        $params = ['order' => ['id' => true], 'limit' => [$start, $count]];
-       $statuses = Item::select(api_user(), [], $condition, $params);
+       $statuses = Item::selectForUser(api_user(), [], $condition, $params);
 
-       $data['status'] = api_format_items(dba::inArray($statuses), $user_info);
+       $data['status'] = api_format_items(Item::inArray($statuses), $user_info);
 
        return api_format_data("statuses", $type, $data);
 }
@@ -1678,7 +1602,8 @@ function api_statuses_home_timeline($type)
 
        $start = $page * $count;
 
-       $condition = ["`uid` = ? AND `verb` = ? AND `item`.`id` > ?", api_user(), ACTIVITY_POST, $since_id];
+       $condition = ["`uid` = ? AND `gravity` IN (?, ?) AND `item`.`id` > ?",
+               api_user(), GRAVITY_PARENT, GRAVITY_COMMENT, $since_id];
 
        if ($max_id > 0) {
                $condition[0] .= " AND `item`.`id` <= ?";
@@ -1693,9 +1618,9 @@ function api_statuses_home_timeline($type)
        }
 
        $params = ['order' => ['id' => true], 'limit' => [$start, $count]];
-       $statuses = Item::select(api_user(), [], $condition, $params);
+       $statuses = Item::selectForUser(api_user(), [], $condition, $params);
 
-       $items = dba::inArray($statuses);
+       $items = Item::inArray($statuses);
 
        $ret = api_format_items($items, $user_info, false, $type);
 
@@ -1706,7 +1631,7 @@ function api_statuses_home_timeline($type)
        }
 
        if (!empty($idarray)) {
-               $unseen = dba::exists('item', ['unseen' => true, 'id' => $idarray]);
+               $unseen = Item::exists(['unseen' => true, 'id' => $idarray]);
                if ($unseen) {
                        Item::update(['unseen' => false], ['unseen' => true, 'id' => $idarray]);
                }
@@ -1761,8 +1686,8 @@ function api_statuses_public_timeline($type)
        $sql_extra = '';
 
        if ($exclude_replies && !$conversation_id) {
-               $condition = ["`verb` = ? AND `iid` > ? AND NOT `private` AND `wall` AND NOT `user`.`hidewall`",
-                       ACTIVITY_POST, $since_id];
+               $condition = ["`gravity` IN (?, ?) AND `iid` > ? AND NOT `private` AND `wall` AND NOT `user`.`hidewall`",
+                       GRAVITY_PARENT, GRAVITY_COMMENT, $since_id];
 
                if ($max_id > 0) {
                        $condition[0] .= " AND `thread`.`iid` <= ?";
@@ -1770,12 +1695,12 @@ function api_statuses_public_timeline($type)
                }
 
                $params = ['order' => ['iid' => true], 'limit' => [$start, $count]];
-               $statuses = Item::selectThread(api_user(), [], $condition, $params);
+               $statuses = Item::selectThreadForUser(api_user(), Item::DISPLAY_FIELDLIST, $condition, $params);
 
-               $r = dba::inArray($statuses);
+               $r = Item::inArray($statuses);
        } else {
-               $condition = ["`verb` = ? AND `id` > ? AND NOT `private` AND `wall` AND NOT `user`.`hidewall` AND `item`.`origin`",
-                       ACTIVITY_POST, $since_id];
+               $condition = ["`gravity` IN (?, ?) AND `id` > ? AND NOT `private` AND `wall` AND NOT `user`.`hidewall` AND `item`.`origin`",
+                       GRAVITY_PARENT, GRAVITY_COMMENT, $since_id];
 
                if ($max_id > 0) {
                        $condition[0] .= " AND `item`.`id` <= ?";
@@ -1787,9 +1712,9 @@ function api_statuses_public_timeline($type)
                }
 
                $params = ['order' => ['id' => true], 'limit' => [$start, $count]];
-               $statuses = Item::select(api_user(), [], $condition, $params);
+               $statuses = Item::selectForUser(api_user(), [], $condition, $params);
 
-               $r = dba::inArray($statuses);
+               $r = Item::inArray($statuses);
        }
 
        $ret = api_format_items($r, $user_info, false, $type);
@@ -1837,8 +1762,8 @@ function api_statuses_networkpublic_timeline($type)
        }
        $start = ($page - 1) * $count;
 
-       $condition = ["`uid` = 0 AND `verb` = ? AND `thread`.`iid` > ? AND NOT `private`",
-               ACTIVITY_POST, $since_id];
+       $condition = ["`uid` = 0 AND `gravity` IN (?, ?) AND `thread`.`iid` > ? AND NOT `private`",
+               GRAVITY_PARENT, GRAVITY_COMMENT, $since_id];
 
        if ($max_id > 0) {
                $condition[0] .= " AND `thread`.`iid` <= ?";
@@ -1846,9 +1771,9 @@ function api_statuses_networkpublic_timeline($type)
        }
 
        $params = ['order' => ['iid' => true], 'limit' => [$start, $count]];
-       $statuses = Item::selectThread(api_user(), [], $condition, $params);
+       $statuses = Item::selectThreadForUser(api_user(), Item::DISPLAY_FIELDLIST, $condition, $params);
 
-       $ret = api_format_items(dba::inArray($statuses), $user_info, false, $type);
+       $ret = api_format_items(Item::inArray($statuses), $user_info, false, $type);
 
        $data = ['status' => $ret];
        switch ($type) {
@@ -1881,50 +1806,50 @@ function api_statuses_show($type)
        }
 
        // params
-       $id = intval($a->argv[3]);
+       $id = intval(defaults($a->argv, 3, 0));
 
        if ($id == 0) {
-               $id = intval($_REQUEST["id"]);
+               $id = intval(defaults($_REQUEST, 'id', 0));
        }
 
        // Hotot workaround
        if ($id == 0) {
-               $id = intval($a->argv[4]);
+               $id = intval(defaults($a->argv, 4, 0));
        }
 
        logger('API: api_statuses_show: ' . $id);
 
-       $conversation = (x($_REQUEST, 'conversation') ? 1 : 0);
+       $conversation = !empty($_REQUEST['conversation']);
 
        // try to fetch the item for the local user - or the public item, if there is no local one
-       $uri_item = dba::selectFirst('item', ['uri'], ['id' => $id]);
-       if (!DBM::is_result($uri_item)) {
+       $uri_item = Item::selectFirst(['uri'], ['id' => $id]);
+       if (!DBA::isResult($uri_item)) {
                throw new BadRequestException("There is no status with this id.");
        }
 
-       $item = dba::selectFirst('item', ['id'], ['uri' => $uri_item['uri'], 'uid' => [0, api_user()]], ['order' => ['uid' => true]]);
-       if (!DBM::is_result($item)) {
+       $item = Item::selectFirst(['id'], ['uri' => $uri_item['uri'], 'uid' => [0, api_user()]], ['order' => ['uid' => true]]);
+       if (!DBA::isResult($item)) {
                throw new BadRequestException("There is no status with this id.");
        }
 
        $id = $item['id'];
 
        if ($conversation) {
-               $condition = ['parent' => $id, 'verb' => ACTIVITY_POST];
+               $condition = ['parent' => $id, 'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT]];
                $params = ['order' => ['id' => true]];
        } else {
-               $condition = ['id' => $id, 'verb' => ACTIVITY_POST];
+               $condition = ['id' => $id, 'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT]];
                $params = [];
        }
 
-       $statuses = Item::select(api_user(), [], $condition, $params);
+       $statuses = Item::selectForUser(api_user(), [], $condition, $params);
 
        /// @TODO How about copying this to above methods which don't check $r ?
-       if (!DBM::is_result($statuses)) {
+       if (!DBA::isResult($statuses)) {
                throw new BadRequestException("There is no status with this id.");
        }
 
-       $ret = api_format_items(dba::inArray($statuses), $user_info, false, $type);
+       $ret = api_format_items(Item::inArray($statuses), $user_info, false, $type);
 
        if ($conversation) {
                $data = ['status' => $ret];
@@ -1954,43 +1879,43 @@ function api_conversation_show($type)
        }
 
        // params
-       $id = intval($a->argv[3]);
-       $count = (x($_REQUEST, 'count') ? $_REQUEST['count'] : 20);
-       $page = (x($_REQUEST, 'page') ? $_REQUEST['page'] - 1 : 0);
+       $id       = intval(defaults($a->argv , 3         , 0));
+       $since_id = intval(defaults($_REQUEST, 'since_id', 0));
+       $max_id   = intval(defaults($_REQUEST, 'max_id'  , 0));
+       $count    = intval(defaults($_REQUEST, 'count'   , 20));
+       $page     = intval(defaults($_REQUEST, 'page'    , 1)) - 1;
        if ($page < 0) {
                $page = 0;
        }
-       $since_id = (x($_REQUEST, 'since_id') ? $_REQUEST['since_id'] : 0);
-       $max_id = (x($_REQUEST, 'max_id') ? $_REQUEST['max_id'] : 0);
 
-       $start = $page*$count;
+       $start = $page * $count;
 
        if ($id == 0) {
-               $id = intval($_REQUEST["id"]);
+               $id = intval(defaults($_REQUEST, 'id', 0));
        }
 
        // Hotot workaround
        if ($id == 0) {
-               $id = intval($a->argv[4]);
+               $id = intval(defaults($a->argv, 4, 0));
        }
 
        logger('API: api_conversation_show: '.$id);
 
        // try to fetch the item for the local user - or the public item, if there is no local one
-       $item = dba::selectFirst('item', ['parent-uri'], ['id' => $id]);
-       if (!DBM::is_result($item)) {
+       $item = Item::selectFirst(['parent-uri'], ['id' => $id]);
+       if (!DBA::isResult($item)) {
                throw new BadRequestException("There is no status with this id.");
        }
 
-       $parent = dba::selectFirst('item', ['id'], ['uri' => $item['parent-uri'], 'uid' => [0, api_user()]], ['order' => ['uid' => true]]);
-       if (!DBM::is_result($parent)) {
+       $parent = Item::selectFirst(['id'], ['uri' => $item['parent-uri'], 'uid' => [0, api_user()]], ['order' => ['uid' => true]]);
+       if (!DBA::isResult($parent)) {
                throw new BadRequestException("There is no status with this id.");
        }
 
        $id = $parent['id'];
 
-       $condition = ["`parent` = ? AND `uid` IN (0, ?) AND `verb` = ? AND `item`.`id` > ?",
-               $id, api_user(), ACTIVITY_POST, $since_id];
+       $condition = ["`parent` = ? AND `uid` IN (0, ?) AND `gravity` IN (?, ?) AND `item`.`id` > ?",
+               $id, api_user(), GRAVITY_PARENT, GRAVITY_COMMENT, $since_id];
 
        if ($max_id > 0) {
                $condition[0] .= " AND `item`.`id` <= ?";
@@ -1998,13 +1923,13 @@ function api_conversation_show($type)
        }
 
        $params = ['order' => ['id' => true], 'limit' => [$start, $count]];
-       $statuses = Item::select(api_user(), [], $condition, $params);
+       $statuses = Item::selectForUser(api_user(), [], $condition, $params);
 
-       if (!DBM::is_result($statuses)) {
+       if (!DBA::isResult($statuses)) {
                throw new BadRequestException("There is no status with id $id.");
        }
 
-       $ret = api_format_items(dba::inArray($statuses), $user_info, false, $type);
+       $ret = api_format_items(Item::inArray($statuses), $user_info, false, $type);
 
        $data = ['status' => $ret];
        return api_format_data("statuses", $type, $data);
@@ -2034,23 +1959,23 @@ function api_statuses_repeat($type)
        api_get_user($a);
 
        // params
-       $id = intval($a->argv[3]);
+       $id = intval(defaults($a->argv, 3, 0));
 
        if ($id == 0) {
-               $id = intval($_REQUEST["id"]);
+               $id = intval(defaults($_REQUEST, 'id', 0));
        }
 
        // Hotot workaround
        if ($id == 0) {
-               $id = intval($a->argv[4]);
+               $id = intval(defaults($a->argv, 4, 0));
        }
 
        logger('API: api_statuses_repeat: '.$id);
 
        $fields = ['body', 'author-name', 'author-link', 'author-avatar', 'guid', 'created', 'plink'];
-       $item = Item::selectFirst(api_user(), $fields, ['id' => $id, 'private' => false]);
+       $item = Item::selectFirst($fields, ['id' => $id, 'private' => false]);
 
-       if (DBM::is_result($item) && $item['body'] != "") {
+       if (DBA::isResult($item) && $item['body'] != "") {
                if (strpos($item['body'], "[/share]") !== false) {
                        $pos = strpos($item['body'], "[share");
                        $post = substr($item['body'], $pos);
@@ -2062,7 +1987,6 @@ function api_statuses_repeat($type)
                }
                $_REQUEST['body'] = $post;
                $_REQUEST['profile_uid'] = api_user();
-               $_REQUEST['type'] = 'wall';
                $_REQUEST['api_source'] = true;
 
                if (!x($_REQUEST, "source")) {
@@ -2100,15 +2024,15 @@ function api_statuses_destroy($type)
        api_get_user($a);
 
        // params
-       $id = intval($a->argv[3]);
+       $id = intval(defaults($a->argv, 3, 0));
 
        if ($id == 0) {
-               $id = intval($_REQUEST["id"]);
+               $id = intval(defaults($_REQUEST, 'id', 0));
        }
 
        // Hotot workaround
        if ($id == 0) {
-               $id = intval($a->argv[4]);
+               $id = intval(defaults($a->argv, 4, 0));
        }
 
        logger('API: api_statuses_destroy: '.$id);
@@ -2158,9 +2082,9 @@ function api_statuses_mentions($type)
 
        $start = ($page - 1) * $count;
 
-       $condition = ["`uid` = ? AND `verb` = ? AND `item`.`id` > ? AND `author-id` != ?
-               AND `item`.`parent` IN (SELECT `iid` FROM `thread` WHERE `uid` = ? AND `mention` AND NOT `ignored`)",
-               api_user(), ACTIVITY_POST, $since_id, $user_info['pid'], api_user()];
+       $condition = ["`uid` = ? AND `gravity` IN (?, ?) AND `item`.`id` > ? AND `author-id` != ?
+               AND `item`.`parent` IN (SELECT `iid` FROM `thread` WHERE `thread`.`uid` = ? AND `thread`.`mention` AND NOT `thread`.`ignored`)",
+               api_user(), GRAVITY_PARENT, GRAVITY_COMMENT, $since_id, $user_info['pid'], api_user()];
 
        if ($max_id > 0) {
                $condition[0] .= " AND `item`.`id` <= ?";
@@ -2168,9 +2092,9 @@ function api_statuses_mentions($type)
        }
 
        $params = ['order' => ['id' => true], 'limit' => [$start, $count]];
-       $statuses = Item::select(api_user(), [], $condition, $params);
+       $statuses = Item::selectForUser(api_user(), [], $condition, $params);
 
-       $ret = api_format_items(dba::inArray($statuses), $user_info, false, $type);
+       $ret = api_format_items(Item::inArray($statuses), $user_info, false, $type);
 
        $data = ['status' => $ret];
        switch ($type) {
@@ -2226,8 +2150,8 @@ function api_statuses_user_timeline($type)
        }
        $start = ($page - 1) * $count;
 
-       $condition = ["`uid` = ? AND `verb` = ? AND `item`.`id` > ? AND `item`.`contact-id` = ?",
-               api_user(), ACTIVITY_POST, $since_id, $user_info['cid']];
+       $condition = ["`uid` = ? AND `gravity` IN (?, ?) AND `item`.`id` > ? AND `item`.`contact-id` = ?",
+               api_user(), GRAVITY_PARENT, GRAVITY_COMMENT, $since_id, $user_info['cid']];
 
        if ($user_info['self'] == 1) {
                $condition[0] .= ' AND `item`.`wall` ';
@@ -2248,9 +2172,9 @@ function api_statuses_user_timeline($type)
        }
 
        $params = ['order' => ['id' => true], 'limit' => [$start, $count]];
-       $statuses = Item::select(api_user(), [], $condition, $params);
+       $statuses = Item::selectForUser(api_user(), [], $condition, $params);
 
-       $ret = api_format_items(dba::inArray($statuses), $user_info, true, $type);
+       $ret = api_format_items(Item::inArray($statuses), $user_info, true, $type);
 
        $data = ['status' => $ret];
        switch ($type) {
@@ -2285,7 +2209,7 @@ function api_favorites_create_destroy($type)
        // for versioned api.
        /// @TODO We need a better global soluton
        $action_argv_id = 2;
-       if ($a->argv[1] == "1.1") {
+       if (count($a->argv) > 1 && $a->argv[1] == "1.1") {
                $action_argv_id = 3;
        }
 
@@ -2294,15 +2218,14 @@ function api_favorites_create_destroy($type)
        }
        $action = str_replace("." . $type, "", $a->argv[$action_argv_id]);
        if ($a->argc == $action_argv_id + 2) {
-               $itemid = intval($a->argv[$action_argv_id + 1]);
+               $itemid = intval(defaults($a->argv, $action_argv_id + 1, 0));
        } else {
-               ///  @TODO use x() to check if _REQUEST contains 'id'
-               $itemid = intval($_REQUEST['id']);
+               $itemid = intval(defaults($_REQUEST, 'id', 0));
        }
 
-       $item = Item::selectFirst(api_user(), [], ['id' => $itemid, 'uid' => api_user()]);
+       $item = Item::selectFirstForUser(api_user(), [], ['id' => $itemid, 'uid' => api_user()]);
 
-       if (!DBM::is_result($item)) {
+       if (!DBA::isResult($item)) {
                throw new BadRequestException("Invalid item.");
        }
 
@@ -2380,8 +2303,8 @@ function api_favorites($type)
 
                $start = $page*$count;
 
-               $condition = ["`uid` = ? AND `verb` = ? AND `id` > ? AND `starred`",
-                       api_user(), ACTIVITY_POST, $since_id];
+               $condition = ["`uid` = ? AND `gravity` IN (?, ?) AND `id` > ? AND `starred`",
+                       api_user(), GRAVITY_PARENT, GRAVITY_COMMENT, $since_id];
 
                $params = ['order' => ['id' => true], 'limit' => [$start, $count]];
 
@@ -2390,9 +2313,9 @@ function api_favorites($type)
                        $condition[] = $max_id;
                }
 
-               $statuses = Item::select(api_user(), [], $condition, $params);
+               $statuses = Item::selectForUser(api_user(), [], $condition, $params);
 
-               $ret = api_format_items(dba::inArray($statuses), $user_info, false, $type);
+               $ret = api_format_items(Item::inArray($statuses), $user_info, false, $type);
        }
 
        $data = ['status' => $ret];
@@ -2420,25 +2343,33 @@ function api_format_messages($item, $recipient, $sender)
 {
        // standard meta information
        $ret = [
-                       'id'                    => $item['id'],
-                       'sender_id'             => $sender['id'] ,
-                       'text'                  => "",
-                       'recipient_id'          => $recipient['id'],
-                       'created_at'            => api_date($item['created']),
-                       'sender_screen_name'    => $sender['screen_name'],
-                       'recipient_screen_name' => $recipient['screen_name'],
-                       'sender'                => $sender,
-                       'recipient'             => $recipient,
-                       'title'                 => "",
-                       'friendica_seen'        => $item['seen'],
-                       'friendica_parent_uri'  => $item['parent-uri'],
+               'id'                    => $item['id'],
+               'sender_id'             => $sender['id'] ,
+               'text'                  => "",
+               'recipient_id'          => $recipient['id'],
+               'created_at'            => api_date(defaults($item, 'created', DateTimeFormat::utcNow())),
+               'sender_screen_name'    => $sender['screen_name'],
+               'recipient_screen_name' => $recipient['screen_name'],
+               'sender'                => $sender,
+               'recipient'             => $recipient,
+               'title'                 => "",
+               'friendica_seen'        => defaults($item, 'seen', 0),
+               'friendica_parent_uri'  => defaults($item, 'parent-uri', ''),
        ];
 
        // "uid" and "self" are only needed for some internal stuff, so remove it from here
-       unset($ret["sender"]["uid"]);
-       unset($ret["sender"]["self"]);
-       unset($ret["recipient"]["uid"]);
-       unset($ret["recipient"]["self"]);
+       if (isset($ret['sender']['uid'])) {
+               unset($ret['sender']['uid']);
+       }
+       if (isset($ret['sender']['self'])) {
+               unset($ret['sender']['self']);
+       }
+       if (isset($ret['recipient']['uid'])) {
+               unset($ret['recipient']['uid']);
+       }
+       if (isset($ret['recipient']['self'])) {
+               unset($ret['recipient']['self']);
+       }
 
        //don't send title to regular StatusNET requests to avoid confusing these apps
        if (x($_GET, 'getText')) {
@@ -2485,8 +2416,8 @@ function api_convert_item($item)
                $statustext = trim($statustitle."\n\n".$statusbody);
        }
 
-       if (($item["network"] == NETWORK_FEED) && (strlen($statustext)> 1000)) {
-               $statustext = substr($statustext, 0, 1000)."... \n".$item["plink"];
+       if ((defaults($item, 'network', Protocol::PHANTOM) == Protocol::FEED) && (strlen($statustext)> 1000)) {
+               $statustext = substr($statustext, 0, 1000) . "... \n" . defaults($item, 'plink', '');
        }
 
        $statushtml = BBCode::convert(api_clean_attachments($body), false);
@@ -2520,7 +2451,7 @@ function api_convert_item($item)
        }
 
        // feeds without body should contain the link
-       if (($item['network'] == NETWORK_FEED) && (strlen($item['body']) == 0)) {
+       if ((defaults($item, 'network', Protocol::PHANTOM) == Protocol::FEED) && (strlen($item['body']) == 0)) {
                $statushtml .= BBCode::convert($item['plink']);
        }
 
@@ -2562,7 +2493,7 @@ function api_get_attachments(&$body)
                }
        }
 
-       if (strstr($_SERVER['HTTP_USER_AGENT'], "AndStatus")) {
+       if (strstr(defaults($_SERVER, 'HTTP_USER_AGENT', ''), "AndStatus")) {
                foreach ($images[0] as $orig) {
                        $body = str_replace($orig, "", $body);
                }
@@ -2587,7 +2518,7 @@ function api_get_entitities(&$text, $bbcode)
                preg_match_all("/\[img](.*?)\[\/img\]/ism", $bbcode, $images);
 
                foreach ($images[1] as $image) {
-                       $replace = proxy_url($image);
+                       $replace = ProxyUtils::proxifyUrl($image);
                        $text = str_replace($image, $replace, $text);
                }
                return [];
@@ -2696,7 +2627,7 @@ function api_get_entitities(&$text, $bbcode)
                                // If image cache is activated, then use the following sizes:
                                // thumb  (150), small (340), medium (600) and large (1024)
                                if (!Config::get("system", "proxy_disabled")) {
-                                       $media_url = proxy_url($url);
+                                       $media_url = ProxyUtils::proxifyUrl($url);
 
                                        $sizes = [];
                                        $scale = Image::getScalingDimensions($image[0], $image[1], 150);
@@ -2806,20 +2737,16 @@ function api_format_items_activities(&$item, $type = "json")
                'attendmaybe' => [],
        ];
 
-       $items = q(
-               'SELECT * FROM `item`
-                       WHERE `uid` = %d AND `thr-parent` = "%s" AND `visible` AND NOT `deleted`',
-               intval($item['uid']),
-               dbesc($item['uri'])
-       );
+       $condition = ['uid' => $item['uid'], 'thr-parent' => $item['uri']];
+       $ret = Item::selectForUser($item['uid'], ['author-id', 'verb'], $condition);
 
-       foreach ($items as $i) {
+       while ($item = Item::fetch($ret)) {
                // not used as result should be structured like other user data
                //builtin_activity_puller($i, $activities);
 
                // get user data and add it to the array of the activity
-               $user = api_get_user($a, $i['author-id']);
-               switch ($i['verb']) {
+               $user = api_get_user($a, $item['author-id']);
+               switch ($item['verb']) {
                        case ACTIVITY_LIKE:
                                $activities['like'][] = $user;
                                break;
@@ -2840,6 +2767,8 @@ function api_format_items_activities(&$item, $type = "json")
                }
        }
 
+       DBA::close($ret);
+
        if ($type == "xml") {
                $xml_activities = [];
                foreach ($activities as $k => $v) {
@@ -3118,7 +3047,7 @@ function api_lists_ownerships($type)
        $user_info = api_get_user($a);
        $uid = $user_info['uid'];
 
-       $groups = dba::select('group', [], ['deleted' => 0, 'uid' => $uid]);
+       $groups = DBA::select('group', [], ['deleted' => 0, 'uid' => $uid]);
 
        // loop through all groups
        $lists = [];
@@ -3182,8 +3111,8 @@ function api_lists_statuses($type)
 
        $start = $page * $count;
 
-       $condition = ["`uid` = ? AND `verb` = ? AND `id` > ? AND `group_member`.`gid` = ?",
-               api_user(), ACTIVITY_POST, $since_id, $_REQUEST['list_id']];
+       $condition = ["`uid` = ? AND `gravity` IN (?, ?) AND `id` > ? AND `group_member`.`gid` = ?",
+               api_user(), GRAVITY_PARENT, GRAVITY_COMMENT, $since_id, $_REQUEST['list_id']];
 
        if ($max_id > 0) {
                $condition[0] .= " AND `item`.`id` <= ?";
@@ -3198,9 +3127,9 @@ function api_lists_statuses($type)
        }
 
        $params = ['order' => ['id' => true], 'limit' => [$start, $count]];
-       $statuses = Item::select(api_user(), [], $condition, $params);
+       $statuses = Item::selectForUser(api_user(), [], $condition, $params);
 
-       $items = api_format_items(dba::inArray($statuses), $user_info, false, $type);
+       $items = api_format_items(Item::inArray($statuses), $user_info, false, $type);
 
        $data = ['status' => $items];
        switch ($type) {
@@ -3257,9 +3186,9 @@ function api_statuses_f($qtype)
 
        $sql_extra = '';
        if ($qtype == 'friends') {
-               $sql_extra = sprintf(" AND ( `rel` = %d OR `rel` = %d ) ", intval(CONTACT_IS_SHARING), intval(CONTACT_IS_FRIEND));
+               $sql_extra = sprintf(" AND ( `rel` = %d OR `rel` = %d ) ", intval(Contact::SHARING), intval(Contact::FRIEND));
        } elseif ($qtype == 'followers') {
-               $sql_extra = sprintf(" AND ( `rel` = %d OR `rel` = %d ) ", intval(CONTACT_IS_FOLLOWER), intval(CONTACT_IS_FRIEND));
+               $sql_extra = sprintf(" AND ( `rel` = %d OR `rel` = %d ) ", intval(Contact::FOLLOWER), intval(Contact::FRIEND));
        }
 
        // friends and followers only for self
@@ -3406,18 +3335,15 @@ function api_statusnet_config($type)
 {
        $a = get_app();
 
-       $name = $a->config['sitename'];
-       $server = $a->get_hostname();
-       $logo = System::baseUrl() . '/images/friendica-64.png';
-       $email = $a->config['admin_email'];
-       $closed = (($a->config['register_policy'] == REGISTER_CLOSED) ? 'true' : 'false');
-       $private = ((Config::get('system', 'block_public')) ? 'true' : 'false');
-       $textlimit = (string) (($a->config['max_import_size']) ? $a->config['max_import_size'] : 200000);
-       if ($a->config['api_import_size']) {
-               $textlimit = (string) $a->config['api_import_size'];
-       }
-       $ssl = ((Config::get('system', 'have_ssl')) ? 'true' : 'false');
-       $sslserver = (($ssl === 'true') ? str_replace('http:', 'https:', System::baseUrl()) : '');
+       $name      = Config::get('config', 'sitename');
+       $server    = $a->get_hostname();
+       $logo      = System::baseUrl() . '/images/friendica-64.png';
+       $email     = Config::get('config', 'admin_email');
+       $closed    = intval(Config::get('config', 'register_policy')) === REGISTER_CLOSED ? 'true' : 'false';
+       $private   = Config::get('system', 'block_public') ? 'true' : 'false';
+       $textlimit = (string) Config::get('config', 'api_import_size', Config::get('config', 'max_import_size', 200000));
+       $ssl       = Config::get('system', 'have_ssl') ? 'true' : 'false';
+       $sslserver = Config::get('system', 'have_ssl') ? str_replace('http:', 'https:', System::baseUrl()) : '';
 
        $config = [
                'site' => ['name' => $name,'server' => $server, 'theme' => 'default', 'path' => '',
@@ -3483,7 +3409,7 @@ function api_ff_ids($type)
                        WHERE `contact`.`uid` = %s AND NOT `contact`.`self`",
                intval(api_user())
        );
-       if (!DBM::is_result($r)) {
+       if (!DBA::isResult($r)) {
                return;
        }
 
@@ -3539,34 +3465,40 @@ api_register_func('api/followers/ids', 'api_followers_ids', true);
  */
 function api_direct_messages_new($type)
 {
-
        $a = get_app();
 
        if (api_user() === false) {
                throw new ForbiddenException();
        }
 
-       if (!x($_POST, "text") || (!x($_POST, "screen_name") && !x($_POST, "user_id"))) {
+       if (empty($_POST["text"]) || empty($_POST["screen_name"]) && empty($_POST["user_id"])) {
                return;
        }
 
        $sender = api_get_user($a);
 
-       if ($_POST['screen_name']) {
+       $recipient = null;
+       if (!empty($_POST['screen_name'])) {
                $r = q(
                        "SELECT `id`, `nurl`, `network` FROM `contact` WHERE `uid`=%d AND `nick`='%s'",
                        intval(api_user()),
-                       dbesc($_POST['screen_name'])
+                       DBA::escape($_POST['screen_name'])
                );
 
-               // Selecting the id by priority, friendica first
-               api_best_nickname($r);
+               if (DBA::isResult($r)) {
+                       // Selecting the id by priority, friendica first
+                       api_best_nickname($r);
 
-               $recipient = api_get_user($a, $r[0]['nurl']);
+                       $recipient = api_get_user($a, $r[0]['nurl']);
+               }
        } else {
                $recipient = api_get_user($a, $_POST['user_id']);
        }
 
+       if (empty($recipient)) {
+               throw new NotFoundException('Recipient not found');
+       }
+
        $replyto = '';
        $sub     = '';
        if (x($_REQUEST, 'replyto')) {
@@ -3647,7 +3579,7 @@ function api_direct_messages_destroy($type)
        }
 
        // add parent-uri to sql command if specified by calling app
-       $sql_extra = ($parenturi != "" ? " AND `parent-uri` = '" . dbesc($parenturi) . "'" : "");
+       $sql_extra = ($parenturi != "" ? " AND `parent-uri` = '" . DBA::escape($parenturi) . "'" : "");
 
        // get data of the specified message id
        $r = q(
@@ -3657,7 +3589,7 @@ function api_direct_messages_destroy($type)
        );
 
        // error message if specified id is not in database
-       if (!DBM::is_result($r)) {
+       if (!DBA::isResult($r)) {
                if ($verbose == "true") {
                        $answer = ['result' => 'error', 'message' => 'message id not in database'];
                        return api_format_data("direct_messages_delete", $type, ['$result' => $answer]);
@@ -3700,24 +3632,21 @@ api_register_func('api/direct_messages/destroy', 'api_direct_messages_destroy',
 function api_direct_messages_box($type, $box, $verbose)
 {
        $a = get_app();
-       $user_info = api_get_user($a);
-
-       if (api_user() === false || $user_info === false) {
+       if (api_user() === false) {
                throw new ForbiddenException();
        }
-
        // params
-       $count = (x($_GET, 'count') ? $_GET['count'] : 20);
-       $page = (x($_REQUEST, 'page') ? $_REQUEST['page'] -1 : 0);
+       $count = defaults($_GET, 'count', 20);
+       $page = defaults($_REQUEST, 'page', 1) - 1;
        if ($page < 0) {
                $page = 0;
        }
 
-       $since_id = (x($_REQUEST, 'since_id') ? $_REQUEST['since_id'] : 0);
-       $max_id = (x($_REQUEST, 'max_id') ? $_REQUEST['max_id'] : 0);
+       $since_id = defaults($_REQUEST, 'since_id', 0);
+       $max_id = defaults($_REQUEST, 'max_id', 0);
 
-       $user_id = (x($_REQUEST, 'user_id') ? $_REQUEST['user_id'] : "");
-       $screen_name = (x($_REQUEST, 'screen_name') ? $_REQUEST['screen_name'] : "");
+       $user_id = defaults($_REQUEST, 'user_id', '');
+       $screen_name = defaults($_REQUEST, 'screen_name', '');
 
        //  caller user info
        unset($_REQUEST["user_id"]);
@@ -3726,6 +3655,10 @@ function api_direct_messages_box($type, $box, $verbose)
        unset($_REQUEST["screen_name"]);
        unset($_GET["screen_name"]);
 
+       $user_info = api_get_user($a);
+       if ($user_info === false) {
+               throw new ForbiddenException();
+       }
        $profile_url = $user_info["url"];
 
        // pagination
@@ -3735,13 +3668,13 @@ function api_direct_messages_box($type, $box, $verbose)
 
        // filters
        if ($box=="sentbox") {
-               $sql_extra = "`mail`.`from-url`='" . dbesc($profile_url) . "'";
+               $sql_extra = "`mail`.`from-url`='" . DBA::escape($profile_url) . "'";
        } elseif ($box == "conversation") {
-               $sql_extra = "`mail`.`parent-uri`='" . dbesc($_GET["uri"])  . "'";
+               $sql_extra = "`mail`.`parent-uri`='" . DBA::escape(defaults($_GET, 'uri', ''))  . "'";
        } elseif ($box == "all") {
                $sql_extra = "true";
        } elseif ($box == "inbox") {
-               $sql_extra = "`mail`.`from-url`!='" . dbesc($profile_url) . "'";
+               $sql_extra = "`mail`.`from-url`!='" . DBA::escape($profile_url) . "'";
        }
 
        if ($max_id > 0) {
@@ -3751,7 +3684,7 @@ function api_direct_messages_box($type, $box, $verbose)
        if ($user_id != "") {
                $sql_extra .= ' AND `mail`.`contact-id` = ' . intval($user_id);
        } elseif ($screen_name !="") {
-               $sql_extra .= " AND `contact`.`nick` = '" . dbesc($screen_name). "'";
+               $sql_extra .= " AND `contact`.`nick` = '" . DBA::escape($screen_name). "'";
        }
 
        $r = q(
@@ -3761,7 +3694,7 @@ function api_direct_messages_box($type, $box, $verbose)
                intval($start),
                intval($count)
        );
-       if ($verbose == "true" && !DBM::is_result($r)) {
+       if ($verbose == "true" && !DBA::isResult($r)) {
                $answer = ['result' => 'error', 'message' => 'no mails available'];
                return api_format_data("direct_messages_all", $type, ['$result' => $answer]);
        }
@@ -3914,29 +3847,26 @@ function api_fr_photoalbum_delete($type)
        $r = q(
                "SELECT DISTINCT `resource-id` FROM `photo` WHERE `uid` = %d AND `album` = '%s'",
                intval(api_user()),
-               dbesc($album)
+               DBA::escape($album)
        );
-       if (!DBM::is_result($r)) {
+       if (!DBA::isResult($r)) {
                throw new BadRequestException("album not available");
        }
 
        // function for setting the items to "deleted = 1" which ensures that comments, likes etc. are not shown anymore
        // to the user and the contacts of the users (drop_items() performs the federation of the deletion to other networks
        foreach ($r as $rr) {
-               $photo_item = q(
-                       "SELECT `id` FROM `item` WHERE `uid` = %d AND `resource-id` = '%s' AND `type` = 'photo'",
-                       intval(local_user()),
-                       dbesc($rr['resource-id'])
-               );
+               $condition = ['uid' => local_user(), 'resource-id' => $rr['resource-id'], 'type' => 'photo'];
+               $photo_item = Item::selectFirstForUser(local_user(), ['id'], $condition);
 
-               if (!DBM::is_result($photo_item)) {
+               if (!DBA::isResult($photo_item)) {
                        throw new InternalServerErrorException("problem with deleting items occured");
                }
-               Item::deleteForUser(['id' => $photo_item[0]['id']], api_user());
+               Item::deleteForUser(['id' => $photo_item['id']], api_user());
        }
 
        // now let's delete all photos from the album
-       $result = dba::delete('photo', ['uid' => api_user(), 'album' => $album]);
+       $result = DBA::delete('photo', ['uid' => api_user(), 'album' => $album]);
 
        // return success of deletion or error message
        if ($result) {
@@ -3970,11 +3900,11 @@ function api_fr_photoalbum_update($type)
                throw new BadRequestException("no new albumname specified");
        }
        // check if album is existing
-       if (!dba::exists('photo', ['uid' => api_user(), 'album' => $album])) {
+       if (!DBA::exists('photo', ['uid' => api_user(), 'album' => $album])) {
                throw new BadRequestException("album not available");
        }
        // now let's update all photos to the albumname
-       $result = dba::update('photo', ['album' => $album_new], ['uid' => api_user(), 'album' => $album]);
+       $result = DBA::update('photo', ['album' => $album_new], ['uid' => api_user(), 'album' => $album]);
 
        // return success of updating or error message
        if ($result) {
@@ -4009,7 +3939,7 @@ function api_fr_photos_list($type)
                'image/gif' => 'gif'
        ];
        $data = ['photo'=>[]];
-       if (DBM::is_result($r)) {
+       if (DBA::isResult($r)) {
                foreach ($r as $rr) {
                        $photo = [];
                        $photo['id'] = $rr['resource-id'];
@@ -4078,10 +4008,10 @@ function api_fr_photo_create_update($type)
                $r = q(
                        "SELECT `id` FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s' AND `album` = '%s'",
                        intval(api_user()),
-                       dbesc($photo_id),
-                       dbesc($album)
+                       DBA::escape($photo_id),
+                       DBA::escape($album)
                );
-               if (!DBM::is_result($r)) {
+               if (!DBA::isResult($r)) {
                        throw new BadRequestException("photo not available");
                }
        }
@@ -4148,8 +4078,8 @@ function api_fr_photo_create_update($type)
                                $sql_extra,
                                DateTimeFormat::utcNow(),   // update edited timestamp
                                intval(api_user()),
-                               dbesc($photo_id),
-                               dbesc($album)
+                               DBA::escape($photo_id),
+                               DBA::escape($album)
                        );
                } else {
                        $nothingtodo = true;
@@ -4202,29 +4132,26 @@ function api_fr_photo_delete($type)
        $r = q(
                "SELECT `id` FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s'",
                intval(api_user()),
-               dbesc($photo_id)
+               DBA::escape($photo_id)
        );
-       if (!DBM::is_result($r)) {
+       if (!DBA::isResult($r)) {
                throw new BadRequestException("photo not available");
        }
        // now we can perform on the deletion of the photo
-       $result = dba::delete('photo', ['uid' => api_user(), 'resource-id' => $photo_id]);
+       $result = DBA::delete('photo', ['uid' => api_user(), 'resource-id' => $photo_id]);
 
        // return success of deletion or error message
        if ($result) {
                // retrieve the id of the parent element (the photo element)
-               $photo_item = q(
-                       "SELECT `id` FROM `item` WHERE `uid` = %d AND `resource-id` = '%s' AND `type` = 'photo'",
-                       intval(local_user()),
-                       dbesc($photo_id)
-               );
+               $condition = ['uid' => local_user(), 'resource-id' => $photo_id, 'type' => 'photo'];
+               $photo_item = Item::selectFirstForUser(local_user(), ['id'], $condition);
 
-               if (!DBM::is_result($photo_item)) {
+               if (!DBA::isResult($photo_item)) {
                        throw new InternalServerErrorException("problem with deleting items occured");
                }
                // function for setting the items to "deleted = 1" which ensures that comments, likes etc. are not shown anymore
                // to the user and the contacts of the users (drop_items() do all the necessary magic to avoid orphans in database and federate deletion)
-               Item::deleteForUser(['id' => $photo_item[0]['id']], api_user());
+               Item::deleteForUser(['id' => $photo_item['id']], api_user());
 
                $answer = ['result' => 'deleted', 'message' => 'photo with id `' . $photo_id . '` has been deleted from server.'];
                return api_format_data("photo_delete", $type, ['$result' => $answer]);
@@ -4284,9 +4211,9 @@ 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' => api_user(), 'id' => $profile_id]);
+               $profile = DBA::selectFirst('profile', ['is-default'], ['uid' => api_user(), 'id' => $profile_id]);
                // error message if specified profile id is not in database
-               if (!DBM::is_result($profile)) {
+               if (!DBA::isResult($profile)) {
                        throw new BadRequestException("profile_id not available");
                }
                $is_default_profile = $profile['is-default'];
@@ -4321,11 +4248,11 @@ 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'], api_user()];
-               dba::update('photo', ['profile' => false], $condition);
+               DBA::update('photo', ['profile' => false], $condition);
        } else {
                $fields = ['photo' => System::baseUrl() . '/photo/' . $data['photo']['id'] . '-4.' . $filetype,
                        'thumb' => System::baseUrl() . '/photo/' . $data['photo']['id'] . '-5.' . $filetype];
-               dba::update('profile', $fields, ['id' => $_REQUEST['profile'], 'uid' => api_user()]);
+               DBA::update('profile', $fields, ['id' => $_REQUEST['profile'], 'uid' => api_user()]);
        }
 
        Contact::updateSelfFromUserID(api_user(), true);
@@ -4370,16 +4297,16 @@ function api_account_update_profile($type)
        $api_user = api_get_user(get_app());
 
        if (!empty($_POST['name'])) {
-               dba::update('profile', ['name' => $_POST['name']], ['uid' => $local_user]);
-               dba::update('user', ['username' => $_POST['name']], ['uid' => $local_user]);
-               dba::update('contact', ['name' => $_POST['name']], ['uid' => $local_user, 'self' => 1]);
-               dba::update('contact', ['name' => $_POST['name']], ['id' => $api_user['id']]);
+               DBA::update('profile', ['name' => $_POST['name']], ['uid' => $local_user]);
+               DBA::update('user', ['username' => $_POST['name']], ['uid' => $local_user]);
+               DBA::update('contact', ['name' => $_POST['name']], ['uid' => $local_user, 'self' => 1]);
+               DBA::update('contact', ['name' => $_POST['name']], ['id' => $api_user['id']]);
        }
 
        if (isset($_POST['description'])) {
-               dba::update('profile', ['about' => $_POST['description']], ['uid' => $local_user]);
-               dba::update('contact', ['about' => $_POST['description']], ['uid' => $local_user, 'self' => 1]);
-               dba::update('contact', ['about' => $_POST['description']], ['id' => $api_user['id']]);
+               DBA::update('profile', ['about' => $_POST['description']], ['uid' => $local_user]);
+               DBA::update('contact', ['about' => $_POST['description']], ['uid' => $local_user, 'self' => 1]);
+               DBA::update('contact', ['about' => $_POST['description']], ['id' => $api_user['id']]);
        }
 
        Worker::add(PRIORITY_LOW, 'ProfileUpdate', $local_user);
@@ -4418,7 +4345,7 @@ function check_acl_input($acl_string)
                        intval($cid),
                        intval(api_user())
                );
-               $contact_not_found |= !DBM::is_result($contact);
+               $contact_not_found |= !DBA::isResult($contact);
        }
        return $contact_not_found;
 }
@@ -4599,11 +4526,11 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $
 function post_photo_item($hash, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $filetype, $visibility = false)
 {
        // get data about the api authenticated user
-       $uri = item_new_uri(get_app()->get_hostname(), intval(api_user()));
+       $uri = Item::newURI(intval(api_user()));
        $owner_record = q("SELECT * FROM `contact` WHERE `uid`= %d AND `self` LIMIT 1", intval(api_user()));
 
        $arr = [];
-       $arr['guid']          = get_guid(32);
+       $arr['guid']          = System::createGUID(32);
        $arr['uid']           = intval(api_user());
        $arr['uri']           = $uri;
        $arr['parent-uri']    = $uri;
@@ -4669,7 +4596,7 @@ function prepare_photo_data($type, $scale, $photo_id)
                        FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s' %s GROUP BY `resource-id`",
                $data_sql,
                intval(local_user()),
-               dbesc($photo_id),
+               DBA::escape($photo_id),
                $scale_sql
        );
 
@@ -4680,7 +4607,7 @@ function prepare_photo_data($type, $scale, $photo_id)
        ];
 
        // prepare output data for photo
-       if (DBM::is_result($r)) {
+       if (DBA::isResult($r)) {
                $data = ['photo' => $r[0]];
                $data['photo']['id'] = $data['photo']['resource-id'];
                if ($scale !== false) {
@@ -4712,21 +4639,19 @@ function prepare_photo_data($type, $scale, $photo_id)
        }
 
        // retrieve item element for getting activities (like, dislike etc.) related to photo
-       $item = q(
-               "SELECT * FROM `item` WHERE `uid` = %d AND `resource-id` = '%s' AND `type` = 'photo'",
-               intval(local_user()),
-               dbesc($photo_id)
-       );
-       $data['photo']['friendica_activities'] = api_format_items_activities($item[0], $type);
+       $condition = ['uid' => local_user(), 'resource-id' => $photo_id, 'type' => 'photo'];
+       $item = Item::selectFirstForUser(local_user(), ['id'], $condition);
+
+       $data['photo']['friendica_activities'] = api_format_items_activities($item, $type);
 
        // retrieve comments on photo
-       $condition = ["`parent` = ? AND `uid` = ? AND (`verb` = ? OR `type`='photo')",
-               $item[0]['parent'], api_user(), ACTIVITY_POST];
+       $condition = ["`parent` = ? AND `uid` = ? AND (`gravity` IN (?, ?) OR `type`='photo')",
+               $item[0]['parent'], api_user(), GRAVITY_PARENT, GRAVITY_COMMENT];
 
-       $statuses = Item::select(api_user(), [], $condition);
+       $statuses = Item::selectForUser(api_user(), [], $condition);
 
        // prepare output of comments
-       $commentData = api_format_items(dba::inArray($statuses), $user_info, false, $type);
+       $commentData = api_format_items(Item::inArray($statuses), $user_info, false, $type);
        $comments = [];
        if ($type == "xml") {
                $k = 0;
@@ -4775,9 +4700,9 @@ function api_friendica_remoteauth()
 
        // traditional DFRN
 
-       $contact = dba::selectFirst('contact', [], ['uid' => api_user(), 'nurl' => $c_url]);
+       $contact = DBA::selectFirst('contact', [], ['uid' => api_user(), 'nurl' => $c_url]);
 
-       if (!DBM::is_result($contact) || ($contact['network'] !== NETWORK_DFRN)) {
+       if (!DBA::isResult($contact) || ($contact['network'] !== NETWORK_DFRN)) {
                throw new BadRequestException("Unknown contact");
        }
 
@@ -4798,7 +4723,7 @@ function api_friendica_remoteauth()
 
        $fields = ['uid' => api_user(), 'cid' => $cid, 'dfrn_id' => $dfrn_id,
                'sec' => $sec, 'expire' => time() + 45];
-       dba::insert('profile_check', $fields);
+       DBA::insert('profile_check', $fields);
 
        logger($contact['name'] . ' ' . $sec, LOGGER_DEBUG);
        $dest = ($url ? '&destination_url=' . $url : '');
@@ -4925,20 +4850,20 @@ function api_get_nick($profile)
 
        $r = q(
                "SELECT `nick` FROM `contact` WHERE `uid` = 0 AND `nurl` = '%s'",
-               dbesc(normalise_link($profile))
+               DBA::escape(normalise_link($profile))
        );
 
-       if (DBM::is_result($r)) {
+       if (DBA::isResult($r)) {
                $nick = $r[0]["nick"];
        }
 
        if (!$nick == "") {
                $r = q(
                        "SELECT `nick` FROM `contact` WHERE `uid` = 0 AND `nurl` = '%s'",
-                       dbesc(normalise_link($profile))
+                       DBA::escape(normalise_link($profile))
                );
 
-               if (DBM::is_result($r)) {
+               if (DBA::isResult($r)) {
                        $nick = $r[0]["nick"];
                }
        }
@@ -5012,35 +4937,26 @@ function api_in_reply_to($item)
        $in_reply_to['screen_name'] = null;
 
        if (($item['thr-parent'] != $item['uri']) && (intval($item['parent']) != intval($item['id']))) {
-               $r = q(
-                       "SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s' LIMIT 1",
-                       intval($item['uid']),
-                       dbesc($item['thr-parent'])
-               );
-
-               if (DBM::is_result($r)) {
-                       $in_reply_to['status_id'] = intval($r[0]['id']);
+               $parent = Item::selectFirst(['id'], ['uid' => $item['uid'], 'uri' => $item['thr-parent']]);
+               if (DBA::isResult($parent)) {
+                       $in_reply_to['status_id'] = intval($parent['id']);
                } else {
                        $in_reply_to['status_id'] = intval($item['parent']);
                }
 
                $in_reply_to['status_id_str'] = (string) intval($in_reply_to['status_id']);
 
-               $r = q(
-                       "SELECT `contact`.`nick`, `contact`.`name`, `contact`.`id`, `contact`.`url` FROM `item`
-                       STRAIGHT_JOIN `contact` ON `contact`.`id` = `item`.`author-id`
-                       WHERE `item`.`id` = %d LIMIT 1",
-                       intval($in_reply_to['status_id'])
-               );
+               $fields = ['author-nick', 'author-name', 'author-id', 'author-link'];
+               $parent = Item::selectFirst($fields, ['id' => $in_reply_to['status_id']]);
 
-               if (DBM::is_result($r)) {
-                       if ($r[0]['nick'] == "") {
-                               $r[0]['nick'] = api_get_nick($r[0]["url"]);
+               if (DBA::isResult($parent)) {
+                       if ($parent['author-nick'] == "") {
+                               $parent['author-nick'] = api_get_nick($parent['author-link']);
                        }
 
-                       $in_reply_to['screen_name'] = (($r[0]['nick']) ? $r[0]['nick'] : $r[0]['name']);
-                       $in_reply_to['user_id'] = intval($r[0]['id']);
-                       $in_reply_to['user_id_str'] = (string) intval($r[0]['id']);
+                       $in_reply_to['screen_name'] = (($parent['author-nick']) ? $parent['author-nick'] : $parent['author-name']);
+                       $in_reply_to['user_id'] = intval($parent['author-id']);
+                       $in_reply_to['user_id_str'] = (string) intval($parent['author-id']);
                }
 
                // There seems to be situation, where both fields are identical:
@@ -5210,7 +5126,7 @@ function api_friendica_group_show($type)
                        intval($gid)
                );
                // error message if specified gid is not in database
-               if (!DBM::is_result($r)) {
+               if (!DBA::isResult($r)) {
                        throw new BadRequestException("gid not available");
                }
        } else {
@@ -5280,7 +5196,7 @@ function api_friendica_group_delete($type)
                intval($gid)
        );
        // error message if specified gid is not in database
-       if (!DBM::is_result($r)) {
+       if (!DBA::isResult($r)) {
                throw new BadRequestException('gid not available');
        }
 
@@ -5289,10 +5205,10 @@ function api_friendica_group_delete($type)
                "SELECT * FROM `group` WHERE `uid` = %d AND `id` = %d AND `name` = '%s'",
                intval($uid),
                intval($gid),
-               dbesc($name)
+               DBA::escape($name)
        );
        // error message if specified gid is not in database
-       if (!DBM::is_result($rname)) {
+       if (!DBA::isResult($rname)) {
                throw new BadRequestException('wrong group name');
        }
 
@@ -5335,7 +5251,7 @@ function api_lists_destroy($type)
        }
 
        // get data of the specified group id
-       $group = dba::selectFirst('group', [], ['uid' => $uid, 'id' => $gid]);
+       $group = DBA::selectFirst('group', [], ['uid' => $uid, 'id' => $gid]);
        // error message if specified gid is not in database
        if (!$group) {
                throw new BadRequestException('gid not available');
@@ -5374,10 +5290,10 @@ function group_create($name, $uid, $users = [])
        $rname = q(
                "SELECT * FROM `group` WHERE `uid` = %d AND `name` = '%s' AND `deleted` = 0",
                intval($uid),
-               dbesc($name)
+               DBA::escape($name)
        );
        // error message if specified group name already exists
-       if (DBM::is_result($rname)) {
+       if (DBA::isResult($rname)) {
                throw new BadRequestException('group name already exists');
        }
 
@@ -5385,10 +5301,10 @@ function group_create($name, $uid, $users = [])
        $rname = q(
                "SELECT * FROM `group` WHERE `uid` = %d AND `name` = '%s' AND `deleted` = 1",
                intval($uid),
-               dbesc($name)
+               DBA::escape($name)
        );
        // error message if specified group name already exists
-       if (DBM::is_result($rname)) {
+       if (DBA::isResult($rname)) {
                $reactivate_group = true;
        }
 
@@ -5589,7 +5505,7 @@ function api_lists_update($type)
        }
 
        // get data of the specified group id
-       $group = dba::selectFirst('group', [], ['uid' => $uid, 'id' => $gid]);
+       $group = DBA::selectFirst('group', [], ['uid' => $uid, 'id' => $gid]);
        // error message if specified gid is not in database
        if (!$group) {
                throw new BadRequestException('gid not available');
@@ -5675,8 +5591,10 @@ function api_friendica_notification($type)
 
        if ($type == "xml") {
                $xmlnotes = [];
-               foreach ($notes as $note) {
-                       $xmlnotes[] = ["@attributes" => $note];
+               if (!empty($notes)) {
+                       foreach ($notes as $note) {
+                               $xmlnotes[] = ["@attributes" => $note];
+                       }
                }
 
                $notes = $xmlnotes;
@@ -5716,8 +5634,8 @@ function api_friendica_notification_seen($type)
        $nm->setSeen($note);
        if ($note['otype']=='item') {
                // would be really better with an ItemsManager and $im->getByID() :-P
-               $item = Item::selectFirst(api_user(), [], ['id' => $note['iid'], 'uid' => api_user()]);
-               if (DBM::is_result($$item)) {
+               $item = Item::selectFirstForUser(api_user(), [], ['id' => $note['iid'], 'uid' => api_user()]);
+               if (DBA::isResult($$item)) {
                        // we found the item, return it to the user
                        $ret = api_format_items([$item], $user_info, false, $type);
                        $data = ['status' => $ret];
@@ -5757,13 +5675,13 @@ function api_friendica_direct_messages_setseen($type)
        }
 
        // error message if specified id is not in database
-       if (!dba::exists('mail', ['id' => $id, 'uid' => $uid])) {
+       if (!DBA::exists('mail', ['id' => $id, 'uid' => $uid])) {
                $answer = ['result' => 'error', 'message' => 'message id not in database'];
                return api_format_data("direct_messages_setseen", $type, ['$result' => $answer]);
        }
 
        // update seen indicator
-       $result = dba::update('mail', ['seen' => true], ['id' => $id]);
+       $result = DBA::update('mail', ['seen' => true], ['id' => $id]);
 
        if ($result) {
                // return success
@@ -5810,13 +5728,13 @@ function api_friendica_direct_messages_search($type, $box = "")
        $r = q(
                "SELECT `mail`.*, `contact`.`nurl` AS `contact-url` FROM `mail`,`contact` WHERE `mail`.`contact-id` = `contact`.`id` AND `mail`.`uid`=%d AND `body` LIKE '%s' ORDER BY `mail`.`id` DESC",
                intval($uid),
-               dbesc('%'.$searchstring.'%')
+               DBA::escape('%'.$searchstring.'%')
        );
 
        $profile_url = $user_info["url"];
 
        // message if nothing was found
-       if (!DBM::is_result($r)) {
+       if (!DBA::isResult($r)) {
                $success = ['success' => false, 'search_results' => 'problem with query'];
        } elseif (count($r) == 0) {
                $success = ['success' => false, 'search_results' => 'nothing found'];
@@ -5874,7 +5792,7 @@ function api_friendica_profile_show($type)
                );
 
                // error message if specified gid is not in database
-               if (!DBM::is_result($r)) {
+               if (!DBA::isResult($r)) {
                        throw new BadRequestException("profile_id not available");
                }
        } else {
@@ -5933,7 +5851,7 @@ api_register_func('api/friendica/profile/show', 'api_friendica_profile_show', tr
  */
 function api_saved_searches_list($type)
 {
-       $terms = dba::select('search', ['id', 'term'], ['uid' => local_user()]);
+       $terms = DBA::select('search', ['id', 'term'], ['uid' => local_user()]);
 
        $result = [];
        while ($term = $terms->fetch()) {
@@ -5947,7 +5865,7 @@ function api_saved_searches_list($type)
                ];
        }
 
-       dba::close($terms);
+       DBA::close($terms);
 
        return api_format_data("terms", $type, ['terms' => $result]);
 }