mirror of
https://github.com/shlinkio/shlink.git
synced 2024-12-26 08:51:13 -06:00
Added option to disable orphan visitstracking
This commit is contained in:
parent
a18486cc2e
commit
2fc6fb0a9a
@ -20,6 +20,7 @@ return [
|
|||||||
'redirect_status_code' => DEFAULT_REDIRECT_STATUS_CODE,
|
'redirect_status_code' => DEFAULT_REDIRECT_STATUS_CODE,
|
||||||
'redirect_cache_lifetime' => DEFAULT_REDIRECT_CACHE_LIFETIME,
|
'redirect_cache_lifetime' => DEFAULT_REDIRECT_CACHE_LIFETIME,
|
||||||
'auto_resolve_titles' => false,
|
'auto_resolve_titles' => false,
|
||||||
|
'track_orphan_visits' => true,
|
||||||
],
|
],
|
||||||
|
|
||||||
];
|
];
|
||||||
|
@ -126,6 +126,7 @@ return [
|
|||||||
'redirect_status_code' => (int) env('REDIRECT_STATUS_CODE', DEFAULT_REDIRECT_STATUS_CODE),
|
'redirect_status_code' => (int) env('REDIRECT_STATUS_CODE', DEFAULT_REDIRECT_STATUS_CODE),
|
||||||
'redirect_cache_lifetime' => (int) env('REDIRECT_CACHE_LIFETIME', DEFAULT_REDIRECT_CACHE_LIFETIME),
|
'redirect_cache_lifetime' => (int) env('REDIRECT_CACHE_LIFETIME', DEFAULT_REDIRECT_CACHE_LIFETIME),
|
||||||
'auto_resolve_titles' => (bool) env('AUTO_RESOLVE_TITLES', false),
|
'auto_resolve_titles' => (bool) env('AUTO_RESOLVE_TITLES', false),
|
||||||
|
'track_orphan_visits' => (bool) env('TRACK_ORPHAN_VISITS', true),
|
||||||
],
|
],
|
||||||
|
|
||||||
'not_found_redirects' => $helper->getNotFoundRedirectsConfig(),
|
'not_found_redirects' => $helper->getNotFoundRedirectsConfig(),
|
||||||
|
@ -85,7 +85,7 @@ return [
|
|||||||
Visit\VisitsTracker::class => [
|
Visit\VisitsTracker::class => [
|
||||||
'em',
|
'em',
|
||||||
EventDispatcherInterface::class,
|
EventDispatcherInterface::class,
|
||||||
'config.url_shortener.anonymize_remote_addr',
|
Options\UrlShortenerOptions::class,
|
||||||
],
|
],
|
||||||
Service\ShortUrlService::class => [
|
Service\ShortUrlService::class => [
|
||||||
'em',
|
'em',
|
||||||
|
@ -19,6 +19,8 @@ class UrlShortenerOptions extends AbstractOptions
|
|||||||
private int $redirectStatusCode = DEFAULT_REDIRECT_STATUS_CODE;
|
private int $redirectStatusCode = DEFAULT_REDIRECT_STATUS_CODE;
|
||||||
private int $redirectCacheLifetime = DEFAULT_REDIRECT_CACHE_LIFETIME;
|
private int $redirectCacheLifetime = DEFAULT_REDIRECT_CACHE_LIFETIME;
|
||||||
private bool $autoResolveTitles = false;
|
private bool $autoResolveTitles = false;
|
||||||
|
private bool $anonymizeRemoteAddr = true;
|
||||||
|
private bool $trackOrphanVisits = true;
|
||||||
|
|
||||||
public function isUrlValidationEnabled(): bool
|
public function isUrlValidationEnabled(): bool
|
||||||
{
|
{
|
||||||
@ -62,9 +64,28 @@ class UrlShortenerOptions extends AbstractOptions
|
|||||||
return $this->autoResolveTitles;
|
return $this->autoResolveTitles;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function setAutoResolveTitles(bool $autoResolveTitles): self
|
protected function setAutoResolveTitles(bool $autoResolveTitles): void
|
||||||
{
|
{
|
||||||
$this->autoResolveTitles = $autoResolveTitles;
|
$this->autoResolveTitles = $autoResolveTitles;
|
||||||
return $this;
|
}
|
||||||
|
|
||||||
|
public function anonymizeRemoteAddr(): bool
|
||||||
|
{
|
||||||
|
return $this->anonymizeRemoteAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function setAnonymizeRemoteAddr(bool $anonymizeRemoteAddr): void
|
||||||
|
{
|
||||||
|
$this->anonymizeRemoteAddr = $anonymizeRemoteAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function trackOrphanVisits(): bool
|
||||||
|
{
|
||||||
|
return $this->trackOrphanVisits;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function setTrackOrphanVisits(bool $trackOrphanVisits): void
|
||||||
|
{
|
||||||
|
$this->trackOrphanVisits = $trackOrphanVisits;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,41 +10,57 @@ use Shlinkio\Shlink\Core\Entity\ShortUrl;
|
|||||||
use Shlinkio\Shlink\Core\Entity\Visit;
|
use Shlinkio\Shlink\Core\Entity\Visit;
|
||||||
use Shlinkio\Shlink\Core\EventDispatcher\Event\UrlVisited;
|
use Shlinkio\Shlink\Core\EventDispatcher\Event\UrlVisited;
|
||||||
use Shlinkio\Shlink\Core\Model\Visitor;
|
use Shlinkio\Shlink\Core\Model\Visitor;
|
||||||
|
use Shlinkio\Shlink\Core\Options\UrlShortenerOptions;
|
||||||
|
|
||||||
class VisitsTracker implements VisitsTrackerInterface
|
class VisitsTracker implements VisitsTrackerInterface
|
||||||
{
|
{
|
||||||
private ORM\EntityManagerInterface $em;
|
private ORM\EntityManagerInterface $em;
|
||||||
private EventDispatcherInterface $eventDispatcher;
|
private EventDispatcherInterface $eventDispatcher;
|
||||||
private bool $anonymizeRemoteAddr;
|
private UrlShortenerOptions $options;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
ORM\EntityManagerInterface $em,
|
ORM\EntityManagerInterface $em,
|
||||||
EventDispatcherInterface $eventDispatcher,
|
EventDispatcherInterface $eventDispatcher,
|
||||||
bool $anonymizeRemoteAddr
|
UrlShortenerOptions $options
|
||||||
) {
|
) {
|
||||||
$this->em = $em;
|
$this->em = $em;
|
||||||
$this->eventDispatcher = $eventDispatcher;
|
$this->eventDispatcher = $eventDispatcher;
|
||||||
$this->anonymizeRemoteAddr = $anonymizeRemoteAddr;
|
$this->options = $options;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function track(ShortUrl $shortUrl, Visitor $visitor): void
|
public function track(ShortUrl $shortUrl, Visitor $visitor): void
|
||||||
{
|
{
|
||||||
$this->trackVisit(Visit::forValidShortUrl($shortUrl, $visitor, $this->anonymizeRemoteAddr), $visitor);
|
$this->trackVisit(
|
||||||
|
Visit::forValidShortUrl($shortUrl, $visitor, $this->options->anonymizeRemoteAddr()),
|
||||||
|
$visitor,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function trackInvalidShortUrlVisit(Visitor $visitor): void
|
public function trackInvalidShortUrlVisit(Visitor $visitor): void
|
||||||
{
|
{
|
||||||
$this->trackVisit(Visit::forInvalidShortUrl($visitor, $this->anonymizeRemoteAddr), $visitor);
|
if (! $this->options->trackOrphanVisits()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->trackVisit(Visit::forInvalidShortUrl($visitor, $this->options->anonymizeRemoteAddr()), $visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function trackBaseUrlVisit(Visitor $visitor): void
|
public function trackBaseUrlVisit(Visitor $visitor): void
|
||||||
{
|
{
|
||||||
$this->trackVisit(Visit::forBasePath($visitor, $this->anonymizeRemoteAddr), $visitor);
|
if (! $this->options->trackOrphanVisits()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->trackVisit(Visit::forBasePath($visitor, $this->options->anonymizeRemoteAddr()), $visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function trackRegularNotFoundVisit(Visitor $visitor): void
|
public function trackRegularNotFoundVisit(Visitor $visitor): void
|
||||||
{
|
{
|
||||||
$this->trackVisit(Visit::forRegularNotFound($visitor, $this->anonymizeRemoteAddr), $visitor);
|
if (! $this->options->trackOrphanVisits()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->trackVisit(Visit::forRegularNotFound($visitor, $this->options->anonymizeRemoteAddr()), $visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function trackVisit(Visit $visit, Visitor $visitor): void
|
private function trackVisit(Visit $visit, Visitor $visitor): void
|
||||||
|
@ -14,6 +14,7 @@ use Shlinkio\Shlink\Core\Entity\ShortUrl;
|
|||||||
use Shlinkio\Shlink\Core\Entity\Visit;
|
use Shlinkio\Shlink\Core\Entity\Visit;
|
||||||
use Shlinkio\Shlink\Core\EventDispatcher\Event\UrlVisited;
|
use Shlinkio\Shlink\Core\EventDispatcher\Event\UrlVisited;
|
||||||
use Shlinkio\Shlink\Core\Model\Visitor;
|
use Shlinkio\Shlink\Core\Model\Visitor;
|
||||||
|
use Shlinkio\Shlink\Core\Options\UrlShortenerOptions;
|
||||||
use Shlinkio\Shlink\Core\Visit\VisitsTracker;
|
use Shlinkio\Shlink\Core\Visit\VisitsTracker;
|
||||||
|
|
||||||
class VisitsTrackerTest extends TestCase
|
class VisitsTrackerTest extends TestCase
|
||||||
@ -23,13 +24,15 @@ class VisitsTrackerTest extends TestCase
|
|||||||
private VisitsTracker $visitsTracker;
|
private VisitsTracker $visitsTracker;
|
||||||
private ObjectProphecy $em;
|
private ObjectProphecy $em;
|
||||||
private ObjectProphecy $eventDispatcher;
|
private ObjectProphecy $eventDispatcher;
|
||||||
|
private UrlShortenerOptions $options;
|
||||||
|
|
||||||
public function setUp(): void
|
public function setUp(): void
|
||||||
{
|
{
|
||||||
$this->em = $this->prophesize(EntityManager::class);
|
$this->em = $this->prophesize(EntityManager::class);
|
||||||
$this->eventDispatcher = $this->prophesize(EventDispatcherInterface::class);
|
$this->eventDispatcher = $this->prophesize(EventDispatcherInterface::class);
|
||||||
|
$this->options = new UrlShortenerOptions();
|
||||||
|
|
||||||
$this->visitsTracker = new VisitsTracker($this->em->reveal(), $this->eventDispatcher->reveal(), true);
|
$this->visitsTracker = new VisitsTracker($this->em->reveal(), $this->eventDispatcher->reveal(), $this->options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -53,4 +56,26 @@ class VisitsTrackerTest extends TestCase
|
|||||||
yield 'trackBaseUrlVisit' => ['trackBaseUrlVisit', [Visitor::emptyInstance()]];
|
yield 'trackBaseUrlVisit' => ['trackBaseUrlVisit', [Visitor::emptyInstance()]];
|
||||||
yield 'trackRegularNotFoundVisit' => ['trackRegularNotFoundVisit', [Visitor::emptyInstance()]];
|
yield 'trackRegularNotFoundVisit' => ['trackRegularNotFoundVisit', [Visitor::emptyInstance()]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @dataProvider provideOrphanTrackingMethodNames
|
||||||
|
*/
|
||||||
|
public function orphanVisitsAreNotTrackedWhenDisabled(string $method): void
|
||||||
|
{
|
||||||
|
$this->options->trackOrphanVisits = false;
|
||||||
|
|
||||||
|
$this->visitsTracker->{$method}(Visitor::emptyInstance());
|
||||||
|
|
||||||
|
$this->eventDispatcher->dispatch(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||||
|
$this->em->persist(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||||
|
$this->em->flush()->shouldNotHaveBeenCalled();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideOrphanTrackingMethodNames(): iterable
|
||||||
|
{
|
||||||
|
yield 'trackInvalidShortUrlVisit' => ['trackInvalidShortUrlVisit'];
|
||||||
|
yield 'trackBaseUrlVisit' => ['trackBaseUrlVisit'];
|
||||||
|
yield 'trackRegularNotFoundVisit' => ['trackRegularNotFoundVisit'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user