diff --git a/src/Symfony/Component/Console/CHANGELOG.md b/src/Symfony/Component/Console/CHANGELOG.md index 5c37be6d3a21c..e797f7174518a 100644 --- a/src/Symfony/Component/Console/CHANGELOG.md +++ b/src/Symfony/Component/Console/CHANGELOG.md @@ -6,6 +6,7 @@ CHANGELOG * Improve truecolor terminal detection in some cases * Add support for 256 color terminals (conversion from Ansi24 to Ansi8 if terminal is capable of it) +* Adding optional columns to Table 6.1 --- diff --git a/src/Symfony/Component/Console/Helper/Table.php b/src/Symfony/Component/Console/Helper/Table.php index 81598dfb49929..f21b101528145 100644 --- a/src/Symfony/Component/Console/Helper/Table.php +++ b/src/Symfony/Component/Console/Helper/Table.php @@ -50,6 +50,9 @@ class Table private array $columnStyles = []; private array $columnWidths = []; private array $columnMaxWidths = []; + private array $optionalColumns = []; + private array $droppedColumns = []; + private int $maxWidth = 0; private bool $rendered = false; private string $displayOrientation = self::DISPLAY_ORIENTATION_DEFAULT; @@ -174,6 +177,20 @@ public function setColumnMaxWidth(int $columnIndex, int $width): static return $this; } + public function setOptionalColumns(array $columns): static + { + $this->optionalColumns = $columns; + + return $this; + } + + public function setMaxWidth(int $maxWidth): static + { + $this->maxWidth = $maxWidth; + + return $this; + } + /** * @return $this */ @@ -377,6 +394,11 @@ public function render() $rowGroups = $this->buildTableRows($rows); $this->calculateColumnsWidth($rowGroups); + if ($this->maxWidth && $this->optionalColumns) { + $this->dropColumn($rowGroups); + $this->calculateColumnsWidth($rowGroups); + } + $isHeader = !$horizontal; $isFirstRow = $horizontal; $hasTitle = (bool) $this->headerTitle; @@ -402,6 +424,16 @@ public function render() continue; } + if ($this->droppedColumns) { + foreach ($this->droppedColumns as $column) { + if ($this->numberOfColumns < \count($row)) { + unset($row[$column]); + } + } + + $row = array_values($row); + } + if ($isHeader && !$isHeaderSeparatorRendered) { $this->renderRowSeparator( $isHeader ? self::SEPARATOR_TOP : self::SEPARATOR_TOP_BOTTOM, @@ -788,6 +820,7 @@ private function getRowColumns(array $row): array */ private function calculateColumnsWidth(iterable $groups) { + $pass2 = \count($this->effectiveColumnWidths); for ($column = 0; $column < $this->numberOfColumns; ++$column) { $lengths = []; foreach ($groups as $group) { @@ -815,6 +848,60 @@ private function calculateColumnsWidth(iterable $groups) $this->effectiveColumnWidths[$column] = max($lengths) + Helper::width($this->style->getCellRowContentFormat()) - 2; } + + if ($pass2) { + $this->effectiveColumnWidths = array_values($this->effectiveColumnWidths); + $this->columnMaxWidths = array_values($this->columnMaxWidths); + $this->columnStyles = array_values($this->columnStyles); + $this->columnWidths = array_values($this->columnWidths); + } + } + + private function dropColumn(iterable $groups) + { + $effectiveColumnWidths = $this->effectiveColumnWidths; + $optionalColumns = []; + + foreach ($this->optionalColumns as $column) { + $optionalColumns[$column] = $effectiveColumnWidths[$column]; + } + + for ($column = $this->numberOfColumns; $this->numberOfColumns > 0; --$column) { + if ($this->maxWidth && $this->maxWidth > array_sum($effectiveColumnWidths)) { + break; + } + + $largestOptionalColumn = array_keys($optionalColumns, max($optionalColumns))[0]; + unset($effectiveColumnWidths[$largestOptionalColumn], $optionalColumns[$largestOptionalColumn]); + $this->droppedColumns[] = $largestOptionalColumn; + + if (empty($optionalColumns)) { + break; + } + } + + if ($this->droppedColumns) { + foreach ($this->droppedColumns as $column) { + foreach ($groups as $group) { + foreach ($group as $row) { + foreach ($row as $index => $cell) { + if ($cell instanceof TableCell && $index + $cell->getColspan() > $column) { + $cell->reduceColspan(); + } + } + } + } + + unset( + $this->effectiveColumnWidths[$column], + $this->columnMaxWidths[$column], + $this->columnStyles[$column], + $this->columnWidths[$column], + ); + } + + $this->numberOfColumns -= \count($this->droppedColumns); + } } private function getColumnSeparatorWidth(): int diff --git a/src/Symfony/Component/Console/Helper/TableCell.php b/src/Symfony/Component/Console/Helper/TableCell.php index 394b2bc959f5f..71ec5cf2f5dda 100644 --- a/src/Symfony/Component/Console/Helper/TableCell.php +++ b/src/Symfony/Component/Console/Helper/TableCell.php @@ -57,6 +57,17 @@ public function getColspan(): int return (int) $this->options['colspan']; } + /** + * Reduces number of colspan. + * Used by optional columns. + */ + public function reduceColspan(): void + { + if ((int) $this->options['colspan'] > 1) { + --$this->options['colspan']; + } + } + /** * Gets number of rowspan. */