Skip to content

Commit 0fae922

Browse files
Merge branch '5.4' into 6.3
* 5.4: [FrameworkBundle] Update docblock AbstractController [HttpFoundation][FrameworkBundle] Fix default locale is ignored when set_locale_from_accept_language is used add missing translations [Validator] updated Lithuanian translation [Validator] fix some non-sense Lithuanian translations [Validator] updated Slovenian translation [Validator] updated Finnish translation [Validator] Add `Charset` french translation [Tests] Streamline CompiledUrlGenerator tests [Serializer] Skip uninitialized properties with deep_object_to_populate fix Constraints\Email::ERROR_NAMES
2 parents 9cbd0d1 + 2d5d053 commit 0fae922

File tree

15 files changed

+105
-40
lines changed

15 files changed

+105
-40
lines changed

src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ protected function generateUrl(string $route, array $parameters = [], int $refer
112112
/**
113113
* Forwards the request to another controller.
114114
*
115-
* @param string $controller The controller name (a string like Bundle\BlogBundle\Controller\PostController::indexAction)
115+
* @param string $controller The controller name (a string like "App\Controller\PostController::index" or "App\Controller\PostController" if it is invokable)
116116
*/
117117
protected function forward(string $controller, array $path = [], array $query = []): Response
118118
{

src/Symfony/Component/HttpKernel/EventListener/LocaleListener.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ private function setLocale(Request $request): void
6969
if ($locale = $request->attributes->get('_locale')) {
7070
$request->setLocale($locale);
7171
} elseif ($this->useAcceptLanguageHeader) {
72-
if ($preferredLanguage = $request->getPreferredLanguage($this->enabledLocales)) {
72+
if ($request->getLanguages() && $preferredLanguage = $request->getPreferredLanguage($this->enabledLocales)) {
7373
$request->setLocale($preferredLanguage);
7474
}
7575
$request->attributes->set('_vary_by_language', true);

src/Symfony/Component/HttpKernel/Tests/EventListener/LocaleListenerTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,28 @@ public function testRequestPreferredLocaleFromAcceptLanguageHeader()
130130
$this->assertEquals('fr', $request->getLocale());
131131
}
132132

133+
public function testRequestDefaultLocaleIfNoAcceptLanguageHeaderIsPresent()
134+
{
135+
$request = new Request();
136+
$listener = new LocaleListener($this->requestStack, 'de', null, true, ['lt', 'de']);
137+
$event = $this->getEvent($request);
138+
139+
$listener->setDefaultLocale($event);
140+
$listener->onKernelRequest($event);
141+
$this->assertEquals('de', $request->getLocale());
142+
}
143+
144+
public function testRequestVaryByLanguageAttributeIsSetIfUsingAcceptLanguageHeader()
145+
{
146+
$request = new Request();
147+
$listener = new LocaleListener($this->requestStack, 'de', null, true, ['lt', 'de']);
148+
$event = $this->getEvent($request);
149+
150+
$listener->setDefaultLocale($event);
151+
$listener->onKernelRequest($event);
152+
$this->assertTrue($request->attributes->get('_vary_by_language'));
153+
}
154+
133155
public function testRequestSecondPreferredLocaleFromAcceptLanguageHeader()
134156
{
135157
$request = Request::create('/');

src/Symfony/Component/Routing/Tests/Generator/Dumper/CompiledUrlGeneratorDumperTest.php

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -123,14 +123,16 @@ public function testDumpWithSimpleLocalizedRoutes()
123123

124124
public function testDumpWithRouteNotFoundLocalizedRoutes()
125125
{
126-
$this->expectException(RouteNotFoundException::class);
127-
$this->expectExceptionMessage('Unable to generate a URL for the named route "test" as such route does not exist.');
128126
$this->routeCollection->add('test.en', (new Route('/testing/is/fun'))->setDefault('_locale', 'en')->setDefault('_canonical_route', 'test')->setRequirement('_locale', 'en'));
129127

130128
$code = $this->generatorDumper->dump();
131129
file_put_contents($this->testTmpFilepath, $code);
132130

133131
$projectUrlGenerator = new CompiledUrlGenerator(require $this->testTmpFilepath, new RequestContext('/app.php'), null, 'pl_PL');
132+
133+
$this->expectException(RouteNotFoundException::class);
134+
$this->expectExceptionMessage('Unable to generate a URL for the named route "test" as such route does not exist.');
135+
134136
$projectUrlGenerator->generate('test');
135137
}
136138

@@ -183,22 +185,25 @@ public function testDumpWithTooManyRoutes()
183185

184186
public function testDumpWithoutRoutes()
185187
{
186-
$this->expectException(\InvalidArgumentException::class);
187188
file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump());
188189

189190
$projectUrlGenerator = new CompiledUrlGenerator(require $this->testTmpFilepath, new RequestContext('/app.php'));
190191

192+
$this->expectException(\InvalidArgumentException::class);
193+
191194
$projectUrlGenerator->generate('Test', []);
192195
}
193196

194197
public function testGenerateNonExistingRoute()
195198
{
196-
$this->expectException(RouteNotFoundException::class);
197199
$this->routeCollection->add('Test', new Route('/test'));
198200

199201
file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump());
200202

201203
$projectUrlGenerator = new CompiledUrlGenerator(require $this->testTmpFilepath, new RequestContext());
204+
205+
$this->expectException(RouteNotFoundException::class);
206+
202207
$projectUrlGenerator->generate('NonExisting', []);
203208
}
204209

@@ -287,66 +292,72 @@ public function testAliases()
287292

288293
public function testTargetAliasNotExisting()
289294
{
290-
$this->expectException(RouteNotFoundException::class);
291-
292-
$this->routeCollection->addAlias('a', 'not-existing');
295+
$this->routeCollection->add('not-existing', new Route('/not-existing'));
296+
$this->routeCollection->addAlias('alias', 'not-existing');
293297

294298
file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump());
295299

296-
$compiledUrlGenerator = new CompiledUrlGenerator(require $this->testTmpFilepath, new RequestContext());
300+
$compiledRoutes = require $this->testTmpFilepath;
301+
unset($compiledRoutes['alias']);
297302

303+
$this->expectException(RouteNotFoundException::class);
304+
305+
$compiledUrlGenerator = new CompiledUrlGenerator($compiledRoutes, new RequestContext());
298306
$compiledUrlGenerator->generate('a');
299307
}
300308

301309
public function testTargetAliasWithNamePrefixNotExisting()
302310
{
303-
$this->expectException(RouteNotFoundException::class);
304-
305311
$subCollection = new RouteCollection();
306-
$subCollection->addAlias('a', 'not-existing');
312+
$subCollection->add('not-existing', new Route('/not-existing'));
313+
$subCollection->addAlias('alias', 'not-existing');
307314
$subCollection->addNamePrefix('sub_');
308315

309316
$this->routeCollection->addCollection($subCollection);
310317

311318
file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump());
312319

313-
$compiledUrlGenerator = new CompiledUrlGenerator(require $this->testTmpFilepath, new RequestContext());
320+
$compiledRoutes = require $this->testTmpFilepath;
321+
unset($compiledRoutes['sub_alias']);
314322

315-
$compiledUrlGenerator->generate('sub_a');
323+
$this->expectException(RouteNotFoundException::class);
324+
325+
$compiledUrlGenerator = new CompiledUrlGenerator($compiledRoutes, new RequestContext());
326+
$compiledUrlGenerator->generate('sub_alias');
316327
}
317328

