From 3fdba53995f4e7700172f75db2c316fae87b372c Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Fri, 27 Dec 2019 09:25:07 +0100 Subject: [PATCH] Added basic implementation for new webhook events --- config/autoload/url-shortener.global.php | 1 + .../Core/config/event_dispatcher.config.php | 10 +++ .../EventDispatcher/NotifyVisitToWebHooks.php | 67 +++++++++++++++++++ .../src/EventDispatcher/ShortUrlLocated.php | 28 ++++++++ 4 files changed, 106 insertions(+) create mode 100644 module/Core/src/EventDispatcher/NotifyVisitToWebHooks.php create mode 100644 module/Core/src/EventDispatcher/ShortUrlLocated.php diff --git a/config/autoload/url-shortener.global.php b/config/autoload/url-shortener.global.php index 46e12593..58bc3faa 100644 --- a/config/autoload/url-shortener.global.php +++ b/config/autoload/url-shortener.global.php @@ -10,6 +10,7 @@ return [ 'hostname' => '', ], 'validate_url' => true, + 'visits_webhooks' => [], ], ]; diff --git a/module/Core/config/event_dispatcher.config.php b/module/Core/config/event_dispatcher.config.php index b5d86b09..8cee1f5c 100644 --- a/module/Core/config/event_dispatcher.config.php +++ b/module/Core/config/event_dispatcher.config.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Shlinkio\Shlink\Core; +use GuzzleHttp\ClientInterface; use Shlinkio\Shlink\CLI\Util\GeolocationDbUpdater; use Shlinkio\Shlink\IpGeolocation\Resolver\IpLocationResolverInterface; use Zend\ServiceManager\AbstractFactory\ConfigAbstractFactory; @@ -16,6 +17,9 @@ return [ EventDispatcher\ShortUrlVisited::class => [ EventDispatcher\LocateShortUrlVisit::class, ], + EventDispatcher\ShortUrlLocated::class => [ + EventDispatcher\NotifyVisitToWebHooks::class, + ], ], ], @@ -32,6 +36,12 @@ return [ 'Logger_Shlink', GeolocationDbUpdater::class, ], + EventDispatcher\NotifyVisitToWebHooks::class => [ + 'httpClient', + 'em', + 'Logger_Shlink', + 'config.url_shortener.visits_webhooks', + ], ], ]; diff --git a/module/Core/src/EventDispatcher/NotifyVisitToWebHooks.php b/module/Core/src/EventDispatcher/NotifyVisitToWebHooks.php new file mode 100644 index 00000000..995323e1 --- /dev/null +++ b/module/Core/src/EventDispatcher/NotifyVisitToWebHooks.php @@ -0,0 +1,67 @@ +httpClient = $httpClient; + $this->em = $em; + $this->logger = $logger; + $this->webhooks = $webhooks; + } + + public function __invoke(ShortUrlLocated $shortUrlLocated): void + { + $visitId = $shortUrlLocated->visitId(); + + /** @var Visit|null $visit */ + $visit = $this->em->find(Visit::class, $visitId); + if ($visit === null) { + $this->logger->warning('Tried to notify webhooks for visit with id "{visitId}", but it does not exist.', [ + 'visitId' => $visitId, + ]); + return; + } + + $requestOptions = [ + RequestOptions::TIMEOUT => 10, + RequestOptions::JSON => $visit->jsonSerialize(), + ]; + $requestPromises = map($this->webhooks, function (string $webhook) use ($requestOptions, $visitId) { + $promise = $this->httpClient->requestAsync(RequestMethodInterface::METHOD_POST, $webhook, $requestOptions); + return $promise->otherwise(function () use ($webhook, $visitId) { + // Log failures + $this->logger->warning('Failed to notify visit with id "{visitId}" to "{webhook}" webhook', [ + 'visitId' => $visitId, + 'webhook' => $webhook, + ]); + }); + }); + } +} diff --git a/module/Core/src/EventDispatcher/ShortUrlLocated.php b/module/Core/src/EventDispatcher/ShortUrlLocated.php new file mode 100644 index 00000000..63390ebf --- /dev/null +++ b/module/Core/src/EventDispatcher/ShortUrlLocated.php @@ -0,0 +1,28 @@ +visitId = $visitId; + } + + public function visitId(): string + { + return $this->visitId; + } + + public function jsonSerialize(): array + { + return ['visitId' => $this->visitId]; + } +}