Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2b935bc

Browse files
[Serializer] Add support of PHP 8.1 backed enumerations
1 parent 1ca10f5 commit 2b935bc

File tree

7 files changed

+210
-0
lines changed

7 files changed

+210
-0
lines changed

src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
3333
use Symfony\Component\Serializer\NameConverter\MetadataAwareNameConverter;
3434
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
35+
use Symfony\Component\Serializer\Normalizer\BackedEnumNormalizer;
3536
use Symfony\Component\Serializer\Normalizer\ConstraintViolationListNormalizer;
3637
use Symfony\Component\Serializer\Normalizer\DataUriNormalizer;
3738
use Symfony\Component\Serializer\Normalizer\DateIntervalNormalizer;
@@ -76,6 +77,9 @@
7677
->alias(ClassDiscriminatorResolverInterface::class, 'serializer.mapping.class_discriminator_resolver')
7778

7879
// Normalizer
80+
->set('serializer.normalizer.backed_enum', BackedEnumNormalizer::class)
81+
->tag('serializer.normalizer', ['priority' => -915])
82+
7983
->set('serializer.normalizer.constraint_violation_list', ConstraintViolationListNormalizer::class)
8084
->args([[], service('serializer.name_converter.metadata_aware')])
8185
->tag('serializer.normalizer', ['priority' => -915])

src/Symfony/Component/Serializer/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
CHANGELOG
22
=========
33

