]> git.mxchange.org Git - friendica.git/blobdiff - include/api.php
Update functions and calls
[friendica.git] / include / api.php
index eb3ef796d2c1bccd61149e89ecc9eab9c2d5e51b..da7a83f51c421e5401e287f96dad7f3dd20a56a8 100644 (file)
@@ -1,11 +1,12 @@
 <?php
 /**
- * @file include/api.php
  * Friendica implementation of statusnet/twitter API
  *
+ * @file include/api.php
  * @todo Automatically detect if incoming data is HTML or BBCode
  */
 use Friendica\App;
+use Friendica\Content\ContactSelector;
 use Friendica\Content\Feature;
 use Friendica\Core\System;
 use Friendica\Core\Config;
@@ -15,6 +16,7 @@ use Friendica\Core\Worker;
 use Friendica\Database\DBM;
 use Friendica\Model\Contact;
 use Friendica\Model\Group;
+use Friendica\Model\Mail;
 use Friendica\Model\Photo;
 use Friendica\Model\User;
 use Friendica\Network\FKOAuth1;
@@ -38,11 +40,9 @@ require_once 'include/html2plain.php';
 require_once 'mod/share.php';
 require_once 'mod/item.php';
 require_once 'include/security.php';
-require_once 'include/contact_selectors.php';
 require_once 'include/html2bbcode.php';
 require_once 'mod/wall_upload.php';
 require_once 'mod/proxy.php';
-require_once 'include/message.php';
 require_once 'include/like.php';
 require_once 'include/plaintext.php';
 
@@ -55,11 +55,11 @@ $API = array();
 $called_api = null;
 
 /**
- * @brief Auth API user
- *
  * It is not sufficient to use local_user() to check whether someone is allowed to use the API,
  * because this will open CSRF holes (just embed an image with src=friendicasite.com/api/statuses/update?status=CSRF
  * into a page, and visitors will post something without noticing it).
+ *
+ * @brief Auth API user
  */
 function api_user()
 {
@@ -71,13 +71,13 @@ function api_user()
 }
 
 /**
- * @brief Get source name from API client
- *
  * Clients can send 'source' parameter to be show in post metadata
  * as "sent via <source>".
  * Some clients doesn't send a source param, we support ones we know
  * (only Twidere, atm)
  *
+ * @brief Get source name from API client
+ *
  * @return string
  *             Client source name, default to "api" if unset/unknown
  */
@@ -110,9 +110,9 @@ function api_date($str)
 }
 
 /**
- * @brief Register API endpoint
+ * Register a function to be the endpoint for defined API path.
  *
- * Register a function to be the endpont for defined API path.
+ * @brief Register API endpoint
  *
  * @param string $path   API URL path, relative to System::baseUrl()
  * @param string $func   Function name to call on path request
@@ -142,11 +142,11 @@ function api_register_func($path, $func, $auth = false, $method = API_METHOD_ANY
 }
 
 /**
- * @brief Login API user
- *
  * Log in user via OAuth1 or Simple HTTP Auth.
  * Simple Auth allow username in form of <pre>user@server</pre>, ignoring server part
  *
+ * @brief Login API user
+ *
  * @param object $a App
  * @hook 'authenticate'
  *             array $addon_auth
@@ -222,11 +222,11 @@ function api_login(App $a)
        } else {
                $user_id = User::authenticate(trim($user), trim($password));
                if ($user_id) {
-                       $record = dba::select('user', [], ['uid' => $user_id], ['limit' => 1]);
+                       $record = dba::selectFirst('user', [], ['uid' => $user_id]);
                }
        }
 
-       if (!$record || !count($record)) {
+       if (!DBM::is_result($record)) {
                logger('API_login failure: ' . print_r($_SERVER, true), LOGGER_DEBUG);
                header('WWW-Authenticate: Basic realm="Friendica"');
                //header('HTTP/1.0 401 Unauthorized');
@@ -242,12 +242,12 @@ function api_login(App $a)
 }
 
 /**
- * @brief Check HTTP method of called API
- *
  * API endpoints can define which HTTP method to accept when called.
  * This function check the current HTTP method agains endpoint
  * registered method.
  *
+ * @brief Check HTTP method of called API
+ *
  * @param string $method Required methods, uppercase, separated by comma
  * @return bool
  */
@@ -260,10 +260,10 @@ function api_check_method($method)
 }
 
 /**
- * @brief Main API entry point
- *
  * Authenticate user, call registered API function, set HTTP headers
  *
+ * @brief Main API entry point
+ *
  * @param object $a App
  * @return string API call result
  */
@@ -304,7 +304,7 @@ function api_call(App $a)
                                logger('API parameters: ' . print_r($_REQUEST, true));
 
                                $stamp =  microtime(true);
-                               $r = call_user_func($info['func'], $type);
+                               $return = call_user_func($info['func'], $type);
                                $duration = (float) (microtime(true) - $stamp);
                                logger("API call duration: " . round($duration, 2) . "\t" . $a->query_string, LOGGER_DEBUG);
 
@@ -352,7 +352,7 @@ function api_call(App $a)
                                        }
                                }
 
