src/Cms/CoreBundle/EventSubscriber/OneRoster/AbstractOneRosterSubscriber.php line 129

Open in your IDE?
  1. <?php
  2. namespace Cms\CoreBundle\EventSubscriber\OneRoster;
  3. use App\Doctrine\ORM\Filters\DiscardableFilter;
  4. use Cms\CoreBundle\Entity\AbstractOneRosterEntity;
  5. use Cms\CoreBundle\Entity\OneRosterJob;
  6. use Cms\CoreBundle\Events\OneRosterEvents;
  7. use Cms\CoreBundle\Service\OneRosterService;
  8. use Cms\CoreBundle\Util\Doctrine\EntityManager;
  9. use Platform\QueueBundle\Event\AsyncEvent;
  10. use Platform\QueueBundle\Model\AsyncMessage;
  11. use Platform\QueueBundle\Service\AsyncQueueService;
  12. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  13. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  14. /**
  15.  * Class AbstractOneRosterSubscriber
  16.  * @package Cms\CoreBundle\EventSubscriber\OneRoster
  17.  */
  18. abstract class AbstractOneRosterSubscriber implements EventSubscriberInterface
  19. {
  20.     protected const MQ_PRIORITY AsyncMessage::PRIORITY__BELOW_NORMAL;
  21.     protected const PRIORITY__FIRST PHP_INT_MAX;
  22.     protected const PRIORITY__LAST PHP_INT_MIN;
  23.     // DI
  24.     protected EntityManager $em;
  25.     protected AsyncQueueService $async;
  26.     protected OneRosterService $oneroster;
  27.     protected EventDispatcherInterface $dispatcher;
  28.     /**
  29.      * @param EntityManager $em
  30.      * @param AsyncQueueService $async
  31.      * @param OneRosterService $oneroster
  32.      * @param EventDispatcherInterface $dispatcher
  33.      */
  34.     public function __construct(
  35.         EntityManager $em,
  36.         AsyncQueueService $async,
  37.         OneRosterService $oneroster,
  38.         EventDispatcherInterface $dispatcher
  39.     )
  40.     {
  41.         $this->em $em;
  42.         $this->async $async;
  43.         $this->oneroster $oneroster;
  44.         $this->dispatcher $dispatcher;
  45.     }
  46.     /**
  47.      * @param AsyncEvent $event
  48.      * @return OneRosterJob
  49.      */
  50.     protected function loadJob(AsyncEvent $event): OneRosterJob
  51.     {
  52.         // data should be an array with an id of a sync
  53.         // see if it is in cache first and load it from there if we can
  54.         if ($this->em->getCache() && $this->em->getCache()->containsEntity(OneRosterJob::class, $event->getParam('job'))) {
  55.             $job $this->em->getRepository(OneRosterJob::class)->find($event->getParam('job'));
  56.         } else {
  57.             $job $this->em->getRepository(OneRosterJob::class)->createQueryBuilder('job')
  58.                 ->leftJoin('job.sync''sync')
  59.                 ->andWhere('job.id = :job')
  60.                 ->setParameter('job'$event->getParam('job'))
  61.                 ->getQuery()
  62.                 ->getSingleResult();
  63.         }
  64.         // make sure we have a job
  65.         if ( ! $job instanceof OneRosterJob) {
  66.             throw new \Exception(sprintf(
  67.                 'Could not load job #%s.',
  68.                 $event->getParam('job')
  69.             ));
  70.         }
  71.         // DEBUGGING
  72.         $event->getOutput()->writeln(sprintf(
  73.             'Sync #%s loaded',
  74.             $job->getIdentifier()
  75.         ));
  76.         return $job;
  77.     }
  78.     /**
  79.      * @return int
  80.      */
  81.     abstract public function phase(): int;
  82.     /**
  83.      * @return int|null
  84.      */
  85.     abstract public function next(): ?int;
  86.     /**
  87.      * @param OneRosterJob $job
  88.      * @param array|int[] $checks
  89.      * @return bool
  90.      */
  91.     protected function checkTypes(OneRosterJob $job, array $checks): bool
  92.     {
  93.         if (empty($checks)) {
  94.             throw new \Exception();
  95.         }
  96.         foreach ($checks as $check) {
  97.             if ($job->getSync()->hasStrategy($check)) {
  98.                 return true;
  99.             }
  100.         }
  101.         return false;
  102.     }
  103.     /**
  104.      * @return void
  105.      */
  106.     public function discardableDisable(): void
  107.     {
  108.         if ($this->em->getFilters()->isEnabled(DiscardableFilter::FILTER)) {
  109.             $this->em->getFilters()->disable(DiscardableFilter::FILTER);
  110.         }
  111.     }
  112.     /**
  113.      * @return void
  114.      */
  115.     public function discardableEnable(): void
  116.     {
  117.         if ( ! $this->em->getFilters()->isEnabled(DiscardableFilter::FILTER)) {
  118.             $this->em->getFilters()->enable(DiscardableFilter::FILTER);
  119.         }
  120.     }
  121.     /**
  122.      * @param AsyncEvent $event
  123.      */
  124.     public function phaseStart(AsyncEvent $event): void
  125.     {
  126.         // get the job
  127.         $job $this->loadJob($event);
  128.         // tracking
  129.         $this->oneroster->orchestratePhaseInit($job$this->phase());
  130.         // refresh the job since we did bulk update prior
  131.         $this->em->refresh($job);
  132.     }
  133.     /**
  134.      * @param AsyncEvent $event
  135.      */
  136.     public function phaseFin(AsyncEvent $event): void
  137.     {
  138.         // get the job
  139.         $job $this->loadJob($event);
  140.         // tracking
  141.         $this->oneroster->orchestratePhaseFin($job$this->phase());
  142.         // refresh the job since we did bulk update prior
  143.         $this->em->refresh($job);
  144.     }
  145.     /**
  146.      * @param AsyncEvent $event
  147.      */
  148.     public function phaseTrigger(AsyncEvent $event): void
  149.     {
  150.         // get the job
  151.         $job $this->loadJob($event);
  152.         // see if we have a next phase and if it has been triggered yet
  153.         if ($this->oneroster->orchestratePhaseConditionalInit($job$this->phase(), $this->next())) {
  154.             // add to mq
  155.             $this->async->send(
  156.                 null,
  157.                 new AsyncMessage(
  158.                     $job,
  159.                     OneRosterEvents::PHASES[$this->next()],
  160.                     [
  161.                         'job' => $job->getId(),
  162.                     ],
  163.                     self::MQ_PRIORITY,
  164.                 )
  165.             );
  166.             // DEBUGGING
  167.             $event->getOutput()->writeln(sprintf(
  168.                 '%s completed, %s triggered for sync #%s',
  169.                 strtoupper(array_search($this->phase(), OneRosterJob::PHASES)),
  170.                 strtoupper(array_search($this->next(), OneRosterJob::PHASES)),
  171.                 $job->getIdentifier()
  172.             ));
  173.         }
  174.     }
  175.     /**
  176.      * @param AsyncEvent $event
  177.      * @return array
  178.      */
  179.     protected function parseForType(AsyncEvent $event): array
  180.     {
  181.         // should also tell us what type we are processing
  182.         // oneroster data type, not fqcn
  183.         $type $event->getParam('type');
  184.         // determine the class based on the type
  185.         $class AbstractOneRosterEntity::ONEROSTER_TYPES[$type];
  186.         return [
  187.             $type,
  188.             $class,
  189.         ];
  190.     }
  191.     /**
  192.      * @param AsyncEvent $event
  193.      * @return array
  194.      */
  195.     protected function parseForObject(AsyncEvent $event): array
  196.     {
  197.         // determine the class based on the type
  198.         $class AbstractOneRosterEntity::ONEROSTER_TYPES[$event->getParam('type')];
  199.         // use the given id to load the data
  200.         $entity $this->em->getRepository($class)->findOneBy([
  201.             'sourcedId' => $event->getParam('id'),
  202.         ]);
  203.         if ( ! $entity instanceof AbstractOneRosterEntity || ! $entity instanceof $class) {
  204.             throw new \Exception();
  205.         }
  206.         return [
  207.             $class,
  208.             $entity,
  209.         ];
  210.     }
  211. }