<?php
/*
* This file is part of the adrec-platform package.
*
* (c) Benjamin Georgeault <https://www.pressop.eu>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\EventSubscriber\Account;
use App\Entity\Channel\Channel;
use App\Entity\Channel\Image;
use App\Entity\Account\User;
use App\Repository\Account\UserRepository;
use App\Repository\Channel\ChannelRepository;
use App\Service\Account\UserAvatar;
use Doctrine\ORM\EntityManagerInterface;
use Liip\ImagineBundle\Imagine\Cache\CacheManager;
use Liip\ImagineBundle\Imagine\Data\DataManager;
use Liip\ImagineBundle\Imagine\Filter\FilterManager;
use Oneup\UploaderBundle\Event\PostPersistEvent;
use Oneup\UploaderBundle\Event\PreUploadEvent;
use Oneup\UploaderBundle\UploadEvents;
use Ramsey\Uuid\Uuid;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Finder\SplFileInfo;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Security;
/**
* Class AvatarSubscriber
*
*/
class AvatarSubscriber implements EventSubscriberInterface
{
/**
* @var string[]
*/
private static $filters = [
'avatar_thumbnail',
];
private EntityManagerInterface $em;
private TokenStorageInterface $token;
private Filesystem $filesystem;
private string $avatarUploadDir;
private string $avatarUploadUri;
private CacheManager $cacheManager;
private DataManager $dataManager;
private FilterManager $filterManager;
private UserAvatar $userAvatar;
private UserRepository $userRepository;
private Security $security;
public function __construct(EntityManagerInterface $em, TokenStorageInterface $token, Filesystem $filesystem, string $avatarUploadDir, string $avatarUploadUri, CacheManager $cacheManager, DataManager $dataManager, FilterManager $filterManager, UserAvatar $userAvatar, UserRepository $userRepository, Security $security)
{
$this->em = $em;
$this->token = $token;
$this->filesystem = $filesystem;
$this->avatarUploadDir = $avatarUploadDir;
$this->avatarUploadUri = $avatarUploadUri;
$this->cacheManager = $cacheManager;
$this->dataManager = $dataManager;
$this->filterManager = $filterManager;
$this->userAvatar = $userAvatar;
$this->userRepository = $userRepository;
$this->security = $security;
}
/**
* @return string[]
*/
public static function getSubscribedEvents(): array
{
return [
UploadEvents::PRE_UPLOAD.'.user_avatar' => 'onPreUpload',
UploadEvents::POST_PERSIST.'.user_avatar' => 'onFinishedUpload',
];
}
/**
* @param PreUploadEvent $event
*/
public function onPreUpload(PreUploadEvent $event)
{
$request = $event->getRequest();
if (!$request->headers->has('user-id')) {
throw new BadRequestHttpException();
}
$user = $this->getUser();
$userFromQuery = $request->headers->get('user-id');
if ($user->getId() !== $userFromQuery && !$this->security->isGranted('ROLE_ADMIN')) {
throw new AccessDeniedHttpException();
}
if (null === $user = $this->userRepository->find($userFromQuery)) {
throw new NotFoundHttpException(sprintf('Cannot found user for id "%s".', $userFromQuery));
}
if (null !== $fileName = $this->userAvatar->getAvatarUrl($user)) {
$finder = new Finder();
$files = $finder->name($fileName)->files()->in($this->avatarUploadDir);
/** @var SplFileInfo $file */
foreach ($files as $file) {
$this->filesystem->remove($file->getPathname());
$this->cacheManager->remove(sprintf(
'%s/%s',
$this->avatarUploadUri,
$fileName
), self::$filters);
}
}
}
/**
* @param PostPersistEvent $event
*/
public function onFinishedUpload(PostPersistEvent $event)
{
/** @var \Oneup\UploaderBundle\Uploader\File\FileInterface $file */
$file = $event->getFile();
$request = $event->getRequest();
if (!$request->headers->has('user-id')) {
throw new BadRequestHttpException();
}
$user = $this->getUser();
$userFromQuery = $request->headers->get('user-id');
if ($user->getId() !== $userFromQuery && !$this->security->isGranted('ROLE_ADMIN')) {
throw new AccessDeniedHttpException();
}
if (null === $user = $this->userRepository->find($userFromQuery)) {
throw new NotFoundHttpException(sprintf('Cannot found user for id "%s".', $userFromQuery));
}
$user->setAvatar(true)->setAvatarFile($file->getBasename());
$this->em->persist($user);
$this->em->flush();
$uri = sprintf(
'%s/%s',
$this->avatarUploadUri,
$file->getBasename()
);
$response = $event->getResponse();
$response['image'] = $uri;
$thumbnails = [];
foreach (self::$filters as $filter) {
try {
$this->cacheManager->store($this->filterManager->applyFilter(
$this->dataManager->find($filter, $uri), $filter), $uri, $filter
);
$thumbnails[$filter] = $this->cacheManager->getBrowserPath($uri, $filter);
} catch (\Exception $e) {
}
}
$response['thumbnails'] = $thumbnails;
}
/**
* @return User|null
*/
private function getUser(): ?User
{
if (null === $token = $this->token->getToken()) {
return null;
}
if (null === $user = $token->getUser()) {
return null;
}
if (!($user instanceof User)) {
throw new ServiceUnavailableHttpException();
}
return $user;
}
}