Completed
Push — develop ( 9d3653...f17214 )
by Alejandro
16s queued 13s
created

GenerateShortUrlCommand::interact()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3.4746

Importance

Changes 0
Metric Value
cc 3
eloc 7
nc 3
nop 2
dl 0
loc 11
ccs 5
cts 8
cp 0.625
crap 3.4746
rs 10
c 0
b 0
f 0
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 Symfony\Component\Console\Command\Command;
13
use Symfony\Component\Console\Input\InputArgument;
14
use Symfony\Component\Console\Input\InputInterface;
15
use Symfony\Component\Console\Input\InputOption;
16
use Symfony\Component\Console\Output\OutputInterface;
17
use Symfony\Component\Console\Style\SymfonyStyle;
18
use Zend\Diactoros\Uri;
19
20
use function array_map;
21
use function Functional\curry;
22
use function Functional\flatten;
23
use function Functional\unique;
24
use function sprintf;
25
26
class GenerateShortUrlCommand extends Command
27
{
28
    public const NAME = 'short-url:generate';
29
30
    private UrlShortenerInterface $urlShortener;
31
    private array $domainConfig;
32
33 4
    public function __construct(UrlShortenerInterface $urlShortener, array $domainConfig)
34
    {
35 4
        parent::__construct();
36 4
        $this->urlShortener = $urlShortener;
37 4
        $this->domainConfig = $domainConfig;
38
    }
39
40 4
    protected function configure(): void
41
    {
42
        $this
43 4
            ->setName(self::NAME)
44 4
            ->setDescription('Generates a short URL for provided long URL and returns it')
45 4
            ->addArgument('longUrl', InputArgument::REQUIRED, 'The long URL to parse')
46 4
            ->addOption(
47 4
                'tags',
48 4
                't',
49 4
                InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED,
50 4
                'Tags to apply to the new short URL'
51
            )
52 4
            ->addOption(
53 4
                'validSince',
54 4
                's',
55 4
                InputOption::VALUE_REQUIRED,
56
                'The date from which this short URL will be valid. '
57 4
                . 'If someone tries to access it before this date, it will not be found.'
58
            )
59 4
            ->addOption(
60 4
                'validUntil',
61 4
                'u',
62 4
                InputOption::VALUE_REQUIRED,
63
                'The date until which this short URL will be valid. '
64 4
                . 'If someone tries to access it after this date, it will not be found.'
65
            )
66 4
            ->addOption(
67 4
                'customSlug',
68 4
                'c',
69 4
                InputOption::VALUE_REQUIRED,
70 4
                'If provided, this slug will be used instead of generating a short code'
71
            )
72 4
            ->addOption(
73 4
                'maxVisits',
74 4
                'm',
75 4
                InputOption::VALUE_REQUIRED,
76 4
                'This will limit the number of visits for this short URL.'
77
            )
78 4
            ->addOption(
79 4
                'findIfExists',
80 4
                'f',
81 4
                InputOption::VALUE_NONE,
82 4
                'This will force existing matching URL to be returned if found, instead of creating a new one.'
83
            )
84 4
            ->addOption(
85 4
                'domain',
86 4
                'd',
87 4
                InputOption::VALUE_REQUIRED,
88 4
                'The domain to which this short URL will be attached.'
89
            );
90
    }
91
92 4
    protected function interact(InputInterface $input, OutputInterface $output): void
93
    {
94 4
        $io = new SymfonyStyle($input, $output);
95 4
        $longUrl = $input->getArgument('longUrl');
96 4
        if (! empty($longUrl)) {
97 4
            return;
98
        }
99
100
        $longUrl = $io->ask('Which URL do you want to shorten?');
101
        if (! empty($longUrl)) {
102
            $input->setArgument('longUrl', $longUrl);
103
        }
104
    }
105
106 4
    protected function execute(InputInterface $input, OutputInterface $output): ?int
107
    {
108 4
        $io = new SymfonyStyle($input, $output);
109 4
        $longUrl = $input->getArgument('longUrl');
110 4
        if (empty($longUrl)) {
111
            $io->error('A URL was not provided!');
112
            return ExitCodes::EXIT_FAILURE;
113
        }
114
115 4
        $explodeWithComma = curry('explode')(',');
116 4
        $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

116
        $tags = unique(flatten(array_map($explodeWithComma, /** @scrutinizer ignore-type */ $input->getOption('tags'))));
Loading history...
117 4
        $customSlug = $input->getOption('customSlug');
118 4
        $maxVisits = $input->getOption('maxVisits');
119
120
        try {
121 4
            $shortUrl = $this->urlShortener->urlToShortCode(
122 4
                new Uri($longUrl),
0 ignored issues
show
Bug introduced by
It seems like $longUrl can also be of type string[]; however, parameter $uri of Zend\Diactoros\Uri::__construct() 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

122
                new Uri(/** @scrutinizer ignore-type */ $longUrl),
Loading history...
123
                $tags,
124 4
                ShortUrlMeta::createFromParams(
125 4
                    $input->getOption('validSince'),
0 ignored issues
show
Bug introduced by
It seems like $input->getOption('validSince') can also be of type string[]; however, parameter $validSince of Shlinkio\Shlink\Core\Mod...eta::createFromParams() does only seem to accept Cake\Chronos\Chronos|null|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

125
                    /** @scrutinizer ignore-type */ $input->getOption('validSince'),
Loading history...
126 4
                    $input->getOption('validUntil'),
0 ignored issues
show
Bug introduced by
It seems like $input->getOption('validUntil') can also be of type string[]; however, parameter $validUntil of Shlinkio\Shlink\Core\Mod...eta::createFromParams() does only seem to accept Cake\Chronos\Chronos|null|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

126
                    /** @scrutinizer ignore-type */ $input->getOption('validUntil'),
Loading history...
127 4
                    $customSlug,
0 ignored issues
show
Bug introduced by
It seems like $customSlug can also be of type string[]; however, parameter $customSlug of Shlinkio\Shlink\Core\Mod...eta::createFromParams() does only seem to accept null|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

127
                    /** @scrutinizer ignore-type */ $customSlug,
Loading history...
128 4
                    $maxVisits !== null ? (int) $maxVisits : null,
129 4
                    $input->getOption('findIfExists'),
130 4
                    $input->getOption('domain')
131
                )
132
            );
133
134 2
            $io->writeln([
135 2
                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

135
                sprintf('Processed long URL: <info>%s</info>', /** @scrutinizer ignore-type */ $longUrl),
Loading history...
136 2
                sprintf('Generated short URL: <info>%s</info>', $shortUrl->toString($this->domainConfig)),
137
            ]);
138 2
            return ExitCodes::EXIT_SUCCESS;
139 2
        } catch (InvalidUrlException | NonUniqueSlugException $e) {
140 2
            $io->error($e->getMessage());
141 2
            return ExitCodes::EXIT_FAILURE;
142
        }
143
    }
144
}
145