-                               if (false === $r) {
+                               if (false === $return) {
                                        /*
                                                * api function returned false withour throw an
                                                * exception. This should not happend, throw a 500
@@ -363,27 +363,27 @@ function api_call(App $a)
                                switch ($type) {
                                        case "xml":
                                                header("Content-Type: text/xml");
-                                               return $r;
                                                break;
                                        case "json":
                                                header("Content-Type: application/json");
-                                               foreach ($r as $rr) {
+                                               foreach ($return as $rr) {
                                                        $json = json_encode($rr);
                                                }
                                                if (x($_GET, 'callback')) {
                                                        $json = $_GET['callback'] . "(" . $json . ")";
                                                }
-                                               return $json;
+                                               $return = $json;
                                                break;
                                        case "rss":
                                                header("Content-Type: application/rss+xml");
-                                               return '<?xml version="1.0" encoding="UTF-8"?>' . "\n" . $r;
+                                               $return  = '<?xml version="1.0" encoding="UTF-8"?>' . "\n" . $return;
                                                break;
                                        case "atom":
                                                header("Content-Type: application/atom+xml");
-                                               return '<?xml version="1.0" encoding="UTF-8"?>' . "\n" . $r;
+                                               $return = '<?xml version="1.0" encoding="UTF-8"?>' . "\n" . $return;
                                                break;
                                }
+                               return $return;
                        }
                }
 
@@ -413,26 +413,25 @@ function api_error($type, $e)
                        "code" => $e->httpcode . " " . $e->httpdesc,
                        "request" => $a->query_string);
 
-       $ret = api_format_data('status', $type, array('status' => $error));
+       $return = api_format_data('status', $type, array('status' => $error));
 
        switch ($type) {
                case "xml":
                        header("Content-Type: text/xml");
-                       return $ret;
                        break;
                case "json":
                        header("Content-Type: application/json");
-                       return json_encode($ret);
+                       $return = json_encode($return);
                        break;
                case "rss":
                        header("Content-Type: application/rss+xml");
-                       return $ret;
                        break;
                case "atom":
                        header("Content-Type: application/atom+xml");
-                       return $ret;
                        break;
        }
+
+       return $return;
 }
 
 /**
@@ -474,7 +473,7 @@ function api_rss_extra(App $a, $arr, $user_info)
  */
 function api_unique_id_to_nurl($id)
 {
-       $r = dba::select('contact', array('nurl'), array('uid' => 0, 'id' => $id), array('limit' => 1));
+       $r = dba::selectFirst('contact', array('nurl'), array('uid' => 0, 'id' => $id));
 
        if (DBM::is_result($r)) {
                return $r["nurl"];
@@ -496,7 +495,6 @@ function api_get_user(App $a, $contact_id = null)
        $user = null;
        $extra_query = "";
        $url = "";
-       $nick = "";
 
        logger("api_get_user: Fetching user data for user ".$contact_id, LOGGER_DEBUG);
 
@@ -540,7 +538,6 @@ function api_get_user(App $a, $contact_id = null)
        }
        if (is_null($user) && x($_GET, 'screen_name')) {
                $user = dbesc($_GET['screen_name']);
-               $nick = $user;
                $extra_query = "AND `contact`.`nick` = '%s' ";
                if (api_user() !== false) {
                        $extra_query .= "AND `contact`.`uid`=".intval(api_user());
@@ -549,7 +546,6 @@ function api_get_user(App $a, $contact_id = null)
 
        if (is_null($user) && x($_GET, 'profileurl')) {
                $user = dbesc(normalise_link($_GET['profileurl']));
-               $nick = $user;
                $extra_query = "AND `contact`.`nurl` = '%s' ";
                if (api_user() !== false) {
                        $extra_query .= "AND `contact`.`uid`=".intval(api_user());
@@ -573,7 +569,6 @@ function api_get_user(App $a, $contact_id = null)
                        }
                } else {
                        $user = dbesc($user);
-                       $nick = $user;
                        $extra_query = "AND `contact`.`nick` = '%s' ";
                        if (api_user() !== false) {
                                $extra_query .= "AND `contact`.`uid`=" . intval(api_user());
@@ -615,7 +610,7 @@ function api_get_user(App $a, $contact_id = null)
                }
 
                if (DBM::is_result($r)) {
-                       $network_name = network_to_name($r[0]['network'], $r[0]['url']);
+                       $network_name = ContactSelector::networkToName($r[0]['network'], $r[0]['url']);
 
                        // If no nick where given, extract it from the address
                        if (($r[0]['nick'] == "") || ($r[0]['name'] == $r[0]['nick'])) {
@@ -739,12 +734,12 @@ function api_get_user(App $a, $contact_id = null)
                $uinfo[0]['nick'] = api_get_nick($uinfo[0]["url"]);
        }
 
-       $network_name = network_to_name($uinfo[0]['network'], $uinfo[0]['url']);
+       $network_name = ContactSelector::networkToName($uinfo[0]['network'], $uinfo[0]['url']);
 
        $pcontact_id  = Contact::getIdForURL($uinfo[0]['url'], 0, true);
 
-       if (!empty($profile[0]['pdesc'])) {
-               $description = $profile[0]['pdesc'];
+       if (!empty($profile[0]['about'])) {
+               $description = $profile[0]['about'];
        } else {
                $description = $uinfo[0]["about"];
        }
@@ -754,7 +749,7 @@ function api_get_user(App $a, $contact_id = null)
        } elseif (!empty($uinfo[0]["location"])) {
                $location = $uinfo[0]["location"];
        } else {
-               $location = network_name;
+               $location = $network_name;
        }
 
        $ret = array(
@@ -797,7 +792,7 @@ 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::select('user', ['theme'], ['uid' => $ret['uid']], ['limit' => 1]);
+               $theme_info = dba::selectFirst('user', ['theme'], ['uid' => $ret['uid']]);
                if ($theme_info['theme'] === 'frio') {
                        $schema = PConfig::get($ret['uid'], 'frio', 'schema');
                        if ($schema && ($schema != '---')) {
@@ -986,7 +981,9 @@ function api_format_data($root_element, $type, $data)
 /**
  * Returns an HTTP 200 OK response code and a representation of the requesting user if authentication was successful;
  * returns a 401 status code and an error message if not.
- * http://developer.twitter.com/doc/get/account/verify_credentials
+ * @see https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/get-account-verify_credentials
+ *
+ * @param string $type Return type (atom, rss, xml, json)
  */
 function api_account_verify_credentials($type)
 {
@@ -1027,11 +1024,13 @@ function api_account_verify_credentials($type)
        return api_format_data("user", $type, array('user' => $user_info));
 }
 
-/// @TODO move to top of file or somwhere better
+/// @TODO move to top of file or somewhere better
 api_register_func('api/account/verify_credentials', 'api_account_verify_credentials', true);
 
 /**
  * Get data from $_POST or $_GET
+ *
+ * @param string $k
  */
 function requestdata($k)
 {
@@ -1044,7 +1043,13 @@ function requestdata($k)
        return null;
 }
 
-/*Waitman Gobble Mod*/
+/**
+ * Waitman Gobble Mod
+ *
+ * @param string $type Return type (atom, rss, xml, json)
+ *
+ * @return array|string
+ */
 function api_statuses_mediap($type)
 {
        $a = get_app();
@@ -1088,6 +1093,14 @@ function api_statuses_mediap($type)
 /// @TODO move this to top of file or somewhere better!
 api_register_func('api/statuses/mediap', 'api_statuses_mediap', true, API_METHOD_POST);
 
+/**
+ * Updates the user’s current status.
+ *
+ * @param string $type Return type (atom, rss, xml, json)
+ *
+ * @return array|string
+ * @see https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-update
+ */
 function api_statuses_update($type)
 {
 
@@ -1098,12 +1111,9 @@ function api_statuses_update($type)
                throw new ForbiddenException();
        }
 
-       $user_info = api_get_user($a);
+       api_get_user($a);
 
        // convert $_POST array items to the form we use for web posts.
-
-       // logger('api_post: ' . print_r($_POST,true));
-
        if (requestdata('htmlstatus')) {
                $txt = requestdata('htmlstatus');
                if ((strpos($txt, '<') !== false) || (strpos($txt, '>') !== false)) {
@@ -1259,11 +1269,17 @@ function api_statuses_update($type)
        return api_status_show($type);
 }
 
-/// @TODO move to top of file or somwhere better
+/// @TODO move to top of file or somewhere better
 api_register_func('api/statuses/update', 'api_statuses_update', true, API_METHOD_POST);
 api_register_func('api/statuses/update_with_media', 'api_statuses_update', true, API_METHOD_POST);
 
-function api_media_upload($type)
+/**
+ * Uploads an image to Friendica.
+ *
+ * @return array
+ * @see https://developer.twitter.com/en/docs/media/upload-media/api-reference/post-media-upload
+ */
+function api_media_upload()
 {
        $a = get_app();
 
@@ -1272,7 +1288,7 @@ function api_media_upload($type)
                throw new ForbiddenException();
        }
 
-       $user_info = api_get_user($a);
+       api_get_user($a);
 
        if (!x($_FILES, 'media')) {
                // Output error
@@ -1298,9 +1314,15 @@ function api_media_upload($type)
        return array("media" => $returndata);
 }
 
-/// @TODO move to top of file or somwhere better
+/// @TODO move to top of file or somewhere better
 api_register_func('api/media/upload', 'api_media_upload', true, API_METHOD_POST);
 
+/**
+ *
+ * @param string $type Return type (atom, rss, xml, json)
+ *
+ * @return array|string
+ */
 function api_status_show($type)
 {
        $a = get_app();
@@ -1383,9 +1405,9 @@ function api_status_show($type)
                }
 
                if (($lastwall['item_network'] != "") && ($status["source"] == 'web')) {
-                       $status_info["source"] = network_to_name($lastwall['item_network'], $user_info['url']);
-               } elseif (($lastwall['item_network'] != "") && (network_to_name($lastwall['item_network'], $user_info['url']) != $status_info["source"])) {
-                       $status_info["source"] = trim($status_info["source"].' ('.network_to_name($lastwall['item_network'], $user_info['url']).')');
+                       $status_info["source"] = ContactSelector::networkToName($lastwall['item_network'], $user_info['url']);
+               } elseif (($lastwall['item_network'] != "") && (ContactSelector::networkToName($lastwall['item_network'], $user_info['url']) != $status_info["source"])) {
+                       $status_info["source"] = trim($status_info["source"].' ('.ContactSelector::networkToName($lastwall['item_network'], $user_info['url']).')');
                }
 
                // "uid" and "self" are only needed for some internal stuff, so remove it from here
@@ -1405,7 +1427,9 @@ function api_status_show($type)
 /**
  * Returns extended information of a given user, specified by ID or screen name as per the required id parameter.
  * The author's most recent status will be returned inline.
- * http://developer.twitter.com/doc/get/users/show
+ *
+ * @param string $type Return type (atom, rss, xml, json)
+ * @see https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-users-show
  */
 function api_users_show($type)
 {
@@ -1472,11 +1496,11 @@ function api_users_show($type)
                }
 
                if (($lastwall['item_network'] != "") && ($user_info["status"]["source"] == 'web')) {
-                       $user_info["status"]["source"] = network_to_name($lastwall['item_network'], $user_info['url']);
+                       $user_info["status"]["source"] = ContactSelector::networkToName($lastwall['item_network'], $user_info['url']);
                }
 
-               if (($lastwall['item_network'] != "") && (network_to_name($lastwall['item_network'], $user_info['url']) != $user_info["status"]["source"])) {
-                       $user_info["status"]["source"] = trim($user_info["status"]["source"] . ' (' . network_to_name($lastwall['item_network'], $user_info['url']) . ')');
+               if (($lastwall['item_network'] != "") && (ContactSelector::networkToName($lastwall['item_network'], $user_info['url']) != $user_info["status"]["source"])) {
+                       $user_info["status"]["source"] = trim($user_info["status"]["source"] . ' (' . ContactSelector::networkToName($lastwall['item_network'], $user_info['url']) . ')');
                }
        }
 
@@ -1491,12 +1515,18 @@ function api_users_show($type)
 api_register_func('api/users/show', 'api_users_show');
 api_register_func('api/externalprofile/show', 'api_users_show');
 
+/**
+ * Search a public user account.
+ *
+ * @param string $type Return type (atom, rss, xml, json)
+ *
+ * @return array|string
+ * @see https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-users-search
+ */
 function api_users_search($type)
 {
        $a = get_app();
 
-       $page = (x($_REQUEST, 'page') ? $_REQUEST['page'] - 1 : 0);
-
        $userlist = array();
 
        if (x($_GET, 'q')) {
@@ -1524,6 +1554,7 @@ function api_users_search($type)
        } else {
                throw new BadRequestException("User not found.");
        }
+
        return api_format_data("users", $type, $userlist);
 }
 
@@ -1621,11 +1652,14 @@ api_register_func('api/search/tweets', 'api_search', true);
 api_register_func('api/search', 'api_search', true);
 
 /**
+ * Returns the most recent statuses posted by the user and the users they follow.
  *
- * http://developer.twitter.com/doc/get/statuses/home_timeline
+ * @see https://developer.twitter.com/en/docs/tweets/timelines/api-reference/get-statuses-home_timeline
  *
- * TODO: Optional parameters
- * TODO: Add reply info
+ * @param string $type Return type (atom, rss, xml, json)
+ *
+ * @todo Optional parameters
+ * @todo Add reply info
  */
 function api_statuses_home_timeline($type)
 {
@@ -1703,7 +1737,7 @@ function api_statuses_home_timeline($type)
                $unseen = q("SELECT `id` FROM `item` WHERE `unseen` AND `id` IN (%s)", $idlist);
 
                if ($unseen) {
-                       $r = q("UPDATE `item` SET `unseen` = 0 WHERE `unseen` AND `id` IN (%s)", $idlist);
+                       q("UPDATE `item` SET `unseen` = 0 WHERE `unseen` AND `id` IN (%s)", $idlist);
                }
        }
 
@@ -1722,6 +1756,13 @@ function api_statuses_home_timeline($type)
 api_register_func('api/statuses/home_timeline', 'api_statuses_home_timeline', true);
 api_register_func('api/statuses/friends_timeline', 'api_statuses_home_timeline', true);
 
+/**
+ * Returns the most recent statuses from public users.
+ *
+ * @param string $type Return type (atom, rss, xml, json)
+ *
+ * @return array|string
+ */
 function api_statuses_public_timeline($type)
 {
        $a = get_app();
@@ -1822,6 +1863,8 @@ function api_statuses_public_timeline($type)
 api_register_func('api/statuses/public_timeline', 'api_statuses_public_timeline', true);
 
 /**
+ * Returns the most recent statuses posted by users this node knows about.
+ *
  * @brief Returns the list of public federated posts this node knows about
  *
  * @param string $type Return format: json, xml, atom, rss
@@ -1892,7 +1935,11 @@ function api_statuses_networkpublic_timeline($type)
 api_register_func('api/statuses/networkpublic_timeline', 'api_statuses_networkpublic_timeline', true);
 
 /**
- * @TODO nothing to say?
+ * Returns a single status.
+ *
+ * @param string $type Return type (atom, rss, xml, json)
+ *
+ * @see https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/get-statuses-show-id
  */
 function api_statuses_show($type)
 {
@@ -1963,7 +2010,10 @@ function api_statuses_show($type)
 api_register_func('api/statuses/show', 'api_statuses_show', true);
 
 /**
- * @TODO nothing to say?
+ *
+ * @param string $type Return type (atom, rss, xml, json)
+ *
+ * @todo nothing to say?
  */
 function api_conversation_show($type)
 {
@@ -2050,7 +2100,11 @@ api_register_func('api/conversation/show', 'api_conversation_show', true);
 api_register_func('api/statusnet/conversation', 'api_conversation_show', true);
 
 /**
- * @TODO nothing to say?
+ * Repeats a status.
+ *
+ * @param string $type Return type (atom, rss, xml, json)
+ *
+ * @see https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-retweet-id
  */
 function api_statuses_repeat($type)
 {
@@ -2062,7 +2116,7 @@ function api_statuses_repeat($type)
                throw new ForbiddenException();
        }
 
-       $user_info = api_get_user($a);
+       api_get_user($a);
 
        // params
        $id = intval($a->argv[3]);
@@ -2128,7 +2182,11 @@ function api_statuses_repeat($type)
 api_register_func('api/statuses/retweet', 'api_statuses_repeat', true, API_METHOD_POST);
 
 /**
- * @TODO nothing to say?
+ * Destroys a specific status.
+ *
+ * @param string $type Return type (atom, rss, xml, json)
+ *
+ * @see https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-destroy-id
  */
 function api_statuses_destroy($type)
 {
@@ -2138,7 +2196,7 @@ function api_statuses_destroy($type)
                throw new ForbiddenException();
        }
 
-       $user_info = api_get_user($a);
+       api_get_user($a);
 
        // params
        $id = intval($a->argv[3]);
@@ -2165,8 +2223,11 @@ function api_statuses_destroy($type)
 api_register_func('api/statuses/destroy', 'api_statuses_destroy', true, API_METHOD_DELETE);
 
 /**
- * @TODO Nothing more than an URL to say?
- * http://developer.twitter.com/doc/get/statuses/mentions
+ * Returns the most recent mentions.
+ *
+ * @param string $type Return type (atom, rss, xml, json)
+ *
+ * @see http://developer.twitter.com/doc/get/statuses/mentions
  */
 function api_statuses_mentions($type)
 {
@@ -2187,23 +2248,20 @@ function api_statuses_mentions($type)
 
 
        // params
-       $count = (x($_REQUEST, 'count') ? $_REQUEST['count'] : 20);
-       $page = (x($_REQUEST, 'page') ? $_REQUEST['page'] -1 : 0);
-       if ($page < 0) {
-               $page = 0;
+       $since_id = defaults($_REQUEST, 'since_id', 0);
+       $max_id   = defaults($_REQUEST, 'max_id'  , 0);
+       $count    = defaults($_REQUEST, 'count'   , 20);
+       $page     = defaults($_REQUEST, 'page'    , 1);
+       if ($page < 1) {
+               $page = 1;
        }
-       $since_id = (x($_REQUEST, 'since_id') ? $_REQUEST['since_id'] : 0);
-       $max_id = (x($_REQUEST, 'max_id') ? $_REQUEST['max_id'] : 0);
-       //$since_id = 0;//$since_id = (x($_REQUEST, 'since_id')?$_REQUEST['since_id'] : 0);
 
-       $start = $page * $count;
+       $start = ($page - 1) * $count;
 
        // Ugly code - should be changed
        $myurl = System::baseUrl() . '/profile/'. $a->user['nickname'];
        $myurl = substr($myurl, strpos($myurl, '://') + 3);
-       //$myurl = str_replace(array('www.','.'),array('','\\.'),$myurl);
        $myurl = str_replace('www.', '', $myurl);
-       $diasp_url = str_replace('/profile/', '/u/', $myurl);
 
        if ($max_id > 0) {
                $sql_extra = ' AND `item`.`id` <= ' . intval($max_id);
@@ -2252,11 +2310,14 @@ api_register_func('api/statuses/mentions', 'api_statuses_mentions', true);
 api_register_func('api/statuses/replies', 'api_statuses_mentions', true);
 
 /**
+ * Returns the most recent statuses posted by the user.
+ *
  * @brief Returns a user's public timeline
  *
  * @param string $type Either "json" or "xml"
  * @return string|array
  * @throws ForbiddenException
+ * @see https://developer.twitter.com/en/docs/tweets/timelines/api-reference/get-statuses-user_timeline
  */
 function api_statuses_user_timeline($type)
 {
@@ -2340,14 +2401,16 @@ function api_statuses_user_timeline($type)
        return api_format_data("statuses", $type, $data);
 }
 
-/// @TODO move to top of file or somwhere better
+/// @TODO move to top of file or somewhere better
 api_register_func('api/statuses/user_timeline', 'api_statuses_user_timeline', true);
 
 /**
- * Star/unstar an item
+ * Star/unstar an item.
  * param: id : id of the item
  *
- * api v1 : https://web.archive.org/web/20131019055350/https://dev.twitter.com/docs/api/1/post/favorites/create/%3Aid
+ * @param string $type Return type (atom, rss, xml, json)
+ *
+ * @see https://web.archive.org/web/20131019055350/https://dev.twitter.com/docs/api/1/post/favorites/create/%3Aid
  */
 function api_favorites_create_destroy($type)
 {
@@ -2415,10 +2478,17 @@ function api_favorites_create_destroy($type)
        return api_format_data("status", $type, $data);
 }
 
-/// @TODO move to top of file or somwhere better
+/// @TODO move to top of file or somewhere better
 api_register_func('api/favorites/create', 'api_favorites_create_destroy', true, API_METHOD_POST);
 api_register_func('api/favorites/destroy', 'api_favorites_create_destroy', true, API_METHOD_DELETE);
 
+/**
+ * Returns the most recent favorite statuses.
+ *
+ * @param string $type Return type (atom, rss, xml, json)
+ *
+ * @return string|array
+ */
 function api_favorites($type)
 {
        global $called_api;
@@ -2490,9 +2560,17 @@ function api_favorites($type)
        return api_format_data("statuses", $type, $data);
 }
 
-/// @TODO move to top of file or somwhere better
+/// @TODO move to top of file or somewhere better
 api_register_func('api/favorites', 'api_favorites', true);
 
+/**
+ *
+ * @param array $item
+ * @param array $recipient
+ * @param array $sender
+ *
+ * @return array
+ */
 function api_format_messages($item, $recipient, $sender)
 {
        // standard meta information
@@ -2537,6 +2615,12 @@ function api_format_messages($item, $recipient, $sender)
        return $ret;
 }
 
+/**
+ *
+ * @param array $item
+ *
+ * @return array
+ */
 function api_convert_item($item)
 {
        $body = $item['body'];
@@ -2606,6 +2690,12 @@ function api_convert_item($item)
        );
 }
 
+/**
+ *
+ * @param string $body
+ *
+ * @return array|false
+ */
 function api_get_attachments(&$body)
 {
        $text = $body;
@@ -2637,15 +2727,16 @@ function api_get_attachments(&$body)
        return $attachments;
 }
 
+/**
+ *
+ * @param string $text
+ * @param string $bbcode
+ *
+ * @return array
+ * @todo Links at the first character of the post
+ */
 function api_get_entitities(&$text, $bbcode)
 {
-       /*
-       To-Do:
-       * Links at the first character of the post
-       */
-
-       $a = get_app();
-
        $include_entities = strtolower(x($_REQUEST, 'include_entities') ? $_REQUEST['include_entities'] : "false");
 
        if ($include_entities != "true") {
@@ -2802,25 +2893,32 @@ function api_get_entitities(&$text, $bbcode)
 
        return $entities;
 }
-function api_format_items_embeded_images(&$item, $text)
+
+/**
+ *
+ * @param array $item
+ * @param string $text
+ *
+ * @return string
+ */
+function api_format_items_embeded_images($item, $text)
 {
        $text = preg_replace_callback(
-               "|data:image/([^;]+)[^=]+=*|m",
-               function ($match) use ($item) {
-                       return System::baseUrl()."/display/".$item['guid'];
+               '|data:image/([^;]+)[^=]+=*|m',
+               function () use ($item) {
+                       return System::baseUrl() . '/display/' . $item['guid'];
                },
                $text
        );
        return $text;
 }
 
-
 /**
  * @brief return <a href='url'>name</a> as array
  *
  * @param string $txt text
  * @return array
- *                     name => 'name'
+ *                     'name' => 'name',
  *                     'url => 'url'
  */
 function api_contactlink_to_array($txt)
@@ -2846,8 +2944,10 @@ function api_contactlink_to_array($txt)
  * @brief return likes, dislikes and attend status for item
  *
  * @param array $item array
+ * @param string $type Return type (atom, rss, xml, json)
+ *
  * @return array
- *                     likes => int count
+ *                     likes => int count,
  *                     dislikes => int count
  */
 function api_format_items_activities(&$item, $type = "json")
@@ -2917,62 +3017,62 @@ function api_format_items_activities(&$item, $type = "json")
 /**
  * @brief return data from profiles
  *
- * @param array  $profile array containing data from db table 'profile'
- * @param string $type    Known types are 'atom', 'rss', 'xml' and 'json'
+ * @param array  $profile_row array containing data from db table 'profile'
  * @return array
  */
-function api_format_items_profiles(&$profile = null, $type = "json")
+function api_format_items_profiles($profile_row)
 {
-       if ($profile != null) {
-               $profile = array('profile_id' => $profile['id'],
-                                               'profile_name' => $profile['profile-name'],
-                                               'is_default' => $profile['is-default'] ? true : false,
-                                               'hide_friends'=> $profile['hide-friends'] ? true : false,
-                                               'profile_photo' => $profile['photo'],
-                                               'profile_thumb' => $profile['thumb'],
-                                               'publish' => $profile['publish'] ? true : false,
-                                               'net_publish' => $profile['net-publish'] ? true : false,
-                                               'description' => $profile['pdesc'],
-                                               'date_of_birth' => $profile['dob'],
-                                               'address' => $profile['address'],
-                                               'city' => $profile['locality'],
-                                               'region' => $profile['region'],
-                                               'postal_code' => $profile['postal-code'],
-                                               'country' => $profile['country-name'],
-                                               'hometown' => $profile['hometown'],
-                                               'gender' => $profile['gender'],
-                                               'marital' => $profile['marital'],
-                                               'marital_with' => $profile['with'],
-                                               'marital_since' => $profile['howlong'],
-                                               'sexual' => $profile['sexual'],
-                                               'politic' => $profile['politic'],
-                                               'religion' => $profile['religion'],
-                                               'public_keywords' => $profile['pub_keywords'],
-                                               'private_keywords' => $profile['prv_keywords'],
-                                               'likes' => bbcode(api_clean_plain_items($profile['likes']), false, false, 2, false),
-                                               'dislikes' => bbcode(api_clean_plain_items($profile['dislikes']), false, false, 2, false),
-                                               'about' => bbcode(api_clean_plain_items($profile['about']), false, false, 2, false),
-                                               'music' => bbcode(api_clean_plain_items($profile['music']), false, false, 2, false),
-                                               'book' => bbcode(api_clean_plain_items($profile['book']), false, false, 2, false),
-                                               'tv' => bbcode(api_clean_plain_items($profile['tv']), false, false, 2, false),
-                                               'film' => bbcode(api_clean_plain_items($profile['film']), false, false, 2, false),
-                                               'interest' => bbcode(api_clean_plain_items($profile['interest']), false, false, 2, false),
-                                               'romance' => bbcode(api_clean_plain_items($profile['romance']), false, false, 2, false),
-                                               'work' => bbcode(api_clean_plain_items($profile['work']), false, false, 2, false),
-                                               'education' => bbcode(api_clean_plain_items($profile['education']), false, false, 2, false),
-                                               'social_networks' => bbcode(api_clean_plain_items($profile['contact']), false, false, 2, false),
-                                               'homepage' => $profile['homepage'],
-                                               'users' => null);
-               return $profile;
-       }
+       $profile = array(
+               'profile_id'       => $profile_row['id'],
+               'profile_name'     => $profile_row['profile-name'],
+               'is_default'       => $profile_row['is-default'] ? true : false,
+               'hide_friends'     => $profile_row['hide-friends'] ? true : false,
+               'profile_photo'    => $profile_row['photo'],
+               'profile_thumb'    => $profile_row['thumb'],
+               'publish'          => $profile_row['publish'] ? true : false,
+               'net_publish'      => $profile_row['net-publish'] ? true : false,
+               'description'      => $profile_row['pdesc'],
+               'date_of_birth'    => $profile_row['dob'],
+               'address'          => $profile_row['address'],
+               'city'             => $profile_row['locality'],
+               'region'           => $profile_row['region'],
+               'postal_code'      => $profile_row['postal-code'],
+               'country'          => $profile_row['country-name'],
+               'hometown'         => $profile_row['hometown'],
+               'gender'           => $profile_row['gender'],
+               'marital'          => $profile_row['marital'],
+               'marital_with'     => $profile_row['with'],
+               'marital_since'    => $profile_row['howlong'],
+               'sexual'           => $profile_row['sexual'],
+               'politic'          => $profile_row['politic'],
+               'religion'         => $profile_row['religion'],
+               'public_keywords'  => $profile_row['pub_keywords'],
+               'private_keywords' => $profile_row['prv_keywords'],
+               'likes'            => bbcode(api_clean_plain_items($profile_row['likes'])    , false, false, 2, false),
+               'dislikes'         => bbcode(api_clean_plain_items($profile_row['dislikes']) , false, false, 2, false),
+               'about'            => bbcode(api_clean_plain_items($profile_row['about'])    , false, false, 2, false),
+               'music'            => bbcode(api_clean_plain_items($profile_row['music'])    , false, false, 2, false),
+               'book'             => bbcode(api_clean_plain_items($profile_row['book'])     , false, false, 2, false),
+               'tv'               => bbcode(api_clean_plain_items($profile_row['tv'])       , false, false, 2, false),
+               'film'             => bbcode(api_clean_plain_items($profile_row['film'])     , false, false, 2, false),
+               'interest'         => bbcode(api_clean_plain_items($profile_row['interest']) , false, false, 2, false),
+               'romance'          => bbcode(api_clean_plain_items($profile_row['romance'])  , false, false, 2, false),
+               'work'             => bbcode(api_clean_plain_items($profile_row['work'])     , false, false, 2, false),
+               'education'        => bbcode(api_clean_plain_items($profile_row['education']), false, false, 2, false),
+               'social_networks'  => bbcode(api_clean_plain_items($profile_row['contact'])  , false, false, 2, false),
+               'homepage'         => $profile_row['homepage'],
+               'users'            => null
+       );
+       return $profile;
 }
 
 /**
  * @brief format items to be returned by api
  *
- * @param array $r array of items
- * @param array $user_info
- * @param bool $filter_user filter items by $user_info
+ * @param array  $r 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)
  */
 function api_format_items($r, $user_info, $filter_user = false, $type = "json")
 {
@@ -3031,9 +3131,9 @@ function api_format_items($r, $user_info, $filter_user = false, $type = "json")
                }
 
                if (($item['item_network'] != "") && ($status["source"] == 'web')) {
-                       $status["source"] = network_to_name($item['item_network'], $user_info['url']);
-               } elseif (($item['item_network'] != "") && (network_to_name($item['item_network'], $user_info['url']) != $status["source"])) {
-                       $status["source"] = trim($status["source"].' ('.network_to_name($item['item_network'], $user_info['url']).')');
+                       $status["source"] = ContactSelector::networkToName($item['item_network'], $user_info['url']);
+               } elseif (($item['item_network'] != "") && (ContactSelector::networkToName($item['item_network'], $user_info['url']) != $status["source"])) {
+                       $status["source"] = trim($status["source"].' ('.ContactSelector::networkToName($item['item_network'], $user_info['url']).')');
                }
 
 
@@ -3087,6 +3187,13 @@ function api_format_items($r, $user_info, $filter_user = false, $type = "json")
        return $ret;
 }
 
+/**
+ * Returns the remaining number of API requests available to the user before the API limit is reached.
+ *
+ * @param string $type Return type (atom, rss, xml, json)
+ *
+ * @return array|string
+ */
 function api_account_rate_limit_status($type)
 {
        if ($type == "xml") {
@@ -3112,9 +3219,16 @@ function api_account_rate_limit_status($type)
        return api_format_data('hash', $type, array('hash' => $hash));
 }
 
-/// @TODO move to top of file or somwhere better
+/// @TODO move to top of file or somewhere better
 api_register_func('api/account/rate_limit_status', 'api_account_rate_limit_status', true);
 
+/**
+ * Returns the string "ok" in the requested format with a 200 OK HTTP status code.
+ *
+ * @param string $type Return type (atom, rss, xml, json)
+ *
+ * @return array|string
+ */
 function api_help_test($type)
 {
        if ($type == 'xml') {
@@ -3126,9 +3240,15 @@ function api_help_test($type)
        return api_format_data('ok', $type, array("ok" => $ok));
 }
 
-/// @TODO move to top of file or somwhere better
+/// @TODO move to top of file or somewhere better
 api_register_func('api/help/test', 'api_help_test', false);
 
+/**
+ *
+ * @param string $type Return type (atom, rss, xml, json)
+ *
+ * @return array|string
+ */
 function api_lists($type)
 {
        $ret = array();
@@ -3136,9 +3256,17 @@ function api_lists($type)
        return api_format_data('lists', $type, array("lists_list" => $ret));
 }
 
-/// @TODO move to top of file or somwhere better
+/// @TODO move to top of file or somewhere better
 api_register_func('api/lists', 'api_lists', true);
 
+/**
+ * Returns all lists the user subscribes to.
+ *
+ * @param string $type Return type (atom, rss, xml, json)
+ *
+ * @return array|string
+ * @see https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/get-lists-list
+ */
 function api_lists_list($type)
 {
        $ret = array();
@@ -3146,15 +3274,15 @@ function api_lists_list($type)
        return api_format_data('lists', $type, array("lists_list" => $ret));
 }
 
-/// @TODO move to top of file or somwhere better
+/// @TODO move to top of file or somewhere better
 api_register_func('api/lists/list', 'api_lists_list', true);
 
 /**
- * @brief Returns either the friends of the follower list
- *
- * Note: Considers friends and followers lists to be private and won't return
+ * Considers friends and followers lists to be private and won't return
  * anything if any user_id parameter is passed.
  *
+ * @brief Returns either the friends of the follower list
+ *
  * @param string $qtype Either "friends" or "followers"
  * @return boolean|array
  * @throws ForbiddenException
@@ -3239,6 +3367,8 @@ function api_statuses_f($qtype)
 
 
 /**
+ * Returns the user's friends.
+ *
  * @brief Returns the list of friends of the provided user
  *
  * @deprecated By Twitter API in favor of friends/list
@@ -3256,7 +3386,9 @@ function api_statuses_friends($type)
 }
 
 /**
- * @brief Returns the list of friends of the provided user
+ * Returns the user's followers.
+ *
+ * @brief Returns the list of followers of the provided user
  *
  * @deprecated By Twitter API in favor of friends/list
  *
@@ -3324,6 +3456,13 @@ function api_friendships_incoming($type)
 /// @TODO move to top of file or somewhere better
 api_register_func('api/friendships/incoming', 'api_friendships_incoming', true);
 
+/**
+ * Returns the instance's configuration information.
+ *
+ * @param string $type Return type (atom, rss, xml, json)
+ *
+ * @return array|string
+ */
 function api_statusnet_config($type)
 {
        $a = get_app();
@@ -3363,6 +3502,12 @@ function api_statusnet_config($type)
 api_register_func('api/gnusocial/config', 'api_statusnet_config', false);
 api_register_func('api/statusnet/config', 'api_statusnet_config', false);
 
+/**
+ *
+ * @param string $type Return type (atom, rss, xml, json)
+ *
+ * @return array|string
+ */
 function api_statusnet_version($type)
 {
        // liar
@@ -3376,19 +3521,20 @@ api_register_func('api/gnusocial/version', 'api_statusnet_version', false);
 api_register_func('api/statusnet/version', 'api_statusnet_version', false);
 
 /**
+ *
+ * @param string $type Return type (atom, rss, xml, json)
+ *
  * @todo use api_format_data() to return data
  */
-function api_ff_ids($type, $qtype)
+function api_ff_ids($type)
 {
-       $a = get_app();
-
        if (! api_user()) {
                throw new ForbiddenException();
        }
 
-       $user_info = api_get_user($a);
+       api_get_user($a);
 
-       $stringify_ids = (x($_REQUEST, 'stringify_ids') ? $_REQUEST['stringify_ids'] : false);
+       $stringify_ids = defaults($_REQUEST, 'stringify_ids', false);
 
        $r = q(
                "SELECT `pcontact`.`id` FROM `contact`
@@ -3396,7 +3542,6 @@ function api_ff_ids($type, $qtype)
                        WHERE `contact`.`uid` = %s AND NOT `contact`.`self`",
                intval(api_user())
        );
-
        if (!DBM::is_result($r)) {
                return;
        }
@@ -3413,20 +3558,44 @@ function api_ff_ids($type, $qtype)
        return api_format_data("ids", $type, array('id' => $ids));
 }
 
+/**
+ * Returns the ID of every user the user is following.
+ *
+ * @param string $type Return type (atom, rss, xml, json)
+ *
+ * @return array|string
+ * @see https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-friends-ids
+ */
 function api_friends_ids($type)
 {
-       return api_ff_ids($type, 'friends');
+       return api_ff_ids($type);
 }
 
+/**
+ * Returns the ID of every user following the user.
+ *
+ * @param string $type Return type (atom, rss, xml, json)
+ *
+ * @return array|string
+ * @see https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-followers-ids
+ */
 function api_followers_ids($type)
 {
-       return api_ff_ids($type, 'followers');
+       return api_ff_ids($type);
 }
 
 /// @TODO move to top of file or somewhere better
 api_register_func('api/friends/ids', 'api_friends_ids', true);
 api_register_func('api/followers/ids', 'api_followers_ids', true);
 
+/**
+ * Sends a new direct message.
+ *
+ * @param string $type Return type (atom, rss, xml, json)
+ *
+ * @return array|string
+ * @see https://developer.twitter.com/en/docs/direct-messages/sending-and-receiving/api-reference/new-message
+ */
 function api_direct_messages_new($type)
 {
 
@@ -3475,7 +3644,7 @@ function api_direct_messages_new($type)
                }
        }
 
-       $id = send_message($recipient['cid'], $_POST['text'], $sub, $replyto);
+       $id = Mail::send($recipient['cid'], $_POST['text'], $sub, $replyto);
 
        if ($id > -1) {
                $r = q("SELECT * FROM `mail` WHERE id=%d", intval($id));
@@ -3499,10 +3668,13 @@ function api_direct_messages_new($type)
 api_register_func('api/direct_messages/new', 'api_direct_messages_new', true, API_METHOD_POST);
 
 /**
+ * Destroys a direct message.
+ *
  * @brief delete a direct_message from mail table through api
  *
  * @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
  * @return string
+ * @see https://developer.twitter.com/en/docs/direct-messages/sending-and-receiving/api-reference/delete-message
  */
 function api_direct_messages_destroy($type)
 {
@@ -3576,6 +3748,14 @@ function api_direct_messages_destroy($type)
 /// @TODO move to top of file or somewhere better
 api_register_func('api/direct_messages/destroy', 'api_direct_messages_destroy', true, API_METHOD_DELETE);
 
+/**
+ *
+ * @param string $type Return type (atom, rss, xml, json)
+ * @param string $box
+ * @param string $verbose
+ *
+ * @return array|string
+ */
 function api_direct_messages_box($type, $box, $verbose)
 {
        $a = get_app();
@@ -3667,24 +3847,52 @@ function api_direct_messages_box($type, $box, $verbose)
        return api_format_data("direct-messages", $type, $data);
 }
 
+/**
+ * Returns the most recent direct messages sent by the user.
+ *
+ * @param string $type Return type (atom, rss, xml, json)
+ *
+ * @return array|string
+ * @see https://developer.twitter.com/en/docs/direct-messages/sending-and-receiving/api-reference/get-sent-message
+ */
 function api_direct_messages_sentbox($type)
 {
        $verbose = (x($_GET, 'friendica_verbose') ? strtolower($_GET['friendica_verbose']) : "false");
        return api_direct_messages_box($type, "sentbox", $verbose);
 }
 
+/**
+ * Returns the most recent direct messages sent to the user.
+ *
+ * @param string $type Return type (atom, rss, xml, json)
+ *
+ * @return array|string
+ * @see https://developer.twitter.com/en/docs/direct-messages/sending-and-receiving/api-reference/get-messages
+ */
 function api_direct_messages_inbox($type)
 {
        $verbose = (x($_GET, 'friendica_verbose') ? strtolower($_GET['friendica_verbose']) : "false");
        return api_direct_messages_box($type, "inbox", $verbose);
 }
 
+/**
+ *
+ * @param string $type Return type (atom, rss, xml, json)
+ *
+ * @return array|string
+ */
 function api_direct_messages_all($type)
 {
        $verbose = (x($_GET, 'friendica_verbose') ? strtolower($_GET['friendica_verbose']) : "false");
        return api_direct_messages_box($type, "all", $verbose);
 }
 
+/**
+ *
+ * @param string $type Return type (atom, rss, xml, json)
+ *
+ * @return array|string
+ */
 function api_direct_messages_conversation($type)
 {
        $verbose = (x($_GET, 'friendica_verbose') ? strtolower($_GET['friendica_verbose']) : "false");
@@ -3697,7 +3905,12 @@ api_register_func('api/direct_messages/all', 'api_direct_messages_all', true);
 api_register_func('api/direct_messages/sent', 'api_direct_messages_sentbox', true);
 api_register_func('api/direct_messages', 'api_direct_messages_inbox', true);
 
-function api_oauth_request_token($type)
+/**
+ * Returns an OAuth Request Token.
+ *
+ * @see https://oauth.net/core/1.0/#auth_step1
+ */
+function api_oauth_request_token()
 {
        $oauth1 = new FKOAuth1();
        try {
@@ -3710,7 +3923,13 @@ function api_oauth_request_token($type)
        killme();
 }
 
-function api_oauth_access_token($type)
+/**
+ * Returns an OAuth Access Token.
+ *
+ * @return array|string
+ * @see https://oauth.net/core/1.0/#auth_step3
+ */
+function api_oauth_access_token()
 {
        $oauth1 = new FKOAuth1();
        try {
@@ -4085,7 +4304,7 @@ function api_fr_photo_delete($type)
  * @brief returns the details of a specified photo id, if scale is given, returns the photo data in base 64
  *
  * @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
- * @return string
+ * @return string|array
  */
 function api_fr_photo_detail($type)
 {
@@ -4107,10 +4326,14 @@ function api_fr_photo_detail($type)
 
 
 /**
+ * Updates the user’s profile image.
+ *
  * @brief updates the profile image for the user (either a specified profile or the default profile)
  *
  * @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
+ *
  * @return string
+ * @see https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/post-account-update_profile_image
  */
 function api_account_update_profile_image($type)
 {
@@ -4118,7 +4341,7 @@ function api_account_update_profile_image($type)
                throw new ForbiddenException();
        }
        // input params
-       $profileid = (x($_REQUEST, 'profile_id') ? $_REQUEST['profile_id'] : 0);
+       $profileid = defaults($_REQUEST, 'profile_id', 0);
 
        // error if image data is missing
        if (!x($_FILES, 'image')) {
@@ -4164,13 +4387,13 @@ function api_account_update_profile_image($type)
        }
        // change specified profile or all profiles to the new resource-id
        if ($is_default_profile) {
-               $r = q(
+               q(
                        "UPDATE `photo` SET `profile` = 0 WHERE `profile` = 1 AND `resource-id` != '%s' AND `uid` = %d",
                        dbesc($data['photo']['id']),
                        intval(local_user())
                );
 
-               $r = q(
+               q(
                        "UPDATE `contact` SET `photo` = '%s', `thumb` = '%s', `micro` = '%s'  WHERE `self` AND `uid` = %d",
                        dbesc(System::baseUrl() . '/photo/' . $data['photo']['id'] . '-4.' . $fileext),
                        dbesc(System::baseUrl() . '/photo/' . $data['photo']['id'] . '-5.' . $fileext),
@@ -4178,7 +4401,7 @@ function api_account_update_profile_image($type)
                        intval(local_user())
                );
        } else {
-               $r = q(
+               q(
                        "UPDATE `profile` SET `photo` = '%s', `thumb` = '%s' WHERE `id` = %d AND `uid` = %d",
                        dbesc(System::baseUrl() . '/photo/' . $data['photo']['id'] . '-4.' . $filetype),
                        dbesc(System::baseUrl() . '/photo/' . $data['photo']['id'] . '-5.' . $filetype),
@@ -4190,7 +4413,7 @@ function api_account_update_profile_image($type)
        // we'll set the updated profile-photo timestamp even if it isn't the default profile,
        // so that browsers will do a cache update unconditionally
 
-       $r = q(
+       q(
                "UPDATE `contact` SET `avatar-date` = '%s' WHERE `self` = 1 AND `uid` = %d",
                dbesc(datetime_convert()),
                intval(local_user())
@@ -4224,7 +4447,47 @@ api_register_func('api/friendica/photo/delete', 'api_fr_photo_delete', true, API
 api_register_func('api/friendica/photo', 'api_fr_photo_detail', true);
 api_register_func('api/account/update_profile_image', 'api_account_update_profile_image', true, API_METHOD_POST);
 
+/**
+ * Update user profile
+ *
+ * @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
+ *
+ * @return array|string
+ */
+function api_account_update_profile($type)
+{
+       $local_user = api_user();
+       $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']]);
+       }
+
+       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']]);
+       }
+
+       Worker::add(PRIORITY_LOW, 'ProfileUpdate', $local_user);
+       // Update global directory in background
+       if ($api_user['url'] && strlen(Config::get('system', 'directory'))) {
+               Worker::add(PRIORITY_LOW, "Directory", $api_user['url']);
+       }
+
+       return api_account_verify_credentials($type);
+}
+
+/// @TODO move to top of file or somewhere better
+api_register_func('api/account/update_profile', 'api_account_update_profile', true, API_METHOD_POST);
+
+/**
+ *
+ * @param string $acl_string
+ */
 function check_acl_input($acl_string)
 {
        if ($acl_string == null || $acl_string == " ") {
@@ -4250,6 +4513,21 @@ function check_acl_input($acl_string)
        return $contact_not_found;
 }
 
+/**
+ *
+ * @param string  $mediatype
+ * @param array   $media
+ * @param string  $type
+ * @param string  $album
+ * @param string  $allow_cid
+ * @param string  $deny_cid
+ * @param string  $allow_gid
+ * @param string  $deny_gid
+ * @param string  $desc
+ * @param integer $profile
+ * @param boolean $visibility
+ * @param string  $photo_id
+ */
 function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $desc, $profile = 0, $visibility = false, $photo_id = null)
 {
        $visitor   = 0;
@@ -4398,6 +4676,16 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $
        }
 }
 
+/**
+ *
+ * @param string  $hash
+ * @param string  $allow_cid
+ * @param string  $deny_cid
+ * @param string  $allow_gid
+ * @param string  $deny_gid
+ * @param string  $filetype
+ * @param boolean $visibility
+ */
 function post_photo_item($hash, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $filetype, $visibility = false)
 {
        // get data about the api authenticated user
@@ -4443,6 +4731,14 @@ function post_photo_item($hash, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $f
        item_store($arr);
 }
 
+/**
+ *
+ * @param string $type
+ * @param int    $scale
+ * @param string $photo_id
+ *
+ * @return array
+ */
 function prepare_photo_data($type, $scale, $photo_id)
 {
        $scale_sql = ($scale === false ? "" : sprintf("AND scale=%d", intval($scale)));
@@ -4574,22 +4870,22 @@ function api_friendica_remoteauth()
 
        // traditional DFRN
 
-       $r = dba::select('contact', [], ['uid' => api_user(), 'nurl' => $c_url], ['limit' => 1]);
+       $contact = dba::selectFirst('contact', [], ['uid' => api_user(), 'nurl' => $c_url]);
 
-       if (!DBM::is_result($r) || ($r['network'] !== NETWORK_DFRN)) {
+       if (!DBM::is_result($contact) || ($contact['network'] !== NETWORK_DFRN)) {
                throw new BadRequestException("Unknown contact");
        }
 
-       $cid = $r['id'];
+       $cid = $contact['id'];
 
-       $dfrn_id = $orig_id = (($r['issued-id']) ? $r['issued-id'] : $r['dfrn-id']);
+       $dfrn_id = defaults($contact, 'issued-id', $contact['dfrn-id']);
 
-       if ($r['duplex'] && $r['issued-id']) {
-               $orig_id = $r['issued-id'];
+       if ($contact['duplex'] && $contact['issued-id']) {
+               $orig_id = $contact['issued-id'];
                $dfrn_id = '1:' . $orig_id;
        }
-       if ($r['duplex'] && $r['dfrn-id']) {
-               $orig_id = $r['dfrn-id'];
+       if ($contact['duplex'] && $contact['dfrn-id']) {
+               $orig_id = $contact['dfrn-id'];
                $dfrn_id = '0:' . $orig_id;
        }
 
@@ -4605,10 +4901,10 @@ function api_friendica_remoteauth()
                intval(time() + 45)
        );
 
-       logger($r['name'] . ' ' . $sec, LOGGER_DEBUG);
+       logger($contact['name'] . ' ' . $sec, LOGGER_DEBUG);
        $dest = ($url ? '&destination_url=' . $url : '');
        goaway(
-               $r['poll'] . '?dfrn_id=' . $dfrn_id
+               $contact['poll'] . '?dfrn_id=' . $dfrn_id
                . '&dfrn_version=' . DFRN_PROTOCOL_VERSION
                . '&type=profile&sec=' . $sec . $dest . $quiet
        );
@@ -4716,13 +5012,16 @@ function api_share_as_retweet(&$item)
        return $reshared_item;
 }
 
+/**
+ *
+ * @param string $profile
+ *
+ * @return string|false
+ * @todo remove trailing junk from profile url
+ * @todo pump.io check has to check the website
+ */
 function api_get_nick($profile)
 {
-       /* To-Do:
-               - remove trailing junk from profile url
-               - pump.io check has to check the website
-       */
-
        $nick = "";
 
        $r = q(
@@ -4797,6 +5096,12 @@ function api_get_nick($profile)
        return false;
 }
 
+/**
+ *
+ * @param array $item
+ *
+ * @return array
+ */
 function api_in_reply_to($item)
 {
        $in_reply_to = array();
@@ -4855,6 +5160,12 @@ function api_in_reply_to($item)
        return $in_reply_to;
 }
 
+/**
+ *
+ * @param string $Text
+ *
+ * @return string
+ */
 function api_clean_plain_items($Text)
 {
        $include_entities = strtolower(x($_REQUEST, 'include_entities') ? $_REQUEST['include_entities'] : "false");
@@ -4904,6 +5215,12 @@ function api_clean_attachments($body)
        return $body;
 }
 
+/**
+ *
+ * @param array $contacts
+ *
+ * @return array
+ */
 function api_best_nickname(&$contacts)
 {
        $best_contact = array();
@@ -4966,7 +5283,13 @@ function api_best_nickname(&$contacts)
        }
 }
 
-// return all or a specified group of the user with the containing contacts
+/**
+ * Return all or a specified group of the user with the containing contacts.
+ *
+ * @param string $type Return type (atom, rss, xml, json)
+ *
+ * @return array|string
+ */
 function api_friendica_group_show($type)
 {
        $a = get_app();
@@ -5024,7 +5347,13 @@ function api_friendica_group_show($type)
 api_register_func('api/friendica/group_show', 'api_friendica_group_show', true);
 
 
-// delete the specified group of the user
+/**
+ * Delete the specified group of the user.
+ *
+ * @param string $type Return type (atom, rss, xml, json)
+ *
+ * @return array|string
+ */
 function api_friendica_group_delete($type)
 {
        $a = get_app();
@@ -5080,7 +5409,13 @@ function api_friendica_group_delete($type)
 api_register_func('api/friendica/group_delete', 'api_friendica_group_delete', true, API_METHOD_DELETE);
 
 
-// create the specified group with the posted array of contacts
+/**
+ * Create the specified group with the posted array of contacts.
+ *
+ * @param string $type Return type (atom, rss, xml, json)
+ *
+ * @return array|string
+ */
 function api_friendica_group_create($type)
 {
        $a = get_app();
@@ -5143,7 +5478,7 @@ function api_friendica_group_create($type)
                        intval($uid)
                );
                if (count($contact)) {
-                       $result = Group::addMember($gid, $cid);
+                       Group::addMember($gid, $cid);
                } else {
                        $erroraddinguser = true;
                        $errorusers[] = $cid;
@@ -5158,7 +5493,13 @@ function api_friendica_group_create($type)
 api_register_func('api/friendica/group_create', 'api_friendica_group_create', true, API_METHOD_POST);
 
 
-// update the specified group with the posted array of contacts
+/**
+ * Update the specified group with the posted array of contacts.
+ *
+ * @param string $type Return type (atom, rss, xml, json)
+ *
+ * @return array|string
+ */
 function api_friendica_group_update($type)
 {
        $a = get_app();
@@ -5193,7 +5534,7 @@ function api_friendica_group_update($type)
                        $found = ($user['cid'] == $cid ? true : false);
                }
                if (!$found) {
-                       $ret = Group::removeMemberByName($uid, $name, $cid);
+                       Group::removeMemberByName($uid, $name, $cid);
                }
        }
 
@@ -5210,7 +5551,7 @@ function api_friendica_group_update($type)
                );
 
                if (count($contact)) {
-                       $result = Group::addMember($gid, $cid);
+                       Group::addMember($gid, $cid);
                } else {
                        $erroraddinguser = true;
                        $errorusers[] = $cid;
@@ -5225,6 +5566,12 @@ function api_friendica_group_update($type)
 
 api_register_func('api/friendica/group_update', 'api_friendica_group_update', true, API_METHOD_POST);
 
+/**
+ *
+ * @param string $type Return type (atom, rss, xml, json)
+ *
+ * @return array|string
+ */
 function api_friendica_activity($type)
 {
        $a = get_app();
@@ -5251,7 +5598,7 @@ function api_friendica_activity($type)
        }
 }
 
-/// @TODO move to top of file or somwhere better
+/// @TODO move to top of file or somewhere better
 api_register_func('api/friendica/activity/like', 'api_friendica_activity', true, API_METHOD_POST);
 api_register_func('api/friendica/activity/dislike', 'api_friendica_activity', true, API_METHOD_POST);
 api_register_func('api/friendica/activity/attendyes', 'api_friendica_activity', true, API_METHOD_POST);
@@ -5296,10 +5643,10 @@ function api_friendica_notification($type)
 }
 
 /**
- * @brief Set notification as seen and returns associated item (if possible)
- *
  * POST request with 'id' param as notification id
  *
+ * @brief Set notification as seen and returns associated item (if possible)
+ *
  * @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
  * @return string
  */
@@ -5342,7 +5689,7 @@ function api_friendica_notification_seen($type)
        return api_format_data('result', $type, array('result' => "success"));
 }
 
-/// @TODO move to top of file or somwhere better
+/// @TODO move to top of file or somewhere better
 api_register_func('api/friendica/notification/seen', 'api_friendica_notification_seen', true, API_METHOD_POST);
 api_register_func('api/friendica/notification', 'api_friendica_notification', true, API_METHOD_GET);
 
@@ -5400,14 +5747,14 @@ function api_friendica_direct_messages_setseen($type)
        }
 }
 
-/// @TODO move to top of file or somwhere better
+/// @TODO move to top of file or somewhere better
 api_register_func('api/friendica/direct_messages_setseen', 'api_friendica_direct_messages_setseen', true);
 
 /**
  * @brief search for direct_messages containing a searchstring through api
  *
  * @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
- * @return string (success: success=true if found and search_result contains found messages
+ * @return string (success: success=true if found and search_result contains found messages,
  *                          success=false if nothing was found, search_result='nothing found',
  *                error: result=error with error message)
  */
@@ -5463,7 +5810,7 @@ function api_friendica_direct_messages_search($type)
        return api_format_data("direct_message_search", $type, array('$result' => $success));
 }
 
-/// @TODO move to top of file or somwhere better
+/// @TODO move to top of file or somewhere better
 api_register_func('api/friendica/direct_messages_search', 'api_friendica_direct_messages_search', true);
 
 /**
@@ -5508,7 +5855,7 @@ function api_friendica_profile_show($type)
        // loop through all returned profiles and retrieve data and users
        $k = 0;
        foreach ($r as $rr) {
-               $profile = api_format_items_profiles($rr, $type);
+               $profile = api_format_items_profiles($rr);
 
                // select all users from contact table, loop and prepare standard return for user data
                $users = array();
@@ -5571,7 +5918,7 @@ function api_saved_searches_list($type)
        return api_format_data("terms", $type, array('terms' => $result));
 }
 
-/// @TODO move to top of file or somwhere better
+/// @TODO move to top of file or somewhere better
 api_register_func('api/saved_searches/list', 'api_saved_searches_list', true);
 
 /*