outputformat.drush.inc

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

Core drush output formats.

Functions

Namesort descending Description
drush_get_command_format_metadata Given a command name or a command record, return the command formatter that is used to process that command's output.
drush_get_outputformat
drush_hide_output_fields Specify that certain fields should not appear in the resulting output.
drush_set_default_outputformat Dynamically switch to a new output format. Does NOT override user-selected output format.
outputformat_drush_command_alter Implements hook_drush_command_alter
outputformat_drush_engine_outputformat Implements hook_drush_engine_ENGINE_TYPE().
outputformat_drush_engine_topic_additional_text Implements hook_drush_engine_topic_additional_text().
outputformat_drush_engine_type_info Implementation of hook_drush_engine_type_info().
outputformat_drush_help_alter Implements hook_drush_help_alter().

Classes

Namesort descending Description
drush_outputformat Interface for output format engines.

File

commands/core/outputformat.drush.inc
View source
  1. <?php
  2. /**
  3. * @file
  4. * Core drush output formats.
  5. */
  6. /**
  7. * @return drush_outputformat The selected output format engine
  8. */
  9. function drush_get_outputformat() {
  10. return drush_get_engine('outputformat');
  11. }
  12. /**
  13. * Dynamically switch to a new output format. Does NOT override
  14. * user-selected output format.
  15. */
  16. function drush_set_default_outputformat($format, $metadata = array()) {
  17. $command = drush_get_command();
  18. $command['engines']['outputformat']['default'] = $format;
  19. $outputformat = drush_load_command_engine($command, 'outputformat', $metadata);
  20. }
  21. /**
  22. * Given a command name or a command record, return the
  23. * command formatter that is used to process that command's output.
  24. */
  25. function drush_get_command_format_metadata($command, $metadata = array()) {
  26. $commands = drush_get_commands();
  27. if (!is_array($command) && array_key_exists($command, $commands)) {
  28. $command = $commands[$command];
  29. }
  30. return drush_get_command_engine_config($command, 'outputformat', $metadata);
  31. }
  32. /**
  33. * Implementation of hook_drush_engine_type_info().
  34. */
  35. function outputformat_drush_engine_type_info() {
  36. $info = array();
  37. $info['outputformat'] = array(
  38. 'description' => 'Output formatting options selection and use.',
  39. 'topic' => 'docs-output-formats',
  40. 'topic-file' => 'docs/output-formats.md',
  41. 'combine-help' => TRUE,
  42. 'option' => 'format',
  43. 'options' => array(
  44. 'format' => array(
  45. 'description' => 'Select output format.',
  46. 'example-value' => 'json',
  47. ),
  48. 'fields' => array(
  49. 'description' => 'Fields to output.',
  50. 'example-value' => 'field1,field2',
  51. 'value' => 'required',
  52. 'list' => TRUE,
  53. ),
  54. 'list-separator' => array(
  55. 'description' => 'Specify how elements in a list should be separated. In lists of lists, this applies to the elements in the inner lists.',
  56. 'hidden' => TRUE,
  57. ),
  58. 'line-separator' => array(
  59. 'description' => 'In nested lists of lists, specify how the outer lists ("lines") should be separated.',
  60. 'hidden' => TRUE,
  61. ),
  62. 'field-labels' => array(
  63. 'description' => 'Add field labels before first line of data. Default is on; use --no-field-labels to disable.',
  64. 'default' => '1',
  65. 'key' => 'include-field-labels',
  66. ),
  67. ),
  68. // Allow output formats to declare their
  69. // "output data type" instead of their
  70. // "required engine capability" for readability.
  71. 'config-aliases' => array(
  72. 'output-data-type' => 'require-engine-capability',
  73. ),
  74. );
  75. return $info;
  76. }
  77. /**
  78. * Implements hook_drush_engine_ENGINE_TYPE().
  79. *
  80. * The output format types supported are represented by
  81. * the 'engine-capabilities' of the output format engine.
  82. * The different capabilities include:
  83. *
  84. * format-single: A simple string.
  85. *
  86. * format-list: An associative array where the key
  87. * is usually the row label, and the value
  88. * is a simple string. Some list formatters
  89. * render the label, and others (like
  90. * "list" and "csv") throw it away.
  91. *
  92. * format-table: An associative array, where the key
  93. * is the row id, and the value is the
  94. * column data. The column data is also
  95. * an associative array where the key
  96. * is the column id and the value is the
  97. * cell data. The cell data should usually
  98. * be a simple string; however, some
  99. * formatters can recursively format their
  100. * cell contents before rendering (e.g. if
  101. * a cell contains a list of items in an array).
  102. *
  103. * These definitions align with the declared 'output-data-type'
  104. * declared in command records. @see drush_parse_command().
  105. *
  106. * Any output format that does not declare any engine capabilities
  107. * is expected to be able to render any php data structure that is
  108. * passed to it.
  109. */
  110. function outputformat_drush_engine_outputformat() {
  111. $common_topic_example = array(
  112. "a" => array("b" => 2, "c" => 3),
  113. "d" => array("e" => 5, "f" => 6)
  114. );
  115. $engines = array();
  116. $engines['table'] = array(
  117. 'description' => 'A formatted, word-wrapped table.',
  118. 'engine-capabilities' => array('format-table'),
  119. );
  120. $engines['key-value'] = array(
  121. 'description' => 'A formatted list of key-value pairs.',
  122. 'engine-capabilities' => array('format-single', 'format-list', 'format-table'),
  123. 'hidden' => TRUE,
  124. );
  125. $engines['key-value-list'] = array(
  126. 'implemented-by' => 'list',
  127. 'list-item-type' => 'key-value',
  128. 'description' => 'A list of formatted lists of key-value pairs.',
  129. 'list-field-selection-control' => 1,
  130. 'engine-capabilities' => array('format-table'),
  131. 'hidden' => TRUE,
  132. );
  133. $engines['json'] = array(
  134. 'machine-parsable' => TRUE,
  135. 'description' => 'Javascript Object Notation.',
  136. 'topic-example' => $common_topic_example,
  137. );
  138. $engines['string'] = array(
  139. 'machine-parsable' => TRUE,
  140. 'description' => 'A simple string.',
  141. 'engine-capabilities' => array('format-single'),
  142. );
  143. $engines['message'] = array(
  144. 'machine-parsable' => FALSE, // depends on the label....
  145. 'hidden' => TRUE,
  146. );
  147. $engines['print-r'] = array(
  148. 'machine-parsable' => TRUE,
  149. 'description' => 'Output via php print_r function.',
  150. 'verbose-only' => TRUE,
  151. 'topic-example' => $common_topic_example,
  152. );
  153. $engines['var_export'] = array(
  154. 'machine-parsable' => TRUE,
  155. 'description' => 'An array in executable php format.',
  156. 'topic-example' => $common_topic_example,
  157. );
  158. $engines['yaml'] = array(
  159. 'machine-parsable' => TRUE,
  160. 'description' => 'Yaml output format.',
  161. 'topic-example' => $common_topic_example,
  162. );
  163. $engines['php'] = array(
  164. 'machine-parsable' => TRUE,
  165. 'description' => 'A serialized php string.',
  166. 'verbose-only' => TRUE,
  167. 'topic-example' => $common_topic_example,
  168. );
  169. $engines['config'] = array(
  170. 'machine-parsable' => TRUE,
  171. 'implemented-by' => 'list',
  172. 'list-item-type' => 'var_export',
  173. 'description' => "A configuration file in executable php format. The variable name is \"config\", and the variable keys are taken from the output data array's keys.",
  174. 'metadata' => array(
  175. 'variable-name' => 'config',
  176. ),
  177. 'list-field-selection-control' => -1,
  178. 'engine-capabilities' => array('format-list','format-table'),
  179. 'verbose-only' => TRUE,
  180. );
  181. $engines['list'] = array(
  182. 'machine-parsable' => TRUE,
  183. 'list-item-type' => 'string',
  184. 'description' => 'A simple list of values.',
  185. // When a table is printed as a list, only the array keys of the rows will print.
  186. 'engine-capabilities' => array('format-list', 'format-table'),
  187. 'topic-example' => array('a', 'b', 'c'),
  188. );
  189. $engines['nested-csv'] = array(
  190. 'machine-parsable' => TRUE,
  191. 'implemented-by' => 'list',
  192. 'list-separator' => ',',
  193. 'list-item-type' => 'csv-or-string',
  194. 'hidden' => TRUE,
  195. );
  196. $engines['csv-or-string'] = array(
  197. 'machine-parsable' => TRUE,
  198. 'hidden' => TRUE,
  199. );
  200. $engines['csv'] = array(
  201. 'machine-parsable' => TRUE,
  202. 'implemented-by' => 'list',
  203. 'list-item-type' => 'nested-csv',
  204. 'labeled-list' => TRUE,
  205. 'description' => 'A list of values, one per row, each of which is a comma-separated list of values.',
  206. 'engine-capabilities' => array('format-table'),
  207. 'topic-example' => array(array('a', 12, 'a@one.com'),array('b', 17, 'b@two.com')),
  208. );
  209. $engines['variables'] = array(
  210. 'machine-parsable' => TRUE,
  211. 'description' => 'A list of php variable assignments.',
  212. 'engine-capabilities' => array('format-table'),
  213. 'verbose-only' => TRUE,
  214. 'list-field-selection-control' => -1,
  215. 'topic-example' => $common_topic_example,
  216. );
  217. $engines['labeled-export'] = array(
  218. 'machine-parsable' => TRUE,
  219. 'description' => 'A list of php exports, labeled with a name.',
  220. 'engine-capabilities' => array('format-table'),
  221. 'verbose-only' => TRUE,
  222. 'implemented-by' => 'list',
  223. 'list-item-type' => 'var_export',
  224. 'metadata' => array(
  225. 'label-template' => '!label: !value',
  226. ),
  227. 'list-field-selection-control' => -1,
  228. 'topic-example' => $common_topic_example,
  229. );
  230. return $engines;
  231. }
  232. /**
  233. * Implements hook_drush_command_alter
  234. */
  235. function outputformat_drush_command_alter(&$command) {
  236. // In --pipe mode, change the default format to the default pipe format, or
  237. // to json, if no default pipe format is given.
  238. if (drush_get_context('DRUSH_PIPE') && (isset($command['engines']['outputformat']))) {
  239. $default_format = isset($command['engines']['outputformat']['pipe-format']) ? $command['engines']['outputformat']['pipe-format'] : 'json';
  240. $command['engines']['outputformat']['default'] = $default_format;
  241. }
  242. }
  243. /**
  244. * Implements hook_drush_help_alter().
  245. */
  246. function outputformat_drush_help_alter(&$command) {
  247. if (isset($command['engines']['outputformat'])) {
  248. $outputformat = $command['engines']['outputformat'];
  249. // If the command defines specific field labels,
  250. // then modify the help for --fields to include
  251. // specific information about the available fields.
  252. if (isset($outputformat['field-labels'])) {
  253. $all_fields = array();
  254. $all_fields_description = array();
  255. foreach ($outputformat['field-labels'] as $field => $human_readable) {
  256. $all_fields[] = $field;
  257. if ((strtolower($field) != strtolower($human_readable)) && !array_key_exists(strtolower($human_readable), $outputformat['field-labels'])) {
  258. $all_fields_description[] = $field . dt(" (or '!other')", array('!other' => strtolower($human_readable)));
  259. }
  260. else {
  261. $all_fields_description[] = $field;
  262. }
  263. }
  264. $field_defaults = isset($outputformat['fields-default']) ? $outputformat['fields-default'] : $all_fields;
  265. $command['options']['fields']['example-value'] = implode(', ', $field_defaults);
  266. $command['options']['fields']['description'] .= ' '. dt('All available fields are: !fields.', array('!fields' => implode(', ', $all_fields_description)));
  267. if (isset($outputformat['fields-default'])) {
  268. $command['options']['full']['description'] = dt("Show the full output, with all fields included.");
  269. }
  270. }
  271. else {
  272. // If the command does not define specific field labels,
  273. // then hide the help for --fields unless the command
  274. // uses output format engines that format tables.
  275. if (isset($outputformat['require-engine-capability']) && is_array($outputformat['require-engine-capability'])) {
  276. if (!in_array('format-table', $outputformat['require-engine-capability'])) {
  277. unset($command['options']['fields']);
  278. unset($command['options']['field-labels']);
  279. }
  280. }
  281. // If the command does define output formats, but does not
  282. // define fields, then just hide the help for the --fields option.
  283. else {
  284. $command['options']['fields']['hidden'] = TRUE;
  285. $command['options']['field-labels']['hidden'] = TRUE;
  286. }
  287. }
  288. // If the command defines a default pipe format, then
  289. // add '--pipe Equivalent to --format=<pipe-default>'.
  290. if (isset($outputformat['pipe-format'])) {
  291. if (isset($command['options']['pipe'])) {
  292. $command['options']['pipe'] .= ' ';
  293. }
  294. else {
  295. $command['options']['pipe'] = '';
  296. }
  297. if (isset($outputformat['pipe-metadata']['message-template'])) {
  298. $command['options']['pipe'] .= dt('Displays output in the form "!message"', array('!message' => $outputformat['pipe-metadata']['message-template']));
  299. }
  300. else {
  301. $command['options']['pipe'] .= dt("Equivalent to --format=!default.", array('!default' => $outputformat['pipe-format']));
  302. }
  303. }
  304. }
  305. }
  306. /**
  307. * Implements hook_drush_engine_topic_additional_text().
  308. */
  309. function outputformat_drush_engine_topic_additional_text($engine, $instance, $config) {
  310. $result = array();
  311. // If the output format engine has a 'topic-example' in
  312. // its configuration, then format the provided array using
  313. // the output formatter, and insert the result of the
  314. // transform into the topic text.
  315. if ($engine == 'outputformat') {
  316. if (array_key_exists('topic-example', $config)) {
  317. $code = $config['topic-example'];
  318. $formatted = drush_format($code, array(), $instance);
  319. $result[] = dt("Code:\n\nreturn !code;\n\nOutput with --format=!instance:\n\n!formatted", array('!code' => var_export($code, TRUE), '!instance' => $instance, '!formatted' => $formatted));
  320. }
  321. }
  322. return $result;
  323. }
  324. /**
  325. * Interface for output format engines.
  326. */
  327. class drush_outputformat {
  328. function __construct($config) {
  329. $config += array(
  330. 'column-widths' => array(),
  331. 'field-mappings' => array(),
  332. 'engine-info' => array(),
  333. );
  334. $config['engine-info'] += array(
  335. 'machine-parsable' => FALSE,
  336. 'metadata' => array(),
  337. );
  338. $config += $config['engine-info']['metadata'];
  339. $this->engine_config = $config;
  340. }
  341. function format_error($message) {
  342. return drush_set_error('DRUSH_FORMAT_ERROR', dt("The output data could not be processed by the selected format '!type'. !message", array('!type' => $this->engine, '!message' => $message)));
  343. }
  344. function formatter_type() {
  345. return $this->engine;
  346. }
  347. function is_list() {
  348. return FALSE;
  349. }
  350. function formatter_is_simple_list() {
  351. if (!isset($this->sub_engine)) {
  352. return false;
  353. }
  354. return ($this->formatter_type() == 'list') && ($this->sub_engine->supports_single_only());
  355. }
  356. function data_type($metadata) {
  357. if (isset($metadata['metameta']['require-engine-capability']) && is_array($metadata['metameta']['require-engine-capability'])) {
  358. return $metadata['metameta']['require-engine-capability'][0];
  359. }
  360. if (isset($metadata['require-engine-capability']) && is_array($metadata['require-engine-capability'])) {
  361. return $metadata['require-engine-capability'][0];
  362. }
  363. return 'unspecified';
  364. }
  365. function supported_data_types($metadata = NULL) {
  366. if ($metadata == NULL) {
  367. $metadata = $this->engine_config;
  368. }
  369. if (isset($metadata['metameta']['engine-info']['engine-capabilities'])) {
  370. return $metadata['metameta']['engine-info']['engine-capabilities'];
  371. }
  372. if (isset($metadata['engine-info']['engine-capabilities'])) {
  373. return $metadata['engine-info']['engine-capabilities'];
  374. }
  375. return array();
  376. }
  377. function supports_single_only($metadata = NULL) {
  378. $supported = $this->supported_data_types($metadata);
  379. return (count($supported) == 1) && ($supported[0] == 'format-single');
  380. }
  381. function get_info($key) {
  382. if (array_key_exists($key, $this->engine_config)) {
  383. return $this->engine_config[$key];
  384. }
  385. elseif (isset($this->sub_engine)) {
  386. return $this->sub_engine->get_info($key);
  387. }
  388. return FALSE;
  389. }
  390. /**
  391. * Perform pre-processing and then format() the $input.
  392. */
  393. function process($input, $metadata = array()) {
  394. $metadata = array_merge_recursive($metadata, $this->engine_config);
  395. if (isset($metadata['private-fields']) && is_array($input)) {
  396. if (!drush_get_option('show-passwords', FALSE)) {
  397. if (!is_array($metadata['private-fields'])) {
  398. $metadata['private-fields'] = array($metadata['private-fields']);
  399. }
  400. foreach ($metadata['private-fields'] as $private) {
  401. drush_unset_recursive($input, $private);
  402. }
  403. }
  404. }
  405. if (isset($metadata[$this->engine . '-metadata'])) {
  406. $engine_specific_metadata = $metadata[$this->engine . '-metadata'];
  407. unset($metadata[$this->engine . '-metadata']);
  408. $metadata = array_merge($metadata, $engine_specific_metadata);
  409. }
  410. if ((drush_get_context('DRUSH_PIPE')) && (isset($metadata['pipe-metadata']))) {
  411. $pipe_specific_metadata = $metadata['pipe-metadata'];
  412. unset($metadata['pipe-metadata']);
  413. $metadata = array_merge($metadata, $pipe_specific_metadata);
  414. }
  415. $machine_parsable = $this->engine_config['engine-info']['machine-parsable'];
  416. $formatter_type = $machine_parsable ? 'parsable' : 'formatted';
  417. if ((!$machine_parsable) && is_bool($input)) {
  418. $input = $input ? 'TRUE' : 'FALSE';
  419. }
  420. // Run $input through any filters that are specified for this formatter.
  421. if (isset($metadata[$formatter_type . '-filter'])) {
  422. $filters = $metadata[$formatter_type . '-filter'];
  423. if (!is_array($filters)) {
  424. $filters = array($filters);
  425. }
  426. foreach ($filters as $filter) {
  427. if (function_exists($filter)) {
  428. $input = $filter($input, $metadata);
  429. }
  430. }
  431. }
  432. if (isset($metadata['field-labels'])) {
  433. foreach (drush_hide_output_fields() as $hidden_field) {
  434. unset($metadata['field-labels'][$hidden_field]);
  435. }
  436. }
  437. return $this->format($input, $metadata);
  438. }
  439. function format($input, $metadata) {
  440. return $input;
  441. }
  442. }
  443. /**
  444. * Specify that certain fields should not appear in the resulting output.
  445. */
  446. function drush_hide_output_fields($fields_to_hide = array()) {
  447. $already_hidden = drush_get_context('DRUSH_HIDDEN_OUTPUT_FIELDS');
  448. if (!is_array($fields_to_hide)) {
  449. $fields_to_hide = array($fields_to_hide);
  450. }
  451. $result = array_merge($already_hidden, $fields_to_hide);
  452. drush_set_context('DRUSH_HIDDEN_OUTPUT_FIELDS', $result);
  453. return $result;
  454. }