From 3076f6655f35ae07be00888ebff724f3d865d5c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Tue, 8 Dec 2015 00:03:04 +0100 Subject: [PATCH 1/3] [Serializer] Add PropertyInfo support in metadata --- .../Serializer/Mapping/AttributeMetadata.php | 31 ++++++++++- .../Mapping/AttributeMetadataInterface.php | 16 ++++++ .../Mapping/Factory/ClassMetadataFactory.php | 55 +++++++++++++++++-- .../Serializer/Tests/Fixtures/TypeDummy.php | 27 +++++++++ .../Tests/Mapping/AttributeMetadataTest.php | 17 +++++- .../Factory/ClassMetadataFactoryTest.php | 24 ++++++++ .../Component/Serializer/composer.json | 7 ++- 7 files changed, 167 insertions(+), 10 deletions(-) create mode 100644 src/Symfony/Component/Serializer/Tests/Fixtures/TypeDummy.php diff --git a/src/Symfony/Component/Serializer/Mapping/AttributeMetadata.php b/src/Symfony/Component/Serializer/Mapping/AttributeMetadata.php index 7a1d3db94a809..f59df6d13ce71 100644 --- a/src/Symfony/Component/Serializer/Mapping/AttributeMetadata.php +++ b/src/Symfony/Component/Serializer/Mapping/AttributeMetadata.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Serializer\Mapping; +use Symfony\Component\PropertyInfo\Type; + /** * {@inheritdoc} * @@ -36,6 +38,15 @@ class AttributeMetadata implements AttributeMetadataInterface */ public $groups = array(); + /** + * @var Type|null + * + * @internal This property is public in order to reduce the size of the + * class' serialized representation. Do not access it. Use + * {@link getTypes()} instead. + */ + public $types; + /** * Constructs a metadata for the given attribute. * @@ -72,6 +83,22 @@ public function getGroups() return $this->groups; } + /** + * {@inheritdoc} + */ + public function setTypes(array $types = null) + { + $this->types = $types; + } + + /** + * {@inheritdoc} + */ + public function getTypes() + { + return $this->types; + } + /** * {@inheritdoc} */ @@ -80,6 +107,8 @@ public function merge(AttributeMetadataInterface $attributeMetadata) foreach ($attributeMetadata->getGroups() as $group) { $this->addGroup($group); } + + // We don't need to merge types, this is handled by the PropertyInfo component } /** @@ -89,6 +118,6 @@ public function merge(AttributeMetadataInterface $attributeMetadata) */ public function __sleep() { - return array('name', 'groups'); + return array('name', 'groups', 'types'); } } diff --git a/src/Symfony/Component/Serializer/Mapping/AttributeMetadataInterface.php b/src/Symfony/Component/Serializer/Mapping/AttributeMetadataInterface.php index 0701a58b56257..569511679d51e 100644 --- a/src/Symfony/Component/Serializer/Mapping/AttributeMetadataInterface.php +++ b/src/Symfony/Component/Serializer/Mapping/AttributeMetadataInterface.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Serializer\Mapping; +use Symfony\Component\PropertyInfo\Type; + /** * Stores metadata needed for serializing and deserializing attributes. * @@ -41,6 +43,20 @@ public function addGroup($group); */ public function getGroups(); + /** + * Sets types of this attribute. + * + * @param Type[]|null $types + */ + public function setTypes(array $types); + + /** + * Gets types of this attribute. + * + * @return Type[]|null + */ + public function getTypes(); + /** * Merges an {@see AttributeMetadataInterface} with in the current one. * diff --git a/src/Symfony/Component/Serializer/Mapping/Factory/ClassMetadataFactory.php b/src/Symfony/Component/Serializer/Mapping/Factory/ClassMetadataFactory.php index 3a354e354e9e3..64b0e0bdbaf56 100644 --- a/src/Symfony/Component/Serializer/Mapping/Factory/ClassMetadataFactory.php +++ b/src/Symfony/Component/Serializer/Mapping/Factory/ClassMetadataFactory.php @@ -12,7 +12,10 @@ namespace Symfony\Component\Serializer\Mapping\Factory; use Doctrine\Common\Cache\Cache; +use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; +use Symfony\Component\PropertyInfo\PropertyListExtractorInterface; use Symfony\Component\Serializer\Exception\InvalidArgumentException; +use Symfony\Component\Serializer\Mapping\AttributeMetadata; use Symfony\Component\Serializer\Mapping\ClassMetadata; use Symfony\Component\Serializer\Mapping\Loader\LoaderInterface; @@ -27,23 +30,33 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface * @var LoaderInterface */ private $loader; + /** * @var Cache */ private $cache; + /** - * @var array + * @var PropertyInfoExtractorInterface */ - private $loadedClasses; + private $propertyTypeExtractor; + + /** + * @var PropertyListExtractorInterface + */ + private $propertyListExtractor; /** - * @param LoaderInterface $loader - * @param Cache|null $cache + * @var array */ - public function __construct(LoaderInterface $loader, Cache $cache = null) + private $loadedClasses; + + public function __construct(LoaderInterface $loader = null, Cache $cache = null, PropertyTypeExtractorInterface $propertyTypeExtractor = null, PropertyListExtractorInterface $propertyListExtractor = null) { $this->loader = $loader; $this->cache = $cache; + $this->propertyTypeExtractor = $propertyTypeExtractor; + $this->propertyListExtractor = $propertyListExtractor; } /** @@ -69,7 +82,9 @@ public function getMetadataFor($value) } $classMetadata = new ClassMetadata($class); - $this->loader->loadClassMetadata($classMetadata); + if ($this->loader) { + $this->loader->loadClassMetadata($classMetadata); + } $reflectionClass = $classMetadata->getReflectionClass(); @@ -83,6 +98,34 @@ public function getMetadataFor($value) $classMetadata->merge($this->getMetadataFor($interface->name)); } + $attributeNames = array(); + + // Populate types of existing metadata + foreach ($classMetadata->getAttributesMetadata() as $attributeMetadata) { + $attributeName = $attributeMetadata->getName(); + $attributeNames[$attributeName] = true; + + if ($this->propertyTypeExtractor) { + $attributeMetadata->setTypes($this->propertyTypeExtractor->getTypes($class, $attributeName)); + } + } + + if ($this->propertyListExtractor) { + // Populate types for not existing metadata + foreach ($this->propertyListExtractor->getProperties($class) as $attributeName) { + if (isset($attributeNames[$attributeName])) { + continue; + } + + $attributeMetadata = new AttributeMetadata($attributeName); + if ($this->propertyTypeExtractor) { + $attributeMetadata->setTypes($this->propertyTypeExtractor->getTypes($class, $attributeName)); + } + + $classMetadata->addAttributeMetadata($attributeMetadata); + } + } + if ($this->cache) { $this->cache->save($class, $classMetadata); } diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/TypeDummy.php b/src/Symfony/Component/Serializer/Tests/Fixtures/TypeDummy.php new file mode 100644 index 0000000000000..6a512a78229bf --- /dev/null +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/TypeDummy.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Tests\Fixtures; + +/** + * @author Kévin Dunglas + */ +class TypeDummy +{ + /** + * @var string + */ + public $foo; + /** + * @var TypeDummy + */ + public $bar; +} diff --git a/src/Symfony/Component/Serializer/Tests/Mapping/AttributeMetadataTest.php b/src/Symfony/Component/Serializer/Tests/Mapping/AttributeMetadataTest.php index 4a32831cb698d..25ddd5e29f7f7 100644 --- a/src/Symfony/Component/Serializer/Tests/Mapping/AttributeMetadataTest.php +++ b/src/Symfony/Component/Serializer/Tests/Mapping/AttributeMetadataTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Serializer\Tests\Mapping; +use Symfony\Component\PropertyInfo\Type; use Symfony\Component\Serializer\Mapping\AttributeMetadata; /** @@ -33,6 +34,8 @@ public function testGetName() public function testGroups() { $attributeMetadata = new AttributeMetadata('group'); + $this->assertEquals(array(), $attributeMetadata->getGroups()); + $attributeMetadata->addGroup('a'); $attributeMetadata->addGroup('a'); $attributeMetadata->addGroup('b'); @@ -40,7 +43,17 @@ public function testGroups() $this->assertEquals(array('a', 'b'), $attributeMetadata->getGroups()); } - public function testMerge() + public function testTypes() + { + $attributeMetadata = new AttributeMetadata('type'); + $this->assertNull($attributeMetadata->getTypes()); + + $attributeMetadata->setTypes(array(new Type(Type::BUILTIN_TYPE_STRING))); + + $this->assertEquals(array(new Type(Type::BUILTIN_TYPE_STRING)), $attributeMetadata->getTypes()); + } + + public function testMergeGroups() { $attributeMetadata1 = new AttributeMetadata('a1'); $attributeMetadata1->addGroup('a'); @@ -61,6 +74,8 @@ public function testSerialize() $attributeMetadata->addGroup('a'); $attributeMetadata->addGroup('b'); + $attributeMetadata->setTypes(array(new Type(Type::BUILTIN_TYPE_INT))); + $serialized = serialize($attributeMetadata); $this->assertEquals($attributeMetadata, unserialize($serialized)); } diff --git a/src/Symfony/Component/Serializer/Tests/Mapping/Factory/ClassMetadataFactoryTest.php b/src/Symfony/Component/Serializer/Tests/Mapping/Factory/ClassMetadataFactoryTest.php index 2e2ba22dcee0b..7631d54e630b7 100644 --- a/src/Symfony/Component/Serializer/Tests/Mapping/Factory/ClassMetadataFactoryTest.php +++ b/src/Symfony/Component/Serializer/Tests/Mapping/Factory/ClassMetadataFactoryTest.php @@ -12,6 +12,12 @@ namespace Symfony\Component\Serializer\Tests\Mapping\Factory; use Doctrine\Common\Annotations\AnnotationReader; +use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor; +use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor; +use Symfony\Component\PropertyInfo\PropertyInfoExtractor; +use Symfony\Component\PropertyInfo\Type; +use Symfony\Component\Serializer\Mapping\AttributeMetadata; +use Symfony\Component\Serializer\Mapping\ClassMetadata; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory; use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader; use Symfony\Component\Serializer\Mapping\Loader\LoaderChain; @@ -75,4 +81,22 @@ public function testCacheNotExists() $this->assertEquals(TestClassMetadataFactory::createClassMetadata(true, true), $metadata); } + + public function testExtractTypes() + { + $factory = new ClassMetadataFactory(null, null, new PhpDocExtractor(), new ReflectionExtractor()); + + $expectedClassMetadata = new ClassMetadata('Symfony\Component\Serializer\Tests\Fixtures\TypeDummy'); + $expectedClassMetadata->getReflectionClass(); + + $foo = new AttributeMetadata('foo'); + $foo->setTypes(array(new Type('string'))); + $expectedClassMetadata->addAttributeMetadata($foo); + + $bar = new AttributeMetadata('bar'); + $bar->setTypes(array(new Type('object', false, 'Symfony\Component\Serializer\Tests\Fixtures\TypeDummy'))); + $expectedClassMetadata->addAttributeMetadata($bar); + + $this->assertEquals($expectedClassMetadata, $factory->getMetadataFor('Symfony\Component\Serializer\Tests\Fixtures\TypeDummy')); + } } diff --git a/src/Symfony/Component/Serializer/composer.json b/src/Symfony/Component/Serializer/composer.json index 4978ebace4cd5..f516525d34ad2 100644 --- a/src/Symfony/Component/Serializer/composer.json +++ b/src/Symfony/Component/Serializer/composer.json @@ -22,15 +22,18 @@ "symfony/yaml": "~2.8|~3.0", "symfony/config": "~2.8|~3.0", "symfony/property-access": "~2.8|~3.0", + "symfony/property-info": "~2.8|3.0", "doctrine/annotations": "~1.0", - "doctrine/cache": "~1.0" + "doctrine/cache": "~1.0", + "phpdocumentor/reflection": "^1.0.7" }, "suggest": { "doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.", "doctrine/cache": "For using the default cached annotation reader and metadata cache.", "symfony/yaml": "For using the default YAML mapping loader.", "symfony/config": "For using the XML mapping loader.", - "symfony/property-access": "For using the ObjectNormalizer." + "symfony/property-access": "For using the ObjectNormalizer.", + "symfony/property-info": "For using the ObjectNormalizer." }, "autoload": { "psr-4": { "Symfony\\Component\\Serializer\\": "" }, From 97583d90a72d21a217f1c0534bf96d760247c3a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Tue, 8 Dec 2015 00:07:10 +0100 Subject: [PATCH 2/3] Fix CS --- .../Tests/Mapping/Factory/ClassMetadataFactoryTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Symfony/Component/Serializer/Tests/Mapping/Factory/ClassMetadataFactoryTest.php b/src/Symfony/Component/Serializer/Tests/Mapping/Factory/ClassMetadataFactoryTest.php index 7631d54e630b7..ca45a4329ad25 100644 --- a/src/Symfony/Component/Serializer/Tests/Mapping/Factory/ClassMetadataFactoryTest.php +++ b/src/Symfony/Component/Serializer/Tests/Mapping/Factory/ClassMetadataFactoryTest.php @@ -14,7 +14,6 @@ use Doctrine\Common\Annotations\AnnotationReader; use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor; use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor; -use Symfony\Component\PropertyInfo\PropertyInfoExtractor; use Symfony\Component\PropertyInfo\Type; use Symfony\Component\Serializer\Mapping\AttributeMetadata; use Symfony\Component\Serializer\Mapping\ClassMetadata; From 1290aa0f19b12db4be17689f650c0ffbd8104f89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Tue, 8 Dec 2015 22:37:04 +0100 Subject: [PATCH 3/3] [FrameworkBundle] PropertyInfo support in Serializer --- .../Bundle/FrameworkBundle/Resources/config/serializer.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml index d514a3666faab..e6388708905b1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml @@ -34,7 +34,8 @@ - null + null + pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy