startDateOption = new StartDateOption($this, 'visits'); $this->endDateOption = new EndDateOption($this, 'visits'); } final protected function execute(InputInterface $input, OutputInterface $output): int { $startDate = $this->startDateOption->get($input, $output); $endDate = $this->endDateOption->get($input, $output); $paginator = $this->getVisitsPaginator($input, buildDateRange($startDate, $endDate)); [$rows, $headers] = VisitsCommandUtils::resolveRowsAndHeaders($paginator, $this->mapExtraFields(...)); ShlinkTable::default($output)->render($headers, $rows); return self::SUCCESS; } /** * @return Paginator */ abstract protected function getVisitsPaginator(InputInterface $input, DateRange $dateRange): Paginator; /** * @return array */ abstract protected function mapExtraFields(Visit $visit): array; }