Skip to content

[Console] added TableCellStyle #37338

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Symfony/Component/Console/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ CHANGELOG
* Added support for signals:
* Added `Application::getSignalRegistry()` and `Application::setSignalsToDispatchEvent()` methods
* Added `SignalableCommandInterface` interface
* Added `TableCellStyle` class to customize table cell

5.1.0
-----
Expand Down
29 changes: 26 additions & 3 deletions src/Symfony/Component/Console/Helper/Table.php
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,30 @@ private function renderCell(array $row, int $column, string $cellFormat): string
$width += Helper::strlen($cell) - Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
$content = sprintf($style->getCellRowContentFormat(), $cell);

return sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $style->getPadType()));
$padType = $style->getPadType();
if ($cell instanceof TableCell && $cell->getStyle() instanceof TableCellStyle) {
$isNotStyledByTag = !preg_match('/^<(\w+|(\w+=[\w,]+;?)*)>.+<\/(\w+|(\w+=\w+;?)*)?>$/', $cell);
if ($isNotStyledByTag) {
$cellFormat = $cell->getStyle()->getCellFormat();
if (!\is_string($cellFormat)) {
$tag = http_build_query($cell->getStyle()->getTagOptions(), null, ';');
$cellFormat = '<'.$tag.'>%s</>';
}

if (strstr($content, '</>')) {
$content = str_replace('</>', '', $content);
$width -= 3;
}
if (strstr($content, '<fg=default;bg=default>')) {
$content = str_replace('<fg=default;bg=default>', '', $content);
$width -= \strlen('<fg=default;bg=default>');
}
}

$padType = $cell->getStyle()->getPadByAlign();
}

return sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $padType));
}

/**
Expand Down Expand Up @@ -618,15 +641,15 @@ private function fillNextRows(array $rows, int $line): array
$lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $cell));
$nbLines = \count($lines) > $nbLines ? substr_count($cell, "\n") : $nbLines;

$rows[$line][$column] = new TableCell($lines[0], ['colspan' => $cell->getColspan()]);
$rows[$line][$column] = new TableCell($lines[0], ['colspan' => $cell->getColspan(), 'style' => $cell->getStyle()]);
unset($lines[0]);
}

// create a two dimensional array (rowspan x colspan)
$unmergedRows = array_replace_recursive(array_fill($line + 1, $nbLines, []), $unmergedRows);
foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
$value = isset($lines[$unmergedRowKey - $line]) ? $lines[$unmergedRowKey - $line] : '';
$unmergedRows[$unmergedRowKey][$column] = new TableCell($value, ['colspan' => $cell->getColspan()]);
$unmergedRows[$unmergedRowKey][$column] = new TableCell($value, ['colspan' => $cell->getColspan(), 'style' => $cell->getStyle()]);
if ($nbLines === $unmergedRowKey - $line) {
break;
}
Expand Down
10 changes: 10 additions & 0 deletions src/Symfony/Component/Console/Helper/TableCell.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class TableCell
private $options = [
'rowspan' => 1,
'colspan' => 1,
'style' => null,
];

public function __construct(string $value = '', array $options = [])
Expand All @@ -33,6 +34,10 @@ public function __construct(string $value = '', array $options = [])
throw new InvalidArgumentException(sprintf('The TableCell does not support the following options: \'%s\'.', implode('\', \'', $diff)));
}

if (isset($options['style']) && !$options['style'] instanceof TableCellStyle) {
throw new InvalidArgumentException('The style option must be an instance of "TableCellStyle".');
}

$this->options = array_merge($this->options, $options);
}

Expand Down Expand Up @@ -65,4 +70,9 @@ public function getRowspan()
{
return (int) $this->options['rowspan'];
}

public function getStyle(): ?TableCellStyle
{
return $this->options['style'];
}
}
89 changes: 89 additions & 0 deletions src/Symfony/Component/Console/Helper/TableCellStyle.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Console\Helper;

use Symfony\Component\Console\Exception\InvalidArgumentException;

/**
* @author Yewhen Khoptynskyi <khoptynskyi@gmail.com>
*/
class TableCellStyle
{
const DEFAULT_ALIGN = 'left';

private $options = [
'fg' => 'default',
'bg' => 'default',
'options' => null,
'align' => self::DEFAULT_ALIGN,
'cellFormat' => null,
];

private $tagOptions = [
'fg',
'bg',
'options',
];

private $alignMap = [
'left' => STR_PAD_RIGHT,
'center' => STR_PAD_BOTH,
'right' => STR_PAD_LEFT,
];

public function __construct(array $options = [])
{
if ($diff = array_diff(array_keys($options), array_keys($this->options))) {
throw new InvalidArgumentException(sprintf('The TableCellStyle does not support the following options: \'%s\'.', implode('\', \'', $diff)));
}

if (isset($options['align']) && !\array_key_exists($options['align'], $this->alignMap)) {
throw new InvalidArgumentException(sprintf('Wrong align value. Value must be following: \'%s\'.', implode('\', \'', array_keys($this->alignMap))));
}

$this->options = array_merge($this->options, $options);
}

/**
* @return array
*/
public function getOptions(): array
{
return $this->options;
}

/**
* Gets options we need for tag for example fg, bg.
*
* @return string[]
*/
public function getTagOptions()
{
return array_filter(
$this->getOptions(),
function ($key) {
return \in_array($key, $this->tagOptions) && isset($this->options[$key]);
},
ARRAY_FILTER_USE_KEY
);
}

public function getPadByAlign()
{
return $this->alignMap[$this->getOptions()['align']];
}

public function getCellFormat(): ?string
{
return $this->getOptions()['cellFormat'];
}
}
27 changes: 27 additions & 0 deletions src/Symfony/Component/Console/Tests/Helper/TableCellStyleTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Console\Tests\Helper;

use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Helper\TableCellStyle;

class TableCellStyleTest extends TestCase
{
public function testCreateTableCellStyle()
{
$tableCellStyle = new TableCellStyle(['fg' => 'red']);
$this->assertEquals('red', $tableCellStyle->getOptions()['fg']);

$this->expectException('Symfony\Component\Console\Exception\InvalidArgumentException');
new TableCellStyle(['wrong_key' => null]);
}
}
Loading