help.drush.inc

  1. 8.0.x commands/core/help.drush.inc
  2. 6.x commands/core/help.drush.inc
  3. 7.x commands/core/help.drush.inc
  4. 4.x commands/core/help.drush.inc
  5. 5.x commands/core/help.drush.inc
  6. master commands/core/help.drush.inc

Functions

Namesort descending Description
drush_core_help Command callback for help command. This is the default command, when none other has been specified.
drush_format_help_section Format one named help section from a command record
drush_global_options_command Build a fake command for the purposes of showing examples and options.
drush_help_categorize Organize commands into categories
drush_help_html Return an HTML page documenting all available commands and global options.
drush_help_html_command_list
drush_help_html_global_options
drush_help_html_header Return an HTML page header.
drush_help_listing_print Print CLI table or HTML table listing all commands.
drush_help_section_default_formatter The default section formatter. Replaces '[command]' with the command name.
drush_help_section_formatter_options The options section formatter. Adds a "--" in front of each item label. Also handles short-form and example-value components in the help attributes.
drush_help_visible
drush_print_help Print the help for a single command to the screen.
drush_show_help Prints out help for a given command.
_drush_format_help_subsection Format one named portion of a subsection from a command record. Subsections allow related parts of a help record to be grouped together. For example, in the 'options' section, sub-options that are related to a particular primary option are…
_drush_help_merge_subcommand_information Check to see if the specified command contains an 'allow-additional-options' record. If it does, find the additional options that are allowed, and add in the help text for the options of all of the sub-commands.
_drush_help_sort_command_options Sort command options alphabetically. Engine options at the end.

File

