mirror of
https://github.com/shlinkio/shlink.git
synced 2026-03-10 17:23:12 +08:00
Added logic to exclude bots from visits when requested
This commit is contained in:
@@ -53,6 +53,11 @@ final class Visitor
|
||||
return new self('', '', null, '');
|
||||
}
|
||||
|
||||
public static function botInstance(): self
|
||||
{
|
||||
return new self('cf-facebook', '', null, '');
|
||||
}
|
||||
|
||||
public function getUserAgent(): string
|
||||
{
|
||||
return $this->userAgent;
|
||||
|
||||
@@ -114,6 +114,10 @@ class VisitRepository extends EntitySpecificationRepository implements VisitRepo
|
||||
$qb->from(Visit::class, 'v')
|
||||
->where($qb->expr()->eq('v.shortUrl', $shortUrlId));
|
||||
|
||||
if ($filtering->excludeBots()) {
|
||||
$qb->andWhere($qb->expr()->eq('v.potentialBot', 'false'));
|
||||
}
|
||||
|
||||
// Apply date range filtering
|
||||
$this->applyDatesInline($qb, $filtering->dateRange());
|
||||
|
||||
@@ -144,6 +148,10 @@ class VisitRepository extends EntitySpecificationRepository implements VisitRepo
|
||||
->join('s.tags', 't')
|
||||
->where($qb->expr()->eq('t.name', '\'' . $tag . '\'')); // This needs to be concatenated, not bound
|
||||
|
||||
if ($filtering->excludeBots()) {
|
||||
$qb->andWhere($qb->expr()->eq('v.potentialBot', 'false'));
|
||||
}
|
||||
|
||||
$this->applyDatesInline($qb, $filtering->dateRange());
|
||||
$this->applySpecification($qb, $filtering->spec(), 'v');
|
||||
|
||||
@@ -158,6 +166,10 @@ class VisitRepository extends EntitySpecificationRepository implements VisitRepo
|
||||
$qb->from(Visit::class, 'v')
|
||||
->where($qb->expr()->isNull('v.shortUrl'));
|
||||
|
||||
if ($filtering->excludeBots()) {
|
||||
$qb->andWhere($qb->expr()->eq('v.potentialBot', 'false'));
|
||||
}
|
||||
|
||||
$this->applyDatesInline($qb, $filtering->dateRange());
|
||||
|
||||
return $this->resolveVisitsWithNativeQuery($qb, $filtering->limit(), $filtering->offset());
|
||||
@@ -165,7 +177,7 @@ class VisitRepository extends EntitySpecificationRepository implements VisitRepo
|
||||
|
||||
public function countOrphanVisits(VisitsCountFiltering $filtering): int
|
||||
{
|
||||
return (int) $this->matchSingleScalarResult(new CountOfOrphanVisits($filtering->dateRange()));
|
||||
return (int) $this->matchSingleScalarResult(new CountOfOrphanVisits($filtering));
|
||||
}
|
||||
|
||||
public function countVisits(?ApiKey $apiKey = null): int
|
||||
|
||||
@@ -7,24 +7,30 @@ namespace Shlinkio\Shlink\Core\Visit\Spec;
|
||||
use Happyr\DoctrineSpecification\Spec;
|
||||
use Happyr\DoctrineSpecification\Specification\BaseSpecification;
|
||||
use Happyr\DoctrineSpecification\Specification\Specification;
|
||||
use Shlinkio\Shlink\Common\Util\DateRange;
|
||||
use Shlinkio\Shlink\Core\Spec\InDateRange;
|
||||
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsCountFiltering;
|
||||
|
||||
class CountOfOrphanVisits extends BaseSpecification
|
||||
{
|
||||
private ?DateRange $dateRange;
|
||||
private VisitsCountFiltering $filtering;
|
||||
|
||||
public function __construct(?DateRange $dateRange)
|
||||
public function __construct(VisitsCountFiltering $filtering)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->dateRange = $dateRange;
|
||||
$this->filtering = $filtering;
|
||||
}
|
||||
|
||||
protected function getSpec(): Specification
|
||||
{
|
||||
return Spec::countOf(Spec::andX(
|
||||
$conditions = [
|
||||
Spec::isNull('shortUrl'),
|
||||
new InDateRange($this->dateRange),
|
||||
));
|
||||
new InDateRange($this->filtering->dateRange()),
|
||||
];
|
||||
|
||||
if ($this->filtering->excludeBots()) {
|
||||
$conditions[] = Spec::eq('potentialBot', false);
|
||||
}
|
||||
|
||||
return Spec::countOf(Spec::andX(...$conditions));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user