diff --git a/composer.json b/composer.json index 7e0a8bfe..191a7d1b 100644 --- a/composer.json +++ b/composer.json @@ -17,13 +17,11 @@ "ext-pdo": "*", "akrabat/ip-address-middleware": "^1.0", "cakephp/chronos": "^1.2", - "cocur/slugify": "^3.0", "doctrine/cache": "^1.9", "doctrine/dbal": "^2.10", "doctrine/migrations": "^2.2", "doctrine/orm": "^2.7", "endroid/qr-code": "^3.6", - "firebase/php-jwt": "^4.0", "geoip2/geoip2": "^2.9", "guzzlehttp/guzzle": "^6.5.1", "laminas/laminas-config": "^3.3", @@ -53,7 +51,7 @@ "shlinkio/shlink-common": "dev-master#e659cf9d9b5b3b131419e2f55f2e595f562baafc as 3.1.0", "shlinkio/shlink-config": "^1.0", "shlinkio/shlink-event-dispatcher": "^1.4", - "shlinkio/shlink-installer": "dev-master#c1412b9e9a150f443874f05452f7ce8e6f9e0339 as 4.4.0", + "shlinkio/shlink-installer": "dev-master#487227bfc03233b44e8a113af0bc5bd0c6d67d5d as 5.0.0", "shlinkio/shlink-ip-geolocation": "^1.4", "symfony/console": "^5.0", "symfony/filesystem": "^5.0", diff --git a/config/autoload/installer.global.php b/config/autoload/installer.global.php index 8f8562e6..6c1bea01 100644 --- a/config/autoload/installer.global.php +++ b/config/autoload/installer.global.php @@ -8,29 +8,29 @@ return [ 'installer' => [ 'enabled_options' => [ - Option\DatabaseDriverConfigOption::class, - Option\DatabaseNameConfigOption::class, - Option\DatabaseHostConfigOption::class, - Option\DatabasePortConfigOption::class, - Option\DatabaseUserConfigOption::class, - Option\DatabasePasswordConfigOption::class, - Option\DatabaseSqlitePathConfigOption::class, - Option\DatabaseMySqlOptionsConfigOption::class, - Option\ShortDomainHostConfigOption::class, - Option\ShortDomainSchemaConfigOption::class, - Option\ValidateUrlConfigOption::class, - Option\VisitsWebhooksConfigOption::class, - Option\BaseUrlRedirectConfigOption::class, - Option\InvalidShortUrlRedirectConfigOption::class, - Option\Regular404RedirectConfigOption::class, + Option\Database\DatabaseDriverConfigOption::class, + Option\Database\DatabaseNameConfigOption::class, + Option\Database\DatabaseHostConfigOption::class, + Option\Database\DatabasePortConfigOption::class, + Option\Database\DatabaseUserConfigOption::class, + Option\Database\DatabasePasswordConfigOption::class, + Option\Database\DatabaseSqlitePathConfigOption::class, + Option\Database\DatabaseMySqlOptionsConfigOption::class, + Option\UrlShortener\ShortDomainHostConfigOption::class, + Option\UrlShortener\ShortDomainSchemaConfigOption::class, + Option\UrlShortener\ValidateUrlConfigOption::class, + Option\Visit\VisitsWebhooksConfigOption::class, + Option\Redirect\BaseUrlRedirectConfigOption::class, + Option\Redirect\InvalidShortUrlRedirectConfigOption::class, + Option\Redirect\Regular404RedirectConfigOption::class, Option\DisableTrackParamConfigOption::class, - Option\CheckVisitsThresholdConfigOption::class, - Option\VisitsThresholdConfigOption::class, + Option\Visit\CheckVisitsThresholdConfigOption::class, + Option\Visit\VisitsThresholdConfigOption::class, Option\BasePathConfigOption::class, - Option\TaskWorkerNumConfigOption::class, - Option\WebWorkerNumConfigOption::class, + Option\Worker\TaskWorkerNumConfigOption::class, + Option\Worker\WebWorkerNumConfigOption::class, Option\RedisServersConfigOption::class, - Option\ShortCodeLengthOption::class, + Option\UrlShortener\ShortCodeLengthOption::class, Option\Mercure\EnableMercureConfigOption::class, Option\Mercure\MercurePublicUrlConfigOption::class, Option\Mercure\MercureInternalUrlConfigOption::class, diff --git a/module/Core/src/EventDispatcher/NotifyVisitToMercure.php b/module/Core/src/EventDispatcher/NotifyVisitToMercure.php index 69527413..af6dd33f 100644 --- a/module/Core/src/EventDispatcher/NotifyVisitToMercure.php +++ b/module/Core/src/EventDispatcher/NotifyVisitToMercure.php @@ -44,6 +44,7 @@ class NotifyVisitToMercure } try { + ($this->publisher)($this->updatesGenerator->newShortUrlVisitUpdate($visit)); ($this->publisher)($this->updatesGenerator->newVisitUpdate($visit)); } catch (Throwable $e) { $this->logger->debug('Error while trying to notify mercure hub with new visit. {e}', [ diff --git a/module/Core/src/Mercure/MercureUpdatesGenerator.php b/module/Core/src/Mercure/MercureUpdatesGenerator.php index 47d4b7be..513b8e50 100644 --- a/module/Core/src/Mercure/MercureUpdatesGenerator.php +++ b/module/Core/src/Mercure/MercureUpdatesGenerator.php @@ -9,6 +9,7 @@ use Shlinkio\Shlink\Core\Transformer\ShortUrlDataTransformer; use Symfony\Component\Mercure\Update; use function json_encode; +use function sprintf; use const JSON_THROW_ON_ERROR; @@ -25,9 +26,25 @@ final class MercureUpdatesGenerator implements MercureUpdatesGeneratorInterface public function newVisitUpdate(Visit $visit): Update { - return new Update(self::NEW_VISIT_TOPIC, json_encode([ + return new Update(self::NEW_VISIT_TOPIC, $this->serialize([ 'shortUrl' => $this->transformer->transform($visit->getShortUrl()), - 'visit' => $visit->jsonSerialize(), - ], JSON_THROW_ON_ERROR)); + 'visit' => $visit, + ])); + } + + public function newShortUrlVisitUpdate(Visit $visit): Update + { + $shortUrl = $visit->getShortUrl(); + $topic = sprintf('%s/%s', self::NEW_VISIT_TOPIC, $shortUrl->getShortCode()); + + return new Update($topic, $this->serialize([ + 'shortUrl' => $this->transformer->transform($visit->getShortUrl()), + 'visit' => $visit, + ])); + } + + private function serialize(array $data): string + { + return json_encode($data, JSON_THROW_ON_ERROR); } } diff --git a/module/Core/src/Mercure/MercureUpdatesGeneratorInterface.php b/module/Core/src/Mercure/MercureUpdatesGeneratorInterface.php index af539803..d433d9ad 100644 --- a/module/Core/src/Mercure/MercureUpdatesGeneratorInterface.php +++ b/module/Core/src/Mercure/MercureUpdatesGeneratorInterface.php @@ -10,4 +10,6 @@ use Symfony\Component\Mercure\Update; interface MercureUpdatesGeneratorInterface { public function newVisitUpdate(Visit $visit): Update; + + public function newShortUrlVisitUpdate(Visit $visit): Update; } diff --git a/module/Core/test/EventDispatcher/NotifyVisitToMercureTest.php b/module/Core/test/EventDispatcher/NotifyVisitToMercureTest.php index 07f8bd1c..fce53344 100644 --- a/module/Core/test/EventDispatcher/NotifyVisitToMercureTest.php +++ b/module/Core/test/EventDispatcher/NotifyVisitToMercureTest.php @@ -43,7 +43,7 @@ class NotifyVisitToMercureTest extends TestCase } /** @test */ - public function notificationIsNotSentWhenVisitCannotBeFound(): void + public function notificationsAreNotSentWhenVisitCannotBeFound(): void { $visitId = '123'; $findVisit = $this->em->find(Visit::class, $visitId)->willReturn(null); @@ -52,6 +52,9 @@ class NotifyVisitToMercureTest extends TestCase ['visitId' => $visitId], ); $logDebug = $this->logger->debug(Argument::cetera()); + $buildNewShortUrlVisitUpdate = $this->updatesGenerator->newShortUrlVisitUpdate( + Argument::type(Visit::class), + )->willReturn(new Update('', '')); $buildNewVisitUpdate = $this->updatesGenerator->newVisitUpdate(Argument::type(Visit::class))->willReturn( new Update('', ''), ); @@ -62,12 +65,13 @@ class NotifyVisitToMercureTest extends TestCase $findVisit->shouldHaveBeenCalledOnce(); $logWarning->shouldHaveBeenCalledOnce(); $logDebug->shouldNotHaveBeenCalled(); + $buildNewShortUrlVisitUpdate->shouldNotHaveBeenCalled(); $buildNewVisitUpdate->shouldNotHaveBeenCalled(); $publish->shouldNotHaveBeenCalled(); } /** @test */ - public function notificationIsSentWhenVisitIsFound(): void + public function notificationsAreSentWhenVisitIsFound(): void { $visitId = '123'; $visit = new Visit(new ShortUrl(''), Visitor::emptyInstance()); @@ -76,6 +80,7 @@ class NotifyVisitToMercureTest extends TestCase $findVisit = $this->em->find(Visit::class, $visitId)->willReturn($visit); $logWarning = $this->logger->warning(Argument::cetera()); $logDebug = $this->logger->debug(Argument::cetera()); + $buildNewShortUrlVisitUpdate = $this->updatesGenerator->newShortUrlVisitUpdate($visit)->willReturn($update); $buildNewVisitUpdate = $this->updatesGenerator->newVisitUpdate($visit)->willReturn($update); $publish = $this->publisher->__invoke($update); @@ -84,8 +89,9 @@ class NotifyVisitToMercureTest extends TestCase $findVisit->shouldHaveBeenCalledOnce(); $logWarning->shouldNotHaveBeenCalled(); $logDebug->shouldNotHaveBeenCalled(); + $buildNewShortUrlVisitUpdate->shouldHaveBeenCalledOnce(); $buildNewVisitUpdate->shouldHaveBeenCalledOnce(); - $publish->shouldHaveBeenCalledOnce(); + $publish->shouldHaveBeenCalledTimes(2); } /** @test */ @@ -101,6 +107,7 @@ class NotifyVisitToMercureTest extends TestCase $logDebug = $this->logger->debug('Error while trying to notify mercure hub with new visit. {e}', [ 'e' => $e, ]); + $buildNewShortUrlVisitUpdate = $this->updatesGenerator->newShortUrlVisitUpdate($visit)->willReturn($update); $buildNewVisitUpdate = $this->updatesGenerator->newVisitUpdate($visit)->willReturn($update); $publish = $this->publisher->__invoke($update)->willThrow($e); @@ -109,7 +116,8 @@ class NotifyVisitToMercureTest extends TestCase $findVisit->shouldHaveBeenCalledOnce(); $logWarning->shouldNotHaveBeenCalled(); $logDebug->shouldHaveBeenCalledOnce(); - $buildNewVisitUpdate->shouldHaveBeenCalledOnce(); + $buildNewShortUrlVisitUpdate->shouldHaveBeenCalledOnce(); + $buildNewVisitUpdate->shouldNotHaveBeenCalled(); $publish->shouldHaveBeenCalledOnce(); } } diff --git a/module/Core/test/Mercure/MercureUpdatesGeneratorTest.php b/module/Core/test/Mercure/MercureUpdatesGeneratorTest.php index 361d3b2f..f72cd82d 100644 --- a/module/Core/test/Mercure/MercureUpdatesGeneratorTest.php +++ b/module/Core/test/Mercure/MercureUpdatesGeneratorTest.php @@ -8,6 +8,7 @@ use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Entity\ShortUrl; use Shlinkio\Shlink\Core\Entity\Visit; use Shlinkio\Shlink\Core\Mercure\MercureUpdatesGenerator; +use Shlinkio\Shlink\Core\Model\ShortUrlMeta; use Shlinkio\Shlink\Core\Model\Visitor; use function Shlinkio\Shlink\Common\json_decode; @@ -21,15 +22,18 @@ class MercureUpdatesGeneratorTest extends TestCase $this->generator = new MercureUpdatesGenerator([]); } - /** @test */ - public function visitIsProperlySerializedIntoUpdate(): void + /** + * @test + * @dataProvider provideMethod + */ + public function visitIsProperlySerializedIntoUpdate(string $method, string $expectedTopic): void { - $shortUrl = new ShortUrl(''); + $shortUrl = new ShortUrl('', ShortUrlMeta::fromRawData(['customSlug' => 'foo'])); $visit = new Visit($shortUrl, Visitor::emptyInstance()); - $update = $this->generator->newVisitUpdate($visit); + $update = $this->generator->{$method}($visit); - $this->assertEquals(['https://shlink.io/new_visit'], $update->getTopics()); + $this->assertEquals([$expectedTopic], $update->getTopics()); $this->assertEquals([ 'shortUrl' => [ 'shortCode' => $shortUrl->getShortCode(), @@ -53,4 +57,10 @@ class MercureUpdatesGeneratorTest extends TestCase ], ], json_decode($update->getData())); } + + public function provideMethod(): iterable + { + yield 'newVisitUpdate' => ['newVisitUpdate', 'https://shlink.io/new_visit']; + yield 'newShortUrlVisitUpdate' => ['newShortUrlVisitUpdate', 'https://shlink.io/new_visit/foo']; + } }