<?php declare(strict_types=1);
namespace App\Subscriber;
use App\Validator\Constraints\Url;
use App\Validator\Constraints\Video;
use Oneup\UploaderBundle\Event\ValidationEvent;
use Oneup\UploaderBundle\Uploader\Exception\ValidationException;
use Oneup\UploaderBundle\UploadEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Validator\Constraints\File;
use Symfony\Component\Validator\Constraints\Image;
use Symfony\Component\Validator\ConstraintViolationInterface;
use Symfony\Component\Validator\ConstraintViolationListInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;
use UploadsBundle\Event\ValidationUrlEvent;
class ValidationSubscriber implements EventSubscriberInterface
{
private ValidatorInterface $validator;
/**
* @var string[]
*/
private array $allowedUrls;
/**
* @param string[] $allowedUrls
*/
public function __construct(ValidatorInterface $validator, array $allowedUrls)
{
$this->validator = $validator;
$this->allowedUrls = $allowedUrls;
}
public function onValidate(ValidationEvent $event): void
{
$constraints = [];
switch ($event->getRequest()->get('domain')) {
case 'project_preview':
case 'project_gallery':
case 'deal_preview':
case 'deal_gallery':
case 'shop_video_preview':
case 'shop_video_gallery':
case 'tag_preview':
case 'performer_preview':
case 'performer_image':
case 'feed_gallery':
case 'message_preview':
case 'message_gallery':
$constraints[] = new Image([
'maxSize' => '200M',
'mimeTypes' => ['image/jpg', 'image/jpeg', 'image/png'],
'mimeTypesMessage' => 'image.mimeTypesMessage',
'minWidth' => 200,
'minHeight' => 200,
]);
break;
case 'deal_video':
case 'deal_trailer':
case 'project_video':
case 'project_trailer':
case 'project_custom_video':
case 'shop_video':
case 'shop_video_trailer':
case 'message_video':
$constraints[] = new File([
'mimeTypes' => [
'video/*',
'audio/mp4',
'application/x-troff-msvideo', // avi
],
'mimeTypesMessage' => 'video.mimeTypesMessage',
]);
$constraints[] = new Video([
'minDuration' => '60',
]);
break;
case 'feed_trailer':
$constraints[] = new File([
'mimeTypes' => [
'video/*',
'audio/mp4',
'application/x-troff-msvideo', // avi
],
'mimeTypesMessage' => 'video.mimeTypesMessage',
]);
$constraints[] = new Video([
'minDuration' => '2',
'maxDuration' => '198',
]);
break;
default:
throw new ValidationException('Unknown domain in ' . __FILE__);
}
$violations = $this->validator->validate($event->getFile()->getPathname(), $constraints);
if ($violations->count() > 0) {
throw new ValidationException($this->createMessage($violations));
}
}
public function onValidateUrl(ValidationUrlEvent $event): void
{
$constraints = [];
switch ($event->getRequest()->get('domain')) {
case 'deal_preview':
case 'project_preview':
case 'shop_video_preview':
$hosts = array_map(static function ($url) {
return strpos($url, 'http') !== false ? parse_url($url, PHP_URL_HOST) : $url;
}, $this->allowedUrls);
$constraints[] = new Url(['hosts' => $hosts]);
break;
default:
throw new ValidationException('Unknown domain');
}
$violations = $this->validator->validate($event->getUrl(), $constraints);
if ($violations->count() > 0) {
throw new ValidationException($this->createMessage($violations));
}
}
/**
* @param ConstraintViolationListInterface<ConstraintViolationInterface> $violations List of violations
*/
private function createMessage(ConstraintViolationListInterface $violations): string
{
$messages = [];
foreach ($violations as $violation) {
$messages[] = $violation->getMessage();
}
return implode('. ', $messages);
}
/**
* @return array<string, array<int|string, array<int|string, int|string>|int|string>|string>
*/
public static function getSubscribedEvents(): array
{
return [
UploadEvents::VALIDATION => 'onValidate',
ValidationUrlEvent::class => 'onValidateUrl',
];
}
}