mirror of
https://github.com/shlinkio/shlink.git
synced 2025-03-30 13:31:59 +03:00
Added logic for new tracking options
This commit is contained in:
parent
d423d18249
commit
f0dc32b6e5
7 changed files with 76 additions and 27 deletions
|
@ -21,9 +21,6 @@ return [
|
||||||
// If true, visits will be tracked, but neither the IP address or the location will be resolved
|
// If true, visits will be tracked, but neither the IP address or the location will be resolved
|
||||||
'disable_ip_tracking' => false,
|
'disable_ip_tracking' => false,
|
||||||
|
|
||||||
// If true, visits will be tracked including the IP address, but the location won't be resolved
|
|
||||||
'disable_location_tracking' => false,
|
|
||||||
|
|
||||||
// If true, the referrer will not be tracked
|
// If true, the referrer will not be tracked
|
||||||
'disable_referrer_tracking' => false,
|
'disable_referrer_tracking' => false,
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,6 @@ return [
|
||||||
'disable_track_param' => env('DISABLE_TRACK_PARAM'),
|
'disable_track_param' => env('DISABLE_TRACK_PARAM'),
|
||||||
'disable_tracking' => (bool) env('DISABLE_TRACKING', false),
|
'disable_tracking' => (bool) env('DISABLE_TRACKING', false),
|
||||||
'disable_ip_tracking' => (bool) env('DISABLE_IP_TRACKING', false),
|
'disable_ip_tracking' => (bool) env('DISABLE_IP_TRACKING', false),
|
||||||
'disable_location_tracking' => (bool) env('DISABLE_LOCATION_TRACKING', false),
|
|
||||||
'disable_referrer_tracking' => (bool) env('DISABLE_REFERRER_TRACKING', false),
|
'disable_referrer_tracking' => (bool) env('DISABLE_REFERRER_TRACKING', false),
|
||||||
'disable_ua_tracking' => (bool) env('DISABLE_UA_TRACKING', false),
|
'disable_ua_tracking' => (bool) env('DISABLE_UA_TRACKING', false),
|
||||||
],
|
],
|
||||||
|
|
|
@ -6,6 +6,7 @@ namespace Shlinkio\Shlink\Core\Model;
|
||||||
|
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Shlinkio\Shlink\Common\Middleware\IpAddressMiddlewareFactory;
|
use Shlinkio\Shlink\Common\Middleware\IpAddressMiddlewareFactory;
|
||||||
|
use Shlinkio\Shlink\Core\Options\TrackingOptions;
|
||||||
|
|
||||||
use function substr;
|
use function substr;
|
||||||
|
|
||||||
|
@ -68,4 +69,16 @@ final class Visitor
|
||||||
{
|
{
|
||||||
return $this->visitedUrl;
|
return $this->visitedUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function normalizeForTrackingOptions(TrackingOptions $options): self
|
||||||
|
{
|
||||||
|
$instance = self::emptyInstance();
|
||||||
|
|
||||||
|
$instance->userAgent = $options->disableUaTracking() ? '' : $this->userAgent;
|
||||||
|
$instance->referer = $options->disableReferrerTracking() ? '' : $this->referer;
|
||||||
|
$instance->remoteAddress = $options->disableIpTracking() ? null : $this->remoteAddress;
|
||||||
|
$instance->visitedUrl = $this->visitedUrl;
|
||||||
|
|
||||||
|
return $instance;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@ class TrackingOptions extends AbstractOptions
|
||||||
private ?string $disableTrackParam = null;
|
private ?string $disableTrackParam = null;
|
||||||
private bool $disableTracking = false;
|
private bool $disableTracking = false;
|
||||||
private bool $disableIpTracking = false;
|
private bool $disableIpTracking = false;
|
||||||
private bool $disableLocationTracking = false;
|
|
||||||
private bool $disableReferrerTracking = false;
|
private bool $disableReferrerTracking = false;
|
||||||
private bool $disableUaTracking = false;
|
private bool $disableUaTracking = false;
|
||||||
|
|
||||||
|
@ -67,16 +66,6 @@ class TrackingOptions extends AbstractOptions
|
||||||
$this->disableIpTracking = $disableIpTracking;
|
$this->disableIpTracking = $disableIpTracking;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function disableLocationTracking(): bool
|
|
||||||
{
|
|
||||||
return $this->disableLocationTracking;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function setDisableLocationTracking(bool $disableLocationTracking): void
|
|
||||||
{
|
|
||||||
$this->disableLocationTracking = $disableLocationTracking;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function disableReferrerTracking(): bool
|
public function disableReferrerTracking(): bool
|
||||||
{
|
{
|
||||||
return $this->disableReferrerTracking;
|
return $this->disableReferrerTracking;
|
||||||
|
|
|
@ -32,39 +32,49 @@ class VisitsTracker implements VisitsTrackerInterface
|
||||||
{
|
{
|
||||||
$this->trackVisit(
|
$this->trackVisit(
|
||||||
Visit::forValidShortUrl($shortUrl, $visitor, $this->options->anonymizeRemoteAddr()),
|
Visit::forValidShortUrl($shortUrl, $visitor, $this->options->anonymizeRemoteAddr()),
|
||||||
$visitor,
|
$visitor->normalizeForTrackingOptions($this->options),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function trackInvalidShortUrlVisit(Visitor $visitor): void
|
public function trackInvalidShortUrlVisit(Visitor $visitor): void
|
||||||
{
|
{
|
||||||
if (! $this->options->trackOrphanVisits()) {
|
$this->trackOrphanVisit(
|
||||||
return;
|
Visit::forInvalidShortUrl($visitor, $this->options->anonymizeRemoteAddr()),
|
||||||
}
|
$visitor->normalizeForTrackingOptions($this->options),
|
||||||
|
);
|
||||||
$this->trackVisit(Visit::forInvalidShortUrl($visitor, $this->options->anonymizeRemoteAddr()), $visitor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function trackBaseUrlVisit(Visitor $visitor): void
|
public function trackBaseUrlVisit(Visitor $visitor): void
|
||||||
{
|
{
|
||||||
if (! $this->options->trackOrphanVisits()) {
|
$this->trackOrphanVisit(
|
||||||
return;
|
Visit::forBasePath($visitor, $this->options->anonymizeRemoteAddr()),
|
||||||
}
|
$visitor->normalizeForTrackingOptions($this->options),
|
||||||
|
);
|
||||||
$this->trackVisit(Visit::forBasePath($visitor, $this->options->anonymizeRemoteAddr()), $visitor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function trackRegularNotFoundVisit(Visitor $visitor): void
|
public function trackRegularNotFoundVisit(Visitor $visitor): void
|
||||||
|
{
|
||||||
|
$this->trackOrphanVisit(
|
||||||
|
Visit::forRegularNotFound($visitor, $this->options->anonymizeRemoteAddr()),
|
||||||
|
$visitor->normalizeForTrackingOptions($this->options),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function trackOrphanVisit(Visit $visit, Visitor $visitor): void
|
||||||
{
|
{
|
||||||
if (! $this->options->trackOrphanVisits()) {
|
if (! $this->options->trackOrphanVisits()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->trackVisit(Visit::forRegularNotFound($visitor, $this->options->anonymizeRemoteAddr()), $visitor);
|
$this->trackVisit($visit, $visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function trackVisit(Visit $visit, Visitor $visitor): void
|
private function trackVisit(Visit $visit, Visitor $visitor): void
|
||||||
{
|
{
|
||||||
|
if ($this->options->disableTracking()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$this->em->transactional(function () use ($visit, $visitor): void {
|
$this->em->transactional(function () use ($visit, $visitor): void {
|
||||||
$this->em->persist($visit);
|
$this->em->persist($visit);
|
||||||
$this->em->flush();
|
$this->em->flush();
|
||||||
|
|
|
@ -6,6 +6,7 @@ namespace ShlinkioTest\Shlink\Core\Model;
|
||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Shlinkio\Shlink\Core\Model\Visitor;
|
use Shlinkio\Shlink\Core\Model\Visitor;
|
||||||
|
use Shlinkio\Shlink\Core\Options\TrackingOptions;
|
||||||
|
|
||||||
use function random_int;
|
use function random_int;
|
||||||
use function str_repeat;
|
use function str_repeat;
|
||||||
|
@ -71,4 +72,28 @@ class VisitorTest extends TestCase
|
||||||
}
|
}
|
||||||
return $randomString;
|
return $randomString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function newNormalizedInstanceIsCreatedFromTrackingOptions(): void
|
||||||
|
{
|
||||||
|
$visitor = new Visitor(
|
||||||
|
$this->generateRandomString(2000),
|
||||||
|
$this->generateRandomString(2000),
|
||||||
|
$this->generateRandomString(2000),
|
||||||
|
$this->generateRandomString(2000),
|
||||||
|
);
|
||||||
|
$normalizedVisitor = $visitor->normalizeForTrackingOptions(new TrackingOptions([
|
||||||
|
'disableIpTracking' => true,
|
||||||
|
'disableReferrerTracking' => true,
|
||||||
|
'disableUaTracking' => true,
|
||||||
|
]));
|
||||||
|
|
||||||
|
self::assertNotSame($visitor, $normalizedVisitor);
|
||||||
|
self::assertEmpty($normalizedVisitor->getUserAgent());
|
||||||
|
self::assertNotEmpty($visitor->getUserAgent());
|
||||||
|
self::assertEmpty($normalizedVisitor->getReferer());
|
||||||
|
self::assertNotEmpty($visitor->getReferer());
|
||||||
|
self::assertNull($normalizedVisitor->getRemoteAddress());
|
||||||
|
self::assertNotNull($visitor->getRemoteAddress());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,22 @@ class VisitsTrackerTest extends TestCase
|
||||||
$this->eventDispatcher->dispatch(Argument::type(UrlVisited::class))->shouldHaveBeenCalled();
|
$this->eventDispatcher->dispatch(Argument::type(UrlVisited::class))->shouldHaveBeenCalled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @dataProvider provideTrackingMethodNames
|
||||||
|
*/
|
||||||
|
public function trackingIsSkippedCompletelyWhenDisabledFromOptions(string $method, array $args): void
|
||||||
|
{
|
||||||
|
$this->options->disableTracking = true;
|
||||||
|
|
||||||
|
$this->visitsTracker->{$method}(...$args);
|
||||||
|
|
||||||
|
$this->eventDispatcher->dispatch(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||||
|
$this->em->transactional(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||||
|
$this->em->persist(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||||
|
$this->em->flush()->shouldNotHaveBeenCalled();
|
||||||
|
}
|
||||||
|
|
||||||
public function provideTrackingMethodNames(): iterable
|
public function provideTrackingMethodNames(): iterable
|
||||||
{
|
{
|
||||||
yield 'track' => ['track', [ShortUrl::createEmpty(), Visitor::emptyInstance()]];
|
yield 'track' => ['track', [ShortUrl::createEmpty(), Visitor::emptyInstance()]];
|
||||||
|
|
Loading…
Add table
Reference in a new issue