Update SpinCommand and Abstract to remove messy directory array in favour of cleaner methods

This commit is contained in:
Daniel Winning 2025-04-23 23:30:51 +01:00
parent 3fe612cb36
commit df67dafb8e
10 changed files with 146 additions and 250 deletions

View file

@ -1,6 +1,7 @@
#!/usr/bin/env php #!/usr/bin/env php
<?php <?php
use Loom\Spinner\Command\DestroyCommand;
use Loom\Spinner\Command\SpinCommand; use Loom\Spinner\Command\SpinCommand;
use Symfony\Component\Console\Application; use Symfony\Component\Console\Application;
@ -9,6 +10,7 @@ require dirname(__DIR__) . '/vendor/autoload.php';
$application = new Application('Loom Spinner'); $application = new Application('Loom Spinner');
$application->add(new SpinCommand()); $application->add(new SpinCommand());
$application->add(new DestroyCommand());
try { try {
$application->run(); $application->run();

View file

@ -4,40 +4,52 @@ declare(strict_types=1);
namespace Loom\Spinner\Classes\Config; namespace Loom\Spinner\Classes\Config;
use Loom\Spinner\Classes\Collection\FilePathCollection;
use Loom\Spinner\Classes\File\Interface\DataPathInterface;
use Loom\Utility\FilePath\FilePath;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Yaml;
class Config class Config
{ {
private FilePathCollection $filePaths; private string $spinnerRootPath;
private string $configDirectory;
private string $dataDirectory;
private ?string $projectWorkPath = null;
public function __construct() public function __construct(string $projectName, ?string $projectWorkPath = null)
{ {
$this->setFilePaths(); $this->spinnerRootPath = dirname(__DIR__, 3);
$this->configDirectory = $this->spinnerRootPath . '/config';
$this->dataDirectory = $this->spinnerRootPath . '/data/environments/' . $projectName;
if ($projectWorkPath) {
$this->projectWorkPath = $projectWorkPath;
}
} }
public function getFilePaths(): FilePathCollection public function getDataDirectory(): string
{ {
return $this->filePaths; return $this->dataDirectory;
} }
public function getFilePath(string $key): ?FilePath public function getConfigFilePath(string $fileName): string
{ {
return $this->filePaths->get($key); return $this->configDirectory . '/' . $fileName;
} }
public function addFilePath(FilePath $filePath, string $key): void public function getConfigFileContents(string $fileName): string|null
{ {
$this->filePaths->add($filePath, $key); if (file_exists($this->configDirectory . '/' . $fileName)) {
return file_get_contents($this->configDirectory . '/' . $fileName);
} }
/** return null;
* @throws \Exception }
*/
public function getPhpVersion(InputInterface $input): ?float public function projectDataExists(string $projectName): bool
{
return file_exists($this->dataDirectory . '/environments/' . $projectName);
}
public function getPhpVersion(InputInterface $input): float
{ {
if ($input->getOption('php')) { if ($input->getOption('php')) {
return (float) $input->getOption('php'); return (float) $input->getOption('php');
@ -91,7 +103,7 @@ class Config
return false; return false;
} }
return $this->getEnvironmentOption('database', 'enabled'); return (bool) $this->getEnvironmentOption('database', 'enabled');
} }
/** /**
@ -118,52 +130,29 @@ class Config
return (int) $this->getEnvironmentOption('node','version'); return (int) $this->getEnvironmentOption('node','version');
} }
/**
* @throws \Exception
*/
public function getEnvironmentOption(string $service, string $option): mixed public function getEnvironmentOption(string $service, string $option): mixed
{ {
$projectCustomConfig = $this->filePaths->get('projectCustomConfig'); $projectCustomConfig = $this->getProjectCustomConfig();
if ($projectCustomConfig->exists()) { if ($projectCustomConfig) {
$customConfig = Yaml::parseFile($projectCustomConfig->getAbsolutePath())['options']['environment'] return $projectCustomConfig[$service][$option] ?? $this->getDefaultConfig()[$service][$option] ?? null;
?? null;
if ($customConfig) {
if (isset($customConfig[$service][$option])) {
return $customConfig[$service][$option];
}
}
} }
return $this->getDefaultConfig()['environment'][$service][$option] ?? null; return $this->getDefaultConfig()[$service][$option] ?? null;
}
public function getProjectCustomConfig(): ?array
{
if ($this->projectWorkPath && file_exists($this->projectWorkPath . '/spinner.yaml')) {
return Yaml::parseFile($this->projectWorkPath . '/spinner.yaml')['options']['environment'];
}
return null;
} }
/**
* @throws \Exception
*/
protected function getDefaultConfig(): ?array protected function getDefaultConfig(): ?array
{ {
return Yaml::parseFile($this->filePaths->get('defaultSpinnerConfig')?->getAbsolutePath())['options'] return Yaml::parseFile($this->configDirectory . '/spinner.yaml')['options']['environment']
?? null; ?? null;
} }
private function setFilePaths(): void
{
$this->filePaths = new FilePathCollection([
'config' => new FilePath('config'),
'defaultSpinnerConfig' => new FilePath('config/spinner.yaml'),
'envTemplate' => new FilePath('config/.template.env'),
'data' => new FilePath('data'),
'phpYamlTemplate' => new FilePath('config/php.yaml'),
'nginxYamlTemplate' => new FilePath('config/nginx.yaml'),
'phpFpmDataDirectory' => new FilePath('config/php-fpm'),
DataPathInterface::CONFIG_PHP_FPM_DOCKERFILE => new FilePath(DataPathInterface::CONFIG_PHP_FPM_DOCKERFILE),
DataPathInterface::CONFIG_NGINX_DOCKERFILE => new FilePath(DataPathInterface::CONFIG_NGINX_DOCKERFILE),
'nodeDockerfileTemplate' => new FilePath('config/php-fpm/Node.Dockerfile'),
'xdebugIniTemplate' => new FilePath('config/php-fpm/xdebug.ini'),
'opcacheIniTemplate' => new FilePath('config/php-fpm/opcache.ini'),
'xdebugDockerfileTemplate' => new FilePath('config/php-fpm/XDebug.Dockerfile'),
]);
}
} }

View file

@ -6,14 +6,13 @@ namespace Loom\Spinner\Classes\File;
use Loom\Spinner\Classes\Config\Config; use Loom\Spinner\Classes\Config\Config;
use Loom\Spinner\Classes\File\Interface\FileBuilderInterface; use Loom\Spinner\Classes\File\Interface\FileBuilderInterface;
use Loom\Utility\FilePath\FilePath;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
abstract class AbstractFileBuilder implements FileBuilderInterface abstract class AbstractFileBuilder implements FileBuilderInterface
{ {
protected string $content; protected string $content;
public function __construct(protected FilePath $path, protected Config $config) public function __construct(protected string $path, protected Config $config)
{ {
return $this; return $this;
} }
@ -22,7 +21,7 @@ abstract class AbstractFileBuilder implements FileBuilderInterface
public function save(): void public function save(): void
{ {
file_put_contents($this->path->getProvidedPath(), $this->content); file_put_contents($this->path, $this->content);
} }

View file

@ -15,13 +15,7 @@ class DockerComposeFileBuilder extends AbstractFileBuilder
*/ */
public function __construct(Config $config) public function __construct(Config $config)
{ {
$projectDockerCompose = $config->getFilePaths()->get('projectDockerCompose'); return parent::__construct($config->getDataDirectory() . '/docker-compose.yaml', $config);
if (!$projectDockerCompose instanceof FilePath) {
throw new \Exception('Project Docker Compose file path not found.');
}
return parent::__construct($projectDockerCompose, $config);
} }
/** /**
@ -29,9 +23,7 @@ class DockerComposeFileBuilder extends AbstractFileBuilder
*/ */
public function build(InputInterface $input): DockerComposeFileBuilder public function build(InputInterface $input): DockerComposeFileBuilder
{ {
$this->content = file_get_contents( $this->content = $this->config->getConfigFileContents('php.yaml');
$this->config->getFilePaths()->get('phpYamlTemplate')->getAbsolutePath()
);
if ($this->config->isDatabaseEnabled($input) && in_array($this->config->getDatabaseDriver($input), ['sqlite3', 'sqlite'])) { if ($this->config->isDatabaseEnabled($input) && in_array($this->config->getDatabaseDriver($input), ['sqlite3', 'sqlite'])) {
$this->addSqliteDatabaseConfig(); $this->addSqliteDatabaseConfig();
@ -49,20 +41,18 @@ class DockerComposeFileBuilder extends AbstractFileBuilder
$this->content .= str_replace( $this->content .= str_replace(
'services:', 'services:',
'', '',
file_get_contents( $this->config->getConfigFileContents('nginx.yaml')
$this->config->getFilePaths()->get('nginxYamlTemplate')->getAbsolutePath()
)
); );
$this->content = str_replace( $this->content = str_replace(
'./nginx/conf.d', './nginx/conf.d',
(new FilePath('config/nginx/conf.d'))->getAbsolutePath(), $this->config->getConfigFilePath('nginx/conf.d'),
$this->content $this->content
); );
} }
private function addSqliteDatabaseConfig(): void private function addSqliteDatabaseConfig(): void
{ {
$sqlLiteConfig = file_get_contents((new FilePath('config/sqlite.yaml'))->getAbsolutePath()); $sqlLiteConfig = $this->config->getConfigFileContents('sqlite.yaml');
$sqlLiteConfig = str_replace('volumes:', '', $sqlLiteConfig); $sqlLiteConfig = str_replace('volumes:', '', $sqlLiteConfig);
$this->content .= $sqlLiteConfig; $this->content .= $sqlLiteConfig;
} }

View file

@ -1,11 +0,0 @@
<?php
declare(strict_types=1);
namespace Loom\Spinner\Classes\File\Interface;
interface DataPathInterface
{
public const string CONFIG_PHP_FPM_DOCKERFILE = 'config/php-fpm/Dockerfile';
public const string CONFIG_NGINX_DOCKERFILE = 'config/nginx/Dockerfile';
}

View file

@ -5,8 +5,6 @@ declare(strict_types=1);
namespace Loom\Spinner\Classes\File; namespace Loom\Spinner\Classes\File;
use Loom\Spinner\Classes\Config\Config; use Loom\Spinner\Classes\Config\Config;
use Loom\Spinner\Classes\File\Interface\DataPathInterface;
use Loom\Utility\FilePath\FilePath;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
class NginxDockerFileBuilder extends AbstractFileBuilder class NginxDockerFileBuilder extends AbstractFileBuilder
@ -16,22 +14,12 @@ class NginxDockerFileBuilder extends AbstractFileBuilder
*/ */
public function __construct(Config $config) public function __construct(Config $config)
{ {
$projectNginxDockerfilePath = $config->getFilePath('projectNginxDockerfile'); return parent::__construct($config->getDataDirectory() . '/nginx/Dockerfile', $config);
if (!$projectNginxDockerfilePath instanceof FilePath) {
throw new \Exception('Project PHP-FPM Dockerfile not found');
}
return parent::__construct($projectNginxDockerfilePath, $config);
} }
public function build(InputInterface $input): AbstractFileBuilder public function build(InputInterface $input): AbstractFileBuilder
{ {
$this->content = file_get_contents( $this->content = $this->config->getConfigFileContents('nginx/Dockerfile');
$this->config->getFilePaths()
->get(DataPathInterface::CONFIG_NGINX_DOCKERFILE)
->getAbsolutePath()
);
return $this; return $this;
} }

View file

@ -5,8 +5,6 @@ declare(strict_types=1);
namespace Loom\Spinner\Classes\File; namespace Loom\Spinner\Classes\File;
use Loom\Spinner\Classes\Config\Config; use Loom\Spinner\Classes\Config\Config;
use Loom\Spinner\Classes\File\Interface\DataPathInterface;
use Loom\Utility\FilePath\FilePath;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
class PHPDockerFileBuilder extends AbstractFileBuilder class PHPDockerFileBuilder extends AbstractFileBuilder
@ -16,13 +14,7 @@ class PHPDockerFileBuilder extends AbstractFileBuilder
*/ */
public function __construct(Config $config) public function __construct(Config $config)
{ {
$projectPhpFpmDockerfile = $config->getFilePath('projectPhpFpmDockerfile'); return parent::__construct($config->getDataDirectory() . '/php-fpm/Dockerfile', $config);
if (!$projectPhpFpmDockerfile instanceof FilePath) {
throw new \Exception('Project PHP-FPM Dockerfile not found');
}
return parent::__construct($projectPhpFpmDockerfile, $config);
} }
/** /**
@ -35,27 +27,27 @@ class PHPDockerFileBuilder extends AbstractFileBuilder
$this->content = str_replace('${PHP_VERSION}', (string) $this->config->getPhpVersion($input), $this->content); $this->content = str_replace('${PHP_VERSION}', (string) $this->config->getPhpVersion($input), $this->content);
file_put_contents( file_put_contents(
(new FilePath(sprintf('data/environments/%s/php-fpm/opcache.ini', $input->getArgument('name'))))->getProvidedPath(), $this->config->getDataDirectory() . '/php-fpm/opcache.ini',
file_get_contents($this->config->getFilePaths()->get('opcacheIniTemplate')->getAbsolutePath()) $this->config->getConfigFileContents('php-fpm/opcache.ini')
); );
if ($this->config->isDatabaseEnabled($input) && in_array($this->config->getDatabaseDriver($input), ['sqlite3', 'sqlite'])) { if ($this->config->isDatabaseEnabled($input) && in_array($this->config->getDatabaseDriver($input), ['sqlite3', 'sqlite'])) {
$this->addNewLine(); $this->addNewLine();
$this->content .= file_get_contents((new FilePath('config/php-fpm/Sqlite.Dockerfile'))->getAbsolutePath()); $this->content .= $this->config->getConfigFileContents('php-fpm/Sqlite.Dockerfile');
} }
if ($this->config->isNodeEnabled($input)) { if ($this->config->isNodeEnabled($input)) {
$this->addNewLine(); $this->addNewLine();
$this->content .= file_get_contents($this->config->getFilePaths()->get('nodeDockerfileTemplate')->getAbsolutePath()); $this->content .= $this->config->getConfigFileContents('php-fpm/Node.Dockerfile');
$this->content = str_replace('${NODE_VERSION}', (string) $this->config->getNodeVersion($input), $this->content); $this->content = str_replace('${NODE_VERSION}', (string) $this->config->getNodeVersion($input), $this->content);
} }
if ($this->config->isXdebugEnabled($input)) { if ($this->config->isXdebugEnabled($input)) {
$this->addNewLine(); $this->addNewLine();
$this->content .= file_get_contents($this->config->getFilePaths()->get('xdebugDockerfileTemplate')->getAbsolutePath()); $this->content .= $this->config->getConfigFileContents('php-fpm/Xdebug.Dockerfile');
file_put_contents( file_put_contents(
(new FilePath(sprintf('data/environments/%s/php-fpm/xdebug.ini', $input->getArgument('name'))))->getProvidedPath(), $this->config->getDataDirectory() . '/php-fpm/xdebug.ini',
file_get_contents($this->config->getFilePaths()->get('xdebugIniTemplate')->getAbsolutePath()) $this->config->getConfigFileContents('php-fpm/xdebug.ini')
); );
} }
@ -64,8 +56,6 @@ class PHPDockerFileBuilder extends AbstractFileBuilder
private function setInitialContent(): void private function setInitialContent(): void
{ {
$this->content = file_get_contents( $this->content = $this->config->getConfigFileContents('php-fpm/Dockerfile');
$this->config->getFilePaths()->get(DataPathInterface::CONFIG_PHP_FPM_DOCKERFILE)->getAbsolutePath()
);
} }
} }

View file

@ -4,16 +4,14 @@ declare(strict_types=1);
namespace Loom\Spinner\Command; namespace Loom\Spinner\Command;
use Loom\Spinner\Classes\Collection\FilePathCollection;
use Loom\Spinner\Classes\Config\Config; use Loom\Spinner\Classes\Config\Config;
use Loom\Spinner\Classes\OS\System; use Loom\Spinner\Classes\OS\System;
use Loom\Spinner\Command\Interface\ConsoleCommandInterface; use Loom\Spinner\Command\Interface\ConsoleCommandInterface;
use Loom\Utility\FilePath\FilePath;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Yaml\Yaml;
class AbstractSpinnerCommand extends Command implements ConsoleCommandInterface class AbstractSpinnerCommand extends Command implements ConsoleCommandInterface
{ {
@ -24,7 +22,6 @@ class AbstractSpinnerCommand extends Command implements ConsoleCommandInterface
public function __construct() public function __construct()
{ {
$this->system = new System(); $this->system = new System();
$this->config = new Config();
parent::__construct(); parent::__construct();
} }
@ -41,12 +38,6 @@ class AbstractSpinnerCommand extends Command implements ConsoleCommandInterface
return Command::FAILURE; return Command::FAILURE;
} }
if (!$this->validatePathArgument($input)) {
return Command::FAILURE;
}
$this->validateNameArgument($input);
return Command::SUCCESS; return Command::SUCCESS;
} }
@ -54,61 +45,13 @@ class AbstractSpinnerCommand extends Command implements ConsoleCommandInterface
{ {
return sprintf( return sprintf(
'cd %s && docker compose --env-file=%s %s%s', 'cd %s && docker compose --env-file=%s %s%s',
$this->config->getFilePaths()->get('projectData')->getAbsolutePath(), $this->config->getDataDirectory(),
$this->config->getFilePaths()->get('projectEnv')->getAbsolutePath(), $this->config->getDataDirectory() . '/.env',
$command, $command,
$daemon ? ' -d' : '' $daemon ? ' -d' : ''
); );
} }
private function validatePathArgument(InputInterface $input): bool
{
if ($input->hasArgument('path')) {
$projectDirectory = new FilePath($input->getArgument('path'));
if (!$projectDirectory->exists() || !$projectDirectory->isDirectory()) {
$this->style->error('The provided path is not a valid directory.');
return false;
}
$this->config->addFilePath($projectDirectory, 'project');
}
return true;
}
private function validateNameArgument(InputInterface $input): void
{
var_dump('Validating name argument');
if ($input->hasArgument('name')) {
$this->config->addFilePath(
new FilePath(sprintf('data/environments/%s', $input->getArgument('name'))),
'projectData'
);
$this->config->addFilePath(
new FilePath(sprintf('data/environments/%s/.env', $input->getArgument('name'))),
'projectEnv'
);
$this->config->addFilePath(
new FilePath(sprintf('data/environments/%s/docker-compose.yml', $input->getArgument('name'))),
'projectDockerCompose'
);
$this->config->addFilePath(
new FilePath(sprintf('data/environments/%s/php-fpm/Dockerfile', $input->getArgument('name'))),
'projectPhpFpmDockerfile'
);
$this->config->addFilePath(
new FilePath(sprintf('data/environments/%s/nginx/Dockerfile', $input->getArgument('name'))),
'projectNginxDockerfile'
);
$this->config->addFilePath(
new FilePath($this->config->getFilePaths()->get('project')->getAbsolutePath() . DIRECTORY_SEPARATOR . 'spinner.yaml'),
'projectCustomConfig'
);
}
}
private function setStyle(InputInterface $input, OutputInterface $output): void private function setStyle(InputInterface $input, OutputInterface $output): void
{ {
$this->style = new SymfonyStyle($input, $output); $this->style = new SymfonyStyle($input, $output);

View file

@ -0,0 +1,33 @@
<?php
declare(strict_types=1);
namespace Loom\Spinner\Command;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
#[AsCommand(name: 'spin:down', description: 'Destroy a development environment')]
class DestroyCommand extends AbstractSpinnerCommand
{
protected function configure(): void
{
$this->addArgument(
'name',
InputArgument::REQUIRED,
'The name of the project (as used when running spin:up).'
);
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
if (parent::execute($input, $output)) {
return Command::FAILURE;
}
return Command::SUCCESS;
}
}

View file

@ -4,11 +4,11 @@ declare(strict_types=1);
namespace Loom\Spinner\Command; namespace Loom\Spinner\Command;
use Loom\Spinner\Classes\Config\Config;
use Loom\Spinner\Classes\File\DockerComposeFileBuilder; use Loom\Spinner\Classes\File\DockerComposeFileBuilder;
use Loom\Spinner\Classes\File\NginxDockerFileBuilder; use Loom\Spinner\Classes\File\NginxDockerFileBuilder;
use Loom\Spinner\Classes\File\PHPDockerFileBuilder; use Loom\Spinner\Classes\File\PHPDockerFileBuilder;
use Loom\Spinner\Classes\OS\PortGenerator; use Loom\Spinner\Classes\OS\PortGenerator;
use Loom\Utility\FilePath\FilePath;
use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
@ -21,6 +21,7 @@ class SpinCommand extends AbstractSpinnerCommand
{ {
private PortGenerator $portGenerator; private PortGenerator $portGenerator;
private array $ports; private array $ports;
private string $projectWorkPath = '';
public function __construct() public function __construct()
{ {
@ -84,14 +85,35 @@ class SpinCommand extends AbstractSpinnerCommand
return Command::FAILURE; return Command::FAILURE;
} }
if ($this->projectDataExists()) { $this->projectWorkPath = $input->getArgument('path') === '.'
return Command::SUCCESS; ? getcwd()
: $input->getArgument('path');
if (!file_exists($this->projectWorkPath)) {
$this->style->error('The provided project path does not exist.');
return Command::FAILURE;
}
$this->config = new Config($input->getArgument('name'), $this->projectWorkPath);
if ($this->config->projectDataExists($input->getArgument('name'))) {
$this->style->error('A project with the same name already exists.');
return Command::FAILURE;
} }
$this->style->success("Spinning up a new development environment..."); $this->style->success("Spinning up a new development environment...");
$this->style->text('Creating project data...'); $this->style->text('Creating project data...');
try {
$this->createProjectData($input); $this->createProjectData($input);
} catch (\Exception $exception) {
$this->style->error('Failed to create project data: '. $exception->getMessage());
return Command::FAILURE;
}
$this->style->success('Project data created.'); $this->style->success('Project data created.');
$this->style->text('Building Docker images...'); $this->style->text('Building Docker images...');
@ -102,23 +124,12 @@ class SpinCommand extends AbstractSpinnerCommand
return Command::SUCCESS; return Command::SUCCESS;
} }
protected function projectDataExists(): bool
{
if ($this->config->getFilePaths()->get('projectData')->exists()) {
$this->style->warning('Project already exists. Skipping new build.');
return true;
}
return false;
}
/** /**
* @throws \Exception * @throws \Exception
*/ */
private function createProjectData(InputInterface $input): void private function createProjectData(InputInterface $input): void
{ {
$this->createProjectDataDirectory(); $this->createProjectDataDirectory($input);
$this->createEnvironmentFile($input); $this->createEnvironmentFile($input);
$this->buildDockerComposeFile($input); $this->buildDockerComposeFile($input);
$this->buildDockerfiles($input); $this->buildDockerfiles($input);
@ -127,15 +138,13 @@ class SpinCommand extends AbstractSpinnerCommand
/** /**
* @throws \Exception * @throws \Exception
*/ */
private function createProjectDataDirectory(): void private function createProjectDataDirectory(InputInterface $input): void
{ {
$projectData = $this->config->getFilePaths()->get('projectData'); mkdir(
$this->config->getDataDirectory(),
if (!$projectData instanceof FilePath) { 0777,
throw new \Exception('Invalid project data directory provided.'); true
} );
mkdir($projectData->getProvidedPath(), 0777, true);
} }
/** /**
@ -143,21 +152,15 @@ class SpinCommand extends AbstractSpinnerCommand
*/ */
private function createEnvironmentFile(InputInterface $input): void private function createEnvironmentFile(InputInterface $input): void
{ {
$projectEnv = $this->config->getFilePaths()->get('projectEnv');
if (!$projectEnv instanceof FilePath) {
throw new \Exception('Invalid project environment file provided.');
}
file_put_contents( file_put_contents(
$projectEnv->getProvidedPath(), $this->config->getDataDirectory() . '/.env',
sprintf( sprintf(
file_get_contents($this->config->getFilePaths()->get('envTemplate')->getAbsolutePath()), $this->config->getConfigFileContents('.template.env'),
$this->config->getFilePaths()->get('project')->getAbsolutePath(), $this->projectWorkPath,
$input->getArgument('name'), $input->getArgument('name'),
$this->config->getPhpVersion($input), $this->config->getPhpVersion($input),
$this->getPort('php'), $this->ports['php'],
$this->getPort('nginx'), $this->ports['nginx'],
) )
); );
} }
@ -167,12 +170,7 @@ class SpinCommand extends AbstractSpinnerCommand
*/ */
private function buildDockerComposeFile(InputInterface $input): void private function buildDockerComposeFile(InputInterface $input): void
{ {
$this->createProjectPhpFpmDirectory(); $this->createProjectDataSubDirectory('php-fpm');
if ($this->config->isServerEnabled($input)) {
$this->createProjectNginxDirectory();
(new NginxDockerFileBuilder($this->config))->build($input)->save();
}
(new DockerComposeFileBuilder($this->config))->build($input)->save(); (new DockerComposeFileBuilder($this->config))->build($input)->save();
} }
@ -182,43 +180,18 @@ class SpinCommand extends AbstractSpinnerCommand
*/ */
private function buildDockerfiles(InputInterface $input): void private function buildDockerfiles(InputInterface $input): void
{ {
if ($this->config->isServerEnabled($input)) {
$this->createProjectDataSubDirectory('nginx');
(new NginxDockerFileBuilder($this->config))->build($input)->save();
}
(new PHPDockerFileBuilder($this->config))->build($input)->save(); (new PHPDockerFileBuilder($this->config))->build($input)->save();
} }
/** private function createProjectDataSubDirectory(string $directory): void
* @throws \Exception
*/
private function createProjectPhpFpmDirectory(): void
{ {
$projectData = $this->config->getFilePaths()->get('projectData'); if (!file_exists($this->config->getDataDirectory() . '/' . $directory)) {
mkdir($this->config->getDataDirectory() . '/' . $directory, 0777, true);
if (!$projectData instanceof FilePath) {
throw new \Exception('Invalid project data directory provided.');
} }
if (!file_exists($projectData->getProvidedPath() . '/php-fpm')) {
mkdir($projectData->getProvidedPath() . '/php-fpm', 0777, true);
}
}
/**
* @throws \Exception
*/
private function createProjectNginxDirectory(): void
{
$projectData = $this->config->getFilePaths()->get('projectData');
if (!$projectData instanceof FilePath) {
throw new \Exception('Invalid project data directory provided.');
}
if (!file_exists($projectData->getProvidedPath() . '/nginx')) {
mkdir($projectData->getProvidedPath() . '/nginx', 0777, true);
}
}
private function getPort(string $service): ?int
{
return $this->ports[$service];
} }
} }