Ensured required config options cannot be left empty

This commit is contained in:
Alejandro Celaya 2018-09-30 09:40:43 +02:00
parent 48f01921e1
commit 8323b87076
8 changed files with 83 additions and 22 deletions

View file

@ -19,20 +19,14 @@ class ApplicationConfigCustomizer implements ConfigCustomizerInterface
return;
}
$validator = function ($value) {
return $value;
};
$appConfig->setApp([
'SECRET' => $io->ask(
'Define a secret string that will be used to sign API tokens (leave empty to autogenerate one)',
null,
$validator
'Define a secret string that will be used to sign API tokens (leave empty to autogenerate one) '
. '<fg=red>[DEPRECATED. TO BE REMOVED]</>'
) ?: $this->generateRandomString(32),
'DISABLE_TRACK_PARAM' => $io->ask(
'Provide a parameter name that you will be able to use to disable tracking on specific request to '
. 'short URLs (leave empty and this feature won\'t be enabled)',
null,
$validator
. 'short URLs (leave empty and this feature won\'t be enabled)'
),
]);
}

View file

@ -4,12 +4,15 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\Installer\Config\Plugin;
use Shlinkio\Shlink\Installer\Model\CustomizableAppConfig;
use Shlinkio\Shlink\Installer\Util\AskUtilsTrait;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Filesystem\Exception\IOException;
use Symfony\Component\Filesystem\Filesystem;
class DatabaseConfigCustomizer implements ConfigCustomizerInterface
{
use AskUtilsTrait;
private const DATABASE_DRIVERS = [
'MySQL' => 'pdo_mysql',
'PostgreSQL' => 'pdo_pgsql',
@ -59,8 +62,8 @@ class DatabaseConfigCustomizer implements ConfigCustomizerInterface
// 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'] = $io->ask('Database username');
$params['PASSWORD'] = $io->ask('Database password');
$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']));
}

View file

@ -19,12 +19,12 @@ class LanguageConfigCustomizer implements ConfigCustomizerInterface
}
$appConfig->setLanguage([
'DEFAULT' => $this->chooseLanguage('Select default language for the application in general', $io),
'CLI' => $this->chooseLanguage('Select default language for CLI executions', $io),
'DEFAULT' => $this->chooseLanguage($io, 'Select default language for the application in general'),
'CLI' => $this->chooseLanguage($io, 'Select default language for CLI executions'),
]);
}
private function chooseLanguage(string $message, SymfonyStyle $io): string
private function chooseLanguage(SymfonyStyle $io, string $message): string
{
return $io->choice($message, self::SUPPORTED_LANGUAGES, self::SUPPORTED_LANGUAGES[0]);
}

View file

@ -5,11 +5,14 @@ namespace Shlinkio\Shlink\Installer\Config\Plugin;
use Shlinkio\Shlink\Core\Service\UrlShortener;
use Shlinkio\Shlink\Installer\Model\CustomizableAppConfig;
use Shlinkio\Shlink\Installer\Util\AskUtilsTrait;
use Symfony\Component\Console\Style\SymfonyStyle;
use function str_shuffle;
class UrlShortenerConfigCustomizer implements ConfigCustomizerInterface
{
use AskUtilsTrait;
public function process(SymfonyStyle $io, CustomizableAppConfig $appConfig): void
{
$io->title('URL SHORTENER');
@ -25,14 +28,9 @@ class UrlShortenerConfigCustomizer implements ConfigCustomizerInterface
['http', 'https'],
'http'
),
'HOSTNAME' => $io->ask('Hostname for generated URLs'),
'CHARS' => $io->ask(
'Character set for generated short codes (leave empty to autogenerate one)',
null,
function ($value) {
return $value;
}
) ?: str_shuffle(UrlShortener::DEFAULT_CHARS),
'HOSTNAME' => $this->askRequired($io, 'hostname', 'Hostname for generated URLs'),
'CHARS' => $io->ask('Character set for generated short codes (leave empty to autogenerate one)')
?: str_shuffle(UrlShortener::DEFAULT_CHARS),
'VALIDATE_URL' => $io->confirm('Do you want to validate long urls by 200 HTTP status code on response'),
]);
}

View file

@ -0,0 +1,10 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\Installer\Exception;
use Throwable;
interface ExceptionInterface extends Throwable
{
}

View file

@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\Installer\Exception;
use RuntimeException;
use function sprintf;
class MissingRequiredOptionException extends RuntimeException implements ExceptionInterface
{
public static function fromOption(string $optionName): self
{
return new self(sprintf('The "%s" is required and can\'t be empty', $optionName));
}
}

View file

@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\Installer\Util;
use Shlinkio\Shlink\Installer\Exception\MissingRequiredOptionException;
use Symfony\Component\Console\Style\SymfonyStyle;
trait AskUtilsTrait
{
/**
* @return mixed
*/
private function askRequired(SymfonyStyle $io, string $optionName, string $question)
{
return $io->ask($question, null, function ($value) use ($optionName) {
if (empty($value)) {
throw MissingRequiredOptionException::fromOption($optionName);
};
});
}
}

View file

@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
namespace ShlinkioTest\Shlink\Installer\Exception;
use Shlinkio\Shlink\Installer\Exception\MissingRequiredOptionException;
use PHPUnit\Framework\TestCase;
class MissingRequiredOptionExceptionTest extends TestCase
{
/**
* @test
*/
public function fromOptionsGeneratesExpectedMessage()
{
$e = MissingRequiredOptionException::fromOption('foo');
$this->assertEquals('The "foo" is required and can\'t be empty', $e->getMessage());
}
}