Skip to content

Commit

Permalink
ACMS-3507: Refactor BaseDrushCommand feature.
Browse files Browse the repository at this point in the history
  • Loading branch information
vishalkhode1 committed Jan 25, 2024
1 parent d3bb8e2 commit 24ab153
Show file tree
Hide file tree
Showing 6 changed files with 268 additions and 56 deletions.
135 changes: 135 additions & 0 deletions src/Common/IO.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
<?php

namespace Acquia\Drupal\RecommendedSettings\Common;

use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ChoiceQuestion;
use Symfony\Component\Console\Question\Question;

/**
* An extension of \Robo\Common\IO.
*/
trait IO {

/**
* Writes text to screen, without decoration.
*
* @param string $text
* The text to write.
*/
protected function say($text) {
$this->writeln($text);
}

/**
* Writes text to screen with big, loud decoration.
*
* @param string $text
* The text to write.
* @param int $length
* The length at which text should be wrapped.
* @param string $color
* The color of the text.
*/
protected function yell($text, $length = 40, $color = 'green') {
$format = "<fg=white;bg=$color;options=bold>%s</fg=white;bg=$color;options=bold>";
$this->formattedOutput($text, $length, $format);
}

/**
* Format text as a question.
*
* @param string $message
* The question text.
*
* @return string
* The formatted question text.
*/
protected function formatQuestion($message) {
return "<question> $message</question> ";
}

/**
* Asks the user a multiple-choice question.
*
* @param string $question
* The question text.
* @param array $options
* An array of available options.
* @param mixed $default
* Default.
*
* @return string
* The chosen option.
*/
protected function askChoice($question, array $options, $default = NULL) {
return $this->doAsk(new ChoiceQuestion($this->formatQuestion($question),
$options, $default));
}

/**
* Asks a required question.
*
* @param string $message
* The question text.
*
* @return string
* The response.
*/
protected function askRequired($message) {
$question = new Question($this->formatQuestion($message));
$question->setValidator(function ($answer) {
if (empty($answer)) {
throw new \RuntimeException(
'You must enter a value!'
);
}

return $answer;
});
return $this->doAsk($question);
}

/**
* Writes an array to the screen as a formatted table.
*
* @param array $array
* The unformatted array.
* @param array $headers
* The headers for the array. Defaults to ['Property','Value'].
*/
protected function printArrayAsTable(
array $array,
array $headers = ['Property', 'Value']
) {
$table = new Table($this->output);
$table->setHeaders($headers)
->setRows(ArrayManipulator::convertArrayToFlatTextArray($array))
->render();
}

/**
* Writes a particular configuration key's value to the log.
*
* @param array $array
* The configuration.
* @param string $prefix
* A prefix to add to each row in the configuration.
* @param int $verbosity
* The verbosity level at which to display the logged message.
*/
protected function logConfig(array $array, $prefix = '', $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE) {
if ($this->output()->getVerbosity() >= $verbosity) {
if ($prefix) {
$this->output()->writeln("<comment>Configuration for $prefix:</comment>");
foreach ($array as $key => $value) {
$array["$prefix.$key"] = $value;
unset($array[$key]);
}
}
$this->printArrayAsTable($array);
}
}

}
36 changes: 20 additions & 16 deletions src/Config/ConfigInitializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@

use Acquia\Drupal\RecommendedSettings\Helpers\EnvironmentDetector;
use Consolidation\Config\Config;
use Consolidation\Config\ConfigInterface;
use Consolidation\Config\Loader\YamlConfigLoader;

