<?php
/**
* Created by simpson <simpsonwork@gmail.com>
* Date: 2019-05-02
* Time: 13:27
*/
namespace App\EventSubscriber;
use App\Service\Features;
use Intervention\Image\ImageManagerStatic as Image;
use League\Flysystem\FilesystemOperator;
use Oneup\UploaderBundle\Event\PostUploadEvent;
use Oneup\UploaderBundle\Event\PreUploadEvent;
use Oneup\UploaderBundle\Event\ValidationEvent;
use Oneup\UploaderBundle\Uploader\Exception\ValidationException;
use Oneup\UploaderBundle\Uploader\File\FileInterface;
use Oneup\UploaderBundle\UploadEvents;
use Symfony\Component\Asset\Packages;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\File\File;
class FileUploadSubscriber implements EventSubscriberInterface
{
private static array $allowedPhotoExtensions = ['jpg', 'jpeg', 'png'];
private static array $allowedVideoExtensions = ['mp4', 'flv', 'mov'];
private int $minAvatarWidth;
private int $minAvatarHeight;
private int $maxImageSideSize;
public function __construct(
private Packages $assetPackage,
ParameterBagInterface $parameterBag,
private Features $features,
private FilesystemOperator $tmpFilesystem
)
{
$this->minAvatarWidth = (int)$parameterBag->get('app.profile.avatar.min_width');
$this->minAvatarHeight = (int)$parameterBag->get('app.profile.avatar.min_height');
$this->maxImageSideSize = (int)$parameterBag->get('app.profile.image.max_side_size');
}
public function returnFilename(PostUploadEvent $event)
{
/** @var File $file */
$file = $event->getFile();
$response = $event->getResponse();
/*
// Path manipulations for orphanage
$fullPath = $file->getPath();
$firstLevelDirectory = basename($fullPath);
$secondLevelDirectory = basename(dirname($fullPath));
$filename = $file->getFilename();
$response['filename'] = "$secondLevelDirectory/$firstLevelDirectory/$filename";
*/
$response['filename'] = $this->getPathname($file);
return $response['filename'];
}
protected function getPathname(FileInterface $file)
{
$filename = $file->getPathname();
if('png' === $file->getExtension()) {
$filename = str_replace('.' . $file->getExtension(), '.jpg', $filename);
}
return $filename;
}
public function validateAvatar(ValidationEvent $event): void
{
$file = $event->getFile();
list($width, $height) = getimagesize($file->getPathname());
if($width < $this->minAvatarWidth || $height < $this->minAvatarHeight)
throw new ValidationException('Image too small.');
$this->validatePhotoFile($event);
}
public function validatePhotoFile(ValidationEvent $event): void
{
$file = $event->getFile();
$extension = strtolower($file->getExtension());
if (!in_array($extension, self::$allowedPhotoExtensions, true)) {
throw new ValidationException('This kind of files is not allowed.');
}
}
public function validateVideoFile(ValidationEvent $event): void
{
$file = $event->getFile();
$extension = strtolower($file->getExtension());
if (!in_array($extension, self::$allowedVideoExtensions, true)) {
throw new ValidationException('This kind of files is not allowed.');
}
}
public function validateApprovalMediaFile(ValidationEvent $event): void
{
$file = $event->getFile();
$extension = strtolower($file->getExtension());
if (!in_array($extension, true === $this->features->approval_by_video() ? self::$allowedVideoExtensions : self::$allowedPhotoExtensions, true)) {
throw new ValidationException('This kind of files is not allowed.');
}
if($event->getFile()->getSize() > 209715200) {
throw new ValidationException('Video is too big.');
}
}
public function postUploadUserAvatar(PostUploadEvent $event): void
{
$response = $event->getResponse();
$pathname = $this->returnFilename($event);
$response['path'] = $this->assetPackage->getUrl($pathname, 'user_media');
}
public function postUploadProfileAvatar(PostUploadEvent $event): void
{
$response = $event->getResponse();
$pathname = $this->returnFilename($event);
$response['path'] = $this->assetPackage->getUrl($pathname, 'profile_media_avatar');
}
public function postUploadSaloonThumb(PostUploadEvent $event): void
{
$response = $event->getResponse();
$pathname = $this->returnFilename($event);
$response['path'] = $this->assetPackage->getUrl($pathname, 'saloon_media_thumb');
}
protected function processFileParameters(File $file)
{
if(str_starts_with($file->getMimeType(), 'video/'))
return;
$image = Image::make($this->tmpFilesystem->read($file->getFilename()));
$maxSideSize = max($image->width(), $image->height());
if($maxSideSize > $this->maxImageSideSize) {
if ($maxSideSize == $image->width()) {
$newWidth = $this->maxImageSideSize;
$newHeight = $newWidth * $image->height() / $image->width();
} else {
$newHeight = $this->maxImageSideSize;
$newWidth = $newHeight * $image->width() / $image->height();
}
$image->resize($newWidth, $newHeight);
}
$this->tmpFilesystem->write($file->getFilename(), $image->encode('jpg'));
}
public function preUpload(PreUploadEvent $event): void
{
/** @var File $file */
$file = $event->getFile();
$this->processFileParameters($file);
}
/**
* @inheritDoc
*/
public static function getSubscribedEvents()
{
return [
PreUploadEvent::NAME => 'preUpload',
UploadEvents::postUpload('profile_media_avatar') => 'postUploadProfileAvatar',
UploadEvents::postUpload('profile_photo') => 'returnFilename',
UploadEvents::postUpload('profile_selfie') => 'returnFilename',
UploadEvents::postUpload('profile_video') => 'returnFilename',
UploadEvents::postUpload('profile_media_approval') => 'returnFilename',
UploadEvents::postUpload('saloon_media') => 'returnFilename',
UploadEvents::postUpload('saloon_media_thumb') => 'postUploadSaloonThumb',
UploadEvents::postUpload('saloon_media_video') => 'returnFilename',
UploadEvents::postUpload('user_media') => 'postUploadUserAvatar',
UploadEvents::postUpload('tmp_media') => 'returnFilename',
UploadEvents::postUpload('process_queue') => 'returnFilename',
UploadEvents::validation('profile_media_avatar') => 'validateAvatar',
UploadEvents::validation('profile_photo') => 'validatePhotoFile',
UploadEvents::validation('profile_selfie') => 'validatePhotoFile',
UploadEvents::validation('profile_video') => 'validateVideoFile',
UploadEvents::validation('profile_media_approval') => 'validateApprovalMediaFile',
UploadEvents::validation('saloon_media') => 'validatePhotoFile',
UploadEvents::validation('saloon_media_thumb') => 'validateAvatar',
UploadEvents::validation('saloon_media_video') => 'validateVideoFile',
UploadEvents::validation('user_media') => 'validateAvatar',
UploadEvents::validation('tmp_media') => 'validateVideoFile',
UploadEvents::validation('process_queue') => 'validateVideoFile',
];
}
}