318329
public function testCircularReferenceShouldThrowAnException()
319330
{
320-
$this->expectException(RouteCircularReferenceException::class);
321-
$this->expectExceptionMessage('Circular reference detected for route "b", path: "b -> a -> b".');
322-
323331
$this->routeCollection->addAlias('a', 'b');
324332
$this->routeCollection->addAlias('b', 'a');
325333

334+
$this->expectException(RouteCircularReferenceException::class);
335+
$this->expectExceptionMessage('Circular reference detected for route "b", path: "b -> a -> b".');
336+
326337
$this->generatorDumper->dump();
327338
}
328339

329340
public function testDeepCircularReferenceShouldThrowAnException()
330341
{
331-
$this->expectException(RouteCircularReferenceException::class);
332-
$this->expectExceptionMessage('Circular reference detected for route "b", path: "b -> c -> b".');
333-
334342
$this->routeCollection->addAlias('a', 'b');
335343
$this->routeCollection->addAlias('b', 'c');
336344
$this->routeCollection->addAlias('c', 'b');
337345

346+
$this->expectException(RouteCircularReferenceException::class);
347+
$this->expectExceptionMessage('Circular reference detected for route "b", path: "b -> c -> b".');
348+
338349
$this->generatorDumper->dump();
339350
}
340351

