<?php
namespace App\Listener;
use App\Controller\Ajax\TutorialController;
use App\Controller\MySief\LegalEntityController;
use App\Entity\LegalEntity;
use App\Entity\LegalEntity\Billing\ContactPerson;
use App\Entity\StaffRequest;
use App\Entity\User;
use Doctrine\Bundle\DoctrineBundle\EventSubscriber\EventSubscriberInterface;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Events;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
use Symfony\Component\HttpKernel\Controller\ErrorController;
use Symfony\Component\HttpKernel\Event\ControllerEvent;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Validator\Exception\ValidatorException;
use Symfony\Component\Validator\Validator\ValidatorInterface;
class ValidationListener implements EventSubscriberInterface, WarmableInterface
{
/**
* @var bool
*/
private static $enabled = true;
/**
* @var ValidatorInterface
*/
private $validator;
/**
* @var TokenStorageInterface
*/
private $storage;
/**
* @var EntityManagerInterface
*/
private $em;
/**
* @var RouterInterface
*/
private $router;
/**
* @var RequestStack
*/
private $requestStack;
/**
* @var LegalEntityController
*/
private $controller;
public function __construct(TokenStorageInterface $storage, EntityManagerInterface $em, RouterInterface $router, ValidatorInterface $validator, RequestStack $requestStack, LegalEntityController $controller, ContainerInterface $container)
{
$this->storage = $storage;
$this->em = $em;
$this->router = $router;
$this->validator = $validator;
$this->requestStack = $requestStack;
$this->controller = $controller;
$this->controller->setContainer($container);
}
public function getSubscribedEvents()
{
return [Events::prePersist, Events::preUpdate];
}
private function validate(LifecycleEventArgs $args)
{
if (!self::$enabled) {
return;
}
$entity = $args->getObject();
if (defined('IMPORT_RUNNING')) {
if ($entity instanceof ContactPerson) {
return;
}
}
$violations = $this->validator->validate($entity);
if ($violations->count() > 0) {
$violation = $violations->get(0);
$message = sprintf('[%s->%s] %s', get_class($entity), $violation->getPropertyPath(), $violation->getMessage());
throw new ValidatorException($message);
}
}
public static function disable()
{
self::$enabled = false;
}
public static function enable()
{
self::$enabled = true;
}
public function prePersist(LifecycleEventArgs $args)
{
$this->validate($args);
}
public function preUpdate(LifecycleEventArgs $args)
{
$this->validate($args);
}
public function onKernelController(ControllerEvent $event)
{
if (!self::$enabled) {
return;
}
$token = $this->storage->getToken();
if (!$token instanceof TokenInterface) {
return;
}
$user = $token->getUser();
if (!$user instanceof User) {
return;
}
if ($user->isStaff()) {
return;
}
$entities = $this->em->getRepository(LegalEntity::class)->findBy(['user' => $user]);
$invalidEntities = [];
$pending = [];
if (count($entities) > 0) {
foreach ($entities as $entity) {
/**
* @var LegalEntity $entity
*/
$billingRequest = $this->em->getRepository(StaffRequest\NonMemberAlterLicensingRequest::class)->findOneBy(['legalEntity' => $entity, 'status' => 'pending']);
$licensingRequest = $this->em->getRepository(StaffRequest\NonMemberAlterLicensingRequest::class)->findOneBy(['legalEntity' => $entity, 'status' => 'pending']);
if ($billingRequest instanceof StaffRequest\NonMemberAlterBillingRequest || $licensingRequest instanceof StaffRequest\NonMemberAlterLicensingRequest) {
$pending[] = $entity;
ValidationListener::disable();
$violations = $this->validator->validate($entity);
if ($violations->count() > 0) {
$entity->setLimited(true);
}
$this->em->persist($entity);
$this->em->flush();
ValidationListener::enable();
continue;
}
/** @var LegalEntity $entity */
$violations = $this->validator->validate($entity);
if ($violations->count() > 0) {
$invalidEntities[] = $entity->getId();
} else {
$entity->setLimited(false);
}
}
}
$session = $this->requestStack->getSession();
if (count($invalidEntities) > 0) {
$session->remove('validation/pending');
$attribute = 'validation/multipleInvalid';
if (1 === count($invalidEntities)) {
$message = "An invalid legal entity was found (some compulsory information is missing), please correct the data for the highlighted legal entity and await approval. To fill in the data, click on the edit button next to the legal entity's name.";
} else {
$message = sprintf("%s invalid legal entities were found (some compulsory information is missing), please correct the data for the highlighted legal entities and await approval. To fill in the data, click on the edit button next to the legal entity's name", count($invalidEntities));
}
$session->set('validation/invalidEntities', $invalidEntities);
$data = true;
} elseif (count($pending) > 0) {
$session->remove('validation/multipleInvalid');
$session->remove('validation/invalidEntities');
$attribute = 'validation/pending';
$message = sprintf("You have %s pending alter request's, awaiting staff approval.", count($pending));
$data = true;
} else {
$session->remove('validation/pending');
$session->remove('validation/multipleInvalid');
$session->remove('validation/invalidEntities');
return;
}
$controller = $event->getController();
if (!is_array($controller)) {
return;
}
if ($controller[0] instanceof TutorialController) {
return;
}
if ($controller[0] instanceof ErrorController) {
// We always need to show error pages
$event->getRequest()->attributes->remove($attribute);
} elseif ($controller[0] instanceof LegalEntityController) {
$event->getRequest()->attributes->set($attribute, false);
} else {
// Redirect to substances
$session->set($attribute, $message);
if (!isset($entity)) {
throw new \Exception('entity is not set');
}
if (!$entity->isLimited()) {
return;
}
$event->getRequest()->attributes->set($attribute, $data);
$event->setController([$this->controller, 'indexAction']);
}
}
public function onKernelResponse(ResponseEvent $event)
{
}
public function warmUp($cacheDir)
{
return [TokenStorageInterface::class, EntityManagerInterface::class, RouterInterface::class, ValidatorInterface::class, RequestStack::class, LegalEntityController::class, ContainerInterface::class];
}
}