src/EventSubscriber/ArticleWorkflowStepSubscriber.php line 230

Open in your IDE?
  1. <?php
  2. namespace App\EventSubscriber;
  3. use App\Entity\Article;
  4. use App\Entity\ArticleWorkflowStep;
  5. use App\Entity\ArticleWorkflowStepAlert;
  6. use App\Entity\MajDossier;
  7. use App\Entity\Message;
  8. use App\Entity\PracticalFile;
  9. use App\Entity\Step;
  10. use App\Entity\StepAlertConfiguration;
  11. use App\Entity\Template;
  12. use App\Entity\User;
  13. use App\Event\AppEvents;
  14. use App\Event\ArticleWorkflowStepEvent;
  15. use App\Service\EzPublishZipImportService;
  16. use App\Service\EzTitaneService;
  17. use App\Service\MailerService;
  18. use App\Service\MajDossierService;
  19. use App\Service\PracticalFileGoogleDriveService;
  20. use Doctrine\ORM\EntityManagerInterface;
  21. use FOS\UserBundle\Model\UserInterface;
  22. use Psr\Log\LoggerInterface;
  23. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  24. use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;
  25. use Symfony\Component\HttpKernel\KernelInterface;
  26. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
  27. /**
  28.  * Ecoute les événements déclenchés lors d'un changement d'étape du workflow
  29.  */
  30. class ArticleWorkflowStepSubscriber implements EventSubscriberInterface
  31. {
  32.     /**
  33.      * Gestionnaire d'envoi d'emails
  34.      *
  35.      * @var MailerService
  36.      */
  37.     private $mailerService;
  38.     /**
  39.      * @var EntityManagerInterface
  40.      */
  41.     private $entityManager;
  42.     /**
  43.      * @var TokenStorageInterface
  44.      */
  45.     private $storage;
  46.     /**
  47.      * @var EzTitaneService
  48.      */
  49.     private $ezTitaneService;
  50.     /**
  51.      * @var PracticalFileGoogleDriveService
  52.      */
  53.     private $practicalFileGoogleDriveService;
  54.     /**
  55.      * @var KernelInterface
  56.      */
  57.     private $kernel;
  58.     /**
  59.      * @var EzPublishZipImportService
  60.      */
  61.     private $ezPublishZipImportService;
  62.     /**
  63.      * @var MajDossierService
  64.      */
  65.     private $majDossierService;
  66.     /**
  67.      * @var FlashBagInterface
  68.      */
  69.     private $flashBag;
  70.     /**
  71.      * @var LoggerInterface
  72.      */
  73.     private $logger;
  74.     /**
  75.      * RegistrationSubscriber constructor
  76.      *
  77.      * @param MailerService $mailerService Gestionnaire d'envoi d'emails
  78.      * @param EntityManagerInterface $manager
  79.      * @param TokenStorageInterface $storage
  80.      * @param EzTitaneService $ezTitaneService
  81.      * @param PracticalFileGoogleDriveService $practicalFileGoogleDriveService
  82.      * @param KernelInterface $kernel
  83.      * @param EzPublishZipImportService $ezPublishZipImportService
  84.      * @param MajDossierService $majDossierService
  85.      */
  86.     public function __construct(
  87.         MailerService $mailerService,
  88.         EntityManagerInterface $manager,
  89.         TokenStorageInterface $storage,
  90.         EzTitaneService $ezTitaneService,
  91.         PracticalFileGoogleDriveService $practicalFileGoogleDriveService,
  92.         KernelInterface $kernel,
  93.         EzPublishZipImportService $ezPublishZipImportService,
  94.         MajDossierService $majDossierService,
  95.         FlashBagInterface $flashBag,
  96.         LoggerInterface $logger
  97.     ) {
  98.         $this->mailerService $mailerService;
  99.         $this->entityManager $manager;
  100.         $this->storage $storage;
  101.         $this->ezTitaneService $ezTitaneService;
  102.         $this->practicalFileGoogleDriveService $practicalFileGoogleDriveService;
  103.         $this->kernel $kernel;
  104.         $this->ezPublishZipImportService $ezPublishZipImportService;
  105.         $this->majDossierService $majDossierService;
  106.         $this->flashBag $flashBag;
  107.         $this->logger $logger;
  108.     }
  109.     /**
  110.      * Returns an array of event names this subscriber wants to listen to
  111.      *
  112.      * @return array
  113.      */
  114.     public static function getSubscribedEvents()
  115.     {
  116.         return array(
  117.             AppEvents::STEP_CHANGED => [
  118.                 ['onFicheEnFabricationStep'30],
  119.                 ['notifyArticleStepChange'40],
  120.                 ['notifyPracticalFileStepChange'50],
  121.                 ['markAsOnline'60],
  122.                 //['EzTitaneXmlExport', 70],
  123.                 ['setStepAlert'80],
  124.                 ['onChangeStep'90]
  125.             ],
  126.         );
  127.     }
  128.     /**
  129.      * Archivage du manuscrit lorsqu'une fiche passe à l'étape fiche_en_fabrication
  130.      */
  131.     public function onFicheEnFabricationStep(ArticleWorkflowStepEvent $event): void
  132.     {
  133.         $entity $event->getCurrentArticleWorkflowStep()->getRelatedEntity()->getRelatedEntity();
  134.         if (!($entity instanceof PracticalFile) || $entity->getCurrentStep()->getCode() !== 'fiche_en_fabrication') {
  135.             return;
  136.         }
  137.         $practicalFile $entity;
  138.         // Attachement en PJ du manuscrit
  139.         if ($practicalFile->getGoogleDocId()) {
  140.             $this->practicalFileGoogleDriveService->getDriveService()->initClient();
  141.             $result $this->practicalFileGoogleDriveService->addDriveFileToAttachment($practicalFile);
  142.             if ($result === false) {
  143.                 $this->flashBag->add('error'"Fiche {$practicalFile->getNumber()} : erreur lors de la récupération du fichier dans Google Drive");
  144.                 $this->logger->error("Fiche {$practicalFile->getNumber()} : erreur lors de la récupération du fichier dans Google Drive");
  145.             }
  146.         }
  147.     }
  148.     /**
  149.      * Créer les alertes de la nouvelle étape
  150.      *
  151.      * @param ArticleWorkflowStepEvent $event
  152.      */
  153.     public function setStepAlert(ArticleWorkflowStepEvent $event)
  154.     {
  155.         $newArticleWorkflowStep $event->getCurrentArticleWorkflowStep();
  156.         $stepAlertConfigurations $this->entityManager->getRepository(StepAlertConfiguration::class)->findBy(
  157.             [
  158.                 'step' => $newArticleWorkflowStep->getWorkflowStep()->getStep()
  159.             ]
  160.         );
  161.         foreach ($stepAlertConfigurations as $stepAlertConfiguration) {
  162.             $articleWorkflowStepAlert = new ArticleWorkflowStepAlert();
  163.             $articleWorkflowStepAlert->setArticleWorkflowStep($event->getCurrentArticleWorkflowStep());
  164.             $articleWorkflowStepAlert->setStepAlertConfiguration($stepAlertConfiguration);
  165.             $this->entityManager->persist($articleWorkflowStepAlert);
  166.         }
  167.         $this->entityManager->flush();
  168.     }
  169.     /**
  170.      * Export XML de l'article s'il s'agit de la validation de l'étape "A exporter sur TITANE"
  171.      *
  172.      * @param ArticleWorkflowStepEvent $event
  173.      */
  174.     public function EzTitaneXmlExport(ArticleWorkflowStepEvent $event)
  175.     {
  176.         $oldStep $event->getOldArticleWorkflowStep()->getWorkflowStep()->getStep();
  177.         $entity $event->getCurrentArticleWorkflowStep()->getRelatedEntity()->getRelatedEntity();
  178.         if ($entity instanceof Article && $oldStep->getLabel() == 'A exporter sur TITANE') {
  179.             $this->ezTitaneService->generateXml($entity);
  180.         }
  181.     }
  182.     /**
  183.      * La fiche pratique est tagguée en "ligne" lorsqu'on est à la dernière étape
  184.      *
  185.      * @param ArticleWorkflowStepEvent $event
  186.      */
  187.     public function markAsOnline(ArticleWorkflowStepEvent $event)
  188.     {
  189.         // S'il ne s'agit pas du workflow principal
  190.         if (!$event->getCurrentArticleWorkflowStep()->getArticleWorkflow()) {
  191.             return;
  192.         }
  193.         $entity $event->getCurrentArticleWorkflowStep()->getRelatedEntity()->getRelatedEntity();
  194.         $newStep $event->getCurrentArticleWorkflowStep()->getWorkflowStep();
  195.         if ($entity instanceof PracticalFile && $newStep->isFinalist()) {
  196.             $entity->setOnline(true);
  197.         }
  198.         $this->entityManager->flush();
  199.     }
  200.     /**
  201.      * Récupération du Docx et des outils d'une fiche pratique depuis le site EzPublish et génération du Google Doc de la fiche
  202.      *
  203.      * @param ArticleWorkflowStepEvent $event
  204.      * @throws \Exception
  205.      */
  206.     public function onChangeStep(ArticleWorkflowStepEvent $event)
  207.     {
  208.         $entity $event->getCurrentArticleWorkflowStep()->getRelatedEntity()->getRelatedEntity();
  209.         if ($entity instanceof PracticalFile) {
  210.             /** @var MajDossier $majDossier */
  211.             foreach ($entity->getMajDossiers() as $majDossier) {
  212.                 if ($majDossier->getStatus() == MajDossier::STATUS_IN_PROGRESS) {
  213.                     $this->majDossierService->updateStatusFinish($majDossier);
  214.                 }
  215.             }
  216.             if ($event->getCurrentArticleWorkflowStep()->getWorkflowStep()->getStep()->getLabel() === "En ligne") {
  217.                 $practicalFile $entity;
  218.                 $this->ezPublishZipImportService->importEzveilleFiles($practicalFile);
  219.             }
  220.         }
  221.     }
  222.     /**
  223.      * Retourne l'utilisateur loggué ou l'utilisateur "system" dans le cas d'un traitement automatique
  224.      *
  225.      * @return UserInterface
  226.      */
  227.     protected function getUser(): UserInterface
  228.     {
  229.         return $this->storage->getToken() ? $this->storage->getToken()->getUser() : $this->entityManager->getRepository(User::class)->findOneBy(['username' => 'system']);
  230.     }
  231.     /**
  232.      * Envoi d'un email de notification de changement d'étape d'une fiche pratique
  233.      */
  234.     public function notifyPracticalFileStepChange(ArticleWorkflowStepEvent $event): void
  235.     {
  236.         $entity $event->getCurrentArticleWorkflowStep()->getRelatedEntity()->getRelatedEntity();
  237.         if (!$entity instanceof PracticalFile || !$event->getArgument('notify')) {
  238.             return;
  239.         }
  240.         $newStep $event->getCurrentArticleWorkflowStep()->getWorkflowStep()->getStep();
  241.         if (!$newStep->getWithNotification()) {
  242.             return;
  243.         }
  244.         $practicalFile $entity;
  245.         $vars = [
  246.             'practical_file' => $practicalFile,
  247.         ];
  248.         $this->mailerService->sendMail(
  249.             $this->getRecipientsEmails($newStep$practicalFile),
  250.             $this->getEmailTemplatePath($newStep$practicalFile),
  251.             $vars
  252.         );
  253.     }
  254.     /**
  255.      * Retourne le chemin du template de notification d'une étape donnée selon l'étape et la société concernées
  256.      */
  257.     protected function getEmailTemplatePath(Step $newStepPracticalFile $practicalFile): string
  258.     {
  259.         if (!$this->mailerService->templateExists("email/notification_{$newStep->getCode()}_{$practicalFile->getEditionPrefix()}.html.twig")) {
  260.             return "email/notification_{$newStep->getCode()}.html.twig";
  261.         } else {
  262.             return "email/notification_{$newStep->getCode()}_{$practicalFile->getEditionPrefix()}.html.twig";
  263.         }
  264.     }
  265.     /**
  266.      * Retourne les mails des destinataires des notifications d'une étape donnée
  267.      *
  268.      * @param Step $step
  269.      * @param $entity Article|PracticalFile
  270.      * @return array
  271.      */
  272.     protected function getRecipientsEmails(Step $step$entity): array
  273.     {
  274.         $recipientsRoles $step->getAlertsDestinationRoles();
  275.         $users array_filter($entity->getUsersByRoles($recipientsRoles), function ($user) {
  276.             return !$user->getStopEmail();
  277.         });
  278.         $recipientsEmails array_map(
  279.             function (?User $user) {
  280.                 if (null === $user) {
  281.                     throw new \Exception("Attention, un utilisateur supposé se charger de cette étape n'a pas été désigné, aucune notification n'a été envoyée.");
  282.                 }
  283.                 return $user $user->getEmail() : null;
  284.             },
  285.             $users
  286.         );
  287.         if ($step->notifyCompositeurOnStepChange()) {
  288.             $compositeurUser $this->entityManager->getRepository(User::class)->findOneBy(['username' => 'compositeur']);
  289.             $recipientsEmails[] = $compositeurUser->getEmail();
  290.         }
  291.         return $recipientsEmails;
  292.     }
  293.     /**
  294.      * Envoi d'un email de notification pour un changement d'étape d'un article
  295.      *
  296.      * @param ArticleWorkflowStepEvent $event
  297.      * @throws \ReflectionException
  298.      * @throws \Twig\Error\LoaderError
  299.      * @throws \Twig\Error\RuntimeError
  300.      * @throws \Twig\Error\SyntaxError
  301.      */
  302.     public function notifyArticleStepChange(ArticleWorkflowStepEvent $event)
  303.     {
  304.         $entity $event->getCurrentArticleWorkflowStep()->getRelatedEntity()->getRelatedEntity();
  305.         if (!$entity instanceof Article || !$event->getArgument('notify')) {
  306.             return;
  307.         }
  308.         $entity $event->getCurrentArticleWorkflowStep()->getRelatedEntity()->getRelatedEntity();
  309.         $oldStep $event->getOldArticleWorkflowStep()->getWorkflowStep()->getStep();
  310.         $newStep $event->getCurrentArticleWorkflowStep()->getWorkflowStep()->getStep();
  311.         $newStepLabel $newStep->getLabel();
  312.         $oldStepLabel $oldStep->getLabel();
  313.         if ( $entity === null || !$newStep->getWithNotification() ) {
  314.             return;
  315.         }
  316.         $senderRole $oldStep->getSignatureRole();
  317.         if ($senderRole !== null) {
  318.             $senderUser $entity->getIntervenorByRole($senderRole);
  319.         } else {
  320.             $senderUser $this->getUser();
  321.         }
  322.         if (array_key_exists(($newStepLabel), ArticleWorkflowStep::NOTIFICATION_ARTICLE_STEPS_LABEL)) {
  323.             $template $this->entityManager->getRepository(Template::class)->findOneByTitle($newStepLabel);
  324.         } else {
  325.             $template $this->entityManager->getRepository(Template::class)->findOneByTitle("Changement d'étape workflow");
  326.         }
  327.         if (is_null($template)) {
  328.             return;
  329.         }
  330.         $message = new Message();
  331.         $message->setTemplate($template);
  332.         $message->setType(Message::TYPE_NOTIFICATION);
  333.         $reflectionClass = new \ReflectionClass($entity);
  334.         $entitySetter 'set' $reflectionClass->getShortName();
  335.         $message->$entitySetter($entity);
  336.         $this->entityManager->persist($message);
  337.         $this->entityManager->flush();
  338.         $subjectParam = [];
  339.         $to $this->getRecipientsEmails($newStep$entity);
  340.         $bodyParam = [
  341.             '%oldStep%' => $oldStepLabel,
  342.             '%newStep%' => $newStepLabel,
  343.             '%responsible%' => $entity->getResponsible(),
  344.             '%type%' => $entity instanceof PracticalFile "la fiche" "l'article",
  345.             '%number%' => $entity->getNumber(),
  346.         ];
  347.         $signatureParam = [
  348.             '%senderName%' => $senderUser->getFullname(),
  349.             '%senderRole%' => !empty($senderRole) ? $senderRole->getLabel() : '',
  350.         ];
  351.         $this->mailerService->sendMessage(
  352.             $to,
  353.             $message,
  354.             "email/message.html.twig",
  355.             $subjectParam,
  356.             $bodyParam,
  357.             $signatureParam
  358.         );
  359.     }
  360. }