From 355f48c7a0583f3430710008edae5b8c00e9ef53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Tue, 19 Jan 2016 14:55:39 +0100 Subject: [PATCH 1/4] [Serializer] Add a PSR-6 adapter --- .../Factory/CacheClassMetadataFactory.php | 68 +++++++++++++++++++ .../Mapping/Factory/ClassMetadataFactory.php | 35 ++++------ .../Mapping/Factory/ClassResolverTrait.php | 48 +++++++++++++ .../Factory/CacheMetadataFactoryTest.php | 65 ++++++++++++++++++ .../Factory/ClassMetadataFactoryTest.php | 18 ++--- .../Component/Serializer/composer.json | 8 ++- 6 files changed, 207 insertions(+), 35 deletions(-) create mode 100644 src/Symfony/Component/Serializer/Mapping/Factory/CacheClassMetadataFactory.php create mode 100644 src/Symfony/Component/Serializer/Mapping/Factory/ClassResolverTrait.php create mode 100644 src/Symfony/Component/Serializer/Tests/Mapping/Factory/CacheMetadataFactoryTest.php diff --git a/src/Symfony/Component/Serializer/Mapping/Factory/CacheClassMetadataFactory.php b/src/Symfony/Component/Serializer/Mapping/Factory/CacheClassMetadataFactory.php new file mode 100644 index 0000000000000..0b904c14400d0 --- /dev/null +++ b/src/Symfony/Component/Serializer/Mapping/Factory/CacheClassMetadataFactory.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Mapping\Factory; + +use Psr\Cache\CacheItemPoolInterface; + +/** + * Caches metadata using a PSR-6 implementation. + * + * @author Kévin Dunglas + */ +class CacheClassMetadataFactory implements ClassMetadataFactoryInterface +{ + use ClassResolverTrait; + + /** + * @var ClassMetadataFactoryInterface + */ + private $decorated; + + /** + * @var CacheItemPoolInterface + */ + private $cacheItemPool; + + public function __construct(ClassMetadataFactoryInterface $decorated, CacheItemPoolInterface $cacheItemPool) + { + $this->decorated = $decorated; + $this->cacheItemPool = $cacheItemPool; + } + + /** + * {@inheritdoc} + */ + public function getMetadataFor($value) + { + $class = $this->getClass($value); + // Key cannot contain backslashes according to PSR-6 + $key = strtr($class, '\\', '_'); + + $item = $this->cacheItemPool->getItem($key); + if ($item->isHit()) { + return $item->get(); + } + + $metadata = $this->decorated->getMetadataFor($value); + $this->cacheItemPool->save($item->set($metadata)); + + return $metadata; + } + + /** + * {@inheritdoc} + */ + public function hasMetadataFor($value) + { + return $this->decorated->hasMetadataFor($value); + } +} diff --git a/src/Symfony/Component/Serializer/Mapping/Factory/ClassMetadataFactory.php b/src/Symfony/Component/Serializer/Mapping/Factory/ClassMetadataFactory.php index 3a354e354e9e3..bd39a97f3839d 100644 --- a/src/Symfony/Component/Serializer/Mapping/Factory/ClassMetadataFactory.php +++ b/src/Symfony/Component/Serializer/Mapping/Factory/ClassMetadataFactory.php @@ -23,6 +23,8 @@ */ class ClassMetadataFactory implements ClassMetadataFactoryInterface { + use ClassResolverTrait; + /** * @var LoaderInterface */ @@ -44,6 +46,10 @@ public function __construct(LoaderInterface $loader, Cache $cache = null) { $this->loader = $loader; $this->cache = $cache; + + if (null !== $cache) { + @trigger_error('Passing a Doctrine Cache instance as 2nd parameter of the "Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface" is deprecated. This parameter will be removed in Symfony 4.0. Use the "Symfony\Component\Serializer\Mapping\Factory\CacheMetadataFactory" class instead.', E_USER_DEPRECATED); + } } /** @@ -52,9 +58,6 @@ public function __construct(LoaderInterface $loader, Cache $cache = null) public function getMetadataFor($value) { $class = $this->getClass($value); - if (!$class) { - throw new InvalidArgumentException(sprintf('Cannot create metadata for non-objects. Got: "%s"', gettype($value))); - } if (isset($this->loadedClasses[$class])) { return $this->loadedClasses[$class]; @@ -64,10 +67,6 @@ public function getMetadataFor($value) return $this->loadedClasses[$class]; } - if (!class_exists($class) && !interface_exists($class)) { - throw new InvalidArgumentException(sprintf('The class or interface "%s" does not exist.', $class)); - } - $classMetadata = new ClassMetadata($class); $this->loader->loadClassMetadata($classMetadata); @@ -95,24 +94,14 @@ public function getMetadataFor($value) */ public function hasMetadataFor($value) { - $class = $this->getClass($value); - - return class_exists($class) || interface_exists($class); - } + try { + $this->getClass($value); - /** - * Gets a class name for a given class or instance. - * - * @param mixed $value - * - * @return string|bool - */ - private function getClass($value) - { - if (!is_object($value) && !is_string($value)) { - return false; + return true; + } catch (InvalidArgumentException $invalidArgumentException) { + // Return false in case of exception } - return ltrim(is_object($value) ? get_class($value) : $value, '\\'); + return false; } } diff --git a/src/Symfony/Component/Serializer/Mapping/Factory/ClassResolverTrait.php b/src/Symfony/Component/Serializer/Mapping/Factory/ClassResolverTrait.php new file mode 100644 index 0000000000000..0a2604190f5b3 --- /dev/null +++ b/src/Symfony/Component/Serializer/Mapping/Factory/ClassResolverTrait.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Mapping\Factory; + +use Symfony\Component\Serializer\Exception\InvalidArgumentException; + +/** + * Resolves a class name. + * + * @author Kévin Dunglas + */ +trait ClassResolverTrait +{ + /** + * Gets a class name for a given class or instance. + * + * @param mixed $value + * + * @return string + * + * @throws InvalidArgumentException If the class does not exists + */ + private function getClass($value) + { + if (is_string($value)) { + if (!class_exists($value) && !interface_exists($value)) { + throw new InvalidArgumentException(sprintf('The class or interface "%s" does not exist.', $value)); + } + + return ltrim($value, '\\'); + } + + if (!is_object($value)) { + throw new InvalidArgumentException(sprintf('Cannot create metadata for non-objects. Got: "%s"', gettype($value))); + } + + return get_class($value); + } +} diff --git a/src/Symfony/Component/Serializer/Tests/Mapping/Factory/CacheMetadataFactoryTest.php b/src/Symfony/Component/Serializer/Tests/Mapping/Factory/CacheMetadataFactoryTest.php new file mode 100644 index 0000000000000..a42003f358906 --- /dev/null +++ b/src/Symfony/Component/Serializer/Tests/Mapping/Factory/CacheMetadataFactoryTest.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Tests\Mapping\Factory; + +use Symfony\Component\Cache\Adapter\ArrayAdapter; +use Symfony\Component\Serializer\Mapping\ClassMetadata; +use Symfony\Component\Serializer\Mapping\Factory\CacheClassMetadataFactory; + +/** + * @author Kévin Dunglas + */ +class CacheMetadataFactoryTest extends \PHPUnit_Framework_TestCase +{ + public function testGetMetadataFor() + { + $metadata = new ClassMetadata('Symfony\Component\Serializer\Tests\Fixtures\Dummy'); + + $decorated = $this->getMock('Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface'); + $decorated + ->expects($this->once()) + ->method('getMetadataFor') + ->will($this->returnValue($metadata)) + ; + + $factory = new CacheClassMetadataFactory($decorated, new ArrayAdapter()); + + $this->assertEquals($metadata, $factory->getMetadataFor('Symfony\Component\Serializer\Tests\Fixtures\Dummy')); + // The second call should retrieve the value from the cache + $this->assertEquals($metadata, $factory->getMetadataFor('Symfony\Component\Serializer\Tests\Fixtures\Dummy')); + } + + public function testHasMetadataFor() + { + $decorated = $this->getMock('Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface'); + $decorated + ->expects($this->once()) + ->method('hasMetadataFor') + ->will($this->returnValue(true)) + ; + + $factory = new CacheClassMetadataFactory($decorated, new ArrayAdapter()); + + $this->assertTrue($factory->hasMetadataFor('Symfony\Component\Serializer\Tests\Fixtures\Dummy')); + } + + /** + * @expectedException \Symfony\Component\Serializer\Exception\InvalidArgumentException + */ + public function testInvalidClassThrowsException() + { + $decorated = $this->getMock('Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface'); + $factory = new CacheClassMetadataFactory($decorated, new ArrayAdapter()); + + $factory->getMetadataFor('Not\Exist'); + } +} diff --git a/src/Symfony/Component/Serializer/Tests/Mapping/Factory/ClassMetadataFactoryTest.php b/src/Symfony/Component/Serializer/Tests/Mapping/Factory/ClassMetadataFactoryTest.php index 2e2ba22dcee0b..a237c32313b12 100644 --- a/src/Symfony/Component/Serializer/Tests/Mapping/Factory/ClassMetadataFactoryTest.php +++ b/src/Symfony/Component/Serializer/Tests/Mapping/Factory/ClassMetadataFactoryTest.php @@ -25,7 +25,7 @@ class ClassMetadataFactoryTest extends \PHPUnit_Framework_TestCase public function testInterface() { $classMetadata = new ClassMetadataFactory(new LoaderChain(array())); - $this->assertInstanceOf('Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory', $classMetadata); + $this->assertInstanceOf('Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface', $classMetadata); } public function testGetMetadataFor() @@ -45,6 +45,9 @@ public function testHasMetadataFor() $this->assertFalse($factory->hasMetadataFor('Dunglas\Entity')); } + /** + * @group legacy + */ public function testCacheExists() { $cache = $this->getMock('Doctrine\Common\Cache\Cache'); @@ -58,17 +61,14 @@ public function testCacheExists() $this->assertEquals('foo', $factory->getMetadataFor('Symfony\Component\Serializer\Tests\Fixtures\GroupDummy')); } + /** + * @group legacy + */ public function testCacheNotExists() { $cache = $this->getMock('Doctrine\Common\Cache\Cache'); - $cache - ->method('fetch') - ->will($this->returnValue(false)) - ; - - $cache - ->method('save') - ; + $cache->method('fetch')->will($this->returnValue(false)); + $cache->method('save'); $factory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()), $cache); $metadata = $factory->getMetadataFor('Symfony\Component\Serializer\Tests\Fixtures\GroupDummy'); diff --git a/src/Symfony/Component/Serializer/composer.json b/src/Symfony/Component/Serializer/composer.json index acec92f24eb21..dae7a5bd3444e 100644 --- a/src/Symfony/Component/Serializer/composer.json +++ b/src/Symfony/Component/Serializer/composer.json @@ -23,16 +23,18 @@ "symfony/config": "~2.8|~3.0", "symfony/property-access": "~2.8|~3.0", "symfony/http-foundation": "~2.8|~3.0", + "symfony/cache": "~3.1", "doctrine/annotations": "~1.0", "doctrine/cache": "~1.0" }, "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/cache": "For using the 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/http-foundation": "To use the DataUriNormalizer." + "symfony/http-foundation": "To use the DataUriNormalizer.", + "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." }, "autoload": { "psr-4": { "Symfony\\Component\\Serializer\\": "" }, From e368b4cd5709a3f2c9d55a9dbd64de454d12da0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Tue, 26 Jan 2016 12:32:13 +0100 Subject: [PATCH 2/4] Fix error message --- .../Serializer/Mapping/Factory/ClassMetadataFactory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Serializer/Mapping/Factory/ClassMetadataFactory.php b/src/Symfony/Component/Serializer/Mapping/Factory/ClassMetadataFactory.php index bd39a97f3839d..00e214fe03d89 100644 --- a/src/Symfony/Component/Serializer/Mapping/Factory/ClassMetadataFactory.php +++ b/src/Symfony/Component/Serializer/Mapping/Factory/ClassMetadataFactory.php @@ -48,7 +48,7 @@ public function __construct(LoaderInterface $loader, Cache $cache = null) $this->cache = $cache; if (null !== $cache) { - @trigger_error('Passing a Doctrine Cache instance as 2nd parameter of the "Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface" is deprecated. This parameter will be removed in Symfony 4.0. Use the "Symfony\Component\Serializer\Mapping\Factory\CacheMetadataFactory" class instead.', E_USER_DEPRECATED); + @trigger_error(sprintf('Passing a Doctrine Cache instance as 2nd parameter of the "%s" constructor is deprecated. This parameter will be removed in Symfony 4.0. Use the "%s" class instead.', __CLASS__, CacheClassMetadataFactory::class), E_USER_DEPRECATED); } } From 57cbfa365c570f18db69661e0fe6a63648782069 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Tue, 26 Jan 2016 12:33:24 +0100 Subject: [PATCH 3/4] Mark the trait as internal --- .../Component/Serializer/Mapping/Factory/ClassResolverTrait.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Symfony/Component/Serializer/Mapping/Factory/ClassResolverTrait.php b/src/Symfony/Component/Serializer/Mapping/Factory/ClassResolverTrait.php index 0a2604190f5b3..e93277a6be765 100644 --- a/src/Symfony/Component/Serializer/Mapping/Factory/ClassResolverTrait.php +++ b/src/Symfony/Component/Serializer/Mapping/Factory/ClassResolverTrait.php @@ -16,6 +16,8 @@ /** * Resolves a class name. * + * @internal + * * @author Kévin Dunglas */ trait ClassResolverTrait From c98f17ab2c8aaaa84739569ed15a3768ab1011bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Tue, 26 Jan 2016 17:53:20 +0100 Subject: [PATCH 4/4] Suggest psr/cache-implementation --- src/Symfony/Component/Serializer/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Serializer/composer.json b/src/Symfony/Component/Serializer/composer.json index dae7a5bd3444e..f17da4d2aafc0 100644 --- a/src/Symfony/Component/Serializer/composer.json +++ b/src/Symfony/Component/Serializer/composer.json @@ -28,7 +28,7 @@ "doctrine/cache": "~1.0" }, "suggest": { - "symfony/cache": "For using the metadata cache.", + "psr/cache-implementation": "For using the 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.", 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