Skip to content

Commit

Permalink
feat: add --ymir-file option so you can select a configuration file
Browse files Browse the repository at this point in the history
  • Loading branch information
carlalexander committed Sep 22, 2022
1 parent ae9bc3c commit 01f7b65
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 42 deletions.
13 changes: 4 additions & 9 deletions config/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ parameters:
build_artifact_path: '%hidden_directory%/build.zip'
cli_configuration_filepath: '%home_directory%/.ymir/config.json'
hidden_directory: '%working_directory%/.ymir'
project_configuration_filepath: '%working_directory%/ymir.yml'
stub_directory: '%application_directory%/stubs'
uploads_directory: '%hidden_directory%/uploads'
version: '1.32.4'
Expand Down Expand Up @@ -57,14 +56,6 @@ services:
arguments:
$configurationFilePath: '%cli_configuration_filepath%'

Ymir\Cli\EventDispatcher\AutowiredEventDispatcher:
arguments:
- !tagged subscriber

Ymir\Cli\ProjectConfiguration\ProjectConfiguration:
arguments:
$configurationFilePath: '%project_configuration_filepath%'

Ymir\Cli\Command\Project\BuildProjectCommand:
arguments:
$buildSteps:
Expand Down Expand Up @@ -99,3 +90,7 @@ services:
arguments:
$deploymentSteps:
- '@Ymir\Cli\Deployment\StartAndMonitorDeploymentStep'

Ymir\Cli\EventDispatcher\AutowiredEventDispatcher:
arguments:
- !tagged subscriber
14 changes: 14 additions & 0 deletions src/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
namespace Ymir\Cli;

use Symfony\Component\Console\Application as BaseApplication;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Ymir\Cli\Exception\CommandCancelledException;

Expand Down Expand Up @@ -42,4 +44,16 @@ public function renderThrowable(\Throwable $exception, OutputInterface $output):

parent::renderThrowable($exception, $output);
}

/**
* {@inheritdoc}
*/
protected function getDefaultInputDefinition(): InputDefinition
{
$definition = parent::getDefaultInputDefinition();

$definition->addOption(new InputOption('ymir-file', null, InputOption::VALUE_OPTIONAL, 'Path to Ymir project configuration file', 'ymir.yml'));

return $definition;
}
}
62 changes: 62 additions & 0 deletions src/EventListener/LoadProjectConfigurationSubscriber.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

declare(strict_types=1);

/*
* This file is part of Ymir command-line tool.
*
* (c) Carl Alexander <support@ymirapp.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Ymir\Cli\EventListener;

use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Ymir\Cli\ProjectConfiguration\ProjectConfiguration;

class LoadProjectConfigurationSubscriber implements EventSubscriberInterface
{
/**
* The Ymir project configuration.
*
* @var ProjectConfiguration
*/
private $projectConfiguration;

/**
* Constructor.
*/
public function __construct(ProjectConfiguration $projectConfiguration)
{
$this->projectConfiguration = $projectConfiguration;
}

/**
* {@inheritdoc}
*/
public static function getSubscribedEvents()
{
return [
ConsoleEvents::COMMAND => 'onConsoleCommand',
];
}

/**
* Load the Ymir project configuration.
*/
public function onConsoleCommand(ConsoleCommandEvent $event)
{
$configurationFilePath = $event->getInput()->getOption('ymir-file');

if (!is_string($configurationFilePath)) {
throw new RuntimeException('The "--ymir-file" option must be a string value');
}

$this->projectConfiguration->loadConfiguration($configurationFilePath);
}
}
75 changes: 42 additions & 33 deletions src/ProjectConfiguration/ProjectConfiguration.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class ProjectConfiguration implements Arrayable
private $configuration;

/**
* The path to the configuration file.
* The path to the Ymir project configuration file.
*
* @var string
*/
Expand All @@ -47,11 +47,11 @@ class ProjectConfiguration implements Arrayable
/**
* Constructor.
*/
public function __construct(string $configurationFilePath, Filesystem $filesystem)
public function __construct(Filesystem $filesystem, string $configurationFilePath = '')
{
$this->configurationFilePath = $configurationFilePath;
$this->filesystem = $filesystem;
$this->configuration = $this->load($configurationFilePath);

$this->loadConfiguration($configurationFilePath);
}

/**
Expand Down Expand Up @@ -115,8 +115,12 @@ public function createNew(Collection $project, array $environments, string $type
*/
public function delete()
{
if ($this->exists()) {
$this->filesystem->remove($this->configurationFilePath);
}

$this->configuration = [];
$this->filesystem->remove($this->configurationFilePath);
$this->configurationFilePath = '';
}

