Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 66028fe

Browse files
committed
[Console] Added support for definition list
1 parent 7a9c5da commit 66028fe

File tree

8 files changed

+210
-7
lines changed

8 files changed

+210
-7
lines changed

src/Symfony/Component/Console/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ CHANGELOG
88
* added method `preventRedrawFasterThan()` and `forceRedrawSlowerThan()` on `ProgressBar`
99
* `Application` implements `ResetInterface`
1010
* marked all dispatched event classes as `@final`
11+
* added support for displaying table horizontally
1112

1213
4.3.0
1314
-----

src/Symfony/Component/Console/Helper/Table.php

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class Table
4848
* Table rows.
4949
*/
5050
private $rows = [];
51+
private $horizontal = false;
5152

5253
/**
5354
* Column widths cache.
@@ -322,6 +323,13 @@ public function setFooterTitle(?string $title): self
322323
return $this;
323324
}
324325

326+
public function setHorizontal(bool $horizontal = true): self
327+
{
328+
$this->horizontal = $horizontal;
329+
330+
return $this;
331+
}
332+
325333
/**
326334
* Renders table to output.
327335
*
@@ -337,14 +345,35 @@ public function setFooterTitle(?string $title): self
337345
*/
338346
public function render()
339347
{
340-
$rows = array_merge($this->headers, [$divider = new TableSeparator()], $this->rows);
348+
$divider = new TableSeparator();
349+
if ($this->horizontal) {
350+
$rows = [];
351+
foreach ($this->headers[0] ?? [] as $i => $header) {
352+
$rows[$i] = [$header];
353+
foreach ($this->rows as $row) {
354+
if ($row instanceof TableSeparator) {
355+
continue;
356+
}
357+
if (isset($row[$i])) {
358+
$rows[$i][] = $row[$i];
359+
} elseif ($rows[$i][0] instanceof TableCell && $rows[$i][0]->getColspan() >= 2) {
360+
// Noop, there is a "title"
361+
} else {
362+
$rows[$i][] = null;
363+
}
364+
}
365+
}
366+
} else {
367+
$rows = array_merge($this->headers, [$divider], $this->rows);
368+
}
369+
341370
$this->calculateNumberOfColumns($rows);
342371

343372
$rows = $this->buildTableRows($rows);
344373
$this->calculateColumnsWidth($rows);
345374

346-
$isHeader = true;
347-
$isFirstRow = false;
375+
$isHeader = !$this->horizontal;
376+
$isFirstRow = $this->horizontal;
348377
foreach ($rows as $row) {
349378
if ($divider === $row) {
350379
$isHeader = false;
@@ -369,8 +398,11 @@ public function render()
369398
$this->renderRowSeparator(self::SEPARATOR_TOP, $this->headerTitle, $this->style->getHeaderTitleFormat());
370399
}
371400
}
372-
373-
$this->renderRow($row, $isHeader ? $this->style->getCellHeaderFormat() : $this->style->getCellRowFormat());
401+
if ($this->horizontal) {
402+
$this->renderRow($row, $this->style->getCellRowFormat(), $this->style->getCellHeaderFormat());
403+
} else {
404+
$this->renderRow($row, $isHeader ? $this->style->getCellHeaderFormat() : $this->style->getCellRowFormat());
405+
}
374406
}
375407
$this->renderRowSeparator(self::SEPARATOR_BOTTOM, $this->footerTitle, $this->style->getFooterTitleFormat());
376408

