diff --git a/module/Core/src/Action/QrCodeAction.php b/module/Core/src/Action/QrCodeAction.php index 5d0549eb..3970d740 100644 --- a/module/Core/src/Action/QrCodeAction.php +++ b/module/Core/src/Action/QrCodeAction.php @@ -3,6 +3,8 @@ namespace Shlinkio\Shlink\Core\Action; use Acelaya\ZsmAnnotatedServices\Annotation\Inject; use Endroid\QrCode\QrCode; +use Interop\Http\ServerMiddleware\DelegateInterface; +use Interop\Http\ServerMiddleware\MiddlewareInterface; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Log\LoggerInterface; @@ -12,7 +14,6 @@ use Shlinkio\Shlink\Core\Exception\InvalidShortCodeException; use Shlinkio\Shlink\Core\Service\UrlShortener; use Shlinkio\Shlink\Core\Service\UrlShortenerInterface; use Zend\Expressive\Router\RouterInterface; -use Zend\Stratigility\MiddlewareInterface; class QrCodeAction implements MiddlewareInterface { @@ -48,42 +49,26 @@ class QrCodeAction implements MiddlewareInterface } /** - * Process an incoming request and/or response. - * - * Accepts a server-side request and a response instance, and does - * something with them. - * - * If the response is not complete and/or further processing would not - * interfere with the work done in the middleware, or if the middleware - * wants to delegate to another process, it can use the `$out` callable - * if present. - * - * If the middleware does not return a value, execution of the current - * request is considered complete, and the response instance provided will - * be considered the response to return. - * - * Alternately, the middleware may return a response instance. - * - * Often, middleware will `return $out();`, with the assumption that a - * later middleware will return a response. + * Process an incoming server request and return a response, optionally delegating + * to the next middleware component to create the response. * * @param Request $request - * @param Response $response - * @param null|callable $out - * @return null|Response + * @param DelegateInterface $delegate + * + * @return Response */ - public function __invoke(Request $request, Response $response, callable $out = null) + public function process(Request $request, DelegateInterface $delegate) { // Make sure the short URL exists for this short code $shortCode = $request->getAttribute('shortCode'); try { $shortUrl = $this->urlShortener->shortCodeToUrl($shortCode); - if (! isset($shortUrl)) { - return $out($request, $response->withStatus(404), 'Not Found'); + if ($shortUrl === null) { + return $delegate->process($request); } } catch (InvalidShortCodeException $e) { $this->logger->warning('Tried to create a QR code with an invalid short code' . PHP_EOL . $e); - return $out($request, $response->withStatus(404), 'Not Found'); + return $delegate->process($request); } $path = $this->router->generateUri('long-url-redirect', ['shortCode' => $shortCode]); @@ -101,13 +86,11 @@ class QrCodeAction implements MiddlewareInterface */ protected function getSizeParam(Request $request) { - $size = intval($request->getAttribute('size', 300)); + $size = (int) $request->getAttribute('size', 300); if ($size < 50) { return 50; - } elseif ($size > 1000) { - return 1000; } - return $size; + return $size > 1000 ? 1000 : $size; } } diff --git a/module/Core/test/Action/QrCodeActionTest.php b/module/Core/test/Action/QrCodeActionTest.php index 6ef8a5f5..dc005b11 100644 --- a/module/Core/test/Action/QrCodeActionTest.php +++ b/module/Core/test/Action/QrCodeActionTest.php @@ -9,7 +9,7 @@ use Shlinkio\Shlink\Core\Action\QrCodeAction; use Shlinkio\Shlink\Core\Entity\ShortUrl; use Shlinkio\Shlink\Core\Exception\InvalidShortCodeException; use Shlinkio\Shlink\Core\Service\UrlShortener; -use Zend\Diactoros\Response; +use ShlinkioTest\Shlink\Common\Util\TestUtils; use Zend\Diactoros\ServerRequestFactory; use Zend\Expressive\Router\RouterInterface; @@ -37,19 +37,18 @@ class QrCodeActionTest extends TestCase /** * @test */ - public function aNonexistentShortCodeWillReturnNotFoundResponse() + public function aNotFoundShortCodeWillDelegateIntoNextMiddleware() { $shortCode = 'abc123'; $this->urlShortener->shortCodeToUrl($shortCode)->willReturn(null)->shouldBeCalledTimes(1); + $delegate = TestUtils::createDelegateMock(); - $resp = $this->action->__invoke( + $this->action->process( ServerRequestFactory::fromGlobals()->withAttribute('shortCode', $shortCode), - new Response(), - function ($req, $resp) { - return $resp; - } + $delegate->reveal() ); - $this->assertEquals(404, $resp->getStatusCode()); + + $delegate->process(Argument::any())->shouldHaveBeenCalledTimes(1); } /** @@ -60,15 +59,14 @@ class QrCodeActionTest extends TestCase $shortCode = 'abc123'; $this->urlShortener->shortCodeToUrl($shortCode)->willThrow(InvalidShortCodeException::class) ->shouldBeCalledTimes(1); + $delegate = TestUtils::createDelegateMock(); - $resp = $this->action->__invoke( + $this->action->process( ServerRequestFactory::fromGlobals()->withAttribute('shortCode', $shortCode), - new Response(), - function ($req, $resp) { - return $resp; - } + $delegate->reveal() ); - $this->assertEquals(404, $resp->getStatusCode()); + + $delegate->process(Argument::any())->shouldHaveBeenCalledTimes(1); } /** @@ -78,16 +76,15 @@ class QrCodeActionTest extends TestCase { $shortCode = 'abc123'; $this->urlShortener->shortCodeToUrl($shortCode)->willReturn(new ShortUrl())->shouldBeCalledTimes(1); + $delegate = TestUtils::createDelegateMock(); - $resp = $this->action->__invoke( + $resp = $this->action->process( ServerRequestFactory::fromGlobals()->withAttribute('shortCode', $shortCode), - new Response(), - function ($req, $resp) { - return $resp; - } + $delegate->reveal() ); $this->assertInstanceOf(QrCodeResponse::class, $resp); $this->assertEquals(200, $resp->getStatusCode()); + $delegate->process(Argument::any())->shouldHaveBeenCalledTimes(0); } }