X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=include%2Fapi.php;h=d762507cf81f02f98fbd9c3c74556bf3fdab719c;hb=6e48df21631f1c616a6c88369677ecf1038f4d1f;hp=20b3844cd5cc93d7a96cf03f1b1f96a34a5920e7;hpb=c5867df24cd921b36d6f2d996ee6c7e229b146c6;p=friendica.git diff --git a/include/api.php b/include/api.php index 20b3844cd5..d762507cf8 100644 --- a/include/api.php +++ b/include/api.php @@ -11,9 +11,9 @@ use Friendica\Content\ContactSelector; use Friendica\Content\Feature; use Friendica\Content\Text\BBCode; use Friendica\Content\Text\HTML; -use Friendica\Core\Addon; use Friendica\Core\Authentication; use Friendica\Core\Config; +use Friendica\Core\Hook; use Friendica\Core\L10n; use Friendica\Core\Logger; use Friendica\Core\NotificationsManager; @@ -46,7 +46,6 @@ use Friendica\Util\Proxy as ProxyUtils; use Friendica\Util\Strings; use Friendica\Util\XML; -require_once 'include/conversation.php'; require_once 'mod/share.php'; require_once 'mod/item.php'; require_once 'mod/wall_upload.php'; @@ -56,6 +55,8 @@ define('API_METHOD_GET', 'GET'); define('API_METHOD_POST', 'POST,PUT'); define('API_METHOD_DELETE', 'POST,DELETE'); +define('API_LOG_PREFIX', 'API {action} - '); + $API = []; $called_api = []; @@ -98,9 +99,9 @@ function api_source() return "Twidere"; } - Logger::log("Unrecognized user-agent ".$_SERVER['HTTP_USER_AGENT'], Logger::DEBUG); + Logger::info(API_LOG_PREFIX . 'Unrecognized user-agent', ['module' => 'api', 'action' => 'source', 'http_user_agent' => $_SERVER['HTTP_USER_AGENT']]); } else { - Logger::log("Empty user-agent", Logger::DEBUG); + Logger::info(API_LOG_PREFIX . 'Empty user-agent', ['module' => 'api', 'action' => 'source']); } return "api"; @@ -175,14 +176,14 @@ function api_login(App $a) list($consumer, $token) = $oauth1->verify_request($request); if (!is_null($token)) { $oauth1->loginUser($token->uid); - Addon::callHooks('logged_in', $a->user); + Hook::callAll('logged_in', $a->user); return; } echo __FILE__.__LINE__.__FUNCTION__ . "
"; var_dump($consumer, $token); die(); } catch (Exception $e) { - Logger::log($e); + Logger::warning(API_LOG_PREFIX . 'error', ['module' => 'api', 'action' => 'login', 'exception' => $e->getMessage()]); } // workaround for HTTP-auth in CGI mode @@ -196,7 +197,7 @@ function api_login(App $a) } if (empty($_SERVER['PHP_AUTH_USER'])) { - Logger::log('API_login: ' . print_r($_SERVER, true), Logger::DEBUG); + Logger::debug(API_LOG_PREFIX . 'failed', ['module' => 'api', 'action' => 'login', 'parameters' => $_SERVER]); header('WWW-Authenticate: Basic realm="Friendica"'); throw new UnauthorizedException("This API requires login"); } @@ -225,7 +226,7 @@ function api_login(App $a) * Addons should never set 'authenticated' except to indicate success - as hooks may be chained * and later addons should not interfere with an earlier one that succeeded. */ - Addon::callHooks('authenticate', $addon_auth); + Hook::callAll('authenticate', $addon_auth); if ($addon_auth['authenticated'] && count($addon_auth['user_record'])) { $record = $addon_auth['user_record']; @@ -237,7 +238,7 @@ function api_login(App $a) } if (!DBA::isResult($record)) { - Logger::log('API_login failure: ' . print_r($_SERVER, true), Logger::DEBUG); + Logger::debug(API_LOG_PREFIX . 'failed', ['module' => 'api', 'action' => 'login', 'parameters' => $_SERVER]); header('WWW-Authenticate: Basic realm="Friendica"'); //header('HTTP/1.0 401 Unauthorized'); //die('This api requires login'); @@ -248,7 +249,7 @@ function api_login(App $a) $_SESSION["allow_api"] = true; - Addon::callHooks('logged_in', $a->user); + Hook::callAll('logged_in', $a->user); } /** @@ -310,33 +311,35 @@ function api_call(App $a) api_login($a); } - Logger::log('API call for ' . $a->user['username'] . ': ' . $a->query_string); - Logger::log('API parameters: ' . print_r($_REQUEST, true)); + Logger::info(API_LOG_PREFIX . 'username {username}', ['module' => 'api', 'action' => 'call', 'username' => $a->user['username']]); + Logger::debug(API_LOG_PREFIX . 'parameters', ['module' => 'api', 'action' => 'call', 'parameters' => $_REQUEST]); $stamp = microtime(true); $return = call_user_func($info['func'], $type); $duration = (float) (microtime(true) - $stamp); - Logger::log("API call duration: " . round($duration, 2) . "\t" . $a->query_string, Logger::DEBUG); + + Logger::info(API_LOG_PREFIX . 'username {username}', ['module' => 'api', 'action' => 'call', 'username' => $a->user['username'], 'duration' => round($duration, 2)]); if (Config::get("system", "profiler")) { $duration = microtime(true)-$a->performance["start"]; /// @TODO round() really everywhere? - Logger::log( - parse_url($a->query_string, PHP_URL_PATH) . ": " . sprintf( - "Database: %s/%s, Cache %s/%s, Network: %s, I/O: %s, Other: %s, Total: %s", - round($a->performance["database"] - $a->performance["database_write"], 3), - round($a->performance["database_write"], 3), - round($a->performance["cache"], 3), - round($a->performance["cache_write"], 3), - round($a->performance["network"], 2), - round($a->performance["file"], 2), - round($duration - ($a->performance["database"] - + $a->performance["cache"] + $a->performance["cache_write"] - + $a->performance["network"] + $a->performance["file"]), 2), - round($duration, 2) - ), - Logger::DEBUG + Logger::debug( + API_LOG_PREFIX . 'performance', + [ + 'module' => 'api', + 'action' => 'call', + 'database_read' => round($a->performance["database"] - $a->performance["database_write"], 3), + 'database_write' => round($a->performance["database_write"], 3), + 'cache_read' => round($a->performance["cache"], 3), + 'cache_write' => round($a->performance["cache_write"], 3), + 'network_io' => round($a->performance["network"], 2), + 'file_io' => round($a->performance["file"], 2), + 'other_io' => round($duration - ($a->performance["database"] + + $a->performance["cache"] + $a->performance["cache_write"] + + $a->performance["network"] + $a->performance["file"]), 2), + 'total' => round($duration, 2) + ] ); if (Config::get("rendertime", "callstack")) { @@ -377,7 +380,7 @@ function api_call(App $a) $o .= $func . ": " . $time . "\n"; } } - Logger::log($o, Logger::DEBUG); + Logger::debug(API_LOG_PREFIX . $o, ['module' => 'api', 'action' => 'call']); } } @@ -414,7 +417,7 @@ function api_call(App $a) } } - Logger::log('API call not implemented: ' . $a->query_string); + Logger::warning(API_LOG_PREFIX . 'not implemented', ['module' => 'api', 'action' => 'call']); throw new NotImplementedException(); } catch (HTTPException $e) { header("HTTP/1.1 {$e->httpcode} {$e->httpdesc}"); @@ -431,7 +434,7 @@ function api_call(App $a) */ function api_error($type, $e) { - $a = get_app(); + $a = \get_app(); $error = ($e->getMessage() !== "" ? $e->getMessage() : $e->httpdesc); /// @TODO: https://dev.twitter.com/overview/api/response-codes @@ -523,7 +526,7 @@ function api_get_user(App $a, $contact_id = null) $extra_query = ""; $url = ""; - Logger::log("api_get_user: Fetching user data for user ".$contact_id, Logger::DEBUG); + Logger::info(API_LOG_PREFIX . 'Fetching data for user {user}', ['module' => 'api', 'action' => 'get_user', 'user' => $contact_id]); // Searching for contact URL if (!is_null($contact_id) && (intval($contact_id) == 0)) { @@ -607,7 +610,7 @@ function api_get_user(App $a, $contact_id = null) } } - Logger::log("api_get_user: user ".$user, Logger::DEBUG); + Logger::info(API_LOG_PREFIX . 'getting user {user}', ['module' => 'api', 'action' => 'get_user', 'user' => $user]); if (!$user) { if (api_user() === false) { @@ -619,7 +622,7 @@ function api_get_user(App $a, $contact_id = null) } } - Logger::log('api_user: ' . $extra_query . ', user: ' . $user); + Logger::info(API_LOG_PREFIX . 'found user {user}', ['module' => 'api', 'action' => 'get_user', 'user' => $user, 'extra_query' => $extra_query]); // user info $uinfo = q( @@ -946,7 +949,6 @@ function api_format_data($root_element, $type, $data) $ret = $data; break; } - return $ret; } @@ -964,7 +966,7 @@ function api_format_data($root_element, $type, $data) function api_account_verify_credentials($type) { - $a = get_app(); + $a = \get_app(); if (api_user() === false) { throw new ForbiddenException(); @@ -1028,7 +1030,7 @@ function requestdata($k) */ function api_statuses_mediap($type) { - $a = get_app(); + $a = \get_app(); if (api_user() === false) { Logger::log('api_statuses_update: no user'); @@ -1076,7 +1078,7 @@ api_register_func('api/statuses/mediap', 'api_statuses_mediap', true, API_METHOD */ function api_statuses_update($type) { - $a = get_app(); + $a = \get_app(); if (api_user() === false) { Logger::log('api_statuses_update: no user'); @@ -1218,7 +1220,7 @@ api_register_func('api/statuses/update_with_media', 'api_statuses_update', true, */ function api_media_upload() { - $a = get_app(); + $a = \get_app(); if (api_user() === false) { Logger::log('no user'); @@ -1243,8 +1245,9 @@ function api_media_upload() $returndata["media_id_string"] = (string)$media["id"]; $returndata["size"] = $media["size"]; $returndata["image"] = ["w" => $media["width"], - "h" => $media["height"], - "image_type" => $media["type"]]; + "h" => $media["height"], + "image_type" => $media["type"], + "friendica_preview_url" => $media["preview"]]; Logger::log("Media uploaded: " . print_r($returndata, true), Logger::DEBUG); @@ -1262,7 +1265,7 @@ api_register_func('api/media/upload', 'api_media_upload', true, API_METHOD_POST) */ function api_status_show($type, $item_id = 0) { - $a = get_app(); + $a = \get_app(); $user_info = api_get_user($a); @@ -1361,7 +1364,7 @@ function api_status_show($type, $item_id = 0) */ function api_users_show($type) { - $a = get_app(); + $a = \get_app(); $user_info = api_get_user($a); @@ -1437,7 +1440,7 @@ api_register_func('api/externalprofile/show', 'api_users_show'); */ function api_users_search($type) { - $a = get_app(); + $a = \get_app(); $userlist = []; @@ -1517,49 +1520,76 @@ api_register_func('api/users/lookup', 'api_users_lookup', true); */ function api_search($type) { - $a = get_app(); + $a = \get_app(); $user_info = api_get_user($a); - if (api_user() === false || $user_info === false) { - throw new ForbiddenException(); - } - - $data = []; + if (api_user() === false || $user_info === false) { throw new ForbiddenException(); } - if (empty($_REQUEST['q'])) { - throw new BadRequestException("q parameter is required."); - } + if (empty($_REQUEST['q'])) { throw new BadRequestException('q parameter is required.'); } + + $searchTerm = trim(rawurldecode($_REQUEST['q'])); + $data = []; + $data['status'] = []; + $count = 15; + $exclude_replies = !empty($_REQUEST['exclude_replies']); if (!empty($_REQUEST['rpp'])) { $count = $_REQUEST['rpp']; } elseif (!empty($_REQUEST['count'])) { $count = $_REQUEST['count']; - } else { - $count = 15; } - + $since_id = defaults($_REQUEST, 'since_id', 0); $max_id = defaults($_REQUEST, 'max_id', 0); $page = (!empty($_REQUEST['page']) ? $_REQUEST['page'] - 1 : 0); - $start = $page * $count; + $params = ['order' => ['id' => true], 'limit' => [$start, $count]]; + if (preg_match('/^#(\w+)$/', $searchTerm, $matches) === 1 && isset($matches[1])) { + $searchTerm = $matches[1]; + $condition = ["`oid` > ? + AND (`uid` = 0 OR (`uid` = ? AND NOT `global`)) + AND `otype` = ? AND `type` = ? AND `term` = ?", + $since_id, local_user(), TERM_OBJ_POST, TERM_HASHTAG, $searchTerm]; + if ($max_id > 0) { + $condition[0] .= ' AND `oid` <= ?'; + $condition[] = $max_id; + } + $terms = DBA::select('term', ['oid'], $condition, []); + $itemIds = []; + while ($term = DBA::fetch($terms)) { + $itemIds[] = $term['oid']; + } + DBA::close($terms); - $condition = ["`gravity` IN (?, ?) AND `item`.`id` > ? - AND (`item`.`uid` = 0 OR (`item`.`uid` = ? AND NOT `item`.`global`)) - AND `item`.`body` LIKE CONCAT('%',?,'%')", - GRAVITY_PARENT, GRAVITY_COMMENT, $since_id, api_user(), $_REQUEST['q']]; + if (empty($itemIds)) { + return api_format_data('statuses', $type, $data); + } - if ($max_id > 0) { - $condition[0] .= " AND `item`.`id` <= ?"; - $condition[] = $max_id; + $preCondition = ['`id` IN (' . implode(', ', $itemIds) . ')']; + if ($exclude_replies) { + $preCondition[] = '`id` = `parent`'; + } + + $condition = [implode(' AND ', $preCondition)]; + } else { + $condition = ["`id` > ? + " . ($exclude_replies ? " AND `id` = `parent` " : ' ') . " + AND (`uid` = 0 OR (`uid` = ? AND NOT `global`)) + AND `body` LIKE CONCAT('%',?,'%')", + $since_id, api_user(), $_REQUEST['q']]; + if ($max_id > 0) { + $condition[0] .= ' AND `id` <= ?'; + $condition[] = $max_id; + } } - $params = ['order' => ['id' => true], 'limit' => [$start, $count]]; $statuses = Item::selectForUser(api_user(), [], $condition, $params); $data['status'] = api_format_items(Item::inArray($statuses), $user_info); - return api_format_data("statuses", $type, $data); + bindComments($data['status']); + + return api_format_data('statuses', $type, $data); } /// @TODO move to top of file or somewhere better @@ -1578,7 +1608,7 @@ api_register_func('api/search', 'api_search', true); */ function api_statuses_home_timeline($type) { - $a = get_app(); + $a = \get_app(); $user_info = api_get_user($a); if (api_user() === false || $user_info === false) { @@ -1640,6 +1670,8 @@ function api_statuses_home_timeline($type) Item::update(['unseen' => false], ['unseen' => true, 'id' => $idarray]); } } + + bindComments($ret); $data = ['status' => $ret]; switch ($type) { @@ -1653,6 +1685,7 @@ function api_statuses_home_timeline($type) return api_format_data("statuses", $type, $data); } + /// @TODO move to top of file or somewhere better api_register_func('api/statuses/home_timeline', 'api_statuses_home_timeline', true); api_register_func('api/statuses/friends_timeline', 'api_statuses_home_timeline', true); @@ -1666,7 +1699,7 @@ api_register_func('api/statuses/friends_timeline', 'api_statuses_home_timeline', */ function api_statuses_public_timeline($type) { - $a = get_app(); + $a = \get_app(); $user_info = api_get_user($a); if (api_user() === false || $user_info === false) { @@ -1722,6 +1755,8 @@ function api_statuses_public_timeline($type) $ret = api_format_items($r, $user_info, false, $type); + bindComments($ret); + $data = ['status' => $ret]; switch ($type) { case "atom": @@ -1748,7 +1783,7 @@ api_register_func('api/statuses/public_timeline', 'api_statuses_public_timeline' */ function api_statuses_networkpublic_timeline($type) { - $a = get_app(); + $a = \get_app(); $user_info = api_get_user($a); if (api_user() === false || $user_info === false) { @@ -1779,6 +1814,8 @@ function api_statuses_networkpublic_timeline($type) $ret = api_format_items(Item::inArray($statuses), $user_info, false, $type); + bindComments($ret); + $data = ['status' => $ret]; switch ($type) { case "atom": @@ -1803,7 +1840,7 @@ api_register_func('api/statuses/networkpublic_timeline', 'api_statuses_networkpu */ function api_statuses_show($type) { - $a = get_app(); + $a = \get_app(); $user_info = api_get_user($a); if (api_user() === false || $user_info === false) { @@ -1876,7 +1913,7 @@ api_register_func('api/statuses/show', 'api_statuses_show', true); */ function api_conversation_show($type) { - $a = get_app(); + $a = \get_app(); $user_info = api_get_user($a); if (api_user() === false || $user_info === false) { @@ -1904,7 +1941,7 @@ function api_conversation_show($type) $id = intval(defaults($a->argv, 4, 0)); } - Logger::log('API: api_conversation_show: '.$id); + Logger::info(API_LOG_PREFIX . '{subaction}', ['module' => 'api', 'action' => 'conversation', 'subaction' => 'show', 'id' => $id]); // try to fetch the item for the local user - or the public item, if there is no local one $item = Item::selectFirst(['parent-uri'], ['id' => $id]); @@ -1955,7 +1992,7 @@ function api_statuses_repeat($type) { global $called_api; - $a = get_app(); + $a = \get_app(); if (api_user() === false) { throw new ForbiddenException(); @@ -2020,7 +2057,7 @@ api_register_func('api/statuses/retweet', 'api_statuses_repeat', true, API_METHO */ function api_statuses_destroy($type) { - $a = get_app(); + $a = \get_app(); if (api_user() === false) { throw new ForbiddenException(); @@ -2061,7 +2098,7 @@ api_register_func('api/statuses/destroy', 'api_statuses_destroy', true, API_METH */ function api_statuses_mentions($type) { - $a = get_app(); + $a = \get_app(); $user_info = api_get_user($a); if (api_user() === false || $user_info === false) { @@ -2129,7 +2166,7 @@ api_register_func('api/statuses/replies', 'api_statuses_mentions', true); */ function api_statuses_user_timeline($type) { - $a = get_app(); + $a = \get_app(); $user_info = api_get_user($a); if (api_user() === false || $user_info === false) { @@ -2182,6 +2219,8 @@ function api_statuses_user_timeline($type) $ret = api_format_items(Item::inArray($statuses), $user_info, true, $type); + bindComments($ret); + $data = ['status' => $ret]; switch ($type) { case "atom": @@ -2207,7 +2246,7 @@ api_register_func('api/statuses/user_timeline', 'api_statuses_user_timeline', tr */ function api_favorites_create_destroy($type) { - $a = get_app(); + $a = \get_app(); if (api_user() === false) { throw new ForbiddenException(); @@ -2285,7 +2324,7 @@ function api_favorites($type) { global $called_api; - $a = get_app(); + $a = \get_app(); $user_info = api_get_user($a); if (api_user() === false || $user_info === false) { @@ -2296,7 +2335,7 @@ function api_favorites($type) // in friendica starred item are private // return favorites only for self - Logger::log('api_favorites: self:' . $user_info['self']); + Logger::info(API_LOG_PREFIX . 'for {self}', ['module' => 'api', 'action' => 'favorites', 'self' => $user_info['self']]); if ($user_info['self'] == 0) { $ret = []; @@ -2327,6 +2366,8 @@ function api_favorites($type) $ret = api_format_items(Item::inArray($statuses), $user_info, false, $type); } + bindComments($ret); + $data = ['status' => $ret]; switch ($type) { case "atom": @@ -2738,7 +2779,7 @@ function api_contactlink_to_array($txt) */ function api_format_items_activities($item, $type = "json") { - $a = get_app(); + $a = \get_app(); $activities = [ 'like' => [], @@ -2860,11 +2901,11 @@ function api_format_items_profiles($profile_row) */ function api_format_items($r, $user_info, $filter_user = false, $type = "json") { - $a = get_app(); + $a = \get_app(); $ret = []; - foreach ($r as $item) { + foreach ((array)$r as $item) { localize_item($item); list($status_user, $owner_user) = api_item_get_user($a, $item); @@ -3050,7 +3091,7 @@ api_register_func('api/lists/subscriptions', 'api_lists_list', true); */ function api_lists_ownerships($type) { - $a = get_app(); + $a = \get_app(); if (api_user() === false) { throw new ForbiddenException(); @@ -3094,7 +3135,7 @@ api_register_func('api/lists/ownerships', 'api_lists_ownerships', true); */ function api_lists_statuses($type) { - $a = get_app(); + $a = \get_app(); $user_info = api_get_user($a); if (api_user() === false || $user_info === false) { @@ -3171,7 +3212,7 @@ api_register_func('api/lists/statuses', 'api_lists_statuses', true); */ function api_statuses_f($qtype) { - $a = get_app(); + $a = \get_app(); if (api_user() === false) { throw new ForbiddenException(); @@ -3347,7 +3388,7 @@ api_register_func('api/friendships/incoming', 'api_friendships_incoming', true); */ function api_statusnet_config($type) { - $a = get_app(); + $a = \get_app(); $name = Config::get('config', 'sitename'); $server = $a->getHostName(); @@ -3411,7 +3452,7 @@ function api_ff_ids($type) throw new ForbiddenException(); } - $a = get_app(); + $a = \get_app(); api_get_user($a); @@ -3479,7 +3520,7 @@ api_register_func('api/followers/ids', 'api_followers_ids', true); */ function api_direct_messages_new($type) { - $a = get_app(); + $a = \get_app(); if (api_user() === false) { throw new ForbiddenException(); @@ -3567,7 +3608,7 @@ api_register_func('api/direct_messages/new', 'api_direct_messages_new', true, AP */ function api_direct_messages_destroy($type) { - $a = get_app(); + $a = \get_app(); if (api_user() === false) { throw new ForbiddenException(); @@ -3649,6 +3690,7 @@ api_register_func('api/direct_messages/destroy', 'api_direct_messages_destroy', function api_friendships_destroy($type) { $uid = api_user(); + $a = get_app(); if ($uid === false) { throw new ForbiddenException(); @@ -3657,7 +3699,7 @@ function api_friendships_destroy($type) $contact_id = defaults($_REQUEST, 'user_id'); if (empty($contact_id)) { - Logger::log("No user_id specified", Logger::DEBUG); + Logger::notice(API_LOG_PREFIX . 'No user_id specified', ['module' => 'api', 'action' => 'friendships_destroy']); throw new BadRequestException("no user_id specified"); } @@ -3665,7 +3707,7 @@ function api_friendships_destroy($type) $contact = DBA::selectFirst('contact', ['url'], ['id' => $contact_id, 'uid' => 0, 'self' => false]); if(!DBA::isResult($contact)) { - Logger::log("No contact found for ID" . $contact_id, Logger::DEBUG); + Logger::notice(API_LOG_PREFIX . 'No contact found for ID {contact}', ['module' => 'api', 'action' => 'friendships_destroy', 'contact' => $contact_id]); throw new NotFoundException("no contact found to given ID"); } @@ -3677,12 +3719,12 @@ function api_friendships_destroy($type) $contact = DBA::selectFirst('contact', [], $condition); if (!DBA::isResult($contact)) { - Logger::log("Not following Contact", Logger::DEBUG); + Logger::notice(API_LOG_PREFIX . 'Not following contact', ['module' => 'api', 'action' => 'friendships_destroy']); throw new NotFoundException("Not following Contact"); } if (!in_array($contact['network'], Protocol::NATIVE_SUPPORT)) { - Logger::log("Not supported", Logger::DEBUG); + Logger::notice(API_LOG_PREFIX . 'Not supported for {network}', ['module' => 'api', 'action' => 'friendships_destroy', 'network' => $contact['network']]); throw new ExpectationFailedException("Not supported"); } @@ -3693,7 +3735,7 @@ function api_friendships_destroy($type) Contact::terminateFriendship($owner, $contact, $dissolve); } else { - Logger::log("No owner found", Logger::DEBUG); + Logger::notice(API_LOG_PREFIX . 'No owner {uid} found', ['module' => 'api', 'action' => 'friendships_destroy', 'uid' => $uid]); throw new NotFoundException("Error Processing Request"); } @@ -3725,7 +3767,7 @@ api_register_func('api/friendships/destroy', 'api_friendships_destroy', true, AP */ function api_direct_messages_box($type, $box, $verbose) { - $a = get_app(); + $a = \get_app(); if (api_user() === false) { throw new ForbiddenException(); } @@ -3891,10 +3933,10 @@ function api_oauth_request_token() $r = $oauth1->fetch_request_token(OAuthRequest::from_request()); } catch (Exception $e) { echo "error=" . OAuthUtil::urlencode_rfc3986($e->getMessage()); - killme(); + exit(); } echo $r; - killme(); + exit(); } /** @@ -3910,10 +3952,10 @@ function api_oauth_access_token() $r = $oauth1->fetch_access_token(OAuthRequest::from_request()); } catch (Exception $e) { echo "error=". OAuthUtil::urlencode_rfc3986($e->getMessage()); - killme(); + exit(); } echo $r; - killme(); + exit(); } /// @TODO move to top of file or somewhere better @@ -3962,7 +4004,7 @@ function api_fr_photoalbum_delete($type) } // now let's delete all photos from the album - $result = DBA::delete('photo', ['uid' => api_user(), 'album' => $album]); + $result = Photo::delete(['uid' => api_user(), 'album' => $album]); // return success of deletion or error message if ($result) { @@ -3996,11 +4038,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 (!Photo::exists(['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 = Photo::update(['album' => $album_new], ['uid' => api_user(), 'album' => $album]); // return success of updating or error message if ($result) { @@ -4100,14 +4142,8 @@ function api_fr_photo_create_update($type) } else { $mode = "update"; - // check if photo is existing in database - $r = q( - "SELECT `id` FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s' AND `album` = '%s'", - intval(api_user()), - DBA::escape($photo_id), - DBA::escape($album) - ); - if (!DBA::isResult($r)) { + // check if photo is existing in databasei + if (!Photo::exists(['resource-id' => $photo_id, 'uid' => api_user(), 'album' => $album])) { throw new BadRequestException("photo not available"); } } @@ -4136,47 +4172,40 @@ function api_fr_photo_create_update($type) // now let's do the changes in update-mode if ($mode == "update") { - $sql_extra = ""; + $updated_fields = []; if (!is_null($desc)) { - $sql_extra .= (($sql_extra != "") ? " ," : "") . "`desc` = '$desc'"; + $updated_fields['desc'] = $desc; } if (!is_null($album_new)) { - $sql_extra .= (($sql_extra != "") ? " ," : "") . "`album` = '$album_new'"; + $updated_fields['album'] = $album_new; } if (!is_null($allow_cid)) { $allow_cid = trim($allow_cid); - $sql_extra .= (($sql_extra != "") ? " ," : "") . "`allow_cid` = '$allow_cid'"; + $updated_fields['allow_cid'] = $allow_cid; } if (!is_null($deny_cid)) { $deny_cid = trim($deny_cid); - $sql_extra .= (($sql_extra != "") ? " ," : "") . "`deny_cid` = '$deny_cid'"; + $updated_fields['deny_cid'] = $deny_cid; } if (!is_null($allow_gid)) { $allow_gid = trim($allow_gid); - $sql_extra .= (($sql_extra != "") ? " ," : "") . "`allow_gid` = '$allow_gid'"; + $updated_fields['allow_gid'] = $allow_gid; } if (!is_null($deny_gid)) { $deny_gid = trim($deny_gid); - $sql_extra .= (($sql_extra != "") ? " ," : "") . "`deny_gid` = '$deny_gid'"; + $updated_fields['deny_gid'] = $deny_gid; } $result = false; - if ($sql_extra != "") { + if (count($updated_fields) > 0) { $nothingtodo = false; - $result = q( - "UPDATE `photo` SET %s, `edited`='%s' WHERE `uid` = %d AND `resource-id` = '%s' AND `album` = '%s'", - $sql_extra, - DateTimeFormat::utcNow(), // update edited timestamp - intval(api_user()), - DBA::escape($photo_id), - DBA::escape($album) - ); + $result = Photo::update($updated_fields, ['uid' => api_user(), 'resource-id' => $photo_id, 'album' => $album]); } else { $nothingtodo = true; } @@ -4225,16 +4254,12 @@ function api_fr_photo_delete($type) throw new BadRequestException("no photo_id specified"); } // check if photo is existing in database - $r = q( - "SELECT `id` FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s'", - intval(api_user()), - DBA::escape($photo_id) - ); - if (!DBA::isResult($r)) { + $r = Photo::exists(['resource-id' => $photo_id, 'uid' => api_user()]); + if (!$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 = Photo::delete(['uid' => api_user(), 'resource-id' => $photo_id]); // return success of deletion or error message if ($result) { @@ -4344,7 +4369,7 @@ 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); + Photo::update(['profile' => false], $condition); } else { $fields = ['photo' => System::baseUrl() . '/photo/' . $data['photo']['id'] . '-4.' . $filetype, 'thumb' => System::baseUrl() . '/photo/' . $data['photo']['id'] . '-5.' . $filetype]; @@ -4354,7 +4379,7 @@ function api_account_update_profile_image($type) Contact::updateSelfFromUserID(api_user(), true); // Update global directory in background - $url = System::baseUrl() . '/profile/' . get_app()->user['nickname']; + $url = System::baseUrl() . '/profile/' . \get_app()->user['nickname']; if ($url && strlen(Config::get('system', 'directory'))) { Worker::add(PRIORITY_LOW, "Directory", $url); } @@ -4669,7 +4694,7 @@ function post_photo_item($hash, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $f */ function prepare_photo_data($type, $scale, $photo_id) { - $a = get_app(); + $a = \get_app(); $user_info = api_get_user($a); if ($user_info === false) { @@ -4817,7 +4842,7 @@ function api_friendica_remoteauth() 'sec' => $sec, 'expire' => time() + 45]; DBA::insert('profile_check', $fields); - Logger::log($contact['name'] . ' ' . $sec, Logger::DEBUG); + Logger::info(API_LOG_PREFIX . 'for contact {contact}', ['module' => 'api', 'action' => 'friendica_remoteauth', 'contact' => $contact['name'], 'hey' => $sec]); $dest = ($url ? '&destination_url=' . $url : ''); System::externalRedirect( @@ -5066,7 +5091,8 @@ function api_in_reply_to($item) // https://github.com/friendica/friendica/issues/1010 // This is a bugfix for that. if (intval($in_reply_to['status_id']) == intval($item['id'])) { - Logger::log('this message should never appear: id: '.$item['id'].' similar to reply-to: '.$in_reply_to['status_id'], Logger::DEBUG); + $a = get_app(); + Logger::warning(API_LOG_PREFIX . 'ID {id} is similar to reply-to {reply-to}', ['module' => 'api', 'action' => 'in_reply_to', 'id' => $item['id'], 'reply-to' => $in_reply_to['status_id']]); $in_reply_to['status_id'] = null; $in_reply_to['user_id'] = null; $in_reply_to['status_id_str'] = null; @@ -5210,7 +5236,7 @@ function api_best_nickname(&$contacts) */ function api_friendica_group_show($type) { - $a = get_app(); + $a = \get_app(); if (api_user() === false) { throw new ForbiddenException(); @@ -5275,7 +5301,7 @@ api_register_func('api/friendica/group_show', 'api_friendica_group_show', true); */ function api_friendica_group_delete($type) { - $a = get_app(); + $a = \get_app(); if (api_user() === false) { throw new ForbiddenException(); @@ -5337,7 +5363,7 @@ api_register_func('api/friendica/group_delete', 'api_friendica_group_delete', tr */ function api_lists_destroy($type) { - $a = get_app(); + $a = \get_app(); if (api_user() === false) { throw new ForbiddenException(); @@ -5453,7 +5479,7 @@ function group_create($name, $uid, $users = []) */ function api_friendica_group_create($type) { - $a = get_app(); + $a = \get_app(); if (api_user() === false) { throw new ForbiddenException(); @@ -5482,7 +5508,7 @@ api_register_func('api/friendica/group_create', 'api_friendica_group_create', tr */ function api_lists_create($type) { - $a = get_app(); + $a = \get_app(); if (api_user() === false) { throw new ForbiddenException(); @@ -5516,7 +5542,7 @@ api_register_func('api/lists/create', 'api_lists_create', true, API_METHOD_POST) */ function api_friendica_group_update($type) { - $a = get_app(); + $a = \get_app(); if (api_user() === false) { throw new ForbiddenException(); @@ -5590,7 +5616,7 @@ api_register_func('api/friendica/group_update', 'api_friendica_group_update', tr */ function api_lists_update($type) { - $a = get_app(); + $a = \get_app(); if (api_user() === false) { throw new ForbiddenException(); @@ -5636,7 +5662,7 @@ api_register_func('api/lists/update', 'api_lists_update', true, API_METHOD_POST) */ function api_friendica_activity($type) { - $a = get_app(); + $a = \get_app(); if (api_user() === false) { throw new ForbiddenException(); @@ -5680,7 +5706,7 @@ api_register_func('api/friendica/activity/unattendmaybe', 'api_friendica_activit */ function api_friendica_notification($type) { - $a = get_app(); + $a = \get_app(); if (api_user() === false) { throw new ForbiddenException(); @@ -5702,7 +5728,6 @@ function api_friendica_notification($type) $notes = $xmlnotes; } - return api_format_data("notes", $type, ['note' => $notes]); } @@ -5716,7 +5741,7 @@ function api_friendica_notification($type) */ function api_friendica_notification_seen($type) { - $a = get_app(); + $a = \get_app(); $user_info = api_get_user($a); if (api_user() === false || $user_info === false) { @@ -5761,7 +5786,7 @@ api_register_func('api/friendica/notification', 'api_friendica_notification', tr */ function api_friendica_direct_messages_setseen($type) { - $a = get_app(); + $a = \get_app(); if (api_user() === false) { throw new ForbiddenException(); } @@ -5810,7 +5835,7 @@ api_register_func('api/friendica/direct_messages_setseen', 'api_friendica_direct */ function api_friendica_direct_messages_search($type, $box = "") { - $a = get_app(); + $a = \get_app(); if (api_user() === false) { throw new ForbiddenException(); @@ -5873,7 +5898,7 @@ api_register_func('api/friendica/direct_messages_search', 'api_friendica_direct_ */ function api_friendica_profile_show($type) { - $a = get_app(); + $a = \get_app(); if (api_user() === false) { throw new ForbiddenException(); @@ -5976,6 +6001,42 @@ function api_saved_searches_list($type) /// @TODO move to top of file or somewhere better api_register_func('api/saved_searches/list', 'api_saved_searches_list', true); +/* + * Bind comment numbers(friendica_comments: Int) on each statuses page of *_timeline / favorites / search + * + * @brief Number of comments + * + * @param object $data [Status, Status] + * + * @return void + */ +function bindComments(&$data) +{ + if (count($data) == 0) { + return; + } + + $ids = []; + $comments = []; + foreach ($data as $item) { + $ids[] = $item['id']; + } + + $idStr = DBA::escape(implode(', ', $ids)); + $sql = "SELECT `parent`, COUNT(*) as comments FROM `item` WHERE `parent` IN ($idStr) AND `deleted` = ? AND `gravity`= ? GROUP BY `parent`"; + $items = DBA::p($sql, 0, GRAVITY_COMMENT); + $itemsData = DBA::toArray($items); + + foreach ($itemsData as $item) { + $comments[$item['parent']] = $item['comments']; + } + + foreach ($data as $idx => $item) { + $id = $item['id']; + $data[$idx]['friendica_comments'] = isset($comments[$id]) ? $comments[$id] : 0; + } +} + /* @TODO Maybe open to implement? To.Do: