From 1546c0dfa0755fed2ad7b84be2f7ef24ed66f0e4 Mon Sep 17 00:00:00 2001 From: jewome62 Date: Sat, 6 Apr 2019 17:45:16 +0200 Subject: [PATCH] [Serializer] Add datetimezone normalizer --- src/Symfony/Component/Serializer/CHANGELOG.md | 1 + .../Normalizer/DateTimeZoneNormalizer.php | 79 ++++++++++++++++++ .../Normalizer/DateTimeZoneNormalizerTest.php | 81 +++++++++++++++++++ 3 files changed, 161 insertions(+) create mode 100644 src/Symfony/Component/Serializer/Normalizer/DateTimeZoneNormalizer.php create mode 100644 src/Symfony/Component/Serializer/Tests/Normalizer/DateTimeZoneNormalizerTest.php diff --git a/src/Symfony/Component/Serializer/CHANGELOG.md b/src/Symfony/Component/Serializer/CHANGELOG.md index 57e4ed1fd7..fc4ab8b0a3 100644 --- a/src/Symfony/Component/Serializer/CHANGELOG.md +++ b/src/Symfony/Component/Serializer/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG ----- * added the list of constraint violations' parameters in `ConstraintViolationListNormalizer` + * added support for serializing `DateTimeZone` objects 4.2.0 ----- diff --git a/src/Symfony/Component/Serializer/Normalizer/DateTimeZoneNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/DateTimeZoneNormalizer.php new file mode 100644 index 0000000000..8d589d71c6 --- /dev/null +++ b/src/Symfony/Component/Serializer/Normalizer/DateTimeZoneNormalizer.php @@ -0,0 +1,79 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Normalizer; + +use Symfony\Component\Serializer\Exception\InvalidArgumentException; +use Symfony\Component\Serializer\Exception\NotNormalizableValueException; + +/** + * Normalizes a {@see \DateTimeZone} object to a timezone string. + * + * @author Jérôme Desjardins + */ +class DateTimeZoneNormalizer implements NormalizerInterface, DenormalizerInterface, CacheableSupportsMethodInterface +{ + /** + * {@inheritdoc} + * + * @throws InvalidArgumentException + */ + public function normalize($object, $format = null, array $context = []) + { + if (!$object instanceof \DateTimeZone) { + throw new InvalidArgumentException('The object must be an instance of "\DateTimeZone".'); + } + + return $object->getName(); + } + + /** + * {@inheritdoc} + */ + public function supportsNormalization($data, $format = null) + { + return $data instanceof \DateTimeZone; + } + + /** + * {@inheritdoc} + * + * @throws NotNormalizableValueException + */ + public function denormalize($data, $class, $format = null, array $context = []) + { + if ('' === $data || null === $data) { + throw new NotNormalizableValueException('The data is either an empty string or null, you should pass a string that can be parsed as a DateTimeZone.'); + } + + try { + return new \DateTimeZone($data); + } catch (\Exception $e) { + throw new NotNormalizableValueException($e->getMessage(), $e->getCode(), $e); + } + } + + /** + * {@inheritdoc} + */ + public function supportsDenormalization($data, $type, $format = null) + { + return \DateTimeZone::class === $type; + } + + /** + * {@inheritdoc} + */ + public function hasCacheableSupportsMethod(): bool + { + return __CLASS__ === \get_class($this); + } +} diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/DateTimeZoneNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/DateTimeZoneNormalizerTest.php new file mode 100644 index 0000000000..6f2486d3db --- /dev/null +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/DateTimeZoneNormalizerTest.php @@ -0,0 +1,81 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Tests\Normalizer; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Serializer\Normalizer\DateTimeZoneNormalizer; + +/** + * @author Jérôme Desjardins + */ +class DateTimeZoneNormalizerTest extends TestCase +{ + /** + * @var DateTimeZoneNormalizer + */ + private $normalizer; + + protected function setUp() + { + $this->normalizer = new DateTimeZoneNormalizer(); + } + + public function testSupportsNormalization() + { + $this->assertTrue($this->normalizer->supportsNormalization(new \DateTimeZone('UTC'))); + $this->assertFalse($this->normalizer->supportsNormalization(new \DateTimeImmutable())); + $this->assertFalse($this->normalizer->supportsNormalization(new \stdClass())); + } + + public function testNormalize() + { + $this->assertEquals('UTC', $this->normalizer->normalize(new \DateTimeZone('UTC'))); + $this->assertEquals('Asia/Tokyo', $this->normalizer->normalize(new \DateTimeZone('Asia/Tokyo'))); + } + + /** + * @expectedException \Symfony\Component\Serializer\Exception\InvalidArgumentException + */ + public function testNormalizeBadObjectTypeThrowsException() + { + $this->normalizer->normalize(new \stdClass()); + } + + public function testSupportsDenormalization() + { + $this->assertTrue($this->normalizer->supportsDenormalization(null, \DateTimeZone::class)); + $this->assertFalse($this->normalizer->supportsDenormalization(null, \DateTimeImmutable::class)); + $this->assertFalse($this->normalizer->supportsDenormalization(null, \stdClass::class)); + } + + public function testDenormalize() + { + $this->assertEquals(new \DateTimeZone('UTC'), $this->normalizer->denormalize('UTC', \DateTimeZone::class, null)); + $this->assertEquals(new \DateTimeZone('Asia/Tokyo'), $this->normalizer->denormalize('Asia/Tokyo', \DateTimeZone::class, null)); + } + + /** + * @expectedException \Symfony\Component\Serializer\Exception\NotNormalizableValueException + */ + public function testDenormalizeNullTimeZoneThrowsException() + { + $this->normalizer->denormalize(null, \DateTimeZone::class, null); + } + + /** + * @expectedException \Symfony\Component\Serializer\Exception\NotNormalizableValueException + */ + public function testDenormalizeBadTimeZoneThrowsException() + { + $this->normalizer->denormalize('Jupiter/Europa', \DateTimeZone::class, null); + } +}