Skip to content

Commit

Permalink
Include visited short URL information with every visit
Browse files Browse the repository at this point in the history
  • Loading branch information
acelaya committed Dec 12, 2024
1 parent d8087c2 commit 5d6abe5
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 14 deletions.
5 changes: 3 additions & 2 deletions module/Core/config/dependencies.config.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
use Shlinkio\Shlink\Common\Doctrine\EntityRepositoryFactory;
use Shlinkio\Shlink\Core\Config\Options\NotFoundRedirectOptions;
use Shlinkio\Shlink\Core\Geolocation\GeolocationDbUpdater;
use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortUrlStringifier;
use Shlinkio\Shlink\Importer\ImportedLinksProcessorInterface;
use Shlinkio\Shlink\IpGeolocation\GeoLite2\DbUpdater;
use Shlinkio\Shlink\IpGeolocation\GeoLite2\GeoLite2ReaderFactory;
Expand Down Expand Up @@ -94,6 +93,7 @@
],
Visit\Listener\ShortUrlVisitsCountTracker::class => InvokableFactory::class,
Visit\Listener\OrphanVisitsCountTracker::class => InvokableFactory::class,
Visit\Transformer\VisitDataTransformer::class => ConfigAbstractFactory::class,

Util\DoctrineBatchHelper::class => ConfigAbstractFactory::class,
Util\RedirectResponseHelper::class => ConfigAbstractFactory::class,
Expand Down Expand Up @@ -128,7 +128,7 @@
Matomo\MatomoTrackerBuilder::class => [Matomo\MatomoOptions::class],
Matomo\MatomoVisitSender::class => [
Matomo\MatomoTrackerBuilder::class,
ShortUrlStringifier::class,
ShortUrl\Helper\ShortUrlStringifier::class,
Visit\Repository\VisitIterationRepository::class,
],

Expand Down Expand Up @@ -168,6 +168,7 @@
Visit\Geolocation\VisitLocator::class => ['em', Visit\Repository\VisitIterationRepository::class],
Visit\Geolocation\VisitToLocationHelper::class => [IpLocationResolverInterface::class],
Visit\VisitsStatsHelper::class => ['em'],
Visit\Transformer\VisitDataTransformer::class => [ShortUrl\Helper\ShortUrlStringifier::class],
Tag\TagService::class => ['em', Tag\Repository\TagRepository::class],
ShortUrl\DeleteShortUrlService::class => [
'em',
Expand Down
16 changes: 12 additions & 4 deletions module/Core/src/Visit/Entity/Visit.php
Original file line number Diff line number Diff line change
Expand Up @@ -169,16 +169,24 @@ public function toArray(callable|null $visitedShortUrlToArray = null): array
'visitedUrl' => $this->visitedUrl,
'redirectUrl' => $this->redirectUrl,
];
if ($this->shortUrl !== null) {
return $visitedShortUrlToArray === null ? $base : [

// Orphan visit
if ($this->shortUrl === null) {
return [
...$base,
'visitedShortUrl' => $visitedShortUrlToArray($this->shortUrl),
'type' => $this->type->value,
];

}

// Should not include visited short URL
if ($visitedShortUrlToArray === null) {
return $base;
}

return [
...$base,
'type' => $this->type->value,
'visitedShortUrl' => $visitedShortUrlToArray($this->shortUrl),
];
}
}
25 changes: 25 additions & 0 deletions module/Core/src/Visit/Transformer/VisitDataTransformer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace Shlinkio\Shlink\Core\Visit\Transformer;

use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortUrlStringifierInterface;
use Shlinkio\Shlink\Core\Visit\Entity\Visit;

