Completed
Pull Request — master (#316)
by Alejandro
06:47 queued 04:02
created

GetVisitsCommand   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 70
Duplicated Lines 0 %

Test Coverage

Coverage 90%

Importance

Changes 0
Metric Value
eloc 40
dl 0
loc 70
rs 10
c 0
b 0
f 0
ccs 36
cts 40
cp 0.9
wmc 8

5 Methods

Rating   Name   Duplication   Size   Complexity  
A getDateOption() 0 4 2
A interact() 0 11 3
A configure() 0 18 1
A execute() 0 15 1
A __construct() 0 4 1
1
<?php
2
declare(strict_types=1);
3
4
namespace Shlinkio\Shlink\CLI\Command\ShortUrl;
5
6
use Cake\Chronos\Chronos;
7
use Shlinkio\Shlink\Common\Console\ShlinkTable;
8
use Shlinkio\Shlink\Common\Util\DateRange;
9
use Shlinkio\Shlink\Core\Entity\Visit;
10
use Shlinkio\Shlink\Core\Model\VisitsParams;
11
use Shlinkio\Shlink\Core\Service\VisitsTrackerInterface;
12
use Symfony\Component\Console\Command\Command;
13
use Symfony\Component\Console\Input\InputArgument;
14
use Symfony\Component\Console\Input\InputInterface;
15
use Symfony\Component\Console\Input\InputOption;
16
use Symfony\Component\Console\Output\OutputInterface;
17
use Symfony\Component\Console\Style\SymfonyStyle;
18
use Zend\Stdlib\ArrayUtils;
19
use function array_map;
20
use function Functional\select_keys;
21
22
class GetVisitsCommand extends Command
23
{
24
    public const NAME = 'short-url:visits';
25
    private const ALIASES = ['shortcode:visits', 'short-code:visits'];
26
27
    /** @var VisitsTrackerInterface */
28
    private $visitsTracker;
29
30 3
    public function __construct(VisitsTrackerInterface $visitsTracker)
31
    {
32 3
        $this->visitsTracker = $visitsTracker;
33 3
        parent::__construct();
34
    }
35
36 3
    protected function configure(): void
37
    {
38
        $this
39 3
            ->setName(self::NAME)
40 3
            ->setAliases(self::ALIASES)
41 3
            ->setDescription('Returns the detailed visits information for provided short code')
42 3
            ->addArgument('shortCode', InputArgument::REQUIRED, 'The short code which visits we want to get')
43 3
            ->addOption(
44 3
                'startDate',
45 3
                's',
46 3
                InputOption::VALUE_OPTIONAL,
47 3
                'Allows to filter visits, returning only those older than start date'
48
            )
49 3
            ->addOption(
50 3
                'endDate',
51 3
                'e',
52 3
                InputOption::VALUE_OPTIONAL,
53 3
                'Allows to filter visits, returning only those newer than end date'
54
            );
55
    }
56
57 3
    protected function interact(InputInterface $input, OutputInterface $output): void
58
    {
59 3
        $shortCode = $input->getArgument('shortCode');
60 3
        if (! empty($shortCode)) {
61 3
            return;
62
        }
63
64
        $io = new SymfonyStyle($input, $output);
65
        $shortCode = $io->ask('A short code was not provided. Which short code do you want to use?');
66
        if (! empty($shortCode)) {
67
            $input->setArgument('shortCode', $shortCode);
68
        }
69
    }
70
71 3
    protected function execute(InputInterface $input, OutputInterface $output): void
72
    {
73 3
        $shortCode = $input->getArgument('shortCode');
74 3
        $startDate = $this->getDateOption($input, 'startDate');
75 3
        $endDate = $this->getDateOption($input, 'endDate');
76
77 3
        $paginator = $this->visitsTracker->info($shortCode, new VisitsParams(new DateRange($startDate, $endDate)));
0 ignored issues
show
Bug introduced by
It seems like $shortCode can also be of type null and string[]; however, parameter $shortCode of Shlinkio\Shlink\Core\Ser...rackerInterface::info() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

77
        $paginator = $this->visitsTracker->info(/** @scrutinizer ignore-type */ $shortCode, new VisitsParams(new DateRange($startDate, $endDate)));
Loading history...
78 3
        $visits = ArrayUtils::iteratorToArray($paginator->getCurrentItems());
79
80
        $rows = array_map(function (Visit $visit) {
81 1
            $rowData = $visit->jsonSerialize();
82 1
            $rowData['country'] = $visit->getVisitLocation()->getCountryName();
83 1
            return select_keys($rowData, ['referer', 'date', 'userAgent', 'country']);
84 3
        }, $visits);
85 3
        ShlinkTable::fromOutput($output)->render(['Referer', 'Date', 'User agent', 'Country'], $rows);
86
    }
87
88 3
    private function getDateOption(InputInterface $input, $key)
89
    {
90 3
        $value = $input->getOption($key);
91 3
        return ! empty($value) ? Chronos::parse($value) : $value;
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type string[]; however, parameter $time of Cake\Chronos\Chronos::parse() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

91
        return ! empty($value) ? Chronos::parse(/** @scrutinizer ignore-type */ $value) : $value;
Loading history...
92
    }
93
}
94