Completed
Pull Request — master (#246)
by Alejandro
05:59
created

ListShortUrlsCommand::execute()   B

Complexity

Conditions 7
Paths 24

Size

Total Lines 46
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 31
CRAP Score 7.0014

Importance

Changes 0
Metric Value
cc 7
eloc 36
nc 24
nop 2
dl 0
loc 46
rs 8.4106
c 0
b 0
f 0
ccs 31
cts 32
cp 0.9688
crap 7.0014
1
<?php
2
declare(strict_types=1);
3
4
namespace Shlinkio\Shlink\CLI\Command\ShortUrl;
5
6
use Shlinkio\Shlink\Common\Paginator\Adapter\PaginableRepositoryAdapter;
7
use Shlinkio\Shlink\Common\Paginator\Util\PaginatorUtilsTrait;
8
use Shlinkio\Shlink\Core\Service\ShortUrlServiceInterface;
9
use Shlinkio\Shlink\Core\Transformer\ShortUrlDataTransformer;
10
use Symfony\Component\Console\Command\Command;
11
use Symfony\Component\Console\Input\InputInterface;
12
use Symfony\Component\Console\Input\InputOption;
13
use Symfony\Component\Console\Output\OutputInterface;
14
use Symfony\Component\Console\Style\SymfonyStyle;
15
use Zend\I18n\Translator\TranslatorInterface;
16
use function array_values;
17
use function count;
18
use function explode;
19
use function implode;
20
use function sprintf;
21
22
class ListShortUrlsCommand extends Command
23
{
24
    use PaginatorUtilsTrait;
25
26
    public const NAME = 'short-url:list';
27
    private const ALIASES = ['shortcode:list', 'short-code:list'];
28
29
    /**
30
     * @var ShortUrlServiceInterface
31
     */
32
    private $shortUrlService;
33
    /**
34
     * @var TranslatorInterface
35
     */
36
    private $translator;
37
    /**
38
     * @var array
39
     */
40
    private $domainConfig;
41
42 5
    public function __construct(
43
        ShortUrlServiceInterface $shortUrlService,
44
        TranslatorInterface $translator,
45
        array $domainConfig
46
    ) {
47 5
        $this->shortUrlService = $shortUrlService;
48 5
        $this->translator = $translator;
49 5
        parent::__construct();
50 5
        $this->domainConfig = $domainConfig;
51 5
    }
52
53 5
    protected function configure(): void
54
    {
55
        $this
56 5
            ->setName(self::NAME)
57 5
            ->setAliases(self::ALIASES)
58 5
            ->setDescription($this->translator->translate('List all short URLs'))
59 5
            ->addOption(
60 5
                'page',
61 5
                'p',
62 5
                InputOption::VALUE_OPTIONAL,
63 5
                sprintf(
64 5
                    $this->translator->translate('The first page to list (%s items per page)'),
65 5
                    PaginableRepositoryAdapter::ITEMS_PER_PAGE
66
                ),
67 5
                1
68
            )
69 5
            ->addOption(
70 5
                'searchTerm',
71 5
                's',
72 5
                InputOption::VALUE_OPTIONAL,
73 5
                $this->translator->translate(
74 5
                    'A query used to filter results by searching for it on the longUrl and shortCode fields'
75
                )
76
            )
77 5
            ->addOption(
78 5
                'tags',
79 5
                't',
80 5
                InputOption::VALUE_OPTIONAL,
81 5
                $this->translator->translate('A comma-separated list of tags to filter results')
82
            )
83 5
            ->addOption(
84 5
                'orderBy',
85 5
                'o',
86 5
                InputOption::VALUE_OPTIONAL,
87 5
                $this->translator->translate(
88 5
                    'The field from which we want to order by. Pass ASC or DESC separated by a comma'
89
                )
90
            )
91 5
            ->addOption(
92 5
                'showTags',
93 5
                null,
94 5
                InputOption::VALUE_NONE,
95 5
                $this->translator->translate('Whether to display the tags or not')
96
            );
97 5
    }
98
99 5
    protected function execute(InputInterface $input, OutputInterface $output): void
100
    {
101 5
        $io = new SymfonyStyle($input, $output);
102 5
        $page = (int) $input->getOption('page');
103 5
        $searchTerm = $input->getOption('searchTerm');
104 5
        $tags = $input->getOption('tags');
105 5
        $tags = ! empty($tags) ? explode(',', $tags) : [];
106 5
        $showTags = $input->getOption('showTags');
107 5
        $transformer = new ShortUrlDataTransformer($this->domainConfig);
108
109
        do {
110 5
            $result = $this->shortUrlService->listShortUrls($page, $searchTerm, $tags, $this->processOrderBy($input));
111 5
            $page++;
112
113
            $headers = [
114 5
                $this->translator->translate('Short code'),
115 5
                $this->translator->translate('Short URL'),
116 5
                $this->translator->translate('Long URL'),
117 5
                $this->translator->translate('Date created'),
118 5
                $this->translator->translate('Visits count'),
119
            ];
120 5
            if ($showTags) {
121 1
                $headers[] = $this->translator->translate('Tags');
122
            }
123
124 5
            $rows = [];
125 5
            foreach ($result as $row) {
126 2
                $shortUrl = $transformer->transform($row);
127 2
                if ($showTags) {
128
                    $shortUrl['tags'] = implode(', ', $shortUrl['tags']);
129
                } else {
130 2
                    unset($shortUrl['tags']);
131
                }
132
133 2
                unset($shortUrl['originalUrl']);
134 2
                $rows[] = array_values($shortUrl);
135
            }
136 5
            $io->table($headers, $rows);
137
138 5
            if ($this->isLastPage($result)) {
139 3
                $continue = false;
140 3
                $io->success($this->translator->translate('Short URLs properly listed'));
141
            } else {
142 2
                $continue = $io->confirm(
143 2
                    sprintf($this->translator->translate('Continue with page') . ' <options=bold>%s</>?', $page),
144 2
                    false
145
                );
146
            }
147 5
        } while ($continue);
148 5
    }
149
150 5
    private function processOrderBy(InputInterface $input)
151
    {
152 5
        $orderBy = $input->getOption('orderBy');
153 5
        if (empty($orderBy)) {
154 5
            return null;
155
        }
156
157
        $orderBy = explode(',', $orderBy);
158
        return count($orderBy) === 1 ? $orderBy[0] : [$orderBy[0] => $orderBy[1]];
159
    }
160
}
161