diff --git a/doc/API-Friendica.md b/doc/API-Friendica.md index 84467430ae..013dd08f59 100644 --- a/doc/API-Friendica.md +++ b/doc/API-Friendica.md @@ -645,11 +645,7 @@ On error: ### GET api/friendica/profile/show -Returns the [Profile](help/API-Entities#Profile) data of all profiles or a single profile of the authenticated user. - -#### Parameters - -* `profile_id` (optional): id of the profile to be returned. If omitted all profiles are returned by default. +Returns the [Profile](help/API-Entities#Profile) data of the authenticated user. #### Return values @@ -664,6 +660,23 @@ HTTP 403 Forbidden: when no authentication was provided HTTP 400 Bad Request: if given profile_id is not in the database or is not assigned to the authenticated user General description of profile data in API returns: +- hide_friends: true if friends are hidden +- profile_photo +- profile_thumb +- publish: true if published on the server's local directory +- net_publish: true if published to global_dir +- fullname +- date_of_birth +- description +- xmpp +- homepage +- address +- locality +- region +- postal_code +- country +- pub_keywords +- custom_fields: list of public custom fields --- diff --git a/include/api.php b/include/api.php index 3f4d5625b0..b602dcd687 100644 --- a/include/api.php +++ b/include/api.php @@ -2906,60 +2906,6 @@ function api_format_items_activities($item, $type = "json") return $activities; } - -/** - * return data from profiles - * - * @param array $profile_row array containing data from db table 'profile' - * @return array - * @throws InternalServerErrorException - */ -function api_format_items_profiles($profile_row) -{ - $profile = [ - 'profile_id' => $profile_row['id'], - 'profile_name' => $profile_row['profile-name'], - 'is_default' => $profile_row['is-default'] ? true : false, - 'hide_friends' => $profile_row['hide-friends'] ? true : false, - 'profile_photo' => $profile_row['photo'], - 'profile_thumb' => $profile_row['thumb'], - 'publish' => $profile_row['publish'] ? true : false, - 'net_publish' => $profile_row['net-publish'] ? true : false, - 'description' => $profile_row['pdesc'], - 'date_of_birth' => $profile_row['dob'], - 'address' => $profile_row['address'], - 'city' => $profile_row['locality'], - 'region' => $profile_row['region'], - 'postal_code' => $profile_row['postal-code'], - 'country' => $profile_row['country-name'], - 'hometown' => $profile_row['hometown'], - 'gender' => $profile_row['gender'], - 'marital' => $profile_row['marital'], - 'marital_with' => $profile_row['with'], - 'marital_since' => $profile_row['howlong'], - 'sexual' => $profile_row['sexual'], - 'politic' => $profile_row['politic'], - 'religion' => $profile_row['religion'], - 'public_keywords' => $profile_row['pub_keywords'], - 'private_keywords' => $profile_row['prv_keywords'], - 'likes' => BBCode::convert(api_clean_plain_items($profile_row['likes']) , false, 2), - 'dislikes' => BBCode::convert(api_clean_plain_items($profile_row['dislikes']) , false, 2), - 'about' => BBCode::convert(api_clean_plain_items($profile_row['about']) , false, 2), - 'music' => BBCode::convert(api_clean_plain_items($profile_row['music']) , false, 2), - 'book' => BBCode::convert(api_clean_plain_items($profile_row['book']) , false, 2), - 'tv' => BBCode::convert(api_clean_plain_items($profile_row['tv']) , false, 2), - 'film' => BBCode::convert(api_clean_plain_items($profile_row['film']) , false, 2), - 'interest' => BBCode::convert(api_clean_plain_items($profile_row['interest']) , false, 2), - 'romance' => BBCode::convert(api_clean_plain_items($profile_row['romance']) , false, 2), - 'work' => BBCode::convert(api_clean_plain_items($profile_row['work']) , false, 2), - 'education' => BBCode::convert(api_clean_plain_items($profile_row['education']), false, 2), - 'social_networks' => BBCode::convert(api_clean_plain_items($profile_row['contact']) , false, 2), - 'homepage' => $profile_row['homepage'], - 'users' => null - ]; - return $profile; -} - /** * format items to be returned by api * @@ -6102,78 +6048,6 @@ function api_friendica_direct_messages_search($type, $box = "") /// @TODO move to top of file or somewhere better api_register_func('api/friendica/direct_messages_search', 'api_friendica_direct_messages_search', true); -/** - * return data of all the profiles a user has to the client - * - * @param string $type Known types are 'atom', 'rss', 'xml' and 'json' - * @return string|array - * @throws BadRequestException - * @throws ForbiddenException - * @throws ImagickException - * @throws InternalServerErrorException - * @throws UnauthorizedException - */ -function api_friendica_profile_show($type) -{ - $a = DI::app(); - - if (api_user() === false) { - throw new ForbiddenException(); - } - - // input params - $profile_id = $_REQUEST['profile_id'] ?? 0; - - // retrieve general information about profiles for user - $multi_profiles = Feature::isEnabled(api_user(), 'multi_profiles'); - $directory = DI::config()->get('system', 'directory'); - - // get data of the specified profile id or all profiles of the user if not specified - if ($profile_id != 0) { - $r = Profile::getById(api_user(), $profile_id); - // error message if specified gid is not in database - if (!DBA::isResult($r)) { - throw new BadRequestException("profile_id not available"); - } - } else { - $r = Profile::getListByUser(api_user()); - } - // loop through all returned profiles and retrieve data and users - $k = 0; - $profiles = []; - if (DBA::isResult($r)) { - foreach ($r as $rr) { - $profile = api_format_items_profiles($rr); - - // select all users from contact table, loop and prepare standard return for user data - $users = []; - $nurls = Contact::selectToArray(['id', 'nurl'], ['uid' => api_user(), 'profile-id' => $rr['id']]); - foreach ($nurls as $nurl) { - $user = api_get_user($a, $nurl['nurl']); - ($type == "xml") ? $users[$k++ . ":user"] = $user : $users[] = $user; - } - $profile['users'] = $users; - - // add prepared profile data to array for final return - if ($type == "xml") { - $profiles[$k++ . ":profile"] = $profile; - } else { - $profiles[] = $profile; - } - } - } - - // return settings, authenticated user and profiles data - $self = DBA::selectFirst('contact', ['nurl'], ['uid' => api_user(), 'self' => true]); - - $result = ['multi_profiles' => $multi_profiles ? true : false, - 'global_dir' => $directory, - 'friendica_owner' => api_get_user($a, $self['nurl']), - 'profiles' => $profiles]; - return api_format_data("friendica_profiles", $type, ['$result' => $result]); -} -api_register_func('api/friendica/profile/show', 'api_friendica_profile_show', true, API_METHOD_GET); - /** * Returns a list of saved searches. * diff --git a/src/Module/Api/Friendica/Profile/Show.php b/src/Module/Api/Friendica/Profile/Show.php new file mode 100644 index 0000000000..2c50c53d50 --- /dev/null +++ b/src/Module/Api/Friendica/Profile/Show.php @@ -0,0 +1,114 @@ +get('system', 'directory'); + + $profile = Profile::getByUID(self::$current_user_id); + + $profileFields = DI::profileField()->select(['uid' => self::$current_user_id, 'psid' => PermissionSet::PUBLIC]); + + $profile = self::formatProfile($profile, $profileFields); + + $profiles = []; + if (self::$format == 'xml') { + $profiles['0:profile'] = $profile; + } else { + $profiles[] = $profile; + } + + // return settings, authenticated user and profiles data + $self = Contact::selectFirst(['nurl'], ['uid' => self::$current_user_id, 'self' => true]); + + $result = [ + 'multi_profiles' => false, + 'global_dir' => $directory, + 'friendica_owner' => self::getUser($self['nurl']), + 'profiles' => $profiles + ]; + + echo self::format('friendica_profiles', ['$result' => $result]); + exit; + } + + /** + * @param array $profile_row array containing data from db table 'profile' + * @param ProfileFields $profileFields + * @return array + * @throws HTTPException\InternalServerErrorException + */ + private static function formatProfile($profile_row, ProfileFields $profileFields) + { + $custom_fields = []; + foreach ($profileFields as $profileField) { + $custom_fields[] = [ + 'label' => $profileField->label, + 'value' => BBCode::convert($profileField->value, false, 2), + ]; + } + + return [ + 'profile_id' => $profile_row['id'], + 'profile_name' => null, + 'is_default' => null, + 'hide_friends' => $profile_row['hide-friends'] ? true : false, + 'profile_photo' => $profile_row['photo'], + 'profile_thumb' => $profile_row['thumb'], + 'publish' => $profile_row['publish'] ? true : false, + 'net_publish' => $profile_row['net-publish'] ? true : false, + 'description' => $profile_row['pdesc'], + 'date_of_birth' => $profile_row['dob'], + 'address' => $profile_row['address'], + 'city' => $profile_row['locality'], + 'region' => $profile_row['region'], + 'postal_code' => $profile_row['postal-code'], + 'country' => $profile_row['country-name'], + 'hometown' => null, + 'gender' => null, + 'marital' => null, + 'marital_with' => null, + 'marital_since' => null, + 'sexual' => null, + 'politic' => null, + 'religion' => null, + 'public_keywords' => $profile_row['pub_keywords'], + 'private_keywords' => $profile_row['prv_keywords'], + 'likes' => null, + 'dislikes' => null, + 'about' => null, + 'music' => null, + 'book' => null, + 'tv' => null, + 'film' => null, + 'interest' => null, + 'romance' => null, + 'work' => null, + 'education' => null, + 'social_networks' => null, + 'homepage' => $profile_row['homepage'], + 'users' => [], + 'custom_fields' => $custom_fields, + ]; + } +} diff --git a/src/Module/BaseApi.php b/src/Module/BaseApi.php index 81814bb0d4..543293872d 100644 --- a/src/Module/BaseApi.php +++ b/src/Module/BaseApi.php @@ -87,20 +87,53 @@ class BaseApi extends BaseModule return api_get_user(DI::app(), $contact_id); } - protected static function format($root_element, $data) + /** + * Formats the data according to the data type + * + * @param string $root_element + * @param array $data An array with a single element containing the returned result + * @return false|string + */ + protected static function format(string $root_element, array $data) { + $return = api_format_data($root_element, self::$format, $data); + switch (self::$format) { - case "atom": - case "rss": case "xml": - $ret = api_create_xml($data, $root_element); + header("Content-Type: text/xml"); break; case "json": - default: - $ret = $data; + header("Content-Type: application/json"); + if (!empty($return)) { + $json = json_encode(end($return)); + if (!empty($_GET['callback'])) { + $json = $_GET['callback'] . "(" . $json . ")"; + } + $return = $json; + } + break; + case "rss": + header("Content-Type: application/rss+xml"); + $return = '' . "\n" . $return; + break; + case "atom": + header("Content-Type: application/atom+xml"); + $return = '' . "\n" . $return; break; } + + return $return; + } - return $ret; + /** + * Creates the XML from a JSON style array + * + * @param $data + * @param $root_element + * @return string + */ + protected static function createXml($data, $root_element) + { + return api_create_xml($data, $root_element); } } diff --git a/static/routes.config.php b/static/routes.config.php index 4aad69d8c7..aac2cbb1b5 100644 --- a/static/routes.config.php +++ b/static/routes.config.php @@ -35,6 +35,9 @@ return [ '/instance' => [Module\Api\Mastodon\Instance::class, [R::GET ]], '/instance/peers' => [Module\Api\Mastodon\Instance\Peers::class, [R::GET ]], ], + '/friendica' => [ + '/profile/show' => [Module\Api\Friendica\Profile\Show::class , [R::GET ]], + ], ], '/admin' => [ diff --git a/tests/include/ApiTest.php b/tests/include/ApiTest.php index 3ef64b3171..6920ea2bf2 100644 --- a/tests/include/ApiTest.php +++ b/tests/include/ApiTest.php @@ -2488,102 +2488,6 @@ class ApiTest extends DatabaseTest $this->assertArrayHasKey('friendica:attendmaybe', $result); } - /** - * Test the api_format_items_profiles() function. - * - * @return void - */ - public function testApiFormatItemsProfiles() - { - $profile_row = [ - 'id' => 'profile_id', - 'profile-name' => 'profile_name', - 'is-default' => true, - 'hide-friends' => true, - 'photo' => 'profile_photo', - 'thumb' => 'profile_thumb', - 'publish' => true, - 'net-publish' => true, - 'pdesc' => 'description', - 'dob' => 'date_of_birth', - 'address' => 'address', - 'locality' => 'city', - 'region' => 'region', - 'postal-code' => 'postal_code', - 'country-name' => 'country', - 'hometown' => 'hometown', - 'gender' => 'gender', - 'marital' => 'marital', - 'with' => 'marital_with', - 'howlong' => 'marital_since', - 'sexual' => 'sexual', - 'politic' => 'politic', - 'religion' => 'religion', - 'pub_keywords' => 'public_keywords', - 'prv_keywords' => 'private_keywords', - - 'likes' => 'likes', - 'dislikes' => 'dislikes', - 'about' => 'about', - 'music' => 'music', - 'book' => 'book', - 'tv' => 'tv', - 'film' => 'film', - 'interest' => 'interest', - 'romance' => 'romance', - 'work' => 'work', - 'education' => 'education', - 'contact' => 'social_networks', - 'homepage' => 'homepage' - ]; - $result = api_format_items_profiles($profile_row); - $this->assertEquals( - [ - 'profile_id' => 'profile_id', - 'profile_name' => 'profile_name', - 'is_default' => true, - 'hide_friends' => true, - 'profile_photo' => 'profile_photo', - 'profile_thumb' => 'profile_thumb', - 'publish' => true, - 'net_publish' => true, - 'description' => 'description', - 'date_of_birth' => 'date_of_birth', - 'address' => 'address', - 'city' => 'city', - 'region' => 'region', - 'postal_code' => 'postal_code', - 'country' => 'country', - 'hometown' => 'hometown', - 'gender' => 'gender', - 'marital' => 'marital', - 'marital_with' => 'marital_with', - 'marital_since' => 'marital_since', - 'sexual' => 'sexual', - 'politic' => 'politic', - 'religion' => 'religion', - 'public_keywords' => 'public_keywords', - 'private_keywords' => 'private_keywords', - - 'likes' => 'likes', - 'dislikes' => 'dislikes', - 'about' => 'about', - 'music' => 'music', - 'book' => 'book', - 'tv' => 'tv', - 'film' => 'film', - 'interest' => 'interest', - 'romance' => 'romance', - 'work' => 'work', - 'education' => 'education', - 'social_networks' => 'social_networks', - 'homepage' => 'homepage', - 'users' => null - ], - $result - ); - } - /** * Test the api_format_items() function. *