Updated Drupal to 8.6. This goes with the following updates because it's possible...
[yaffs-website] / vendor / drush / drush / src / Commands / help / ListCommands.php
1 <?php
2 namespace Drush\Commands\help;
3
4 use Consolidation\AnnotatedCommand\Help\HelpDocument;
5 use Consolidation\OutputFormatters\FormatterManager;
6 use Consolidation\OutputFormatters\Options\FormatterOptions;
7 use Consolidation\OutputFormatters\StructuredData\RowsOfFields;
8 use Drush\Commands\DrushCommands;
9 use Drush\Drush;
10 use Symfony\Component\Console\Command\Command;
11 use Symfony\Component\Console\Descriptor\JsonDescriptor;
12 use Symfony\Component\Console\Descriptor\XmlDescriptor;
13 use Symfony\Component\Console\Helper\Table;
14 use Symfony\Component\Console\Helper\TableCell;
15 use Symfony\Component\Console\Output\OutputInterface;
16
17 class ListCommands extends DrushCommands
18 {
19     /**
20      * List available commands.
21      *
22      * @command list
23      * @option filter Restrict command list to those commands defined in the specified file. Omit value to choose from a list of names.
24      * @option raw Show a simple table of command names and descriptions.
25      * @bootstrap max
26      * @usage drush list
27      *   List all commands.
28      * @usage drush list --filter=devel_generate
29      *   Show only commands starting with devel-
30      * @usage drush list --format=xml
31      *   List all commands in Symfony compatible xml format.
32      *
33      * @return string
34      */
35     public function helpList($options = ['format' => 'listcli', 'raw' => false, 'filter' => self::REQ])
36     {
37         $application = Drush::getApplication();
38         $all = $application->all();
39         $namespaced = $this->categorize($all);
40
41         // Filter out namespaces that the user does not want to see
42         $filter_category = $options['filter'];
43         if (!empty($filter_category)) {
44             if (!array_key_exists($filter_category, $namespaced)) {
45                 throw new \Exception(dt("The specified command category !filter does not exist.", ['!filter' => $filter_category]));
46             }
47             $namespaced = [$filter_category => $namespaced[$filter_category]];
48         }
49
50         /**
51          * The listcli,json and raw formats don't yet go through the output formatter system.
52          * because \Consolidation\OutputFormatters\Transformations\DomToArraySimplifier
53          * can't yet handle the DomDocument that produces the Symfony expected XML. For consistency, the XML
54          * output chooses to use the Symfony descriptor as well.
55          */
56         if ($options['raw']) {
57             $this->renderListRaw($namespaced);
58             return null;
59         } elseif ($options['format'] == 'listcli') {
60             $preamble = dt('Run `drush help [command]` to view command-specific help.  Run `drush topic` to read even more documentation.');
61             $this->renderListCLI($application, $namespaced, $this->output(), $preamble);
62             if (!Drush::bootstrapManager()->hasBootstrapped((DRUSH_BOOTSTRAP_DRUPAL_ROOT))) {
63                 $this->io()->note(dt('Drupal root not found. Pass --root or a @siteAlias in order to see Drupal-specific commands.'));
64             }
65             return null;
66         } elseif ($options['format'] == 'xml') {
67             $descriptor  = new XmlDescriptor($this->output(), []);
68             return $descriptor->describe($this->output, $application, []);
69         } elseif ($options['format'] == 'json') {
70             $descriptor  = new JsonDescriptor($this->output(), []);
71             return $descriptor->describe($this->output, $application, []);
72         } else {
73             // No longer used. Works for XML, but gives error for JSON.
74             // $dom = $this->buildDom($namespaced, $application);
75             // return $dom;
76         }
77     }
78
79     /**
80      * @param $namespaced
81      * @param $application
82      * @return \DOMDocument
83      */
84     public function buildDom($namespaced, $application)
85     {
86         $dom = new \DOMDocument('1.0', 'UTF-8');
87         $rootXml = $dom->createElement('symfony');
88         $rootXml->setAttribute('name', $application->getName());
89         if ($application->getVersion() !== 'UNKNOWN') {
90             $rootXml->setAttribute('version', $application->getVersion());
91         }
92
93
94         // Create two top level  elements.
95         $commandsXML = $dom->createElement('commands');
96         $namespacesXML = $dom->createElement('namespaces');
97
98         foreach ($namespaced as $namespace => $commands) {
99             $namespaceXML = $dom->createElement('namespace');
100             $namespaceXML->setAttribute('id', $namespace);
101             foreach ($commands as $key => $command) {
102                 $helpDocument = new HelpDocument($command);
103                 $domData = $helpDocument->getDomData();
104                 $node = $domData->getElementsByTagName("command")->item(0);
105                 $element = $dom->importNode($node, true);
106                 $commandsXML->appendChild($element);
107
108                 $ncommandXML = $dom->createElement('command', $key);
109                 $namespaceXML->appendChild($ncommandXML);
110             }
111             $namespacesXML->appendChild($namespaceXML);
112         }
113
114         // Append top level elements to root element in correct order.
115         $rootXml->appendChild($commandsXML);
116         $rootXml->appendChild($namespacesXML);
117         $dom->appendChild($rootXml);
118         return $dom;
119     }
120
121     /**
122      * @param \Symfony\Component\Console\Application $application
123      * @param array $namespaced
124      * @param OutputInterface $output
125      * @param string $preamble
126      */
127     public static function renderListCLI($application, $namespaced, $output, $preamble)
128     {
129         $output->writeln($application->getHelp());
130         $output->writeln('');
131         $output
132         ->writeln($preamble);
133         $output->writeln('');
134
135         $rows[] = ['Available commands:', ''];
136         foreach ($namespaced as $namespace => $list) {
137             $rows[] = ['<comment>' . $namespace . ':</comment>', ''];
138             foreach ($list as $name => $command) {
139                 $description = $command->getDescription();
140
141                 // For commands such as foo:bar, remove
142                 // any alias 'foo-bar' from the alias list.
143                 $aliasList = array_filter(
144                     $command->getAliases(),
145                     function ($aliasName) use ($name) {
146                         return $aliasName != str_replace(':', '-', $name);
147                     }
148                 );
149
150                 $aliases = implode(', ', $aliasList);
151                 $suffix = $aliases ? " ($aliases)" : '';
152                 $rows[] = ['  ' . $name . $suffix, $description];
153             }
154         }
155         $formatterManager = new FormatterManager();
156         list($terminalWidth,) = $application->getTerminalDimensions();
157         $opts = [
158             FormatterOptions::INCLUDE_FIELD_LABELS => false,
159             FormatterOptions::TABLE_STYLE => 'compact',
160             FormatterOptions::TERMINAL_WIDTH => $terminalWidth,
161         ];
162         $formatterOptions = new FormatterOptions([], $opts);
163
164         $formatterManager->write($output, 'table', new RowsOfFields($rows), $formatterOptions);
165     }
166
167     public function getTerminalWidth()
168     {
169         // From \Consolidation\AnnotatedCommand\Options\PrepareTerminalWidthOption::getTerminalWidth
170         $application = Drush::getApplication();
171         $dimensions = $application->getTerminalDimensions();
172         if ($dimensions[0] == null) {
173             return 0;
174         }
175         return $dimensions[0];
176     }
177
178     /**
179      * @param array $namespaced
180      */
181     public function renderListRaw($namespaced)
182     {
183         $table = new Table($this->output());
184         $table->setStyle('compact');
185         foreach ($namespaced as $namespace => $commands) {
186             foreach ($commands as $command) {
187                 $table->addRow([$command->getName(), $command->getDescription()]);
188             }
189         }
190         $table->render();
191     }
192
193     /**
194      * @param Command[] $all
195      * @param string $separator
196      *
197      * @return array
198      */
199     public static function categorize($all, $separator = ':')
200     {
201         foreach ($all as $key => $command) {
202             if (!in_array($key, $command->getAliases()) && !$command->isHidden()) {
203                 $parts = explode($separator, $key);
204                 $namespace = count($parts) >= 2 ? array_shift($parts) : '_global';
205                 $namespaced[$namespace][$key] = $command;
206             }
207         }
208
209         // Avoid solo namespaces.
210         foreach ($namespaced as $namespace => $commands) {
211             if (count($commands) == 1) {
212                 $namespaced['_global'] += $commands;
213                 unset($namespaced[$namespace]);
214             }
215         }
216
217         ksort($namespaced);
218         return $namespaced;
219     }
220 }