8000 Merge branch '6.3' into 6.4 · WoutervanderLoopNL/symfony@072db6b · GitHub
[go: up one dir, main page]

Skip to content

Commit 072db6b

Browse files
committed
Merge branch '6.3' into 6.4
* 6.3: fix merge [VarDumper] Test intl formatter broken since dumper does not replace the nnbsp character by standard space [WebProfilerBundle] Fix intercept external redirects [Webhook] Added missing XML attribute in config XSD [String] Skip a test when an issue is detected in PCRE2 [ExpressionLanguage] Fix null coalescing propagation [Mailer] Stop using the (local) AWS shared configuration in the PHPUnit tests. detect colors on not windows fix xterm detection refactor: hyper check Missing translations for Slovak (sk) symfony#51954 Remove redundant PHPdoc line properly handle SYMFONY_DOTENV_VARS being the empty string Avoid incompatibility with symfony/console 7 bug symfony#45057 [Messenger] Avoid reconnecting active Redis connections. [HttpKernel] Catch `TypeError` if the wrong type is used in `BackedEnumValueResolver` [Serializer] fix regression where nullable int cannot be serialized do not overwrite an application's default serialization context
2 parents b926004 + 1c4feac commit 072db6b

File tree

25 files changed

+246
-47
lines changed

25 files changed

+246
-47
lines changed

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1990,21 +1990,23 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder
19901990
$container->getDefinition('serializer.name_converter.metadata_aware')->setArgument(1, new Reference($config['name_converter']));
19911991
}
19921992

1993+
$defaultContext = $config['default_context'] ?? [];
1994+
1995+
if ($defaultContext) {
1996+
$container->setParameter('serializer.default_context', $defaultContext);
1997+
}
1998+
19931999
if (isset($config['circular_reference_handler']) && $config['circular_reference_handler']) {
19942000
$arguments = $container->getDefinition('serializer.normalizer.object')->getArguments();
1995-
$context = ($arguments[6] ?? []) + ['circular_reference_handler' => new Reference($config['circular_reference_handler'])];
2001+
$context = ($arguments[6] ?? $defaultContext) + ['circular_reference_handler' => new Reference($config['circular_reference_handler'])];
19962002
$container->getDefinition('serializer.normalizer.object')->setArgument(5, null);
19972003
$container->getDefinition('serializer.normalizer.object')->setArgument(6, $context);
19982004
}
19992005

20002006
if ($config['max_depth_handler'] ?? false) {
2001-
$defaultContext = $container->getDefinition('serializer.normalizer.object')->getArgument(6);
2002-
$defaultContext += ['max_depth_handler' => new Reference($config['max_depth_handler'])];
2003-
$container->getDefinition('serializer.normalizer.object')->replaceArgument(6, $defaultContext);
2004-
}
2005-
2006-
if (isset($config['default_context']) && $config['default_context']) {
2007-
$container->setParameter('serializer.default_context', $config['default_context']);
2007+
$arguments = $container->getDefinition('serializer.normalizer.object')->getArguments();
2008+
$context = ($arguments[6] ?? $defaultContext) + ['max_depth_handler' => new Reference($config['max_depth_handler'])];
2009+
$container->getDefinition('serializer.normalizer.object')->setArgument(6, $context);
20082010
}
20092011
}
20102012

src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -979,6 +979,7 @@
979979
<xsd:element name="service" type="xsd:string" minOccurs="0" maxOccurs="1" />
980980
<xsd:element name="secret" type="xsd:string" minOccurs="0" maxOccurs="1" />
981981
</xsd:sequence>
982+
<xsd:attribute name="type" type="xsd:string" use="required" />
982983
</xsd:complexType>
983984

