Skip to content

Commit a08090d

Browse files
Merge branch '6.4' into 7.2
* 6.4: [Console] Table counts wrong column width when using colspan and `setColumnMaxWidth()` [Console] Table counts wrong number of padding symbols in `renderCell()` method when cell contain unicode variant selector [Cache] Fix using a `ChainAdapter` as an adapter for a pool [Serializer] Fix collect_denormalization_errors flag in defaultContext [VarDumper] Avoid deprecated call in PgSqlCaster Fix command option mode (InputOption::VALUE_REQUIRED) [Uid] Improve entropy of the increment for UUIDv7
2 parents 56d7d02 + 9056771 commit a08090d

File tree

4 files changed

+89
-18
lines changed

4 files changed

+89
-18
lines changed

Application.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1277,7 +1277,7 @@ private function splitStringByWidth(string $string, int $width): array
12771277

12781278
foreach (preg_split('//u', $m[0]) as $char) {
12791279
// test if $char could be appended to current line
1280-
if (mb_strwidth($line.$char, 'utf8') <= $width) {
1280+
if (Helper::width($line.$char) <= $width) {
12811281
$line .= $char;
12821282
continue;
12831283
}

Helper/Helper.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ public static function width(?string $string): int
4242
$string ??= '';
4343

4444
if (preg_match('//u', $string)) {
45-
return (new UnicodeString($string))->width(false);
45+
$string = preg_replace('/[\p{Cc}\x7F]++/u', '', $string, -1, $count);
46+
47+
return (new UnicodeString($string))->width(false) + $count;
4648
}
4749

4850
if (false === $encoding = mb_detect_encoding($string, null, true)) {

Helper/Table.php

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -558,10 +558,7 @@ private function renderCell(array $row, int $column, string $cellFormat): string
558558
}
559559

560560
// str_pad won't work properly with multi-byte strings, we need to fix the padding
561-
if (false !== $encoding = mb_detect_encoding($cell, null, true)) {
562-
$width += \strlen($cell) - mb_strwidth($cell, $encoding);
563-
}
564-
561+
$width += \strlen($cell) - Helper::width($cell) - substr_count($cell, "\0");
565562
$style = $this->getColumnStyle($column);
566563

567564
if ($cell instanceof TableSeparator) {
@@ -626,8 +623,48 @@ private function buildTableRows(array $rows): TableRows
626623
foreach ($rows[$rowKey] as $column => $cell) {
627624
$colspan = $cell instanceof TableCell ? $cell->getColspan() : 1;
628625

629-
if (isset($this->columnMaxWidths[$column]) && Helper::width(Helper::removeDecoration($formatter, $cell)) > $this->columnMaxWidths[$column]) {
630-
$cell = $formatter->formatAndWrap($cell, $this->columnMaxWidths[$column] * $colspan);
626+
$minWrappedWidth = 0;
627+
$widthApplied = [];
628+
$lengthColumnBorder = $this->getColumnSeparatorWidth() + Helper::width($this->style->getCellRowContentFormat()) - 2;
629+
for ($i = $column; $i < ($column + $colspan); ++$i) {
630+
if (isset($this->columnMaxWidths[$i])) {
631+
$minWrappedWidth += $this->columnMaxWidths[$i];
632+
$widthApplied[] = ['type' => 'max', 'column' => $i];
633+
} elseif (($this->columnWidths[$i] ?? 0) > 0 && $colspan > 1) {
634+
$minWrappedWidth += $this->columnWidths[$i];
635+
$widthApplied[] = ['type' => 'min', 'column' => $i];
636+
}
637+
}
638+
if (1 === \count($widthApplied)) {
639+
if ($colspan > 1) {
640+
$minWrappedWidth *= $colspan; // previous logic
641+
}
642+
} elseif (\count($widthApplied) > 1) {
643+
$minWrappedWidth += (\count($widthApplied) - 1) * $lengthColumnBorder;
644+
}
645+
646+
$cellWidth = Helper::width(Helper::removeDecoration($formatter, $cell));
647+
if ($minWrappedWidth && $cellWidth > $minWrappedWidth) {
648+
$cell = $formatter->formatAndWrap($cell, $minWrappedWidth);
649+
}
650+
// update minimal columnWidths for spanned columns
651+
if ($colspan > 1 && $minWrappedWidth > 0) {
652+
$columnsMinWidthProcessed = [];
653+
$cellWidth = min($cellWidth, $minWrappedWidth);
654+
foreach ($widthApplied as $item) {
655+
if ('max' === $item['type'] && $cellWidth >= $this->columnMaxWidths[$item['column']]) {
656+
$minWidthColumn = $this->columnMaxWidths[$item['column']];
657+
$this->columnWidths[$item['column']] = $minWidthColumn;
658+
$columnsMinWidthProcessed[$item['column']] = true;
659+
$cellWidth -= $minWidthColumn + $lengthColumnBorder;
660+
}
661+
}
662+
for ($i = $column; $i < ($column + $colspan); ++$i) {
663+
if (isset($columnsMinWidthProcessed[$i])) {
664+
continue;
665+
}
666+
$this->columnWidths[$i] = $cellWidth + $lengthColumnBorder;
667+
}
631668
}
632669
if (!str_contains($cell ?? '', "\n")) {
633670
continue;

Tests/Helper/TableTest.php

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,9 +1294,9 @@ public static function renderSetTitle()
12941294
'footer',
12951295
'default',
12961296
<<<'TABLE'
1297-
+---------------+---- Multiline
1297+
+---------------+--- Multiline
12981298
header
1299-
here -+------------------+
1299+
here +------------------+
13001300
| ISBN | Title | Author |
13011301
+---------------+--------------------------+------------------+
13021302
| 99921-58-10-7 | Divine Comedy | Dante Alighieri |
@@ -1576,17 +1576,17 @@ public function testWithColspanAndMaxWith()
15761576
$expected =
15771577
<<<TABLE
15781578
+-----------------+-----------------+-----------------+
1579-
| Lorem ipsum dolor sit amet, consectetur adipi |
1580-
| scing elit, sed do eiusmod tempor |
1579+
| Lorem ipsum dolor sit amet, consectetur adipiscing |
1580+
| elit, sed do eiusmod tempor |
15811581
+-----------------+-----------------+-----------------+
1582-
| Lorem ipsum dolor sit amet, consectetur |
1583-
| adipiscing elit, sed do eiusmod tempor |
1582+
| Lorem ipsum dolor sit amet, consectetur adipiscing |
1583+
| elit, sed do eiusmod tempor |
15841584
+-----------------+-----------------+-----------------+
1585-
| Lorem ipsum dolor sit amet, co | hello world |
1586-
| nsectetur | |
1585+
| Lorem ipsum dolor sit amet, conse | hello world |
1586+
| ctetur | |
15871587
+-----------------+-----------------+-----------------+
1588-
| hello world | Lorem ipsum dolor sit amet, co |
1589-
| | nsectetur adipiscing elit |
1588+
| hello world | Lorem ipsum dolor sit amet, conse |
1589+
| | ctetur adipiscing elit |
15901590
+-----------------+-----------------+-----------------+
15911591
| hello | world | Lorem ipsum |
15921592
| | | dolor sit amet, |
@@ -2078,4 +2078,36 @@ public function testGithubIssue52101HorizontalFalse()
20782078
$this->getOutputContent($output)
20792079
);
20802080
}
2081+
2082+
public function testGithubIssue60038WidthOfCellWithEmoji()
2083+
{
2084+
$table = (new Table($output = $this->getOutputStream()))
2085+
->setHeaderTitle('Test Title')
2086+
->setHeaders(['Title', 'Author'])
2087+
->setRows([
2088+
["🎭 💫 ☯"." Divine Comedy", "Dante Alighieri"],
2089+
// the snowflake (e2 9d 84 ef b8 8f) has a variant selector
2090+
["👑 ❄️ 🗡"." Game of Thrones", "George R.R. Martin"],
2091+
// the snowflake in text style (e2 9d 84 ef b8 8e) has a variant selector
2092+
["❄︎❄︎❄︎ snowflake in text style ❄︎❄︎❄︎", ""],
2093+
["And a very long line to show difference in previous lines", ""],
2094+
])
2095+
;
2096+
$table->render();
2097+
2098+
$this->assertSame(<<<TABLE
2099+
+---------------------------------- Test Title -------------+--------------------+
2100+
| Title | Author |
2101+
+-----------------------------------------------------------+--------------------+
2102+
| 🎭 💫 ☯ Divine Comedy | Dante Alighieri |
2103+
| 👑 ❄️ 🗡 Game of Thrones | George R.R. Martin |
2104+
| ❄︎❄︎❄︎ snowflake in text style ❄︎❄︎❄︎ | |
2105+
| And a very long line to show difference in previous lines | |
2106+
+-----------------------------------------------------------+--------------------+
2107+
2108+
TABLE
2109+
,
2110+
$this->getOutputContent($output)
2111+
);
2112+
}
20812113
}

0 commit comments

Comments
 (0)
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