diff --git a/module/CLI/src/Command/Shortcode/GenerateShortcodeCommand.php b/module/CLI/src/Command/Shortcode/GenerateShortcodeCommand.php index f4c56f98..08af7a86 100644 --- a/module/CLI/src/Command/Shortcode/GenerateShortcodeCommand.php +++ b/module/CLI/src/Command/Shortcode/GenerateShortcodeCommand.php @@ -6,6 +6,7 @@ namespace Shlinkio\Shlink\CLI\Command\Shortcode; use Shlinkio\Shlink\Core\Exception\InvalidUrlException; use Shlinkio\Shlink\Core\Exception\NonUniqueSlugException; use Shlinkio\Shlink\Core\Service\UrlShortenerInterface; +use Shlinkio\Shlink\Core\Util\ShortUrlBuilderTrait; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -17,7 +18,9 @@ use Zend\I18n\Translator\TranslatorInterface; class GenerateShortcodeCommand extends Command { - const NAME = 'shortcode:generate'; + use ShortUrlBuilderTrait; + + public const NAME = 'shortcode:generate'; /** * @var UrlShortenerInterface @@ -115,10 +118,8 @@ class GenerateShortcodeCommand extends Command $this->getOptionalDate($input, 'validUntil'), $customSlug, $maxVisits !== null ? (int) $maxVisits : null - ); - $shortUrl = (new Uri())->withPath($shortCode) - ->withScheme($this->domainConfig['schema']) - ->withHost($this->domainConfig['hostname']); + )->getShortCode(); + $shortUrl = $this->buildShortUrl($this->domainConfig, $shortCode); $io->writeln([ \sprintf('%s %s', $this->translator->translate('Processed long URL:'), $longUrl), diff --git a/module/CLI/src/Command/Shortcode/ListShortcodesCommand.php b/module/CLI/src/Command/Shortcode/ListShortcodesCommand.php index f0e9efa3..85caf840 100644 --- a/module/CLI/src/Command/Shortcode/ListShortcodesCommand.php +++ b/module/CLI/src/Command/Shortcode/ListShortcodesCommand.php @@ -117,7 +117,7 @@ class ListShortcodesCommand extends Command foreach ($result as $row) { $shortUrl = $transformer->transform($row); if ($showTags) { - $shortUrl['tags'] = implode(', ', $shortUrl['tags']); + $shortUrl['tags'] = \implode(', ', $shortUrl['tags']); } else { unset($shortUrl['tags']); } @@ -146,7 +146,7 @@ class ListShortcodesCommand extends Command return null; } - $orderBy = explode(',', $orderBy); - return count($orderBy) === 1 ? $orderBy[0] : [$orderBy[0] => $orderBy[1]]; + $orderBy = \explode(',', $orderBy); + return \count($orderBy) === 1 ? $orderBy[0] : [$orderBy[0] => $orderBy[1]]; } } diff --git a/module/CLI/test/Command/Shortcode/GenerateShortcodeCommandTest.php b/module/CLI/test/Command/Shortcode/GenerateShortcodeCommandTest.php index 5b83cc4f..501d036e 100644 --- a/module/CLI/test/Command/Shortcode/GenerateShortcodeCommandTest.php +++ b/module/CLI/test/Command/Shortcode/GenerateShortcodeCommandTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Prophecy\Prophecy\ObjectProphecy; use Shlinkio\Shlink\CLI\Command\Shortcode\GenerateShortcodeCommand; +use Shlinkio\Shlink\Core\Entity\ShortUrl; use Shlinkio\Shlink\Core\Exception\InvalidUrlException; use Shlinkio\Shlink\Core\Service\UrlShortener; use Symfony\Component\Console\Application; @@ -41,8 +42,12 @@ class GenerateShortcodeCommandTest extends TestCase */ public function properShortCodeIsCreatedIfLongUrlIsCorrect() { - $this->urlShortener->urlToShortCode(Argument::cetera())->willReturn('abc123') - ->shouldBeCalledTimes(1); + $this->urlShortener->urlToShortCode(Argument::cetera()) + ->willReturn( + (new ShortUrl())->setShortCode('abc123') + ->setLongUrl('') + ) + ->shouldBeCalledTimes(1); $this->commandTester->execute([ 'command' => 'shortcode:generate', diff --git a/module/Core/src/Service/UrlShortener.php b/module/Core/src/Service/UrlShortener.php index 50113b0b..4ae4c510 100644 --- a/module/Core/src/Service/UrlShortener.php +++ b/module/Core/src/Service/UrlShortener.php @@ -69,7 +69,6 @@ class UrlShortener implements UrlShortenerInterface * @param \DateTime|null $validUntil * @param string|null $customSlug * @param int|null $maxVisits - * @return string * @throws NonUniqueSlugException * @throws InvalidUrlException * @throws RuntimeException @@ -81,7 +80,7 @@ class UrlShortener implements UrlShortenerInterface \DateTime $validUntil = null, string $customSlug = null, int $maxVisits = null - ): string { + ): ShortUrl { // If the URL validation is enabled, check that the URL actually exists if ($this->urlValidationEnabled) { $this->checkUrlExists($url); @@ -108,7 +107,7 @@ class UrlShortener implements UrlShortenerInterface $this->em->flush(); $this->em->commit(); - return $shortCode; + return $shortUrl; } catch (\Throwable $e) { if ($this->em->getConnection()->isTransactionActive()) { $this->em->rollback(); diff --git a/module/Core/src/Service/UrlShortenerInterface.php b/module/Core/src/Service/UrlShortenerInterface.php index 7b97af91..a12b78ff 100644 --- a/module/Core/src/Service/UrlShortenerInterface.php +++ b/module/Core/src/Service/UrlShortenerInterface.php @@ -33,7 +33,7 @@ interface UrlShortenerInterface \DateTime $validUntil = null, string $customSlug = null, int $maxVisits = null - ): string; + ): ShortUrl; /** * Tries to find the mapped URL for provided short code. Returns null if not found diff --git a/module/Core/src/Transformer/ShortUrlDataTransformer.php b/module/Core/src/Transformer/ShortUrlDataTransformer.php index c1113a81..0c0fb2cd 100644 --- a/module/Core/src/Transformer/ShortUrlDataTransformer.php +++ b/module/Core/src/Transformer/ShortUrlDataTransformer.php @@ -6,9 +6,12 @@ namespace Shlinkio\Shlink\Core\Transformer; use Shlinkio\Shlink\Common\Rest\DataTransformerInterface; use Shlinkio\Shlink\Core\Entity\ShortUrl; use Shlinkio\Shlink\Core\Entity\Tag; +use Shlinkio\Shlink\Core\Util\ShortUrlBuilderTrait; class ShortUrlDataTransformer implements DataTransformerInterface { + use ShortUrlBuilderTrait; + /** * @var array */ @@ -31,12 +34,7 @@ class ShortUrlDataTransformer implements DataTransformerInterface return [ 'shortCode' => $shortCode, - 'shortUrl' => \sprintf( - '%s://%s/%s', - $this->domainConfig['schema'] ?? 'http', - $this->domainConfig['hostname'] ?? '', - $shortCode - ), + 'shortUrl' => $this->buildShortUrl($this->domainConfig, $shortCode), 'longUrl' => $longUrl, 'dateCreated' => $dateCreated !== null ? $dateCreated->format(\DateTime::ATOM) : null, 'visitsCount' => $value->getVisitsCount(), diff --git a/module/Core/src/Util/ShortUrlBuilderTrait.php b/module/Core/src/Util/ShortUrlBuilderTrait.php new file mode 100644 index 00000000..fe627b0f --- /dev/null +++ b/module/Core/src/Util/ShortUrlBuilderTrait.php @@ -0,0 +1,16 @@ +withPath($shortCode) + ->withScheme($domainConfig['schema'] ?? 'http') + ->withHost($domainConfig['hostname'] ?? ''); + } +} diff --git a/module/Core/test/Service/UrlShortenerTest.php b/module/Core/test/Service/UrlShortenerTest.php index b28c57a3..234240b7 100644 --- a/module/Core/test/Service/UrlShortenerTest.php +++ b/module/Core/test/Service/UrlShortenerTest.php @@ -85,8 +85,8 @@ class UrlShortenerTest extends TestCase public function urlIsProperlyShortened() { // 10 -> 12C1c - $shortCode = $this->urlShortener->urlToShortCode(new Uri('http://foobar.com/12345/hello?foo=bar')); - $this->assertEquals('12C1c', $shortCode); + $shortUrl = $this->urlShortener->urlToShortCode(new Uri('http://foobar.com/12345/hello?foo=bar')); + $this->assertEquals('12C1c', $shortUrl->getShortCode()); } /** diff --git a/module/Rest/src/Action/ShortCode/AbstractCreateShortCodeAction.php b/module/Rest/src/Action/ShortCode/AbstractCreateShortCodeAction.php index 57b87bc5..833f49c6 100644 --- a/module/Rest/src/Action/ShortCode/AbstractCreateShortCodeAction.php +++ b/module/Rest/src/Action/ShortCode/AbstractCreateShortCodeAction.php @@ -11,10 +11,10 @@ use Shlinkio\Shlink\Core\Exception\InvalidUrlException; use Shlinkio\Shlink\Core\Exception\NonUniqueSlugException; use Shlinkio\Shlink\Core\Model\CreateShortCodeData; use Shlinkio\Shlink\Core\Service\UrlShortenerInterface; +use Shlinkio\Shlink\Core\Transformer\ShortUrlDataTransformer; use Shlinkio\Shlink\Rest\Action\AbstractRestAction; use Shlinkio\Shlink\Rest\Util\RestUtils; use Zend\Diactoros\Response\JsonResponse; -use Zend\Diactoros\Uri; use Zend\I18n\Translator\TranslatorInterface; abstract class AbstractCreateShortCodeAction extends AbstractRestAction @@ -65,7 +65,7 @@ abstract class AbstractCreateShortCodeAction extends AbstractRestAction } try { - $shortCode = $this->urlShortener->urlToShortCode( + $shortUrl = $this->urlShortener->urlToShortCode( $longUrl, $shortCodeData->getTags(), $shortCodeMeta->getValidSince(), @@ -73,15 +73,9 @@ abstract class AbstractCreateShortCodeAction extends AbstractRestAction $customSlug, $shortCodeMeta->getMaxVisits() ); - $shortUrl = (new Uri())->withPath($shortCode) - ->withScheme($this->domainConfig['schema']) - ->withHost($this->domainConfig['hostname']); + $transformer = new ShortUrlDataTransformer($this->domainConfig); - return new JsonResponse([ - 'longUrl' => (string) $longUrl, - 'shortUrl' => (string) $shortUrl, - 'shortCode' => $shortCode, - ]); + return new JsonResponse($transformer->transform($shortUrl)); } catch (InvalidUrlException $e) { $this->logger->warning('Provided Invalid URL.' . PHP_EOL . $e); return new JsonResponse([ diff --git a/module/Rest/test/Action/ShortCode/CreateShortCodeActionTest.php b/module/Rest/test/Action/ShortCode/CreateShortCodeActionTest.php index 3ac5ad33..8b7afe7c 100644 --- a/module/Rest/test/Action/ShortCode/CreateShortCodeActionTest.php +++ b/module/Rest/test/Action/ShortCode/CreateShortCodeActionTest.php @@ -6,6 +6,7 @@ namespace ShlinkioTest\Shlink\Rest\Action\ShortCode; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Prophecy\Prophecy\ObjectProphecy; +use Shlinkio\Shlink\Core\Entity\ShortUrl; use Shlinkio\Shlink\Core\Exception\InvalidUrlException; use Shlinkio\Shlink\Core\Exception\NonUniqueSlugException; use Shlinkio\Shlink\Core\Service\UrlShortener; @@ -50,7 +51,10 @@ class CreateShortCodeActionTest extends TestCase public function properShortcodeConversionReturnsData() { $this->urlShortener->urlToShortCode(Argument::type(Uri::class), Argument::type('array'), Argument::cetera()) - ->willReturn('abc123') + ->willReturn( + (new ShortUrl())->setShortCode('abc123') + ->setLongUrl('') + ) ->shouldBeCalledTimes(1); $request = ServerRequestFactory::fromGlobals()->withParsedBody([ diff --git a/module/Rest/test/Action/ShortCode/SingleStepCreateShortCodeActionTest.php b/module/Rest/test/Action/ShortCode/SingleStepCreateShortCodeActionTest.php index 88d722e5..0a7d6981 100644 --- a/module/Rest/test/Action/ShortCode/SingleStepCreateShortCodeActionTest.php +++ b/module/Rest/test/Action/ShortCode/SingleStepCreateShortCodeActionTest.php @@ -8,6 +8,7 @@ use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Prophecy\Prophecy\ObjectProphecy; use Psr\Http\Message\UriInterface; +use Shlinkio\Shlink\Core\Entity\ShortUrl; use Shlinkio\Shlink\Core\Service\UrlShortenerInterface; use Shlinkio\Shlink\Rest\Action\ShortCode\SingleStepCreateShortCodeAction; use Shlinkio\Shlink\Rest\Entity\ApiKey; @@ -112,7 +113,7 @@ class SingleStepCreateShortCodeActionTest extends TestCase null, null, null - ); + )->willReturn((new ShortUrl())->setLongUrl('')); $resp = $this->action->handle($request);