/**
* Config init.
*/
class ConfigInitializer {

const DEFAULT_CONFIG_FILE_PATH = "/config/build.yml";
const CONFIG_FILE_PATH = "/config/build.yml";

/**
* Config.
Expand Down Expand Up @@ -39,25 +40,13 @@ class ConfigInitializer {
* @param string $site
* Drupal site uri. Ex: site1, site2 etc.
*/
public function __construct(string $site = "default") {
$this->config = new Config();
public function __construct(ConfigInterface $config) {
$this->config = $config;
$this->loader = new YamlConfigLoader();
$this->processor = new YamlConfigProcessor();
$this->setSite($site);
$this->initialize();
}

/**
* Set site.
*
* @param string $site
* Given Site.
*/
public function setSite(string $site): void {
$this->site = $site;
$this->config->set('site', $site);
}

/**
* Initialize.
*/
Expand All @@ -72,6 +61,7 @@ public function initialize(): ConfigInitializer {
*/
public function loadAllConfig(): ConfigInitializer {
$this->loadDefaultConfig();
$this->loadProjectConfig();
return $this;
}

Expand All @@ -81,7 +71,18 @@ public function loadAllConfig(): ConfigInitializer {
protected function loadDefaultConfig(): ConfigInitializer {
$this->addConfig($this->config->export());
$drsDirectory = dirname(__FILE__, 3);
$this->processor->extend($this->loader->load($drsDirectory . self::DEFAULT_CONFIG_FILE_PATH));
$this->processor->extend($this->loader->load($drsDirectory . self::CONFIG_FILE_PATH));
return $this;
}

/**
* Load config.
*
* @return $this
* Config.
*/
public function loadProjectConfig(): ConfigInitializer {
$this->processor->extend($this->loader->load($this->config->get('repo.root') . self::CONFIG_FILE_PATH));
return $this;
}

Expand All @@ -102,6 +103,9 @@ public function addConfig(array $data): Config {
* @throws \ReflectionException
*/
public function determineEnvironment(): string {
if ($this->config->get('environment')) {
return $this->config->get('environment');
}
if (EnvironmentDetector::isCiEnv()) {
return 'ci';
}
Expand Down
30 changes: 30 additions & 0 deletions src/Config/DefaultConfig.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Acquia\Drupal\RecommendedSettings\Config;

use Consolidation\Config\Config;
use Grasmash\YamlExpander\YamlExpander;
use Psr\Log\NullLogger;

/**
* The configuration for settings.
*/
class DefaultConfig extends Config {

/**
* Config Constructor.
*
* @param string[] $data
* Data array, if available.
*/
public function __construct(string $drupal_root) {
parent::__construct();
$repo_root = dirname($drupal_root);
$this->set('repo.root', $repo_root);
$this->set('docroot', $drupal_root);
$this->set('composer.bin', $repo_root . '/vendor/bin');
$this->set('site', 'default');
$this->set('tmp.dir', sys_get_temp_dir());
}

}
36 changes: 36 additions & 0 deletions src/Config/DefaultDrushConfig.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace Acquia\Drupal\RecommendedSettings\Config;

use Consolidation\Config\Config;
use Drush\Config\DrushConfig;
use Grasmash\YamlExpander\YamlExpander;
use Psr\Log\NullLogger;

/**
* The configuration for settings.
*/
class DefaultDrushConfig extends Config {

/**
* Config Constructor.
*
* @param string[] $data
* Data array, if available.
*/
public function __construct(DrushConfig $config) {
$uri = $config->get("options.uri") ?? "default";
$config->set('repo.root', $config->get("runtime.project"));
$config->set('docroot', $config->get("options.root"));
$config->set('composer.bin', $config->get("drush.vendor-dir") . '/bin');
$config->set('drush.uri', $config->get("options.uri"));
$config->set('site', $config->get("options.uri"));
if ($config->get("options.ansi")) {
$config->set('drush.ansi', $config->get("options.ansi"));
}
$config->set('drush.bin', $config->get("runtime.drush-script"));
$config->setDefault('drush.alias', "self");
parent::__construct($config->export());
}

}
40 changes: 21 additions & 19 deletions src/Drush/Commands/BaseDrushCommands.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@

namespace Acquia\Drupal\RecommendedSettings\Drush\Commands;

use Acquia\Drupal\RecommendedSettings\Common\IO;
use Acquia\Drupal\RecommendedSettings\Config\ConfigInitializer;
use Acquia\Drupal\RecommendedSettings\Config\DefaultDrushConfig;
use Acquia\Drupal\RecommendedSettings\Exceptions\SettingsException;
use Acquia\Drupal\RecommendedSettings\Robo\Config\ConfigAwareTrait;
use Acquia\Drupal\RecommendedSettings\Robo\Tasks\DrushTask;
use Acquia\Drupal\RecommendedSettings\Robo\Tasks\LoadTasks;
use Consolidation\AnnotatedCommand\AnnotationData;
use Consolidation\AnnotatedCommand\Hooks\HookManager;
Expand All @@ -20,6 +24,7 @@
use Robo\Contract\IOAwareInterface;
use Robo\LoadAllTasks;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Process\Process;

/**
Expand All @@ -31,19 +36,17 @@ class BaseDrushCommands extends DrushCommands implements ConfigAwareInterface, L
use LoadAllTasks;
use ConfigAwareTrait;
use LoadTasks;
use IO;

/**
* {@inheritdoc}
*/
#[CLI\Hook(type: HookManager::INITIALIZE)]
public function init(InputInterface $input, AnnotationData $annotationData): void {
if ($this->getConfig()->get("options.uri")) {
$this->getConfig()->setDefault('drush.uri', $this->getConfig()->get("options.uri"));
}
if ($this->getConfig()->get("options.ansi")) {
$this->getConfig()->setDefault('drush.ansi', $this->getConfig()->get("options.ansi"));
}
$this->getConfig()->setDefault('drush.bin', $this->getConfig()->get("runtime.drush-script"));
$config = new DefaultDrushConfig($this->getConfig());
$configInitializer = new ConfigInitializer($config);
$config = $configInitializer->loadAllConfig()->processConfig();
$this->setConfig($config);
}

/**
Expand Down Expand Up @@ -72,33 +75,32 @@ protected function invokeCommands(array $commands) {
* Invokes a single Drush command.
*
* @param string $command_name
* The name of the command, e.g., 'tests:behat:run'.
* The name of the command, e.g., 'status'.
* @param array $args
* An array of arguments to pass to the command.
*
* @throws \Acquia\Drupal\RecommendedSettings\Exceptions\SettingsException
*/
protected function invokeCommand(string $command_name, array $args = []): void {
$options = $this->input()->getOptions();
$drushOptions = [];
foreach ($options as $key => $value) {
if ($value === NULL || $key === "define") {
if ($value === NULL || $key === "define" || $value == FALSE) {
unset($options[$key]);
}
}
$process = Drush::drush(Drush::aliasManager()->getSelf(), $command_name, $args, $options);
$this->output->writeln("<comment> > " . $process->getCommandLine() . "</comment>");
$process->run($process->showRealtime()->hideStderr());
$errorOutput = $process->getErrorOutput();
if ($errorOutput) {
if (!$process->isSuccessful()) {
$errorOutput = preg_replace("/^\s+|\s+$/", "", $errorOutput);
throw new SettingsException($errorOutput);
$this->output->writeln("<comment> > " . $command_name. "</comment>");
$output = $this->output();
$process->setTty(Process::isTtySupported());
$process->run(static function ($type, $buffer) use ($output, $process) {
if (Process::ERR === $type) {
$output->getErrorOutput()->write($buffer, false, OutputInterface::OUTPUT_NORMAL);
}
else {
$errorOutput = str_replace("[success]", "<bg=green;options=bold;fg=white>[success]</>", $errorOutput);
$this->io()->write($errorOutput);
$output->write($buffer, false, OutputInterface::OUTPUT_NORMAL);
}
}
});
}

}
Loading

0 comments on commit 24ab153

Please sign in to comment.