Skip to content

Commit 2a5b899

Browse files
Merge branch '5.4' into 6.2
* 5.4: [Serializer] Throw NotNormalizableValueException if it doesn't concern a backedEnum in construct method Do not expose `Sfjs` as it is unused and conflicts with WebProfilerBundle’s [PropertyInfo] Fix phpDocExtractor nullable array value type
2 parents 0732edf + a22b6f7 commit 2a5b899

File tree

5 files changed

+63
-4
lines changed

5 files changed

+63
-4
lines changed

Normalizer/AbstractNormalizer.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@ protected function instantiateObject(array &$data, string $class, array &$contex
322322

323323
$constructor = $this->getConstructor($data, $class, $context, $reflectionClass, $allowedAttributes);
324324
if ($constructor) {
325+
$context['has_constructor'] = true;
325326
if (true !== $constructor->isPublic()) {
326327
return $reflectionClass->newInstanceWithoutConstructor();
327328
}
@@ -412,6 +413,8 @@ protected function instantiateObject(array &$data, string $class, array &$contex
412413
}
413414
}
414415

416+
unset($context['has_constructor']);
417+
415418
return new $class();
416419
}
417420

Normalizer/BackedEnumNormalizer.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,11 @@ public function denormalize(mixed $data, string $type, string $format = null, ar
5252
try {
5353
return $type::from($data);
5454
} catch (\ValueError $e) {
55-
throw new InvalidArgumentException('The data must belong to a backed enumeration of type '.$type);
55+
if (isset($context['has_constructor'])) {
56+
throw new InvalidArgumentException('The data must belong to a backed enumeration of type '.$type);
57+
}
58+
59+
throw NotNormalizableValueException::createForUnexpectedDataType('The data must belong to a backed enumeration of type '.$type, $data, [$type], $context['deserialization_path'] ?? null, true, 0, $e);
5660
}
5761
}
5862

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Symfony\Component\Serializer\Tests\Fixtures;
4+
5+
use Symfony\Component\Serializer\Tests\Fixtures\StringBackedEnumDummy;
6+
7+
class DummyObjectWithEnumProperty
8+
{
9+
public StringBackedEnumDummy $get;
10+
}

Tests/Normalizer/BackedEnumNormalizerTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ public function testDenormalizeObjectThrowsException()
8888

8989
public function testDenormalizeBadBackingValueThrowsException()
9090
{
91-
$this->expectException(InvalidArgumentException::class);
91+
$this->expectException(NotNormalizableValueException::class);
9292
$this->expectExceptionMessage('The data must belong to a backed enumeration of type '.StringBackedEnumDummy::class);
9393

9494
$this->normalizer->denormalize('POST', StringBackedEnumDummy::class);

Tests/SerializerTest.php

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
use Symfony\Component\Serializer\Tests\Fixtures\DummyMessageNumberOne;
6161
use Symfony\Component\Serializer\Tests\Fixtures\DummyMessageNumberTwo;
6262
use Symfony\Component\Serializer\Tests\Fixtures\DummyObjectWithEnumConstructor;
63+
use Symfony\Component\Serializer\Tests\Fixtures\DummyObjectWithEnumProperty;
6364
use Symfony\Component\Serializer\Tests\Fixtures\FalseBuiltInDummy;
6465
use Symfony\Component\Serializer\Tests\Fixtures\NormalizableTraversableDummy;
6566
use Symfony\Component\Serializer\Tests\Fixtures\Php74Full;
@@ -1232,7 +1233,48 @@ public function testCollectDenormalizationErrorsWithEnumConstructor()
12321233
$this->assertSame($expected, $exceptionsAsArray);
12331234
}
12341235

1235-
public function testNoCollectDenormalizationErrorsWithWrongEnum()
1236+
public function testCollectDenormalizationErrorsWithWrongPropertyWithoutConstruct()
1237+
{
1238+
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader());
1239+
$reflectionExtractor = new ReflectionExtractor();
1240+
$propertyInfoExtractor = new PropertyInfoExtractor([], [$reflectionExtractor], [], [], []);
1241+
1242+
$serializer = new Serializer(
1243+
[
1244+
new BackedEnumNormalizer(),
1245+
new ObjectNormalizer($classMetadataFactory, null, null, $propertyInfoExtractor),
1246+
],
1247+
['json' => new JsonEncoder()]
1248+
);
1249+
1250+
try {
1251+
$serializer->deserialize('{"get": "POST"}', DummyObjectWithEnumProperty::class, 'json', [
1252+
DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS => true,
1253+
]);
1254+
} catch (\Throwable $e) {
1255+
$this->assertInstanceOf(PartialDenormalizationException::class, $e);
1256+
}
1257+
1258+
$exceptionsAsArray = array_map(function (NotNormalizableValueException $e): array {
1259+
return [
1260+
'currentType' => $e->getCurrentType(),
1261+
'useMessageForUser' => $e->canUseMessageForUser(),
1262+
'message' => $e->getMessage(),
1263+
];
1264+
}, $e->getErrors());
1265+
1266+
$expected = [
1267+
[
1268+
'currentType' => 'string',
1269+
'useMessageForUser' => true,
1270+
'message' => 'The data must belong to a backed enumeration of type Symfony\Component\Serializer\Tests\Fixtures\StringBackedEnumDummy',
1271+
],
1272+
];
1273+
1274+
$this->assertSame($expected, $exceptionsAsArray);
1275+
}
1276+
1277+
public function testNoCollectDenormalizationErrorsWithWrongEnumOnConstructor()
12361278
{
12371279
$serializer = new Serializer(
12381280
[
@@ -1243,7 +1285,7 @@ public function testNoCollectDenormalizationErrorsWithWrongEnum()
12431285
);
12441286

12451287
try {
1246-
$serializer->deserialize('{"get": "invalid"}', DummyObjectWithEnumConstructor::class, 'json', [
1288+
$serializer->deserialize('{"get": "POST"}', DummyObjectWithEnumConstructor::class, 'json', [
12471289
DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS => true,
12481290
]);
12491291
} catch (\Throwable $th) {

0 commit comments

Comments
 (0)