mirror of
https://github.com/shlinkio/shlink.git
synced 2024-12-27 17:31:20 -06:00
Merge pull request #2168 from acelaya-forks/feature/update-common
Update to latest shlink-common and remove deprecation references
This commit is contained in:
commit
c10f0db170
@ -44,7 +44,7 @@
|
|||||||
"pagerfanta/core": "^3.8",
|
"pagerfanta/core": "^3.8",
|
||||||
"ramsey/uuid": "^4.7",
|
"ramsey/uuid": "^4.7",
|
||||||
"shlinkio/doctrine-specification": "^2.1.1",
|
"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-config": "^3.0",
|
||||||
"shlinkio/shlink-event-dispatcher": "^4.1",
|
"shlinkio/shlink-event-dispatcher": "^4.1",
|
||||||
"shlinkio/shlink-importer": "^5.3.2",
|
"shlinkio/shlink-importer": "^5.3.2",
|
||||||
|
@ -77,7 +77,7 @@ services:
|
|||||||
|
|
||||||
shlink_db_postgres:
|
shlink_db_postgres:
|
||||||
container_name: shlink_db_postgres
|
container_name: shlink_db_postgres
|
||||||
image: postgres:12.2-alpine
|
image: postgres:16.3-alpine
|
||||||
ports:
|
ports:
|
||||||
- "5434:5432"
|
- "5434:5432"
|
||||||
volumes:
|
volumes:
|
||||||
|
@ -33,6 +33,9 @@ class GetDomainVisitsCommand extends AbstractVisitsListCommand
|
|||||||
->addArgument('domain', InputArgument::REQUIRED, 'The domain which visits we want to get.');
|
->addArgument('domain', InputArgument::REQUIRED, 'The domain which visits we want to get.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Paginator<Visit>
|
||||||
|
*/
|
||||||
protected function getVisitsPaginator(InputInterface $input, DateRange $dateRange): Paginator
|
protected function getVisitsPaginator(InputInterface $input, DateRange $dateRange): Paginator
|
||||||
{
|
{
|
||||||
$domain = $input->getArgument('domain');
|
$domain = $input->getArgument('domain');
|
||||||
|
@ -46,6 +46,9 @@ class GetShortUrlVisitsCommand extends AbstractVisitsListCommand
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Paginator<Visit>
|
||||||
|
*/
|
||||||
protected function getVisitsPaginator(InputInterface $input, DateRange $dateRange): Paginator
|
protected function getVisitsPaginator(InputInterface $input, DateRange $dateRange): Paginator
|
||||||
{
|
{
|
||||||
$identifier = $this->shortUrlIdentifierInput->toShortUrlIdentifier($input);
|
$identifier = $this->shortUrlIdentifierInput->toShortUrlIdentifier($input);
|
||||||
|
@ -9,14 +9,14 @@ use Shlinkio\Shlink\CLI\Input\StartDateOption;
|
|||||||
use Shlinkio\Shlink\CLI\Util\ExitCode;
|
use Shlinkio\Shlink\CLI\Util\ExitCode;
|
||||||
use Shlinkio\Shlink\CLI\Util\ShlinkTable;
|
use Shlinkio\Shlink\CLI\Util\ShlinkTable;
|
||||||
use Shlinkio\Shlink\Common\Paginator\Paginator;
|
use Shlinkio\Shlink\Common\Paginator\Paginator;
|
||||||
use Shlinkio\Shlink\Common\Paginator\Util\PagerfantaUtilsTrait;
|
use Shlinkio\Shlink\Common\Paginator\Util\PagerfantaUtils;
|
||||||
use Shlinkio\Shlink\Common\Rest\DataTransformerInterface;
|
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
|
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlsParams;
|
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlsParams;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlWithVisitsSummary;
|
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlWithVisitsSummary;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Model\TagsMode;
|
use Shlinkio\Shlink\Core\ShortUrl\Model\TagsMode;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Model\Validation\ShortUrlsParamsInputFilter;
|
use Shlinkio\Shlink\Core\ShortUrl\Model\Validation\ShortUrlsParamsInputFilter;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\ShortUrlListServiceInterface;
|
use Shlinkio\Shlink\Core\ShortUrl\ShortUrlListServiceInterface;
|
||||||
|
use Shlinkio\Shlink\Core\ShortUrl\Transformer\ShortUrlDataTransformerInterface;
|
||||||
use Symfony\Component\Console\Command\Command;
|
use Symfony\Component\Console\Command\Command;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
@ -32,8 +32,6 @@ use function sprintf;
|
|||||||
|
|
||||||
class ListShortUrlsCommand extends Command
|
class ListShortUrlsCommand extends Command
|
||||||
{
|
{
|
||||||
use PagerfantaUtilsTrait;
|
|
||||||
|
|
||||||
public const NAME = 'short-url:list';
|
public const NAME = 'short-url:list';
|
||||||
|
|
||||||
private readonly StartDateOption $startDateOption;
|
private readonly StartDateOption $startDateOption;
|
||||||
@ -41,7 +39,7 @@ class ListShortUrlsCommand extends Command
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly ShortUrlListServiceInterface $shortUrlService,
|
private readonly ShortUrlListServiceInterface $shortUrlService,
|
||||||
private readonly DataTransformerInterface $transformer,
|
private readonly ShortUrlDataTransformerInterface $transformer,
|
||||||
) {
|
) {
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->startDateOption = new StartDateOption($this, 'short URLs');
|
$this->startDateOption = new StartDateOption($this, 'short URLs');
|
||||||
@ -179,6 +177,7 @@ class ListShortUrlsCommand extends Command
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array<string, callable(array $serializedShortUrl, ShortUrl $shortUrl): ?string> $columnsMap
|
* @param array<string, callable(array $serializedShortUrl, ShortUrl $shortUrl): ?string> $columnsMap
|
||||||
|
* @return Paginator<ShortUrlWithVisitsSummary>
|
||||||
*/
|
*/
|
||||||
private function renderPage(
|
private function renderPage(
|
||||||
OutputInterface $output,
|
OutputInterface $output,
|
||||||
@ -196,7 +195,7 @@ class ListShortUrlsCommand extends Command
|
|||||||
ShlinkTable::default($output)->render(
|
ShlinkTable::default($output)->render(
|
||||||
array_keys($columnsMap),
|
array_keys($columnsMap),
|
||||||
$rows,
|
$rows,
|
||||||
$all ? null : $this->formatCurrentPageMessage($shortUrls, 'Page %s of %s'),
|
$all ? null : PagerfantaUtils::formatCurrentPageMessage($shortUrls, 'Page %s of %s'),
|
||||||
);
|
);
|
||||||
|
|
||||||
return $shortUrls;
|
return $shortUrls;
|
||||||
|
@ -33,6 +33,9 @@ class GetTagVisitsCommand extends AbstractVisitsListCommand
|
|||||||
->addArgument('tag', InputArgument::REQUIRED, 'The tag which visits we want to get.');
|
->addArgument('tag', InputArgument::REQUIRED, 'The tag which visits we want to get.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Paginator<Visit>
|
||||||
|
*/
|
||||||
protected function getVisitsPaginator(InputInterface $input, DateRange $dateRange): Paginator
|
protected function getVisitsPaginator(InputInterface $input, DateRange $dateRange): Paginator
|
||||||
{
|
{
|
||||||
$tag = $input->getArgument('tag');
|
$tag = $input->getArgument('tag');
|
||||||
|
@ -46,6 +46,9 @@ abstract class AbstractVisitsListCommand extends Command
|
|||||||
return ExitCode::EXIT_SUCCESS;
|
return ExitCode::EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Paginator<Visit> $paginator
|
||||||
|
*/
|
||||||
private function resolveRowsAndHeaders(Paginator $paginator): array
|
private function resolveRowsAndHeaders(Paginator $paginator): array
|
||||||
{
|
{
|
||||||
$extraKeys = [];
|
$extraKeys = [];
|
||||||
@ -74,6 +77,9 @@ abstract class AbstractVisitsListCommand extends Command
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Paginator<Visit>
|
||||||
|
*/
|
||||||
abstract protected function getVisitsPaginator(InputInterface $input, DateRange $dateRange): Paginator;
|
abstract protected function getVisitsPaginator(InputInterface $input, DateRange $dateRange): Paginator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,6 +30,9 @@ class GetNonOrphanVisitsCommand extends AbstractVisitsListCommand
|
|||||||
->setDescription('Returns the list of non-orphan visits.');
|
->setDescription('Returns the list of non-orphan visits.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Paginator<Visit>
|
||||||
|
*/
|
||||||
protected function getVisitsPaginator(InputInterface $input, DateRange $dateRange): Paginator
|
protected function getVisitsPaginator(InputInterface $input, DateRange $dateRange): Paginator
|
||||||
{
|
{
|
||||||
return $this->visitsHelper->nonOrphanVisits(new VisitsParams($dateRange));
|
return $this->visitsHelper->nonOrphanVisits(new VisitsParams($dateRange));
|
||||||
|
@ -30,6 +30,9 @@ class GetOrphanVisitsCommand extends AbstractVisitsListCommand
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Paginator<Visit>
|
||||||
|
*/
|
||||||
protected function getVisitsPaginator(InputInterface $input, DateRange $dateRange): Paginator
|
protected function getVisitsPaginator(InputInterface $input, DateRange $dateRange): Paginator
|
||||||
{
|
{
|
||||||
$rawType = $input->getOption('type');
|
$rawType = $input->getOption('type');
|
||||||
|
@ -7,6 +7,7 @@ namespace ShlinkioTest\Shlink\CLI\Command\Db;
|
|||||||
use Doctrine\DBAL\Connection;
|
use Doctrine\DBAL\Connection;
|
||||||
use Doctrine\DBAL\Driver;
|
use Doctrine\DBAL\Driver;
|
||||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||||
|
use Doctrine\DBAL\Platforms\SQLitePlatform;
|
||||||
use Doctrine\DBAL\Schema\AbstractSchemaManager;
|
use Doctrine\DBAL\Schema\AbstractSchemaManager;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||||
@ -31,6 +32,7 @@ class CreateDatabaseCommandTest extends TestCase
|
|||||||
private MockObject & ProcessRunnerInterface $processHelper;
|
private MockObject & ProcessRunnerInterface $processHelper;
|
||||||
private MockObject & Connection $regularConn;
|
private MockObject & Connection $regularConn;
|
||||||
private MockObject & ClassMetadataFactory $metadataFactory;
|
private MockObject & ClassMetadataFactory $metadataFactory;
|
||||||
|
/** @var MockObject&AbstractSchemaManager<SQLitePlatform> */
|
||||||
private MockObject & AbstractSchemaManager $schemaManager;
|
private MockObject & AbstractSchemaManager $schemaManager;
|
||||||
private MockObject & Driver $driver;
|
private MockObject & Driver $driver;
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ use Shlinkio\Shlink\Core\ShortUrl\Spec\BelongsToApiKey;
|
|||||||
use Shlinkio\Shlink\Rest\ApiKey\Role;
|
use Shlinkio\Shlink\Rest\ApiKey\Role;
|
||||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||||
|
|
||||||
|
/** @extends EntitySpecificationRepository<Domain> */
|
||||||
class DomainRepository extends EntitySpecificationRepository implements DomainRepositoryInterface
|
class DomainRepository extends EntitySpecificationRepository implements DomainRepositoryInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -9,6 +9,7 @@ use Happyr\DoctrineSpecification\Repository\EntitySpecificationRepositoryInterfa
|
|||||||
use Shlinkio\Shlink\Core\Domain\Entity\Domain;
|
use Shlinkio\Shlink\Core\Domain\Entity\Domain;
|
||||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||||
|
|
||||||
|
/** @extends ObjectRepository<Domain> */
|
||||||
interface DomainRepositoryInterface extends ObjectRepository, EntitySpecificationRepositoryInterface
|
interface DomainRepositoryInterface extends ObjectRepository, EntitySpecificationRepositoryInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -8,6 +8,7 @@ use Laminas\InputFilter\InputFilter;
|
|||||||
use Shlinkio\Shlink\Common\Validation\HostAndPortValidator;
|
use Shlinkio\Shlink\Common\Validation\HostAndPortValidator;
|
||||||
use Shlinkio\Shlink\Common\Validation\InputFactory;
|
use Shlinkio\Shlink\Common\Validation\InputFactory;
|
||||||
|
|
||||||
|
/** @extends InputFilter<mixed> */
|
||||||
class DomainRedirectsInputFilter extends InputFilter
|
class DomainRedirectsInputFilter extends InputFilter
|
||||||
{
|
{
|
||||||
public const DOMAIN = 'domain';
|
public const DOMAIN = 'domain';
|
||||||
|
@ -4,21 +4,21 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Shlinkio\Shlink\Core\EventDispatcher;
|
namespace Shlinkio\Shlink\Core\EventDispatcher;
|
||||||
|
|
||||||
use Shlinkio\Shlink\Common\Rest\DataTransformerInterface;
|
|
||||||
use Shlinkio\Shlink\Common\UpdatePublishing\Update;
|
use Shlinkio\Shlink\Common\UpdatePublishing\Update;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
|
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
|
||||||
|
use Shlinkio\Shlink\Core\ShortUrl\Transformer\ShortUrlDataTransformerInterface;
|
||||||
use Shlinkio\Shlink\Core\Visit\Entity\Visit;
|
use Shlinkio\Shlink\Core\Visit\Entity\Visit;
|
||||||
|
|
||||||
final readonly class PublishingUpdatesGenerator implements PublishingUpdatesGeneratorInterface
|
final readonly class PublishingUpdatesGenerator implements PublishingUpdatesGeneratorInterface
|
||||||
{
|
{
|
||||||
public function __construct(private DataTransformerInterface $shortUrlTransformer)
|
public function __construct(private ShortUrlDataTransformerInterface $shortUrlTransformer)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public function newVisitUpdate(Visit $visit): Update
|
public function newVisitUpdate(Visit $visit): Update
|
||||||
{
|
{
|
||||||
return Update::forTopicAndPayload(Topic::NEW_VISIT->value, [
|
return Update::forTopicAndPayload(Topic::NEW_VISIT->value, [
|
||||||
'shortUrl' => $this->shortUrlTransformer->transform($visit->shortUrl),
|
'shortUrl' => $this->transformShortUrl($visit->shortUrl),
|
||||||
'visit' => $visit->jsonSerialize(),
|
'visit' => $visit->jsonSerialize(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@ -36,7 +36,7 @@ final readonly class PublishingUpdatesGenerator implements PublishingUpdatesGene
|
|||||||
$topic = Topic::newShortUrlVisit($shortUrl?->getShortCode());
|
$topic = Topic::newShortUrlVisit($shortUrl?->getShortCode());
|
||||||
|
|
||||||
return Update::forTopicAndPayload($topic, [
|
return Update::forTopicAndPayload($topic, [
|
||||||
'shortUrl' => $this->shortUrlTransformer->transform($shortUrl),
|
'shortUrl' => $this->transformShortUrl($shortUrl),
|
||||||
'visit' => $visit->jsonSerialize(),
|
'visit' => $visit->jsonSerialize(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@ -47,4 +47,9 @@ final readonly class PublishingUpdatesGenerator implements PublishingUpdatesGene
|
|||||||
'shortUrl' => $this->shortUrlTransformer->transform($shortUrl),
|
'shortUrl' => $this->shortUrlTransformer->transform($shortUrl),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function transformShortUrl(?ShortUrl $shortUrl): array
|
||||||
|
{
|
||||||
|
return $shortUrl === null ? [] : $this->shortUrlTransformer->transform($shortUrl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,9 @@ class ValidationException extends InvalidArgumentException implements ProblemDet
|
|||||||
|
|
||||||
private array $invalidElements;
|
private array $invalidElements;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param InputFilterInterface<mixed> $inputFilter
|
||||||
|
*/
|
||||||
public static function fromInputFilter(InputFilterInterface $inputFilter, ?Throwable $prev = null): self
|
public static function fromInputFilter(InputFilterInterface $inputFilter, ?Throwable $prev = null): self
|
||||||
{
|
{
|
||||||
return static::fromArray($inputFilter->getMessages(), $prev);
|
return static::fromArray($inputFilter->getMessages(), $prev);
|
||||||
|
@ -6,6 +6,10 @@ namespace Shlinkio\Shlink\Core\Paginator\Adapter;
|
|||||||
|
|
||||||
use Pagerfanta\Adapter\AdapterInterface;
|
use Pagerfanta\Adapter\AdapterInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @template T
|
||||||
|
* @implements AdapterInterface<T>
|
||||||
|
*/
|
||||||
abstract class AbstractCacheableCountPaginatorAdapter implements AdapterInterface
|
abstract class AbstractCacheableCountPaginatorAdapter implements AdapterInterface
|
||||||
{
|
{
|
||||||
private ?int $count = null;
|
private ?int $count = null;
|
||||||
|
@ -17,6 +17,7 @@ use Shlinkio\Shlink\Core\Util\IpAddressUtils;
|
|||||||
use function Shlinkio\Shlink\Core\ArrayUtils\contains;
|
use function Shlinkio\Shlink\Core\ArrayUtils\contains;
|
||||||
use function Shlinkio\Shlink\Core\enumValues;
|
use function Shlinkio\Shlink\Core\enumValues;
|
||||||
|
|
||||||
|
/** @extends InputFilter<mixed> */
|
||||||
class RedirectRulesInputFilter extends InputFilter
|
class RedirectRulesInputFilter extends InputFilter
|
||||||
{
|
{
|
||||||
public const REDIRECT_RULES = 'redirectRules';
|
public const REDIRECT_RULES = 'redirectRules';
|
||||||
@ -44,6 +45,9 @@ class RedirectRulesInputFilter extends InputFilter
|
|||||||
return $instance;
|
return $instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return InputFilter<mixed>
|
||||||
|
*/
|
||||||
private static function createRedirectRuleInputFilter(): InputFilter
|
private static function createRedirectRuleInputFilter(): InputFilter
|
||||||
{
|
{
|
||||||
$redirectRuleInputFilter = new InputFilter();
|
$redirectRuleInputFilter = new InputFilter();
|
||||||
@ -60,6 +64,9 @@ class RedirectRulesInputFilter extends InputFilter
|
|||||||
return $redirectRuleInputFilter;
|
return $redirectRuleInputFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return InputFilter<mixed>
|
||||||
|
*/
|
||||||
private static function createRedirectConditionInputFilter(): InputFilter
|
private static function createRedirectConditionInputFilter(): InputFilter
|
||||||
{
|
{
|
||||||
$redirectConditionInputFilter = new InputFilter();
|
$redirectConditionInputFilter = new InputFilter();
|
||||||
|
@ -37,8 +37,8 @@ class ShortUrl extends AbstractEntity
|
|||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param Collection<int, Tag> $tags
|
* @param Collection<int, Tag> $tags
|
||||||
* @param Collection<int, Visit> & Selectable $visits
|
* @param Collection<int, Visit> & Selectable<int, Visit> $visits
|
||||||
* @param Collection<int, ShortUrlVisitsCount> & Selectable $visitsCounts
|
* @param Collection<int, ShortUrlVisitsCount> & Selectable<int, ShortUrlVisitsCount> $visitsCounts
|
||||||
*/
|
*/
|
||||||
private function __construct(
|
private function __construct(
|
||||||
private string $longUrl,
|
private string $longUrl,
|
||||||
@ -213,7 +213,7 @@ class ShortUrl extends AbstractEntity
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Collection<int, Visit> & Selectable $visits
|
* @param Collection<int, Visit> & Selectable<int, Visit> $visits
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
public function setVisits(Collection & Selectable $visits): self
|
public function setVisits(Collection & Selectable $visits): self
|
||||||
|
@ -20,6 +20,7 @@ use function substr;
|
|||||||
use const Shlinkio\Shlink\LOOSE_URI_MATCHER;
|
use const Shlinkio\Shlink\LOOSE_URI_MATCHER;
|
||||||
use const Shlinkio\Shlink\MIN_SHORT_CODES_LENGTH;
|
use const Shlinkio\Shlink\MIN_SHORT_CODES_LENGTH;
|
||||||
|
|
||||||
|
/** @extends InputFilter<mixed> */
|
||||||
class ShortUrlInputFilter extends InputFilter
|
class ShortUrlInputFilter extends InputFilter
|
||||||
{
|
{
|
||||||
// Fields for creation only
|
// Fields for creation only
|
||||||
|
@ -13,6 +13,7 @@ use Shlinkio\Shlink\Core\ShortUrl\Model\TagsMode;
|
|||||||
|
|
||||||
use function Shlinkio\Shlink\Core\enumValues;
|
use function Shlinkio\Shlink\Core\enumValues;
|
||||||
|
|
||||||
|
/** @extends InputFilter<mixed> */
|
||||||
class ShortUrlsParamsInputFilter extends InputFilter
|
class ShortUrlsParamsInputFilter extends InputFilter
|
||||||
{
|
{
|
||||||
public const PAGE = 'page';
|
public const PAGE = 'page';
|
||||||
|
@ -6,11 +6,13 @@ namespace Shlinkio\Shlink\Core\ShortUrl\Paginator\Adapter;
|
|||||||
|
|
||||||
use Pagerfanta\Adapter\AdapterInterface;
|
use Pagerfanta\Adapter\AdapterInterface;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlsParams;
|
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\ShortUrlsCountFiltering;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Persistence\ShortUrlsListFiltering;
|
use Shlinkio\Shlink\Core\ShortUrl\Persistence\ShortUrlsListFiltering;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Repository\ShortUrlListRepositoryInterface;
|
use Shlinkio\Shlink\Core\ShortUrl\Repository\ShortUrlListRepositoryInterface;
|
||||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||||
|
|
||||||
|
/** @implements AdapterInterface<ShortUrlWithVisitsSummary> */
|
||||||
readonly class ShortUrlRepositoryAdapter implements AdapterInterface
|
readonly class ShortUrlRepositoryAdapter implements AdapterInterface
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
|
@ -7,6 +7,7 @@ namespace Shlinkio\Shlink\Core\ShortUrl\Repository;
|
|||||||
use Happyr\DoctrineSpecification\Repository\EntitySpecificationRepository;
|
use Happyr\DoctrineSpecification\Repository\EntitySpecificationRepository;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
|
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
|
||||||
|
|
||||||
|
/** @extends EntitySpecificationRepository<ShortUrl> */
|
||||||
class CrawlableShortCodesQuery extends EntitySpecificationRepository implements CrawlableShortCodesQueryInterface
|
class CrawlableShortCodesQuery extends EntitySpecificationRepository implements CrawlableShortCodesQueryInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -13,6 +13,7 @@ use Shlinkio\Shlink\Core\Visit\Entity\ShortUrlVisitsCount;
|
|||||||
|
|
||||||
use function sprintf;
|
use function sprintf;
|
||||||
|
|
||||||
|
/** @extends EntitySpecificationRepository<ShortUrl> */
|
||||||
class ExpiredShortUrlsRepository extends EntitySpecificationRepository implements ExpiredShortUrlsRepositoryInterface
|
class ExpiredShortUrlsRepository extends EntitySpecificationRepository implements ExpiredShortUrlsRepositoryInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -20,6 +20,7 @@ use Shlinkio\Shlink\Core\Visit\Entity\ShortUrlVisitsCount;
|
|||||||
use function Shlinkio\Shlink\Core\ArrayUtils\map;
|
use function Shlinkio\Shlink\Core\ArrayUtils\map;
|
||||||
use function sprintf;
|
use function sprintf;
|
||||||
|
|
||||||
|
/** @extends EntitySpecificationRepository<ShortUrl> */
|
||||||
class ShortUrlListRepository extends EntitySpecificationRepository implements ShortUrlListRepositoryInterface
|
class ShortUrlListRepository extends EntitySpecificationRepository implements ShortUrlListRepositoryInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -20,6 +20,7 @@ use Shlinkio\Shlink\Importer\Model\ImportedShlinkUrl;
|
|||||||
use function count;
|
use function count;
|
||||||
use function strtolower;
|
use function strtolower;
|
||||||
|
|
||||||
|
/** @extends EntitySpecificationRepository<ShortUrl> */
|
||||||
class ShortUrlRepository extends EntitySpecificationRepository implements ShortUrlRepositoryInterface
|
class ShortUrlRepository extends EntitySpecificationRepository implements ShortUrlRepositoryInterface
|
||||||
{
|
{
|
||||||
public function findOneWithDomainFallback(ShortUrlIdentifier $identifier, ShortUrlMode $shortUrlMode): ?ShortUrl
|
public function findOneWithDomainFallback(ShortUrlIdentifier $identifier, ShortUrlMode $shortUrlMode): ?ShortUrl
|
||||||
|
@ -13,6 +13,7 @@ use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlIdentifier;
|
|||||||
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlMode;
|
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlMode;
|
||||||
use Shlinkio\Shlink\Importer\Model\ImportedShlinkUrl;
|
use Shlinkio\Shlink\Importer\Model\ImportedShlinkUrl;
|
||||||
|
|
||||||
|
/** @extends ObjectRepository<ShortUrl> */
|
||||||
interface ShortUrlRepositoryInterface extends ObjectRepository, EntitySpecificationRepositoryInterface
|
interface ShortUrlRepositoryInterface extends ObjectRepository, EntitySpecificationRepositoryInterface
|
||||||
{
|
{
|
||||||
public function findOneWithDomainFallback(ShortUrlIdentifier $identifier, ShortUrlMode $shortUrlMode): ?ShortUrl;
|
public function findOneWithDomainFallback(ShortUrlIdentifier $identifier, ShortUrlMode $shortUrlMode): ?ShortUrl;
|
||||||
|
@ -7,7 +7,6 @@ namespace Shlinkio\Shlink\Core\ShortUrl;
|
|||||||
use Shlinkio\Shlink\Common\Paginator\Paginator;
|
use Shlinkio\Shlink\Common\Paginator\Paginator;
|
||||||
use Shlinkio\Shlink\Core\Options\UrlShortenerOptions;
|
use Shlinkio\Shlink\Core\Options\UrlShortenerOptions;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlsParams;
|
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\Paginator\Adapter\ShortUrlRepositoryAdapter;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Repository\ShortUrlListRepositoryInterface;
|
use Shlinkio\Shlink\Core\ShortUrl\Repository\ShortUrlListRepositoryInterface;
|
||||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
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
|
public function listShortUrls(ShortUrlsParams $params, ?ApiKey $apiKey = null): Paginator
|
||||||
{
|
{
|
||||||
|
@ -12,7 +12,7 @@ use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
|||||||
interface ShortUrlListServiceInterface
|
interface ShortUrlListServiceInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @return ShortUrlWithVisitsSummary[]|Paginator
|
* @return Paginator<ShortUrlWithVisitsSummary>
|
||||||
*/
|
*/
|
||||||
public function listShortUrls(ShortUrlsParams $params, ?ApiKey $apiKey = null): Paginator;
|
public function listShortUrls(ShortUrlsParams $params, ?ApiKey $apiKey = null): Paginator;
|
||||||
}
|
}
|
||||||
|
@ -4,24 +4,17 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Shlinkio\Shlink\Core\ShortUrl\Transformer;
|
namespace Shlinkio\Shlink\Core\ShortUrl\Transformer;
|
||||||
|
|
||||||
use Shlinkio\Shlink\Common\Rest\DataTransformerInterface;
|
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
|
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortUrlStringifierInterface;
|
use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortUrlStringifierInterface;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlWithVisitsSummary;
|
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlWithVisitsSummary;
|
||||||
|
|
||||||
/**
|
readonly class ShortUrlDataTransformer implements ShortUrlDataTransformerInterface
|
||||||
* @fixme Do not implement DataTransformerInterface, but a separate interface
|
|
||||||
*/
|
|
||||||
readonly class ShortUrlDataTransformer implements DataTransformerInterface
|
|
||||||
{
|
{
|
||||||
public function __construct(private ShortUrlStringifierInterface $stringifier)
|
public function __construct(private ShortUrlStringifierInterface $stringifier)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function transform(ShortUrlWithVisitsSummary|ShortUrl $data): array
|
||||||
* @param ShortUrlWithVisitsSummary|ShortUrl $data
|
|
||||||
*/
|
|
||||||
public function transform($data): array // phpcs:ignore
|
|
||||||
{
|
{
|
||||||
$shortUrl = $data instanceof ShortUrlWithVisitsSummary ? $data->shortUrl : $data;
|
$shortUrl = $data instanceof ShortUrlWithVisitsSummary ? $data->shortUrl : $data;
|
||||||
return [
|
return [
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Shlinkio\Shlink\Core\ShortUrl\Transformer;
|
||||||
|
|
||||||
|
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
|
||||||
|
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlWithVisitsSummary;
|
||||||
|
|
||||||
|
interface ShortUrlDataTransformerInterface
|
||||||
|
{
|
||||||
|
public function transform(ShortUrlWithVisitsSummary|ShortUrl $data): array;
|
||||||
|
}
|
@ -7,9 +7,11 @@ namespace Shlinkio\Shlink\Core\Tag\Entity;
|
|||||||
use Doctrine\Common\Collections;
|
use Doctrine\Common\Collections;
|
||||||
use JsonSerializable;
|
use JsonSerializable;
|
||||||
use Shlinkio\Shlink\Common\Entity\AbstractEntity;
|
use Shlinkio\Shlink\Common\Entity\AbstractEntity;
|
||||||
|
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
|
||||||
|
|
||||||
class Tag extends AbstractEntity implements JsonSerializable
|
class Tag extends AbstractEntity implements JsonSerializable
|
||||||
{
|
{
|
||||||
|
/** @var Collections\Collection<int, ShortUrl> */
|
||||||
private Collections\Collection $shortUrls;
|
private Collections\Collection $shortUrls;
|
||||||
|
|
||||||
public function __construct(private string $name)
|
public function __construct(private string $name)
|
||||||
|
@ -12,6 +12,10 @@ use Shlinkio\Shlink\Core\Tag\Repository\TagRepositoryInterface;
|
|||||||
use Shlinkio\Shlink\Rest\ApiKey\Spec\WithApiKeySpecsEnsuringJoin;
|
use Shlinkio\Shlink\Rest\ApiKey\Spec\WithApiKeySpecsEnsuringJoin;
|
||||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @template T
|
||||||
|
* @implements AdapterInterface<T>
|
||||||
|
*/
|
||||||
abstract class AbstractTagsPaginatorAdapter implements AdapterInterface
|
abstract class AbstractTagsPaginatorAdapter implements AdapterInterface
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
|
@ -4,8 +4,10 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Shlinkio\Shlink\Core\Tag\Paginator\Adapter;
|
namespace Shlinkio\Shlink\Core\Tag\Paginator\Adapter;
|
||||||
|
|
||||||
|
use Shlinkio\Shlink\Core\Tag\Model\TagInfo;
|
||||||
use Shlinkio\Shlink\Core\Tag\Model\TagsListFiltering;
|
use Shlinkio\Shlink\Core\Tag\Model\TagsListFiltering;
|
||||||
|
|
||||||
|
/** @extends AbstractTagsPaginatorAdapter<TagInfo> */
|
||||||
class TagsInfoPaginatorAdapter extends AbstractTagsPaginatorAdapter
|
class TagsInfoPaginatorAdapter extends AbstractTagsPaginatorAdapter
|
||||||
{
|
{
|
||||||
public function getSlice(int $offset, int $length): iterable
|
public function getSlice(int $offset, int $length): iterable
|
||||||
|
@ -5,8 +5,10 @@ declare(strict_types=1);
|
|||||||
namespace Shlinkio\Shlink\Core\Tag\Paginator\Adapter;
|
namespace Shlinkio\Shlink\Core\Tag\Paginator\Adapter;
|
||||||
|
|
||||||
use Happyr\DoctrineSpecification\Spec;
|
use Happyr\DoctrineSpecification\Spec;
|
||||||
|
use Shlinkio\Shlink\Core\Tag\Entity\Tag;
|
||||||
use Shlinkio\Shlink\Rest\ApiKey\Spec\WithApiKeySpecsEnsuringJoin;
|
use Shlinkio\Shlink\Rest\ApiKey\Spec\WithApiKeySpecsEnsuringJoin;
|
||||||
|
|
||||||
|
/** @extends AbstractTagsPaginatorAdapter<Tag> */
|
||||||
class TagsPaginatorAdapter extends AbstractTagsPaginatorAdapter
|
class TagsPaginatorAdapter extends AbstractTagsPaginatorAdapter
|
||||||
{
|
{
|
||||||
public function getSlice(int $offset, int $length): iterable
|
public function getSlice(int $offset, int $length): iterable
|
||||||
|
@ -23,6 +23,7 @@ use function Shlinkio\Shlink\Core\camelCaseToSnakeCase;
|
|||||||
|
|
||||||
use const PHP_INT_MAX;
|
use const PHP_INT_MAX;
|
||||||
|
|
||||||
|
/** @extends EntitySpecificationRepository<Tag> */
|
||||||
class TagRepository extends EntitySpecificationRepository implements TagRepositoryInterface
|
class TagRepository extends EntitySpecificationRepository implements TagRepositoryInterface
|
||||||
{
|
{
|
||||||
public function deleteByName(array $names): int
|
public function deleteByName(array $names): int
|
||||||
|
@ -6,10 +6,12 @@ namespace Shlinkio\Shlink\Core\Tag\Repository;
|
|||||||
|
|
||||||
use Doctrine\Persistence\ObjectRepository;
|
use Doctrine\Persistence\ObjectRepository;
|
||||||
use Happyr\DoctrineSpecification\Repository\EntitySpecificationRepositoryInterface;
|
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\TagInfo;
|
||||||
use Shlinkio\Shlink\Core\Tag\Model\TagsListFiltering;
|
use Shlinkio\Shlink\Core\Tag\Model\TagsListFiltering;
|
||||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||||
|
|
||||||
|
/** @extends ObjectRepository<Tag> */
|
||||||
interface TagRepositoryInterface extends ObjectRepository, EntitySpecificationRepositoryInterface
|
interface TagRepositoryInterface extends ObjectRepository, EntitySpecificationRepositoryInterface
|
||||||
{
|
{
|
||||||
public function deleteByName(array $names): int;
|
public function deleteByName(array $names): int;
|
||||||
|
@ -11,7 +11,6 @@ use Shlinkio\Shlink\Core\Exception\ForbiddenTagOperationException;
|
|||||||
use Shlinkio\Shlink\Core\Exception\TagConflictException;
|
use Shlinkio\Shlink\Core\Exception\TagConflictException;
|
||||||
use Shlinkio\Shlink\Core\Exception\TagNotFoundException;
|
use Shlinkio\Shlink\Core\Exception\TagNotFoundException;
|
||||||
use Shlinkio\Shlink\Core\Tag\Entity\Tag;
|
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\TagRenaming;
|
||||||
use Shlinkio\Shlink\Core\Tag\Model\TagsParams;
|
use Shlinkio\Shlink\Core\Tag\Model\TagsParams;
|
||||||
use Shlinkio\Shlink\Core\Tag\Paginator\Adapter\TagsInfoPaginatorAdapter;
|
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\Core\Tag\Repository\TagRepositoryInterface;
|
||||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
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
|
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
|
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);
|
return $this->createPaginator(new TagsInfoPaginatorAdapter($repo, $params, $apiKey), $params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @template T
|
||||||
|
* @param AdapterInterface<T> $adapter
|
||||||
|
* @return Paginator<T>
|
||||||
|
*/
|
||||||
private function createPaginator(AdapterInterface $adapter, TagsParams $params): Paginator
|
private function createPaginator(AdapterInterface $adapter, TagsParams $params): Paginator
|
||||||
{
|
{
|
||||||
return (new Paginator($adapter))
|
return (new Paginator($adapter))
|
||||||
@ -54,8 +58,7 @@ class TagService implements TagServiceInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string[] $tagNames
|
* @inheritDoc
|
||||||
* @throws ForbiddenTagOperationException
|
|
||||||
*/
|
*/
|
||||||
public function deleteTags(array $tagNames, ?ApiKey $apiKey = null): void
|
public function deleteTags(array $tagNames, ?ApiKey $apiKey = null): void
|
||||||
{
|
{
|
||||||
@ -69,9 +72,7 @@ class TagService implements TagServiceInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws TagNotFoundException
|
* @inheritDoc
|
||||||
* @throws TagConflictException
|
|
||||||
* @throws ForbiddenTagOperationException
|
|
||||||
*/
|
*/
|
||||||
public function renameTag(TagRenaming $renaming, ?ApiKey $apiKey = null): Tag
|
public function renameTag(TagRenaming $renaming, ?ApiKey $apiKey = null): Tag
|
||||||
{
|
{
|
||||||
|
@ -17,12 +17,12 @@ use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
|||||||
interface TagServiceInterface
|
interface TagServiceInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @return Tag[]|Paginator
|
* @return Paginator<Tag>
|
||||||
*/
|
*/
|
||||||
public function listTags(TagsParams $params, ?ApiKey $apiKey = null): Paginator;
|
public function listTags(TagsParams $params, ?ApiKey $apiKey = null): Paginator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return TagInfo[]|Paginator
|
* @return Paginator<TagInfo>
|
||||||
*/
|
*/
|
||||||
public function tagsInfo(TagsParams $params, ?ApiKey $apiKey = null): Paginator;
|
public function tagsInfo(TagsParams $params, ?ApiKey $apiKey = null): Paginator;
|
||||||
|
|
||||||
|
@ -5,19 +5,23 @@ declare(strict_types=1);
|
|||||||
namespace Shlinkio\Shlink\Core\Visit\Paginator\Adapter;
|
namespace Shlinkio\Shlink\Core\Visit\Paginator\Adapter;
|
||||||
|
|
||||||
use Shlinkio\Shlink\Core\Paginator\Adapter\AbstractCacheableCountPaginatorAdapter;
|
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\Model\VisitsParams;
|
||||||
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsCountFiltering;
|
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsCountFiltering;
|
||||||
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsListFiltering;
|
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsListFiltering;
|
||||||
use Shlinkio\Shlink\Core\Visit\Repository\VisitRepositoryInterface;
|
use Shlinkio\Shlink\Core\Visit\Repository\VisitRepositoryInterface;
|
||||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends AbstractCacheableCountPaginatorAdapter<Visit>
|
||||||
|
*/
|
||||||
class DomainVisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdapter
|
class DomainVisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdapter
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private VisitRepositoryInterface $visitRepository,
|
private readonly VisitRepositoryInterface $visitRepository,
|
||||||
private string $domain,
|
private readonly string $domain,
|
||||||
private VisitsParams $params,
|
private readonly VisitsParams $params,
|
||||||
private ?ApiKey $apiKey,
|
private readonly ?ApiKey $apiKey,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,18 +5,20 @@ declare(strict_types=1);
|
|||||||
namespace Shlinkio\Shlink\Core\Visit\Paginator\Adapter;
|
namespace Shlinkio\Shlink\Core\Visit\Paginator\Adapter;
|
||||||
|
|
||||||
use Shlinkio\Shlink\Core\Paginator\Adapter\AbstractCacheableCountPaginatorAdapter;
|
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\Model\VisitsParams;
|
||||||
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsCountFiltering;
|
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsCountFiltering;
|
||||||
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsListFiltering;
|
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsListFiltering;
|
||||||
use Shlinkio\Shlink\Core\Visit\Repository\VisitRepositoryInterface;
|
use Shlinkio\Shlink\Core\Visit\Repository\VisitRepositoryInterface;
|
||||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||||
|
|
||||||
|
/** @extends AbstractCacheableCountPaginatorAdapter<Visit> */
|
||||||
class NonOrphanVisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdapter
|
class NonOrphanVisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdapter
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private VisitRepositoryInterface $repo,
|
private readonly VisitRepositoryInterface $repo,
|
||||||
private VisitsParams $params,
|
private readonly VisitsParams $params,
|
||||||
private ?ApiKey $apiKey,
|
private readonly ?ApiKey $apiKey,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,12 +5,14 @@ declare(strict_types=1);
|
|||||||
namespace Shlinkio\Shlink\Core\Visit\Paginator\Adapter;
|
namespace Shlinkio\Shlink\Core\Visit\Paginator\Adapter;
|
||||||
|
|
||||||
use Shlinkio\Shlink\Core\Paginator\Adapter\AbstractCacheableCountPaginatorAdapter;
|
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\Model\OrphanVisitsParams;
|
||||||
use Shlinkio\Shlink\Core\Visit\Persistence\OrphanVisitsCountFiltering;
|
use Shlinkio\Shlink\Core\Visit\Persistence\OrphanVisitsCountFiltering;
|
||||||
use Shlinkio\Shlink\Core\Visit\Persistence\OrphanVisitsListFiltering;
|
use Shlinkio\Shlink\Core\Visit\Persistence\OrphanVisitsListFiltering;
|
||||||
use Shlinkio\Shlink\Core\Visit\Repository\VisitRepositoryInterface;
|
use Shlinkio\Shlink\Core\Visit\Repository\VisitRepositoryInterface;
|
||||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||||
|
|
||||||
|
/** @extends AbstractCacheableCountPaginatorAdapter<Visit> */
|
||||||
class OrphanVisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdapter
|
class OrphanVisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdapter
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
|
@ -6,19 +6,21 @@ namespace Shlinkio\Shlink\Core\Visit\Paginator\Adapter;
|
|||||||
|
|
||||||
use Shlinkio\Shlink\Core\Paginator\Adapter\AbstractCacheableCountPaginatorAdapter;
|
use Shlinkio\Shlink\Core\Paginator\Adapter\AbstractCacheableCountPaginatorAdapter;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlIdentifier;
|
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\Model\VisitsParams;
|
||||||
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsCountFiltering;
|
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsCountFiltering;
|
||||||
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsListFiltering;
|
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsListFiltering;
|
||||||
use Shlinkio\Shlink\Core\Visit\Repository\VisitRepositoryInterface;
|
use Shlinkio\Shlink\Core\Visit\Repository\VisitRepositoryInterface;
|
||||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||||
|
|
||||||
|
/** @extends AbstractCacheableCountPaginatorAdapter<Visit> */
|
||||||
class ShortUrlVisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdapter
|
class ShortUrlVisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdapter
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private VisitRepositoryInterface $visitRepository,
|
private readonly VisitRepositoryInterface $visitRepository,
|
||||||
private ShortUrlIdentifier $identifier,
|
private readonly ShortUrlIdentifier $identifier,
|
||||||
private VisitsParams $params,
|
private readonly VisitsParams $params,
|
||||||
private ?ApiKey $apiKey,
|
private readonly ?ApiKey $apiKey,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,19 +5,21 @@ declare(strict_types=1);
|
|||||||
namespace Shlinkio\Shlink\Core\Visit\Paginator\Adapter;
|
namespace Shlinkio\Shlink\Core\Visit\Paginator\Adapter;
|
||||||
|
|
||||||
use Shlinkio\Shlink\Core\Paginator\Adapter\AbstractCacheableCountPaginatorAdapter;
|
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\Model\VisitsParams;
|
||||||
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsCountFiltering;
|
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsCountFiltering;
|
||||||
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsListFiltering;
|
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsListFiltering;
|
||||||
use Shlinkio\Shlink\Core\Visit\Repository\VisitRepositoryInterface;
|
use Shlinkio\Shlink\Core\Visit\Repository\VisitRepositoryInterface;
|
||||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||||
|
|
||||||
|
/** @extends AbstractCacheableCountPaginatorAdapter<Visit> */
|
||||||
class TagVisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdapter
|
class TagVisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdapter
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private VisitRepositoryInterface $visitRepository,
|
private readonly VisitRepositoryInterface $visitRepository,
|
||||||
private string $tag,
|
private readonly string $tag,
|
||||||
private VisitsParams $params,
|
private readonly VisitsParams $params,
|
||||||
private ?ApiKey $apiKey,
|
private readonly ?ApiKey $apiKey,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ use Shlinkio\Shlink\Core\Visit\Entity\OrphanVisitsCount;
|
|||||||
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsCountFiltering;
|
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsCountFiltering;
|
||||||
use Shlinkio\Shlink\Rest\ApiKey\Role;
|
use Shlinkio\Shlink\Rest\ApiKey\Role;
|
||||||
|
|
||||||
|
/** @extends EntitySpecificationRepository<OrphanVisitsCount> */
|
||||||
class OrphanVisitsCountRepository extends EntitySpecificationRepository implements OrphanVisitsCountRepositoryInterface
|
class OrphanVisitsCountRepository extends EntitySpecificationRepository implements OrphanVisitsCountRepositoryInterface
|
||||||
{
|
{
|
||||||
public function countOrphanVisits(VisitsCountFiltering $filtering): int
|
public function countOrphanVisits(VisitsCountFiltering $filtering): int
|
||||||
|
@ -5,9 +5,11 @@ declare(strict_types=1);
|
|||||||
namespace Shlinkio\Shlink\Core\Visit\Repository;
|
namespace Shlinkio\Shlink\Core\Visit\Repository;
|
||||||
|
|
||||||
use Happyr\DoctrineSpecification\Repository\EntitySpecificationRepository;
|
use Happyr\DoctrineSpecification\Repository\EntitySpecificationRepository;
|
||||||
|
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
|
||||||
use Shlinkio\Shlink\Core\Visit\Entity\ShortUrlVisitsCount;
|
use Shlinkio\Shlink\Core\Visit\Entity\ShortUrlVisitsCount;
|
||||||
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsCountFiltering;
|
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsCountFiltering;
|
||||||
|
|
||||||
|
/** @extends EntitySpecificationRepository<ShortUrl> */
|
||||||
class ShortUrlVisitsCountRepository extends EntitySpecificationRepository implements
|
class ShortUrlVisitsCountRepository extends EntitySpecificationRepository implements
|
||||||
ShortUrlVisitsCountRepositoryInterface
|
ShortUrlVisitsCountRepositoryInterface
|
||||||
{
|
{
|
||||||
|
@ -8,6 +8,7 @@ use Happyr\DoctrineSpecification\Repository\EntitySpecificationRepository;
|
|||||||
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
|
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
|
||||||
use Shlinkio\Shlink\Core\Visit\Entity\Visit;
|
use Shlinkio\Shlink\Core\Visit\Entity\Visit;
|
||||||
|
|
||||||
|
/** @extends EntitySpecificationRepository<Visit> */
|
||||||
class VisitDeleterRepository extends EntitySpecificationRepository implements VisitDeleterRepositoryInterface
|
class VisitDeleterRepository extends EntitySpecificationRepository implements VisitDeleterRepositoryInterface
|
||||||
{
|
{
|
||||||
public function deleteShortUrlVisits(ShortUrl $shortUrl): int
|
public function deleteShortUrlVisits(ShortUrl $shortUrl): int
|
||||||
|
@ -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
|
* Allows iterating large amounts of visits in a memory-efficient way, to use in batch processes
|
||||||
|
* @extends EntitySpecificationRepository<Visit>
|
||||||
*/
|
*/
|
||||||
class VisitIterationRepository extends EntitySpecificationRepository implements VisitIterationRepositoryInterface
|
class VisitIterationRepository extends EntitySpecificationRepository implements VisitIterationRepositoryInterface
|
||||||
{
|
{
|
||||||
|
@ -23,6 +23,7 @@ use Shlinkio\Shlink\Rest\ApiKey\Role;
|
|||||||
|
|
||||||
use const PHP_INT_MAX;
|
use const PHP_INT_MAX;
|
||||||
|
|
||||||
|
/** @extends EntitySpecificationRepository<Visit> */
|
||||||
class VisitRepository extends EntitySpecificationRepository implements VisitRepositoryInterface
|
class VisitRepository extends EntitySpecificationRepository implements VisitRepositoryInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -13,6 +13,9 @@ use Shlinkio\Shlink\Core\Visit\Persistence\OrphanVisitsListFiltering;
|
|||||||
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsCountFiltering;
|
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsCountFiltering;
|
||||||
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsListFiltering;
|
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsListFiltering;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends ObjectRepository<Visit>
|
||||||
|
*/
|
||||||
interface VisitRepositoryInterface extends ObjectRepository, EntitySpecificationRepositoryInterface
|
interface VisitRepositoryInterface extends ObjectRepository, EntitySpecificationRepositoryInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -63,8 +63,7 @@ readonly class VisitsStatsHelper implements VisitsStatsHelperInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Visit[]|Paginator
|
* @inheritDoc
|
||||||
* @throws ShortUrlNotFoundException
|
|
||||||
*/
|
*/
|
||||||
public function visitsForShortUrl(
|
public function visitsForShortUrl(
|
||||||
ShortUrlIdentifier $identifier,
|
ShortUrlIdentifier $identifier,
|
||||||
@ -87,8 +86,7 @@ readonly class VisitsStatsHelper implements VisitsStatsHelperInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Visit[]|Paginator
|
* @inheritDoc
|
||||||
* @throws TagNotFoundException
|
|
||||||
*/
|
*/
|
||||||
public function visitsForTag(string $tag, VisitsParams $params, ?ApiKey $apiKey = null): Paginator
|
public function visitsForTag(string $tag, VisitsParams $params, ?ApiKey $apiKey = null): Paginator
|
||||||
{
|
{
|
||||||
@ -105,8 +103,7 @@ readonly class VisitsStatsHelper implements VisitsStatsHelperInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Visit[]|Paginator
|
* @inheritDoc
|
||||||
* @throws DomainNotFoundException
|
|
||||||
*/
|
*/
|
||||||
public function visitsForDomain(string $domain, VisitsParams $params, ?ApiKey $apiKey = null): Paginator
|
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
|
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);
|
return $this->createPaginator(new NonOrphanVisitsPaginatorAdapter($repo, $params, $apiKey), $params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param AdapterInterface<Visit> $adapter
|
||||||
|
* @return Paginator<Visit>
|
||||||
|
*/
|
||||||
private function createPaginator(AdapterInterface $adapter, VisitsParams $params): Paginator
|
private function createPaginator(AdapterInterface $adapter, VisitsParams $params): Paginator
|
||||||
{
|
{
|
||||||
$paginator = new Paginator($adapter);
|
$paginator = new Paginator($adapter);
|
||||||
|
@ -20,7 +20,7 @@ interface VisitsStatsHelperInterface
|
|||||||
public function getVisitsStats(?ApiKey $apiKey = null): VisitsStats;
|
public function getVisitsStats(?ApiKey $apiKey = null): VisitsStats;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Visit[]|Paginator
|
* @return Paginator<Visit>
|
||||||
* @throws ShortUrlNotFoundException
|
* @throws ShortUrlNotFoundException
|
||||||
*/
|
*/
|
||||||
public function visitsForShortUrl(
|
public function visitsForShortUrl(
|
||||||
@ -30,24 +30,24 @@ interface VisitsStatsHelperInterface
|
|||||||
): Paginator;
|
): Paginator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Visit[]|Paginator
|
* @return Paginator<Visit>
|
||||||
* @throws TagNotFoundException
|
* @throws TagNotFoundException
|
||||||
*/
|
*/
|
||||||
public function visitsForTag(string $tag, VisitsParams $params, ?ApiKey $apiKey = null): Paginator;
|
public function visitsForTag(string $tag, VisitsParams $params, ?ApiKey $apiKey = null): Paginator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Visit[]|Paginator
|
* @return Paginator<Visit>
|
||||||
* @throws DomainNotFoundException
|
* @throws DomainNotFoundException
|
||||||
*/
|
*/
|
||||||
public function visitsForDomain(string $domain, VisitsParams $params, ?ApiKey $apiKey = null): Paginator;
|
public function visitsForDomain(string $domain, VisitsParams $params, ?ApiKey $apiKey = null): Paginator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Visit[]|Paginator
|
* @return Paginator<Visit>
|
||||||
*/
|
*/
|
||||||
public function orphanVisits(OrphanVisitsParams $params, ?ApiKey $apiKey = null): Paginator;
|
public function orphanVisits(OrphanVisitsParams $params, ?ApiKey $apiKey = null): Paginator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Visit[]|Paginator
|
* @return Paginator<Visit>
|
||||||
*/
|
*/
|
||||||
public function nonOrphanVisits(VisitsParams $params, ?ApiKey $apiKey = null): Paginator;
|
public function nonOrphanVisits(VisitsParams $params, ?ApiKey $apiKey = null): Paginator;
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,11 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace ShlinkioDbTest\Shlink\Core\Visit\Listener;
|
namespace ShlinkioDbTest\Shlink\Core\Visit\Listener;
|
||||||
|
|
||||||
use Doctrine\ORM\EntityRepository;
|
|
||||||
use PHPUnit\Framework\Attributes\Test;
|
use PHPUnit\Framework\Attributes\Test;
|
||||||
use Shlinkio\Shlink\Core\Visit\Entity\OrphanVisitsCount;
|
use Shlinkio\Shlink\Core\Visit\Entity\OrphanVisitsCount;
|
||||||
use Shlinkio\Shlink\Core\Visit\Entity\Visit;
|
use Shlinkio\Shlink\Core\Visit\Entity\Visit;
|
||||||
use Shlinkio\Shlink\Core\Visit\Model\Visitor;
|
use Shlinkio\Shlink\Core\Visit\Model\Visitor;
|
||||||
|
use Shlinkio\Shlink\Core\Visit\Repository\OrphanVisitsCountRepository;
|
||||||
use Shlinkio\Shlink\TestUtils\DbTest\DatabaseTestCase;
|
use Shlinkio\Shlink\TestUtils\DbTest\DatabaseTestCase;
|
||||||
|
|
||||||
use function array_filter;
|
use function array_filter;
|
||||||
@ -16,7 +16,7 @@ use function array_values;
|
|||||||
|
|
||||||
class OrphanVisitsCountTrackerTest extends DatabaseTestCase
|
class OrphanVisitsCountTrackerTest extends DatabaseTestCase
|
||||||
{
|
{
|
||||||
private EntityRepository $repo;
|
private OrphanVisitsCountRepository $repo;
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
|
@ -4,12 +4,12 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace ShlinkioDbTest\Shlink\Core\Visit\Listener;
|
namespace ShlinkioDbTest\Shlink\Core\Visit\Listener;
|
||||||
|
|
||||||
use Doctrine\ORM\EntityRepository;
|
|
||||||
use PHPUnit\Framework\Attributes\Test;
|
use PHPUnit\Framework\Attributes\Test;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
|
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
|
||||||
use Shlinkio\Shlink\Core\Visit\Entity\ShortUrlVisitsCount;
|
use Shlinkio\Shlink\Core\Visit\Entity\ShortUrlVisitsCount;
|
||||||
use Shlinkio\Shlink\Core\Visit\Entity\Visit;
|
use Shlinkio\Shlink\Core\Visit\Entity\Visit;
|
||||||
use Shlinkio\Shlink\Core\Visit\Model\Visitor;
|
use Shlinkio\Shlink\Core\Visit\Model\Visitor;
|
||||||
|
use Shlinkio\Shlink\Core\Visit\Repository\ShortUrlVisitsCountRepository;
|
||||||
use Shlinkio\Shlink\TestUtils\DbTest\DatabaseTestCase;
|
use Shlinkio\Shlink\TestUtils\DbTest\DatabaseTestCase;
|
||||||
|
|
||||||
use function array_filter;
|
use function array_filter;
|
||||||
@ -17,7 +17,7 @@ use function array_values;
|
|||||||
|
|
||||||
class ShortUrlVisitsCountTrackerTest extends DatabaseTestCase
|
class ShortUrlVisitsCountTrackerTest extends DatabaseTestCase
|
||||||
{
|
{
|
||||||
private EntityRepository $repo;
|
private ShortUrlVisitsCountRepository $repo;
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
|
@ -104,7 +104,7 @@ class ShortUrlRedirectRuleTest extends TestCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ArrayCollection<RedirectCondition> $conditions
|
* @param ArrayCollection<int, RedirectCondition> $conditions
|
||||||
*/
|
*/
|
||||||
private function createRule(ArrayCollection $conditions): ShortUrlRedirectRule
|
private function createRule(ArrayCollection $conditions): ShortUrlRedirectRule
|
||||||
{
|
{
|
||||||
|
@ -103,6 +103,9 @@ class ShortUrlTitleResolutionHelperTest extends TestCase
|
|||||||
self::assertEquals('Resolved "title"', $result->title);
|
self::assertEquals('Resolved "title"', $result->title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return InvocationMocker<ClientInterface>
|
||||||
|
*/
|
||||||
private function expectRequestToBeCalled(): InvocationMocker
|
private function expectRequestToBeCalled(): InvocationMocker
|
||||||
{
|
{
|
||||||
return $this->httpClient->expects($this->once())->method('request')->with(
|
return $this->httpClient->expects($this->once())->method('request')->with(
|
||||||
|
@ -7,10 +7,10 @@ namespace Shlinkio\Shlink\Rest\Action\ShortUrl;
|
|||||||
use Laminas\Diactoros\Response\JsonResponse;
|
use Laminas\Diactoros\Response\JsonResponse;
|
||||||
use Psr\Http\Message\ResponseInterface as Response;
|
use Psr\Http\Message\ResponseInterface as Response;
|
||||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||||
use Shlinkio\Shlink\Common\Rest\DataTransformerInterface;
|
|
||||||
use Shlinkio\Shlink\Core\Exception\ValidationException;
|
use Shlinkio\Shlink\Core\Exception\ValidationException;
|
||||||
use Shlinkio\Shlink\Core\Options\UrlShortenerOptions;
|
use Shlinkio\Shlink\Core\Options\UrlShortenerOptions;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlCreation;
|
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlCreation;
|
||||||
|
use Shlinkio\Shlink\Core\ShortUrl\Transformer\ShortUrlDataTransformerInterface;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\UrlShortenerInterface;
|
use Shlinkio\Shlink\Core\ShortUrl\UrlShortenerInterface;
|
||||||
use Shlinkio\Shlink\Rest\Action\AbstractRestAction;
|
use Shlinkio\Shlink\Rest\Action\AbstractRestAction;
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ abstract class AbstractCreateShortUrlAction extends AbstractRestAction
|
|||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly UrlShortenerInterface $urlShortener,
|
private readonly UrlShortenerInterface $urlShortener,
|
||||||
private readonly DataTransformerInterface $transformer,
|
private readonly ShortUrlDataTransformerInterface $transformer,
|
||||||
protected readonly UrlShortenerOptions $urlShortenerOptions,
|
protected readonly UrlShortenerOptions $urlShortenerOptions,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
@ -7,10 +7,10 @@ namespace Shlinkio\Shlink\Rest\Action\ShortUrl;
|
|||||||
use Laminas\Diactoros\Response\JsonResponse;
|
use Laminas\Diactoros\Response\JsonResponse;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Shlinkio\Shlink\Common\Rest\DataTransformerInterface;
|
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlEdition;
|
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlEdition;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlIdentifier;
|
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlIdentifier;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\ShortUrlServiceInterface;
|
use Shlinkio\Shlink\Core\ShortUrl\ShortUrlServiceInterface;
|
||||||
|
use Shlinkio\Shlink\Core\ShortUrl\Transformer\ShortUrlDataTransformerInterface;
|
||||||
use Shlinkio\Shlink\Rest\Action\AbstractRestAction;
|
use Shlinkio\Shlink\Rest\Action\AbstractRestAction;
|
||||||
use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware;
|
use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware;
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ class EditShortUrlAction extends AbstractRestAction
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly ShortUrlServiceInterface $shortUrlService,
|
private readonly ShortUrlServiceInterface $shortUrlService,
|
||||||
private readonly DataTransformerInterface $transformer,
|
private readonly ShortUrlDataTransformerInterface $transformer,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,23 +7,21 @@ namespace Shlinkio\Shlink\Rest\Action\ShortUrl;
|
|||||||
use Laminas\Diactoros\Response\JsonResponse;
|
use Laminas\Diactoros\Response\JsonResponse;
|
||||||
use Psr\Http\Message\ResponseInterface as Response;
|
use Psr\Http\Message\ResponseInterface as Response;
|
||||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||||
use Shlinkio\Shlink\Common\Paginator\Util\PagerfantaUtilsTrait;
|
use Shlinkio\Shlink\Common\Paginator\Util\PagerfantaUtils;
|
||||||
use Shlinkio\Shlink\Common\Rest\DataTransformerInterface;
|
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlsParams;
|
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlsParams;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\ShortUrlListServiceInterface;
|
use Shlinkio\Shlink\Core\ShortUrl\ShortUrlListServiceInterface;
|
||||||
|
use Shlinkio\Shlink\Core\ShortUrl\Transformer\ShortUrlDataTransformerInterface;
|
||||||
use Shlinkio\Shlink\Rest\Action\AbstractRestAction;
|
use Shlinkio\Shlink\Rest\Action\AbstractRestAction;
|
||||||
use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware;
|
use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware;
|
||||||
|
|
||||||
class ListShortUrlsAction extends AbstractRestAction
|
class ListShortUrlsAction extends AbstractRestAction
|
||||||
{
|
{
|
||||||
use PagerfantaUtilsTrait;
|
|
||||||
|
|
||||||
protected const ROUTE_PATH = '/short-urls';
|
protected const ROUTE_PATH = '/short-urls';
|
||||||
protected const ROUTE_ALLOWED_METHODS = [self::METHOD_GET];
|
protected const ROUTE_ALLOWED_METHODS = [self::METHOD_GET];
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly ShortUrlListServiceInterface $shortUrlService,
|
private readonly ShortUrlListServiceInterface $shortUrlService,
|
||||||
private readonly DataTransformerInterface $transformer,
|
private readonly ShortUrlDataTransformerInterface $transformer,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,6 +31,8 @@ class ListShortUrlsAction extends AbstractRestAction
|
|||||||
ShortUrlsParams::fromRawData($request->getQueryParams()),
|
ShortUrlsParams::fromRawData($request->getQueryParams()),
|
||||||
AuthenticationMiddleware::apiKeyFromRequest($request),
|
AuthenticationMiddleware::apiKeyFromRequest($request),
|
||||||
);
|
);
|
||||||
return new JsonResponse(['shortUrls' => $this->serializePaginator($shortUrls, $this->transformer)]);
|
return new JsonResponse([
|
||||||
|
'shortUrls' => PagerfantaUtils::serializePaginator($shortUrls, $this->transformer->transform(...)),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,9 +7,9 @@ namespace Shlinkio\Shlink\Rest\Action\ShortUrl;
|
|||||||
use Laminas\Diactoros\Response\JsonResponse;
|
use Laminas\Diactoros\Response\JsonResponse;
|
||||||
use Psr\Http\Message\ResponseInterface as Response;
|
use Psr\Http\Message\ResponseInterface as Response;
|
||||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
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\Model\ShortUrlIdentifier;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\ShortUrlResolverInterface;
|
use Shlinkio\Shlink\Core\ShortUrl\ShortUrlResolverInterface;
|
||||||
|
use Shlinkio\Shlink\Core\ShortUrl\Transformer\ShortUrlDataTransformerInterface;
|
||||||
use Shlinkio\Shlink\Rest\Action\AbstractRestAction;
|
use Shlinkio\Shlink\Rest\Action\AbstractRestAction;
|
||||||
use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware;
|
use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware;
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ class ResolveShortUrlAction extends AbstractRestAction
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly ShortUrlResolverInterface $urlResolver,
|
private readonly ShortUrlResolverInterface $urlResolver,
|
||||||
private readonly DataTransformerInterface $transformer,
|
private readonly ShortUrlDataTransformerInterface $transformer,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ namespace Shlinkio\Shlink\Rest\Action\Tag;
|
|||||||
use Laminas\Diactoros\Response\JsonResponse;
|
use Laminas\Diactoros\Response\JsonResponse;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
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\Model\TagsParams;
|
||||||
use Shlinkio\Shlink\Core\Tag\TagServiceInterface;
|
use Shlinkio\Shlink\Core\Tag\TagServiceInterface;
|
||||||
use Shlinkio\Shlink\Rest\Action\AbstractRestAction;
|
use Shlinkio\Shlink\Rest\Action\AbstractRestAction;
|
||||||
@ -15,12 +15,10 @@ use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware;
|
|||||||
|
|
||||||
class ListTagsAction extends AbstractRestAction
|
class ListTagsAction extends AbstractRestAction
|
||||||
{
|
{
|
||||||
use PagerfantaUtilsTrait;
|
|
||||||
|
|
||||||
protected const ROUTE_PATH = '/tags';
|
protected const ROUTE_PATH = '/tags';
|
||||||
protected const ROUTE_ALLOWED_METHODS = [self::METHOD_GET];
|
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);
|
$apiKey = AuthenticationMiddleware::apiKeyFromRequest($request);
|
||||||
|
|
||||||
return new JsonResponse([
|
return new JsonResponse([
|
||||||
'tags' => $this->serializePaginator($this->tagService->listTags($params, $apiKey)),
|
'tags' => PagerfantaUtils::serializePaginator($this->tagService->listTags($params, $apiKey)),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ namespace Shlinkio\Shlink\Rest\Action\Tag;
|
|||||||
use Laminas\Diactoros\Response\JsonResponse;
|
use Laminas\Diactoros\Response\JsonResponse;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
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\Model\TagsParams;
|
||||||
use Shlinkio\Shlink\Core\Tag\TagServiceInterface;
|
use Shlinkio\Shlink\Core\Tag\TagServiceInterface;
|
||||||
use Shlinkio\Shlink\Rest\Action\AbstractRestAction;
|
use Shlinkio\Shlink\Rest\Action\AbstractRestAction;
|
||||||
@ -15,8 +15,6 @@ use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware;
|
|||||||
|
|
||||||
class TagsStatsAction extends AbstractRestAction
|
class TagsStatsAction extends AbstractRestAction
|
||||||
{
|
{
|
||||||
use PagerfantaUtilsTrait;
|
|
||||||
|
|
||||||
protected const ROUTE_PATH = '/tags/stats';
|
protected const ROUTE_PATH = '/tags/stats';
|
||||||
protected const ROUTE_ALLOWED_METHODS = [self::METHOD_GET];
|
protected const ROUTE_ALLOWED_METHODS = [self::METHOD_GET];
|
||||||
|
|
||||||
@ -30,6 +28,6 @@ class TagsStatsAction extends AbstractRestAction
|
|||||||
$apiKey = AuthenticationMiddleware::apiKeyFromRequest($request);
|
$apiKey = AuthenticationMiddleware::apiKeyFromRequest($request);
|
||||||
$tagsInfo = $this->tagService->tagsInfo($params, $apiKey);
|
$tagsInfo = $this->tagService->tagsInfo($params, $apiKey);
|
||||||
|
|
||||||
return new JsonResponse(['tags' => $this->serializePaginator($tagsInfo)]);
|
return new JsonResponse(['tags' => PagerfantaUtils::serializePaginator($tagsInfo)]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,15 +7,12 @@ namespace Shlinkio\Shlink\Rest\Action\Visit;
|
|||||||
use Laminas\Diactoros\Response\JsonResponse;
|
use Laminas\Diactoros\Response\JsonResponse;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Shlinkio\Shlink\Common\Paginator\Util\PagerfantaUtilsTrait;
|
|
||||||
use Shlinkio\Shlink\Core\Visit\VisitsDeleterInterface;
|
use Shlinkio\Shlink\Core\Visit\VisitsDeleterInterface;
|
||||||
use Shlinkio\Shlink\Rest\Action\AbstractRestAction;
|
use Shlinkio\Shlink\Rest\Action\AbstractRestAction;
|
||||||
use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware;
|
use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware;
|
||||||
|
|
||||||
class DeleteOrphanVisitsAction extends AbstractRestAction
|
class DeleteOrphanVisitsAction extends AbstractRestAction
|
||||||
{
|
{
|
||||||
use PagerfantaUtilsTrait;
|
|
||||||
|
|
||||||
protected const ROUTE_PATH = '/visits/orphan';
|
protected const ROUTE_PATH = '/visits/orphan';
|
||||||
protected const ROUTE_ALLOWED_METHODS = [self::METHOD_DELETE];
|
protected const ROUTE_ALLOWED_METHODS = [self::METHOD_DELETE];
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ namespace Shlinkio\Shlink\Rest\Action\Visit;
|
|||||||
use Laminas\Diactoros\Response\JsonResponse;
|
use Laminas\Diactoros\Response\JsonResponse;
|
||||||
use Psr\Http\Message\ResponseInterface as Response;
|
use Psr\Http\Message\ResponseInterface as Response;
|
||||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
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\Model\VisitsParams;
|
||||||
use Shlinkio\Shlink\Core\Visit\VisitsStatsHelperInterface;
|
use Shlinkio\Shlink\Core\Visit\VisitsStatsHelperInterface;
|
||||||
use Shlinkio\Shlink\Rest\Action\AbstractRestAction;
|
use Shlinkio\Shlink\Rest\Action\AbstractRestAction;
|
||||||
@ -15,13 +15,13 @@ use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware;
|
|||||||
|
|
||||||
class DomainVisitsAction extends AbstractRestAction
|
class DomainVisitsAction extends AbstractRestAction
|
||||||
{
|
{
|
||||||
use PagerfantaUtilsTrait;
|
|
||||||
|
|
||||||
protected const ROUTE_PATH = '/domains/{domain}/visits';
|
protected const ROUTE_PATH = '/domains/{domain}/visits';
|
||||||
protected const ROUTE_ALLOWED_METHODS = [self::METHOD_GET];
|
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
|
public function handle(Request $request): Response
|
||||||
@ -31,9 +31,7 @@ class DomainVisitsAction extends AbstractRestAction
|
|||||||
$apiKey = AuthenticationMiddleware::apiKeyFromRequest($request);
|
$apiKey = AuthenticationMiddleware::apiKeyFromRequest($request);
|
||||||
$visits = $this->visitsHelper->visitsForDomain($domain, $params, $apiKey);
|
$visits = $this->visitsHelper->visitsForDomain($domain, $params, $apiKey);
|
||||||
|
|
||||||
return new JsonResponse([
|
return new JsonResponse(['visits' => PagerfantaUtils::serializePaginator($visits)]);
|
||||||
'visits' => $this->serializePaginator($visits),
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function resolveDomainParam(Request $request): string
|
private function resolveDomainParam(Request $request): string
|
||||||
|
@ -7,7 +7,7 @@ namespace Shlinkio\Shlink\Rest\Action\Visit;
|
|||||||
use Laminas\Diactoros\Response\JsonResponse;
|
use Laminas\Diactoros\Response\JsonResponse;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
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\Model\VisitsParams;
|
||||||
use Shlinkio\Shlink\Core\Visit\VisitsStatsHelperInterface;
|
use Shlinkio\Shlink\Core\Visit\VisitsStatsHelperInterface;
|
||||||
use Shlinkio\Shlink\Rest\Action\AbstractRestAction;
|
use Shlinkio\Shlink\Rest\Action\AbstractRestAction;
|
||||||
@ -15,12 +15,10 @@ use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware;
|
|||||||
|
|
||||||
class NonOrphanVisitsAction extends AbstractRestAction
|
class NonOrphanVisitsAction extends AbstractRestAction
|
||||||
{
|
{
|
||||||
use PagerfantaUtilsTrait;
|
|
||||||
|
|
||||||
protected const ROUTE_PATH = '/visits/non-orphan';
|
protected const ROUTE_PATH = '/visits/non-orphan';
|
||||||
protected const ROUTE_ALLOWED_METHODS = [self::METHOD_GET];
|
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);
|
$apiKey = AuthenticationMiddleware::apiKeyFromRequest($request);
|
||||||
$visits = $this->visitsHelper->nonOrphanVisits($params, $apiKey);
|
$visits = $this->visitsHelper->nonOrphanVisits($params, $apiKey);
|
||||||
|
|
||||||
return new JsonResponse([
|
return new JsonResponse(['visits' => PagerfantaUtils::serializePaginator($visits)]);
|
||||||
'visits' => $this->serializePaginator($visits),
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ namespace Shlinkio\Shlink\Rest\Action\Visit;
|
|||||||
use Laminas\Diactoros\Response\JsonResponse;
|
use Laminas\Diactoros\Response\JsonResponse;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
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\Model\OrphanVisitsParams;
|
||||||
use Shlinkio\Shlink\Core\Visit\VisitsStatsHelperInterface;
|
use Shlinkio\Shlink\Core\Visit\VisitsStatsHelperInterface;
|
||||||
use Shlinkio\Shlink\Rest\Action\AbstractRestAction;
|
use Shlinkio\Shlink\Rest\Action\AbstractRestAction;
|
||||||
@ -15,8 +15,6 @@ use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware;
|
|||||||
|
|
||||||
class OrphanVisitsAction extends AbstractRestAction
|
class OrphanVisitsAction extends AbstractRestAction
|
||||||
{
|
{
|
||||||
use PagerfantaUtilsTrait;
|
|
||||||
|
|
||||||
protected const ROUTE_PATH = '/visits/orphan';
|
protected const ROUTE_PATH = '/visits/orphan';
|
||||||
protected const ROUTE_ALLOWED_METHODS = [self::METHOD_GET];
|
protected const ROUTE_ALLOWED_METHODS = [self::METHOD_GET];
|
||||||
|
|
||||||
@ -30,8 +28,6 @@ class OrphanVisitsAction extends AbstractRestAction
|
|||||||
$apiKey = AuthenticationMiddleware::apiKeyFromRequest($request);
|
$apiKey = AuthenticationMiddleware::apiKeyFromRequest($request);
|
||||||
$visits = $this->visitsHelper->orphanVisits($params, $apiKey);
|
$visits = $this->visitsHelper->orphanVisits($params, $apiKey);
|
||||||
|
|
||||||
return new JsonResponse([
|
return new JsonResponse(['visits' => PagerfantaUtils::serializePaginator($visits)]);
|
||||||
'visits' => $this->serializePaginator($visits),
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ namespace Shlinkio\Shlink\Rest\Action\Visit;
|
|||||||
use Laminas\Diactoros\Response\JsonResponse;
|
use Laminas\Diactoros\Response\JsonResponse;
|
||||||
use Psr\Http\Message\ResponseInterface as Response;
|
use Psr\Http\Message\ResponseInterface as Response;
|
||||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
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\ShortUrl\Model\ShortUrlIdentifier;
|
||||||
use Shlinkio\Shlink\Core\Visit\Model\VisitsParams;
|
use Shlinkio\Shlink\Core\Visit\Model\VisitsParams;
|
||||||
use Shlinkio\Shlink\Core\Visit\VisitsStatsHelperInterface;
|
use Shlinkio\Shlink\Core\Visit\VisitsStatsHelperInterface;
|
||||||
@ -16,12 +16,10 @@ use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware;
|
|||||||
|
|
||||||
class ShortUrlVisitsAction extends AbstractRestAction
|
class ShortUrlVisitsAction extends AbstractRestAction
|
||||||
{
|
{
|
||||||
use PagerfantaUtilsTrait;
|
|
||||||
|
|
||||||
protected const ROUTE_PATH = '/short-urls/{shortCode}/visits';
|
protected const ROUTE_PATH = '/short-urls/{shortCode}/visits';
|
||||||
protected const ROUTE_ALLOWED_METHODS = [self::METHOD_GET];
|
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);
|
$apiKey = AuthenticationMiddleware::apiKeyFromRequest($request);
|
||||||
$visits = $this->visitsHelper->visitsForShortUrl($identifier, $params, $apiKey);
|
$visits = $this->visitsHelper->visitsForShortUrl($identifier, $params, $apiKey);
|
||||||
|
|
||||||
return new JsonResponse([
|
return new JsonResponse(['visits' => PagerfantaUtils::serializePaginator($visits)]);
|
||||||
'visits' => $this->serializePaginator($visits),
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ namespace Shlinkio\Shlink\Rest\Action\Visit;
|
|||||||
use Laminas\Diactoros\Response\JsonResponse;
|
use Laminas\Diactoros\Response\JsonResponse;
|
||||||
use Psr\Http\Message\ResponseInterface as Response;
|
use Psr\Http\Message\ResponseInterface as Response;
|
||||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
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\Model\VisitsParams;
|
||||||
use Shlinkio\Shlink\Core\Visit\VisitsStatsHelperInterface;
|
use Shlinkio\Shlink\Core\Visit\VisitsStatsHelperInterface;
|
||||||
use Shlinkio\Shlink\Rest\Action\AbstractRestAction;
|
use Shlinkio\Shlink\Rest\Action\AbstractRestAction;
|
||||||
@ -15,12 +15,10 @@ use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware;
|
|||||||
|
|
||||||
class TagVisitsAction extends AbstractRestAction
|
class TagVisitsAction extends AbstractRestAction
|
||||||
{
|
{
|
||||||
use PagerfantaUtilsTrait;
|
|
||||||
|
|
||||||
protected const ROUTE_PATH = '/tags/{tag}/visits';
|
protected const ROUTE_PATH = '/tags/{tag}/visits';
|
||||||
protected const ROUTE_ALLOWED_METHODS = [self::METHOD_GET];
|
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);
|
$apiKey = AuthenticationMiddleware::apiKeyFromRequest($request);
|
||||||
$visits = $this->visitsHelper->visitsForTag($tag, $params, $apiKey);
|
$visits = $this->visitsHelper->visitsForTag($tag, $params, $apiKey);
|
||||||
|
|
||||||
return new JsonResponse([
|
return new JsonResponse(['visits' => PagerfantaUtils::serializePaginator($visits)]);
|
||||||
'visits' => $this->serializePaginator($visits),
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,9 @@ use Happyr\DoctrineSpecification\Repository\EntitySpecificationRepository;
|
|||||||
use Shlinkio\Shlink\Rest\ApiKey\Model\ApiKeyMeta;
|
use Shlinkio\Shlink\Rest\ApiKey\Model\ApiKeyMeta;
|
||||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends EntitySpecificationRepository<ApiKey>
|
||||||
|
*/
|
||||||
class ApiKeyRepository extends EntitySpecificationRepository implements ApiKeyRepositoryInterface
|
class ApiKeyRepository extends EntitySpecificationRepository implements ApiKeyRepositoryInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -8,6 +8,9 @@ use Doctrine\Persistence\ObjectRepository;
|
|||||||
use Happyr\DoctrineSpecification\Repository\EntitySpecificationRepositoryInterface;
|
use Happyr\DoctrineSpecification\Repository\EntitySpecificationRepositoryInterface;
|
||||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends ObjectRepository<ApiKey>
|
||||||
|
*/
|
||||||
interface ApiKeyRepositoryInterface extends ObjectRepository, EntitySpecificationRepositoryInterface
|
interface ApiKeyRepositoryInterface extends ObjectRepository, EntitySpecificationRepositoryInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -12,12 +12,12 @@ use PHPUnit\Framework\Attributes\DataProvider;
|
|||||||
use PHPUnit\Framework\Attributes\Test;
|
use PHPUnit\Framework\Attributes\Test;
|
||||||
use PHPUnit\Framework\MockObject\MockObject;
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Shlinkio\Shlink\Common\Rest\DataTransformerInterface;
|
|
||||||
use Shlinkio\Shlink\Core\Exception\ValidationException;
|
use Shlinkio\Shlink\Core\Exception\ValidationException;
|
||||||
use Shlinkio\Shlink\Core\Options\UrlShortenerOptions;
|
use Shlinkio\Shlink\Core\Options\UrlShortenerOptions;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
|
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlCreation;
|
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlCreation;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Model\UrlShorteningResult;
|
use Shlinkio\Shlink\Core\ShortUrl\Model\UrlShorteningResult;
|
||||||
|
use Shlinkio\Shlink\Core\ShortUrl\Transformer\ShortUrlDataTransformerInterface;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\UrlShortener;
|
use Shlinkio\Shlink\Core\ShortUrl\UrlShortener;
|
||||||
use Shlinkio\Shlink\Rest\Action\ShortUrl\CreateShortUrlAction;
|
use Shlinkio\Shlink\Rest\Action\ShortUrl\CreateShortUrlAction;
|
||||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||||
@ -26,12 +26,12 @@ class CreateShortUrlActionTest extends TestCase
|
|||||||
{
|
{
|
||||||
private CreateShortUrlAction $action;
|
private CreateShortUrlAction $action;
|
||||||
private MockObject & UrlShortener $urlShortener;
|
private MockObject & UrlShortener $urlShortener;
|
||||||
private MockObject & DataTransformerInterface $transformer;
|
private MockObject & ShortUrlDataTransformerInterface $transformer;
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
$this->urlShortener = $this->createMock(UrlShortener::class);
|
$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());
|
$this->action = new CreateShortUrlAction($this->urlShortener, $this->transformer, new UrlShortenerOptions());
|
||||||
}
|
}
|
||||||
|
@ -8,11 +8,11 @@ use Laminas\Diactoros\ServerRequest;
|
|||||||
use PHPUnit\Framework\Attributes\Test;
|
use PHPUnit\Framework\Attributes\Test;
|
||||||
use PHPUnit\Framework\MockObject\MockObject;
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Shlinkio\Shlink\Common\Rest\DataTransformerInterface;
|
|
||||||
use Shlinkio\Shlink\Core\Options\UrlShortenerOptions;
|
use Shlinkio\Shlink\Core\Options\UrlShortenerOptions;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
|
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlCreation;
|
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlCreation;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\Model\UrlShorteningResult;
|
use Shlinkio\Shlink\Core\ShortUrl\Model\UrlShorteningResult;
|
||||||
|
use Shlinkio\Shlink\Core\ShortUrl\Transformer\ShortUrlDataTransformerInterface;
|
||||||
use Shlinkio\Shlink\Core\ShortUrl\UrlShortenerInterface;
|
use Shlinkio\Shlink\Core\ShortUrl\UrlShortenerInterface;
|
||||||
use Shlinkio\Shlink\Rest\Action\ShortUrl\SingleStepCreateShortUrlAction;
|
use Shlinkio\Shlink\Rest\Action\ShortUrl\SingleStepCreateShortUrlAction;
|
||||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||||
@ -25,7 +25,7 @@ class SingleStepCreateShortUrlActionTest extends TestCase
|
|||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
$this->urlShortener = $this->createMock(UrlShortenerInterface::class);
|
$this->urlShortener = $this->createMock(UrlShortenerInterface::class);
|
||||||
$transformer = $this->createMock(DataTransformerInterface::class);
|
$transformer = $this->createMock(ShortUrlDataTransformerInterface::class);
|
||||||
$transformer->method('transform')->willReturn([]);
|
$transformer->method('transform')->willReturn([]);
|
||||||
|
|
||||||
$this->action = new SingleStepCreateShortUrlAction(
|
$this->action = new SingleStepCreateShortUrlAction(
|
||||||
|
@ -12,5 +12,4 @@ parameters:
|
|||||||
ignoreErrors:
|
ignoreErrors:
|
||||||
- '#should return int<0, max> but returns int#'
|
- '#should return int<0, max> but returns int#'
|
||||||
- '#expects -1\|int<1, max>, int given#'
|
- '#expects -1\|int<1, max>, int given#'
|
||||||
- identifier: missingType.generics
|
|
||||||
- identifier: missingType.iterableValue
|
- identifier: missingType.iterableValue
|
||||||
|
Loading…
Reference in New Issue
Block a user