984985
<xsd:complexType name="remote-event">
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
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\Bundle\FrameworkBundle\Tests\Fixtures\Serializer;
13+
14+
class CircularReferenceHandler
15+
{
16+
public function __invoke()
17+
{
18+
}
19+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
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\Bundle\FrameworkBundle\Tests\Fixtures\Serializer;
13+
14+
class MaxDepthHandler
15+
{
16+
public function __invoke()
17+
{
18+
}
19+
}

src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Serializer/config.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ framework:
66
translator: true
77
serializer:
88
enabled: true
9+
circular_reference_handler: Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Serializer\CircularReferenceHandler
10+
max_depth_handler: Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Serializer\MaxDepthHandler
911
default_context:
1012
enable_max_depth: true
1113
fake_context_option: foo
@@ -63,3 +65,7 @@ services:
6365
serializer.encoder.csv.alias:
6466
alias: serializer.encoder.csv
6567
public: true
68+
69+
Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Serializer\CircularReferenceHandler: ~
70+
71+
Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Serializer\MaxDepthHandler: ~

src/Symfony/Bundle/FrameworkBundle/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@
8282
"symfony/asset": "<5.4",
8383
"symfony/asset-mapper": "<6.4",
8484
"symfony/clock": "<6.3",
85-
"symfony/console": "<5.4",
85+
"symfony/console": "<5.4|>=7.0",
8686
"symfony/dotenv": "<5.4",
8787
"symfony/dom-crawler": "<6.4",
8888
"symfony/http-client": "<6.3",

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@
3939
<div class="block-exception">
4040
<h1>Redirection Intercepted</h1>
4141

42-
{% set absolute_url = host in location ? location : host ~ location %}
42+
{% set absolute_url = absolute_url(location) %}
4343
<p>This request redirects to <strong>{{ absolute_url }}</strong></p>
4444

45-
<p><a class="btn" href="{{ location }}">Follow redirect</a></p>
45+
<p><a class="btn" href="{{ absolute_url }}">Follow redirect</a></p>
4646

4747
<p class="sf-redirection-help">
4848
The redirect was intercepted by the Symfony Web Debug toolbar to help debugging.

src/Symfony/Component/Console/Output/StreamOutput.php

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -97,18 +97,17 @@ protected function hasColorSupport(): bool
9797
return false;
9898
}
9999

100-
if ('Hyper' === getenv('TERM_PROGRAM')) {
100+
if (\DIRECTORY_SEPARATOR === '\\'
101+
&& \function_exists('sapi_windows_vt100_support')
102+
&& @sapi_windows_vt100_support($this->stream)
103+
) {
101104
return true;
102105
}
103106

104-
if (\DIRECTORY_SEPARATOR === '\\') {
105-
return (\function_exists('sapi_windows_vt100_support')
106-
&& @sapi_windows_vt100_support($this->stream))
107-
|| false !== getenv('ANSICON')
108-
|| 'ON' === getenv('ConEmuANSI')
109-
|| 'xterm' === getenv('TERM');
110-
}
111-
112-
return stream_isatty($this->stream);
107+
return 'Hyper' === getenv('TERM_PROGRAM')
108+
|| false !== getenv('ANSICON')
109+
|| 'ON' === getenv('ConEmuANSI')
110+
|| str_starts_with((string) getenv('TERM'), 'xterm')
111+
|| stream_isatty($this->stream);
113112
}
114113
}

