Skip to content

Commit

Permalink
[Console] Add non-auto column width functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
Arjan Keeman authored and fabpot committed Mar 1, 2016
1 parent a76821c commit 2d1e5ce
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 9 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ CHANGELOG
-----

* added truncate method to FormatterHelper
* added setColumnWidth(s) method to Table

2.8.3
-----
Expand Down
59 changes: 50 additions & 9 deletions Helper/Table.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class Table
*
* @var array
*/
private $columnWidths = array();
private $effectiveColumnWidths = array();

/**
* Number of columns cache.
Expand All @@ -67,6 +67,13 @@ class Table
*/
private $columnStyles = array();

/**
* User set column widths.
*
* @var array
*/
private $columnWidths = array();

private static $styles;

public function __construct(OutputInterface $output)
Expand Down Expand Up @@ -186,6 +193,38 @@ public function getColumnStyle($columnIndex)
return $this->getStyle();
}

/**
* Sets the minimum width of a column.
*
* @param int $columnIndex Column index
* @param int $width Minimum column width in characters
*
* @return Table
*/
public function setColumnWidth($columnIndex, $width)
{
$this->columnWidths[intval($columnIndex)] = intval($width);

return $this;
}

/**
* Sets the minimum width of all columns.
*
* @param array $widths
*
* @return Table
*/
public function setColumnWidths(array $widths)
{
$this->columnWidths = array();
foreach ($widths as $index => $width) {
$this->setColumnWidth($index, $width);
}

return $this;
}

public function setHeaders(array $headers)
{
$headers = array_values($headers);
Expand Down Expand Up @@ -296,7 +335,7 @@ private function renderRowSeparator()

$markup = $this->style->getCrossingChar();
for ($column = 0; $column < $count; ++$column) {
$markup .= str_repeat($this->style->getHorizontalBorderChar(), $this->columnWidths[$column]).$this->style->getCrossingChar();
$markup .= str_repeat($this->style->getHorizontalBorderChar(), $this->effectiveColumnWidths[$column]).$this->style->getCrossingChar();
}

$this->output->writeln(sprintf($this->style->getBorderFormat(), $markup));
Expand Down Expand Up @@ -342,11 +381,11 @@ private function renderRow(array $row, $cellFormat)
private function renderCell(array $row, $column, $cellFormat)
{
$cell = isset($row[$column]) ? $row[$column] : '';
$width = $this->columnWidths[$column];
$width = $this->effectiveColumnWidths[$column];
if ($cell instanceof TableCell && $cell->getColspan() > 1) {
// add the width of the following columns(numbers of colspan).
foreach (range($column + 1, $column + $cell->getColspan() - 1) as $nextColumn) {
$width += $this->getColumnSeparatorWidth() + $this->columnWidths[$nextColumn];
$width += $this->getColumnSeparatorWidth() + $this->effectiveColumnWidths[$nextColumn];
}
}

Expand Down Expand Up @@ -572,7 +611,7 @@ private function calculateColumnsWidth($rows)
$lengths[] = $this->getCellWidth($row, $column);
}

$this->columnWidths[$column] = max($lengths) + strlen($this->style->getCellRowContentFormat()) - 2;
$this->effectiveColumnWidths[$column] = max($lengths) + strlen($this->style->getCellRowContentFormat()) - 2;
}
}

Expand All @@ -596,26 +635,28 @@ private function getColumnSeparatorWidth()
*/
private function getCellWidth(array $row, $column)
{
$cellWidth = 0;

if (isset($row[$column])) {
$cell = $row[$column];
$cellWidth = Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
if ($cell instanceof TableCell && $cell->getColspan() > 1) {
// we assume that cell value will be across more than one column.
$cellWidth = $cellWidth / $cell->getColspan();
}

return $cellWidth;
}

return 0;
$columnWidth = isset($this->columnWidths[$column]) ? $this->columnWidths[$column] : 0;

return max($cellWidth, $columnWidth);
}

/**
* Called after rendering to cleanup cache data.
*/
private function cleanup()
{
$this->columnWidths = array();
$this->effectiveColumnWidths = array();
$this->numberOfColumns = null;
}

Expand Down
63 changes: 63 additions & 0 deletions Tests/Helper/TableTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,69 @@ public function testColumnStyle()
| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | 139.25 |
+---------------+----------------------+-----------------+--------+
TABLE;

$this->assertEquals($expected, $this->getOutputContent($output));
}

public function testColumnWith()
{
$table = new Table($output = $this->getOutputStream());
$table
->setHeaders(array('ISBN', 'Title', 'Author', 'Price'))
->setRows(array(
array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri', '9.95'),
array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens', '139.25'),
))
->setColumnWidth(0, 15)
->setColumnWidth(3, 10);

$style = new TableStyle();
$style->setPadType(STR_PAD_LEFT);
$table->setColumnStyle(3, $style);

$table->render();

$expected =
<<<TABLE
+-----------------+----------------------+-----------------+------------+
| ISBN | Title | Author | Price |
+-----------------+----------------------+-----------------+------------+
| 99921-58-10-7 | Divine Comedy | Dante Alighieri | 9.95 |
| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | 139.25 |
+-----------------+----------------------+-----------------+------------+
TABLE;

$this->assertEquals($expected, $this->getOutputContent($output));
}

public function testColumnWiths()
{
$table = new Table($output = $this->getOutputStream());
$table
->setHeaders(array('ISBN', 'Title', 'Author', 'Price'))
->setRows(array(
array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri', '9.95'),
array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens', '139.25'),
))
->setColumnWidths(array(15, 0, -1, 10));

$style = new TableStyle();
$style->setPadType(STR_PAD_LEFT);
$table->setColumnStyle(3, $style);

$table->render();

$expected =
<<<TABLE
+-----------------+----------------------+-----------------+------------+
| ISBN | Title | Author | Price |
+-----------------+----------------------+-----------------+------------+
| 99921-58-10-7 | Divine Comedy | Dante Alighieri | 9.95 |
| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | 139.25 |
+-----------------+----------------------+-----------------+------------+
TABLE;

$this->assertEquals($expected, $this->getOutputContent($output));
Expand Down

0 comments on commit 2d1e5ce

Please sign in to comment.