Completed
Pull Request — master (#224)
by Alejandro
03:34
created

DatabaseConfigCustomizer::ask()   B

Complexity

Conditions 7
Paths 7

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
nc 7
nop 3
dl 0
loc 21
rs 8.6506
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\Installer\Model\CustomizableAppConfig;
7
use Shlinkio\Shlink\Installer\Util\AskUtilsTrait;
8
use Symfony\Component\Console\Style\SymfonyStyle;
9
use Symfony\Component\Filesystem\Exception\IOException;
10
use Symfony\Component\Filesystem\Filesystem;
11
use function array_diff;
12
use function array_keys;
13
use function Shlinkio\Shlink\Common\contains;
14
15
class DatabaseConfigCustomizer implements ConfigCustomizerInterface
16
{
17
    use AskUtilsTrait;
18
19
    private const DRIVER = 'DRIVER';
20
    private const NAME = 'NAME';
21
    private const USER = 'USER';
22
    private const PASSWORD = 'PASSWORD';
23
    private const HOST = 'HOST';
24
    private const PORT = 'PORT';
25
    private const DRIVER_DEPENDANT_OPTIONS = [
26
        self::DRIVER,
27
        self::NAME,
28
        self::USER,
29
        self::PASSWORD,
30
        self::HOST,
31
        self::PORT,
32
    ];
33
    private const EXPECTED_KEYS = self::DRIVER_DEPENDANT_OPTIONS; // Same now, but could change in the future
34
35
    private const DATABASE_DRIVERS = [
36
        'MySQL' => 'pdo_mysql',
37
        'PostgreSQL' => 'pdo_pgsql',
38
        'SQLite' => 'pdo_sqlite',
39
    ];
40
41
    /**
42
     * @var Filesystem
43
     */
44
    private $filesystem;
45
46
    public function __construct(Filesystem $filesystem)
47
    {
48
        $this->filesystem = $filesystem;
49
    }
50
51
    /**
52
     * @throws IOException
53
     */
54
    public function process(SymfonyStyle $io, CustomizableAppConfig $appConfig): void
55
    {
56
        $io->title('DATABASE');
57
58
        $db = $appConfig->getDatabase();
59
        $doImport = $appConfig->hasDatabase() && $io->confirm('Do you want to keep imported database config?');
60
        $keysToAskFor = $doImport ? array_diff(self::EXPECTED_KEYS, array_keys($db)) : self::EXPECTED_KEYS;
61
62
        // If the user selected to keep DB, try to import SQLite database
63
        if ($doImport) {
64
            $this->importSqliteDbFile($io, $appConfig);
65
        }
66
67
        if (empty($keysToAskFor)) {
68
            return;
69
        }
70
71
        // If the driver is one of the params to ask for, ask for it first
72
        if (contains(self::DRIVER, $keysToAskFor)) {
73
            $db[self::DRIVER] = $this->ask($io, self::DRIVER);
74
            $keysToAskFor = array_diff($keysToAskFor, [self::DRIVER]);
75
        }
76
77
        // If driver is SQLite, do not ask any driver-dependant option
78
        if ($db[self::DRIVER] === self::DATABASE_DRIVERS['SQLite']) {
79
            $keysToAskFor = array_diff($keysToAskFor, self::DRIVER_DEPENDANT_OPTIONS);
80
        }
81
82
        // Iterate any remaining option and ask for it
83
        foreach ($keysToAskFor as $key) {
84
            $db[$key] = $this->ask($io, $key, $db);
85
        }
86
        $appConfig->setDatabase($db);
87
    }
88
89
    private function importSqliteDbFile(SymfonyStyle $io, CustomizableAppConfig $appConfig): void
90
    {
91
        if ($appConfig->getDatabase()[self::DRIVER] !== self::DATABASE_DRIVERS['SQLite']) {
92
            return;
93
        }
94
95
        try {
96
            $this->filesystem->copy(
97
                $appConfig->getImportedInstallationPath() . '/' . CustomizableAppConfig::SQLITE_DB_PATH,
98
                CustomizableAppConfig::SQLITE_DB_PATH
99
            );
100
        } catch (IOException $e) {
0 ignored issues
show
Bug introduced by
The class Symfony\Component\Filesystem\Exception\IOException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
101
            $io->error('It wasn\'t possible to import the SQLite database');
102
            throw $e;
103
        }
104
    }
105
106
    private function ask(SymfonyStyle $io, string $key, array $params = [])
107
    {
108
        switch ($key) {
109
            case self::DRIVER:
110
                $databases = array_keys(self::DATABASE_DRIVERS);
111
                $dbType = $io->choice('Select database type', $databases, $databases[0]);
112
                return self::DATABASE_DRIVERS[$dbType];
113
            case self::NAME:
114
                return $io->ask('Database name', 'shlink');
115
            case self::USER:
116
                return $this->askRequired($io, 'username', 'Database username');
117
            case self::PASSWORD:
118
                return $this->askRequired($io, 'password', 'Database password');
119
            case self::HOST:
120
                return $io->ask('Database host', 'localhost');
121
            case self::PORT:
122
                return $io->ask('Database port', $this->getDefaultDbPort($params[self::DRIVER]));
123
        }
124
125
        return '';
126
    }
127
128
    private function getDefaultDbPort(string $driver): string
129
    {
130
        return $driver === 'pdo_mysql' ? '3306' : '5432';
131
    }
132
}
133