mirror of
https://github.com/shlinkio/shlink.git
synced 2025-02-25 18:45:27 -06:00
Make Visit::jsonSerialize() return different props for orphan visits
This commit is contained in:
parent
fbd35b7974
commit
a327e6c0a7
@ -54,7 +54,10 @@ abstract class AbstractVisitsListCommand extends Command
|
|||||||
$extraKeys = array_keys($extraFields);
|
$extraKeys = array_keys($extraFields);
|
||||||
|
|
||||||
$rowData = [
|
$rowData = [
|
||||||
...$visit->jsonSerialize(),
|
'referer' => $visit->referer,
|
||||||
|
'date' => $visit->getDate()->toAtomString(),
|
||||||
|
'userAgent' => $visit->userAgent,
|
||||||
|
'potentialBot' => $visit->potentialBot,
|
||||||
'country' => $visit->getVisitLocation()?->countryName ?? 'Unknown',
|
'country' => $visit->getVisitLocation()?->countryName ?? 'Unknown',
|
||||||
'city' => $visit->getVisitLocation()?->cityName ?? 'Unknown',
|
'city' => $visit->getVisitLocation()?->cityName ?? 'Unknown',
|
||||||
...$extraFields,
|
...$extraFields,
|
||||||
|
@ -25,17 +25,60 @@ class Visit extends AbstractEntity implements JsonSerializable
|
|||||||
public readonly VisitType $type,
|
public readonly VisitType $type,
|
||||||
public readonly string $userAgent,
|
public readonly string $userAgent,
|
||||||
public readonly string $referer,
|
public readonly string $referer,
|
||||||
private readonly bool $potentialBot,
|
public readonly bool $potentialBot,
|
||||||
public readonly ?string $remoteAddr = null,
|
public readonly ?string $remoteAddr = null,
|
||||||
public readonly ?string $visitedUrl = null,
|
public readonly ?string $visitedUrl = null,
|
||||||
private ?VisitLocation $visitLocation = null,
|
private ?VisitLocation $visitLocation = null,
|
||||||
|
// TODO Make public readonly once VisitRepositoryTest does not try to set it
|
||||||
private Chronos $date = new Chronos(),
|
private Chronos $date = new Chronos(),
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function forValidShortUrl(ShortUrl $shortUrl, Visitor $visitor, bool $anonymize = true): self
|
public static function forValidShortUrl(ShortUrl $shortUrl, Visitor $visitor, bool $anonymize = true): self
|
||||||
{
|
{
|
||||||
return self::hydrateFromVisitor($shortUrl, VisitType::VALID_SHORT_URL, $visitor, $anonymize);
|
return self::fromVisitor($shortUrl, VisitType::VALID_SHORT_URL, $visitor, $anonymize);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function forBasePath(Visitor $visitor, bool $anonymize = true): self
|
||||||
|
{
|
||||||
|
return self::fromVisitor(null, VisitType::BASE_URL, $visitor, $anonymize);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function forInvalidShortUrl(Visitor $visitor, bool $anonymize = true): self
|
||||||
|
{
|
||||||
|
return self::fromVisitor(null, VisitType::INVALID_SHORT_URL, $visitor, $anonymize);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function forRegularNotFound(Visitor $visitor, bool $anonymize = true): self
|
||||||
|
{
|
||||||
|
return self::fromVisitor(null, VisitType::REGULAR_404, $visitor, $anonymize);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function fromVisitor(?ShortUrl $shortUrl, VisitType $type, Visitor $visitor, bool $anonymize): self
|
||||||
|
{
|
||||||
|
return new self(
|
||||||
|
shortUrl: $shortUrl,
|
||||||
|
type: $type,
|
||||||
|
userAgent: $visitor->userAgent,
|
||||||
|
referer: $visitor->referer,
|
||||||
|
potentialBot: $visitor->isPotentialBot(),
|
||||||
|
remoteAddr: self::processAddress($visitor->remoteAddress, $anonymize),
|
||||||
|
visitedUrl: $visitor->visitedUrl,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function processAddress(?string $address, bool $anonymize): ?string
|
||||||
|
{
|
||||||
|
// Localhost address does not need to be anonymized
|
||||||
|
if (! $anonymize || $address === null || $address === IpAddress::LOCALHOST) {
|
||||||
|
return $address;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return IpAddress::fromString($address)->getAnonymizedCopy()->__toString();
|
||||||
|
} catch (InvalidArgumentException) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function fromImport(ShortUrl $shortUrl, ImportedShlinkVisit $importedVisit): self
|
public static function fromImport(ShortUrl $shortUrl, ImportedShlinkVisit $importedVisit): self
|
||||||
@ -69,52 +112,6 @@ class Visit extends AbstractEntity implements JsonSerializable
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function forBasePath(Visitor $visitor, bool $anonymize = true): self
|
|
||||||
{
|
|
||||||
return self::hydrateFromVisitor(null, VisitType::BASE_URL, $visitor, $anonymize);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function forInvalidShortUrl(Visitor $visitor, bool $anonymize = true): self
|
|
||||||
{
|
|
||||||
return self::hydrateFromVisitor(null, VisitType::INVALID_SHORT_URL, $visitor, $anonymize);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function forRegularNotFound(Visitor $visitor, bool $anonymize = true): self
|
|
||||||
{
|
|
||||||
return self::hydrateFromVisitor(null, VisitType::REGULAR_404, $visitor, $anonymize);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function hydrateFromVisitor(
|
|
||||||
?ShortUrl $shortUrl,
|
|
||||||
VisitType $type,
|
|
||||||
Visitor $visitor,
|
|
||||||
bool $anonymize,
|
|
||||||
): self {
|
|
||||||
return new self(
|
|
||||||
shortUrl: $shortUrl,
|
|
||||||
type: $type,
|
|
||||||
userAgent: $visitor->userAgent,
|
|
||||||
referer: $visitor->referer,
|
|
||||||
potentialBot: $visitor->isPotentialBot(),
|
|
||||||
remoteAddr: self::processAddress($anonymize, $visitor->remoteAddress),
|
|
||||||
visitedUrl: $visitor->visitedUrl,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function processAddress(bool $anonymize, ?string $address): ?string
|
|
||||||
{
|
|
||||||
// Localhost addresses do not need to be anonymized
|
|
||||||
if (! $anonymize || $address === null || $address === IpAddress::LOCALHOST) {
|
|
||||||
return $address;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return IpAddress::fromString($address)->getAnonymizedCopy()->__toString();
|
|
||||||
} catch (InvalidArgumentException) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function hasRemoteAddr(): bool
|
public function hasRemoteAddr(): bool
|
||||||
{
|
{
|
||||||
return ! empty($this->remoteAddr);
|
return ! empty($this->remoteAddr);
|
||||||
@ -160,12 +157,21 @@ class Visit extends AbstractEntity implements JsonSerializable
|
|||||||
|
|
||||||
public function jsonSerialize(): array
|
public function jsonSerialize(): array
|
||||||
{
|
{
|
||||||
return [
|
$base = [
|
||||||
'referer' => $this->referer,
|
'referer' => $this->referer,
|
||||||
'date' => $this->date->toAtomString(),
|
'date' => $this->date->toAtomString(),
|
||||||
'userAgent' => $this->userAgent,
|
'userAgent' => $this->userAgent,
|
||||||
'visitLocation' => $this->visitLocation,
|
'visitLocation' => $this->visitLocation,
|
||||||
'potentialBot' => $this->potentialBot,
|
'potentialBot' => $this->potentialBot,
|
||||||
];
|
];
|
||||||
|
if (! $this->isOrphan()) {
|
||||||
|
return $base;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
...$base,
|
||||||
|
'visitedUrl' => $this->visitedUrl,
|
||||||
|
'type' => $this->type->value,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,10 +14,6 @@ class OrphanVisitDataTransformer implements DataTransformerInterface
|
|||||||
*/
|
*/
|
||||||
public function transform($visit): array // phpcs:ignore
|
public function transform($visit): array // phpcs:ignore
|
||||||
{
|
{
|
||||||
$serializedVisit = $visit->jsonSerialize();
|
return $visit->jsonSerialize();
|
||||||
$serializedVisit['visitedUrl'] = $visit->visitedUrl;
|
|
||||||
$serializedVisit['type'] = $visit->type->value;
|
|
||||||
|
|
||||||
return $serializedVisit;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user