Skip to content

Commit 93518c2

Browse files
committed
Merge branch '6.4' into 7.2
* 6.4: [Lock] Fix using fractional TTLs on all platforms [Lock] Fixes an issue with PostgreSQL when using fractional TTLs [Console][Table] Fix unnecessary wrapping disable detecting modified indexes with DBAL 4.3 [cache] RedisTrait::doFetch should use pipeline instead of mget for Relay\Cluster relax assertions for forward compatibility with Symfony 7.4 [Console][Table] Fix invalid UTF-8 due to text wrapping
2 parents fc5fd0d + 59266a5 commit 93518c2

File tree

3 files changed

+40
-7
lines changed

3 files changed

+40
-7
lines changed

Formatter/OutputFormatter.php

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Console\Formatter;
1313

1414
use Symfony\Component\Console\Exception\InvalidArgumentException;
15+
use Symfony\Component\Console\Helper\Helper;
1516

1617
use function Symfony\Component\String\b;
1718

@@ -136,9 +137,11 @@ public function formatAndWrap(?string $message, int $width): string
136137
continue;
137138
}
138139

140+
// convert byte position to character position.
141+
$pos = Helper::length(substr($message, 0, $pos));
139142
// add the text up to the next tag
140-
$output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset), $output, $width, $currentLineLength);
141-
$offset = $pos + \strlen($text);
143+
$output .= $this->applyCurrentStyle(Helper::substr($message, $offset, $pos - $offset), $output, $width, $currentLineLength);
144+
$offset = $pos + Helper::length($text);
142145

143146
// opening tag?
144147
if ($open = '/' !== $text[1]) {
@@ -159,7 +162,7 @@ public function formatAndWrap(?string $message, int $width): string
159162
}
160163
}
161164

162-
$output .= $this->applyCurrentStyle(substr($message, $offset), $output, $width, $currentLineLength);
165+
$output .= $this->applyCurrentStyle(Helper::substr($message, $offset), $output, $width, $currentLineLength);
163166

164167
return strtr($output, ["\0" => '\\', '\\<' => '<', '\\>' => '>']);
165168
}
@@ -226,8 +229,18 @@ private function applyCurrentStyle(string $text, string $current, int $width, in
226229
}
227230