src/Symfony/Component/DependencyInjection/EnvVarProcessorInterface.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ interface EnvVarProcessorInterface
2323
/**
2424
* Returns the value of the given variable as managed by the current instance.
2525
*
26-
* @param string $prefix The namespace of the variable
2726
* @param string $prefix The namespace of the variable; when the empty string is passed, null values should be kept as is
2827
* @param string $name The name of the variable within the namespace
2928
* @param \Closure(string): mixed $getEnv A closure that allows fetching more env vars

src/Symfony/Component/Dotenv/Command/DebugCommand.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,13 @@ private function getVariables(array $envFiles, ?string $nameFilter): array
151151

152152
private function getAvailableVars(): array
153153
{
154-
$vars = explode(',', $_SERVER['SYMFONY_DOTENV_VARS'] ?? '');
154+
$dotenvVars = $_SERVER['SYMFONY_DOTENV_VARS'] ?? '';
155+
156+
if ('' === $dotenvVars) {
157+
return [];
158+
}
159+
160+
$vars = explode(',', $dotenvVars);
155161
sort($vars);
156162

157163
return $vars;

src/Symfony/Component/Dotenv/Tests/Command/DebugCommandTest.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ class DebugCommandTest extends TestCase
2727
*/
2828
public function testErrorOnUninitializedDotenv()
2929
{
30+
unset($_SERVER['SYMFONY_DOTENV_VARS']);
31+
3032
$command = new DebugCommand('dev', __DIR__.'/Fixtures/Scenario1');
3133
$command->setHelperSet(new HelperSet([new FormatterHelper()]));
3234
$tester = new CommandTester($command);
@@ -36,6 +38,30 @@ public function testErrorOnUninitializedDotenv()
3638
$this->assertStringContainsString('[ERROR] Dotenv component is not initialized', $output);
3739
}
3840

41+
/**
42+
* @runInSeparateProcess
43+
*/
44+
public function testEmptyDotEnvVarsList()
45+
{
46+
$_SERVER['SYMFONY_DOTENV_VARS'] = '';
47+
48+
$command = new DebugCommand('dev', __DIR__.'/Fixtures/Scenario1');
49+
$command->setHelperSet(new HelperSet([new FormatterHelper()]));
50+
$tester = new CommandTester($command);
51+
$tester->execute([]);
52+
$expectedFormat = <<<'OUTPUT'
53+
%a
54+
---------- ------- ------------ ------%S
55+
Variable Value .env.local .env%S
56+
---------- ------- ------------ ------%S
57+
58+
// Note that values might be different between web and CLI.%S
59+
%a
60+
OUTPUT;
61+
62+
$this->assertStringMatchesFormat($expectedFormat, $tester->getDisplay());
63+
}
64+
3965
public function testScenario1InDevEnv()
4066
{
4167
$output = $this->executeCommand(__DIR__.'/Fixtures/Scenario1', 'dev');

src/Symfony/Component/ExpressionLanguage/Node/NullCoalesceNode.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public function compile(Compiler $compiler): void
3939
public function evaluate(array $functions, array $values): mixed
4040
{
4141
if ($this->nodes['expr1'] instanceof GetAttrNode) {
42-
$this->nodes['expr1']->attributes['is_null_coalesce'] = true;
42+
$this->addNullCoalesceAttributeToGetAttrNodes($this->nodes['expr1']);
4343
}
4444

4545
return $this->nodes['expr1']->evaluate($functions, $values) ?? $this->nodes['expr2']->evaluate($functions, $values);
@@ -49,4 +49,17 @@ public function toArray(): array
4949
{
5050
return ['(', $this->nodes['expr1'], ') ?? (', $this->nodes['expr2'], ')'];
5151
}
52+
53+
private function addNullCoalesceAttributeToGetAttrNodes(Node $node): void
54+
{
55+
if (!$node instanceof GetAttrNode) {
56+
return;
57+
}
58+
59+
$node->attributes['is_null_coalesce'] = true;
60+
61+
foreach ($node->nodes as $node) {
62+
$this->addNullCoalesceAttributeToGetAttrNodes($node);
63+
}
64+
}
5265
}

src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,9 @@ public function bar()
424424
yield ['foo["bar"]["baz"] ?? "default"', ['bar' => null]];
425425
yield ['foo["bar"].baz ?? "default"', ['bar' => null]];
426426
yield ['foo.bar().baz ?? "default"', $foo];
427+
yield ['foo.bar.baz.bam ?? "default"', (object) ['bar' => null]];
428+
yield ['foo?.bar?.baz?.qux ?? "default"', (object) ['bar' => null]];
429+
yield ['foo[123][456][789] ?? "default"', [123 => []]];
427430
}
428431

