Extracted logic to stringify ShortUrls to its own service

This commit is contained in:
Alejandro Celaya
2021-02-01 22:55:52 +01:00
parent 01aebd90d5
commit 9cddedcdba
28 changed files with 215 additions and 135 deletions

View File

@@ -16,6 +16,7 @@ use Shlinkio\Shlink\Common\Response\QrCodeResponse;
use Shlinkio\Shlink\Core\Exception\ShortUrlNotFoundException;
use Shlinkio\Shlink\Core\Model\ShortUrlIdentifier;
use Shlinkio\Shlink\Core\Service\ShortUrl\ShortUrlResolverInterface;
use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortUrlStringifierInterface;
class QrCodeAction implements MiddlewareInterface
{
@@ -24,17 +25,17 @@ class QrCodeAction implements MiddlewareInterface
private const MAX_SIZE = 1000;
private ShortUrlResolverInterface $urlResolver;
private array $domainConfig;
private ShortUrlStringifierInterface $stringifier;
private LoggerInterface $logger;
public function __construct(
ShortUrlResolverInterface $urlResolver,
array $domainConfig,
ShortUrlStringifierInterface $stringifier,
?LoggerInterface $logger = null
) {
$this->urlResolver = $urlResolver;
$this->domainConfig = $domainConfig;
$this->logger = $logger ?? new NullLogger();
$this->stringifier = $stringifier;
}
public function process(Request $request, RequestHandlerInterface $handler): Response
@@ -52,7 +53,7 @@ class QrCodeAction implements MiddlewareInterface
// Size attribute is deprecated
$size = $this->normalizeSize((int) $request->getAttribute('size', $query['size'] ?? self::DEFAULT_SIZE));
$qrCode = new QrCode($shortUrl->toString($this->domainConfig));
$qrCode = new QrCode($this->stringifier->stringify($shortUrl));
$qrCode->setSize($size);
$qrCode->setMargin(0);

View File

@@ -7,7 +7,6 @@ namespace Shlinkio\Shlink\Core\Entity;
use Cake\Chronos\Chronos;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Laminas\Diactoros\Uri;
use Shlinkio\Shlink\Common\Entity\AbstractEntity;
use Shlinkio\Shlink\Core\Exception\ShortCodeCannotBeRegeneratedException;
use Shlinkio\Shlink\Core\Model\ShortUrlEdit;
@@ -128,6 +127,36 @@ class ShortUrl extends AbstractEntity
return $this->tags;
}
public function getValidSince(): ?Chronos
{
return $this->validSince;
}
public function getValidUntil(): ?Chronos
{
return $this->validUntil;
}
public function getVisitsCount(): int
{
return count($this->visits);
}
/**
* @param Collection|Visit[] $visits
* @internal
*/
public function setVisits(Collection $visits): self
{
$this->visits = $visits;
return $this;
}
public function getMaxVisits(): ?int
{
return $this->maxVisits;
}
public function update(
ShortUrlEdit $shortUrlEdit,
?ShortUrlRelationResolverInterface $relationResolver = null
@@ -168,36 +197,6 @@ class ShortUrl extends AbstractEntity
$this->shortCode = generateRandomShortCode($this->shortCodeLength);
}
public function getValidSince(): ?Chronos
{
return $this->validSince;
}
public function getValidUntil(): ?Chronos
{
return $this->validUntil;
}
public function getVisitsCount(): int
{
return count($this->visits);
}
/**
* @param Collection|Visit[] $visits
* @internal
*/
public function setVisits(Collection $visits): self
{
$this->visits = $visits;
return $this;
}
public function getMaxVisits(): ?int
{
return $this->maxVisits;
}
public function isEnabled(): bool
{
$maxVisitsReached = $this->maxVisits !== null && $this->getVisitsCount() >= $this->maxVisits;
@@ -218,21 +217,4 @@ class ShortUrl extends AbstractEntity
return true;
}
public function toString(array $domainConfig): string
{
return (new Uri())->withPath($this->shortCode)
->withScheme($domainConfig['schema'] ?? 'http')
->withHost($this->resolveDomain($domainConfig['hostname'] ?? ''))
->__toString();
}
private function resolveDomain(string $fallback = ''): string
{
if ($this->domain === null) {
return $fallback;
}
return $this->domain->getAuthority();
}
}

View File

