diff --git a/CHANGELOG.md b/CHANGELOG.md index 86dacaa0..baf1f824 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this * [#986](https://github.com/shlinkio/shlink/issues/986) Updated official docker image to use PHP 8. ### Deprecated -* *Nothing* +* [#959](https://github.com/shlinkio/shlink/issues/959) Deprecated all command flags using camelCase format (like `--expirationDate`), adding kebab-case replacements for all of them (like `--expiration-date`). + + All the existing camelCase flags will continue working for now, but will be removed in Shlink 3.0.0 ### Removed * *Nothing* diff --git a/module/CLI/src/Command/Api/GenerateKeyCommand.php b/module/CLI/src/Command/Api/GenerateKeyCommand.php index 2dc91c51..119fa020 100644 --- a/module/CLI/src/Command/Api/GenerateKeyCommand.php +++ b/module/CLI/src/Command/Api/GenerateKeyCommand.php @@ -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 Command +class GenerateKeyCommand extends BaseCommand { public const NAME = 'api-key:generate'; @@ -42,9 +42,9 @@ class GenerateKeyCommand extends Command %command.full_name% - You can optionally set its expiration date with --expirationDate or -e: + You can optionally set its expiration date with --expiration-date or -e: - %command.full_name% --expirationDate 2020-01-01 + %command.full_name% --expiration-date 2020-01-01 You can also set roles to the API key: @@ -56,8 +56,8 @@ class GenerateKeyCommand extends Command $this ->setName(self::NAME) ->setDescription('Generates a new valid API key.') - ->addOption( - 'expirationDate', + ->addOptionWithDeprecatedFallback( + 'expiration-date', 'e', InputOption::VALUE_REQUIRED, 'The date in which the API key should expire. Use any valid PHP format.', @@ -79,7 +79,7 @@ class GenerateKeyCommand extends Command protected function execute(InputInterface $input, OutputInterface $output): ?int { - $expirationDate = $input->getOption('expirationDate'); + $expirationDate = $this->getOptionWithDeprecatedFallback($input, 'expiration-date'); $apiKey = $this->apiKeyService->create( isset($expirationDate) ? Chronos::parse($expirationDate) : null, ...$this->roleResolver->determineRoles($input), diff --git a/module/CLI/src/Command/Api/ListKeysCommand.php b/module/CLI/src/Command/Api/ListKeysCommand.php index cf09e614..9243779b 100644 --- a/module/CLI/src/Command/Api/ListKeysCommand.php +++ b/module/CLI/src/Command/Api/ListKeysCommand.php @@ -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 Command +class ListKeysCommand extends BaseCommand { private const ERROR_STRING_PATTERN = '%s'; private const SUCCESS_STRING_PATTERN = '%s'; @@ -40,8 +40,8 @@ class ListKeysCommand extends Command $this ->setName(self::NAME) ->setDescription('Lists all the available API keys.') - ->addOption( - 'enabledOnly', + ->addOptionWithDeprecatedFallback( + 'enabled-only', 'e', InputOption::VALUE_NONE, 'Tells if only enabled API keys should be returned.', @@ -50,7 +50,7 @@ class ListKeysCommand extends Command protected function execute(InputInterface $input, OutputInterface $output): ?int { - $enabledOnly = $input->getOption('enabledOnly'); + $enabledOnly = $this->getOptionWithDeprecatedFallback($input, 'enabled-only'); $rows = map($this->apiKeyService->listKeys($enabledOnly), function (ApiKey $apiKey) use ($enabledOnly) { $expiration = $apiKey->getExpirationDate(); diff --git a/module/CLI/src/Command/BaseCommand.php b/module/CLI/src/Command/BaseCommand.php new file mode 100644 index 00000000..443b37ec --- /dev/null +++ b/module/CLI/src/Command/BaseCommand.php @@ -0,0 +1,51 @@ +addOption($name, $shortcut, $mode, $description, $default); + + if (str_contains($name, '-')) { + $camelCaseName = kebabCaseToCamelCase($name); + $this->addOption($camelCaseName, null, $mode, sprintf('[DEPRECATED] Same as "%s".', $name), $default); + } + + return $this; + } + + /** + * @return bool|string|string[]|null + */ + protected function getOptionWithDeprecatedFallback(InputInterface $input, string $name) + { + $rawInput = method_exists($input, '__toString') ? $input->__toString() : ''; + $camelCaseName = kebabCaseToCamelCase($name); + + if (str_contains($rawInput, $camelCaseName)) { + return $input->getOption($camelCaseName); + } + + return $input->getOption($name); + } +} diff --git a/module/CLI/src/Command/ShortUrl/GenerateShortUrlCommand.php b/module/CLI/src/Command/ShortUrl/GenerateShortUrlCommand.php index 12bbb3fb..7ceb0435 100644 --- a/module/CLI/src/Command/ShortUrl/GenerateShortUrlCommand.php +++ b/module/CLI/src/Command/ShortUrl/GenerateShortUrlCommand.php @@ -4,13 +4,13 @@ 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; use Shlinkio\Shlink\Core\Model\ShortUrlMeta; use Shlinkio\Shlink\Core\Service\UrlShortenerInterface; use Shlinkio\Shlink\Core\Validation\ShortUrlMetaInputFilter; -use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -23,9 +23,9 @@ use function Functional\flatten; use function Functional\unique; use function method_exists; use function sprintf; -use function strpos; +use function str_contains; -class GenerateShortUrlCommand extends Command +class GenerateShortUrlCommand extends BaseCommand { public const NAME = 'short-url:generate'; @@ -53,34 +53,34 @@ class GenerateShortUrlCommand extends Command InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Tags to apply to the new short URL', ) - ->addOption( - 'validSince', + ->addOptionWithDeprecatedFallback( + '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.', ) - ->addOption( - 'validUntil', + ->addOptionWithDeprecatedFallback( + '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.', ) - ->addOption( - 'customSlug', + ->addOptionWithDeprecatedFallback( + 'custom-slug', 'c', InputOption::VALUE_REQUIRED, 'If provided, this slug will be used instead of generating a short code', ) - ->addOption( - 'maxVisits', + ->addOptionWithDeprecatedFallback( + 'max-visits', 'm', InputOption::VALUE_REQUIRED, 'This will limit the number of visits for this short URL.', ) - ->addOption( - 'findIfExists', + ->addOptionWithDeprecatedFallback( + 'find-if-exists', 'f', InputOption::VALUE_NONE, 'This will force existing matching URL to be returned if found, instead of creating a new one.', @@ -91,11 +91,11 @@ class GenerateShortUrlCommand extends Command InputOption::VALUE_REQUIRED, 'The domain to which this short URL will be attached.', ) - ->addOption( - 'shortCodeLength', + ->addOptionWithDeprecatedFallback( + 'short-code-length', 'l', InputOption::VALUE_REQUIRED, - 'The length for generated short code (it will be ignored if --customSlug was provided).', + 'The length for generated short code (it will be ignored if --custom-slug was provided).', ) ->addOption( 'validate-url', @@ -136,18 +136,24 @@ class GenerateShortUrlCommand extends Command $explodeWithComma = curry('explode')(','); $tags = unique(flatten(array_map($explodeWithComma, $input->getOption('tags')))); - $customSlug = $input->getOption('customSlug'); - $maxVisits = $input->getOption('maxVisits'); - $shortCodeLength = $input->getOption('shortCodeLength') ?? $this->defaultShortCodeLength; + $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); try { $shortUrl = $this->urlShortener->shorten($longUrl, $tags, ShortUrlMeta::fromRawData([ - ShortUrlMetaInputFilter::VALID_SINCE => $input->getOption('validSince'), - ShortUrlMetaInputFilter::VALID_UNTIL => $input->getOption('validUntil'), + ShortUrlMetaInputFilter::VALID_SINCE => $this->getOptionWithDeprecatedFallback($input, 'valid-since'), + ShortUrlMetaInputFilter::VALID_UNTIL => $this->getOptionWithDeprecatedFallback($input, 'valid-until'), ShortUrlMetaInputFilter::CUSTOM_SLUG => $customSlug, ShortUrlMetaInputFilter::MAX_VISITS => $maxVisits !== null ? (int) $maxVisits : null, - ShortUrlMetaInputFilter::FIND_IF_EXISTS => $input->getOption('findIfExists'), + ShortUrlMetaInputFilter::FIND_IF_EXISTS => $this->getOptionWithDeprecatedFallback( + $input, + 'find-if-exists', + ), ShortUrlMetaInputFilter::DOMAIN => $input->getOption('domain'), ShortUrlMetaInputFilter::SHORT_CODE_LENGTH => $shortCodeLength, ShortUrlMetaInputFilter::VALIDATE_URL => $doValidateUrl, @@ -168,10 +174,10 @@ class GenerateShortUrlCommand extends Command { $rawInput = method_exists($input, '__toString') ? $input->__toString() : ''; - if (strpos($rawInput, '--no-validate-url') !== false) { + if (str_contains($rawInput, '--no-validate-url')) { return false; } - if (strpos($rawInput, '--validate-url') !== false) { + if (str_contains($rawInput, '--validate-url')) { return true; } diff --git a/module/CLI/src/Command/ShortUrl/GetVisitsCommand.php b/module/CLI/src/Command/ShortUrl/GetVisitsCommand.php index b58ea3ac..0b7de663 100644 --- a/module/CLI/src/Command/ShortUrl/GetVisitsCommand.php +++ b/module/CLI/src/Command/ShortUrl/GetVisitsCommand.php @@ -21,6 +21,7 @@ use Symfony\Component\Console\Style\SymfonyStyle; use function Functional\map; use function Functional\select_keys; +use function sprintf; class GetVisitsCommand extends AbstractWithDateRangeCommand { @@ -39,18 +40,18 @@ class GetVisitsCommand extends AbstractWithDateRangeCommand $this ->setName(self::NAME) ->setDescription('Returns the detailed visits information for provided short code') - ->addArgument('shortCode', InputArgument::REQUIRED, 'The short code which visits we want to get') - ->addOption('domain', 'd', InputOption::VALUE_REQUIRED, 'The domain for the short code'); + ->addArgument('shortCode', InputArgument::REQUIRED, 'The short code which visits we want to get.') + ->addOption('domain', 'd', InputOption::VALUE_REQUIRED, 'The domain for the short code.'); } - protected function getStartDateDesc(): string + protected function getStartDateDesc(string $optionName): string { - return 'Allows to filter visits, returning only those older than start date'; + return sprintf('Allows to filter visits, returning only those older than "%s".', $optionName); } - protected function getEndDateDesc(): string + protected function getEndDateDesc(string $optionName): string { - return 'Allows to filter visits, returning only those newer than end date'; + return sprintf('Allows to filter visits, returning only those newer than "%s".', $optionName); } protected function interact(InputInterface $input, OutputInterface $output): void @@ -70,8 +71,8 @@ class GetVisitsCommand extends AbstractWithDateRangeCommand protected function execute(InputInterface $input, OutputInterface $output): ?int { $identifier = ShortUrlIdentifier::fromCli($input); - $startDate = $this->getDateOption($input, $output, 'startDate'); - $endDate = $this->getDateOption($input, $output, 'endDate'); + $startDate = $this->getStartDateOption($input, $output); + $endDate = $this->getEndDateOption($input, $output); $paginator = $this->visitsTracker->info($identifier, new VisitsParams(new DateRange($startDate, $endDate))); diff --git a/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php b/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php index 3f539e27..cf20e328 100644 --- a/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php +++ b/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php @@ -60,28 +60,33 @@ class ListShortUrlsCommand extends AbstractWithDateRangeCommand 'page', 'p', InputOption::VALUE_REQUIRED, - 'The first page to list (10 items per page unless "--all" is provided)', + 'The first page to list (10 items per page unless "--all" is provided).', '1', ) - ->addOption( - 'searchTerm', + ->addOptionWithDeprecatedFallback( + 'search-term', 'st', InputOption::VALUE_REQUIRED, - 'A query used to filter results by searching for it on the longUrl and shortCode fields', + 'A query used to filter results by searching for it on the longUrl and shortCode fields.', ) ->addOption( 'tags', 't', InputOption::VALUE_REQUIRED, - 'A comma-separated list of tags to filter results', + 'A comma-separated list of tags to filter results.', ) - ->addOption( - 'orderBy', + ->addOptionWithDeprecatedFallback( + 'order-by', 'o', InputOption::VALUE_REQUIRED, - 'The field from which we want to order by. Pass ASC or DESC separated by a comma', + 'The field from which we want to order by. Pass ASC or DESC separated by a comma.', + ) + ->addOptionWithDeprecatedFallback( + 'show-tags', + null, + InputOption::VALUE_NONE, + 'Whether to display the tags or not.', ) - ->addOption('showTags', null, InputOption::VALUE_NONE, 'Whether to display the tags or not') ->addOption( 'all', 'a', @@ -91,14 +96,14 @@ class ListShortUrlsCommand extends AbstractWithDateRangeCommand ); } - protected function getStartDateDesc(): string + protected function getStartDateDesc(string $optionName): string { - return 'Allows to filter short URLs, returning only those created after "startDate"'; + return sprintf('Allows to filter short URLs, returning only those created after "%s".', $optionName); } - protected function getEndDateDesc(): string + protected function getEndDateDesc(string $optionName): string { - return 'Allows to filter short URLs, returning only those created before "endDate"'; + return sprintf('Allows to filter short URLs, returning only those created before "%s".', $optionName); } protected function execute(InputInterface $input, OutputInterface $output): ?int @@ -106,13 +111,13 @@ class ListShortUrlsCommand extends AbstractWithDateRangeCommand $io = new SymfonyStyle($input, $output); $page = (int) $input->getOption('page'); - $searchTerm = $input->getOption('searchTerm'); + $searchTerm = $this->getOptionWithDeprecatedFallback($input, 'search-term'); $tags = $input->getOption('tags'); $tags = ! empty($tags) ? explode(',', $tags) : []; - $showTags = (bool) $input->getOption('showTags'); - $all = (bool) $input->getOption('all'); - $startDate = $this->getDateOption($input, $output, 'startDate'); - $endDate = $this->getDateOption($input, $output, 'endDate'); + $showTags = $this->getOptionWithDeprecatedFallback($input, 'show-tags'); + $all = $input->getOption('all'); + $startDate = $this->getStartDateOption($input, $output); + $endDate = $this->getEndDateOption($input, $output); $orderBy = $this->processOrderBy($input); $data = [ @@ -178,7 +183,7 @@ class ListShortUrlsCommand extends AbstractWithDateRangeCommand */ private function processOrderBy(InputInterface $input) { - $orderBy = $input->getOption('orderBy'); + $orderBy = $this->getOptionWithDeprecatedFallback($input, 'order-by'); if (empty($orderBy)) { return null; } diff --git a/module/CLI/src/Command/Util/AbstractWithDateRangeCommand.php b/module/CLI/src/Command/Util/AbstractWithDateRangeCommand.php index bd64701a..39e60c9a 100644 --- a/module/CLI/src/Command/Util/AbstractWithDateRangeCommand.php +++ b/module/CLI/src/Command/Util/AbstractWithDateRangeCommand.php @@ -5,7 +5,7 @@ declare(strict_types=1); namespace Shlinkio\Shlink\CLI\Command\Util; use Cake\Chronos\Chronos; -use Symfony\Component\Console\Command\Command; +use Shlinkio\Shlink\CLI\Command\BaseCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; @@ -13,19 +13,42 @@ use Throwable; use function sprintf; -abstract class AbstractWithDateRangeCommand extends Command +abstract class AbstractWithDateRangeCommand extends BaseCommand { + private const START_DATE = 'start-date'; + private const END_DATE = 'end-date'; + final protected function configure(): void { $this->doConfigure(); $this - ->addOption('startDate', 's', InputOption::VALUE_REQUIRED, $this->getStartDateDesc()) - ->addOption('endDate', 'e', InputOption::VALUE_REQUIRED, $this->getEndDateDesc()); + ->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), + ); } - protected function getDateOption(InputInterface $input, OutputInterface $output, string $key): ?Chronos + protected function getStartDateOption(InputInterface $input, OutputInterface $output): ?Chronos { - $value = $input->getOption($key); + return $this->getDateOption($input, $output, self::START_DATE); + } + + protected function getEndDateOption(InputInterface $input, OutputInterface $output): ?Chronos + { + return $this->getDateOption($input, $output, self::END_DATE); + } + + private function getDateOption(InputInterface $input, OutputInterface $output, string $key): ?Chronos + { + $value = $this->getOptionWithDeprecatedFallback($input, $key); if (empty($value)) { return null; } @@ -49,6 +72,7 @@ abstract class AbstractWithDateRangeCommand extends Command abstract protected function doConfigure(): void; - abstract protected function getStartDateDesc(): string; - abstract protected function getEndDateDesc(): string; + abstract protected function getStartDateDesc(string $optionName): string; + + abstract protected function getEndDateDesc(string $optionName): string; } diff --git a/module/CLI/test/Command/Api/GenerateKeyCommandTest.php b/module/CLI/test/Command/Api/GenerateKeyCommandTest.php index 744fb482..00548f17 100644 --- a/module/CLI/test/Command/Api/GenerateKeyCommandTest.php +++ b/module/CLI/test/Command/Api/GenerateKeyCommandTest.php @@ -55,7 +55,7 @@ class GenerateKeyCommandTest extends TestCase $this->apiKeyService->create(Argument::type(Chronos::class))->shouldBeCalledOnce() ->willReturn(new ApiKey()); $this->commandTester->execute([ - '--expirationDate' => '2016-01-01', + '--expiration-date' => '2016-01-01', ]); } } diff --git a/module/CLI/test/Command/Api/ListKeysCommandTest.php b/module/CLI/test/Command/Api/ListKeysCommandTest.php index 116f979d..e0cada5d 100644 --- a/module/CLI/test/Command/Api/ListKeysCommandTest.php +++ b/module/CLI/test/Command/Api/ListKeysCommandTest.php @@ -39,7 +39,7 @@ class ListKeysCommandTest extends TestCase { $listKeys = $this->apiKeyService->listKeys($enabledOnly)->willReturn($keys); - $this->commandTester->execute(['--enabledOnly' => $enabledOnly]); + $this->commandTester->execute(['--enabled-only' => $enabledOnly]); $output = $this->commandTester->getDisplay(); self::assertEquals($expected, $output); diff --git a/module/CLI/test/Command/ShortUrl/GenerateShortUrlCommandTest.php b/module/CLI/test/Command/ShortUrl/GenerateShortUrlCommandTest.php index 82f38713..3283dced 100644 --- a/module/CLI/test/Command/ShortUrl/GenerateShortUrlCommandTest.php +++ b/module/CLI/test/Command/ShortUrl/GenerateShortUrlCommandTest.php @@ -48,7 +48,7 @@ class GenerateShortUrlCommandTest extends TestCase $this->commandTester->execute([ 'longUrl' => 'http://domain.com/foo/bar', - '--maxVisits' => '3', + '--max-visits' => '3', ]); $output = $this->commandTester->getDisplay(); @@ -78,7 +78,7 @@ class GenerateShortUrlCommandTest extends TestCase NonUniqueSlugException::fromSlug('my-slug'), ); - $this->commandTester->execute(['longUrl' => 'http://domain.com/invalid', '--customSlug' => 'my-slug']); + $this->commandTester->execute(['longUrl' => 'http://domain.com/invalid', '--custom-slug' => 'my-slug']); $output = $this->commandTester->getDisplay(); self::assertEquals(ExitCodes::EXIT_FAILURE, $this->commandTester->getStatusCode()); diff --git a/module/CLI/test/Command/ShortUrl/GetVisitsCommandTest.php b/module/CLI/test/Command/ShortUrl/GetVisitsCommandTest.php index 50c1751f..51394414 100644 --- a/module/CLI/test/Command/ShortUrl/GetVisitsCommandTest.php +++ b/module/CLI/test/Command/ShortUrl/GetVisitsCommandTest.php @@ -71,8 +71,8 @@ class GetVisitsCommandTest extends TestCase $this->commandTester->execute([ 'shortCode' => $shortCode, - '--startDate' => $startDate, - '--endDate' => $endDate, + '--start-date' => $startDate, + '--end-date' => $endDate, ]); } @@ -86,13 +86,13 @@ class GetVisitsCommandTest extends TestCase $this->commandTester->execute([ 'shortCode' => $shortCode, - '--startDate' => $startDate, + '--start-date' => $startDate, ]); $output = $this->commandTester->getDisplay(); $info->shouldHaveBeenCalledOnce(); self::assertStringContainsString( - sprintf('Ignored provided "startDate" since its value "%s" is not a valid date', $startDate), + sprintf('Ignored provided "start-date" since its value "%s" is not a valid date', $startDate), $output, ); } diff --git a/module/CLI/test/Command/ShortUrl/ListShortUrlsCommandTest.php b/module/CLI/test/Command/ShortUrl/ListShortUrlsCommandTest.php index aca72e06..43047bbf 100644 --- a/module/CLI/test/Command/ShortUrl/ListShortUrlsCommandTest.php +++ b/module/CLI/test/Command/ShortUrl/ListShortUrlsCommandTest.php @@ -104,7 +104,7 @@ class ListShortUrlsCommandTest extends TestCase ->shouldBeCalledOnce(); $this->commandTester->setInputs(['y']); - $this->commandTester->execute(['--showTags' => true]); + $this->commandTester->execute(['--show-tags' => true]); $output = $this->commandTester->getDisplay(); self::assertStringContainsString('Tags', $output); } @@ -139,22 +139,22 @@ class ListShortUrlsCommandTest extends TestCase { yield [[], 1, null, []]; yield [['--page' => $page = 3], $page, null, []]; - yield [['--searchTerm' => $searchTerm = 'search this'], 1, $searchTerm, []]; + yield [['--search-term' => $searchTerm = 'search this'], 1, $searchTerm, []]; yield [ - ['--page' => $page = 3, '--searchTerm' => $searchTerm = 'search this', '--tags' => $tags = 'foo,bar'], + ['--page' => $page = 3, '--search-term' => $searchTerm = 'search this', '--tags' => $tags = 'foo,bar'], $page, $searchTerm, explode(',', $tags), ]; yield [ - ['--startDate' => $startDate = '2019-01-01'], + ['--start-date' => $startDate = '2019-01-01'], 1, null, [], $startDate, ]; yield [ - ['--endDate' => $endDate = '2020-05-23'], + ['--end-date' => $endDate = '2020-05-23'], 1, null, [], @@ -162,7 +162,7 @@ class ListShortUrlsCommandTest extends TestCase $endDate, ]; yield [ - ['--startDate' => $startDate = '2019-01-01', '--endDate' => $endDate = '2020-05-23'], + ['--start-date' => $startDate = '2019-01-01', '--end-date' => $endDate = '2020-05-23'], 1, null, [], @@ -191,9 +191,9 @@ class ListShortUrlsCommandTest extends TestCase public function provideOrderBy(): iterable { yield [[], null]; - yield [['--orderBy' => 'foo'], 'foo']; - yield [['--orderBy' => 'foo,ASC'], ['foo' => 'ASC']]; - yield [['--orderBy' => 'bar,DESC'], ['bar' => 'DESC']]; + yield [['--order-by' => 'foo'], 'foo']; + yield [['--order-by' => 'foo,ASC'], ['foo' => 'ASC']]; + yield [['--order-by' => 'bar,DESC'], ['bar' => 'DESC']]; } /** @test */ diff --git a/module/Core/functions/functions.php b/module/Core/functions/functions.php index 076de6a0..531f8038 100644 --- a/module/Core/functions/functions.php +++ b/module/Core/functions/functions.php @@ -12,9 +12,12 @@ use PUGX\Shortid\Factory as ShortIdFactory; use function Functional\reduce_left; use function is_array; +use function lcfirst; use function print_r; use function sprintf; use function str_repeat; +use function str_replace; +use function ucwords; const DEFAULT_DELETE_SHORT_URL_THRESHOLD = 15; const DEFAULT_SHORT_CODES_LENGTH = 5; @@ -97,3 +100,8 @@ function arrayToString(array $array, int $indentSize = 4): string ); }, ''); } + +function kebabCaseToCamelCase(string $name): string +{ + return lcfirst(str_replace(' ', '', ucwords(str_replace('-', ' ', $name)))); +}