Completed
Push — master ( 17779d...c32e20 )
by Alejandro
13s
created

GenerateShortcodeCommand::getOptionalDate()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 2
dl 0
loc 5
rs 10
c 0
b 0
f 0
ccs 3
cts 3
cp 1
crap 2
1
<?php
2
declare(strict_types=1);
3
4
namespace Shlinkio\Shlink\CLI\Command\Shortcode;
5
6
use Shlinkio\Shlink\Core\Exception\InvalidUrlException;
7
use Shlinkio\Shlink\Core\Exception\NonUniqueSlugException;
8
use Shlinkio\Shlink\Core\Service\UrlShortenerInterface;
9
use Shlinkio\Shlink\Core\Util\ShortUrlBuilderTrait;
10
use Symfony\Component\Console\Command\Command;
11
use Symfony\Component\Console\Input\InputArgument;
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\Style\SymfonyStyle;
16
use Zend\Diactoros\Uri;
17
use Zend\I18n\Translator\TranslatorInterface;
18
19
class GenerateShortcodeCommand extends Command
20
{
21
    use ShortUrlBuilderTrait;
22
23
    public const NAME = 'shortcode:generate';
24
25
    /**
26
     * @var UrlShortenerInterface
27
     */
28
    private $urlShortener;
29
    /**
30
     * @var array
31
     */
32
    private $domainConfig;
33
    /**
34
     * @var TranslatorInterface
35
     */
36
    private $translator;
37
38 2
    public function __construct(
39
        UrlShortenerInterface $urlShortener,
40
        TranslatorInterface $translator,
41
        array $domainConfig
42
    ) {
43 2
        $this->urlShortener = $urlShortener;
44 2
        $this->translator = $translator;
45 2
        $this->domainConfig = $domainConfig;
46 2
        parent::__construct(null);
47 2
    }
48
49 2
    public function configure()
50
    {
51 2
        $this->setName(self::NAME)
52 2
             ->setDescription(
53 2
                 $this->translator->translate('Generates a short code for provided URL and returns the short URL')
54
             )
55 2
             ->addArgument('longUrl', InputArgument::REQUIRED, $this->translator->translate('The long URL to parse'))
56 2
             ->addOption(
57 2
                 'tags',
58 2
                 't',
59 2
                 InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED,
60 2
                 $this->translator->translate('Tags to apply to the new short URL')
61
             )
62 2
             ->addOption('validSince', 's', InputOption::VALUE_REQUIRED, $this->translator->translate(
63
                 'The date from which this short URL will be valid. '
64 2
                 . 'If someone tries to access it before this date, it will not be found.'
65
             ))
66 2
             ->addOption('validUntil', 'u', InputOption::VALUE_REQUIRED, $this->translator->translate(
67
                 'The date until which this short URL will be valid. '
68 2
                 . 'If someone tries to access it after this date, it will not be found.'
69
             ))
70 2
             ->addOption('customSlug', 'c', InputOption::VALUE_REQUIRED, $this->translator->translate(
71 2
                 'If provided, this slug will be used instead of generating a short code'
72
             ))
73 2
             ->addOption('maxVisits', 'm', InputOption::VALUE_REQUIRED, $this->translator->translate(
74 2
                 'This will limit the number of visits for this short URL.'
75
             ));
76 2
    }
77
78 2
    public function interact(InputInterface $input, OutputInterface $output)
79
    {
80 2
        $io = new SymfonyStyle($input, $output);
81 2
        $longUrl = $input->getArgument('longUrl');
82 2
        if (! empty($longUrl)) {
83 2
            return;
84
        }
85
86
        $longUrl = $io->ask(
87
            $this->translator->translate('A long URL was not provided. Which URL do you want to be shortened?')
88
        );
89
        if (! empty($longUrl)) {
90
            $input->setArgument('longUrl', $longUrl);
91
        }
92
    }
93
94 2
    public function execute(InputInterface $input, OutputInterface $output)
95
    {
96 2
        $io = new SymfonyStyle($input, $output);
97 2
        $longUrl = $input->getArgument('longUrl');
98 2
        if (empty($longUrl)) {
99
            $io->error($this->translator->translate('A URL was not provided!'));
100
            return;
101
        }
102
103 2
        $tags = $input->getOption('tags');
104 2
        $processedTags = [];
105 2
        foreach ($tags as $key => $tag) {
106
            $explodedTags = \explode(',', $tag);
107
            $processedTags = \array_merge($processedTags, $explodedTags);
108
        }
109 2
        $tags = $processedTags;
110 2
        $customSlug = $input->getOption('customSlug');
111 2
        $maxVisits = $input->getOption('maxVisits');
112
113
        try {
114 2
            $shortCode = $this->urlShortener->urlToShortCode(
115 2
                new Uri($longUrl),
116 2
                $tags,
117 2
                $this->getOptionalDate($input, 'validSince'),
118 2
                $this->getOptionalDate($input, 'validUntil'),
119 2
                $customSlug,
120 2
                $maxVisits !== null ? (int) $maxVisits : null
121 1
            )->getShortCode();
122 1
            $shortUrl = $this->buildShortUrl($this->domainConfig, $shortCode);
123
124 1
            $io->writeln([
125 1
                \sprintf('%s <info>%s</info>', $this->translator->translate('Processed long URL:'), $longUrl),
126 1
                \sprintf('%s <info>%s</info>', $this->translator->translate('Generated short URL:'), $shortUrl),
127
            ]);
128 1
        } catch (InvalidUrlException $e) {
129 1
            $io->error(\sprintf(
130 1
                $this->translator->translate('Provided URL "%s" is invalid. Try with a different one.'),
131 1
                $longUrl
132
            ));
133
        } catch (NonUniqueSlugException $e) {
134
            $io->error(\sprintf(
135
                $this->translator->translate(
136
                    'Provided slug "%s" is already in use by another URL. Try with a different one.'
137
                ),
138
                $customSlug
139
            ));
140
        }
141 2
    }
142
143 2
    private function getOptionalDate(InputInterface $input, string $fieldName)
144
    {
145 2
        $since = $input->getOption($fieldName);
146 2
        return $since !== null ? new \DateTime($since) : null;
147
    }
148
}
149