From b52ceaff9a95e9a33dd2aca776581875441ff82c Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Mon, 29 Jul 2024 19:39:31 +0200 Subject: [PATCH 1/3] Update to latest shlink-common and remove deprecation references --- composer.json | 2 +- docker-compose.yml | 2 +- .../src/Command/ShortUrl/ListShortUrlsCommand.php | 10 ++++------ .../EventDispatcher/PublishingUpdatesGenerator.php | 4 ++-- .../Transformer/ShortUrlDataTransformer.php | 11 ++--------- .../ShortUrlDataTransformerInterface.php | 13 +++++++++++++ .../ShortUrl/AbstractCreateShortUrlAction.php | 4 ++-- .../src/Action/ShortUrl/EditShortUrlAction.php | 4 ++-- .../src/Action/ShortUrl/ListShortUrlsAction.php | 12 ++++++------ .../src/Action/ShortUrl/ResolveShortUrlAction.php | 4 ++-- module/Rest/src/Action/Tag/ListTagsAction.php | 8 +++----- module/Rest/src/Action/Tag/TagsStatsAction.php | 6 ++---- .../src/Action/Visit/DeleteOrphanVisitsAction.php | 3 --- .../Rest/src/Action/Visit/DomainVisitsAction.php | 14 ++++++-------- .../src/Action/Visit/NonOrphanVisitsAction.php | 10 +++------- .../Rest/src/Action/Visit/OrphanVisitsAction.php | 8 ++------ .../Rest/src/Action/Visit/ShortUrlVisitsAction.php | 10 +++------- module/Rest/src/Action/Visit/TagVisitsAction.php | 10 +++------- .../Action/ShortUrl/CreateShortUrlActionTest.php | 6 +++--- .../SingleStepCreateShortUrlActionTest.php | 4 ++-- 20 files changed, 62 insertions(+), 83 deletions(-) create mode 100644 module/Core/src/ShortUrl/Transformer/ShortUrlDataTransformerInterface.php diff --git a/composer.json b/composer.json index f792a468..f695b063 100644 --- a/composer.json +++ b/composer.json @@ -44,7 +44,7 @@ "pagerfanta/core": "^3.8", "ramsey/uuid": "^4.7", "shlinkio/doctrine-specification": "^2.1.1", - "shlinkio/shlink-common": "^6.1", + "shlinkio/shlink-common": "dev-main#144e5c1 as 6.2", "shlinkio/shlink-config": "^3.0", "shlinkio/shlink-event-dispatcher": "^4.1", "shlinkio/shlink-importer": "^5.3.2", diff --git a/docker-compose.yml b/docker-compose.yml index d1673b51..41f54cba 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -77,7 +77,7 @@ services: shlink_db_postgres: container_name: shlink_db_postgres - image: postgres:12.2-alpine + image: postgres:16.3-alpine ports: - "5434:5432" volumes: diff --git a/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php b/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php index 4e3a7706..1aa95631 100644 --- a/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php +++ b/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php @@ -9,14 +9,14 @@ use Shlinkio\Shlink\CLI\Input\StartDateOption; use Shlinkio\Shlink\CLI\Util\ExitCode; use Shlinkio\Shlink\CLI\Util\ShlinkTable; use Shlinkio\Shlink\Common\Paginator\Paginator; -use Shlinkio\Shlink\Common\Paginator\Util\PagerfantaUtilsTrait; -use Shlinkio\Shlink\Common\Rest\DataTransformerInterface; +use Shlinkio\Shlink\Common\Paginator\Util\PagerfantaUtils; use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl; use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlsParams; use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlWithVisitsSummary; use Shlinkio\Shlink\Core\ShortUrl\Model\TagsMode; use Shlinkio\Shlink\Core\ShortUrl\Model\Validation\ShortUrlsParamsInputFilter; use Shlinkio\Shlink\Core\ShortUrl\ShortUrlListServiceInterface; +use Shlinkio\Shlink\Core\ShortUrl\Transformer\ShortUrlDataTransformerInterface; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -32,8 +32,6 @@ use function sprintf; class ListShortUrlsCommand extends Command { - use PagerfantaUtilsTrait; - public const NAME = 'short-url:list'; private readonly StartDateOption $startDateOption; @@ -41,7 +39,7 @@ class ListShortUrlsCommand extends Command public function __construct( private readonly ShortUrlListServiceInterface $shortUrlService, - private readonly DataTransformerInterface $transformer, + private readonly ShortUrlDataTransformerInterface $transformer, ) { parent::__construct(); $this->startDateOption = new StartDateOption($this, 'short URLs'); @@ -196,7 +194,7 @@ class ListShortUrlsCommand extends Command ShlinkTable::default($output)->render( array_keys($columnsMap), $rows, - $all ? null : $this->formatCurrentPageMessage($shortUrls, 'Page %s of %s'), + $all ? null : PagerfantaUtils::formatCurrentPageMessage($shortUrls, 'Page %s of %s'), ); return $shortUrls; diff --git a/module/Core/src/EventDispatcher/PublishingUpdatesGenerator.php b/module/Core/src/EventDispatcher/PublishingUpdatesGenerator.php index 82ada6e1..211768b3 100644 --- a/module/Core/src/EventDispatcher/PublishingUpdatesGenerator.php +++ b/module/Core/src/EventDispatcher/PublishingUpdatesGenerator.php @@ -4,14 +4,14 @@ declare(strict_types=1); namespace Shlinkio\Shlink\Core\EventDispatcher; -use Shlinkio\Shlink\Common\Rest\DataTransformerInterface; use Shlinkio\Shlink\Common\UpdatePublishing\Update; use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl; +use Shlinkio\Shlink\Core\ShortUrl\Transformer\ShortUrlDataTransformerInterface; use Shlinkio\Shlink\Core\Visit\Entity\Visit; final readonly class PublishingUpdatesGenerator implements PublishingUpdatesGeneratorInterface { - public function __construct(private DataTransformerInterface $shortUrlTransformer) + public function __construct(private ShortUrlDataTransformerInterface $shortUrlTransformer) { } diff --git a/module/Core/src/ShortUrl/Transformer/ShortUrlDataTransformer.php b/module/Core/src/ShortUrl/Transformer/ShortUrlDataTransformer.php index 413f5a69..d2bdb73a 100644 --- a/module/Core/src/ShortUrl/Transformer/ShortUrlDataTransformer.php +++ b/module/Core/src/ShortUrl/Transformer/ShortUrlDataTransformer.php @@ -4,24 +4,17 @@ declare(strict_types=1); namespace Shlinkio\Shlink\Core\ShortUrl\Transformer; -use Shlinkio\Shlink\Common\Rest\DataTransformerInterface; use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl; use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortUrlStringifierInterface; use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlWithVisitsSummary; -/** - * @fixme Do not implement DataTransformerInterface, but a separate interface - */ -readonly class ShortUrlDataTransformer implements DataTransformerInterface +readonly class ShortUrlDataTransformer implements ShortUrlDataTransformerInterface { public function __construct(private ShortUrlStringifierInterface $stringifier) { } - /** - * @param ShortUrlWithVisitsSummary|ShortUrl $data - */ - public function transform($data): array // phpcs:ignore + public function transform(ShortUrlWithVisitsSummary|ShortUrl $data): array { $shortUrl = $data instanceof ShortUrlWithVisitsSummary ? $data->shortUrl : $data; return [ diff --git a/module/Core/src/ShortUrl/Transformer/ShortUrlDataTransformerInterface.php b/module/Core/src/ShortUrl/Transformer/ShortUrlDataTransformerInterface.php new file mode 100644 index 00000000..e1101f70 --- /dev/null +++ b/module/Core/src/ShortUrl/Transformer/ShortUrlDataTransformerInterface.php @@ -0,0 +1,13 @@ +getQueryParams()), AuthenticationMiddleware::apiKeyFromRequest($request), ); - return new JsonResponse(['shortUrls' => $this->serializePaginator($shortUrls, $this->transformer)]); + return new JsonResponse([ + 'shortUrls' => PagerfantaUtils::serializePaginator($shortUrls, $this->transformer->transform(...)), + ]); } } diff --git a/module/Rest/src/Action/ShortUrl/ResolveShortUrlAction.php b/module/Rest/src/Action/ShortUrl/ResolveShortUrlAction.php index 0fb2cc10..39a9d7f2 100644 --- a/module/Rest/src/Action/ShortUrl/ResolveShortUrlAction.php +++ b/module/Rest/src/Action/ShortUrl/ResolveShortUrlAction.php @@ -7,9 +7,9 @@ namespace Shlinkio\Shlink\Rest\Action\ShortUrl; use Laminas\Diactoros\Response\JsonResponse; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; -use Shlinkio\Shlink\Common\Rest\DataTransformerInterface; use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlIdentifier; use Shlinkio\Shlink\Core\ShortUrl\ShortUrlResolverInterface; +use Shlinkio\Shlink\Core\ShortUrl\Transformer\ShortUrlDataTransformerInterface; use Shlinkio\Shlink\Rest\Action\AbstractRestAction; use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware; @@ -20,7 +20,7 @@ class ResolveShortUrlAction extends AbstractRestAction public function __construct( private readonly ShortUrlResolverInterface $urlResolver, - private readonly DataTransformerInterface $transformer, + private readonly ShortUrlDataTransformerInterface $transformer, ) { } diff --git a/module/Rest/src/Action/Tag/ListTagsAction.php b/module/Rest/src/Action/Tag/ListTagsAction.php index 13898584..426f94e7 100644 --- a/module/Rest/src/Action/Tag/ListTagsAction.php +++ b/module/Rest/src/Action/Tag/ListTagsAction.php @@ -7,7 +7,7 @@ namespace Shlinkio\Shlink\Rest\Action\Tag; use Laminas\Diactoros\Response\JsonResponse; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; -use Shlinkio\Shlink\Common\Paginator\Util\PagerfantaUtilsTrait; +use Shlinkio\Shlink\Common\Paginator\Util\PagerfantaUtils; use Shlinkio\Shlink\Core\Tag\Model\TagsParams; use Shlinkio\Shlink\Core\Tag\TagServiceInterface; use Shlinkio\Shlink\Rest\Action\AbstractRestAction; @@ -15,12 +15,10 @@ use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware; class ListTagsAction extends AbstractRestAction { - use PagerfantaUtilsTrait; - protected const ROUTE_PATH = '/tags'; protected const ROUTE_ALLOWED_METHODS = [self::METHOD_GET]; - public function __construct(private TagServiceInterface $tagService) + public function __construct(private readonly TagServiceInterface $tagService) { } @@ -30,7 +28,7 @@ class ListTagsAction extends AbstractRestAction $apiKey = AuthenticationMiddleware::apiKeyFromRequest($request); return new JsonResponse([ - 'tags' => $this->serializePaginator($this->tagService->listTags($params, $apiKey)), + 'tags' => PagerfantaUtils::serializePaginator($this->tagService->listTags($params, $apiKey)), ]); } } diff --git a/module/Rest/src/Action/Tag/TagsStatsAction.php b/module/Rest/src/Action/Tag/TagsStatsAction.php index 6db3c62a..1ae470e0 100644 --- a/module/Rest/src/Action/Tag/TagsStatsAction.php +++ b/module/Rest/src/Action/Tag/TagsStatsAction.php @@ -7,7 +7,7 @@ namespace Shlinkio\Shlink\Rest\Action\Tag; use Laminas\Diactoros\Response\JsonResponse; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; -use Shlinkio\Shlink\Common\Paginator\Util\PagerfantaUtilsTrait; +use Shlinkio\Shlink\Common\Paginator\Util\PagerfantaUtils; use Shlinkio\Shlink\Core\Tag\Model\TagsParams; use Shlinkio\Shlink\Core\Tag\TagServiceInterface; use Shlinkio\Shlink\Rest\Action\AbstractRestAction; @@ -15,8 +15,6 @@ use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware; class TagsStatsAction extends AbstractRestAction { - use PagerfantaUtilsTrait; - protected const ROUTE_PATH = '/tags/stats'; protected const ROUTE_ALLOWED_METHODS = [self::METHOD_GET]; @@ -30,6 +28,6 @@ class TagsStatsAction extends AbstractRestAction $apiKey = AuthenticationMiddleware::apiKeyFromRequest($request); $tagsInfo = $this->tagService->tagsInfo($params, $apiKey); - return new JsonResponse(['tags' => $this->serializePaginator($tagsInfo)]); + return new JsonResponse(['tags' => PagerfantaUtils::serializePaginator($tagsInfo)]); } } diff --git a/module/Rest/src/Action/Visit/DeleteOrphanVisitsAction.php b/module/Rest/src/Action/Visit/DeleteOrphanVisitsAction.php index d1d2bc84..3a016451 100644 --- a/module/Rest/src/Action/Visit/DeleteOrphanVisitsAction.php +++ b/module/Rest/src/Action/Visit/DeleteOrphanVisitsAction.php @@ -7,15 +7,12 @@ namespace Shlinkio\Shlink\Rest\Action\Visit; use Laminas\Diactoros\Response\JsonResponse; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; -use Shlinkio\Shlink\Common\Paginator\Util\PagerfantaUtilsTrait; use Shlinkio\Shlink\Core\Visit\VisitsDeleterInterface; use Shlinkio\Shlink\Rest\Action\AbstractRestAction; use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware; class DeleteOrphanVisitsAction extends AbstractRestAction { - use PagerfantaUtilsTrait; - protected const ROUTE_PATH = '/visits/orphan'; protected const ROUTE_ALLOWED_METHODS = [self::METHOD_DELETE]; diff --git a/module/Rest/src/Action/Visit/DomainVisitsAction.php b/module/Rest/src/Action/Visit/DomainVisitsAction.php index 7dce57fb..91f071b5 100644 --- a/module/Rest/src/Action/Visit/DomainVisitsAction.php +++ b/module/Rest/src/Action/Visit/DomainVisitsAction.php @@ -7,7 +7,7 @@ namespace Shlinkio\Shlink\Rest\Action\Visit; use Laminas\Diactoros\Response\JsonResponse; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; -use Shlinkio\Shlink\Common\Paginator\Util\PagerfantaUtilsTrait; +use Shlinkio\Shlink\Common\Paginator\Util\PagerfantaUtils; use Shlinkio\Shlink\Core\Visit\Model\VisitsParams; use Shlinkio\Shlink\Core\Visit\VisitsStatsHelperInterface; use Shlinkio\Shlink\Rest\Action\AbstractRestAction; @@ -15,13 +15,13 @@ use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware; class DomainVisitsAction extends AbstractRestAction { - use PagerfantaUtilsTrait; - protected const ROUTE_PATH = '/domains/{domain}/visits'; protected const ROUTE_ALLOWED_METHODS = [self::METHOD_GET]; - public function __construct(private VisitsStatsHelperInterface $visitsHelper, private string $defaultDomain) - { + public function __construct( + private readonly VisitsStatsHelperInterface $visitsHelper, + private readonly string $defaultDomain, + ) { } public function handle(Request $request): Response @@ -31,9 +31,7 @@ class DomainVisitsAction extends AbstractRestAction $apiKey = AuthenticationMiddleware::apiKeyFromRequest($request); $visits = $this->visitsHelper->visitsForDomain($domain, $params, $apiKey); - return new JsonResponse([ - 'visits' => $this->serializePaginator($visits), - ]); + return new JsonResponse(['visits' => PagerfantaUtils::serializePaginator($visits)]); } private function resolveDomainParam(Request $request): string diff --git a/module/Rest/src/Action/Visit/NonOrphanVisitsAction.php b/module/Rest/src/Action/Visit/NonOrphanVisitsAction.php index fe0f0e0c..1fffdb8b 100644 --- a/module/Rest/src/Action/Visit/NonOrphanVisitsAction.php +++ b/module/Rest/src/Action/Visit/NonOrphanVisitsAction.php @@ -7,7 +7,7 @@ namespace Shlinkio\Shlink\Rest\Action\Visit; use Laminas\Diactoros\Response\JsonResponse; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; -use Shlinkio\Shlink\Common\Paginator\Util\PagerfantaUtilsTrait; +use Shlinkio\Shlink\Common\Paginator\Util\PagerfantaUtils; use Shlinkio\Shlink\Core\Visit\Model\VisitsParams; use Shlinkio\Shlink\Core\Visit\VisitsStatsHelperInterface; use Shlinkio\Shlink\Rest\Action\AbstractRestAction; @@ -15,12 +15,10 @@ use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware; class NonOrphanVisitsAction extends AbstractRestAction { - use PagerfantaUtilsTrait; - protected const ROUTE_PATH = '/visits/non-orphan'; protected const ROUTE_ALLOWED_METHODS = [self::METHOD_GET]; - public function __construct(private VisitsStatsHelperInterface $visitsHelper) + public function __construct(private readonly VisitsStatsHelperInterface $visitsHelper) { } @@ -30,8 +28,6 @@ class NonOrphanVisitsAction extends AbstractRestAction $apiKey = AuthenticationMiddleware::apiKeyFromRequest($request); $visits = $this->visitsHelper->nonOrphanVisits($params, $apiKey); - return new JsonResponse([ - 'visits' => $this->serializePaginator($visits), - ]); + return new JsonResponse(['visits' => PagerfantaUtils::serializePaginator($visits)]); } } diff --git a/module/Rest/src/Action/Visit/OrphanVisitsAction.php b/module/Rest/src/Action/Visit/OrphanVisitsAction.php index 0224022d..7906fdae 100644 --- a/module/Rest/src/Action/Visit/OrphanVisitsAction.php +++ b/module/Rest/src/Action/Visit/OrphanVisitsAction.php @@ -7,7 +7,7 @@ namespace Shlinkio\Shlink\Rest\Action\Visit; use Laminas\Diactoros\Response\JsonResponse; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; -use Shlinkio\Shlink\Common\Paginator\Util\PagerfantaUtilsTrait; +use Shlinkio\Shlink\Common\Paginator\Util\PagerfantaUtils; use Shlinkio\Shlink\Core\Visit\Model\OrphanVisitsParams; use Shlinkio\Shlink\Core\Visit\VisitsStatsHelperInterface; use Shlinkio\Shlink\Rest\Action\AbstractRestAction; @@ -15,8 +15,6 @@ use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware; class OrphanVisitsAction extends AbstractRestAction { - use PagerfantaUtilsTrait; - protected const ROUTE_PATH = '/visits/orphan'; protected const ROUTE_ALLOWED_METHODS = [self::METHOD_GET]; @@ -30,8 +28,6 @@ class OrphanVisitsAction extends AbstractRestAction $apiKey = AuthenticationMiddleware::apiKeyFromRequest($request); $visits = $this->visitsHelper->orphanVisits($params, $apiKey); - return new JsonResponse([ - 'visits' => $this->serializePaginator($visits), - ]); + return new JsonResponse(['visits' => PagerfantaUtils::serializePaginator($visits)]); } } diff --git a/module/Rest/src/Action/Visit/ShortUrlVisitsAction.php b/module/Rest/src/Action/Visit/ShortUrlVisitsAction.php index 52f09825..fe5099a2 100644 --- a/module/Rest/src/Action/Visit/ShortUrlVisitsAction.php +++ b/module/Rest/src/Action/Visit/ShortUrlVisitsAction.php @@ -7,7 +7,7 @@ namespace Shlinkio\Shlink\Rest\Action\Visit; use Laminas\Diactoros\Response\JsonResponse; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; -use Shlinkio\Shlink\Common\Paginator\Util\PagerfantaUtilsTrait; +use Shlinkio\Shlink\Common\Paginator\Util\PagerfantaUtils; use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlIdentifier; use Shlinkio\Shlink\Core\Visit\Model\VisitsParams; use Shlinkio\Shlink\Core\Visit\VisitsStatsHelperInterface; @@ -16,12 +16,10 @@ use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware; class ShortUrlVisitsAction extends AbstractRestAction { - use PagerfantaUtilsTrait; - protected const ROUTE_PATH = '/short-urls/{shortCode}/visits'; protected const ROUTE_ALLOWED_METHODS = [self::METHOD_GET]; - public function __construct(private VisitsStatsHelperInterface $visitsHelper) + public function __construct(private readonly VisitsStatsHelperInterface $visitsHelper) { } @@ -32,8 +30,6 @@ class ShortUrlVisitsAction extends AbstractRestAction $apiKey = AuthenticationMiddleware::apiKeyFromRequest($request); $visits = $this->visitsHelper->visitsForShortUrl($identifier, $params, $apiKey); - return new JsonResponse([ - 'visits' => $this->serializePaginator($visits), - ]); + return new JsonResponse(['visits' => PagerfantaUtils::serializePaginator($visits)]); } } diff --git a/module/Rest/src/Action/Visit/TagVisitsAction.php b/module/Rest/src/Action/Visit/TagVisitsAction.php index 8b88a2cd..1739264f 100644 --- a/module/Rest/src/Action/Visit/TagVisitsAction.php +++ b/module/Rest/src/Action/Visit/TagVisitsAction.php @@ -7,7 +7,7 @@ namespace Shlinkio\Shlink\Rest\Action\Visit; use Laminas\Diactoros\Response\JsonResponse; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; -use Shlinkio\Shlink\Common\Paginator\Util\PagerfantaUtilsTrait; +use Shlinkio\Shlink\Common\Paginator\Util\PagerfantaUtils; use Shlinkio\Shlink\Core\Visit\Model\VisitsParams; use Shlinkio\Shlink\Core\Visit\VisitsStatsHelperInterface; use Shlinkio\Shlink\Rest\Action\AbstractRestAction; @@ -15,12 +15,10 @@ use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware; class TagVisitsAction extends AbstractRestAction { - use PagerfantaUtilsTrait; - protected const ROUTE_PATH = '/tags/{tag}/visits'; protected const ROUTE_ALLOWED_METHODS = [self::METHOD_GET]; - public function __construct(private VisitsStatsHelperInterface $visitsHelper) + public function __construct(private readonly VisitsStatsHelperInterface $visitsHelper) { } @@ -31,8 +29,6 @@ class TagVisitsAction extends AbstractRestAction $apiKey = AuthenticationMiddleware::apiKeyFromRequest($request); $visits = $this->visitsHelper->visitsForTag($tag, $params, $apiKey); - return new JsonResponse([ - 'visits' => $this->serializePaginator($visits), - ]); + return new JsonResponse(['visits' => PagerfantaUtils::serializePaginator($visits)]); } } diff --git a/module/Rest/test/Action/ShortUrl/CreateShortUrlActionTest.php b/module/Rest/test/Action/ShortUrl/CreateShortUrlActionTest.php index c79eab86..7361df5c 100644 --- a/module/Rest/test/Action/ShortUrl/CreateShortUrlActionTest.php +++ b/module/Rest/test/Action/ShortUrl/CreateShortUrlActionTest.php @@ -12,12 +12,12 @@ use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Shlinkio\Shlink\Common\Rest\DataTransformerInterface; use Shlinkio\Shlink\Core\Exception\ValidationException; use Shlinkio\Shlink\Core\Options\UrlShortenerOptions; use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl; use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlCreation; use Shlinkio\Shlink\Core\ShortUrl\Model\UrlShorteningResult; +use Shlinkio\Shlink\Core\ShortUrl\Transformer\ShortUrlDataTransformerInterface; use Shlinkio\Shlink\Core\ShortUrl\UrlShortener; use Shlinkio\Shlink\Rest\Action\ShortUrl\CreateShortUrlAction; use Shlinkio\Shlink\Rest\Entity\ApiKey; @@ -26,12 +26,12 @@ class CreateShortUrlActionTest extends TestCase { private CreateShortUrlAction $action; private MockObject & UrlShortener $urlShortener; - private MockObject & DataTransformerInterface $transformer; + private MockObject & ShortUrlDataTransformerInterface $transformer; protected function setUp(): void { $this->urlShortener = $this->createMock(UrlShortener::class); - $this->transformer = $this->createMock(DataTransformerInterface::class); + $this->transformer = $this->createMock(ShortUrlDataTransformerInterface::class); $this->action = new CreateShortUrlAction($this->urlShortener, $this->transformer, new UrlShortenerOptions()); } diff --git a/module/Rest/test/Action/ShortUrl/SingleStepCreateShortUrlActionTest.php b/module/Rest/test/Action/ShortUrl/SingleStepCreateShortUrlActionTest.php index c1ac6544..69914f0e 100644 --- a/module/Rest/test/Action/ShortUrl/SingleStepCreateShortUrlActionTest.php +++ b/module/Rest/test/Action/ShortUrl/SingleStepCreateShortUrlActionTest.php @@ -8,11 +8,11 @@ use Laminas\Diactoros\ServerRequest; use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Shlinkio\Shlink\Common\Rest\DataTransformerInterface; use Shlinkio\Shlink\Core\Options\UrlShortenerOptions; use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl; use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlCreation; use Shlinkio\Shlink\Core\ShortUrl\Model\UrlShorteningResult; +use Shlinkio\Shlink\Core\ShortUrl\Transformer\ShortUrlDataTransformerInterface; use Shlinkio\Shlink\Core\ShortUrl\UrlShortenerInterface; use Shlinkio\Shlink\Rest\Action\ShortUrl\SingleStepCreateShortUrlAction; use Shlinkio\Shlink\Rest\Entity\ApiKey; @@ -25,7 +25,7 @@ class SingleStepCreateShortUrlActionTest extends TestCase protected function setUp(): void { $this->urlShortener = $this->createMock(UrlShortenerInterface::class); - $transformer = $this->createMock(DataTransformerInterface::class); + $transformer = $this->createMock(ShortUrlDataTransformerInterface::class); $transformer->method('transform')->willReturn([]); $this->action = new SingleStepCreateShortUrlAction( From 1d24750f43f1d87f8908f33c20adca4e313975dd Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Mon, 29 Jul 2024 19:59:46 +0200 Subject: [PATCH 2/3] Fix phpstan checks --- .../src/EventDispatcher/PublishingUpdatesGenerator.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/module/Core/src/EventDispatcher/PublishingUpdatesGenerator.php b/module/Core/src/EventDispatcher/PublishingUpdatesGenerator.php index 211768b3..b762af7e 100644 --- a/module/Core/src/EventDispatcher/PublishingUpdatesGenerator.php +++ b/module/Core/src/EventDispatcher/PublishingUpdatesGenerator.php @@ -18,7 +18,7 @@ final readonly class PublishingUpdatesGenerator implements PublishingUpdatesGene public function newVisitUpdate(Visit $visit): Update { return Update::forTopicAndPayload(Topic::NEW_VISIT->value, [ - 'shortUrl' => $this->shortUrlTransformer->transform($visit->shortUrl), + 'shortUrl' => $this->transformShortUrl($visit->shortUrl), 'visit' => $visit->jsonSerialize(), ]); } @@ -36,7 +36,7 @@ final readonly class PublishingUpdatesGenerator implements PublishingUpdatesGene $topic = Topic::newShortUrlVisit($shortUrl?->getShortCode()); return Update::forTopicAndPayload($topic, [ - 'shortUrl' => $this->shortUrlTransformer->transform($shortUrl), + 'shortUrl' => $this->transformShortUrl($shortUrl), 'visit' => $visit->jsonSerialize(), ]); } @@ -47,4 +47,9 @@ final readonly class PublishingUpdatesGenerator implements PublishingUpdatesGene 'shortUrl' => $this->shortUrlTransformer->transform($shortUrl), ]); } + + private function transformShortUrl(?ShortUrl $shortUrl): array + { + return $shortUrl === null ? [] : $this->shortUrlTransformer->transform($shortUrl); + } } From 037cd8a389bc34e19ea94b2199c9572b05cf3dc8 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Mon, 29 Jul 2024 20:43:52 +0200 Subject: [PATCH 3/3] Add missing generic tyoes annotations --- .../Command/Domain/GetDomainVisitsCommand.php | 3 +++ .../ShortUrl/GetShortUrlVisitsCommand.php | 3 +++ .../Command/ShortUrl/ListShortUrlsCommand.php | 1 + .../src/Command/Tag/GetTagVisitsCommand.php | 3 +++ .../Visit/AbstractVisitsListCommand.php | 6 ++++++ .../Visit/GetNonOrphanVisitsCommand.php | 3 +++ .../Command/Visit/GetOrphanVisitsCommand.php | 3 +++ .../Command/Db/CreateDatabaseCommandTest.php | 2 ++ .../Domain/Repository/DomainRepository.php | 1 + .../Repository/DomainRepositoryInterface.php | 1 + .../Validation/DomainRedirectsInputFilter.php | 1 + .../src/Exception/ValidationException.php | 3 +++ ...AbstractCacheableCountPaginatorAdapter.php | 4 ++++ .../Validation/RedirectRulesInputFilter.php | 7 +++++++ module/Core/src/ShortUrl/Entity/ShortUrl.php | 6 +++--- .../Model/Validation/ShortUrlInputFilter.php | 1 + .../Validation/ShortUrlsParamsInputFilter.php | 1 + .../Adapter/ShortUrlRepositoryAdapter.php | 2 ++ .../Repository/CrawlableShortCodesQuery.php | 1 + .../Repository/ExpiredShortUrlsRepository.php | 1 + .../Repository/ShortUrlListRepository.php | 1 + .../Repository/ShortUrlRepository.php | 1 + .../ShortUrlRepositoryInterface.php | 1 + .../Core/src/ShortUrl/ShortUrlListService.php | 3 +-- .../ShortUrl/ShortUrlListServiceInterface.php | 2 +- module/Core/src/Tag/Entity/Tag.php | 2 ++ .../Adapter/AbstractTagsPaginatorAdapter.php | 4 ++++ .../Adapter/TagsInfoPaginatorAdapter.php | 2 ++ .../Adapter/TagsPaginatorAdapter.php | 2 ++ .../Core/src/Tag/Repository/TagRepository.php | 1 + .../Tag/Repository/TagRepositoryInterface.php | 2 ++ module/Core/src/Tag/TagService.php | 21 ++++++++++--------- module/Core/src/Tag/TagServiceInterface.php | 4 ++-- .../Adapter/DomainVisitsPaginatorAdapter.php | 12 +++++++---- .../NonOrphanVisitsPaginatorAdapter.php | 8 ++++--- .../Adapter/OrphanVisitsPaginatorAdapter.php | 2 ++ .../ShortUrlVisitsPaginatorAdapter.php | 10 +++++---- .../Adapter/TagVisitsPaginatorAdapter.php | 10 +++++---- .../OrphanVisitsCountRepository.php | 1 + .../ShortUrlVisitsCountRepository.php | 2 ++ .../Repository/VisitDeleterRepository.php | 1 + .../Repository/VisitIterationRepository.php | 1 + .../src/Visit/Repository/VisitRepository.php | 1 + .../Repository/VisitRepositoryInterface.php | 3 +++ module/Core/src/Visit/VisitsStatsHelper.php | 15 ++++++------- .../src/Visit/VisitsStatsHelperInterface.php | 10 ++++----- .../Listener/OrphanVisitsCountTrackerTest.php | 4 ++-- .../ShortUrlVisitsCountTrackerTest.php | 4 ++-- .../Entity/ShortUrlRedirectRuleTest.php | 2 +- .../ShortUrlTitleResolutionHelperTest.php | 3 +++ .../ApiKey/Repository/ApiKeyRepository.php | 3 +++ .../Repository/ApiKeyRepositoryInterface.php | 3 +++ phpstan.neon | 1 - 53 files changed, 144 insertions(+), 51 deletions(-) diff --git a/module/CLI/src/Command/Domain/GetDomainVisitsCommand.php b/module/CLI/src/Command/Domain/GetDomainVisitsCommand.php index dd3797f8..6477539e 100644 --- a/module/CLI/src/Command/Domain/GetDomainVisitsCommand.php +++ b/module/CLI/src/Command/Domain/GetDomainVisitsCommand.php @@ -33,6 +33,9 @@ class GetDomainVisitsCommand extends AbstractVisitsListCommand ->addArgument('domain', InputArgument::REQUIRED, 'The domain which visits we want to get.'); } + /** + * @return Paginator + */ protected function getVisitsPaginator(InputInterface $input, DateRange $dateRange): Paginator { $domain = $input->getArgument('domain'); diff --git a/module/CLI/src/Command/ShortUrl/GetShortUrlVisitsCommand.php b/module/CLI/src/Command/ShortUrl/GetShortUrlVisitsCommand.php index 8a662209..8583a242 100644 --- a/module/CLI/src/Command/ShortUrl/GetShortUrlVisitsCommand.php +++ b/module/CLI/src/Command/ShortUrl/GetShortUrlVisitsCommand.php @@ -46,6 +46,9 @@ class GetShortUrlVisitsCommand extends AbstractVisitsListCommand } } + /** + * @return Paginator + */ protected function getVisitsPaginator(InputInterface $input, DateRange $dateRange): Paginator { $identifier = $this->shortUrlIdentifierInput->toShortUrlIdentifier($input); diff --git a/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php b/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php index 1aa95631..6d38ff0f 100644 --- a/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php +++ b/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php @@ -177,6 +177,7 @@ class ListShortUrlsCommand extends Command /** * @param array $columnsMap + * @return Paginator */ private function renderPage( OutputInterface $output, diff --git a/module/CLI/src/Command/Tag/GetTagVisitsCommand.php b/module/CLI/src/Command/Tag/GetTagVisitsCommand.php index 1dfd0ba9..18da41fb 100644 --- a/module/CLI/src/Command/Tag/GetTagVisitsCommand.php +++ b/module/CLI/src/Command/Tag/GetTagVisitsCommand.php @@ -33,6 +33,9 @@ class GetTagVisitsCommand extends AbstractVisitsListCommand ->addArgument('tag', InputArgument::REQUIRED, 'The tag which visits we want to get.'); } + /** + * @return Paginator + */ protected function getVisitsPaginator(InputInterface $input, DateRange $dateRange): Paginator { $tag = $input->getArgument('tag'); diff --git a/module/CLI/src/Command/Visit/AbstractVisitsListCommand.php b/module/CLI/src/Command/Visit/AbstractVisitsListCommand.php index d3a49c53..dea28e92 100644 --- a/module/CLI/src/Command/Visit/AbstractVisitsListCommand.php +++ b/module/CLI/src/Command/Visit/AbstractVisitsListCommand.php @@ -46,6 +46,9 @@ abstract class AbstractVisitsListCommand extends Command return ExitCode::EXIT_SUCCESS; } + /** + * @param Paginator $paginator + */ private function resolveRowsAndHeaders(Paginator $paginator): array { $extraKeys = []; @@ -74,6 +77,9 @@ abstract class AbstractVisitsListCommand extends Command ]; } + /** + * @return Paginator + */ abstract protected function getVisitsPaginator(InputInterface $input, DateRange $dateRange): Paginator; /** diff --git a/module/CLI/src/Command/Visit/GetNonOrphanVisitsCommand.php b/module/CLI/src/Command/Visit/GetNonOrphanVisitsCommand.php index 1462620d..58035509 100644 --- a/module/CLI/src/Command/Visit/GetNonOrphanVisitsCommand.php +++ b/module/CLI/src/Command/Visit/GetNonOrphanVisitsCommand.php @@ -30,6 +30,9 @@ class GetNonOrphanVisitsCommand extends AbstractVisitsListCommand ->setDescription('Returns the list of non-orphan visits.'); } + /** + * @return Paginator + */ protected function getVisitsPaginator(InputInterface $input, DateRange $dateRange): Paginator { return $this->visitsHelper->nonOrphanVisits(new VisitsParams($dateRange)); diff --git a/module/CLI/src/Command/Visit/GetOrphanVisitsCommand.php b/module/CLI/src/Command/Visit/GetOrphanVisitsCommand.php index d495db77..ea5c0fe2 100644 --- a/module/CLI/src/Command/Visit/GetOrphanVisitsCommand.php +++ b/module/CLI/src/Command/Visit/GetOrphanVisitsCommand.php @@ -30,6 +30,9 @@ class GetOrphanVisitsCommand extends AbstractVisitsListCommand )); } + /** + * @return Paginator + */ protected function getVisitsPaginator(InputInterface $input, DateRange $dateRange): Paginator { $rawType = $input->getOption('type'); diff --git a/module/CLI/test/Command/Db/CreateDatabaseCommandTest.php b/module/CLI/test/Command/Db/CreateDatabaseCommandTest.php index b4a5c840..9563ef27 100644 --- a/module/CLI/test/Command/Db/CreateDatabaseCommandTest.php +++ b/module/CLI/test/Command/Db/CreateDatabaseCommandTest.php @@ -7,6 +7,7 @@ namespace ShlinkioTest\Shlink\CLI\Command\Db; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Driver; use Doctrine\DBAL\Platforms\AbstractPlatform; +use Doctrine\DBAL\Platforms\SQLitePlatform; use Doctrine\DBAL\Schema\AbstractSchemaManager; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Mapping\ClassMetadata; @@ -31,6 +32,7 @@ class CreateDatabaseCommandTest extends TestCase private MockObject & ProcessRunnerInterface $processHelper; private MockObject & Connection $regularConn; private MockObject & ClassMetadataFactory $metadataFactory; + /** @var MockObject&AbstractSchemaManager */ private MockObject & AbstractSchemaManager $schemaManager; private MockObject & Driver $driver; diff --git a/module/Core/src/Domain/Repository/DomainRepository.php b/module/Core/src/Domain/Repository/DomainRepository.php index aae44aed..fedf4f54 100644 --- a/module/Core/src/Domain/Repository/DomainRepository.php +++ b/module/Core/src/Domain/Repository/DomainRepository.php @@ -14,6 +14,7 @@ use Shlinkio\Shlink\Core\ShortUrl\Spec\BelongsToApiKey; use Shlinkio\Shlink\Rest\ApiKey\Role; use Shlinkio\Shlink\Rest\Entity\ApiKey; +/** @extends EntitySpecificationRepository */ class DomainRepository extends EntitySpecificationRepository implements DomainRepositoryInterface { /** diff --git a/module/Core/src/Domain/Repository/DomainRepositoryInterface.php b/module/Core/src/Domain/Repository/DomainRepositoryInterface.php index d703542b..d215e475 100644 --- a/module/Core/src/Domain/Repository/DomainRepositoryInterface.php +++ b/module/Core/src/Domain/Repository/DomainRepositoryInterface.php @@ -9,6 +9,7 @@ use Happyr\DoctrineSpecification\Repository\EntitySpecificationRepositoryInterfa use Shlinkio\Shlink\Core\Domain\Entity\Domain; use Shlinkio\Shlink\Rest\Entity\ApiKey; +/** @extends ObjectRepository */ interface DomainRepositoryInterface extends ObjectRepository, EntitySpecificationRepositoryInterface { /** diff --git a/module/Core/src/Domain/Validation/DomainRedirectsInputFilter.php b/module/Core/src/Domain/Validation/DomainRedirectsInputFilter.php index 48035c6c..d448b819 100644 --- a/module/Core/src/Domain/Validation/DomainRedirectsInputFilter.php +++ b/module/Core/src/Domain/Validation/DomainRedirectsInputFilter.php @@ -8,6 +8,7 @@ use Laminas\InputFilter\InputFilter; use Shlinkio\Shlink\Common\Validation\HostAndPortValidator; use Shlinkio\Shlink\Common\Validation\InputFactory; +/** @extends InputFilter */ class DomainRedirectsInputFilter extends InputFilter { public const DOMAIN = 'domain'; diff --git a/module/Core/src/Exception/ValidationException.php b/module/Core/src/Exception/ValidationException.php index dcb11fa4..95da6d5e 100644 --- a/module/Core/src/Exception/ValidationException.php +++ b/module/Core/src/Exception/ValidationException.php @@ -26,6 +26,9 @@ class ValidationException extends InvalidArgumentException implements ProblemDet private array $invalidElements; + /** + * @param InputFilterInterface $inputFilter + */ public static function fromInputFilter(InputFilterInterface $inputFilter, ?Throwable $prev = null): self { return static::fromArray($inputFilter->getMessages(), $prev); diff --git a/module/Core/src/Paginator/Adapter/AbstractCacheableCountPaginatorAdapter.php b/module/Core/src/Paginator/Adapter/AbstractCacheableCountPaginatorAdapter.php index 217d5eff..890c8845 100644 --- a/module/Core/src/Paginator/Adapter/AbstractCacheableCountPaginatorAdapter.php +++ b/module/Core/src/Paginator/Adapter/AbstractCacheableCountPaginatorAdapter.php @@ -6,6 +6,10 @@ namespace Shlinkio\Shlink\Core\Paginator\Adapter; use Pagerfanta\Adapter\AdapterInterface; +/** + * @template T + * @implements AdapterInterface + */ abstract class AbstractCacheableCountPaginatorAdapter implements AdapterInterface { private ?int $count = null; diff --git a/module/Core/src/RedirectRule/Model/Validation/RedirectRulesInputFilter.php b/module/Core/src/RedirectRule/Model/Validation/RedirectRulesInputFilter.php index 892b93e4..c2fee661 100644 --- a/module/Core/src/RedirectRule/Model/Validation/RedirectRulesInputFilter.php +++ b/module/Core/src/RedirectRule/Model/Validation/RedirectRulesInputFilter.php @@ -17,6 +17,7 @@ use Shlinkio\Shlink\Core\Util\IpAddressUtils; use function Shlinkio\Shlink\Core\ArrayUtils\contains; use function Shlinkio\Shlink\Core\enumValues; +/** @extends InputFilter */ class RedirectRulesInputFilter extends InputFilter { public const REDIRECT_RULES = 'redirectRules'; @@ -44,6 +45,9 @@ class RedirectRulesInputFilter extends InputFilter return $instance; } + /** + * @return InputFilter + */ private static function createRedirectRuleInputFilter(): InputFilter { $redirectRuleInputFilter = new InputFilter(); @@ -60,6 +64,9 @@ class RedirectRulesInputFilter extends InputFilter return $redirectRuleInputFilter; } + /** + * @return InputFilter + */ private static function createRedirectConditionInputFilter(): InputFilter { $redirectConditionInputFilter = new InputFilter(); diff --git a/module/Core/src/ShortUrl/Entity/ShortUrl.php b/module/Core/src/ShortUrl/Entity/ShortUrl.php index 084acabd..e394fb5a 100644 --- a/module/Core/src/ShortUrl/Entity/ShortUrl.php +++ b/module/Core/src/ShortUrl/Entity/ShortUrl.php @@ -37,8 +37,8 @@ class ShortUrl extends AbstractEntity { /** * @param Collection $tags - * @param Collection & Selectable $visits - * @param Collection & Selectable $visitsCounts + * @param Collection & Selectable $visits + * @param Collection & Selectable $visitsCounts */ private function __construct( private string $longUrl, @@ -213,7 +213,7 @@ class ShortUrl extends AbstractEntity } /** - * @param Collection & Selectable $visits + * @param Collection & Selectable $visits * @internal */ public function setVisits(Collection & Selectable $visits): self diff --git a/module/Core/src/ShortUrl/Model/Validation/ShortUrlInputFilter.php b/module/Core/src/ShortUrl/Model/Validation/ShortUrlInputFilter.php index e8d35284..f4a35969 100644 --- a/module/Core/src/ShortUrl/Model/Validation/ShortUrlInputFilter.php +++ b/module/Core/src/ShortUrl/Model/Validation/ShortUrlInputFilter.php @@ -20,6 +20,7 @@ use function substr; use const Shlinkio\Shlink\LOOSE_URI_MATCHER; use const Shlinkio\Shlink\MIN_SHORT_CODES_LENGTH; +/** @extends InputFilter */ class ShortUrlInputFilter extends InputFilter { // Fields for creation only diff --git a/module/Core/src/ShortUrl/Model/Validation/ShortUrlsParamsInputFilter.php b/module/Core/src/ShortUrl/Model/Validation/ShortUrlsParamsInputFilter.php index f4f7c338..0a0d45ed 100644 --- a/module/Core/src/ShortUrl/Model/Validation/ShortUrlsParamsInputFilter.php +++ b/module/Core/src/ShortUrl/Model/Validation/ShortUrlsParamsInputFilter.php @@ -13,6 +13,7 @@ use Shlinkio\Shlink\Core\ShortUrl\Model\TagsMode; use function Shlinkio\Shlink\Core\enumValues; +/** @extends InputFilter */ class ShortUrlsParamsInputFilter extends InputFilter { public const PAGE = 'page'; diff --git a/module/Core/src/ShortUrl/Paginator/Adapter/ShortUrlRepositoryAdapter.php b/module/Core/src/ShortUrl/Paginator/Adapter/ShortUrlRepositoryAdapter.php index 56f8e5a5..ac3379df 100644 --- a/module/Core/src/ShortUrl/Paginator/Adapter/ShortUrlRepositoryAdapter.php +++ b/module/Core/src/ShortUrl/Paginator/Adapter/ShortUrlRepositoryAdapter.php @@ -6,11 +6,13 @@ namespace Shlinkio\Shlink\Core\ShortUrl\Paginator\Adapter; use Pagerfanta\Adapter\AdapterInterface; use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlsParams; +use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlWithVisitsSummary; use Shlinkio\Shlink\Core\ShortUrl\Persistence\ShortUrlsCountFiltering; use Shlinkio\Shlink\Core\ShortUrl\Persistence\ShortUrlsListFiltering; use Shlinkio\Shlink\Core\ShortUrl\Repository\ShortUrlListRepositoryInterface; use Shlinkio\Shlink\Rest\Entity\ApiKey; +/** @implements AdapterInterface */ readonly class ShortUrlRepositoryAdapter implements AdapterInterface { public function __construct( diff --git a/module/Core/src/ShortUrl/Repository/CrawlableShortCodesQuery.php b/module/Core/src/ShortUrl/Repository/CrawlableShortCodesQuery.php index 89aef69e..2831269d 100644 --- a/module/Core/src/ShortUrl/Repository/CrawlableShortCodesQuery.php +++ b/module/Core/src/ShortUrl/Repository/CrawlableShortCodesQuery.php @@ -7,6 +7,7 @@ namespace Shlinkio\Shlink\Core\ShortUrl\Repository; use Happyr\DoctrineSpecification\Repository\EntitySpecificationRepository; use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl; +/** @extends EntitySpecificationRepository */ class CrawlableShortCodesQuery extends EntitySpecificationRepository implements CrawlableShortCodesQueryInterface { /** diff --git a/module/Core/src/ShortUrl/Repository/ExpiredShortUrlsRepository.php b/module/Core/src/ShortUrl/Repository/ExpiredShortUrlsRepository.php index 0b796971..05944f29 100644 --- a/module/Core/src/ShortUrl/Repository/ExpiredShortUrlsRepository.php +++ b/module/Core/src/ShortUrl/Repository/ExpiredShortUrlsRepository.php @@ -13,6 +13,7 @@ use Shlinkio\Shlink\Core\Visit\Entity\ShortUrlVisitsCount; use function sprintf; +/** @extends EntitySpecificationRepository */ class ExpiredShortUrlsRepository extends EntitySpecificationRepository implements ExpiredShortUrlsRepositoryInterface { /** diff --git a/module/Core/src/ShortUrl/Repository/ShortUrlListRepository.php b/module/Core/src/ShortUrl/Repository/ShortUrlListRepository.php index 8aac9b73..e8fd4ac6 100644 --- a/module/Core/src/ShortUrl/Repository/ShortUrlListRepository.php +++ b/module/Core/src/ShortUrl/Repository/ShortUrlListRepository.php @@ -20,6 +20,7 @@ use Shlinkio\Shlink\Core\Visit\Entity\ShortUrlVisitsCount; use function Shlinkio\Shlink\Core\ArrayUtils\map; use function sprintf; +/** @extends EntitySpecificationRepository */ class ShortUrlListRepository extends EntitySpecificationRepository implements ShortUrlListRepositoryInterface { /** diff --git a/module/Core/src/ShortUrl/Repository/ShortUrlRepository.php b/module/Core/src/ShortUrl/Repository/ShortUrlRepository.php index e151a6c7..015c8eac 100644 --- a/module/Core/src/ShortUrl/Repository/ShortUrlRepository.php +++ b/module/Core/src/ShortUrl/Repository/ShortUrlRepository.php @@ -20,6 +20,7 @@ use Shlinkio\Shlink\Importer\Model\ImportedShlinkUrl; use function count; use function strtolower; +/** @extends EntitySpecificationRepository */ class ShortUrlRepository extends EntitySpecificationRepository implements ShortUrlRepositoryInterface { public function findOneWithDomainFallback(ShortUrlIdentifier $identifier, ShortUrlMode $shortUrlMode): ?ShortUrl diff --git a/module/Core/src/ShortUrl/Repository/ShortUrlRepositoryInterface.php b/module/Core/src/ShortUrl/Repository/ShortUrlRepositoryInterface.php index 8af53cb9..d0934197 100644 --- a/module/Core/src/ShortUrl/Repository/ShortUrlRepositoryInterface.php +++ b/module/Core/src/ShortUrl/Repository/ShortUrlRepositoryInterface.php @@ -13,6 +13,7 @@ use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlIdentifier; use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlMode; use Shlinkio\Shlink\Importer\Model\ImportedShlinkUrl; +/** @extends ObjectRepository */ interface ShortUrlRepositoryInterface extends ObjectRepository, EntitySpecificationRepositoryInterface { public function findOneWithDomainFallback(ShortUrlIdentifier $identifier, ShortUrlMode $shortUrlMode): ?ShortUrl; diff --git a/module/Core/src/ShortUrl/ShortUrlListService.php b/module/Core/src/ShortUrl/ShortUrlListService.php index d86c4988..f8441454 100644 --- a/module/Core/src/ShortUrl/ShortUrlListService.php +++ b/module/Core/src/ShortUrl/ShortUrlListService.php @@ -7,7 +7,6 @@ namespace Shlinkio\Shlink\Core\ShortUrl; use Shlinkio\Shlink\Common\Paginator\Paginator; use Shlinkio\Shlink\Core\Options\UrlShortenerOptions; use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlsParams; -use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlWithVisitsSummary; use Shlinkio\Shlink\Core\ShortUrl\Paginator\Adapter\ShortUrlRepositoryAdapter; use Shlinkio\Shlink\Core\ShortUrl\Repository\ShortUrlListRepositoryInterface; use Shlinkio\Shlink\Rest\Entity\ApiKey; @@ -21,7 +20,7 @@ readonly class ShortUrlListService implements ShortUrlListServiceInterface } /** - * @return ShortUrlWithVisitsSummary[]|Paginator + * @inheritDoc */ public function listShortUrls(ShortUrlsParams $params, ?ApiKey $apiKey = null): Paginator { diff --git a/module/Core/src/ShortUrl/ShortUrlListServiceInterface.php b/module/Core/src/ShortUrl/ShortUrlListServiceInterface.php index ffbb1374..b83abd4c 100644 --- a/module/Core/src/ShortUrl/ShortUrlListServiceInterface.php +++ b/module/Core/src/ShortUrl/ShortUrlListServiceInterface.php @@ -12,7 +12,7 @@ use Shlinkio\Shlink\Rest\Entity\ApiKey; interface ShortUrlListServiceInterface { /** - * @return ShortUrlWithVisitsSummary[]|Paginator + * @return Paginator */ public function listShortUrls(ShortUrlsParams $params, ?ApiKey $apiKey = null): Paginator; } diff --git a/module/Core/src/Tag/Entity/Tag.php b/module/Core/src/Tag/Entity/Tag.php index 5ad272ea..9224b38c 100644 --- a/module/Core/src/Tag/Entity/Tag.php +++ b/module/Core/src/Tag/Entity/Tag.php @@ -7,9 +7,11 @@ namespace Shlinkio\Shlink\Core\Tag\Entity; use Doctrine\Common\Collections; use JsonSerializable; use Shlinkio\Shlink\Common\Entity\AbstractEntity; +use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl; class Tag extends AbstractEntity implements JsonSerializable { + /** @var Collections\Collection */ private Collections\Collection $shortUrls; public function __construct(private string $name) diff --git a/module/Core/src/Tag/Paginator/Adapter/AbstractTagsPaginatorAdapter.php b/module/Core/src/Tag/Paginator/Adapter/AbstractTagsPaginatorAdapter.php index 49f9c721..98126e27 100644 --- a/module/Core/src/Tag/Paginator/Adapter/AbstractTagsPaginatorAdapter.php +++ b/module/Core/src/Tag/Paginator/Adapter/AbstractTagsPaginatorAdapter.php @@ -12,6 +12,10 @@ use Shlinkio\Shlink\Core\Tag\Repository\TagRepositoryInterface; use Shlinkio\Shlink\Rest\ApiKey\Spec\WithApiKeySpecsEnsuringJoin; use Shlinkio\Shlink\Rest\Entity\ApiKey; +/** + * @template T + * @implements AdapterInterface + */ abstract class AbstractTagsPaginatorAdapter implements AdapterInterface { public function __construct( diff --git a/module/Core/src/Tag/Paginator/Adapter/TagsInfoPaginatorAdapter.php b/module/Core/src/Tag/Paginator/Adapter/TagsInfoPaginatorAdapter.php index c2917200..2c1a481a 100644 --- a/module/Core/src/Tag/Paginator/Adapter/TagsInfoPaginatorAdapter.php +++ b/module/Core/src/Tag/Paginator/Adapter/TagsInfoPaginatorAdapter.php @@ -4,8 +4,10 @@ declare(strict_types=1); namespace Shlinkio\Shlink\Core\Tag\Paginator\Adapter; +use Shlinkio\Shlink\Core\Tag\Model\TagInfo; use Shlinkio\Shlink\Core\Tag\Model\TagsListFiltering; +/** @extends AbstractTagsPaginatorAdapter */ class TagsInfoPaginatorAdapter extends AbstractTagsPaginatorAdapter { public function getSlice(int $offset, int $length): iterable diff --git a/module/Core/src/Tag/Paginator/Adapter/TagsPaginatorAdapter.php b/module/Core/src/Tag/Paginator/Adapter/TagsPaginatorAdapter.php index 7d54940e..e6cb400c 100644 --- a/module/Core/src/Tag/Paginator/Adapter/TagsPaginatorAdapter.php +++ b/module/Core/src/Tag/Paginator/Adapter/TagsPaginatorAdapter.php @@ -5,8 +5,10 @@ declare(strict_types=1); namespace Shlinkio\Shlink\Core\Tag\Paginator\Adapter; use Happyr\DoctrineSpecification\Spec; +use Shlinkio\Shlink\Core\Tag\Entity\Tag; use Shlinkio\Shlink\Rest\ApiKey\Spec\WithApiKeySpecsEnsuringJoin; +/** @extends AbstractTagsPaginatorAdapter */ class TagsPaginatorAdapter extends AbstractTagsPaginatorAdapter { public function getSlice(int $offset, int $length): iterable diff --git a/module/Core/src/Tag/Repository/TagRepository.php b/module/Core/src/Tag/Repository/TagRepository.php index c63d461d..a2820e7b 100644 --- a/module/Core/src/Tag/Repository/TagRepository.php +++ b/module/Core/src/Tag/Repository/TagRepository.php @@ -23,6 +23,7 @@ use function Shlinkio\Shlink\Core\camelCaseToSnakeCase; use const PHP_INT_MAX; +/** @extends EntitySpecificationRepository */ class TagRepository extends EntitySpecificationRepository implements TagRepositoryInterface { public function deleteByName(array $names): int diff --git a/module/Core/src/Tag/Repository/TagRepositoryInterface.php b/module/Core/src/Tag/Repository/TagRepositoryInterface.php index 44ecfbf1..ccb33de0 100644 --- a/module/Core/src/Tag/Repository/TagRepositoryInterface.php +++ b/module/Core/src/Tag/Repository/TagRepositoryInterface.php @@ -6,10 +6,12 @@ namespace Shlinkio\Shlink\Core\Tag\Repository; use Doctrine\Persistence\ObjectRepository; use Happyr\DoctrineSpecification\Repository\EntitySpecificationRepositoryInterface; +use Shlinkio\Shlink\Core\Tag\Entity\Tag; use Shlinkio\Shlink\Core\Tag\Model\TagInfo; use Shlinkio\Shlink\Core\Tag\Model\TagsListFiltering; use Shlinkio\Shlink\Rest\Entity\ApiKey; +/** @extends ObjectRepository */ interface TagRepositoryInterface extends ObjectRepository, EntitySpecificationRepositoryInterface { public function deleteByName(array $names): int; diff --git a/module/Core/src/Tag/TagService.php b/module/Core/src/Tag/TagService.php index 36fd0514..de16fada 100644 --- a/module/Core/src/Tag/TagService.php +++ b/module/Core/src/Tag/TagService.php @@ -11,7 +11,6 @@ use Shlinkio\Shlink\Core\Exception\ForbiddenTagOperationException; use Shlinkio\Shlink\Core\Exception\TagConflictException; use Shlinkio\Shlink\Core\Exception\TagNotFoundException; use Shlinkio\Shlink\Core\Tag\Entity\Tag; -use Shlinkio\Shlink\Core\Tag\Model\TagInfo; use Shlinkio\Shlink\Core\Tag\Model\TagRenaming; use Shlinkio\Shlink\Core\Tag\Model\TagsParams; use Shlinkio\Shlink\Core\Tag\Paginator\Adapter\TagsInfoPaginatorAdapter; @@ -20,14 +19,14 @@ use Shlinkio\Shlink\Core\Tag\Repository\TagRepository; use Shlinkio\Shlink\Core\Tag\Repository\TagRepositoryInterface; use Shlinkio\Shlink\Rest\Entity\ApiKey; -class TagService implements TagServiceInterface +readonly class TagService implements TagServiceInterface { - public function __construct(private readonly ORM\EntityManagerInterface $em) + public function __construct(private ORM\EntityManagerInterface $em) { } /** - * @return Tag[]|Paginator + * @inheritDoc */ public function listTags(TagsParams $params, ?ApiKey $apiKey = null): Paginator { @@ -37,7 +36,7 @@ class TagService implements TagServiceInterface } /** - * @return TagInfo[]|Paginator + * @inheritDoc */ public function tagsInfo(TagsParams $params, ?ApiKey $apiKey = null): Paginator { @@ -46,6 +45,11 @@ class TagService implements TagServiceInterface return $this->createPaginator(new TagsInfoPaginatorAdapter($repo, $params, $apiKey), $params); } + /** + * @template T + * @param AdapterInterface $adapter + * @return Paginator + */ private function createPaginator(AdapterInterface $adapter, TagsParams $params): Paginator { return (new Paginator($adapter)) @@ -54,8 +58,7 @@ class TagService implements TagServiceInterface } /** - * @param string[] $tagNames - * @throws ForbiddenTagOperationException + * @inheritDoc */ public function deleteTags(array $tagNames, ?ApiKey $apiKey = null): void { @@ -69,9 +72,7 @@ class TagService implements TagServiceInterface } /** - * @throws TagNotFoundException - * @throws TagConflictException - * @throws ForbiddenTagOperationException + * @inheritDoc */ public function renameTag(TagRenaming $renaming, ?ApiKey $apiKey = null): Tag { diff --git a/module/Core/src/Tag/TagServiceInterface.php b/module/Core/src/Tag/TagServiceInterface.php index c4f8bd3c..60aeb7c7 100644 --- a/module/Core/src/Tag/TagServiceInterface.php +++ b/module/Core/src/Tag/TagServiceInterface.php @@ -17,12 +17,12 @@ use Shlinkio\Shlink\Rest\Entity\ApiKey; interface TagServiceInterface { /** - * @return Tag[]|Paginator + * @return Paginator */ public function listTags(TagsParams $params, ?ApiKey $apiKey = null): Paginator; /** - * @return TagInfo[]|Paginator + * @return Paginator */ public function tagsInfo(TagsParams $params, ?ApiKey $apiKey = null): Paginator; diff --git a/module/Core/src/Visit/Paginator/Adapter/DomainVisitsPaginatorAdapter.php b/module/Core/src/Visit/Paginator/Adapter/DomainVisitsPaginatorAdapter.php index 6d766073..330d8692 100644 --- a/module/Core/src/Visit/Paginator/Adapter/DomainVisitsPaginatorAdapter.php +++ b/module/Core/src/Visit/Paginator/Adapter/DomainVisitsPaginatorAdapter.php @@ -5,19 +5,23 @@ declare(strict_types=1); namespace Shlinkio\Shlink\Core\Visit\Paginator\Adapter; use Shlinkio\Shlink\Core\Paginator\Adapter\AbstractCacheableCountPaginatorAdapter; +use Shlinkio\Shlink\Core\Visit\Entity\Visit; use Shlinkio\Shlink\Core\Visit\Model\VisitsParams; use Shlinkio\Shlink\Core\Visit\Persistence\VisitsCountFiltering; use Shlinkio\Shlink\Core\Visit\Persistence\VisitsListFiltering; use Shlinkio\Shlink\Core\Visit\Repository\VisitRepositoryInterface; use Shlinkio\Shlink\Rest\Entity\ApiKey; +/** + * @extends AbstractCacheableCountPaginatorAdapter + */ class DomainVisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdapter { public function __construct( - private VisitRepositoryInterface $visitRepository, - private string $domain, - private VisitsParams $params, - private ?ApiKey $apiKey, + private readonly VisitRepositoryInterface $visitRepository, + private readonly string $domain, + private readonly VisitsParams $params, + private readonly ?ApiKey $apiKey, ) { } diff --git a/module/Core/src/Visit/Paginator/Adapter/NonOrphanVisitsPaginatorAdapter.php b/module/Core/src/Visit/Paginator/Adapter/NonOrphanVisitsPaginatorAdapter.php index 0d8fecb9..7929bcfd 100644 --- a/module/Core/src/Visit/Paginator/Adapter/NonOrphanVisitsPaginatorAdapter.php +++ b/module/Core/src/Visit/Paginator/Adapter/NonOrphanVisitsPaginatorAdapter.php @@ -5,18 +5,20 @@ declare(strict_types=1); namespace Shlinkio\Shlink\Core\Visit\Paginator\Adapter; use Shlinkio\Shlink\Core\Paginator\Adapter\AbstractCacheableCountPaginatorAdapter; +use Shlinkio\Shlink\Core\Visit\Entity\Visit; use Shlinkio\Shlink\Core\Visit\Model\VisitsParams; use Shlinkio\Shlink\Core\Visit\Persistence\VisitsCountFiltering; use Shlinkio\Shlink\Core\Visit\Persistence\VisitsListFiltering; use Shlinkio\Shlink\Core\Visit\Repository\VisitRepositoryInterface; use Shlinkio\Shlink\Rest\Entity\ApiKey; +/** @extends AbstractCacheableCountPaginatorAdapter */ class NonOrphanVisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdapter { public function __construct( - private VisitRepositoryInterface $repo, - private VisitsParams $params, - private ?ApiKey $apiKey, + private readonly VisitRepositoryInterface $repo, + private readonly VisitsParams $params, + private readonly ?ApiKey $apiKey, ) { } diff --git a/module/Core/src/Visit/Paginator/Adapter/OrphanVisitsPaginatorAdapter.php b/module/Core/src/Visit/Paginator/Adapter/OrphanVisitsPaginatorAdapter.php index 863460a1..9deedf9a 100644 --- a/module/Core/src/Visit/Paginator/Adapter/OrphanVisitsPaginatorAdapter.php +++ b/module/Core/src/Visit/Paginator/Adapter/OrphanVisitsPaginatorAdapter.php @@ -5,12 +5,14 @@ declare(strict_types=1); namespace Shlinkio\Shlink\Core\Visit\Paginator\Adapter; use Shlinkio\Shlink\Core\Paginator\Adapter\AbstractCacheableCountPaginatorAdapter; +use Shlinkio\Shlink\Core\Visit\Entity\Visit; use Shlinkio\Shlink\Core\Visit\Model\OrphanVisitsParams; use Shlinkio\Shlink\Core\Visit\Persistence\OrphanVisitsCountFiltering; use Shlinkio\Shlink\Core\Visit\Persistence\OrphanVisitsListFiltering; use Shlinkio\Shlink\Core\Visit\Repository\VisitRepositoryInterface; use Shlinkio\Shlink\Rest\Entity\ApiKey; +/** @extends AbstractCacheableCountPaginatorAdapter */ class OrphanVisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdapter { public function __construct( diff --git a/module/Core/src/Visit/Paginator/Adapter/ShortUrlVisitsPaginatorAdapter.php b/module/Core/src/Visit/Paginator/Adapter/ShortUrlVisitsPaginatorAdapter.php index 1268d7b3..43bc02ff 100644 --- a/module/Core/src/Visit/Paginator/Adapter/ShortUrlVisitsPaginatorAdapter.php +++ b/module/Core/src/Visit/Paginator/Adapter/ShortUrlVisitsPaginatorAdapter.php @@ -6,19 +6,21 @@ namespace Shlinkio\Shlink\Core\Visit\Paginator\Adapter; use Shlinkio\Shlink\Core\Paginator\Adapter\AbstractCacheableCountPaginatorAdapter; use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlIdentifier; +use Shlinkio\Shlink\Core\Visit\Entity\Visit; use Shlinkio\Shlink\Core\Visit\Model\VisitsParams; use Shlinkio\Shlink\Core\Visit\Persistence\VisitsCountFiltering; use Shlinkio\Shlink\Core\Visit\Persistence\VisitsListFiltering; use Shlinkio\Shlink\Core\Visit\Repository\VisitRepositoryInterface; use Shlinkio\Shlink\Rest\Entity\ApiKey; +/** @extends AbstractCacheableCountPaginatorAdapter */ class ShortUrlVisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdapter { public function __construct( - private VisitRepositoryInterface $visitRepository, - private ShortUrlIdentifier $identifier, - private VisitsParams $params, - private ?ApiKey $apiKey, + private readonly VisitRepositoryInterface $visitRepository, + private readonly ShortUrlIdentifier $identifier, + private readonly VisitsParams $params, + private readonly ?ApiKey $apiKey, ) { } diff --git a/module/Core/src/Visit/Paginator/Adapter/TagVisitsPaginatorAdapter.php b/module/Core/src/Visit/Paginator/Adapter/TagVisitsPaginatorAdapter.php index 30324419..93a182bd 100644 --- a/module/Core/src/Visit/Paginator/Adapter/TagVisitsPaginatorAdapter.php +++ b/module/Core/src/Visit/Paginator/Adapter/TagVisitsPaginatorAdapter.php @@ -5,19 +5,21 @@ declare(strict_types=1); namespace Shlinkio\Shlink\Core\Visit\Paginator\Adapter; use Shlinkio\Shlink\Core\Paginator\Adapter\AbstractCacheableCountPaginatorAdapter; +use Shlinkio\Shlink\Core\Visit\Entity\Visit; use Shlinkio\Shlink\Core\Visit\Model\VisitsParams; use Shlinkio\Shlink\Core\Visit\Persistence\VisitsCountFiltering; use Shlinkio\Shlink\Core\Visit\Persistence\VisitsListFiltering; use Shlinkio\Shlink\Core\Visit\Repository\VisitRepositoryInterface; use Shlinkio\Shlink\Rest\Entity\ApiKey; +/** @extends AbstractCacheableCountPaginatorAdapter */ class TagVisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdapter { public function __construct( - private VisitRepositoryInterface $visitRepository, - private string $tag, - private VisitsParams $params, - private ?ApiKey $apiKey, + private readonly VisitRepositoryInterface $visitRepository, + private readonly string $tag, + private readonly VisitsParams $params, + private readonly ?ApiKey $apiKey, ) { } diff --git a/module/Core/src/Visit/Repository/OrphanVisitsCountRepository.php b/module/Core/src/Visit/Repository/OrphanVisitsCountRepository.php index d5e7670c..628ed2ba 100644 --- a/module/Core/src/Visit/Repository/OrphanVisitsCountRepository.php +++ b/module/Core/src/Visit/Repository/OrphanVisitsCountRepository.php @@ -9,6 +9,7 @@ use Shlinkio\Shlink\Core\Visit\Entity\OrphanVisitsCount; use Shlinkio\Shlink\Core\Visit\Persistence\VisitsCountFiltering; use Shlinkio\Shlink\Rest\ApiKey\Role; +/** @extends EntitySpecificationRepository */ class OrphanVisitsCountRepository extends EntitySpecificationRepository implements OrphanVisitsCountRepositoryInterface { public function countOrphanVisits(VisitsCountFiltering $filtering): int diff --git a/module/Core/src/Visit/Repository/ShortUrlVisitsCountRepository.php b/module/Core/src/Visit/Repository/ShortUrlVisitsCountRepository.php index f07aab33..45ddb1f7 100644 --- a/module/Core/src/Visit/Repository/ShortUrlVisitsCountRepository.php +++ b/module/Core/src/Visit/Repository/ShortUrlVisitsCountRepository.php @@ -5,9 +5,11 @@ declare(strict_types=1); namespace Shlinkio\Shlink\Core\Visit\Repository; use Happyr\DoctrineSpecification\Repository\EntitySpecificationRepository; +use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl; use Shlinkio\Shlink\Core\Visit\Entity\ShortUrlVisitsCount; use Shlinkio\Shlink\Core\Visit\Persistence\VisitsCountFiltering; +/** @extends EntitySpecificationRepository */ class ShortUrlVisitsCountRepository extends EntitySpecificationRepository implements ShortUrlVisitsCountRepositoryInterface { diff --git a/module/Core/src/Visit/Repository/VisitDeleterRepository.php b/module/Core/src/Visit/Repository/VisitDeleterRepository.php index 19f79dc7..94c57091 100644 --- a/module/Core/src/Visit/Repository/VisitDeleterRepository.php +++ b/module/Core/src/Visit/Repository/VisitDeleterRepository.php @@ -8,6 +8,7 @@ use Happyr\DoctrineSpecification\Repository\EntitySpecificationRepository; use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl; use Shlinkio\Shlink\Core\Visit\Entity\Visit; +/** @extends EntitySpecificationRepository */ class VisitDeleterRepository extends EntitySpecificationRepository implements VisitDeleterRepositoryInterface { public function deleteShortUrlVisits(ShortUrl $shortUrl): int diff --git a/module/Core/src/Visit/Repository/VisitIterationRepository.php b/module/Core/src/Visit/Repository/VisitIterationRepository.php index cf342611..71590d7e 100644 --- a/module/Core/src/Visit/Repository/VisitIterationRepository.php +++ b/module/Core/src/Visit/Repository/VisitIterationRepository.php @@ -12,6 +12,7 @@ use Shlinkio\Shlink\Core\Visit\Entity\Visit; /** * Allows iterating large amounts of visits in a memory-efficient way, to use in batch processes + * @extends EntitySpecificationRepository */ class VisitIterationRepository extends EntitySpecificationRepository implements VisitIterationRepositoryInterface { diff --git a/module/Core/src/Visit/Repository/VisitRepository.php b/module/Core/src/Visit/Repository/VisitRepository.php index b86f1463..0708a4e1 100644 --- a/module/Core/src/Visit/Repository/VisitRepository.php +++ b/module/Core/src/Visit/Repository/VisitRepository.php @@ -23,6 +23,7 @@ use Shlinkio\Shlink\Rest\ApiKey\Role; use const PHP_INT_MAX; +/** @extends EntitySpecificationRepository */ class VisitRepository extends EntitySpecificationRepository implements VisitRepositoryInterface { /** diff --git a/module/Core/src/Visit/Repository/VisitRepositoryInterface.php b/module/Core/src/Visit/Repository/VisitRepositoryInterface.php index 9904181b..774e1677 100644 --- a/module/Core/src/Visit/Repository/VisitRepositoryInterface.php +++ b/module/Core/src/Visit/Repository/VisitRepositoryInterface.php @@ -13,6 +13,9 @@ use Shlinkio\Shlink\Core\Visit\Persistence\OrphanVisitsListFiltering; use Shlinkio\Shlink\Core\Visit\Persistence\VisitsCountFiltering; use Shlinkio\Shlink\Core\Visit\Persistence\VisitsListFiltering; +/** + * @extends ObjectRepository + */ interface VisitRepositoryInterface extends ObjectRepository, EntitySpecificationRepositoryInterface { /** diff --git a/module/Core/src/Visit/VisitsStatsHelper.php b/module/Core/src/Visit/VisitsStatsHelper.php index 65d9a1c8..7f3e2282 100644 --- a/module/Core/src/Visit/VisitsStatsHelper.php +++ b/module/Core/src/Visit/VisitsStatsHelper.php @@ -63,8 +63,7 @@ readonly class VisitsStatsHelper implements VisitsStatsHelperInterface } /** - * @return Visit[]|Paginator - * @throws ShortUrlNotFoundException + * @inheritDoc */ public function visitsForShortUrl( ShortUrlIdentifier $identifier, @@ -87,8 +86,7 @@ readonly class VisitsStatsHelper implements VisitsStatsHelperInterface } /** - * @return Visit[]|Paginator - * @throws TagNotFoundException + * @inheritDoc */ public function visitsForTag(string $tag, VisitsParams $params, ?ApiKey $apiKey = null): Paginator { @@ -105,8 +103,7 @@ readonly class VisitsStatsHelper implements VisitsStatsHelperInterface } /** - * @return Visit[]|Paginator - * @throws DomainNotFoundException + * @inheritDoc */ public function visitsForDomain(string $domain, VisitsParams $params, ?ApiKey $apiKey = null): Paginator { @@ -123,7 +120,7 @@ readonly class VisitsStatsHelper implements VisitsStatsHelperInterface } /** - * @return Visit[]|Paginator + * @inheritDoc */ public function orphanVisits(OrphanVisitsParams $params, ?ApiKey $apiKey = null): Paginator { @@ -141,6 +138,10 @@ readonly class VisitsStatsHelper implements VisitsStatsHelperInterface return $this->createPaginator(new NonOrphanVisitsPaginatorAdapter($repo, $params, $apiKey), $params); } + /** + * @param AdapterInterface $adapter + * @return Paginator + */ private function createPaginator(AdapterInterface $adapter, VisitsParams $params): Paginator { $paginator = new Paginator($adapter); diff --git a/module/Core/src/Visit/VisitsStatsHelperInterface.php b/module/Core/src/Visit/VisitsStatsHelperInterface.php index 265174ed..87e0980b 100644 --- a/module/Core/src/Visit/VisitsStatsHelperInterface.php +++ b/module/Core/src/Visit/VisitsStatsHelperInterface.php @@ -20,7 +20,7 @@ interface VisitsStatsHelperInterface public function getVisitsStats(?ApiKey $apiKey = null): VisitsStats; /** - * @return Visit[]|Paginator + * @return Paginator * @throws ShortUrlNotFoundException */ public function visitsForShortUrl( @@ -30,24 +30,24 @@ interface VisitsStatsHelperInterface ): Paginator; /** - * @return Visit[]|Paginator + * @return Paginator * @throws TagNotFoundException */ public function visitsForTag(string $tag, VisitsParams $params, ?ApiKey $apiKey = null): Paginator; /** - * @return Visit[]|Paginator + * @return Paginator * @throws DomainNotFoundException */ public function visitsForDomain(string $domain, VisitsParams $params, ?ApiKey $apiKey = null): Paginator; /** - * @return Visit[]|Paginator + * @return Paginator */ public function orphanVisits(OrphanVisitsParams $params, ?ApiKey $apiKey = null): Paginator; /** - * @return Visit[]|Paginator + * @return Paginator */ public function nonOrphanVisits(VisitsParams $params, ?ApiKey $apiKey = null): Paginator; } diff --git a/module/Core/test-db/Visit/Listener/OrphanVisitsCountTrackerTest.php b/module/Core/test-db/Visit/Listener/OrphanVisitsCountTrackerTest.php index 20302c75..ad8edcd2 100644 --- a/module/Core/test-db/Visit/Listener/OrphanVisitsCountTrackerTest.php +++ b/module/Core/test-db/Visit/Listener/OrphanVisitsCountTrackerTest.php @@ -4,11 +4,11 @@ declare(strict_types=1); namespace ShlinkioDbTest\Shlink\Core\Visit\Listener; -use Doctrine\ORM\EntityRepository; use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\Core\Visit\Entity\OrphanVisitsCount; use Shlinkio\Shlink\Core\Visit\Entity\Visit; use Shlinkio\Shlink\Core\Visit\Model\Visitor; +use Shlinkio\Shlink\Core\Visit\Repository\OrphanVisitsCountRepository; use Shlinkio\Shlink\TestUtils\DbTest\DatabaseTestCase; use function array_filter; @@ -16,7 +16,7 @@ use function array_values; class OrphanVisitsCountTrackerTest extends DatabaseTestCase { - private EntityRepository $repo; + private OrphanVisitsCountRepository $repo; protected function setUp(): void { diff --git a/module/Core/test-db/Visit/Listener/ShortUrlVisitsCountTrackerTest.php b/module/Core/test-db/Visit/Listener/ShortUrlVisitsCountTrackerTest.php index 29f5d5d1..7a2a6c29 100644 --- a/module/Core/test-db/Visit/Listener/ShortUrlVisitsCountTrackerTest.php +++ b/module/Core/test-db/Visit/Listener/ShortUrlVisitsCountTrackerTest.php @@ -4,12 +4,12 @@ declare(strict_types=1); namespace ShlinkioDbTest\Shlink\Core\Visit\Listener; -use Doctrine\ORM\EntityRepository; use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl; use Shlinkio\Shlink\Core\Visit\Entity\ShortUrlVisitsCount; use Shlinkio\Shlink\Core\Visit\Entity\Visit; use Shlinkio\Shlink\Core\Visit\Model\Visitor; +use Shlinkio\Shlink\Core\Visit\Repository\ShortUrlVisitsCountRepository; use Shlinkio\Shlink\TestUtils\DbTest\DatabaseTestCase; use function array_filter; @@ -17,7 +17,7 @@ use function array_values; class ShortUrlVisitsCountTrackerTest extends DatabaseTestCase { - private EntityRepository $repo; + private ShortUrlVisitsCountRepository $repo; protected function setUp(): void { diff --git a/module/Core/test/RedirectRule/Entity/ShortUrlRedirectRuleTest.php b/module/Core/test/RedirectRule/Entity/ShortUrlRedirectRuleTest.php index dc19dcd3..d55f13ac 100644 --- a/module/Core/test/RedirectRule/Entity/ShortUrlRedirectRuleTest.php +++ b/module/Core/test/RedirectRule/Entity/ShortUrlRedirectRuleTest.php @@ -104,7 +104,7 @@ class ShortUrlRedirectRuleTest extends TestCase } /** - * @param ArrayCollection $conditions + * @param ArrayCollection $conditions */ private function createRule(ArrayCollection $conditions): ShortUrlRedirectRule { diff --git a/module/Core/test/ShortUrl/Helper/ShortUrlTitleResolutionHelperTest.php b/module/Core/test/ShortUrl/Helper/ShortUrlTitleResolutionHelperTest.php index 92fac8eb..4e3056b3 100644 --- a/module/Core/test/ShortUrl/Helper/ShortUrlTitleResolutionHelperTest.php +++ b/module/Core/test/ShortUrl/Helper/ShortUrlTitleResolutionHelperTest.php @@ -103,6 +103,9 @@ class ShortUrlTitleResolutionHelperTest extends TestCase self::assertEquals('Resolved "title"', $result->title); } + /** + * @return InvocationMocker + */ private function expectRequestToBeCalled(): InvocationMocker { return $this->httpClient->expects($this->once())->method('request')->with( diff --git a/module/Rest/src/ApiKey/Repository/ApiKeyRepository.php b/module/Rest/src/ApiKey/Repository/ApiKeyRepository.php index ad09b22d..2b7aa0a2 100644 --- a/module/Rest/src/ApiKey/Repository/ApiKeyRepository.php +++ b/module/Rest/src/ApiKey/Repository/ApiKeyRepository.php @@ -9,6 +9,9 @@ use Happyr\DoctrineSpecification\Repository\EntitySpecificationRepository; use Shlinkio\Shlink\Rest\ApiKey\Model\ApiKeyMeta; use Shlinkio\Shlink\Rest\Entity\ApiKey; +/** + * @extends EntitySpecificationRepository + */ class ApiKeyRepository extends EntitySpecificationRepository implements ApiKeyRepositoryInterface { /** diff --git a/module/Rest/src/ApiKey/Repository/ApiKeyRepositoryInterface.php b/module/Rest/src/ApiKey/Repository/ApiKeyRepositoryInterface.php index a557e603..57c2a7f6 100644 --- a/module/Rest/src/ApiKey/Repository/ApiKeyRepositoryInterface.php +++ b/module/Rest/src/ApiKey/Repository/ApiKeyRepositoryInterface.php @@ -8,6 +8,9 @@ use Doctrine\Persistence\ObjectRepository; use Happyr\DoctrineSpecification\Repository\EntitySpecificationRepositoryInterface; use Shlinkio\Shlink\Rest\Entity\ApiKey; +/** + * @extends ObjectRepository + */ interface ApiKeyRepositoryInterface extends ObjectRepository, EntitySpecificationRepositoryInterface { /** diff --git a/phpstan.neon b/phpstan.neon index 691b951a..7e21a038 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -12,5 +12,4 @@ parameters: ignoreErrors: - '#should return int<0, max> but returns int#' - '#expects -1\|int<1, max>, int given#' - - identifier: missingType.generics - identifier: missingType.iterableValue