diff --git a/config/services.yaml b/config/services.yaml index 46b7f89e..1bd81868 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -33,6 +33,8 @@ services: # please note that last definitions always *replace* previous ones App\PHPDocker\Zip\Archiver: + arguments: + $baseFolder: 'phpdocker' shared: false # Instantiate some third party libraries we need for autowiring our own services @@ -49,4 +51,3 @@ services: Symfony\Component\HttpFoundation\Session\Storage\Handler\RedisSessionHandler: arguments: [ '@Redis' ] - diff --git a/src/Controller/GeneratorController.php b/src/Controller/GeneratorController.php index 3e51690b..8be26dc7 100644 --- a/src/Controller/GeneratorController.php +++ b/src/Controller/GeneratorController.php @@ -21,9 +21,7 @@ use App\Form\Generator\ProjectType; use App\PHPDocker\Generator\Generator; use App\PHPDocker\PhpExtension\AvailableExtensionsFactory; -use App\PHPDocker\Project\Project; -use App\PHPDocker\Project\ServiceOptions\GlobalOptions; -use App\PHPDocker\Project\ServiceOptions\Php as PhpOptions; +use App\PHPDocker\Project\ProjectFactory; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\Request; @@ -37,6 +35,7 @@ class GeneratorController extends AbstractController { public function __construct( private readonly Generator $generator, + private readonly ProjectFactory $projectFactory, private readonly string $environment, ) { } @@ -52,7 +51,7 @@ public function create(Request $request): BinaryFileResponse|Response if ($form->isSubmitted() === true && $form->isValid() === true) { /** @var array $data */ $data = $form->getData(); - $project = $this->hydrateProject($data); + $project = $this->projectFactory->fromFormData($data); // Generate zip file with docker project $zipFile = $this->generator->generate($project); @@ -71,86 +70,7 @@ public function create(Request $request): BinaryFileResponse|Response return $this->render('generator.html.twig', [ 'form' => $form->createView(), - 'phpExtensionsJson' => json_encode(AvailableExtensionsFactory::getAllExtensionNames()), + 'phpExtensionsJson' => json_encode(AvailableExtensionsFactory::getAllExtensionNames(), JSON_THROW_ON_ERROR), ]); } - - private function hydrateProject(array $formData): Project - { - $phpData = $formData['phpOptions']; - - $extensions = $phpData['phpExtensions'] ?? []; - - $phpOptions = new PhpOptions( - version: $phpData['version'], - extensions: $extensions, - hasGit: $phpData['hasGit'], - frontControllerPath: $phpData['frontControllerPath'], - ); - - $globalOptionsData = $formData['globalOptions']; - $globalOptions = new GlobalOptions( - basePort: $globalOptionsData['basePort'], - appPath: rtrim($globalOptionsData['appPath'], '/'), - dockerWorkingDir: rtrim($globalOptionsData['dockerWorkingDir'], '/'), - ); - - $project = new Project( - phpOptions: $phpOptions, - globalOptions: $globalOptions, - ); - - $project->getMemcachedOptions()->setEnabled($formData['hasMemcached']); - $project->getRedisOptions()->setEnabled($formData['hasRedis']); - $project->getMailhogOptions()->setEnabled($formData['hasMailhog']); - $project->getClickhouseOptions()->setEnabled($formData['hasClickhouse']); - - $mysqlData = $formData['mysqlOptions']; - if ($mysqlData['hasMysql'] === true) { - $project - ->getMysqlOptions() - ->setEnabled(true) - ->setVersion($mysqlData['version']) - ->setDatabaseName($mysqlData['databaseName']) - ->setRootPassword($mysqlData['rootPassword']) - ->setUsername($mysqlData['username']) - ->setPassword($mysqlData['password']); - } - - $mariaDbData = $formData['mariadbOptions']; - if ($mariaDbData['hasMariadb'] === true) { - $project - ->getMariadbOptions() - ->setEnabled(true) - ->setVersion($mariaDbData['version']) - ->setDatabaseName($mariaDbData['databaseName']) - ->setRootPassword($mariaDbData['rootPassword']) - ->setUsername($mariaDbData['username']) - ->setPassword($mariaDbData['password']); - } - - // For some reason, form data comes with version as int (instead of the original string) - // because postgres versions can be cast as int (eg Postgres::VERSION_15 = '15' at some point the form casts - // it to 15 - $pgData = $formData['postgresOptions']; - if ($pgData['hasPostgres'] === true) { - $project - ->getPostgresOptions() - ->setEnabled(true) - ->setVersion((string) $pgData['version']) - ->setDatabaseName($pgData['databaseName']) - ->setRootUser($pgData['rootUser']) - ->setRootPassword($pgData['rootPassword']); - } - - $esData = $formData['elasticsearchOptions']; - if ($esData['hasElasticsearch'] === true) { - $project - ->getElasticsearchOptions() - ->setEnabled(true) - ->setVersion($esData['version']); - } - - return $project; - } } diff --git a/src/PHPDocker/Generator/Files/DockerCompose.php b/src/PHPDocker/Generator/Files/DockerCompose.php index f4c22f05..6ebd7020 100644 --- a/src/PHPDocker/Generator/Files/DockerCompose.php +++ b/src/PHPDocker/Generator/Files/DockerCompose.php @@ -23,41 +23,19 @@ use App\PHPDocker\Project\Project; use Symfony\Component\Yaml\Dumper; -class DockerCompose implements GeneratedFileInterface +final readonly class DockerCompose implements GeneratedFileInterface { private const string DOCKER_COMPOSE_FILE_VERSION = '3.1'; - /** @var array */ - private array $services; - private string $defaultVolume; - private int $basePort; - - public function __construct(private readonly Dumper $yaml, private readonly Project $project, private readonly string $phpIniLocation) + public function __construct(private Dumper $yaml, private Project $project, private string $phpIniLocation) { - $this->basePort = $this->project->getGlobalOptions()->getBasePort(); } public function getContents(): string { - $workingDir = $this->project->getGlobalOptions(); - - $this->defaultVolume = sprintf('%s:%s', $workingDir->getAppPath(), $workingDir->getDockerWorkingDir()); - - $this - ->addMemcached() - ->addMailhog() - ->addRedis() - ->addMysql() - ->addMariadb() - ->addPostgres() - ->addElasticsearch() - ->addClickhouse() - ->addWebserver() - ->addPhpFpm(); - $data = [ 'version' => self::DOCKER_COMPOSE_FILE_VERSION, - 'services' => $this->services, + 'services' => $this->buildServices(), ]; return $this->tidyYaml($this->yaml->dump(input: $data, inline: 4)); @@ -68,156 +46,231 @@ public function getFilename(): string return 'docker-compose.yml'; } - private function addMemcached(): self + /** + * @return array> + */ + private function buildServices(): array { - if ($this->project->hasMemcached() === true) { - $this->services['memcached'] = ['image' => 'memcached:alpine']; + $globalOptions = $this->project->getGlobalOptions(); + $basePort = $globalOptions->getBasePort(); + $defaultVolume = sprintf('%s:%s', $globalOptions->getAppPath(), $globalOptions->getDockerWorkingDir()); + + $services = []; + + if ($memcached = $this->buildMemcachedService()) { + $services['memcached'] = $memcached; + } + + if ($mailhog = $this->buildMailhogService($basePort)) { + $services['mailhog'] = $mailhog; + } + + if ($redis = $this->buildRedisService()) { + $services['redis'] = $redis; + } + + if ($mysql = $this->buildMysqlService($defaultVolume, $basePort)) { + $services['mysql'] = $mysql; + } + + if ($mariadb = $this->buildMariadbService($defaultVolume, $basePort)) { + $services['mariadb'] = $mariadb; + } + + if ($postgres = $this->buildPostgresService($defaultVolume, $basePort)) { + $services['postgres'] = $postgres; } - return $this; + if ($elasticsearch = $this->buildElasticsearchService()) { + $services['elasticsearch'] = $elasticsearch; + } + + if ($clickhouse = $this->buildClickhouseService()) { + $services['clickhouse'] = $clickhouse; + } + + $services['webserver'] = $this->buildWebserverService($defaultVolume, $basePort); + $services['php-fpm'] = $this->buildPhpFpmService($defaultVolume); + + return $services; } - private function addMailhog(): self + /** + * @return array|null + */ + private function buildMemcachedService(): ?array { - if ($this->project->hasMailhog() === true) { - $extPort = $this->project->getMailhogOptions()->getExternalPort($this->basePort); + if ($this->project->hasMemcached() === false) { + return null; + } - $this->services['mailhog'] = [ - 'image' => 'mailhog/mailhog:latest', - 'ports' => [sprintf('%s:8025', $extPort)], - ]; + return ['image' => 'memcached:alpine']; + } + + /** + * @return array|string>|null + */ + private function buildMailhogService(int $basePort): ?array + { + if ($this->project->hasMailhog() === false) { + return null; } - return $this; + $extPort = $this->project->getMailhogOptions()->getExternalPort($basePort); + + return [ + 'image' => 'mailhog/mailhog:latest', + 'ports' => [sprintf('%s:8025', $extPort)], + ]; } - private function addRedis(): self + /** + * @return array|null + */ + private function buildRedisService(): ?array { - if ($this->project->hasRedis() === true) { - $this->services['redis'] = ['image' => 'redis:alpine']; + if ($this->project->hasRedis() === false) { + return null; } - return $this; + return ['image' => 'redis:alpine']; } - private function addMysql(): self + /** + * @return array|string>|null + */ + private function buildMysqlService(string $defaultVolume, int $basePort): ?array { - if ($this->project->hasMysql() === true) { - $mysql = $this->project->getMysqlOptions(); - $extPort = $mysql->getExternalPort($this->basePort); - - $this->services['mysql'] = [ - 'image' => sprintf('mysql:%s', $mysql->getVersion()), - 'working_dir' => $this->project->getGlobalOptions()->getDockerWorkingDir(), - 'volumes' => [$this->defaultVolume], - 'environment' => [ - sprintf('MYSQL_ROOT_PASSWORD=%s', $mysql->getRootPassword()), - sprintf('MYSQL_DATABASE=%s', $mysql->getDatabaseName()), - sprintf('MYSQL_USER=%s', $mysql->getUsername()), - sprintf('MYSQL_PASSWORD=%s', $mysql->getPassword()), - ], - 'ports' => [sprintf('%s:3306', $extPort)], - ]; + if ($this->project->hasMysql() === false) { + return null; } - return $this; + $mysql = $this->project->getMysqlOptions(); + $extPort = $mysql->getExternalPort($basePort); + + return [ + 'image' => sprintf('mysql:%s', $mysql->getVersion()), + 'working_dir' => $this->project->getGlobalOptions()->getDockerWorkingDir(), + 'volumes' => [$defaultVolume], + 'environment' => [ + sprintf('MYSQL_ROOT_PASSWORD=%s', $mysql->getRootPassword()), + sprintf('MYSQL_DATABASE=%s', $mysql->getDatabaseName()), + sprintf('MYSQL_USER=%s', $mysql->getUsername()), + sprintf('MYSQL_PASSWORD=%s', $mysql->getPassword()), + ], + 'ports' => [sprintf('%s:3306', $extPort)], + ]; } - private function addMariadb(): self + /** + * @return array|string>|null + */ + private function buildMariadbService(string $defaultVolume, int $basePort): ?array { - if ($this->project->hasMariadb() === true) { - $mariadb = $this->project->getMariadbOptions(); - $extPort = $mariadb->getExternalPort($this->basePort); - - $this->services['mariadb'] = [ - 'image' => sprintf('mariadb:%s', $mariadb->getVersion()), - 'working_dir' => $this->project->getGlobalOptions()->getDockerWorkingDir(), - 'volumes' => [$this->defaultVolume], - 'environment' => [ - sprintf('MYSQL_ROOT_PASSWORD=%s', $mariadb->getRootPassword()), - sprintf('MYSQL_DATABASE=%s', $mariadb->getDatabaseName()), - sprintf('MYSQL_USER=%s', $mariadb->getUsername()), - sprintf('MYSQL_PASSWORD=%s', $mariadb->getPassword()), - ], - 'ports' => [sprintf('%s:3306', $extPort)], - ]; + if ($this->project->hasMariadb() === false) { + return null; } - return $this; + $mariadb = $this->project->getMariadbOptions(); + $extPort = $mariadb->getExternalPort($basePort); + + return [ + 'image' => sprintf('mariadb:%s', $mariadb->getVersion()), + 'working_dir' => $this->project->getGlobalOptions()->getDockerWorkingDir(), + 'volumes' => [$defaultVolume], + 'environment' => [ + sprintf('MYSQL_ROOT_PASSWORD=%s', $mariadb->getRootPassword()), + sprintf('MYSQL_DATABASE=%s', $mariadb->getDatabaseName()), + sprintf('MYSQL_USER=%s', $mariadb->getUsername()), + sprintf('MYSQL_PASSWORD=%s', $mariadb->getPassword()), + ], + 'ports' => [sprintf('%s:3306', $extPort)], + ]; } - private function addPostgres(): self + /** + * @return array|string>|null + */ + private function buildPostgresService(string $defaultVolume, int $basePort): ?array { - if ($this->project->hasPostgres() === true) { - $postgres = $this->project->getPostgresOptions(); - $extPort = $postgres->getExternalPort($this->basePort); - - $this->services['postgres'] = [ - 'image' => sprintf('postgres:%s-alpine', $postgres->getVersion()), - 'working_dir' => $this->project->getGlobalOptions()->getDockerWorkingDir(), - 'volumes' => [$this->defaultVolume], - 'environment' => [ - sprintf('POSTGRES_USER=%s', $postgres->getRootUser()), - sprintf('POSTGRES_PASSWORD=%s', $postgres->getRootPassword()), - sprintf('POSTGRES_DB=%s', $postgres->getDatabaseName()), - ], - 'ports' => [sprintf('%s:5432', $extPort)], - ]; + if ($this->project->hasPostgres() === false) { + return null; } - return $this; + $postgres = $this->project->getPostgresOptions(); + $extPort = $postgres->getExternalPort($basePort); + + return [ + 'image' => sprintf('postgres:%s-alpine', $postgres->getVersion()), + 'working_dir' => $this->project->getGlobalOptions()->getDockerWorkingDir(), + 'volumes' => [$defaultVolume], + 'environment' => [ + sprintf('POSTGRES_USER=%s', $postgres->getRootUser()), + sprintf('POSTGRES_PASSWORD=%s', $postgres->getRootPassword()), + sprintf('POSTGRES_DB=%s', $postgres->getDatabaseName()), + ], + 'ports' => [sprintf('%s:5432', $extPort)], + ]; } - private function addElasticsearch(): self + /** + * @return array|null + */ + private function buildElasticsearchService(): ?array { - if ($this->project->hasElasticsearch() === true) { - $this->services['elasticsearch'] = [ - 'image' => sprintf('elasticsearch:%s', $this->project->getElasticsearchOptions()->getVersion()), - ]; + if ($this->project->hasElasticsearch() === false) { + return null; } - return $this; + return [ + 'image' => sprintf('elasticsearch:%s', $this->project->getElasticsearchOptions()->getVersion()), + ]; } - private function addClickhouse(): self + /** + * @return array|null + */ + private function buildClickhouseService(): ?array { - if ($this->project->hasClickhouse() === true) { - $this->services['clickhouse'] = ['image' => 'clickhouse/clickhouse-server:latest']; + if ($this->project->hasClickhouse() === false) { + return null; } - return $this; + return ['image' => 'clickhouse/clickhouse-server:latest']; } - private function addWebserver(): self + /** + * @return array|string> + */ + private function buildWebserverService(string $defaultVolume, int $basePort): array { - $this->services['webserver'] = [ + return [ 'image' => 'nginx:alpine', 'working_dir' => $this->project->getGlobalOptions()->getDockerWorkingDir(), 'volumes' => [ - $this->defaultVolume, + $defaultVolume, './phpdocker/nginx/nginx.conf:/etc/nginx/conf.d/default.conf', ], - 'ports' => [sprintf('%s:80', $this->basePort)], + 'ports' => [sprintf('%s:80', $basePort)], ]; - - return $this; } - private function addPhpFpm(): self + /** + * @return array|string> + */ + private function buildPhpFpmService(string $defaultVolume): array { $shortVersion = str_replace(search: '.x', replace: '', subject: $this->project->getPhpOptions()->getVersion()); - $this->services['php-fpm'] = [ + return [ 'build' => 'phpdocker/php-fpm', 'working_dir' => $this->project->getGlobalOptions()->getDockerWorkingDir(), 'volumes' => [ - $this->defaultVolume, + $defaultVolume, sprintf('./phpdocker/%s:/etc/php/%s/fpm/conf.d/99-overrides.ini', $this->phpIniLocation, $shortVersion), sprintf('./phpdocker/%s:/etc/php/%s/cli/conf.d/99-overrides.ini', $this->phpIniLocation, $shortVersion), ], ]; - - return $this; } private function tidyYaml(string $renderedYaml): string diff --git a/src/PHPDocker/Generator/Files/Dockerfile.php b/src/PHPDocker/Generator/Files/Dockerfile.php index 7324bdd3..9a6b6161 100644 --- a/src/PHPDocker/Generator/Files/Dockerfile.php +++ b/src/PHPDocker/Generator/Files/Dockerfile.php @@ -23,7 +23,7 @@ use App\PHPDocker\Project\Project; use Twig\Environment; -class Dockerfile implements GeneratedFileInterface +final readonly class Dockerfile implements GeneratedFileInterface { private const string FILENAME = 'php-fpm' . DIRECTORY_SEPARATOR . 'Dockerfile'; diff --git a/src/PHPDocker/Generator/Files/NginxConf.php b/src/PHPDocker/Generator/Files/NginxConf.php index bb0e51f8..c078f4d2 100644 --- a/src/PHPDocker/Generator/Files/NginxConf.php +++ b/src/PHPDocker/Generator/Files/NginxConf.php @@ -23,7 +23,7 @@ use App\PHPDocker\Project\Project; use Twig\Environment; -readonly class NginxConf implements GeneratedFileInterface +final readonly class NginxConf implements GeneratedFileInterface { public function __construct(private Environment $twig, private Project $project) { diff --git a/src/PHPDocker/Generator/Files/PhpIni.php b/src/PHPDocker/Generator/Files/PhpIni.php index ea1014cf..d0a142ce 100644 --- a/src/PHPDocker/Generator/Files/PhpIni.php +++ b/src/PHPDocker/Generator/Files/PhpIni.php @@ -22,9 +22,8 @@ use App\PHPDocker\Interfaces\GeneratedFileInterface; use Twig\Environment; -readonly class PhpIni implements GeneratedFileInterface +final readonly class PhpIni implements GeneratedFileInterface { - public function __construct(private Environment $twig) { } diff --git a/src/PHPDocker/Generator/Files/ReadmeHtml.php b/src/PHPDocker/Generator/Files/ReadmeHtml.php index 0e2609d8..f296f760 100644 --- a/src/PHPDocker/Generator/Files/ReadmeHtml.php +++ b/src/PHPDocker/Generator/Files/ReadmeHtml.php @@ -23,7 +23,7 @@ use Michelf\MarkdownExtra; use Twig\Environment; -readonly class ReadmeHtml implements GeneratedFileInterface +final readonly class ReadmeHtml implements GeneratedFileInterface { public function __construct(private Environment $twig, private MarkdownExtra $markdown, private string $readmeMd) { diff --git a/src/PHPDocker/Generator/Files/ReadmeMd.php b/src/PHPDocker/Generator/Files/ReadmeMd.php index 725cc80f..2cd53f72 100644 --- a/src/PHPDocker/Generator/Files/ReadmeMd.php +++ b/src/PHPDocker/Generator/Files/ReadmeMd.php @@ -23,7 +23,7 @@ use App\PHPDocker\Project\Project; use Twig\Environment; -readonly class ReadmeMd implements GeneratedFileInterface +final readonly class ReadmeMd implements GeneratedFileInterface { public function __construct(private Environment $twig, private Project $project) { diff --git a/src/PHPDocker/Generator/Generator.php b/src/PHPDocker/Generator/Generator.php index 3dd3e1ff..6a0974b9 100644 --- a/src/PHPDocker/Generator/Generator.php +++ b/src/PHPDocker/Generator/Generator.php @@ -37,7 +37,6 @@ */ class Generator { - private const string BASE_ZIP_FOLDER = 'phpdocker'; private const string ARCHIVE_FILENAME = 'phpdocker.zip'; public function __construct( @@ -46,7 +45,6 @@ public function __construct( private readonly MarkdownExtra $markdownExtra, private readonly Dumper $yaml, ) { - $this->archiver->setBaseFolder(self::BASE_ZIP_FOLDER); } /** diff --git a/src/PHPDocker/PhpExtension/BaseAvailableExtensions.php b/src/PHPDocker/PhpExtension/BaseAvailableExtensions.php index d824793d..4d33907a 100644 --- a/src/PHPDocker/PhpExtension/BaseAvailableExtensions.php +++ b/src/PHPDocker/PhpExtension/BaseAvailableExtensions.php @@ -23,22 +23,24 @@ */ abstract class BaseAvailableExtensions { - /** @var array> */ + /** + * @var array + */ private array $allExtensions = []; /** * Must return an array of all available mandatory extensions, indexed by display name - * and containing an array of ['packages' => ['deb-package-1', 'deb-package-2' ...] + * and containing a list of package names. * - * @return array> + * @return array */ abstract protected function getMandatoryExtensionsMap(): array; /** * Must return an array of all available optional extensions, indexed by display name - * and containing an array of ['packages' => ['deb-package-1', 'deb-package-2' ...] + * and containing a list of package names. * - * @return array> + * @return array */ abstract protected function getOptionalExtensionsMap(): array; @@ -53,12 +55,15 @@ public function isAvailable(string $name): bool /** * Returns all available extensions, mandatory or not. * - * @return array> + * @return array */ public function getAll(): array { if ($this->allExtensions === []) { - $this->allExtensions = array_merge($this->getMandatoryExtensionsMap(), $this->getOptionalExtensionsMap()); + $this->allExtensions = array_merge( + $this->createExtensions($this->getMandatoryExtensionsMap()), + $this->createExtensions($this->getOptionalExtensionsMap()), + ); } return $this->allExtensions; @@ -75,16 +80,7 @@ public function getPhpExtension(string $name): PhpExtension throw new Exception\NotFoundException(sprintf('PHP extension %s is not available to install', $name)); } - $raw = $this->getAll()[$name]; - - $extension = new PhpExtension(); - $extension->setName($name); - - foreach ($raw['packages'] ?? [] as $package) { - $extension->addPackage($package); - } - - return $extension; + return $this->getAll()[$name]; } /** @@ -94,10 +90,20 @@ public function getPhpExtension(string $name): PhpExtension * @throws Exception\NotFoundException */ public function getOptional(): array + { + return array_values($this->createExtensions($this->getOptionalExtensionsMap())); + } + + /** + * @param array $extensionMap + * + * @return array + */ + private function createExtensions(array $extensionMap): array { $extensions = []; - foreach ($this->getOptionalExtensionsMap() as $name => $value) { - $extensions[] = $this->getPhpExtension($name); + foreach ($extensionMap as $name => $packages) { + $extensions[$name] = new PhpExtension($name, $packages); } return $extensions; diff --git a/src/PHPDocker/PhpExtension/Php82AvailableExtensions.php b/src/PHPDocker/PhpExtension/Php82AvailableExtensions.php index e90bc806..bde4fc23 100644 --- a/src/PHPDocker/PhpExtension/Php82AvailableExtensions.php +++ b/src/PHPDocker/PhpExtension/Php82AvailableExtensions.php @@ -19,102 +19,102 @@ namespace App\PHPDocker\PhpExtension; -class Php82AvailableExtensions extends BaseAvailableExtensions +final class Php82AvailableExtensions extends BaseAvailableExtensions { /** * @inheritDoc - * @return array> + * @return array */ protected function getMandatoryExtensionsMap(): array { return [ - 'cURL' => ['packages' => ['php8.2-curl']], - 'MBSTRING' => ['packages' => ['php8.2-mbstring']], - 'OPCache' => ['packages' => ['php8.2-opcache']], - 'Readline' => ['packages' => ['php8.2-readline']], - 'XML' => ['packages' => ['php8.2-xml']], - 'Zip' => ['packages' => ['php8.2-zip']], + 'cURL' => ['php8.2-curl'], + 'MBSTRING' => ['php8.2-mbstring'], + 'OPCache' => ['php8.2-opcache'], + 'Readline' => ['php8.2-readline'], + 'XML' => ['php8.2-xml'], + 'Zip' => ['php8.2-zip'], ]; } /** * @inheritDoc - * @return array> + * @return array */ protected function getOptionalExtensionsMap(): array { return [ - 'AMQP' => ['packages' => ['php8.2-amqp']], - 'AST' => ['packages' => ['php8.2-ast']], - 'Bcmath' => ['packages' => ['php8.2-bcmath']], - 'bzip2' => ['packages' => ['php8.2-bz2']], - 'CGI' => ['packages' => ['php8.2-cgi']], - 'DBA' => ['packages' => ['php8.2-dba']], - 'Decimal' => ['packages' => ['php8.2-decimal']], - 'DS (Data Structures)' => ['packages' => ['php8.2-ds']], - 'Enchant' => ['packages' => ['php8.2-enchant']], - 'GD' => ['packages' => ['php8.2-gd']], - 'Gearman' => ['packages' => ['php8.2-gearman']], - 'Gmagick (GraphicsMagick)' => ['packages' => ['php8.2-gmagick']], - 'GMP' => ['packages' => ['php8.2-gmp']], - 'GNUPG' => ['packages' => ['php8.2-gnupg']], - 'GRPC' => ['packages' => ['php8.2-grpc']], - 'HTTP' => ['packages' => ['php8.2-http']], - 'igbinary' => ['packages' => ['php8.2-igbinary']], - 'ImageMagick' => ['packages' => ['php8.2-imagick']], - 'IMAP' => ['packages' => ['php8.2-imap']], - 'Inotify' => ['packages' => ['php8.2-inotify']], - 'Interbase' => ['packages' => ['php8.2-interbase']], - 'Intl (Internationalisation)' => ['packages' => ['php8.2-intl']], - 'LDAP' => ['packages' => ['php8.2-ldap']], - 'LZ4' => ['packages' => ['php8.2-lz4']], - 'Mailparse' => ['packages' => ['php8.2-mailparse']], - 'MaxMind DB' => ['packages' => ['php8.2-maxminddb']], - 'mcrypt' => ['packages' => ['php8.2-mcrypt']], - 'Memcache' => ['packages' => ['php8.2-memcache']], - 'Memcached' => ['packages' => ['php8.2-memcached']], - 'MongoDB' => ['packages' => ['php8.2-mongodb']], - 'MessagePack' => ['packages' => ['php8.2-msgpack']], - 'MySQL' => ['packages' => ['php8.2-mysql']], - 'OAuth' => ['packages' => ['php8.2-oauth']], - 'ODBC' => ['packages' => ['php8.2-odbc']], - 'OpenTelemetry' => ['packages' => ['php8.2-opentelemetry']], - 'Pcov' => ['packages' => ['php8.2-pcov']], - 'PostgreSQL' => ['packages' => ['php8.2-pgsql']], - 'PostgreSQL (libpq)' => ['packages' => ['php8.2-pq']], - 'Phalcon 5' => ['packages' => ['php8.2-phalcon']], - 'Pinba' => ['packages' => ['php8.2-pinba']], - 'PHPDBG' => ['packages' => ['php8.2-phpdbg']], - 'propro' => ['packages' => ['php8.2-propro']], - 'Protobuf' => ['packages' => ['php8.2-protobuf']], - 'ps' => ['packages' => ['php8.2-ps']], - 'pspell' => ['packages' => ['php8.2-pspell']], - 'PSR' => ['packages' => ['php8.2-psr']], - 'raphf' => ['packages' => ['php8.2-raphf']], - 'Redis' => ['packages' => ['php8.2-redis']], - 'rrd' => ['packages' => ['php8.2-rrd']], - 'Samba Client' => ['packages' => ['php8.2-smbclient']], - 'SNMP' => ['packages' => ['php8.2-snmp']], - 'SOAP' => ['packages' => ['php8.2-soap']], - 'Solr' => ['packages' => ['php8.2-solr']], - 'SQLite3' => ['packages' => ['php8.2-sqlite3']], - 'ssh2' => ['packages' => ['php8.2-ssh2']], - 'STOMP protocol' => ['packages' => ['php8.2-stomp']], - 'Swoole' => ['packages' => ['php8.2-swoole']], - 'Sybase' => ['packages' => ['php8.2-sybase']], - 'Tidy' => ['packages' => ['php8.2-tidy']], - 'UOPZ' => ['packages' => ['php8.2-uopz']], - 'Upload progress' => ['packages' => ['php8.2-uploadprogress']], - 'UUID' => ['packages' => ['php8.2-uuid']], - 'vips' => ['packages' => ['php8.2-vips']], - 'Xdebug' => ['packages' => ['php8.2-xdebug']], - 'Xhprof' => ['packages' => ['php8.2-xhprof']], - 'XMLRPC' => ['packages' => ['php8.2-xmlrpc']], - 'XSL' => ['packages' => ['php8.2-xsl']], - 'Yac' => ['packages' => ['php8.2-yac']], - 'YAML' => ['packages' => ['php8.2-yaml']], - 'ZMQ (ZeroMQ)' => ['packages' => ['php8.2-zmq']], - 'zstd (Zstandard)' => ['packages' => ['php8.2-zstd']], + 'AMQP' => ['php8.2-amqp'], + 'AST' => ['php8.2-ast'], + 'Bcmath' => ['php8.2-bcmath'], + 'bzip2' => ['php8.2-bz2'], + 'CGI' => ['php8.2-cgi'], + 'DBA' => ['php8.2-dba'], + 'Decimal' => ['php8.2-decimal'], + 'DS (Data Structures)' => ['php8.2-ds'], + 'Enchant' => ['php8.2-enchant'], + 'GD' => ['php8.2-gd'], + 'Gearman' => ['php8.2-gearman'], + 'Gmagick (GraphicsMagick)' => ['php8.2-gmagick'], + 'GMP' => ['php8.2-gmp'], + 'GNUPG' => ['php8.2-gnupg'], + 'GRPC' => ['php8.2-grpc'], + 'HTTP' => ['php8.2-http'], + 'igbinary' => ['php8.2-igbinary'], + 'ImageMagick' => ['php8.2-imagick'], + 'IMAP' => ['php8.2-imap'], + 'Inotify' => ['php8.2-inotify'], + 'Interbase' => ['php8.2-interbase'], + 'Intl (Internationalisation)' => ['php8.2-intl'], + 'LDAP' => ['php8.2-ldap'], + 'LZ4' => ['php8.2-lz4'], + 'Mailparse' => ['php8.2-mailparse'], + 'MaxMind DB' => ['php8.2-maxminddb'], + 'mcrypt' => ['php8.2-mcrypt'], + 'Memcache' => ['php8.2-memcache'], + 'Memcached' => ['php8.2-memcached'], + 'MongoDB' => ['php8.2-mongodb'], + 'MessagePack' => ['php8.2-msgpack'], + 'MySQL' => ['php8.2-mysql'], + 'OAuth' => ['php8.2-oauth'], + 'ODBC' => ['php8.2-odbc'], + 'OpenTelemetry' => ['php8.2-opentelemetry'], + 'Pcov' => ['php8.2-pcov'], + 'PostgreSQL' => ['php8.2-pgsql'], + 'PostgreSQL (libpq)' => ['php8.2-pq'], + 'Phalcon 5' => ['php8.2-phalcon'], + 'Pinba' => ['php8.2-pinba'], + 'PHPDBG' => ['php8.2-phpdbg'], + 'propro' => ['php8.2-propro'], + 'Protobuf' => ['php8.2-protobuf'], + 'ps' => ['php8.2-ps'], + 'pspell' => ['php8.2-pspell'], + 'PSR' => ['php8.2-psr'], + 'raphf' => ['php8.2-raphf'], + 'Redis' => ['php8.2-redis'], + 'rrd' => ['php8.2-rrd'], + 'Samba Client' => ['php8.2-smbclient'], + 'SNMP' => ['php8.2-snmp'], + 'SOAP' => ['php8.2-soap'], + 'Solr' => ['php8.2-solr'], + 'SQLite3' => ['php8.2-sqlite3'], + 'ssh2' => ['php8.2-ssh2'], + 'STOMP protocol' => ['php8.2-stomp'], + 'Swoole' => ['php8.2-swoole'], + 'Sybase' => ['php8.2-sybase'], + 'Tidy' => ['php8.2-tidy'], + 'UOPZ' => ['php8.2-uopz'], + 'Upload progress' => ['php8.2-uploadprogress'], + 'UUID' => ['php8.2-uuid'], + 'vips' => ['php8.2-vips'], + 'Xdebug' => ['php8.2-xdebug'], + 'Xhprof' => ['php8.2-xhprof'], + 'XMLRPC' => ['php8.2-xmlrpc'], + 'XSL' => ['php8.2-xsl'], + 'Yac' => ['php8.2-yac'], + 'YAML' => ['php8.2-yaml'], + 'ZMQ (ZeroMQ)' => ['php8.2-zmq'], + 'zstd (Zstandard)' => ['php8.2-zstd'], ]; } } diff --git a/src/PHPDocker/PhpExtension/Php83AvailableExtensions.php b/src/PHPDocker/PhpExtension/Php83AvailableExtensions.php index 36f2d028..e4a9f7b1 100644 --- a/src/PHPDocker/PhpExtension/Php83AvailableExtensions.php +++ b/src/PHPDocker/PhpExtension/Php83AvailableExtensions.php @@ -19,101 +19,101 @@ namespace App\PHPDocker\PhpExtension; -class Php83AvailableExtensions extends BaseAvailableExtensions +final class Php83AvailableExtensions extends BaseAvailableExtensions { /** * @inheritDoc - * @return array> + * @return array */ protected function getMandatoryExtensionsMap(): array { return [ - 'cURL' => ['packages' => ['php8.3-curl']], - 'MBSTRING' => ['packages' => ['php8.3-mbstring']], - 'OPCache' => ['packages' => ['php8.3-opcache']], - 'Readline' => ['packages' => ['php8.3-readline']], - 'XML' => ['packages' => ['php8.3-xml']], - 'Zip' => ['packages' => ['php8.3-zip']], + 'cURL' => ['php8.3-curl'], + 'MBSTRING' => ['php8.3-mbstring'], + 'OPCache' => ['php8.3-opcache'], + 'Readline' => ['php8.3-readline'], + 'XML' => ['php8.3-xml'], + 'Zip' => ['php8.3-zip'], ]; } /** * @inheritDoc - * @return array> + * @return array */ protected function getOptionalExtensionsMap(): array { return [ - 'AMQP' => ['packages' => ['php8.3-amqp']], - 'AST' => ['packages' => ['php8.3-ast']], - 'Bcmath' => ['packages' => ['php8.3-bcmath']], - 'bzip2' => ['packages' => ['php8.3-bz2']], - 'CGI' => ['packages' => ['php8.3-cgi']], - 'DBA' => ['packages' => ['php8.3-dba']], - 'Decimal' => ['packages' => ['php8.3-decimal']], - 'DS (Data Structures)' => ['packages' => ['php8.3-ds']], - 'Enchant' => ['packages' => ['php8.3-enchant']], - 'GD' => ['packages' => ['php8.3-gd']], - 'Gearman' => ['packages' => ['php8.3-gearman']], - 'Gmagick (GraphicsMagick)' => ['packages' => ['php8.3-gmagick']], - 'GMP' => ['packages' => ['php8.3-gmp']], - 'GNUPG' => ['packages' => ['php8.3-gnupg']], - 'GRPC' => ['packages' => ['php8.3-grpc']], - 'HTTP' => ['packages' => ['php8.3-http']], - 'igbinary' => ['packages' => ['php8.3-igbinary']], - 'ImageMagick' => ['packages' => ['php8.3-imagick']], - 'IMAP' => ['packages' => ['php8.3-imap']], - 'Inotify' => ['packages' => ['php8.3-inotify']], - 'Interbase' => ['packages' => ['php8.3-interbase']], - 'Intl (Internationalisation)' => ['packages' => ['php8.3-intl']], - 'LDAP' => ['packages' => ['php8.3-ldap']], - 'LZ4' => ['packages' => ['php8.3-lz4']], - 'Mailparse' => ['packages' => ['php8.3-mailparse']], - 'MaxMind DB' => ['packages' => ['php8.3-maxminddb']], - 'mcrypt' => ['packages' => ['php8.3-mcrypt']], - 'Memcache' => ['packages' => ['php8.3-memcache']], - 'Memcached' => ['packages' => ['php8.3-memcached']], - 'MongoDB' => ['packages' => ['php8.3-mongodb']], - 'MessagePack' => ['packages' => ['php8.3-msgpack']], - 'MySQL' => ['packages' => ['php8.3-mysql']], - 'OAuth' => ['packages' => ['php8.3-oauth']], - 'ODBC' => ['packages' => ['php8.3-odbc']], - 'OpenTelemetry' => ['packages' => ['php8.3-opentelemetry']], - 'Pcov' => ['packages' => ['php8.3-pcov']], - 'PostgreSQL' => ['packages' => ['php8.3-pgsql']], - 'PostgreSQL (libpq)' => ['packages' => ['php8.3-pq']], - 'Phalcon 5' => ['packages' => ['php8.3-phalcon']], - 'Pinba' => ['packages' => ['php8.3-pinba']], - 'PHPDBG' => ['packages' => ['php8.3-phpdbg']], - 'Protobuf' => ['packages' => ['php8.3-protobuf']], - 'ps' => ['packages' => ['php8.3-ps']], - 'pspell' => ['packages' => ['php8.3-pspell']], - 'PSR' => ['packages' => ['php8.3-psr']], - 'raphf' => ['packages' => ['php8.3-raphf']], - 'Redis' => ['packages' => ['php8.3-redis']], - 'rrd' => ['packages' => ['php8.3-rrd']], - 'Samba Client' => ['packages' => ['php8.3-smbclient']], - 'SNMP' => ['packages' => ['php8.3-snmp']], - 'SOAP' => ['packages' => ['php8.3-soap']], - 'Solr' => ['packages' => ['php8.3-solr']], - 'SQLite3' => ['packages' => ['php8.3-sqlite3']], - 'ssh2' => ['packages' => ['php8.3-ssh2']], - 'STOMP protocol' => ['packages' => ['php8.3-stomp']], - 'Swoole' => ['packages' => ['php8.3-swoole']], - 'Sybase' => ['packages' => ['php8.3-sybase']], - 'Tidy' => ['packages' => ['php8.3-tidy']], - 'UOPZ' => ['packages' => ['php8.3-uopz']], - 'Upload progress' => ['packages' => ['php8.3-uploadprogress']], - 'UUID' => ['packages' => ['php8.3-uuid']], - 'vips' => ['packages' => ['php8.3-vips']], - 'Xdebug' => ['packages' => ['php8.3-xdebug']], - 'Xhprof' => ['packages' => ['php8.3-xhprof']], - 'XMLRPC' => ['packages' => ['php8.3-xmlrpc']], - 'XSL' => ['packages' => ['php8.3-xsl']], - 'Yac' => ['packages' => ['php8.3-yac']], - 'YAML' => ['packages' => ['php8.3-yaml']], - 'ZMQ (ZeroMQ)' => ['packages' => ['php8.3-zmq']], - 'zstd (Zstandard)' => ['packages' => ['php8.3-zstd']], + 'AMQP' => ['php8.3-amqp'], + 'AST' => ['php8.3-ast'], + 'Bcmath' => ['php8.3-bcmath'], + 'bzip2' => ['php8.3-bz2'], + 'CGI' => ['php8.3-cgi'], + 'DBA' => ['php8.3-dba'], + 'Decimal' => ['php8.3-decimal'], + 'DS (Data Structures)' => ['php8.3-ds'], + 'Enchant' => ['php8.3-enchant'], + 'GD' => ['php8.3-gd'], + 'Gearman' => ['php8.3-gearman'], + 'Gmagick (GraphicsMagick)' => ['php8.3-gmagick'], + 'GMP' => ['php8.3-gmp'], + 'GNUPG' => ['php8.3-gnupg'], + 'GRPC' => ['php8.3-grpc'], + 'HTTP' => ['php8.3-http'], + 'igbinary' => ['php8.3-igbinary'], + 'ImageMagick' => ['php8.3-imagick'], + 'IMAP' => ['php8.3-imap'], + 'Inotify' => ['php8.3-inotify'], + 'Interbase' => ['php8.3-interbase'], + 'Intl (Internationalisation)' => ['php8.3-intl'], + 'LDAP' => ['php8.3-ldap'], + 'LZ4' => ['php8.3-lz4'], + 'Mailparse' => ['php8.3-mailparse'], + 'MaxMind DB' => ['php8.3-maxminddb'], + 'mcrypt' => ['php8.3-mcrypt'], + 'Memcache' => ['php8.3-memcache'], + 'Memcached' => ['php8.3-memcached'], + 'MongoDB' => ['php8.3-mongodb'], + 'MessagePack' => ['php8.3-msgpack'], + 'MySQL' => ['php8.3-mysql'], + 'OAuth' => ['php8.3-oauth'], + 'ODBC' => ['php8.3-odbc'], + 'OpenTelemetry' => ['php8.3-opentelemetry'], + 'Pcov' => ['php8.3-pcov'], + 'PostgreSQL' => ['php8.3-pgsql'], + 'PostgreSQL (libpq)' => ['php8.3-pq'], + 'Phalcon 5' => ['php8.3-phalcon'], + 'Pinba' => ['php8.3-pinba'], + 'PHPDBG' => ['php8.3-phpdbg'], + 'Protobuf' => ['php8.3-protobuf'], + 'ps' => ['php8.3-ps'], + 'pspell' => ['php8.3-pspell'], + 'PSR' => ['php8.3-psr'], + 'raphf' => ['php8.3-raphf'], + 'Redis' => ['php8.3-redis'], + 'rrd' => ['php8.3-rrd'], + 'Samba Client' => ['php8.3-smbclient'], + 'SNMP' => ['php8.3-snmp'], + 'SOAP' => ['php8.3-soap'], + 'Solr' => ['php8.3-solr'], + 'SQLite3' => ['php8.3-sqlite3'], + 'ssh2' => ['php8.3-ssh2'], + 'STOMP protocol' => ['php8.3-stomp'], + 'Swoole' => ['php8.3-swoole'], + 'Sybase' => ['php8.3-sybase'], + 'Tidy' => ['php8.3-tidy'], + 'UOPZ' => ['php8.3-uopz'], + 'Upload progress' => ['php8.3-uploadprogress'], + 'UUID' => ['php8.3-uuid'], + 'vips' => ['php8.3-vips'], + 'Xdebug' => ['php8.3-xdebug'], + 'Xhprof' => ['php8.3-xhprof'], + 'XMLRPC' => ['php8.3-xmlrpc'], + 'XSL' => ['php8.3-xsl'], + 'Yac' => ['php8.3-yac'], + 'YAML' => ['php8.3-yaml'], + 'ZMQ (ZeroMQ)' => ['php8.3-zmq'], + 'zstd (Zstandard)' => ['php8.3-zstd'], ]; } } diff --git a/src/PHPDocker/PhpExtension/Php84AvailableExtensions.php b/src/PHPDocker/PhpExtension/Php84AvailableExtensions.php index e644fad2..035ff88a 100644 --- a/src/PHPDocker/PhpExtension/Php84AvailableExtensions.php +++ b/src/PHPDocker/PhpExtension/Php84AvailableExtensions.php @@ -19,104 +19,104 @@ namespace App\PHPDocker\PhpExtension; -class Php84AvailableExtensions extends BaseAvailableExtensions +final class Php84AvailableExtensions extends BaseAvailableExtensions { /** * @inheritDoc - * @return array> + * @return array */ protected function getMandatoryExtensionsMap(): array { return [ - 'cURL' => ['packages' => ['php8.4-curl']], - 'MBSTRING' => ['packages' => ['php8.4-mbstring']], - 'OPCache' => ['packages' => ['php8.4-opcache']], - 'Readline' => ['packages' => ['php8.4-readline']], - 'XML' => ['packages' => ['php8.4-xml']], - 'Zip' => ['packages' => ['php8.4-zip']], + 'cURL' => ['php8.4-curl'], + 'MBSTRING' => ['php8.4-mbstring'], + 'OPCache' => ['php8.4-opcache'], + 'Readline' => ['php8.4-readline'], + 'XML' => ['php8.4-xml'], + 'Zip' => ['php8.4-zip'], ]; } /** * @inheritDoc - * @return array> + * @return array */ protected function getOptionalExtensionsMap(): array { return [ - // 'Decimal' => ['packages' => ['php8.4-decimal']], - // 'GRPC' => ['packages' => ['php8.4-grpc']], - // 'Inotify' => ['packages' => ['php8.4-inotify']], - // 'LZ4' => ['packages' => ['php8.4-lz4']], - // 'Protobuf' => ['packages' => ['php8.4-protobuf']], - // 'Pinba' => ['packages' => ['php8.4-pinba']], - // 'Samba Client' => ['packages' => ['php8.4-smbclient']], - // 'Solr' => ['packages' => ['php8.4-solr']], - // 'Swoole' => ['packages' => ['php8.4-swoole']], - // 'vips' => ['packages' => ['php8.4-vips']], - // 'Xhprof' => ['packages' => ['php8.4-xhprof']], - // 'zstd (Zstandard)' => ['packages' => ['php8.4-zstd']], + // 'Decimal' => ['php8.4-decimal'], + // 'GRPC' => ['php8.4-grpc'], + // 'Inotify' => ['php8.4-inotify'], + // 'LZ4' => ['php8.4-lz4'], + // 'Protobuf' => ['php8.4-protobuf'], + // 'Pinba' => ['php8.4-pinba'], + // 'Samba Client' => ['php8.4-smbclient'], + // 'Solr' => ['php8.4-solr'], + // 'Swoole' => ['php8.4-swoole'], + // 'vips' => ['php8.4-vips'], + // 'Xhprof' => ['php8.4-xhprof'], + // 'zstd (Zstandard)' => ['php8.4-zstd'], - 'AMQP' => ['packages' => ['php8.4-amqp']], - 'AST' => ['packages' => ['php8.4-ast']], - 'Bcmath' => ['packages' => ['php8.4-bcmath']], - 'bzip2' => ['packages' => ['php8.4-bz2']], - 'CGI' => ['packages' => ['php8.4-cgi']], - 'DBA' => ['packages' => ['php8.4-dba']], - 'DS (Data Structures)' => ['packages' => ['php8.4-ds']], - 'Enchant' => ['packages' => ['php8.4-enchant']], - 'Excimer' => ['packages' => ['php8.4-excimer']], - 'GD' => ['packages' => ['php8.4-gd']], - 'Gearman' => ['packages' => ['php8.4-gearman']], - 'Gmagick (GraphicsMagick)' => ['packages' => ['php8.4-gmagick']], - 'GMP' => ['packages' => ['php8.4-gmp']], - 'GNUPG' => ['packages' => ['php8.4-gnupg']], - 'HTTP' => ['packages' => ['php8.4-http']], - 'igbinary' => ['packages' => ['php8.4-igbinary']], - 'ImageMagick' => ['packages' => ['php8.4-imagick']], - 'IMAP' => ['packages' => ['php8.4-imap']], - 'Interbase' => ['packages' => ['php8.4-interbase']], - 'Intl (Internationalisation)' => ['packages' => ['php8.4-intl']], - 'LDAP' => ['packages' => ['php8.4-ldap']], - 'Libvirt' => ['packages' => ['php8.4-libvirt-php']], - 'Mailparse' => ['packages' => ['php8.4-mailparse']], - 'MaxMind DB' => ['packages' => ['php8.4-maxminddb']], - 'mcrypt' => ['packages' => ['php8.4-mcrypt']], - 'Memcache' => ['packages' => ['php8.4-memcache']], - 'Memcached' => ['packages' => ['php8.4-memcached']], - 'MongoDB' => ['packages' => ['php8.4-mongodb']], - 'MessagePack' => ['packages' => ['php8.4-msgpack']], - 'MySQL' => ['packages' => ['php8.4-mysql']], - 'OAuth' => ['packages' => ['php8.4-oauth']], - 'ODBC' => ['packages' => ['php8.4-odbc']], - 'OpenTelemetry' => ['packages' => ['php8.4-opentelemetry']], - 'Pcov' => ['packages' => ['php8.4-pcov']], - 'PostgreSQL' => ['packages' => ['php8.4-pgsql']], - 'PostgreSQL (libpq)' => ['packages' => ['php8.4-pq']], - 'Phalcon 5' => ['packages' => ['php8.4-phalcon']], - 'PHPDBG' => ['packages' => ['php8.4-phpdbg']], - 'ps' => ['packages' => ['php8.4-ps']], - 'pspell' => ['packages' => ['php8.4-pspell']], - 'PSR' => ['packages' => ['php8.4-psr']], - 'raphf' => ['packages' => ['php8.4-raphf']], - 'Redis' => ['packages' => ['php8.4-redis']], - 'rrd' => ['packages' => ['php8.4-rrd']], - 'SNMP' => ['packages' => ['php8.4-snmp']], - 'SOAP' => ['packages' => ['php8.4-soap']], - 'SQLite3' => ['packages' => ['php8.4-sqlite3']], - 'ssh2' => ['packages' => ['php8.4-ssh2']], - 'STOMP protocol' => ['packages' => ['php8.4-stomp']], - 'Sybase' => ['packages' => ['php8.4-sybase']], - 'Tidy' => ['packages' => ['php8.4-tidy']], - 'UOPZ' => ['packages' => ['php8.4-uopz']], - 'Upload progress' => ['packages' => ['php8.4-uploadprogress']], - 'UUID' => ['packages' => ['php8.4-uuid']], - 'Xdebug' => ['packages' => ['php8.4-xdebug']], - 'XMLRPC' => ['packages' => ['php8.4-xmlrpc']], - 'XSL' => ['packages' => ['php8.4-xsl']], - 'Yac' => ['packages' => ['php8.4-yac']], - 'YAML' => ['packages' => ['php8.4-yaml']], - 'ZMQ (ZeroMQ)' => ['packages' => ['php8.4-zmq']], + 'AMQP' => ['php8.4-amqp'], + 'AST' => ['php8.4-ast'], + 'Bcmath' => ['php8.4-bcmath'], + 'bzip2' => ['php8.4-bz2'], + 'CGI' => ['php8.4-cgi'], + 'DBA' => ['php8.4-dba'], + 'DS (Data Structures)' => ['php8.4-ds'], + 'Enchant' => ['php8.4-enchant'], + 'Excimer' => ['php8.4-excimer'], + 'GD' => ['php8.4-gd'], + 'Gearman' => ['php8.4-gearman'], + 'Gmagick (GraphicsMagick)' => ['php8.4-gmagick'], + 'GMP' => ['php8.4-gmp'], + 'GNUPG' => ['php8.4-gnupg'], + 'HTTP' => ['php8.4-http'], + 'igbinary' => ['php8.4-igbinary'], + 'ImageMagick' => ['php8.4-imagick'], + 'IMAP' => ['php8.4-imap'], + 'Interbase' => ['php8.4-interbase'], + 'Intl (Internationalisation)' => ['php8.4-intl'], + 'LDAP' => ['php8.4-ldap'], + 'Libvirt' => ['php8.4-libvirt-php'], + 'Mailparse' => ['php8.4-mailparse'], + 'MaxMind DB' => ['php8.4-maxminddb'], + 'mcrypt' => ['php8.4-mcrypt'], + 'Memcache' => ['php8.4-memcache'], + 'Memcached' => ['php8.4-memcached'], + 'MongoDB' => ['php8.4-mongodb'], + 'MessagePack' => ['php8.4-msgpack'], + 'MySQL' => ['php8.4-mysql'], + 'OAuth' => ['php8.4-oauth'], + 'ODBC' => ['php8.4-odbc'], + 'OpenTelemetry' => ['php8.4-opentelemetry'], + 'Pcov' => ['php8.4-pcov'], + 'PostgreSQL' => ['php8.4-pgsql'], + 'PostgreSQL (libpq)' => ['php8.4-pq'], + 'Phalcon 5' => ['php8.4-phalcon'], + 'PHPDBG' => ['php8.4-phpdbg'], + 'ps' => ['php8.4-ps'], + 'pspell' => ['php8.4-pspell'], + 'PSR' => ['php8.4-psr'], + 'raphf' => ['php8.4-raphf'], + 'Redis' => ['php8.4-redis'], + 'rrd' => ['php8.4-rrd'], + 'SNMP' => ['php8.4-snmp'], + 'SOAP' => ['php8.4-soap'], + 'SQLite3' => ['php8.4-sqlite3'], + 'ssh2' => ['php8.4-ssh2'], + 'STOMP protocol' => ['php8.4-stomp'], + 'Sybase' => ['php8.4-sybase'], + 'Tidy' => ['php8.4-tidy'], + 'UOPZ' => ['php8.4-uopz'], + 'Upload progress' => ['php8.4-uploadprogress'], + 'UUID' => ['php8.4-uuid'], + 'Xdebug' => ['php8.4-xdebug'], + 'XMLRPC' => ['php8.4-xmlrpc'], + 'XSL' => ['php8.4-xsl'], + 'Yac' => ['php8.4-yac'], + 'YAML' => ['php8.4-yaml'], + 'ZMQ (ZeroMQ)' => ['php8.4-zmq'], ]; } } diff --git a/src/PHPDocker/PhpExtension/Php85AvailableExtensions.php b/src/PHPDocker/PhpExtension/Php85AvailableExtensions.php index 4955c576..858bfe46 100644 --- a/src/PHPDocker/PhpExtension/Php85AvailableExtensions.php +++ b/src/PHPDocker/PhpExtension/Php85AvailableExtensions.php @@ -19,104 +19,104 @@ namespace App\PHPDocker\PhpExtension; -class Php85AvailableExtensions extends BaseAvailableExtensions +final class Php85AvailableExtensions extends BaseAvailableExtensions { /** * @inheritDoc - * @return array> + * @return array */ protected function getMandatoryExtensionsMap(): array { return [ - 'cURL' => ['packages' => ['php8.5-curl']], - 'MBSTRING' => ['packages' => ['php8.5-mbstring']], - 'OPCache' => ['packages' => ['php8.5-opcache']], - 'Readline' => ['packages' => ['php8.5-readline']], - 'XML' => ['packages' => ['php8.5-xml']], - 'Zip' => ['packages' => ['php8.5-zip']], + 'cURL' => ['php8.5-curl'], + 'MBSTRING' => ['php8.5-mbstring'], + 'OPCache' => ['php8.5-opcache'], + 'Readline' => ['php8.5-readline'], + 'XML' => ['php8.5-xml'], + 'Zip' => ['php8.5-zip'], ]; } /** * @inheritDoc - * @return array> + * @return array */ protected function getOptionalExtensionsMap(): array { return [ - // 'Decimal' => ['packages' => ['php8.5-decimal']], - // 'GRPC' => ['packages' => ['php8.5-grpc']], - // 'Inotify' => ['packages' => ['php8.5-inotify']], - // 'LZ4' => ['packages' => ['php8.5-lz4']], - // 'Protobuf' => ['packages' => ['php8.5-protobuf']], - // 'Pinba' => ['packages' => ['php8.5-pinba']], - // 'Samba Client' => ['packages' => ['php8.5-smbclient']], - // 'Solr' => ['packages' => ['php8.5-solr']], - // 'Swoole' => ['packages' => ['php8.5-swoole']], - // 'vips' => ['packages' => ['php8.5-vips']], - // 'Xhprof' => ['packages' => ['php8.5-xhprof']], - // 'zstd (Zstandard)' => ['packages' => ['php8.5-zstd']], + // 'Decimal' => ['php8.5-decimal'], + // 'GRPC' => ['php8.5-grpc'], + // 'Inotify' => ['php8.5-inotify'], + // 'LZ4' => ['php8.5-lz4'], + // 'Protobuf' => ['php8.5-protobuf'], + // 'Pinba' => ['php8.5-pinba'], + // 'Samba Client' => ['php8.5-smbclient'], + // 'Solr' => ['php8.5-solr'], + // 'Swoole' => ['php8.5-swoole'], + // 'vips' => ['php8.5-vips'], + // 'Xhprof' => ['php8.5-xhprof'], + // 'zstd (Zstandard)' => ['php8.5-zstd'], - 'AMQP' => ['packages' => ['php8.5-amqp']], - 'AST' => ['packages' => ['php8.5-ast']], - 'Bcmath' => ['packages' => ['php8.5-bcmath']], - 'bzip2' => ['packages' => ['php8.5-bz2']], - 'CGI' => ['packages' => ['php8.5-cgi']], - 'DBA' => ['packages' => ['php8.5-dba']], - 'DS (Data Structures)' => ['packages' => ['php8.5-ds']], - 'Enchant' => ['packages' => ['php8.5-enchant']], - 'Excimer' => ['packages' => ['php8.5-excimer']], - 'GD' => ['packages' => ['php8.5-gd']], - 'Gearman' => ['packages' => ['php8.5-gearman']], - 'Gmagick (GraphicsMagick)' => ['packages' => ['php8.5-gmagick']], - 'GMP' => ['packages' => ['php8.5-gmp']], - 'GNUPG' => ['packages' => ['php8.5-gnupg']], - 'HTTP' => ['packages' => ['php8.5-http']], - 'igbinary' => ['packages' => ['php8.5-igbinary']], - 'ImageMagick' => ['packages' => ['php8.5-imagick']], - 'IMAP' => ['packages' => ['php8.5-imap']], - 'Interbase' => ['packages' => ['php8.5-interbase']], - 'Intl (Internationalisation)' => ['packages' => ['php8.5-intl']], - 'LDAP' => ['packages' => ['php8.5-ldap']], - 'Libvirt' => ['packages' => ['php8.5-libvirt-php']], - 'Mailparse' => ['packages' => ['php8.5-mailparse']], - 'MaxMind DB' => ['packages' => ['php8.5-maxminddb']], - 'mcrypt' => ['packages' => ['php8.5-mcrypt']], - 'Memcache' => ['packages' => ['php8.5-memcache']], - 'Memcached' => ['packages' => ['php8.5-memcached']], - 'MongoDB' => ['packages' => ['php8.5-mongodb']], - 'MessagePack' => ['packages' => ['php8.5-msgpack']], - 'MySQL' => ['packages' => ['php8.5-mysql']], - 'OAuth' => ['packages' => ['php8.5-oauth']], - 'ODBC' => ['packages' => ['php8.5-odbc']], - 'OpenTelemetry' => ['packages' => ['php8.5-opentelemetry']], - 'Pcov' => ['packages' => ['php8.5-pcov']], - 'PostgreSQL' => ['packages' => ['php8.5-pgsql']], - 'PostgreSQL (libpq)' => ['packages' => ['php8.5-pq']], - 'Phalcon 5' => ['packages' => ['php8.5-phalcon']], - 'PHPDBG' => ['packages' => ['php8.5-phpdbg']], - 'ps' => ['packages' => ['php8.5-ps']], - 'pspell' => ['packages' => ['php8.5-pspell']], - 'PSR' => ['packages' => ['php8.5-psr']], - 'raphf' => ['packages' => ['php8.5-raphf']], - 'Redis' => ['packages' => ['php8.5-redis']], - 'rrd' => ['packages' => ['php8.5-rrd']], - 'SNMP' => ['packages' => ['php8.5-snmp']], - 'SOAP' => ['packages' => ['php8.5-soap']], - 'SQLite3' => ['packages' => ['php8.5-sqlite3']], - 'ssh2' => ['packages' => ['php8.5-ssh2']], - 'STOMP protocol' => ['packages' => ['php8.5-stomp']], - 'Sybase' => ['packages' => ['php8.5-sybase']], - 'Tidy' => ['packages' => ['php8.5-tidy']], - 'UOPZ' => ['packages' => ['php8.5-uopz']], - 'Upload progress' => ['packages' => ['php8.5-uploadprogress']], - 'UUID' => ['packages' => ['php8.5-uuid']], - 'Xdebug' => ['packages' => ['php8.5-xdebug']], - 'XMLRPC' => ['packages' => ['php8.5-xmlrpc']], - 'XSL' => ['packages' => ['php8.5-xsl']], - 'Yac' => ['packages' => ['php8.5-yac']], - 'YAML' => ['packages' => ['php8.5-yaml']], - 'ZMQ (ZeroMQ)' => ['packages' => ['php8.5-zmq']], + 'AMQP' => ['php8.5-amqp'], + 'AST' => ['php8.5-ast'], + 'Bcmath' => ['php8.5-bcmath'], + 'bzip2' => ['php8.5-bz2'], + 'CGI' => ['php8.5-cgi'], + 'DBA' => ['php8.5-dba'], + 'DS (Data Structures)' => ['php8.5-ds'], + 'Enchant' => ['php8.5-enchant'], + 'Excimer' => ['php8.5-excimer'], + 'GD' => ['php8.5-gd'], + 'Gearman' => ['php8.5-gearman'], + 'Gmagick (GraphicsMagick)' => ['php8.5-gmagick'], + 'GMP' => ['php8.5-gmp'], + 'GNUPG' => ['php8.5-gnupg'], + 'HTTP' => ['php8.5-http'], + 'igbinary' => ['php8.5-igbinary'], + 'ImageMagick' => ['php8.5-imagick'], + 'IMAP' => ['php8.5-imap'], + 'Interbase' => ['php8.5-interbase'], + 'Intl (Internationalisation)' => ['php8.5-intl'], + 'LDAP' => ['php8.5-ldap'], + 'Libvirt' => ['php8.5-libvirt-php'], + 'Mailparse' => ['php8.5-mailparse'], + 'MaxMind DB' => ['php8.5-maxminddb'], + 'mcrypt' => ['php8.5-mcrypt'], + 'Memcache' => ['php8.5-memcache'], + 'Memcached' => ['php8.5-memcached'], + 'MongoDB' => ['php8.5-mongodb'], + 'MessagePack' => ['php8.5-msgpack'], + 'MySQL' => ['php8.5-mysql'], + 'OAuth' => ['php8.5-oauth'], + 'ODBC' => ['php8.5-odbc'], + 'OpenTelemetry' => ['php8.5-opentelemetry'], + 'Pcov' => ['php8.5-pcov'], + 'PostgreSQL' => ['php8.5-pgsql'], + 'PostgreSQL (libpq)' => ['php8.5-pq'], + 'Phalcon 5' => ['php8.5-phalcon'], + 'PHPDBG' => ['php8.5-phpdbg'], + 'ps' => ['php8.5-ps'], + 'pspell' => ['php8.5-pspell'], + 'PSR' => ['php8.5-psr'], + 'raphf' => ['php8.5-raphf'], + 'Redis' => ['php8.5-redis'], + 'rrd' => ['php8.5-rrd'], + 'SNMP' => ['php8.5-snmp'], + 'SOAP' => ['php8.5-soap'], + 'SQLite3' => ['php8.5-sqlite3'], + 'ssh2' => ['php8.5-ssh2'], + 'STOMP protocol' => ['php8.5-stomp'], + 'Sybase' => ['php8.5-sybase'], + 'Tidy' => ['php8.5-tidy'], + 'UOPZ' => ['php8.5-uopz'], + 'Upload progress' => ['php8.5-uploadprogress'], + 'UUID' => ['php8.5-uuid'], + 'Xdebug' => ['php8.5-xdebug'], + 'XMLRPC' => ['php8.5-xmlrpc'], + 'XSL' => ['php8.5-xsl'], + 'Yac' => ['php8.5-yac'], + 'YAML' => ['php8.5-yaml'], + 'ZMQ (ZeroMQ)' => ['php8.5-zmq'], ]; } } diff --git a/src/PHPDocker/PhpExtension/PhpExtension.php b/src/PHPDocker/PhpExtension/PhpExtension.php index 62829498..f805918a 100644 --- a/src/PHPDocker/PhpExtension/PhpExtension.php +++ b/src/PHPDocker/PhpExtension/PhpExtension.php @@ -19,27 +19,24 @@ namespace App\PHPDocker\PhpExtension; /** - * Describes a PHP extension + * Describes a PHP extension. */ -class PhpExtension +final readonly class PhpExtension { - protected string $name; - - /** @var string[] */ - protected array $packages = []; + /** + * @param string[] $packages + */ + public function __construct( + private string $name, + private array $packages = [], + ) { + } public function getName(): string { return $this->name; } - public function setName(string $name): self - { - $this->name = $name; - - return $this; - } - /** * @return string[] */ @@ -47,11 +44,4 @@ public function getPackages(): array { return $this->packages; } - - public function addPackage(string $package): self - { - $this->packages[] = $package; - - return $this; - } } diff --git a/src/PHPDocker/Project/Project.php b/src/PHPDocker/Project/Project.php index 9f0235a4..772c73e0 100644 --- a/src/PHPDocker/Project/Project.php +++ b/src/PHPDocker/Project/Project.php @@ -19,37 +19,55 @@ namespace App\PHPDocker\Project; +use App\PHPDocker\Project\ServiceOptions\Clickhouse; +use App\PHPDocker\Project\ServiceOptions\Elasticsearch; +use App\PHPDocker\Project\ServiceOptions\GlobalOptions; +use App\PHPDocker\Project\ServiceOptions\Mailhog; +use App\PHPDocker\Project\ServiceOptions\MariaDB; +use App\PHPDocker\Project\ServiceOptions\Memcached; +use App\PHPDocker\Project\ServiceOptions\MySQL; +use App\PHPDocker\Project\ServiceOptions\Nginx; use App\PHPDocker\Project\ServiceOptions\Php; +use App\PHPDocker\Project\ServiceOptions\Postgres; +use App\PHPDocker\Project\ServiceOptions\Redis; /** * Defines a single project. */ -class Project +final readonly class Project { - private ServiceOptions\Nginx $nginxOptions; - private ServiceOptions\MySQL $mysqlOptions; - private ServiceOptions\MariaDB $mariadbOptions; - private ServiceOptions\Postgres $postgresOptions; - private ServiceOptions\Memcached $memcachedOptions; - private ServiceOptions\Redis $redisOptions; - private ServiceOptions\Mailhog $mailhogOptions; - private ServiceOptions\Elasticsearch $elasticsearchOptions; - private ServiceOptions\Clickhouse $clickhouseOptions; + private Nginx $nginxOptions; + private MySQL $mysqlOptions; + private MariaDB $mariadbOptions; + private Postgres $postgresOptions; + private Memcached $memcachedOptions; + private Redis $redisOptions; + private Mailhog $mailhogOptions; + private Elasticsearch $elasticsearchOptions; + private Clickhouse $clickhouseOptions; public function __construct( - private readonly Php $phpOptions, - private readonly ServiceOptions\GlobalOptions $globalOptions, + private Php $phpOptions, + private GlobalOptions $globalOptions, + ?Nginx $nginxOptions = null, + ?MySQL $mysqlOptions = null, + ?MariaDB $mariadbOptions = null, + ?Postgres $postgresOptions = null, + ?Memcached $memcachedOptions = null, + ?Redis $redisOptions = null, + ?Mailhog $mailhogOptions = null, + ?Elasticsearch $elasticsearchOptions = null, + ?Clickhouse $clickhouseOptions = null, ) { - // Initialise project properties - $this->nginxOptions = new ServiceOptions\Nginx(); - $this->mysqlOptions = new ServiceOptions\MySQL(); - $this->mariadbOptions = new ServiceOptions\MariaDB(); - $this->postgresOptions = new ServiceOptions\Postgres(); - $this->redisOptions = new ServiceOptions\Redis(); - $this->memcachedOptions = new ServiceOptions\Memcached(); - $this->mailhogOptions = new ServiceOptions\Mailhog(); - $this->elasticsearchOptions = new ServiceOptions\Elasticsearch(); - $this->clickhouseOptions = new ServiceOptions\Clickhouse(); + $this->nginxOptions = $nginxOptions ?? new Nginx(); + $this->mysqlOptions = $mysqlOptions ?? new MySQL(); + $this->mariadbOptions = $mariadbOptions ?? new MariaDB(); + $this->postgresOptions = $postgresOptions ?? new Postgres(); + $this->memcachedOptions = $memcachedOptions ?? new Memcached(); + $this->redisOptions = $redisOptions ?? new Redis(); + $this->mailhogOptions = $mailhogOptions ?? new Mailhog(); + $this->elasticsearchOptions = $elasticsearchOptions ?? new Elasticsearch(); + $this->clickhouseOptions = $clickhouseOptions ?? new Clickhouse(); } public function hasNginx(): bool @@ -57,7 +75,7 @@ public function hasNginx(): bool return $this->nginxOptions->isEnabled(); } - public function getNginxOptions(): ServiceOptions\Nginx + public function getNginxOptions(): Nginx { return $this->nginxOptions; } @@ -67,7 +85,7 @@ public function hasMysql(): bool return $this->mysqlOptions->isEnabled(); } - public function getMysqlOptions(): ServiceOptions\MySQL + public function getMysqlOptions(): MySQL { return $this->mysqlOptions; } @@ -77,7 +95,7 @@ public function hasMariadb(): bool return $this->mariadbOptions->isEnabled(); } - public function getMariadbOptions(): ServiceOptions\MariaDB + public function getMariadbOptions(): MariaDB { return $this->mariadbOptions; } @@ -87,17 +105,17 @@ public function hasPostgres(): bool return $this->postgresOptions->isEnabled(); } - public function getPostgresOptions(): ServiceOptions\Postgres + public function getPostgresOptions(): Postgres { return $this->postgresOptions; } - public function getPhpOptions(): ServiceOptions\Php + public function getPhpOptions(): Php { return $this->phpOptions; } - public function getMemcachedOptions(): ServiceOptions\Memcached + public function getMemcachedOptions(): Memcached { return $this->memcachedOptions; } @@ -107,7 +125,7 @@ public function hasMemcached(): bool return $this->memcachedOptions->isEnabled(); } - public function getRedisOptions(): ServiceOptions\Redis + public function getRedisOptions(): Redis { return $this->redisOptions; } @@ -117,7 +135,7 @@ public function hasRedis(): bool return $this->redisOptions->isEnabled(); } - public function getMailhogOptions(): ServiceOptions\Mailhog + public function getMailhogOptions(): Mailhog { return $this->mailhogOptions; } @@ -127,7 +145,7 @@ public function hasMailhog(): bool return $this->mailhogOptions->isEnabled(); } - public function getElasticsearchOptions(): ServiceOptions\Elasticsearch + public function getElasticsearchOptions(): Elasticsearch { return $this->elasticsearchOptions; } @@ -137,7 +155,7 @@ public function hasElasticsearch(): bool return $this->elasticsearchOptions->isEnabled(); } - public function getClickhouseOptions(): ServiceOptions\Clickhouse + public function getClickhouseOptions(): Clickhouse { return $this->clickhouseOptions; } @@ -147,7 +165,7 @@ public function hasClickhouse(): bool return $this->clickhouseOptions->isEnabled(); } - public function getGlobalOptions(): ServiceOptions\GlobalOptions + public function getGlobalOptions(): GlobalOptions { return $this->globalOptions; } diff --git a/src/PHPDocker/Project/ProjectFactory.php b/src/PHPDocker/Project/ProjectFactory.php new file mode 100644 index 00000000..9922add7 --- /dev/null +++ b/src/PHPDocker/Project/ProjectFactory.php @@ -0,0 +1,176 @@ + $formData + */ + public function fromFormData(array $formData): Project + { + /** @var array $phpData */ + $phpData = $formData['phpOptions']; + /** @var string[] $extensions */ + $extensions = $phpData['phpExtensions'] ?? []; + + /** @var array $globalOptionsData */ + $globalOptionsData = $formData['globalOptions']; + + /** @var array $mysqlData */ + $mysqlData = $formData['mysqlOptions']; + /** @var array $mariadbData */ + $mariadbData = $formData['mariadbOptions']; + /** @var array $postgresData */ + $postgresData = $formData['postgresOptions']; + /** @var array $elasticsearchData */ + $elasticsearchData = $formData['elasticsearchOptions']; + + return new Project( + phpOptions: new Php( + version: $this->stringValue($phpData, 'version'), + extensions: $extensions, + hasGit: $this->boolValue($phpData, 'hasGit'), + frontControllerPath: $this->stringValue($phpData, 'frontControllerPath'), + ), + globalOptions: new GlobalOptions( + basePort: $this->intValue($globalOptionsData, 'basePort'), + appPath: rtrim($this->stringValue($globalOptionsData, 'appPath'), '/'), + dockerWorkingDir: rtrim($this->stringValue($globalOptionsData, 'dockerWorkingDir'), '/'), + ), + nginxOptions: new Nginx(), + mysqlOptions: $this->buildMySqlOptions($mysqlData), + mariadbOptions: $this->buildMariaDbOptions($mariadbData), + postgresOptions: $this->buildPostgresOptions($postgresData), + memcachedOptions: new Memcached(enabled: $this->boolValue($formData, 'hasMemcached')), + redisOptions: new Redis(enabled: $this->boolValue($formData, 'hasRedis')), + mailhogOptions: new Mailhog(enabled: $this->boolValue($formData, 'hasMailhog')), + elasticsearchOptions: $this->buildElasticsearchOptions($elasticsearchData), + clickhouseOptions: new Clickhouse(enabled: $this->boolValue($formData, 'hasClickhouse')), + ); + } + + /** + * @param array $data + */ + private function buildMySqlOptions(array $data): ?MySQL + { + if ($data['hasMysql'] !== true) { + return null; + } + + return new MySQL( + version: $this->stringValue($data, 'version'), + rootPassword: $this->stringValue($data, 'rootPassword'), + databaseName: $this->stringValue($data, 'databaseName'), + username: $this->stringValue($data, 'username'), + password: $this->stringValue($data, 'password'), + enabled: true, + ); + } + + /** + * @param array $data + */ + private function buildMariaDbOptions(array $data): ?MariaDB + { + if ($data['hasMariadb'] !== true) { + return null; + } + + return new MariaDB( + version: $this->stringValue($data, 'version'), + rootPassword: $this->stringValue($data, 'rootPassword'), + databaseName: $this->stringValue($data, 'databaseName'), + username: $this->stringValue($data, 'username'), + password: $this->stringValue($data, 'password'), + enabled: true, + ); + } + + /** + * @param array $data + */ + private function buildPostgresOptions(array $data): ?Postgres + { + if ($data['hasPostgres'] !== true) { + return null; + } + + return new Postgres( + version: $this->stringValue($data, 'version'), + rootUser: $this->stringValue($data, 'rootUser'), + rootPassword: $this->stringValue($data, 'rootPassword'), + databaseName: $this->stringValue($data, 'databaseName'), + enabled: true, + ); + } + + /** + * @param array $data + */ + private function buildElasticsearchOptions(array $data): ?Elasticsearch + { + if ($data['hasElasticsearch'] !== true) { + return null; + } + + return new Elasticsearch( + version: $this->stringValue($data, 'version'), + enabled: true, + ); + } + + /** + * @param array $data + */ + private function stringValue(array $data, string $key): string + { + $value = $data[$key] ?? null; + if (is_string($value) || is_int($value) || is_float($value)) { + return (string) $value; + } + + throw new UnexpectedValueException(sprintf('Expected "%s" to be a scalar string value.', $key)); + } + + /** + * @param array $data + */ + private function intValue(array $data, string $key): int + { + $value = $data[$key] ?? null; + if (is_int($value)) { + return $value; + } + + throw new UnexpectedValueException(sprintf('Expected "%s" to be an integer value.', $key)); + } + + /** + * @param array $data + */ + private function boolValue(array $data, string $key): bool + { + $value = $data[$key] ?? null; + if (is_bool($value)) { + return $value; + } + + throw new UnexpectedValueException(sprintf('Expected "%s" to be a boolean value.', $key)); + } +} diff --git a/src/PHPDocker/Project/ServiceOptions/AbstractMySQL.php b/src/PHPDocker/Project/ServiceOptions/AbstractMySQL.php index 021fb1ff..9d2ccce8 100644 --- a/src/PHPDocker/Project/ServiceOptions/AbstractMySQL.php +++ b/src/PHPDocker/Project/ServiceOptions/AbstractMySQL.php @@ -26,11 +26,11 @@ */ abstract class AbstractMySQL extends Base { - protected string $version; - protected ?string $rootPassword; - protected ?string $databaseName; - protected ?string $username; - protected ?string $password; + private readonly string $version; + private readonly ?string $rootPassword; + private readonly ?string $databaseName; + private readonly ?string $username; + private readonly ?string $password; /** * Return an array of available versions, like so: @@ -43,32 +43,35 @@ abstract class AbstractMySQL extends Base */ abstract public static function getChoices(): array; - public function getVersion(): string - { - return $this->version; - } + public function __construct( + string $version, + ?string $rootPassword = null, + ?string $databaseName = null, + ?string $username = null, + ?string $password = null, + bool $enabled = false, + ) { + parent::__construct($enabled); - public function setVersion(string $version): self - { if (array_key_exists($version, static::getChoices()) === false) { throw new InvalidArgumentException(sprintf('Version %s is not supported', $version)); } - $this->version = $version; - - return $this; + $this->version = $version; + $this->rootPassword = $rootPassword; + $this->databaseName = $databaseName; + $this->username = $username; + $this->password = $password; } - public function getRootPassword(): ?string + public function getVersion(): string { - return $this->rootPassword; + return $this->version; } - public function setRootPassword(?string $rootPassword): self + public function getRootPassword(): ?string { - $this->rootPassword = $rootPassword; - - return $this; + return $this->rootPassword; } public function getDatabaseName(): ?string @@ -76,34 +79,13 @@ public function getDatabaseName(): ?string return $this->databaseName; } - public function setDatabaseName(?string $databaseName): self - { - $this->databaseName = $databaseName; - - return $this; - } - public function getUsername(): ?string { return $this->username; } - public function setUsername(?string $username): self - { - $this->username = $username; - - return $this; - } - public function getPassword(): ?string { return $this->password; } - - public function setPassword(?string $password): self - { - $this->password = $password; - - return $this; - } } diff --git a/src/PHPDocker/Project/ServiceOptions/Base.php b/src/PHPDocker/Project/ServiceOptions/Base.php index e2e0ba2c..91d5d8db 100644 --- a/src/PHPDocker/Project/ServiceOptions/Base.php +++ b/src/PHPDocker/Project/ServiceOptions/Base.php @@ -23,18 +23,13 @@ */ abstract class Base { - protected bool $enabled = false; - - public function isEnabled(): bool + public function __construct(private readonly bool $enabled = false) { - return $this->enabled; } - public function setEnabled(bool $enabled): static + public function isEnabled(): bool { - $this->enabled = $enabled; - - return $this; + return $this->enabled; } /** diff --git a/src/PHPDocker/Project/ServiceOptions/Clickhouse.php b/src/PHPDocker/Project/ServiceOptions/Clickhouse.php index 55a3bfda..5b6d45d2 100644 --- a/src/PHPDocker/Project/ServiceOptions/Clickhouse.php +++ b/src/PHPDocker/Project/ServiceOptions/Clickhouse.php @@ -21,6 +21,10 @@ /** * Options for clickhouse container */ -class Clickhouse extends Base +final class Clickhouse extends Base { + public function __construct(bool $enabled = false) + { + parent::__construct($enabled); + } } diff --git a/src/PHPDocker/Project/ServiceOptions/Elasticsearch.php b/src/PHPDocker/Project/ServiceOptions/Elasticsearch.php index 4073dcb0..9a149154 100644 --- a/src/PHPDocker/Project/ServiceOptions/Elasticsearch.php +++ b/src/PHPDocker/Project/ServiceOptions/Elasticsearch.php @@ -19,47 +19,45 @@ namespace App\PHPDocker\Project\ServiceOptions; -use InvalidArgumentException; - /** * Options for Elasticsearch container. */ -class Elasticsearch extends Base +final class Elasticsearch extends Base { - /** - * Available versions - */ - private const string VERSION_56 = '5.6'; private const string VERSION_65 = '6.5.4'; - private const array ALLOWED_VERSIONS = [ - self::VERSION_65 => '6.5.x', - self::VERSION_56 => '5.6.x', - ]; + private readonly string $version; + + public function __construct(string $version = self::VERSION_65, bool $enabled = false) + { + parent::__construct($enabled); - private string $version = self::VERSION_65; + $this->version = self::fromString($version)->value; + } public function getVersion(): string { return $this->version; } - public function setVersion(string $version): self + /** + * @return array + */ + public static function getChoices(): array { - if (array_key_exists($version, self::ALLOWED_VERSIONS) === false) { - throw new InvalidArgumentException(sprintf('Version %s is not supported', $version)); - } - - $this->version = $version; - - return $this; + return self::choices(); } /** * @return array */ - public static function getChoices(): array + private static function choices(): array + { + return ElasticsearchVersion::choices(); + } + + private static function fromString(string $version): ElasticsearchVersion { - return self::ALLOWED_VERSIONS; + return ElasticsearchVersion::fromString($version); } } diff --git a/src/PHPDocker/Project/ServiceOptions/ElasticsearchVersion.php b/src/PHPDocker/Project/ServiceOptions/ElasticsearchVersion.php new file mode 100644 index 00000000..bf3bf455 --- /dev/null +++ b/src/PHPDocker/Project/ServiceOptions/ElasticsearchVersion.php @@ -0,0 +1,64 @@ + + */ + public static function choices(): array + { + $choices = []; + + foreach (self::cases() as $version) { + $choices[$version->value] = $version->label(); + } + + return $choices; + } + + /** + * @return string[] + */ + public static function values(): array + { + return array_map(static fn (self $version): string => $version->value, self::cases()); + } + + public static function fromString(string $version): self + { + return self::tryFrom($version) ?? throw new InvalidArgumentException(sprintf('Version %s is not supported', $version)); + } + + private function label(): string + { + return match ($this) { + self::V65 => '6.5.x', + self::V56 => '5.6.x', + }; + } +} diff --git a/src/PHPDocker/Project/ServiceOptions/GlobalOptions.php b/src/PHPDocker/Project/ServiceOptions/GlobalOptions.php index 393d4e24..dc7ba2b7 100644 --- a/src/PHPDocker/Project/ServiceOptions/GlobalOptions.php +++ b/src/PHPDocker/Project/ServiceOptions/GlobalOptions.php @@ -3,11 +3,13 @@ namespace App\PHPDocker\Project\ServiceOptions; -final class GlobalOptions extends Base +final readonly class GlobalOptions { - - public function __construct(private readonly int $basePort, private readonly string $appPath, private readonly string $dockerWorkingDir) - { + public function __construct( + private int $basePort, + private string $appPath, + private string $dockerWorkingDir, + ) { } public function getBasePort(): int diff --git a/src/PHPDocker/Project/ServiceOptions/Mailhog.php b/src/PHPDocker/Project/ServiceOptions/Mailhog.php index c670ec05..33744b5d 100644 --- a/src/PHPDocker/Project/ServiceOptions/Mailhog.php +++ b/src/PHPDocker/Project/ServiceOptions/Mailhog.php @@ -21,9 +21,14 @@ /** * Options for Mailhog container. */ -class Mailhog extends Base +final class Mailhog extends Base { - protected function getExternalPortOffset(): ?int + public function __construct(bool $enabled = false) + { + parent::__construct($enabled); + } + + protected function getExternalPortOffset(): int { return 1; } diff --git a/src/PHPDocker/Project/ServiceOptions/MariaDB.php b/src/PHPDocker/Project/ServiceOptions/MariaDB.php index 1d930fe8..2dac14fd 100644 --- a/src/PHPDocker/Project/ServiceOptions/MariaDB.php +++ b/src/PHPDocker/Project/ServiceOptions/MariaDB.php @@ -21,42 +21,29 @@ /** * Options for MariaDB container. */ -class MariaDB extends AbstractMySQL +final class MariaDB extends AbstractMySQL { - /** - * Available versions - */ - private const string VERSION_104 = '10.4'; - private const string VERSION_105 = '10.5'; - private const string VERSION_106 = '10.6'; - private const string VERSION_107 = '10.7'; - private const string VERSION_108 = '10.8'; - private const string VERSION_109 = '10.9'; - private const string VERSION_1010 = '10.10'; - private const string VERSION_1011 = '10.11'; - private const string VERSION_110 = '11.0'; - - private const array ALLOWED_VERSIONS = [ - self::VERSION_110 => '11.0.x', - self::VERSION_1011 => '10.11.x', - self::VERSION_1010 => '10.10.x', - self::VERSION_109 => '10.9.x', - self::VERSION_108 => '10.8.x', - self::VERSION_107 => '10.7.x', - self::VERSION_106 => '10.6.x', - self::VERSION_105 => '10.5.x', - self::VERSION_104 => '10.4.x', - ]; + private const string VERSION_110 = '11.0'; - /** - * Set default version. - */ - public function __construct() - { - $this->version = self::VERSION_110; + public function __construct( + string $version = self::VERSION_110, + ?string $rootPassword = null, + ?string $databaseName = null, + ?string $username = null, + ?string $password = null, + bool $enabled = false, + ) { + parent::__construct( + version: $version, + rootPassword: $rootPassword, + databaseName: $databaseName, + username: $username, + password: $password, + enabled: $enabled, + ); } - protected function getExternalPortOffset(): ?int + protected function getExternalPortOffset(): int { return 3; } @@ -67,6 +54,14 @@ protected function getExternalPortOffset(): ?int */ public static function getChoices(): array { - return self::ALLOWED_VERSIONS; + return self::choices(); + } + + /** + * @return array + */ + private static function choices(): array + { + return MariaDBVersion::choices(); } } diff --git a/src/PHPDocker/Project/ServiceOptions/MariaDBVersion.php b/src/PHPDocker/Project/ServiceOptions/MariaDBVersion.php new file mode 100644 index 00000000..b30cc6e7 --- /dev/null +++ b/src/PHPDocker/Project/ServiceOptions/MariaDBVersion.php @@ -0,0 +1,77 @@ + + */ + public static function choices(): array + { + $choices = []; + + foreach (self::cases() as $version) { + $choices[$version->value] = $version->label(); + } + + return $choices; + } + + /** + * @return string[] + */ + public static function values(): array + { + return array_map(static fn (self $version): string => $version->value, self::cases()); + } + + public static function fromString(string $version): self + { + return self::tryFrom($version) ?? throw new InvalidArgumentException(sprintf('Version %s is not supported', $version)); + } + + private function label(): string + { + return match ($this) { + self::V110 => '11.0.x', + self::V1011 => '10.11.x', + self::V1010 => '10.10.x', + self::V109 => '10.9.x', + self::V108 => '10.8.x', + self::V107 => '10.7.x', + self::V106 => '10.6.x', + self::V105 => '10.5.x', + self::V104 => '10.4.x', + }; + } +} diff --git a/src/PHPDocker/Project/ServiceOptions/Memcached.php b/src/PHPDocker/Project/ServiceOptions/Memcached.php index 93dcc302..cbc3da78 100644 --- a/src/PHPDocker/Project/ServiceOptions/Memcached.php +++ b/src/PHPDocker/Project/ServiceOptions/Memcached.php @@ -21,8 +21,13 @@ /** * Options for Memcached container. */ -class Memcached extends Base +final class Memcached extends Base { + public function __construct(bool $enabled = false) + { + parent::__construct($enabled); + } + public function getContainerNameSuffix(): string { return 'memcached'; diff --git a/src/PHPDocker/Project/ServiceOptions/MySQL.php b/src/PHPDocker/Project/ServiceOptions/MySQL.php index d4b4d94c..21c7c2a8 100644 --- a/src/PHPDocker/Project/ServiceOptions/MySQL.php +++ b/src/PHPDocker/Project/ServiceOptions/MySQL.php @@ -21,29 +21,29 @@ /** * Options for MySQL container. */ -class MySQL extends AbstractMySQL +final class MySQL extends AbstractMySQL { - /** - * Available versions - */ - private const string VERSION_55 = '5.5'; - private const string VERSION_56 = '5.6'; - private const string VERSION_57 = '5.7'; private const string VERSION_80 = '8.0'; - private const array ALLOWED_VERSIONS = [ - self::VERSION_80 => '8.0', - self::VERSION_57 => '5.7.x', - self::VERSION_56 => '5.6.x', - self::VERSION_55 => '5.5.x', - ]; - - public function __construct() - { - $this->version = self::VERSION_80; + public function __construct( + string $version = self::VERSION_80, + ?string $rootPassword = null, + ?string $databaseName = null, + ?string $username = null, + ?string $password = null, + bool $enabled = false, + ) { + parent::__construct( + version: $version, + rootPassword: $rootPassword, + databaseName: $databaseName, + username: $username, + password: $password, + enabled: $enabled, + ); } - protected function getExternalPortOffset(): ?int + protected function getExternalPortOffset(): int { return 2; } @@ -54,6 +54,14 @@ protected function getExternalPortOffset(): ?int */ public static function getChoices(): array { - return self::ALLOWED_VERSIONS; + return self::choices(); + } + + /** + * @return array + */ + private static function choices(): array + { + return MySQLVersion::choices(); } } diff --git a/src/PHPDocker/Project/ServiceOptions/MySQLVersion.php b/src/PHPDocker/Project/ServiceOptions/MySQLVersion.php new file mode 100644 index 00000000..375a8f36 --- /dev/null +++ b/src/PHPDocker/Project/ServiceOptions/MySQLVersion.php @@ -0,0 +1,67 @@ + + */ + public static function choices(): array + { + $choices = []; + + foreach (self::cases() as $version) { + $choices[$version->value] = $version->label(); + } + + return $choices; + } + + /** + * @return string[] + */ + public static function values(): array + { + return array_map(static fn (self $version): string => $version->value, self::cases()); + } + + public static function fromString(string $version): self + { + return self::tryFrom($version) ?? throw new InvalidArgumentException(sprintf('Version %s is not supported', $version)); + } + + private function label(): string + { + return match ($this) { + self::V80 => '8.0', + self::V57 => '5.7.x', + self::V56 => '5.6.x', + self::V55 => '5.5.x', + }; + } +} diff --git a/src/PHPDocker/Project/ServiceOptions/Nginx.php b/src/PHPDocker/Project/ServiceOptions/Nginx.php index 461d2bff..19e57229 100644 --- a/src/PHPDocker/Project/ServiceOptions/Nginx.php +++ b/src/PHPDocker/Project/ServiceOptions/Nginx.php @@ -21,10 +21,10 @@ /** * Options for nginx container. */ -class Nginx extends Base +final class Nginx extends Base { - public function __construct() + public function __construct(bool $enabled = true) { - $this->setEnabled(true); + parent::__construct($enabled); } } diff --git a/src/PHPDocker/Project/ServiceOptions/Php.php b/src/PHPDocker/Project/ServiceOptions/Php.php index 65c89a2c..16a62c2b 100644 --- a/src/PHPDocker/Project/ServiceOptions/Php.php +++ b/src/PHPDocker/Project/ServiceOptions/Php.php @@ -21,32 +21,16 @@ use App\PHPDocker\PhpExtension\AvailableExtensionsFactory; use App\PHPDocker\PhpExtension\PhpExtension; -use InvalidArgumentException; /** * Options for PHP container. */ -class Php extends Base +final class Php extends Base { - public const string PHP_VERSION_82 = '8.2'; - public const string PHP_VERSION_83 = '8.3'; - public const string PHP_VERSION_84 = '8.4'; - public const string PHP_VERSION_85 = '8.5'; - - private string $version; + private readonly string $version; /** @var PhpExtension[] */ - private array $extensions = []; - - /** - * Supported PHP versions - */ - private const array SUPPORTED_VERSIONS = [ - self::PHP_VERSION_85, - self::PHP_VERSION_84, - self::PHP_VERSION_83, - self::PHP_VERSION_82, - ]; + private readonly array $extensions; /** * @param string[] $extensions @@ -58,19 +42,17 @@ public function __construct( private readonly bool $hasGit, private readonly string $frontControllerPath ) { - $this->setEnabled(true); + parent::__construct(true); - // Validate & set version - if (in_array($version, self::SUPPORTED_VERSIONS, true) === false) { - throw new InvalidArgumentException(sprintf('PHP version specified (%s) is unsupported', $version)); - } - - $this->version = $version; + $this->version = self::fromString($version)->value; // Parse extensions + $parsedExtensions = []; foreach ($extensions as $phpExtension) { - $this->addExtensionByName($phpExtension); + $parsedExtensions[] = $this->addExtensionByName($phpExtension); } + + $this->extensions = $parsedExtensions; } public function getVersion(): string @@ -98,25 +80,29 @@ public function getExtensions(): array */ public static function getSupportedVersions(): array { - return self::SUPPORTED_VERSIONS; + return self::values(); } /** * Adds an extension given the name only. */ - private function addExtensionByName(string $extensionName): void + private function addExtensionByName(string $extensionName): PhpExtension { - static $extensionInstance; - - if ($extensionInstance === null) { - $extensionInstance = AvailableExtensionsFactory::create($this->getVersion()); - } - - $this->extensions[] = $extensionInstance->getPhpExtension($extensionName); + return AvailableExtensionsFactory::create($this->getVersion())->getPhpExtension($extensionName); } public function getFrontControllerPath(): string { return $this->frontControllerPath; } + + private static function values(): array + { + return PhpVersion::values(); + } + + private static function fromString(string $version): PhpVersion + { + return PhpVersion::fromString($version); + } } diff --git a/src/PHPDocker/Project/ServiceOptions/PhpVersion.php b/src/PHPDocker/Project/ServiceOptions/PhpVersion.php new file mode 100644 index 00000000..391f00ac --- /dev/null +++ b/src/PHPDocker/Project/ServiceOptions/PhpVersion.php @@ -0,0 +1,44 @@ + $version->value, self::cases()); + } + + public static function fromString(string $version): self + { + return self::tryFrom($version) ?? throw new InvalidArgumentException(sprintf('PHP version specified (%s) is unsupported', $version)); + } +} diff --git a/src/PHPDocker/Project/ServiceOptions/Postgres.php b/src/PHPDocker/Project/ServiceOptions/Postgres.php index 0862026d..e3f5756b 100644 --- a/src/PHPDocker/Project/ServiceOptions/Postgres.php +++ b/src/PHPDocker/Project/ServiceOptions/Postgres.php @@ -19,40 +19,34 @@ namespace App\PHPDocker\Project\ServiceOptions; -use InvalidArgumentException; - /** * Postgres configuration */ -class Postgres extends Base +final class Postgres extends Base { - /** - * Available versions - */ private const string VERSION_15 = '15'; - private const string VERSION_14 = '14'; - private const string VERSION_13 = '13'; - private const string VERSION_12 = '12'; - private const string VERSION_11 = '11'; - private const string VERSION_10 = '10'; - private const string VERSION_96 = '9.6'; - - private const array ALLOWED_VERSIONS = [ - self::VERSION_15 => '15.x', - self::VERSION_14 => '14.x', - self::VERSION_13 => '13.x', - self::VERSION_12 => '12.x', - self::VERSION_11 => '11.x', - self::VERSION_10 => '10.x', - self::VERSION_96 => '9.6.x', - ]; - private string $version = self::VERSION_15; - private string $rootUser; - private string $rootPassword; - private string $databaseName; + private readonly string $version; + private readonly string $rootUser; + private readonly string $rootPassword; + private readonly string $databaseName; + + public function __construct( + string $version = self::VERSION_15, + string $rootUser = '', + string $rootPassword = '', + string $databaseName = '', + bool $enabled = false, + ) { + parent::__construct($enabled); + + $this->version = self::fromString($version)->value; + $this->rootUser = $rootUser; + $this->rootPassword = $rootPassword; + $this->databaseName = $databaseName; + } - protected function getExternalPortOffset(): ?int + protected function getExternalPortOffset(): int { return 4; } @@ -62,59 +56,39 @@ public function getVersion(): string return $this->version; } - public function setVersion(string $version): self - { - if (array_key_exists($version, self::ALLOWED_VERSIONS) === false) { - throw new InvalidArgumentException(sprintf('Version %s is not supported', $version)); - } - - $this->version = $version; - - return $this; - } - public function getRootUser(): string { return $this->rootUser; } - public function setRootUser(string $rootUser): self - { - $this->rootUser = $rootUser; - - return $this; - } - public function getRootPassword(): string { return $this->rootPassword; } - public function setRootPassword(string $rootPassword): self - { - $this->rootPassword = $rootPassword; - - return $this; - } - public function getDatabaseName(): string { return $this->databaseName; } - public function setDatabaseName(string $databaseName): self + /** + * @return array + */ + public static function getChoices(): array { - $this->databaseName = $databaseName; - - return $this; + return self::choices(); } /** - * @return array + * @return array */ - public static function getChoices(): array + private static function choices(): array + { + return PostgresVersion::choices(); + } + + private static function fromString(string $version): PostgresVersion { - // @phpstan-ignore return.type (numeric string keys become int at runtime) - return self::ALLOWED_VERSIONS; + return PostgresVersion::fromString($version); } } diff --git a/src/PHPDocker/Project/ServiceOptions/PostgresVersion.php b/src/PHPDocker/Project/ServiceOptions/PostgresVersion.php new file mode 100644 index 00000000..dfbb3dcc --- /dev/null +++ b/src/PHPDocker/Project/ServiceOptions/PostgresVersion.php @@ -0,0 +1,74 @@ + + */ + public static function choices(): array + { + $choices = []; + + foreach (self::cases() as $version) { + $choices[$version->value] = $version->label(); + } + + return $choices; + } + + /** + * @return string[] + */ + public static function values(): array + { + return array_map(static fn (self $version): string => $version->value, self::cases()); + } + + public static function fromString(string $version): self + { + return self::tryFrom($version) ?? throw new InvalidArgumentException(sprintf('Version %s is not supported', $version)); + } + + private function label(): string + { + return match ($this) { + self::V15 => '15.x', + self::V14 => '14.x', + self::V13 => '13.x', + self::V12 => '12.x', + self::V11 => '11.x', + self::V10 => '10.x', + self::V96 => '9.6.x', + }; + } +} diff --git a/src/PHPDocker/Project/ServiceOptions/Redis.php b/src/PHPDocker/Project/ServiceOptions/Redis.php index b630336e..cb9b9e72 100644 --- a/src/PHPDocker/Project/ServiceOptions/Redis.php +++ b/src/PHPDocker/Project/ServiceOptions/Redis.php @@ -21,6 +21,10 @@ /** * Options for redis container */ -class Redis extends Base +final class Redis extends Base { + public function __construct(bool $enabled = false) + { + parent::__construct($enabled); + } } diff --git a/src/PHPDocker/Zip/Archiver.php b/src/PHPDocker/Zip/Archiver.php index 31052208..34ee5720 100644 --- a/src/PHPDocker/Zip/Archiver.php +++ b/src/PHPDocker/Zip/Archiver.php @@ -26,17 +26,14 @@ /** * Creates a zip file. */ -class Archiver +final class Archiver { - /** @var string[] */ - protected array $files = []; - protected string $baseFolder = ''; - private ZipArchive $zipFile; + private readonly ZipArchive $zipFile; /** * Initialise Zip File via the zip PECL extension into a temporary file on local storage. */ - public function __construct() + public function __construct(private readonly string $baseFolder = '') { $this->zipFile = new ZipArchive(); @@ -72,22 +69,7 @@ public function generateArchive(string $archiveFilename): ArchiveInterface throw new Exception\ArchiveNotCreatedException('Archive creation failed for an unknown reason'); } - $file = new File(); - $file - ->setFilename($archiveFilename) - ->setTmpFilename($filename); - - return $file; - } - - /** - * Sets the base folder all given files will be added into. - */ - public function setBaseFolder(string $baseFolder): self - { - $this->baseFolder = $baseFolder; - - return $this; + return new File($archiveFilename, $filename); } /** diff --git a/src/PHPDocker/Zip/File.php b/src/PHPDocker/Zip/File.php index 47b7f8b1..d0bd4ca9 100644 --- a/src/PHPDocker/Zip/File.php +++ b/src/PHPDocker/Zip/File.php @@ -24,32 +24,21 @@ /** * Represents a zip file. */ -class File implements ArchiveInterface +final readonly class File implements ArchiveInterface { - protected string $filename; - protected string $tmpFilename; + public function __construct( + private string $filename, + private string $tmpFilename, + ) { + } public function getFilename(): string { return $this->filename; } - public function setFilename(string $filename): self - { - $this->filename = $filename; - - return $this; - } - public function getTmpFilename(): string { return $this->tmpFilename; } - - public function setTmpFilename(string $tmpFilename): self - { - $this->tmpFilename = $tmpFilename; - - return $this; - } } diff --git a/tests/Unit/PHPDocker/PhpExtension/BaseAvailableExtensionsTest.php b/tests/Unit/PHPDocker/PhpExtension/BaseAvailableExtensionsTest.php index e1bbc89a..a532ea66 100644 --- a/tests/Unit/PHPDocker/PhpExtension/BaseAvailableExtensionsTest.php +++ b/tests/Unit/PHPDocker/PhpExtension/BaseAvailableExtensionsTest.php @@ -19,10 +19,15 @@ protected function setUp(): void } #[Test] - public function getAllReturnsNonEmptyArray(): void + public function getAllReturnsPhpExtensionInstancesIndexedByName(): void { $all = $this->extensions->getAll(); + self::assertNotEmpty($all); + self::assertArrayHasKey('Xdebug', $all); + self::assertContainsOnlyInstancesOf(PhpExtension::class, $all); + self::assertSame('Xdebug', $all['Xdebug']->getName()); + self::assertContains('php8.4-xdebug', $all['Xdebug']->getPackages()); } #[Test] @@ -49,8 +54,10 @@ public function isAvailableReturnsFalseForUnknownExtension(): void public function getPhpExtensionReturnsCorrectExtension(): void { $ext = $this->extensions->getPhpExtension('Xdebug'); + self::assertInstanceOf(PhpExtension::class, $ext); self::assertSame('Xdebug', $ext->getName()); + self::assertContains('php8.4-xdebug', $ext->getPackages()); } #[Test] @@ -64,16 +71,10 @@ public function getPhpExtensionThrowsForUnknownExtension(): void public function getOptionalReturnsArrayOfPhpExtensionObjects(): void { $optional = $this->extensions->getOptional(); + self::assertNotEmpty($optional); foreach ($optional as $ext) { self::assertInstanceOf(PhpExtension::class, $ext); } } - - #[Test] - public function extensionPackagesAreMappedCorrectly(): void - { - $ext = $this->extensions->getPhpExtension('Xdebug'); - self::assertContains('php8.4-xdebug', $ext->getPackages()); - } } diff --git a/tests/Unit/PHPDocker/PhpExtension/PhpExtensionTest.php b/tests/Unit/PHPDocker/PhpExtension/PhpExtensionTest.php new file mode 100644 index 00000000..56b7f86d --- /dev/null +++ b/tests/Unit/PHPDocker/PhpExtension/PhpExtensionTest.php @@ -0,0 +1,30 @@ +isFinal()); + self::assertTrue($reflection->isReadOnly()); + } + + #[Test] + public function itExposesNameAndPackagesFromConstructor(): void + { + $extension = new PhpExtension('Xdebug', ['php8.4-xdebug']); + + self::assertSame('Xdebug', $extension->getName()); + self::assertSame(['php8.4-xdebug'], $extension->getPackages()); + } +} diff --git a/tests/Unit/PHPDocker/Project/ProjectFactoryTest.php b/tests/Unit/PHPDocker/Project/ProjectFactoryTest.php new file mode 100644 index 00000000..656682ca --- /dev/null +++ b/tests/Unit/PHPDocker/Project/ProjectFactoryTest.php @@ -0,0 +1,118 @@ +fromFormData($this->formData()); + + self::assertSame('8.4', $project->getPhpOptions()->getVersion()); + self::assertSame('.', $project->getGlobalOptions()->getAppPath()); + self::assertSame('/application', $project->getGlobalOptions()->getDockerWorkingDir()); + self::assertTrue($project->hasNginx()); + self::assertFalse($project->hasMysql()); + self::assertFalse($project->hasRedis()); + } + + #[Test] + public function fromFormDataBuildsEnabledServices(): void + { + $project = (new ProjectFactory())->fromFormData($this->formData([ + 'hasMemcached' => true, + 'hasRedis' => true, + 'hasMailhog' => true, + 'hasClickhouse' => true, + 'mysqlOptions' => [ + 'hasMysql' => true, + 'version' => '5.7', + 'rootPassword' => 'root', + 'databaseName' => 'app', + 'username' => 'user', + 'password' => 'pass', + ], + 'postgresOptions' => [ + 'hasPostgres' => true, + 'version' => 14, + 'rootUser' => 'pguser', + 'rootPassword' => 'pgpass', + 'databaseName' => 'pgdb', + ], + 'elasticsearchOptions' => [ + 'hasElasticsearch' => true, + 'version' => '5.6', + ], + ])); + + self::assertTrue($project->hasMemcached()); + self::assertTrue($project->hasRedis()); + self::assertTrue($project->hasMailhog()); + self::assertTrue($project->hasClickhouse()); + self::assertTrue($project->hasMysql()); + self::assertSame('5.7', $project->getMysqlOptions()->getVersion()); + self::assertTrue($project->hasPostgres()); + self::assertSame('14', $project->getPostgresOptions()->getVersion()); + self::assertTrue($project->hasElasticsearch()); + self::assertSame('5.6', $project->getElasticsearchOptions()->getVersion()); + } + + /** + * @param array $overrides + * + * @return array + */ + private function formData(array $overrides = []): array + { + return array_replace_recursive([ + 'hasMemcached' => false, + 'hasRedis' => false, + 'hasMailhog' => false, + 'hasClickhouse' => false, + 'phpOptions' => [ + 'version' => '8.4', + 'phpExtensions' => [], + 'hasGit' => false, + 'frontControllerPath' => 'public/index.php', + ], + 'globalOptions' => [ + 'basePort' => 8000, + 'appPath' => './', + 'dockerWorkingDir' => '/application/', + ], + 'mysqlOptions' => [ + 'hasMysql' => false, + 'version' => '8.0', + 'rootPassword' => '', + 'databaseName' => '', + 'username' => '', + 'password' => '', + ], + 'mariadbOptions' => [ + 'hasMariadb' => false, + 'version' => '11.0', + 'rootPassword' => '', + 'databaseName' => '', + 'username' => '', + 'password' => '', + ], + 'postgresOptions' => [ + 'hasPostgres' => false, + 'version' => '15', + 'rootUser' => '', + 'rootPassword' => '', + 'databaseName' => '', + ], + 'elasticsearchOptions' => [ + 'hasElasticsearch' => false, + 'version' => '6.5.4', + ], + ], $overrides); + } +} diff --git a/tests/Unit/PHPDocker/Project/ProjectTest.php b/tests/Unit/PHPDocker/Project/ProjectTest.php index 7307eaf6..aaf7fd80 100644 --- a/tests/Unit/PHPDocker/Project/ProjectTest.php +++ b/tests/Unit/PHPDocker/Project/ProjectTest.php @@ -31,16 +31,20 @@ public function elasticsearchOptionsArePresentDisabledByDefaultAndReflectEnabled self::assertFalse($project->hasElasticsearch()); self::assertInstanceOf(Elasticsearch::class, $project->getElasticsearchOptions()); - $project->getElasticsearchOptions()->setEnabled(true); + $project = $this->createProject( + elasticsearchOptions: new Elasticsearch(enabled: true), + ); self::assertTrue($project->hasElasticsearch()); } - private function createProject(): Project + private function createProject(?Elasticsearch $elasticsearchOptions = null): Project { return new Project( new Php('8.4', [], false, 'index.php'), new GlobalOptions(8000, './', '/application'), + nginxOptions: new Nginx(), + elasticsearchOptions: $elasticsearchOptions, ); } } diff --git a/tests/Unit/PHPDocker/Project/ServiceOptions/BaseTest.php b/tests/Unit/PHPDocker/Project/ServiceOptions/BaseTest.php index 8b227ce1..1d1aa8db 100644 --- a/tests/Unit/PHPDocker/Project/ServiceOptions/BaseTest.php +++ b/tests/Unit/PHPDocker/Project/ServiceOptions/BaseTest.php @@ -23,18 +23,11 @@ public function isEnabledReturnsFalseByDefault(): void } #[Test] - public function setEnabledTrueReturnsTrue(): void + public function constructorWithEnabledTrueReturnsTrue(): void { - $this->service->setEnabled(true); - self::assertTrue($this->service->isEnabled()); - } + $service = new class(true) extends Base {}; - #[Test] - public function setEnabledFalseReturnsFalse(): void - { - $this->service->setEnabled(true); - $this->service->setEnabled(false); - self::assertFalse($this->service->isEnabled()); + self::assertTrue($service->isEnabled()); } #[Test] diff --git a/tests/Unit/PHPDocker/Project/ServiceOptions/ElasticsearchTest.php b/tests/Unit/PHPDocker/Project/ServiceOptions/ElasticsearchTest.php index d4477ea4..3fcc58f7 100644 --- a/tests/Unit/PHPDocker/Project/ServiceOptions/ElasticsearchTest.php +++ b/tests/Unit/PHPDocker/Project/ServiceOptions/ElasticsearchTest.php @@ -18,18 +18,17 @@ public function defaultVersionIs654(): void } #[Test] - public function setVersionTo56Succeeds(): void + public function constructorWithVersion56Succeeds(): void { - $es = new Elasticsearch(); - $es->setVersion('5.6'); + $es = new Elasticsearch(version: '5.6'); self::assertSame('5.6', $es->getVersion()); } #[Test] - public function setVersionWithInvalidVersionThrowsInvalidArgumentException(): void + public function constructorWithInvalidVersionThrowsInvalidArgumentException(): void { $this->expectException(InvalidArgumentException::class); - (new Elasticsearch())->setVersion('invalid'); + new Elasticsearch(version: 'invalid'); } #[Test] diff --git a/tests/Unit/PHPDocker/Project/ServiceOptions/MariaDBTest.php b/tests/Unit/PHPDocker/Project/ServiceOptions/MariaDBTest.php index d2081417..3afe593b 100644 --- a/tests/Unit/PHPDocker/Project/ServiceOptions/MariaDBTest.php +++ b/tests/Unit/PHPDocker/Project/ServiceOptions/MariaDBTest.php @@ -18,18 +18,17 @@ public function defaultVersionIs110(): void } #[Test] - public function setVersionTo104Succeeds(): void + public function constructorWithVersion104Succeeds(): void { - $mariadb = new MariaDB(); - $mariadb->setVersion('10.4'); + $mariadb = new MariaDB(version: '10.4'); self::assertSame('10.4', $mariadb->getVersion()); } #[Test] - public function setVersionWithInvalidVersionThrowsInvalidArgumentException(): void + public function constructorWithInvalidVersionThrowsInvalidArgumentException(): void { $this->expectException(InvalidArgumentException::class); - (new MariaDB())->setVersion('invalid'); + new MariaDB(version: 'invalid'); } #[Test] diff --git a/tests/Unit/PHPDocker/Project/ServiceOptions/MemcachedTest.php b/tests/Unit/PHPDocker/Project/ServiceOptions/MemcachedTest.php index be0a670c..a84115d8 100644 --- a/tests/Unit/PHPDocker/Project/ServiceOptions/MemcachedTest.php +++ b/tests/Unit/PHPDocker/Project/ServiceOptions/MemcachedTest.php @@ -16,15 +16,13 @@ public function getContainerNameSuffixReturnsMemcached(): void } #[Test] - public function isDisabledByDefaultAndCanBeEnabled(): void + public function isDisabledByDefaultAndCanBeEnabledThroughConstructor(): void { $memcached = new Memcached(); self::assertFalse($memcached->isEnabled()); - $memcached->setEnabled(true); - - self::assertTrue($memcached->isEnabled()); + self::assertTrue((new Memcached(enabled: true))->isEnabled()); } #[Test] diff --git a/tests/Unit/PHPDocker/Project/ServiceOptions/MySQLTest.php b/tests/Unit/PHPDocker/Project/ServiceOptions/MySQLTest.php index a1cd0a13..5154916a 100644 --- a/tests/Unit/PHPDocker/Project/ServiceOptions/MySQLTest.php +++ b/tests/Unit/PHPDocker/Project/ServiceOptions/MySQLTest.php @@ -18,34 +18,31 @@ public function defaultVersionIs80(): void } #[Test] - public function setVersionTo57Succeeds(): void + public function constructorWithVersion57Succeeds(): void { - $mysql = new MySQL(); - $mysql->setVersion('5.7'); + $mysql = new MySQL(version: '5.7'); self::assertSame('5.7', $mysql->getVersion()); } #[Test] - public function setVersionTo56Succeeds(): void + public function constructorWithVersion56Succeeds(): void { - $mysql = new MySQL(); - $mysql->setVersion('5.6'); + $mysql = new MySQL(version: '5.6'); self::assertSame('5.6', $mysql->getVersion()); } #[Test] - public function setVersionTo55Succeeds(): void + public function constructorWithVersion55Succeeds(): void { - $mysql = new MySQL(); - $mysql->setVersion('5.5'); + $mysql = new MySQL(version: '5.5'); self::assertSame('5.5', $mysql->getVersion()); } #[Test] - public function setVersionWithInvalidVersionThrowsInvalidArgumentException(): void + public function constructorWithInvalidVersionThrowsInvalidArgumentException(): void { $this->expectException(InvalidArgumentException::class); - (new MySQL())->setVersion('invalid'); + new MySQL(version: 'invalid'); } #[Test] diff --git a/tests/Unit/PHPDocker/Project/ServiceOptions/PostgresTest.php b/tests/Unit/PHPDocker/Project/ServiceOptions/PostgresTest.php index a088d6b1..a06fe258 100644 --- a/tests/Unit/PHPDocker/Project/ServiceOptions/PostgresTest.php +++ b/tests/Unit/PHPDocker/Project/ServiceOptions/PostgresTest.php @@ -18,18 +18,17 @@ public function defaultVersionIs15(): void } #[Test] - public function setVersionTo96Succeeds(): void + public function constructorWithVersion96Succeeds(): void { - $postgres = new Postgres(); - $postgres->setVersion('9.6'); + $postgres = new Postgres(version: '9.6'); self::assertSame('9.6', $postgres->getVersion()); } #[Test] - public function setVersionWithInvalidVersionThrowsInvalidArgumentException(): void + public function constructorWithInvalidVersionThrowsInvalidArgumentException(): void { $this->expectException(InvalidArgumentException::class); - (new Postgres())->setVersion('invalid'); + new Postgres(version: 'invalid'); } #[Test] diff --git a/tests/Unit/PHPDocker/Zip/ArchiverTest.php b/tests/Unit/PHPDocker/Zip/ArchiverTest.php index 6e420a5b..9e6e63f6 100644 --- a/tests/Unit/PHPDocker/Zip/ArchiverTest.php +++ b/tests/Unit/PHPDocker/Zip/ArchiverTest.php @@ -35,7 +35,7 @@ public function getContents(): string #[Test] public function generateArchiveReturnsArchiveWithCorrectFilename(): void { - $archiver = new Archiver(); + $archiver = new Archiver('phpdocker'); $archive = $archiver->generateArchive('test.zip'); self::assertInstanceOf(ArchiveInterface::class, $archive); @@ -45,7 +45,7 @@ public function generateArchiveReturnsArchiveWithCorrectFilename(): void #[Test] public function generateArchiveReturnsTmpFilenamePointingToActualFile(): void { - $archiver = new Archiver(); + $archiver = new Archiver('phpdocker'); $archiver->addFile($this->makeFile('placeholder.txt', 'content')); $archive = $archiver->generateArchive('test.zip'); @@ -55,8 +55,7 @@ public function generateArchiveReturnsTmpFilenamePointingToActualFile(): void #[Test] public function addFileWithBaseFolderPrefixesFilename(): void { - $archiver = new Archiver(); - $archiver->setBaseFolder('myfolder'); + $archiver = new Archiver('myfolder'); $archiver->addFile($this->makeFile('config.txt', 'content')); $archive = $archiver->generateArchive('out.zip'); @@ -70,8 +69,7 @@ public function addFileWithBaseFolderPrefixesFilename(): void #[Test] public function addFileWithIgnorePrefixDoesNotApplyBaseFolder(): void { - $archiver = new Archiver(); - $archiver->setBaseFolder('myfolder'); + $archiver = new Archiver('myfolder'); $archiver->addFile($this->makeFile('readme.txt', 'content'), ignorePrefix: true); $archive = $archiver->generateArchive('out.zip');