From 5acb53a765690c8dfc94e174029f45bd3f1b34c2 Mon Sep 17 00:00:00 2001 From: Gilles Roustan Date: Mon, 20 Jul 2020 13:49:23 +0200 Subject: [PATCH] fix: Allow UuidInterface array deserialization This commit will allow deserialization of array of UuidInterface using PhpDocExtractor. Ref: #12 --- CHANGELOG.md | 20 ++- README.md | 28 ++-- composer.json | 57 ++++---- src/UuidDenormalizer.php | 14 +- src/UuidNormalizer.php | 2 +- .../DenormalizeUsingPhpDocTest.php | 126 ++++++++++++++++++ tests/Functionnal/NomalizeTest.php | 74 ++++++++++ tests/UuidDenormalizerTest.php | 24 ++-- 8 files changed, 274 insertions(+), 71 deletions(-) create mode 100644 tests/Functionnal/DenormalizeUsingPhpDocTest.php create mode 100644 tests/Functionnal/NomalizeTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d665dc..a762eb3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,25 +1,33 @@ # Change Log + All notable changes to this project will be documented in this file based on the [Keep a Changelog](http://keepachangelog.com/) Standard. This project adheres to [Semantic Versioning](http://semver.org/). -## [Unreleased](https://github.com/gbprod/uuid-normalizer/compare/v1.1.0...HEAD) +## [Unreleased](https://github.com/gbprod/uuid-normalizer/compare/v1.2.0...HEAD) + +- Fix array of UuidInterface deserialization (#12) + +## [Unreleased](https://github.com/gbprod/uuid-normalizer/compare/v1.1.0...v1.2.0) - - Changing licence +- Update dependencies to php 8, Symfony 5 and Ramsey Uuid 4 +- Changing licence ## [v1.1.0](https://github.com/gbprod/uuid-normalizer/compare/v1.0.1...v1.1.0) - - - Symfony 4 compatibility - - Add Contributing file - - Drop php 5.5 compatibility + +- Symfony 4 compatibility +- Add Contributing file +- Drop php 5.5 compatibility ## [v1.0.0](https://github.com/gbprod/uuid-normalizer/compare/v1.0.0...v1.0.1) ### Added + - Version eye badge - Changelog - Compatibility and tests for Symfony Serializer 3.1 and Ramsey/Uuid 3.3 and 3.4 - More examples in documentation ### Changed + - Scrutinizer use PSR2 codesniffer - Use codecov instead of scrutinizer for coverage diff --git a/README.md b/README.md index 84a3b43..29a8a2b 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # Uuid normalizer -[![Build Status](https://travis-ci.org/gbprod/uuid-normalizer.svg?branch=master)](https://travis-ci.org/gbprod/uuid-normalizer) +[![Build Status](https://travis-ci.org/gbprod/uuid-normalizer.svg?branch=master)](https://travis-ci.org/gbprod/uuid-normalizer) [![codecov](https://codecov.io/gh/gbprod/uuid-normalizer/branch/master/graph/badge.svg)](https://codecov.io/gh/gbprod/uuid-normalizer) -[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/gbprod/uuid-normalizer/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/gbprod/uuid-normalizer/?branch=master) +[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/gbprod/uuid-normalizer/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/gbprod/uuid-normalizer/?branch=master) [![Dependency Status](https://www.versioneye.com/user/projects/574a9caace8d0e004130d3aa/badge.svg)](https://www.versioneye.com/user/projects/574a9caace8d0e004130d3aa) [![Latest Stable Version](https://poser.pugx.org/gbprod/uuid-normalizer/v/stable)](https://packagist.org/packages/gbprod/uuid-normalizer) @@ -23,9 +23,9 @@ composer require gbprod/uuid-normalizer ## Why By default, [Symfony Serializer](https://github.com/symfony/serializer) can't handle serialization and deserialization of [Ramsey Uuid](https://github.com/ramsey/uuid). -You will have that kind of errors: +You will have that kind of errors: -> Not a time-based UUID +> Not a time-based UUID > 500 Internal Server Error - UnsupportedOperationException ### Setup @@ -34,15 +34,15 @@ In your `app/config/service.yml` file: ```yaml services: - uuid_normalizer: - class: GBProd\UuidNormalizer\UuidNormalizer - tags: - - { name: serializer.normalizer } - - uuid_denormalizer: - class: GBProd\UuidNormalizer\UuidDenormalizer - tags: - - { name: serializer.normalizer } + uuid_normalizer: + class: GBProd\UuidNormalizer\UuidNormalizer + tags: + - { name: serializer.normalizer } + + uuid_denormalizer: + class: GBProd\UuidNormalizer\UuidDenormalizer + tags: + - { name: serializer.normalizer } ``` Or using `xml`: @@ -87,7 +87,7 @@ $serializer = new Serializer([ ## Requirements - * PHP 5.6+ +- PHP 5.6+ ## Contributing diff --git a/composer.json b/composer.json index eb0b524..88e19f0 100644 --- a/composer.json +++ b/composer.json @@ -1,30 +1,31 @@ { - "name": "gbprod/uuid-normalizer", - "description": "Normalizer to serialize Ramsey Uuid with Symfony Serializer", - "type": "library", - "autoload": { - "psr-4": { - "GBProd\\UuidNormalizer\\": "src/" - } - }, - "autoload-dev": { - "psr-4": { - "Tests\\GBProd\\UuidNormalizer\\": "tests/" - } - }, - "require": { - "php": "^5.6|^7.0|^8.0", - "ramsey/uuid": "^3.0|^4.0", - "symfony/serializer": "^2.3|^3.0|^4.0|^5.0" - }, - "require-dev": { - "phpunit/phpunit": "^5.7|^6.0" - }, - "license": "WTFPL", - "authors": [ - { - "name": "GBProd", - "email": "contact@gb-prod.fr" - } - ] + "name": "gbprod/uuid-normalizer", + "description": "Normalizer to serialize Ramsey Uuid with Symfony Serializer", + "type": "library", + "autoload": { + "psr-4": { + "GBProd\\UuidNormalizer\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "Tests\\GBProd\\UuidNormalizer\\": "tests/" + } + }, + "require": { + "php": "^5.6|^7.0|^8.0", + "ramsey/uuid": "^3.0|^4.0", + "symfony/serializer": "^2.3|^3.0|^4.0|^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.7|^6.0", + "symfony/property-access": "^2.3|^3.0|^4.0|^5.0" + }, + "license": "WTFPL", + "authors": [ + { + "name": "GBProd", + "email": "contact@gb-prod.fr" + } + ] } diff --git a/src/UuidDenormalizer.php b/src/UuidDenormalizer.php index 222cd55..510b58a 100644 --- a/src/UuidDenormalizer.php +++ b/src/UuidDenormalizer.php @@ -4,6 +4,7 @@ use Ramsey\Uuid\Uuid; use Ramsey\Uuid\UuidInterface; +use Symfony\Component\Serializer\Exception\UnexpectedValueException; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; /** @@ -18,6 +19,10 @@ class UuidDenormalizer implements DenormalizerInterface */ public function denormalize($data, $class, $format = null, array $context = array()) { + if (!$this->isValid($data)) { + throw new UnexpectedValueException('Expected a valid Uuid.'); + } + if (null === $data) { return null; } @@ -30,15 +35,12 @@ public function denormalize($data, $class, $format = null, array $context = arra */ public function supportsDenormalization($data, $type, $format = null) { - return (Uuid::class === $type || UuidInterface::class === $type) - && $this->isValid($data) - ; + return (Uuid::class === $type || UuidInterface::class === $type); } private function isValid($data) { return $data === null - || (is_string($data) && Uuid::isValid($data)) - ; + || (is_string($data) && Uuid::isValid($data)); } -} \ No newline at end of file +} diff --git a/src/UuidNormalizer.php b/src/UuidNormalizer.php index 1de2904..1180bd5 100644 --- a/src/UuidNormalizer.php +++ b/src/UuidNormalizer.php @@ -27,4 +27,4 @@ public function supportsNormalization($data, $format = null) { return $data instanceof UuidInterface; } -} \ No newline at end of file +} diff --git a/tests/Functionnal/DenormalizeUsingPhpDocTest.php b/tests/Functionnal/DenormalizeUsingPhpDocTest.php new file mode 100644 index 0000000..58f9ce2 --- /dev/null +++ b/tests/Functionnal/DenormalizeUsingPhpDocTest.php @@ -0,0 +1,126 @@ +serializer = new Serializer($normalizers, [ + new JsonEncoder(), + ]); + } + + public function testDenormalizeWithUuid() + { + $uuid = Uuid::uuid4(); + $denormalized = $this->serializer->denormalize( + ['uuid' => $uuid->toString()], + ClassWithUuidAttribute::class + ); + + $this->assertEquals($uuid, $denormalized->uuid); + } + + public function testDenormalizeWithUuidInterface() + { + $uuid = Uuid::uuid4(); + $denormalized = $this->serializer->denormalize( + ['uuid' => $uuid->toString()], + ClassWithUuidInterfaceAttribute::class + ); + + $this->assertEquals($uuid, $denormalized->uuid); + } + + public function testDenormalizeWithArrayOfUuid() + { + $uuids = [ + Uuid::uuid1(), + Uuid::uuid3(Uuid::NAMESPACE_DNS, 'php.net'), + Uuid::uuid4(), + Uuid::uuid5(Uuid::NAMESPACE_DNS, 'php.net'), + ]; + + $denormalized = $this->serializer->denormalize( + ['uuids' => array_map(function ($uuid) { + return $uuid->toString(); + }, $uuids)], + ClassWithArrayOfUuidAttribute::class + ); + + $this->assertEquals($uuids, $denormalized->uuids); + } + + public function testDenormalizeWithArrayOfUuidInterface() + { + $uuids = [ + Uuid::uuid1(), + Uuid::uuid3(Uuid::NAMESPACE_DNS, 'php.net'), + Uuid::uuid4(), + Uuid::uuid5(Uuid::NAMESPACE_DNS, 'php.net'), + ]; + + $denormalized = $this->serializer->denormalize( + ['uuids' => array_map(function ($uuid) { + return $uuid->toString(); + }, $uuids)], + ClassWithArrayOfUuidInterfaceAttribute::class + ); + + $this->assertEquals($uuids, $denormalized->uuids); + } +} + +class ClassWithUuidAttribute +{ + /** @var Uuid */ + public $uuid; +} + +class ClassWithUuidInterfaceAttribute +{ + /** @var UuidInterface */ + public $uuid; +} + + +class ClassWithArrayOfUuidAttribute +{ + /** @var Uuid[] */ + public $uuids; +} + +class ClassWithArrayOfUuidInterfaceAttribute +{ + /** @var UuidInterface[] */ + public $uuids; +} diff --git a/tests/Functionnal/NomalizeTest.php b/tests/Functionnal/NomalizeTest.php new file mode 100644 index 0000000..3c4e033 --- /dev/null +++ b/tests/Functionnal/NomalizeTest.php @@ -0,0 +1,74 @@ +serializer = new Serializer([ + new UuidNormalizer(), + new UuidDenormalizer(), + new ObjectNormalizer(), + ], []); + } + + public function testNormalizeOnArray() + { + $uuid = Uuid::uuid4(); + + $normalized = $this->serializer->normalize( + ['uuid' => $uuid] + ); + + $this->assertEquals( + $uuid->toString(), + $normalized['uuid'] + ); + } + + public function testNormalizeOnObject() + { + $object = new ClassWithUuid(); + $object->uuid = Uuid::uuid4(); + + $normalized = $this->serializer->normalize($object); + + $this->assertEquals( + $object->uuid->toString(), + $normalized['uuid'] + ); + } + + public function testNormalizeArrayOfUuidOnObject() + { + $object = new ClassWithUuid(); + $object->uuid = [ + Uuid::uuid4(), + Uuid::uuid4(), + Uuid::uuid4(), + ]; + + $normalized = $this->serializer->normalize($object); + + $this->assertEquals( + $object->uuid[0]->toString(), + $normalized['uuid'][0] + ); + } +} + +class ClassWithUuid +{ + public $uuid; +} diff --git a/tests/UuidDenormalizerTest.php b/tests/UuidDenormalizerTest.php index 2fd3cb3..9362d24 100644 --- a/tests/UuidDenormalizerTest.php +++ b/tests/UuidDenormalizerTest.php @@ -6,6 +6,7 @@ use PHPUnit\Framework\TestCase; use Ramsey\Uuid\Uuid; use Ramsey\Uuid\UuidInterface; +use Symfony\Component\Serializer\Exception\UnexpectedValueException; /** * Tests for UuidDenormalizer @@ -16,6 +17,7 @@ class UuidDenormalizerTest extends TestCase { const UUID_SAMPLE = '110e8400-e29b-11d4-a716-446655440000'; + /** @var UuidDenormalizer */ private $denormalizer; public function setUp() @@ -33,13 +35,13 @@ public function testSupportsIsFalseIfNotUuidClass() ); } - public function testSupportsIsFalseIfNotWellFormatted() + public function testThrowExceptionIfNotWellFormatted() { - $this->assertFalse( - $this->denormalizer->supportsDenormalization( - 'BAD_UUID', - Uuid::class - ) + $this->expectException(UnexpectedValueException::class); + + $this->denormalizer->denormalize( + 'BAD_UUID', + Uuid::class ); } @@ -63,16 +65,6 @@ public function testSupportsIsTrueIfTypeIsUuidInterface() ); } - public function testSupportsIsFalseIfBadType() - { - $this->assertFalse( - $this->denormalizer->supportsDenormalization( - 42, - Uuid::class - ) - ); - } - public function testSupportsIsTrueIfNull() { $this->assertTrue(