@@ -450,13 +482,17 @@ private function renderColumnSeparator(int $type = self::BORDER_OUTSIDE)
450482
*
451483
* | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |
452484
*/
453-
private function renderRow(array $row, string $cellFormat)
485+
private function renderRow(array $row, string $cellFormat, string $firstCellFormat = null)
454486
{
455487
$rowContent = $this->renderColumnSeparator(self::BORDER_OUTSIDE);
456488
$columns = $this->getRowColumns($row);
457489
$last = \count($columns) - 1;
458490
foreach ($columns as $i => $column) {
459-
$rowContent .= $this->renderCell($row, $column, $cellFormat);
491+
if ($firstCellFormat && 0 === $i) {
492+
$rowContent .= $this->renderCell($row, $column, $firstCellFormat);
493+
} else {
494+
$rowContent .= $this->renderCell($row, $column, $cellFormat);
495+
}
460496
$rowContent .= $this->renderColumnSeparator($last === $i ? self::BORDER_OUTSIDE : self::BORDER_INSIDE);
461497
}
462498
$this->output->writeln($rowContent);

src/Symfony/Component/Console/Style/SymfonyStyle.php

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,15 @@
1111

1212
namespace Symfony\Component\Console\Style;
1313

14+
use Symfony\Component\Console\Exception\InvalidArgumentException;
1415
use Symfony\Component\Console\Exception\RuntimeException;
1516
use Symfony\Component\Console\Formatter\OutputFormatter;
1617
use Symfony\Component\Console\Helper\Helper;
1718
use Symfony\Component\Console\Helper\ProgressBar;
1819
use Symfony\Component\Console\Helper\SymfonyQuestionHelper;
1920
use Symfony\Component\Console\Helper\Table;
21+
use Symfony\Component\Console\Helper\TableCell;
22+
use Symfony\Component\Console\Helper\TableSeparator;
2023
use Symfony\Component\Console\Input\InputInterface;
2124
use Symfony\Component\Console\Output\BufferedOutput;
2225
use Symfony\Component\Console\Output\OutputInterface;
@@ -190,6 +193,69 @@ public function table(array $headers, array $rows)
190193
$this->newLine();
191194
}
192195

196+
/**
197+
* Formats a horizontal table.
198+
*/
199+
public function horizontalTable(array $headers, array $rows)
200+
{
201+
$style = clone Table::getStyleDefinition('symfony-style-guide');
202+
$style->setCellHeaderFormat('<info>%s</info>');
203+
204+
$table = new Table($this);
205+
$table->setHeaders($headers);
206+
$table->setRows($rows);
207+
$table->setStyle($style);
208+
$table->setHorizontal(true);
209+
210+
$table->render();
211+
$this->newLine();
212+
}
213+
214+
/**
215+
* Formats a list of key/value horizontally.
216+
*
217+
* Each row can be one of:
218+
* * 'A title'
219+
* * ['key' => 'value']
220+
* * new TableSeparator()
221+
*
222+
* @param string|array|TableSeparator ...$list
223+
*/
224+
public function definitionList(...$list)
225+
{
226+
$style = clone Table::getStyleDefinition('symfony-style-guide');
227+
$style->setCellHeaderFormat('<info>%s</info>');
228+
229+
$table = new Table($this);
230+
$headers = [];
231+
$row = [];
232+
foreach ($list as $value) {
233+
if ($value instanceof TableSeparator) {
234+
$headers[] = $value;
235+
$row[] = $value;
236+
continue;
237+
}
238+
if (\is_string($value)) {
239+
$headers[] = new TableCell($value, ['colspan' => 2]);
240+
$row[] = null;
241+
continue;
242+
}
243+
if (!\is_array($value)) {
244+
throw new InvalidArgumentException('Value should be an array, string, or an instance of TableSeparator.');
245+
}
246+
$headers[] = key($value);
247+
$row[] = current($value);
248+
}
249+
250+
$table->setHeaders($headers);
251+
$table->setRows([$row]);
252+
$table->setHorizontal();
253+
$table->setStyle($style);
254+
255+
$table->render();
256+
$this->newLine();
257+
}
258+
193259
/**
194260
* {@inheritdoc}
195261
*/
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
use Symfony\Component\Console\Helper\TableSeparator;
4+
use Symfony\Component\Console\Input\InputInterface;
5+
use Symfony\Component\Console\Output\OutputInterface;
6+
use Symfony\Component\Console\Style\SymfonyStyle;
7+
8+
return function (InputInterface $input, OutputInterface $output) {
9+
$output = new SymfonyStyle($input, $output);
10+
11+
$output->definitionList(
12+
['foo' => 'bar'],
13+
new TableSeparator(),
14+
'this is a title',
15+
new TableSeparator(),
16+
['foo2' => 'bar2']
17+
);
18+
};
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
use Symfony\Component\Console\Helper\TableCell;
4+
use Symfony\Component\Console\Input\InputInterface;
5+
use Symfony\Component\Console\Output\OutputInterface;
6+
use Symfony\Component\Console\Style\SymfonyStyle;
7+
8+
//Ensure formatting tables when using multiple headers with TableCell
9+
return function (InputInterface $input, OutputInterface $output) {
10+
$output = new SymfonyStyle($input, $output);
11+
$output->horizontalTable(['a', 'b', 'c', 'd'], [[1, 2, 3], [4, 5], [7, 8, 9]]);
12+
};
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---------- ---------
2+
foo bar
3+
---------- ---------
4+
this is a title
5+
---------- ---------
6+
foo2 bar2
7+
---------- ---------
8+
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
--- --- --- ---
2+
a 1 4 7
3+
b 2 5 8
4+
c 3 9
5+
d
6+
--- --- --- ---
7+

