From c0e70a756ce639928598b8556bdcb3e0e076c93a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Fri, 4 Dec 2015 23:03:03 +0100 Subject: [PATCH] [PropertyAccess] Add Doctrine Cache --- .../PropertyAccess/PropertyAccessor.php | 24 ++++++++++++-- .../PropertyAccessorBuilder.php | 33 ++++++++++++++++++- .../Tests/PropertyAccessorBuilderTest.php | 9 +++++ .../Tests/PropertyAccessorTest.php | 13 ++++++++ .../Component/PropertyAccess/composer.json | 6 ++++ 5 files changed, 81 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index 008f55001f20e..54c0d7d2131c0 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -11,6 +11,7 @@ namespace Symfony\Component\PropertyAccess; +use Doctrine\Common\Cache\Cache; use Symfony\Component\PropertyAccess\Exception\AccessException; use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException; use Symfony\Component\PropertyAccess\Exception\NoSuchIndexException; @@ -38,6 +39,9 @@ class PropertyAccessor implements PropertyAccessorInterface const ACCESS_TYPE_MAGIC = 2; const ACCESS_TYPE_ADDER_AND_REMOVER = 3; const ACCESS_TYPE_NOT_FOUND = 4; + const CACHE_PREFIX_PROPERTY_PATH = 'pp'; + const CACHE_PREFIX_READ = 'r'; + const CACHE_PREFIX_WRITE = 'w'; /** * @var bool @@ -49,6 +53,11 @@ class PropertyAccessor implements PropertyAccessorInterface */ private $ignoreInvalidIndices; + /** + * @var Cache + */ + private $cache; + /** * @var array */ @@ -63,10 +72,11 @@ class PropertyAccessor implements PropertyAccessorInterface * Should not be used by application code. Use * {@link PropertyAccess::createPropertyAccessor()} instead. */ - public function __construct($magicCall = false, $throwExceptionOnInvalidIndex = false) + public function __construct($magicCall = false, $throwExceptionOnInvalidIndex = false, Cache $cache = null) { $this->magicCall = $magicCall; $this->ignoreInvalidIndices = !$throwExceptionOnInvalidIndex; + $this->cache = $cache; } /** @@ -401,7 +411,7 @@ private function getReadAccessInfo($object, $property) if (isset($this->readPropertyCache[$key])) { $access = $this->readPropertyCache[$key]; - } else { + } elseif (!$this->cache || !$access = $this->cache->fetch(self::CACHE_PREFIX_READ.$key)) { $access = array(); $reflClass = new \ReflectionClass($object); @@ -456,6 +466,10 @@ private function getReadAccessInfo($object, $property) ); } + if ($this->cache) { + $this->cache->save(self::CACHE_PREFIX_READ.$key, $access); + } + $this->readPropertyCache[$key] = $access; } @@ -583,7 +597,7 @@ private function getWriteAccessInfo($object, $property, $value) if (isset($this->writePropertyCache[$key])) { $access = $this->writePropertyCache[$key]; - } else { + } elseif (!$this->cache || !$access = $this->cache->fetch(self::CACHE_PREFIX_WRITE.$key)) { $access = array(); $reflClass = new \ReflectionClass($object); @@ -645,6 +659,10 @@ private function getWriteAccessInfo($object, $property, $value) } } + if ($this->cache) { + $this->cache->save(self::CACHE_PREFIX_WRITE.$key, $access); + } + $this->writePropertyCache[$key] = $access; } diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessorBuilder.php b/src/Symfony/Component/PropertyAccess/PropertyAccessorBuilder.php index fc8ac4ed2dd4f..664c553a197fe 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessorBuilder.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessorBuilder.php @@ -11,6 +11,8 @@ namespace Symfony\Component\PropertyAccess; +use Doctrine\Common\Cache\Cache; + /** * A configurable builder to create a PropertyAccessor. * @@ -28,6 +30,11 @@ class PropertyAccessorBuilder */ private $throwExceptionOnInvalidIndex = false; + /** + * @var Cache|null + */ + private $cache; + /** * Enables the use of "__call" by the PropertyAccessor. * @@ -97,6 +104,30 @@ public function isExceptionOnInvalidIndexEnabled() return $this->throwExceptionOnInvalidIndex; } + /** + * Uses a cache system. + * + * @param Cache|null $cache + * + * @return PropertyAccessorBuilder The builder object + */ + public function useCache(Cache $cache = null) + { + $this->cache = $cache; + + return $this; + } + + /** + * Gets the cache system. + * + * @return Cache|null + */ + public function getCache() + { + return $this->cache; + } + /** * Builds and returns a new PropertyAccessor object. * @@ -104,6 +135,6 @@ public function isExceptionOnInvalidIndexEnabled() */ public function getPropertyAccessor() { - return new PropertyAccessor($this->magicCall, $this->throwExceptionOnInvalidIndex); + return new PropertyAccessor($this->magicCall, $this->throwExceptionOnInvalidIndex, $this->cache); } } diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorBuilderTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorBuilderTest.php index 951c6802f93b7..6957857a71748 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorBuilderTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorBuilderTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\PropertyAccess\Tests; +use Doctrine\Common\Cache\ArrayCache; use Symfony\Component\PropertyAccess\PropertyAccessorBuilder; class PropertyAccessorBuilderTest extends \PHPUnit_Framework_TestCase @@ -52,4 +53,12 @@ public function testGetPropertyAccessor() $this->assertInstanceOf('Symfony\Component\PropertyAccess\PropertyAccessor', $this->builder->getPropertyAccessor()); $this->assertInstanceOf('Symfony\Component\PropertyAccess\PropertyAccessor', $this->builder->enableMagicCall()->getPropertyAccessor()); } + + public function testUseCache() + { + $cache = new ArrayCache(); + $this->builder->useCache($cache); + $this->assertEquals($cache, $this->builder->getCache()); + $this->assertInstanceOf('Symfony\Component\PropertyAccess\PropertyAccessor', $this->builder->getPropertyAccessor()); + } } diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php index ce4438550e8d3..501a8034912d5 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\PropertyAccess\Tests; +use Doctrine\Common\Cache\ArrayCache; +use Doctrine\Common\Cache\Cache; use Symfony\Component\PropertyAccess\Exception\NoSuchIndexException; use Symfony\Component\PropertyAccess\PropertyAccessor; use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClass; @@ -510,4 +512,15 @@ public function testIsWritableForReferenceChainIssue($object, $path, $value) { $this->assertEquals($value, $this->propertyAccessor->isWritable($object, $path)); } + + public function testCacheReadAccess() + { + $obj = new TestClass('foo'); + + $propertyAccessor = new PropertyAccessor(false, false, new ArrayCache()); + $this->assertEquals('foo', $propertyAccessor->getValue($obj, 'publicAccessor')); + $propertyAccessor->setValue($obj, 'publicAccessor', 'bar'); + $propertyAccessor->setValue($obj, 'publicAccessor', 'baz'); + $this->assertEquals('baz', $propertyAccessor->getValue($obj, 'publicAccessor')); + } } diff --git a/src/Symfony/Component/PropertyAccess/composer.json b/src/Symfony/Component/PropertyAccess/composer.json index fc657c1d21f9f..48c17a05ef6e4 100644 --- a/src/Symfony/Component/PropertyAccess/composer.json +++ b/src/Symfony/Component/PropertyAccess/composer.json @@ -18,6 +18,12 @@ "require": { "php": ">=5.5.9" }, + "require-dev": { + "doctrine/cache": "~1.0" + }, + "suggest": { + "doctrine/cache": "To cache access methods" + }, "autoload": { "psr-4": { "Symfony\\Component\\PropertyAccess\\": "" }, "exclude-from-classmap": [