|
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
|
4 |
|
public function __construct(Filesystem $filesystem) |
|
47
|
|
|
{ |
|
48
|
4 |
|
$this->filesystem = $filesystem; |
|
49
|
4 |
|
} |
|
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(self::DRIVER, $keysToAskFor)) { |
|
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
|
3 |
|
} |
|
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
|
1 |
|
} |
|
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
|
|
|
|
Scrutinizer analyzes your
composer.json/composer.lockfile 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.