341352
public function testIndirectCircularReferenceShouldThrowAnException()
342353
{
343-
$this->expectException(RouteCircularReferenceException::class);
344-
$this->expectExceptionMessage('Circular reference detected for route "b", path: "b -> c -> a -> b".');
345-
346354
$this->routeCollection->addAlias('a', 'b');
347355
$this->routeCollection->addAlias('b', 'c');
348356
$this->routeCollection->addAlias('c', 'a');
349357

358+
$this->expectException(RouteCircularReferenceException::class);
359+
$this->expectExceptionMessage('Circular reference detected for route "b", path: "b -> c -> a -> b".');
360+
350361
$this->generatorDumper->dump();
351362
}
352363

src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -190,12 +190,7 @@ public function normalize(mixed $object, string $format = null, array $context =
190190
$attributeValue = $attribute === $this->classDiscriminatorResolver?->getMappingForMappedObject($object)?->getTypeProperty()
191191
? $this->classDiscriminatorResolver?->getTypeForMappedObject($object)
192192
: $this->getAttributeValue($object, $attribute, $format, $attributeContext);
193-
} catch (UninitializedPropertyException $e) {
194-
if ($context[self::SKIP_UNINITIALIZED_VALUES] ?? $this->defaultContext[self::SKIP_UNINITIALIZED_VALUES] ?? true) {
195-
continue;
196-
}
197-
throw $e;
198-
} catch (\Error $e) {
193+
} catch (UninitializedPropertyException|\Error $e) {
199194
if (($context[self::SKIP_UNINITIALIZED_VALUES] ?? $this->defaultContext[self::SKIP_UNINITIALIZED_VALUES] ?? true) && $this->isUninitializedValueError($e)) {
200195
continue;
201196
}
@@ -373,6 +368,10 @@ public function denormalize(mixed $data, string $type, string $format = null, ar
373368
? $discriminatorMapping
374369
: $this->getAttributeValue($object, $attribute, $format, $attributeContext);
375370
} catch (NoSuchPropertyException) {
371+
} catch (UninitializedPropertyException|\Error $e) {
372+
if (!(($context[self::SKIP_UNINITIALIZED_VALUES] ?? $this->defaultContext[self::SKIP_UNINITIALIZED_VALUES] ?? true) && $this->isUninitializedValueError($e))) {
373+
throw $e;
374+
}
376375
}
377376
}
378377

@@ -769,9 +768,10 @@ private function getCacheKey(?string $format, array $context): bool|string
769768
* This error may occur when specific object normalizer implementation gets attribute value
770769
* by accessing a public uninitialized property or by calling a method accessing such property.
771770
*/
772-
private function isUninitializedValueError(\Error $e): bool
771+
private function isUninitializedValueError(\Error|UninitializedPropertyException $e): bool
773772
{
774-
return str_starts_with($e->getMessage(), 'Typed property')
773+
return $e instanceof UninitializedPropertyException
774+
|| str_starts_with($e->getMessage(), 'Typed property')
775775
&& str_ends_with($e->getMessage(), 'must not be accessed before initialization');
776776
}
777777

