diff --git a/src/Symfony/Component/Console/CHANGELOG.md b/src/Symfony/Component/Console/CHANGELOG.md index 17c05c9e42a2..b9e837a8d10c 100644 --- a/src/Symfony/Component/Console/CHANGELOG.md +++ b/src/Symfony/Component/Console/CHANGELOG.md @@ -8,6 +8,7 @@ CHANGELOG * added method `preventRedrawFasterThan()` and `forceRedrawSlowerThan()` on `ProgressBar` * `Application` implements `ResetInterface` * marked all dispatched event classes as `@final` + * added support for displaying table horizontally 4.3.0 ----- diff --git a/src/Symfony/Component/Console/Helper/Table.php b/src/Symfony/Component/Console/Helper/Table.php index 5af631559de0..80257aa8ccd3 100644 --- a/src/Symfony/Component/Console/Helper/Table.php +++ b/src/Symfony/Component/Console/Helper/Table.php @@ -48,6 +48,7 @@ class Table * Table rows. */ private $rows = []; + private $horizontal = false; /** * Column widths cache. @@ -322,6 +323,13 @@ public function setFooterTitle(?string $title): self return $this; } + public function setHorizontal(bool $horizontal = true): self + { + $this->horizontal = $horizontal; + + return $this; + } + /** * Renders table to output. * @@ -337,14 +345,35 @@ public function setFooterTitle(?string $title): self */ public function render() { - $rows = array_merge($this->headers, [$divider = new TableSeparator()], $this->rows); + $divider = new TableSeparator(); + if ($this->horizontal) { + $rows = []; + foreach ($this->headers[0] ?? [] as $i => $header) { + $rows[$i] = [$header]; + foreach ($this->rows as $row) { + if ($row instanceof TableSeparator) { + continue; + } + if (isset($row[$i])) { + $rows[$i][] = $row[$i]; + } elseif ($rows[$i][0] instanceof TableCell && $rows[$i][0]->getColspan() >= 2) { + // Noop, there is a "title" + } else { + $rows[$i][] = null; + } + } + } + } else { + $rows = array_merge($this->headers, [$divider], $this->rows); + } + $this->calculateNumberOfColumns($rows); $rows = $this->buildTableRows($rows); $this->calculateColumnsWidth($rows); - $isHeader = true; - $isFirstRow = false; + $isHeader = !$this->horizontal; + $isFirstRow = $this->horizontal; foreach ($rows as $row) { if ($divider === $row) { $isHeader = false; @@ -369,8 +398,11 @@ public function render() $this->renderRowSeparator(self::SEPARATOR_TOP, $this->headerTitle, $this->style->getHeaderTitleFormat()); } } - - $this->renderRow($row, $isHeader ? $this->style->getCellHeaderFormat() : $this->style->getCellRowFormat()); + if ($this->horizontal) { + $this->renderRow($row, $this->style->getCellRowFormat(), $this->style->getCellHeaderFormat()); + } else { + $this->renderRow($row, $isHeader ? $this->style->getCellHeaderFormat() : $this->style->getCellRowFormat()); + } } $this->renderRowSeparator(self::SEPARATOR_BOTTOM, $this->footerTitle, $this->style->getFooterTitleFormat()); @@ -450,13 +482,17 @@ private function renderColumnSeparator(int $type = self::BORDER_OUTSIDE) * * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | */ - private function renderRow(array $row, string $cellFormat) + private function renderRow(array $row, string $cellFormat, string $firstCellFormat = null) { $rowContent = $this->renderColumnSeparator(self::BORDER_OUTSIDE); $columns = $this->getRowColumns($row); $last = \count($columns) - 1; foreach ($columns as $i => $column) { - $rowContent .= $this->renderCell($row, $column, $cellFormat); + if ($firstCellFormat && 0 === $i) { + $rowContent .= $this->renderCell($row, $column, $firstCellFormat); + } else { + $rowContent .= $this->renderCell($row, $column, $cellFormat); + } $rowContent .= $this->renderColumnSeparator($last === $i ? self::BORDER_OUTSIDE : self::BORDER_INSIDE); } $this->output->writeln($rowContent); diff --git a/src/Symfony/Component/Console/Style/SymfonyStyle.php b/src/Symfony/Component/Console/Style/SymfonyStyle.php index 962ba923f3de..4a104ca3fc07 100644 --- a/src/Symfony/Component/Console/Style/SymfonyStyle.php +++ b/src/Symfony/Component/Console/Style/SymfonyStyle.php @@ -11,12 +11,15 @@ namespace Symfony\Component\Console\Style; +use Symfony\Component\Console\Exception\InvalidArgumentException; use Symfony\Component\Console\Exception\RuntimeException; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Helper\Helper; use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Helper\SymfonyQuestionHelper; use Symfony\Component\Console\Helper\Table; +use Symfony\Component\Console\Helper\TableCell; +use Symfony\Component\Console\Helper\TableSeparator; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\BufferedOutput; use Symfony\Component\Console\Output\OutputInterface; @@ -190,6 +193,69 @@ public function table(array $headers, array $rows) $this->newLine(); } + /** + * Formats a horizontal table. + */ + public function horizontalTable(array $headers, array $rows) + { + $style = clone Table::getStyleDefinition('symfony-style-guide'); + $style->setCellHeaderFormat('%s'); + + $table = new Table($this); + $table->setHeaders($headers); + $table->setRows($rows); + $table->setStyle($style); + $table->setHorizontal(true); + + $table->render(); + $this->newLine(); + } + + /** + * Formats a list of key/value horizontally. + * + * Each row can be one of: + * * 'A title' + * * ['key' => 'value'] + * * new TableSeparator() + * + * @param string|array|TableSeparator ...$list + */ + public function definitionList(...$list) + { + $style = clone Table::getStyleDefinition('symfony-style-guide'); + $style->setCellHeaderFormat('%s'); + + $table = new Table($this); + $headers = []; + $row = []; + foreach ($list as $value) { + if ($value instanceof TableSeparator) { + $headers[] = $value; + $row[] = $value; + continue; + } + if (\is_string($value)) { + $headers[] = new TableCell($value, ['colspan' => 2]); + $row[] = null; + continue; + } + if (!\is_array($value)) { + throw new InvalidArgumentException('Value should be an array, string, or an instance of TableSeparator.'); + } + $headers[] = key($value); + $row[] = current($value); + } + + $table->setHeaders($headers); + $table->setRows([$row]); + $table->setHorizontal(); + $table->setStyle($style); + + $table->render(); + $this->newLine(); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/command/command_18.php b/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/command/command_18.php new file mode 100644 index 000000000000..d4afa45cf37c --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/command/command_18.php @@ -0,0 +1,18 @@ +definitionList( + ['foo' => 'bar'], + new TableSeparator(), + 'this is a title', + new TableSeparator(), + ['foo2' => 'bar2'] + ); +}; diff --git a/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/command/command_19.php b/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/command/command_19.php new file mode 100644 index 000000000000..e44b18b76654 --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/command/command_19.php @@ -0,0 +1,12 @@ +horizontalTable(['a', 'b', 'c', 'd'], [[1, 2, 3], [4, 5], [7, 8, 9]]); +}; diff --git a/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/output/output_18.txt b/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/output/output_18.txt new file mode 100644 index 000000000000..e836b26f38a2 --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/output/output_18.txt @@ -0,0 +1,8 @@ + ---------- --------- + foo bar + ---------- --------- + this is a title + ---------- --------- + foo2 bar2 + ---------- --------- + diff --git a/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/output/output_19.txt b/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/output/output_19.txt new file mode 100644 index 000000000000..cc7d9c7e62fd --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/output/output_19.txt @@ -0,0 +1,7 @@ + --- --- --- --- + a 1 4 7 + b 2 5 8 + c 3 9 + d + --- --- --- --- + diff --git a/src/Symfony/Component/Console/Tests/Helper/TableTest.php b/src/Symfony/Component/Console/Tests/Helper/TableTest.php index a3c2d30b7934..124309dd5b02 100644 --- a/src/Symfony/Component/Console/Tests/Helper/TableTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/TableTest.php @@ -1125,6 +1125,61 @@ public function testBoxedStyleWithColspan() $this->assertSame($expected, $this->getOutputContent($output)); } + public function provideRenderHorizontalTests() + { + $headers = ['foo', 'bar', 'baz']; + $rows = [['one', 'two', 'tree'], ['1', '2', '3']]; + $expected = <<getOutputStream()); + $table + ->setHeaders($headers) + ->setRows($rows) + ->setHorizontal() + ; + $table->render(); + + $this->assertEquals($expected, $this->getOutputContent($output)); + } + protected function getOutputStream($decorated = false) { return new StreamOutput($this->stream, StreamOutput::VERBOSITY_NORMAL, $decorated); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy