Updated resolve short url action to return all data for that short url

This commit is contained in:
Alejandro Celaya 2018-08-11 10:40:44 +02:00
parent 2d6d35a398
commit 563021bdc1
15 changed files with 52 additions and 72 deletions

View file

@ -66,8 +66,10 @@ class ResolveUrlCommand extends Command
$shortCode = $input->getArgument('shortCode'); $shortCode = $input->getArgument('shortCode');
try { try {
$longUrl = $this->urlShortener->shortCodeToUrl($shortCode); $url = $this->urlShortener->shortCodeToUrl($shortCode);
$output->writeln(\sprintf('%s <info>%s</info>', $this->translator->translate('Long URL:'), $longUrl)); $output->writeln(
\sprintf('%s <info>%s</info>', $this->translator->translate('Long URL:'), $url->getLongUrl())
);
} catch (InvalidShortCodeException $e) { } catch (InvalidShortCodeException $e) {
$io->error( $io->error(
\sprintf($this->translator->translate('Provided short code "%s" has an invalid format.'), $shortCode) \sprintf($this->translator->translate('Provided short code "%s" has an invalid format.'), $shortCode)

View file

@ -6,6 +6,7 @@ namespace ShlinkioTest\Shlink\CLI\Command\Shortcode;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Prophecy\Prophecy\ObjectProphecy; use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\CLI\Command\Shortcode\ResolveUrlCommand; use Shlinkio\Shlink\CLI\Command\Shortcode\ResolveUrlCommand;
use Shlinkio\Shlink\Core\Entity\ShortUrl;
use Shlinkio\Shlink\Core\Exception\EntityDoesNotExistException; use Shlinkio\Shlink\Core\Exception\EntityDoesNotExistException;
use Shlinkio\Shlink\Core\Exception\InvalidShortCodeException; use Shlinkio\Shlink\Core\Exception\InvalidShortCodeException;
use Shlinkio\Shlink\Core\Service\UrlShortener; use Shlinkio\Shlink\Core\Service\UrlShortener;
@ -41,7 +42,8 @@ class ResolveUrlCommandTest extends TestCase
{ {
$shortCode = 'abc123'; $shortCode = 'abc123';
$expectedUrl = 'http://domain.com/foo/bar'; $expectedUrl = 'http://domain.com/foo/bar';
$this->urlShortener->shortCodeToUrl($shortCode)->willReturn($expectedUrl) $shortUrl = (new ShortUrl())->setLongUrl($expectedUrl);
$this->urlShortener->shortCodeToUrl($shortCode)->willReturn($shortUrl)
->shouldBeCalledTimes(1); ->shouldBeCalledTimes(1);
$this->commandTester->execute([ $this->commandTester->execute([

View file

@ -42,7 +42,6 @@ return [
Service\UrlShortener::class => [ Service\UrlShortener::class => [
'httpClient', 'httpClient',
'em', 'em',
Cache::class,
'config.url_shortener.validate_url', 'config.url_shortener.validate_url',
'config.url_shortener.shortcode_chars', 'config.url_shortener.shortcode_chars',
], ],

View file

@ -65,14 +65,14 @@ abstract class AbstractTrackingAction implements MiddlewareInterface
$disableTrackParam = $this->appOptions->getDisableTrackParam(); $disableTrackParam = $this->appOptions->getDisableTrackParam();
try { try {
$longUrl = $this->urlShortener->shortCodeToUrl($shortCode); $url = $this->urlShortener->shortCodeToUrl($shortCode);
// Track visit to this short code // Track visit to this short code
if ($disableTrackParam === null || ! \array_key_exists($disableTrackParam, $query)) { if ($disableTrackParam === null || ! \array_key_exists($disableTrackParam, $query)) {
$this->visitTracker->track($shortCode, $request); $this->visitTracker->track($shortCode, $request);
} }
return $this->createResp($longUrl); return $this->createResp($url->getLongUrl());
} catch (InvalidShortCodeException | EntityDoesNotExistException $e) { } catch (InvalidShortCodeException | EntityDoesNotExistException $e) {
$this->logger->warning('An error occurred while tracking short code.' . PHP_EOL . $e); $this->logger->warning('An error occurred while tracking short code.' . PHP_EOL . $e);
return $this->buildErrorResponse($request, $handler); return $this->buildErrorResponse($request, $handler);

View file

@ -60,7 +60,7 @@ class PreviewAction implements MiddlewareInterface
try { try {
$url = $this->urlShortener->shortCodeToUrl($shortCode); $url = $this->urlShortener->shortCodeToUrl($shortCode);
$imagePath = $this->previewGenerator->generatePreview($url); $imagePath = $this->previewGenerator->generatePreview($url->getLongUrl());
return $this->generateImageResponse($imagePath); return $this->generateImageResponse($imagePath);
} catch (InvalidShortCodeException | EntityDoesNotExistException | PreviewGenerationException $e) { } catch (InvalidShortCodeException | EntityDoesNotExistException | PreviewGenerationException $e) {
$this->logger->warning('An error occurred while generating preview image.' . PHP_EOL . $e); $this->logger->warning('An error occurred while generating preview image.' . PHP_EOL . $e);

View file

@ -5,7 +5,6 @@ namespace Shlinkio\Shlink\Core\Service;
use Cocur\Slugify\Slugify; use Cocur\Slugify\Slugify;
use Cocur\Slugify\SlugifyInterface; use Cocur\Slugify\SlugifyInterface;
use Doctrine\Common\Cache\Cache;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use GuzzleHttp\ClientInterface; use GuzzleHttp\ClientInterface;
use GuzzleHttp\Exception\GuzzleException; use GuzzleHttp\Exception\GuzzleException;
@ -37,10 +36,6 @@ class UrlShortener implements UrlShortenerInterface
* @var string * @var string
*/ */
private $chars; private $chars;
/**
* @var Cache
*/
private $cache;
/** /**
* @var SlugifyInterface * @var SlugifyInterface
*/ */
@ -53,14 +48,12 @@ class UrlShortener implements UrlShortenerInterface
public function __construct( public function __construct(
ClientInterface $httpClient, ClientInterface $httpClient,
EntityManagerInterface $em, EntityManagerInterface $em,
Cache $cache,
$urlValidationEnabled, $urlValidationEnabled,
$chars = self::DEFAULT_CHARS, $chars = self::DEFAULT_CHARS,
SlugifyInterface $slugger = null SlugifyInterface $slugger = null
) { ) {
$this->httpClient = $httpClient; $this->httpClient = $httpClient;
$this->em = $em; $this->em = $em;
$this->cache = $cache;
$this->urlValidationEnabled = $urlValidationEnabled; $this->urlValidationEnabled = $urlValidationEnabled;
$this->chars = empty($chars) ? self::DEFAULT_CHARS : $chars; $this->chars = empty($chars) ? self::DEFAULT_CHARS : $chars;
$this->slugger = $slugger ?: new Slugify(); $this->slugger = $slugger ?: new Slugify();
@ -192,19 +185,11 @@ class UrlShortener implements UrlShortenerInterface
/** /**
* Tries to find the mapped URL for provided short code. Returns null if not found * Tries to find the mapped URL for provided short code. Returns null if not found
* *
* @param string $shortCode
* @return string
* @throws InvalidShortCodeException * @throws InvalidShortCodeException
* @throws EntityDoesNotExistException * @throws EntityDoesNotExistException
*/ */
public function shortCodeToUrl(string $shortCode): string public function shortCodeToUrl(string $shortCode): ShortUrl
{ {
$cacheKey = sprintf('%s_longUrl', $shortCode);
// Check if the short code => URL map is already cached
if ($this->cache->contains($cacheKey)) {
return $this->cache->fetch($cacheKey);
}
// Validate short code format // Validate short code format
if (! preg_match('|[' . $this->chars . ']+|', $shortCode)) { if (! preg_match('|[' . $this->chars . ']+|', $shortCode)) {
throw InvalidShortCodeException::fromCharset($shortCode, $this->chars); throw InvalidShortCodeException::fromCharset($shortCode, $this->chars);
@ -219,9 +204,6 @@ class UrlShortener implements UrlShortenerInterface
]); ]);
} }
// Cache the shortcode return $shortUrl;
$url = $shortUrl->getOriginalUrl();
$this->cache->save($cacheKey, $url);
return $url;
} }
} }

View file

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\Core\Service; namespace Shlinkio\Shlink\Core\Service;
use Psr\Http\Message\UriInterface; use Psr\Http\Message\UriInterface;
use Shlinkio\Shlink\Core\Entity\ShortUrl;
use Shlinkio\Shlink\Core\Exception\EntityDoesNotExistException; use Shlinkio\Shlink\Core\Exception\EntityDoesNotExistException;
use Shlinkio\Shlink\Core\Exception\InvalidShortCodeException; use Shlinkio\Shlink\Core\Exception\InvalidShortCodeException;
use Shlinkio\Shlink\Core\Exception\InvalidUrlException; use Shlinkio\Shlink\Core\Exception\InvalidUrlException;
@ -21,7 +22,6 @@ interface UrlShortenerInterface
* @param \DateTime|null $validUntil * @param \DateTime|null $validUntil
* @param string|null $customSlug * @param string|null $customSlug
* @param int|null $maxVisits * @param int|null $maxVisits
* @return string
* @throws NonUniqueSlugException * @throws NonUniqueSlugException
* @throws InvalidUrlException * @throws InvalidUrlException
* @throws RuntimeException * @throws RuntimeException
@ -38,10 +38,8 @@ interface UrlShortenerInterface
/** /**
* Tries to find the mapped URL for provided short code. Returns null if not found * Tries to find the mapped URL for provided short code. Returns null if not found
* *
* @param string $shortCode
* @return string
* @throws InvalidShortCodeException * @throws InvalidShortCodeException
* @throws EntityDoesNotExistException * @throws EntityDoesNotExistException
*/ */
public function shortCodeToUrl(string $shortCode): string; public function shortCodeToUrl(string $shortCode): ShortUrl;
} }

View file

@ -9,6 +9,7 @@ use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\Common\Response\PixelResponse; use Shlinkio\Shlink\Common\Response\PixelResponse;
use Shlinkio\Shlink\Core\Action\PixelAction; use Shlinkio\Shlink\Core\Action\PixelAction;
use Shlinkio\Shlink\Core\Action\RedirectAction; use Shlinkio\Shlink\Core\Action\RedirectAction;
use Shlinkio\Shlink\Core\Entity\ShortUrl;
use Shlinkio\Shlink\Core\Options\AppOptions; use Shlinkio\Shlink\Core\Options\AppOptions;
use Shlinkio\Shlink\Core\Service\UrlShortener; use Shlinkio\Shlink\Core\Service\UrlShortener;
use Shlinkio\Shlink\Core\Service\VisitsTracker; use Shlinkio\Shlink\Core\Service\VisitsTracker;
@ -48,8 +49,9 @@ class PixelActionTest extends TestCase
public function imageIsReturned() public function imageIsReturned()
{ {
$shortCode = 'abc123'; $shortCode = 'abc123';
$this->urlShortener->shortCodeToUrl($shortCode)->willReturn('http://domain.com/foo/bar') $this->urlShortener->shortCodeToUrl($shortCode)->willReturn(
->shouldBeCalledTimes(1); (new ShortUrl())->setLongUrl('http://domain.com/foo/bar')
)->shouldBeCalledTimes(1);
$this->visitTracker->track(Argument::cetera())->willReturn(null) $this->visitTracker->track(Argument::cetera())->willReturn(null)
->shouldBeCalledTimes(1); ->shouldBeCalledTimes(1);

View file

@ -10,6 +10,7 @@ use Prophecy\Prophecy\ObjectProphecy;
use Psr\Http\Server\RequestHandlerInterface; use Psr\Http\Server\RequestHandlerInterface;
use Shlinkio\Shlink\Common\Service\PreviewGenerator; use Shlinkio\Shlink\Common\Service\PreviewGenerator;
use Shlinkio\Shlink\Core\Action\PreviewAction; use Shlinkio\Shlink\Core\Action\PreviewAction;
use Shlinkio\Shlink\Core\Entity\ShortUrl;
use Shlinkio\Shlink\Core\Exception\EntityDoesNotExistException; use Shlinkio\Shlink\Core\Exception\EntityDoesNotExistException;
use Shlinkio\Shlink\Core\Exception\InvalidShortCodeException; use Shlinkio\Shlink\Core\Exception\InvalidShortCodeException;
use Shlinkio\Shlink\Core\Service\UrlShortener; use Shlinkio\Shlink\Core\Service\UrlShortener;
@ -64,8 +65,9 @@ class PreviewActionTest extends TestCase
{ {
$shortCode = 'abc123'; $shortCode = 'abc123';
$url = 'foobar.com'; $url = 'foobar.com';
$shortUrl = (new ShortUrl())->setLongUrl($url);
$path = __FILE__; $path = __FILE__;
$this->urlShortener->shortCodeToUrl($shortCode)->willReturn($url)->shouldBeCalledTimes(1); $this->urlShortener->shortCodeToUrl($shortCode)->willReturn($shortUrl)->shouldBeCalledTimes(1);
$this->previewGenerator->generatePreview($url)->willReturn($path)->shouldBeCalledTimes(1); $this->previewGenerator->generatePreview($url)->willReturn($path)->shouldBeCalledTimes(1);
$resp = $this->action->process( $resp = $this->action->process(

View file

@ -10,6 +10,7 @@ use Prophecy\Prophecy\ObjectProphecy;
use Psr\Http\Server\RequestHandlerInterface; use Psr\Http\Server\RequestHandlerInterface;
use Shlinkio\Shlink\Common\Response\QrCodeResponse; use Shlinkio\Shlink\Common\Response\QrCodeResponse;
use Shlinkio\Shlink\Core\Action\QrCodeAction; use Shlinkio\Shlink\Core\Action\QrCodeAction;
use Shlinkio\Shlink\Core\Entity\ShortUrl;
use Shlinkio\Shlink\Core\Exception\EntityDoesNotExistException; use Shlinkio\Shlink\Core\Exception\EntityDoesNotExistException;
use Shlinkio\Shlink\Core\Exception\InvalidShortCodeException; use Shlinkio\Shlink\Core\Exception\InvalidShortCodeException;
use Shlinkio\Shlink\Core\Service\UrlShortener; use Shlinkio\Shlink\Core\Service\UrlShortener;
@ -83,7 +84,8 @@ class QrCodeActionTest extends TestCase
public function aCorrectRequestReturnsTheQrCodeResponse() public function aCorrectRequestReturnsTheQrCodeResponse()
{ {
$shortCode = 'abc123'; $shortCode = 'abc123';
$this->urlShortener->shortCodeToUrl($shortCode)->willReturn('')->shouldBeCalledTimes(1); $this->urlShortener->shortCodeToUrl($shortCode)->willReturn((new ShortUrl())->setLongUrl(''))
->shouldBeCalledTimes(1);
$delegate = $this->prophesize(RequestHandlerInterface::class); $delegate = $this->prophesize(RequestHandlerInterface::class);
$resp = $this->action->process( $resp = $this->action->process(

View file

@ -9,6 +9,7 @@ use Prophecy\Prophecy\MethodProphecy;
use Prophecy\Prophecy\ObjectProphecy; use Prophecy\Prophecy\ObjectProphecy;
use Psr\Http\Server\RequestHandlerInterface; use Psr\Http\Server\RequestHandlerInterface;
use Shlinkio\Shlink\Core\Action\RedirectAction; use Shlinkio\Shlink\Core\Action\RedirectAction;
use Shlinkio\Shlink\Core\Entity\ShortUrl;
use Shlinkio\Shlink\Core\Exception\EntityDoesNotExistException; use Shlinkio\Shlink\Core\Exception\EntityDoesNotExistException;
use Shlinkio\Shlink\Core\Options\AppOptions; use Shlinkio\Shlink\Core\Options\AppOptions;
use Shlinkio\Shlink\Core\Service\UrlShortener; use Shlinkio\Shlink\Core\Service\UrlShortener;
@ -51,7 +52,8 @@ class RedirectActionTest extends TestCase
{ {
$shortCode = 'abc123'; $shortCode = 'abc123';
$expectedUrl = 'http://domain.com/foo/bar'; $expectedUrl = 'http://domain.com/foo/bar';
$this->urlShortener->shortCodeToUrl($shortCode)->willReturn($expectedUrl) $shortUrl = (new ShortUrl())->setLongUrl($expectedUrl);
$this->urlShortener->shortCodeToUrl($shortCode)->willReturn($shortUrl)
->shouldBeCalledTimes(1); ->shouldBeCalledTimes(1);
$this->visitTracker->track(Argument::cetera())->willReturn(null) $this->visitTracker->track(Argument::cetera())->willReturn(null)
->shouldBeCalledTimes(1); ->shouldBeCalledTimes(1);
@ -93,7 +95,8 @@ class RedirectActionTest extends TestCase
{ {
$shortCode = 'abc123'; $shortCode = 'abc123';
$expectedUrl = 'http://domain.com/foo/bar'; $expectedUrl = 'http://domain.com/foo/bar';
$this->urlShortener->shortCodeToUrl($shortCode)->willReturn($expectedUrl) $shortUrl = (new ShortUrl())->setLongUrl($expectedUrl);
$this->urlShortener->shortCodeToUrl($shortCode)->willReturn($shortUrl)
->shouldBeCalledTimes(1); ->shouldBeCalledTimes(1);
$this->visitTracker->track(Argument::cetera())->willReturn(null) $this->visitTracker->track(Argument::cetera())->willReturn(null)
->shouldNotBeCalled(); ->shouldNotBeCalled();

View file

@ -4,8 +4,6 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\Core\Service; namespace ShlinkioTest\Shlink\Core\Service;
use Cocur\Slugify\SlugifyInterface; use Cocur\Slugify\SlugifyInterface;
use Doctrine\Common\Cache\ArrayCache;
use Doctrine\Common\Cache\Cache;
use Doctrine\Common\Persistence\ObjectRepository; use Doctrine\Common\Persistence\ObjectRepository;
use Doctrine\DBAL\Connection; use Doctrine\DBAL\Connection;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
@ -37,10 +35,6 @@ class UrlShortenerTest extends TestCase
* @var ObjectProphecy * @var ObjectProphecy
*/ */
protected $httpClient; protected $httpClient;
/**
* @var Cache
*/
protected $cache;
/** /**
* @var ObjectProphecy * @var ObjectProphecy
*/ */
@ -66,7 +60,6 @@ class UrlShortenerTest extends TestCase
$repo->findOneBy(Argument::any())->willReturn(null); $repo->findOneBy(Argument::any())->willReturn(null);
$this->em->getRepository(ShortUrl::class)->willReturn($repo->reveal()); $this->em->getRepository(ShortUrl::class)->willReturn($repo->reveal());
$this->cache = new ArrayCache();
$this->slugger = $this->prophesize(SlugifyInterface::class); $this->slugger = $this->prophesize(SlugifyInterface::class);
$this->setUrlShortener(false); $this->setUrlShortener(false);
@ -80,7 +73,6 @@ class UrlShortenerTest extends TestCase
$this->urlShortener = new UrlShortener( $this->urlShortener = new UrlShortener(
$this->httpClient->reveal(), $this->httpClient->reveal(),
$this->em->reveal(), $this->em->reveal(),
$this->cache,
$urlValidationEnabled, $urlValidationEnabled,
UrlShortener::DEFAULT_CHARS, UrlShortener::DEFAULT_CHARS,
$this->slugger->reveal() $this->slugger->reveal()
@ -205,10 +197,8 @@ class UrlShortenerTest extends TestCase
$repo->findOneByShortCode($shortCode)->willReturn($shortUrl); $repo->findOneByShortCode($shortCode)->willReturn($shortUrl);
$this->em->getRepository(ShortUrl::class)->willReturn($repo->reveal()); $this->em->getRepository(ShortUrl::class)->willReturn($repo->reveal());
$this->assertFalse($this->cache->contains($shortCode . '_longUrl'));
$url = $this->urlShortener->shortCodeToUrl($shortCode); $url = $this->urlShortener->shortCodeToUrl($shortCode);
$this->assertEquals($shortUrl->getOriginalUrl(), $url); $this->assertSame($shortUrl, $url);
$this->assertTrue($this->cache->contains($shortCode . '_longUrl'));
} }
/** /**
@ -219,18 +209,4 @@ class UrlShortenerTest extends TestCase
{ {
$this->urlShortener->shortCodeToUrl('&/('); $this->urlShortener->shortCodeToUrl('&/(');
} }
/**
* @test
*/
public function cachedShortCodeDoesNotHitDatabase()
{
$shortCode = '12C1c';
$expectedUrl = 'expected_url';
$this->cache->save($shortCode . '_longUrl', $expectedUrl);
$this->em->getRepository(ShortUrl::class)->willReturn(null)->shouldBeCalledTimes(0);
$url = $this->urlShortener->shortCodeToUrl($shortCode);
$this->assertEquals($expectedUrl, $url);
}
} }

View file

@ -59,7 +59,11 @@ return [
'Logger_Shlink', 'Logger_Shlink',
], ],
Action\ShortCode\EditShortCodeAction::class => [Service\ShortUrlService::class, 'translator', 'Logger_Shlink',], Action\ShortCode\EditShortCodeAction::class => [Service\ShortUrlService::class, 'translator', 'Logger_Shlink',],
Action\ShortCode\ResolveUrlAction::class => [Service\UrlShortener::class, 'translator'], Action\ShortCode\ResolveUrlAction::class => [
Service\UrlShortener::class,
'translator',
'config.url_shortener.domain',
],
Action\Visit\GetVisitsAction::class => [Service\VisitsTracker::class, 'translator', 'Logger_Shlink'], Action\Visit\GetVisitsAction::class => [Service\VisitsTracker::class, 'translator', 'Logger_Shlink'],
Action\ShortCode\ListShortCodesAction::class => [ Action\ShortCode\ListShortCodesAction::class => [
Service\ShortUrlService::class, Service\ShortUrlService::class,

View file

@ -9,6 +9,7 @@ use Psr\Log\LoggerInterface;
use Shlinkio\Shlink\Core\Exception\EntityDoesNotExistException; use Shlinkio\Shlink\Core\Exception\EntityDoesNotExistException;
use Shlinkio\Shlink\Core\Exception\InvalidShortCodeException; use Shlinkio\Shlink\Core\Exception\InvalidShortCodeException;
use Shlinkio\Shlink\Core\Service\UrlShortenerInterface; use Shlinkio\Shlink\Core\Service\UrlShortenerInterface;
use Shlinkio\Shlink\Core\Transformer\ShortUrlDataTransformer;
use Shlinkio\Shlink\Rest\Action\AbstractRestAction; use Shlinkio\Shlink\Rest\Action\AbstractRestAction;
use Shlinkio\Shlink\Rest\Util\RestUtils; use Shlinkio\Shlink\Rest\Util\RestUtils;
use Zend\Diactoros\Response\JsonResponse; use Zend\Diactoros\Response\JsonResponse;
@ -27,15 +28,21 @@ class ResolveUrlAction extends AbstractRestAction
* @var TranslatorInterface * @var TranslatorInterface
*/ */
private $translator; private $translator;
/**
* @var array
*/
private $domainConfig;
public function __construct( public function __construct(
UrlShortenerInterface $urlShortener, UrlShortenerInterface $urlShortener,
TranslatorInterface $translator, TranslatorInterface $translator,
array $domainConfig,
LoggerInterface $logger = null LoggerInterface $logger = null
) { ) {
parent::__construct($logger); parent::__construct($logger);
$this->urlShortener = $urlShortener; $this->urlShortener = $urlShortener;
$this->translator = $translator; $this->translator = $translator;
$this->domainConfig = $domainConfig;
} }
/** /**
@ -46,17 +53,16 @@ class ResolveUrlAction extends AbstractRestAction
public function handle(Request $request): Response public function handle(Request $request): Response
{ {
$shortCode = $request->getAttribute('shortCode'); $shortCode = $request->getAttribute('shortCode');
$transformer = new ShortUrlDataTransformer($this->domainConfig);
try { try {
$longUrl = $this->urlShortener->shortCodeToUrl($shortCode); $url = $this->urlShortener->shortCodeToUrl($shortCode);
return new JsonResponse([ return new JsonResponse($transformer->transform($url));
'longUrl' => $longUrl,
]);
} catch (InvalidShortCodeException $e) { } catch (InvalidShortCodeException $e) {
$this->logger->warning('Provided short code with invalid format.' . PHP_EOL . $e); $this->logger->warning('Provided short code with invalid format.' . PHP_EOL . $e);
return new JsonResponse([ return new JsonResponse([
'error' => RestUtils::getRestErrorCodeFromException($e), 'error' => RestUtils::getRestErrorCodeFromException($e),
'message' => sprintf( 'message' => \sprintf(
$this->translator->translate('Provided short code "%s" has an invalid format'), $this->translator->translate('Provided short code "%s" has an invalid format'),
$shortCode $shortCode
), ),
@ -65,7 +71,7 @@ class ResolveUrlAction extends AbstractRestAction
$this->logger->warning('Provided short code couldn\'t be found.' . PHP_EOL . $e); $this->logger->warning('Provided short code couldn\'t be found.' . PHP_EOL . $e);
return new JsonResponse([ return new JsonResponse([
'error' => RestUtils::INVALID_ARGUMENT_ERROR, 'error' => RestUtils::INVALID_ARGUMENT_ERROR,
'message' => sprintf($this->translator->translate('No URL found for short code "%s"'), $shortCode), 'message' => \sprintf($this->translator->translate('No URL found for short code "%s"'), $shortCode),
], self::STATUS_NOT_FOUND); ], self::STATUS_NOT_FOUND);
} catch (\Exception $e) { } catch (\Exception $e) {
$this->logger->error('Unexpected error while resolving the URL behind a short code.' . PHP_EOL . $e); $this->logger->error('Unexpected error while resolving the URL behind a short code.' . PHP_EOL . $e);

View file

@ -5,6 +5,7 @@ namespace ShlinkioTest\Shlink\Rest\Action\ShortCode;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Prophecy\Prophecy\ObjectProphecy; use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\Core\Entity\ShortUrl;
use Shlinkio\Shlink\Core\Exception\EntityDoesNotExistException; use Shlinkio\Shlink\Core\Exception\EntityDoesNotExistException;
use Shlinkio\Shlink\Core\Exception\InvalidShortCodeException; use Shlinkio\Shlink\Core\Exception\InvalidShortCodeException;
use Shlinkio\Shlink\Core\Service\UrlShortener; use Shlinkio\Shlink\Core\Service\UrlShortener;
@ -27,7 +28,7 @@ class ResolveUrlActionTest extends TestCase
public function setUp() public function setUp()
{ {
$this->urlShortener = $this->prophesize(UrlShortener::class); $this->urlShortener = $this->prophesize(UrlShortener::class);
$this->action = new ResolveUrlAction($this->urlShortener->reveal(), Translator::factory([])); $this->action = new ResolveUrlAction($this->urlShortener->reveal(), Translator::factory([]), []);
} }
/** /**
@ -51,8 +52,9 @@ class ResolveUrlActionTest extends TestCase
public function correctShortCodeReturnsSuccess() public function correctShortCodeReturnsSuccess()
{ {
$shortCode = 'abc123'; $shortCode = 'abc123';
$this->urlShortener->shortCodeToUrl($shortCode)->willReturn('http://domain.com/foo/bar') $this->urlShortener->shortCodeToUrl($shortCode)->willReturn(
->shouldBeCalledTimes(1); (new ShortUrl())->setLongUrl('http://domain.com/foo/bar')
)->shouldBeCalledTimes(1);
$request = ServerRequestFactory::fromGlobals()->withAttribute('shortCode', $shortCode); $request = ServerRequestFactory::fromGlobals()->withAttribute('shortCode', $shortCode);
$response = $this->action->handle($request); $response = $this->action->handle($request);