8000 bug #50192 [Serializer] backed enum throw notNormalizableValueExcepti… · symfony/symfony@2ca50be · GitHub
[go: up one dir, main page]

Skip to content

Commit 2ca50be

Browse files
committed
bug #50192 [Serializer] backed enum throw notNormalizableValueException outside construct method (alli83)
This PR was merged into the 5.4 branch. Discussion ---------- [Serializer] backed enum throw notNormalizableValueException outside construct method | Q | A | ------------- | --- | Branch? | 5.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | #47128 (comment) | License | MIT | Doc PR | PR #47128 (comment) was aiming to throw an InvalidArgumentException if a constructor's argument is not a valid backedEnum( knowing an error will be thrown in all case e.g when it will be instantiated). This PR aims to throw a NotNormalizableValueException (like it was the case before) if an error occurs on an BackedEnum outside the case of the first PR So we have two different types of exceptions depending on whether it's an error at the constructor level or not. Commits ------- 5549493 [Serializer] Throw NotNormalizableValueException if it doesn't concern a backedEnum in construct method
2 parents 9af90a8 + 5549493 commit 2ca50be

File tree

5 files changed

+66
-4
lines changed

5 files changed

+66
-4
lines changed

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

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

343343
$constructor = $this->getConstructor($data, $class, $context, $reflectionClass, $allowedAttributes);
344344
if ($constructor) {
345+
$context['has_constructor'] = true;
345346
if (true !== $constructor->isPublic()) {
346347
return $reflectionClass->newInstanceWithoutConstructor();
347348
}
@@ -431,6 +432,8 @@ protected function instantiateObject(array &$data, string $class, array &$contex
431432
}
432433
}
433434

435+
unset($context['has_constructor']);
436+
434437
return new $class();
435438
}
436439

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,11 @@ public function denormalize($data, string $type, string $format = null, array $c
6464
try {
6565
return $type::from($data);
6666
} catch (\ValueError $e) {
67-
throw new InvalidArgumentException('The data must belong to a backed enumeration of type '.$type);
67+
if (isset($context['has_constructor'])) {
68+
throw new InvalidArgumentException('The data must belong to a backed enumeration of type '.$type);
69+
}
70+
71+
throw NotNormalizableValueException::createForUnexpectedDataType('The data must belong to a backed enumeration of type '.$type, $data, [$type], $context['deserialization_path'] ?? null, true, 0, $e);
6872
}
6973
}
7074

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+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ public function testDenormalizeObjectThrowsException()
115115
*/
116116
public function testDenormalizeBadBackingValueThrowsException()
117117
{
118-
$this->expectException(InvalidArgumentException::class);
118+
$this->expectException(NotNormalizableValueException::class);
119119
$this->expectExceptionMessage('The data must belong to a backed enumeration of type '.StringBackedEnumDummy::class);
120120

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

src/Symfony/Component/Serializer/Tests/SerializerTest.php

Lines changed: 47 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;
@@ -1230,7 +1231,51 @@ public function testCollectDenormalizationErrorsWithEnumConstructor()
12301231
/**
12311232
* @requires PHP 8.1
12321233
*/
1233-
public function testNoCollectDenormalizationErrorsWithWrongEnum()
1234+
public function testCollectDenormalizationErrorsWithWrongPropertyWithoutConstruct()
1235+
{
1236+
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader());
1237+
$reflectionExtractor = new ReflectionExtractor();
1238+
$propertyInfoExtractor = new PropertyInfoExtractor([], [$reflectionExtractor], [], [], []);
1239+
1240+
$serializer = new Serializer(
1241+
[
1242+
new BackedEnumNormalizer(),
1243+
new ObjectNormalizer($classMetadataFactory, null, null, $propertyInfoExtractor),
1244+
],
1245+
['json' => new JsonEncoder()]
1246+
);
1247+
1248+
try {
1249+
$serializer->deserialize('{"get": "POST"}', DummyObjectWithEnumProperty::class, 'json', [
1250+
DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS => true,
1251+
]);
1252+
} catch (\Throwable $e) {
1253+
$this->assertInstanceOf(PartialDenormalizationException::class, $e);
1254+
}
1255+
1256+
$exceptionsAsArray = array_map(function (NotNormalizableValueException $e): array {
1257+
return [
1258+
'currentType' => $e->getCurrentType(),
1259+
'useMessageForUser' => $e->canUseMessageForUser(),
1260+
'message' => $e->getMessage(),
1261+
];
1262+
}, $e->getErrors());
1263+
1264+
$expected = [
1265+
[
1266+
'currentType' => 'string',
1267+
'useMessageForUser' => true,
1268+
'message' => 'The data must belong to a backed enumeration of type Symfony\Component\Serializer\Tests\Fixtures\StringBackedEnumDummy',
1269+
],
1270+
];
1271+
1272+
$this->assertSame($expected, $exceptionsAsArray);
1273+
}
1274+
1275+
/**
1276+
* @requires PHP 8.1
1277+
*/
1278+
public function testNoCollectDenormalizationErrorsWithWrongEnumOnConstructor()
12341279
{
12351280
$serializer = new Serializer(
12361281
[
@@ -1241,7 +1286,7 @@ public function testNoCollectDenormalizationErrorsWithWrongEnum()
12411286
);
12421287

12431288
try {
1244-
$serializer->deserialize('{"get": "invalid"}', DummyObjectWithEnumConstructor::class, 'json', [
1289+
$serializer->deserialize('{"get": "POST"}', DummyObjectWithEnumConstructor::class, 'json', [
12451290
DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS => true,
12461291
]);
12471292
} catch (\Throwable $th) {

0 commit comments

Comments
 (0)
0