diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 10ec1df..345cba3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,5 +10,7 @@ on: jobs: ci: uses: shlinkio/github-actions/.github/workflows/php-lib-ci.yml@main + with: + with-php-eight: false secrets: INFECTION_BADGE_API_KEY: ${{ secrets.INFECTION_BADGE_API_KEY }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 5966263..c604c0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this * *Nothing* ### Removed -* *Nothing* +* [#161](https://github.com/shlinkio/shlink-installer/issues/161) Dropped support for PHP 8.0 ### Fixed * *Nothing* diff --git a/composer.json b/composer.json index 87fa040..b174638 100644 --- a/composer.json +++ b/composer.json @@ -12,26 +12,26 @@ } ], "require": { - "php": "^8.0", + "php": "^8.1", "laminas/laminas-config": "^3.7", - "laminas/laminas-config-aggregator": "^1.7", - "laminas/laminas-servicemanager": "^3.11.2", - "laminas/laminas-stdlib": "^3.7", + "laminas/laminas-config-aggregator": "^1.8", + "laminas/laminas-servicemanager": "^3.16", + "laminas/laminas-stdlib": "^3.11", "lstrojny/functional-php": "^1.17", "shlinkio/shlink-config": "^1.6", - "symfony/console": "^6.0", - "symfony/filesystem": "^6.0", - "symfony/process": "^6.0" + "symfony/console": "^6.1", + "symfony/filesystem": "^6.1", + "symfony/process": "^6.1" }, "require-dev": { "devster/ubench": "^2.0", "infection/infection": "^0.26", "phpspec/prophecy-phpunit": "^2.0", - "phpstan/phpstan": "^1.5", + "phpstan/phpstan": "^1.8", "phpunit/phpunit": "^9.5", "roave/security-advisories": "dev-master", "shlinkio/php-coding-standard": "~2.3.0", - "symfony/var-dumper": "^6.0" + "symfony/var-dumper": "^6.1" }, "autoload": { "psr-4": { diff --git a/config/config.local.php.dist b/config/config.local.php.dist index 4b1f5cd..0cf21d5 100644 --- a/config/config.local.php.dist +++ b/config/config.local.php.dist @@ -9,16 +9,16 @@ return [ 'installer' => [ 'installation_commands' => [ - InstallationCommand::DB_CREATE_SCHEMA => [ + InstallationCommand::DB_CREATE_SCHEMA->value => [ 'command' => '-v', // Just print PHP version ], - InstallationCommand::DB_MIGRATE => [ + InstallationCommand::DB_MIGRATE->value => [ 'command' => null, // Skip ], - InstallationCommand::ORM_PROXIES => [ + InstallationCommand::ORM_PROXIES->value => [ 'command' => '-v', // Just print PHP version ], - InstallationCommand::ORM_CLEAR_CACHE => [ + InstallationCommand::ORM_CLEAR_CACHE->value => [ 'command' => '-v', // Just print PHP version ], ], diff --git a/config/config.php b/config/config.php index 0bf9884..fde54db 100644 --- a/config/config.php +++ b/config/config.php @@ -222,31 +222,31 @@ 'enabled_options' => null, 'installation_commands' => [ - InstallationCommand::DB_CREATE_SCHEMA => [ + InstallationCommand::DB_CREATE_SCHEMA->value => [ 'command' => 'vendor/doctrine/orm/bin/doctrine.php orm:schema-tool:create', 'initMessage' => 'Initializing database...', 'errorMessage' => 'Error generating database.', 'failOnError' => true, ], - InstallationCommand::DB_MIGRATE => [ + InstallationCommand::DB_MIGRATE->value => [ 'command' => 'vendor/doctrine/migrations/bin/doctrine-migrations.php migrations:migrate', 'initMessage' => 'Updating database...', 'errorMessage' => 'Error updating database.', 'failOnError' => true, ], - InstallationCommand::ORM_PROXIES => [ + InstallationCommand::ORM_PROXIES->value => [ 'command' => 'vendor/doctrine/orm/bin/doctrine.php orm:generate-proxies', 'initMessage' => 'Generating proxies...', 'errorMessage' => 'Error generating proxies.', 'failOnError' => true, ], - InstallationCommand::ORM_CLEAR_CACHE => [ + InstallationCommand::ORM_CLEAR_CACHE->value => [ 'command' => 'vendor/doctrine/orm/bin/doctrine.php orm:clear-cache:metadata', 'initMessage' => 'Clearing entities cache...', 'errorMessage' => 'Error clearing entities cache.', 'failOnError' => false, ], - InstallationCommand::GEOLITE_DOWNLOAD_DB => [ + InstallationCommand::GEOLITE_DOWNLOAD_DB->value => [ 'command' => null, // Disabled by default, to avoid dependency on consumer (Shlink) 'initMessage' => 'Downloading GeoLite2 db file...', 'errorMessage' => 'Error downloading GeoLite2 db.', diff --git a/src/Command/AbstractInstallCommand.php b/src/Command/AbstractInstallCommand.php index bccd242..d054367 100644 --- a/src/Command/AbstractInstallCommand.php +++ b/src/Command/AbstractInstallCommand.php @@ -44,9 +44,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int $importedConfig = $this->resolvePreviousConfig($io); if ($this->isUpdate()) { - $this->assetsHandler->importShlinkAssetsFromPath($io, $importedConfig->importPath()); + $this->assetsHandler->importShlinkAssetsFromPath($io, $importedConfig->importPath); } - $config = $this->configGenerator->generateConfigInteractively($io, $importedConfig->importedConfig()); + $config = $this->configGenerator->generateConfigInteractively($io, $importedConfig->importedConfig); $configArray = Utils::normalizeAndKeepEnvVarKeys($config->toArray()); // Generate config params files @@ -77,7 +77,10 @@ private function execPostInstallCommands(SymfonyStyle $io): bool ? InstallationCommand::POST_UPDATE_COMMANDS : InstallationCommand::POST_INSTALL_COMMANDS; - return every($commands, fn (string $commandName) => $this->commandsRunner->execPhpCommand($commandName, $io)); + return every( + $commands, + fn (InstallationCommand $command) => $this->commandsRunner->execPhpCommand($command->value, $io), + ); } abstract protected function isUpdate(): bool; diff --git a/src/Config/Option/Database/AbstractNonSqliteDependentConfigOption.php b/src/Config/Option/Database/AbstractNonSqliteDependentConfigOption.php index 0646436..6b06949 100644 --- a/src/Config/Option/Database/AbstractNonSqliteDependentConfigOption.php +++ b/src/Config/Option/Database/AbstractNonSqliteDependentConfigOption.php @@ -4,6 +4,8 @@ namespace Shlinkio\Shlink\Installer\Config\Option\Database; +use Shlinkio\Shlink\Installer\Config\Util\DatabaseDriver; + use function str_contains; abstract class AbstractNonSqliteDependentConfigOption extends AbstractDriverDependentConfigOption @@ -11,8 +13,8 @@ abstract class AbstractNonSqliteDependentConfigOption extends AbstractDriverDepe protected function shouldBeAskedForDbDriver(string $dbDriver): bool { // DEPRECATED. - // Should just compare with strict equality ($dbDriver === DatabaseDriverConfigOption::SQLITE_DRIVER) + // Should just compare with strict equality (DatabaseDriver::tryFrom($dbDriver) === DatabaseDriver::SQLITE) // Using str_contains instead for backwards compatibility when importing the pdo_sqlite value - return ! str_contains($dbDriver, DatabaseDriverConfigOption::SQLITE_DRIVER); + return ! str_contains($dbDriver, DatabaseDriver::SQLITE->value); } } diff --git a/src/Config/Option/Database/DatabaseDriverConfigOption.php b/src/Config/Option/Database/DatabaseDriverConfigOption.php index a56e65c..fbfdd25 100644 --- a/src/Config/Option/Database/DatabaseDriverConfigOption.php +++ b/src/Config/Option/Database/DatabaseDriverConfigOption.php @@ -6,6 +6,7 @@ use Shlinkio\Shlink\Config\Collection\PathCollection; use Shlinkio\Shlink\Installer\Config\Option\BaseConfigOption; +use Shlinkio\Shlink\Installer\Config\Util\DatabaseDriver; use Symfony\Component\Console\Style\StyleInterface; use function array_keys; @@ -14,16 +15,12 @@ class DatabaseDriverConfigOption extends BaseConfigOption { public const ENV_VAR = 'DB_DRIVER'; public const CONFIG_PATH = [self::ENV_VAR]; - public const MYSQL_DRIVER = 'mysql'; - public const POSTGRES_DRIVER = 'postgres'; - public const SQLITE_DRIVER = 'sqlite'; - public const MSSQL_DRIVER = 'mssql'; private const DATABASE_DRIVERS = [ - 'MySQL' => self::MYSQL_DRIVER, - 'MariaDB' => self::MYSQL_DRIVER, - 'PostgreSQL' => self::POSTGRES_DRIVER, - 'MicrosoftSQL' => self::MSSQL_DRIVER, - 'SQLite' => self::SQLITE_DRIVER, + 'MySQL' => DatabaseDriver::MYSQL, + 'MariaDB' => DatabaseDriver::MYSQL, + 'PostgreSQL' => DatabaseDriver::POSTGRES, + 'MicrosoftSQL' => DatabaseDriver::MSSQL, + 'SQLite' => DatabaseDriver::SQLITE, ]; public function getDeprecatedPath(): array @@ -40,6 +37,6 @@ public function ask(StyleInterface $io, PathCollection $currentOptions): string { $databases = array_keys(self::DATABASE_DRIVERS); $dbType = $io->choice('Select database type', $databases, $databases[0]); - return self::DATABASE_DRIVERS[$dbType]; + return self::DATABASE_DRIVERS[$dbType]->value; } } diff --git a/src/Config/Option/Database/DatabaseHostConfigOption.php b/src/Config/Option/Database/DatabaseHostConfigOption.php index c5dfc4c..0efe99e 100644 --- a/src/Config/Option/Database/DatabaseHostConfigOption.php +++ b/src/Config/Option/Database/DatabaseHostConfigOption.php @@ -5,6 +5,7 @@ namespace Shlinkio\Shlink\Installer\Config\Option\Database; use Shlinkio\Shlink\Config\Collection\PathCollection; +use Shlinkio\Shlink\Installer\Config\Util\DatabaseDriver; use Symfony\Component\Console\Style\StyleInterface; class DatabaseHostConfigOption extends AbstractNonSqliteDependentConfigOption @@ -22,7 +23,7 @@ public function getEnvVar(): string public function ask(StyleInterface $io, PathCollection $currentOptions): string { $dbDriver = $currentOptions->getValueInPath(DatabaseDriverConfigOption::CONFIG_PATH); - $extra = $dbDriver === DatabaseDriverConfigOption::POSTGRES_DRIVER ? ' (or unix socket)' : ''; + $extra = DatabaseDriver::tryFrom($dbDriver) === DatabaseDriver::POSTGRES ? ' (or unix socket)' : ''; return $io->ask('Database host' . $extra, 'localhost'); } diff --git a/src/Config/Option/Database/DatabasePortConfigOption.php b/src/Config/Option/Database/DatabasePortConfigOption.php index 62ddc48..7d0daaa 100644 --- a/src/Config/Option/Database/DatabasePortConfigOption.php +++ b/src/Config/Option/Database/DatabasePortConfigOption.php @@ -5,16 +5,11 @@ namespace Shlinkio\Shlink\Installer\Config\Option\Database; use Shlinkio\Shlink\Config\Collection\PathCollection; +use Shlinkio\Shlink\Installer\Config\Util\DatabaseDriver; use Symfony\Component\Console\Style\StyleInterface; class DatabasePortConfigOption extends AbstractNonSqliteDependentConfigOption { - private const DRIVER_PORT_MAPPING = [ - DatabaseDriverConfigOption::MYSQL_DRIVER => '3306', - DatabaseDriverConfigOption::POSTGRES_DRIVER => '5432', - DatabaseDriverConfigOption::MSSQL_DRIVER => '1433', - ]; - public function getDeprecatedPath(): array { return ['entity_manager', 'connection', 'port']; @@ -34,6 +29,6 @@ public function ask(StyleInterface $io, PathCollection $currentOptions): string private function getDefaultDbPortForDriver(string $driver): string { - return self::DRIVER_PORT_MAPPING[$driver] ?? ''; + return DatabaseDriver::tryFrom($driver)?->defaultPort() ?? ''; } } diff --git a/src/Config/Option/Database/DatabaseUnixSocketConfigOption.php b/src/Config/Option/Database/DatabaseUnixSocketConfigOption.php index 25c86fc..e4eb0b9 100644 --- a/src/Config/Option/Database/DatabaseUnixSocketConfigOption.php +++ b/src/Config/Option/Database/DatabaseUnixSocketConfigOption.php @@ -5,6 +5,7 @@ namespace Shlinkio\Shlink\Installer\Config\Option\Database; use Shlinkio\Shlink\Config\Collection\PathCollection; +use Shlinkio\Shlink\Installer\Config\Util\DatabaseDriver; use Symfony\Component\Console\Style\StyleInterface; class DatabaseUnixSocketConfigOption extends AbstractDriverDependentConfigOption @@ -26,6 +27,6 @@ public function ask(StyleInterface $io, PathCollection $currentOptions): ?string protected function shouldBeAskedForDbDriver(string $dbDriver): bool { - return $dbDriver === DatabaseDriverConfigOption::MYSQL_DRIVER; + return DatabaseDriver::tryFrom($dbDriver) === DatabaseDriver::MYSQL; } } diff --git a/src/Config/Util/DatabaseDriver.php b/src/Config/Util/DatabaseDriver.php new file mode 100644 index 0000000..1c96e22 --- /dev/null +++ b/src/Config/Util/DatabaseDriver.php @@ -0,0 +1,23 @@ + '3306', + self::POSTGRES => '5432', + self::MSSQL => '1433', + self::SQLITE => null, + }; + } +} diff --git a/src/Model/ImportedConfig.php b/src/Model/ImportedConfig.php index 53dba7c..5f33e1c 100644 --- a/src/Model/ImportedConfig.php +++ b/src/Model/ImportedConfig.php @@ -6,7 +6,7 @@ final class ImportedConfig { - private function __construct(private string $importPath, private array $importedConfig) + private function __construct(public readonly string $importPath, public readonly array $importedConfig) { } @@ -19,14 +19,4 @@ public static function imported(string $importPath, array $importedConfig): self { return new self($importPath, $importedConfig); } - - public function importPath(): string - { - return $this->importPath; - } - - public function importedConfig(): array - { - return $this->importedConfig; - } } diff --git a/src/Util/InstallationCommand.php b/src/Util/InstallationCommand.php index 952023b..b5a1ab9 100644 --- a/src/Util/InstallationCommand.php +++ b/src/Util/InstallationCommand.php @@ -4,13 +4,13 @@ namespace Shlinkio\Shlink\Installer\Util; -final class InstallationCommand +enum InstallationCommand: string { - public const DB_CREATE_SCHEMA = 'db_create_schema'; - public const DB_MIGRATE = 'db_migrate'; - public const ORM_PROXIES = 'orm_proxies'; - public const ORM_CLEAR_CACHE = 'orm_clear_cache'; - public const GEOLITE_DOWNLOAD_DB = 'geolite_download_db'; + case DB_CREATE_SCHEMA = 'db_create_schema'; + case DB_MIGRATE = 'db_migrate'; + case ORM_PROXIES = 'orm_proxies'; + case ORM_CLEAR_CACHE = 'orm_clear_cache'; + case GEOLITE_DOWNLOAD_DB = 'geolite_download_db'; public const POST_INSTALL_COMMANDS = [ self::DB_CREATE_SCHEMA, diff --git a/test/Command/InstallCommandTest.php b/test/Command/InstallCommandTest.php index 94bae1f..06f246f 100644 --- a/test/Command/InstallCommandTest.php +++ b/test/Command/InstallCommandTest.php @@ -22,6 +22,7 @@ use Symfony\Component\Process\PhpExecutableFinder; use function count; +use function Functional\map; class InstallCommandTest extends TestCase { @@ -65,10 +66,12 @@ public function setUp(): void public function commandIsExecutedAsExpected(): void { $execPhpCommand = $this->commandsRunner->execPhpCommand( - Argument::that(function (string $command) { - Assert::assertContains($command, InstallationCommand::POST_INSTALL_COMMANDS); - - return $command; + Argument::that(function (string $commandName) { + Assert::assertContains($commandName, map( + InstallationCommand::POST_INSTALL_COMMANDS, + fn (InstallationCommand $command) => $command->value, + )); + return true; }), Argument::cetera(), )->willReturn(true); diff --git a/test/Command/UpdateCommandTest.php b/test/Command/UpdateCommandTest.php index 6c5a4fa..5126008 100644 --- a/test/Command/UpdateCommandTest.php +++ b/test/Command/UpdateCommandTest.php @@ -22,6 +22,7 @@ use Symfony\Component\Process\PhpExecutableFinder; use function count; +use function Functional\map; class UpdateCommandTest extends TestCase { @@ -65,10 +66,12 @@ public function setUp(): void public function commandIsExecutedAsExpected(): void { $execPhpCommand = $this->commandsRunner->execPhpCommand( - Argument::that(function (string $command) { - Assert::assertContains($command, InstallationCommand::POST_UPDATE_COMMANDS); - - return $command; + Argument::that(function (string $commandName) { + Assert::assertContains($commandName, map( + InstallationCommand::POST_UPDATE_COMMANDS, + fn (InstallationCommand $command) => $command->value, + )); + return true; }), Argument::cetera(), )->willReturn(true); diff --git a/test/Config/Option/Database/DatabaseDriverConfigOptionTest.php b/test/Config/Option/Database/DatabaseDriverConfigOptionTest.php index 97158b5..a0fabf2 100644 --- a/test/Config/Option/Database/DatabaseDriverConfigOptionTest.php +++ b/test/Config/Option/Database/DatabaseDriverConfigOptionTest.php @@ -8,6 +8,7 @@ use Prophecy\PhpUnit\ProphecyTrait; use Shlinkio\Shlink\Config\Collection\PathCollection; use Shlinkio\Shlink\Installer\Config\Option\Database\DatabaseDriverConfigOption; +use Shlinkio\Shlink\Installer\Config\Util\DatabaseDriver; use Symfony\Component\Console\Style\StyleInterface; class DatabaseDriverConfigOptionTest extends TestCase @@ -31,7 +32,7 @@ public function returnsExpectedConfig(): void /** @test */ public function expectedQuestionIsAsked(): void { - $expectedAnswer = DatabaseDriverConfigOption::SQLITE_DRIVER; + $expectedAnswer = DatabaseDriver::SQLITE->value; $io = $this->prophesize(StyleInterface::class); $choice = $io->choice( 'Select database type', diff --git a/test/Config/Option/Database/DatabaseHostConfigOptionTest.php b/test/Config/Option/Database/DatabaseHostConfigOptionTest.php index c33d4a6..855a63c 100644 --- a/test/Config/Option/Database/DatabaseHostConfigOptionTest.php +++ b/test/Config/Option/Database/DatabaseHostConfigOptionTest.php @@ -9,6 +9,7 @@ use Shlinkio\Shlink\Config\Collection\PathCollection; use Shlinkio\Shlink\Installer\Config\Option\Database\DatabaseDriverConfigOption; use Shlinkio\Shlink\Installer\Config\Option\Database\DatabaseHostConfigOption; +use Shlinkio\Shlink\Installer\Config\Util\DatabaseDriver; use Symfony\Component\Console\Style\StyleInterface; class DatabaseHostConfigOptionTest extends TestCase @@ -50,12 +51,9 @@ public function expectedQuestionIsAsked(string $driver, string $expectedQuestion public function provideDrivers(): iterable { - yield 'mysql' => [DatabaseDriverConfigOption::MYSQL_DRIVER, 'Database host']; - yield 'mssql' => [DatabaseDriverConfigOption::MSSQL_DRIVER, 'Database host']; - yield 'postgres' => [ - DatabaseDriverConfigOption::POSTGRES_DRIVER, - 'Database host (or unix socket)', - ]; + yield 'mysql' => [DatabaseDriver::MYSQL->value, 'Database host']; + yield 'mssql' => [DatabaseDriver::MSSQL->value, 'Database host']; + yield 'postgres' => [DatabaseDriver::POSTGRES->value, 'Database host (or unix socket)']; } /** @test */ @@ -85,11 +83,11 @@ public function provideCurrentOptions(): iterable return $collection; }; - yield 'sqlite' => [$buildCollection(DatabaseDriverConfigOption::SQLITE_DRIVER), false]; + yield 'sqlite' => [$buildCollection(DatabaseDriver::SQLITE->value), false]; yield 'old sqlite' => [$buildCollection('pdo_sqlite'), false]; - yield 'mysql' => [$buildCollection(DatabaseDriverConfigOption::MYSQL_DRIVER), true]; - yield 'postgres' => [$buildCollection(DatabaseDriverConfigOption::POSTGRES_DRIVER), true]; - yield 'mysql with value' => [$buildCollection(DatabaseDriverConfigOption::MYSQL_DRIVER, true), false]; - yield 'postgres with value' => [$buildCollection(DatabaseDriverConfigOption::POSTGRES_DRIVER, true), false]; + yield 'mysql' => [$buildCollection(DatabaseDriver::MYSQL->value), true]; + yield 'postgres' => [$buildCollection(DatabaseDriver::POSTGRES->value), true]; + yield 'mysql with value' => [$buildCollection(DatabaseDriver::MYSQL->value, true), false]; + yield 'postgres with value' => [$buildCollection(DatabaseDriver::POSTGRES->value, true), false]; } } diff --git a/test/Config/Option/Database/DatabasePortConfigOptionTest.php b/test/Config/Option/Database/DatabasePortConfigOptionTest.php index 71a34f9..f5bba43 100644 --- a/test/Config/Option/Database/DatabasePortConfigOptionTest.php +++ b/test/Config/Option/Database/DatabasePortConfigOptionTest.php @@ -9,6 +9,7 @@ use Shlinkio\Shlink\Config\Collection\PathCollection; use Shlinkio\Shlink\Installer\Config\Option\Database\DatabaseDriverConfigOption; use Shlinkio\Shlink\Installer\Config\Option\Database\DatabasePortConfigOption; +use Shlinkio\Shlink\Installer\Config\Util\DatabaseDriver; use Symfony\Component\Console\Style\StyleInterface; class DatabasePortConfigOptionTest extends TestCase @@ -54,10 +55,10 @@ public function provideCurrentOptions(): iterable return $collection; }; - yield 'mysql' => [$buildCollection(DatabaseDriverConfigOption::MYSQL_DRIVER), '3306']; - yield 'postgres' => [$buildCollection(DatabaseDriverConfigOption::POSTGRES_DRIVER), '5432']; - yield 'mssql' => [$buildCollection(DatabaseDriverConfigOption::MSSQL_DRIVER), '1433']; - yield 'sqlite' => [$buildCollection(DatabaseDriverConfigOption::SQLITE_DRIVER), '']; + yield 'mysql' => [$buildCollection(DatabaseDriver::MYSQL->value), '3306']; + yield 'postgres' => [$buildCollection(DatabaseDriver::POSTGRES->value), '5432']; + yield 'mssql' => [$buildCollection(DatabaseDriver::MSSQL->value), '1433']; + yield 'sqlite' => [$buildCollection(DatabaseDriver::SQLITE->value), '']; yield 'unsupported' => [$buildCollection('unsupported'), '']; } } diff --git a/test/Service/ShlinkAssetsHandlerTest.php b/test/Service/ShlinkAssetsHandlerTest.php index a3bf441..c7482ed 100644 --- a/test/Service/ShlinkAssetsHandlerTest.php +++ b/test/Service/ShlinkAssetsHandlerTest.php @@ -114,7 +114,7 @@ public function configIsImportedOnlyIfExistingPathIsProvided(bool $exists): void $result = $this->assetsHandler->resolvePreviousConfig($this->io->reveal()); - self::assertEquals($exists ? $importPath : '', $result->importPath()); + self::assertEquals($exists ? $importPath : '', $result->importPath); $confirm->shouldHaveBeenCalledTimes($exists ? 1 : 4); $ask->shouldHaveBeenCalledTimes($exists ? 1 : 3); $configExists->shouldHaveBeenCalledTimes($exists ? 1 : 3);