Take redirect rules into consideration when resolving the long URL for a short URL

This commit is contained in:
Alejandro Celaya 2024-02-25 12:25:55 +01:00
parent 7f83d37b3c
commit 4e87affb0b
2 changed files with 26 additions and 2 deletions

View File

@ -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),
);
}
}

View File

@ -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);