src/Symfony/Component/Console/Tests/Helper/TableTest.php

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,6 +1125,61 @@ public function testBoxedStyleWithColspan()
11251125
$this->assertSame($expected, $this->getOutputContent($output));
11261126
}
11271127

1128+
public function provideRenderHorizontalTests()
1129+
{
1130+
$headers = ['foo', 'bar', 'baz'];
1131+
$rows = [['one', 'two', 'tree'], ['1', '2', '3']];
1132+
$expected = <<<EOTXT
1133+
+-----+------+---+
1134+
| foo | one | 1 |
1135+
| bar | two | 2 |
1136+
| baz | tree | 3 |
1137+
+-----+------+---+
1138+
1139+
EOTXT;
1140+
yield [$headers, $rows, $expected];
1141+
1142+
$headers = ['foo', 'bar', 'baz'];
1143+
$rows = [['one', 'two'], ['1']];
1144+
$expected = <<<EOTXT
1145+
+-----+-----+---+
1146+
| foo | one | 1 |
1147+
| bar | two | |
1148+
| baz | | |
1149+
+-----+-----+---+
1150+
1151+
EOTXT;
1152+
yield [$headers, $rows, $expected];
1153+
1154+
$headers = ['foo', 'bar', 'baz'];
1155+
$rows = [['one', 'two', 'tree'], new TableSeparator(), ['1', '2', '3']];
1156+
$expected = <<<EOTXT
1157+
+-----+------+---+
1158+
| foo | one | 1 |
1159+
| bar | two | 2 |
1160+
| baz | tree | 3 |
1161+
+-----+------+---+
1162+
1163+
EOTXT;
1164+
yield [$headers, $rows, $expected];
1165+
}
1166+
1167+
/**
1168+
* @dataProvider provideRenderHorizontalTests
1169+
*/
1170+
public function testRenderHorizontal(array $headers, array $rows, string $expected)
1171+
{
1172+
$table = new Table($output = $this->getOutputStream());
1173+
$table
1174+
->setHeaders($headers)
1175+
->setRows($rows)
1176+
->setHorizontal()
1177+
;
1178+
$table->render();
1179+
1180+
$this->assertEquals($expected, $this->getOutputContent($output));
1181+
}
1182+
11281183
protected function getOutputStream($decorated = false)
11291184
{
11301185
return new StreamOutput($this->stream, StreamOutput::VERBOSITY_NORMAL, $decorated);

0 commit comments

Comments
 (0)