Completed
Pull Request — master (#227)
by Alejandro
03:30
created

ApplicationConfigCustomizer::process()   B

Complexity

Conditions 6
Paths 8

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 6

Importance

Changes 0
Metric Value
cc 6
nc 8
nop 2
dl 0
loc 20
ccs 12
cts 12
cp 1
crap 6
rs 8.9777
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace Shlinkio\Shlink\Installer\Config\Plugin;
5
6
use Shlinkio\Shlink\Common\Util\StringUtilsTrait;
7
use Shlinkio\Shlink\Installer\Exception\InvalidConfigOptionException;
8
use Shlinkio\Shlink\Installer\Model\CustomizableAppConfig;
9
use Symfony\Component\Console\Style\SymfonyStyle;
10
use function array_diff;
11
use function array_keys;
12
use function is_numeric;
13
use function sprintf;
14
15
class ApplicationConfigCustomizer implements ConfigCustomizerInterface
16
{
17
    use StringUtilsTrait;
18
19
    public const SECRET = 'SECRET';
20
    public const DISABLE_TRACK_PARAM = 'DISABLE_TRACK_PARAM';
21
    public const CHECK_VISITS_THRESHOLD = 'CHECK_VISITS_THRESHOLD';
22
    public const VISITS_THRESHOLD = 'VISITS_THRESHOLD';
23
    private const EXPECTED_KEYS = [
24
        self::SECRET,
25
        self::DISABLE_TRACK_PARAM,
26
        self::CHECK_VISITS_THRESHOLD,
27
        self::VISITS_THRESHOLD,
28
    ];
29
30 4
    public function process(SymfonyStyle $io, CustomizableAppConfig $appConfig): void
31
    {
32 4
        $app = $appConfig->getApp();
33 4
        $keysToAskFor = $appConfig->hasApp() ? array_diff(self::EXPECTED_KEYS, array_keys($app)) : self::EXPECTED_KEYS;
34
35 4
        if (empty($keysToAskFor)) {
36 1
            return;
37
        }
38
39 3
        $io->title('APPLICATION');
40 3
        foreach ($keysToAskFor as $key) {
41
            // Skip visits threshold when the user decided not to check visits on deletions
42 3
            if ($key === self::VISITS_THRESHOLD && ! $app[self::CHECK_VISITS_THRESHOLD]) {
43 1
                continue;
44
            }
45
46 3
            $app[$key] = $this->ask($io, $key);
47
        }
48 3
        $appConfig->setApp($app);
49 3
    }
50
51 3
    private function ask(SymfonyStyle $io, string $key)
52
    {
53
        switch ($key) {
54 3
            case self::SECRET:
55 2
                return $io->ask(
56
                    'Define a secret string that will be used to sign API tokens (leave empty to autogenerate one) '
57 2
                    . '<fg=red>[DEPRECATED. TO BE REMOVED]</>'
58 2
                ) ?: $this->generateRandomString(32);
59 3
            case self::DISABLE_TRACK_PARAM:
60 3
                return $io->ask(
61
                    'Provide a parameter name that you will be able to use to disable tracking on specific request to '
62 3
                    . 'short URLs (leave empty and this feature won\'t be enabled)'
63
                );
64 2
            case self::CHECK_VISITS_THRESHOLD:
65 2
                return $io->confirm(
66
                    'Do you want to enable a safety check which will not allow short URLs to be deleted when they '
67 2
                    . 'have more than a specific amount of visits?'
68
                );
69 1
            case self::VISITS_THRESHOLD:
70 1
                return $io->ask(
71 1
                    'What is the amount of visits from which the system will not allow short URLs to be deleted?',
72 1
                    15,
73 1
                    [$this, 'validateVisitsThreshold']
74
                );
75
        }
76
77
        return '';
78
    }
79
80 10
    public function validateVisitsThreshold($value): int
81
    {
82 10
        if (! is_numeric($value) || $value < 1) {
83 6
            throw new InvalidConfigOptionException(
84 6
                sprintf('Provided value "%s" is invalid. Expected a number greater than 1', $value)
85
            );
86
        }
87
88 4
        return (int) $value;
89
    }
90
}
91