228231
if ($currentLineLength) {
229-
$prefix = substr($text, 0, $i = $width - $currentLineLength)."\n";
230-
$text = substr($text, $i);
232+
$lines = explode("\n", $text, 2);
233+
$prefix = Helper::substr($lines[0], 0, $i = $width - $currentLineLength)."\n";
234+
$text = Helper::substr($lines[0], $i);
235+
236+
if (isset($lines[1])) {
237+
// $prefix may contain the full first line in which the \n is already a part of $prefix.
238+
if ('' !== $text) {
239+
$text .= "\n";
240+
}
241+
242+
$text .= $lines[1];
243+
}
231244
} else {
232245
$prefix = '';
233246
}
@@ -242,8 +255,8 @@ private function applyCurrentStyle(string $text, string $current, int $width, in
242255

243256
$lines = explode("\n", $text);
244257

245-
foreach ($lines as $line) {
246-
$currentLineLength += \strlen($line);
258+
foreach ($lines as $i => $line) {
259+
$currentLineLength = 0 === $i ? $currentLineLength + Helper::length($line) : Helper::length($line);
247260
if ($width <= $currentLineLength) {
248261
$currentLineLength = 0;
249262
}

Helper/Helper.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ public static function substr(?string $string, int $from, ?int $length = null):
8080
{
8181
$string ??= '';
8282

83+
if (preg_match('//u', $string)) {
84+
return (new UnicodeString($string))->slice($from, $length);
85+
}
86+
8387
if (false === $encoding = mb_detect_encoding($string, null, true)) {
8488
return substr($string, $from, $length);
8589
}

Tests/Formatter/OutputFormatterTest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,14 @@ public function testFormatAndWrap()
365365
$this->assertSame("Lore\nm \e[37;41mip\e[39;49m\n\e[37;41msum\e[39;49m \ndolo\nr \e[32msi\e[39m\n\e[32mt\e[39m am\net", $formatter->formatAndWrap('Lorem <error>ipsum</error> dolor <info>sit</info> amet', 4));
366366
$this->assertSame("Lorem \e[37;41mip\e[39;49m\n\e[37;41msum\e[39;49m dolo\nr \e[32msit\e[39m am\net", $formatter->formatAndWrap('Lorem <error>ipsum</error> dolor <info>sit</info> amet', 8));
367367
$this->assertSame("Lorem \e[37;41mipsum\e[39;49m dolor \e[32m\e[39m\n\e[32msit\e[39m, \e[37;41mamet\e[39;49m et \e[32mlauda\e[39m\n\e[32mntium\e[39m architecto", $formatter->formatAndWrap('Lorem <error>ipsum</error> dolor <info>sit</info>, <error>amet</error> et <info>laudantium</info> architecto', 18));
368+
$this->assertSame("\e[37;41mnon-empty-array\e[39;49m\e[37;41m<mixed, mixed>\e[39;49m given.\n🪪 argument.type", $formatter->formatAndWrap("<error>non-empty-array<mixed, mixed></error> given.\n🪪 argument.type", 38));
369+
$this->assertSame("Usuário <strong>{{user_name}}</strong> não é válid\no.", $formatter->formatAndWrap('Usuário <strong>{{user_name}}</strong> não é válido.', 50));
370+
$this->assertSame("foo\e[37;41mb\e[39;49m\n\e[37;41mar\e[39;49mbaz", $formatter->formatAndWrap("foo<error>b\nar</error>baz", 7));
371+
$this->assertSame("foo\e[37;41mbar\e[39;49mbaz\nnewline", $formatter->formatAndWrap("foo<error>bar</error>baz\nnewline", 11));
372+
$this->assertSame("foobarbaz\n\e[37;41mnewline\e[39;49m", $formatter->formatAndWrap("foobarbaz\n<error>newline</error>", 11));
373+
$this->assertSame("foobar\e[37;41mbaz\e[39;49m\n\e[37;41mnewline\e[39;49m", $formatter->formatAndWrap("foobar<error>baz\nnewline</error>", 11));
374+
$this->assertSame("foobar\e[37;41mbazne\e[39;49m\n\e[37;41mwline\e[39;49m", $formatter->formatAndWrap("foobar<error>bazne\nwline</error>", 11));
375+
$this->assertSame("foobar\e[37;41mbazne\e[39;49m\n\e[37;41mw\e[39;49m\n\e[37;41mline\e[39;49m", $formatter->formatAndWrap("foobar<error>baznew\nline</error>", 11));
368376

369377
$formatter = new OutputFormatter();
370378

@@ -376,6 +384,14 @@ public function testFormatAndWrap()
376384
$this->assertSame("Â rèälly\nlöng tîtlè\nthät cöüld\nnèêd\nmúltîplê\nlínès", $formatter->formatAndWrap('Â rèälly löng tîtlè thät cöüld nèêd múltîplê línès', 10));
377385
$this->assertSame("Â rèälly\nlöng tîtlè\nthät cöüld\nnèêd\nmúltîplê\n línès", $formatter->formatAndWrap("Â rèälly löng tîtlè thät cöüld nèêd múltîplê\n línès", 10));
378386
$this->assertSame('', $formatter->formatAndWrap(null, 5));
387+
$this->assertSame("non-empty-array<mixed, mixed> given.\n🪪 argument.type", $formatter->formatAndWrap("<error>non-empty-array<mixed, mixed></error> given.\n🪪 argument.type", 38));
388+
$this->assertSame("Usuário <strong>{{user_name}}</strong> não é válid\no.", $formatter->formatAndWrap('Usuário <strong>{{user_name}}</strong> não é válido.', 50));
389+
$this->assertSame("foob\narbaz", $formatter->formatAndWrap("foo<error>b\nar</error>baz", 7));
390+
$this->assertSame("foobarbaz\nnewline", $formatter->formatAndWrap("foo<error>bar</error>baz\nnewline", 11));
391+
$this->assertSame("foobarbaz\nnewline", $formatter->formatAndWrap("foobarbaz\n<error>newline</error>", 11));
392+
$this->assertSame("foobarbaz\nnewline", $formatter->formatAndWrap("foobar<error>baz\nnewline</error>", 11));
393+
$this->assertSame("foobarbazne\nwline", $formatter->formatAndWrap("foobar<error>bazne\nwline</error>", 11));
394+
$this->assertSame("foobarbazne\nw\nline", $formatter->formatAndWrap("foobar<error>baznew\nline</error>", 11));
379395
}
380396
}
381397

0 commit comments

Comments
 (0)