Added new models to pass to repositories when listing visits of any kind

This commit is contained in:
Alejandro Celaya
2021-05-22 20:32:30 +02:00
parent 6327ed814a
commit db3c5a3031
10 changed files with 116 additions and 101 deletions

View File

@@ -7,6 +7,7 @@ namespace Shlinkio\Shlink\Core\Paginator\Adapter;
use Shlinkio\Shlink\Core\Model\VisitsParams;
use Shlinkio\Shlink\Core\Repository\VisitRepositoryInterface;
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsCountFiltering;
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsListFiltering;
class OrphanVisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdapter
{
@@ -26,6 +27,12 @@ class OrphanVisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdapte
public function getSlice($offset, $length): iterable // phpcs:ignore
{
return $this->repo->findOrphanVisits($this->params->getDateRange(), $length, $offset);
return $this->repo->findOrphanVisits(new VisitsListFiltering(
$this->params->getDateRange(),
$this->params->excludeBots(),
null,
$length,
$offset,
));
}
}

View File

@@ -8,6 +8,7 @@ use Happyr\DoctrineSpecification\Specification\Specification;
use Shlinkio\Shlink\Core\Model\VisitsParams;
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 VisitsForTagPaginatorAdapter extends AbstractCacheableCountPaginatorAdapter
@@ -33,10 +34,13 @@ class VisitsForTagPaginatorAdapter extends AbstractCacheableCountPaginatorAdapte
{
return $this->visitRepository->findVisitsByTag(
$this->tag,
$this->params->getDateRange(),
$length,
$offset,
$this->resolveSpec(),
new VisitsListFiltering(
$this->params->getDateRange(),
$this->params->excludeBots(),
$this->resolveSpec(),
$length,
$offset,
),
);
}

View File

@@ -9,6 +9,7 @@ use Shlinkio\Shlink\Core\Model\ShortUrlIdentifier;
use Shlinkio\Shlink\Core\Model\VisitsParams;
use Shlinkio\Shlink\Core\Repository\VisitRepositoryInterface;
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsCountFiltering;
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsListFiltering;
class VisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdapter
{
@@ -34,10 +35,13 @@ class VisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdapter
return $this->visitRepository->findVisitsByShortCode(
$this->identifier->shortCode(),
$this->identifier->domain(),
$this->params->getDateRange(),
$length,
$offset,
$this->spec,
new VisitsListFiltering(
$this->params->getDateRange(),
$this->params->excludeBots(),
$this->spec,
$length,
$offset,
),
);
}

View File

