From 4e87affb0bfd7a8dbe576a80ab0f01db7ff9b6f1 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Sun, 25 Feb 2024 12:25:55 +0100 Subject: [PATCH] Take redirect rules into consideration when resolving the long URL for a short URL --- .../RedirectRule/Entity/ShortUrlRedirectRule.php | 16 +++++++++++++++- .../RedirectRule/ShortUrlRedirectionResolver.php | 12 +++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/module/Core/src/RedirectRule/Entity/ShortUrlRedirectRule.php b/module/Core/src/RedirectRule/Entity/ShortUrlRedirectRule.php index 65b39901..7fa1a671 100644 --- a/module/Core/src/RedirectRule/Entity/ShortUrlRedirectRule.php +++ b/module/Core/src/RedirectRule/Entity/ShortUrlRedirectRule.php @@ -4,9 +4,12 @@ namespace Shlinkio\Shlink\Core\RedirectRule\Entity; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; +use Psr\Http\Message\ServerRequestInterface; use Shlinkio\Shlink\Common\Entity\AbstractEntity; use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl; +use function Shlinkio\Shlink\Core\ArrayUtils\every; + class ShortUrlRedirectRule extends AbstractEntity { /** @@ -14,9 +17,20 @@ class ShortUrlRedirectRule extends AbstractEntity */ public function __construct( private readonly ShortUrl $shortUrl, // No need to read this field. It's used by doctrine - public readonly int $priority, + private readonly int $priority, public readonly string $longUrl, public readonly Collection $conditions = new ArrayCollection(), ) { } + + /** + * Tells if this condition matches provided request + */ + public function matchesRequest(ServerRequestInterface $request): bool + { + return every( + $this->conditions, + static fn (RedirectCondition $condition) => $condition->matchesRequest($request), + ); + } } diff --git a/module/Core/src/RedirectRule/ShortUrlRedirectionResolver.php b/module/Core/src/RedirectRule/ShortUrlRedirectionResolver.php index dc2ae131..b916d78b 100644 --- a/module/Core/src/RedirectRule/ShortUrlRedirectionResolver.php +++ b/module/Core/src/RedirectRule/ShortUrlRedirectionResolver.php @@ -5,6 +5,7 @@ namespace Shlinkio\Shlink\Core\RedirectRule; use Doctrine\ORM\EntityManagerInterface; use Psr\Http\Message\ServerRequestInterface; use Shlinkio\Shlink\Core\Model\DeviceType; +use Shlinkio\Shlink\Core\RedirectRule\Entity\ShortUrlRedirectRule; use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl; readonly class ShortUrlRedirectionResolver implements ShortUrlRedirectionResolverInterface @@ -15,7 +16,16 @@ readonly class ShortUrlRedirectionResolver implements ShortUrlRedirectionResolve public function resolveLongUrl(ShortUrl $shortUrl, ServerRequestInterface $request): string { - // TODO Resolve rules and check if any of them matches + $rules = $this->em->getRepository(ShortUrlRedirectRule::class)->findBy( + criteria: ['shortUrl' => $shortUrl], + orderBy: ['priority' => 'ASC'], + ); + foreach ($rules as $rule) { + // Return the long URL for the first rule found that matches + if ($rule->matchesRequest($request)) { + return $rule->longUrl; + } + } $device = DeviceType::matchFromUserAgent($request->getHeaderLine('User-Agent')); return $shortUrl->longUrlForDevice($device);