From ebf2e459e858ba9219d9fd2f32d8261fd4dc25ed Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Fri, 5 Oct 2018 18:43:39 +0200 Subject: [PATCH] Refactored Databa config customizer so that it uses new structure --- module/Common/functions/functions.php | 5 + .../Installer/src/Command/InstallCommand.php | 2 +- .../Plugin/DatabaseConfigCustomizer.php | 107 +++++++++++++----- .../Plugin/LanguageConfigCustomizer.php | 3 +- .../Plugin/UrlShortenerConfigCustomizer.php | 4 +- 5 files changed, 90 insertions(+), 31 deletions(-) diff --git a/module/Common/functions/functions.php b/module/Common/functions/functions.php index 8e99dd96..1a5e58c2 100644 --- a/module/Common/functions/functions.php +++ b/module/Common/functions/functions.php @@ -40,3 +40,8 @@ function env($key, $default = null) return trim($value); } + +function contains($needle, array $haystack) +{ + return \in_array($needle, $haystack, true); +} diff --git a/module/Installer/src/Command/InstallCommand.php b/module/Installer/src/Command/InstallCommand.php index 9383fee2..a08b6eeb 100644 --- a/module/Installer/src/Command/InstallCommand.php +++ b/module/Installer/src/Command/InstallCommand.php @@ -146,7 +146,7 @@ class InstallCommand extends Command $this->io->writeln(['Custom configuration properly generated!', '']); // If current command is not update, generate database - if (! $this->isUpdate) { + if (! $this->isUpdate) { $this->io->write('Initializing database...'); if (! $this->runPhpCommand( 'vendor/doctrine/orm/bin/doctrine.php orm:schema-tool:create', diff --git a/module/Installer/src/Config/Plugin/DatabaseConfigCustomizer.php b/module/Installer/src/Config/Plugin/DatabaseConfigCustomizer.php index 3868dc74..410ea912 100644 --- a/module/Installer/src/Config/Plugin/DatabaseConfigCustomizer.php +++ b/module/Installer/src/Config/Plugin/DatabaseConfigCustomizer.php @@ -8,12 +8,30 @@ use Shlinkio\Shlink\Installer\Util\AskUtilsTrait; use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Filesystem\Exception\IOException; use Symfony\Component\Filesystem\Filesystem; +use function array_diff; use function array_keys; +use function Shlinkio\Shlink\Common\contains; class DatabaseConfigCustomizer implements ConfigCustomizerInterface { use AskUtilsTrait; + private const DRIVER = 'DRIVER'; + private const NAME = 'NAME'; + private const USER = 'USER'; + private const PASSWORD = 'PASSWORD'; + private const HOST = 'HOST'; + private const PORT = 'PORT'; + private const DRIVER_DEPENDANT_OPTIONS = [ + self::DRIVER, + self::NAME, + self::USER, + self::PASSWORD, + self::HOST, + self::PORT, + ]; + private const EXPECTED_KEYS = self::DRIVER_DEPENDANT_OPTIONS; // Same now, but could change in the future + private const DATABASE_DRIVERS = [ 'MySQL' => 'pdo_mysql', 'PostgreSQL' => 'pdo_pgsql', @@ -37,39 +55,74 @@ class DatabaseConfigCustomizer implements ConfigCustomizerInterface { $io->title('DATABASE'); - if ($appConfig->hasDatabase() && $io->confirm('Do you want to keep imported database config?')) { - // If the user selected to keep DB config and is configured to use sqlite, copy DB file - if ($appConfig->getDatabase()['DRIVER'] === self::DATABASE_DRIVERS['SQLite']) { - try { - $this->filesystem->copy( - $appConfig->getImportedInstallationPath() . '/' . CustomizableAppConfig::SQLITE_DB_PATH, - CustomizableAppConfig::SQLITE_DB_PATH - ); - } catch (IOException $e) { - $io->error('It wasn\'t possible to import the SQLite database'); - throw $e; - } - } + $db = $appConfig->getDatabase(); + $doImport = $appConfig->hasDatabase() && $io->confirm('Do you want to keep imported database config?'); + $keysToAskFor = $doImport ? array_diff(self::EXPECTED_KEYS, array_keys($db)) : self::EXPECTED_KEYS; + // If the user selected to keep DB, try to import SQLite database + if ($doImport) { + $this->importSqliteDbFile($io, $appConfig); + } + + if (empty($keysToAskFor)) { return; } - // Select database type - $params = []; - $databases = array_keys(self::DATABASE_DRIVERS); - $dbType = $io->choice('Select database type', $databases, $databases[0]); - $params['DRIVER'] = self::DATABASE_DRIVERS[$dbType]; - - // Ask for connection params if database is not SQLite - if ($params['DRIVER'] !== self::DATABASE_DRIVERS['SQLite']) { - $params['NAME'] = $io->ask('Database name', 'shlink'); - $params['USER'] = $this->askRequired($io, 'username', 'Database username'); - $params['PASSWORD'] = $this->askRequired($io, 'password', 'Database password'); - $params['HOST'] = $io->ask('Database host', 'localhost'); - $params['PORT'] = $io->ask('Database port', $this->getDefaultDbPort($params['DRIVER'])); + // If the driver is one of the params to ask for, ask for it first + if (contains(self::DRIVER, $keysToAskFor)) { + $db[self::DRIVER] = $this->ask($io, self::DRIVER); + $keysToAskFor = array_diff($keysToAskFor, [self::DRIVER]); } - $appConfig->setDatabase($params); + // If driver is SQLite, do not ask any driver-dependant option + if ($db[self::DRIVER] === self::DATABASE_DRIVERS['SQLite']) { + $keysToAskFor = array_diff($keysToAskFor, self::DRIVER_DEPENDANT_OPTIONS); + } + + // Iterate any remaining option and ask for it + foreach ($keysToAskFor as $key) { + $db[$key] = $this->ask($io, $key, $db); + } + $appConfig->setDatabase($db); + } + + private function importSqliteDbFile(SymfonyStyle $io, CustomizableAppConfig $appConfig): void + { + if ($appConfig->getDatabase()[self::DRIVER] !== self::DATABASE_DRIVERS['SQLite']) { + return; + } + + try { + $this->filesystem->copy( + $appConfig->getImportedInstallationPath() . '/' . CustomizableAppConfig::SQLITE_DB_PATH, + CustomizableAppConfig::SQLITE_DB_PATH + ); + } catch (IOException $e) { + $io->error('It wasn\'t possible to import the SQLite database'); + throw $e; + } + } + + private function ask(SymfonyStyle $io, string $key, array $params = []) + { + switch ($key) { + case self::DRIVER: + $databases = array_keys(self::DATABASE_DRIVERS); + $dbType = $io->choice('Select database type', $databases, $databases[0]); + return self::DATABASE_DRIVERS[$dbType]; + case self::NAME: + return $io->ask('Database name', 'shlink'); + case self::USER: + return $this->askRequired($io, 'username', 'Database username'); + case self::PASSWORD: + return $this->askRequired($io, 'password', 'Database password'); + case self::HOST: + return $io->ask('Database host', 'localhost'); + case self::PORT: + return $io->ask('Database port', $this->getDefaultDbPort($params[self::DRIVER])); + } + + return ''; } private function getDefaultDbPort(string $driver): string diff --git a/module/Installer/src/Config/Plugin/LanguageConfigCustomizer.php b/module/Installer/src/Config/Plugin/LanguageConfigCustomizer.php index 429f3b9e..2f291a2e 100644 --- a/module/Installer/src/Config/Plugin/LanguageConfigCustomizer.php +++ b/module/Installer/src/Config/Plugin/LanguageConfigCustomizer.php @@ -10,7 +10,6 @@ use function array_keys; class LanguageConfigCustomizer implements ConfigCustomizerInterface { - private const SUPPORTED_LANGUAGES = ['en', 'es']; private const DEFAULT_LANG = 'DEFAULT'; private const CLI_LANG = 'CLI'; private const EXPECTED_KEYS = [ @@ -18,6 +17,8 @@ class LanguageConfigCustomizer implements ConfigCustomizerInterface self::CLI_LANG, ]; + private const SUPPORTED_LANGUAGES = ['en', 'es']; + public function process(SymfonyStyle $io, CustomizableAppConfig $appConfig): void { $io->title('LANGUAGE'); diff --git a/module/Installer/src/Config/Plugin/UrlShortenerConfigCustomizer.php b/module/Installer/src/Config/Plugin/UrlShortenerConfigCustomizer.php index e54bcdfb..119eae83 100644 --- a/module/Installer/src/Config/Plugin/UrlShortenerConfigCustomizer.php +++ b/module/Installer/src/Config/Plugin/UrlShortenerConfigCustomizer.php @@ -31,8 +31,8 @@ class UrlShortenerConfigCustomizer implements ConfigCustomizerInterface $io->title('URL SHORTENER'); $urlShortener = $appConfig->getUrlShortener(); - $diffKeys = $appConfig->hasUrlShortener() && $io->confirm('Do you want to keep imported URL shortener config?'); - $keysToAskFor = $diffKeys ? array_diff(self::EXPECTED_KEYS, array_keys($urlShortener)) : self::EXPECTED_KEYS; + $doImport = $appConfig->hasUrlShortener() && $io->confirm('Do you want to keep imported URL shortener config?'); + $keysToAskFor = $doImport ? array_diff(self::EXPECTED_KEYS, array_keys($urlShortener)) : self::EXPECTED_KEYS; if (empty($keysToAskFor)) { return;