readonly class VisitDataTransformer implements VisitDataTransformerInterface
{
public function __construct(private ShortUrlStringifierInterface $stringifier)
{
}

public function transform(Visit $visit): array
{
return $visit->toArray(fn (ShortUrl $shortUrl) => [

Check failure on line 19 in module/Core/src/Visit/Transformer/VisitDataTransformer.php

View workflow job for this annotation

GitHub Actions / static-analysis (8.3, stan)

Parameter #1 $visitedShortUrlToArray of method Shlinkio\Shlink\Core\Visit\Entity\Visit::toArray() expects (callable(Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl): Shlinkio\Shlink\Core\Visit\Entity\VisitedShortUrl)|null, Closure(Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl): array{shortCode: string, domain: string|null, shortUrl: string} given.
'shortCode' => $shortUrl->getShortCode(),
'domain' => $shortUrl->getDomain()?->authority,
'shortUrl' => $this->stringifier->stringify($shortUrl),
]);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Shlinkio\Shlink\Core\Visit\Transformer;

use Shlinkio\Shlink\Core\Visit\Entity\Visit;

interface VisitDataTransformerInterface
{
public function transform(Visit $visit): array;
}
21 changes: 17 additions & 4 deletions module/Rest/config/dependencies.config.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,16 +85,29 @@
ShortUrl\ShortUrlResolver::class,
ShortUrlDataTransformer::class,
],
Action\Visit\ShortUrlVisitsAction::class => [Visit\VisitsStatsHelper::class],
Action\Visit\TagVisitsAction::class => [Visit\VisitsStatsHelper::class],
Action\Visit\ShortUrlVisitsAction::class => [
Visit\VisitsStatsHelper::class,
Visit\Transformer\VisitDataTransformer::class,
],
Action\Visit\TagVisitsAction::class => [
Visit\VisitsStatsHelper::class,
Visit\Transformer\VisitDataTransformer::class,
],
Action\Visit\DomainVisitsAction::class => [
Visit\VisitsStatsHelper::class,
Config\Options\UrlShortenerOptions::class,
Visit\Transformer\VisitDataTransformer::class,
],
Action\Visit\GlobalVisitsAction::class => [Visit\VisitsStatsHelper::class],
Action\Visit\OrphanVisitsAction::class => [Visit\VisitsStatsHelper::class],
Action\Visit\OrphanVisitsAction::class => [
Visit\VisitsStatsHelper::class,
Visit\Transformer\VisitDataTransformer::class,
],
Action\Visit\DeleteOrphanVisitsAction::class => [Visit\VisitsDeleter::class],
Action\Visit\NonOrphanVisitsAction::class => [Visit\VisitsStatsHelper::class],
Action\Visit\NonOrphanVisitsAction::class => [
Visit\VisitsStatsHelper::class,
Visit\Transformer\VisitDataTransformer::class,
],
Action\ShortUrl\ListShortUrlsAction::class => [
ShortUrl\ShortUrlListService::class,
ShortUrlDataTransformer::class,
Expand Down
11 changes: 8 additions & 3 deletions module/Rest/src/Action/Visit/AbstractListVisitsAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Shlinkio\Shlink\Common\Paginator\Util\PagerfantaUtils;
use Shlinkio\Shlink\Core\Visit\Entity\Visit;
use Shlinkio\Shlink\Core\Visit\Model\VisitsParams;
use Shlinkio\Shlink\Core\Visit\Transformer\VisitDataTransformerInterface;
use Shlinkio\Shlink\Core\Visit\VisitsStatsHelperInterface;
use Shlinkio\Shlink\Rest\Action\AbstractRestAction;
use Shlinkio\Shlink\Rest\Entity\ApiKey;
Expand All @@ -20,8 +21,10 @@ abstract class AbstractListVisitsAction extends AbstractRestAction
{
protected const array ROUTE_ALLOWED_METHODS = [self::METHOD_GET];

public function __construct(protected readonly VisitsStatsHelperInterface $visitsHelper)
{
public function __construct(
protected readonly VisitsStatsHelperInterface $visitsHelper,
private readonly VisitDataTransformerInterface $transformer,
) {
}

public function handle(ServerRequestInterface $request): ResponseInterface
Expand All @@ -30,7 +33,9 @@ public function handle(ServerRequestInterface $request): ResponseInterface
$apiKey = AuthenticationMiddleware::apiKeyFromRequest($request);
$visits = $this->getVisitsPaginator($request, $params, $apiKey);

return new JsonResponse(['visits' => PagerfantaUtils::serializePaginator($visits)]);
return new JsonResponse([
'visits' => PagerfantaUtils::serializePaginator($visits, $this->transformer->transform(...)),
]);
}

/**
Expand Down
4 changes: 3 additions & 1 deletion module/Rest/src/Action/Visit/DomainVisitsAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Shlinkio\Shlink\Core\Config\Options\UrlShortenerOptions;
use Shlinkio\Shlink\Core\Domain\Entity\Domain;
use Shlinkio\Shlink\Core\Visit\Model\VisitsParams;
use Shlinkio\Shlink\Core\Visit\Transformer\VisitDataTransformerInterface;
use Shlinkio\Shlink\Core\Visit\VisitsStatsHelperInterface;
use Shlinkio\Shlink\Rest\Entity\ApiKey;

Expand All @@ -19,8 +20,9 @@ class DomainVisitsAction extends AbstractListVisitsAction
public function __construct(
VisitsStatsHelperInterface $visitsHelper,
private readonly UrlShortenerOptions $urlShortenerOptions,
VisitDataTransformerInterface $transformer,
) {
parent::__construct($visitsHelper);
parent::__construct($visitsHelper, $transformer);
}

protected function getVisitsPaginator(Request $request, VisitsParams $params, ApiKey $apiKey): Pagerfanta
Expand Down

0 comments on commit 5d6abe5

Please sign in to comment.