8000 Merge branch '6.4' into 7.0 · symfony/symfony@d95ed09 · GitHub
[go: up one dir, main page]

Skip to content

Commit d95ed09

Browse files
Merge branch '6.4' into 7.0
* 6.4: [DependencyInjection] Fix computing error messages involving service locators [Serializer] Fix unknown types normalization type when know type [ErrorHandler] Fix parsing messages that contain anonymous classes on PHP >= 8.3.3 [AssetMapper] Fix enquoted string pattern [Validator] Review Romanian (ro) translations [Console] Fix display of Table on Windows OS [FrameworkBundle] Fix config builder with extensions extended in `build()` [Translation] Fix extracting qualified t() function calls Fix vertical table on windows Fix the `command -v` exception when the command option with a dash prefix [WebProfilerBundle] disable turbo in web profiler toolbar to avoid link prefetching explicitly cast boolean SSL stream options return the unchanged text if preg_replace_callback() fails the 'use_notify' option is on the factory, not on the postgres connection class review translations
2 parents 635a9f1 + 9caa541 commit d95ed09

File tree

23 files changed

+222
-51
lines changed

23 files changed

+222
-51
lines changed

src/Symfony/Bundle/FrameworkBundle/CacheWarmer/ConfigBuilderCacheWarmer.php

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use Symfony\Component\DependencyInjection\ParameterBag\ContainerBag;
2323
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
2424
use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface;
25+
use Symfony\Component\HttpKernel\Kernel;
2526
use Symfony\Component\HttpKernel\KernelInterface;
2627

2728
/**
@@ -48,12 +49,27 @@ public function warmUp(string $cacheDir, ?string $buildDir = null): array
4849

4950
$generator = new ConfigBuilderGenerator($buildDir);
5051

51-
foreach ($this->kernel->getBundles() as $bundle) {
52-
$extension = $bundle->getContainerExtension();
53-
if (null === $extension) {
54-
continue;
52+
if ($this->kernel instanceof Kernel) {
53+
/** @var ContainerBuilder $container */
54+
$container = \Closure::bind(function (Kernel $kernel) {
55+
$containerBuilder = $kernel->getContainerBuilder();
56+
$kernel->prepareContainer($containerBuilder);
57+
58+
return $containerBuilder;
59+
}, null, $this->kernel)($this->kernel);
60+
61+
$extensions = $container->getExtensions();
62+
} else {
63+
$extensions = [];
64+
foreach ($this->kernel->getBundles() as $bundle) {
65+
$extension = $bundle->getContainerExtension();
66+
if (null !== $extension) {
67+
$extensions[] = $extension;
68+
}
5569
}
70+
}
5671

