diff options
Diffstat (limited to 'src/Client/Script')
-rw-r--r-- | src/Client/Script/Command/Site/Create.php | 348 | ||||
-rw-r--r-- | src/Client/Script/Console.php | 24 |
2 files changed, 372 insertions, 0 deletions
diff --git a/src/Client/Script/Command/Site/Create.php b/src/Client/Script/Command/Site/Create.php new file mode 100644 index 0000000..df9fc18 --- /dev/null +++ b/src/Client/Script/Command/Site/Create.php @@ -0,0 +1,348 @@ +<?php + +namespace App\Script\Command\Site; + +use Symfony\Component\Console\Command\Command as SyCommand; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Helper\ProgressBar; +use App\Filesystem\CreateFile; +use App\Filesystem\CreateDirectory; +use App\Task\TaskInterface; + +/** + * A new Symfony command for creating a new site deployment + * + * @author Phil Burton <phil@d3r.com> + */ +class Create extends SyCommand +{ + /** + * Symfony Progress Bar for command + * + * @var Symfony\Component\Console\Helper\ProgressBar + */ + protected $progressBar; + + /** + * Array of task sets containing tasks + * + * @var mixed + */ + protected $tasks; + + /** + * Name of the deployment + * + * @var string + */ + protected $name; + + /** + * Domain name of the deployment + * + * @var string + */ + protected $domain; + + /** + * Configure the command + * + * @author Phil Burton <phil@d3r.com> + */ + protected function configure() + { + $this->addArgument('name', InputArgument::REQUIRED, 'The name of the new site.'); + $this->addArgument('domain', InputArgument::REQUIRED, 'The domain name of the new site.'); + + $this + ->setName('site:create') + ->setDescription('Create a new site.') + ->setHelp('This command allows you to create a new site.'); + + $this->addOption( + 'test', + 't', + InputOption::VALUE_NONE, + 'Run in test mode without any file or directory created?' + ); + + $this->addOption( + 'ignore-config', + 'c', + InputOption::VALUE_NONE, + 'Ignore writing the config?' + ); + + $this->addOption( + 'ignore-filesystem', + 'f', + InputOption::VALUE_NONE, + 'Ignore writing the deployment files and directories?' + ); + } + + /** + * Run the command + * + * @param InputInterface $input + * @param OutputInterface $output + * @author Phil Burton <phil@d3r.com> + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $taskCount = 9; + if ($input->getOption('ignore-filesystem')) { + $taskCount -= 8; + } + + if ($input->getOption('ignore-config')) { + $taskCount -= 1; + } + + if ($taskCount <= 0) { + echo "Nothing to do.\n"; + exit; + } + + $this->name = $input->getArgument('name'); + $this->domain = $input->getArgument('domain'); + + $output->writeln( + 'Creating new site with name: ' + . $input->getArgument('name') + . ' and domain: ' + . $input->getArgument('domain') + ); + + // Set-up progress bar + $this->progressBar = new ProgressBar($output, $taskCount); + $this->progressBar->setFormatDefinition('custom', ' %current%/%max% -- %message%'); + $this->progressBar->setFormat('custom'); + $this->progressBar->setMessage('Starting...'); + $this->progressBar->start(); + $this->progressBar->setMessage('Running pre-flight checks'); + + // Construct the file commands so we run checks first + $this->progressBar->advance(); + + try { + $this->runPreflightChecks($input); + } catch (\Exception $e) { + $this->complete($output, "Error with pre-flight checks:\n" . $e->getMessage()); + } + try { + if (!$input->getOption('test')) { + if (!$input->getOption('ignore-config')) { + $this->createConfig($input); + } + + if (!$input->getOption('ignore-filesystem')) { + $this->createFilesystem($input); + } + } + } catch (\Exception $e) { + $this->complete($output, "Unexpected Error creating files and directories:\n " . $e->getMessage()); + } + // Finish up + $this->complete($output, 'Complete', true); + } + + /** + * Show a message and end the program + * Optionally complete the progress bar + * + * @author Phil Burton <phil@pgburton.com> + * @param OutputInterface $output + * @param string $message + * @param boolean $completeProgressBar + */ + public function complete(OutputInterface $output, string $message, $completeProgressBar = false) + { + if ($completeProgressBar) { + $this->progressBar->advance(); + $this->progressBar->finish(); + } + + $output->writeln(''); + $output->writeln($message); + exit; + } + + /** + * Run the required tasks to check we can complete the full deployment + * + * @author Phil Burton <phil@pgburton.com> + * @param InputInterface $input + */ + public function runPreflightChecks(InputInterface $input) + { + $ignoreFilesystem = $input->getOption('ignore-filesystem'); + $ignoreConfig = $input->getOption('ignore-config'); + + if (!$ignoreFilesystem) { + $this->addTask( + 'check-filesystem', + 'Creating site directory', + new CreateDirectory( + $this->getFullSitesPath($this->name) + ) + ); + } + + if (!$ignoreConfig) { + $this->addTask( + 'check-config', + 'Creating nginx config file', + new CreateFile( + CONFIG_ROOT . '/' . $this->name . '.conf', + include_once(DIPPER_ROOT . '/nginx/stub.php') + ) + ); + } + } + + /** + * Run the creation of the config tasks + * + * @author Phil Burton <phil@pgburton.com> + */ + public function createConfig() + { + $this->runTaskSet('check-config'); + } + + /** + * Run the creatuion of the filesystem tasks + * + * @author Phil Burton <phil@pgburton.com> + * @param InputInterface $input + */ + public function createFilesystem(InputInterface $input) + { + $this->runTaskSet('check-filesystem'); + + $this->runTask( + 'Creating logs directory', + new CreateDirectory( + $this->getFullSitesPath($this->name) . '/logs' + ), + true + ); + + $this->runTask( + 'Creating access log file', + new CreateFile( + $this->getFullSitesPath($this->name) . '/logs/' . $this->name . '.access_log' + ), + true + ); + + $this->runTask( + 'Creating error log file', + new CreateFile( + $this->getFullSitesPath($this->name) . '/logs/' . $this->name . '.errors_log' + ), + true + ); + + $this->runTask( + 'Creating web folder', + new CreateDirectory( + $this->getFullSitesPath($this->name) . '/web' + ), + true + ); + + $this->runTask( + 'Creating directory index.php', + new CreateFile( + $this->getFullSitesPath($this->name) . '/web/index.php' + ), + true + ); + } + + /** + * Add a task to a task set + * + * @author Phil Burton <phil@pgburton.com> + * @param string $taskSetName + * @param string $taskName + * @param TaskInterface $task + */ + public function addTask(string $taskSetName, string $taskName, TaskInterface $task) + { + $this->taskPriority[$taskSetName][] = $taskName; + $this->tasks[$taskSetName][$taskName] = $task; + } + + /** + * Get the array of tasks from a taskset + * + * @author Phil Burton <phil@pgburton.com> + * @param string $taskSetName + * @return TaskInterface[] + */ + public function getTaskSet(string $taskSetName) + { + $tasks = $this->tasks; + if (array_key_exists($taskSetName, $tasks)) { + return $tasks[$taskSetName]; + } + + return false; + } + + /** + * Run all the tasks in a taskset + * + * @author Phil Burton <phil@pgburton.com> + * @param string $taskSetName] + * @param boolean $advanceProgressBar + */ + public function runTaskSet(string $taskSetName, $advanceProgressBar = false) + { + $tasks = $this->getTaskSet($taskSetName); + + if (!$tasks) { + throw new \Exception('Could not find task set `' . $taskSetName . '`'); + } + foreach ($this->taskPriority[$taskSetName] as $message) { + $task = $tasks[$message]; + // Create file in web root for execution + $this->runTask($message, $task, $advanceProgressBar); + } + } + + /** + * Return the full path of a given file + * + * @author Phil Burton <phil@pgburton.com> + * @param string $path + * @return string + */ + protected function getFullSitesPath($path) + { + return SITES_ROOT . "/" . $path; + } + + /** + * Run a task + * + * @author Phil Burton <phil@pgburton.com> + * @param mixed $task + * @param string $message + * @return string + */ + protected function runTask(string $message, TaskInterface $task, $advanceProgressBar = false) + { + if ($advanceProgressBar) { + $this->progressBar->advance(); + $this->progressBar->setMessage($message); + } + $task->execute(); + } +} diff --git a/src/Client/Script/Console.php b/src/Client/Script/Console.php new file mode 100644 index 0000000..5f5d90d --- /dev/null +++ b/src/Client/Script/Console.php @@ -0,0 +1,24 @@ +<?php + +namespace App\Script; + +use Symfony\Component\Console\Application; +use App\Script\Command\Site\Create; + +/** + * Main application class + */ +class Console +{ + /** + * Create symfony application and add commands + * + * @author Phil Burton <phil@pgburton.com> + */ + public function __construct() + { + $application = new Application(); + $application->add(new Create()); + $application->run(); + } +} |