From 319f91301d72540cba3a75360c5ccfe8bc13578d Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 12 Nov 2021 19:52:01 +0100 Subject: [PATCH 01/22] Move API Response methods into an own class to make them mockable --- include/api.php | 114 +++++----- src/Module/Api/ApiResponse.php | 215 ++++++++++++++++++ src/Module/Api/Friendica/Activity.php | 5 +- .../Api/Friendica/DirectMessages/Setseen.php | 7 +- src/Module/Api/Friendica/Events/Index.php | 3 +- src/Module/Api/Friendica/Notification.php | 3 +- src/Module/Api/Friendica/Photo/Delete.php | 3 +- .../Api/Friendica/Photoalbum/Delete.php | 3 +- .../Api/Friendica/Photoalbum/Update.php | 3 +- src/Module/Api/Friendica/Profile/Show.php | 3 +- .../Api/GNUSocial/GNUSocial/Version.php | 3 +- src/Module/Api/GNUSocial/Help/Test.php | 3 +- .../Mastodon/Accounts/UpdateCredentials.php | 3 +- src/Module/Api/Mastodon/Filters.php | 3 +- src/Module/Api/Mastodon/Lists/Accounts.php | 5 +- src/Module/Api/Mastodon/Markers.php | 3 +- src/Module/Api/Mastodon/ScheduledStatuses.php | 3 +- src/Module/Api/Mastodon/Unimplemented.php | 11 +- .../Api/Twitter/Account/RateLimitStatus.php | 3 +- src/Module/Api/Twitter/SavedSearches.php | 3 +- src/Module/BaseApi.php | 172 -------------- tests/legacy/ApiTest.php | 15 +- 22 files changed, 327 insertions(+), 259 deletions(-) create mode 100644 src/Module/Api/ApiResponse.php diff --git a/include/api.php b/include/api.php index cf633374f7..118db50bce 100644 --- a/include/api.php +++ b/include/api.php @@ -42,6 +42,7 @@ use Friendica\Model\Post; use Friendica\Model\Profile; use Friendica\Model\User; use Friendica\Model\Verb; +use Friendica\Module\Api\ApiResponse; use Friendica\Module\BaseApi; use Friendica\Network\HTTPException; use Friendica\Network\HTTPException\BadRequestException; @@ -282,7 +283,7 @@ function api_call(App $a, App\Arguments $args = null) Logger::warning(API_LOG_PREFIX . 'not implemented', ['module' => 'api', 'action' => 'call', 'query' => DI::args()->getQueryString()]); throw new NotFoundException(); } catch (HTTPException $e) { - BaseApi::error($e->getCode(), $e->getDescription(), $e->getMessage(), $type); + ApiResponse::error($e->getCode(), $e->getDescription(), $e->getMessage(), $type); } } @@ -420,7 +421,7 @@ function api_get_user($contact_id = null) if (!empty(DI::args()->getArgv()[$argid])) { $data = explode(".", DI::args()->getArgv()[$argid]); if (count($data) > 1) { - list($user, $null) = $data; + [$user, $null] = $data; } } if (is_numeric($user)) { @@ -706,7 +707,7 @@ function api_account_verify_credentials($type) unset($user_info["uid"]); unset($user_info["self"]); - return BaseApi::formatData("user", $type, ['user' => $user_info]); + return ApiResponse::formatData("user", $type, ['user' => $user_info]); } /// @TODO move to top of file or somewhere better @@ -1095,7 +1096,7 @@ function api_status_show($type, $item_id) Logger::info(API_LOG_PREFIX . 'End', ['action' => 'get_status', 'status_info' => $status_info]); - return BaseApi::formatData('statuses', $type, ['status' => $status_info]); + return ApiResponse::formatData('statuses', $type, ['status' => $status_info]); } /** @@ -1161,7 +1162,7 @@ function api_users_show($type) unset($user_info['uid']); unset($user_info['self']); - return BaseApi::formatData('user', $type, ['user' => $user_info]); + return ApiResponse::formatData('user', $type, ['user' => $user_info]); } /// @TODO move to top of file or somewhere better @@ -1217,7 +1218,7 @@ function api_users_search($type) throw new BadRequestException('No search term specified.'); } - return BaseApi::formatData('users', $type, $userlist); + return ApiResponse::formatData('users', $type, $userlist); } /// @TODO move to top of file or somewhere better @@ -1253,7 +1254,7 @@ function api_users_lookup($type) throw new NotFoundException; } - return BaseApi::formatData("users", $type, ['users' => $users]); + return ApiResponse::formatData("users", $type, ['users' => $users]); } /// @TODO move to top of file or somewhere better @@ -1316,7 +1317,7 @@ function api_search($type) DBA::close($tags); if (empty($uriids)) { - return BaseApi::formatData('statuses', $type, $data); + return ApiResponse::formatData('statuses', $type, $data); } $condition = ['uri-id' => $uriids]; @@ -1357,7 +1358,7 @@ function api_search($type) bindComments($data['status']); - return BaseApi::formatData('statuses', $type, $data); + return ApiResponse::formatData('statuses', $type, $data); } /// @TODO move to top of file or somewhere better @@ -1454,7 +1455,7 @@ function api_statuses_home_timeline($type) break; } - return BaseApi::formatData("statuses", $type, $data); + return ApiResponse::formatData("statuses", $type, $data); } @@ -1540,7 +1541,7 @@ function api_statuses_public_timeline($type) break; } - return BaseApi::formatData("statuses", $type, $data); + return ApiResponse::formatData("statuses", $type, $data); } /// @TODO move to top of file or somewhere better @@ -1599,7 +1600,7 @@ function api_statuses_networkpublic_timeline($type) break; } - return BaseApi::formatData("statuses", $type, $data); + return ApiResponse::formatData("statuses", $type, $data); } /// @TODO move to top of file or somewhere better @@ -1675,10 +1676,10 @@ function api_statuses_show($type) if ($conversation) { $data = ['status' => $ret]; - return BaseApi::formatData("statuses", $type, $data); + return ApiResponse::formatData("statuses", $type, $data); } else { $data = ['status' => $ret[0]]; - return BaseApi::formatData("status", $type, $data); + return ApiResponse::formatData("status", $type, $data); } } @@ -1757,7 +1758,7 @@ function api_conversation_show($type) $ret = api_format_items(Post::toArray($statuses), $user_info, false, $type); $data = ['status' => $ret]; - return BaseApi::formatData("statuses", $type, $data); + return ApiResponse::formatData("statuses", $type, $data); } /// @TODO move to top of file or somewhere better @@ -1968,7 +1969,7 @@ function api_statuses_mentions($type) break; } - return BaseApi::formatData("statuses", $type, $data); + return ApiResponse::formatData("statuses", $type, $data); } /// @TODO move to top of file or somewhere better @@ -2046,7 +2047,7 @@ function api_statuses_user_timeline($type) break; } - return BaseApi::formatData("statuses", $type, $data); + return ApiResponse::formatData("statuses", $type, $data); } /// @TODO move to top of file or somewhere better @@ -2128,7 +2129,7 @@ function api_favorites_create_destroy($type) break; } - return BaseApi::formatData("status", $type, $data); + return ApiResponse::formatData("status", $type, $data); } /// @TODO move to top of file or somewhere better @@ -2201,7 +2202,7 @@ function api_favorites($type) break; } - return BaseApi::formatData("statuses", $type, $data); + return ApiResponse::formatData("statuses", $type, $data); } /// @TODO move to top of file or somewhere better @@ -2710,7 +2711,7 @@ function api_format_items($items, $user_info, $filter_user = false, $type = "jso } foreach ((array)$items as $item) { - list($status_user, $author_user, $owner_user) = api_item_get_user($a, $item); + [$status_user, $author_user, $owner_user] = api_item_get_user($a, $item); // Look if the posts are matching if they should be filtered by user id if ($filter_user && ($status_user["id"] != $user_info["id"])) { @@ -2742,7 +2743,7 @@ function api_format_item($item, $type = "json", $status_user = null, $author_use $a = Friendica\DI::app(); if (empty($status_user) || empty($author_user) || empty($owner_user)) { - list($status_user, $author_user, $owner_user) = api_item_get_user($a, $item); + [$status_user, $author_user, $owner_user] = api_item_get_user($a, $item); } DI::contentItem()->localize($item); @@ -2907,7 +2908,7 @@ function api_lists_list($type) { $ret = []; /// @TODO $ret is not filled here? - return BaseApi::formatData('lists', $type, ["lists_list" => $ret]); + return ApiResponse::formatData('lists', $type, ["lists_list" => $ret]); } /// @TODO move to top of file or somewhere better @@ -2957,7 +2958,7 @@ function api_lists_ownerships($type) 'mode' => $mode ]; } - return BaseApi::formatData("lists", $type, ['lists' => ['lists' => $lists]]); + return ApiResponse::formatData("lists", $type, ['lists' => ['lists' => $lists]]); } /// @TODO move to top of file or somewhere better @@ -3037,7 +3038,7 @@ function api_lists_statuses($type) break; } - return BaseApi::formatData("statuses", $type, $data); + return ApiResponse::formatData("statuses", $type, $data); } /// @TODO move to top of file or somewhere better @@ -3151,7 +3152,7 @@ function api_statuses_friends($type) if ($data === false) { return false; } - return BaseApi::formatData("users", $type, $data); + return ApiResponse::formatData("users", $type, $data); } /** @@ -3170,7 +3171,7 @@ function api_statuses_followers($type) if ($data === false) { return false; } - return BaseApi::formatData("users", $type, $data); + return ApiResponse::formatData("users", $type, $data); } /// @TODO move to top of file or somewhere better @@ -3194,7 +3195,7 @@ function api_blocks_list($type) if ($data === false) { return false; } - return BaseApi::formatData("users", $type, $data); + return ApiResponse::formatData("users", $type, $data); } /// @TODO move to top of file or somewhere better @@ -3223,7 +3224,7 @@ function api_friendships_incoming($type) $ids[] = $user['id']; } - return BaseApi::formatData("ids", $type, ['id' => $ids]); + return ApiResponse::formatData("ids", $type, ['id' => $ids]); } /// @TODO move to top of file or somewhere better @@ -3264,7 +3265,7 @@ function api_statusnet_config($type) ], ]; - return BaseApi::formatData('config', $type, ['config' => $config]); + return ApiResponse::formatData('config', $type, ['config' => $config]); } /// @TODO move to top of file or somewhere better @@ -3348,7 +3349,7 @@ function api_direct_messages_new($type) break; } - return BaseApi::formatData("direct-messages", $type, $data); + return ApiResponse::formatData("direct-messages", $type, $data); } /// @TODO move to top of file or somewhere better @@ -3387,7 +3388,7 @@ function api_direct_messages_destroy($type) // error if no id or parenturi specified (for clients posting parent-uri as well) if ($verbose == "true" && ($id == 0 || $parenturi == "")) { $answer = ['result' => 'error', 'message' => 'message id or parenturi not specified']; - return BaseApi::formatData("direct_messages_delete", $type, ['$result' => $answer]); + return ApiResponse::formatData("direct_messages_delete", $type, ['$result' => $answer]); } // BadRequestException if no id specified (for clients using Twitter API) @@ -3402,7 +3403,7 @@ function api_direct_messages_destroy($type) if (!DBA::exists('mail', ["`uid` = ? AND `id` = ? " . $sql_extra, $uid, $id])) { if ($verbose == "true") { $answer = ['result' => 'error', 'message' => 'message id not in database']; - return BaseApi::formatData("direct_messages_delete", $type, ['$result' => $answer]); + return ApiResponse::formatData("direct_messages_delete", $type, ['$result' => $answer]); } /// @todo BadRequestException ok for Twitter API clients? throw new BadRequestException('message id not in database'); @@ -3415,10 +3416,10 @@ function api_direct_messages_destroy($type) if ($result) { // return success $answer = ['result' => 'ok', 'message' => 'message deleted']; - return BaseApi::formatData("direct_message_delete", $type, ['$result' => $answer]); + return ApiResponse::formatData("direct_message_delete", $type, ['$result' => $answer]); } else { $answer = ['result' => 'error', 'message' => 'unknown error']; - return BaseApi::formatData("direct_messages_delete", $type, ['$result' => $answer]); + return ApiResponse::formatData("direct_messages_delete", $type, ['$result' => $answer]); } } /// @todo return JSON data like Twitter API not yet implemented @@ -3503,8 +3504,9 @@ function api_friendships_destroy($type) // Set screen_name since Twidere requests it $contact['screen_name'] = $contact['nick']; - return BaseApi::formatData('friendships-destroy', $type, ['user' => $contact]); + return ApiResponse::formatData('friendships-destroy', $type, ['user' => $contact]); } + api_register_func('api/friendships/destroy', 'api_friendships_destroy', true, API_METHOD_POST); /** @@ -3584,7 +3586,7 @@ function api_direct_messages_box($type, $box, $verbose) )); if ($verbose == "true" && !DBA::isResult($r)) { $answer = ['result' => 'error', 'message' => 'no mails available']; - return BaseApi::formatData("direct_messages_all", $type, ['$result' => $answer]); + return ApiResponse::formatData("direct_messages_all", $type, ['$result' => $answer]); } $ret = []; @@ -3612,7 +3614,7 @@ function api_direct_messages_box($type, $box, $verbose) break; } - return BaseApi::formatData("direct-messages", $type, $data); + return ApiResponse::formatData("direct-messages", $type, $data); } /** @@ -3726,7 +3728,7 @@ function api_fr_photos_list($type) } } } - return BaseApi::formatData("photos", $type, $data); + return ApiResponse::formatData("photos", $type, $data); } /** @@ -3798,7 +3800,7 @@ function api_fr_photo_create_update($type) // return success of updating or error message if (!is_null($data)) { - return BaseApi::formatData("photo_create", $type, $data); + return ApiResponse::formatData("photo_create", $type, $data); } else { throw new InternalServerErrorException("unknown error - uploading photo failed, see Friendica log for more information"); } @@ -3849,18 +3851,18 @@ function api_fr_photo_create_update($type) $media = $_FILES['media']; $data = save_media_to_database("photo", $media, $type, $album, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $desc, Photo::DEFAULT, $visibility, $photo_id); if (!is_null($data)) { - return BaseApi::formatData("photo_update", $type, $data); + return ApiResponse::formatData("photo_update", $type, $data); } } // return success of updating or error message if ($result) { $answer = ['result' => 'updated', 'message' => 'Image id `' . $photo_id . '` has been updated.']; - return BaseApi::formatData("photo_update", $type, ['$result' => $answer]); + return ApiResponse::formatData("photo_update", $type, ['$result' => $answer]); } else { if ($nothingtodo) { $answer = ['result' => 'cancelled', 'message' => 'Nothing to update for image id `' . $photo_id . '`.']; - return BaseApi::formatData("photo_update", $type, ['$result' => $answer]); + return ApiResponse::formatData("photo_update", $type, ['$result' => $answer]); } throw new InternalServerErrorException("unknown error - update photo entry in database failed"); } @@ -3893,7 +3895,7 @@ function api_fr_photo_detail($type) // prepare json/xml output with data from database for the requested photo $data = prepare_photo_data($type, $scale, $photo_id); - return BaseApi::formatData("photo_detail", $type, $data); + return ApiResponse::formatData("photo_detail", $type, $data); } @@ -4624,8 +4626,9 @@ function api_friendica_group_show($type) } $grps[] = ['name' => $rr['name'], 'gid' => $rr['id'], $user_element => $users]; } - return BaseApi::formatData("groups", $type, ['group' => $grps]); + return ApiResponse::formatData("groups", $type, ['group' => $grps]); } + api_register_func('api/friendica/group_show', 'api_friendica_group_show', true); @@ -4681,7 +4684,7 @@ function api_friendica_group_delete($type) if ($ret) { // return success $success = ['success' => $ret, 'gid' => $gid, 'name' => $name, 'status' => 'deleted', 'wrong users' => []]; - return BaseApi::formatData("group_delete", $type, ['result' => $success]); + return ApiResponse::formatData("group_delete", $type, ['result' => $success]); } else { throw new BadRequestException('other API error'); } @@ -4734,9 +4737,10 @@ function api_lists_destroy($type) 'user' => $user_info ]; - return BaseApi::formatData("lists", $type, ['lists' => $list]); + return ApiResponse::formatData("lists", $type, ['lists' => $list]); } } + api_register_func('api/lists/destroy', 'api_lists_destroy', true, API_METHOD_DELETE); /** @@ -4822,8 +4826,9 @@ function api_friendica_group_create($type) $success = group_create($name, $uid, $users); - return BaseApi::formatData("group_create", $type, ['result' => $success]); + return ApiResponse::formatData("group_create", $type, ['result' => $success]); } + api_register_func('api/friendica/group_create', 'api_friendica_group_create', true, API_METHOD_POST); /** @@ -4861,9 +4866,10 @@ function api_lists_create($type) 'user' => $user_info ]; - return BaseApi::formatData("lists", $type, ['lists'=>$grp]); + return ApiResponse::formatData("lists", $type, ['lists' => $grp]); } } + api_register_func('api/lists/create', 'api_lists_create', true, API_METHOD_POST); /** @@ -4934,7 +4940,7 @@ function api_friendica_group_update($type) // return success message incl. missing users in array $status = ($erroraddinguser ? "missing user" : "ok"); $success = ['success' => true, 'gid' => $gid, 'name' => $name, 'status' => $status, 'wrong users' => $errorusers]; - return BaseApi::formatData("group_update", $type, ['result' => $success]); + return ApiResponse::formatData("group_update", $type, ['result' => $success]); } api_register_func('api/friendica/group_update', 'api_friendica_group_update', true, API_METHOD_POST); @@ -4986,7 +4992,7 @@ function api_lists_update($type) 'user' => $user_info ]; - return BaseApi::formatData("lists", $type, ['lists' => $list]); + return ApiResponse::formatData("lists", $type, ['lists' => $list]); } } @@ -5038,12 +5044,12 @@ function api_friendica_notification_seen($type) // we found the item, return it to the user $ret = api_format_items([$item], $user_info, false, $type); $data = ['status' => $ret]; - return BaseApi::formatData('status', $type, $data); + return ApiResponse::formatData('status', $type, $data); } // the item can't be found, but we set the notification as seen, so we count this as a success } - return BaseApi::formatData('result', $type, ['result' => 'success']); + return ApiResponse::formatData('result', $type, ['result' => 'success']); } catch (NotFoundException $e) { throw new BadRequestException('Invalid argument', $e); } catch (Exception $e) { @@ -5084,7 +5090,7 @@ function api_friendica_direct_messages_search($type, $box = "") // error if no searchstring specified if ($searchstring == "") { $answer = ['result' => 'error', 'message' => 'searchstring not specified']; - return BaseApi::formatData("direct_messages_search", $type, ['$result' => $answer]); + return ApiResponse::formatData("direct_messages_search", $type, ['$result' => $answer]); } // get data for the specified searchstring @@ -5119,7 +5125,7 @@ function api_friendica_direct_messages_search($type, $box = "") $success = ['success' => true, 'search_results' => $ret]; } - return BaseApi::formatData("direct_message_search", $type, ['$result' => $success]); + return ApiResponse::formatData("direct_message_search", $type, ['$result' => $success]); } /// @TODO move to top of file or somewhere better diff --git a/src/Module/Api/ApiResponse.php b/src/Module/Api/ApiResponse.php new file mode 100644 index 0000000000..768dacb5fb --- /dev/null +++ b/src/Module/Api/ApiResponse.php @@ -0,0 +1,215 @@ +l10n = $l10n; + $this->args = $args; + } + + /** + * Creates the XML from a JSON style array + * + * @param array $data JSON style array + * @param string $root_element Name of the root element + * + * @return string The XML data + */ + public static function createXML(array $data, string $root_element): string + { + $childname = key($data); + $data2 = array_pop($data); + + $namespaces = ['' => 'http://api.twitter.com', + 'statusnet' => 'http://status.net/schema/api/1/', + 'friendica' => 'http://friendi.ca/schema/api/1/', + 'georss' => 'http://www.georss.org/georss']; + + /// @todo Auto detection of needed namespaces + if (in_array($root_element, ['ok', 'hash', 'config', 'version', 'ids', 'notes', 'photos'])) { + $namespaces = []; + } + + if (is_array($data2)) { + $key = key($data2); + Arrays::walkRecursive($data2, ['Friendica\Module\Api\ApiResponse', 'reformatXML']); + + if ($key == '0') { + $data4 = []; + $i = 1; + + foreach ($data2 as $item) { + $data4[$i++ . ':' . $childname] = $item; + } + + $data2 = $data4; + } + } + + $data3 = [$root_element => $data2]; + + return XML::fromArray($data3, $xml, false, $namespaces); + } + + /** + * Formats the data according to the data type + * + * @param string $root_element Name of the root element + * @param string $type Return type (atom, rss, xml, json) + * @param array $data JSON style array + * + * @return array|string (string|array) XML data or JSON data + */ + public static function formatData(string $root_element, string $type, array $data) + { + switch ($type) { + case 'atom': + case 'rss': + case 'xml': + $ret = static::createXML($data, $root_element); + break; + case 'json': + default: + $ret = $data; + break; + } + return $ret; + } + + /** + * Callback function to transform the array in an array that can be transformed in a XML file + * + * @param mixed $item Array item value + * @param string $key Array key + * + * @return boolean + */ + public static function reformatXML(&$item, string &$key): bool + { + if (is_bool($item)) { + $item = ($item ? 'true' : 'false'); + } + + if (substr($key, 0, 10) == 'statusnet_') { + $key = 'statusnet:' . substr($key, 10); + } elseif (substr($key, 0, 10) == 'friendica_') { + $key = 'friendica:' . substr($key, 10); + } + return true; + } + + /** + * Exit with error code + * + * @param int $code + * @param string $description + * @param string $message + * @param string|null $format + * + * @return void + */ + public static function error(int $code, string $description, string $message, string $format = null) + { + $error = [ + 'error' => $message ?: $description, + 'code' => $code . ' ' . $description, + 'request' => DI::args()->getQueryString() + ]; + + header(($_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.1') . ' ' . $code . ' ' . $description); + + self::exit('status', ['status' => $error], $format); + } + + /** + * Outputs formatted data according to the data type and then exits the execution. + * + * @param string $root_element + * @param array $data An array with a single element containing the returned result + * @param string|null $format Output format (xml, json, rss, atom) + * + * @return void + */ + public static function exit(string $root_element, array $data, string $format = null) + { + $format = $format ?? 'json'; + + $return = static::formatData($root_element, $format, $data); + + switch ($format) { + case 'xml': + header('Content-Type: text/xml'); + break; + case 'json': + header('Content-Type: application/json'); + if (!empty($return)) { + $json = json_encode(end($return)); + if (!empty($_GET['callback'])) { + $json = $_GET['callback'] . '(' . $json . ')'; + } + $return = $json; + } + break; + case 'rss': + header('Content-Type: application/rss+xml'); + $return = '' . "\n" . $return; + break; + case 'atom': + header('Content-Type: application/atom+xml'); + $return = '' . "\n" . $return; + break; + } + + echo $return; + exit; + } + + /** + * Quit execution with the message that the endpoint isn't implemented + * + * @param string $method + * + * @return void + * @throws \Exception + */ + public static function unsupported(string $method = 'all') + { + $path = DI::args()->getQueryString(); + Logger::info('Unimplemented API call', + [ + 'method' => $method, + 'path' => $path, + 'agent' => $_SERVER['HTTP_USER_AGENT'] ?? '', + 'request' => HTTPInputData::process() + ]); + $error = DI::l10n()->t('API endpoint %s %s is not implemented', strtoupper($method), $path); + $error_description = DI::l10n()->t('The API endpoint is currently not implemented but might be in the future.'); + $errorobj = new Error($error, $error_description); + System::jsonError(501, $errorobj->toArray()); + } +} diff --git a/src/Module/Api/Friendica/Activity.php b/src/Module/Api/Friendica/Activity.php index e88f6a7c9d..41500dfe01 100644 --- a/src/Module/Api/Friendica/Activity.php +++ b/src/Module/Api/Friendica/Activity.php @@ -22,6 +22,7 @@ namespace Friendica\Module\Api\Friendica; use Friendica\Model\Item; +use Friendica\Module\Api\ApiResponse; use Friendica\Module\BaseApi; /** @@ -56,9 +57,9 @@ class Activity extends BaseApi } else { $ok = 'ok'; } - self::exit('ok', ['ok' => $ok], $parameters['extension'] ?? null); + ApiResponse::exit('ok', ['ok' => $ok], $parameters['extension'] ?? null); } else { - self::error(500, 'Error adding activity', '', $parameters['extension'] ?? null); + ApiResponse::error(500, 'Error adding activity', '', $parameters['extension'] ?? null); } } } diff --git a/src/Module/Api/Friendica/DirectMessages/Setseen.php b/src/Module/Api/Friendica/DirectMessages/Setseen.php index 334f4e295f..a7eab43e22 100644 --- a/src/Module/Api/Friendica/DirectMessages/Setseen.php +++ b/src/Module/Api/Friendica/DirectMessages/Setseen.php @@ -22,6 +22,7 @@ namespace Friendica\Module\Api\Friendica\DirectMessages; use Friendica\Database\DBA; +use Friendica\Module\Api\ApiResponse; use Friendica\Module\BaseApi; /** @@ -41,13 +42,13 @@ class Setseen extends BaseApi // return error if id is zero if (empty($request['id'])) { $answer = ['result' => 'error', 'message' => 'message id not specified']; - self::exit('direct_messages_setseen', ['$result' => $answer], $parameters['extension'] ?? null); + ApiResponse::exit('direct_messages_setseen', ['$result' => $answer], $parameters['extension'] ?? null); } // error message if specified id is not in database if (!DBA::exists('mail', ['id' => $request['id'], 'uid' => $uid])) { $answer = ['result' => 'error', 'message' => 'message id not in database']; - self::exit('direct_messages_setseen', ['$result' => $answer], $parameters['extension'] ?? null); + ApiResponse::exit('direct_messages_setseen', ['$result' => $answer], $parameters['extension'] ?? null); } // update seen indicator @@ -57,6 +58,6 @@ class Setseen extends BaseApi $answer = ['result' => 'error', 'message' => 'unknown error']; } - self::exit('direct_messages_setseen', ['$result' => $answer], $parameters['extension'] ?? null); + ApiResponse::exit('direct_messages_setseen', ['$result' => $answer], $parameters['extension'] ?? null); } } diff --git a/src/Module/Api/Friendica/Events/Index.php b/src/Module/Api/Friendica/Events/Index.php index b0ca78ac9e..7bfeaa2ef7 100644 --- a/src/Module/Api/Friendica/Events/Index.php +++ b/src/Module/Api/Friendica/Events/Index.php @@ -23,6 +23,7 @@ namespace Friendica\Module\Api\Friendica\Events; use Friendica\Content\Text\BBCode; use Friendica\Database\DBA; +use Friendica\Module\Api\ApiResponse; use Friendica\Module\BaseApi; use Friendica\Network\HTTPException; @@ -70,6 +71,6 @@ class Index extends BaseApi ]; } - self::exit('events', ['events' => $items], $parameters['extension'] ?? null); + ApiResponse::exit('events', ['events' => $items], $parameters['extension'] ?? null); } } diff --git a/src/Module/Api/Friendica/Notification.php b/src/Module/Api/Friendica/Notification.php index e3872040f2..fb028dd752 100644 --- a/src/Module/Api/Friendica/Notification.php +++ b/src/Module/Api/Friendica/Notification.php @@ -23,6 +23,7 @@ namespace Friendica\Module\Api\Friendica; use Friendica\Collection\Api\Notifications as ApiNotifications; use Friendica\DI; +use Friendica\Module\Api\ApiResponse; use Friendica\Module\BaseApi; use Friendica\Object\Api\Friendica\Notification as ApiNotification; @@ -56,6 +57,6 @@ class Notification extends BaseApi $result = false; } - self::exit('notes', ['note' => $result], $parameters['extension'] ?? null); + ApiResponse::exit('notes', ['note' => $result], $parameters['extension'] ?? null); } } diff --git a/src/Module/Api/Friendica/Photo/Delete.php b/src/Module/Api/Friendica/Photo/Delete.php index 702c11ee8f..1e6b86ca85 100644 --- a/src/Module/Api/Friendica/Photo/Delete.php +++ b/src/Module/Api/Friendica/Photo/Delete.php @@ -23,6 +23,7 @@ namespace Friendica\Module\Api\Friendica\Photo; use Friendica\Model\Item; use Friendica\Model\Photo; +use Friendica\Module\Api\ApiResponse; use Friendica\Module\BaseApi; use Friendica\Network\HTTPException\BadRequestException; use Friendica\Network\HTTPException\InternalServerErrorException; @@ -63,7 +64,7 @@ class Delete extends BaseApi Item::deleteForUser($condition, $uid); $result = ['result' => 'deleted', 'message' => 'photo with id `' . $request['photo_id'] . '` has been deleted from server.']; - self::exit('photo_delete', ['$result' => $result], $parameters['extension'] ?? null); + ApiResponse::exit('photo_delete', ['$result' => $result], $parameters['extension'] ?? null); } else { throw new InternalServerErrorException("unknown error on deleting photo from database table"); } diff --git a/src/Module/Api/Friendica/Photoalbum/Delete.php b/src/Module/Api/Friendica/Photoalbum/Delete.php index 0cb2158eb0..3ee3e2dc39 100644 --- a/src/Module/Api/Friendica/Photoalbum/Delete.php +++ b/src/Module/Api/Friendica/Photoalbum/Delete.php @@ -24,6 +24,7 @@ namespace Friendica\Module\Api\Friendica\Photoalbum; use Friendica\Database\DBA; use Friendica\Model\Item; use Friendica\Model\Photo; +use Friendica\Module\Api\ApiResponse; use Friendica\Module\BaseApi; use Friendica\Network\HTTPException\BadRequestException; use Friendica\Network\HTTPException\InternalServerErrorException; @@ -66,7 +67,7 @@ class Delete extends BaseApi // return success of deletion or error message if ($result) { $answer = ['result' => 'deleted', 'message' => 'album `' . $request['album'] . '` with all containing photos has been deleted.']; - self::exit('photoalbum_delete', ['$result' => $answer], $parameters['extension'] ?? null); + ApiResponse::exit('photoalbum_delete', ['$result' => $answer], $parameters['extension'] ?? null); } else { throw new InternalServerErrorException("unknown error - deleting from database failed"); } diff --git a/src/Module/Api/Friendica/Photoalbum/Update.php b/src/Module/Api/Friendica/Photoalbum/Update.php index d6c4725e45..75ea48a82d 100644 --- a/src/Module/Api/Friendica/Photoalbum/Update.php +++ b/src/Module/Api/Friendica/Photoalbum/Update.php @@ -22,6 +22,7 @@ namespace Friendica\Module\Api\Friendica\Photoalbum; use Friendica\Model\Photo; +use Friendica\Module\Api\ApiResponse; use Friendica\Module\BaseApi; use Friendica\Network\HTTPException\BadRequestException; use Friendica\Network\HTTPException\InternalServerErrorException; @@ -58,7 +59,7 @@ class Update extends BaseApi // return success of updating or error message if ($result) { $answer = ['result' => 'updated', 'message' => 'album `' . $request['album'] . '` with all containing photos has been renamed to `' . $request['album_new'] . '`.']; - self::exit('photoalbum_update', ['$result' => $answer], $parameters['extension'] ?? null); + ApiResponse::exit('photoalbum_update', ['$result' => $answer], $parameters['extension'] ?? null); } else { throw new InternalServerErrorException("unknown error - updating in database failed"); } diff --git a/src/Module/Api/Friendica/Profile/Show.php b/src/Module/Api/Friendica/Profile/Show.php index 18671e0dd5..bb3197ad21 100644 --- a/src/Module/Api/Friendica/Profile/Show.php +++ b/src/Module/Api/Friendica/Profile/Show.php @@ -21,6 +21,7 @@ namespace Friendica\Module\Api\Friendica\Profile; +use Friendica\Module\Api\ApiResponse; use Friendica\Profile\ProfileField\Collection\ProfileFields; use Friendica\Content\Text\BBCode; use Friendica\DI; @@ -66,7 +67,7 @@ class Show extends BaseApi 'profiles' => $profiles ]; - self::exit('friendica_profiles', ['$result' => $result], $parameters['extension'] ?? null); + ApiResponse::exit('friendica_profiles', ['$result' => $result], $parameters['extension'] ?? null); } /** diff --git a/src/Module/Api/GNUSocial/GNUSocial/Version.php b/src/Module/Api/GNUSocial/GNUSocial/Version.php index 818e9a1c05..4b9d745030 100644 --- a/src/Module/Api/GNUSocial/GNUSocial/Version.php +++ b/src/Module/Api/GNUSocial/GNUSocial/Version.php @@ -21,6 +21,7 @@ namespace Friendica\Module\Api\GNUSocial\GNUSocial; +use Friendica\Module\Api\ApiResponse; use Friendica\Module\BaseApi; /** @@ -30,6 +31,6 @@ class Version extends BaseApi { public static function rawContent(array $parameters = []) { - self::exit('version', ['version' => '0.9.7'], $parameters['extension'] ?? null); + ApiResponse::exit('version', ['version' => '0.9.7'], $parameters['extension'] ?? null); } } diff --git a/src/Module/Api/GNUSocial/Help/Test.php b/src/Module/Api/GNUSocial/Help/Test.php index 361610a8b5..bfd7559a45 100644 --- a/src/Module/Api/GNUSocial/Help/Test.php +++ b/src/Module/Api/GNUSocial/Help/Test.php @@ -21,6 +21,7 @@ namespace Friendica\Module\Api\GNUSocial\Help; +use Friendica\Module\Api\ApiResponse; use Friendica\Module\BaseApi; /** @@ -36,6 +37,6 @@ class Test extends BaseApi $ok = 'ok'; } - self::exit('ok', ['ok' => $ok], $parameters['extension'] ?? null); + ApiResponse::exit('ok', ['ok' => $ok], $parameters['extension'] ?? null); } } diff --git a/src/Module/Api/Mastodon/Accounts/UpdateCredentials.php b/src/Module/Api/Mastodon/Accounts/UpdateCredentials.php index 5051aec4ec..ccd2e903c0 100644 --- a/src/Module/Api/Mastodon/Accounts/UpdateCredentials.php +++ b/src/Module/Api/Mastodon/Accounts/UpdateCredentials.php @@ -23,6 +23,7 @@ namespace Friendica\Module\Api\Mastodon\Accounts; use Friendica\App\Router; use Friendica\Core\Logger; +use Friendica\Module\Api\ApiResponse; use Friendica\Module\BaseApi; use Friendica\Util\HTTPInputData; @@ -40,6 +41,6 @@ class UpdateCredentials extends BaseApi Logger::info('Patch data', ['data' => $data]); - self::unsupported(Router::PATCH); + ApiResponse::unsupported(Router::PATCH); } } diff --git a/src/Module/Api/Mastodon/Filters.php b/src/Module/Api/Mastodon/Filters.php index 2b505e0f29..8a9cd810b6 100644 --- a/src/Module/Api/Mastodon/Filters.php +++ b/src/Module/Api/Mastodon/Filters.php @@ -23,6 +23,7 @@ namespace Friendica\Module\Api\Mastodon; use Friendica\App\Router; use Friendica\Core\System; +use Friendica\Module\Api\ApiResponse; use Friendica\Module\BaseApi; /** @@ -34,7 +35,7 @@ class Filters extends BaseApi { self::checkAllowedScope(self::SCOPE_WRITE); - self::unsupported(Router::POST); + ApiResponse::unsupported(Router::POST); } /** diff --git a/src/Module/Api/Mastodon/Lists/Accounts.php b/src/Module/Api/Mastodon/Lists/Accounts.php index 6e11235630..e1de45b64d 100644 --- a/src/Module/Api/Mastodon/Lists/Accounts.php +++ b/src/Module/Api/Mastodon/Lists/Accounts.php @@ -25,6 +25,7 @@ use Friendica\App\Router; use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\DI; +use Friendica\Module\Api\ApiResponse; use Friendica\Module\BaseApi; /** @@ -36,12 +37,12 @@ class Accounts extends BaseApi { public static function delete(array $parameters = []) { - self::unsupported(Router::DELETE); + ApiResponse::unsupported(Router::DELETE); } public static function post(array $parameters = []) { - self::unsupported(Router::POST); + ApiResponse::unsupported(Router::POST); } /** diff --git a/src/Module/Api/Mastodon/Markers.php b/src/Module/Api/Mastodon/Markers.php index 50c0864990..a45611c2dc 100644 --- a/src/Module/Api/Mastodon/Markers.php +++ b/src/Module/Api/Mastodon/Markers.php @@ -23,6 +23,7 @@ namespace Friendica\Module\Api\Mastodon; use Friendica\App\Router; use Friendica\Core\System; +use Friendica\Module\Api\ApiResponse; use Friendica\Module\BaseApi; /** @@ -34,7 +35,7 @@ class Markers extends BaseApi { self::checkAllowedScope(self::SCOPE_WRITE); - self::unsupported(Router::POST); + ApiResponse::unsupported(Router::POST); } /** diff --git a/src/Module/Api/Mastodon/ScheduledStatuses.php b/src/Module/Api/Mastodon/ScheduledStatuses.php index 5b43f4515a..9f3e53c046 100644 --- a/src/Module/Api/Mastodon/ScheduledStatuses.php +++ b/src/Module/Api/Mastodon/ScheduledStatuses.php @@ -26,6 +26,7 @@ use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Post; +use Friendica\Module\Api\ApiResponse; use Friendica\Module\BaseApi; /** @@ -38,7 +39,7 @@ class ScheduledStatuses extends BaseApi self::checkAllowedScope(self::SCOPE_WRITE); $uid = self::getCurrentUserID(); - self::unsupported(Router::PUT); + ApiResponse::unsupported(Router::PUT); } public static function delete(array $parameters = []) diff --git a/src/Module/Api/Mastodon/Unimplemented.php b/src/Module/Api/Mastodon/Unimplemented.php index 035b6d2c95..d0b32b9974 100644 --- a/src/Module/Api/Mastodon/Unimplemented.php +++ b/src/Module/Api/Mastodon/Unimplemented.php @@ -22,6 +22,7 @@ namespace Friendica\Module\Api\Mastodon; use Friendica\App\Router; +use Friendica\Module\Api\ApiResponse; use Friendica\Module\BaseApi; /** @@ -35,7 +36,7 @@ class Unimplemented extends BaseApi */ public static function delete(array $parameters = []) { - self::unsupported(Router::DELETE); + ApiResponse::unsupported(Router::DELETE); } /** @@ -44,7 +45,7 @@ class Unimplemented extends BaseApi */ public static function patch(array $parameters = []) { - self::unsupported(Router::PATCH); + ApiResponse::unsupported(Router::PATCH); } /** @@ -53,7 +54,7 @@ class Unimplemented extends BaseApi */ public static function post(array $parameters = []) { - self::unsupported(Router::POST); + ApiResponse::unsupported(Router::POST); } /** @@ -62,7 +63,7 @@ class Unimplemented extends BaseApi */ public static function put(array $parameters = []) { - self::unsupported(Router::PUT); + ApiResponse::unsupported(Router::PUT); } /** @@ -71,6 +72,6 @@ class Unimplemented extends BaseApi */ public static function rawContent(array $parameters = []) { - self::unsupported(Router::GET); + ApiResponse::unsupported(Router::GET); } } diff --git a/src/Module/Api/Twitter/Account/RateLimitStatus.php b/src/Module/Api/Twitter/Account/RateLimitStatus.php index 1f410e4cfa..1ef3c8d67b 100644 --- a/src/Module/Api/Twitter/Account/RateLimitStatus.php +++ b/src/Module/Api/Twitter/Account/RateLimitStatus.php @@ -21,6 +21,7 @@ namespace Friendica\Module\Api\Twitter\Account; +use Friendica\Module\Api\ApiResponse; use Friendica\Module\BaseApi; use Friendica\Util\DateTimeFormat; @@ -51,6 +52,6 @@ class RateLimitStatus extends BaseApi ]; } - self::exit('hash', ['hash' => $hash], $parameters['extension'] ?? null); + ApiResponse::exit('hash', ['hash' => $hash], $parameters['extension'] ?? null); } } diff --git a/src/Module/Api/Twitter/SavedSearches.php b/src/Module/Api/Twitter/SavedSearches.php index ce183168b5..7a65b917a9 100644 --- a/src/Module/Api/Twitter/SavedSearches.php +++ b/src/Module/Api/Twitter/SavedSearches.php @@ -22,6 +22,7 @@ namespace Friendica\Module\Api\Twitter; use Friendica\Database\DBA; +use Friendica\Module\Api\ApiResponse; use Friendica\Module\BaseApi; /** @@ -44,6 +45,6 @@ class SavedSearches extends BaseApi DBA::close($terms); - self::exit('terms', ['terms' => $result], $parameters['extension'] ?? null); + ApiResponse::exit('terms', ['terms' => $result], $parameters['extension'] ?? null); } } diff --git a/src/Module/BaseApi.php b/src/Module/BaseApi.php index 44461117da..a0a94c336f 100644 --- a/src/Module/BaseApi.php +++ b/src/Module/BaseApi.php @@ -89,22 +89,6 @@ class BaseApi extends BaseModule } } - /** - * Quit execution with the message that the endpoint isn't implemented - * - * @param string $method - * @return void - */ - public static function unsupported(string $method = 'all') - { - $path = DI::args()->getQueryString(); - Logger::info('Unimplemented API call', ['method' => $method, 'path' => $path, 'agent' => $_SERVER['HTTP_USER_AGENT'] ?? '', 'request' => HTTPInputData::process()]); - $error = DI::l10n()->t('API endpoint %s %s is not implemented', strtoupper($method), $path); - $error_description = DI::l10n()->t('The API endpoint is currently not implemented but might be in the future.'); - $errorobj = new \Friendica\Object\Api\Mastodon\Error($error, $error_description); - System::jsonError(501, $errorobj->toArray()); - } - /** * Processes data from GET requests and sets defaults * @@ -326,160 +310,4 @@ class BaseApi extends BaseModule { return api_get_user($contact_id); } - - /** - * Exit with error code - * - * @param int $code - * @param string $description - * @param string $message - * @param string|null $format - * @return void - */ - public static function error(int $code, string $description, string $message, string $format = null) - { - $error = [ - 'error' => $message ?: $description, - 'code' => $code . ' ' . $description, - 'request' => DI::args()->getQueryString() - ]; - - header(($_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.1') . ' ' . $code . ' ' . $description); - - self::exit('status', ['status' => $error], $format); - } - - /** - * Outputs formatted data according to the data type and then exits the execution. - * - * @param string $root_element - * @param array $data An array with a single element containing the returned result - * @param string $format Output format (xml, json, rss, atom) - * @return false|string - */ - protected static function exit(string $root_element, array $data, string $format = null) - { - $format = $format ?? 'json'; - - $return = self::formatData($root_element, $format, $data); - - switch ($format) { - case 'xml': - header('Content-Type: text/xml'); - break; - case 'json': - header('Content-Type: application/json'); - if (!empty($return)) { - $json = json_encode(end($return)); - if (!empty($_GET['callback'])) { - $json = $_GET['callback'] . '(' . $json . ')'; - } - $return = $json; - } - break; - case 'rss': - header('Content-Type: application/rss+xml'); - $return = '' . "\n" . $return; - break; - case 'atom': - header('Content-Type: application/atom+xml'); - $return = '' . "\n" . $return; - break; - } - - echo $return; - exit; - } - - /** - * Formats the data according to the data type - * - * @param string $root_element Name of the root element - * @param string $type Return type (atom, rss, xml, json) - * @param array $data JSON style array - * - * @return array|string (string|array) XML data or JSON data - */ - public static function formatData($root_element, string $type, array $data) - { - switch ($type) { - case 'atom': - case 'rss': - case 'xml': - $ret = self::createXML($data, $root_element); - break; - case 'json': - default: - $ret = $data; - break; - } - return $ret; - } - - /** - * Callback function to transform the array in an array that can be transformed in a XML file - * - * @param mixed $item Array item value - * @param string $key Array key - * - * @return boolean - */ - public static function reformatXML(&$item, &$key) - { - if (is_bool($item)) { - $item = ($item ? 'true' : 'false'); - } - - if (substr($key, 0, 10) == 'statusnet_') { - $key = 'statusnet:'.substr($key, 10); - } elseif (substr($key, 0, 10) == 'friendica_') { - $key = 'friendica:'.substr($key, 10); - } - return true; - } - - /** - * Creates the XML from a JSON style array - * - * @param array $data JSON style array - * @param string $root_element Name of the root element - * - * @return string The XML data - */ - public static function createXML(array $data, $root_element) - { - $childname = key($data); - $data2 = array_pop($data); - - $namespaces = ['' => 'http://api.twitter.com', - 'statusnet' => 'http://status.net/schema/api/1/', - 'friendica' => 'http://friendi.ca/schema/api/1/', - 'georss' => 'http://www.georss.org/georss']; - - /// @todo Auto detection of needed namespaces - if (in_array($root_element, ['ok', 'hash', 'config', 'version', 'ids', 'notes', 'photos'])) { - $namespaces = []; - } - - if (is_array($data2)) { - $key = key($data2); - Arrays::walkRecursive($data2, ['Friendica\Module\BaseApi', 'reformatXML']); - - if ($key == '0') { - $data4 = []; - $i = 1; - - foreach ($data2 as $item) { - $data4[$i++ . ':' . $childname] = $item; - } - - $data2 = $data4; - } - } - - $data3 = [$root_element => $data2]; - - $ret = XML::fromArray($data3, $xml, false, $namespaces); - return $ret; - } } diff --git a/tests/legacy/ApiTest.php b/tests/legacy/ApiTest.php index 6f57f3bbd7..4ea5c784a6 100644 --- a/tests/legacy/ApiTest.php +++ b/tests/legacy/ApiTest.php @@ -10,6 +10,7 @@ use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues; use Friendica\Core\Protocol; use Friendica\DI; +use Friendica\Module\Api\ApiResponse; use Friendica\Module\BaseApi; use Friendica\Network\HTTPException; use Friendica\Security\BasicAuth; @@ -1069,7 +1070,7 @@ class ApiTest extends FixtureTest { $item = true; $key = ''; - self::assertTrue(BaseApi::reformatXML($item, $key)); + self::assertTrue(ApiResponse::reformatXML($item, $key)); self::assertEquals('true', $item); } @@ -1082,7 +1083,7 @@ class ApiTest extends FixtureTest { $item = ''; $key = 'statusnet_api'; - self::assertTrue(BaseApi::reformatXML($item, $key)); + self::assertTrue(ApiResponse::reformatXML($item, $key)); self::assertEquals('statusnet:api', $key); } @@ -1095,7 +1096,7 @@ class ApiTest extends FixtureTest { $item = ''; $key = 'friendica_api'; - self::assertTrue(BaseApi::reformatXML($item, $key)); + self::assertTrue(ApiResponse::reformatXML($item, $key)); self::assertEquals('friendica:api', $key); } @@ -1113,7 +1114,7 @@ class ApiTest extends FixtureTest 'xmlns:georss="http://www.georss.org/georss">' . "\n" . ' some_data' . "\n" . '' . "\n", - BaseApi::createXML(['data' => ['some_data']], 'root_element') + ApiResponse::createXML(['data' => ['some_data']], 'root_element') ); } @@ -1129,7 +1130,7 @@ class ApiTest extends FixtureTest '' . "\n" . ' some_data' . "\n" . '' . "\n", - BaseApi::createXML(['data' => ['some_data']], 'ok') + ApiResponse::createXML(['data' => ['some_data']], 'ok') ); } @@ -1141,7 +1142,7 @@ class ApiTest extends FixtureTest public function testApiFormatData() { $data = ['some_data']; - self::assertEquals($data, BaseApi::formatData('root_element', 'json', $data)); + self::assertEquals($data, ApiResponse::formatData('root_element', 'json', $data)); } /** @@ -1158,7 +1159,7 @@ class ApiTest extends FixtureTest 'xmlns:georss="http://www.georss.org/georss">' . "\n" . ' some_data' . "\n" . '' . "\n", - BaseApi::formatData('root_element', 'xml', ['data' => ['some_data']]) + ApiResponse::formatData('root_element', 'xml', ['data' => ['some_data']]) ); } From f28e64299e8d73fccc3c1370127df02bab8000e3 Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 12 Nov 2021 19:56:37 +0100 Subject: [PATCH 02/22] Transform ApiResponse::createXML() into dynamic method --- src/DI.php | 9 +++++++++ src/Module/Api/ApiResponse.php | 14 ++++++++------ tests/legacy/ApiTest.php | 4 ++-- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/DI.php b/src/DI.php index 692d87870d..ead125cff2 100644 --- a/src/DI.php +++ b/src/DI.php @@ -430,6 +430,15 @@ abstract class DI return self::$dice->create(Model\Log\ParsedLogIterator::class); } + // + // "Module" namespace + // + + public static function apiResponse(): Module\Api\ApiResponse + { + return self::$dice->create(Module\Api\ApiResponse::class); + } + // // "Network" namespace // diff --git a/src/Module/Api/ApiResponse.php b/src/Module/Api/ApiResponse.php index 768dacb5fb..270185025a 100644 --- a/src/Module/Api/ApiResponse.php +++ b/src/Module/Api/ApiResponse.php @@ -40,15 +40,17 @@ class ApiResponse * * @return string The XML data */ - public static function createXML(array $data, string $root_element): string + public function createXML(array $data, string $root_element): string { $childname = key($data); $data2 = array_pop($data); - $namespaces = ['' => 'http://api.twitter.com', - 'statusnet' => 'http://status.net/schema/api/1/', - 'friendica' => 'http://friendi.ca/schema/api/1/', - 'georss' => 'http://www.georss.org/georss']; + $namespaces = [ + '' => 'http://api.twitter.com', + 'statusnet' => 'http://status.net/schema/api/1/', + 'friendica' => 'http://friendi.ca/schema/api/1/', + 'georss' => 'http://www.georss.org/georss' + ]; /// @todo Auto detection of needed namespaces if (in_array($root_element, ['ok', 'hash', 'config', 'version', 'ids', 'notes', 'photos'])) { @@ -91,7 +93,7 @@ class ApiResponse case 'atom': case 'rss': case 'xml': - $ret = static::createXML($data, $root_element); + $ret = DI::apiResponse()->createXML($data, $root_element); break; case 'json': default: diff --git a/tests/legacy/ApiTest.php b/tests/legacy/ApiTest.php index 4ea5c784a6..c5d28f2d52 100644 --- a/tests/legacy/ApiTest.php +++ b/tests/legacy/ApiTest.php @@ -1114,7 +1114,7 @@ class ApiTest extends FixtureTest 'xmlns:georss="http://www.georss.org/georss">' . "\n" . ' some_data' . "\n" . '' . "\n", - ApiResponse::createXML(['data' => ['some_data']], 'root_element') + DI::apiResponse()->createXML(['data' => ['some_data']], 'root_element') ); } @@ -1130,7 +1130,7 @@ class ApiTest extends FixtureTest '' . "\n" . ' some_data' . "\n" . '' . "\n", - ApiResponse::createXML(['data' => ['some_data']], 'ok') + DI::apiResponse()->createXML(['data' => ['some_data']], 'ok') ); } From 4309f814e0b2e4a23e659bbec21adbfd3eef6227 Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 12 Nov 2021 19:59:16 +0100 Subject: [PATCH 03/22] Transform ApiResponse::formatData() into dynamic method --- include/api.php | 100 ++++++++++++++++----------------- src/Module/Api/ApiResponse.php | 6 +- tests/legacy/ApiTest.php | 4 +- 3 files changed, 55 insertions(+), 55 deletions(-) diff --git a/include/api.php b/include/api.php index 118db50bce..346863f741 100644 --- a/include/api.php +++ b/include/api.php @@ -707,7 +707,7 @@ function api_account_verify_credentials($type) unset($user_info["uid"]); unset($user_info["self"]); - return ApiResponse::formatData("user", $type, ['user' => $user_info]); + return DI::apiResponse()->formatData("user", $type, ['user' => $user_info]); } /// @TODO move to top of file or somewhere better @@ -1096,7 +1096,7 @@ function api_status_show($type, $item_id) Logger::info(API_LOG_PREFIX . 'End', ['action' => 'get_status', 'status_info' => $status_info]); - return ApiResponse::formatData('statuses', $type, ['status' => $status_info]); + return DI::apiResponse()->formatData('statuses', $type, ['status' => $status_info]); } /** @@ -1162,7 +1162,7 @@ function api_users_show($type) unset($user_info['uid']); unset($user_info['self']); - return ApiResponse::formatData('user', $type, ['user' => $user_info]); + return DI::apiResponse()->formatData('user', $type, ['user' => $user_info]); } /// @TODO move to top of file or somewhere better @@ -1218,7 +1218,7 @@ function api_users_search($type) throw new BadRequestException('No search term specified.'); } - return ApiResponse::formatData('users', $type, $userlist); + return DI::apiResponse()->formatData('users', $type, $userlist); } /// @TODO move to top of file or somewhere better @@ -1254,7 +1254,7 @@ function api_users_lookup($type) throw new NotFoundException; } - return ApiResponse::formatData("users", $type, ['users' => $users]); + return DI::apiResponse()->formatData("users", $type, ['users' => $users]); } /// @TODO move to top of file or somewhere better @@ -1317,7 +1317,7 @@ function api_search($type) DBA::close($tags); if (empty($uriids)) { - return ApiResponse::formatData('statuses', $type, $data); + return DI::apiResponse()->formatData('statuses', $type, $data); } $condition = ['uri-id' => $uriids]; @@ -1358,7 +1358,7 @@ function api_search($type) bindComments($data['status']); - return ApiResponse::formatData('statuses', $type, $data); + return DI::apiResponse()->formatData('statuses', $type, $data); } /// @TODO move to top of file or somewhere better @@ -1455,7 +1455,7 @@ function api_statuses_home_timeline($type) break; } - return ApiResponse::formatData("statuses", $type, $data); + return DI::apiResponse()->formatData("statuses", $type, $data); } @@ -1541,7 +1541,7 @@ function api_statuses_public_timeline($type) break; } - return ApiResponse::formatData("statuses", $type, $data); + return DI::apiResponse()->formatData("statuses", $type, $data); } /// @TODO move to top of file or somewhere better @@ -1600,7 +1600,7 @@ function api_statuses_networkpublic_timeline($type) break; } - return ApiResponse::formatData("statuses", $type, $data); + return DI::apiResponse()->formatData("statuses", $type, $data); } /// @TODO move to top of file or somewhere better @@ -1676,10 +1676,10 @@ function api_statuses_show($type) if ($conversation) { $data = ['status' => $ret]; - return ApiResponse::formatData("statuses", $type, $data); + return DI::apiResponse()->formatData("statuses", $type, $data); } else { $data = ['status' => $ret[0]]; - return ApiResponse::formatData("status", $type, $data); + return DI::apiResponse()->formatData("status", $type, $data); } } @@ -1758,7 +1758,7 @@ function api_conversation_show($type) $ret = api_format_items(Post::toArray($statuses), $user_info, false, $type); $data = ['status' => $ret]; - return ApiResponse::formatData("statuses", $type, $data); + return DI::apiResponse()->formatData("statuses", $type, $data); } /// @TODO move to top of file or somewhere better @@ -1969,7 +1969,7 @@ function api_statuses_mentions($type) break; } - return ApiResponse::formatData("statuses", $type, $data); + return DI::apiResponse()->formatData("statuses", $type, $data); } /// @TODO move to top of file or somewhere better @@ -2047,7 +2047,7 @@ function api_statuses_user_timeline($type) break; } - return ApiResponse::formatData("statuses", $type, $data); + return DI::apiResponse()->formatData("statuses", $type, $data); } /// @TODO move to top of file or somewhere better @@ -2129,7 +2129,7 @@ function api_favorites_create_destroy($type) break; } - return ApiResponse::formatData("status", $type, $data); + return DI::apiResponse()->formatData("status", $type, $data); } /// @TODO move to top of file or somewhere better @@ -2202,7 +2202,7 @@ function api_favorites($type) break; } - return ApiResponse::formatData("statuses", $type, $data); + return DI::apiResponse()->formatData("statuses", $type, $data); } /// @TODO move to top of file or somewhere better @@ -2908,7 +2908,7 @@ function api_lists_list($type) { $ret = []; /// @TODO $ret is not filled here? - return ApiResponse::formatData('lists', $type, ["lists_list" => $ret]); + return DI::apiResponse()->formatData('lists', $type, ["lists_list" => $ret]); } /// @TODO move to top of file or somewhere better @@ -2958,7 +2958,7 @@ function api_lists_ownerships($type) 'mode' => $mode ]; } - return ApiResponse::formatData("lists", $type, ['lists' => ['lists' => $lists]]); + return DI::apiResponse()->formatData("lists", $type, ['lists' => ['lists' => $lists]]); } /// @TODO move to top of file or somewhere better @@ -3038,7 +3038,7 @@ function api_lists_statuses($type) break; } - return ApiResponse::formatData("statuses", $type, $data); + return DI::apiResponse()->formatData("statuses", $type, $data); } /// @TODO move to top of file or somewhere better @@ -3152,7 +3152,7 @@ function api_statuses_friends($type) if ($data === false) { return false; } - return ApiResponse::formatData("users", $type, $data); + return DI::apiResponse()->formatData("users", $type, $data); } /** @@ -3171,7 +3171,7 @@ function api_statuses_followers($type) if ($data === false) { return false; } - return ApiResponse::formatData("users", $type, $data); + return DI::apiResponse()->formatData("users", $type, $data); } /// @TODO move to top of file or somewhere better @@ -3195,7 +3195,7 @@ function api_blocks_list($type) if ($data === false) { return false; } - return ApiResponse::formatData("users", $type, $data); + return DI::apiResponse()->formatData("users", $type, $data); } /// @TODO move to top of file or somewhere better @@ -3224,7 +3224,7 @@ function api_friendships_incoming($type) $ids[] = $user['id']; } - return ApiResponse::formatData("ids", $type, ['id' => $ids]); + return DI::apiResponse()->formatData("ids", $type, ['id' => $ids]); } /// @TODO move to top of file or somewhere better @@ -3265,7 +3265,7 @@ function api_statusnet_config($type) ], ]; - return ApiResponse::formatData('config', $type, ['config' => $config]); + return DI::apiResponse()->formatData('config', $type, ['config' => $config]); } /// @TODO move to top of file or somewhere better @@ -3349,7 +3349,7 @@ function api_direct_messages_new($type) break; } - return ApiResponse::formatData("direct-messages", $type, $data); + return DI::apiResponse()->formatData("direct-messages", $type, $data); } /// @TODO move to top of file or somewhere better @@ -3388,7 +3388,7 @@ function api_direct_messages_destroy($type) // error if no id or parenturi specified (for clients posting parent-uri as well) if ($verbose == "true" && ($id == 0 || $parenturi == "")) { $answer = ['result' => 'error', 'message' => 'message id or parenturi not specified']; - return ApiResponse::formatData("direct_messages_delete", $type, ['$result' => $answer]); + return DI::apiResponse()->formatData("direct_messages_delete", $type, ['$result' => $answer]); } // BadRequestException if no id specified (for clients using Twitter API) @@ -3403,7 +3403,7 @@ function api_direct_messages_destroy($type) if (!DBA::exists('mail', ["`uid` = ? AND `id` = ? " . $sql_extra, $uid, $id])) { if ($verbose == "true") { $answer = ['result' => 'error', 'message' => 'message id not in database']; - return ApiResponse::formatData("direct_messages_delete", $type, ['$result' => $answer]); + return DI::apiResponse()->formatData("direct_messages_delete", $type, ['$result' => $answer]); } /// @todo BadRequestException ok for Twitter API clients? throw new BadRequestException('message id not in database'); @@ -3416,10 +3416,10 @@ function api_direct_messages_destroy($type) if ($result) { // return success $answer = ['result' => 'ok', 'message' => 'message deleted']; - return ApiResponse::formatData("direct_message_delete", $type, ['$result' => $answer]); + return DI::apiResponse()->formatData("direct_message_delete", $type, ['$result' => $answer]); } else { $answer = ['result' => 'error', 'message' => 'unknown error']; - return ApiResponse::formatData("direct_messages_delete", $type, ['$result' => $answer]); + return DI::apiResponse()->formatData("direct_messages_delete", $type, ['$result' => $answer]); } } /// @todo return JSON data like Twitter API not yet implemented @@ -3504,7 +3504,7 @@ function api_friendships_destroy($type) // Set screen_name since Twidere requests it $contact['screen_name'] = $contact['nick']; - return ApiResponse::formatData('friendships-destroy', $type, ['user' => $contact]); + return DI::apiResponse()->formatData('friendships-destroy', $type, ['user' => $contact]); } api_register_func('api/friendships/destroy', 'api_friendships_destroy', true, API_METHOD_POST); @@ -3586,7 +3586,7 @@ function api_direct_messages_box($type, $box, $verbose) )); if ($verbose == "true" && !DBA::isResult($r)) { $answer = ['result' => 'error', 'message' => 'no mails available']; - return ApiResponse::formatData("direct_messages_all", $type, ['$result' => $answer]); + return DI::apiResponse()->formatData("direct_messages_all", $type, ['$result' => $answer]); } $ret = []; @@ -3614,7 +3614,7 @@ function api_direct_messages_box($type, $box, $verbose) break; } - return ApiResponse::formatData("direct-messages", $type, $data); + return DI::apiResponse()->formatData("direct-messages", $type, $data); } /** @@ -3728,7 +3728,7 @@ function api_fr_photos_list($type) } } } - return ApiResponse::formatData("photos", $type, $data); + return DI::apiResponse()->formatData("photos", $type, $data); } /** @@ -3800,7 +3800,7 @@ function api_fr_photo_create_update($type) // return success of updating or error message if (!is_null($data)) { - return ApiResponse::formatData("photo_create", $type, $data); + return DI::apiResponse()->formatData("photo_create", $type, $data); } else { throw new InternalServerErrorException("unknown error - uploading photo failed, see Friendica log for more information"); } @@ -3851,18 +3851,18 @@ function api_fr_photo_create_update($type) $media = $_FILES['media']; $data = save_media_to_database("photo", $media, $type, $album, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $desc, Photo::DEFAULT, $visibility, $photo_id); if (!is_null($data)) { - return ApiResponse::formatData("photo_update", $type, $data); + return DI::apiResponse()->formatData("photo_update", $type, $data); } } // return success of updating or error message if ($result) { $answer = ['result' => 'updated', 'message' => 'Image id `' . $photo_id . '` has been updated.']; - return ApiResponse::formatData("photo_update", $type, ['$result' => $answer]); + return DI::apiResponse()->formatData("photo_update", $type, ['$result' => $answer]); } else { if ($nothingtodo) { $answer = ['result' => 'cancelled', 'message' => 'Nothing to update for image id `' . $photo_id . '`.']; - return ApiResponse::formatData("photo_update", $type, ['$result' => $answer]); + return DI::apiResponse()->formatData("photo_update", $type, ['$result' => $answer]); } throw new InternalServerErrorException("unknown error - update photo entry in database failed"); } @@ -3895,7 +3895,7 @@ function api_fr_photo_detail($type) // prepare json/xml output with data from database for the requested photo $data = prepare_photo_data($type, $scale, $photo_id); - return ApiResponse::formatData("photo_detail", $type, $data); + return DI::apiResponse()->formatData("photo_detail", $type, $data); } @@ -4626,7 +4626,7 @@ function api_friendica_group_show($type) } $grps[] = ['name' => $rr['name'], 'gid' => $rr['id'], $user_element => $users]; } - return ApiResponse::formatData("groups", $type, ['group' => $grps]); + return DI::apiResponse()->formatData("groups", $type, ['group' => $grps]); } api_register_func('api/friendica/group_show', 'api_friendica_group_show', true); @@ -4684,7 +4684,7 @@ function api_friendica_group_delete($type) if ($ret) { // return success $success = ['success' => $ret, 'gid' => $gid, 'name' => $name, 'status' => 'deleted', 'wrong users' => []]; - return ApiResponse::formatData("group_delete", $type, ['result' => $success]); + return DI::apiResponse()->formatData("group_delete", $type, ['result' => $success]); } else { throw new BadRequestException('other API error'); } @@ -4737,7 +4737,7 @@ function api_lists_destroy($type) 'user' => $user_info ]; - return ApiResponse::formatData("lists", $type, ['lists' => $list]); + return DI::apiResponse()->formatData("lists", $type, ['lists' => $list]); } } @@ -4826,7 +4826,7 @@ function api_friendica_group_create($type) $success = group_create($name, $uid, $users); - return ApiResponse::formatData("group_create", $type, ['result' => $success]); + return DI::apiResponse()->formatData("group_create", $type, ['result' => $success]); } api_register_func('api/friendica/group_create', 'api_friendica_group_create', true, API_METHOD_POST); @@ -4866,7 +4866,7 @@ function api_lists_create($type) 'user' => $user_info ]; - return ApiResponse::formatData("lists", $type, ['lists' => $grp]); + return DI::apiResponse()->formatData("lists", $type, ['lists' => $grp]); } } @@ -4940,7 +4940,7 @@ function api_friendica_group_update($type) // return success message incl. missing users in array $status = ($erroraddinguser ? "missing user" : "ok"); $success = ['success' => true, 'gid' => $gid, 'name' => $name, 'status' => $status, 'wrong users' => $errorusers]; - return ApiResponse::formatData("group_update", $type, ['result' => $success]); + return DI::apiResponse()->formatData("group_update", $type, ['result' => $success]); } api_register_func('api/friendica/group_update', 'api_friendica_group_update', true, API_METHOD_POST); @@ -4992,7 +4992,7 @@ function api_lists_update($type) 'user' => $user_info ]; - return ApiResponse::formatData("lists", $type, ['lists' => $list]); + return DI::apiResponse()->formatData("lists", $type, ['lists' => $list]); } } @@ -5044,12 +5044,12 @@ function api_friendica_notification_seen($type) // we found the item, return it to the user $ret = api_format_items([$item], $user_info, false, $type); $data = ['status' => $ret]; - return ApiResponse::formatData('status', $type, $data); + return DI::apiResponse()->formatData('status', $type, $data); } // the item can't be found, but we set the notification as seen, so we count this as a success } - return ApiResponse::formatData('result', $type, ['result' => 'success']); + return DI::apiResponse()->formatData('result', $type, ['result' => 'success']); } catch (NotFoundException $e) { throw new BadRequestException('Invalid argument', $e); } catch (Exception $e) { @@ -5090,7 +5090,7 @@ function api_friendica_direct_messages_search($type, $box = "") // error if no searchstring specified if ($searchstring == "") { $answer = ['result' => 'error', 'message' => 'searchstring not specified']; - return ApiResponse::formatData("direct_messages_search", $type, ['$result' => $answer]); + return DI::apiResponse()->formatData("direct_messages_search", $type, ['$result' => $answer]); } // get data for the specified searchstring @@ -5125,7 +5125,7 @@ function api_friendica_direct_messages_search($type, $box = "") $success = ['success' => true, 'search_results' => $ret]; } - return ApiResponse::formatData("direct_message_search", $type, ['$result' => $success]); + return DI::apiResponse()->formatData("direct_message_search", $type, ['$result' => $success]); } /// @TODO move to top of file or somewhere better diff --git a/src/Module/Api/ApiResponse.php b/src/Module/Api/ApiResponse.php index 270185025a..2ce9137337 100644 --- a/src/Module/Api/ApiResponse.php +++ b/src/Module/Api/ApiResponse.php @@ -87,13 +87,13 @@ class ApiResponse * * @return array|string (string|array) XML data or JSON data */ - public static function formatData(string $root_element, string $type, array $data) + public function formatData(string $root_element, string $type, array $data) { switch ($type) { case 'atom': case 'rss': case 'xml': - $ret = DI::apiResponse()->createXML($data, $root_element); + $ret = $this->createXML($data, $root_element); break; case 'json': default: @@ -161,7 +161,7 @@ class ApiResponse { $format = $format ?? 'json'; - $return = static::formatData($root_element, $format, $data); + $return = DI::apiResponse()->formatData($root_element, $format, $data); switch ($format) { case 'xml': diff --git a/tests/legacy/ApiTest.php b/tests/legacy/ApiTest.php index c5d28f2d52..6bf144463a 100644 --- a/tests/legacy/ApiTest.php +++ b/tests/legacy/ApiTest.php @@ -1142,7 +1142,7 @@ class ApiTest extends FixtureTest public function testApiFormatData() { $data = ['some_data']; - self::assertEquals($data, ApiResponse::formatData('root_element', 'json', $data)); + self::assertEquals($data, DI::apiResponse()->formatData('root_element', 'json', $data)); } /** @@ -1159,7 +1159,7 @@ class ApiTest extends FixtureTest 'xmlns:georss="http://www.georss.org/georss">' . "\n" . ' some_data' . "\n" . '' . "\n", - ApiResponse::formatData('root_element', 'xml', ['data' => ['some_data']]) + DI::apiResponse()->formatData('root_element', 'xml', ['data' => ['some_data']]) ); } From ea0f41ecf0218644e5c83f7dd2269a8947f775c6 Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 12 Nov 2021 20:03:27 +0100 Subject: [PATCH 04/22] Transform ApiResponse::exit() into dynamic method --- src/Module/Api/ApiResponse.php | 6 +++--- src/Module/Api/Friendica/Activity.php | 3 ++- src/Module/Api/Friendica/DirectMessages/Setseen.php | 8 ++++---- src/Module/Api/Friendica/Events/Index.php | 5 ++--- src/Module/Api/Friendica/Notification.php | 3 +-- src/Module/Api/Friendica/Photo/Delete.php | 4 ++-- src/Module/Api/Friendica/Photoalbum/Delete.php | 4 ++-- src/Module/Api/Friendica/Photoalbum/Update.php | 4 ++-- src/Module/Api/Friendica/Profile/Show.php | 4 +--- src/Module/Api/GNUSocial/GNUSocial/Version.php | 4 ++-- src/Module/Api/GNUSocial/Help/Test.php | 4 ++-- src/Module/Api/Twitter/Account/RateLimitStatus.php | 4 ++-- src/Module/Api/Twitter/SavedSearches.php | 4 ++-- 13 files changed, 27 insertions(+), 30 deletions(-) diff --git a/src/Module/Api/ApiResponse.php b/src/Module/Api/ApiResponse.php index 2ce9137337..47d52ca1fc 100644 --- a/src/Module/Api/ApiResponse.php +++ b/src/Module/Api/ApiResponse.php @@ -145,7 +145,7 @@ class ApiResponse header(($_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.1') . ' ' . $code . ' ' . $description); - self::exit('status', ['status' => $error], $format); + DI::apiResponse()->exit('status', ['status' => $error], $format); } /** @@ -157,11 +157,11 @@ class ApiResponse * * @return void */ - public static function exit(string $root_element, array $data, string $format = null) + public function exit(string $root_element, array $data, string $format = null) { $format = $format ?? 'json'; - $return = DI::apiResponse()->formatData($root_element, $format, $data); + $return = $this->formatData($root_element, $format, $data); switch ($format) { case 'xml': diff --git a/src/Module/Api/Friendica/Activity.php b/src/Module/Api/Friendica/Activity.php index 41500dfe01..2f4c0ff53a 100644 --- a/src/Module/Api/Friendica/Activity.php +++ b/src/Module/Api/Friendica/Activity.php @@ -21,6 +21,7 @@ namespace Friendica\Module\Api\Friendica; +use Friendica\DI; use Friendica\Model\Item; use Friendica\Module\Api\ApiResponse; use Friendica\Module\BaseApi; @@ -57,7 +58,7 @@ class Activity extends BaseApi } else { $ok = 'ok'; } - ApiResponse::exit('ok', ['ok' => $ok], $parameters['extension'] ?? null); + DI::apiResponse()->exit('ok', ['ok' => $ok], $parameters['extension'] ?? null); } else { ApiResponse::error(500, 'Error adding activity', '', $parameters['extension'] ?? null); } diff --git a/src/Module/Api/Friendica/DirectMessages/Setseen.php b/src/Module/Api/Friendica/DirectMessages/Setseen.php index a7eab43e22..e55ad74b96 100644 --- a/src/Module/Api/Friendica/DirectMessages/Setseen.php +++ b/src/Module/Api/Friendica/DirectMessages/Setseen.php @@ -22,7 +22,7 @@ namespace Friendica\Module\Api\Friendica\DirectMessages; use Friendica\Database\DBA; -use Friendica\Module\Api\ApiResponse; +use Friendica\DI; use Friendica\Module\BaseApi; /** @@ -42,13 +42,13 @@ class Setseen extends BaseApi // return error if id is zero if (empty($request['id'])) { $answer = ['result' => 'error', 'message' => 'message id not specified']; - ApiResponse::exit('direct_messages_setseen', ['$result' => $answer], $parameters['extension'] ?? null); + DI::apiResponse()->exit('direct_messages_setseen', ['$result' => $answer], $parameters['extension'] ?? null); } // error message if specified id is not in database if (!DBA::exists('mail', ['id' => $request['id'], 'uid' => $uid])) { $answer = ['result' => 'error', 'message' => 'message id not in database']; - ApiResponse::exit('direct_messages_setseen', ['$result' => $answer], $parameters['extension'] ?? null); + DI::apiResponse()->exit('direct_messages_setseen', ['$result' => $answer], $parameters['extension'] ?? null); } // update seen indicator @@ -58,6 +58,6 @@ class Setseen extends BaseApi $answer = ['result' => 'error', 'message' => 'unknown error']; } - ApiResponse::exit('direct_messages_setseen', ['$result' => $answer], $parameters['extension'] ?? null); + DI::apiResponse()->exit('direct_messages_setseen', ['$result' => $answer], $parameters['extension'] ?? null); } } diff --git a/src/Module/Api/Friendica/Events/Index.php b/src/Module/Api/Friendica/Events/Index.php index 7bfeaa2ef7..31c55069da 100644 --- a/src/Module/Api/Friendica/Events/Index.php +++ b/src/Module/Api/Friendica/Events/Index.php @@ -23,9 +23,8 @@ namespace Friendica\Module\Api\Friendica\Events; use Friendica\Content\Text\BBCode; use Friendica\Database\DBA; -use Friendica\Module\Api\ApiResponse; +use Friendica\DI; use Friendica\Module\BaseApi; -use Friendica\Network\HTTPException; /** * api/friendica/events @@ -71,6 +70,6 @@ class Index extends BaseApi ]; } - ApiResponse::exit('events', ['events' => $items], $parameters['extension'] ?? null); + DI::apiResponse()->exit('events', ['events' => $items], $parameters['extension'] ?? null); } } diff --git a/src/Module/Api/Friendica/Notification.php b/src/Module/Api/Friendica/Notification.php index fb028dd752..2a50bde7b5 100644 --- a/src/Module/Api/Friendica/Notification.php +++ b/src/Module/Api/Friendica/Notification.php @@ -23,7 +23,6 @@ namespace Friendica\Module\Api\Friendica; use Friendica\Collection\Api\Notifications as ApiNotifications; use Friendica\DI; -use Friendica\Module\Api\ApiResponse; use Friendica\Module\BaseApi; use Friendica\Object\Api\Friendica\Notification as ApiNotification; @@ -57,6 +56,6 @@ class Notification extends BaseApi $result = false; } - ApiResponse::exit('notes', ['note' => $result], $parameters['extension'] ?? null); + DI::apiResponse()->exit('notes', ['note' => $result], $parameters['extension'] ?? null); } } diff --git a/src/Module/Api/Friendica/Photo/Delete.php b/src/Module/Api/Friendica/Photo/Delete.php index 1e6b86ca85..13ea7ebe7a 100644 --- a/src/Module/Api/Friendica/Photo/Delete.php +++ b/src/Module/Api/Friendica/Photo/Delete.php @@ -21,9 +21,9 @@ namespace Friendica\Module\Api\Friendica\Photo; +use Friendica\DI; use Friendica\Model\Item; use Friendica\Model\Photo; -use Friendica\Module\Api\ApiResponse; use Friendica\Module\BaseApi; use Friendica\Network\HTTPException\BadRequestException; use Friendica\Network\HTTPException\InternalServerErrorException; @@ -64,7 +64,7 @@ class Delete extends BaseApi Item::deleteForUser($condition, $uid); $result = ['result' => 'deleted', 'message' => 'photo with id `' . $request['photo_id'] . '` has been deleted from server.']; - ApiResponse::exit('photo_delete', ['$result' => $result], $parameters['extension'] ?? null); + DI::apiResponse()->exit('photo_delete', ['$result' => $result], $parameters['extension'] ?? null); } else { throw new InternalServerErrorException("unknown error on deleting photo from database table"); } diff --git a/src/Module/Api/Friendica/Photoalbum/Delete.php b/src/Module/Api/Friendica/Photoalbum/Delete.php index 3ee3e2dc39..dd18365b46 100644 --- a/src/Module/Api/Friendica/Photoalbum/Delete.php +++ b/src/Module/Api/Friendica/Photoalbum/Delete.php @@ -22,9 +22,9 @@ namespace Friendica\Module\Api\Friendica\Photoalbum; use Friendica\Database\DBA; +use Friendica\DI; use Friendica\Model\Item; use Friendica\Model\Photo; -use Friendica\Module\Api\ApiResponse; use Friendica\Module\BaseApi; use Friendica\Network\HTTPException\BadRequestException; use Friendica\Network\HTTPException\InternalServerErrorException; @@ -67,7 +67,7 @@ class Delete extends BaseApi // return success of deletion or error message if ($result) { $answer = ['result' => 'deleted', 'message' => 'album `' . $request['album'] . '` with all containing photos has been deleted.']; - ApiResponse::exit('photoalbum_delete', ['$result' => $answer], $parameters['extension'] ?? null); + DI::apiResponse()->exit('photoalbum_delete', ['$result' => $answer], $parameters['extension'] ?? null); } else { throw new InternalServerErrorException("unknown error - deleting from database failed"); } diff --git a/src/Module/Api/Friendica/Photoalbum/Update.php b/src/Module/Api/Friendica/Photoalbum/Update.php index 75ea48a82d..9b75596fa7 100644 --- a/src/Module/Api/Friendica/Photoalbum/Update.php +++ b/src/Module/Api/Friendica/Photoalbum/Update.php @@ -21,8 +21,8 @@ namespace Friendica\Module\Api\Friendica\Photoalbum; +use Friendica\DI; use Friendica\Model\Photo; -use Friendica\Module\Api\ApiResponse; use Friendica\Module\BaseApi; use Friendica\Network\HTTPException\BadRequestException; use Friendica\Network\HTTPException\InternalServerErrorException; @@ -59,7 +59,7 @@ class Update extends BaseApi // return success of updating or error message if ($result) { $answer = ['result' => 'updated', 'message' => 'album `' . $request['album'] . '` with all containing photos has been renamed to `' . $request['album_new'] . '`.']; - ApiResponse::exit('photoalbum_update', ['$result' => $answer], $parameters['extension'] ?? null); + DI::apiResponse()->exit('photoalbum_update', ['$result' => $answer], $parameters['extension'] ?? null); } else { throw new InternalServerErrorException("unknown error - updating in database failed"); } diff --git a/src/Module/Api/Friendica/Profile/Show.php b/src/Module/Api/Friendica/Profile/Show.php index bb3197ad21..e388405eff 100644 --- a/src/Module/Api/Friendica/Profile/Show.php +++ b/src/Module/Api/Friendica/Profile/Show.php @@ -21,7 +21,6 @@ namespace Friendica\Module\Api\Friendica\Profile; -use Friendica\Module\Api\ApiResponse; use Friendica\Profile\ProfileField\Collection\ProfileFields; use Friendica\Content\Text\BBCode; use Friendica\DI; @@ -29,7 +28,6 @@ use Friendica\Model\Contact; use Friendica\Model\Profile; use Friendica\Module\BaseApi; use Friendica\Network\HTTPException; -use Friendica\Security\PermissionSet\Repository\PermissionSet; /** * API endpoint: /api/friendica/profile/show @@ -67,7 +65,7 @@ class Show extends BaseApi 'profiles' => $profiles ]; - ApiResponse::exit('friendica_profiles', ['$result' => $result], $parameters['extension'] ?? null); + DI::apiResponse()->exit('friendica_profiles', ['$result' => $result], $parameters['extension'] ?? null); } /** diff --git a/src/Module/Api/GNUSocial/GNUSocial/Version.php b/src/Module/Api/GNUSocial/GNUSocial/Version.php index 4b9d745030..52393702f9 100644 --- a/src/Module/Api/GNUSocial/GNUSocial/Version.php +++ b/src/Module/Api/GNUSocial/GNUSocial/Version.php @@ -21,8 +21,8 @@ namespace Friendica\Module\Api\GNUSocial\GNUSocial; -use Friendica\Module\Api\ApiResponse; use Friendica\Module\BaseApi; +use Friendica\DI; /** * API endpoint: /api/gnusocial/version, /api/statusnet/version @@ -31,6 +31,6 @@ class Version extends BaseApi { public static function rawContent(array $parameters = []) { - ApiResponse::exit('version', ['version' => '0.9.7'], $parameters['extension'] ?? null); + DI::apiResponse()->exit('version', ['version' => '0.9.7'], $parameters['extension'] ?? null); } } diff --git a/src/Module/Api/GNUSocial/Help/Test.php b/src/Module/Api/GNUSocial/Help/Test.php index bfd7559a45..3df694c859 100644 --- a/src/Module/Api/GNUSocial/Help/Test.php +++ b/src/Module/Api/GNUSocial/Help/Test.php @@ -21,8 +21,8 @@ namespace Friendica\Module\Api\GNUSocial\Help; -use Friendica\Module\Api\ApiResponse; use Friendica\Module\BaseApi; +use Friendica\DI; /** * API endpoint: /api/help/test @@ -37,6 +37,6 @@ class Test extends BaseApi $ok = 'ok'; } - ApiResponse::exit('ok', ['ok' => $ok], $parameters['extension'] ?? null); + DI::apiResponse()->exit('ok', ['ok' => $ok], $parameters['extension'] ?? null); } } diff --git a/src/Module/Api/Twitter/Account/RateLimitStatus.php b/src/Module/Api/Twitter/Account/RateLimitStatus.php index 1ef3c8d67b..fe422c79f1 100644 --- a/src/Module/Api/Twitter/Account/RateLimitStatus.php +++ b/src/Module/Api/Twitter/Account/RateLimitStatus.php @@ -21,8 +21,8 @@ namespace Friendica\Module\Api\Twitter\Account; -use Friendica\Module\Api\ApiResponse; use Friendica\Module\BaseApi; +use Friendica\DI; use Friendica\Util\DateTimeFormat; /** @@ -52,6 +52,6 @@ class RateLimitStatus extends BaseApi ]; } - ApiResponse::exit('hash', ['hash' => $hash], $parameters['extension'] ?? null); + DI::apiResponse()->exit('hash', ['hash' => $hash], $parameters['extension'] ?? null); } } diff --git a/src/Module/Api/Twitter/SavedSearches.php b/src/Module/Api/Twitter/SavedSearches.php index 7a65b917a9..b2e2c5f0d6 100644 --- a/src/Module/Api/Twitter/SavedSearches.php +++ b/src/Module/Api/Twitter/SavedSearches.php @@ -22,7 +22,7 @@ namespace Friendica\Module\Api\Twitter; use Friendica\Database\DBA; -use Friendica\Module\Api\ApiResponse; +use Friendica\DI; use Friendica\Module\BaseApi; /** @@ -45,6 +45,6 @@ class SavedSearches extends BaseApi DBA::close($terms); - ApiResponse::exit('terms', ['terms' => $result], $parameters['extension'] ?? null); + DI::apiResponse()->exit('terms', ['terms' => $result], $parameters['extension'] ?? null); } } From ebf56674f1d36d50052b29ca6f5e12d882f7296b Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 12 Nov 2021 20:04:47 +0100 Subject: [PATCH 05/22] Transform ApiResponse::error() into dynamic method --- include/api.php | 2 +- src/Module/Api/ApiResponse.php | 6 +++--- src/Module/Api/Friendica/Activity.php | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/api.php b/include/api.php index 346863f741..4aafadfab1 100644 --- a/include/api.php +++ b/include/api.php @@ -283,7 +283,7 @@ function api_call(App $a, App\Arguments $args = null) Logger::warning(API_LOG_PREFIX . 'not implemented', ['module' => 'api', 'action' => 'call', 'query' => DI::args()->getQueryString()]); throw new NotFoundException(); } catch (HTTPException $e) { - ApiResponse::error($e->getCode(), $e->getDescription(), $e->getMessage(), $type); + DI::apiResponse()->error($e->getCode(), $e->getDescription(), $e->getMessage(), $type); } } diff --git a/src/Module/Api/ApiResponse.php b/src/Module/Api/ApiResponse.php index 47d52ca1fc..d09cfe3bc5 100644 --- a/src/Module/Api/ApiResponse.php +++ b/src/Module/Api/ApiResponse.php @@ -135,17 +135,17 @@ class ApiResponse * * @return void */ - public static function error(int $code, string $description, string $message, string $format = null) + public function error(int $code, string $description, string $message, string $format = null) { $error = [ 'error' => $message ?: $description, 'code' => $code . ' ' . $description, - 'request' => DI::args()->getQueryString() + 'request' => $this->args->getQueryString() ]; header(($_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.1') . ' ' . $code . ' ' . $description); - DI::apiResponse()->exit('status', ['status' => $error], $format); + $this->exit('status', ['status' => $error], $format); } /** diff --git a/src/Module/Api/Friendica/Activity.php b/src/Module/Api/Friendica/Activity.php index 2f4c0ff53a..fa27876d3b 100644 --- a/src/Module/Api/Friendica/Activity.php +++ b/src/Module/Api/Friendica/Activity.php @@ -60,7 +60,7 @@ class Activity extends BaseApi } DI::apiResponse()->exit('ok', ['ok' => $ok], $parameters['extension'] ?? null); } else { - ApiResponse::error(500, 'Error adding activity', '', $parameters['extension'] ?? null); + DI::apiResponse()->error(500, 'Error adding activity', '', $parameters['extension'] ?? null); } } } From 5bfcc8b91c149391f6b8be75ea87f1f4add5bb6c Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 12 Nov 2021 20:07:05 +0100 Subject: [PATCH 06/22] Transform ApiResponse::unspported() into dynamic method --- src/Module/Api/ApiResponse.php | 9 ++++----- .../Api/Mastodon/Accounts/UpdateCredentials.php | 4 ++-- src/Module/Api/Mastodon/Filters.php | 4 ++-- src/Module/Api/Mastodon/Lists/Accounts.php | 4 ++-- src/Module/Api/Mastodon/Markers.php | 4 ++-- src/Module/Api/Mastodon/ScheduledStatuses.php | 2 +- src/Module/Api/Mastodon/Unimplemented.php | 12 ++++++------ 7 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/Module/Api/ApiResponse.php b/src/Module/Api/ApiResponse.php index d09cfe3bc5..5f7e4e51fb 100644 --- a/src/Module/Api/ApiResponse.php +++ b/src/Module/Api/ApiResponse.php @@ -6,7 +6,6 @@ use Friendica\App\Arguments; use Friendica\Core\L10n; use Friendica\Core\Logger; use Friendica\Core\System; -use Friendica\DI; use Friendica\Object\Api\Mastodon\Error; use Friendica\Util\Arrays; use Friendica\Util\HTTPInputData; @@ -199,9 +198,9 @@ class ApiResponse * @return void * @throws \Exception */ - public static function unsupported(string $method = 'all') + public function unsupported(string $method = 'all') { - $path = DI::args()->getQueryString(); + $path = $this->args->getQueryString(); Logger::info('Unimplemented API call', [ 'method' => $method, @@ -209,8 +208,8 @@ class ApiResponse 'agent' => $_SERVER['HTTP_USER_AGENT'] ?? '', 'request' => HTTPInputData::process() ]); - $error = DI::l10n()->t('API endpoint %s %s is not implemented', strtoupper($method), $path); - $error_description = DI::l10n()->t('The API endpoint is currently not implemented but might be in the future.'); + $error = $this->l10n->t('API endpoint %s %s is not implemented', strtoupper($method), $path); + $error_description = $this->l10n->t('The API endpoint is currently not implemented but might be in the future.'); $errorobj = new Error($error, $error_description); System::jsonError(501, $errorobj->toArray()); } diff --git a/src/Module/Api/Mastodon/Accounts/UpdateCredentials.php b/src/Module/Api/Mastodon/Accounts/UpdateCredentials.php index ccd2e903c0..449e26fb96 100644 --- a/src/Module/Api/Mastodon/Accounts/UpdateCredentials.php +++ b/src/Module/Api/Mastodon/Accounts/UpdateCredentials.php @@ -23,7 +23,7 @@ namespace Friendica\Module\Api\Mastodon\Accounts; use Friendica\App\Router; use Friendica\Core\Logger; -use Friendica\Module\Api\ApiResponse; +use Friendica\DI; use Friendica\Module\BaseApi; use Friendica\Util\HTTPInputData; @@ -41,6 +41,6 @@ class UpdateCredentials extends BaseApi Logger::info('Patch data', ['data' => $data]); - ApiResponse::unsupported(Router::PATCH); + DI::apiResponse()->unsupported(Router::PATCH); } } diff --git a/src/Module/Api/Mastodon/Filters.php b/src/Module/Api/Mastodon/Filters.php index 8a9cd810b6..f14b74a0bd 100644 --- a/src/Module/Api/Mastodon/Filters.php +++ b/src/Module/Api/Mastodon/Filters.php @@ -23,7 +23,7 @@ namespace Friendica\Module\Api\Mastodon; use Friendica\App\Router; use Friendica\Core\System; -use Friendica\Module\Api\ApiResponse; +use Friendica\DI; use Friendica\Module\BaseApi; /** @@ -35,7 +35,7 @@ class Filters extends BaseApi { self::checkAllowedScope(self::SCOPE_WRITE); - ApiResponse::unsupported(Router::POST); + DI::apiResponse()->unsupported(Router::POST); } /** diff --git a/src/Module/Api/Mastodon/Lists/Accounts.php b/src/Module/Api/Mastodon/Lists/Accounts.php index e1de45b64d..b83f4903a9 100644 --- a/src/Module/Api/Mastodon/Lists/Accounts.php +++ b/src/Module/Api/Mastodon/Lists/Accounts.php @@ -37,12 +37,12 @@ class Accounts extends BaseApi { public static function delete(array $parameters = []) { - ApiResponse::unsupported(Router::DELETE); + DI::apiResponse()->unsupported(Router::DELETE); } public static function post(array $parameters = []) { - ApiResponse::unsupported(Router::POST); + DI::apiResponse()->unsupported(Router::POST); } /** diff --git a/src/Module/Api/Mastodon/Markers.php b/src/Module/Api/Mastodon/Markers.php index a45611c2dc..394d508d77 100644 --- a/src/Module/Api/Mastodon/Markers.php +++ b/src/Module/Api/Mastodon/Markers.php @@ -23,7 +23,7 @@ namespace Friendica\Module\Api\Mastodon; use Friendica\App\Router; use Friendica\Core\System; -use Friendica\Module\Api\ApiResponse; +use Friendica\DI; use Friendica\Module\BaseApi; /** @@ -35,7 +35,7 @@ class Markers extends BaseApi { self::checkAllowedScope(self::SCOPE_WRITE); - ApiResponse::unsupported(Router::POST); + DI::apiResponse()->unsupported(Router::POST); } /** diff --git a/src/Module/Api/Mastodon/ScheduledStatuses.php b/src/Module/Api/Mastodon/ScheduledStatuses.php index 9f3e53c046..82be0d6e7b 100644 --- a/src/Module/Api/Mastodon/ScheduledStatuses.php +++ b/src/Module/Api/Mastodon/ScheduledStatuses.php @@ -39,7 +39,7 @@ class ScheduledStatuses extends BaseApi self::checkAllowedScope(self::SCOPE_WRITE); $uid = self::getCurrentUserID(); - ApiResponse::unsupported(Router::PUT); + DI::apiResponse()->unsupported(Router::PUT); } public static function delete(array $parameters = []) diff --git a/src/Module/Api/Mastodon/Unimplemented.php b/src/Module/Api/Mastodon/Unimplemented.php index d0b32b9974..6a0a100c31 100644 --- a/src/Module/Api/Mastodon/Unimplemented.php +++ b/src/Module/Api/Mastodon/Unimplemented.php @@ -22,7 +22,7 @@ namespace Friendica\Module\Api\Mastodon; use Friendica\App\Router; -use Friendica\Module\Api\ApiResponse; +use Friendica\DI; use Friendica\Module\BaseApi; /** @@ -36,7 +36,7 @@ class Unimplemented extends BaseApi */ public static function delete(array $parameters = []) { - ApiResponse::unsupported(Router::DELETE); + DI::apiResponse()->unsupported(Router::DELETE); } /** @@ -45,7 +45,7 @@ class Unimplemented extends BaseApi */ public static function patch(array $parameters = []) { - ApiResponse::unsupported(Router::PATCH); + DI::apiResponse()->unsupported(Router::PATCH); } /** @@ -54,7 +54,7 @@ class Unimplemented extends BaseApi */ public static function post(array $parameters = []) { - ApiResponse::unsupported(Router::POST); + DI::apiResponse()->unsupported(Router::POST); } /** @@ -63,7 +63,7 @@ class Unimplemented extends BaseApi */ public static function put(array $parameters = []) { - ApiResponse::unsupported(Router::PUT); + DI::apiResponse()->unsupported(Router::PUT); } /** @@ -72,6 +72,6 @@ class Unimplemented extends BaseApi */ public static function rawContent(array $parameters = []) { - ApiResponse::unsupported(Router::GET); + DI::apiResponse()->unsupported(Router::GET); } } From a9ddd6687bfc8e50c7fd2d3ff0bf7cd9cbd72ef1 Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 12 Nov 2021 20:08:30 +0100 Subject: [PATCH 07/22] Replace Logger:: with logger property --- src/Module/Api/ApiResponse.php | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/Module/Api/ApiResponse.php b/src/Module/Api/ApiResponse.php index 5f7e4e51fb..ed3b446d0c 100644 --- a/src/Module/Api/ApiResponse.php +++ b/src/Module/Api/ApiResponse.php @@ -4,12 +4,12 @@ namespace Friendica\Module\Api; use Friendica\App\Arguments; use Friendica\Core\L10n; -use Friendica\Core\Logger; use Friendica\Core\System; use Friendica\Object\Api\Mastodon\Error; use Friendica\Util\Arrays; use Friendica\Util\HTTPInputData; use Friendica\Util\XML; +use Psr\Log\LoggerInterface; /** * This class is used to format and return API responses @@ -20,15 +20,19 @@ class ApiResponse protected $l10n; /** @var Arguments */ protected $args; + /** @var LoggerInterface */ + protected $logger; /** - * @param L10n $l10n - * @param Arguments $args + * @param L10n $l10n + * @param Arguments $args + * @param LoggerInterface $logger */ - public function __construct(L10n $l10n, Arguments $args) + public function __construct(L10n $l10n, Arguments $args, LoggerInterface $logger) { - $this->l10n = $l10n; - $this->args = $args; + $this->l10n = $l10n; + $this->args = $args; + $this->logger = $logger; } /** @@ -201,7 +205,7 @@ class ApiResponse public function unsupported(string $method = 'all') { $path = $this->args->getQueryString(); - Logger::info('Unimplemented API call', + $this->logger->info('Unimplemented API call', [ 'method' => $method, 'path' => $path, From a0c5c918866db7707a91f4434b446e78313877b5 Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 12 Nov 2021 20:13:04 +0100 Subject: [PATCH 08/22] Simplify code --- src/Module/Api/ApiResponse.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Module/Api/ApiResponse.php b/src/Module/Api/ApiResponse.php index ed3b446d0c..82801f2e60 100644 --- a/src/Module/Api/ApiResponse.php +++ b/src/Module/Api/ApiResponse.php @@ -96,14 +96,11 @@ class ApiResponse case 'atom': case 'rss': case 'xml': - $ret = $this->createXML($data, $root_element); - break; + return $this->createXML($data, $root_element); case 'json': default: - $ret = $data; - break; + return $data; } - return $ret; } /** From e477cf215dace8f84c856952d865df28a182c83e Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 12 Nov 2021 21:08:36 +0100 Subject: [PATCH 09/22] Make API testable & move PhotoAlbum tests to new destination --- src/Module/Api/Friendica/Photo/Delete.php | 2 +- .../Api/Friendica/Photoalbum/Update.php | 4 +- src/Security/Authentication.php | 14 ++- tests/FixtureTest.php | 2 +- tests/Util/AuthenticationDouble.php | 13 +++ tests/Util/authtest/authtest.php | 21 +++++ tests/legacy/ApiTest.php | 91 ------------------- tests/src/Module/Api/ApiTest.php | 58 ++++++++++++ .../Module/Api/Friendica/Photo/DeleteTest.php | 27 ++++++ .../Module/Api/Friendica/Photo/UpdateTest.php | 38 ++++++++ 10 files changed, 174 insertions(+), 96 deletions(-) create mode 100644 tests/Util/AuthenticationDouble.php create mode 100644 tests/Util/authtest/authtest.php create mode 100644 tests/src/Module/Api/ApiTest.php create mode 100644 tests/src/Module/Api/Friendica/Photo/DeleteTest.php create mode 100644 tests/src/Module/Api/Friendica/Photo/UpdateTest.php diff --git a/src/Module/Api/Friendica/Photo/Delete.php b/src/Module/Api/Friendica/Photo/Delete.php index 13ea7ebe7a..cf287d3d33 100644 --- a/src/Module/Api/Friendica/Photo/Delete.php +++ b/src/Module/Api/Friendica/Photo/Delete.php @@ -44,7 +44,7 @@ class Delete extends BaseApi // do several checks on input parameters // we do not allow calls without photo id - if ($request['photo_id'] == null) { + if (empty($request['photo_id'])) { throw new BadRequestException("no photo_id specified"); } diff --git a/src/Module/Api/Friendica/Photoalbum/Update.php b/src/Module/Api/Friendica/Photoalbum/Update.php index 9b75596fa7..369d33e825 100644 --- a/src/Module/Api/Friendica/Photoalbum/Update.php +++ b/src/Module/Api/Friendica/Photoalbum/Update.php @@ -43,10 +43,10 @@ class Update extends BaseApi ]); // we do not allow calls without album string - if ($request['album'] == "") { + if (empty($request['album'])) { throw new BadRequestException("no albumname specified"); } - if ($request['album_new'] == "") { + if (empty($request['album_new'])) { throw new BadRequestException("no new albumname specified"); } // check if album is existing diff --git a/src/Security/Authentication.php b/src/Security/Authentication.php index b570af7802..0b2fc9f9cf 100644 --- a/src/Security/Authentication.php +++ b/src/Security/Authentication.php @@ -65,6 +65,18 @@ class Authentication /** @var IManagePersonalConfigValues */ private $pConfig; + /** + * Sets the X-Account-Management-Status header + * + * mainly extracted to make it overridable for tests + * + * @param array $user_record + */ + protected function setXAccMgmtStatusHeader(array $user_record) + { + header('X-Account-Management-Status: active; name="' . $user_record['username'] . '"; id="' . $user_record['nickname'] . '"'); + } + /** * Authentication constructor. * @@ -314,7 +326,7 @@ class Authentication $this->session->set('cid', $contact['id']); } - header('X-Account-Management-Status: active; name="' . $user_record['username'] . '"; id="' . $user_record['nickname'] . '"'); + $this->setXAccMgmtStatusHeader($user_record); if ($login_initial || $login_refresh) { $this->dba->update('user', ['login_date' => DateTimeFormat::utcNow()], ['uid' => $user_record['uid']]); diff --git a/tests/FixtureTest.php b/tests/FixtureTest.php index 17e606a9e6..17760c85d4 100644 --- a/tests/FixtureTest.php +++ b/tests/FixtureTest.php @@ -26,7 +26,7 @@ abstract class FixtureTest extends DatabaseTest /** * Create variables used by tests. */ - protected function setUp() : void + protected function setUp(): void { parent::setUp(); diff --git a/tests/Util/AuthenticationDouble.php b/tests/Util/AuthenticationDouble.php new file mode 100644 index 0000000000..c2969394f4 --- /dev/null +++ b/tests/Util/AuthenticationDouble.php @@ -0,0 +1,13 @@ + + */ + +use Friendica\Core\Hook; +use Friendica\Model\User; + +function authtest_install() +{ + Hook::register('authenticate', 'tests/Util/authtest/authtest.php', 'authtest_authenticate'); +} + +function authtest_authenticate($a,&$b) +{ + $b['authenticated'] = 1; + $b['user_record'] = User::getById(42); +} diff --git a/tests/legacy/ApiTest.php b/tests/legacy/ApiTest.php index 6bf144463a..645c078a46 100644 --- a/tests/legacy/ApiTest.php +++ b/tests/legacy/ApiTest.php @@ -3178,97 +3178,6 @@ class ApiTest extends FixtureTest $this->markTestIncomplete('exit() kills phpunit as well'); } - /** - * Test the api_fr_photoalbum_delete() function. - * - * @return void - */ - public function testApiFrPhotoalbumDelete() - { - // $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class); - // api_fr_photoalbum_delete('json'); - } - - /** - * Test the api_fr_photoalbum_delete() function with an album name. - * - * @return void - */ - public function testApiFrPhotoalbumDeleteWithAlbum() - { - // $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class); - // $_REQUEST['album'] = 'album_name'; - // api_fr_photoalbum_delete('json'); - } - - /** - * Test the api_fr_photoalbum_delete() function with an album name. - * - * @return void - */ - public function testApiFrPhotoalbumDeleteWithValidAlbum() - { - $this->markTestIncomplete('We need to add a dataset for this.'); - } - - /** - * Test the api_fr_photoalbum_delete() function. - * - * @return void - */ - public function testApiFrPhotoalbumUpdate() - { - // $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class); - // api_fr_photoalbum_update('json'); - } - - /** - * Test the api_fr_photoalbum_delete() function with an album name. - * - * @return void - */ - public function testApiFrPhotoalbumUpdateWithAlbum() - { - // $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class); - // $_REQUEST['album'] = 'album_name'; - // api_fr_photoalbum_update('json'); - } - - /** - * Test the api_fr_photoalbum_delete() function with an album name. - * - * @return void - */ - public function testApiFrPhotoalbumUpdateWithAlbumAndNewAlbum() - { - // $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class); - // $_REQUEST['album'] = 'album_name'; - // $_REQUEST['album_new'] = 'album_name'; - // api_fr_photoalbum_update('json'); - } - - /** - * Test the api_fr_photoalbum_update() function without an authenticated user. - * - * @return void - */ - public function testApiFrPhotoalbumUpdateWithoutAuthenticatedUser() - { - // $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class); - // $_SESSION['authenticated'] = false; - // api_fr_photoalbum_update('json'); - } - - /** - * Test the api_fr_photoalbum_delete() function with an album name. - * - * @return void - */ - public function testApiFrPhotoalbumUpdateWithValidAlbum() - { - $this->markTestIncomplete('We need to add a dataset for this.'); - } - /** * Test the api_fr_photos_list() function. * diff --git a/tests/src/Module/Api/ApiTest.php b/tests/src/Module/Api/ApiTest.php new file mode 100644 index 0000000000..b2c38c31e6 --- /dev/null +++ b/tests/src/Module/Api/ApiTest.php @@ -0,0 +1,58 @@ +dice = $this->dice + ->addRule(Authentication::class, ['instanceOf' => AuthenticationDouble::class, 'shared' => true]); + DI::init($this->dice); + + $this->installAuthTest(); + } + + /** + * installs auththest. + * + * @throws \Exception + */ + public function installAuthTest() + { + $addon = 'authtest'; + $addon_file_path = __DIR__ . '/../../../Util/authtest/authtest.php'; + $t = @filemtime($addon_file_path); + + @include_once($addon_file_path); + if (function_exists($addon . '_install')) { + $func = $addon . '_install'; + $func(DI::app()); + } + + /** @var Database $dba */ + $dba = $this->dice->create(Database::class); + + $dba->insert('addon', [ + 'name' => $addon, + 'installed' => true, + 'timestamp' => $t, + 'plugin_admin' => function_exists($addon . '_addon_admin'), + 'hidden' => file_exists('addon/' . $addon . '/.hidden') + ]); + + Addon::loadAddons(); + Hook::loadHooks(); + } +} diff --git a/tests/src/Module/Api/Friendica/Photo/DeleteTest.php b/tests/src/Module/Api/Friendica/Photo/DeleteTest.php new file mode 100644 index 0000000000..69e9dbd314 --- /dev/null +++ b/tests/src/Module/Api/Friendica/Photo/DeleteTest.php @@ -0,0 +1,27 @@ + 'album_name']); + } + + public function testValid() + { + self::markTestIncomplete('We need to add a dataset for this.'); + } +} diff --git a/tests/src/Module/Api/Friendica/Photo/UpdateTest.php b/tests/src/Module/Api/Friendica/Photo/UpdateTest.php new file mode 100644 index 0000000000..f233998731 --- /dev/null +++ b/tests/src/Module/Api/Friendica/Photo/UpdateTest.php @@ -0,0 +1,38 @@ + 'album_name']); + } + + public function testWrongUpdate() + { + self::expectException(BadRequestException::class); + Update::rawContent(['album' => 'album_name', 'album_new' => 'album_name']); + } + + public function testUpdateWithoutAuthenticatedUser() + { + self::markTestIncomplete('Needs BasicAuth as dynamic method for overriding first'); + } + + public function testValid() + { + self::markTestIncomplete('We need to add a dataset for this.'); + } +} From f2ca21935e8c76b3e417efb6ddf5ebef7a8df292 Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 12 Nov 2021 21:12:00 +0100 Subject: [PATCH 10/22] Move API\Photo testcases --- tests/legacy/ApiTest.php | 45 ------------------- .../Module/Api/Friendica/Photo/DeleteTest.php | 11 +++-- .../Api/Friendica/Photoalbum/DeleteTest.php | 27 +++++++++++ .../{Photo => Photoalbum}/UpdateTest.php | 4 +- 4 files changed, 37 insertions(+), 50 deletions(-) create mode 100644 tests/src/Module/Api/Friendica/Photoalbum/DeleteTest.php rename tests/src/Module/Api/Friendica/{Photo => Photoalbum}/UpdateTest.php (88%) diff --git a/tests/legacy/ApiTest.php b/tests/legacy/ApiTest.php index 645c078a46..1a88e6403f 100644 --- a/tests/legacy/ApiTest.php +++ b/tests/legacy/ApiTest.php @@ -3254,51 +3254,6 @@ class ApiTest extends FixtureTest $this->markTestIncomplete(); } - /** - * Test the api_fr_photo_delete() function. - * - * @return void - */ - public function testApiFrPhotoDelete() - { - // $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class); - // api_fr_photo_delete('json'); - } - - /** - * Test the api_fr_photo_delete() function without an authenticated user. - * - * @return void - */ - public function testApiFrPhotoDeleteWithoutAuthenticatedUser() - { - // $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class); - // $_SESSION['authenticated'] = false; - // api_fr_photo_delete('json'); - } - - /** - * Test the api_fr_photo_delete() function with a photo ID. - * - * @return void - */ - public function testApiFrPhotoDeleteWithPhotoId() - { - // $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class); - // $_REQUEST['photo_id'] = 1; - // api_fr_photo_delete('json'); - } - - /** - * Test the api_fr_photo_delete() function with a correct photo ID. - * - * @return void - */ - public function testApiFrPhotoDeleteWithCorrectPhotoId() - { - $this->markTestIncomplete('We need to create a dataset for this.'); - } - /** * Test the api_fr_photo_detail() function. * diff --git a/tests/src/Module/Api/Friendica/Photo/DeleteTest.php b/tests/src/Module/Api/Friendica/Photo/DeleteTest.php index 69e9dbd314..a47c87e98a 100644 --- a/tests/src/Module/Api/Friendica/Photo/DeleteTest.php +++ b/tests/src/Module/Api/Friendica/Photo/DeleteTest.php @@ -2,7 +2,7 @@ namespace Friendica\Test\src\Module\Api\Friendica\Photo; -use Friendica\Module\Api\Friendica\Photoalbum\Delete; +use Friendica\Module\Api\Friendica\Photo\Delete; use Friendica\Network\HTTPException\BadRequestException; use Friendica\Test\src\Module\Api\ApiTest; @@ -14,13 +14,18 @@ class DeleteTest extends ApiTest Delete::rawContent(); } + public function testWithoutAuthenticatedUser() + { + self::markTestIncomplete('Needs BasicAuth as dynamic method for overriding first'); + } + public function testWrong() { self::expectException(BadRequestException::class); - Delete::rawContent(['album' => 'album_name']); + Delete::rawContent(['photo_id' => 1]); } - public function testValid() + public function testWithCorrectPhotoId() { self::markTestIncomplete('We need to add a dataset for this.'); } diff --git a/tests/src/Module/Api/Friendica/Photoalbum/DeleteTest.php b/tests/src/Module/Api/Friendica/Photoalbum/DeleteTest.php new file mode 100644 index 0000000000..ed9cd11578 --- /dev/null +++ b/tests/src/Module/Api/Friendica/Photoalbum/DeleteTest.php @@ -0,0 +1,27 @@ + 'album_name']); + } + + public function testValid() + { + self::markTestIncomplete('We need to add a dataset for this.'); + } +} diff --git a/tests/src/Module/Api/Friendica/Photo/UpdateTest.php b/tests/src/Module/Api/Friendica/Photoalbum/UpdateTest.php similarity index 88% rename from tests/src/Module/Api/Friendica/Photo/UpdateTest.php rename to tests/src/Module/Api/Friendica/Photoalbum/UpdateTest.php index f233998731..93c1cdc866 100644 --- a/tests/src/Module/Api/Friendica/Photo/UpdateTest.php +++ b/tests/src/Module/Api/Friendica/Photoalbum/UpdateTest.php @@ -1,6 +1,6 @@ 'album_name', 'album_new' => 'album_name']); } - public function testUpdateWithoutAuthenticatedUser() + public function testWithoutAuthenticatedUser() { self::markTestIncomplete('Needs BasicAuth as dynamic method for overriding first'); } From 6725f05ab203ea6a1425f7b023dc61b017da1ee2 Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 12 Nov 2021 21:35:21 +0100 Subject: [PATCH 11/22] Moved API\Notification tests --- src/Module/Api/ApiResponse.php | 36 ++++++++-- tests/Util/ApiResponseDouble.php | 54 ++++++++++++++ tests/legacy/ApiTest.php | 71 ------------------- tests/src/Module/Api/ApiTest.php | 12 +++- .../Module/Api/Friendica/NotificationTest.php | 60 ++++++++++++++++ .../Module/Api/Friendica/Photo/DeleteTest.php | 4 +- .../Api/Friendica/Photoalbum/DeleteTest.php | 4 +- .../Api/Friendica/Photoalbum/UpdateTest.php | 6 +- 8 files changed, 161 insertions(+), 86 deletions(-) create mode 100644 tests/Util/ApiResponseDouble.php create mode 100644 tests/src/Module/Api/Friendica/NotificationTest.php diff --git a/src/Module/Api/ApiResponse.php b/src/Module/Api/ApiResponse.php index 82801f2e60..d0d03da994 100644 --- a/src/Module/Api/ApiResponse.php +++ b/src/Module/Api/ApiResponse.php @@ -35,6 +35,29 @@ class ApiResponse $this->logger = $logger; } + /** + * Sets header directly + * mainly used to override it for tests + * + * @param string $header + */ + protected function setHeader(string $header) + { + header($header); + } + + /** + * Prints output directly to the caller + * mainly used to override it for tests + * + * @param string $output + */ + protected function printOutput(string $output) + { + echo $output; + exit; + } + /** * Creates the XML from a JSON style array * @@ -143,7 +166,7 @@ class ApiResponse 'request' => $this->args->getQueryString() ]; - header(($_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.1') . ' ' . $code . ' ' . $description); + $this->setHeader(($_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.1') . ' ' . $code . ' ' . $description); $this->exit('status', ['status' => $error], $format); } @@ -165,10 +188,10 @@ class ApiResponse switch ($format) { case 'xml': - header('Content-Type: text/xml'); + $this->setHeader('Content-Type: text/xml'); break; case 'json': - header('Content-Type: application/json'); + $this->setHeader('Content-Type: application/json'); if (!empty($return)) { $json = json_encode(end($return)); if (!empty($_GET['callback'])) { @@ -178,17 +201,16 @@ class ApiResponse } break; case 'rss': - header('Content-Type: application/rss+xml'); + $this->setHeader('Content-Type: application/rss+xml'); $return = '' . "\n" . $return; break; case 'atom': - header('Content-Type: application/atom+xml'); + $this->setHeader('Content-Type: application/atom+xml'); $return = '' . "\n" . $return; break; } - echo $return; - exit; + $this->printOutput($return); } /** diff --git a/tests/Util/ApiResponseDouble.php b/tests/Util/ApiResponseDouble.php new file mode 100644 index 0000000000..c931f2bec4 --- /dev/null +++ b/tests/Util/ApiResponseDouble.php @@ -0,0 +1,54 @@ +markTestIncomplete(); } - /** - * Test the api_friendica_notification() function. - * - * @return void - */ - public function testApiFriendicaNotification() - { - // $this->expectException(\Friendica\Network\HTTPException\BadRequestException::class); - // api_friendica_notification('json'); - } - - /** - * Test the api_friendica_notification() function without an authenticated user. - * - * @return void - */ - public function testApiFriendicaNotificationWithoutAuthenticatedUser() - { - // $this->expectException(\Friendica\Network\HTTPException\ForbiddenException::class); - // $_SESSION['authenticated'] = false; - // api_friendica_notification('json'); - } - - /** - * Test the api_friendica_notification() function with empty result - * - * @return void - */ - public function testApiFriendicaNotificationWithEmptyResult() - { - // DI::args()->setArgv(['api', 'friendica', 'notification']); - // $_SESSION['uid'] = 41; - // $result = api_friendica_notification('json'); - // self::assertEquals(['note' => false], $result); - } - - /** - * Test the api_friendica_notification() function with an XML result. - * - * @return void - */ - public function testApiFriendicaNotificationWithXmlResult() - { - /* - DI::args()->setArgv(['api', 'friendica', 'notification']); - $result = api_friendica_notification('xml'); - $date = DateTimeFormat::local('2020-01-01 12:12:02'); - $dateRel = Temporal::getRelativeDate('2020-01-01 07:12:02'); - - $assertXml=<< - - - -XML; - self::assertXmlStringEqualsXmlString($assertXml, $result); - */ - } - - /** - * Test the api_friendica_notification() function with an JSON result. - * - * @return void - */ - public function testApiFriendicaNotificationWithJsonResult() - { - // DI::args()->setArgv(['api', 'friendica', 'notification']); - // $result = json_encode(api_friendica_notification('json')); - // self::assertJson($result); - } - /** * Test the api_friendica_notification_seen() function. * diff --git a/tests/src/Module/Api/ApiTest.php b/tests/src/Module/Api/ApiTest.php index b2c38c31e6..95d04041f9 100644 --- a/tests/src/Module/Api/ApiTest.php +++ b/tests/src/Module/Api/ApiTest.php @@ -7,8 +7,10 @@ use Friendica\Core\Addon; use Friendica\Core\Hook; use Friendica\Database\Database; use Friendica\DI; +use Friendica\Module\Api\ApiResponse; use Friendica\Security\Authentication; use Friendica\Test\FixtureTest; +use Friendica\Test\Util\ApiResponseDouble; use Friendica\Test\Util\AuthenticationDouble; class ApiTest extends FixtureTest @@ -18,12 +20,20 @@ class ApiTest extends FixtureTest parent::setUp(); // TODO: Change the autogenerated stub $this->dice = $this->dice - ->addRule(Authentication::class, ['instanceOf' => AuthenticationDouble::class, 'shared' => true]); + ->addRule(Authentication::class, ['instanceOf' => AuthenticationDouble::class, 'shared' => true]) + ->addRule(ApiResponse::class, ['instanceOf' => ApiResponseDouble::class, 'shared' => true]); DI::init($this->dice); $this->installAuthTest(); } + protected function tearDown(): void + { + ApiResponseDouble::reset(); + + parent::tearDown(); + } + /** * installs auththest. * diff --git a/tests/src/Module/Api/Friendica/NotificationTest.php b/tests/src/Module/Api/Friendica/NotificationTest.php new file mode 100644 index 0000000000..d9451d0bf9 --- /dev/null +++ b/tests/src/Module/Api/Friendica/NotificationTest.php @@ -0,0 +1,60 @@ +expectException(BadRequestException::class); + DI::session()->set('uid', ''); + + Notification::rawContent(); + } + + public function testWithoutAuthenticatedUser() + { + self::markTestIncomplete('Needs BasicAuth as dynamic method for overriding first'); + + $this->expectException(BadRequestException::class); + DI::session()->set('uid', 41); + + Notification::rawContent(); + } + + public function testWithXmlResult() + { + $date = DateTimeFormat::local('2020-01-01 12:12:02'); + $dateRel = Temporal::getRelativeDate('2020-01-01 07:12:02'); + + $assertXml = << + + + +XML; + + Notification::rawContent(['extension' => 'xml']); + + self::assertXmlStringEqualsXmlString($assertXml, ApiResponseDouble::getOutput()); + } + + public function testWithJsonResult() + { + Notification::rawContent(['parameter' => 'json']); + + $result = json_encode(ApiResponseDouble::getOutput()); + + self::assertJson($result); + } +} diff --git a/tests/src/Module/Api/Friendica/Photo/DeleteTest.php b/tests/src/Module/Api/Friendica/Photo/DeleteTest.php index a47c87e98a..5023cd6c16 100644 --- a/tests/src/Module/Api/Friendica/Photo/DeleteTest.php +++ b/tests/src/Module/Api/Friendica/Photo/DeleteTest.php @@ -10,7 +10,7 @@ class DeleteTest extends ApiTest { public function testEmpty() { - self::expectException(BadRequestException::class); + $this->expectException(BadRequestException::class); Delete::rawContent(); } @@ -21,7 +21,7 @@ class DeleteTest extends ApiTest public function testWrong() { - self::expectException(BadRequestException::class); + $this->expectException(BadRequestException::class); Delete::rawContent(['photo_id' => 1]); } diff --git a/tests/src/Module/Api/Friendica/Photoalbum/DeleteTest.php b/tests/src/Module/Api/Friendica/Photoalbum/DeleteTest.php index ed9cd11578..a8f07d5aa1 100644 --- a/tests/src/Module/Api/Friendica/Photoalbum/DeleteTest.php +++ b/tests/src/Module/Api/Friendica/Photoalbum/DeleteTest.php @@ -10,13 +10,13 @@ class DeleteTest extends ApiTest { public function testEmpty() { - self::expectException(BadRequestException::class); + $this->expectException(BadRequestException::class); Delete::rawContent(); } public function testWrong() { - self::expectException(BadRequestException::class); + $this->expectException(BadRequestException::class); Delete::rawContent(['album' => 'album_name']); } diff --git a/tests/src/Module/Api/Friendica/Photoalbum/UpdateTest.php b/tests/src/Module/Api/Friendica/Photoalbum/UpdateTest.php index 93c1cdc866..2e4de7a798 100644 --- a/tests/src/Module/Api/Friendica/Photoalbum/UpdateTest.php +++ b/tests/src/Module/Api/Friendica/Photoalbum/UpdateTest.php @@ -10,19 +10,19 @@ class UpdateTest extends ApiTest { public function testEmpty() { - self::expectException(BadRequestException::class); + $this->expectException(BadRequestException::class); Update::rawContent(); } public function testTooFewArgs() { - self::expectException(BadRequestException::class); + $this->expectException(BadRequestException::class); Update::rawContent(['album' => 'album_name']); } public function testWrongUpdate() { - self::expectException(BadRequestException::class); + $this->expectException(BadRequestException::class); Update::rawContent(['album' => 'album_name', 'album_new' => 'album_name']); } From 2c407a7323cea20e2f1e83f0b4a247d0181fed40 Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 12 Nov 2021 21:38:38 +0100 Subject: [PATCH 12/22] Small improvement --- src/Module/Api/Friendica/Activity.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Module/Api/Friendica/Activity.php b/src/Module/Api/Friendica/Activity.php index fa27876d3b..00228c0ccc 100644 --- a/src/Module/Api/Friendica/Activity.php +++ b/src/Module/Api/Friendica/Activity.php @@ -23,7 +23,6 @@ namespace Friendica\Module\Api\Friendica; use Friendica\DI; use Friendica\Model\Item; -use Friendica\Module\Api\ApiResponse; use Friendica\Module\BaseApi; /** From bfe925aabe8c02c8319f1c189d4b36b313948518 Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 12 Nov 2021 21:50:02 +0100 Subject: [PATCH 13/22] Make PHP-CS happy and add (c) header --- tests/Util/ApiResponseDouble.php | 19 ++++++++++++++++++ tests/Util/AuthenticationDouble.php | 19 ++++++++++++++++++ tests/src/Module/Api/ApiTest.php | 20 ++++++++++++++++++- .../Module/Api/Friendica/NotificationTest.php | 19 ++++++++++++++++++ .../Module/Api/Friendica/Photo/DeleteTest.php | 19 ++++++++++++++++++ .../Api/Friendica/Photoalbum/DeleteTest.php | 19 ++++++++++++++++++ .../Api/Friendica/Photoalbum/UpdateTest.php | 19 ++++++++++++++++++ .../Api/Twitter/ContactEndpointMock.php | 19 ++++++++++++++++++ .../Api/Twitter/ContactEndpointTest.php | 19 ++++++++++++++++++ 9 files changed, 171 insertions(+), 1 deletion(-) diff --git a/tests/Util/ApiResponseDouble.php b/tests/Util/ApiResponseDouble.php index c931f2bec4..cc1402c7a6 100644 --- a/tests/Util/ApiResponseDouble.php +++ b/tests/Util/ApiResponseDouble.php @@ -1,4 +1,23 @@ . + * + */ namespace Friendica\Test\Util; diff --git a/tests/Util/AuthenticationDouble.php b/tests/Util/AuthenticationDouble.php index c2969394f4..adc503d788 100644 --- a/tests/Util/AuthenticationDouble.php +++ b/tests/Util/AuthenticationDouble.php @@ -1,4 +1,23 @@ . + * + */ namespace Friendica\Test\Util; diff --git a/tests/src/Module/Api/ApiTest.php b/tests/src/Module/Api/ApiTest.php index 95d04041f9..23a109e6f8 100644 --- a/tests/src/Module/Api/ApiTest.php +++ b/tests/src/Module/Api/ApiTest.php @@ -1,8 +1,26 @@ . + * + */ namespace Friendica\Test\src\Module\Api; -use Dice\Dice; use Friendica\Core\Addon; use Friendica\Core\Hook; use Friendica\Database\Database; diff --git a/tests/src/Module/Api/Friendica/NotificationTest.php b/tests/src/Module/Api/Friendica/NotificationTest.php index d9451d0bf9..542ebad724 100644 --- a/tests/src/Module/Api/Friendica/NotificationTest.php +++ b/tests/src/Module/Api/Friendica/NotificationTest.php @@ -1,4 +1,23 @@ . + * + */ namespace Friendica\Test\src\Module\Api\Friendica; diff --git a/tests/src/Module/Api/Friendica/Photo/DeleteTest.php b/tests/src/Module/Api/Friendica/Photo/DeleteTest.php index 5023cd6c16..3fd1d92f72 100644 --- a/tests/src/Module/Api/Friendica/Photo/DeleteTest.php +++ b/tests/src/Module/Api/Friendica/Photo/DeleteTest.php @@ -1,4 +1,23 @@ . + * + */ namespace Friendica\Test\src\Module\Api\Friendica\Photo; diff --git a/tests/src/Module/Api/Friendica/Photoalbum/DeleteTest.php b/tests/src/Module/Api/Friendica/Photoalbum/DeleteTest.php index a8f07d5aa1..f99e61bd1b 100644 --- a/tests/src/Module/Api/Friendica/Photoalbum/DeleteTest.php +++ b/tests/src/Module/Api/Friendica/Photoalbum/DeleteTest.php @@ -1,4 +1,23 @@ . + * + */ namespace Friendica\Test\src\Module\Api\Friendica\Photoalbum; diff --git a/tests/src/Module/Api/Friendica/Photoalbum/UpdateTest.php b/tests/src/Module/Api/Friendica/Photoalbum/UpdateTest.php index 2e4de7a798..b07d4c5bcf 100644 --- a/tests/src/Module/Api/Friendica/Photoalbum/UpdateTest.php +++ b/tests/src/Module/Api/Friendica/Photoalbum/UpdateTest.php @@ -1,4 +1,23 @@ . + * + */ namespace Friendica\Test\src\Module\Api\Friendica\Photoalbum; diff --git a/tests/src/Module/Api/Twitter/ContactEndpointMock.php b/tests/src/Module/Api/Twitter/ContactEndpointMock.php index 84c6ce68c1..c566668436 100644 --- a/tests/src/Module/Api/Twitter/ContactEndpointMock.php +++ b/tests/src/Module/Api/Twitter/ContactEndpointMock.php @@ -1,4 +1,23 @@ . + * + */ namespace Friendica\Test\src\Module\Api\Twitter; diff --git a/tests/src/Module/Api/Twitter/ContactEndpointTest.php b/tests/src/Module/Api/Twitter/ContactEndpointTest.php index d9506a60ec..1f309a1260 100644 --- a/tests/src/Module/Api/Twitter/ContactEndpointTest.php +++ b/tests/src/Module/Api/Twitter/ContactEndpointTest.php @@ -1,4 +1,23 @@ . + * + */ namespace Friendica\Test\src\Module\Api\Twitter; From 9482ef3c344c5e4899d7dbf3f9e850b76f513474 Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 12 Nov 2021 21:55:02 +0100 Subject: [PATCH 14/22] Update messages.po --- view/lang/C/messages.po | 50 ++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/view/lang/C/messages.po b/view/lang/C/messages.po index c7faaf2a82..70e7982135 100644 --- a/view/lang/C/messages.po +++ b/view/lang/C/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 2021.12-dev\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-08 07:28+0000\n" +"POT-Creation-Date: 2021-11-12 21:54+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -18,21 +18,21 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" -#: include/api.php:1114 src/Module/BaseApi.php:294 +#: include/api.php:860 src/Module/BaseApi.php:260 #, php-format msgid "Daily posting limit of %d post reached. The post was rejected." msgid_plural "Daily posting limit of %d posts reached. The post was rejected." msgstr[0] "" msgstr[1] "" -#: include/api.php:1128 src/Module/BaseApi.php:310 +#: include/api.php:874 src/Module/BaseApi.php:276 #, php-format msgid "Weekly posting limit of %d post reached. The post was rejected." msgid_plural "Weekly posting limit of %d posts reached. The post was rejected." msgstr[0] "" msgstr[1] "" -#: include/api.php:1142 src/Module/BaseApi.php:326 +#: include/api.php:888 src/Module/BaseApi.php:292 #, php-format msgid "Monthly posting limit of %d post reached. The post was rejected." msgstr "" @@ -145,9 +145,9 @@ msgstr "" #: mod/unfollow.php:50 mod/unfollow.php:82 mod/wall_attach.php:68 #: mod/wall_attach.php:71 mod/wall_upload.php:90 mod/wall_upload.php:93 #: mod/wallmessage.php:36 mod/wallmessage.php:55 mod/wallmessage.php:89 -#: mod/wallmessage.php:109 src/Module/Attach.php:55 src/Module/BaseApi.php:79 -#: src/Module/BaseApi.php:88 src/Module/BaseApi.php:97 -#: src/Module/BaseApi.php:106 src/Module/BaseNotifications.php:88 +#: mod/wallmessage.php:109 src/Module/Attach.php:55 src/Module/BaseApi.php:61 +#: src/Module/BaseApi.php:70 src/Module/BaseApi.php:79 +#: src/Module/BaseApi.php:88 src/Module/BaseNotifications.php:88 #: src/Module/Contact.php:328 src/Module/Contact/Advanced.php:44 #: src/Module/Delegation.php:118 src/Module/FollowConfirm.php:17 #: src/Module/FriendSuggest.php:44 src/Module/Group.php:44 @@ -4473,13 +4473,13 @@ msgstr "" msgid "Invalid OpenID url" msgstr "" -#: src/Model/User.php:942 src/Security/Authentication.php:223 +#: src/Model/User.php:942 src/Security/Authentication.php:235 msgid "" "We encountered a problem while logging in with the OpenID you provided. " "Please check the correct spelling of the ID." msgstr "" -#: src/Model/User.php:942 src/Security/Authentication.php:223 +#: src/Model/User.php:942 src/Security/Authentication.php:235 msgid "The error message was:" msgstr "" @@ -6798,6 +6798,16 @@ msgstr "" msgid "Deny" msgstr "" +#: src/Module/Api/ApiResponse.php:234 +#, php-format +msgid "API endpoint %s %s is not implemented" +msgstr "" + +#: src/Module/Api/ApiResponse.php:235 +msgid "" +"The API endpoint is currently not implemented but might be in the future." +msgstr "" + #: src/Module/Api/Mastodon/Apps.php:58 msgid "Missing parameters" msgstr "" @@ -6940,18 +6950,8 @@ msgstr "" msgid "User registrations waiting for confirmation" msgstr "" -#: src/Module/BaseApi.php:120 -#, php-format -msgid "API endpoint %s %s is not implemented" -msgstr "" - -#: src/Module/BaseApi.php:121 -msgid "" -"The API endpoint is currently not implemented but might be in the future." -msgstr "" - -#: src/Module/BaseApi.php:293 src/Module/BaseApi.php:309 -#: src/Module/BaseApi.php:325 +#: src/Module/BaseApi.php:259 src/Module/BaseApi.php:275 +#: src/Module/BaseApi.php:291 msgid "Too Many Requests" msgstr "" @@ -10585,20 +10585,20 @@ msgstr "" msgid "The folder view/smarty3/ must be writable by webserver." msgstr "" -#: src/Security/Authentication.php:209 +#: src/Security/Authentication.php:221 msgid "Login failed." msgstr "" -#: src/Security/Authentication.php:250 +#: src/Security/Authentication.php:262 msgid "Login failed. Please check your credentials." msgstr "" -#: src/Security/Authentication.php:348 +#: src/Security/Authentication.php:360 #, php-format msgid "Welcome %s" msgstr "" -#: src/Security/Authentication.php:349 +#: src/Security/Authentication.php:361 msgid "Please upload a profile photo." msgstr "" From 0757c00d52c8fb7113c18da77451027563a46214 Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 12 Nov 2021 22:03:41 +0100 Subject: [PATCH 15/22] Move Api\Help --- tests/legacy/ApiTest.php | 24 ------------------- tests/src/Module/Api/ApiTest.php | 15 ++++++++++++ .../Module/Api/GnuSocial/Help/TestTest.php | 24 +++++++++++++++++++ 3 files changed, 39 insertions(+), 24 deletions(-) create mode 100644 tests/src/Module/Api/GnuSocial/Help/TestTest.php diff --git a/tests/legacy/ApiTest.php b/tests/legacy/ApiTest.php index 0c1af085ca..800bc772e4 100644 --- a/tests/legacy/ApiTest.php +++ b/tests/legacy/ApiTest.php @@ -2567,30 +2567,6 @@ class ApiTest extends FixtureTest // self::assertXml($result, 'hash'); } - /** - * Test the api_help_test() function. - * - * @return void - */ - public function testApiHelpTest() - { - // @todo How to test the new API? - // $result = \Friendica\Module\Api\Friendica\Help\Test::rawcontent(['extension' => 'json']); - // self::assertEquals(['ok' => 'ok'], $result); - } - - /** - * Test the api_help_test() function with an XML result. - * - * @return void - */ - public function testApiHelpTestWithXml() - { - // @todo How to test the new API? - // $result = api_help_test('xml'); - // self::assertXml($result, 'ok'); - } - /** * Test the api_lists_list() function. * diff --git a/tests/src/Module/Api/ApiTest.php b/tests/src/Module/Api/ApiTest.php index 23a109e6f8..58bbb5c388 100644 --- a/tests/src/Module/Api/ApiTest.php +++ b/tests/src/Module/Api/ApiTest.php @@ -33,6 +33,21 @@ use Friendica\Test\Util\AuthenticationDouble; class ApiTest extends FixtureTest { + /** + * Assert that the string is XML and contain the root element. + * + * @param string $result XML string + * @param string $root_element Root element name + * + * @return void + */ + protected function assertXml(string $result = '', string $root_element = '') + { + self::assertStringStartsWith('', $result); + self::assertStringContainsString('<' . $root_element, $result); + // We could probably do more checks here. + } + protected function setUp(): void { parent::setUp(); // TODO: Change the autogenerated stub diff --git a/tests/src/Module/Api/GnuSocial/Help/TestTest.php b/tests/src/Module/Api/GnuSocial/Help/TestTest.php new file mode 100644 index 0000000000..c962cac302 --- /dev/null +++ b/tests/src/Module/Api/GnuSocial/Help/TestTest.php @@ -0,0 +1,24 @@ + 'json']); + + self::assertEquals('"ok"', ApiResponseDouble::getOutput()); + } + + public function testXml() + { + Test::rawContent(['extension' => 'xml']); + + self::assertxml(ApiResponseDouble::getOutput(), 'ok'); + } +} From 829c43ba3b29af74bf4cf23f30cc80b9f71b7c64 Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 12 Nov 2021 22:09:03 +0100 Subject: [PATCH 16/22] Migrate Api\RateLimitStatus --- tests/legacy/ApiTest.php | 26 ----------------- .../Twitter/Account/RateLimitStatusTest.php | 28 +++++++++++++++++++ 2 files changed, 28 insertions(+), 26 deletions(-) create mode 100644 tests/src/Module/Api/Twitter/Account/RateLimitStatusTest.php diff --git a/tests/legacy/ApiTest.php b/tests/legacy/ApiTest.php index 800bc772e4..3bf14a31bc 100644 --- a/tests/legacy/ApiTest.php +++ b/tests/legacy/ApiTest.php @@ -2541,32 +2541,6 @@ class ApiTest extends FixtureTest } } - /** - * Test the api_format_items() function. - * - * @return void - */ - public function testApiAccountRateLimitStatus() - { - // @todo How to test the new API? - // $result = api_account_rate_limit_status('json'); - // self::assertEquals(150, $result['hash']['remaining_hits']); - // self::assertEquals(150, $result['hash']['hourly_limit']); - // self::assertIsInt($result['hash']['reset_time_in_seconds']); - } - - /** - * Test the api_format_items() function with an XML result. - * - * @return void - */ - public function testApiAccountRateLimitStatusWithXml() - { - // @todo How to test the new API? - // $result = api_account_rate_limit_status('xml'); - // self::assertXml($result, 'hash'); - } - /** * Test the api_lists_list() function. * diff --git a/tests/src/Module/Api/Twitter/Account/RateLimitStatusTest.php b/tests/src/Module/Api/Twitter/Account/RateLimitStatusTest.php new file mode 100644 index 0000000000..46088d330f --- /dev/null +++ b/tests/src/Module/Api/Twitter/Account/RateLimitStatusTest.php @@ -0,0 +1,28 @@ + 'json']); + + $result = json_decode(ApiResponseDouble::getOutput()); + + self::assertEquals(150, $result->remaining_hits); + self::assertEquals(150, $result->hourly_limit); + self::assertIsInt($result->reset_time_in_seconds); + } + + public function testWithXml() + { + RateLimitStatus::rawContent(['extension' => 'xml']); + + self::assertXml(ApiResponseDouble::getOutput(), 'hash'); + } +} From de1e839a2b85ac1c04b371f343b6c26a263557b6 Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 12 Nov 2021 22:12:28 +0100 Subject: [PATCH 17/22] Migrate API\StatusNetVersion --- tests/legacy/ApiTest.php | 12 ------------ .../Api/GnuSocial/GnuSocial/VersionTest.php | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 12 deletions(-) create mode 100644 tests/src/Module/Api/GnuSocial/GnuSocial/VersionTest.php diff --git a/tests/legacy/ApiTest.php b/tests/legacy/ApiTest.php index 3bf14a31bc..b51e0bb1b2 100644 --- a/tests/legacy/ApiTest.php +++ b/tests/legacy/ApiTest.php @@ -2792,18 +2792,6 @@ class ApiTest extends FixtureTest self::assertEquals(30, $result['config']['site']['shorturllength']); } - /** - * Test the api_statusnet_version() function. - * - * @return void - */ - public function testApiStatusnetVersion() - { - // @todo How to test the new API? - // $result = api_statusnet_version('json'); - // self::assertEquals('0.9.7', $result['version']); - } - /** * Test the api_direct_messages_new() function. * diff --git a/tests/src/Module/Api/GnuSocial/GnuSocial/VersionTest.php b/tests/src/Module/Api/GnuSocial/GnuSocial/VersionTest.php new file mode 100644 index 0000000000..454b8ef40d --- /dev/null +++ b/tests/src/Module/Api/GnuSocial/GnuSocial/VersionTest.php @@ -0,0 +1,19 @@ + 'json']); + + $result = json_decode(ApiResponseDouble::getOutput()); + + self::assertEquals('0.9.7', $result); + } +} From 23939cd0f1abb79a796f2fde390126845ebaf888 Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 12 Nov 2021 22:15:43 +0100 Subject: [PATCH 18/22] Mirate API\SavedSearches tests --- tests/legacy/ApiTest.php | 14 ------------ .../Module/Api/Twitter/SavedSearchesTest.php | 22 +++++++++++++++++++ 2 files changed, 22 insertions(+), 14 deletions(-) create mode 100644 tests/src/Module/Api/Twitter/SavedSearchesTest.php diff --git a/tests/legacy/ApiTest.php b/tests/legacy/ApiTest.php index b51e0bb1b2..9bcf2e1164 100644 --- a/tests/legacy/ApiTest.php +++ b/tests/legacy/ApiTest.php @@ -3532,18 +3532,4 @@ class ApiTest extends FixtureTest { $this->markTestIncomplete(); } - - /** - * Test the api_saved_searches_list() function. - * - * @return void - */ - public function testApiSavedSearchesList() - { - // $result = api_saved_searches_list('json'); - // self::assertEquals(1, $result['terms'][0]['id']); - // self::assertEquals(1, $result['terms'][0]['id_str']); - // self::assertEquals('Saved search', $result['terms'][0]['name']); - // self::assertEquals('Saved search', $result['terms'][0]['query']); - } } diff --git a/tests/src/Module/Api/Twitter/SavedSearchesTest.php b/tests/src/Module/Api/Twitter/SavedSearchesTest.php new file mode 100644 index 0000000000..f4dad04fc1 --- /dev/null +++ b/tests/src/Module/Api/Twitter/SavedSearchesTest.php @@ -0,0 +1,22 @@ + 'json']); + + $result = json_decode(ApiResponseDouble::getOutput()); + + self::assertEquals(1, $result[0]->id); + self::assertEquals(1, $result[0]->id_str); + self::assertEquals('Saved search', $result[0]->name); + self::assertEquals('Saved search', $result[0]->query); + } +} From 7797c3a0a813592e5991e55dff335d774abd5372 Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 12 Nov 2021 22:29:58 +0100 Subject: [PATCH 19/22] Migrate API\error tests and fix ApiResponse for RSS/atom --- src/Module/Api/ApiResponse.php | 2 - tests/legacy/ApiTest.php | 110 ----------------------- tests/src/Module/Api/ApiResponseTest.php | 93 +++++++++++++++++++ 3 files changed, 93 insertions(+), 112 deletions(-) create mode 100644 tests/src/Module/Api/ApiResponseTest.php diff --git a/src/Module/Api/ApiResponse.php b/src/Module/Api/ApiResponse.php index d0d03da994..c0ce7c756b 100644 --- a/src/Module/Api/ApiResponse.php +++ b/src/Module/Api/ApiResponse.php @@ -202,11 +202,9 @@ class ApiResponse break; case 'rss': $this->setHeader('Content-Type: application/rss+xml'); - $return = '' . "\n" . $return; break; case 'atom': $this->setHeader('Content-Type: application/atom+xml'); - $return = '' . "\n" . $return; break; } diff --git a/tests/legacy/ApiTest.php b/tests/legacy/ApiTest.php index 9bcf2e1164..73ea1b3327 100644 --- a/tests/legacy/ApiTest.php +++ b/tests/legacy/ApiTest.php @@ -622,30 +622,6 @@ class ApiTest extends FixtureTest ); } - /** - * Test the api_call() function with an unallowed method. - * - * @runInSeparateProcess - * @preserveGlobalState disabled - */ - public function testApiCallWithWrongMethod() - { - // Shouldn't be needed anymore due to the router? - /* - global $API; - $API['api_path'] = ['method' => 'method']; - - $_SERVER['QUERY_STRING'] = 'pagename=api_path'; - - $args = DI::args()->determine($_SERVER, $_GET); - - self::assertEquals( - '{"status":{"error":"Method Not Allowed","code":"405 Method Not Allowed","request":"api_path"}}', - api_call($this->app, $args) - ); - */ - } - /** * Test the api_call() function with an unauthorized user. * @@ -674,92 +650,6 @@ class ApiTest extends FixtureTest */ } - /** - * Test the api_error() function with a JSON result. - * - * @runInSeparateProcess - * @preserveGlobalState disabled - */ - public function testApiErrorWithJson() - { - // @todo How to test the new API? - // self::assertEquals( - // '{"status":{"error":"error_message","code":"200 OK","request":""}}', - // api_error('json', new HTTPException\OKException('error_message'), DI::args()) - // ); - } - - /** - * Test the api_error() function with an XML result. - * - * @runInSeparateProcess - * @preserveGlobalState disabled - */ - public function testApiErrorWithXml() - { - // @todo How to test the new API? - /* - self::assertEquals( - '' . "\n" . - '' . "\n" . - ' error_message' . "\n" . - ' 200 OK' . "\n" . - ' ' . "\n" . - '' . "\n", - api_error('xml', new HTTPException\OKException('error_message'), DI::args()) - ); - */ - } - - /** - * Test the api_error() function with an RSS result. - * - * @runInSeparateProcess - * @preserveGlobalState disabled - */ - public function testApiErrorWithRss() - { - // @todo How to test the new API? - /* - self::assertEquals( - '' . "\n" . - '' . "\n" . - ' error_message' . "\n" . - ' 200 OK' . "\n" . - ' ' . "\n" . - '' . "\n", - api_error('rss', new HTTPException\OKException('error_message'), DI::args()) - ); - */ - } - - /** - * Test the api_error() function with an Atom result. - * - * @runInSeparateProcess - * @preserveGlobalState disabled - */ - public function testApiErrorWithAtom() - { - // @todo How to test the new API? - /* - self::assertEquals( - '' . "\n" . - '' . "\n" . - ' error_message' . "\n" . - ' 200 OK' . "\n" . - ' ' . "\n" . - '' . "\n", - api_error('atom', new HTTPException\OKException('error_message'), DI::args()) - ); - */ - } /** * Test the api_rss_extra() function. diff --git a/tests/src/Module/Api/ApiResponseTest.php b/tests/src/Module/Api/ApiResponseTest.php new file mode 100644 index 0000000000..7499e9a35c --- /dev/null +++ b/tests/src/Module/Api/ApiResponseTest.php @@ -0,0 +1,93 @@ +shouldReceive('getQueryString')->andReturn(''); + + $response = new ApiResponseDouble($l10n, $args, new NullLogger()); + $response->error(200, 'OK', 'error_message', 'json'); + + self::assertEquals('{"error":"error_message","code":"200 OK","request":""}', ApiResponseDouble::getOutput()); + } + + public function testErrorWithXml() + { + $l10n = \Mockery::mock(L10n::class); + $args = \Mockery::mock(Arguments::class); + $args->shouldReceive('getQueryString')->andReturn(''); + + $response = new ApiResponseDouble($l10n, $args, new NullLogger()); + $response->error(200, 'OK', 'error_message', 'xml'); + + self::assertEquals('' . "\n" . + '' . "\n" . + ' error_message' . "\n" . + ' 200 OK' . "\n" . + ' ' . "\n" . + '' . "\n", + ApiResponseDouble::getOutput()); + } + + public function testErrorWithRss() + { + $l10n = \Mockery::mock(L10n::class); + $args = \Mockery::mock(Arguments::class); + $args->shouldReceive('getQueryString')->andReturn(''); + + $response = new ApiResponseDouble($l10n, $args, new NullLogger()); + $response->error(200, 'OK', 'error_message', 'rss'); + + self::assertEquals( + '' . "\n" . + '' . "\n" . + ' error_message' . "\n" . + ' 200 OK' . "\n" . + ' ' . "\n" . + '' . "\n", + ApiResponseDouble::getOutput()); + } + + public function testErrorWithAtom() + { + $l10n = \Mockery::mock(L10n::class); + $args = \Mockery::mock(Arguments::class); + $args->shouldReceive('getQueryString')->andReturn(''); + + $response = new ApiResponseDouble($l10n, $args, new NullLogger()); + $response->error(200, 'OK', 'error_message', 'atom'); + + self::assertEquals( + '' . "\n" . + '' . "\n" . + ' error_message' . "\n" . + ' 200 OK' . "\n" . + ' ' . "\n" . + '' . "\n", + ApiResponseDouble::getOutput()); + } +} From c0219fe2faf80f7d54e656cf09446d80ff8889dc Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 12 Nov 2021 22:30:48 +0100 Subject: [PATCH 20/22] class type --- tests/src/Module/Api/ApiTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/src/Module/Api/ApiTest.php b/tests/src/Module/Api/ApiTest.php index 58bbb5c388..e168c26555 100644 --- a/tests/src/Module/Api/ApiTest.php +++ b/tests/src/Module/Api/ApiTest.php @@ -31,7 +31,7 @@ use Friendica\Test\FixtureTest; use Friendica\Test\Util\ApiResponseDouble; use Friendica\Test\Util\AuthenticationDouble; -class ApiTest extends FixtureTest +abstract class ApiTest extends FixtureTest { /** * Assert that the string is XML and contain the root element. From e7f84d493489c4850cd766b83ee5457d777eb03e Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 12 Nov 2021 22:44:59 +0100 Subject: [PATCH 21/22] Move Api\unsupported tests and remove dependency to System::jsonExit() --- src/Module/Api/ApiResponse.php | 6 +-- tests/legacy/ApiTest.php | 46 ------------------- tests/src/Module/Api/ApiResponseTest.php | 15 ++++++ .../Module/Api/Friendica/NotificationTest.php | 4 ++ tests/src/Module/BaseApiTest.php | 31 +++++++++++++ 5 files changed, 52 insertions(+), 50 deletions(-) create mode 100644 tests/src/Module/BaseApiTest.php diff --git a/src/Module/Api/ApiResponse.php b/src/Module/Api/ApiResponse.php index c0ce7c756b..9521e2270a 100644 --- a/src/Module/Api/ApiResponse.php +++ b/src/Module/Api/ApiResponse.php @@ -4,8 +4,6 @@ namespace Friendica\Module\Api; use Friendica\App\Arguments; use Friendica\Core\L10n; -use Friendica\Core\System; -use Friendica\Object\Api\Mastodon\Error; use Friendica\Util\Arrays; use Friendica\Util\HTTPInputData; use Friendica\Util\XML; @@ -231,7 +229,7 @@ class ApiResponse ]); $error = $this->l10n->t('API endpoint %s %s is not implemented', strtoupper($method), $path); $error_description = $this->l10n->t('The API endpoint is currently not implemented but might be in the future.'); - $errorobj = new Error($error, $error_description); - System::jsonError(501, $errorobj->toArray()); + + $this->exit('error', ['error' => ['error' => $error, 'error_description' => $error_description]]); } } diff --git a/tests/legacy/ApiTest.php b/tests/legacy/ApiTest.php index 73ea1b3327..cf5b09f98c 100644 --- a/tests/legacy/ApiTest.php +++ b/tests/legacy/ApiTest.php @@ -499,23 +499,6 @@ class ApiTest extends FixtureTest */ } - /** - * Test the api_call() function with an unimplemented API. - * - * @runInSeparateProcess - * @preserveGlobalState disabled - */ - public function testApiCallWithUninplementedApi() - { - // @todo How to test the new API? - /* - self::assertEquals( - '{"status":{"error":"Not Found","code":"404 Not Found","request":""}}', - api_call($this->app) - ); - */ - } - /** * Test the api_call() function with a JSON result. * @@ -622,35 +605,6 @@ class ApiTest extends FixtureTest ); } - /** - * Test the api_call() function with an unauthorized user. - * - * @runInSeparateProcess - * @preserveGlobalState disabled - */ - public function testApiCallWithWrongAuth() - { - // @todo How to test the new API? - /* - global $API; - $API['api_path'] = [ - 'method' => 'method', - 'auth' => true - ]; - $_SESSION['authenticated'] = false; - $_SERVER['REQUEST_METHOD'] = 'method'; - $_SERVER['QUERY_STRING'] = 'pagename=api_path'; - - $args = DI::args()->determine($_SERVER, $_GET); - - self::assertEquals( - '{"status":{"error":"This API requires login","code":"401 Unauthorized","request":"api_path"}}', - api_call($this->app, $args) - ); - */ - } - - /** * Test the api_rss_extra() function. * diff --git a/tests/src/Module/Api/ApiResponseTest.php b/tests/src/Module/Api/ApiResponseTest.php index 7499e9a35c..b6f5826214 100644 --- a/tests/src/Module/Api/ApiResponseTest.php +++ b/tests/src/Module/Api/ApiResponseTest.php @@ -90,4 +90,19 @@ class ApiResponseTest extends MockedTest '' . "\n", ApiResponseDouble::getOutput()); } + + public function testUnsupported() + { + $l10n = \Mockery::mock(L10n::class); + $l10n->shouldReceive('t')->andReturnUsing(function ($args) { + return $args; + }); + $args = \Mockery::mock(Arguments::class); + $args->shouldReceive('getQueryString')->andReturn(''); + + $response = new ApiResponseDouble($l10n, $args, new NullLogger()); + $response->unsupported(); + + self::assertEquals('{"error":"API endpoint %s %s is not implemented","error_description":"The API endpoint is currently not implemented but might be in the future."}', ApiResponseDouble::getOutput()); + } } diff --git a/tests/src/Module/Api/Friendica/NotificationTest.php b/tests/src/Module/Api/Friendica/NotificationTest.php index 542ebad724..7a213e2a5b 100644 --- a/tests/src/Module/Api/Friendica/NotificationTest.php +++ b/tests/src/Module/Api/Friendica/NotificationTest.php @@ -35,20 +35,24 @@ class NotificationTest extends ApiTest { self::markTestIncomplete('Needs BasicAuth as dynamic method for overriding first'); + /* $this->expectException(BadRequestException::class); DI::session()->set('uid', ''); Notification::rawContent(); + */ } public function testWithoutAuthenticatedUser() { self::markTestIncomplete('Needs BasicAuth as dynamic method for overriding first'); + /* $this->expectException(BadRequestException::class); DI::session()->set('uid', 41); Notification::rawContent(); + */ } public function testWithXmlResult() diff --git a/tests/src/Module/BaseApiTest.php b/tests/src/Module/BaseApiTest.php new file mode 100644 index 0000000000..c985ade2a7 --- /dev/null +++ b/tests/src/Module/BaseApiTest.php @@ -0,0 +1,31 @@ + 'method', + 'auth' => true + ]; + $_SESSION['authenticated'] = false; + $_SERVER['REQUEST_METHOD'] = 'method'; + $_SERVER['QUERY_STRING'] = 'pagename=api_path'; + + $args = DI::args()->determine($_SERVER, $_GET); + + self::assertEquals( + '{"status":{"error":"This API requires login","code":"401 Unauthorized","request":"api_path"}}', + api_call($this->app, $args) + ); + */ + } +} From 6b7babd58f5ece97969e81d2ad21df1a60725bef Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 12 Nov 2021 22:46:18 +0100 Subject: [PATCH 22/22] Remove test for deprecated way of calling API methods --- tests/legacy/ApiTest.php | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/tests/legacy/ApiTest.php b/tests/legacy/ApiTest.php index cf5b09f98c..05ad39cf3f 100644 --- a/tests/legacy/ApiTest.php +++ b/tests/legacy/ApiTest.php @@ -470,35 +470,6 @@ class ApiTest extends FixtureTest ); } - /** - * Test the api_call() function without any result. - * - * @runInSeparateProcess - * @preserveGlobalState disabled - */ - public function testApiCallWithNoResult() - { - // @todo How to test the new API? - /* - global $API; - $API['api_path'] = [ - 'method' => 'method', - 'func' => function () { - return false; - } - ]; - $_SERVER['REQUEST_METHOD'] = 'method'; - $_SERVER['QUERY_STRING'] = 'pagename=api_path'; - - $args = DI::args()->determine($_SERVER, $_GET); - - self::assertEquals( - '{"status":{"error":"Internal Server Error","code":"500 Internal Server Error","request":"api_path"}}', - api_call($this->app, $args) - ); - */ - } - /** * Test the api_call() function with a JSON result. *