From aecc36a46359d4bb17e69c9e45be459f96de0d12 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Wed, 17 Dec 2025 15:27:39 +0100 Subject: [PATCH] Convert GetOrphanVisitsCommand into invokable command --- .../Command/Visit/GetOrphanVisitsCommand.php | 70 ++++++++----------- 1 file changed, 31 insertions(+), 39 deletions(-) diff --git a/module/CLI/src/Command/Visit/GetOrphanVisitsCommand.php b/module/CLI/src/Command/Visit/GetOrphanVisitsCommand.php index 0804215a..5640361f 100644 --- a/module/CLI/src/Command/Visit/GetOrphanVisitsCommand.php +++ b/module/CLI/src/Command/Visit/GetOrphanVisitsCommand.php @@ -4,64 +4,56 @@ declare(strict_types=1); namespace Shlinkio\Shlink\CLI\Command\Visit; -use Shlinkio\Shlink\CLI\Input\DomainOption; -use Shlinkio\Shlink\Common\Paginator\Paginator; -use Shlinkio\Shlink\Common\Util\DateRange; +use Shlinkio\Shlink\CLI\Input\VisitsDateRangeInput; +use Shlinkio\Shlink\CLI\Util\ShlinkTable; use Shlinkio\Shlink\Core\Domain\Entity\Domain; use Shlinkio\Shlink\Core\Visit\Entity\Visit; use Shlinkio\Shlink\Core\Visit\Model\OrphanVisitsParams; use Shlinkio\Shlink\Core\Visit\Model\OrphanVisitType; use Shlinkio\Shlink\Core\Visit\VisitsStatsHelperInterface; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Attribute\AsCommand; +use Symfony\Component\Console\Attribute\MapInput; +use Symfony\Component\Console\Attribute\Option; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Style\SymfonyStyle; -use function Shlinkio\Shlink\Core\enumToString; -use function sprintf; - -class GetOrphanVisitsCommand extends AbstractVisitsListCommand +#[AsCommand(GetOrphanVisitsCommand::NAME, 'Returns the list of orphan visits')] +class GetOrphanVisitsCommand extends Command { public const string NAME = 'visit:orphan'; - private readonly DomainOption $domainOption; - - public function __construct(VisitsStatsHelperInterface $visitsHelper) + public function __construct(private readonly VisitsStatsHelperInterface $visitsHelper) { - parent::__construct($visitsHelper); - $this->domainOption = new DomainOption($this, sprintf( - 'Return visits that belong to this domain only. Use %s keyword for visits in default domain', - Domain::DEFAULT_AUTHORITY, - )); + parent::__construct(); } - protected function configure(): void - { - $this - ->setName(self::NAME) - ->setDescription('Returns the list of orphan visits.') - ->addOption('type', 't', InputOption::VALUE_REQUIRED, sprintf( - 'Return visits only with this type. One of %s', - enumToString(OrphanVisitType::class), - )); - } - - /** - * @return Paginator - */ - protected function getVisitsPaginator(InputInterface $input, DateRange $dateRange): Paginator - { - $rawType = $input->getOption('type'); - $type = $rawType !== null ? OrphanVisitType::from($rawType) : null; - return $this->visitsHelper->orphanVisits(new OrphanVisitsParams( - dateRange: $dateRange, - domain: $this->domainOption->get($input), + public function __invoke( + SymfonyStyle $io, + #[MapInput] VisitsDateRangeInput $dateRangeInput, + #[Option( + 'Return visits that belong to this domain only. Use ' . Domain::DEFAULT_AUTHORITY . ' keyword for visits ' + . 'in default domain', + shortcut: 'd', + )] + string|null $domain = null, + #[Option('Return visits only with this type', shortcut: 't')] OrphanVisitType|null $type = null, + ): int { + $paginator = $this->visitsHelper->orphanVisits(new OrphanVisitsParams( + dateRange: $dateRangeInput->toDateRange(), + domain: $domain, type: $type, )); + [$rows, $headers] = VisitsCommandUtils::resolveRowsAndHeaders($paginator, $this->mapExtraFields(...)); + + ShlinkTable::default($io)->render($headers, $rows); + + return self::SUCCESS; } /** * @return array */ - protected function mapExtraFields(Visit $visit): array + private function mapExtraFields(Visit $visit): array { return ['type' => $visit->type->value]; }