<?php
declare(strict_types=1);
namespace Harmonizely\Webhooks\EventSubscriber;
use FOS\RestBundle\Context\Context;
use FOS\RestBundle\Serializer\JMSSerializerAdapter;
use Harmonizely\CalendarEvents;
use Harmonizely\Model\EventInterface;
use Harmonizely\Webhooks\Client\WebhookClient;
use Harmonizely\Webhooks\Client\WebhookPayload;
use Harmonizely\Webhooks\Query\FindWebhookForEventQuery;
use Harmonizely\Webhooks\Webhooks;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\EventDispatcher\GenericEvent;
use Webmozart\Assert\Assert;
final class SendWebhookPayloadSubscriber implements EventSubscriberInterface
{
private JMSSerializerAdapter $serializer;
private LoggerInterface $logger;
private FindWebhookForEventQuery $findWebhookForEventQuery;
private WebhookClient $webhookClient;
public function __construct(
JMSSerializerAdapter $serializer,
FindWebhookForEventQuery $findWebhookForEventQuery,
LoggerInterface $logger,
WebhookClient $webhookClient
) {
$this->serializer = $serializer;
$this->findWebhookForEventQuery = $findWebhookForEventQuery;
$this->logger = $logger;
$this->webhookClient = $webhookClient;
}
public static function getSubscribedEvents(): array
{
return [
CalendarEvents::EVENT_POST_CREATE => 'sendScheduled',
CalendarEvents::EVENT_POST_CANCEL => 'sendCancelled',
CalendarEvents::EVENT_POST_RESCHEDULE => 'sendRescheduled',
];
}
public function sendScheduled(GenericEvent $event): void
{
/** @var EventInterface $event */
$event = $event->getSubject();
Assert::isInstanceOf($event, EventInterface::class);
$this->sendPayload($event, Webhooks::MEETING_SCHEDULED);
}
public function sendRescheduled(GenericEvent $event): void
{
/** @var EventInterface $event */
$event = $event->getSubject();
Assert::isInstanceOf($event, EventInterface::class);
$this->sendPayload($event, Webhooks::MEETING_RESCHEDULED);
}
public function sendCancelled(GenericEvent $event): void
{
/** @var EventInterface $event */
$event = $event->getSubject();
Assert::isInstanceOf($event, EventInterface::class);
$this->sendPayload($event, Webhooks::MEETING_CANCELLED);
}
private function sendPayload(EventInterface $event, string $webhookEventName): void
{
$user = $event->getUser();
$webhook = ($this->findWebhookForEventQuery)((int) $user->getId(), $webhookEventName);
if (null === $webhook) {
return;
}
$webhookPayload = new WebhookPayload($event, $webhookEventName, $webhook->getUuid());
$context = new Context();
$context->setGroups(['integration']);
$context->setSerializeNull(true);
$payload = $this->serializer->serialize($webhookPayload, 'json', $context);
try {
$this->webhookClient->post($webhook->getUrl(), $payload, $webhook->getSecret());
} catch (\Throwable $e) {
$this->logger->error($e->getMessage());
}
}
}