Completed
Push — master ( f7424d...b53e51 )
by Alejandro
07:43
created

ListShortcodesCommand   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 142
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 9

Test Coverage

Coverage 91.49%

Importance

Changes 0
Metric Value
dl 0
loc 142
ccs 86
cts 94
cp 0.9149
rs 10
c 0
b 0
f 0
wmc 13
lcom 1
cbo 9

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A processOrderBy() 0 10 3
B configure() 0 43 1
B execute() 0 59 8
1
<?php
2
namespace Shlinkio\Shlink\CLI\Command\Shortcode;
3
4
use Acelaya\ZsmAnnotatedServices\Annotation\Inject;
5
use Shlinkio\Shlink\Common\Paginator\Adapter\PaginableRepositoryAdapter;
6
use Shlinkio\Shlink\Common\Paginator\Util\PaginatorUtilsTrait;
7
use Shlinkio\Shlink\Core\Service\ShortUrlService;
8
use Shlinkio\Shlink\Core\Service\ShortUrlServiceInterface;
9
use Symfony\Component\Console\Command\Command;
10
use Symfony\Component\Console\Helper\QuestionHelper;
11
use Symfony\Component\Console\Helper\Table;
12
use Symfony\Component\Console\Input\InputInterface;
13
use Symfony\Component\Console\Input\InputOption;
14
use Symfony\Component\Console\Output\OutputInterface;
15
use Symfony\Component\Console\Question\ConfirmationQuestion;
16
use Zend\I18n\Translator\TranslatorInterface;
17
18
class ListShortcodesCommand extends Command
19
{
20
    use PaginatorUtilsTrait;
21
22
    /**
23
     * @var ShortUrlServiceInterface
24
     */
25
    private $shortUrlService;
26
    /**
27
     * @var TranslatorInterface
28
     */
29
    private $translator;
30
31
    /**
32
     * ListShortcodesCommand constructor.
33
     * @param ShortUrlServiceInterface $shortUrlService
34
     * @param TranslatorInterface $translator
35
     *
36
     * @Inject({ShortUrlService::class, "translator"})
37
     */
38 5
    public function __construct(ShortUrlServiceInterface $shortUrlService, TranslatorInterface $translator)
39
    {
40 5
        $this->shortUrlService = $shortUrlService;
41 5
        $this->translator = $translator;
42 5
        parent::__construct(null);
43 5
    }
44
45 5
    public function configure()
46
    {
47 5
        $this->setName('shortcode:list')
48 5
             ->setDescription($this->translator->translate('List all short URLs'))
49 5
             ->addOption(
50 5
                 'page',
51 5
                 'p',
52 5
                 InputOption::VALUE_OPTIONAL,
53 5
                 sprintf(
54 5
                     $this->translator->translate('The first page to list (%s items per page)'),
55
                     PaginableRepositoryAdapter::ITEMS_PER_PAGE
56 5
                 ),
57
                 1
58 5
             )
59 5
             ->addOption(
60 5
                 'searchTerm',
61 5
                 's',
62 5
                 InputOption::VALUE_OPTIONAL,
63 5
                 $this->translator->translate(
64
                     'A query used to filter results by searching for it on the longUrl and shortCode fields'
65 5
                 )
66 5
             )
67 5
             ->addOption(
68 5
                 'tags',
69 5
                 't',
70 5
                 InputOption::VALUE_OPTIONAL,
71 5
                 $this->translator->translate('A comma-separated list of tags to filter results')
72 5
             )
73 5
             ->addOption(
74 5
                 'orderBy',
75 5
                 'o',
76 5
                 InputOption::VALUE_OPTIONAL,
77 5
                 $this->translator->translate(
78
                     'The field from which we want to order by. Pass ASC or DESC separated by a comma'
79 5
                 )
80 5
             )
81 5
             ->addOption(
82 5
                 'showTags',
83 5
                 null,
84 5
                 InputOption::VALUE_NONE,
85 5
                 $this->translator->translate('Whether to display the tags or not')
86 5
             );
87 5
    }
88
89 5
    public function execute(InputInterface $input, OutputInterface $output)
90
    {
91 5
        $page = intval($input->getOption('page'));
92 5
        $searchTerm = $input->getOption('searchTerm');
93 5
        $tags = $input->getOption('tags');
94 5
        $tags = ! empty($tags) ? explode(',', $tags) : [];
95 5
        $showTags = $input->getOption('showTags');
96 5
        $orderBy = $input->getOption('orderBy');
0 ignored issues
show
Unused Code introduced by
$orderBy is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
97
98
        /** @var QuestionHelper $helper */
99 5
        $helper = $this->getHelper('question');
100
101
        do {
102 5
            $result = $this->shortUrlService->listShortUrls($page, $searchTerm, $tags, $this->processOrderBy($input));
103 5
            $page++;
104 5
            $table = new Table($output);
105
106
            $headers = [
107 5
                $this->translator->translate('Short code'),
108 5
                $this->translator->translate('Original URL'),
109 5
                $this->translator->translate('Date created'),
110 5
                $this->translator->translate('Visits count'),
111 5
            ];
112 5
            if ($showTags) {
113 1
                $headers[] = $this->translator->translate('Tags');
114 1
            }
115 5
            $table->setHeaders($headers);
116
117 5
            foreach ($result as $row) {
118 2
                $shortUrl = $row->jsonSerialize();
119 2
                if ($showTags) {
120
                    $shortUrl['tags'] = [];
121
                    foreach ($row->getTags() as $tag) {
122
                        $shortUrl['tags'][] = $tag->getName();
123
                    }
124
                    $shortUrl['tags'] = implode(', ', $shortUrl['tags']);
125
                } else {
126 2
                    unset($shortUrl['tags']);
127
                }
128
129 2
                $table->addRow(array_values($shortUrl));
130 5
            }
131 5
            $table->render();
132
133 5
            if ($this->isLastPage($result)) {
0 ignored issues
show
Bug introduced by
It seems like $result defined by $this->shortUrlService->...processOrderBy($input)) on line 102 can also be of type array<integer,object<Shl...\Core\Entity\ShortUrl>>; however, Shlinkio\Shlink\Common\P...tilsTrait::isLastPage() does only seem to accept object<Zend\Paginator\Paginator>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
134 4
                $continue = false;
135 4
                $output->writeln(
136 4
                    sprintf('<info>%s</info>', $this->translator->translate('You have reached last page'))
137 4
                );
138 4
            } else {
139 2
                $continue = $helper->ask($input, $output, new ConfirmationQuestion(
140 2
                    sprintf('<question>' . $this->translator->translate(
141
                        'Continue with page'
142 2
                    ) . ' <bg=cyan;options=bold>%s</>? (y/N)</question> ', $page),
143
                    false
144 2
                ));
145
            }
146 5
        } while ($continue);
147 5
    }
148
149 5
    protected function processOrderBy(InputInterface $input)
150
    {
151 5
        $orderBy = $input->getOption('orderBy');
152 5
        if (empty($orderBy)) {
153 5
            return null;
154
        }
155
156
        $orderBy = explode(',', $orderBy);
157
        return count($orderBy) === 1 ? $orderBy[0] : [$orderBy[0] => $orderBy[1]];
158
    }
159
}
160