Completed
Push — develop ( 1f78f5...10fbf8 )
by Alejandro
16s queued 11s
created

GenerateShortUrlCommand::configure()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 67
Code Lines 56

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 54
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 56
c 0
b 0
f 0
dl 0
loc 67
rs 8.9599
ccs 54
cts 54
cp 1
cc 1
nc 1
nop 0
crap 1

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Shlinkio\Shlink\CLI\Command\ShortUrl;
6
7
use Shlinkio\Shlink\CLI\Util\ExitCodes;
8
use Shlinkio\Shlink\Core\Exception\InvalidUrlException;
9
use Shlinkio\Shlink\Core\Exception\NonUniqueSlugException;
10
use Shlinkio\Shlink\Core\Model\ShortUrlMeta;
11
use Shlinkio\Shlink\Core\Service\UrlShortenerInterface;
12
use Shlinkio\Shlink\Core\Validation\ShortUrlMetaInputFilter;
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
20
use function array_map;
21
use function Functional\curry;
22
use function Functional\flatten;
23
use function Functional\unique;
24
use function method_exists;
25
use function sprintf;
26
use function strpos;
27
28
class GenerateShortUrlCommand extends Command
29
{
30
    public const NAME = 'short-url:generate';
31
32
    private UrlShortenerInterface $urlShortener;
33
    private array $domainConfig;
34
    private int $defaultShortCodeLength;
35
36 8
    public function __construct(UrlShortenerInterface $urlShortener, array $domainConfig, int $defaultShortCodeLength)
37
    {
38 8
        parent::__construct();
39 8
        $this->urlShortener = $urlShortener;
40 8
        $this->domainConfig = $domainConfig;
41 8
        $this->defaultShortCodeLength = $defaultShortCodeLength;
42
    }
43
44 8
    protected function configure(): void
45
    {
46
        $this
47 8
            ->setName(self::NAME)
48 8
            ->setDescription('Generates a short URL for provided long URL and returns it')
49 8
            ->addArgument('longUrl', InputArgument::REQUIRED, 'The long URL to parse')
50 8
            ->addOption(
51 8
                'tags',
52 8
                't',
53 8
                InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED,
54 8
                'Tags to apply to the new short URL',
55
            )
56 8
            ->addOption(
57 8
                'validSince',
58 8
                's',
59 8
                InputOption::VALUE_REQUIRED,
60
                'The date from which this short URL will be valid. '
61 8
                . 'If someone tries to access it before this date, it will not be found.',
62
            )
63 8
            ->addOption(
64 8
                'validUntil',
65 8
                'u',
66 8
                InputOption::VALUE_REQUIRED,
67
                'The date until which this short URL will be valid. '
68 8
                . 'If someone tries to access it after this date, it will not be found.',
69
            )
70 8
            ->addOption(
71 8
                'customSlug',
72 8
                'c',
73 8
                InputOption::VALUE_REQUIRED,
74 8
                'If provided, this slug will be used instead of generating a short code',
75
            )
76 8
            ->addOption(
77 8
                'maxVisits',
78 8
                'm',
79 8
                InputOption::VALUE_REQUIRED,
80 8
                'This will limit the number of visits for this short URL.',
81
            )
82 8
            ->addOption(
83 8
                'findIfExists',
84 8
                'f',
85 8
                InputOption::VALUE_NONE,
86 8
                'This will force existing matching URL to be returned if found, instead of creating a new one.',
87
            )
88 8
            ->addOption(
89 8
                'domain',
90 8
                'd',
91 8
                InputOption::VALUE_REQUIRED,
92 8
                'The domain to which this short URL will be attached.',
93
            )
94 8
            ->addOption(
95 8
                'shortCodeLength',
96 8
                'l',
97 8
                InputOption::VALUE_REQUIRED,
98 8
                'The length for generated short code (it will be ignored if --customSlug was provided).',
99
            )
100 8
            ->addOption(
101 8
                'validate-url',
102 8
                null,
103 8
                InputOption::VALUE_NONE,
104 8
                'Forces the long URL to be validated, regardless what is globally configured.',
105
            )
106 8
            ->addOption(
107 8
                'no-validate-url',
108 8
                null,
109 8
                InputOption::VALUE_NONE,
110 8
                'Forces the long URL to not be validated, regardless what is globally configured.',
111
            );
112
    }
113
114 8
    protected function interact(InputInterface $input, OutputInterface $output): void
115
    {
116 8
        $io = new SymfonyStyle($input, $output);
117 8
        $longUrl = $input->getArgument('longUrl');
118 8
        if (! empty($longUrl)) {
119 8
            return;
120
        }
121
122
        $longUrl = $io->ask('Which URL do you want to shorten?');
123
        if (! empty($longUrl)) {
124
            $input->setArgument('longUrl', $longUrl);
125
        }
126
    }
127
128 8
    protected function execute(InputInterface $input, OutputInterface $output): ?int
129
    {
130 8
        $io = new SymfonyStyle($input, $output);
131 8
        $longUrl = $input->getArgument('longUrl');
132 8
        if (empty($longUrl)) {
133
            $io->error('A URL was not provided!');
134
            return ExitCodes::EXIT_FAILURE;
135
        }
136
137 8
        $explodeWithComma = curry('explode')(',');
138 8
        $tags = unique(flatten(array_map($explodeWithComma, $input->getOption('tags'))));
0 ignored issues
show
Bug introduced by
It seems like $input->getOption('tags') can also be of type boolean and null and string; however, parameter $arr1 of array_map() does only seem to accept array, 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

138
        $tags = unique(flatten(array_map($explodeWithComma, /** @scrutinizer ignore-type */ $input->getOption('tags'))));
Loading history...
139 8
        $customSlug = $input->getOption('customSlug');
140 8
        $maxVisits = $input->getOption('maxVisits');
141 8
        $shortCodeLength = $input->getOption('shortCodeLength') ?? $this->defaultShortCodeLength;
142 8
        $doValidateUrl = $this->doValidateUrl($input);
143
144
        try {
145 8
            $shortUrl = $this->urlShortener->urlToShortCode($longUrl, $tags, ShortUrlMeta::fromRawData([
0 ignored issues
show
Bug introduced by
It seems like $longUrl can also be of type string[]; however, parameter $url of Shlinkio\Shlink\Core\Ser...rface::urlToShortCode() 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

145
            $shortUrl = $this->urlShortener->urlToShortCode(/** @scrutinizer ignore-type */ $longUrl, $tags, ShortUrlMeta::fromRawData([
Loading history...
146 8
                ShortUrlMetaInputFilter::VALID_SINCE => $input->getOption('validSince'),
147 8
                ShortUrlMetaInputFilter::VALID_UNTIL => $input->getOption('validUntil'),
148 8
                ShortUrlMetaInputFilter::CUSTOM_SLUG => $customSlug,
149 1
                ShortUrlMetaInputFilter::MAX_VISITS => $maxVisits !== null ? (int) $maxVisits : null,
150 8
                ShortUrlMetaInputFilter::FIND_IF_EXISTS => $input->getOption('findIfExists'),
151 8
                ShortUrlMetaInputFilter::DOMAIN => $input->getOption('domain'),
152 8
                ShortUrlMetaInputFilter::SHORT_CODE_LENGTH => $shortCodeLength,
153 8
                ShortUrlMetaInputFilter::VALIDATE_URL => $doValidateUrl,
154
            ]));
155
156 6
            $io->writeln([
157 6
                sprintf('Processed long URL: <info>%s</info>', $longUrl),
0 ignored issues
show
Bug introduced by
It seems like $longUrl can also be of type string[]; however, parameter $args of sprintf() 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

157
                sprintf('Processed long URL: <info>%s</info>', /** @scrutinizer ignore-type */ $longUrl),
Loading history...
158 6
                sprintf('Generated short URL: <info>%s</info>', $shortUrl->toString($this->domainConfig)),
159
            ]);
160 6
            return ExitCodes::EXIT_SUCCESS;
161 2
        } catch (InvalidUrlException | NonUniqueSlugException $e) {
162 2
            $io->error($e->getMessage());
163 2
            return ExitCodes::EXIT_FAILURE;
164
        }
165
    }
166
167 8
    private function doValidateUrl(InputInterface $input): ?bool
168
    {
169 8
        $rawInput = method_exists($input, '__toString') ? $input->__toString() : '';
170
171 8
        if (strpos($rawInput, '--no-validate-url') !== false) {
172 2
            return false;
173
        }
174 6
        if (strpos($rawInput, '--validate-url') !== false) {
175 1
            return true;
176
        }
177
178 5
        return null;
179
    }
180
}
181