<?php
namespace App\Listener\NonMember;
use App\Controller\Ajax\TutorialController;
use App\Controller\MySief\LegalEntityController;
use App\Controller\MySief\TransferController;
use App\Entity\LegalEntity;
use App\Entity\Notification;
use App\Entity\Notification\NonMember\TransferIncomingNotification;
use App\Entity\TransferEntity;
use App\Entity\User;
use Doctrine\Bundle\DoctrineBundle\EventSubscriber\EventSubscriberInterface;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Event\OnFlushEventArgs;
use Doctrine\ORM\Events;
use Symfony\Component\HttpFoundation\RedirectResponse;
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\Validator\ValidatorInterface;
class TransferListener implements EventSubscriberInterface, WarmableInterface
{
/**
* @var TokenStorageInterface
*/
private $storage;
/**
* @var EntityManagerInterface
*/
private $em;
/**
* @var RouterInterface
*/
private $router;
/**
* @var ValidatorInterface
*/
private $validator;
public function __construct(TokenStorageInterface $storage, EntityManagerInterface $em, RouterInterface $router, ValidatorInterface $validator)
{
$this->storage = $storage;
$this->em = $em;
$this->router = $router;
$this->validator = $validator;
}
public function getSubscribedEvents()
{
return [Events::postPersist, Events::postUpdate, Events::postRemove, Events::onFlush];
}
public function postPersist(LifecycleEventArgs $args)
{
if (!$args->getEntity() instanceof TransferEntity) {
return;
}
$this->processRequest($args->getEntityManager(), $args->getEntity());
}
public function postUpdate(LifecycleEventArgs $args)
{
if (!$args->getEntity() instanceof TransferEntity) {
return;
}
$this->processRequest($args->getEntityManager(), $args->getEntity());
}
public function postRemove(LifecycleEventArgs $args)
{
}
public function onFlush(OnFlushEventArgs $args)
{
}
private function processRequest(EntityManagerInterface $em, TransferEntity $transfer)
{
if (!$transfer->getSend()) {
return;
}
$repository = $em->getRepository(Notification::class);
$user = $this->em->getRepository(User::class)->findUser($transfer->getUserEmail());
if (!$user instanceof User) {
return;
}
if ($transfer->getAwaitingApproval()) {
$notifications = $repository->findBy(['internalCode' => $transfer->getId()]);
foreach ($notifications as $notification) {
if (!$notification instanceof TransferIncomingNotification) {
continue;
}
$repository->removeByInternalCode($notification);
break;
}
} elseif (!$transfer->isAccepted()) {
// show notification
$notification = (new TransferIncomingNotification())
->setup($this->em, $user, $transfer)
->setUser($user);
// Remove the existing notification (if there is one)
$repository->removeByInternalCode($notification);
// Create a new one if one or more contracts require acceptance
/** @var TransferIncomingNotification $notification */
if ($notification->getPending() > 0) {
$repository->notifyUser($notification);
}
}
}
public function onKernelController(ControllerEvent $event)
{
$token = $this->storage->getToken();
if (!$token instanceof TokenInterface) {
return;
}
$user = $token->getUser();
if (!$user instanceof User) {
return;
}
$transferEntity = $this->em->getRepository(TransferEntity::class)->findOneBy(['userEmail' => $user->getEmail(), 'destinationEntityId' => null]);
if (!$transferEntity instanceof TransferEntity) {
return;
}
foreach ($user->getEntities() as $entity) {
if ($entity->isNonMember()) {
if (!$entity->getInitialOrder()) {
continue;
}
if (!$entity->getLicenseAgreement()->isAccepted()) {
if ($entity->getLicenseAgreement()->getFile()->hasFile()) {
return;
}
}
}
}
if (!$transferEntity->getSend()) {
return;
}
$controller = $event->getController();
$entities = $this->em->getRepository(LegalEntity::class)->findBy(['user' => $user]);
if (count($entities) > 0) {
foreach ($entities as $entity) {
$violations = $this->validator->validate($entity);
if ($violations->count() > 0) {
return;
}
}
}
if ($transferEntity->getDestinationEntityId()) {
$entity = $this->em->getRepository(LegalEntity::class)->find($transferEntity->getDestinationEntityId());
} else {
$entity = '';
}
$pending = $this->em->createQueryBuilder()
->from(TransferEntity::class, 'tr')
->select('COUNT(tr)')
->where('tr.userEmail = :user')
->setParameter('user', $user->getEmail())
->andWhere('tr.accepted = FALSE')
->getQuery()->useQueryCache(true)->getSingleScalarResult();
if (0 === $pending && $entity instanceof LegalEntity) {
return;
}
if (!is_array($controller)) {
return;
}
if ($controller[0] instanceof TutorialController) {
return;
}
if ('CancelTransferEntityCreation' == $controller[1]) {
$transferEntity->setAccepted(false);
}
if (!$transferEntity->isAccepted()) {
if (count($entities) > 1) {
return;
}
}
if (!$entity instanceof LegalEntity && !$transferEntity->isAccepted()) {
if ($controller[0] instanceof ErrorController) {
// We always need to show error pages
$event->getRequest()->attributes->remove('new');
} elseif ($controller[0] instanceof TransferController) {
$event->getRequest()->attributes->set('new', false);
} else {
// Redirect to overview transfer page
$event->getRequest()->attributes->set('new', true);
}
} elseif (!$entity instanceof LegalEntity && $transferEntity->isAccepted()) {
if ($controller[0] instanceof ErrorController) {
// We always need to show error pages
$event->getRequest()->attributes->remove('newAccepted');
} elseif ($controller[0] instanceof LegalEntityController) {
$event->getRequest()->attributes->set('newAccepted', false);
} else {
// Redirect to create entity page
$event->getRequest()->attributes->set('newAccepted', true);
$event->getRequest()->attributes->set('member', $transferEntity->getMember());
}
}
}
public function onKernelResponse(ResponseEvent $event)
{
if (true === $event->getRequest()->attributes->get('new')) {
$url = $this->router->generate('my-sief-page.overview.transfer', [], RouterInterface::ABSOLUTE_URL);
$event->setResponse(new RedirectResponse($url));
} elseif (true === $event->getRequest()->attributes->get('newAccepted')) {
$url = $this->router->generate('my-sief-page.legal-entities.create', ['step' => 1, 'member' => (int) $event->getRequest()->attributes->get('member')], RouterInterface::ABSOLUTE_URL);
$event->setResponse(new RedirectResponse($url));
}
}
public function warmUp($cacheDir): array
{
return [TokenStorageInterface::class, EntityManagerInterface::class, RouterInterface::class, ValidatorInterface::class];
}
}