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