3 * @copyright Copyright (C) 2010-2022, the Friendica project
5 * @license GNU AGPL version 3 or any later version
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as
9 * published by the Free Software Foundation, either version 3 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 namespace Friendica\Module\Profile;
25 use Friendica\Content\Pager;
26 use Friendica\Content\Widget;
27 use Friendica\Core\Config\Capability\IManageConfigValues;
28 use Friendica\Core\L10n;
29 use Friendica\Core\Renderer;
30 use Friendica\Core\Session\Capability\IHandleUserSessions;
31 use Friendica\Database\Database;
32 use Friendica\Model\Contact;
33 use Friendica\Model\Photo;
34 use Friendica\Model\Profile;
35 use Friendica\Model\User;
36 use Friendica\Module\Response;
37 use Friendica\Network\HTTPException;
38 use Friendica\Security\Security;
39 use Friendica\Util\Images;
40 use Friendica\Util\Profiler;
41 use Psr\Log\LoggerInterface;
43 class Photos extends \Friendica\Module\BaseProfile
45 /** @var IHandleUserSessions */
49 /** @var IManageConfigValues */
56 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 = [])
58 parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters);
60 $this->session = $session;
62 $this->config = $config;
64 $this->database = $database;
67 protected function content(array $request = []): string
69 parent::content($request);
71 if ($this->config->get('system', 'block_public') && !$this->session->isAuthenticated()) {
72 throw new HttpException\ForbiddenException($this->t('Public access denied.'));
75 $owner = User::getOwnerDataByNick($this->parameters['nickname']);
76 if (!isset($owner['account_removed']) || $owner['account_removed']) {
77 throw new HTTPException\NotFoundException($this->t('User not found.'));
80 $owner_uid = $owner['uid'];
81 $is_owner = $this->session->getLocalUserId() && ($this->session->getLocalUserId() == $owner_uid);
83 $remote_contact = false;
84 if ($this->session->getRemoteContactID($owner_uid)) {
85 $contact_id = $this->session->getRemoteContactID($owner_uid);
87 $contact = Contact::getContactForUser($contact_id, $owner_uid, ['blocked', 'pending']);
88 $remote_contact = $contact && !$contact['blocked'] && !$contact['pending'];
91 if ($owner['hidewall'] && !$is_owner && !$remote_contact) {
92 throw new HttpException\ForbiddenException($this->t('Access to this item is restricted.'));
95 $this->session->set('photo_return', $this->args->getCommand());
97 $sql_extra = Security::getPermissionsSQLByUserId($owner_uid);
99 $photo = $this->database->toArray($this->database->p(
100 "SELECT COUNT(DISTINCT `resource-id`) AS `count`
108 $total = $photo[0]['count'];
110 $pager = new Pager($this->l10n, $this->args->getQueryString(), 20);
112 $photos = $this->database->toArray($this->database->p(
115 ANY_VALUE(`id`) AS `id`,
116 ANY_VALUE(`filename`) AS `filename`,
117 ANY_VALUE(`type`) AS `type`,
118 ANY_VALUE(`album`) AS `album`,
119 max(`scale`) AS `scale`,
120 ANY_VALUE(`created`) AS `created`
125 GROUP BY `resource-id`
126 ORDER BY `created` DESC
131 $pager->getItemsPerPage()
134 $phototypes = Images::supportedTypes();
136 $photos = array_map(function ($photo) use ($owner, $phototypes) {
138 'id' => $photo['id'],
139 'link' => 'photos/' . $owner['nickname'] . '/image/' . $photo['resource-id'],
140 'title' => $this->t('View Photo'),
141 'src' => 'photo/' . $photo['resource-id'] . '-' . ((($photo['scale']) == 6) ? 4 : $photo['scale']) . '.' . $phototypes[$photo['type']],
142 'alt' => $photo['filename'],
144 'link' => 'photos/' . $owner['nickname'] . '/album/' . bin2hex($photo['album']),
145 'name' => $photo['album'],
146 'alt' => $this->t('View Album'),
151 $tpl = Renderer::getMarkupTemplate('photos_head.tpl');
152 $this->page['htmlhead'] .= Renderer::replaceMacros($tpl, [
153 '$ispublic' => $this->t('everybody')
156 if ($albums = Photo::getAlbums($owner['uid'])) {
157 $albums = array_map(function ($album) use ($owner) {
159 'text' => $album['album'],
160 'total' => $album['total'],
161 'url' => 'photos/' . $owner['nickname'] . '/album/' . bin2hex($album['album']),
162 'urlencode' => urlencode($album['album']),
163 'bin2hex' => bin2hex($album['album'])
167 $photo_albums_widget = Renderer::replaceMacros(Renderer::getMarkupTemplate('photo_albums.tpl'), [
168 '$nick' => $owner['nickname'],
169 '$title' => $this->t('Photo Albums'),
170 '$recent' => $this->t('Recent Photos'),
171 '$albums' => $albums,
172 '$upload' => [$this->t('Upload New Photos'), 'photos/' . $owner['nickname'] . '/upload'],
173 '$can_post' => $this->session->getLocalUserId() && $owner['uid'] == $this->session->getLocalUserId(),
177 $this->page['aside'] .= Widget\VCard::getHTML($owner);
179 if (!empty($photo_albums_widget)) {
180 $this->page['aside'] .= $photo_albums_widget;
183 $o = self::getTabsHTML($this->app, 'photos', $is_owner, $owner['nickname'], Profile::getByUID($owner['uid'])['hide-friends'] ?? false);
185 $tpl = Renderer::getMarkupTemplate('photos_recent.tpl');
186 $o .= Renderer::replaceMacros($tpl, [
187 '$title' => $this->t('Recent Photos'),
188 '$can_post' => $is_owner || $remote_contact && $owner['page-flags'] == User::PAGE_FLAGS_COMMUNITY,
189 '$upload' => [$this->t('Upload New Photos'), 'photos/' . $owner['nickname'] . '/upload'],
190 '$photos' => $photos,
191 '$paginate' => $pager->renderFull($total),