429432
/**

src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/BackedEnumValueResolver.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ public function resolve(Request $request, ArgumentMetadata $argument): iterable
8686

8787
try {
8888
return [$enumType::from($value)];
89-
} catch (\ValueError $e) {
89+
} catch (\ValueError|\TypeError $e) {
9090
throw new NotFoundHttpException(sprintf('Could not resolve the "%s $%s" controller argument: ', $argument->getType(), $argument->getName()).$e->getMessage(), $e);
9191
}
9292
}

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\BackedEnumValueResolver;
1717
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
1818
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
19+
use Symfony\Component\HttpKernel\Tests\Fixtures\IntEnum;
1920
use Symfony\Component\HttpKernel\Tests\Fixtures\Suit;
2021

2122
class BackedEnumValueResolverTest extends TestCase
@@ -134,6 +135,18 @@ public function testResolveThrowsOnUnexpectedType()
134135
$resolver->resolve($request, $metadata);
135136
}
136137

138+
public function testResolveThrowsOnTypeError()
139+
{
140+
$resolver = new BackedEnumValueResolver();
141+
$request = self::createRequest(['suit' => 'value']);
142+
$metadata = self::createArgumentMetadata('suit', IntEnum::class);
143+
144+
$this->expectException(NotFoundHttpException::class);
145+
$this->expectExceptionMessage('Could not resolve the "Symfony\Component\HttpKernel\Tests\Fixtures\IntEnum $suit" controller argument: Symfony\Component\HttpKernel\Tests\Fixtures\IntEnum::from(): Argument #1 ($value) must be of type int, string given');
146+
147+
$resolver->resolve($request, $metadata);
148+
}
149+
137150
private static function createRequest(array $attributes = []): Request
138151
{
139152
return new Request([], [], $attributes);
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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\HttpKernel\Tests\Fixtures;
13+
14+
enum IntEnum: int
15+
{
16+
case One = 1;
17+
case Two = 2;
18+
}

src/Symfony/Component/Mailer/Bridge/Amazon/Tests/Transport/SesApiAsyncAwsTransportTest.php

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,35 +38,35 @@ public static function getTransportData()
3838
{
3939
return [
4040
[
41-
new SesApiAsyncAwsTransport(new SesClient(Configuration::create(['accessKeyId' => 'ACCESS_KEY', 'accessKeySecret' => 'SECRET_KEY']))),
41+
new SesApiAsyncAwsTransport(new SesClient(Configuration::create(['sharedConfigFile' => false, 'accessKeyId' => 'ACCESS_KEY', 'accessKeySecret' => 'SECRET_KEY']))),
4242
'ses+api://ACCESS_KEY@us-east-1',
4343
],
4444
[
45-
new SesApiAsyncAwsTransport(new SesClient(Configuration::create(['accessKeyId' => 'ACCESS_KEY', 'accessKeySecret' => 'SECRET_KEY', 'region' => 'us-west-1']))),
45+
new SesApiAsyncAwsTransport(new SesClient(Configuration::create(['sharedConfigFile' => false, 'accessKeyId' => 'ACCESS_KEY', 'accessKeySecret' => 'SECRET_KEY', 'region' => 'us-west-1']))),
4646
'ses+api://ACCESS_KEY@us-west-1',
4747
],
4848
[
49-
new SesApiAsyncAwsTransport(new SesClient(Configuration::create(['accessKeyId' => 'ACCESS_KEY', 'accessKeySecret' => 'SECRET_KEY', 'endpoint' => 'https://example.com']))),
49+
new SesApiAsyncAwsTransport(new SesClient(Configuration::create(['sharedConfigFile' => false, 'accessKeyId' => 'ACCESS_KEY', 'accessKeySecret' => 'SECRET_KEY', 'endpoint' => 'https://example.com']))),
5050
'ses+api://ACCESS_KEY@example.com',
5151
],
5252
[
53-
new SesApiAsyncAwsTransport(new SesClient(Configuration::create(['accessKeyId' => 'ACCESS_KEY', 'accessKeySecret' => 'SECRET_KEY', 'endpoint' => 'https://example.com:99']))),
53+
new SesApiAsyncAwsTransport(new SesClient(Configuration::create(['sharedConfigFile' => false, 'accessKeyId' => 'ACCESS_KEY', 'accessKeySecret' => 'SECRET_KEY', 'endpoint' => 'https://example.com:99']))),
5454
'ses+api://ACCESS_KEY@example.com:99',
5555
],
5656
[
57-
new SesApiAsyncAwsTransport(new SesClient(Configuration::create(['accessKeyId' => 'ACCESS_KEY', 'accessKeySecret' => 'SECRET_KEY', 'sessionToken' => 'SESSION_TOKEN']))),
57+
new SesApiAsyncAwsTransport(new SesClient(Configuration::create(['sharedConfigFile' => false, 'accessKeyId' => 'ACCESS_KEY', 'accessKeySecret' => 'SECRET_KEY', 'sessionToken' => 'SESSION_TOKEN']))),
5858
'ses+api://ACCESS_KEY@us-east-1',
5959
],
6060
[
61-
new SesApiAsyncAwsTransport(new SesClient(Configuration::create(['accessKeyId' => 'ACCESS_KEY', 'accessKeySecret' => 'SECRET_KEY', 'region' => 'us-west-1', 'sessionToken' => 'SESSION_TOKEN']))),
61+
new SesApiAsyncAwsTransport(new SesClient(Configuration::create(['sharedConfigFile' => false, 'accessKeyId' => 'ACCESS_KEY', 'accessKeySecret' => 'SECRET_KEY', 'region' => 'us-west-1', 'sessionToken' => 'SESSION_TOKEN']))),
6262
'ses+api://ACCESS_KEY@us-west-1',
6363
],
6464
[
65-
new SesApiAsyncAwsTransport(new SesClient(Configuration::create(['accessKeyId' => 'ACCESS_KEY', 'accessKeySecret' => 'SECRET_KEY', 'endpoint' => 'https://example.com', 'sessionToken' => 'SESSION_TOKEN']))),
65+
new SesApiAsyncAwsTransport(new SesClient(Configuration::create(['sharedConfigFile' => false, 'accessKeyId' => 'ACCESS_KEY', 'accessKeySecret' => 'SECRET_KEY', 'endpoint' => 'https://example.com', 'sessionToken' => 'SESSION_TOKEN']))),
6666
'ses+api://ACCESS_KEY@example.com',
6767
],
6868
[
69-
new SesApiAsyncAwsTransport(new SesClient(Configuration::create(['accessKeyId' => 'ACCESS_KEY', 'accessKeySecret' => 'SECRET_KEY', 'endpoint' => 'https://example.com:99', 'sessionToken' => 'SESSION_TOKEN']))),
69+
new SesApiAsyncAwsTransport(new SesClient(Configuration::create(['sharedConfigFile' => false, 'accessKeyId' => 'ACCESS_KEY', 'accessKeySecret' => 'SECRET_KEY', 'endpoint' => 'https://example.com:99', 'sessionToken' => 'SESSION_TOKEN']))),
7070
'ses+api://ACCESS_KEY@example.com:99',
7171
],
7272
];
@@ -99,7 +99,7 @@ public function testSend()
9999
]);
100100
});
101101

102-
$transport = new SesApiAsyncAwsTransport(new SesClient(Configuration::create([]), new NullProvider(), $client));
102+
$transport = new SesApiAsyncAwsTransport(new SesClient(Configuration::create(['sharedConfigFile' => false]), new NullProvider(), $client));
103103

104104
$mail = new Email();
105105
$mail->subject('Hello!')

0 commit comments

Comments
 (0)
0