mirror of
https://github.com/shlinkio/shlink.git
synced 2024-11-23 01:16:23 -06:00
Created action to delete short URLs
This commit is contained in:
parent
159529937d
commit
5714a8f884
@ -26,6 +26,7 @@ return [
|
||||
Service\ShortUrlService::class => ConfigAbstractFactory::class,
|
||||
Service\VisitService::class => ConfigAbstractFactory::class,
|
||||
Service\Tag\TagService::class => ConfigAbstractFactory::class,
|
||||
Service\ShortUrl\DeleteShortUrlService::class => ConfigAbstractFactory::class,
|
||||
|
||||
// Middleware
|
||||
Action\RedirectAction::class => ConfigAbstractFactory::class,
|
||||
@ -50,6 +51,7 @@ return [
|
||||
Service\ShortUrlService::class => ['em'],
|
||||
Service\VisitService::class => ['em'],
|
||||
Service\Tag\TagService::class => ['em'],
|
||||
Service\ShortUrl\DeleteShortUrlService::class => ['em', Options\DeleteShortUrlsOptions::class],
|
||||
|
||||
// Middleware
|
||||
Action\RedirectAction::class => [
|
||||
|
@ -22,6 +22,10 @@ class QrCodeAction implements MiddlewareInterface
|
||||
{
|
||||
use ErrorResponseBuilderTrait;
|
||||
|
||||
private const DEFAULT_SIZE = 300;
|
||||
private const MIN_SIZE = 50;
|
||||
private const MAX_SIZE = 1000;
|
||||
|
||||
/**
|
||||
* @var RouterInterface
|
||||
*/
|
||||
@ -82,11 +86,11 @@ class QrCodeAction implements MiddlewareInterface
|
||||
*/
|
||||
private function getSizeParam(Request $request): int
|
||||
{
|
||||
$size = (int) $request->getAttribute('size', 300);
|
||||
if ($size < 50) {
|
||||
return 50;
|
||||
$size = (int) $request->getAttribute('size', self::DEFAULT_SIZE);
|
||||
if ($size < self::MIN_SIZE) {
|
||||
return self::MIN_SIZE;
|
||||
}
|
||||
|
||||
return $size > 1000 ? 1000 : $size;
|
||||
return $size > self::MAX_SIZE ? self::MAX_SIZE : $size;
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ return [
|
||||
Action\ShortCode\CreateShortCodeAction::class => ConfigAbstractFactory::class,
|
||||
Action\ShortCode\SingleStepCreateShortCodeAction::class => ConfigAbstractFactory::class,
|
||||
Action\ShortCode\EditShortCodeAction::class => ConfigAbstractFactory::class,
|
||||
Action\ShortCode\DeleteShortCodeAction::class => ConfigAbstractFactory::class,
|
||||
Action\ShortCode\ResolveUrlAction::class => ConfigAbstractFactory::class,
|
||||
Action\Visit\GetVisitsAction::class => ConfigAbstractFactory::class,
|
||||
Action\ShortCode\ListShortCodesAction::class => ConfigAbstractFactory::class,
|
||||
@ -58,7 +59,12 @@ return [
|
||||
'config.url_shortener.domain',
|
||||
'Logger_Shlink',
|
||||
],
|
||||
Action\ShortCode\EditShortCodeAction::class => [Service\ShortUrlService::class, 'translator', 'Logger_Shlink',],
|
||||
Action\ShortCode\EditShortCodeAction::class => [Service\ShortUrlService::class, 'translator', 'Logger_Shlink'],
|
||||
Action\ShortCode\DeleteShortCodeAction::class => [
|
||||
Service\ShortUrl\DeleteShortUrlService::class,
|
||||
'translator',
|
||||
'Logger_Shlink',
|
||||
],
|
||||
Action\ShortCode\ResolveUrlAction::class => [
|
||||
Service\UrlShortener::class,
|
||||
'translator',
|
||||
|
@ -18,6 +18,7 @@ return [
|
||||
Middleware\ShortCode\CreateShortCodeContentNegotiationMiddleware::class,
|
||||
]),
|
||||
Action\ShortCode\EditShortCodeAction::getRouteDef(),
|
||||
Action\ShortCode\DeleteShortCodeAction::getRouteDef(),
|
||||
Action\ShortCode\ResolveUrlAction::getRouteDef(),
|
||||
Action\ShortCode\ListShortCodesAction::getRouteDef(),
|
||||
Action\ShortCode\EditShortCodeTagsAction::getRouteDef(),
|
||||
|
71
module/Rest/src/Action/ShortCode/DeleteShortCodeAction.php
Normal file
71
module/Rest/src/Action/ShortCode/DeleteShortCodeAction.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\Rest\Action\ShortCode;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Shlinkio\Shlink\Core\Exception;
|
||||
use Shlinkio\Shlink\Core\Service\ShortUrl\DeleteShortUrlServiceInterface;
|
||||
use Shlinkio\Shlink\Rest\Action\AbstractRestAction;
|
||||
use Shlinkio\Shlink\Rest\Util\RestUtils;
|
||||
use Zend\Diactoros\Response\EmptyResponse;
|
||||
use Zend\Diactoros\Response\JsonResponse;
|
||||
use Zend\I18n\Translator\TranslatorInterface;
|
||||
|
||||
class DeleteShortCodeAction extends AbstractRestAction
|
||||
{
|
||||
protected const ROUTE_PATH = '/short-codes/{shortCode}';
|
||||
protected const ROUTE_ALLOWED_METHODS = [self::METHOD_DELETE];
|
||||
|
||||
/**
|
||||
* @var DeleteShortUrlServiceInterface
|
||||
*/
|
||||
private $deleteShortUrlService;
|
||||
/**
|
||||
* @var TranslatorInterface
|
||||
*/
|
||||
private $translator;
|
||||
|
||||
public function __construct(
|
||||
DeleteShortUrlServiceInterface $deleteShortUrlService,
|
||||
TranslatorInterface $translator,
|
||||
LoggerInterface $logger = null
|
||||
) {
|
||||
parent::__construct($logger);
|
||||
$this->deleteShortUrlService = $deleteShortUrlService;
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the request and return a response.
|
||||
*/
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
$shortCode = $request->getAttribute('shortCode', '');
|
||||
|
||||
try {
|
||||
$this->deleteShortUrlService->deleteByShortCode($shortCode);
|
||||
return new EmptyResponse();
|
||||
} catch (Exception\InvalidShortCodeException $e) {
|
||||
$this->logger->warning(
|
||||
\sprintf('Provided short code %s does not belong to any URL.', $shortCode) . PHP_EOL . $e
|
||||
);
|
||||
return new JsonResponse([
|
||||
'error' => RestUtils::getRestErrorCodeFromException($e),
|
||||
'message' => \sprintf($this->translator->translate('No URL found for short code "%s"'), $shortCode),
|
||||
], self::STATUS_NOT_FOUND);
|
||||
} catch (Exception\DeleteShortUrlException $e) {
|
||||
$this->logger->warning('Provided data is invalid.' . PHP_EOL . $e);
|
||||
$messagePlaceholder = $this->translator->translate(
|
||||
'It is not possible to delete URL with short code "%s" because it has reached more than "%s" visits.'
|
||||
);
|
||||
|
||||
return new JsonResponse([
|
||||
'error' => RestUtils::getRestErrorCodeFromException($e),
|
||||
'message' => \sprintf($messagePlaceholder, $shortCode, $e->getVisitsThreshold()),
|
||||
], self::STATUS_BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
}
|
@ -10,6 +10,7 @@ use Shlinkio\Shlink\Rest\Exception as Rest;
|
||||
class RestUtils
|
||||
{
|
||||
public const INVALID_SHORTCODE_ERROR = 'INVALID_SHORTCODE';
|
||||
public const INVALID_SHORTCODE_DELETION_ERROR = 'INVALID_SHORTCODE_DELETION';
|
||||
public const INVALID_URL_ERROR = 'INVALID_URL';
|
||||
public const INVALID_ARGUMENT_ERROR = 'INVALID_ARGUMENT';
|
||||
public const INVALID_SLUG_ERROR = 'INVALID_SLUG';
|
||||
@ -35,6 +36,8 @@ class RestUtils
|
||||
return self::INVALID_ARGUMENT_ERROR;
|
||||
case $e instanceof Rest\AuthenticationException:
|
||||
return self::INVALID_CREDENTIALS_ERROR;
|
||||
case $e instanceof Core\DeleteShortUrlException:
|
||||
return self::INVALID_SHORTCODE_DELETION_ERROR;
|
||||
default:
|
||||
return self::UNKNOWN_ERROR;
|
||||
}
|
||||
|
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ShlinkioTest\Shlink\Rest\Action\ShortCode;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\Core\Exception;
|
||||
use Shlinkio\Shlink\Core\Service\ShortUrl\DeleteShortUrlServiceInterface;
|
||||
use Shlinkio\Shlink\Rest\Action\ShortCode\DeleteShortCodeAction;
|
||||
use Shlinkio\Shlink\Rest\Util\RestUtils;
|
||||
use Zend\Diactoros\Response\JsonResponse;
|
||||
use Zend\Diactoros\ServerRequestFactory;
|
||||
use Zend\I18n\Translator\Translator;
|
||||
|
||||
class DeleteShortCodeActionTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var DeleteShortCodeAction
|
||||
*/
|
||||
private $action;
|
||||
/**
|
||||
* @var ObjectProphecy
|
||||
*/
|
||||
private $service;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->service = $this->prophesize(DeleteShortUrlServiceInterface::class);
|
||||
$this->action = new DeleteShortCodeAction($this->service->reveal(), Translator::factory([]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function emptyResponseIsReturnedIfProperlyDeleted()
|
||||
{
|
||||
$deleteByShortCode = $this->service->deleteByShortCode(Argument::any())->will(function () {
|
||||
});
|
||||
|
||||
$resp = $this->action->handle(ServerRequestFactory::fromGlobals());
|
||||
|
||||
$this->assertEquals(204, $resp->getStatusCode());
|
||||
$deleteByShortCode->shouldHaveBeenCalledTimes(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @dataProvider provideExceptions
|
||||
*/
|
||||
public function returnsErrorResponseInCaseOfException(\Throwable $e, string $error, int $statusCode)
|
||||
{
|
||||
$deleteByShortCode = $this->service->deleteByShortCode(Argument::any())->willThrow($e);
|
||||
|
||||
/** @var JsonResponse $resp */
|
||||
$resp = $this->action->handle(ServerRequestFactory::fromGlobals());
|
||||
$payload = $resp->getPayload();
|
||||
|
||||
$this->assertEquals($statusCode, $resp->getStatusCode());
|
||||
$this->assertEquals($error, $payload['error']);
|
||||
$deleteByShortCode->shouldHaveBeenCalledTimes(1);
|
||||
}
|
||||
|
||||
public function provideExceptions(): array
|
||||
{
|
||||
return [
|
||||
[new Exception\InvalidShortCodeException(), RestUtils::INVALID_SHORTCODE_ERROR, 404],
|
||||
[new Exception\DeleteShortUrlException(5), RestUtils::INVALID_SHORTCODE_DELETION_ERROR, 400],
|
||||
];
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user