mirror of
https://github.com/shlinkio/shlink.git
synced 2024-12-28 18:01:04 -06:00
Changed VisitsCountFiltering and VisitsListFiltering so that they encapsulate an ApiKey instead of a Spec
This commit is contained in:
parent
3436405c55
commit
60c0ca3ae5
@ -104,10 +104,10 @@ class VisitRepository extends EntitySpecificationRepository implements VisitRepo
|
||||
): QueryBuilder {
|
||||
/** @var ShortUrlRepositoryInterface $shortUrlRepo */
|
||||
$shortUrlRepo = $this->getEntityManager()->getRepository(ShortUrl::class);
|
||||
$shortUrlId = $shortUrlRepo->findOne($identifier, $filtering->spec())?->getId() ?? '-1';
|
||||
$shortUrlId = $shortUrlRepo->findOne($identifier, $filtering->apiKey()?->spec())?->getId() ?? '-1';
|
||||
|
||||
// Parameters in this query need to be part of the query itself, as we need to use it a sub-query later
|
||||
// Since they are not strictly provided by the caller, it's reasonably safe
|
||||
// Since they are not provided by the caller, it's reasonably safe
|
||||
$qb = $this->getEntityManager()->createQueryBuilder();
|
||||
$qb->from(Visit::class, 'v')
|
||||
->where($qb->expr()->eq('v.shortUrl', $shortUrlId));
|
||||
@ -150,7 +150,7 @@ class VisitRepository extends EntitySpecificationRepository implements VisitRepo
|
||||
}
|
||||
|
||||
$this->applyDatesInline($qb, $filtering->dateRange());
|
||||
$this->applySpecification($qb, $filtering->spec(), 'v'); // FIXME This is actually binding arguments
|
||||
$this->applySpecification($qb, $filtering->apiKey()?->spec(true), 'v');
|
||||
|
||||
return $qb;
|
||||
}
|
||||
@ -175,11 +175,13 @@ class VisitRepository extends EntitySpecificationRepository implements VisitRepo
|
||||
$qb = $this->createAllVisitsQueryBuilder($filtering);
|
||||
$qb->andWhere($qb->expr()->isNotNull('v.shortUrl'));
|
||||
|
||||
$this->applySpecification($qb, $filtering->spec());
|
||||
$this->applySpecification($qb, $filtering->apiKey()?->spec(true));
|
||||
|
||||
return $this->resolveVisitsWithNativeQuery($qb, $filtering->limit(), $filtering->offset());
|
||||
}
|
||||
|
||||
// TODO This should support counting in a date range or excluding bots
|
||||
// TODO Rename to countNonOrphanVisits
|
||||
public function countVisits(?ApiKey $apiKey = null): int
|
||||
{
|
||||
return (int) $this->matchSingleScalarResult(new CountOfShortUrlVisits($apiKey));
|
||||
@ -188,7 +190,7 @@ class VisitRepository extends EntitySpecificationRepository implements VisitRepo
|
||||
private function createAllVisitsQueryBuilder(VisitsListFiltering $filtering): QueryBuilder
|
||||
{
|
||||
// Parameters in this query need to be inlined, not bound, as we need to use it as sub-query later
|
||||
// Since they are not strictly provided by the caller, it's reasonably safe
|
||||
// Since they are not provided by the caller, it's reasonably safe
|
||||
$qb = $this->getEntityManager()->createQueryBuilder();
|
||||
$qb->from(Visit::class, 'v');
|
||||
|
||||
|
@ -12,6 +12,7 @@ use Shlinkio\Shlink\Core\Visit\Persistence\VisitsCountFiltering;
|
||||
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsListFiltering;
|
||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||
|
||||
// TODO Split into VisitsListsRepository and VisitsLocationRepository
|
||||
interface VisitRepositoryInterface extends ObjectRepository, EntitySpecificationRepositoryInterface
|
||||
{
|
||||
public const DEFAULT_BLOCK_SIZE = 10000;
|
||||
|
@ -4,13 +4,13 @@ declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\Core\Visit\Paginator\Adapter;
|
||||
|
||||
use Happyr\DoctrineSpecification\Specification\Specification;
|
||||
use Shlinkio\Shlink\Core\Model\ShortUrlIdentifier;
|
||||
use Shlinkio\Shlink\Core\Model\VisitsParams;
|
||||
use Shlinkio\Shlink\Core\Paginator\Adapter\AbstractCacheableCountPaginatorAdapter;
|
||||
use Shlinkio\Shlink\Core\Repository\VisitRepositoryInterface;
|
||||
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsCountFiltering;
|
||||
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsListFiltering;
|
||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||
|
||||
class ShortUrlVisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdapter
|
||||
{
|
||||
@ -18,7 +18,7 @@ class ShortUrlVisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdap
|
||||
private VisitRepositoryInterface $visitRepository,
|
||||
private ShortUrlIdentifier $identifier,
|
||||
private VisitsParams $params,
|
||||
private ?Specification $spec,
|
||||
private ?ApiKey $apiKey,
|
||||
) {
|
||||
}
|
||||
|
||||
@ -29,7 +29,7 @@ class ShortUrlVisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdap
|
||||
new VisitsListFiltering(
|
||||
$this->params->getDateRange(),
|
||||
$this->params->excludeBots(),
|
||||
$this->spec,
|
||||
$this->apiKey,
|
||||
$length,
|
||||
$offset,
|
||||
),
|
||||
@ -43,7 +43,7 @@ class ShortUrlVisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdap
|
||||
new VisitsCountFiltering(
|
||||
$this->params->getDateRange(),
|
||||
$this->params->excludeBots(),
|
||||
$this->spec,
|
||||
$this->apiKey,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ class TagVisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdapter
|
||||
new VisitsListFiltering(
|
||||
$this->params->getDateRange(),
|
||||
$this->params->excludeBots(),
|
||||
$this->apiKey?->spec(true),
|
||||
$this->apiKey,
|
||||
$length,
|
||||
$offset,
|
||||
),
|
||||
@ -42,7 +42,7 @@ class TagVisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdapter
|
||||
new VisitsCountFiltering(
|
||||
$this->params->getDateRange(),
|
||||
$this->params->excludeBots(),
|
||||
$this->apiKey?->spec(true),
|
||||
$this->apiKey,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -4,15 +4,15 @@ declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\Core\Visit\Persistence;
|
||||
|
||||
use Happyr\DoctrineSpecification\Specification\Specification;
|
||||
use Shlinkio\Shlink\Common\Util\DateRange;
|
||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||
|
||||
class VisitsCountFiltering
|
||||
{
|
||||
public function __construct(
|
||||
private ?DateRange $dateRange = null,
|
||||
private bool $excludeBots = false,
|
||||
private ?Specification $spec = null,
|
||||
private ?ApiKey $apiKey = null,
|
||||
) {
|
||||
}
|
||||
|
||||
@ -26,8 +26,8 @@ class VisitsCountFiltering
|
||||
return $this->excludeBots;
|
||||
}
|
||||
|
||||
public function spec(): ?Specification
|
||||
public function apiKey(): ?ApiKey
|
||||
{
|
||||
return $this->spec;
|
||||
return $this->apiKey;
|
||||
}
|
||||
}
|
||||
|
@ -4,19 +4,19 @@ declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\Core\Visit\Persistence;
|
||||
|
||||
use Happyr\DoctrineSpecification\Specification\Specification;
|
||||
use Shlinkio\Shlink\Common\Util\DateRange;
|
||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||
|
||||
final class VisitsListFiltering extends VisitsCountFiltering
|
||||
{
|
||||
public function __construct(
|
||||
?DateRange $dateRange = null,
|
||||
bool $excludeBots = false,
|
||||
?Specification $spec = null,
|
||||
?ApiKey $apiKey = null,
|
||||
private ?int $limit = null,
|
||||
private ?int $offset = null,
|
||||
) {
|
||||
parent::__construct($dateRange, $excludeBots, $spec);
|
||||
parent::__construct($dateRange, $excludeBots, $apiKey);
|
||||
}
|
||||
|
||||
public function limit(): ?int
|
||||
|
@ -51,18 +51,19 @@ class VisitsStatsHelper implements VisitsStatsHelperInterface
|
||||
VisitsParams $params,
|
||||
?ApiKey $apiKey = null,
|
||||
): Paginator {
|
||||
$spec = $apiKey?->spec();
|
||||
|
||||
/** @var ShortUrlRepositoryInterface $repo */
|
||||
$repo = $this->em->getRepository(ShortUrl::class);
|
||||
if (! $repo->shortCodeIsInUse($identifier, $spec)) {
|
||||
if (! $repo->shortCodeIsInUse($identifier, $apiKey?->spec())) {
|
||||
throw ShortUrlNotFoundException::fromNotFound($identifier);
|
||||
}
|
||||
|
||||
/** @var VisitRepositoryInterface $repo */
|
||||
$repo = $this->em->getRepository(Visit::class);
|
||||
|
||||
return $this->createPaginator(new ShortUrlVisitsPaginatorAdapter($repo, $identifier, $params, $spec), $params);
|
||||
return $this->createPaginator(
|
||||
new ShortUrlVisitsPaginatorAdapter($repo, $identifier, $params, $apiKey),
|
||||
$params,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -192,19 +192,19 @@ class VisitRepositoryTest extends DatabaseTestCase
|
||||
|
||||
self::assertNotEmpty($this->repo->findVisitsByShortCode(
|
||||
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode1),
|
||||
new VisitsListFiltering(null, false, $adminApiKey->spec()),
|
||||
new VisitsListFiltering(null, false, $adminApiKey),
|
||||
));
|
||||
self::assertNotEmpty($this->repo->findVisitsByShortCode(
|
||||
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode2),
|
||||
new VisitsListFiltering(null, false, $adminApiKey->spec()),
|
||||
new VisitsListFiltering(null, false, $adminApiKey),
|
||||
));
|
||||
self::assertEmpty($this->repo->findVisitsByShortCode(
|
||||
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode1),
|
||||
new VisitsListFiltering(null, false, $restrictedApiKey->spec()),
|
||||
new VisitsListFiltering(null, false, $restrictedApiKey),
|
||||
));
|
||||
self::assertNotEmpty($this->repo->findVisitsByShortCode(
|
||||
ShortUrlIdentifier::fromShortCodeAndDomain($shortCode2),
|
||||
new VisitsListFiltering(null, false, $restrictedApiKey->spec()),
|
||||
new VisitsListFiltering(null, false, $restrictedApiKey),
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ class VisitsForTagPaginatorAdapterTest extends TestCase
|
||||
$adapter = $this->createAdapter($apiKey);
|
||||
$countVisits = $this->repo->countVisitsByTag(
|
||||
'foo',
|
||||
new VisitsCountFiltering(DateRange::emptyInstance(), false, $apiKey->spec()),
|
||||
new VisitsCountFiltering(DateRange::emptyInstance(), false, $apiKey),
|
||||
)->willReturn(3);
|
||||
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
|
@ -54,7 +54,7 @@ class VisitsPaginatorAdapterTest extends TestCase
|
||||
$adapter = $this->createAdapter($apiKey);
|
||||
$countVisits = $this->repo->countVisitsByShortCode(
|
||||
ShortUrlIdentifier::fromShortCodeAndDomain(''),
|
||||
new VisitsCountFiltering(DateRange::emptyInstance(), false, $apiKey->spec()),
|
||||
new VisitsCountFiltering(DateRange::emptyInstance(), false, $apiKey),
|
||||
)->willReturn(3);
|
||||
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
@ -70,7 +70,7 @@ class VisitsPaginatorAdapterTest extends TestCase
|
||||
$this->repo->reveal(),
|
||||
new ShortUrlIdentifier(''),
|
||||
VisitsParams::fromRawData([]),
|
||||
$apiKey?->spec(),
|
||||
$apiKey,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user