mirror of
https://github.com/shlinkio/shlink.git
synced 2024-10-23 04:35:34 +03:00
Moved logic to reuse command options to option classes instead of base abstract command classes
This commit is contained in:
parent
27b680e0cd
commit
1557438fdf
11 changed files with 141 additions and 106 deletions
|
@ -25,7 +25,7 @@ class GetDomainVisitsCommand extends AbstractVisitsListCommand
|
|||
parent::__construct($visitsHelper);
|
||||
}
|
||||
|
||||
protected function doConfigure(): void
|
||||
protected function configure(): void
|
||||
{
|
||||
$this
|
||||
->setName(self::NAME)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ class GetTagVisitsCommand extends AbstractVisitsListCommand
|
|||
parent::__construct($visitsHelper);
|
||||
}
|
||||
|
||||
protected function doConfigure(): void
|
||||
protected function configure(): void
|
||||
{
|
||||
$this
|
||||
->setName(self::NAME)
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\CLI\Command\Util;
|
||||
|
||||
use Cake\Chronos\Chronos;
|
||||
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 Throwable;
|
||||
|
||||
use function is_string;
|
||||
use function sprintf;
|
||||
|
||||
abstract class AbstractWithDateRangeCommand extends Command
|
||||
{
|
||||
private const START_DATE = 'start-date';
|
||||
private const END_DATE = 'end-date';
|
||||
|
||||
final protected function configure(): void
|
||||
{
|
||||
$this->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(
|
||||
'<comment>> Ignored provided "%s" since its value "%s" is not a valid date. <</comment>',
|
||||
$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;
|
||||
}
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ class GetNonOrphanVisitsCommand extends AbstractVisitsListCommand
|
|||
parent::__construct($visitsHelper);
|
||||
}
|
||||
|
||||
protected function doConfigure(): void
|
||||
protected function configure(): void
|
||||
{
|
||||
$this
|
||||
->setName(self::NAME)
|
||||
|
|
|
@ -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)
|
||||
|
|
51
module/CLI/src/Option/DateOption.php
Normal file
51
module/CLI/src/Option/DateOption.php
Normal file
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\CLI\Option;
|
||||
|
||||
use Cake\Chronos\Chronos;
|
||||
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 Throwable;
|
||||
|
||||
use function is_string;
|
||||
use function sprintf;
|
||||
|
||||
class DateOption
|
||||
{
|
||||
public function __construct(
|
||||
private readonly Command $command,
|
||||
private readonly string $name,
|
||||
string $shortcut,
|
||||
string $description,
|
||||
) {
|
||||
$command->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(
|
||||
'<comment>> Ignored provided "%s" since its value "%s" is not a valid date. <</comment>',
|
||||
$this->name,
|
||||
$value,
|
||||
));
|
||||
|
||||
if ($output->isVeryVerbose()) {
|
||||
$this->command->getApplication()?->renderThrowable($e, $output);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
30
module/CLI/src/Option/EndDateOption.php
Normal file
30
module/CLI/src/Option/EndDateOption.php
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\CLI\Option;
|
||||
|
||||
use Cake\Chronos\Chronos;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
class EndDateOption
|
||||
{
|
||||
private readonly DateOption $dateOption;
|
||||
|
||||
public function __construct(Command $command, string $descriptionHint)
|
||||
{
|
||||
$this->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);
|
||||
}
|
||||
}
|
30
module/CLI/src/Option/StartDateOption.php
Normal file
30
module/CLI/src/Option/StartDateOption.php
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\CLI\Option;
|
||||
|
||||
use Cake\Chronos\Chronos;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
class StartDateOption
|
||||
{
|
||||
private readonly DateOption $dateOption;
|
||||
|
||||
public function __construct(Command $command, string $descriptionHint)
|
||||
{
|
||||
$this->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);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue