Skip to content

Commit 1bf214a

Browse files
committed
[Console] added TableCellStyle
1 parent 6a6f478 commit 1bf214a

File tree

6 files changed

+402
-3
lines changed

6 files changed

+402
-3
lines changed

src/Symfony/Component/Console/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
5.2.0
5+
-----
6+
7+
* Add `TableCellStyle` class to customize table cell
8+
49
5.1.0
510
-----
611

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

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,33 @@ private function renderCell(array $row, int $column, string $cellFormat): string
514514
$width += Helper::strlen($cell) - Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
515515
$content = sprintf($style->getCellRowContentFormat(), $cell);
516516

517-
return sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $style->getPadType()));
517+
$padType = $style->getPadType();
518+
if ($cell instanceof TableCell && $cell->getStyle() instanceof TableCellStyle) {
519+
$isNotStyledByTag = !preg_match('/^<(\w+|(\w+=[\w,]+;?)*)>.+<\/(\w+|(\w+=\w+;?)*)?>$/', $cell);
520+
if ($isNotStyledByTag) {
521+
if ($cell->hasCellFormat()) {
522+
$cellFormat = $cell->getStyle()->getCellFormat();
523+
} else {
524+
$tag = http_build_query($cell->getStyle()->getTagOptions(), null, ';');
525+
$cellFormat = '<'.$tag.'>%s</>';
526+
}
527+
528+
if (strstr($content, '</>')) {
529+
$content = str_replace('</>', '', $content);
530+
$width -= 3;
531+
}
532+
if (strstr($content, '<fg=default;bg=default>')) {
533+
$content = str_replace('<fg=default;bg=default>', '', $content);
534+
$width -= \strlen('<fg=default;bg=default>');
535+
}
536+
}
537+
538+
if ($cell->hasAlign()) {
539+
$padType = $cell->getStyle()->getPadByAlign();
540+
}
541+
}
542+
543+
return sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $padType));
518544
}
519545

520546
/**
@@ -615,15 +641,19 @@ private function fillNextRows(array $rows, int $line): array
615641
$lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $cell));
616642
$nbLines = \count($lines) > $nbLines ? substr_count($cell, "\n") : $nbLines;
617643

618-
$rows[$line][$column] = new TableCell($lines[0], ['colspan' => $cell->getColspan()]);
644+
$rows[$line][$column] = new TableCell(
645+
$lines[0], ['colspan' => $cell->getColspan(), 'style' => $cell->getStyle()]
646+
);
619647
unset($lines[0]);
620648
}
621649

622650
// create a two dimensional array (rowspan x colspan)
623651
$unmergedRows = array_replace_recursive(array_fill($line + 1, $nbLines, []), $unmergedRows);
624652
foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
625653
$value = isset($lines[$unmergedRowKey - $line]) ? $lines[$unmergedRowKey - $line] : '';
626-
$unmergedRows[$unmergedRowKey][$column] = new TableCell($value, ['colspan' => $cell->getColspan()]);
654+
$unmergedRows[$unmergedRowKey][$column] = new TableCell(
655+
$value, ['colspan' => $cell->getColspan(), 'style' => $cell->getStyle()]
656+
);
627657
if ($nbLines === $unmergedRowKey - $line) {
628658
break;
629659
}

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class TableCell
2222
private $options = [
2323
'rowspan' => 1,
2424
'colspan' => 1,
25+
'style' => null,
2526
];
2627

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

37+
if (isset($options['style']) && !$options['style'] instanceof TableCellStyle) {
38+
throw new InvalidArgumentException('The style option must be instance of TableCellStyle.');
39+
}
40+
3641
$this->options = array_merge($this->options, $options);
3742
}
3843

@@ -65,4 +70,25 @@ public function getRowspan()
6570
{
6671
return (int) $this->options['rowspan'];
6772
}
73+
74+
public function getStyle(): ?TableCellStyle
75+
{
76+
return $this->options['style'];
77+
}
78+
79+
public function hasAlign(): bool
80+
{
81+
$style = $this->getStyle();
82+
83+
return $style instanceof TableCellStyle
84+
&& $style->hasAlign();
85+
}
86+
87+
public function hasCellFormat(): bool
88+
{
89+
$style = $this->getStyle();
90+
91+
return $style instanceof TableCellStyle
92+
&& $style->getCellFormat();
93+
}
6894
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Console\Helper;
13+
14+
use Symfony\Component\Console\Exception\InvalidArgumentException;
15+
16+
/**
17+
* @author Yewhen Khoptynskyi <khoptynskyi@gmail.com>
18+
*/
19+
class TableCellStyle
20+
{
21+
const DEFAULT_ALIGN = 'left';
22+
23+
private $options = [
24+
'fg' => 'default',
25+
'bg' => 'default',
26+
'options' => null,
27+
'align' => self::DEFAULT_ALIGN,
28+
'cellFormat' => null,
29+
];
30+
31+
private $tagOptions = [
32+
'fg',
33+
'bg',
34+
'options',
35+
];
36+
37+
private $alignMap = [
38+
'left' => STR_PAD_RIGHT,
39+
'center' => STR_PAD_BOTH,
40+
'right' => STR_PAD_LEFT,
41+
];
42+
43+
public function __construct(array $options = [])
44+
{
45+
if ($diff = array_diff(array_keys($options), array_keys($this->options))) {
46+
throw new InvalidArgumentException(sprintf('The TableCellStyle does not support the following options: \'%s\'.', implode('\', \'', $diff)));
47+
}
48+
49+
if (isset($options['align']) && !\array_key_exists($options['align'], $this->alignMap)) {
50+
throw new InvalidArgumentException(sprintf('Wrong align value. Value must be following: \'%s\'.', implode('\', \'', array_keys($this->alignMap))));
51+
}
52+
53+
$this->options = array_merge($this->options, $options);
54+
}
55+
56+
/**
57+
* @return array|string[]
58+
*/
59+
public function getOptions(): array
60+
{
61+
return $this->options;
62+
}
63+
64+
/**
65+
* Gets options we need for tag for example fg, bg.
66+
*
67+
* @return array|string[]
68+
*/
69+
public function getTagOptions()
70+
{
71+
return array_filter(
72+
$this->getOptions(),
73+
function ($key) {
74+
return \in_array($key, $this->tagOptions) && isset($this->options[$key]);
75+
},
76+
ARRAY_FILTER_USE_KEY
77+
);
78+
}
79+
80+
public function getPadByAlign()
81+
{
82+
return $this->alignMap[$this->getOptions()['align']];
83+
}
84+
85+
public function getCellFormat(): ?string
86+
{
87+
return $this->getOptions()['cellFormat'];
88+
}
89+
90+
public function hasAlign(): bool
91+
{
92+
$options = $this->getOptions();
93+
94+
return isset($options['align'])
95+
&& self::DEFAULT_ALIGN !== $options['align'];
96+
}
97+
98+
public function hasCellFormat(): bool
99+
{
100+
$options = $this->getOptions();
101+
102+
return isset($options['cellFormat']) && \is_string($options['cellFormat']);
103+
}
104+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Console\Tests\Helper;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\Console\Helper\TableCellStyle;
16+
17+
class TableCellStyleTest extends TestCase
18+
{
19+
public function testCreateTableCellStyle()
20+
{
21+
$tableCellStyle = new TableCellStyle(['fg' => 'red']);
22+
$this->assertEquals('red', $tableCellStyle->getOptions()['fg']);
23+
24+
$this->expectException('Symfony\Component\Console\Exception\InvalidArgumentException');
25+
new TableCellStyle(['wrong_key' => null]);
26+
}
27+
}

0 commit comments

Comments
 (0)