Patched to Drupal 8.4.8 level. See https://www.drupal.org/sa-core-2018-004 and patch...
[yaffs-website] / vendor / drupal / console-core / src / Descriptor / TextDescriptor.php
1 <?php
2 /*
3  * This file is part of the Symfony package.
4  *
5  * (c) Fabien Potencier <fabien@symfony.com>
6  *
7  * For the full copyright and license information, please view the LICENSE
8  * file that was distributed with this source code.
9  */
10 namespace Drupal\Console\Core\Descriptor;
11
12 use Symfony\Component\Console\Application;
13 use Symfony\Component\Console\Command\Command;
14 use Symfony\Component\Console\Input\InputArgument;
15 use Symfony\Component\Console\Input\InputDefinition;
16 use Symfony\Component\Console\Input\InputOption;
17 use Symfony\Component\Console\Descriptor\Descriptor;
18 use Symfony\Component\Console\Descriptor\ApplicationDescription;
19
20 /**
21  * Text descriptor.
22  *
23  * @author Jean-François Simon <contact@jfsimon.fr>
24  *
25  * @internal
26  */
27 class TextDescriptor extends Descriptor
28 {
29     /**
30      * {@inheritdoc}
31      */
32     protected function describeInputArgument(InputArgument $argument, array $options = [])
33     {
34         if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault()))) {
35             $default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($argument->getDefault()));
36         } else {
37             $default = '';
38         }
39         $totalWidth = isset($options['total_width']) ? $options['total_width'] : strlen($argument->getName());
40         $spacingWidth = $totalWidth - strlen($argument->getName()) + 2;
41         $this->writeText(
42             sprintf(
43                 '  <info>%s</info>%s%s%s',
44                 $argument->getName(),
45                 str_repeat(' ', $spacingWidth),
46                 // + 17 = 2 spaces + <info> + </info> + 2 spaces
47                 preg_replace(
48                     '/\s*\R\s*/',
49                     PHP_EOL.str_repeat(' ', $totalWidth + 17),
50                     $options['translator']->trans($argument->getDescription())
51                 ),
52                 $default
53             ), $options
54         );
55     }
56     /**
57      * {@inheritdoc}
58      */
59     protected function describeInputOption(InputOption $option, array $options = [])
60     {
61         if ($option->acceptValue() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) {
62             $default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($option->getDefault()));
63         } else {
64             $default = '';
65         }
66         $value = '';
67         if ($option->acceptValue()) {
68             $value = '='.strtoupper($option->getName());
69             if ($option->isValueOptional()) {
70                 $value = '['.$value.']';
71             }
72         }
73         $totalWidth = isset($options['total_width']) ? $options['total_width'] : $this->calculateTotalWidthForOptions([$option]);
74         $synopsis = sprintf(
75             '%s%s',
76             $option->getShortcut() ? sprintf('-%s, ', $option->getShortcut()) : '    ',
77             sprintf('--%s%s', $option->getName(), $value)
78         );
79         $spacingWidth = $totalWidth - strlen($synopsis) + 2;
80         $this->writeText(
81             sprintf(
82                 '  <info>%s</info>%s%s%s%s',
83                 $synopsis,
84                 str_repeat(' ', $spacingWidth),
85                 // + 17 = 2 spaces + <info> + </info> + 2 spaces
86                 preg_replace(
87                     '/\s*\R\s*/',
88                     "\n".str_repeat(' ', $totalWidth + 17),
89                     $options['translator']->trans($option->getDescription())
90                 ),
91                 $default,
92                 $option->isArray() ? '<comment> (multiple values allowed)</comment>' : ''
93             ), $options
94         );
95     }
96     /**
97      * {@inheritdoc}
98      */
99     protected function describeInputDefinition(InputDefinition $definition, array $options = [])
100     {
101         $command_name = null;
102         if (array_key_exists('command', $options)) {
103             $command_name = $options['command']->getName();
104         }
105
106         $totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions());
107         foreach ($definition->getArguments() as $argument) {
108             $totalWidth = max($totalWidth, strlen($argument->getName()));
109         }
110
111         if ($definition->getArguments()) {
112             $this->writeText($options['translator']->trans('commands.list.messages.arguments'), $options);
113             $this->writeText("\n");
114             foreach ($definition->getArguments() as $argument) {
115                 $this->describeInputArgument($argument, array_merge($options, ['total_width' => $totalWidth]));
116                 $this->writeText("\n");
117             }
118         }
119         if ($definition->getArguments() && $definition->getOptions()) {
120             $this->writeText("\n");
121         }
122         if ($definition->getOptions()) {
123             $laterOptions = [];
124             $this->writeText($options['translator']->trans('commands.list.messages.options'), $options);
125
126             $exitOptionName = 'help';
127             if ($command_name === $exitOptionName) {
128                 $exitOptionName = '';
129             }
130
131             foreach ($definition->getOptions() as $option) {
132                 if ($option->getName() === $exitOptionName) {
133                     break;
134                 }
135
136                 if (strlen($option->getShortcut()) > 1) {
137                     $laterOptions[] = $option;
138                     continue;
139                 }
140                 $this->writeText("\n");
141                 $this->describeInputOption($option, array_merge($options, ['total_width' => $totalWidth]));
142             }
143             foreach ($laterOptions as $option) {
144                 $this->writeText("\n");
145                 $this->describeInputOption($option, array_merge($options, ['total_width' => $totalWidth]));
146             }
147         }
148     }
149     /**
150      * {@inheritdoc}
151      */
152     protected function describeCommand(Command $command, array $options = [])
153     {
154         $namespace = substr(
155             $command->getName(),
156             0,
157             (strpos($command->getName(), ':')?:0)
158         );
159         $commandData = $command->getApplication()->getData();
160         $commands = $commandData['commands'][$namespace];
161         $examples = [];
162         foreach ($commands as $item) {
163             if ($item['name'] ==  $command->getName()) {
164                 $examples = $item['examples'];
165                 break;
166             }
167         }
168
169         $command->getSynopsis(true);
170         $command->getSynopsis(false);
171         $command->mergeApplicationDefinition(false);
172
173         $this->writeText($command->trans('commands.list.messages.usage'), $options);
174         foreach (array_merge([$command->getSynopsis(true)], $command->getAliases(), $command->getUsages()) as $key => $usage) {
175             if ($key > 0) {
176                 $this->writeText("\n");
177             }
178             $this->writeText('  '.$usage, $options);
179         }
180
181         $this->writeText("\n");
182         $definition = $command->getNativeDefinition();
183         if ($definition->getOptions() || $definition->getArguments()) {
184             $this->writeText("\n");
185             $options =
186                 array_merge(
187                     $options,
188                     [ 'command' => $command ]
189                 );
190             $this->describeInputDefinition($definition, $options);
191             $this->writeText("\n");
192         }
193
194         if ($examples) {
195             $this->writeText("\n");
196             $this->writeText("<comment>Examples:</comment>", $options);
197             foreach ($examples as $key => $example) {
198                 $this->writeText("\n");
199                 if ($key != 0) {
200                     $this->writeText("\n");
201                 }
202                 $this->writeText('  <info>'.$example['description'].'</info>');
203                 $this->writeText("\n");
204                 $this->writeText('  '.$example['execution']);
205             }
206         }
207
208         if ($help = $command->getProcessedHelp()) {
209             $this->writeText("\n");
210             $this->writeText($command->trans('commands.list.messages.help'), $options);
211             $this->writeText("\n");
212             $this->writeText(' '.str_replace("\n", "\n ", $help), $options);
213             $this->writeText("\n");
214         }
215     }
216     /**
217      * {@inheritdoc}
218      */
219     protected function describeApplication(Application $application, array $options = [])
220     {
221         $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
222         $description = new ApplicationDescription($application, $describedNamespace);
223         if (isset($options['raw_text']) && $options['raw_text']) {
224             $width = $this->getColumnWidth($description->getCommands());
225             foreach ($description->getCommands() as $command) {
226                 $this->writeText(sprintf("%-${width}s %s", $command->getName(), $command->getDescription()), $options);
227                 $this->writeText("\n");
228             }
229         } else {
230             if ('' != $help = $application->getHelp()) {
231                 $this->writeText("$help\n\n", $options);
232             }
233             if (empty($describedNamespace)) {
234                 $this->writeText(
235                     $application->trans('commands.list.messages.usage'),
236                     $options
237                 );
238                 $this->writeText(
239                     $application->trans(
240                         'commands.list.messages.usage-details'
241                     ),
242                     $options
243                 );
244                 $options['application'] = $application;
245
246                 $this->describeInputDefinition(
247                     new InputDefinition(
248                         $application->getDefinition()->getOptions()
249                     ),
250                     $options
251                 );
252                 $this->writeText("\n");
253                 $this->writeText("\n");
254             }
255
256             $width = $this->getColumnWidth($description->getCommands()) + 4;
257             if ($describedNamespace) {
258                 $this->writeText(sprintf($application->trans('commands.list.messages.comment'), $describedNamespace), $options);
259             } else {
260                 $this->writeText($application->trans('commands.list.messages.available-commands'), $options);
261             }
262
263             $singleCommands = [
264                 'about',
265                 'chain',
266                 'check',
267                 'composerize',
268                 'exec',
269                 'help',
270                 'init',
271                 'list',
272                 'shell',
273                 'server'
274             ];
275
276             // add commands by namespace
277             foreach ($description->getNamespaces() as $namespace) {
278                 if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
279                     $this->writeText("\n");
280                     $this->writeText(' <comment>'.$namespace['id'].'</comment>', $options);
281                 }
282                 foreach ($namespace['commands'] as $name) {
283                     if (ApplicationDescription::GLOBAL_NAMESPACE == $namespace['id']) {
284                         if (!in_array($name, $singleCommands)) {
285                             continue;
286                         }
287                     }
288
289                     $this->writeText("\n");
290                     $alias = '';
291                     if ($description->getCommand($name)->getAliases()) {
292                         $alias = sprintf(
293                             '(%s)',
294                             implode(',', $description->getCommand($name)->getAliases())
295                         );
296                     }
297
298                     $spacingWidth = $width - strlen($name.$alias);
299                     if ($spacingWidth < 0) {
300                         $spacingWidth = 0;
301                     }
302
303                     $this->writeText(
304                         sprintf(
305                             '  <info>%s</info> <comment>%s</comment> %s%s',
306                             $name,
307                             $alias,
308                             str_repeat(' ', $spacingWidth),
309                             $description->getCommand($name)->getDescription(
310                             )
311                         ),
312                         $options
313                     );
314                 }
315             }
316             $this->writeText("\n");
317         }
318     }
319     /**
320      * {@inheritdoc}
321      */
322     private function writeText($content, array $options = [])
323     {
324         $this->write(
325             isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content,
326             isset($options['raw_output']) ? !$options['raw_output'] : true
327         );
328     }
329     /**
330      * Formats input option/argument default value.
331      *
332      * @param mixed $default
333      *
334      * @return string
335      */
336     private function formatDefaultValue($default)
337     {
338         if (PHP_VERSION_ID < 50400) {
339             return str_replace('\/', '/', json_encode($default));
340         }
341         return json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
342     }
343     /**
344      * @param Command[] $commands
345      *
346      * @return int
347      */
348     private function getColumnWidth(array $commands)
349     {
350         $width = 0;
351         foreach ($commands as $command) {
352             $width = strlen($command->getName()) > $width ? strlen($command->getName()) : $width;
353         }
354         return $width + 2;
355     }
356     /**
357      * @param InputOption[] $options
358      *
359      * @return int
360      */
361     private function calculateTotalWidthForOptions($options)
362     {
363         $totalWidth = 0;
364         foreach ($options as $option) {
365             // "-" + shortcut + ", --" + name
366             $nameLength = 1 + max(strlen($option->getShortcut()), 1) + 4 + strlen($option->getName());
367             if ($option->acceptValue()) {
368                 $valueLength = 1 + strlen($option->getName()); // = + value
369                 $valueLength += $option->isValueOptional() ? 2 : 0; // [ + ]
370                 $nameLength += $valueLength;
371             }
372             $totalWidth = max($totalWidth, $nameLength);
373         }
374         return $totalWidth;
375     }
376 }