DrushCommand.php

  1. 8.0.x lib/Drush/Psysh/DrushCommand.php
  2. master lib/Drush/Psysh/DrushCommand.php

Contains \Drush\Psysh\DrushCommand.

DrushCommand is a PsySH proxy command which accepts a Drush command config array and tries to build an appropriate PsySH command for it.

Namespace

Drush\Psysh

Classes

Namesort descending Description
DrushCommand Main Drush command.

File

lib/Drush/Psysh/DrushCommand.php
View source
  1. <?php
  2. /**
  3. * @file
  4. * Contains \Drush\Psysh\DrushCommand.
  5. *
  6. * DrushCommand is a PsySH proxy command which accepts a Drush command config
  7. * array and tries to build an appropriate PsySH command for it.
  8. */
  9. namespace Drush\Psysh;
  10. use Psy\Command\Command as BaseCommand;
  11. use Symfony\Component\Console\Formatter\OutputFormatter;
  12. use Symfony\Component\Console\Input\InputArgument;
  13. use Symfony\Component\Console\Input\InputOption;
  14. use Symfony\Component\Console\Input\InputInterface;
  15. use Symfony\Component\Console\Output\OutputInterface;
  16. /**
  17. * Main Drush command.
  18. */
  19. class DrushCommand extends BaseCommand {
  20. /**
  21. * @var array
  22. */
  23. private $config;
  24. /**
  25. * @var string
  26. */
  27. private $category = '';
  28. /**
  29. * DrushCommand constructor.
  30. *
  31. * This accepts the Drush command configuration array and does a pretty
  32. * decent job of building a PsySH command proxy for it. Wheee!
  33. *
  34. * @param array $config
  35. * Drush command configuration array.
  36. */
  37. public function __construct(array $config) {
  38. $this->config = $config;
  39. parent::__construct();
  40. }
  41. /**
  42. * Get Category of this command.
  43. */
  44. public function getCategory() {
  45. return $this->category;
  46. }
  47. /**
  48. * Sets the category title.
  49. *
  50. * @param string $category_title
  51. */
  52. public function setCategory($category_title) {
  53. $this->category = $category_title;
  54. }
  55. /**
  56. * {@inheritdoc}
  57. */
  58. protected function configure() {
  59. $this
  60. ->setName($this->config['command'])
  61. ->setAliases($this->buildAliasesFromConfig())
  62. ->setDefinition($this->buildDefinitionFromConfig())
  63. ->setDescription($this->config['description'])
  64. ->setHelp($this->buildHelpFromConfig());
  65. }
  66. /**
  67. * {@inheritdoc}
  68. */
  69. protected function execute(InputInterface $input, OutputInterface $output) {
  70. $args = $input->getArguments();
  71. $first = array_shift($args);
  72. // If the first argument is an alias, assign the next argument as the
  73. // command.
  74. if (strpos($first, '@') === 0) {
  75. $alias = $first;
  76. $command = array_shift($args);
  77. }
  78. // Otherwise, default the alias to '@self' and use the first argument as the
  79. // command.
  80. else {
  81. $alias = '@self';
  82. $command = $first;
  83. }
  84. $options = $input->getOptions();
  85. // Force the 'backend' option to TRUE.
  86. $options['backend'] = TRUE;
  87. $return = drush_invoke_process($alias, $command, array_values($args), $options, ['interactive' => TRUE]);
  88. if ($return['error_status'] > 0) {
  89. foreach ($return['error_log'] as $error_type => $errors) {
  90. $output->write($errors);
  91. }
  92. // Add a newline after so the shell returns on a new line.
  93. $output->writeln('');
  94. }
  95. else {
  96. $output->page(drush_backend_get_result());
  97. }
  98. }
  99. /**
  100. * Extract Drush command aliases from config array.
  101. *
  102. * @return array
  103. * The command aliases.
  104. */
  105. protected function buildAliasesFromConfig() {
  106. return !empty($this->config['aliases']) ? $this->config['aliases'] : [];
  107. }
  108. /**
  109. * Build a command definition from Drush command configuration array.
  110. *
  111. * Currently, adds all non-hidden arguments and options, and makes a decent
  112. * effort to guess whether an option accepts a value or not. It isn't always
  113. * right :P
  114. *
  115. * @return array
  116. * the command definition.
  117. */
  118. protected function buildDefinitionFromConfig() {
  119. $definitions = [];
  120. if (isset($this->config['arguments']) && !empty($this->config['arguments'])) {
  121. $required_args = $this->config['required-arguments'];
  122. if ($required_args === FALSE) {
  123. $required_args = 0;
  124. }
  125. elseif ($required_args === TRUE) {
  126. $required_args = count($this->config['arguments']);
  127. }
  128. foreach ($this->config['arguments'] as $name => $argument) {
  129. if (!is_array($argument)) {
  130. $argument = ['description' => $argument];
  131. }
  132. if (!empty($argument['hidden'])) {
  133. continue;
  134. }
  135. $input_type = ($required_args-- > 0) ? InputArgument::REQUIRED : InputArgument::OPTIONAL;
  136. $definitions[] = new InputArgument($name, $input_type, $argument['description'], NULL);
  137. }
  138. }
  139. // First create all global options.
  140. $options = $this->config['options'] + drush_get_global_options();
  141. // Add command specific options.
  142. $definitions = array_merge($definitions, $this->createInputOptionsFromConfig($options));
  143. return $definitions;
  144. }
  145. /**
  146. * Creates input definitions from command options.
  147. *
  148. * @param array $options_config
  149. *
  150. * @return \Symfony\Component\Console\Input\InputInterface[]
  151. */
  152. protected function createInputOptionsFromConfig(array $options_config) {
  153. $definitions = [];
  154. foreach ($options_config as $name => $option) {
  155. // Some commands will conflict.
  156. if (in_array($name, ['help', 'command'])) {
  157. continue;
  158. }
  159. if (!is_array($option)) {
  160. $option = ['description' => $option];
  161. }
  162. if (!empty($option['hidden'])) {
  163. continue;
  164. }
  165. // @todo: Figure out if there's a way to detect InputOption::VALUE_NONE
  166. // (i.e. flags) via the config array.
  167. if (isset($option['value']) && $option['value'] === 'required') {
  168. $input_type = InputOption::VALUE_REQUIRED;
  169. }
  170. else {
  171. $input_type = InputOption::VALUE_OPTIONAL;
  172. }
  173. $definitions[] = new InputOption($name, !empty($option['short-form']) ? $option['short-form'] : '', $input_type, $option['description']);
  174. }
  175. return $definitions;
  176. }
  177. /**
  178. * Build a command help from the Drush configuration array.
  179. *
  180. * Currently it's a word-wrapped description, plus any examples provided.
  181. *
  182. * @return string
  183. * The help string.
  184. */
  185. protected function buildHelpFromConfig() {
  186. $help = wordwrap($this->config['description']);
  187. $examples = [];
  188. foreach ($this->config['examples'] as $ex => $def) {
  189. // Skip empty examples and things with obvious pipes...
  190. if (($ex === '') || (strpos($ex, '|') !== FALSE)) {
  191. continue;
  192. }
  193. $ex = preg_replace('/^drush\s+/', '', $ex);
  194. $examples[$ex] = $def;
  195. }
  196. if (!empty($examples)) {
  197. $help .= "\n\ne.g.";
  198. foreach ($examples as $ex => $def) {
  199. $help .= sprintf("\n<return>// %s</return>\n", wordwrap(OutputFormatter::escape($def), 75, "</return>\n<return>// "));
  200. $help .= sprintf("<return>>>> %s</return>\n", OutputFormatter::escape($ex));
  201. }
  202. }
  203. return $help;
  204. }
  205. }