4+
6.0
5+
---
6+
* Add serializer support for backed enumerations
7+
48
5.3
59
---
610

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\Serializer\Normalizer;
13+
14+
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
15+
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
16+
17+
/**
18+
* Normalizes a {@see \BackedEnum} enumeration to a string or an integer.
19+
*
20+
* @author Alexandre Daubois <[email protected]>
21+
*/
22+
class BackedEnumNormalizer implements NormalizerInterface, DenormalizerInterface, CacheableSupportsMethodInterface
23+
{
24+
/**
25+
* {@inheritdoc}
26+
*
27+
* @throws InvalidArgumentException
28+
*
29+
* @return string
30+
*/
31+
public function normalize($object, string $format = null, array $context = [])
32+
{
33+
if (!is_subclass_of(\get_class($object), '\BackedEnum')) {
34+
throw new InvalidArgumentException('The object must belong to a backed enumeration.');
35+
}
36+
37+
return $object->value;
38+
}
39+
40+
/**
41+
* {@inheritdoc}
42+
*/
43+
public function supportsNormalization($data, string $format = null)
44+
{
45+
return is_subclass_of(\get_class($data), '\BackedEnum');
46+
}
47+
48+
/**
49+
* {@inheritdoc}
50+
*
51+
* @throws NotNormalizableValueException
52+
*
53+
* @return string|int
54+
*/
55+
public function denormalize($data, string $type, string $format = null, array $context = [])
56+
{
57+
if ('' === $data || null === $data) {
58+
throw new NotNormalizableValueException('The data is either an empty string or null, you should pass a string that can be parsed as an enumeration case of type '.$type.'.');
59+
}
60+
61+
try {
62+
return $type::from($data);
63+
} catch (\Exception | \ValueError $e) {
64+
throw new NotNormalizableValueException($e->getMessage(), $e->getCode(), $e);
65+
}
66+
}
67+
68+
/**
69+
* {@inheritdoc}
70+
*/
71+
public function supportsDenormalization($data, string $type, string $format = null)
72+
{
73+
return is_subclass_of($type, '\BackedEnum');
74+
}
75+
76+
/**
77+
* {@inheritdoc}
78+
*/
79+
public function hasCacheableSupportsMethod(): bool
80+
{
81+
return __CLASS__ === static::class;
82+
}
83+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
4+
namespace Symfony\Component\Serializer\Tests\Fixtures;
5+
6+
7+
enum IntegerBackedEnumDummy: int
8+
{
9+
case SUCCESS = 200;
10+
case NOT_FOUND = 404;
11+
case ERROR = 500;
12+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
4+
namespace Symfony\Component\Serializer\Tests\Fixtures;
5+
6+
7+
enum StringBackedEnumDummy: string
8+
{
9+
case GET = 'GET';
10+
case POST = 'POST';
11+
case PUT = 'PUT';
12+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
4+
namespace Symfony\Component\Serializer\Tests\Fixtures;
5+
6+
7+
enum UnitEnumDummy
8+
{
9+
case GET;
10+
case POST;
11+
case PUT;
12+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\Serializer\Tests\Normalizer;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
16+
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
17+
use Symfony\Component\Serializer\Normalizer\BackedEnumNormalizer;
18+
use Symfony\Component\Serializer\Tests\Fixtures\IntegerBackedEnumDummy;
19+
use Symfony\Component\Serializer\Tests\Fixtures\StringBackedEnumDummy;
20+
use Symfony\Component\Serializer\Tests\Fixtures\UnitEnumDummy;
21+
22+
/**
23+
* @author Alexandre Daubois <[email protected]>
24+
*/
25+
class BackedEnumNormalizerTest extends TestCase
26+
{
27+
/**
28+
* @var BackedEnumNormalizer
29+
*/
30+
private $normalizer;
31+
32+
protected function setUp(): void
33+
{
34+
$this->normalizer = new BackedEnumNormalizer();
35+
}
36+
37+
public function testSupportsNormalization()
38+
{
39+
$this->assertTrue($this->normalizer->supportsNormalization(StringBackedEnumDummy::POST));
40+
$this->assertTrue($this->normalizer->supportsNormalization(IntegerBackedEnumDummy::SUCCESS));
41+
$this->assertFalse($this->normalizer->supportsNormalization(UnitEnumDummy::POST));
42+
$this->assertFalse($this->normalizer->supportsNormalization(new \stdClass()));
43+
}
44+
45+
public function testNormalize()
46+
{
47+
$this->assertEquals('POST', $this->normalizer->normalize(StringBackedEnumDummy::POST));
48+
$this->assertEquals(500, $this->normalizer->normalize(IntegerBackedEnumDummy::ERROR));
49+
}
50+
51+
public function testNormalizeBadObjectTypeThrowsException()
52+
{
53+
$this->expectException(InvalidArgumentException::class);
54+
$this->normalizer->normalize(new \stdClass());
55+
}
56+
57+
public function testSupportsDenormalization()
58+
{
59+
$this->assertTrue($this->normalizer->supportsDenormalization(null, StringBackedEnumDummy::class));
60+
$this->assertTrue($this->normalizer->supportsDenormalization(null, IntegerBackedEnumDummy::class));
61+
$this->assertFalse($this->normalizer->supportsDenormalization(null, UnitEnumDummy::class));
62+
$this->assertFalse($this->normalizer->supportsDenormalization(null, \stdClass::class));
63+
}
64+
65+
public function testDenormalize()
66+
{
67+
$this->assertEquals(StringBackedEnumDummy::PUT, $this->normalizer->denormalize('PUT', StringBackedEnumDummy::class));
68+
$this->assertEquals(IntegerBackedEnumDummy::SUCCESS, $this->normalizer->denormalize(200, IntegerBackedEnumDummy::class));
69+
}
70+
71+
public function testDenormalizeNullValueThrowsException()
72+
{
73+
$this->expectException(NotNormalizableValueException::class);
74+
$this->normalizer->denormalize(null, StringBackedEnumDummy::class);
75+
}
76+
77+
public function testDenormalizeBadTimeZoneThrowsException()
78+
{
79+
$this->expectException(NotNormalizableValueException::class);
80+
$this->expectExceptionMessage('"HEAD" is not a valid backing value for enum "'.StringBackedEnumDummy::class.'"');
81+
$this->normalizer->denormalize('HEAD', StringBackedEnumDummy::class);
82+
}
83+
}

0 commit comments

Comments
 (0)