Add logic to dynamically resolve the long URL to redirect to based on requesting device

This commit is contained in:
Alejandro Celaya
2023-01-21 11:15:38 +01:00
parent 237fb95b4b
commit b1b67c497e
7 changed files with 109 additions and 36 deletions

View File

@@ -12,7 +12,7 @@ class DeviceLongUrl extends AbstractEntity
{
private function __construct(
private readonly ShortUrl $shortUrl, // No need to read this field. It's used by doctrine
private readonly DeviceType $deviceType,
public readonly DeviceType $deviceType,
private string $longUrl,
) {
}
@@ -27,11 +27,6 @@ class DeviceLongUrl extends AbstractEntity
return $this->longUrl;
}
public function deviceType(): DeviceType
{
return $this->deviceType;
}
public function updateLongUrl(string $longUrl): void
{
$this->longUrl = $longUrl;

View File

@@ -12,6 +12,7 @@ use Doctrine\Common\Collections\Selectable;
use Shlinkio\Shlink\Common\Entity\AbstractEntity;
use Shlinkio\Shlink\Core\Domain\Entity\Domain;
use Shlinkio\Shlink\Core\Exception\ShortCodeCannotBeRegeneratedException;
use Shlinkio\Shlink\Core\Model\DeviceType;
use Shlinkio\Shlink\Core\ShortUrl\Model\DeviceLongUrlPair;
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlCreation;
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlEdition;
@@ -170,7 +171,7 @@ class ShortUrl extends AbstractEntity
}
foreach ($shortUrlEdit->deviceLongUrls as $deviceLongUrlPair) {
$deviceLongUrl = $this->deviceLongUrls->findFirst(
fn ($_, DeviceLongUrl $d) => $d->deviceType() === $deviceLongUrlPair->deviceType,
fn ($_, DeviceLongUrl $d) => $d->deviceType === $deviceLongUrlPair->deviceType,
);
if ($deviceLongUrl !== null) {
@@ -186,6 +187,15 @@ class ShortUrl extends AbstractEntity
return $this->longUrl;
}
public function longUrlForDevice(?DeviceType $deviceType): string
{
$deviceLongUrl = $this->deviceLongUrls->findFirst(
static fn ($_, DeviceLongUrl $longUrl) => $longUrl->deviceType === $deviceType,
);
return $deviceLongUrl?->longUrl() ?? $this->longUrl;
}
public function getShortCode(): string
{
return $this->shortCode;
@@ -322,7 +332,7 @@ class ShortUrl extends AbstractEntity
{
$data = [];
foreach ($this->deviceLongUrls as $deviceUrl) {
$data[$deviceUrl->deviceType()->value] = $deviceUrl->longUrl();
$data[$deviceUrl->deviceType->value] = $deviceUrl->longUrl();
}
return $data;

View File

@@ -8,6 +8,7 @@ use GuzzleHttp\Psr7\Query;
use Laminas\Stdlib\ArrayUtils;
use League\Uri\Uri;
use Psr\Http\Message\ServerRequestInterface;
use Shlinkio\Shlink\Core\Model\DeviceType;
use Shlinkio\Shlink\Core\Options\TrackingOptions;
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
@@ -25,7 +26,8 @@ class ShortUrlRedirectionBuilder implements ShortUrlRedirectionBuilderInterface
?string $extraPath = null,
): string {
$currentQuery = $request->getQueryParams();
$uri = Uri::createFromString($shortUrl->getLongUrl());
$device = DeviceType::matchFromUserAgent($request->getHeaderLine('User-Agent'));
$uri = Uri::createFromString($shortUrl->longUrlForDevice($device));
$shouldForwardQuery = $shortUrl->forwardQuery();
return $uri