/**
Expand All @@ -130,11 +134,11 @@ public function deleteEnvironment(string $environment)
}

/**
* Checks if the project configuration file exists.
* Checks if the Ymir project configuration file exists.
*/
public function exists(): bool
{
return $this->filesystem->exists($this->configurationFilePath);
return !empty($this->configurationFilePath) && $this->filesystem->exists($this->configurationFilePath);
}

/**
Expand All @@ -143,7 +147,7 @@ public function exists(): bool
public function getEnvironment(string $environment): array
{
if (!$this->hasEnvironment($environment)) {
throw new InvalidArgumentException(sprintf('Environment "%s" not found in ymir.yml file', $environment));
throw new InvalidArgumentException(sprintf('Environment "%s" not found in Ymir project configuration file', $environment));
}

return (array) $this->configuration['environments'][$environment];
Expand All @@ -163,7 +167,7 @@ public function getEnvironments(): array
public function getProjectId(): int
{
if (empty($this->configuration['id'])) {
throw new RuntimeException('No "id" found in ymir.yml file');
throw new RuntimeException('No "id" found in Ymir project configuration file');
}

return (int) $this->configuration['id'];
Expand All @@ -175,7 +179,7 @@ public function getProjectId(): int
public function getProjectName(): string
{
if (empty($this->configuration['name'])) {
throw new RuntimeException('No "name" found in ymir.yml file');
throw new RuntimeException('No "name" found in Ymir project configuration file');
}

return (string) $this->configuration['name'];
Expand All @@ -187,7 +191,7 @@ public function getProjectName(): string
public function getProjectType(): string
{
if (empty($this->configuration['type'])) {
throw new RuntimeException('No "type" found in ymir.yml file');
throw new RuntimeException('No "type" found in Ymir project configuration file');
}

return (string) $this->configuration['type'];
Expand All @@ -201,6 +205,25 @@ public function hasEnvironment(string $environment): bool
return array_key_exists($environment, $this->configuration['environments']);
}

/**
* Load the given Ymir project configuration file.
*/
public function loadConfiguration(string $configurationFilePath)
{
$configuration = [];

if ($this->filesystem->exists($configurationFilePath)) {
$configuration = Yaml::parse((string) file_get_contents($configurationFilePath));
}

if (!empty($configuration) && !is_array($configuration)) {
throw new RuntimeException('Error parsing Ymir project configuration file');
}

$this->configuration = $configuration;
$this->configurationFilePath = $configurationFilePath;
}

/**
* {@inheritdoc}
*/
Expand All @@ -215,41 +238,27 @@ public function toArray()
public function validate()
{
if (!$this->exists()) {
throw new RuntimeException(sprintf('No Ymir project found in the current directory. You can initialize one with the "%s" command.', InitializeProjectCommand::ALIAS));
throw new RuntimeException(sprintf('No Ymir project configuration file found. You can create one by initializing a project with the "%s" command.', InitializeProjectCommand::ALIAS));
} elseif (empty($this->configuration['id'])) {
throw new RuntimeException('The ymir.yml file must have an "id"');
throw new RuntimeException('The Ymir project configuration file must have an "id"');
} elseif (empty($this->configuration['environments'])) {
throw new RuntimeException('The ymir.yml file must have at least one environment');
throw new RuntimeException('The Ymir project configuration file must have at least one environment');
} elseif (empty($this->configuration['type'])) {
throw new RuntimeException('The ymir.yml file must have a "type"');
throw new RuntimeException('The Ymir project configuration file must have a "type"');
} elseif (!in_array($this->configuration['type'], ['bedrock', 'wordpress'])) {
throw new RuntimeException('The allowed project "type" are "bedrock" or "wordpress"');
}
}

/**
* Load the options from the configuration file.
*/
private function load(string $configurationFilePath): array
{
$configuration = [];

if ($this->filesystem->exists($configurationFilePath)) {
$configuration = Yaml::parse((string) file_get_contents($configurationFilePath));
}

if (!empty($configuration) && !is_array($configuration)) {
throw new RuntimeException('Error parsing ymir.yml file');
}

return $configuration;
}

/**
* Save the configuration options to the configuration file.
*/
private function save()
{
if (empty($this->configurationFilePath)) {
throw new RuntimeException('No Ymir project configuration file path set');
}

$this->filesystem->dumpFile($this->configurationFilePath, str_replace('!!float 8', '8.0', Yaml::dump($this->configuration, 20, 2, Yaml::DUMP_NULL_AS_TILDE)));
}
}

0 comments on commit 01f7b65

Please sign in to comment.