From 34f21b40f477605b96913571d43e721a25274209 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Wed, 23 Nov 2022 14:08:58 -0500 Subject: [PATCH] Move missing POST part of Profile\Photos from mod/photos --- mod/photos.php | 216 +----------------------- src/Module/Profile/Photos.php | 298 ++++++++++++++++++++++++++++++---- static/routes.config.php | 2 +- 3 files changed, 274 insertions(+), 242 deletions(-) diff --git a/mod/photos.php b/mod/photos.php index 8bcd9f460..d7d25c0ed 100644 --- a/mod/photos.php +++ b/mod/photos.php @@ -20,7 +20,6 @@ */ use Friendica\App; -use Friendica\Content\Feature; use Friendica\Content\Nav; use Friendica\Content\Pager; use Friendica\Content\Text\BBCode; @@ -41,18 +40,17 @@ use Friendica\Model\Profile; use Friendica\Model\Tag; use Friendica\Model\User; use Friendica\Module\BaseProfile; +use Friendica\Network\HTTPException; use Friendica\Network\Probe; -use Friendica\Object\Image; use Friendica\Protocol\Activity; +use Friendica\Security\Security; use Friendica\Util\Crypto; use Friendica\Util\DateTimeFormat; use Friendica\Util\Images; use Friendica\Util\Map; -use Friendica\Security\Security; use Friendica\Util\Strings; use Friendica\Util\Temporal; use Friendica\Util\XML; -use Friendica\Network\HTTPException; function photos_init(App $a) { @@ -565,213 +563,6 @@ function photos_post(App $a) DI::baseUrl()->redirect($_SESSION['photo_return']); return; // NOTREACHED } - - - // default post action - upload a photo - Hook::callAll('photo_post_init', $_POST); - - // Determine the album to use - $album = trim($_REQUEST['album'] ?? ''); - $newalbum = trim($_REQUEST['newalbum'] ?? ''); - - Logger::debug('album= ' . $album . ' newalbum= ' . $newalbum); - - if (!strlen($album)) { - if (strlen($newalbum)) { - $album = $newalbum; - } else { - $album = DateTimeFormat::localNow('Y'); - } - } - - /* - * We create a wall item for every photo, but we don't want to - * overwhelm the data stream with a hundred newly uploaded photos. - * So we will make the first photo uploaded to this album in the last several hours - * visible by default, the rest will become visible over time when and if - * they acquire comments, likes, dislikes, and/or tags - */ - - $r = Photo::selectToArray([], ['`album` = ? AND `uid` = ? AND `created` > ?', $album, $page_owner_uid, DateTimeFormat::utc('now - 3 hours')]); - - if (!DBA::isResult($r) || ($album == DI::l10n()->t(Photo::PROFILE_PHOTOS))) { - $visible = 1; - } else { - $visible = 0; - } - - if (!empty($_REQUEST['not_visible']) && $_REQUEST['not_visible'] !== 'false') { - $visible = 0; - } - - $ret = ['src' => '', 'filename' => '', 'filesize' => 0, 'type' => '']; - - Hook::callAll('photo_post_file', $ret); - - if (!empty($ret['src']) && !empty($ret['filesize'])) { - $src = $ret['src']; - $filename = $ret['filename']; - $filesize = $ret['filesize']; - $type = $ret['type']; - $error = UPLOAD_ERR_OK; - } elseif (!empty($_FILES['userfile'])) { - $src = $_FILES['userfile']['tmp_name']; - $filename = basename($_FILES['userfile']['name']); - $filesize = intval($_FILES['userfile']['size']); - $type = $_FILES['userfile']['type']; - $error = $_FILES['userfile']['error']; - } else { - $error = UPLOAD_ERR_NO_FILE; - } - - if ($error !== UPLOAD_ERR_OK) { - switch ($error) { - case UPLOAD_ERR_INI_SIZE: - DI::sysmsg()->addNotice(DI::l10n()->t('Image exceeds size limit of %s', ini_get('upload_max_filesize'))); - break; - case UPLOAD_ERR_FORM_SIZE: - DI::sysmsg()->addNotice(DI::l10n()->t('Image exceeds size limit of %s', Strings::formatBytes($_REQUEST['MAX_FILE_SIZE'] ?? 0))); - break; - case UPLOAD_ERR_PARTIAL: - DI::sysmsg()->addNotice(DI::l10n()->t('Image upload didn\'t complete, please try again')); - break; - case UPLOAD_ERR_NO_FILE: - DI::sysmsg()->addNotice(DI::l10n()->t('Image file is missing')); - break; - case UPLOAD_ERR_NO_TMP_DIR: - case UPLOAD_ERR_CANT_WRITE: - case UPLOAD_ERR_EXTENSION: - DI::sysmsg()->addNotice(DI::l10n()->t('Server can\'t accept new file upload at this time, please contact your administrator')); - break; - } - @unlink($src); - $foo = 0; - Hook::callAll('photo_post_end', $foo); - return; - } - - $type = Images::getMimeTypeBySource($src, $filename, $type); - - Logger::info('photos: upload: received file: ' . $filename . ' as ' . $src . ' ('. $type . ') ' . $filesize . ' bytes'); - - $maximagesize = Strings::getBytesFromShorthand(DI::config()->get('system', 'maximagesize')); - - if ($maximagesize && ($filesize > $maximagesize)) { - DI::sysmsg()->addNotice(DI::l10n()->t('Image exceeds size limit of %s', Strings::formatBytes($maximagesize))); - @unlink($src); - $foo = 0; - Hook::callAll('photo_post_end', $foo); - return; - } - - if (!$filesize) { - DI::sysmsg()->addNotice(DI::l10n()->t('Image file is empty.')); - @unlink($src); - $foo = 0; - Hook::callAll('photo_post_end', $foo); - return; - } - - Logger::debug('loading contents', ['src' => $src]); - - $imagedata = @file_get_contents($src); - - $image = new Image($imagedata, $type); - - if (!$image->isValid()) { - Logger::notice('unable to process image'); - DI::sysmsg()->addNotice(DI::l10n()->t('Unable to process image.')); - @unlink($src); - $foo = 0; - Hook::callAll('photo_post_end',$foo); - return; - } - - $exif = $image->orient($src); - @unlink($src); - - $max_length = DI::config()->get('system', 'max_image_length'); - if ($max_length > 0) { - $image->scaleDown($max_length); - } - - $width = $image->getWidth(); - $height = $image->getHeight(); - - $smallest = 0; - - $resource_id = Photo::newResource(); - - $r = Photo::store($image, $page_owner_uid, $visitor, $resource_id, $filename, $album, 0 , Photo::DEFAULT, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny); - - if (!$r) { - Logger::warning('image store failed'); - DI::sysmsg()->addNotice(DI::l10n()->t('Image upload failed.')); - return; - } - - if ($width > 640 || $height > 640) { - $image->scaleDown(640); - Photo::store($image, $page_owner_uid, $visitor, $resource_id, $filename, $album, 1, Photo::DEFAULT, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny); - $smallest = 1; - } - - if ($width > 320 || $height > 320) { - $image->scaleDown(320); - Photo::store($image, $page_owner_uid, $visitor, $resource_id, $filename, $album, 2, Photo::DEFAULT, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny); - $smallest = 2; - } - - $uri = Item::newURI(); - - // Create item container - $lat = $lon = null; - if (!empty($exif['GPS']) && Feature::isEnabled($page_owner_uid, 'photo_location')) { - $lat = Photo::getGps($exif['GPS']['GPSLatitude'], $exif['GPS']['GPSLatitudeRef']); - $lon = Photo::getGps($exif['GPS']['GPSLongitude'], $exif['GPS']['GPSLongitudeRef']); - } - - $arr = []; - if ($lat && $lon) { - $arr['coord'] = $lat . ' ' . $lon; - } - - $arr['guid'] = System::createUUID(); - $arr['uid'] = $page_owner_uid; - $arr['uri'] = $uri; - $arr['post-type'] = Item::PT_IMAGE; - $arr['wall'] = 1; - $arr['resource-id'] = $resource_id; - $arr['contact-id'] = $owner_record['id']; - $arr['owner-name'] = $owner_record['name']; - $arr['owner-link'] = $owner_record['url']; - $arr['owner-avatar'] = $owner_record['thumb']; - $arr['author-name'] = $owner_record['name']; - $arr['author-link'] = $owner_record['url']; - $arr['author-avatar'] = $owner_record['thumb']; - $arr['title'] = ''; - $arr['allow_cid'] = $str_contact_allow; - $arr['allow_gid'] = $str_group_allow; - $arr['deny_cid'] = $str_contact_deny; - $arr['deny_gid'] = $str_group_deny; - $arr['visible'] = $visible; - $arr['origin'] = 1; - - $arr['body'] = '[url=' . DI::baseUrl() . '/photos/' . $owner_record['nickname'] . '/image/' . $resource_id . ']' - . '[img]' . DI::baseUrl() . "/photo/{$resource_id}-{$smallest}.".$image->getExt() . '[/img]' - . '[/url]'; - - $item_id = Item::insert($arr); - // Update the photo albums cache - Photo::clearAlbumCache($page_owner_uid); - - Hook::callAll('photo_post_end', $item_id); - - // addon uploaders should call "exit()" within the photo_post_end hook - // if they do not wish to be redirected - - DI::baseUrl()->redirect($_SESSION['photo_return']); - // NOTREACHED } function photos_content(App $a) @@ -884,6 +675,9 @@ function photos_content(App $a) return; } + // This prevents the photo upload form to return to itself without a hint the picture has been correctly uploaded. + DI::session()->remove('photo_return'); + $selname = (!is_null($datum) && Strings::isHex($datum)) ? hex2bin($datum) : ''; $albumselect = ''; diff --git a/src/Module/Profile/Photos.php b/src/Module/Profile/Photos.php index 12c0552b6..caf0d1601 100644 --- a/src/Module/Profile/Photos.php +++ b/src/Module/Profile/Photos.php @@ -22,22 +22,29 @@ namespace Friendica\Module\Profile; use Friendica\App; +use Friendica\Content\Feature; use Friendica\Content\Pager; -use Friendica\Content\Widget; use Friendica\Core\Config\Capability\IManageConfigValues; +use Friendica\Core\Hook; use Friendica\Core\L10n; use Friendica\Core\Renderer; use Friendica\Core\Session\Capability\IHandleUserSessions; +use Friendica\Core\System; use Friendica\Database\Database; use Friendica\Model\Contact; +use Friendica\Model\Item; use Friendica\Model\Photo; use Friendica\Model\Profile; -use Friendica\Model\User; use Friendica\Module\Response; +use Friendica\Navigation\SystemMessages; use Friendica\Network\HTTPException; +use Friendica\Object\Image; use Friendica\Security\Security; +use Friendica\Util\ACLFormatter; +use Friendica\Util\DateTimeFormat; use Friendica\Util\Images; use Friendica\Util\Profiler; +use Friendica\Util\Strings; use Psr\Log\LoggerInterface; class Photos extends \Friendica\Module\BaseProfile @@ -52,16 +59,252 @@ class Photos extends \Friendica\Module\BaseProfile private $app; /** @var Database */ private $database; + /** @var SystemMessages */ + private $systemMessages; + /** @var ACLFormatter */ + private $aclFormatter; + /** @var array owner-view record */ + private $owner; - public function __construct(Database $database, App $app, IManageConfigValues $config, App\Page $page, IHandleUserSessions $session, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = []) + public function __construct(ACLFormatter $aclFormatter, SystemMessages $systemMessages, Database $database, App $app, IManageConfigValues $config, App\Page $page, IHandleUserSessions $session, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = []) { parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); - $this->session = $session; - $this->page = $page; - $this->config = $config; - $this->app = $app; - $this->database = $database; + $this->session = $session; + $this->page = $page; + $this->config = $config; + $this->app = $app; + $this->database = $database; + $this->systemMessages = $systemMessages; + $this->aclFormatter = $aclFormatter; + + $owner = Profile::load($this->app, $this->parameters['nickname'] ?? ''); + if (!$owner || $owner['account_removed'] || $owner['account_expired']) { + throw new HTTPException\NotFoundException($this->t('User not found.')); + } + + $this->owner = $owner; + } + + protected function post(array $request = []) + { + if ($this->session->getLocalUserId() != $this->owner['uid']) { + throw new HTTPException\ForbiddenException($this->t('Permission denied.')); + } + + $str_contact_allow = isset($request['contact_allow']) ? $this->aclFormatter->toString($request['contact_allow']) : $this->owner['allow_cid'] ?? ''; + $str_group_allow = isset($request['group_allow']) ? $this->aclFormatter->toString($request['group_allow']) : $this->owner['allow_gid'] ?? ''; + $str_contact_deny = isset($request['contact_deny']) ? $this->aclFormatter->toString($request['contact_deny']) : $this->owner['deny_cid'] ?? ''; + $str_group_deny = isset($request['group_deny']) ? $this->aclFormatter->toString($request['group_deny']) : $this->owner['deny_gid'] ?? ''; + + $visibility = $request['visibility'] ?? ''; + if ($visibility === 'public') { + // The ACL selector introduced in version 2019.12 sends ACL input data even when the Public visibility is selected + $str_contact_allow = $str_group_allow = $str_contact_deny = $str_group_deny = ''; + } else if ($visibility === 'custom') { + // Since we know from the visibility parameter the item should be private, we have to prevent the empty ACL + // case that would make it public. So we always append the author's contact id to the allowed contacts. + // See https://github.com/friendica/friendica/issues/9672 + $str_contact_allow .= $this->aclFormatter->toString(Contact::getPublicIdByUserId($this->owner['uid'])); + } + + // default post action - upload a photo + Hook::callAll('photo_post_init', $request); + + // Determine the album to use + $album = trim($request['album'] ?? ''); + $newalbum = trim($request['newalbum'] ?? ''); + + $this->logger->debug('album= ' . $album . ' newalbum= ' . $newalbum); + + $album = $album ?: $newalbum ?: DateTimeFormat::localNow('Y'); + + /* + * We create a wall item for every photo, but we don't want to + * overwhelm the data stream with a hundred newly uploaded photos. + * So we will make the first photo uploaded to this album in the last several hours + * visible by default, the rest will become visible over time when and if + * they acquire comments, likes, dislikes, and/or tags + */ + + $r = Photo::selectToArray([], ['`album` = ? AND `uid` = ? AND `created` > ?', $album, $this->owner['uid'], DateTimeFormat::utc('now - 3 hours')]); + if (!$r || ($album == $this->t(Photo::PROFILE_PHOTOS))) { + $visible = 1; + } else { + $visible = 0; + } + + if (!empty($request['not_visible']) && $request['not_visible'] !== 'false') { + $visible = 0; + } + + $ret = ['src' => '', 'filename' => '', 'filesize' => 0, 'type' => '']; + + Hook::callAll('photo_post_file', $ret); + + if (!empty($ret['src']) && !empty($ret['filesize'])) { + $src = $ret['src']; + $filename = $ret['filename']; + $filesize = $ret['filesize']; + $type = $ret['type']; + $error = UPLOAD_ERR_OK; + } elseif (!empty($_FILES['userfile'])) { + $src = $_FILES['userfile']['tmp_name']; + $filename = basename($_FILES['userfile']['name']); + $filesize = intval($_FILES['userfile']['size']); + $type = $_FILES['userfile']['type']; + $error = $_FILES['userfile']['error']; + } else { + $error = UPLOAD_ERR_NO_FILE; + } + + if ($error !== UPLOAD_ERR_OK) { + switch ($error) { + case UPLOAD_ERR_INI_SIZE: + $this->systemMessages->addNotice($this->t('Image exceeds size limit of %s', ini_get('upload_max_filesize'))); + break; + case UPLOAD_ERR_FORM_SIZE: + $this->systemMessages->addNotice($this->t('Image exceeds size limit of %s', Strings::formatBytes($request['MAX_FILE_SIZE'] ?? 0))); + break; + case UPLOAD_ERR_PARTIAL: + $this->systemMessages->addNotice($this->t('Image upload didn\'t complete, please try again')); + break; + case UPLOAD_ERR_NO_FILE: + $this->systemMessages->addNotice($this->t('Image file is missing')); + break; + case UPLOAD_ERR_NO_TMP_DIR: + case UPLOAD_ERR_CANT_WRITE: + case UPLOAD_ERR_EXTENSION: + $this->systemMessages->addNotice($this->t('Server can\'t accept new file upload at this time, please contact your administrator')); + break; + } + @unlink($src); + $foo = 0; + Hook::callAll('photo_post_end', $foo); + return; + } + + $type = Images::getMimeTypeBySource($src, $filename, $type); + + $this->logger->info('photos: upload: received file: ' . $filename . ' as ' . $src . ' ('. $type . ') ' . $filesize . ' bytes'); + + $maximagesize = Strings::getBytesFromShorthand($this->config->get('system', 'maximagesize')); + + if ($maximagesize && ($filesize > $maximagesize)) { + $this->systemMessages->addNotice($this->t('Image exceeds size limit of %s', Strings::formatBytes($maximagesize))); + @unlink($src); + $foo = 0; + Hook::callAll('photo_post_end', $foo); + return; + } + + if (!$filesize) { + $this->systemMessages->addNotice($this->t('Image file is empty.')); + @unlink($src); + $foo = 0; + Hook::callAll('photo_post_end', $foo); + return; + } + + $this->logger->debug('loading contents', ['src' => $src]); + + $imagedata = @file_get_contents($src); + + $image = new Image($imagedata, $type); + + if (!$image->isValid()) { + $this->logger->notice('unable to process image'); + $this->systemMessages->addNotice($this->t('Unable to process image.')); + @unlink($src); + $foo = 0; + Hook::callAll('photo_post_end',$foo); + return; + } + + $exif = $image->orient($src); + @unlink($src); + + $max_length = $this->config->get('system', 'max_image_length'); + if ($max_length > 0) { + $image->scaleDown($max_length); + } + + $width = $image->getWidth(); + $height = $image->getHeight(); + + $smallest = 0; + + $resource_id = Photo::newResource(); + + $r = Photo::store($image, $this->owner['uid'], 0, $resource_id, $filename, $album, 0 , Photo::DEFAULT, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny); + + if (!$r) { + $this->logger->warning('image store failed'); + $this->systemMessages->addNotice($this->t('Image upload failed.')); + return; + } + + if ($width > 640 || $height > 640) { + $image->scaleDown(640); + Photo::store($image, $this->owner['uid'], 0, $resource_id, $filename, $album, 1, Photo::DEFAULT, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny); + $smallest = 1; + } + + if ($width > 320 || $height > 320) { + $image->scaleDown(320); + Photo::store($image, $this->owner['uid'], 0, $resource_id, $filename, $album, 2, Photo::DEFAULT, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny); + $smallest = 2; + } + + $uri = Item::newURI(); + + // Create item container + $lat = $lon = null; + if (!empty($exif['GPS']) && Feature::isEnabled($this->owner['uid'], 'photo_location')) { + $lat = Photo::getGps($exif['GPS']['GPSLatitude'], $exif['GPS']['GPSLatitudeRef']); + $lon = Photo::getGps($exif['GPS']['GPSLongitude'], $exif['GPS']['GPSLongitudeRef']); + } + + $arr = []; + if ($lat && $lon) { + $arr['coord'] = $lat . ' ' . $lon; + } + + $arr['guid'] = System::createUUID(); + $arr['uid'] = $this->owner['uid']; + $arr['uri'] = $uri; + $arr['post-type'] = Item::PT_IMAGE; + $arr['wall'] = 1; + $arr['resource-id'] = $resource_id; + $arr['contact-id'] = $this->owner['id']; + $arr['owner-name'] = $this->owner['name']; + $arr['owner-link'] = $this->owner['url']; + $arr['owner-avatar'] = $this->owner['thumb']; + $arr['author-name'] = $this->owner['name']; + $arr['author-link'] = $this->owner['url']; + $arr['author-avatar'] = $this->owner['thumb']; + $arr['title'] = ''; + $arr['allow_cid'] = $str_contact_allow; + $arr['allow_gid'] = $str_group_allow; + $arr['deny_cid'] = $str_contact_deny; + $arr['deny_gid'] = $str_group_deny; + $arr['visible'] = $visible; + $arr['origin'] = 1; + + $arr['body'] = '[url=' . $this->baseUrl . '/photos/' . $this->owner['nickname'] . '/image/' . $resource_id . ']' + . '[img]' . $this->baseUrl . "/photo/{$resource_id}-{$smallest}.".$image->getExt() . '[/img]' + . '[/url]'; + + $item_id = Item::insert($arr); + // Update the photo albums cache + Photo::clearAlbumCache($this->owner['uid']); + + Hook::callAll('photo_post_end', $item_id); + + // addon uploaders should call "exit()" within the photo_post_end hook + // if they do not wish to be redirected + + $this->baseUrl->redirect($this->session->get('photo_return') ?? 'profile/' . $this->owner['nickname'] . '/photos'); } protected function content(array $request = []): string @@ -72,13 +315,8 @@ class Photos extends \Friendica\Module\BaseProfile throw new HttpException\ForbiddenException($this->t('Public access denied.')); } - $owner = Profile::load($this->app, $this->parameters['nickname'] ?? ''); - if (!$owner || $owner['account_removed'] || $owner['account_expired']) { - throw new HTTPException\NotFoundException($this->t('User not found.')); - } - - $owner_uid = $owner['uid']; - $is_owner = $this->session->getLocalUserId() && ($this->session->getLocalUserId() == $owner_uid); + $owner_uid = $this->owner['uid']; + $is_owner = $this->session->getLocalUserId() == $owner_uid; $remote_contact = false; if ($this->session->getRemoteContactID($owner_uid)) { @@ -88,7 +326,7 @@ class Photos extends \Friendica\Module\BaseProfile $remote_contact = $contact && !$contact['blocked'] && !$contact['pending']; } - if ($owner['hidewall'] && !$this->session->isAuthenticated()) { + if ($this->owner['hidewall'] && !$this->session->isAuthenticated()) { $this->baseUrl->redirect('profile/' . $owner['nickname'] . '/restricted'); } @@ -102,7 +340,7 @@ class Photos extends \Friendica\Module\BaseProfile WHERE `uid` = ? AND `photo-type` = ? $sql_extra", - $owner['uid'], + $this->owner['uid'], Photo::DEFAULT, )); $total = $photo[0]['count']; @@ -125,7 +363,7 @@ class Photos extends \Friendica\Module\BaseProfile GROUP BY `resource-id` ORDER BY `created` DESC LIMIT ? , ?", - $owner['uid'], + $this->owner['uid'], Photo::DEFAULT, $pager->getStart(), $pager->getItemsPerPage() @@ -133,15 +371,15 @@ class Photos extends \Friendica\Module\BaseProfile $phototypes = Images::supportedTypes(); - $photos = array_map(function ($photo) use ($owner, $phototypes) { + $photos = array_map(function ($photo) use ($phototypes) { return [ 'id' => $photo['id'], - 'link' => 'photos/' . $owner['nickname'] . '/image/' . $photo['resource-id'], + 'link' => 'photos/' . $this->owner['nickname'] . '/image/' . $photo['resource-id'], 'title' => $this->t('View Photo'), 'src' => 'photo/' . $photo['resource-id'] . '-' . ((($photo['scale']) == 6) ? 4 : $photo['scale']) . '.' . $phototypes[$photo['type']], 'alt' => $photo['filename'], 'album' => [ - 'link' => 'photos/' . $owner['nickname'] . '/album/' . bin2hex($photo['album']), + 'link' => 'photos/' . $this->owner['nickname'] . '/album/' . bin2hex($photo['album']), 'name' => $photo['album'], 'alt' => $this->t('View Album'), ], @@ -153,24 +391,24 @@ class Photos extends \Friendica\Module\BaseProfile '$ispublic' => $this->t('everybody') ]); - if ($albums = Photo::getAlbums($owner['uid'])) { - $albums = array_map(function ($album) use ($owner) { + if ($albums = Photo::getAlbums($this->owner['uid'])) { + $albums = array_map(function ($album) { return [ 'text' => $album['album'], 'total' => $album['total'], - 'url' => 'photos/' . $owner['nickname'] . '/album/' . bin2hex($album['album']), + 'url' => 'photos/' . $this->owner['nickname'] . '/album/' . bin2hex($album['album']), 'urlencode' => urlencode($album['album']), 'bin2hex' => bin2hex($album['album']) ]; }, $albums); $photo_albums_widget = Renderer::replaceMacros(Renderer::getMarkupTemplate('photo_albums.tpl'), [ - '$nick' => $owner['nickname'], + '$nick' => $this->owner['nickname'], '$title' => $this->t('Photo Albums'), '$recent' => $this->t('Recent Photos'), '$albums' => $albums, - '$upload' => [$this->t('Upload New Photos'), 'photos/' . $owner['nickname'] . '/upload'], - '$can_post' => $this->session->getLocalUserId() && $owner['uid'] == $this->session->getLocalUserId(), + '$upload' => [$this->t('Upload New Photos'), 'photos/' . $this->owner['nickname'] . '/upload'], + '$can_post' => $this->session->getLocalUserId() && $this->owner['uid'] == $this->session->getLocalUserId(), ]); } @@ -178,13 +416,13 @@ class Photos extends \Friendica\Module\BaseProfile $this->page['aside'] .= $photo_albums_widget; } - $o = self::getTabsHTML('photos', $is_owner, $owner['nickname'], Profile::getByUID($owner['uid'])['hide-friends'] ?? false); + $o = self::getTabsHTML('photos', $is_owner, $this->owner['nickname'], Profile::getByUID($this->owner['uid'])['hide-friends'] ?? false); $tpl = Renderer::getMarkupTemplate('photos_recent.tpl'); $o .= Renderer::replaceMacros($tpl, [ '$title' => $this->t('Recent Photos'), - '$can_post' => $is_owner || $remote_contact && $owner['page-flags'] == User::PAGE_FLAGS_COMMUNITY, - '$upload' => [$this->t('Upload New Photos'), 'photos/' . $owner['nickname'] . '/upload'], + '$can_post' => $is_owner, + '$upload' => [$this->t('Upload New Photos'), 'photos/' . $this->owner['nickname'] . '/upload'], '$photos' => $photos, '$paginate' => $pager->renderFull($total), ]); diff --git a/static/routes.config.php b/static/routes.config.php index b4ce8f79e..f33cd9581 100644 --- a/static/routes.config.php +++ b/static/routes.config.php @@ -35,7 +35,7 @@ $profileRoutes = [ '/contacts/common' => [Module\Profile\Common::class, [R::GET]], '/contacts[/{type}]' => [Module\Profile\Contacts::class, [R::GET]], '/media' => [Module\Profile\Media::class, [R::GET]], - '/photos' => [Module\Profile\Photos::class, [R::GET ]], + '/photos' => [Module\Profile\Photos::class, [R::GET, R::POST]], '/profile' => [Module\Profile\Profile::class, [R::GET]], '/remote_follow' => [Module\Profile\RemoteFollow::class, [R::GET, R::POST]], '/restricted' => [Module\Profile\Restricted::class, [R::GET ]],