72+
foreach ($extensions as $extension) {
5773
try {
5874
$this->dumpExtension($extension, $generator);
5975
} catch (\Exception $e) {

src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.html.twig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
</div>
77
<div id="sfToolbarClearer-{{ token }}" class="sf-toolbar-clearer"></div>
88

9-
<div id="sfToolbarMainContent-{{ token }}" class="sf-toolbarreset notranslate clear-fix" data-no-turbolink>
9+
<div id="sfToolbarMainContent-{{ token }}" class="sf-toolbarreset notranslate clear-fix" data-no-turbolink data-turbo="false">
1010
{% for name, template in templates %}
1111
{% if block('toolbar', template) is defined %}
1212
{% with {

src/Symfony/Component/AssetMapper/Compiler/JavaScriptImportPathCompiler.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ final class JavaScriptImportPathCompiler implements AssetCompilerInterface
3535
(?:\/\/.*) # Lines that start with comments
3636
|
3737
(?:
38-
\'(?:[^\'\\\\]|\\\\.)*\' # Strings enclosed in single quotes
38+
\'(?:[^\'\\\\\n]|\\\\.)*\' # Strings enclosed in single quotes
3939
|
40-
"(?:[^"\\\\]|\\\\.)*" # Strings enclosed in double quotes
40+
"(?:[^"\\\\\n]|\\\\.)*" # Strings enclosed in double quotes
4141
)
4242
|
4343
(?: # Import statements (script captured)
@@ -49,7 +49,7 @@ final class JavaScriptImportPathCompiler implements AssetCompilerInterface
4949
|
5050
\bimport\(
5151
)
52-
\s*[\'"`](\.\/[^\'"`]+|(\.\.\/)*[^\'"`]+)[\'"`]\s*[;\)]
52+
\s*[\'"`](\.\/[^\'"`\n]+|(\.\.\/)*[^\'"`\n]+)[\'"`]\s*[;\)]
5353
?
5454
/mx';
5555

src/Symfony/Component/AssetMapper/Tests/Compiler/JavaScriptImportPathCompilerTest.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,11 @@ public function testCompileFindsCorrectImports(string $input, array $expectedJav
6868
->willReturnCallback(function ($path) {
6969
return match ($path) {
7070
'/project/assets/foo.js' => new MappedAsset('foo.js', '/can/be/anything.js', publicPathWithoutDigest: '/assets/foo.js'),
71+
'/project/assets/bootstrap.js' => new MappedAsset('bootstrap.js', '/can/be/anything.js', publicPathWithoutDigest: '/assets/bootstrap.js'),
7172
'/project/assets/other.js' => new MappedAsset('other.js', '/can/be/anything.js', publicPathWithoutDigest: '/assets/other.js'),
7273
'/project/assets/subdir/foo.js' => new MappedAsset('subdir/foo.js', '/can/be/anything.js', publicPathWithoutDigest: '/assets/subdir/foo.js'),
74+
'/project/assets/styles/app.css' => new MappedAsset('styles/app.css', '/can/be/anything.js', publicPathWithoutDigest: '/assets/styles/app.css'),
75+
'/project/assets/styles/app.scss' => new MappedAsset('styles/app.scss', '/can/be/anything.js', publicPathWithoutDigest: '/assets/styles/app.scss'),
7376
'/project/assets/styles.css' => new MappedAsset('styles.css', '/can/be/anything.js', publicPathWithoutDigest: '/assets/styles.css'),
7477
'/project/assets/vendor/module_in_importmap_remote.js' => new MappedAsset('module_in_importmap_remote.js', '/can/be/anything.js', publicPathWithoutDigest: '/assets/module_in_importmap_remote.js'),
7578
'/project/assets/vendor/@popperjs/core.js' => new MappedAsset('assets/vendor/@popperjs/core.js', '/can/be/anything.js', publicPathWithoutDigest: '/assets/@popperjs/core.js'),
@@ -90,6 +93,26 @@ public function testCompileFindsCorrectImports(string $input, array $expectedJav
9093

9194
public static function provideCompileTests(): iterable
9295
{
96+
yield 'standard_symfony_app_js' => [
97+
'input' => <<<EOF
98+
import './bootstrap.js';
99+
100+
/*
101+
* Welcome to your app's main JavaScript file!
102+
*
103+
* This file will be included onto the page via the importmap() Twig function,
104+
* which should already be in your base.html.twig.
105+
*/
106+
import './styles/app.css';
107+
108+
console.log('This log comes from assets/app.js - welcome to AssetMapper! 🎉');
109+
EOF,
110+
'expectedJavaScriptImports' => [
111+
'/assets/bootstrap.js' => ['lazy' => false, 'asset' => 'bootstrap.js', 'add' => true],
112+
'/assets/styles/app.css' => ['lazy' => false, 'asset' => 'styles/app.css', 'add' => true],
113+
],
114+
];
115+
93116
yield 'dynamic_simple_double_quotes' => [
94117
'input' => 'import("./other.js");',
95118
'expectedJavaScriptImports' => ['/assets/other.js' => ['lazy' => true, 'asset' => 'other.js', 'add' => true]],

src/Symfony/Component/Cache/Traits/RedisTrait.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,22 @@ public static function createConnection(#[\SensitiveParameter] string $dsn, arra
260260
$extra = [
261261
'stream' => $params['ssl'] ?? null,
262262
];
263+
$booleanStreamOptions = [
264+
'allow_self_signed',
265+
'capture_peer_cert',
266+
'capture_peer_cert_chain',
267+
'disable_compression',
268+
'SNI_enabled',
269+
'verify_peer',
270+
'verify_peer_name',
271+
];
272+
273+
foreach ($extra['stream'] ?? [] as $streamOption => $value) {
274+
if (\in_array($streamOption, $booleanStreamOptions, true) && \is_string($value)) {
275+
$extra['stream'][$streamOption] = filter_var($value, \FILTER_VALIDATE_BOOL);
276+
}
277+
}
278+
263279
if (isset($params['auth'])) {
264280
$extra['auth'] = $params['auth'];
265281
}

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

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,8 @@ public function render(): void
361361
for ($i = 0; $i < $maxRows; ++$i) {
362362
$cell = (string) ($row[$i] ?? '');
363363

364-
$parts = explode("\n", $cell);
364+
$eol = str_contains($cell, "\r\n") ? "\r\n" : "\n";
365+
$parts = explode($eol, $cell);
365366
foreach ($parts as $idx => $part) {
366367
if ($headers && !$containsColspan) {
367368
if (0 === $idx) {
@@ -632,9 +633,10 @@ private function buildTableRows(array $rows): TableRows
632633
if (!str_contains($cell ?? '', "\n")) {
633634
continue;
634635
}
635-
$escaped = implode("\n", array_map(OutputFormatter::escapeTrailingBackslash(...), explode("\n", $cell)));
636+
$eol = str_contains($cell ?? '', "\r\n") ? "\r\n" : "\n";
637+
$escaped = implode($eol, array_map(OutputFormatter::escapeTrailingBackslash(...), explode($eol, $cell)));
636638
$cell = $cell instanceof TableCell ? new TableCell($escaped, ['colspan' => $cell->getColspan()]) : $escaped;
637-
$lines = explode("\n", str_replace("\n", "<fg=default;bg=default></>\n", $cell));
639+
$lines = explode($eol, str_replace($eol, '<fg=default;bg=default></>'.$eol, $cell));
638640
foreach ($lines as $lineKey => $line) {
639641
if ($colspan > 1) {
640642
$line = new TableCell($line, ['colspan' => $colspan]);
@@ -696,8 +698,9 @@ private function fillNextRows(array $rows, int $line): array
696698
$nbLines = $cell->getRowspan() - 1;
697699
$lines = [$cell];
698700
if (str_contains($cell, "\n")) {
699-
$lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $cell));
700-
$nbLines = \count($lines) > $nbLines ? substr_count($cell, "\n") : $nbLines;
701+
$eol = str_contains($cell, "\r\n") ? "\r\n" : "\n";
702+
$lines = explode($eol, str_replace($eol, '<fg=default;bg=default>'.$eol.'</>', $cell));
703+
$nbLines = \count($lines) > $nbLines ? substr_count($cell, $eol) : $nbLines;
701704

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

src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ protected function processValue(mixed $value, bool $isRoot = false)
7676
continue;
7777
}
7878
if ($isRoot) {
79-
if ($v->hasTag('container.excluded')) {
79+
if ($v instanceof Definition && $v->hasTag('container.excluded')) {
8080
continue;
8181
}
8282
$this->currentId = $k;

src/Symfony/Component/DependencyInjection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,7 @@ protected function processValue(mixed $value, bool $isRoot = false): mixed
5757
if (isset($this->serviceLocatorContextIds[$currentId])) {
5858
$currentId = $this->serviceLocatorContextIds[$currentId];
5959
$locator = $this->container->getDefinition($this->currentId)->getFactory()[0];
60-
61-
foreach ($locator->getArgument(0) as $k => $v) {
62-
if ($v->getValues()[0] === $value) {
63-
if ($k !== $id) {
64-
$currentId = $k.'" in the container provided to "'.$currentId;
65-
}
66-
throw new ServiceNotFoundException($id, $currentId, null, $this->getAlternatives($id));
67-
}
68-
}
60+
$this->throwServiceNotFoundException($value, $currentId, $locator->getArgument(0));
6961
}
7062

7163
if ('.' === $currentId[0] && $graph->hasNode($currentId)) {
@@ -79,14 +71,21 @@ protected function processValue(mixed $value, bool $isRoot = false): mixed
7971
$currentId = $sourceId;
8072
break;
8173
}
74+
75+
if (isset($this->serviceLocatorContextIds[$sourceId])) {
76+
$currentId = $this->serviceLocatorContextIds[$sourceId];
77+
$locator = $this->container->getDefinition($this->currentId);
78+
$this->throwServiceNotFoundException($value, $currentId, $locator->getArgument(0));
79+
}
8280
}
8381
}
8482

85-
throw new ServiceNotFoundException($id, $currentId, null, $this->getAlternatives($id));
83+
$this->throwServiceNotFoundException($value, $currentId, $value);
8684
}
8785

88-
private function getAlternatives(string $id): array
86+
private function throwServiceNotFoundException(Reference $ref, string $sourceId, $value): void
8987
{
88+
$id = (string) $ref;
9089
$alternatives = [];
9190
foreach ($this->container->getServiceIds() as $knownId) {
9291
if ('' === $knownId || '.' === $knownId[0] || $knownId === $this->currentId) {
@@ -99,6 +98,28 @@ private function getAlternatives(string $id): array
9998
}
10099
}
101100

102-
return $alternatives;
101+
$pass = new class() extends AbstractRecursivePass {
102+
public Reference $ref;
103+
public string $sourceId;
104+
public array $alternatives;
105+
106+
public function processValue(mixed $value, bool $isRoot = false): mixed
107+
{
108+
if ($this->ref !== $value) {
109+
return parent::processValue($value, $isRoot);
110+
}
111+
$sourceId = $this->sourceId;
112+
if (null !== $this->currentId && $this->currentId !== (string) $value) {
113+
$sourceId = $this->currentId.'" in the container provided to "'.$sourceId;
114+
}
115+
116+
throw new ServiceNotFoundException((string) $value, $sourceId, null, $this->alternatives);
117+
}
118+
};
119+
$pass->ref = $ref;
120+
$pass->sourceId = $sourceId;
121+
$pass->alternatives = $alternatives;
122+
123+
$pass->processValue($value, true);
103124
}
104125
}

src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckExceptionOnInvalidReferenceBehaviorPassTest.php

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,29 +84,41 @@ public function testProcessDefinitionWithBindings()
8484
$this->addToAssertionCount(1);
8585
}
8686

87-
public function testWithErroredServiceLocator()
87+
/**
88+
* @testWith [true]
89+
* [false]
90+
*/
91+
public function testWithErroredServiceLocator(bool $inline)
8892
{
8993
$container = new ContainerBuilder();
9094

9195
ServiceLocatorTagPass::register($container, ['foo' => new Reference('baz')], 'bar');
9296

9397
(new AnalyzeServiceReferencesPass())->process($container);
94-
(new InlineServiceDefinitionsPass())->process($container);
98+
if ($inline) {
99+
(new InlineServiceDefinitionsPass())->process($container);
100+
}
95101

96102
$this->expectException(ServiceNotFoundException::class);
97103
$this->expectExceptionMessage('The service "foo" in the container provided to "bar" has a dependency on a non-existent service "baz".');
98104

99105
$this->process($container);
100106
}
101107

102-
public function testWithErroredHiddenService()
108+
/**
109+
* @testWith [true]
110+
* [false]
111+
*/
112+
public function testWithErroredHiddenService(bool $inline)
103113
{
104114
$container = new ContainerBuilder();
105115

106116
ServiceLocatorTagPass::register($container, ['foo' => new Reference('foo')], 'bar');
107117

108118
(new AnalyzeServiceReferencesPass())->process($container);
109-
(new InlineServiceDefinitionsPass())->process($container);
119+
if ($inline) {
120+
(new InlineServiceDefinitionsPass())->process($container);
121+
}
110122

111123
$this->expectException(ServiceNotFoundException::class);
112124
$this->expectExceptionMessage('The service "bar" has a dependency on a non-existent service "foo".');

src/Symfony/Component/ErrorHandler/DebugClassLoader.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1135,7 +1135,7 @@ private function fixReturnStatements(\ReflectionMethod $method, string $returnTy
11351135
$braces = 0;
11361136
for (; $i < $end; ++$i) {
11371137
if (!$inClosure) {
1138-
$inClosure = str_contains($code[$i], 'function (');
1138+
$inClosure = false !== strpos($code[$i], 'function (');
11391139
}
11401140

11411141
if ($inClosure) {

src/Symfony/Component/ErrorHandler/ErrorHandler.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -432,23 +432,27 @@ public function handleError(int $type, string $message, string $file, int $line)
432432
return true;
433433
}
434434
} else {
435-
if (str_contains($message, '@anonymous')) {
435+
if (PHP_VERSION_ID < 80303 && str_contains($message, '@anonymous')) {
436436
$backtrace = debug_backtrace(false, 5);
437437

438438
for ($i = 1; isset($backtrace[$i]); ++$i) {
439439
if (isset($backtrace[$i]['function'], $backtrace[$i]['args'][0])
440440
&& ('trigger_error' === $backtrace[$i]['function'] || 'user_error' === $backtrace[$i]['function'])
441441
) {
442442
if ($backtrace[$i]['args'][0] !== $message) {
443-
$message = $this->parseAnonymousClass($backtrace[$i]['args'][0]);
444-
$logMessage = $this->levels[$type].': '.$message;
443+
$message = $backtrace[$i]['args'][0];
445444
}
446445

447446
break;
448447
}
449448
}
450449
}
451450

451+
if (false !== strpos($message, "@anonymous\0")) {
452+
$message = $this->parseAnonymousClass($message);
453+
$logMessage = $this->levels[$type].': '.$message;
454+
}
455+
452456
$errorAsException = new \ErrorException($logMessage, 0, $type, $file, $line);
453457

454458
if ($throw || $this->tracedErrors & $type) {

src/Symfony/Component/ErrorHandler/ErrorRenderer/HtmlErrorRenderer.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ private function fixCodeMarkup(string $line): string
301301

302302
private function formatFileFromText(string $text): string
303303
{
304< F438 code>-
return preg_replace_callback('/in ("|&quot;)?(.+?)\1(?: +(?:on|at))? +line (\d+)/s', fn ($match) => 'in '.$this->formatFile($match[2], $match[3]), $text);
304+
return preg_replace_callback('/in ("|&quot;)?(.+?)\1(?: +(?:on|at))? +line (\d+)/s', fn ($match) => 'in '.$this->formatFile($match[2], $match[3]), $text) ?? $text;
305305
}
306306

307307
private function formatLogMessage(string $message, array $context): string

src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/RequestPayloadValueResolverTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ public function testValidationNotPerformedWhenPartialDenormalizationReturnsViola
284284
} catch (HttpException $e) {
285285
$validationFailedException = $e->getPrevious();
286286
$this->assertInstanceOf(ValidationFailedException::class, $validationFailedException);
287-
$this->assertSame('This value should be of type unknown.', $validationFailedException->getViolations()[0]->getMessage());
287+
$this->assertSame('This value should be of type string.', $validationFailedException->getViolations()[0]->getMessage());
288288
}
289289
}
290290

src/Symfony/Component/Messenger/Bridge/Doctrine/Transport/DoctrineTransportFactory.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ public function __construct(ConnectionRegistry $registry)
3232
$this->registry = $registry;
3333
}
3434

35+
/**
36+
* @param array $options You can set 'use_notify' to false to not use LISTEN/NOTIFY with postgresql
37+
*/
3538
public function createTransport(#[\SensitiveParameter] string $dsn, array $options, SerializerInterface $serializer): TransportInterface
3639
{
3740
$useNotify = ($options['use_notify'] ?? true);

src/Symfony/Component/Messenger/Bridge/Doctrine/Transport/PostgreSqlConnection.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,19 @@
1616
/**
1717
* Uses PostgreSQL LISTEN/NOTIFY to push messages to workers.
1818
*
19+
* If you do not want to use the LISTEN mechanism, set the `use_notify` option to `false` when calling DoctrineTransportFactory::createTransport.
20+
*
1921
* @internal
2022
*
2123
* @author Kévin Dunglas <dunglas@gmail.com>
2224
*/
2325
final class PostgreSqlConnection extends Connection
2426
{
2527
/**
26-
* * use_notify: Set to false to disable the use of LISTEN/NOTIFY. Default: true
2728
* * check_delayed_interval: The interval to check for delayed messages, in milliseconds. Set to 0 to disable checks. Default: 60000 (1 minute)
2829
* * get_notify_timeout: The length of time to wait for a response when calling PDO::pgsqlGetNotify, in milliseconds. Default: 0.
2930
*/
3031
protected const DEFAULT_OPTIONS = parent::DEFAULT_OPTIONS + [
31-
'use_notify' => true,
3232
'check_delayed_interval' => 60000,
3333
'get_notify_timeout' => 0,
3434
];

src/Symfony/Component/Process/ExecutableFinder.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public function find(string $name, ?string $default = null, array $extraDirs = [
6868
}
6969
}
7070

71-
$command = '\\' === \DIRECTORY_SEPARATOR ? 'where' : 'command -v';
71+
$command = '\\' === \DIRECTORY_SEPARATOR ? 'where' : 'command -v --';
7272
if (\function_exists('exec') && ($executablePath = strtok(@exec($command.' '.escapeshellarg($name)), \PHP_EOL)) && @is_executable($executablePath)) {
7373
return $executablePath;
7474
}

0 commit comments

Comments
 (0)
0