From bca3e62cede32d08f679352a8854670a5d0e0bce Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Sat, 23 Apr 2022 14:00:47 +0200 Subject: [PATCH] Updated to readonly public props on as many models as possible --- .../Command/Domain/DomainRedirectsCommand.php | 2 +- .../src/Command/Domain/ListDomainsCommand.php | 4 +- .../ShortUrl/DeleteShortUrlCommand.php | 2 +- .../CLI/src/Command/Tag/ListTagsCommand.php | 2 +- .../Command/Util/AbstractLockedCommand.php | 6 +-- .../src/Command/Util/LockedCommandConfig.php | 21 ++--------- module/CLI/src/Util/ShlinkTable.php | 2 +- .../ShortUrl/DeleteShortUrlCommandTest.php | 26 +++++++------ .../Command/ShortUrl/GetVisitsCommandTest.php | 11 ++++-- .../ShortUrl/ResolveUrlCommandTest.php | 9 +++-- module/Core/src/Action/Model/QrCodeParams.php | 35 +++--------------- module/Core/src/Action/QrCodeAction.php | 10 ++--- module/Core/src/Config/NotFoundRedirects.php | 21 ++--------- module/Core/src/Domain/Model/DomainItem.php | 20 +++------- module/Core/src/Entity/Domain.php | 6 +-- module/Core/src/Entity/Visit.php | 8 ++-- .../Event/AbstractVisitEvent.php | 7 +--- .../src/EventDispatcher/Event/UrlVisited.php | 7 +--- .../Core/src/EventDispatcher/LocateVisit.php | 4 +- .../EventDispatcher/NotifyVisitToMercure.php | 2 +- .../EventDispatcher/NotifyVisitToRabbitMq.php | 2 +- .../EventDispatcher/NotifyVisitToWebHooks.php | 2 +- .../src/Exception/DeleteShortUrlException.php | 4 +- .../Exception/ShortUrlNotFoundException.php | 4 +- .../Core/src/Importer/ShortUrlImporting.php | 2 +- .../AbstractInfinitePaginableListParams.php | 14 +------ module/Core/src/Model/Ordering.php | 12 +----- module/Core/src/Model/ShortUrlIdentifier.php | 12 +----- module/Core/src/Model/Visitor.php | 28 ++------------ module/Core/src/Model/VisitsParams.php | 14 +------ .../src/Repository/ShortUrlRepository.php | 12 +++--- module/Core/src/Repository/TagRepository.php | 16 ++++---- .../Core/src/Repository/VisitRepository.php | 34 ++++++++--------- module/Core/src/Tag/Model/TagInfo.php | 22 +++-------- module/Core/src/Tag/Model/TagRenaming.php | 12 +----- .../Core/src/Tag/Model/TagsListFiltering.php | 37 +++---------------- module/Core/src/Tag/Model/TagsParams.php | 21 ++--------- .../Adapter/AbstractTagsPaginatorAdapter.php | 2 +- .../Adapter/TagsPaginatorAdapter.php | 4 +- module/Core/src/Tag/TagService.php | 12 +++--- .../Adapter/DomainVisitsPaginatorAdapter.php | 8 ++-- .../NonOrphanVisitsPaginatorAdapter.php | 8 ++-- .../Adapter/OrphanVisitsPaginatorAdapter.php | 8 ++-- .../ShortUrlVisitsPaginatorAdapter.php | 8 ++-- .../Adapter/TagVisitsPaginatorAdapter.php | 8 ++-- .../Persistence/VisitsCountFiltering.php | 21 ++--------- .../Visit/Persistence/VisitsListFiltering.php | 14 +------ .../src/Visit/Spec/CountOfNonOrphanVisits.php | 6 +-- .../src/Visit/Spec/CountOfOrphanVisits.php | 4 +- module/Core/src/Visit/VisitsStatsHelper.php | 4 +- module/Core/src/Visit/VisitsTracker.php | 2 +- .../test-db/Repository/TagRepositoryTest.php | 8 ++-- module/Core/test/Action/PixelActionTest.php | 7 ++-- module/Core/test/Action/QrCodeActionTest.php | 10 ++--- .../Core/test/Action/RedirectActionTest.php | 4 +- .../ShortUrlNotFoundExceptionTest.php | 2 +- module/Core/test/Model/VisitorTest.php | 18 ++++----- .../ShortUrl/DeleteShortUrlServiceTest.php | 8 ++-- .../Service/ShortUrl/ShortUrlResolverTest.php | 4 +- .../Core/test/Service/ShortUrlServiceTest.php | 8 +++- .../NonOrphanVisitsPaginatorAdapterTest.php | 6 +-- .../OrphanVisitsPaginatorAdapterTest.php | 4 +- .../ShortUrlVisitsPaginatorAdapterTest.php | 2 +- module/Rest/src/Action/Tag/ListTagsAction.php | 4 +- module/Rest/src/ApiKey/Model/ApiKeyMeta.php | 28 +++----------- .../Rest/src/ApiKey/Model/RoleDefinition.php | 12 +----- module/Rest/src/Entity/ApiKey.php | 15 +++----- .../Middleware/AuthenticationMiddleware.php | 2 +- module/Rest/src/Service/ApiKeyCheckResult.php | 7 +--- .../Request/DomainRedirectsRequestTest.php | 6 +-- .../ShortUrl/ResolveShortUrlActionTest.php | 8 ++-- .../Action/Visit/ShortUrlVisitsActionTest.php | 4 +- .../test/ApiKey/Model/RoleDefinitionTest.php | 8 ++-- .../Rest/test/Service/ApiKeyServiceTest.php | 6 +-- 74 files changed, 249 insertions(+), 494 deletions(-) diff --git a/module/CLI/src/Command/Domain/DomainRedirectsCommand.php b/module/CLI/src/Command/Domain/DomainRedirectsCommand.php index 90cfd1f7..c546fd5b 100644 --- a/module/CLI/src/Command/Domain/DomainRedirectsCommand.php +++ b/module/CLI/src/Command/Domain/DomainRedirectsCommand.php @@ -53,7 +53,7 @@ class DomainRedirectsCommand extends Command /** @var string[] $availableDomains */ $availableDomains = invoke( - filter($this->domainService->listDomains(), static fn (DomainItem $item) => ! $item->isDefault()), + filter($this->domainService->listDomains(), static fn (DomainItem $item) => ! $item->isDefault), 'toString', ); if (empty($availableDomains)) { diff --git a/module/CLI/src/Command/Domain/ListDomainsCommand.php b/module/CLI/src/Command/Domain/ListDomainsCommand.php index 447bf92f..8f2ee22c 100644 --- a/module/CLI/src/Command/Domain/ListDomainsCommand.php +++ b/module/CLI/src/Command/Domain/ListDomainsCommand.php @@ -48,12 +48,12 @@ class ListDomainsCommand extends Command $table->render( $showRedirects ? [...$commonFields, '"Not found" redirects'] : $commonFields, map($domains, function (DomainItem $domain) use ($showRedirects) { - $commonValues = [$domain->toString(), $domain->isDefault() ? 'Yes' : 'No']; + $commonValues = [$domain->toString(), $domain->isDefault ? 'Yes' : 'No']; return $showRedirects ? [ ...$commonValues, - $this->notFoundRedirectsToString($domain->notFoundRedirectConfig()), + $this->notFoundRedirectsToString($domain->notFoundRedirectConfig), ] : $commonValues; }), diff --git a/module/CLI/src/Command/ShortUrl/DeleteShortUrlCommand.php b/module/CLI/src/Command/ShortUrl/DeleteShortUrlCommand.php index fc4e8331..db1b1dfd 100644 --- a/module/CLI/src/Command/ShortUrl/DeleteShortUrlCommand.php +++ b/module/CLI/src/Command/ShortUrl/DeleteShortUrlCommand.php @@ -81,6 +81,6 @@ class DeleteShortUrlCommand extends Command private function runDelete(SymfonyStyle $io, ShortUrlIdentifier $identifier, bool $ignoreThreshold): void { $this->deleteShortUrlService->deleteByShortCode($identifier, $ignoreThreshold); - $io->success(sprintf('Short URL with short code "%s" successfully deleted.', $identifier->shortCode())); + $io->success(sprintf('Short URL with short code "%s" successfully deleted.', $identifier->shortCode)); } } diff --git a/module/CLI/src/Command/Tag/ListTagsCommand.php b/module/CLI/src/Command/Tag/ListTagsCommand.php index 9c7269fa..cd820169 100644 --- a/module/CLI/src/Command/Tag/ListTagsCommand.php +++ b/module/CLI/src/Command/Tag/ListTagsCommand.php @@ -46,7 +46,7 @@ class ListTagsCommand extends Command return map( $tags, - static fn (TagInfo $tagInfo) => [$tagInfo->tag(), $tagInfo->shortUrlsCount(), $tagInfo->visitsCount()], + static fn (TagInfo $tagInfo) => [$tagInfo->tag, $tagInfo->shortUrlsCount, $tagInfo->visitsCount], ); } } diff --git a/module/CLI/src/Command/Util/AbstractLockedCommand.php b/module/CLI/src/Command/Util/AbstractLockedCommand.php index 9482694b..5f3a33ea 100644 --- a/module/CLI/src/Command/Util/AbstractLockedCommand.php +++ b/module/CLI/src/Command/Util/AbstractLockedCommand.php @@ -22,11 +22,11 @@ abstract class AbstractLockedCommand extends Command final protected function execute(InputInterface $input, OutputInterface $output): ?int { $lockConfig = $this->getLockConfig(); - $lock = $this->locker->createLock($lockConfig->lockName(), $lockConfig->ttl(), $lockConfig->isBlocking()); + $lock = $this->locker->createLock($lockConfig->lockName, $lockConfig->ttl, $lockConfig->isBlocking); - if (! $lock->acquire($lockConfig->isBlocking())) { + if (! $lock->acquire($lockConfig->isBlocking)) { $output->writeln( - sprintf('Command "%s" is already in progress. Skipping.', $lockConfig->lockName()), + sprintf('Command "%s" is already in progress. Skipping.', $lockConfig->lockName), ); return ExitCodes::EXIT_WARNING; } diff --git a/module/CLI/src/Command/Util/LockedCommandConfig.php b/module/CLI/src/Command/Util/LockedCommandConfig.php index f053d99a..8e357329 100644 --- a/module/CLI/src/Command/Util/LockedCommandConfig.php +++ b/module/CLI/src/Command/Util/LockedCommandConfig.php @@ -9,9 +9,9 @@ final class LockedCommandConfig public const DEFAULT_TTL = 600.0; // 10 minutes private function __construct( - private string $lockName, - private bool $isBlocking, - private float $ttl = self::DEFAULT_TTL, + public readonly string $lockName, + public readonly bool $isBlocking, + public readonly float $ttl = self::DEFAULT_TTL, ) { } @@ -24,19 +24,4 @@ final class LockedCommandConfig { return new self($lockName, false); } - - public function lockName(): string - { - return $this->lockName; - } - - public function isBlocking(): bool - { - return $this->isBlocking; - } - - public function ttl(): float - { - return $this->ttl; - } } diff --git a/module/CLI/src/Util/ShlinkTable.php b/module/CLI/src/Util/ShlinkTable.php index 1d4143c1..cd38e5cd 100644 --- a/module/CLI/src/Util/ShlinkTable.php +++ b/module/CLI/src/Util/ShlinkTable.php @@ -15,7 +15,7 @@ final class ShlinkTable private const DEFAULT_STYLE_NAME = 'default'; private const TABLE_TITLE_STYLE = ' %s '; - private function __construct(private Table $baseTable, private bool $withRowSeparators) + private function __construct(private readonly Table $baseTable, private readonly bool $withRowSeparators) { } diff --git a/module/CLI/test/Command/ShortUrl/DeleteShortUrlCommandTest.php b/module/CLI/test/Command/ShortUrl/DeleteShortUrlCommandTest.php index 10a363c7..947b7443 100644 --- a/module/CLI/test/Command/ShortUrl/DeleteShortUrlCommandTest.php +++ b/module/CLI/test/Command/ShortUrl/DeleteShortUrlCommandTest.php @@ -36,10 +36,11 @@ class DeleteShortUrlCommandTest extends TestCase public function successMessageIsPrintedIfUrlIsProperlyDeleted(): void { $shortCode = 'abc123'; - $deleteByShortCode = $this->service->deleteByShortCode(new ShortUrlIdentifier($shortCode), false)->will( - function (): void { - }, - ); + $deleteByShortCode = $this->service->deleteByShortCode( + ShortUrlIdentifier::fromShortCodeAndDomain($shortCode), + false, + )->will(function (): void { + }); $this->commandTester->execute(['shortCode' => $shortCode]); $output = $this->commandTester->getDisplay(); @@ -55,7 +56,7 @@ class DeleteShortUrlCommandTest extends TestCase public function invalidShortCodePrintsMessage(): void { $shortCode = 'abc123'; - $identifier = new ShortUrlIdentifier($shortCode); + $identifier = ShortUrlIdentifier::fromShortCodeAndDomain($shortCode); $deleteByShortCode = $this->service->deleteByShortCode($identifier, false)->willThrow( Exception\ShortUrlNotFoundException::fromNotFound($identifier), ); @@ -77,7 +78,7 @@ class DeleteShortUrlCommandTest extends TestCase string $expectedMessage, ): void { $shortCode = 'abc123'; - $identifier = new ShortUrlIdentifier($shortCode); + $identifier = ShortUrlIdentifier::fromShortCodeAndDomain($shortCode); $deleteByShortCode = $this->service->deleteByShortCode($identifier, Argument::type('bool'))->will( function (array $args) use ($shortCode): void { $ignoreThreshold = array_pop($args); @@ -114,12 +115,13 @@ class DeleteShortUrlCommandTest extends TestCase public function deleteIsNotRetriedWhenThresholdIsReachedAndQuestionIsDeclined(): void { $shortCode = 'abc123'; - $deleteByShortCode = $this->service->deleteByShortCode(new ShortUrlIdentifier($shortCode), false)->willThrow( - Exception\DeleteShortUrlException::fromVisitsThreshold( - 10, - ShortUrlIdentifier::fromShortCodeAndDomain($shortCode), - ), - ); + $deleteByShortCode = $this->service->deleteByShortCode( + ShortUrlIdentifier::fromShortCodeAndDomain($shortCode), + false, + )->willThrow(Exception\DeleteShortUrlException::fromVisitsThreshold( + 10, + ShortUrlIdentifier::fromShortCodeAndDomain($shortCode), + )); $this->commandTester->setInputs(['no']); $this->commandTester->execute(['shortCode' => $shortCode]); diff --git a/module/CLI/test/Command/ShortUrl/GetVisitsCommandTest.php b/module/CLI/test/Command/ShortUrl/GetVisitsCommandTest.php index ca9e0981..7a884c89 100644 --- a/module/CLI/test/Command/ShortUrl/GetVisitsCommandTest.php +++ b/module/CLI/test/Command/ShortUrl/GetVisitsCommandTest.php @@ -44,7 +44,7 @@ class GetVisitsCommandTest extends TestCase { $shortCode = 'abc123'; $this->visitsHelper->visitsForShortUrl( - new ShortUrlIdentifier($shortCode), + ShortUrlIdentifier::fromShortCodeAndDomain($shortCode), new VisitsParams(DateRange::emptyInstance()), ) ->willReturn(new Paginator(new ArrayAdapter([]))) @@ -60,7 +60,7 @@ class GetVisitsCommandTest extends TestCase $startDate = '2016-01-01'; $endDate = '2016-02-01'; $this->visitsHelper->visitsForShortUrl( - new ShortUrlIdentifier($shortCode), + ShortUrlIdentifier::fromShortCodeAndDomain($shortCode), new VisitsParams(DateRange::withStartAndEndDate(Chronos::parse($startDate), Chronos::parse($endDate))), ) ->willReturn(new Paginator(new ArrayAdapter([]))) @@ -79,7 +79,7 @@ class GetVisitsCommandTest extends TestCase $shortCode = 'abc123'; $startDate = 'foo'; $info = $this->visitsHelper->visitsForShortUrl( - new ShortUrlIdentifier($shortCode), + ShortUrlIdentifier::fromShortCodeAndDomain($shortCode), new VisitsParams(DateRange::emptyInstance()), )->willReturn(new Paginator(new ArrayAdapter([]))); @@ -100,7 +100,10 @@ class GetVisitsCommandTest extends TestCase public function outputIsProperlyGenerated(): void { $shortCode = 'abc123'; - $this->visitsHelper->visitsForShortUrl(new ShortUrlIdentifier($shortCode), Argument::any())->willReturn( + $this->visitsHelper->visitsForShortUrl( + ShortUrlIdentifier::fromShortCodeAndDomain($shortCode), + Argument::any(), + )->willReturn( new Paginator(new ArrayAdapter([ Visit::forValidShortUrl(ShortUrl::createEmpty(), new Visitor('bar', 'foo', '', ''))->locate( VisitLocation::fromGeolocation(new Location('', 'Spain', '', '', 0, 0, '')), diff --git a/module/CLI/test/Command/ShortUrl/ResolveUrlCommandTest.php b/module/CLI/test/Command/ShortUrl/ResolveUrlCommandTest.php index 2a816207..12e29eaf 100644 --- a/module/CLI/test/Command/ShortUrl/ResolveUrlCommandTest.php +++ b/module/CLI/test/Command/ShortUrl/ResolveUrlCommandTest.php @@ -37,8 +37,9 @@ class ResolveUrlCommandTest extends TestCase $shortCode = 'abc123'; $expectedUrl = 'http://domain.com/foo/bar'; $shortUrl = ShortUrl::withLongUrl($expectedUrl); - $this->urlResolver->resolveShortUrl(new ShortUrlIdentifier($shortCode))->willReturn($shortUrl) - ->shouldBeCalledOnce(); + $this->urlResolver->resolveShortUrl(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode))->willReturn( + $shortUrl, + )->shouldBeCalledOnce(); $this->commandTester->execute(['shortCode' => $shortCode]); $output = $this->commandTester->getDisplay(); @@ -48,8 +49,8 @@ class ResolveUrlCommandTest extends TestCase /** @test */ public function incorrectShortCodeOutputsErrorMessage(): void { - $identifier = new ShortUrlIdentifier('abc123'); - $shortCode = $identifier->shortCode(); + $identifier = ShortUrlIdentifier::fromShortCodeAndDomain('abc123'); + $shortCode = $identifier->shortCode; $this->urlResolver->resolveShortUrl($identifier) ->willThrow(ShortUrlNotFoundException::fromNotFound($identifier)) diff --git a/module/Core/src/Action/Model/QrCodeParams.php b/module/Core/src/Action/Model/QrCodeParams.php index 42d643d3..7c1f0e34 100644 --- a/module/Core/src/Action/Model/QrCodeParams.php +++ b/module/Core/src/Action/Model/QrCodeParams.php @@ -29,11 +29,11 @@ final class QrCodeParams private const SUPPORTED_FORMATS = ['png', 'svg']; private function __construct( - private int $size, - private int $margin, - private WriterInterface $writer, - private ErrorCorrectionLevelInterface $errorCorrectionLevel, - private RoundBlockSizeModeInterface $roundBlockSizeMode, + public readonly int $size, + public readonly int $margin, + public readonly WriterInterface $writer, + public readonly ErrorCorrectionLevelInterface $errorCorrectionLevel, + public readonly RoundBlockSizeModeInterface $roundBlockSizeMode, ) { } @@ -105,29 +105,4 @@ final class QrCodeParams { return strtolower(trim($param)); } - - public function size(): int - { - return $this->size; - } - - public function margin(): int - { - return $this->margin; - } - - public function writer(): WriterInterface - { - return $this->writer; - } - - public function errorCorrectionLevel(): ErrorCorrectionLevelInterface - { - return $this->errorCorrectionLevel; - } - - public function roundBlockSizeMode(): RoundBlockSizeModeInterface - { - return $this->roundBlockSizeMode; - } } diff --git a/module/Core/src/Action/QrCodeAction.php b/module/Core/src/Action/QrCodeAction.php index 7772a5c8..17bdbdfd 100644 --- a/module/Core/src/Action/QrCodeAction.php +++ b/module/Core/src/Action/QrCodeAction.php @@ -42,11 +42,11 @@ class QrCodeAction implements MiddlewareInterface $params = QrCodeParams::fromRequest($request, $this->defaultOptions); $qrCodeBuilder = Builder::create() ->data($this->stringifier->stringify($shortUrl)) - ->size($params->size()) - ->margin($params->margin()) - ->writer($params->writer()) - ->errorCorrectionLevel($params->errorCorrectionLevel()) - ->roundBlockSizeMode($params->roundBlockSizeMode()); + ->size($params->size) + ->margin($params->margin) + ->writer($params->writer) + ->errorCorrectionLevel($params->errorCorrectionLevel) + ->roundBlockSizeMode($params->roundBlockSizeMode); return new QrCodeResponse($qrCodeBuilder->build()); } diff --git a/module/Core/src/Config/NotFoundRedirects.php b/module/Core/src/Config/NotFoundRedirects.php index 492a00bc..48437924 100644 --- a/module/Core/src/Config/NotFoundRedirects.php +++ b/module/Core/src/Config/NotFoundRedirects.php @@ -9,9 +9,9 @@ use JsonSerializable; final class NotFoundRedirects implements JsonSerializable { private function __construct( - private ?string $baseUrlRedirect, - private ?string $regular404Redirect, - private ?string $invalidShortUrlRedirect, + public readonly ?string $baseUrlRedirect, + public readonly ?string $regular404Redirect, + public readonly ?string $invalidShortUrlRedirect, ) { } @@ -33,21 +33,6 @@ final class NotFoundRedirects implements JsonSerializable return new self($config->baseUrlRedirect(), $config->regular404Redirect(), $config->invalidShortUrlRedirect()); } - public function baseUrlRedirect(): ?string - { - return $this->baseUrlRedirect; - } - - public function regular404Redirect(): ?string - { - return $this->regular404Redirect; - } - - public function invalidShortUrlRedirect(): ?string - { - return $this->invalidShortUrlRedirect; - } - public function jsonSerialize(): array { return [ diff --git a/module/Core/src/Domain/Model/DomainItem.php b/module/Core/src/Domain/Model/DomainItem.php index 5547fe8d..cc968e95 100644 --- a/module/Core/src/Domain/Model/DomainItem.php +++ b/module/Core/src/Domain/Model/DomainItem.php @@ -12,9 +12,9 @@ use Shlinkio\Shlink\Core\Entity\Domain; final class DomainItem implements JsonSerializable { private function __construct( - private string $authority, - private NotFoundRedirectConfigInterface $notFoundRedirectConfig, - private bool $isDefault, + private readonly string $authority, + public readonly NotFoundRedirectConfigInterface $notFoundRedirectConfig, + public readonly bool $isDefault, ) { } @@ -23,9 +23,9 @@ final class DomainItem implements JsonSerializable return new self($domain->getAuthority(), $domain, false); } - public static function forDefaultDomain(string $authority, NotFoundRedirectConfigInterface $config): self + public static function forDefaultDomain(string $defaultDomain, NotFoundRedirectConfigInterface $config): self { - return new self($authority, $config, true); + return new self($defaultDomain, $config, true); } public function jsonSerialize(): array @@ -41,14 +41,4 @@ final class DomainItem implements JsonSerializable { return $this->authority; } - - public function isDefault(): bool - { - return $this->isDefault; - } - - public function notFoundRedirectConfig(): NotFoundRedirectConfigInterface - { - return $this->notFoundRedirectConfig; - } } diff --git a/module/Core/src/Entity/Domain.php b/module/Core/src/Entity/Domain.php index 65ca8ce6..9c31bbe2 100644 --- a/module/Core/src/Entity/Domain.php +++ b/module/Core/src/Entity/Domain.php @@ -66,8 +66,8 @@ class Domain extends AbstractEntity implements JsonSerializable, NotFoundRedirec public function configureNotFoundRedirects(NotFoundRedirects $redirects): void { - $this->baseUrlRedirect = $redirects->baseUrlRedirect(); - $this->regular404Redirect = $redirects->regular404Redirect(); - $this->invalidShortUrlRedirect = $redirects->invalidShortUrlRedirect(); + $this->baseUrlRedirect = $redirects->baseUrlRedirect; + $this->regular404Redirect = $redirects->regular404Redirect; + $this->invalidShortUrlRedirect = $redirects->invalidShortUrlRedirect; } } diff --git a/module/Core/src/Entity/Visit.php b/module/Core/src/Entity/Visit.php index 31bfcdcd..48344a03 100644 --- a/module/Core/src/Entity/Visit.php +++ b/module/Core/src/Entity/Visit.php @@ -89,10 +89,10 @@ class Visit extends AbstractEntity implements JsonSerializable private function hydrateFromVisitor(Visitor $visitor, bool $anonymize = true): void { - $this->userAgent = $visitor->getUserAgent(); - $this->referer = $visitor->getReferer(); - $this->remoteAddr = $this->processAddress($anonymize, $visitor->getRemoteAddress()); - $this->visitedUrl = $visitor->getVisitedUrl(); + $this->userAgent = $visitor->userAgent; + $this->referer = $visitor->referer; + $this->remoteAddr = $this->processAddress($anonymize, $visitor->remoteAddress); + $this->visitedUrl = $visitor->visitedUrl; $this->potentialBot = $visitor->isPotentialBot(); } diff --git a/module/Core/src/EventDispatcher/Event/AbstractVisitEvent.php b/module/Core/src/EventDispatcher/Event/AbstractVisitEvent.php index c4bc1818..6fadaa5d 100644 --- a/module/Core/src/EventDispatcher/Event/AbstractVisitEvent.php +++ b/module/Core/src/EventDispatcher/Event/AbstractVisitEvent.php @@ -8,15 +8,10 @@ use JsonSerializable; abstract class AbstractVisitEvent implements JsonSerializable { - public function __construct(protected string $visitId) + public function __construct(public readonly string $visitId) { } - public function visitId(): string - { - return $this->visitId; - } - public function jsonSerialize(): array { return ['visitId' => $this->visitId]; diff --git a/module/Core/src/EventDispatcher/Event/UrlVisited.php b/module/Core/src/EventDispatcher/Event/UrlVisited.php index 633b439e..02452a3e 100644 --- a/module/Core/src/EventDispatcher/Event/UrlVisited.php +++ b/module/Core/src/EventDispatcher/Event/UrlVisited.php @@ -6,13 +6,8 @@ namespace Shlinkio\Shlink\Core\EventDispatcher\Event; final class UrlVisited extends AbstractVisitEvent { - public function __construct(string $visitId, private ?string $originalIpAddress = null) + public function __construct(string $visitId, public readonly ?string $originalIpAddress = null) { parent::__construct($visitId); } - - public function originalIpAddress(): ?string - { - return $this->originalIpAddress; - } } diff --git a/module/Core/src/EventDispatcher/LocateVisit.php b/module/Core/src/EventDispatcher/LocateVisit.php index fbd32962..197ce9a0 100644 --- a/module/Core/src/EventDispatcher/LocateVisit.php +++ b/module/Core/src/EventDispatcher/LocateVisit.php @@ -30,7 +30,7 @@ class LocateVisit public function __invoke(UrlVisited $shortUrlVisited): void { - $visitId = $shortUrlVisited->visitId(); + $visitId = $shortUrlVisited->visitId; /** @var Visit|null $visit */ $visit = $this->em->find(Visit::class, $visitId); @@ -41,7 +41,7 @@ class LocateVisit return; } - $this->locateVisit($visitId, $shortUrlVisited->originalIpAddress(), $visit); + $this->locateVisit($visitId, $shortUrlVisited->originalIpAddress, $visit); $this->eventDispatcher->dispatch(new VisitLocated($visitId)); } diff --git a/module/Core/src/EventDispatcher/NotifyVisitToMercure.php b/module/Core/src/EventDispatcher/NotifyVisitToMercure.php index ed205f40..096e7e65 100644 --- a/module/Core/src/EventDispatcher/NotifyVisitToMercure.php +++ b/module/Core/src/EventDispatcher/NotifyVisitToMercure.php @@ -27,7 +27,7 @@ class NotifyVisitToMercure public function __invoke(VisitLocated $shortUrlLocated): void { - $visitId = $shortUrlLocated->visitId(); + $visitId = $shortUrlLocated->visitId; /** @var Visit|null $visit */ $visit = $this->em->find(Visit::class, $visitId); diff --git a/module/Core/src/EventDispatcher/NotifyVisitToRabbitMq.php b/module/Core/src/EventDispatcher/NotifyVisitToRabbitMq.php index f05ecf64..a81f2cab 100644 --- a/module/Core/src/EventDispatcher/NotifyVisitToRabbitMq.php +++ b/module/Core/src/EventDispatcher/NotifyVisitToRabbitMq.php @@ -37,7 +37,7 @@ class NotifyVisitToRabbitMq return; } - $visitId = $shortUrlLocated->visitId(); + $visitId = $shortUrlLocated->visitId; $visit = $this->em->find(Visit::class, $visitId); if ($visit === null) { diff --git a/module/Core/src/EventDispatcher/NotifyVisitToWebHooks.php b/module/Core/src/EventDispatcher/NotifyVisitToWebHooks.php index 73ff9266..1bf09517 100644 --- a/module/Core/src/EventDispatcher/NotifyVisitToWebHooks.php +++ b/module/Core/src/EventDispatcher/NotifyVisitToWebHooks.php @@ -40,7 +40,7 @@ class NotifyVisitToWebHooks return; } - $visitId = $shortUrlLocated->visitId(); + $visitId = $shortUrlLocated->visitId; /** @var Visit|null $visit */ $visit = $this->em->find(Visit::class, $visitId); diff --git a/module/Core/src/Exception/DeleteShortUrlException.php b/module/Core/src/Exception/DeleteShortUrlException.php index e6f3bd0d..0d331400 100644 --- a/module/Core/src/Exception/DeleteShortUrlException.php +++ b/module/Core/src/Exception/DeleteShortUrlException.php @@ -20,8 +20,8 @@ class DeleteShortUrlException extends DomainException implements ProblemDetailsE public static function fromVisitsThreshold(int $threshold, ShortUrlIdentifier $identifier): self { - $shortCode = $identifier->shortCode(); - $domain = $identifier->domain(); + $shortCode = $identifier->shortCode; + $domain = $identifier->domain; $suffix = $domain === null ? '' : sprintf(' for domain "%s"', $domain); $e = new self(sprintf( 'Impossible to delete short URL with short code "%s"%s, since it has more than "%s" visits.', diff --git a/module/Core/src/Exception/ShortUrlNotFoundException.php b/module/Core/src/Exception/ShortUrlNotFoundException.php index 0ae29da5..c59c20ef 100644 --- a/module/Core/src/Exception/ShortUrlNotFoundException.php +++ b/module/Core/src/Exception/ShortUrlNotFoundException.php @@ -20,8 +20,8 @@ class ShortUrlNotFoundException extends DomainException implements ProblemDetail public static function fromNotFound(ShortUrlIdentifier $identifier): self { - $shortCode = $identifier->shortCode(); - $domain = $identifier->domain(); + $shortCode = $identifier->shortCode; + $domain = $identifier->domain; $suffix = $domain === null ? '' : sprintf(' for domain "%s"', $domain); $e = new self(sprintf('No URL found with short code "%s"%s', $shortCode, $suffix)); diff --git a/module/Core/src/Importer/ShortUrlImporting.php b/module/Core/src/Importer/ShortUrlImporting.php index e1680517..4aa87166 100644 --- a/module/Core/src/Importer/ShortUrlImporting.php +++ b/module/Core/src/Importer/ShortUrlImporting.php @@ -14,7 +14,7 @@ use function sprintf; final class ShortUrlImporting { - private function __construct(private ShortUrl $shortUrl, private bool $isNew) + private function __construct(private readonly ShortUrl $shortUrl, private readonly bool $isNew) { } diff --git a/module/Core/src/Model/AbstractInfinitePaginableListParams.php b/module/Core/src/Model/AbstractInfinitePaginableListParams.php index ae107fdc..d4b2aaab 100644 --- a/module/Core/src/Model/AbstractInfinitePaginableListParams.php +++ b/module/Core/src/Model/AbstractInfinitePaginableListParams.php @@ -10,8 +10,8 @@ abstract class AbstractInfinitePaginableListParams { private const FIRST_PAGE = 1; - private int $page; - private int $itemsPerPage; + public readonly int $page; + public readonly int $itemsPerPage; protected function __construct(?int $page, ?int $itemsPerPage) { @@ -28,14 +28,4 @@ abstract class AbstractInfinitePaginableListParams { return $itemsPerPage === null || $itemsPerPage < 0 ? Paginator::ALL_ITEMS : $itemsPerPage; } - - public function getPage(): int - { - return $this->page; - } - - public function getItemsPerPage(): int - { - return $this->itemsPerPage; - } } diff --git a/module/Core/src/Model/Ordering.php b/module/Core/src/Model/Ordering.php index bd648227..5adbb161 100644 --- a/module/Core/src/Model/Ordering.php +++ b/module/Core/src/Model/Ordering.php @@ -8,7 +8,7 @@ final class Ordering { private const DEFAULT_DIR = 'ASC'; - private function __construct(private ?string $field, private string $dir) + private function __construct(public readonly ?string $field, public readonly string $direction) { } @@ -26,16 +26,6 @@ final class Ordering return self::fromTuple([null, null]); } - public function orderField(): ?string - { - return $this->field; - } - - public function orderDirection(): string - { - return $this->dir; - } - public function hasOrderField(): bool { return $this->field !== null; diff --git a/module/Core/src/Model/ShortUrlIdentifier.php b/module/Core/src/Model/ShortUrlIdentifier.php index 815a5313..9b62f501 100644 --- a/module/Core/src/Model/ShortUrlIdentifier.php +++ b/module/Core/src/Model/ShortUrlIdentifier.php @@ -10,7 +10,7 @@ use Symfony\Component\Console\Input\InputInterface; final class ShortUrlIdentifier { - public function __construct(private string $shortCode, private ?string $domain = null) + public function __construct(public readonly string $shortCode, public readonly ?string $domain = null) { } @@ -54,14 +54,4 @@ final class ShortUrlIdentifier { return new self($shortCode, $domain); } - - public function shortCode(): string - { - return $this->shortCode; - } - - public function domain(): ?string - { - return $this->domain; - } } diff --git a/module/Core/src/Model/Visitor.php b/module/Core/src/Model/Visitor.php index 9436e900..2207fad8 100644 --- a/module/Core/src/Model/Visitor.php +++ b/module/Core/src/Model/Visitor.php @@ -18,10 +18,10 @@ final class Visitor public const REMOTE_ADDRESS_MAX_LENGTH = 256; public const VISITED_URL_MAX_LENGTH = 2048; - private string $userAgent; - private string $referer; - private string $visitedUrl; - private ?string $remoteAddress; + public readonly string $userAgent; + public readonly string $referer; + public readonly string $visitedUrl; + public readonly ?string $remoteAddress; private bool $potentialBot; public function __construct(string $userAgent, string $referer, ?string $remoteAddress, string $visitedUrl) @@ -61,26 +61,6 @@ final class Visitor return new self('cf-facebook', '', null, ''); } - public function getUserAgent(): string - { - return $this->userAgent; - } - - public function getReferer(): string - { - return $this->referer; - } - - public function getRemoteAddress(): ?string - { - return $this->remoteAddress; - } - - public function getVisitedUrl(): string - { - return $this->visitedUrl; - } - public function isPotentialBot(): bool { return $this->potentialBot; diff --git a/module/Core/src/Model/VisitsParams.php b/module/Core/src/Model/VisitsParams.php index 718a4bc5..ab9e8002 100644 --- a/module/Core/src/Model/VisitsParams.php +++ b/module/Core/src/Model/VisitsParams.php @@ -10,13 +10,13 @@ use function Shlinkio\Shlink\Core\parseDateRangeFromQuery; final class VisitsParams extends AbstractInfinitePaginableListParams { - private DateRange $dateRange; + public readonly DateRange $dateRange; public function __construct( ?DateRange $dateRange = null, ?int $page = null, ?int $itemsPerPage = null, - private bool $excludeBots = false, + public readonly bool $excludeBots = false, ) { parent::__construct($page, $itemsPerPage); $this->dateRange = $dateRange ?? DateRange::emptyInstance(); @@ -31,14 +31,4 @@ final class VisitsParams extends AbstractInfinitePaginableListParams isset($query['excludeBots']), ); } - - public function getDateRange(): DateRange - { - return $this->dateRange; - } - - public function excludeBots(): bool - { - return $this->excludeBots; - } } diff --git a/module/Core/src/Repository/ShortUrlRepository.php b/module/Core/src/Repository/ShortUrlRepository.php index 9852c530..357b7357 100644 --- a/module/Core/src/Repository/ShortUrlRepository.php +++ b/module/Core/src/Repository/ShortUrlRepository.php @@ -47,8 +47,8 @@ class ShortUrlRepository extends EntitySpecificationRepository implements ShortU private function processOrderByForList(QueryBuilder $qb, Ordering $orderBy): array { - $fieldName = $orderBy->orderField(); - $order = $orderBy->orderDirection(); + $fieldName = $orderBy->field; + $order = $orderBy->direction; if ($fieldName === 'visits') { // FIXME This query is inefficient. @@ -146,8 +146,8 @@ class ShortUrlRepository extends EntitySpecificationRepository implements ShortU $query = $this->getEntityManager()->createQuery($dql); $query->setMaxResults(1) ->setParameters([ - 'shortCode' => $identifier->shortCode(), - 'domain' => $identifier->domain(), + 'shortCode' => $identifier->shortCode, + 'domain' => $identifier->domain, ]); // Since we ordered by domain, we will have first the URL matching provided domain, followed by the one @@ -198,10 +198,10 @@ class ShortUrlRepository extends EntitySpecificationRepository implements ShortU $qb->from(ShortUrl::class, 's') ->where($qb->expr()->isNotNull('s.shortCode')) ->andWhere($qb->expr()->eq('s.shortCode', ':slug')) - ->setParameter('slug', $identifier->shortCode()) + ->setParameter('slug', $identifier->shortCode) ->setMaxResults(1); - $this->whereDomainIs($qb, $identifier->domain()); + $this->whereDomainIs($qb, $identifier->domain); $this->applySpecification($qb, $spec, 's'); diff --git a/module/Core/src/Repository/TagRepository.php b/module/Core/src/Repository/TagRepository.php index aa24e0a1..47dd0cf5 100644 --- a/module/Core/src/Repository/TagRepository.php +++ b/module/Core/src/Repository/TagRepository.php @@ -41,8 +41,8 @@ class TagRepository extends EntitySpecificationRepository implements TagReposito */ public function findTagsWithInfo(?TagsListFiltering $filtering = null): array { - $orderField = $filtering?->orderBy()?->orderField(); - $orderDir = $filtering?->orderBy()?->orderDirection(); + $orderField = $filtering?->orderBy?->field; + $orderDir = $filtering?->orderBy?->direction; $orderMainQuery = contains(['shortUrlsCount', 'visitsCount'], $orderField); $conn = $this->getEntityManager()->getConnection(); @@ -51,16 +51,16 @@ class TagRepository extends EntitySpecificationRepository implements TagReposito if (! $orderMainQuery) { $subQb->orderBy('t.name', $orderDir ?? 'ASC') - ->setMaxResults($filtering?->limit() ?? PHP_INT_MAX) - ->setFirstResult($filtering?->offset() ?? 0); + ->setMaxResults($filtering?->limit ?? PHP_INT_MAX) + ->setFirstResult($filtering?->offset ?? 0); } - $searchTerm = $filtering?->searchTerm(); + $searchTerm = $filtering?->searchTerm; if ($searchTerm !== null) { $subQb->andWhere($subQb->expr()->like('t.name', $conn->quote('%' . $searchTerm . '%'))); } - $apiKey = $filtering?->apiKey(); + $apiKey = $filtering?->apiKey; $this->applySpecification($subQb, new WithInlinedApiKeySpecsEnsuringJoin($apiKey), 't'); // A native query builder needs to be used here, because DQL and ORM query builders do not support @@ -97,8 +97,8 @@ class TagRepository extends EntitySpecificationRepository implements TagReposito $orderField === 'shortUrlsCount' ? 'short_urls_count' : 'visits_count', $orderDir ?? 'ASC', ) - ->setMaxResults($filtering?->limit() ?? PHP_INT_MAX) - ->setFirstResult($filtering?->offset() ?? 0); + ->setMaxResults($filtering?->limit ?? PHP_INT_MAX) + ->setFirstResult($filtering?->offset ?? 0); } // Add ordering by tag name, as a fallback in case of same amount, or as default ordering diff --git a/module/Core/src/Repository/VisitRepository.php b/module/Core/src/Repository/VisitRepository.php index 51a0c333..e0b51ce9 100644 --- a/module/Core/src/Repository/VisitRepository.php +++ b/module/Core/src/Repository/VisitRepository.php @@ -86,7 +86,7 @@ class VisitRepository extends EntitySpecificationRepository implements VisitRepo public function findVisitsByShortCode(ShortUrlIdentifier $identifier, VisitsListFiltering $filtering): array { $qb = $this->createVisitsByShortCodeQueryBuilder($identifier, $filtering); - return $this->resolveVisitsWithNativeQuery($qb, $filtering->limit(), $filtering->offset()); + return $this->resolveVisitsWithNativeQuery($qb, $filtering->limit, $filtering->offset); } public function countVisitsByShortCode(ShortUrlIdentifier $identifier, VisitsCountFiltering $filtering): int @@ -103,7 +103,7 @@ class VisitRepository extends EntitySpecificationRepository implements VisitRepo ): QueryBuilder { /** @var ShortUrlRepositoryInterface $shortUrlRepo */ $shortUrlRepo = $this->getEntityManager()->getRepository(ShortUrl::class); - $shortUrlId = $shortUrlRepo->findOne($identifier, $filtering->apiKey()?->spec())?->getId() ?? '-1'; + $shortUrlId = $shortUrlRepo->findOne($identifier, $filtering->apiKey?->spec())?->getId() ?? '-1'; // Parameters in this query need to be part of the query itself, as we need to use it as sub-query later // Since they are not provided by the caller, it's reasonably safe @@ -111,12 +111,12 @@ class VisitRepository extends EntitySpecificationRepository implements VisitRepo $qb->from(Visit::class, 'v') ->where($qb->expr()->eq('v.shortUrl', $shortUrlId)); - if ($filtering->excludeBots()) { + if ($filtering->excludeBots) { $qb->andWhere($qb->expr()->eq('v.potentialBot', 'false')); } // Apply date range filtering - $this->applyDatesInline($qb, $filtering->dateRange()); + $this->applyDatesInline($qb, $filtering->dateRange); return $qb; } @@ -124,7 +124,7 @@ class VisitRepository extends EntitySpecificationRepository implements VisitRepo public function findVisitsByTag(string $tag, VisitsListFiltering $filtering): array { $qb = $this->createVisitsByTagQueryBuilder($tag, $filtering); - return $this->resolveVisitsWithNativeQuery($qb, $filtering->limit(), $filtering->offset()); + return $this->resolveVisitsWithNativeQuery($qb, $filtering->limit, $filtering->offset); } public function countVisitsByTag(string $tag, VisitsCountFiltering $filtering): int @@ -144,12 +144,12 @@ class VisitRepository extends EntitySpecificationRepository implements VisitRepo ->join('s.tags', 't') ->where($qb->expr()->eq('t.name', $this->getEntityManager()->getConnection()->quote($tag))); - if ($filtering->excludeBots()) { + if ($filtering->excludeBots) { $qb->andWhere($qb->expr()->eq('v.potentialBot', 'false')); } - $this->applyDatesInline($qb, $filtering->dateRange()); - $this->applySpecification($qb, $filtering->apiKey()?->inlinedSpec(), 'v'); + $this->applyDatesInline($qb, $filtering->dateRange); + $this->applySpecification($qb, $filtering->apiKey?->inlinedSpec(), 'v'); return $qb; } @@ -160,7 +160,7 @@ class VisitRepository extends EntitySpecificationRepository implements VisitRepo public function findVisitsByDomain(string $domain, VisitsListFiltering $filtering): array { $qb = $this->createVisitsByDomainQueryBuilder($domain, $filtering); - return $this->resolveVisitsWithNativeQuery($qb, $filtering->limit(), $filtering->offset()); + return $this->resolveVisitsWithNativeQuery($qb, $filtering->limit, $filtering->offset); } public function countVisitsByDomain(string $domain, VisitsCountFiltering $filtering): int @@ -185,12 +185,12 @@ class VisitRepository extends EntitySpecificationRepository implements VisitRepo ->where($qb->expr()->eq('d.authority', $this->getEntityManager()->getConnection()->quote($domain))); } - if ($filtering->excludeBots()) { + if ($filtering->excludeBots) { $qb->andWhere($qb->expr()->eq('v.potentialBot', 'false')); } - $this->applyDatesInline($qb, $filtering->dateRange()); - $this->applySpecification($qb, $filtering->apiKey()?->inlinedSpec(), 'v'); + $this->applyDatesInline($qb, $filtering->dateRange); + $this->applySpecification($qb, $filtering->apiKey?->inlinedSpec(), 'v'); return $qb; } @@ -199,7 +199,7 @@ class VisitRepository extends EntitySpecificationRepository implements VisitRepo { $qb = $this->createAllVisitsQueryBuilder($filtering); $qb->andWhere($qb->expr()->isNull('v.shortUrl')); - return $this->resolveVisitsWithNativeQuery($qb, $filtering->limit(), $filtering->offset()); + return $this->resolveVisitsWithNativeQuery($qb, $filtering->limit, $filtering->offset); } public function countOrphanVisits(VisitsCountFiltering $filtering): int @@ -215,9 +215,9 @@ class VisitRepository extends EntitySpecificationRepository implements VisitRepo $qb = $this->createAllVisitsQueryBuilder($filtering); $qb->andWhere($qb->expr()->isNotNull('v.shortUrl')); - $this->applySpecification($qb, $filtering->apiKey()?->inlinedSpec()); + $this->applySpecification($qb, $filtering->apiKey?->inlinedSpec()); - return $this->resolveVisitsWithNativeQuery($qb, $filtering->limit(), $filtering->offset()); + return $this->resolveVisitsWithNativeQuery($qb, $filtering->limit, $filtering->offset); } public function countNonOrphanVisits(VisitsCountFiltering $filtering): int @@ -232,11 +232,11 @@ class VisitRepository extends EntitySpecificationRepository implements VisitRepo $qb = $this->getEntityManager()->createQueryBuilder(); $qb->from(Visit::class, 'v'); - if ($filtering->excludeBots()) { + if ($filtering->excludeBots) { $qb->andWhere($qb->expr()->eq('v.potentialBot', 'false')); } - $this->applyDatesInline($qb, $filtering->dateRange()); + $this->applyDatesInline($qb, $filtering->dateRange); return $qb; } diff --git a/module/Core/src/Tag/Model/TagInfo.php b/module/Core/src/Tag/Model/TagInfo.php index 6e917399..8a4f196b 100644 --- a/module/Core/src/Tag/Model/TagInfo.php +++ b/module/Core/src/Tag/Model/TagInfo.php @@ -8,23 +8,11 @@ use JsonSerializable; final class TagInfo implements JsonSerializable { - public function __construct(private string $tag, private int $shortUrlsCount, private int $visitsCount) - { - } - - public function tag(): string - { - return $this->tag; - } - - public function shortUrlsCount(): int - { - return $this->shortUrlsCount; - } - - public function visitsCount(): int - { - return $this->visitsCount; + public function __construct( + public readonly string $tag, + public readonly int $shortUrlsCount, + public readonly int $visitsCount, + ) { } public function jsonSerialize(): array diff --git a/module/Core/src/Tag/Model/TagRenaming.php b/module/Core/src/Tag/Model/TagRenaming.php index 3bdae21c..9c523b8b 100644 --- a/module/Core/src/Tag/Model/TagRenaming.php +++ b/module/Core/src/Tag/Model/TagRenaming.php @@ -10,7 +10,7 @@ use function sprintf; final class TagRenaming { - private function __construct(private string $oldName, private string $newName) + private function __construct(public readonly string $oldName, public readonly string $newName) { } @@ -31,16 +31,6 @@ final class TagRenaming return self::fromNames($payload['oldName'], $payload['newName']); } - public function oldName(): string - { - return $this->oldName; - } - - public function newName(): string - { - return $this->newName; - } - public function nameChanged(): bool { return $this->oldName !== $this->newName; diff --git a/module/Core/src/Tag/Model/TagsListFiltering.php b/module/Core/src/Tag/Model/TagsListFiltering.php index 8f078788..236dde4a 100644 --- a/module/Core/src/Tag/Model/TagsListFiltering.php +++ b/module/Core/src/Tag/Model/TagsListFiltering.php @@ -10,41 +10,16 @@ use Shlinkio\Shlink\Rest\Entity\ApiKey; final class TagsListFiltering { public function __construct( - private ?int $limit = null, - private ?int $offset = null, - private ?string $searchTerm = null, - private ?Ordering $orderBy = null, - private ?ApiKey $apiKey = null, + public readonly ?int $limit = null, + public readonly ?int $offset = null, + public readonly ?string $searchTerm = null, + public readonly ?Ordering $orderBy = null, + public readonly ?ApiKey $apiKey = null, ) { } public static function fromRangeAndParams(int $limit, int $offset, TagsParams $params, ?ApiKey $apiKey): self { - return new self($limit, $offset, $params->searchTerm(), $params->orderBy(), $apiKey); - } - - public function limit(): ?int - { - return $this->limit; - } - - public function offset(): ?int - { - return $this->offset; - } - - public function searchTerm(): ?string - { - return $this->searchTerm; - } - - public function orderBy(): ?Ordering - { - return $this->orderBy; - } - - public function apiKey(): ?ApiKey - { - return $this->apiKey; + return new self($limit, $offset, $params->searchTerm, $params->orderBy, $apiKey); } } diff --git a/module/Core/src/Tag/Model/TagsParams.php b/module/Core/src/Tag/Model/TagsParams.php index 3f40debe..633fd5f2 100644 --- a/module/Core/src/Tag/Model/TagsParams.php +++ b/module/Core/src/Tag/Model/TagsParams.php @@ -12,9 +12,9 @@ use function Shlinkio\Shlink\Common\parseOrderBy; final class TagsParams extends AbstractInfinitePaginableListParams { private function __construct( - private ?string $searchTerm, - private Ordering $orderBy, - private bool $withStats, + public readonly ?string $searchTerm, + public readonly Ordering $orderBy, + public readonly bool $withStats, ?int $page, ?int $itemsPerPage, ) { @@ -31,19 +31,4 @@ final class TagsParams extends AbstractInfinitePaginableListParams isset($query['itemsPerPage']) ? (int) $query['itemsPerPage'] : null, ); } - - public function searchTerm(): ?string - { - return $this->searchTerm; - } - - public function orderBy(): Ordering - { - return $this->orderBy; - } - - public function withStats(): bool - { - return $this->withStats; - } } diff --git a/module/Core/src/Tag/Paginator/Adapter/AbstractTagsPaginatorAdapter.php b/module/Core/src/Tag/Paginator/Adapter/AbstractTagsPaginatorAdapter.php index ba6bc78d..ee0086cd 100644 --- a/module/Core/src/Tag/Paginator/Adapter/AbstractTagsPaginatorAdapter.php +++ b/module/Core/src/Tag/Paginator/Adapter/AbstractTagsPaginatorAdapter.php @@ -30,7 +30,7 @@ abstract class AbstractTagsPaginatorAdapter implements AdapterInterface new WithApiKeySpecsEnsuringJoin($this->apiKey), ]; - $searchTerm = $this->params->searchTerm(); + $searchTerm = $this->params->searchTerm; if ($searchTerm !== null) { $conditions[] = Spec::like('name', $searchTerm); } diff --git a/module/Core/src/Tag/Paginator/Adapter/TagsPaginatorAdapter.php b/module/Core/src/Tag/Paginator/Adapter/TagsPaginatorAdapter.php index d6bc0b7b..7d54940e 100644 --- a/module/Core/src/Tag/Paginator/Adapter/TagsPaginatorAdapter.php +++ b/module/Core/src/Tag/Paginator/Adapter/TagsPaginatorAdapter.php @@ -15,13 +15,13 @@ class TagsPaginatorAdapter extends AbstractTagsPaginatorAdapter new WithApiKeySpecsEnsuringJoin($this->apiKey), Spec::orderBy( 'name', // Ordering by other fields makes no sense here - $this->params->orderBy()->orderDirection(), + $this->params->orderBy->direction, ), Spec::limit($length), Spec::offset($offset), ]; - $searchTerm = $this->params->searchTerm(); + $searchTerm = $this->params->searchTerm; if ($searchTerm !== null) { $conditions[] = Spec::like('name', $searchTerm); } diff --git a/module/Core/src/Tag/TagService.php b/module/Core/src/Tag/TagService.php index 40eb413f..b8d7f710 100644 --- a/module/Core/src/Tag/TagService.php +++ b/module/Core/src/Tag/TagService.php @@ -49,8 +49,8 @@ class TagService implements TagServiceInterface private function createPaginator(AdapterInterface $adapter, TagsParams $params): Paginator { return (new Paginator($adapter)) - ->setMaxPerPage($params->getItemsPerPage()) - ->setCurrentPage($params->getPage()); + ->setMaxPerPage($params->itemsPerPage) + ->setCurrentPage($params->page); } /** @@ -83,17 +83,17 @@ class TagService implements TagServiceInterface $repo = $this->em->getRepository(Tag::class); /** @var Tag|null $tag */ - $tag = $repo->findOneBy(['name' => $renaming->oldName()]); + $tag = $repo->findOneBy(['name' => $renaming->oldName]); if ($tag === null) { - throw TagNotFoundException::fromTag($renaming->oldName()); + throw TagNotFoundException::fromTag($renaming->oldName); } - $newNameExists = $renaming->nameChanged() && $repo->count(['name' => $renaming->newName()]) > 0; + $newNameExists = $renaming->nameChanged() && $repo->count(['name' => $renaming->newName]) > 0; if ($newNameExists) { throw TagConflictException::forExistingTag($renaming); } - $tag->rename($renaming->newName()); + $tag->rename($renaming->newName); $this->em->flush(); return $tag; diff --git a/module/Core/src/Visit/Paginator/Adapter/DomainVisitsPaginatorAdapter.php b/module/Core/src/Visit/Paginator/Adapter/DomainVisitsPaginatorAdapter.php index 508a7b36..93250d78 100644 --- a/module/Core/src/Visit/Paginator/Adapter/DomainVisitsPaginatorAdapter.php +++ b/module/Core/src/Visit/Paginator/Adapter/DomainVisitsPaginatorAdapter.php @@ -26,8 +26,8 @@ class DomainVisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdapte return $this->visitRepository->countVisitsByDomain( $this->domain, new VisitsCountFiltering( - $this->params->getDateRange(), - $this->params->excludeBots(), + $this->params->dateRange, + $this->params->excludeBots, $this->apiKey, ), ); @@ -38,8 +38,8 @@ class DomainVisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdapte return $this->visitRepository->findVisitsByDomain( $this->domain, new VisitsListFiltering( - $this->params->getDateRange(), - $this->params->excludeBots(), + $this->params->dateRange, + $this->params->excludeBots, $this->apiKey, $length, $offset, diff --git a/module/Core/src/Visit/Paginator/Adapter/NonOrphanVisitsPaginatorAdapter.php b/module/Core/src/Visit/Paginator/Adapter/NonOrphanVisitsPaginatorAdapter.php index ba5b6663..5f06ea09 100644 --- a/module/Core/src/Visit/Paginator/Adapter/NonOrphanVisitsPaginatorAdapter.php +++ b/module/Core/src/Visit/Paginator/Adapter/NonOrphanVisitsPaginatorAdapter.php @@ -23,8 +23,8 @@ class NonOrphanVisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAda protected function doCount(): int { return $this->repo->countNonOrphanVisits(new VisitsCountFiltering( - $this->params->getDateRange(), - $this->params->excludeBots(), + $this->params->dateRange, + $this->params->excludeBots, $this->apiKey, )); } @@ -32,8 +32,8 @@ class NonOrphanVisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAda public function getSlice(int $offset, int $length): iterable { return $this->repo->findNonOrphanVisits(new VisitsListFiltering( - $this->params->getDateRange(), - $this->params->excludeBots(), + $this->params->dateRange, + $this->params->excludeBots, $this->apiKey, $length, $offset, diff --git a/module/Core/src/Visit/Paginator/Adapter/OrphanVisitsPaginatorAdapter.php b/module/Core/src/Visit/Paginator/Adapter/OrphanVisitsPaginatorAdapter.php index 8a47c9d7..f18dbb05 100644 --- a/module/Core/src/Visit/Paginator/Adapter/OrphanVisitsPaginatorAdapter.php +++ b/module/Core/src/Visit/Paginator/Adapter/OrphanVisitsPaginatorAdapter.php @@ -19,16 +19,16 @@ class OrphanVisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdapte protected function doCount(): int { return $this->repo->countOrphanVisits(new VisitsCountFiltering( - $this->params->getDateRange(), - $this->params->excludeBots(), + $this->params->dateRange, + $this->params->excludeBots, )); } public function getSlice(int $offset, int $length): iterable { return $this->repo->findOrphanVisits(new VisitsListFiltering( - $this->params->getDateRange(), - $this->params->excludeBots(), + $this->params->dateRange, + $this->params->excludeBots, null, $length, $offset, diff --git a/module/Core/src/Visit/Paginator/Adapter/ShortUrlVisitsPaginatorAdapter.php b/module/Core/src/Visit/Paginator/Adapter/ShortUrlVisitsPaginatorAdapter.php index 2e47fbf8..5169c327 100644 --- a/module/Core/src/Visit/Paginator/Adapter/ShortUrlVisitsPaginatorAdapter.php +++ b/module/Core/src/Visit/Paginator/Adapter/ShortUrlVisitsPaginatorAdapter.php @@ -27,8 +27,8 @@ class ShortUrlVisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdap return $this->visitRepository->findVisitsByShortCode( $this->identifier, new VisitsListFiltering( - $this->params->getDateRange(), - $this->params->excludeBots(), + $this->params->dateRange, + $this->params->excludeBots, $this->apiKey, $length, $offset, @@ -41,8 +41,8 @@ class ShortUrlVisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdap return $this->visitRepository->countVisitsByShortCode( $this->identifier, new VisitsCountFiltering( - $this->params->getDateRange(), - $this->params->excludeBots(), + $this->params->dateRange, + $this->params->excludeBots, $this->apiKey, ), ); diff --git a/module/Core/src/Visit/Paginator/Adapter/TagVisitsPaginatorAdapter.php b/module/Core/src/Visit/Paginator/Adapter/TagVisitsPaginatorAdapter.php index 162b6cba..aed79d02 100644 --- a/module/Core/src/Visit/Paginator/Adapter/TagVisitsPaginatorAdapter.php +++ b/module/Core/src/Visit/Paginator/Adapter/TagVisitsPaginatorAdapter.php @@ -26,8 +26,8 @@ class TagVisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdapter return $this->visitRepository->findVisitsByTag( $this->tag, new VisitsListFiltering( - $this->params->getDateRange(), - $this->params->excludeBots(), + $this->params->dateRange, + $this->params->excludeBots, $this->apiKey, $length, $offset, @@ -40,8 +40,8 @@ class TagVisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdapter return $this->visitRepository->countVisitsByTag( $this->tag, new VisitsCountFiltering( - $this->params->getDateRange(), - $this->params->excludeBots(), + $this->params->dateRange, + $this->params->excludeBots, $this->apiKey, ), ); diff --git a/module/Core/src/Visit/Persistence/VisitsCountFiltering.php b/module/Core/src/Visit/Persistence/VisitsCountFiltering.php index 140ec9b9..f839a945 100644 --- a/module/Core/src/Visit/Persistence/VisitsCountFiltering.php +++ b/module/Core/src/Visit/Persistence/VisitsCountFiltering.php @@ -10,9 +10,9 @@ use Shlinkio\Shlink\Rest\Entity\ApiKey; class VisitsCountFiltering { public function __construct( - private ?DateRange $dateRange = null, - private bool $excludeBots = false, - private ?ApiKey $apiKey = null, + public readonly ?DateRange $dateRange = null, + public readonly bool $excludeBots = false, + public readonly ?ApiKey $apiKey = null, ) { } @@ -20,19 +20,4 @@ class VisitsCountFiltering { return new self(null, false, $apiKey); } - - public function dateRange(): ?DateRange - { - return $this->dateRange; - } - - public function excludeBots(): bool - { - return $this->excludeBots; - } - - public function apiKey(): ?ApiKey - { - return $this->apiKey; - } } diff --git a/module/Core/src/Visit/Persistence/VisitsListFiltering.php b/module/Core/src/Visit/Persistence/VisitsListFiltering.php index b17964a6..747a3ce0 100644 --- a/module/Core/src/Visit/Persistence/VisitsListFiltering.php +++ b/module/Core/src/Visit/Persistence/VisitsListFiltering.php @@ -13,19 +13,9 @@ final class VisitsListFiltering extends VisitsCountFiltering ?DateRange $dateRange = null, bool $excludeBots = false, ?ApiKey $apiKey = null, - private ?int $limit = null, - private ?int $offset = null, + public readonly ?int $limit = null, + public readonly ?int $offset = null, ) { parent::__construct($dateRange, $excludeBots, $apiKey); } - - public function limit(): ?int - { - return $this->limit; - } - - public function offset(): ?int - { - return $this->offset; - } } diff --git a/module/Core/src/Visit/Spec/CountOfNonOrphanVisits.php b/module/Core/src/Visit/Spec/CountOfNonOrphanVisits.php index 52be52a8..a7b2a1d6 100644 --- a/module/Core/src/Visit/Spec/CountOfNonOrphanVisits.php +++ b/module/Core/src/Visit/Spec/CountOfNonOrphanVisits.php @@ -22,14 +22,14 @@ class CountOfNonOrphanVisits extends BaseSpecification { $conditions = [ Spec::isNotNull('shortUrl'), - new InDateRange($this->filtering->dateRange()), + new InDateRange($this->filtering->dateRange), ]; - if ($this->filtering->excludeBots()) { + if ($this->filtering->excludeBots) { $conditions[] = Spec::eq('potentialBot', false); } - $apiKey = $this->filtering->apiKey(); + $apiKey = $this->filtering->apiKey; if ($apiKey !== null) { $conditions[] = new WithApiKeySpecsEnsuringJoin($apiKey, 'shortUrl'); } diff --git a/module/Core/src/Visit/Spec/CountOfOrphanVisits.php b/module/Core/src/Visit/Spec/CountOfOrphanVisits.php index d8e6b2d2..106350c6 100644 --- a/module/Core/src/Visit/Spec/CountOfOrphanVisits.php +++ b/module/Core/src/Visit/Spec/CountOfOrphanVisits.php @@ -21,10 +21,10 @@ class CountOfOrphanVisits extends BaseSpecification { $conditions = [ Spec::isNull('shortUrl'), - new InDateRange($this->filtering->dateRange()), + new InDateRange($this->filtering->dateRange), ]; - if ($this->filtering->excludeBots()) { + if ($this->filtering->excludeBots) { $conditions[] = Spec::eq('potentialBot', false); } diff --git a/module/Core/src/Visit/VisitsStatsHelper.php b/module/Core/src/Visit/VisitsStatsHelper.php index 007ed334..4f19103f 100644 --- a/module/Core/src/Visit/VisitsStatsHelper.php +++ b/module/Core/src/Visit/VisitsStatsHelper.php @@ -129,8 +129,8 @@ class VisitsStatsHelper implements VisitsStatsHelperInterface private function createPaginator(AdapterInterface $adapter, VisitsParams $params): Paginator { $paginator = new Paginator($adapter); - $paginator->setMaxPerPage($params->getItemsPerPage()) - ->setCurrentPage($params->getPage()); + $paginator->setMaxPerPage($params->itemsPerPage) + ->setCurrentPage($params->page); return $paginator; } diff --git a/module/Core/src/Visit/VisitsTracker.php b/module/Core/src/Visit/VisitsTracker.php index f4e5bf92..3aef46df 100644 --- a/module/Core/src/Visit/VisitsTracker.php +++ b/module/Core/src/Visit/VisitsTracker.php @@ -72,6 +72,6 @@ class VisitsTracker implements VisitsTrackerInterface $this->em->persist($visit); $this->em->flush(); - $this->eventDispatcher->dispatch(new UrlVisited($visit->getId(), $visitor->getRemoteAddress())); + $this->eventDispatcher->dispatch(new UrlVisited($visit->getId(), $visitor->remoteAddress)); } } diff --git a/module/Core/test-db/Repository/TagRepositoryTest.php b/module/Core/test-db/Repository/TagRepositoryTest.php index fe544376..87cd7280 100644 --- a/module/Core/test-db/Repository/TagRepositoryTest.php +++ b/module/Core/test-db/Repository/TagRepositoryTest.php @@ -64,7 +64,7 @@ class TagRepositoryTest extends DatabaseTestCase $this->getEntityManager()->persist(new Tag($name)); } - $apiKey = $filtering?->apiKey(); + $apiKey = $filtering?->apiKey; if ($apiKey !== null) { $this->getEntityManager()->persist($apiKey); } @@ -101,9 +101,9 @@ class TagRepositoryTest extends DatabaseTestCase self::assertCount(count($expectedList), $result); foreach ($expectedList as $index => [$tag, $shortUrlsCount, $visitsCount]) { - self::assertEquals($shortUrlsCount, $result[$index]->shortUrlsCount()); - self::assertEquals($visitsCount, $result[$index]->visitsCount()); - self::assertEquals($tag, $result[$index]->tag()); + self::assertEquals($shortUrlsCount, $result[$index]->shortUrlsCount); + self::assertEquals($visitsCount, $result[$index]->visitsCount); + self::assertEquals($tag, $result[$index]->tag); } } diff --git a/module/Core/test/Action/PixelActionTest.php b/module/Core/test/Action/PixelActionTest.php index 3eb1ad79..fdd291a5 100644 --- a/module/Core/test/Action/PixelActionTest.php +++ b/module/Core/test/Action/PixelActionTest.php @@ -37,9 +37,10 @@ class PixelActionTest extends TestCase public function imageIsReturned(): void { $shortCode = 'abc123'; - $this->urlResolver->resolveEnabledShortUrl(new ShortUrlIdentifier($shortCode, ''))->willReturn( - ShortUrl::withLongUrl('http://domain.com/foo/bar'), - )->shouldBeCalledOnce(); + $this->urlResolver->resolveEnabledShortUrl( + ShortUrlIdentifier::fromShortCodeAndDomain($shortCode, ''), + )->willReturn(ShortUrl::withLongUrl('http://domain.com/foo/bar')) + ->shouldBeCalledOnce(); $this->requestTracker->trackIfApplicable(Argument::cetera())->shouldBeCalledOnce(); $request = (new ServerRequest())->withAttribute('shortCode', $shortCode); diff --git a/module/Core/test/Action/QrCodeActionTest.php b/module/Core/test/Action/QrCodeActionTest.php index 419febec..fb9e4e6a 100644 --- a/module/Core/test/Action/QrCodeActionTest.php +++ b/module/Core/test/Action/QrCodeActionTest.php @@ -59,7 +59,7 @@ class QrCodeActionTest extends TestCase public function aNotFoundShortCodeWillDelegateIntoNextMiddleware(): void { $shortCode = 'abc123'; - $this->urlResolver->resolveEnabledShortUrl(new ShortUrlIdentifier($shortCode, '')) + $this->urlResolver->resolveEnabledShortUrl(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode, '')) ->willThrow(ShortUrlNotFoundException::class) ->shouldBeCalledOnce(); $delegate = $this->prophesize(RequestHandlerInterface::class); @@ -74,7 +74,7 @@ class QrCodeActionTest extends TestCase public function aCorrectRequestReturnsTheQrCodeResponse(): void { $shortCode = 'abc123'; - $this->urlResolver->resolveEnabledShortUrl(new ShortUrlIdentifier($shortCode, '')) + $this->urlResolver->resolveEnabledShortUrl(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode, '')) ->willReturn(ShortUrl::createEmpty()) ->shouldBeCalledOnce(); $delegate = $this->prophesize(RequestHandlerInterface::class); @@ -100,7 +100,7 @@ class QrCodeActionTest extends TestCase ): void { $this->options->setFromArray(['format' => $defaultFormat]); $code = 'abc123'; - $this->urlResolver->resolveEnabledShortUrl(new ShortUrlIdentifier($code, ''))->willReturn( + $this->urlResolver->resolveEnabledShortUrl(ShortUrlIdentifier::fromShortCodeAndDomain($code, ''))->willReturn( ShortUrl::createEmpty(), ); $delegate = $this->prophesize(RequestHandlerInterface::class); @@ -134,7 +134,7 @@ class QrCodeActionTest extends TestCase ): void { $this->options->setFromArray($defaults); $code = 'abc123'; - $this->urlResolver->resolveEnabledShortUrl(new ShortUrlIdentifier($code, ''))->willReturn( + $this->urlResolver->resolveEnabledShortUrl(ShortUrlIdentifier::fromShortCodeAndDomain($code, ''))->willReturn( ShortUrl::createEmpty(), ); $delegate = $this->prophesize(RequestHandlerInterface::class); @@ -214,7 +214,7 @@ class QrCodeActionTest extends TestCase ->withQueryParams(['size' => 250, 'roundBlockSize' => $roundBlockSize]) ->withAttribute('shortCode', $code); - $this->urlResolver->resolveEnabledShortUrl(new ShortUrlIdentifier($code, ''))->willReturn( + $this->urlResolver->resolveEnabledShortUrl(ShortUrlIdentifier::fromShortCodeAndDomain($code, ''))->willReturn( ShortUrl::withLongUrl('https://shlink.io'), ); $delegate = $this->prophesize(RequestHandlerInterface::class); diff --git a/module/Core/test/Action/RedirectActionTest.php b/module/Core/test/Action/RedirectActionTest.php index b3017fad..cde2b9aa 100644 --- a/module/Core/test/Action/RedirectActionTest.php +++ b/module/Core/test/Action/RedirectActionTest.php @@ -54,7 +54,7 @@ class RedirectActionTest extends TestCase $shortCode = 'abc123'; $shortUrl = ShortUrl::withLongUrl(self::LONG_URL); $shortCodeToUrl = $this->urlResolver->resolveEnabledShortUrl( - new ShortUrlIdentifier($shortCode, ''), + ShortUrlIdentifier::fromShortCodeAndDomain($shortCode, ''), )->willReturn($shortUrl); $track = $this->requestTracker->trackIfApplicable(Argument::cetera())->will(function (): void { }); @@ -74,7 +74,7 @@ class RedirectActionTest extends TestCase public function nextMiddlewareIsInvokedIfLongUrlIsNotFound(): void { $shortCode = 'abc123'; - $this->urlResolver->resolveEnabledShortUrl(new ShortUrlIdentifier($shortCode, '')) + $this->urlResolver->resolveEnabledShortUrl(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode, '')) ->willThrow(ShortUrlNotFoundException::class) ->shouldBeCalledOnce(); $this->requestTracker->trackIfApplicable(Argument::cetera())->shouldNotBeCalled(); diff --git a/module/Core/test/Exception/ShortUrlNotFoundExceptionTest.php b/module/Core/test/Exception/ShortUrlNotFoundExceptionTest.php index ea4e606d..e86a63cb 100644 --- a/module/Core/test/Exception/ShortUrlNotFoundExceptionTest.php +++ b/module/Core/test/Exception/ShortUrlNotFoundExceptionTest.php @@ -24,7 +24,7 @@ class ShortUrlNotFoundExceptionTest extends TestCase $expectedAdditional['domain'] = $domain; } - $e = ShortUrlNotFoundException::fromNotFound(new ShortUrlIdentifier($shortCode, $domain)); + $e = ShortUrlNotFoundException::fromNotFound(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode, $domain)); self::assertEquals($expectedMessage, $e->getMessage()); self::assertEquals($expectedMessage, $e->getDetail()); diff --git a/module/Core/test/Model/VisitorTest.php b/module/Core/test/Model/VisitorTest.php index 50c277c4..92a46a16 100644 --- a/module/Core/test/Model/VisitorTest.php +++ b/module/Core/test/Model/VisitorTest.php @@ -24,9 +24,9 @@ class VisitorTest extends TestCase $visitor = new Visitor(...$params); ['userAgent' => $userAgent, 'referer' => $referer, 'remoteAddress' => $remoteAddress] = $expected; - self::assertEquals($userAgent, $visitor->getUserAgent()); - self::assertEquals($referer, $visitor->getReferer()); - self::assertEquals($remoteAddress, $visitor->getRemoteAddress()); + self::assertEquals($userAgent, $visitor->userAgent); + self::assertEquals($referer, $visitor->referer); + self::assertEquals($remoteAddress, $visitor->remoteAddress); } public function provideParams(): iterable @@ -89,11 +89,11 @@ class VisitorTest extends TestCase ])); self::assertNotSame($visitor, $normalizedVisitor); - self::assertEmpty($normalizedVisitor->getUserAgent()); - self::assertNotEmpty($visitor->getUserAgent()); - self::assertEmpty($normalizedVisitor->getReferer()); - self::assertNotEmpty($visitor->getReferer()); - self::assertNull($normalizedVisitor->getRemoteAddress()); - self::assertNotNull($visitor->getRemoteAddress()); + self::assertEmpty($normalizedVisitor->userAgent); + self::assertNotEmpty($visitor->userAgent); + self::assertEmpty($normalizedVisitor->referer); + self::assertNotEmpty($visitor->referer); + self::assertNull($normalizedVisitor->remoteAddress); + self::assertNotNull($visitor->remoteAddress); } } diff --git a/module/Core/test/Service/ShortUrl/DeleteShortUrlServiceTest.php b/module/Core/test/Service/ShortUrl/DeleteShortUrlServiceTest.php index 6c03d7b5..cd4d6193 100644 --- a/module/Core/test/Service/ShortUrl/DeleteShortUrlServiceTest.php +++ b/module/Core/test/Service/ShortUrl/DeleteShortUrlServiceTest.php @@ -55,7 +55,7 @@ class DeleteShortUrlServiceTest extends TestCase $this->shortCode, )); - $service->deleteByShortCode(new ShortUrlIdentifier($this->shortCode)); + $service->deleteByShortCode(ShortUrlIdentifier::fromShortCodeAndDomain($this->shortCode)); } /** @test */ @@ -66,7 +66,7 @@ class DeleteShortUrlServiceTest extends TestCase $remove = $this->em->remove(Argument::type(ShortUrl::class))->willReturn(null); $flush = $this->em->flush()->willReturn(null); - $service->deleteByShortCode(new ShortUrlIdentifier($this->shortCode), true); + $service->deleteByShortCode(ShortUrlIdentifier::fromShortCodeAndDomain($this->shortCode), true); $remove->shouldHaveBeenCalledOnce(); $flush->shouldHaveBeenCalledOnce(); @@ -80,7 +80,7 @@ class DeleteShortUrlServiceTest extends TestCase $remove = $this->em->remove(Argument::type(ShortUrl::class))->willReturn(null); $flush = $this->em->flush()->willReturn(null); - $service->deleteByShortCode(new ShortUrlIdentifier($this->shortCode)); + $service->deleteByShortCode(ShortUrlIdentifier::fromShortCodeAndDomain($this->shortCode)); $remove->shouldHaveBeenCalledOnce(); $flush->shouldHaveBeenCalledOnce(); @@ -94,7 +94,7 @@ class DeleteShortUrlServiceTest extends TestCase $remove = $this->em->remove(Argument::type(ShortUrl::class))->willReturn(null); $flush = $this->em->flush()->willReturn(null); - $service->deleteByShortCode(new ShortUrlIdentifier($this->shortCode)); + $service->deleteByShortCode(ShortUrlIdentifier::fromShortCodeAndDomain($this->shortCode)); $remove->shouldHaveBeenCalledOnce(); $flush->shouldHaveBeenCalledOnce(); diff --git a/module/Core/test/Service/ShortUrl/ShortUrlResolverTest.php b/module/Core/test/Service/ShortUrl/ShortUrlResolverTest.php index 70857e5e..bdccfa3f 100644 --- a/module/Core/test/Service/ShortUrl/ShortUrlResolverTest.php +++ b/module/Core/test/Service/ShortUrl/ShortUrlResolverTest.php @@ -91,7 +91,7 @@ class ShortUrlResolverTest extends TestCase )->willReturn($shortUrl); $getRepo = $this->em->getRepository(ShortUrl::class)->willReturn($repo->reveal()); - $result = $this->urlResolver->resolveEnabledShortUrl(new ShortUrlIdentifier($shortCode)); + $result = $this->urlResolver->resolveEnabledShortUrl(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode)); self::assertSame($shortUrl, $result); $findOneByShortCode->shouldHaveBeenCalledOnce(); @@ -116,7 +116,7 @@ class ShortUrlResolverTest extends TestCase $findOneByShortCode->shouldBeCalledOnce(); $getRepo->shouldBeCalledOnce(); - $this->urlResolver->resolveEnabledShortUrl(new ShortUrlIdentifier($shortCode)); + $this->urlResolver->resolveEnabledShortUrl(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode)); } public function provideDisabledShortUrls(): iterable diff --git a/module/Core/test/Service/ShortUrlServiceTest.php b/module/Core/test/Service/ShortUrlServiceTest.php index b07d4df9..90000423 100644 --- a/module/Core/test/Service/ShortUrlServiceTest.php +++ b/module/Core/test/Service/ShortUrlServiceTest.php @@ -88,7 +88,7 @@ class ShortUrlServiceTest extends TestCase $shortUrl = ShortUrl::withLongUrl($originalLongUrl); $findShortUrl = $this->urlResolver->resolveShortUrl( - new ShortUrlIdentifier('abc123'), + ShortUrlIdentifier::fromShortCodeAndDomain('abc123'), $apiKey, )->willReturn($shortUrl); $flush = $this->em->flush()->willReturn(null); @@ -97,7 +97,11 @@ class ShortUrlServiceTest extends TestCase $shortUrlEdit, ); - $result = $this->service->updateShortUrl(new ShortUrlIdentifier('abc123'), $shortUrlEdit, $apiKey); + $result = $this->service->updateShortUrl( + ShortUrlIdentifier::fromShortCodeAndDomain('abc123'), + $shortUrlEdit, + $apiKey, + ); self::assertSame($shortUrl, $result); self::assertEquals($shortUrlEdit->validSince(), $shortUrl->getValidSince()); diff --git a/module/Core/test/Visit/Paginator/Adapter/NonOrphanVisitsPaginatorAdapterTest.php b/module/Core/test/Visit/Paginator/Adapter/NonOrphanVisitsPaginatorAdapterTest.php index 4c4c00e5..ba1d2767 100644 --- a/module/Core/test/Visit/Paginator/Adapter/NonOrphanVisitsPaginatorAdapterTest.php +++ b/module/Core/test/Visit/Paginator/Adapter/NonOrphanVisitsPaginatorAdapterTest.php @@ -39,7 +39,7 @@ class NonOrphanVisitsPaginatorAdapterTest extends TestCase { $expectedCount = 5; $repoCount = $this->repo->countNonOrphanVisits( - new VisitsCountFiltering($this->params->getDateRange(), $this->params->excludeBots(), $this->apiKey), + new VisitsCountFiltering($this->params->dateRange, $this->params->excludeBots, $this->apiKey), )->willReturn($expectedCount); $result = $this->adapter->getNbResults(); @@ -57,8 +57,8 @@ class NonOrphanVisitsPaginatorAdapterTest extends TestCase $visitor = Visitor::emptyInstance(); $list = [Visit::forRegularNotFound($visitor), Visit::forInvalidShortUrl($visitor)]; $repoFind = $this->repo->findNonOrphanVisits(new VisitsListFiltering( - $this->params->getDateRange(), - $this->params->excludeBots(), + $this->params->dateRange, + $this->params->excludeBots, $this->apiKey, $limit, $offset, diff --git a/module/Core/test/Visit/Paginator/Adapter/OrphanVisitsPaginatorAdapterTest.php b/module/Core/test/Visit/Paginator/Adapter/OrphanVisitsPaginatorAdapterTest.php index 0ea91f29..6709c538 100644 --- a/module/Core/test/Visit/Paginator/Adapter/OrphanVisitsPaginatorAdapterTest.php +++ b/module/Core/test/Visit/Paginator/Adapter/OrphanVisitsPaginatorAdapterTest.php @@ -35,7 +35,7 @@ class OrphanVisitsPaginatorAdapterTest extends TestCase { $expectedCount = 5; $repoCount = $this->repo->countOrphanVisits( - new VisitsCountFiltering($this->params->getDateRange()), + new VisitsCountFiltering($this->params->dateRange), )->willReturn($expectedCount); $result = $this->adapter->getNbResults(); @@ -53,7 +53,7 @@ class OrphanVisitsPaginatorAdapterTest extends TestCase $visitor = Visitor::emptyInstance(); $list = [Visit::forRegularNotFound($visitor), Visit::forInvalidShortUrl($visitor)]; $repoFind = $this->repo->findOrphanVisits( - new VisitsListFiltering($this->params->getDateRange(), $this->params->excludeBots(), null, $limit, $offset), + new VisitsListFiltering($this->params->dateRange, $this->params->excludeBots, null, $limit, $offset), )->willReturn($list); $result = $this->adapter->getSlice($offset, $limit); diff --git a/module/Core/test/Visit/Paginator/Adapter/ShortUrlVisitsPaginatorAdapterTest.php b/module/Core/test/Visit/Paginator/Adapter/ShortUrlVisitsPaginatorAdapterTest.php index 04e17bc6..ae9a2a64 100644 --- a/module/Core/test/Visit/Paginator/Adapter/ShortUrlVisitsPaginatorAdapterTest.php +++ b/module/Core/test/Visit/Paginator/Adapter/ShortUrlVisitsPaginatorAdapterTest.php @@ -68,7 +68,7 @@ class ShortUrlVisitsPaginatorAdapterTest extends TestCase { return new ShortUrlVisitsPaginatorAdapter( $this->repo->reveal(), - new ShortUrlIdentifier(''), + ShortUrlIdentifier::fromShortCodeAndDomain(''), VisitsParams::fromRawData([]), $apiKey, ); diff --git a/module/Rest/src/Action/Tag/ListTagsAction.php b/module/Rest/src/Action/Tag/ListTagsAction.php index ab81400c..d52436d2 100644 --- a/module/Rest/src/Action/Tag/ListTagsAction.php +++ b/module/Rest/src/Action/Tag/ListTagsAction.php @@ -32,7 +32,7 @@ class ListTagsAction extends AbstractRestAction $params = TagsParams::fromRawData($request->getQueryParams()); $apiKey = AuthenticationMiddleware::apiKeyFromRequest($request); - if (! $params->withStats()) { + if (! $params->withStats) { return new JsonResponse([ 'tags' => $this->serializePaginator($this->tagService->listTags($params, $apiKey)), ]); @@ -41,7 +41,7 @@ class ListTagsAction extends AbstractRestAction // This part is deprecated. To get tags with stats, the /tags/stats endpoint should be used instead $tagsInfo = $this->tagService->tagsInfo($params, $apiKey); $rawTags = $this->serializePaginator($tagsInfo, null, 'stats'); - $rawTags['data'] = map($tagsInfo, static fn (TagInfo $info) => $info->tag()); + $rawTags['data'] = map($tagsInfo, static fn (TagInfo $info) => $info->tag); return new JsonResponse(['tags' => $rawTags]); } diff --git a/module/Rest/src/ApiKey/Model/ApiKeyMeta.php b/module/Rest/src/ApiKey/Model/ApiKeyMeta.php index 39b5dca1..430221a2 100644 --- a/module/Rest/src/ApiKey/Model/ApiKeyMeta.php +++ b/module/Rest/src/ApiKey/Model/ApiKeyMeta.php @@ -8,11 +8,13 @@ use Cake\Chronos\Chronos; final class ApiKeyMeta { + /** + * @param RoleDefinition[] $roleDefinitions + */ private function __construct( - private ?string $name, - private ?Chronos $expirationDate, - /** @var RoleDefinition[] */ - private array $roleDefinitions, + public readonly ?string $name, + public readonly ?Chronos $expirationDate, + public readonly array $roleDefinitions, ) { } @@ -35,22 +37,4 @@ final class ApiKeyMeta { return new self(null, null, $roleDefinitions); } - - public function name(): ?string - { - return $this->name; - } - - public function expirationDate(): ?Chronos - { - return $this->expirationDate; - } - - /** - * @return RoleDefinition[] - */ - public function roleDefinitions(): array - { - return $this->roleDefinitions; - } } diff --git a/module/Rest/src/ApiKey/Model/RoleDefinition.php b/module/Rest/src/ApiKey/Model/RoleDefinition.php index fdd4d5cb..20061cbc 100644 --- a/module/Rest/src/ApiKey/Model/RoleDefinition.php +++ b/module/Rest/src/ApiKey/Model/RoleDefinition.php @@ -9,7 +9,7 @@ use Shlinkio\Shlink\Rest\ApiKey\Role; final class RoleDefinition { - private function __construct(private string $roleName, private array $meta) + private function __construct(public readonly string $roleName, public readonly array $meta) { } @@ -25,14 +25,4 @@ final class RoleDefinition ['domain_id' => $domain->getId(), 'authority' => $domain->getAuthority()], ); } - - public function roleName(): string - { - return $this->roleName; - } - - public function meta(): array - { - return $this->meta; - } } diff --git a/module/Rest/src/Entity/ApiKey.php b/module/Rest/src/Entity/ApiKey.php index 2940bc69..cd0aa4ff 100644 --- a/module/Rest/src/Entity/ApiKey.php +++ b/module/Rest/src/Entity/ApiKey.php @@ -44,8 +44,8 @@ class ApiKey extends AbstractEntity public static function fromMeta(ApiKeyMeta $meta): self { - $apiKey = new self($meta->name(), $meta->expirationDate()); - foreach ($meta->roleDefinitions() as $roleDefinition) { + $apiKey = new self($meta->name, $meta->expirationDate); + foreach ($meta->roleDefinitions as $roleDefinition) { $apiKey->registerRole($roleDefinition); } @@ -137,21 +137,16 @@ class ApiKey extends AbstractEntity public function registerRole(RoleDefinition $roleDefinition): void { - $roleName = $roleDefinition->roleName(); - $meta = $roleDefinition->meta(); + $roleName = $roleDefinition->roleName; + $meta = $roleDefinition->meta; if ($this->hasRole($roleName)) { /** @var ApiKeyRole $role */ $role = $this->roles->get($roleName); $role->updateMeta($meta); } else { - $role = new ApiKeyRole($roleDefinition->roleName(), $roleDefinition->meta(), $this); + $role = new ApiKeyRole($roleDefinition->roleName, $roleDefinition->meta, $this); $this->roles[$roleName] = $role; } } - - public function removeRole(string $roleName): void - { - $this->roles->remove($roleName); - } } diff --git a/module/Rest/src/Middleware/AuthenticationMiddleware.php b/module/Rest/src/Middleware/AuthenticationMiddleware.php index 25f1fbe5..7b911817 100644 --- a/module/Rest/src/Middleware/AuthenticationMiddleware.php +++ b/module/Rest/src/Middleware/AuthenticationMiddleware.php @@ -49,7 +49,7 @@ class AuthenticationMiddleware implements MiddlewareInterface, StatusCodeInterfa throw VerifyAuthenticationException::forInvalidApiKey(); } - return $handler->handle($request->withAttribute(ApiKey::class, $result->apiKey())); + return $handler->handle($request->withAttribute(ApiKey::class, $result->apiKey)); } public static function apiKeyFromRequest(Request $request): ApiKey diff --git a/module/Rest/src/Service/ApiKeyCheckResult.php b/module/Rest/src/Service/ApiKeyCheckResult.php index 2caee4e1..ff74fb79 100644 --- a/module/Rest/src/Service/ApiKeyCheckResult.php +++ b/module/Rest/src/Service/ApiKeyCheckResult.php @@ -8,7 +8,7 @@ use Shlinkio\Shlink\Rest\Entity\ApiKey; final class ApiKeyCheckResult { - public function __construct(private ?ApiKey $apiKey = null) + public function __construct(public readonly ?ApiKey $apiKey = null) { } @@ -16,9 +16,4 @@ final class ApiKeyCheckResult { return $this->apiKey !== null && $this->apiKey->isValid(); } - - public function apiKey(): ?ApiKey - { - return $this->apiKey; - } } diff --git a/module/Rest/test/Action/Domain/Request/DomainRedirectsRequestTest.php b/module/Rest/test/Action/Domain/Request/DomainRedirectsRequestTest.php index 55828368..05212fe7 100644 --- a/module/Rest/test/Action/Domain/Request/DomainRedirectsRequestTest.php +++ b/module/Rest/test/Action/Domain/Request/DomainRedirectsRequestTest.php @@ -44,9 +44,9 @@ class DomainRedirectsRequestTest extends TestCase $notFound = $request->toNotFoundRedirects($defaults); self::assertEquals($expectedAuthority, $request->authority()); - self::assertEquals($expectedBaseUrlRedirect, $notFound->baseUrlRedirect()); - self::assertEquals($expectedRegular404Redirect, $notFound->regular404Redirect()); - self::assertEquals($expectedInvalidShortUrlRedirect, $notFound->invalidShortUrlRedirect()); + self::assertEquals($expectedBaseUrlRedirect, $notFound->baseUrlRedirect); + self::assertEquals($expectedRegular404Redirect, $notFound->regular404Redirect); + self::assertEquals($expectedInvalidShortUrlRedirect, $notFound->invalidShortUrlRedirect); } public function provideValidData(): iterable diff --git a/module/Rest/test/Action/ShortUrl/ResolveShortUrlActionTest.php b/module/Rest/test/Action/ShortUrl/ResolveShortUrlActionTest.php index 04ffb107..19422d9d 100644 --- a/module/Rest/test/Action/ShortUrl/ResolveShortUrlActionTest.php +++ b/module/Rest/test/Action/ShortUrl/ResolveShortUrlActionTest.php @@ -36,9 +36,11 @@ class ResolveShortUrlActionTest extends TestCase { $shortCode = 'abc123'; $apiKey = ApiKey::create(); - $this->urlResolver->resolveShortUrl(new ShortUrlIdentifier($shortCode), $apiKey)->willReturn( - ShortUrl::withLongUrl('http://domain.com/foo/bar'), - )->shouldBeCalledOnce(); + $this->urlResolver->resolveShortUrl( + ShortUrlIdentifier::fromShortCodeAndDomain($shortCode), + $apiKey, + )->willReturn(ShortUrl::withLongUrl('http://domain.com/foo/bar')) + ->shouldBeCalledOnce(); $request = (new ServerRequest())->withAttribute('shortCode', $shortCode)->withAttribute(ApiKey::class, $apiKey); $response = $this->action->handle($request); diff --git a/module/Rest/test/Action/Visit/ShortUrlVisitsActionTest.php b/module/Rest/test/Action/Visit/ShortUrlVisitsActionTest.php index 6e982aec..50cabe8e 100644 --- a/module/Rest/test/Action/Visit/ShortUrlVisitsActionTest.php +++ b/module/Rest/test/Action/Visit/ShortUrlVisitsActionTest.php @@ -38,7 +38,7 @@ class ShortUrlVisitsActionTest extends TestCase { $shortCode = 'abc123'; $this->visitsHelper->visitsForShortUrl( - new ShortUrlIdentifier($shortCode), + ShortUrlIdentifier::fromShortCodeAndDomain($shortCode), Argument::type(VisitsParams::class), Argument::type(ApiKey::class), )->willReturn(new Paginator(new ArrayAdapter([]))) @@ -52,7 +52,7 @@ class ShortUrlVisitsActionTest extends TestCase public function paramsAreReadFromQuery(): void { $shortCode = 'abc123'; - $this->visitsHelper->visitsForShortUrl(new ShortUrlIdentifier($shortCode), new VisitsParams( + $this->visitsHelper->visitsForShortUrl(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode), new VisitsParams( DateRange::withEndDate(Chronos::parse('2016-01-01 00:00:00')), 3, 10, diff --git a/module/Rest/test/ApiKey/Model/RoleDefinitionTest.php b/module/Rest/test/ApiKey/Model/RoleDefinitionTest.php index 8e6a58ad..de0763a4 100644 --- a/module/Rest/test/ApiKey/Model/RoleDefinitionTest.php +++ b/module/Rest/test/ApiKey/Model/RoleDefinitionTest.php @@ -16,8 +16,8 @@ class RoleDefinitionTest extends TestCase { $definition = RoleDefinition::forAuthoredShortUrls(); - self::assertEquals(Role::AUTHORED_SHORT_URLS, $definition->roleName()); - self::assertEquals([], $definition->meta()); + self::assertEquals(Role::AUTHORED_SHORT_URLS, $definition->roleName); + self::assertEquals([], $definition->meta); } /** @test */ @@ -26,7 +26,7 @@ class RoleDefinitionTest extends TestCase $domain = Domain::withAuthority('foo.com')->setId('123'); $definition = RoleDefinition::forDomain($domain); - self::assertEquals(Role::DOMAIN_SPECIFIC, $definition->roleName()); - self::assertEquals(['domain_id' => '123', 'authority' => 'foo.com'], $definition->meta()); + self::assertEquals(Role::DOMAIN_SPECIFIC, $definition->roleName); + self::assertEquals(['domain_id' => '123', 'authority' => 'foo.com'], $definition->meta); } } diff --git a/module/Rest/test/Service/ApiKeyServiceTest.php b/module/Rest/test/Service/ApiKeyServiceTest.php index de17d8bd..97c0772b 100644 --- a/module/Rest/test/Service/ApiKeyServiceTest.php +++ b/module/Rest/test/Service/ApiKeyServiceTest.php @@ -46,7 +46,7 @@ class ApiKeyServiceTest extends TestCase self::assertEquals($date, $key->getExpirationDate()); self::assertEquals($name, $key->name()); foreach ($roles as $roleDefinition) { - self::assertTrue($key->hasRole($roleDefinition->roleName())); + self::assertTrue($key->hasRole($roleDefinition->roleName)); } } @@ -77,7 +77,7 @@ class ApiKeyServiceTest extends TestCase $result = $this->service->check('12345'); self::assertFalse($result->isValid()); - self::assertSame($invalidKey, $result->apiKey()); + self::assertSame($invalidKey, $result->apiKey); } public function provideInvalidApiKeys(): iterable @@ -100,7 +100,7 @@ class ApiKeyServiceTest extends TestCase $result = $this->service->check('12345'); self::assertTrue($result->isValid()); - self::assertSame($apiKey, $result->apiKey()); + self::assertSame($apiKey, $result->apiKey); } /** @test */