src/EventSubscriber/CreateZoomMeetingSubscriber.php line 122

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace Harmonizely\EventSubscriber;
  4. use DateTimeZone;
  5. use Doctrine\ORM\EntityManagerInterface;
  6. use Harmonizely\CalendarEvents;
  7. use Harmonizely\EventTypes\LocationTypeProvider;
  8. use Harmonizely\Integration\Provider\ZoomClientProviderInterface;
  9. use Harmonizely\Integration\Zoom\Exception\CouldNotUpdateZoomMeetingException;
  10. use Harmonizely\Model\EventInterface;
  11. use Harmonizely\Model\EventTypeInterface;
  12. use Harmonizely\Model\Integration;
  13. use Harmonizely\Model\IntegrationInterface;
  14. use Harmonizely\Model\UserInterface;
  15. use Psr\Log\LoggerInterface;
  16. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  17. use Symfony\Component\EventDispatcher\GenericEvent;
  18. use Webmozart\Assert\Assert;
  19. use Harmonizely\Types\IntegrationType;
  20. final class CreateZoomMeetingSubscriber implements EventSubscriberInterface
  21. {
  22.     private $zoomClientProvider;
  23.     private $entityManager;
  24.     private $logger;
  25.     private LocationTypeProvider $locationTypeProvider;
  26.     public function __construct(
  27.         ZoomClientProviderInterface $zoomClientProvider,
  28.         EntityManagerInterface $entityManager,
  29.         LoggerInterface $logger,
  30.         LocationTypeProvider $locationTypeProvider
  31.     ) {
  32.         $this->zoomClientProvider $zoomClientProvider;
  33.         $this->entityManager $entityManager;
  34.         $this->logger $logger;
  35.         $this->locationTypeProvider $locationTypeProvider;
  36.     }
  37.     public static function getSubscribedEvents(): array
  38.     {
  39.         return [
  40.             CalendarEvents::EVENT_PRE_CREATE => 'createMeeting',
  41.             CalendarEvents::EVENT_POST_CANCEL => 'cancelMeeting',
  42.             CalendarEvents::EVENT_POST_RESCHEDULE => 'updateMeeting',
  43.         ];
  44.     }
  45.     public function createMeeting(GenericEvent $event): void
  46.     {
  47.         /** @var EventInterface $event */
  48.         $event $event->getSubject();
  49.         Assert::isInstanceOf($eventEventInterface::class);
  50.         $eventType $event->getEventType();
  51.         $user $event->getUser();
  52.         $locationType $this->locationTypeProvider->provideFor($eventType$user$event);
  53.         $integration $this->findIntegration($user);
  54.         if (null === $integration || EventTypeInterface::LOCATION_TYPE_ZOOM !== $locationType) {
  55.             return;
  56.         }
  57.         if (!$integration->isEnabled()) {
  58.             return;
  59.         }
  60.         if ($eventType->isGroupMeetingType() && $event->getLocation()) {
  61.             return;
  62.         }
  63.         try {
  64.             $zoomClientAdapter $this->zoomClientProvider->getZoomClient($integration);
  65.             $zoomMeeting $zoomClientAdapter->createMeeting($event);
  66.         } catch (\Exception $e) {
  67.             $this->logger->critical($e->getMessage());
  68.             return;
  69.         }
  70.         $event->setLocation($zoomMeeting['join_url']);
  71.     }
  72.     public function cancelMeeting(GenericEvent $genericEvent): void
  73.     {
  74.         /** @var EventInterface $event */
  75.         $event $genericEvent->getSubject();
  76.         Assert::isInstanceOf($eventEventInterface::class);
  77.         $eventType $event->getEventType();
  78.         $user $genericEvent->hasArgument('previousUser')
  79.             ? $genericEvent->getArgument('previousUser')
  80.             : $event->getUser();
  81.         $locationType $this->locationTypeProvider->provideFor($eventType$user$event);
  82.         $integration $this->findIntegration($user);
  83.         if (null === $integration || EventTypeInterface::LOCATION_TYPE_ZOOM !== $locationType) {
  84.             return;
  85.         }
  86.         if (!$integration->isEnabled()) {
  87.             return;
  88.         }
  89.         try {
  90.             $zoomClientAdapter $this->zoomClientProvider->getZoomClient($integration);
  91.             $zoomClientAdapter->cancelMeeting($event);
  92.         } catch (\Exception $e) {
  93.             $this->logger->critical('Zoom meeting cancellation failed.', [
  94.                 'message' => $e->getMessage(),
  95.                 'user_email' => $user->getEmail(),
  96.                 'invitee_email' => $event->getInvitee()->getEmail(),
  97.             ]);
  98.         }
  99.     }
  100.     public function updateMeeting(GenericEvent $genericEvent): void
  101.     {
  102.         /** @var EventInterface $event */
  103.         $event $genericEvent->getSubject();
  104.         Assert::isInstanceOf($eventEventInterface::class);
  105.         /** @var EventTypeInterface $eventType */
  106.         $eventType $event->getEventType();
  107.         $user $event->getUser();
  108.         if ($event->getRescheduling()->getPreviousUser()) {
  109.             $genericEvent->setArgument('previousUser'$event->getRescheduling()->getPreviousUser());
  110.             $this->cancelMeeting($genericEvent);
  111.             $this->createMeeting($genericEvent);
  112.         } else {
  113.             $locationType $this->locationTypeProvider->provideFor($eventType$user$event);
  114.             $integration $this->findIntegration($user);
  115.             if (null === $integration || EventTypeInterface::LOCATION_TYPE_ZOOM !== $locationType) {
  116.                 return;
  117.             }
  118.             if (!$integration->isEnabled()) {
  119.                 return;
  120.             }
  121.             $eventType $event->getEventType();
  122.             $startTimeInUserTimezone = clone $event->getScheduledAt();
  123.             $startTimeInUserTimezone->setTimezone(new DateTimeZone($eventType->getUser()->getTimezone()));
  124.             $startsAt $startTimeInUserTimezone->format('Y-m-d\\TH:i:s');
  125.             $invitee $event->getInvitee();
  126.             $topic $eventType->getName().' - '.$invitee->getFullName();
  127.             $duration $event->getDuration();
  128.             if (null === ($zoomLink $event->getLocation())) {
  129.                 return;
  130.             }
  131.             $zoomMeetingId = (int) basename($zoomLink);
  132.             try {
  133.                 $zoomClientAdapter $this->zoomClientProvider->getZoomClient($integration);
  134.                 $zoomClientAdapter->updateMeeting($zoomMeetingId$topic$duration$startsAt);
  135.             } catch (CouldNotUpdateZoomMeetingException $e) {
  136.                 $this->logger->critical($e->getMessage());
  137.                 return;
  138.             }
  139.         }
  140.     }
  141.     private function findIntegration(UserInterface $user): ?IntegrationInterface
  142.     {
  143.         $integrationRepository $this->entityManager->getRepository(Integration::class);
  144.         return $integrationRepository->findOneBy([
  145.             'type' => IntegrationType::TYPE_ZOOM,
  146.             'user' => $user,
  147.         ]);
  148.     }
  149. }