Completed
Push — master ( 62fb38...736054 )
by Alejandro
13s queued 10s
created

ListShortUrlsCommand::configure()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 32
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 26
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 26
nc 1
nop 0
dl 0
loc 32
ccs 26
cts 26
cp 1
crap 1
rs 9.504
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace Shlinkio\Shlink\CLI\Command\ShortUrl;
5
6
use Shlinkio\Shlink\Common\Console\ShlinkTable;
7
use Shlinkio\Shlink\Common\Paginator\Adapter\PaginableRepositoryAdapter;
8
use Shlinkio\Shlink\Common\Paginator\Util\PaginatorUtilsTrait;
9
use Shlinkio\Shlink\Common\Rest\DataTransformerInterface;
10
use Shlinkio\Shlink\Core\Service\ShortUrlServiceInterface;
11
use Shlinkio\Shlink\Core\Transformer\ShortUrlDataTransformer;
12
use Symfony\Component\Console\Command\Command;
13
use Symfony\Component\Console\Input\InputInterface;
14
use Symfony\Component\Console\Input\InputOption;
15
use Symfony\Component\Console\Output\OutputInterface;
16
use Symfony\Component\Console\Style\SymfonyStyle;
17
use Zend\Paginator\Paginator;
18
use function array_values;
19
use function count;
20
use function explode;
21
use function implode;
22
use function sprintf;
23
24
class ListShortUrlsCommand extends Command
25
{
26
    use PaginatorUtilsTrait;
27
28
    public const NAME = 'short-url:list';
29
    private const ALIASES = ['shortcode:list', 'short-code:list'];
30
31
    /** @var ShortUrlServiceInterface */
32
    private $shortUrlService;
33
    /** @var array */
34
    private $domainConfig;
35
36 5
    public function __construct(ShortUrlServiceInterface $shortUrlService, array $domainConfig)
37
    {
38 5
        parent::__construct();
39 5
        $this->shortUrlService = $shortUrlService;
40 5
        $this->domainConfig = $domainConfig;
41
    }
42
43 5
    protected function configure(): void
44
    {
45
        $this
46 5
            ->setName(self::NAME)
47 5
            ->setAliases(self::ALIASES)
48 5
            ->setDescription('List all short URLs')
49 5
            ->addOption(
50 5
                'page',
51 5
                'p',
52 5
                InputOption::VALUE_OPTIONAL,
53 5
                sprintf('The first page to list (%s items per page)', PaginableRepositoryAdapter::ITEMS_PER_PAGE),
54 5
                '1'
55
            )
56 5
            ->addOption(
57 5
                'searchTerm',
58 5
                's',
59 5
                InputOption::VALUE_OPTIONAL,
60 5
                'A query used to filter results by searching for it on the longUrl and shortCode fields'
61
            )
62 5
            ->addOption(
63 5
                'tags',
64 5
                't',
65 5
                InputOption::VALUE_OPTIONAL,
66 5
                'A comma-separated list of tags to filter results'
67
            )
68 5
            ->addOption(
69 5
                'orderBy',
70 5
                'o',
71 5
                InputOption::VALUE_OPTIONAL,
72 5
                'The field from which we want to order by. Pass ASC or DESC separated by a comma'
73
            )
74 5
            ->addOption('showTags', null, InputOption::VALUE_NONE, 'Whether to display the tags or not');
75
    }
76
77 5
    protected function execute(InputInterface $input, OutputInterface $output): void
78
    {
79 5
        $io = new SymfonyStyle($input, $output);
80 5
        $page = (int) $input->getOption('page');
81 5
        $searchTerm = $input->getOption('searchTerm');
82 5
        $tags = $input->getOption('tags');
83 5
        $tags = ! empty($tags) ? explode(',', $tags) : [];
0 ignored issues
show
Bug introduced by
It seems like $tags can also be of type string[]; however, parameter $string of explode() 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

83
        $tags = ! empty($tags) ? explode(',', /** @scrutinizer ignore-type */ $tags) : [];
Loading history...
84 5
        $showTags = (bool) $input->getOption('showTags');
85 5
        $transformer = new ShortUrlDataTransformer($this->domainConfig);
86
87
        do {
88 5
            $result = $this->renderPage($input, $output, $page, $searchTerm, $tags, $showTags, $transformer);
89 5
            $page++;
90
91 5
            $continue = $this->isLastPage($result)
92 3
                ? false
93 5
                : $io->confirm(sprintf('Continue with page <options=bold>%s</>?', $page), false);
94 5
        } while ($continue);
95
96 5
        $io->newLine();
97 5
        $io->success('Short URLs properly listed');
98
    }
99
100 5
    private function renderPage(
101
        InputInterface $input,
102
        OutputInterface $output,
103
        int $page,
104
        ?string $searchTerm,
105
        array $tags,
106
        bool $showTags,
107
        DataTransformerInterface $transformer
108
    ): Paginator {
109 5
        $result = $this->shortUrlService->listShortUrls($page, $searchTerm, $tags, $this->processOrderBy($input));
110
111 5
        $headers = ['Short code', 'Short URL', 'Long URL', 'Date created', 'Visits count'];
112 5
        if ($showTags) {
113 1
            $headers[] = 'Tags';
114
        }
115
116 5
        $rows = [];
117 5
        foreach ($result as $row) {
118 2
            $shortUrl = $transformer->transform($row);
119 2
            if ($showTags) {
120
                $shortUrl['tags'] = implode(', ', $shortUrl['tags']);
121
            } else {
122 2
                unset($shortUrl['tags']);
123
            }
124
125 2
            unset($shortUrl['originalUrl']);
126 2
            $rows[] = array_values($shortUrl);
127
        }
128
129 5
        ShlinkTable::fromOutput($output)->render($headers, $rows, $this->formatCurrentPageMessage(
130 5
            $result,
131 5
            'Page %s of %s'
132
        ));
133 5
        return $result;
134
    }
135
136 5
    private function processOrderBy(InputInterface $input)
137
    {
138 5
        $orderBy = $input->getOption('orderBy');
139 5
        if (empty($orderBy)) {
140 5
            return null;
141
        }
142
143
        $orderBy = explode(',', $orderBy);
0 ignored issues
show
Bug introduced by
It seems like $orderBy can also be of type string[]; however, parameter $string of explode() 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

143
        $orderBy = explode(',', /** @scrutinizer ignore-type */ $orderBy);
Loading history...
144
        return count($orderBy) === 1 ? $orderBy[0] : [$orderBy[0] => $orderBy[1]];
145
    }
146
}
147