mirror of
https://github.com/shlinkio/shlink.git
synced 2025-12-10 11:05:50 -06:00
Allow filtering by domain in VisitRepository::findOrphanVisits
This commit is contained in:
parent
9dcc51abde
commit
94426c7bf4
@ -20,9 +20,9 @@
|
||||
"ext-pdo": "*",
|
||||
"akrabat/ip-address-middleware": "^2.6",
|
||||
"cakephp/chronos": "^3.1",
|
||||
"doctrine/dbal": "^4.2",
|
||||
"doctrine/migrations": "^3.8",
|
||||
"doctrine/orm": "^3.3",
|
||||
"doctrine/dbal": "^4.3",
|
||||
"doctrine/migrations": "^3.9",
|
||||
"doctrine/orm": "^3.5",
|
||||
"donatj/phpuseragentparser": "^1.10",
|
||||
"endroid/qr-code": "^6.0.5",
|
||||
"friendsofphp/proxy-manager-lts": "^1.0",
|
||||
|
||||
@ -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]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user