Completed
Push — master ( 6eef69...27b08f )
by Alejandro
07:50
created

ListShortcodesCommand::processOrderBy()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 6
nc 3
nop 1
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
ccs 0
cts 0
cp 0
crap 12
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 5
                     'A query used to filter results by searching for it on the longUrl and shortCode fields'
65 5
                 )
66
             )
67 5
             ->addOption(
68
                 'tags',
69 5
                 't',
70 5
                 InputOption::VALUE_OPTIONAL,
71
                 $this->translator->translate('A comma-separated list of tags to filter results')
72
             )
73 5
             ->addOption(
74
                 'orderBy',
75
                 'o',
76 5
                 InputOption::VALUE_OPTIONAL,
77 5
                 $this->translator->translate(
78 5
                     'The field from which we want to order by. Pass ASC or DESC separated by a comma'
79
                 )
80
             )
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 1
    }
88 1
89 5
    public function execute(InputInterface $input, OutputInterface $output)
90
    {
91 5
        $page = intval($input->getOption('page'));
92 2
        $searchTerm = $input->getOption('searchTerm');
93 2
        $tags = $input->getOption('tags');
94
        $tags = ! empty($tags) ? explode(',', $tags) : [];
95
        $showTags = $input->getOption('showTags');
96
        $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
        $helper = $this->getHelper('question');
100 2
101
        do {
102
            $result = $this->shortUrlService->listShortUrls($page, $searchTerm, $tags, $this->processOrderBy($input));
103 2
            $page++;
104 5
            $table = new Table($output);
105 5
106
            $headers = [
107 5
                $this->translator->translate('Short code'),
108 4
                $this->translator->translate('Original URL'),
109 4
                $this->translator->translate('Date created'),
110 4
                $this->translator->translate('Visits count'),
111 4
            ];
112 4
            if ($showTags) {
113 2
                $headers[] = $this->translator->translate('Tags');
114 2
            }
115
            $table->setHeaders($headers);
116 2
117
            foreach ($result as $row) {
118 2
                $shortUrl = $row->jsonSerialize();
119
                if ($showTags) {
120 5
                    $shortUrl['tags'] = [];
121 5
                    foreach ($row->getTags() as $tag) {
122
                        $shortUrl['tags'][] = $tag->getName();
123
                    }
124
                    $shortUrl['tags'] = implode(', ', $shortUrl['tags']);
125
                } else {
126
                    unset($shortUrl['tags']);
127
                }
128
129
                $table->addRow(array_values($shortUrl));
130
            }
131
            $table->render();
132
133
            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
                $continue = false;
135
                $output->writeln(
136
                    sprintf('<info>%s</info>', $this->translator->translate('You have reached last page'))
137
                );
138
            } else {
139
                $continue = $helper->ask($input, $output, new ConfirmationQuestion(
140
                    sprintf('<question>' . $this->translator->translate(
141
                        'Continue with page'
142
                    ) . ' <bg=cyan;options=bold>%s</>? (y/N)</question> ', $page),
143
                    false
144
                ));
145
            }
146
        } while ($continue);
0 ignored issues
show
Bug Best Practice introduced by
The expression $continue of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
147
    }
148
149
    protected function processOrderBy(InputInterface $input)
150
    {
151
        $orderBy = $input->getOption('orderBy');
152
        if (empty($orderBy)) {
153
            return null;
154
        }
155
156
        $orderBy = explode(',', $orderBy);
157
        return count($orderBy) === 1 ? $orderBy[0] : [$orderBy[0] => $orderBy[1]];
158
    }
159
}
160