Merge pull request #10976 from nupplaphil/feat/api_tests
Regain API Testability
This commit is contained in:
commit
d5703e350c
42 changed files with 1130 additions and 759 deletions
114
include/api.php
114
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);
|
||||
DI::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 DI::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 DI::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 DI::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 DI::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 DI::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 DI::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 DI::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 DI::apiResponse()->formatData("statuses", $type, $data);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1540,7 +1541,7 @@ function api_statuses_public_timeline($type)
|
|||
break;
|
||||
}
|
||||
|
||||
return BaseApi::formatData("statuses", $type, $data);
|
||||
return DI::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 DI::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 DI::apiResponse()->formatData("statuses", $type, $data);
|
||||
} else {
|
||||
$data = ['status' => $ret[0]];
|
||||
return BaseApi::formatData("status", $type, $data);
|
||||
return DI::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 DI::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 DI::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 DI::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 DI::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 DI::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 DI::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 DI::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 DI::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 DI::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 DI::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 DI::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 DI::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 DI::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 DI::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 DI::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 DI::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 DI::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 DI::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 DI::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 DI::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 DI::apiResponse()->formatData("direct-messages", $type, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3726,7 +3728,7 @@ function api_fr_photos_list($type)
|
|||
}
|
||||
}
|
||||
}
|
||||
return BaseApi::formatData("photos", $type, $data);
|
||||
return DI::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 DI::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 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 BaseApi::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 BaseApi::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");
|
||||
}
|
||||
|
@ -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 DI::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 DI::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 DI::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 DI::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 DI::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 DI::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 DI::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 DI::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 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 BaseApi::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) {
|
||||
|
@ -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 DI::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 DI::apiResponse()->formatData("direct_message_search", $type, ['$result' => $success]);
|
||||
}
|
||||
|
||||
/// @TODO move to top of file or somewhere better
|
||||
|
|
|
@ -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
|
||||
//
|
||||
|
|
235
src/Module/Api/ApiResponse.php
Normal file
235
src/Module/Api/ApiResponse.php
Normal file
|
@ -0,0 +1,235 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Module\Api;
|
||||
|
||||
use Friendica\App\Arguments;
|
||||
use Friendica\Core\L10n;
|
||||
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
|
||||
*/
|
||||
class ApiResponse
|
||||
{
|
||||
/** @var L10n */
|
||||
protected $l10n;
|
||||
/** @var Arguments */
|
||||
protected $args;
|
||||
/** @var LoggerInterface */
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* @param L10n $l10n
|
||||
* @param Arguments $args
|
||||
* @param LoggerInterface $logger
|
||||
*/
|
||||
public function __construct(L10n $l10n, Arguments $args, LoggerInterface $logger)
|
||||
{
|
||||
$this->l10n = $l10n;
|
||||
$this->args = $args;
|
||||
$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
|
||||
*
|
||||
* @param array $data JSON style array
|
||||
* @param string $root_element Name of the root element
|
||||
*
|
||||
* @return string The XML data
|
||||
*/
|
||||
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'
|
||||
];
|
||||
|
||||
/// @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 function formatData(string $root_element, string $type, array $data)
|
||||
{
|
||||
switch ($type) {
|
||||
case 'atom':
|
||||
case 'rss':
|
||||
case 'xml':
|
||||
return $this->createXML($data, $root_element);
|
||||
case 'json':
|
||||
default:
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 function error(int $code, string $description, string $message, string $format = null)
|
||||
{
|
||||
$error = [
|
||||
'error' => $message ?: $description,
|
||||
'code' => $code . ' ' . $description,
|
||||
'request' => $this->args->getQueryString()
|
||||
];
|
||||
|
||||
$this->setHeader(($_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.1') . ' ' . $code . ' ' . $description);
|
||||
|
||||
$this->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 function exit(string $root_element, array $data, string $format = null)
|
||||
{
|
||||
$format = $format ?? 'json';
|
||||
|
||||
$return = $this->formatData($root_element, $format, $data);
|
||||
|
||||
switch ($format) {
|
||||
case 'xml':
|
||||
$this->setHeader('Content-Type: text/xml');
|
||||
break;
|
||||
case 'json':
|
||||
$this->setHeader('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':
|
||||
$this->setHeader('Content-Type: application/rss+xml');
|
||||
break;
|
||||
case 'atom':
|
||||
$this->setHeader('Content-Type: application/atom+xml');
|
||||
break;
|
||||
}
|
||||
|
||||
$this->printOutput($return);
|
||||
}
|
||||
|
||||
/**
|
||||
* Quit execution with the message that the endpoint isn't implemented
|
||||
*
|
||||
* @param string $method
|
||||
*
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function unsupported(string $method = 'all')
|
||||
{
|
||||
$path = $this->args->getQueryString();
|
||||
$this->logger->info('Unimplemented API call',
|
||||
[
|
||||
'method' => $method,
|
||||
'path' => $path,
|
||||
'agent' => $_SERVER['HTTP_USER_AGENT'] ?? '',
|
||||
'request' => HTTPInputData::process()
|
||||
]);
|
||||
$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.');
|
||||
|
||||
$this->exit('error', ['error' => ['error' => $error, 'error_description' => $error_description]]);
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
namespace Friendica\Module\Api\Friendica;
|
||||
|
||||
use Friendica\DI;
|
||||
use Friendica\Model\Item;
|
||||
use Friendica\Module\BaseApi;
|
||||
|
||||
|
@ -56,9 +57,9 @@ class Activity extends BaseApi
|
|||
} else {
|
||||
$ok = 'ok';
|
||||
}
|
||||
self::exit('ok', ['ok' => $ok], $parameters['extension'] ?? null);
|
||||
DI::apiResponse()->exit('ok', ['ok' => $ok], $parameters['extension'] ?? null);
|
||||
} else {
|
||||
self::error(500, 'Error adding activity', '', $parameters['extension'] ?? null);
|
||||
DI::apiResponse()->error(500, 'Error adding activity', '', $parameters['extension'] ?? null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
namespace Friendica\Module\Api\Friendica\DirectMessages;
|
||||
|
||||
use Friendica\Database\DBA;
|
||||
use Friendica\DI;
|
||||
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);
|
||||
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'];
|
||||
self::exit('direct_messages_setseen', ['$result' => $answer], $parameters['extension'] ?? null);
|
||||
DI::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);
|
||||
DI::apiResponse()->exit('direct_messages_setseen', ['$result' => $answer], $parameters['extension'] ?? null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,8 +23,8 @@ namespace Friendica\Module\Api\Friendica\Events;
|
|||
|
||||
use Friendica\Content\Text\BBCode;
|
||||
use Friendica\Database\DBA;
|
||||
use Friendica\DI;
|
||||
use Friendica\Module\BaseApi;
|
||||
use Friendica\Network\HTTPException;
|
||||
|
||||
/**
|
||||
* api/friendica/events
|
||||
|
@ -70,6 +70,6 @@ class Index extends BaseApi
|
|||
];
|
||||
}
|
||||
|
||||
self::exit('events', ['events' => $items], $parameters['extension'] ?? null);
|
||||
DI::apiResponse()->exit('events', ['events' => $items], $parameters['extension'] ?? null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,6 +56,6 @@ class Notification extends BaseApi
|
|||
$result = false;
|
||||
}
|
||||
|
||||
self::exit('notes', ['note' => $result], $parameters['extension'] ?? null);
|
||||
DI::apiResponse()->exit('notes', ['note' => $result], $parameters['extension'] ?? null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
namespace Friendica\Module\Api\Friendica\Photo;
|
||||
|
||||
use Friendica\DI;
|
||||
use Friendica\Model\Item;
|
||||
use Friendica\Model\Photo;
|
||||
use Friendica\Module\BaseApi;
|
||||
|
@ -43,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");
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
DI::apiResponse()->exit('photo_delete', ['$result' => $result], $parameters['extension'] ?? null);
|
||||
} else {
|
||||
throw new InternalServerErrorException("unknown error on deleting photo from database table");
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
namespace Friendica\Module\Api\Friendica\Photoalbum;
|
||||
|
||||
use Friendica\Database\DBA;
|
||||
use Friendica\DI;
|
||||
use Friendica\Model\Item;
|
||||
use Friendica\Model\Photo;
|
||||
use Friendica\Module\BaseApi;
|
||||
|
@ -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);
|
||||
DI::apiResponse()->exit('photoalbum_delete', ['$result' => $answer], $parameters['extension'] ?? null);
|
||||
} else {
|
||||
throw new InternalServerErrorException("unknown error - deleting from database failed");
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
namespace Friendica\Module\Api\Friendica\Photoalbum;
|
||||
|
||||
use Friendica\DI;
|
||||
use Friendica\Model\Photo;
|
||||
use Friendica\Module\BaseApi;
|
||||
use Friendica\Network\HTTPException\BadRequestException;
|
||||
|
@ -42,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
|
||||
|
@ -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);
|
||||
DI::apiResponse()->exit('photoalbum_update', ['$result' => $answer], $parameters['extension'] ?? null);
|
||||
} else {
|
||||
throw new InternalServerErrorException("unknown error - updating in database failed");
|
||||
}
|
||||
|
|
|
@ -28,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
|
||||
|
@ -66,7 +65,7 @@ class Show extends BaseApi
|
|||
'profiles' => $profiles
|
||||
];
|
||||
|
||||
self::exit('friendica_profiles', ['$result' => $result], $parameters['extension'] ?? null);
|
||||
DI::apiResponse()->exit('friendica_profiles', ['$result' => $result], $parameters['extension'] ?? null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
namespace Friendica\Module\Api\GNUSocial\GNUSocial;
|
||||
|
||||
use Friendica\Module\BaseApi;
|
||||
use Friendica\DI;
|
||||
|
||||
/**
|
||||
* API endpoint: /api/gnusocial/version, /api/statusnet/version
|
||||
|
@ -30,6 +31,6 @@ class Version extends BaseApi
|
|||
{
|
||||
public static function rawContent(array $parameters = [])
|
||||
{
|
||||
self::exit('version', ['version' => '0.9.7'], $parameters['extension'] ?? null);
|
||||
DI::apiResponse()->exit('version', ['version' => '0.9.7'], $parameters['extension'] ?? null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
namespace Friendica\Module\Api\GNUSocial\Help;
|
||||
|
||||
use Friendica\Module\BaseApi;
|
||||
use Friendica\DI;
|
||||
|
||||
/**
|
||||
* API endpoint: /api/help/test
|
||||
|
@ -36,6 +37,6 @@ class Test extends BaseApi
|
|||
$ok = 'ok';
|
||||
}
|
||||
|
||||
self::exit('ok', ['ok' => $ok], $parameters['extension'] ?? null);
|
||||
DI::apiResponse()->exit('ok', ['ok' => $ok], $parameters['extension'] ?? null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ namespace Friendica\Module\Api\Mastodon\Accounts;
|
|||
|
||||
use Friendica\App\Router;
|
||||
use Friendica\Core\Logger;
|
||||
use Friendica\DI;
|
||||
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);
|
||||
DI::apiResponse()->unsupported(Router::PATCH);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ namespace Friendica\Module\Api\Mastodon;
|
|||
|
||||
use Friendica\App\Router;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\DI;
|
||||
use Friendica\Module\BaseApi;
|
||||
|
||||
/**
|
||||
|
@ -34,7 +35,7 @@ class Filters extends BaseApi
|
|||
{
|
||||
self::checkAllowedScope(self::SCOPE_WRITE);
|
||||
|
||||
self::unsupported(Router::POST);
|
||||
DI::apiResponse()->unsupported(Router::POST);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
DI::apiResponse()->unsupported(Router::DELETE);
|
||||
}
|
||||
|
||||
public static function post(array $parameters = [])
|
||||
{
|
||||
self::unsupported(Router::POST);
|
||||
DI::apiResponse()->unsupported(Router::POST);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -23,6 +23,7 @@ namespace Friendica\Module\Api\Mastodon;
|
|||
|
||||
use Friendica\App\Router;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\DI;
|
||||
use Friendica\Module\BaseApi;
|
||||
|
||||
/**
|
||||
|
@ -34,7 +35,7 @@ class Markers extends BaseApi
|
|||
{
|
||||
self::checkAllowedScope(self::SCOPE_WRITE);
|
||||
|
||||
self::unsupported(Router::POST);
|
||||
DI::apiResponse()->unsupported(Router::POST);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
DI::apiResponse()->unsupported(Router::PUT);
|
||||
}
|
||||
|
||||
public static function delete(array $parameters = [])
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
namespace Friendica\Module\Api\Mastodon;
|
||||
|
||||
use Friendica\App\Router;
|
||||
use Friendica\DI;
|
||||
use Friendica\Module\BaseApi;
|
||||
|
||||
/**
|
||||
|
@ -35,7 +36,7 @@ class Unimplemented extends BaseApi
|
|||
*/
|
||||
public static function delete(array $parameters = [])
|
||||
{
|
||||
self::unsupported(Router::DELETE);
|
||||
DI::apiResponse()->unsupported(Router::DELETE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -44,7 +45,7 @@ class Unimplemented extends BaseApi
|
|||
*/
|
||||
public static function patch(array $parameters = [])
|
||||
{
|
||||
self::unsupported(Router::PATCH);
|
||||
DI::apiResponse()->unsupported(Router::PATCH);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -53,7 +54,7 @@ class Unimplemented extends BaseApi
|
|||
*/
|
||||
public static function post(array $parameters = [])
|
||||
{
|
||||
self::unsupported(Router::POST);
|
||||
DI::apiResponse()->unsupported(Router::POST);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -62,7 +63,7 @@ class Unimplemented extends BaseApi
|
|||
*/
|
||||
public static function put(array $parameters = [])
|
||||
{
|
||||
self::unsupported(Router::PUT);
|
||||
DI::apiResponse()->unsupported(Router::PUT);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -71,6 +72,6 @@ class Unimplemented extends BaseApi
|
|||
*/
|
||||
public static function rawContent(array $parameters = [])
|
||||
{
|
||||
self::unsupported(Router::GET);
|
||||
DI::apiResponse()->unsupported(Router::GET);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
namespace Friendica\Module\Api\Twitter\Account;
|
||||
|
||||
use Friendica\Module\BaseApi;
|
||||
use Friendica\DI;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
|
||||
/**
|
||||
|
@ -51,6 +52,6 @@ class RateLimitStatus extends BaseApi
|
|||
];
|
||||
}
|
||||
|
||||
self::exit('hash', ['hash' => $hash], $parameters['extension'] ?? null);
|
||||
DI::apiResponse()->exit('hash', ['hash' => $hash], $parameters['extension'] ?? null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
namespace Friendica\Module\Api\Twitter;
|
||||
|
||||
use Friendica\Database\DBA;
|
||||
use Friendica\DI;
|
||||
use Friendica\Module\BaseApi;
|
||||
|
||||
/**
|
||||
|
@ -44,6 +45,6 @@ class SavedSearches extends BaseApi
|
|||
|
||||
DBA::close($terms);
|
||||
|
||||
self::exit('terms', ['terms' => $result], $parameters['extension'] ?? null);
|
||||
DI::apiResponse()->exit('terms', ['terms' => $result], $parameters['extension'] ?? null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 = '<?xml version="1.0" encoding="UTF-8"?>' . "\n" . $return;
|
||||
break;
|
||||
case 'atom':
|
||||
header('Content-Type: application/atom+xml');
|
||||
$return = '<?xml version="1.0" encoding="UTF-8"?>' . "\n" . $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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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']]);
|
||||
|
|
|
@ -26,7 +26,7 @@ abstract class FixtureTest extends DatabaseTest
|
|||
/**
|
||||
* Create variables used by tests.
|
||||
*/
|
||||
protected function setUp() : void
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
|
|
73
tests/Util/ApiResponseDouble.php
Normal file
73
tests/Util/ApiResponseDouble.php
Normal file
|
@ -0,0 +1,73 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2021, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Test\Util;
|
||||
|
||||
use Friendica\Module\Api\ApiResponse;
|
||||
|
||||
class ApiResponseDouble extends ApiResponse
|
||||
{
|
||||
/**
|
||||
* The header list
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected static $header = [];
|
||||
|
||||
/**
|
||||
* The printed output
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected static $output = '';
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public static function getHeader(): array
|
||||
{
|
||||
return static::$header;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public static function getOutput(): string
|
||||
{
|
||||
return static::$output;
|
||||
}
|
||||
|
||||
public static function reset()
|
||||
{
|
||||
self::$output = '';
|
||||
self::$header = [];
|
||||
}
|
||||
|
||||
protected function setHeader(string $header)
|
||||
{
|
||||
static::$header[] = $header;
|
||||
}
|
||||
|
||||
protected function printOutput(string $output)
|
||||
{
|
||||
static::$output .= $output;
|
||||
}
|
||||
}
|
32
tests/Util/AuthenticationDouble.php
Normal file
32
tests/Util/AuthenticationDouble.php
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2021, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Test\Util;
|
||||
|
||||
use Friendica\Security\Authentication;
|
||||
|
||||
class AuthenticationDouble extends Authentication
|
||||
{
|
||||
protected function setXAccMgmtStatusHeader(array $user_record)
|
||||
{
|
||||
// Don't set any header..
|
||||
}
|
||||
}
|
21
tests/Util/authtest/authtest.php
Normal file
21
tests/Util/authtest/authtest.php
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
/**
|
||||
* Name: TEST-ADDON: Authentication "allow all"
|
||||
* Description: For testing purpose only
|
||||
* Version: 1.0
|
||||
* Author: Philipp Holzer <admin@philipp.info>
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
|
@ -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;
|
||||
|
@ -469,52 +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 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.
|
||||
*
|
||||
|
@ -621,145 +576,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.
|
||||
*
|
||||
* @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_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(
|
||||
'<?xml version="1.0"?>' . "\n" .
|
||||
'<status xmlns="http://api.twitter.com" xmlns:statusnet="http://status.net/schema/api/1/" ' .
|
||||
'xmlns:friendica="http://friendi.ca/schema/api/1/" ' .
|
||||
'xmlns:georss="http://www.georss.org/georss">' . "\n" .
|
||||
' <error>error_message</error>' . "\n" .
|
||||
' <code>200 OK</code>' . "\n" .
|
||||
' <request/>' . "\n" .
|
||||
'</status>' . "\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(
|
||||
'<?xml version="1.0"?>' . "\n" .
|
||||
'<status xmlns="http://api.twitter.com" xmlns:statusnet="http://status.net/schema/api/1/" ' .
|
||||
'xmlns:friendica="http://friendi.ca/schema/api/1/" ' .
|
||||
'xmlns:georss="http://www.georss.org/georss">' . "\n" .
|
||||
' <error>error_message</error>' . "\n" .
|
||||
' <code>200 OK</code>' . "\n" .
|
||||
' <request/>' . "\n" .
|
||||
'</status>' . "\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(
|
||||
'<?xml version="1.0"?>' . "\n" .
|
||||
'<status xmlns="http://api.twitter.com" xmlns:statusnet="http://status.net/schema/api/1/" ' .
|
||||
'xmlns:friendica="http://friendi.ca/schema/api/1/" ' .
|
||||
'xmlns:georss="http://www.georss.org/georss">' . "\n" .
|
||||
' <error>error_message</error>' . "\n" .
|
||||
' <code>200 OK</code>' . "\n" .
|
||||
' <request/>' . "\n" .
|
||||
'</status>' . "\n",
|
||||
api_error('atom', new HTTPException\OKException('error_message'), DI::args())
|
||||
);
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the api_rss_extra() function.
|
||||
*
|
||||
|
@ -1069,7 +885,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 +898,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 +911,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 +929,7 @@ class ApiTest extends FixtureTest
|
|||
'xmlns:georss="http://www.georss.org/georss">' . "\n" .
|
||||
' <data>some_data</data>' . "\n" .
|
||||
'</root_element>' . "\n",
|
||||
BaseApi::createXML(['data' => ['some_data']], 'root_element')
|
||||
DI::apiResponse()->createXML(['data' => ['some_data']], 'root_element')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1129,7 +945,7 @@ class ApiTest extends FixtureTest
|
|||
'<ok>' . "\n" .
|
||||
' <data>some_data</data>' . "\n" .
|
||||
'</ok>' . "\n",
|
||||
BaseApi::createXML(['data' => ['some_data']], 'ok')
|
||||
DI::apiResponse()->createXML(['data' => ['some_data']], 'ok')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1141,7 +957,7 @@ class ApiTest extends FixtureTest
|
|||
public function testApiFormatData()
|
||||
{
|
||||
$data = ['some_data'];
|
||||
self::assertEquals($data, BaseApi::formatData('root_element', 'json', $data));
|
||||
self::assertEquals($data, DI::apiResponse()->formatData('root_element', 'json', $data));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1158,7 +974,7 @@ class ApiTest extends FixtureTest
|
|||
'xmlns:georss="http://www.georss.org/georss">' . "\n" .
|
||||
' <data>some_data</data>' . "\n" .
|
||||
'</root_element>' . "\n",
|
||||
BaseApi::formatData('root_element', 'xml', ['data' => ['some_data']])
|
||||
DI::apiResponse()->formatData('root_element', 'xml', ['data' => ['some_data']])
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2540,56 +2356,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_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.
|
||||
*
|
||||
|
@ -2841,18 +2607,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.
|
||||
*
|
||||
|
@ -3177,97 +2931,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.
|
||||
*
|
||||
|
@ -3344,51 +3007,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.
|
||||
*
|
||||
|
@ -3700,77 +3318,6 @@ class ApiTest extends FixtureTest
|
|||
$this->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
|
||||
<?xml version="1.0"?>
|
||||
<notes>
|
||||
<note date="$date" date_rel="$dateRel" id="1" iid="4" link="http://localhost/notification/1" msg="A test reply from an item" msg_cache="A test reply from an item" msg_html="A test reply from an item" msg_plain="A test reply from an item" name="Reply to" name_cache="Reply to" otype="item" parent="" photo="http://localhost/" seen="false" timestamp="1577880722" type="8" uid="42" url="http://localhost/display/1" verb="http://activitystrea.ms/schema/1.0/post"/>
|
||||
</notes>
|
||||
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.
|
||||
*
|
||||
|
@ -3800,18 +3347,4 @@ XML;
|
|||
{
|
||||
$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']);
|
||||
}
|
||||
}
|
||||
|
|
108
tests/src/Module/Api/ApiResponseTest.php
Normal file
108
tests/src/Module/Api/ApiResponseTest.php
Normal file
|
@ -0,0 +1,108 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Test\src\Module\Api;
|
||||
|
||||
use Friendica\App\Arguments;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Test\MockedTest;
|
||||
use Friendica\Test\Util\ApiResponseDouble;
|
||||
use Psr\Log\NullLogger;
|
||||
|
||||
class ApiResponseTest extends MockedTest
|
||||
{
|
||||
protected function tearDown(): void
|
||||
{
|
||||
ApiResponseDouble::reset();
|
||||
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
public function testErrorWithJson()
|
||||
{
|
||||
$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', '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('<?xml version="1.0"?>' . "\n" .
|
||||
'<status xmlns="http://api.twitter.com" xmlns:statusnet="http://status.net/schema/api/1/" ' .
|
||||
'xmlns:friendica="http://friendi.ca/schema/api/1/" ' .
|
||||
'xmlns:georss="http://www.georss.org/georss">' . "\n" .
|
||||
' <error>error_message</error>' . "\n" .
|
||||
' <code>200 OK</code>' . "\n" .
|
||||
' <request/>' . "\n" .
|
||||
'</status>' . "\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(
|
||||
'<?xml version="1.0"?>' . "\n" .
|
||||
'<status xmlns="http://api.twitter.com" xmlns:statusnet="http://status.net/schema/api/1/" ' .
|
||||
'xmlns:friendica="http://friendi.ca/schema/api/1/" ' .
|
||||
'xmlns:georss="http://www.georss.org/georss">' . "\n" .
|
||||
' <error>error_message</error>' . "\n" .
|
||||
' <code>200 OK</code>' . "\n" .
|
||||
' <request/>' . "\n" .
|
||||
'</status>' . "\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(
|
||||
'<?xml version="1.0"?>' . "\n" .
|
||||
'<status xmlns="http://api.twitter.com" xmlns:statusnet="http://status.net/schema/api/1/" ' .
|
||||
'xmlns:friendica="http://friendi.ca/schema/api/1/" ' .
|
||||
'xmlns:georss="http://www.georss.org/georss">' . "\n" .
|
||||
' <error>error_message</error>' . "\n" .
|
||||
' <code>200 OK</code>' . "\n" .
|
||||
' <request/>' . "\n" .
|
||||
'</status>' . "\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());
|
||||
}
|
||||
}
|
101
tests/src/Module/Api/ApiTest.php
Normal file
101
tests/src/Module/Api/ApiTest.php
Normal file
|
@ -0,0 +1,101 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2021, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Test\src\Module\Api;
|
||||
|
||||
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;
|
||||
|
||||
abstract 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('<?xml version="1.0"?>', $result);
|
||||
self::assertStringContainsString('<' . $root_element, $result);
|
||||
// We could probably do more checks here.
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp(); // TODO: Change the autogenerated stub
|
||||
|
||||
$this->dice = $this->dice
|
||||
->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.
|
||||
*
|
||||
* @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();
|
||||
}
|
||||
}
|
83
tests/src/Module/Api/Friendica/NotificationTest.php
Normal file
83
tests/src/Module/Api/Friendica/NotificationTest.php
Normal file
|
@ -0,0 +1,83 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2021, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Test\src\Module\Api\Friendica;
|
||||
|
||||
use Friendica\DI;
|
||||
use Friendica\Module\Api\Friendica\Notification;
|
||||
use Friendica\Network\HTTPException\BadRequestException;
|
||||
use Friendica\Test\src\Module\Api\ApiTest;
|
||||
use Friendica\Test\Util\ApiResponseDouble;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
use Friendica\Util\Temporal;
|
||||
|
||||
class NotificationTest extends ApiTest
|
||||
{
|
||||
public function testEmpty()
|
||||
{
|
||||
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()
|
||||
{
|
||||
$date = DateTimeFormat::local('2020-01-01 12:12:02');
|
||||
$dateRel = Temporal::getRelativeDate('2020-01-01 07:12:02');
|
||||
|
||||
$assertXml = <<<XML
|
||||
<?xml version="1.0"?>
|
||||
<notes>
|
||||
<note date="$date" date_rel="$dateRel" id="1" iid="4" link="http://localhost/notification/1" msg="A test reply from an item" msg_cache="A test reply from an item" msg_html="A test reply from an item" msg_plain="A test reply from an item" name="Reply to" name_cache="Reply to" otype="item" parent="" photo="http://localhost/" seen="false" timestamp="1577880722" type="8" uid="42" url="http://localhost/display/1" verb="http://activitystrea.ms/schema/1.0/post"/>
|
||||
</notes>
|
||||
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);
|
||||
}
|
||||
}
|
51
tests/src/Module/Api/Friendica/Photo/DeleteTest.php
Normal file
51
tests/src/Module/Api/Friendica/Photo/DeleteTest.php
Normal file
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2021, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Test\src\Module\Api\Friendica\Photo;
|
||||
|
||||
use Friendica\Module\Api\Friendica\Photo\Delete;
|
||||
use Friendica\Network\HTTPException\BadRequestException;
|
||||
use Friendica\Test\src\Module\Api\ApiTest;
|
||||
|
||||
class DeleteTest extends ApiTest
|
||||
{
|
||||
public function testEmpty()
|
||||
{
|
||||
$this->expectException(BadRequestException::class);
|
||||
Delete::rawContent();
|
||||
}
|
||||
|
||||
public function testWithoutAuthenticatedUser()
|
||||
{
|
||||
self::markTestIncomplete('Needs BasicAuth as dynamic method for overriding first');
|
||||
}
|
||||
|
||||
public function testWrong()
|
||||
{
|
||||
$this->expectException(BadRequestException::class);
|
||||
Delete::rawContent(['photo_id' => 1]);
|
||||
}
|
||||
|
||||
public function testWithCorrectPhotoId()
|
||||
{
|
||||
self::markTestIncomplete('We need to add a dataset for this.');
|
||||
}
|
||||
}
|
46
tests/src/Module/Api/Friendica/Photoalbum/DeleteTest.php
Normal file
46
tests/src/Module/Api/Friendica/Photoalbum/DeleteTest.php
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2021, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Test\src\Module\Api\Friendica\Photoalbum;
|
||||
|
||||
use Friendica\Module\Api\Friendica\Photoalbum\Delete;
|
||||
use Friendica\Network\HTTPException\BadRequestException;
|
||||
use Friendica\Test\src\Module\Api\ApiTest;
|
||||
|
||||
class DeleteTest extends ApiTest
|
||||
{
|
||||
public function testEmpty()
|
||||
{
|
||||
$this->expectException(BadRequestException::class);
|
||||
Delete::rawContent();
|
||||
}
|
||||
|
||||
public function testWrong()
|
||||
{
|
||||
$this->expectException(BadRequestException::class);
|
||||
Delete::rawContent(['album' => 'album_name']);
|
||||
}
|
||||
|
||||
public function testValid()
|
||||
{
|
||||
self::markTestIncomplete('We need to add a dataset for this.');
|
||||
}
|
||||
}
|
57
tests/src/Module/Api/Friendica/Photoalbum/UpdateTest.php
Normal file
57
tests/src/Module/Api/Friendica/Photoalbum/UpdateTest.php
Normal file
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2021, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Test\src\Module\Api\Friendica\Photoalbum;
|
||||
|
||||
use Friendica\Module\Api\Friendica\Photoalbum\Update;
|
||||
use Friendica\Network\HTTPException\BadRequestException;
|
||||
use Friendica\Test\src\Module\Api\ApiTest;
|
||||
|
||||
class UpdateTest extends ApiTest
|
||||
{
|
||||
public function testEmpty()
|
||||
{
|
||||
$this->expectException(BadRequestException::class);
|
||||
Update::rawContent();
|
||||
}
|
||||
|
||||
public function testTooFewArgs()
|
||||
{
|
||||
$this->expectException(BadRequestException::class);
|
||||
Update::rawContent(['album' => 'album_name']);
|
||||
}
|
||||
|
||||
public function testWrongUpdate()
|
||||
{
|
||||
$this->expectException(BadRequestException::class);
|
||||
Update::rawContent(['album' => 'album_name', 'album_new' => 'album_name']);
|
||||
}
|
||||
|
||||
public function testWithoutAuthenticatedUser()
|
||||
{
|
||||
self::markTestIncomplete('Needs BasicAuth as dynamic method for overriding first');
|
||||
}
|
||||
|
||||
public function testValid()
|
||||
{
|
||||
self::markTestIncomplete('We need to add a dataset for this.');
|
||||
}
|
||||
}
|
19
tests/src/Module/Api/GnuSocial/GnuSocial/VersionTest.php
Normal file
19
tests/src/Module/Api/GnuSocial/GnuSocial/VersionTest.php
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Test\src\Module\Api\GnuSocial\GnuSocial;
|
||||
|
||||
use Friendica\Module\Api\GNUSocial\GNUSocial\Version;
|
||||
use Friendica\Test\src\Module\Api\ApiTest;
|
||||
use Friendica\Test\Util\ApiResponseDouble;
|
||||
|
||||
class VersionTest extends ApiTest
|
||||
{
|
||||
public function test()
|
||||
{
|
||||
Version::rawContent(['extension' => 'json']);
|
||||
|
||||
$result = json_decode(ApiResponseDouble::getOutput());
|
||||
|
||||
self::assertEquals('0.9.7', $result);
|
||||
}
|
||||
}
|
24
tests/src/Module/Api/GnuSocial/Help/TestTest.php
Normal file
24
tests/src/Module/Api/GnuSocial/Help/TestTest.php
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Test\src\Module\Api\GnuSocial\Help;
|
||||
|
||||
use Friendica\Module\Api\GNUSocial\Help\Test;
|
||||
use Friendica\Test\src\Module\Api\ApiTest;
|
||||
use Friendica\Test\Util\ApiResponseDouble;
|
||||
|
||||
class TestTest extends ApiTest
|
||||
{
|
||||
public function testJson()
|
||||
{
|
||||
Test::rawContent(['extension' => 'json']);
|
||||
|
||||
self::assertEquals('"ok"', ApiResponseDouble::getOutput());
|
||||
}
|
||||
|
||||
public function testXml()
|
||||
{
|
||||
Test::rawContent(['extension' => 'xml']);
|
||||
|
||||
self::assertxml(ApiResponseDouble::getOutput(), 'ok');
|
||||
}
|
||||
}
|
28
tests/src/Module/Api/Twitter/Account/RateLimitStatusTest.php
Normal file
28
tests/src/Module/Api/Twitter/Account/RateLimitStatusTest.php
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Test\src\Module\Api\Twitter\Account;
|
||||
|
||||
use Friendica\Module\Api\Twitter\Account\RateLimitStatus;
|
||||
use Friendica\Test\src\Module\Api\ApiTest;
|
||||
use Friendica\Test\Util\ApiResponseDouble;
|
||||
|
||||
class RateLimitStatusTest extends ApiTest
|
||||
{
|
||||
public function testWithJson()
|
||||
{
|
||||
RateLimitStatus::rawContent(['extension' => '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');
|
||||
}
|
||||
}
|
|
@ -1,4 +1,23 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2021, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Test\src\Module\Api\Twitter;
|
||||
|
||||
|
|
|
@ -1,4 +1,23 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2021, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Test\src\Module\Api\Twitter;
|
||||
|
||||
|
|
22
tests/src/Module/Api/Twitter/SavedSearchesTest.php
Normal file
22
tests/src/Module/Api/Twitter/SavedSearchesTest.php
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Test\src\Module\Api\Twitter;
|
||||
|
||||
use Friendica\Module\Api\Twitter\SavedSearches;
|
||||
use Friendica\Test\src\Module\Api\ApiTest;
|
||||
use Friendica\Test\Util\ApiResponseDouble;
|
||||
|
||||
class SavedSearchesTest extends ApiTest
|
||||
{
|
||||
public function test()
|
||||
{
|
||||
SavedSearches::rawContent(['extension' => '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);
|
||||
}
|
||||
}
|
31
tests/src/Module/BaseApiTest.php
Normal file
31
tests/src/Module/BaseApiTest.php
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Test\src\Module;
|
||||
|
||||
use Friendica\Test\src\Module\Api\ApiTest;
|
||||
|
||||
class BaseApiTest extends ApiTest
|
||||
{
|
||||
public function withWrongAuth()
|
||||
{
|
||||
self::markTestIncomplete('Needs BasicAuth as dynamic method for overriding first');
|
||||
|
||||
/*
|
||||
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)
|
||||
);
|
||||
*/
|
||||
}
|
||||
}
|
|
@ -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 <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\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 ""
|
||||
|
||||
|
|
Loading…
Reference in a new issue