Make Visit::date field readonly

This commit is contained in:
Alejandro Celaya 2024-04-12 18:42:59 +02:00
parent ce0f61b66d
commit ca42425b33
13 changed files with 41 additions and 46 deletions

View file

@ -55,7 +55,7 @@ abstract class AbstractVisitsListCommand extends Command
$rowData = [
'referer' => $visit->referer,
'date' => $visit->getDate()->toAtomString(),
'date' => $visit->date->toAtomString(),
'userAgent' => $visit->userAgent,
'potentialBot' => $visit->potentialBot,
'country' => $visit->getVisitLocation()?->countryName ?? 'Unknown',

View file

@ -60,7 +60,7 @@ class GetDomainVisitsCommandTest extends TestCase
+---------+---------------------------+------------+---------+--------+---------------+
| Referer | Date | User agent | Country | City | Short Url |
+---------+---------------------------+------------+---------+--------+---------------+
| foo | {$visit->getDate()->toAtomString()} | bar | Spain | Madrid | the_short_url |
| foo | {$visit->date->toAtomString()} | bar | Spain | Madrid | the_short_url |
+---------+---------------------------+------------+---------+--------+---------------+
OUTPUT,

View file

@ -110,7 +110,7 @@ class GetShortUrlVisitsCommandTest extends TestCase
+---------+---------------------------+------------+---------+--------+
| Referer | Date | User agent | Country | City |
+---------+---------------------------+------------+---------+--------+
| foo | {$visit->getDate()->toAtomString()} | bar | Spain | Madrid |
| foo | {$visit->date->toAtomString()} | bar | Spain | Madrid |
+---------+---------------------------+------------+---------+--------+
OUTPUT,

View file

@ -57,7 +57,7 @@ class GetTagVisitsCommandTest extends TestCase
+---------+---------------------------+------------+---------+--------+---------------+
| Referer | Date | User agent | Country | City | Short Url |
+---------+---------------------------+------------+---------+--------+---------------+
| foo | {$visit->getDate()->toAtomString()} | bar | Spain | Madrid | the_short_url |
| foo | {$visit->date->toAtomString()} | bar | Spain | Madrid | the_short_url |
+---------+---------------------------+------------+---------+--------+---------------+
OUTPUT,

View file

@ -56,7 +56,7 @@ class GetNonOrphanVisitsCommandTest extends TestCase
+---------+---------------------------+------------+---------+--------+---------------+
| Referer | Date | User agent | Country | City | Short Url |
+---------+---------------------------+------------+---------+--------+---------------+
| foo | {$visit->getDate()->toAtomString()} | bar | Spain | Madrid | the_short_url |
| foo | {$visit->date->toAtomString()} | bar | Spain | Madrid | the_short_url |
+---------+---------------------------+------------+---------+--------+---------------+
OUTPUT,

View file

@ -54,7 +54,7 @@ class GetOrphanVisitsCommandTest extends TestCase
+---------+---------------------------+------------+---------+--------+----------+
| Referer | Date | User agent | Country | City | Type |
+---------+---------------------------+------------+---------+--------+----------+
| foo | {$visit->getDate()->toAtomString()} | bar | Spain | Madrid | base_url |
| foo | {$visit->date->toAtomString()} | bar | Spain | Madrid | base_url |
+---------+---------------------------+------------+---------+--------+----------+
OUTPUT,

View file

@ -139,7 +139,7 @@ class ImportedLinksProcessor implements ImportedLinksProcessorInterface
$importedVisits = 0;
foreach ($iterable as $importedOrphanVisit) {
// Skip visits which are older than the most recent already imported visit's date
if ($mostRecentOrphanVisit?->getDate()->greaterThanOrEquals(normalizeDate($importedOrphanVisit->date))) {
if ($mostRecentOrphanVisit?->date->greaterThanOrEquals(normalizeDate($importedOrphanVisit->date))) {
continue;
}

View file

@ -209,7 +209,7 @@ class ShortUrl extends AbstractEntity
->setMaxResults(1);
$visit = $this->visits->matching($criteria)->last();
return $visit instanceof Visit ? $visit->getDate() : null;
return $visit instanceof Visit ? $visit->date : null;
}
/**

View file

@ -29,8 +29,7 @@ class Visit extends AbstractEntity implements JsonSerializable
public readonly ?string $remoteAddr = null,
public readonly ?string $visitedUrl = null,
private ?VisitLocation $visitLocation = null,
// TODO Make public readonly once VisitRepositoryTest does not try to set it
private Chronos $date = new Chronos(),
public readonly Chronos $date = new Chronos(),
) {
}
@ -147,14 +146,6 @@ class Visit extends AbstractEntity implements JsonSerializable
return $this->type;
}
/**
* @internal
*/
public function getDate(): Chronos
{
return $this->date;
}
public function jsonSerialize(): array
{
$base = [

View file

@ -6,7 +6,6 @@ namespace ShlinkioDbTest\Shlink\Core\Visit\Repository;
use Cake\Chronos\Chronos;
use PHPUnit\Framework\Attributes\Test;
use ReflectionObject;
use Shlinkio\Shlink\Common\Util\DateRange;
use Shlinkio\Shlink\Core\Domain\Entity\Domain;
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
@ -371,15 +370,15 @@ class VisitRepositoryTest extends DatabaseTestCase
$botsCount = 3;
for ($i = 0; $i < 6; $i++) {
$this->getEntityManager()->persist($this->setDateOnVisit(
Visit::forBasePath($botsCount < 1 ? Visitor::emptyInstance() : Visitor::botInstance()),
fn () => Visit::forBasePath($botsCount < 1 ? Visitor::emptyInstance() : Visitor::botInstance()),
Chronos::parse(sprintf('2020-01-0%s', $i + 1)),
));
$this->getEntityManager()->persist($this->setDateOnVisit(
Visit::forInvalidShortUrl(Visitor::emptyInstance()),
fn () => Visit::forInvalidShortUrl(Visitor::emptyInstance()),
Chronos::parse(sprintf('2020-01-0%s', $i + 1)),
));
$this->getEntityManager()->persist($this->setDateOnVisit(
Visit::forRegularNotFound(Visitor::emptyInstance()),
fn () => Visit::forRegularNotFound(Visitor::emptyInstance()),
Chronos::parse(sprintf('2020-01-0%s', $i + 1)),
));
@ -429,15 +428,15 @@ class VisitRepositoryTest extends DatabaseTestCase
for ($i = 0; $i < 6; $i++) {
$this->getEntityManager()->persist($this->setDateOnVisit(
Visit::forBasePath(Visitor::emptyInstance()),
fn () => Visit::forBasePath(Visitor::emptyInstance()),
Chronos::parse(sprintf('2020-01-0%s', $i + 1)),
));
$this->getEntityManager()->persist($this->setDateOnVisit(
Visit::forInvalidShortUrl(Visitor::emptyInstance()),
fn () => Visit::forInvalidShortUrl(Visitor::emptyInstance()),
Chronos::parse(sprintf('2020-01-0%s', $i + 1)),
));
$this->getEntityManager()->persist($this->setDateOnVisit(
Visit::forRegularNotFound(Visitor::emptyInstance()),
fn () => Visit::forRegularNotFound(Visitor::emptyInstance()),
Chronos::parse(sprintf('2020-01-0%s', $i + 1)),
));
}
@ -566,7 +565,7 @@ class VisitRepositoryTest extends DatabaseTestCase
{
for ($i = 0; $i < $amount; $i++) {
$visit = $this->setDateOnVisit(
Visit::forValidShortUrl(
fn () => Visit::forValidShortUrl(
$shortUrl,
$botsAmount < 1 ? Visitor::emptyInstance() : Visitor::botInstance(),
),
@ -578,12 +577,14 @@ class VisitRepositoryTest extends DatabaseTestCase
}
}
private function setDateOnVisit(Visit $visit, Chronos $date): Visit
/**
* @param callable(): Visit $createVisit
*/
private function setDateOnVisit(callable $createVisit, Chronos $date): Visit
{
$ref = new ReflectionObject($visit);
$dateProp = $ref->getProperty('date');
$dateProp->setAccessible(true);
$dateProp->setValue($visit, $date);
Chronos::setTestNow($date);
$visit = $createVisit();
Chronos::setTestNow();
return $visit;
}

View file

@ -76,7 +76,7 @@ class PublishingUpdatesGeneratorTest extends TestCase
'referer' => '',
'userAgent' => '',
'visitLocation' => null,
'date' => $visit->getDate()->toAtomString(),
'date' => $visit->date->toAtomString(),
'potentialBot' => false,
'visitedUrl' => '',
],
@ -100,7 +100,7 @@ class PublishingUpdatesGeneratorTest extends TestCase
'referer' => '',
'userAgent' => '',
'visitLocation' => null,
'date' => $orphanVisit->getDate()->toAtomString(),
'date' => $orphanVisit->date->toAtomString(),
'potentialBot' => false,
'visitedUrl' => $orphanVisit->visitedUrl,
'type' => $orphanVisit->type->value,

View file

@ -26,7 +26,7 @@ class VisitTest extends TestCase
self::assertEquals([
'referer' => 'some site',
'date' => $visit->getDate()->toAtomString(),
'date' => $visit->date->toAtomString(),
'userAgent' => $userAgent,
'visitLocation' => null,
'potentialBot' => $expectedToBePotentialBot,
@ -58,7 +58,7 @@ class VisitTest extends TestCase
$visit = Visit::forBasePath(Visitor::emptyInstance()),
[
'referer' => '',
'date' => $visit->getDate()->toAtomString(),
'date' => $visit->date->toAtomString(),
'userAgent' => '',
'visitLocation' => null,
'potentialBot' => false,
@ -74,7 +74,7 @@ class VisitTest extends TestCase
)),
[
'referer' => 'bar',
'date' => $visit->getDate()->toAtomString(),
'date' => $visit->date->toAtomString(),
'userAgent' => 'foo',
'visitLocation' => null,
'potentialBot' => false,
@ -92,7 +92,7 @@ class VisitTest extends TestCase
)->locate($location = VisitLocation::fromGeolocation(Location::emptyInstance())),
[
'referer' => 'referer',
'date' => $visit->getDate()->toAtomString(),
'date' => $visit->date->toAtomString(),
'userAgent' => 'user-agent',
'visitLocation' => $location,
'potentialBot' => false,

View file

@ -8,7 +8,6 @@ use Cake\Chronos\Chronos;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
use Doctrine\Persistence\ObjectManager;
use ReflectionObject;
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
use Shlinkio\Shlink\Core\Visit\Entity\Visit;
use Shlinkio\Shlink\Core\Visit\Model\Visitor;
@ -50,27 +49,31 @@ class VisitsFixture extends AbstractFixture implements DependentFixtureInterface
);
$manager->persist($this->setVisitDate(
Visit::forBasePath(new Visitor('shlink-tests-agent', 'https://s.test', '1.2.3.4', '')),
fn () => Visit::forBasePath(new Visitor('shlink-tests-agent', 'https://s.test', '1.2.3.4', '')),
'2020-01-01',
));
$manager->persist($this->setVisitDate(
Visit::forRegularNotFound(new Visitor('shlink-tests-agent', 'https://s.test/foo/bar', '1.2.3.4', '')),
fn () => Visit::forRegularNotFound(
new Visitor('shlink-tests-agent', 'https://s.test/foo/bar', '1.2.3.4', ''),
),
'2020-02-01',
));
$manager->persist($this->setVisitDate(
Visit::forInvalidShortUrl(new Visitor('cf-facebook', 'https://s.test/foo', '1.2.3.4', 'foo.com')),
fn () => Visit::forInvalidShortUrl(new Visitor('cf-facebook', 'https://s.test/foo', '1.2.3.4', 'foo.com')),
'2020-03-01',
));
$manager->flush();
}
private function setVisitDate(Visit $visit, string $date): Visit
/**
* @param callable(): Visit $createVisit
*/
private function setVisitDate(callable $createVisit, string $date): Visit
{
$ref = new ReflectionObject($visit);
$dateProp = $ref->getProperty('date');
$dateProp->setAccessible(true);
$dateProp->setValue($visit, Chronos::parse($date));
Chronos::setTestNow($date);
$visit = $createVisit();
Chronos::setTestNow();
return $visit;
}