diff --git a/bin/install b/bin/install
index 651ae8e3..b1ce8a1e 100755
--- a/bin/install
+++ b/bin/install
@@ -2,10 +2,13 @@
add(new InstallCommand());
+$app->add(new InstallCommand(new PhpArray()));
$app->setDefaultCommand('shlink:install');
$app->run();
diff --git a/module/CLI/src/Command/Install/InstallCommand.php b/module/CLI/src/Command/Install/InstallCommand.php
index b4b0d3e1..8d1c533e 100644
--- a/module/CLI/src/Command/Install/InstallCommand.php
+++ b/module/CLI/src/Command/Install/InstallCommand.php
@@ -1,14 +1,27 @@
'pdo_mysql',
+ 'PostgreSQL' => 'pdo_pgsql',
+ 'SQLite' => 'pdo_sqlite',
+ ];
+ const SUPPORTED_LANGUAGES = ['en', 'es'];
+
/**
* @var InputInterface
*/
@@ -17,6 +30,20 @@ class InstallCommand extends Command
* @var OutputInterface
*/
private $output;
+ /**
+ * @var QuestionHelper
+ */
+ private $questionHelper;
+ /**
+ * @var WriterInterface
+ */
+ private $configWriter;
+
+ public function __construct(WriterInterface $configWriter)
+ {
+ parent::__construct(null);
+ $this->configWriter = $configWriter;
+ }
public function configure()
{
@@ -28,6 +55,7 @@ class InstallCommand extends Command
{
$this->input = $input;
$this->output = $output;
+ $this->questionHelper = $this->getHelper('question');
$params = [];
$output->writeln([
@@ -35,32 +63,186 @@ class InstallCommand extends Command
'This will guide you through the installation process.',
]);
- $params['DB_NAME'] = $this->ask('Database name', 'shlink');
- $params['DB_USER'] = $this->ask('Database username');
- $params['DB_PASSWORD'] = $this->ask('Database password');
+ // Check if a cached config file exists and drop it if so
+ if (file_exists('data/cache/app_config.php')) {
+ $output->write('Deleting old cached config...');
+ if (unlink('data/cache/app_config.php')) {
+ $output->writeln(' Success');
+ } else {
+ $output->writeln(
+ ' Failed! You will have to manually delete the data/cache/app_config.php file to get'
+ . ' new config applied.'
+ );
+ }
+ }
+
+ // Ask for custom config params
+ $params['DATABASE'] = $this->askDatabase();
+ $params['URL_SHORTENER'] = $this->askUrlShortener();
+ $params['LANGUAGE'] = $this->askLanguage();
+ $params['APP'] = $this->askApplication();
+
+ // Generate config params files
+ $config = $this->buildAppConfig($params);
+ $this->configWriter->toFile('config/params/generated_config.php', $config);
+ $output->writeln('Custom configuration properly generated!');
+ }
+
+ protected function askDatabase()
+ {
+ $params = [];
+ $this->printTitle('DATABASE');
+
+ // Select database type
+ $databases = array_keys(self::DATABASE_DRIVERS);
+ $dbType = $this->questionHelper->ask($this->input, $this->output, new ChoiceQuestion(
+ 'Select database type (defaults to ' . $databases[0] . '):',
+ $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'] = $this->ask('Database name', 'shlink');
+ $params['USER'] = $this->ask('Database username');
+ $params['PASSWORD'] = $this->ask('Database password');
+ }
+
+ return $params;
+ }
+
+ protected function askUrlShortener()
+ {
+ $this->printTitle('URL SHORTENER');
+
+ // Ask for URL shortener params
+ return [
+ 'SCHEMA' => $this->questionHelper->ask($this->input, $this->output, new ChoiceQuestion(
+ 'Select schema for generated short URLs (defaults to http):',
+ ['http', 'https'],
+ 0
+ )),
+ 'HOSTNAME' => $this->ask('Hostname for generated URLs'),
+ 'CHARS' => $this->ask(
+ 'Character set for generated short codes (leave empty to autogenerate one)',
+ null,
+ true
+ ) ?: str_shuffle(UrlShortener::DEFAULT_CHARS)
+ ];
+ }
+
+ protected function askLanguage()
+ {
+ $this->printTitle('LANGUAGE');
+
+ return [
+ 'DEFAULT' => $this->questionHelper->ask($this->input, $this->output, new ChoiceQuestion(
+ 'Select default language for the application in general (defaults to '
+ . self::SUPPORTED_LANGUAGES[0] . '):',
+ self::SUPPORTED_LANGUAGES,
+ 0
+ )),
+ 'CLI' => $this->questionHelper->ask($this->input, $this->output, new ChoiceQuestion(
+ 'Select default language for CLI executions (defaults to '
+ . self::SUPPORTED_LANGUAGES[0] . '):',
+ self::SUPPORTED_LANGUAGES,
+ 0
+ )),
+ ];
+ }
+
+ protected function askApplication()
+ {
+ $this->printTitle('APPLICATION');
+
+ return [
+ 'SECRET' => $this->ask(
+ 'Define a secret string that will be used to sign API tokens (leave empty to autogenerate one)',
+ null,
+ true
+ ) ?: $this->generateRandomString(32),
+ ];
+ }
+
+ /**
+ * @param string $text
+ */
+ protected function printTitle($text)
+ {
+ $text = trim($text);
+ $length = strlen($text) + 4;
+ $header = str_repeat('*', $length);
+
+ $this->output->writeln([
+ '',
+ '' . $header . '',
+ '* ' . strtoupper($text) . ' *',
+ '' . $header . '',
+ ]);
}
/**
* @param string $text
* @param string|null $default
+ * @param bool $allowEmpty
* @return string
*/
- protected function ask($text, $default = null)
+ protected function ask($text, $default = null, $allowEmpty = false)
{
- /** @var QuestionHelper $questionHelper */
- $questionHelper = $this->getHelper('question');
-
if (isset($default)) {
$text .= ' (defaults to ' . $default . ')';
}
- $value = '';
- while (empty($value) && empty($default)) {
- $value = $questionHelper->ask($this->input, $this->output, new Question(
- ' ' . $text . ': ',
+ do {
+ $value = $this->questionHelper->ask($this->input, $this->output, new Question(
+ '' . $text . ': ',
$default
));
- }
+ if (empty($value) && ! $allowEmpty) {
+ $this->output->writeln('Value can\'t be empty');
+ }
+ } while (empty($value) && empty($default) && ! $allowEmpty);
return $value;
}
+
+ /**
+ * @param array $params
+ * @return array
+ */
+ protected function buildAppConfig(array $params)
+ {
+ // Build simple config
+ $config = [
+ 'app_options' => [
+ 'secret_key' => $params['APP']['SECRET'],
+ ],
+ 'entity_manager' => [
+ 'connection' => [
+ 'driver' => $params['DATABASE']['DRIVER'],
+ ],
+ ],
+ 'translator' => [
+ 'locale' => $params['LANGUAGE']['DEFAULT'],
+ ],
+ 'url_shortener' => [
+ 'domain' => [
+ 'schema' => $params['URL_SHORTENER']['SCHEMA'],
+ 'hostname' => $params['URL_SHORTENER']['HOSTNAME'],
+ ],
+ 'shortcode_chars' => $params['URL_SHORTENER']['CHARS'],
+ ],
+ ];
+
+ // Build dynamic database config
+ if ($params['DATABASE']['DRIVER'] === 'pdo_sqlite') {
+ $config['entity_manager']['connection']['path'] = 'data/database.sqlite';
+ } else {
+ $config['entity_manager']['connection']['user'] = $params['DATABASE']['USER'];
+ $config['entity_manager']['connection']['password'] = $params['DATABASE']['PASSWORD'];
+ $config['entity_manager']['connection']['dbname'] = $params['DATABASE']['NAME'];
+ }
+
+ return $config;
+ }
}
diff --git a/module/Rest/config/rest.config.php b/module/Rest/config/rest.config.php
deleted file mode 100644
index 223c864f..00000000
--- a/module/Rest/config/rest.config.php
+++ /dev/null
@@ -1,9 +0,0 @@
- [
- 'username' => env('REST_USER'),
- 'password' => env('REST_PASSWORD'),
- ],
-
-];