mirror of
https://github.com/shlinkio/shlink.git
synced 2026-02-28 04:03:12 +08:00
Allow filtering by domain in VisitRepository::findOrphanVisits
This commit is contained in:
@@ -21,7 +21,6 @@ use Shlinkio\Shlink\Core\Visit\Persistence\VisitsListFiltering;
|
||||
use Shlinkio\Shlink\Core\Visit\Persistence\WithDomainVisitsCountFiltering;
|
||||
use Shlinkio\Shlink\Core\Visit\Persistence\WithDomainVisitsListFiltering;
|
||||
use Shlinkio\Shlink\Core\Visit\Spec\CountOfNonOrphanVisits;
|
||||
use Shlinkio\Shlink\Core\Visit\Spec\CountOfOrphanVisits;
|
||||
use Shlinkio\Shlink\Rest\ApiKey\Role;
|
||||
use Shlinkio\Shlink\Rest\Entity\ApiKey;
|
||||
|
||||
@@ -161,15 +160,7 @@ class VisitRepository extends EntitySpecificationRepository implements VisitRepo
|
||||
return [];
|
||||
}
|
||||
|
||||
$qb = $this->createAllVisitsQueryBuilder($filtering);
|
||||
$qb->andWhere($qb->expr()->isNull('v.shortUrl'));
|
||||
|
||||
// Parameters in this query need to be inlined, not bound, as we need to use it as sub-query later
|
||||
if ($filtering->type) {
|
||||
$conn = $this->getEntityManager()->getConnection();
|
||||
$qb->andWhere($qb->expr()->eq('v.type', $conn->quote($filtering->type->value)));
|
||||
}
|
||||
|
||||
$qb = $this->createOrphanVisitsQueryBuilder($filtering);
|
||||
return $this->resolveVisitsWithNativeQuery($qb, $filtering->limit, $filtering->offset);
|
||||
}
|
||||
|
||||
@@ -179,7 +170,32 @@ class VisitRepository extends EntitySpecificationRepository implements VisitRepo
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int) $this->matchSingleScalarResult(new CountOfOrphanVisits($filtering));
|
||||
$qb = $this->createOrphanVisitsQueryBuilder($filtering);
|
||||
$qb->select('COUNT(v.id)');
|
||||
|
||||
return (int) $qb->getQuery()->getSingleScalarResult();
|
||||
}
|
||||
|
||||
private function createOrphanVisitsQueryBuilder(OrphanVisitsCountFiltering $filtering): QueryBuilder
|
||||
{
|
||||
$qb = $this->createAllVisitsQueryBuilder($filtering);
|
||||
$qb->andWhere($qb->expr()->isNull('v.shortUrl'));
|
||||
|
||||
// Parameters in this query need to be inlined, not bound, as we need to use it as sub-query later
|
||||
$conn = $this->getEntityManager()->getConnection();
|
||||
|
||||
if ($filtering->type) {
|
||||
$qb->andWhere($qb->expr()->eq('v.type', $conn->quote($filtering->type->value)));
|
||||
}
|
||||
|
||||
$domain = $filtering->domain;
|
||||
if ($domain === Domain::DEFAULT_AUTHORITY) {
|
||||
// TODO
|
||||
} elseif ($domain !== null) {
|
||||
$qb->andWhere($qb->expr()->like('v.visitedUrl', $conn->quote('%' . $domain . '%')));
|
||||
}
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\Core\Visit\Spec;
|
||||
|
||||
use Happyr\DoctrineSpecification\Spec;
|
||||
use Happyr\DoctrineSpecification\Specification\BaseSpecification;
|
||||
use Happyr\DoctrineSpecification\Specification\Specification;
|
||||
use Shlinkio\Shlink\Core\Spec\InDateRange;
|
||||
use Shlinkio\Shlink\Core\Visit\Persistence\OrphanVisitsCountFiltering;
|
||||
|
||||
class CountOfOrphanVisits extends BaseSpecification
|
||||
{
|
||||
public function __construct(private readonly OrphanVisitsCountFiltering $filtering)
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function getSpec(): Specification
|
||||
{
|
||||
$conditions = [
|
||||
Spec::isNull('shortUrl'),
|
||||
new InDateRange($this->filtering->dateRange),
|
||||
];
|
||||
|
||||
if ($this->filtering->excludeBots) {
|
||||
$conditions[] = Spec::eq('potentialBot', false);
|
||||
}
|
||||
|
||||
if ($this->filtering->type) {
|
||||
$conditions[] = Spec::eq('type', $this->filtering->type->value);
|
||||
}
|
||||
|
||||
return Spec::countOf(Spec::andX(...$conditions));
|
||||
}
|
||||
}
|
||||
@@ -399,7 +399,7 @@ class VisitRepositoryTest extends DatabaseTestCase
|
||||
Chronos::parse(sprintf('2020-01-0%s', $i + 1)),
|
||||
));
|
||||
$this->getEntityManager()->persist($this->setDateOnVisit(
|
||||
fn () => Visit::forRegularNotFound(Visitor::empty()),
|
||||
fn () => Visit::forRegularNotFound(Visitor::fromParams(visitedUrl: 'https://example.com/foo?1=2')),
|
||||
Chronos::parse(sprintf('2020-01-0%s', $i + 1)),
|
||||
));
|
||||
|
||||
@@ -438,6 +438,7 @@ class VisitRepositoryTest extends DatabaseTestCase
|
||||
type: OrphanVisitType::BASE_URL,
|
||||
limit: 4,
|
||||
)));
|
||||
self::assertCount(6, $this->repo->findOrphanVisits(new OrphanVisitsListFiltering(domain: 'example.com')));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
@@ -457,7 +458,7 @@ class VisitRepositoryTest extends DatabaseTestCase
|
||||
Chronos::parse(sprintf('2020-01-0%s', $i + 1)),
|
||||
));
|
||||
$this->getEntityManager()->persist($this->setDateOnVisit(
|
||||
fn () => Visit::forRegularNotFound(Visitor::empty()),
|
||||
fn () => Visit::forRegularNotFound(Visitor::fromParams(visitedUrl: 'https://example.com/foo/bar')),
|
||||
Chronos::parse(sprintf('2020-01-0%s', $i + 1)),
|
||||
));
|
||||
}
|
||||
@@ -486,6 +487,9 @@ class VisitRepositoryTest extends DatabaseTestCase
|
||||
self::assertEquals(6, $this->repo->countOrphanVisits(new OrphanVisitsCountFiltering(
|
||||
type: OrphanVisitType::REGULAR_404,
|
||||
)));
|
||||
self::assertEquals(6, $this->repo->countOrphanVisits(new OrphanVisitsCountFiltering(
|
||||
domain: 'example.com',
|
||||
)));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
|
||||
Reference in New Issue
Block a user