2 namespace Consolidation\OutputFormatters\Formatters;
4 use Symfony\Component\Console\Output\OutputInterface;
5 use Symfony\Component\Console\Helper\Table;
6 use Symfony\Component\Console\Helper\TableStyle;
8 use Consolidation\OutputFormatters\Validate\ValidDataTypesInterface;
9 use Consolidation\OutputFormatters\Options\FormatterOptions;
10 use Consolidation\OutputFormatters\Validate\ValidDataTypesTrait;
11 use Consolidation\OutputFormatters\StructuredData\TableDataInterface;
12 use Consolidation\OutputFormatters\Transformations\ReorderFields;
13 use Consolidation\OutputFormatters\Exception\IncompatibleDataException;
14 use Consolidation\OutputFormatters\Transformations\WordWrapper;
15 use Consolidation\OutputFormatters\Formatters\HumanReadableFormat;
18 * Display a table of data with the Symfony Table class.
20 * This formatter takes data of either the RowsOfFields or
21 * PropertyList data type. Tables can be rendered with the
22 * rows running either vertically (the normal orientation) or
23 * horizontally. By default, associative lists will be displayed
24 * as two columns, with the key in the first column and the
25 * value in the second column.
27 class TableFormatter implements FormatterInterface, ValidDataTypesInterface, RenderDataInterface, MetadataFormatterInterface, HumanReadableFormat
29 use ValidDataTypesTrait;
30 use RenderTableDataTrait;
31 use MetadataFormatterTrait;
33 protected $fieldLabels;
34 protected $defaultFields;
36 public function __construct()
40 public function validDataTypes()
44 new \ReflectionClass('\Consolidation\OutputFormatters\StructuredData\RowsOfFields'),
45 new \ReflectionClass('\Consolidation\OutputFormatters\StructuredData\PropertyList')
52 public function validate($structuredData)
54 // If the provided data was of class RowsOfFields
55 // or PropertyList, it will be converted into
56 // a TableTransformation object by the restructure call.
57 if (!$structuredData instanceof TableDataInterface) {
58 throw new IncompatibleDataException(
61 $this->validDataTypes()
64 return $structuredData;
70 public function write(OutputInterface $output, $tableTransformer, FormatterOptions $options)
74 FormatterOptions::TABLE_STYLE => 'consolidation',
75 FormatterOptions::INCLUDE_FIELD_LABELS => true,
78 $table = new Table($output);
80 static::addCustomTableStyles($table);
82 $table->setStyle($options->get(FormatterOptions::TABLE_STYLE, $defaults));
83 $isList = $tableTransformer->isList();
84 $includeHeaders = $options->get(FormatterOptions::INCLUDE_FIELD_LABELS, $defaults);
85 $listDelimiter = $options->get(FormatterOptions::LIST_DELIMITER, $defaults);
87 $headers = $tableTransformer->getHeaders();
88 $data = $tableTransformer->getTableData($includeHeaders && $isList);
91 if (!empty($headers)) {
92 array_splice($headers, 1, 0, ':');
94 $data = array_map(function ($item) {
95 array_splice($item, 1, 0, ':');
100 if ($includeHeaders && !$isList) {
101 $table->setHeaders($headers);
104 // todo: $output->getFormatter();
105 $data = $this->wrap($headers, $data, $table->getStyle(), $options);
106 $table->setRows($data);
111 * Wrap the table data
113 * @param TableStyle $tableStyle
114 * @param FormatterOptions $options
117 protected function wrap($headers, $data, TableStyle $tableStyle, FormatterOptions $options)
119 $wrapper = new WordWrapper($options->get(FormatterOptions::TERMINAL_WIDTH));
120 $wrapper->setPaddingFromStyle($tableStyle);
121 if (!empty($headers)) {
122 $headerLengths = array_map(function ($item) {
123 return strlen($item);
125 $wrapper->setMinimumWidths($headerLengths);
127 return $wrapper->wrap($data);
131 * Add our custom table style(s) to the table.
133 protected static function addCustomTableStyles($table)
135 // The 'consolidation' style is the same as the 'symfony-style-guide'
136 // style, except it maintains the colored headers used in 'default'.
137 $consolidationStyle = new TableStyle();
139 ->setHorizontalBorderChar('-')
140 ->setVerticalBorderChar(' ')
141 ->setCrossingChar(' ')
143 $table->setStyleDefinition('consolidation', $consolidationStyle);