@@ -12,10 +12,10 @@ use GuzzleHttp\Promise\Promise;
use GuzzleHttp\Promise\PromiseInterface;
use GuzzleHttp\RequestOptions;
use Psr\Log\LoggerInterface;
use Shlinkio\Shlink\Common\Rest\DataTransformerInterface;
use Shlinkio\Shlink\Core\Entity\Visit;
use Shlinkio\Shlink\Core\EventDispatcher\Event\VisitLocated;
use Shlinkio\Shlink\Core\Options\AppOptions;
use Shlinkio\Shlink\Core\Transformer\ShortUrlDataTransformer;
use Throwable;
use function Functional\map;
@@ -29,7 +29,7 @@ class NotifyVisitToWebHooks
private LoggerInterface $logger;
/** @var string[] */
private array $webhooks;
private ShortUrlDataTransformer $transformer;
private DataTransformerInterface $transformer;
private AppOptions $appOptions;
public function __construct(
@@ -37,14 +37,14 @@ class NotifyVisitToWebHooks
EntityManagerInterface $em,
LoggerInterface $logger,
array $webhooks,
array $domainConfig,
DataTransformerInterface $transformer,
AppOptions $appOptions
) {
$this->httpClient = $httpClient;
$this->em = $em;
$this->logger = $logger;
$this->webhooks = $webhooks;
$this->transformer = new ShortUrlDataTransformer($domainConfig);
$this->transformer = $transformer;
$this->appOptions = $appOptions;
}

View File

@@ -4,8 +4,8 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\Core\Mercure;
use Shlinkio\Shlink\Common\Rest\DataTransformerInterface;
use Shlinkio\Shlink\Core\Entity\Visit;
use Shlinkio\Shlink\Core\Transformer\ShortUrlDataTransformer;
use Symfony\Component\Mercure\Update;
use function json_encode;
@@ -17,11 +17,11 @@ final class MercureUpdatesGenerator implements MercureUpdatesGeneratorInterface
{
private const NEW_VISIT_TOPIC = 'https://shlink.io/new-visit';
private ShortUrlDataTransformer $transformer;
private DataTransformerInterface $transformer;
public function __construct(array $domainConfig)
public function __construct(DataTransformerInterface $transformer)
{
$this->transformer = new ShortUrlDataTransformer($domainConfig);
$this->transformer = $transformer;
}
public function newVisitUpdate(Visit $visit): Update

View File

@@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\Core\ShortUrl\Helper;
use Laminas\Diactoros\Uri;
use Shlinkio\Shlink\Core\Entity\ShortUrl;
class ShortUrlStringifier implements ShortUrlStringifierInterface
{
private array $domainConfig;
public function __construct(array $domainConfig)
{
$this->domainConfig = $domainConfig;
}
public function stringify(ShortUrl $shortUrl): string
{
return (new Uri())->withPath($shortUrl->getShortCode())
->withScheme($this->domainConfig['schema'] ?? 'http')
->withHost($this->resolveDomain($shortUrl))
->__toString();
}
private function resolveDomain(ShortUrl $shortUrl): string
{
$domain = $shortUrl->getDomain();
if ($domain === null) {
return $this->domainConfig['hostname'] ?? '';
}
return $domain->getAuthority();
}
}

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\Core\ShortUrl\Helper;
use Shlinkio\Shlink\Core\Entity\ShortUrl;
interface ShortUrlStringifierInterface
{
public function stringify(ShortUrl $shortUrl): string;
}

View File

@@ -2,21 +2,22 @@
declare(strict_types=1);
namespace Shlinkio\Shlink\Core\Transformer;
namespace Shlinkio\Shlink\Core\ShortUrl\Transformer;
use Shlinkio\Shlink\Common\Rest\DataTransformerInterface;
use Shlinkio\Shlink\Core\Entity\ShortUrl;
use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortUrlStringifierInterface;
use function Functional\invoke;
use function Functional\invoke_if;
class ShortUrlDataTransformer implements DataTransformerInterface
{
private array $domainConfig;
private ShortUrlStringifierInterface $stringifier;
public function __construct(array $domainConfig)
public function __construct(ShortUrlStringifierInterface $stringifier)
{
$this->domainConfig = $domainConfig;
$this->stringifier = $stringifier;
}
/**
@@ -26,7 +27,7 @@ class ShortUrlDataTransformer implements DataTransformerInterface
{
return [
'shortCode' => $shortUrl->getShortCode(),
'shortUrl' => $shortUrl->toString($this->domainConfig),
'shortUrl' => $this->stringifier->stringify($shortUrl),
'longUrl' => $shortUrl->getLongUrl(),
'dateCreated' => $shortUrl->getDateCreated()->toAtomString(),
'visitsCount' => $shortUrl->getVisitsCount(),