Passed
Pull Request — master (#357)
by Alejandro
05:24
created

GetVisitsCommand::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
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\CLI\Util\ExitCodes;
8
use Shlinkio\Shlink\Common\Console\ShlinkTable;
9
use Shlinkio\Shlink\Common\Util\DateRange;
10
use Shlinkio\Shlink\Core\Entity\Visit;
11
use Shlinkio\Shlink\Core\Model\VisitsParams;
12
use Shlinkio\Shlink\Core\Service\VisitsTrackerInterface;
13
use Symfony\Component\Console\Command\Command;
14
use Symfony\Component\Console\Input\InputArgument;
15
use Symfony\Component\Console\Input\InputInterface;
16
use Symfony\Component\Console\Input\InputOption;
17
use Symfony\Component\Console\Output\OutputInterface;
18
use Symfony\Component\Console\Style\SymfonyStyle;
19
use Zend\Stdlib\ArrayUtils;
20
use function array_map;
21
use function Functional\select_keys;
22
23
class GetVisitsCommand extends Command
24
{
25
    public const NAME = 'short-url:visits';
26
    private const ALIASES = ['shortcode:visits', 'short-code:visits'];
27
28
    /** @var VisitsTrackerInterface */
29
    private $visitsTracker;
30
31 3
    public function __construct(VisitsTrackerInterface $visitsTracker)
32
    {
33 3
        $this->visitsTracker = $visitsTracker;
34 3
        parent::__construct();
35
    }
36
37 3
    protected function configure(): void
38
    {
39
        $this
40 3
            ->setName(self::NAME)
41 3
            ->setAliases(self::ALIASES)
42 3
            ->setDescription('Returns the detailed visits information for provided short code')
43 3
            ->addArgument('shortCode', InputArgument::REQUIRED, 'The short code which visits we want to get')
44 3
            ->addOption(
45 3
                'startDate',
46 3
                's',
47 3
                InputOption::VALUE_OPTIONAL,
48 3
                'Allows to filter visits, returning only those older than start date'
49
            )
50 3
            ->addOption(
51 3
                'endDate',
52 3
                'e',
53 3
                InputOption::VALUE_OPTIONAL,
54 3
                'Allows to filter visits, returning only those newer than end date'
55
            );
56
    }
57
58 3
    protected function interact(InputInterface $input, OutputInterface $output): void
59
    {
60 3
        $shortCode = $input->getArgument('shortCode');
61 3
        if (! empty($shortCode)) {
62 3
            return;
63
        }
64
65
        $io = new SymfonyStyle($input, $output);
66
        $shortCode = $io->ask('A short code was not provided. Which short code do you want to use?');
67
        if (! empty($shortCode)) {
68
            $input->setArgument('shortCode', $shortCode);
69
        }
70
    }
71
72 3
    protected function execute(InputInterface $input, OutputInterface $output): ?int
73
    {
74 3
        $shortCode = $input->getArgument('shortCode');
75 3
        $startDate = $this->getDateOption($input, 'startDate');
76 3
        $endDate = $this->getDateOption($input, 'endDate');
77
78 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

78
        $paginator = $this->visitsTracker->info(/** @scrutinizer ignore-type */ $shortCode, new VisitsParams(new DateRange($startDate, $endDate)));
Loading history...
79 3
        $visits = ArrayUtils::iteratorToArray($paginator->getCurrentItems());
80
81
        $rows = array_map(function (Visit $visit) {
82 1
            $rowData = $visit->jsonSerialize();
83 1
            $rowData['country'] = $visit->getVisitLocation()->getCountryName();
84 1
            return select_keys($rowData, ['referer', 'date', 'userAgent', 'country']);
85 3
        }, $visits);
86 3
        ShlinkTable::fromOutput($output)->render(['Referer', 'Date', 'User agent', 'Country'], $rows);
87 3
        return ExitCodes::EXIT_SUCCESS;
88
    }
89
90 3
    private function getDateOption(InputInterface $input, $key)
91
    {
92 3
        $value = $input->getOption($key);
93 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

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