From 0c612bddbe9bc7b2b805c8b160cecd9beac7d33c Mon Sep 17 00:00:00 2001 From: Diogo Peralta Cordeiro Date: Thu, 5 Aug 2021 03:15:07 +0100 Subject: [PATCH] [Avatar] Store as regular attachments --- components/Avatar/Avatar.php | 52 +++++++++++++------------ components/Avatar/Controller/Avatar.php | 20 ++++------ 2 files changed, 35 insertions(+), 37 deletions(-) diff --git a/components/Avatar/Avatar.php b/components/Avatar/Avatar.php index 00478e4d5c..7782dcc234 100644 --- a/components/Avatar/Avatar.php +++ b/components/Avatar/Avatar.php @@ -24,10 +24,10 @@ use App\Core\DB\DB; use App\Core\Event; use App\Core\GSFile; use App\Core\Modules\Component; +use App\Core\Router\Router; use App\Util\Common; use Component\Avatar\Controller as C; use Component\Avatar\Exception\NoAvatarException; -use Exception; use Symfony\Component\Asset\Package; use Symfony\Component\Asset\VersionStrategy\EmptyVersionStrategy; use Symfony\Component\HttpFoundation\Request; @@ -67,21 +67,22 @@ class Avatar extends Component return Event::next; } - public function onDeleteCachedAvatar(int $gsactor_id) + public function onAvatarUpdate(int $gsactor_id): bool { Cache::delete('avatar-' . $gsactor_id); Cache::delete('avatar-url-' . $gsactor_id); Cache::delete('avatar-file-info-' . $gsactor_id); + return Event::next; } // UTILS ---------------------------------- /** - * Get the avatar associated with the given nickname + * Get the avatar associated with the given GSActor id */ public static function getAvatar(?int $gsactor_id = null): Entity\Avatar { - $gsactor_id = $gsactor_id ?: Common::userNickname(); + $gsactor_id = $gsactor_id ?: Common::userId(); return GSFile::error(NoAvatarException::class, $gsactor_id, Cache::get("avatar-{$gsactor_id}", @@ -93,18 +94,19 @@ class Avatar extends Component } /** - * Get the cached avatar associated with the given nickname, or the current user if not given + * Get the cached avatar associated with the given GSActor id, or the current user if not given */ public static function getAvatarUrl(?int $gsactor_id = null): string { $gsactor_id = $gsactor_id ?: Common::userId(); return Cache::get("avatar-url-{$gsactor_id}", function () use ($gsactor_id) { - try { - return self::getAvatar($gsactor_id)->getUrl(); - } catch (NoAvatarException $e) { + $attachment_id = self::getAvatarFileInfo($gsactor_id)['id']; + if ($attachment_id !== null) { + return Router::url('attachment_view', ['id' => $attachment_id]); + } else { + $package = new Package(new EmptyVersionStrategy()); + return $package->getUrl(Common::config('avatar', 'default')); } - $package = new Package(new EmptyVersionStrategy()); - return $package->getUrl(Common::config('avatar', 'default')); }); } @@ -116,22 +118,22 @@ class Avatar extends Component */ public static function getAvatarFileInfo(int $gsactor_id): array { - try { - $res = GSFile::error(NoAvatarException::class, - $gsactor_id, - Cache::get("avatar-file-info-{$gsactor_id}", - function () use ($gsactor_id) { - return DB::dql('select f.file_hash, f.mimetype, f.title ' . - 'from App\Entity\Attachment f ' . - 'join Component\Avatar\Entity\Avatar a with f.id = a.attachment_id ' . - 'where a.gsactor_id = :gsactor_id', - ['gsactor_id' => $gsactor_id]); - })); - $res['file_path'] = Entity\Avatar::getFilePathStatic($res['file_hash']); - return $res; - } catch (Exception $e) { + $res = Cache::get("avatar-file-info-{$gsactor_id}", + function () use ($gsactor_id) { + return DB::dql('select f.id, f.filename, f.mimetype, f.title ' . + 'from App\Entity\Attachment f ' . + 'join Component\Avatar\Entity\Avatar a with f.id = a.attachment_id ' . + 'where a.gsactor_id = :gsactor_id', + ['gsactor_id' => $gsactor_id]); + } + ); + if ($res === []) { // Avatar not found $filepath = INSTALLDIR . '/public/assets/default-avatar.svg'; - return ['file_path' => $filepath, 'mimetype' => 'image/svg+xml', 'title' => null]; + return ['id' => null, 'file_path' => $filepath, 'mimetype' => 'image/svg+xml', 'title' => null]; + } else { + $res = $res[0]; // A user must always only have one avatar. + $res['file_path'] = DB::findOneBy('attachment', ['id' => $res['id']])->getPath(); + return $res; } } } diff --git a/components/Avatar/Controller/Avatar.php b/components/Avatar/Controller/Avatar.php index 2cedf4a0e0..adea96a18b 100644 --- a/components/Avatar/Controller/Avatar.php +++ b/components/Avatar/Controller/Avatar.php @@ -29,6 +29,7 @@ use App\Core\GSFile; use App\Core\GSFile as M; use function App\Core\I18n\_m; use App\Core\Log; +use App\Core\Security; use App\Util\Common; use App\Util\Exception\ClientException; use App\Util\Exception\NotFoundException; @@ -81,7 +82,7 @@ class Avatar extends Controller try { $avatar = DB::findOneBy('avatar', ['gsactor_id' => $gsactor_id]); $avatar->delete(); - Event::handle('DeleteCachedAvatar', [$user->getId()]); + Event::handle('AvatarUpdate', [$user->getId()]); } catch (NotFoundException) { $form->addError(new FormError(_m('No avatar set, so cannot delete'))); } @@ -107,25 +108,20 @@ class Avatar extends Controller } $attachment = GSFile::validateAndStoreFileAsAttachment( $file, - dest_dir: Common::config('avatar', 'dir'), + dest_dir: Common::config('attachments', 'dir'), actor_id: $gsactor_id, - title: _m("Avatar for Actor {$gsactor_id}"), + title: Security::sanitize($file->getClientOriginalName()), is_local: true ); - // Must get old id before inserting another one - $old_attachment = null; - $avatar = DB::find('avatar', ['gsactor_id' => $gsactor_id]); - $old_attachment = $avatar?->delete(); + // Delete current avatar if there's one + $avatar = DB::find('avatar', ['gsactor_id' => $gsactor_id]); + $avatar?->delete(); DB::persist($attachment); // Can only get new id after inserting DB::flush(); DB::persist(AvatarEntity::create(['gsactor_id' => $gsactor_id, 'attachment_id' => $attachment->getId()])); DB::flush(); - // Only delete files if the commit went through - if ($old_attachment != null) { - @unlink($old_attachment); - } - Event::handle('DeleteCachedAvatar', [$user->getId()]); + Event::handle('AvatarUpdate', [$user->getId()]); } }