Removed everything that was deprecated

This commit is contained in:
Alejandro Celaya
2021-12-14 22:21:53 +01:00
parent 351e36b273
commit 1ff241411b
54 changed files with 108 additions and 1507 deletions

View File

@@ -22,7 +22,6 @@ return [
Command\Api\ListKeysCommand::NAME => Command\Api\ListKeysCommand::class,
Command\Tag\ListTagsCommand::NAME => Command\Tag\ListTagsCommand::class,
Command\Tag\CreateTagCommand::NAME => Command\Tag\CreateTagCommand::class,
Command\Tag\RenameTagCommand::NAME => Command\Tag\RenameTagCommand::class,
Command\Tag\DeleteTagsCommand::NAME => Command\Tag\DeleteTagsCommand::class,

View File

@@ -53,7 +53,6 @@ return [
Command\Api\ListKeysCommand::class => ConfigAbstractFactory::class,
Command\Tag\ListTagsCommand::class => ConfigAbstractFactory::class,
Command\Tag\CreateTagCommand::class => ConfigAbstractFactory::class,
Command\Tag\RenameTagCommand::class => ConfigAbstractFactory::class,
Command\Tag\DeleteTagsCommand::class => ConfigAbstractFactory::class,
@@ -101,7 +100,6 @@ return [
Command\Api\ListKeysCommand::class => [ApiKeyService::class],
Command\Tag\ListTagsCommand::class => [TagService::class],
Command\Tag\CreateTagCommand::class => [TagService::class],
Command\Tag\RenameTagCommand::class => [TagService::class],
Command\Tag\DeleteTagsCommand::class => [TagService::class],

View File

@@ -6,11 +6,11 @@ namespace Shlinkio\Shlink\CLI\Command\Api;
use Cake\Chronos\Chronos;
use Shlinkio\Shlink\CLI\ApiKey\RoleResolverInterface;
use Shlinkio\Shlink\CLI\Command\BaseCommand;
use Shlinkio\Shlink\CLI\Util\ExitCodes;
use Shlinkio\Shlink\CLI\Util\ShlinkTable;
use Shlinkio\Shlink\Rest\ApiKey\Role;
use Shlinkio\Shlink\Rest\Service\ApiKeyServiceInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
@@ -19,7 +19,7 @@ use Symfony\Component\Console\Style\SymfonyStyle;
use function Shlinkio\Shlink\Core\arrayToString;
use function sprintf;
class GenerateKeyCommand extends BaseCommand
class GenerateKeyCommand extends Command
{
public const NAME = 'api-key:generate';
@@ -63,7 +63,7 @@ class GenerateKeyCommand extends BaseCommand
InputOption::VALUE_REQUIRED,
'The name by which this API key will be known.',
)
->addOptionWithDeprecatedFallback(
->addOption(
'expiration-date',
'e',
InputOption::VALUE_REQUIRED,
@@ -86,7 +86,7 @@ class GenerateKeyCommand extends BaseCommand
protected function execute(InputInterface $input, OutputInterface $output): ?int
{
$expirationDate = $this->getOptionWithDeprecatedFallback($input, 'expiration-date');
$expirationDate = $input->getOption('expiration-date');
$apiKey = $this->apiKeyService->create(
isset($expirationDate) ? Chronos::parse($expirationDate) : null,
$input->getOption('name'),

View File

@@ -4,12 +4,12 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Api;
use Shlinkio\Shlink\CLI\Command\BaseCommand;
use Shlinkio\Shlink\CLI\Util\ExitCodes;
use Shlinkio\Shlink\CLI\Util\ShlinkTable;
use Shlinkio\Shlink\Rest\ApiKey\Role;
use Shlinkio\Shlink\Rest\Entity\ApiKey;
use Shlinkio\Shlink\Rest\Service\ApiKeyServiceInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
@@ -19,7 +19,7 @@ use function Functional\map;
use function implode;
use function sprintf;
class ListKeysCommand extends BaseCommand
class ListKeysCommand extends Command
{
private const ERROR_STRING_PATTERN = '<fg=red>%s</>';
private const SUCCESS_STRING_PATTERN = '<info>%s</info>';
@@ -37,7 +37,7 @@ class ListKeysCommand extends BaseCommand
$this
->setName(self::NAME)
->setDescription('Lists all the available API keys.')
->addOptionWithDeprecatedFallback(
->addOption(
'enabled-only',
'e',
InputOption::VALUE_NONE,
@@ -47,7 +47,7 @@ class ListKeysCommand extends BaseCommand
protected function execute(InputInterface $input, OutputInterface $output): ?int
{
$enabledOnly = $this->getOptionWithDeprecatedFallback($input, 'enabled-only');
$enabledOnly = $input->getOption('enabled-only');
$rows = map($this->apiKeyService->listKeys($enabledOnly), function (ApiKey $apiKey) use ($enabledOnly) {
$expiration = $apiKey->getExpirationDate();

View File

@@ -1,47 +0,0 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use function method_exists;
use function Shlinkio\Shlink\Core\kebabCaseToCamelCase;
use function sprintf;
use function str_contains;
/** @deprecated */
abstract class BaseCommand extends Command
{
/**
* @param string|string[]|bool|null $default
*/
protected function addOptionWithDeprecatedFallback(
string $name,
?string $shortcut = null,
?int $mode = null,
string $description = '',
bool|string|array|null $default = null,
): self {
$this->addOption($name, $shortcut, $mode, $description, $default);
if (str_contains($name, '-')) {
$camelCaseName = kebabCaseToCamelCase($name);
$this->addOption($camelCaseName, null, $mode, sprintf('[DEPRECATED] Alias for "%s".', $name), $default);
}
return $this;
}
// @phpstan-ignore-next-line
protected function getOptionWithDeprecatedFallback(InputInterface $input, string $name) // phpcs:ignore
{
$rawInput = method_exists($input, '__toString') ? $input->__toString() : '';
$camelCaseName = kebabCaseToCamelCase($name);
$resolvedOptionName = str_contains($rawInput, $camelCaseName) ? $camelCaseName : $name;
return $input->getOption($resolvedOptionName);
}
}

View File

@@ -4,7 +4,6 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\ShortUrl;
use Shlinkio\Shlink\CLI\Command\BaseCommand;
use Shlinkio\Shlink\CLI\Util\ExitCodes;
use Shlinkio\Shlink\Core\Exception\InvalidUrlException;
use Shlinkio\Shlink\Core\Exception\NonUniqueSlugException;
@@ -12,6 +11,7 @@ use Shlinkio\Shlink\Core\Model\ShortUrlMeta;
use Shlinkio\Shlink\Core\Service\UrlShortenerInterface;
use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortUrlStringifierInterface;
use Shlinkio\Shlink\Core\Validation\ShortUrlInputFilter;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
@@ -22,11 +22,9 @@ use function array_map;
use function Functional\curry;
use function Functional\flatten;
use function Functional\unique;
use function method_exists;
use function sprintf;
use function str_contains;
class CreateShortUrlCommand extends BaseCommand
class CreateShortUrlCommand extends Command
{
public const NAME = 'short-url:create';
@@ -45,7 +43,6 @@ class CreateShortUrlCommand extends BaseCommand
{
$this
->setName(self::NAME)
->setAliases(['short-url:generate']) // Deprecated
->setDescription('Generates a short URL for provided long URL and returns it')
->addArgument('longUrl', InputArgument::REQUIRED, 'The long URL to parse')
->addOption(
@@ -54,33 +51,33 @@ class CreateShortUrlCommand extends BaseCommand
InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED,
'Tags to apply to the new short URL',
)
->addOptionWithDeprecatedFallback(
->addOption(
'valid-since',
's',
InputOption::VALUE_REQUIRED,
'The date from which this short URL will be valid. '
. 'If someone tries to access it before this date, it will not be found.',
)
->addOptionWithDeprecatedFallback(
->addOption(
'valid-until',
'u',
InputOption::VALUE_REQUIRED,
'The date until which this short URL will be valid. '
. 'If someone tries to access it after this date, it will not be found.',
)
->addOptionWithDeprecatedFallback(
->addOption(
'custom-slug',
'c',
InputOption::VALUE_REQUIRED,
'If provided, this slug will be used instead of generating a short code',
)
->addOptionWithDeprecatedFallback(
->addOption(
'max-visits',
'm',
InputOption::VALUE_REQUIRED,
'This will limit the number of visits for this short URL.',
)
->addOptionWithDeprecatedFallback(
->addOption(
'find-if-exists',
'f',
InputOption::VALUE_NONE,
@@ -92,7 +89,7 @@ class CreateShortUrlCommand extends BaseCommand
InputOption::VALUE_REQUIRED,
'The domain to which this short URL will be attached.',
)
->addOptionWithDeprecatedFallback(
->addOption(
'short-code-length',
'l',
InputOption::VALUE_REQUIRED,
@@ -104,12 +101,6 @@ class CreateShortUrlCommand extends BaseCommand
InputOption::VALUE_NONE,
'Forces the long URL to be validated, regardless what is globally configured.',
)
->addOption(
'no-validate-url',
null,
InputOption::VALUE_NONE,
'[DEPRECATED] Forces the long URL to not be validated, regardless what is globally configured.',
)
->addOption(
'crawlable',
'r',
@@ -161,25 +152,19 @@ class CreateShortUrlCommand extends BaseCommand
$explodeWithComma = curry('explode')(',');
$tags = unique(flatten(array_map($explodeWithComma, $input->getOption('tags'))));
$customSlug = $this->getOptionWithDeprecatedFallback($input, 'custom-slug');
$maxVisits = $this->getOptionWithDeprecatedFallback($input, 'max-visits');
$shortCodeLength = $this->getOptionWithDeprecatedFallback(
$input,
'short-code-length',
) ?? $this->defaultShortCodeLength;
$doValidateUrl = $this->doValidateUrl($input);
$customSlug = $input->getOption('custom-slug');
$maxVisits = $input->getOption('max-visits');
$shortCodeLength = $input->getOption('short-code-length') ?? $this->defaultShortCodeLength;
$doValidateUrl = $input->getOption('validate-url');
try {
$shortUrl = $this->urlShortener->shorten(ShortUrlMeta::fromRawData([
ShortUrlInputFilter::LONG_URL => $longUrl,
ShortUrlInputFilter::VALID_SINCE => $this->getOptionWithDeprecatedFallback($input, 'valid-since'),
ShortUrlInputFilter::VALID_UNTIL => $this->getOptionWithDeprecatedFallback($input, 'valid-until'),
ShortUrlInputFilter::VALID_SINCE => $input->getOption('valid-since'),
ShortUrlInputFilter::VALID_UNTIL => $input->getOption('valid-until'),
ShortUrlInputFilter::CUSTOM_SLUG => $customSlug,
ShortUrlInputFilter::MAX_VISITS => $maxVisits !== null ? (int) $maxVisits : null,
ShortUrlInputFilter::FIND_IF_EXISTS => $this->getOptionWithDeprecatedFallback(
$input,
'find-if-exists',
),
ShortUrlInputFilter::FIND_IF_EXISTS => $input->getOption('find-if-exists'),
ShortUrlInputFilter::DOMAIN => $input->getOption('domain'),
ShortUrlInputFilter::SHORT_CODE_LENGTH => $shortCodeLength,
ShortUrlInputFilter::VALIDATE_URL => $doValidateUrl,
@@ -199,20 +184,6 @@ class CreateShortUrlCommand extends BaseCommand
}
}
private function doValidateUrl(InputInterface $input): ?bool
{
$rawInput = method_exists($input, '__toString') ? $input->__toString() : '';
if (str_contains($rawInput, '--no-validate-url')) {
return false;
}
if (str_contains($rawInput, '--validate-url')) {
return true;
}
return null;
}
private function getIO(InputInterface $input, OutputInterface $output): SymfonyStyle
{
return $this->io ?? ($this->io = new SymfonyStyle($input, $output));

View File

@@ -52,7 +52,7 @@ class ListShortUrlsCommand extends AbstractWithDateRangeCommand
'The first page to list (10 items per page unless "--all" is provided).',
'1',
)
->addOptionWithDeprecatedFallback(
->addOption(
'search-term',
'st',
InputOption::VALUE_REQUIRED,
@@ -64,14 +64,14 @@ class ListShortUrlsCommand extends AbstractWithDateRangeCommand
InputOption::VALUE_REQUIRED,
'A comma-separated list of tags to filter results.',
)
->addOptionWithDeprecatedFallback(
->addOption(
'order-by',
'o',
InputOption::VALUE_REQUIRED,
'The field from which you want to order by. '
. 'Define ordering dir by passing ASC or DESC after "," or "-".',
. 'Define ordering dir by passing ASC or DESC after "-" or ",".',
)
->addOptionWithDeprecatedFallback(
->addOption(
'show-tags',
null,
InputOption::VALUE_NONE,
@@ -113,7 +113,7 @@ class ListShortUrlsCommand extends AbstractWithDateRangeCommand
$io = new SymfonyStyle($input, $output);
$page = (int) $input->getOption('page');
$searchTerm = $this->getOptionWithDeprecatedFallback($input, 'search-term');
$searchTerm = $input->getOption('search-term');
$tags = $input->getOption('tags');
$tags = ! empty($tags) ? explode(',', $tags) : [];
$all = $input->getOption('all');
@@ -175,7 +175,7 @@ class ListShortUrlsCommand extends AbstractWithDateRangeCommand
private function processOrderBy(InputInterface $input): ?string
{
$orderBy = $this->getOptionWithDeprecatedFallback($input, 'order-by');
$orderBy = $input->getOption('order-by');
if (empty($orderBy)) {
return null;
}
@@ -195,7 +195,7 @@ class ListShortUrlsCommand extends AbstractWithDateRangeCommand
'Date created' => $pickProp('dateCreated'),
'Visits count' => $pickProp('visitsCount'),
];
if ($this->getOptionWithDeprecatedFallback($input, 'show-tags')) {
if ($input->getOption('show-tags')) {
$columnsMap['Tags'] = static fn (array $shortUrl): string => implode(', ', $shortUrl['tags']);
}
if ($input->getOption('show-api-key')) {

View File

@@ -1,52 +0,0 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Tag;
use Shlinkio\Shlink\CLI\Util\ExitCodes;
use Shlinkio\Shlink\Core\Tag\TagServiceInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
/** @deprecated */
class CreateTagCommand extends Command
{
public const NAME = 'tag:create';
public function __construct(private TagServiceInterface $tagService)
{
parent::__construct();
}
protected function configure(): void
{
$this
->setName(self::NAME)
->setDescription('[Deprecated] Creates one or more tags.')
->addOption(
'name',
't',
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
'The name of the tags to create',
);
}
protected function execute(InputInterface $input, OutputInterface $output): ?int
{
$io = new SymfonyStyle($input, $output);
$tagNames = $input->getOption('name');
if (empty($tagNames)) {
$io->warning('You have to provide at least one tag name');
return ExitCodes::EXIT_WARNING;
}
$this->tagService->createTags($tagNames);
$io->success('Tags properly created');
return ExitCodes::EXIT_SUCCESS;
}
}

View File

@@ -5,7 +5,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Util;
use Cake\Chronos\Chronos;
use Shlinkio\Shlink\CLI\Command\BaseCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
@@ -14,7 +14,7 @@ use Throwable;
use function is_string;
use function sprintf;
abstract class AbstractWithDateRangeCommand extends BaseCommand
abstract class AbstractWithDateRangeCommand extends Command
{
private const START_DATE = 'start-date';
private const END_DATE = 'end-date';
@@ -23,18 +23,8 @@ abstract class AbstractWithDateRangeCommand extends BaseCommand
{
$this->doConfigure();
$this
->addOptionWithDeprecatedFallback(
self::START_DATE,
's',
InputOption::VALUE_REQUIRED,
$this->getStartDateDesc(self::START_DATE),
)
->addOptionWithDeprecatedFallback(
self::END_DATE,
'e',
InputOption::VALUE_REQUIRED,
$this->getEndDateDesc(self::END_DATE),
);
->addOption(self::START_DATE, 's', InputOption::VALUE_REQUIRED, $this->getStartDateDesc(self::START_DATE))
->addOption(self::END_DATE, 'e', InputOption::VALUE_REQUIRED, $this->getEndDateDesc(self::END_DATE));
}
protected function getStartDateOption(InputInterface $input, OutputInterface $output): ?Chronos
@@ -49,7 +39,7 @@ abstract class AbstractWithDateRangeCommand extends BaseCommand
private function getDateOption(InputInterface $input, OutputInterface $output, string $key): ?Chronos
{
$value = $this->getOptionWithDeprecatedFallback($input, $key);
$value = $input->getOption($key);
if (empty($value) || ! is_string($value)) {
return null;
}

View File

@@ -149,7 +149,7 @@ class CreateShortUrlCommandTest extends TestCase
* @test
* @dataProvider provideFlags
*/
public function urlValidationHasExpectedValueBasedOnProvidedTags(array $options, ?bool $expectedValidateUrl): void
public function urlValidationHasExpectedValueBasedOnProvidedFlags(array $options, ?bool $expectedValidateUrl): void
{
$shortUrl = ShortUrl::createEmpty();
$urlToShortCode = $this->urlShortener->shorten(
@@ -168,8 +168,6 @@ class CreateShortUrlCommandTest extends TestCase
public function provideFlags(): iterable
{
yield 'no flags' => [[], null];
yield 'no-validate-url only' => [['--no-validate-url' => true], false];
yield 'validate-url' => [['--validate-url' => true], true];
yield 'both flags' => [['--validate-url' => true, '--no-validate-url' => true], false];
}
}

View File

@@ -241,7 +241,7 @@ class ListShortUrlsCommandTest extends TestCase
* @test
* @dataProvider provideOrderBy
*/
public function orderByIsProperlyComputed(array $commandArgs, string|array|null $expectedOrderBy): void
public function orderByIsProperlyComputed(array $commandArgs, ?string $expectedOrderBy): void
{
$listShortUrls = $this->shortUrlService->listShortUrls(ShortUrlsParams::fromRawData([
'orderBy' => $expectedOrderBy,
@@ -257,8 +257,9 @@ class ListShortUrlsCommandTest extends TestCase
{
yield [[], null];
yield [['--order-by' => 'foo'], 'foo'];
yield [['--order-by' => 'foo,ASC'], ['foo' => 'ASC']];
yield [['--order-by' => 'bar,DESC'], ['bar' => 'DESC']];
yield [['--order-by' => 'foo,ASC'], 'foo-ASC'];
yield [['--order-by' => 'bar,DESC'], 'bar-DESC'];
yield [['--order-by' => 'baz-DESC'], 'baz-DESC'];
}
/** @test */

View File

@@ -1,51 +0,0 @@
<?php
declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\Tag;
use Doctrine\Common\Collections\ArrayCollection;
use PHPUnit\Framework\TestCase;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\CLI\Command\Tag\CreateTagCommand;
use Shlinkio\Shlink\Core\Tag\TagServiceInterface;
use ShlinkioTest\Shlink\CLI\CliTestUtilsTrait;
use Symfony\Component\Console\Tester\CommandTester;
class CreateTagCommandTest extends TestCase
{
use CliTestUtilsTrait;
private CommandTester $commandTester;
private ObjectProphecy $tagService;
public function setUp(): void
{
$this->tagService = $this->prophesize(TagServiceInterface::class);
$this->commandTester = $this->testerForCommand(new CreateTagCommand($this->tagService->reveal()));
}
/** @test */
public function errorIsReturnedWhenNoTagsAreProvided(): void
{
$this->commandTester->execute([]);
$output = $this->commandTester->getDisplay();
self::assertStringContainsString('You have to provide at least one tag name', $output);
}
/** @test */
public function serviceIsInvokedOnSuccess(): void
{
$tagNames = ['foo', 'bar'];
$createTags = $this->tagService->createTags($tagNames)->willReturn(new ArrayCollection());
$this->commandTester->execute([
'--name' => $tagNames,
]);
$output = $this->commandTester->getDisplay();
self::assertStringContainsString('Tags properly created', $output);
$createTags->shouldHaveBeenCalled();
}
}