commands/core/help.drush.inc
View source
  1. <?php
  2. use Drush\Log\LogLevel;
  3. /**
  4. * Prints out help for a given command.
  5. */
  6. function drush_show_help($commandstring) {
  7. // First check and see if the command can already be found.
  8. $commands = drush_get_commands();
  9. if (!array_key_exists($commandstring, $commands)) {
  10. // If the command cannot be found, then bootstrap so that
  11. // additional commands will be brought in.
  12. // For speed, only bootstrap up to DRUSH_BOOTSTRAP_DRUPAL_SITE.
  13. drush_bootstrap_max(DRUSH_BOOTSTRAP_DRUPAL_SITE);
  14. $commands = drush_get_commands();
  15. }
  16. if (array_key_exists($commandstring, $commands)) {
  17. $command = $commands[$commandstring];
  18. drush_print_help($command);
  19. return TRUE;
  20. }
  21. $shell_aliases = drush_get_context('shell-aliases', array());
  22. if (array_key_exists($commandstring, $shell_aliases)) {
  23. $msg = dt("'@alias-name' is a shell alias. Its value is: !name. See `drush topic docs-shell-aliases` and `drush shell-alias` for more information.", array('@alias-name' => $commandstring, '!name' => $shell_aliases[$commandstring]));
  24. drush_log($msg, LogLevel::OK);
  25. return TRUE;
  26. }
  27. return drush_set_error('DRUSH_COMMAND_NOT_FOUND', dt('Invalid command !command.', array('!command' => $commandstring)));
  28. }
  29. /**
  30. * Print the help for a single command to the screen.
  31. *
  32. * @param array $command
  33. * A fully loaded $command array.
  34. */
  35. function drush_print_help($command) {
  36. _drush_help_merge_subcommand_information($command);
  37. if (!$help = drush_command_invoke_all('drush_help', 'drush:'. $command['command'])) {
  38. $help = array($command['description']);
  39. }
  40. if ($command['strict-option-handling']) {
  41. $command['topics'][] = 'docs-strict-options';
  42. }
  43. // Give commandfiles an opportunity to add examples and options to the command.
  44. drush_bootstrap_max(DRUSH_BOOTSTRAP_DRUPAL_SITE);
  45. drush_engine_add_help_topics($command);
  46. drush_command_invoke_all_ref('drush_help_alter', $command);
  47. drush_print(wordwrap(implode("\n", $help), drush_get_context('DRUSH_COLUMNS', 80)));
  48. drush_print();
  49. $global_options = drush_get_global_options();
  50. foreach ($command['global-options'] as $global_option) {
  51. $command['options'][$global_option] = $global_options[$global_option];
  52. }
  53. // Sort command options.
  54. uksort($command['options'], '_drush_help_sort_command_options');
  55. // Print command sections help.
  56. foreach ($command['sections'] as $key => $value) {
  57. if (!empty($command[$key])) {
  58. $rows = drush_format_help_section($command, $key);
  59. if ($rows) {
  60. drush_print(dt($value) . ':');
  61. drush_print_table($rows, FALSE, array('label' => 40));
  62. unset($rows);
  63. drush_print();
  64. }
  65. }
  66. }
  67. // Append aliases if any.
  68. if ($command['aliases']) {
  69. drush_print(dt("Aliases: ") . implode(', ', $command['aliases']));
  70. }
  71. }
  72. /**
  73. * Sort command options alphabetically. Engine options at the end.
  74. */
  75. function _drush_help_sort_command_options($a, $b) {
  76. $engine_a = strpos($a, '=');
  77. $engine_b = strpos($b, '=');
  78. if ($engine_a && !$engine_b) {
  79. return 1;
  80. }
  81. else if (!$engine_a && $engine_b) {
  82. return -1;
  83. }
  84. elseif ($engine_a && $engine_b) {
  85. if (substr($a, 0, $engine_a) == substr($b, 0, $engine_b)) {
  86. return 0;
  87. }
  88. }
  89. return ($a < $b) ? -1 : 1;
  90. }
  91. /**
  92. * Check to see if the specified command contains an 'allow-additional-options'
  93. * record. If it does, find the additional options that are allowed, and
  94. * add in the help text for the options of all of the sub-commands.
  95. */
  96. function _drush_help_merge_subcommand_information(&$command) {
  97. // 'allow-additional-options' will either be FALSE (default),
  98. // TRUE ("allow anything"), or an array that lists subcommands
  99. // that are or may be called via drush_invoke by this command.
  100. if (is_array($command['allow-additional-options'])) {
  101. $implemented = drush_get_commands();
  102. foreach ($command['allow-additional-options'] as $subcommand_name) {
  103. if (array_key_exists($subcommand_name, $implemented)) {
  104. $command['options'] += $implemented[$subcommand_name]['options'];
  105. $command['sub-options'] = array_merge_recursive($command['sub-options'], $implemented[$subcommand_name]['sub-options']);
  106. if (empty($command['arguments'])) {
  107. $command['arguments'] = $implemented[$subcommand_name]['arguments'];
  108. }
  109. $command['topics'] = array_merge($command['topics'], $implemented[$subcommand_name]['topics']);
  110. }
  111. }
  112. }
  113. }
  114. /**
  115. * Format one named help section from a command record
  116. *
  117. * @param $command
  118. * A command record with help information
  119. * @param $section
  120. * The name of the section to format ('options', 'topic', etc.)
  121. * @returns array
  122. * Formatted rows, suitable for printing via drush_print_table. The returned
  123. * array can be empty.
  124. */
  125. function drush_format_help_section($command, $section) {
  126. $rows = array();
  127. $formatter = (function_exists('drush_help_section_formatter_' . $section)) ? 'drush_help_section_formatter_' . $section : 'drush_help_section_default_formatter';
  128. foreach ($command[$section] as $name => $help_attributes) {
  129. if (!is_array($help_attributes)) {
  130. $help_attributes = array('description' => $help_attributes);
  131. }
  132. $help_attributes['label'] = $name;
  133. call_user_func_array($formatter, array($command, &$help_attributes));
  134. if (empty($help_attributes['hidden'])) {
  135. $rows[] = array('label' => $help_attributes['label'], 'description' => $help_attributes['description']);
  136. // Process the subsections too, if any
  137. if (!empty($command['sub-' . $section]) && array_key_exists($name, $command['sub-' . $section])) {
  138. $rows = array_merge($rows, _drush_format_help_subsection($command, $section, $name, $formatter));
  139. }
  140. }
  141. }
  142. return $rows;
  143. }
  144. /**
  145. * Format one named portion of a subsection from a command record.
  146. * Subsections allow related parts of a help record to be grouped
  147. * together. For example, in the 'options' section, sub-options that
  148. * are related to a particular primary option are stored in a 'sub-options'
  149. * section whose name == the name of the primary option.
  150. *
  151. * @param $command
  152. * A command record with help information
  153. * @param $section
  154. * The name of the section to format ('options', 'topic', etc.)
  155. * @param $subsection
  156. * The name of the subsection (e.g. the name of the primary option)
  157. * @param $formatter
  158. * The name of a function to use to format the rows of the subsection
  159. * @param $prefix
  160. * Characters to prefix to the front of the label (for indentation)
  161. * @returns array
  162. * Formatted rows, suitable for printing via drush_print_table.
  163. */
  164. function _drush_format_help_subsection($command, $section, $subsection, $formatter, $prefix = ' ') {
  165. $rows = array();
  166. foreach ($command['sub-' . $section][$subsection] as $name => $help_attributes) {
  167. if (!is_array($help_attributes)) {
  168. $help_attributes = array('description' => $help_attributes);
  169. }
  170. $help_attributes['label'] = $name;
  171. call_user_func_array($formatter, array($command, &$help_attributes));
  172. if (!array_key_exists('hidden', $help_attributes)) {
  173. $rows[] = array('label' => $prefix . $help_attributes['label'], 'description' => $help_attributes['description']);
  174. // Process the subsections too, if any
  175. if (!empty($command['sub-' . $section]) && array_key_exists($name, $command['sub-' . $section])) {
  176. $rows = array_merge($rows, _drush_format_help_subsection($command, $section, $name, $formatter, $prefix . ' '));
  177. }
  178. }
  179. }
  180. return $rows;
  181. }
  182. /**
  183. * The options section formatter. Adds a "--" in front of each
  184. * item label. Also handles short-form and example-value
  185. * components in the help attributes.
  186. */
  187. function drush_help_section_formatter_options($command, &$help_attributes) {
  188. if ($help_attributes['label'][0] == '-') {
  189. drush_log(dt("Option '!option' of command !command should instead be declared as '!fixed'", array('!option' => $help_attributes['label'], '!command' => $command['command'], '!fixed' => preg_replace('/^--*/', '', $help_attributes['label']))), LogLevel::DEBUG);
  190. }
  191. else {
  192. $help_attributes['label'] = '--' . $help_attributes['label'];
  193. }
  194. if (!empty($help_attributes['required'])) {
  195. $help_attributes['description'] .= " " . dt("Required.");
  196. }
  197. $prefix = '<';
  198. $suffix = '>';
  199. if (array_key_exists('example-value', $help_attributes)) {
  200. if (isset($help_attributes['value']) && $help_attributes['value'] == 'optional') {
  201. $prefix = '[';
  202. $suffix = ']';
  203. }
  204. $help_attributes['label'] .= '=' . $prefix . $help_attributes['example-value'] . $suffix;
  205. if (array_key_exists('short-form', $help_attributes)) {
  206. $help_attributes['short-form'] .= " $prefix" . $help_attributes['example-value'] . $suffix;
  207. }
  208. }
  209. if (array_key_exists('short-form', $help_attributes)) {
  210. $help_attributes['label'] = '-' . $help_attributes['short-form'] . ', ' . $help_attributes['label'];
  211. }
  212. drush_help_section_default_formatter($command, $help_attributes);
  213. }
  214. /**
  215. * The default section formatter. Replaces '[command]' with the
  216. * command name.
  217. */
  218. function drush_help_section_default_formatter($command, &$help_attributes) {
  219. // '[command]' is a token representing the current command. @see pm_drush_engine_version_control().
  220. $help_attributes['label'] = str_replace('[command]', $command['command'], $help_attributes['label']);
  221. }
  222. /**
  223. * Build a fake command for the purposes of showing examples and options.
  224. */
  225. function drush_global_options_command($brief = FALSE) {
  226. $global_options_help = array(
  227. 'description' => 'Execute a drush command. Run `drush help [command]` to view command-specific help. Run `drush topic` to read even more documentation.',
  228. 'sections' => array(
  229. 'options' => 'Global options (see `drush topic core-global-options` for the full list)',
  230. ),
  231. 'options' => drush_get_global_options($brief),
  232. 'examples' => array(
  233. 'drush dl cck zen' => 'Download CCK module and Zen theme.',
  234. 'drush --uri=http://example.com status' => 'Show status command for the example.com multi-site.',
  235. ),
  236. '#brief' => TRUE,
  237. );
  238. $global_options_help += drush_command_defaults('global-options', 'global_options', __FILE__);
  239. drush_command_invoke_all_ref('drush_help_alter', $global_options_help);
  240. ksort($global_options_help['options']);
  241. return $global_options_help;
  242. }
  243. /**
  244. * Command callback for help command. This is the default command, when none
  245. * other has been specified.
  246. */
  247. function drush_core_help() {
  248. $commands = func_get_args();
  249. $format = drush_get_option('format');
  250. // Backwards compatibility for --html option.
  251. if (drush_get_option('html')) {
  252. $format = 'html';
  253. }
  254. if (empty($commands)) {
  255. // For speed, only bootstrap up to DRUSH_BOOTSTRAP_DRUPAL_CONFIGURATION.
  256. drush_bootstrap_max(DRUSH_BOOTSTRAP_DRUPAL_CONFIGURATION);
  257. $implemented = drush_get_commands();
  258. ksort($implemented);
  259. $command_categories = drush_help_categorize($implemented);
  260. $visible = drush_help_visible($command_categories);
  261. // If the user specified --filter w/out a value, then
  262. // present a choice list of help categories.
  263. if (drush_get_option('filter', FALSE) === TRUE) {
  264. $help_categories = array();
  265. foreach ($command_categories as $key => $info) {
  266. $description = $info['title'];
  267. if (array_key_exists('summary', $info)) {
  268. $description .= ": " . $info['summary'];
  269. }
  270. $help_categories[$key] = $description;
  271. }
  272. $result = drush_choice($help_categories, 'Select a help category:');
  273. if (!$result) {
  274. return drush_user_abort();
  275. }
  276. drush_set_option('filter', $result);
  277. }
  278. // Filter out categories that the user does not want to see
  279. $filter_category = drush_get_option('filter');
  280. if (!empty($filter_category) && ($filter_category !== TRUE)) {
  281. if (!array_key_exists($filter_category, $command_categories)) {
  282. return drush_set_error('DRUSH_NO_CATEGORY', dt("The specified command category !filter does not exist.", array('!filter' => $filter_category)));
  283. }
  284. $command_categories = array($filter_category => $command_categories[$filter_category]);
  285. }
  286. if ($format == 'html') {
  287. drush_print(drush_help_html_header());
  288. }
  289. // Make a fake command section to hold the global options, then print it.
  290. $global_options_help = drush_global_options_command(TRUE);
  291. if (!in_array($format, array('html', 'var_export', 'json')) && !drush_get_option('filter')) {
  292. drush_print_help($global_options_help);
  293. }
  294. if ($format == 'json' || $format == 'var_export') {
  295. // Print giant array, and set backend_result. We do it this way because this command
  296. // isn't yet fully compliant with outputformat system. To do so, we need to deal with
  297. // the fact that this command varies output significantly when showing help for one
  298. // command versus a listing. We also have oddball HTML format.
  299. drush_print(drush_format($command_categories, 'commands'));
  300. drush_backend_set_result($command_categories);
  301. return NULL;
  302. }
  303. else {
  304. // HTML and CLI command listing (in a table).
  305. drush_help_listing_print($command_categories, $format);
  306. if ($format == 'html') {
  307. // Print global options and long-form help for all commands.
  308. drush_print(drush_help_html_global_options($global_options_help));
  309. drush_print(drush_help_html($visible));
  310. }
  311. }
  312. // Newline-delimited list for use by other scripts. Set the --pipe option.
  313. if (drush_get_option('pipe')) {
  314. drush_print_pipe(implode("\n", array_keys($visible)));
  315. }
  316. return;
  317. }
  318. else {
  319. $result = TRUE;
  320. while ((count($commands) > 0) && !drush_get_error()) {
  321. $result = drush_show_help(array_shift($commands));
  322. }
  323. return $result;
  324. }
  325. return drush_set_error('DRUSH_COMMAND_NOT_FOUND', dt('Invalid command !command.', array('!command' => implode(" ", $commands))));
  326. }
  327. // Uncategorize the list of commands. Hiddens have been removed and
  328. // filtering performed.
  329. function drush_help_visible($command_categories) {
  330. $all = array();
  331. foreach ($command_categories as $category => $info) {
  332. $all = array_merge($all, $info['commands']);
  333. }
  334. return $all;
  335. }
  336. /**
  337. * Print CLI table or HTML table listing all commands.
  338. */
  339. function drush_help_listing_print($command_categories, $format) {
  340. $all_commands = array();
  341. foreach ($command_categories as $key => $info) {
  342. // Get the commands in this category.
  343. $commands = $info['commands'];
  344. // Build rows for drush_print_table().
  345. $rows = array();
  346. foreach($commands as $cmd => $command) {
  347. $name = $command['aliases'] ? $cmd . ' (' . implode(', ', $command['aliases']) . ')': $cmd;
  348. $rows[$cmd] = array('name' => $name, 'description' => $command['description']);
  349. }
  350. // Vary the output by mode: CLI or HTML
  351. if ($format == 'html') {
  352. drush_print("<h3>" . $info['title'] . "</h3>");
  353. drush_print(drush_help_html_command_list($commands));
  354. }
  355. else {
  356. drush_print($info['title'] . ": (" . $key . ")");
  357. drush_print_table($rows, FALSE, array('name' => 20));
  358. }
  359. }
  360. }
  361. /**
  362. * Organize commands into categories
  363. */
  364. function drush_help_categorize($implemented) {
  365. $command_categories = array();
  366. $category_map = array();
  367. foreach ($implemented as $key => $candidate) {
  368. if ((!array_key_exists('is_alias', $candidate) || !$candidate['is_alias']) && !$candidate['hidden']) {
  369. $category = $candidate['category'];
  370. // If we have decided to remap a category, remap every command
  371. if (array_key_exists($category, $category_map)) {
  372. $category = $category_map[$category];
  373. }
  374. if (!array_key_exists($category, $command_categories)) {
  375. $title = drush_command_invoke_all('drush_help', "meta:$category:title");
  376. $alternate_title = '';
  377. if (!$title) {
  378. // If there is no title, then check to see if the
  379. // command file is stored in a folder with the same
  380. // name as some other command file (e.g. 'core') that
  381. // defines a title.
  382. $alternate = basename($candidate['path']);
  383. $alternate_title = drush_command_invoke_all('drush_help', "meta:$alternate:title");
  384. }
  385. if (!empty($alternate_title)) {
  386. $category_map[$category] = $alternate;
  387. $category = $alternate;
  388. $title = $alternate_title;
  389. }
  390. $command_categories[$category]['title'] = empty($title) ? '' : $title[0];
  391. $summary = drush_command_invoke_all('drush_help', "meta:$category:summary");
  392. if ($summary) {
  393. $command_categories[$category]['summary'] = $summary[0];
  394. }
  395. }
  396. $candidate['category'] = $category;
  397. $command_categories[$category]['commands'][$key] = $candidate;
  398. }
  399. }
  400. // Make sure that 'core' is always first in the list
  401. $core_category = array('core' => $command_categories['core']);
  402. unset($command_categories['core']);
  403. // Post-process the categories that have no title.
  404. // Any that have fewer than 4 commands go into a section called "other".
  405. $processed_categories = array();
  406. $misc_categories = array();
  407. $other_commands = array();
  408. $other_categories = array();
  409. foreach ($command_categories as $key => $info) {
  410. if (empty($info['title'])) {
  411. $one_category = $key;
  412. if (count($info['commands']) < 4) {
  413. $other_commands = array_merge($other_commands, $info['commands']);
  414. $other_categories[] = $one_category;
  415. }
  416. else {
  417. $info['title'] = dt("All commands in !category", array('!category' => $key));
  418. $misc_categories[$one_category] = $info;
  419. }
  420. }
  421. else {
  422. $processed_categories[$key] = $info;
  423. }
  424. }
  425. $other_category = array();
  426. if (!empty($other_categories)) {
  427. $other_category[implode(',', $other_categories)] = array('title' => dt("Other commands"), 'commands' => $other_commands);
  428. }
  429. asort($processed_categories);
  430. asort($misc_categories);
  431. $command_categories = array_merge($core_category, $processed_categories, $misc_categories, $other_category);
  432. // If the user specified --sort, then merge all of the remaining
  433. // categories together
  434. if (drush_get_option('sort', FALSE)) {
  435. $combined_commands = array();
  436. foreach ($command_categories as $key => $info) {
  437. $combined_commands = array_merge($combined_commands, $info['commands']);
  438. }
  439. $command_categories = array('all' => array('commands' => $combined_commands, 'title' => dt("Commands:")));
  440. }
  441. return $command_categories;
  442. }
  443. /**
  444. * Return an HTML page header.
  445. */
  446. function drush_help_html_header() {
  447. return "<html><head><title>Drush help</title><style>dt {font-size: 110%; font-weight: bold}</style></head><body>\n";
  448. }
  449. function drush_help_html_global_options($global_options_help) {
  450. // Global options
  451. $global_option_rows = drush_format_help_section($global_options_help, 'options');
  452. $output = '<h3>Global Options (see `drush topic core-global-options` for the full list)</h3><table>';
  453. foreach ($global_option_rows as $row) {
  454. $output .= "<tr>";
  455. foreach ($row as $value) {
  456. $output .= "<td>" . htmlspecialchars($value) . "</td>\n";
  457. }
  458. $output .= "</tr>";
  459. }
  460. $output .= "</table>\n";
  461. return $output;
  462. }
  463. function drush_help_html_command_list($commands) {
  464. // Command table
  465. $output = "<table>\n";
  466. foreach ($commands as $key => $command) {
  467. $output .= " <tr><td><a href=\"#$key\">$key</a></td><td>" . $command['description'] . "</td></tr>\n";
  468. }
  469. $output .= "</table>\n";
  470. return $output;
  471. }
  472. /**
  473. * Return an HTML page documenting all available commands and global options.
  474. */
  475. function drush_help_html($commands) {
  476. // Command details
  477. $output = '<h3>Command detail</h3><dl>';
  478. foreach ($commands as $key => $command) {
  479. $output .= "\n<a name=\"$key\"></a><dt>$key</dt><dd><pre>\n";
  480. ob_start();
  481. drush_show_help($key);
  482. $output .= ob_get_clean();
  483. $output .= "</pre></dd>\n";
  484. }
  485. $output .= "</body></html>\n";
  486. return $output;
  487. }