Completed
Pull Request — master (#252)
by Alejandro
03:36 queued 01:06
created

DatabaseConfigCustomizer::importSqliteDbFile()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3.3332

Importance

Changes 0
Metric Value
cc 3
eloc 9
nc 3
nop 2
dl 0
loc 14
rs 9.9666
c 0
b 0
f 0
ccs 6
cts 9
cp 0.6667
crap 3.3332
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 Functional\contains;
14
15
class DatabaseConfigCustomizer implements ConfigCustomizerInterface
16
{
17
    use AskUtilsTrait;
18
19
    public const DRIVER = 'DRIVER';
20
    public const NAME = 'NAME';
21
    public const USER = 'USER';
22
    public const PASSWORD = 'PASSWORD';
23
    public const HOST = 'HOST';
24
    public 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 4
    public function __construct(Filesystem $filesystem)
47
    {
48 4
        $this->filesystem = $filesystem;
49
    }
50
51
    /**
52
     * @throws IOException
53
     */
54 4
    public function process(SymfonyStyle $io, CustomizableAppConfig $appConfig): void
55
    {
56 4
        $titlePrinted = false;
57 4
        $db = $appConfig->getDatabase();
58 4
        $doImport = $appConfig->hasDatabase();
59 4
        $keysToAskFor = $doImport ? array_diff(self::EXPECTED_KEYS, array_keys($db)) : self::EXPECTED_KEYS;
60
61
        // If the user selected to keep DB, try to import SQLite database
62 4
        if ($doImport) {
63 3
            $this->importSqliteDbFile($io, $appConfig);
64
        }
65
66 4
        if (empty($keysToAskFor)) {
67 1
            return;
68
        }
69
70
        // If the driver is one of the params to ask for, ask for it first
71 3
        if (contains($keysToAskFor, self::DRIVER)) {
72 1
            $io->title('DATABASE');
73 1
            $titlePrinted = true;
74 1
            $db[self::DRIVER] = $this->ask($io, self::DRIVER);
75 1
            $keysToAskFor = array_diff($keysToAskFor, [self::DRIVER]);
76
        }
77
78
        // If driver is SQLite, do not ask any driver-dependant option
79 3
        if ($db[self::DRIVER] === self::DATABASE_DRIVERS['SQLite']) {
80 1
            $keysToAskFor = array_diff($keysToAskFor, self::DRIVER_DEPENDANT_OPTIONS);
81
        }
82
83 3
        if (! $titlePrinted && ! empty($keysToAskFor)) {
84 1
            $io->title('DATABASE');
85
        }
86 3
        foreach ($keysToAskFor as $key) {
87 2
            $db[$key] = $this->ask($io, $key, $db);
88
        }
89 3
        $appConfig->setDatabase($db);
90
    }
91
92 3
    private function importSqliteDbFile(SymfonyStyle $io, CustomizableAppConfig $appConfig): void
93
    {
94 3
        if ($appConfig->getDatabase()[self::DRIVER] !== self::DATABASE_DRIVERS['SQLite']) {
95 2
            return;
96
        }
97
98
        try {
99 1
            $this->filesystem->copy(
100 1
                $appConfig->getImportedInstallationPath() . '/' . CustomizableAppConfig::SQLITE_DB_PATH,
101 1
                CustomizableAppConfig::SQLITE_DB_PATH
102
            );
103
        } catch (IOException $e) {
104
            $io->error('It wasn\'t possible to import the SQLite database');
105
            throw $e;
106
        }
107
    }
108
109 2
    private function ask(SymfonyStyle $io, string $key, array $params = [])
110
    {
111
        switch ($key) {
112 2
            case self::DRIVER:
113 1
                $databases = array_keys(self::DATABASE_DRIVERS);
114 1
                $dbType = $io->choice('Select database type', $databases, $databases[0]);
115 1
                return self::DATABASE_DRIVERS[$dbType];
116 2
            case self::NAME:
117 1
                return $io->ask('Database name', 'shlink');
118 2
            case self::USER:
119 2
                return $this->askRequired($io, 'username', 'Database username');
120 2
            case self::PASSWORD:
121 1
                return $this->askRequired($io, 'password', 'Database password');
122 2
            case self::HOST:
123 2
                return $io->ask('Database host', 'localhost');
124 2
            case self::PORT:
125 2
                return $io->ask('Database port', $this->getDefaultDbPort($params[self::DRIVER]));
126
        }
127
128
        return '';
129
    }
130
131 2
    private function getDefaultDbPort(string $driver): string
132
    {
133 2
        return $driver === 'pdo_mysql' ? '3306' : '5432';
134
    }
135
}
136