[Avatar] Store as regular attachments

This commit is contained in:
Diogo Peralta Cordeiro 2021-08-05 03:15:07 +01:00
parent c155f4e30e
commit 289eef5cf7
Signed by: diogo
GPG Key ID: 18D2D35001FBFAB0
2 changed files with 35 additions and 37 deletions

View File

@ -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;
}
}
}

View File

@ -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()]);
}
}