@@ -7,12 +7,12 @@ namespace Shlinkio\Shlink\Core\Repository;
use Doctrine\ORM\Query\ResultSetMappingBuilder;
use Doctrine\ORM\QueryBuilder;
use Happyr\DoctrineSpecification\Repository\EntitySpecificationRepository;
use Happyr\DoctrineSpecification\Specification\Specification;
use Shlinkio\Shlink\Common\Util\DateRange;
use Shlinkio\Shlink\Core\Entity\ShortUrl;
use Shlinkio\Shlink\Core\Entity\Visit;
use Shlinkio\Shlink\Core\Entity\VisitLocation;
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsCountFiltering;
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsListFiltering;
use Shlinkio\Shlink\Core\Visit\Spec\CountOfOrphanVisits;
use Shlinkio\Shlink\Core\Visit\Spec\CountOfShortUrlVisits;
use Shlinkio\Shlink\Rest\Entity\ApiKey;
@@ -84,21 +84,15 @@ class VisitRepository extends EntitySpecificationRepository implements VisitRepo
/**
* @return Visit[]
*/
public function findVisitsByShortCode(
string $shortCode,
?string $domain = null,
?DateRange $dateRange = null,
?int $limit = null,
?int $offset = null,
?Specification $spec = null
): array {
$qb = $this->createVisitsByShortCodeQueryBuilder($shortCode, $domain, $dateRange, $spec);
return $this->resolveVisitsWithNativeQuery($qb, $limit, $offset);
public function findVisitsByShortCode(string $shortCode, ?string $domain, VisitsListFiltering $filtering): array
{
$qb = $this->createVisitsByShortCodeQueryBuilder($shortCode, $domain, $filtering);
return $this->resolveVisitsWithNativeQuery($qb, $filtering->limit(), $filtering->offset());
}
public function countVisitsByShortCode(string $shortCode, ?string $domain, VisitsCountFiltering $filtering): int
{
$qb = $this->createVisitsByShortCodeQueryBuilder($shortCode, $domain, $filtering->dateRange(), $filtering->spec());
$qb = $this->createVisitsByShortCodeQueryBuilder($shortCode, $domain, $filtering);
$qb->select('COUNT(v.id)');
return (int) $qb->getQuery()->getSingleScalarResult();
@@ -107,12 +101,11 @@ class VisitRepository extends EntitySpecificationRepository implements VisitRepo
private function createVisitsByShortCodeQueryBuilder(
string $shortCode,
?string $domain,
?DateRange $dateRange,
?Specification $spec = null
VisitsCountFiltering $filtering
): QueryBuilder {
/** @var ShortUrlRepositoryInterface $shortUrlRepo */
$shortUrlRepo = $this->getEntityManager()->getRepository(ShortUrl::class);
$shortUrl = $shortUrlRepo->findOne($shortCode, $domain, $spec);
$shortUrl = $shortUrlRepo->findOne($shortCode, $domain, $filtering->spec());
$shortUrlId = $shortUrl !== null ? $shortUrl->getId() : -1;
// Parameters in this query need to be part of the query itself, as we need to use it a sub-query later
@@ -122,35 +115,27 @@ class VisitRepository extends EntitySpecificationRepository implements VisitRepo
->where($qb->expr()->eq('v.shortUrl', $shortUrlId));
// Apply date range filtering
$this->applyDatesInline($qb, $dateRange);
$this->applyDatesInline($qb, $filtering->dateRange());
return $qb;
}
public function findVisitsByTag(
string $tag,
?DateRange $dateRange = null,
?int $limit = null,
?int $offset = null,
?Specification $spec = null
): array {
$qb = $this->createVisitsByTagQueryBuilder($tag, $dateRange, $spec);
return $this->resolveVisitsWithNativeQuery($qb, $limit, $offset);
public function findVisitsByTag(string $tag, VisitsListFiltering $filtering): array
{
$qb = $this->createVisitsByTagQueryBuilder($tag, $filtering);
return $this->resolveVisitsWithNativeQuery($qb, $filtering->limit(), $filtering->offset());
}
public function countVisitsByTag(string $tag, VisitsCountFiltering $filtering): int
{
$qb = $this->createVisitsByTagQueryBuilder($tag, $filtering->dateRange(), $filtering->spec());
$qb = $this->createVisitsByTagQueryBuilder($tag, $filtering);
$qb->select('COUNT(v.id)');
return (int) $qb->getQuery()->getSingleScalarResult();
}
private function createVisitsByTagQueryBuilder(
string $tag,
?DateRange $dateRange,
?Specification $spec
): QueryBuilder {
private function createVisitsByTagQueryBuilder(string $tag, VisitsCountFiltering $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
$qb = $this->getEntityManager()->createQueryBuilder();
@@ -159,13 +144,13 @@ class VisitRepository extends EntitySpecificationRepository implements VisitRepo
->join('s.tags', 't')
->where($qb->expr()->eq('t.name', '\'' . $tag . '\'')); // This needs to be concatenated, not bound
$this->applyDatesInline($qb, $dateRange);
$this->applySpecification($qb, $spec, 'v');
$this->applyDatesInline($qb, $filtering->dateRange());
$this->applySpecification($qb, $filtering->spec(), 'v');
return $qb;
}
public function findOrphanVisits(?DateRange $dateRange = null, ?int $limit = null, ?int $offset = null): array
public function findOrphanVisits(VisitsListFiltering $filtering): array
{
// 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
@@ -173,9 +158,9 @@ class VisitRepository extends EntitySpecificationRepository implements VisitRepo
$qb->from(Visit::class, 'v')
->where($qb->expr()->isNull('v.shortUrl'));
$this->applyDatesInline($qb, $dateRange);
$this->applyDatesInline($qb, $filtering->dateRange());
return $this->resolveVisitsWithNativeQuery($qb, $limit, $offset);
return $this->resolveVisitsWithNativeQuery($qb, $filtering->limit(), $filtering->offset());
}
public function countOrphanVisits(VisitsCountFiltering $filtering): int

View File

@@ -6,10 +6,9 @@ namespace Shlinkio\Shlink\Core\Repository;
use Doctrine\Persistence\ObjectRepository;
use Happyr\DoctrineSpecification\Repository\EntitySpecificationRepositoryInterface;
use Happyr\DoctrineSpecification\Specification\Specification;
use Shlinkio\Shlink\Common\Util\DateRange;
use Shlinkio\Shlink\Core\Entity\Visit;
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsCountFiltering;
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsListFiltering;
use Shlinkio\Shlink\Rest\Entity\ApiKey;
interface VisitRepositoryInterface extends ObjectRepository, EntitySpecificationRepositoryInterface
@@ -34,34 +33,21 @@ interface VisitRepositoryInterface extends ObjectRepository, EntitySpecification
/**
* @return Visit[]
*/
public function findVisitsByShortCode(
string $shortCode,
?string $domain = null,
?DateRange $dateRange = null,
?int $limit = null,
?int $offset = null,
?Specification $spec = null
): array;
public function findVisitsByShortCode(string $shortCode, ?string $domain, VisitsListFiltering $filtering): array;
public function countVisitsByShortCode(string $shortCode, ?string $domain, VisitsCountFiltering $filtering): int;
/**
* @return Visit[]
*/
public function findVisitsByTag(
string $tag,
?DateRange $dateRange = null,
?int $limit = null,
?int $offset = null,
?Specification $spec = null
): array;
public function findVisitsByTag(string $tag, VisitsListFiltering $filtering): array;
public function countVisitsByTag(string $tag, VisitsCountFiltering $filtering): int;
/**
* @return Visit[]
*/
public function findOrphanVisits(?DateRange $dateRange = null, ?int $limit = null, ?int $offset = null): array;
public function findOrphanVisits(VisitsListFiltering $filtering): array;
public function countOrphanVisits(VisitsCountFiltering $filtering): int;