diff --git a/mod/msearch.php b/mod/msearch.php index b51757cf7..1e858f1db 100644 --- a/mod/msearch.php +++ b/mod/msearch.php @@ -74,7 +74,7 @@ function msearch_post(App $a) $results[] = [ 'name' => $search_result['name'], 'url' => DI::baseUrl() . '/profile/' . $search_result['nickname'], - 'photo' => User::getAvatarUrlForId($search_result['uid'], Proxy::SIZE_THUMB), + 'photo' => User::getAvatarUrl($search_result, Proxy::SIZE_THUMB), 'tags' => str_replace([',', ' '], [' ', ' '], $search_result['pub_keywords']) ]; } diff --git a/src/Model/Contact.php b/src/Model/Contact.php index faad2adc7..72145c17b 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -653,9 +653,9 @@ class Contact 'nick' => $user['nickname'], 'pubkey' => $user['pubkey'], 'prvkey' => $user['prvkey'], - 'photo' => User::getAvatarUrlForId($user['uid']), - 'thumb' => User::getAvatarUrlForId($user['uid'], Proxy::SIZE_THUMB), - 'micro' => User::getAvatarUrlForId($user['uid'], Proxy::SIZE_MICRO), + 'photo' => User::getAvatarUrl($user), + 'thumb' => User::getAvatarUrl($user, Proxy::SIZE_THUMB), + 'micro' => User::getAvatarUrl($user, Proxy::SIZE_MICRO), 'blocked' => 0, 'pending' => 0, 'url' => DI::baseUrl() . '/profile/' . $user['nickname'], @@ -709,7 +709,7 @@ class Contact return false; } - $fields = ['nickname', 'page-flags', 'account-type', 'prvkey', 'pubkey']; + $fields = ['uid', 'nickname', 'page-flags', 'account-type', 'prvkey', 'pubkey']; $user = DBA::selectFirst('user', $fields, ['uid' => $uid, 'account_expired' => false]); if (!DBA::isResult($user)) { return false; @@ -768,7 +768,7 @@ class Contact $fields['micro'] = self::getDefaultAvatar($fields, Proxy::SIZE_MICRO); } - $fields['avatar'] = User::getAvatarUrlForId($uid); + $fields['avatar'] = User::getAvatarUrl($user); $fields['forum'] = $user['page-flags'] == User::PAGE_FLAGS_COMMUNITY; $fields['prv'] = $user['page-flags'] == User::PAGE_FLAGS_PRVGROUP; $fields['unsearchable'] = !$profile['net-publish']; @@ -795,8 +795,8 @@ class Contact // Update the profile $fields = [ - 'photo' => User::getAvatarUrlForId($uid), - 'thumb' => User::getAvatarUrlForId($uid, Proxy::SIZE_THUMB) + 'photo' => User::getAvatarUrl($user), + 'thumb' => User::getAvatarUrl($user, Proxy::SIZE_THUMB) ]; DBA::update('profile', $fields, ['uid' => $uid]); diff --git a/src/Model/Photo.php b/src/Model/Photo.php index c09434d7f..7d97d6398 100644 --- a/src/Model/Photo.php +++ b/src/Model/Photo.php @@ -799,22 +799,6 @@ class Photo Photo::update($fields, $condition); } - /** - * Strips known picture extensions from picture links - * - * @param string $name Picture link - * @return string stripped picture link - * @throws \Exception - */ - public static function stripExtension($name) - { - $name = str_replace([".jpg", ".png", ".gif"], ["", "", ""], $name); - foreach (Images::supportedTypes() as $m => $e) { - $name = str_replace("." . $e, "", $name); - } - return $name; - } - /** * Fetch the guid and scale from picture links * @@ -831,7 +815,7 @@ class Photo return []; } - $guid = self::stripExtension($guid); + $guid = pathinfo($guid, PATHINFO_FILENAME); if (substr($guid, -2, 1) != "-") { return []; } diff --git a/src/Model/User.php b/src/Model/User.php index f3f837eb2..8f69aa87c 100644 --- a/src/Model/User.php +++ b/src/Model/User.php @@ -841,13 +841,14 @@ class User } /** - * Get avatar link for given user id + * Get avatar link for given user * - * @param integer $uid user id - * @param string $size One of the ProxyUtils::SIZE_* constants + * @param array $user + * @param string $size One of the ProxyUtils::SIZE_* constants * @return string avatar link + * @throws Exception */ - public static function getAvatarUrlForId(int $uid, string $size = ''):string + public static function getAvatarUrl(array $user, string $size = ''):string { $url = DI::baseUrl() . '/photo/'; @@ -869,26 +870,16 @@ class User $updated = ''; $imagetype = IMAGETYPE_JPEG; - $photo = Photo::selectFirst(['type', 'created', 'edited', 'updated'], ["scale" => $scale, 'uid' => $uid, 'profile' => true]); + $photo = Photo::selectFirst(['type', 'created', 'edited', 'updated'], ["scale" => $scale, 'uid' => $user['uid'], 'profile' => true]); if (!empty($photo)) { $updated = max($photo['created'], $photo['edited'], $photo['updated']); - switch ($photo['type']) { - case 'image/png': - $imagetype = IMAGETYPE_PNG; - break; - - case 'image/gif': - $imagetype = IMAGETYPE_PNG; - break; - - default: - $imagetype = IMAGETYPE_JPEG; - break; + if (in_array($photo['type'], ['image/png', 'image/gif'])) { + $imagetype = IMAGETYPE_PNG; } } - return $url . $uid . image_type_to_extension($imagetype) . ($updated ? '?ts=' . strtotime($updated) : ''); + return $url . $user['nickname'] . image_type_to_extension($imagetype) . ($updated ? '?ts=' . strtotime($updated) : ''); } /** @@ -1105,8 +1096,8 @@ class User $insert_result = DBA::insert('profile', [ 'uid' => $uid, 'name' => $username, - 'photo' => self::getAvatarUrlForId($uid), - 'thumb' => self::getAvatarUrlForId($uid, Proxy::SIZE_THUMB), + 'photo' => self::getAvatarUrl($user), + 'thumb' => self::getAvatarUrl($user, Proxy::SIZE_THUMB), 'publish' => $publish, 'net-publish' => $netpublish, ]); diff --git a/src/Module/Delegation.php b/src/Module/Delegation.php index 54f868881..579b4d6b5 100644 --- a/src/Module/Delegation.php +++ b/src/Module/Delegation.php @@ -122,7 +122,7 @@ class Delegation extends BaseModule //getting additinal information for each identity foreach ($identities as $key => $identity) { - $identities[$key]['thumb'] = User::getAvatarUrlForId($identity['uid'], Proxy::SIZE_THUMB); + $identities[$key]['thumb'] = User::getAvatarUrl($identity, Proxy::SIZE_THUMB); $identities[$key]['selected'] = ($identity['nickname'] === DI::app()->getLoggedInUserNickname()); diff --git a/src/Module/NoScrape.php b/src/Module/NoScrape.php index b791c5cd7..253003896 100644 --- a/src/Module/NoScrape.php +++ b/src/Module/NoScrape.php @@ -49,20 +49,20 @@ class NoScrape extends BaseModule System::jsonError(403, 'Authentication required'); } - $profile = User::getOwnerDataByNick($which); + $owner = User::getOwnerDataByNick($which); - if (empty($profile['uid'])) { + if (empty($owner['uid'])) { System::jsonError(404, 'Profile not found'); } $json_info = [ - 'addr' => $profile['addr'], + 'addr' => $owner['addr'], 'nick' => $which, - 'guid' => $profile['guid'], - 'key' => $profile['upubkey'], - 'homepage' => DI::baseUrl() . "/profile/{$which}", - 'comm' => ($profile['account-type'] == User::ACCOUNT_TYPE_COMMUNITY), - 'account-type' => $profile['account-type'], + 'guid' => $owner['guid'], + 'key' => $owner['upubkey'], + 'homepage' => DI::baseUrl() . '/profile/' . $which, + 'comm' => ($owner['account-type'] == User::ACCOUNT_TYPE_COMMUNITY), + 'account-type' => $owner['account-type'], ]; $dfrn_pages = ['request', 'confirm', 'notify', 'poll']; @@ -70,28 +70,28 @@ class NoScrape extends BaseModule $json_info["dfrn-{$dfrn}"] = DI::baseUrl() . "/dfrn_{$dfrn}/{$which}"; } - if (!$profile['net-publish']) { + if (!$owner['net-publish']) { $json_info['hide'] = true; System::jsonExit($json_info); } - $keywords = $profile['pub_keywords'] ?? ''; + $keywords = $owner['pub_keywords'] ?? ''; $keywords = str_replace(['#', ',', ' ', ',,'], ['', ' ', ',', ','], $keywords); $keywords = explode(',', $keywords); - $json_info['fn'] = $profile['name']; - $json_info['photo'] = User::getAvatarUrlForId($profile['uid']); + $json_info['fn'] = $owner['name']; + $json_info['photo'] = User::getAvatarUrl($owner); $json_info['tags'] = $keywords; - $json_info['language'] = $profile['language']; + $json_info['language'] = $owner['language']; - if (!empty($profile['last-item'])) { - $json_info['updated'] = date("c", strtotime($profile['last-item'])); + if (!empty($owner['last-item'])) { + $json_info['updated'] = date("c", strtotime($owner['last-item'])); } - if (!($profile['hide-friends'] ?? false)) { + if (!($owner['hide-friends'] ?? false)) { $json_info['contacts'] = DBA::count('contact', [ - 'uid' => $profile['uid'], + 'uid' => $owner['uid'], 'self' => 0, 'blocked' => 0, 'pending' => 0, @@ -103,13 +103,13 @@ class NoScrape extends BaseModule // We display the last activity (post or login), reduced to year and week number $last_active = 0; - $condition = ['uid' => $profile['uid'], 'self' => true]; + $condition = ['uid' => $owner['uid'], 'self' => true]; $contact = DBA::selectFirst('contact', ['last-item'], $condition); if (DBA::isResult($contact)) { $last_active = strtotime($contact['last-item']); } - $condition = ['uid' => $profile['uid']]; + $condition = ['uid' => $owner['uid']]; $user = DBA::selectFirst('user', ['login_date'], $condition); if (DBA::isResult($user)) { if ($last_active < strtotime($user['login_date'])) { @@ -121,8 +121,8 @@ class NoScrape extends BaseModule //These are optional fields. $profile_fields = ['about', 'locality', 'region', 'postal-code', 'country-name', 'xmpp', 'matrix']; foreach ($profile_fields as $field) { - if (!empty($profile[$field])) { - $json_info["$field"] = $profile[$field]; + if (!empty($owner[$field])) { + $json_info["$field"] = $owner[$field]; } } diff --git a/src/Module/Photo.php b/src/Module/Photo.php index 9d2d31b45..32403a5d1 100644 --- a/src/Module/Photo.php +++ b/src/Module/Photo.php @@ -30,15 +30,13 @@ use Friendica\Model\Photo as MPhoto; use Friendica\Model\Post; use Friendica\Model\Profile; use Friendica\Model\Storage\ExternalResource; -use Friendica\Model\Storage\ReferenceStorageException; -use Friendica\Model\Storage\StorageException; use Friendica\Model\Storage\SystemResource; -use Friendica\Network\HTTPException\InternalServerErrorException; -use Friendica\Network\HTTPException\NotFoundException; -use Friendica\Util\Proxy; +use Friendica\Model\User; +use Friendica\Network\HTTPException; use Friendica\Object\Image; use Friendica\Util\Images; use Friendica\Util\Network; +use Friendica\Util\Proxy; /** * Photo Module @@ -75,18 +73,32 @@ class Photo extends BaseModule $customsize = 0; $square_resize = true; - $photo = false; $scale = null; $stamp = microtime(true); - if (!empty($parameters['customsize'])) { - $customsize = intval($parameters['customsize']); - $uid = MPhoto::stripExtension($parameters['name']); - $photo = self::getAvatar($uid, $parameters['type'], $customsize); - $square_resize = !in_array($parameters['type'], ['media', 'preview']); - } elseif (!empty($parameters['type'])) { - $uid = MPhoto::stripExtension($parameters['name']); - $photo = self::getAvatar($uid, $parameters['type'], Proxy::PIXEL_SMALL); - } elseif (!empty($parameters['name'])) { + // User avatar + if (!empty($parameters['type'])) { + if (!empty($parameters['customsize'])) { + $customsize = intval($parameters['customsize']); + $square_resize = !in_array($parameters['type'], ['media', 'preview']); + } + + if (!empty($parameters['nickname_ext'])) { + $nickname = pathinfo($parameters['nickname_ext'], PATHINFO_FILENAME); + $user = User::getByNickname($nickname, ['uid']); + if (empty($user)) { + throw new HTTPException\NotFoundException(); + } + + $uid = $user['uid']; + } + + // User Id Fallback, to remove after version 2021.12 + if (!empty($parameters['uid_ext'])) { + $uid = intval(pathinfo($parameters['uid_ext'], PATHINFO_FILENAME)); + } + + $photo = self::getAvatar($uid, $parameters['type'], $customsize ?: Proxy::PIXEL_SMALL); + } else { $photoid = MPhoto::stripExtension($parameters['name']); $scale = 0; if (substr($photoid, -2, 1) == "-") { @@ -95,15 +107,14 @@ class Photo extends BaseModule } $photo = MPhoto::getPhoto($photoid, $scale); if ($photo === false) { - throw new \Friendica\Network\HTTPException\NotFoundException(DI::l10n()->t('The Photo with id %s is not available.', $photoid)); + throw new HTTPException\NotFoundException(DI::l10n()->t('The Photo with id %s is not available.', $photoid)); } - } else { - throw new \Friendica\Network\HTTPException\BadRequestException(); } + $fetch = microtime(true) - $stamp; if ($photo === false) { - throw new \Friendica\Network\HTTPException\NotFoundException(); + throw new HTTPException\NotFoundException(); } $cacheable = ($photo["allow_cid"] . $photo["allow_gid"] . $photo["deny_cid"] . $photo["deny_gid"] === "") && (isset($photo["cacheable"]) ? $photo["cacheable"] : true); @@ -112,7 +123,7 @@ class Photo extends BaseModule $imgdata = MPhoto::getImageDataForPhoto($photo); if (empty($imgdata)) { - throw new NotFoundException(); + throw new HTTPException\NotFoundException(); } // The mimetype for an external or system resource can only be known reliably after it had been fetched @@ -133,7 +144,7 @@ class Photo extends BaseModule } else { $error = DI::l10n()->t('Invalid photo with id %s.', $photo['id']); } - throw new \Friendica\Network\HTTPException\InternalServerErrorException($error); + throw new HTTPException\InternalServerErrorException($error); } // if customsize is set and image is not a gif, resize it @@ -186,7 +197,7 @@ class Photo extends BaseModule exit(); } - private static function getAvatar($uid, $type="avatar", $customsize) + private static function getAvatar(int $uid, $type, $customsize) { switch($type) { case "preview": diff --git a/src/Module/Register.php b/src/Module/Register.php index a589ebe0a..976e43a5d 100644 --- a/src/Module/Register.php +++ b/src/Module/Register.php @@ -374,7 +374,7 @@ class Register extends BaseModule 'source_mail' => $user['email'], 'source_nick' => $user['nickname'], 'source_link' => $base_url . '/admin/users/', - 'source_photo' => User::getAvatarUrlForId($user['uid'], Proxy::SIZE_THUMB), + 'source_photo' => User::getAvatarUrl($user, Proxy::SIZE_THUMB), 'show_in_notification_page' => false ]); } diff --git a/src/Module/Xrd.php b/src/Module/Xrd.php index 48623bf70..1d4082de1 100644 --- a/src/Module/Xrd.php +++ b/src/Module/Xrd.php @@ -196,7 +196,7 @@ class Xrd extends BaseModule [ 'rel' => 'http://webfinger.net/rel/avatar', 'type' => $avatar['type'], - 'href' => User::getAvatarUrlForId($owner['uid']), + 'href' => User::getAvatarUrl($owner), ], [ 'rel' => 'http://joindiaspora.com/seed_location', @@ -252,7 +252,7 @@ class Xrd extends BaseModule '$hcard_url' => $baseURL . '/hcard/' . $owner['nickname'], '$atom' => $owner['poll'], '$poco_url' => $owner['poco'], - '$photo' => User::getAvatarUrlForId($owner['uid']), + '$photo' => User::getAvatarUrl($owner), '$type' => $avatar['type'], '$salmon' => $baseURL . '/salmon/' . $owner['nickname'], '$salmen' => $baseURL . '/salmon/' . $owner['nickname'] . '/mention', diff --git a/src/Network/Probe.php b/src/Network/Probe.php index 4aa50b4be..23c115eab 100644 --- a/src/Network/Probe.php +++ b/src/Network/Probe.php @@ -2229,29 +2229,29 @@ class Probe throw new HTTPException\NotFoundException('User not found.'); } - $profile = User::getOwnerDataById($uid); + $owner = User::getOwnerDataById($uid); $approfile = ActivityPub\Transmitter::getProfile($uid); - if (empty($profile['gsid'])) { - $profile['gsid'] = GServer::getID($approfile['generator']['url']); + if (empty($owner['gsid'])) { + $owner['gsid'] = GServer::getID($approfile['generator']['url']); } $data = [ - 'name' => $profile['name'], 'nick' => $profile['nick'], 'guid' => $approfile['diaspora:guid'] ?? '', - 'url' => $profile['url'], 'addr' => $profile['addr'], 'alias' => $profile['alias'], - 'photo' => User::getAvatarUrlForId($uid), - 'header' => $profile['header'] ? Contact::getHeaderUrlForId($profile['id'], $profile['updated']) : '', - 'account-type' => $profile['contact-type'], 'community' => ($profile['contact-type'] == User::ACCOUNT_TYPE_COMMUNITY), - 'keywords' => $profile['keywords'], 'location' => $profile['location'], 'about' => $profile['about'], - 'xmpp' => $profile['xmpp'], 'matrix' => $profile['matrix'], - 'hide' => !$profile['net-publish'], 'batch' => '', 'notify' => $profile['notify'], - 'poll' => $profile['poll'], 'request' => $profile['request'], 'confirm' => $profile['confirm'], - 'subscribe' => $approfile['generator']['url'] . '/follow?url={uri}', 'poco' => $profile['poco'], + 'name' => $owner['name'], 'nick' => $owner['nick'], 'guid' => $approfile['diaspora:guid'] ?? '', + 'url' => $owner['url'], 'addr' => $owner['addr'], 'alias' => $owner['alias'], + 'photo' => User::getAvatarUrl($owner), + 'header' => $owner['header'] ? Contact::getHeaderUrlForId($owner['id'], $owner['updated']) : '', + 'account-type' => $owner['contact-type'], 'community' => ($owner['contact-type'] == User::ACCOUNT_TYPE_COMMUNITY), + 'keywords' => $owner['keywords'], 'location' => $owner['location'], 'about' => $owner['about'], + 'xmpp' => $owner['xmpp'], 'matrix' => $owner['matrix'], + 'hide' => !$owner['net-publish'], 'batch' => '', 'notify' => $owner['notify'], + 'poll' => $owner['poll'], 'request' => $owner['request'], 'confirm' => $owner['confirm'], + 'subscribe' => $approfile['generator']['url'] . '/follow?url={uri}', 'poco' => $owner['poco'], 'following' => $approfile['following'], 'followers' => $approfile['followers'], 'inbox' => $approfile['inbox'], 'outbox' => $approfile['outbox'], 'sharedinbox' => $approfile['endpoints']['sharedInbox'], 'network' => Protocol::DFRN, - 'pubkey' => $profile['upubkey'], 'baseurl' => $approfile['generator']['url'], 'gsid' => $profile['gsid'], - 'manually-approve' => in_array($profile['page-flags'], [User::PAGE_FLAGS_NORMAL, User::PAGE_FLAGS_PRVGROUP]) + 'pubkey' => $owner['upubkey'], 'baseurl' => $approfile['generator']['url'], 'gsid' => $owner['gsid'], + 'manually-approve' => in_array($owner['page-flags'], [User::PAGE_FLAGS_NORMAL, User::PAGE_FLAGS_PRVGROUP]) ]; } catch (Exception $e) { // Default values for non existing targets diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index d84baa555..375036d1c 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -370,7 +370,7 @@ class Transmitter 'owner' => $owner['url'], 'publicKeyPem' => $owner['pubkey']]; $data['endpoints'] = ['sharedInbox' => DI::baseUrl() . '/inbox']; - $data['icon'] = ['type' => 'Image', 'url' => User::getAvatarUrlForId($uid)]; + $data['icon'] = ['type' => 'Image', 'url' => User::getAvatarUrl($owner)]; $resourceid = Photo::ridFromURI($owner['photo']); if (!empty($resourceid)) { diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index 2c2309ba4..53f7e752d 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -449,7 +449,7 @@ class DFRN $attributes = ["rel" => "photo", "type" => "image/jpeg", "media:width" => Proxy::PIXEL_SMALL, "media:height" => Proxy::PIXEL_SMALL, - "href" => User::getAvatarUrlForId($owner['uid'], Proxy::SIZE_SMALL)]; + "href" => User::getAvatarUrl($owner, Proxy::SIZE_SMALL)]; if (!$public || !$hide) { $attributes["dfrn:updated"] = $picdate; diff --git a/src/Protocol/Feed.php b/src/Protocol/Feed.php index 680e8803b..90e9395b2 100644 --- a/src/Protocol/Feed.php +++ b/src/Protocol/Feed.php @@ -965,7 +965,7 @@ class Feed XML::addElement($doc, $root, "id", DI::baseUrl() . "/profile/" . $owner["nick"]); XML::addElement($doc, $root, "title", $title); XML::addElement($doc, $root, "subtitle", sprintf("Updates from %s on %s", $owner["name"], DI::config()->get('config', 'sitename'))); - XML::addElement($doc, $root, "logo", User::getAvatarUrlForId($owner['uid'], Proxy::SIZE_SMALL)); + XML::addElement($doc, $root, "logo", User::getAvatarUrl($owner, Proxy::SIZE_SMALL)); XML::addElement($doc, $root, "updated", DateTimeFormat::utcNow(DateTimeFormat::ATOM)); $author = self::addAuthor($doc, $owner); diff --git a/src/Protocol/OStatus.php b/src/Protocol/OStatus.php index 4155fb084..21f07d46b 100644 --- a/src/Protocol/OStatus.php +++ b/src/Protocol/OStatus.php @@ -1275,7 +1275,7 @@ class OStatus XML::addElement($doc, $root, "id", DI::baseUrl() . "/profile/" . $owner["nick"]); XML::addElement($doc, $root, "title", $title); XML::addElement($doc, $root, "subtitle", sprintf("Updates from %s on %s", $owner["name"], DI::config()->get('config', 'sitename'))); - XML::addElement($doc, $root, "logo", User::getAvatarUrlForId($owner['uid'], ProxyUtils::SIZE_SMALL)); + XML::addElement($doc, $root, "logo", User::getAvatarUrl($owner, ProxyUtils::SIZE_SMALL)); XML::addElement($doc, $root, "updated", DateTimeFormat::utcNow(DateTimeFormat::ATOM)); $author = self::addAuthor($doc, $owner, true); @@ -1432,7 +1432,7 @@ class OStatus "type" => "image/jpeg", // To-Do? "media:width" => ProxyUtils::PIXEL_SMALL, "media:height" => ProxyUtils::PIXEL_SMALL, - "href" => User::getAvatarUrlForId($owner['uid'], ProxyUtils::SIZE_SMALL)]; + "href" => User::getAvatarUrl($owner, ProxyUtils::SIZE_SMALL)]; XML::addElement($doc, $author, "link", "", $attributes); if (isset($owner["thumb"])) { @@ -1441,7 +1441,7 @@ class OStatus "type" => "image/jpeg", // To-Do? "media:width" => ProxyUtils::PIXEL_THUMB, "media:height" => ProxyUtils::PIXEL_THUMB, - "href" => User::getAvatarUrlForId($owner['uid'], ProxyUtils::SIZE_THUMB)]; + "href" => User::getAvatarUrl($owner, ProxyUtils::SIZE_THUMB)]; XML::addElement($doc, $author, "link", "", $attributes); } diff --git a/static/routes.config.php b/static/routes.config.php index 2c9765b3c..a76b19d88 100644 --- a/static/routes.config.php +++ b/static/routes.config.php @@ -371,9 +371,13 @@ return [ '/permission/tooltip/{type}/{id:\d+}' => [Module\PermissionTooltip::class, [R::GET]], '/photo' => [ - '/{name}' => [Module\Photo::class, [R::GET]], - '/{type}/{name}' => [Module\Photo::class, [R::GET]], - '/{type}/{customsize}/{name}' => [Module\Photo::class, [R::GET]], + '/{name}' => [Module\Photo::class, [R::GET]], + // User Id Fallback, to remove after version 2021.12 + '/{type}/{uid_ext:\d+}' => [Module\Photo::class, [R::GET]], + '/{type}/{nickname_ext}' => [Module\Photo::class, [R::GET]], + // User Id Fallback, to remove after version 2021.12 + '/{type}/{customsize}/{uid_ext:\d+}' => [Module\Photo::class, [R::GET]], + '/{type}/{customsize}/{nickname_ext}' => [Module\Photo::class, [R::GET]], ], '/pretheme' => [Module\ThemeDetails::class, [R::GET]],