From 1557438fdfada83eb2c9e1f370add6e645b8a89f Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Thu, 6 Oct 2022 21:29:27 +0200 Subject: [PATCH] Moved logic to reuse command options to option classes instead of base abstract command classes --- .../Command/Domain/GetDomainVisitsCommand.php | 2 +- .../ShortUrl/GetShortUrlVisitsCommand.php | 2 +- .../Command/ShortUrl/ListShortUrlsCommand.php | 31 ++++----- .../src/Command/Tag/GetTagVisitsCommand.php | 2 +- .../Util/AbstractWithDateRangeCommand.php | 69 ------------------- .../Visit/AbstractVisitsListCommand.php | 26 +++---- .../Visit/GetNonOrphanVisitsCommand.php | 2 +- .../Command/Visit/GetOrphanVisitsCommand.php | 2 +- module/CLI/src/Option/DateOption.php | 51 ++++++++++++++ module/CLI/src/Option/EndDateOption.php | 30 ++++++++ module/CLI/src/Option/StartDateOption.php | 30 ++++++++ 11 files changed, 141 insertions(+), 106 deletions(-) delete mode 100644 module/CLI/src/Command/Util/AbstractWithDateRangeCommand.php create mode 100644 module/CLI/src/Option/DateOption.php create mode 100644 module/CLI/src/Option/EndDateOption.php create mode 100644 module/CLI/src/Option/StartDateOption.php diff --git a/module/CLI/src/Command/Domain/GetDomainVisitsCommand.php b/module/CLI/src/Command/Domain/GetDomainVisitsCommand.php index 676a2141..8d2eb8c9 100644 --- a/module/CLI/src/Command/Domain/GetDomainVisitsCommand.php +++ b/module/CLI/src/Command/Domain/GetDomainVisitsCommand.php @@ -25,7 +25,7 @@ class GetDomainVisitsCommand extends AbstractVisitsListCommand parent::__construct($visitsHelper); } - protected function doConfigure(): void + protected function configure(): void { $this ->setName(self::NAME) diff --git a/module/CLI/src/Command/ShortUrl/GetShortUrlVisitsCommand.php b/module/CLI/src/Command/ShortUrl/GetShortUrlVisitsCommand.php index 7f81e4da..a6a4f31d 100644 --- a/module/CLI/src/Command/ShortUrl/GetShortUrlVisitsCommand.php +++ b/module/CLI/src/Command/ShortUrl/GetShortUrlVisitsCommand.php @@ -20,7 +20,7 @@ class GetShortUrlVisitsCommand extends AbstractVisitsListCommand { public const NAME = 'short-url:visits'; - protected function doConfigure(): void + protected function configure(): void { $this ->setName(self::NAME) diff --git a/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php b/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php index 0889bb03..11443abc 100644 --- a/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php +++ b/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php @@ -4,7 +4,8 @@ declare(strict_types=1); namespace Shlinkio\Shlink\CLI\Command\ShortUrl; -use Shlinkio\Shlink\CLI\Command\Util\AbstractWithDateRangeCommand; +use Shlinkio\Shlink\CLI\Option\EndDateOption; +use Shlinkio\Shlink\CLI\Option\StartDateOption; use Shlinkio\Shlink\CLI\Util\ExitCodes; use Shlinkio\Shlink\CLI\Util\ShlinkTable; use Shlinkio\Shlink\Common\Paginator\Paginator; @@ -15,6 +16,7 @@ use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlsParams; use Shlinkio\Shlink\Core\ShortUrl\Model\TagsMode; use Shlinkio\Shlink\Core\ShortUrl\Model\Validation\ShortUrlsParamsInputFilter; use Shlinkio\Shlink\Core\ShortUrl\ShortUrlServiceInterface; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; @@ -27,20 +29,25 @@ use function Functional\map; use function implode; use function sprintf; -class ListShortUrlsCommand extends AbstractWithDateRangeCommand +class ListShortUrlsCommand extends Command { use PagerfantaUtilsTrait; public const NAME = 'short-url:list'; + private readonly StartDateOption $startDateOption; + private readonly EndDateOption $endDateOption; + public function __construct( - private ShortUrlServiceInterface $shortUrlService, - private DataTransformerInterface $transformer, + private readonly ShortUrlServiceInterface $shortUrlService, + private readonly DataTransformerInterface $transformer, ) { parent::__construct(); + $this->startDateOption = new StartDateOption($this, 'short URLs'); + $this->endDateOption = new EndDateOption($this, 'short URLs'); } - protected function doConfigure(): void + protected function configure(): void { $this ->setName(self::NAME) @@ -104,16 +111,6 @@ class ListShortUrlsCommand extends AbstractWithDateRangeCommand ); } - protected function getStartDateDesc(string $optionName): string - { - return sprintf('Allows to filter short URLs, returning only those created after "%s".', $optionName); - } - - protected function getEndDateDesc(string $optionName): string - { - return sprintf('Allows to filter short URLs, returning only those created before "%s".', $optionName); - } - protected function execute(InputInterface $input, OutputInterface $output): ?int { $io = new SymfonyStyle($input, $output); @@ -124,8 +121,8 @@ class ListShortUrlsCommand extends AbstractWithDateRangeCommand $tagsMode = $input->getOption('including-all-tags') === true ? TagsMode::ALL->value : TagsMode::ANY->value; $tags = ! empty($tags) ? explode(',', $tags) : []; $all = $input->getOption('all'); - $startDate = $this->getStartDateOption($input, $output); - $endDate = $this->getEndDateOption($input, $output); + $startDate = $this->startDateOption->get($input, $output); + $endDate = $this->endDateOption->get($input, $output); $orderBy = $this->processOrderBy($input); $columnsMap = $this->resolveColumnsMap($input); diff --git a/module/CLI/src/Command/Tag/GetTagVisitsCommand.php b/module/CLI/src/Command/Tag/GetTagVisitsCommand.php index 842c9b45..290a172a 100644 --- a/module/CLI/src/Command/Tag/GetTagVisitsCommand.php +++ b/module/CLI/src/Command/Tag/GetTagVisitsCommand.php @@ -25,7 +25,7 @@ class GetTagVisitsCommand extends AbstractVisitsListCommand parent::__construct($visitsHelper); } - protected function doConfigure(): void + protected function configure(): void { $this ->setName(self::NAME) diff --git a/module/CLI/src/Command/Util/AbstractWithDateRangeCommand.php b/module/CLI/src/Command/Util/AbstractWithDateRangeCommand.php deleted file mode 100644 index c3e3c407..00000000 --- a/module/CLI/src/Command/Util/AbstractWithDateRangeCommand.php +++ /dev/null @@ -1,69 +0,0 @@ -doConfigure(); - $this - ->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 - { - 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 = $input->getOption($key); - if (empty($value) || ! is_string($value)) { - return null; - } - - try { - return Chronos::parse($value); - } catch (Throwable $e) { - $output->writeln(sprintf( - '> Ignored provided "%s" since its value "%s" is not a valid date. <', - $key, - $value, - )); - - if ($output->isVeryVerbose()) { - $this->getApplication()?->renderThrowable($e, $output); - } - - return null; - } - } - - abstract protected function doConfigure(): void; - - abstract protected function getStartDateDesc(string $optionName): string; - - abstract protected function getEndDateDesc(string $optionName): string; -} diff --git a/module/CLI/src/Command/Visit/AbstractVisitsListCommand.php b/module/CLI/src/Command/Visit/AbstractVisitsListCommand.php index 37a875c6..402d5ba4 100644 --- a/module/CLI/src/Command/Visit/AbstractVisitsListCommand.php +++ b/module/CLI/src/Command/Visit/AbstractVisitsListCommand.php @@ -4,13 +4,15 @@ declare(strict_types=1); namespace Shlinkio\Shlink\CLI\Command\Visit; -use Shlinkio\Shlink\CLI\Command\Util\AbstractWithDateRangeCommand; +use Shlinkio\Shlink\CLI\Option\EndDateOption; +use Shlinkio\Shlink\CLI\Option\StartDateOption; use Shlinkio\Shlink\CLI\Util\ExitCodes; use Shlinkio\Shlink\CLI\Util\ShlinkTable; use Shlinkio\Shlink\Common\Paginator\Paginator; use Shlinkio\Shlink\Common\Util\DateRange; use Shlinkio\Shlink\Core\Visit\Entity\Visit; use Shlinkio\Shlink\Core\Visit\VisitsStatsHelperInterface; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -19,29 +21,23 @@ use function Functional\map; use function Functional\select_keys; use function Shlinkio\Shlink\Common\buildDateRange; use function Shlinkio\Shlink\Core\camelCaseToHumanFriendly; -use function sprintf; -abstract class AbstractVisitsListCommand extends AbstractWithDateRangeCommand +abstract class AbstractVisitsListCommand extends Command { + private readonly StartDateOption $startDateOption; + private readonly EndDateOption $endDateOption; + public function __construct(protected readonly VisitsStatsHelperInterface $visitsHelper) { parent::__construct(); - } - - final protected function getStartDateDesc(string $optionName): string - { - return sprintf('Allows to filter visits, returning only those older than "%s".', $optionName); - } - - final protected function getEndDateDesc(string $optionName): string - { - return sprintf('Allows to filter visits, returning only those newer than "%s".', $optionName); + $this->startDateOption = new StartDateOption($this, 'visits'); + $this->endDateOption = new EndDateOption($this, 'visits'); } final protected function execute(InputInterface $input, OutputInterface $output): ?int { - $startDate = $this->getStartDateOption($input, $output); - $endDate = $this->getEndDateOption($input, $output); + $startDate = $this->startDateOption->get($input, $output); + $endDate = $this->endDateOption->get($input, $output); $paginator = $this->getVisitsPaginator($input, buildDateRange($startDate, $endDate)); [$rows, $headers] = $this->resolveRowsAndHeaders($paginator); diff --git a/module/CLI/src/Command/Visit/GetNonOrphanVisitsCommand.php b/module/CLI/src/Command/Visit/GetNonOrphanVisitsCommand.php index 0b4a4612..0dd32f3e 100644 --- a/module/CLI/src/Command/Visit/GetNonOrphanVisitsCommand.php +++ b/module/CLI/src/Command/Visit/GetNonOrphanVisitsCommand.php @@ -23,7 +23,7 @@ class GetNonOrphanVisitsCommand extends AbstractVisitsListCommand parent::__construct($visitsHelper); } - protected function doConfigure(): void + protected function configure(): void { $this ->setName(self::NAME) diff --git a/module/CLI/src/Command/Visit/GetOrphanVisitsCommand.php b/module/CLI/src/Command/Visit/GetOrphanVisitsCommand.php index c2d353af..618a35cd 100644 --- a/module/CLI/src/Command/Visit/GetOrphanVisitsCommand.php +++ b/module/CLI/src/Command/Visit/GetOrphanVisitsCommand.php @@ -14,7 +14,7 @@ class GetOrphanVisitsCommand extends AbstractVisitsListCommand { public const NAME = 'visit:orphan'; - protected function doConfigure(): void + protected function configure(): void { $this ->setName(self::NAME) diff --git a/module/CLI/src/Option/DateOption.php b/module/CLI/src/Option/DateOption.php new file mode 100644 index 00000000..a863696f --- /dev/null +++ b/module/CLI/src/Option/DateOption.php @@ -0,0 +1,51 @@ +addOption($name, $shortcut, InputOption::VALUE_REQUIRED, $description); + } + + public function get(InputInterface $input, OutputInterface $output): ?Chronos + { + $value = $input->getOption($this->name); + if (empty($value) || ! is_string($value)) { + return null; + } + + try { + return Chronos::parse($value); + } catch (Throwable $e) { + $output->writeln(sprintf( + '> Ignored provided "%s" since its value "%s" is not a valid date. <', + $this->name, + $value, + )); + + if ($output->isVeryVerbose()) { + $this->command->getApplication()?->renderThrowable($e, $output); + } + + return null; + } + } +} diff --git a/module/CLI/src/Option/EndDateOption.php b/module/CLI/src/Option/EndDateOption.php new file mode 100644 index 00000000..72421981 --- /dev/null +++ b/module/CLI/src/Option/EndDateOption.php @@ -0,0 +1,30 @@ +dateOption = new DateOption($command, 'end-date', 'e', sprintf( + 'Allows to filter %s, returning only those newer than provided date.', + $descriptionHint, + )); + } + + public function get(InputInterface $input, OutputInterface $output): ?Chronos + { + return $this->dateOption->get($input, $output); + } +} diff --git a/module/CLI/src/Option/StartDateOption.php b/module/CLI/src/Option/StartDateOption.php new file mode 100644 index 00000000..2da5aaee --- /dev/null +++ b/module/CLI/src/Option/StartDateOption.php @@ -0,0 +1,30 @@ +dateOption = new DateOption($command, 'start-date', 's', sprintf( + 'Allows to filter %s, returning only those older than provided date.', + $descriptionHint, + )); + } + + public function get(InputInterface $input, OutputInterface $output): ?Chronos + { + return $this->dateOption->get($input, $output); + } +}