src/Symfony/Component/Serializer/Tests/Normalizer/Features/SkipUninitializedValuesTestTrait.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@
1212
namespace Symfony\Component\Serializer\Tests\Normalizer\Features;
1313

1414
use Symfony\Component\PropertyAccess\Exception\UninitializedPropertyException;
15-
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
15+
use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer;
1616

1717
/**
1818
* Test AbstractObjectNormalizer::SKIP_UNINITIALIZED_VALUES.
1919
*/
2020
trait SkipUninitializedValuesTestTrait
2121
{
22-
abstract protected function getNormalizerForSkipUninitializedValues(): NormalizerInterface;
22+
abstract protected function getNormalizerForSkipUninitializedValues(): AbstractObjectNormalizer;
2323

2424
/**
2525
* @dataProvider skipUninitializedValuesFlagProvider
@@ -31,6 +31,15 @@ public function testSkipUninitializedValues(array $context)
3131
$normalizer = $this->getNormalizerForSkipUninitializedValues();
3232
$result = $normalizer->normalize($object, null, $context);
3333
$this->assertSame(['initialized' => 'value'], $result);
34+
35+
$normalizer->denormalize(
36+
['unInitialized' => 'value'],
37+
TypedPropertiesObjectWithGetters::class,
38+
null,
39+
['object_to_populate' => $objectToPopulate = new TypedPropertiesObjectWithGetters(), 'deep_object_to_populate' => true] + $context
40+
);
41+
42+
$this->assertSame('value', $objectToPopulate->getUninitialized());
3443
}
3544

3645
public function skipUninitializedValuesFlagProvider(): iterable

src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ protected function getNormalizerForCacheableObjectAttributesTest(): GetSetMethod
493493
return new GetSetMethodNormalizer();
494494
}
495495

496-
protected function getNormalizerForSkipUninitializedValues(): NormalizerInterface
496+
protected function getNormalizerForSkipUninitializedValues(): GetSetMethodNormalizer
497497
{
498498
return new GetSetMethodNormalizer(new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader())));
499499
}

src/Symfony/Component/Serializer/Tests/Normalizer/PropertyNormalizerTest.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer;
2727
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
2828
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
29-
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
3029
use Symfony\Component\Serializer\Normalizer\PropertyNormalizer;
3130
use Symfony\Component\Serializer\Serializer;
3231
use Symfony\Component\Serializer\SerializerInterface;
@@ -500,7 +499,7 @@ protected function getNormalizerForCacheableObjectAttributesTest(): AbstractObje
500499
return new PropertyNormalizer();
501500
}
502501

503-
protected function getNormalizerForSkipUninitializedValues(): NormalizerInterface
502+
protected function getNormalizerForSkipUninitializedValues(): PropertyNormalizer
504503
{
505504
return new PropertyNormalizer(new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader())));
506505
}

src/Symfony/Component/Validator/Constraints/Email.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class Email extends Constraint
4343
];
4444

4545
protected const ERROR_NAMES = [
46-
self::INVALID_FORMAT_ERROR => 'STRICT_CHECK_FAILED_ERROR',
46+
self::INVALID_FORMAT_ERROR => 'INVALID_FORMAT_ERROR',
4747
];
4848

4949
/**

src/Symfony/Component/Validator/Resources/translations/validators.de.xlf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,10 @@
430430
<source>The extension of the file is invalid ({{ extension }}). Allowed extensions are {{ extensions }}.</source>
431431
<target>Die Dateiendung ist ungültig ({{ extension }}). Gültige Dateiendungen sind {{ extensions }}.</target>
432432
</trans-unit>
433+
<trans-unit id="111">
434+
<source>The detected character encoding is invalid ({{ detected }}). Allowed encodings are {{ encodings }}.</source>
435+
<target>Der erkannte Zeichensatz ist nicht gültig ({{ detected }}). Gültige Zeichensätze sind "{{ encodings }}".</target>
436+
</trans-unit>
433437
</body>
434438
</file>
435439
</xliff>

0 commit comments

Comments
 (0)