From 05d9476014a2cea95e43740bbc279c25c7d2b741 Mon Sep 17 00:00:00 2001 From: Michael Moravec Date: Mon, 25 Feb 2019 15:46:03 +0100 Subject: [PATCH] Drop CachedReader --- UPGRADE.md | 4 + composer.json | 1 - lib/Doctrine/Annotations/CachedReader.php | 245 ------------------ ...CachedReadPerformanceWithInMemoryBench.php | 38 --- .../Tests/Annotations/CachedReaderTest.php | 162 ------------ 5 files changed, 4 insertions(+), 446 deletions(-) delete mode 100644 lib/Doctrine/Annotations/CachedReader.php delete mode 100644 tests/Doctrine/Performance/Annotations/CachedReadPerformanceWithInMemoryBench.php delete mode 100644 tests/Doctrine/Tests/Annotations/CachedReaderTest.php diff --git a/UPGRADE.md b/UPGRADE.md index 3ec9c1380..4b7d6253f 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -33,6 +33,10 @@ Please use `Doctrine\Annotations\AnnotationReader` instead. `Doctrine\Common\Annotations\AnnotationRegistry` has been dropped. Annotations now rely purely on autoloading, no explicit registration is needed anymore. +## Doctrine\Common\Annotations\CachedReader removed + +`Doctrine\Common\Annotations\CachedReader` has been removed as caching annotations themselves is marginally useful. Please cache the resulting structures constructed from annotations instead. + ## Doctrine\Common\Annotations\FileCacheReader removed `Doctrine\Common\Annotations\FileCacheReader` has been removed. Please use Doctrine Cache adapter instead. diff --git a/composer.json b/composer.json index 618cc26e8..232e63c37 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,6 @@ "doctrine/lexer": "1.*" }, "require-dev": { - "doctrine/cache": "1.*", "doctrine/coding-standard": "^4.0", "phpunit/phpunit": "^7.0" }, diff --git a/lib/Doctrine/Annotations/CachedReader.php b/lib/Doctrine/Annotations/CachedReader.php deleted file mode 100644 index 831ffda6e..000000000 --- a/lib/Doctrine/Annotations/CachedReader.php +++ /dev/null @@ -1,245 +0,0 @@ - - * @author Benjamin Eberlei - */ -final class CachedReader implements Reader -{ - /** - * @var Reader - */ - private $delegate; - - /** - * @var Cache - */ - private $cache; - - /** - * @var boolean - */ - private $debug; - - /** - * @var array - */ - private $loadedAnnotations = []; - - /** - * Constructor. - * - * @param Reader $reader - * @param Cache $cache - * @param bool $debug - */ - public function __construct(Reader $reader, Cache $cache, $debug = false) - { - $this->delegate = $reader; - $this->cache = $cache; - $this->debug = (boolean) $debug; - } - - /** - * {@inheritDoc} - */ - public function getClassAnnotations(ReflectionClass $class) - { - $cacheKey = $class->getName(); - - if (isset($this->loadedAnnotations[$cacheKey])) { - return $this->loadedAnnotations[$cacheKey]; - } - - if (false === ($annots = $this->fetchFromCache($cacheKey, $class))) { - $annots = $this->delegate->getClassAnnotations($class); - $this->saveToCache($cacheKey, $annots); - } - - return $this->loadedAnnotations[$cacheKey] = $annots; - } - - /** - * {@inheritDoc} - */ - public function getClassAnnotation(ReflectionClass $class, $annotationName) - { - foreach ($this->getClassAnnotations($class) as $annot) { - if ($annot instanceof $annotationName) { - return $annot; - } - } - - return null; - } - - /** - * {@inheritDoc} - */ - public function getPropertyAnnotations(\ReflectionProperty $property) - { - $class = $property->getDeclaringClass(); - $cacheKey = $class->getName().'$'.$property->getName(); - - if (isset($this->loadedAnnotations[$cacheKey])) { - return $this->loadedAnnotations[$cacheKey]; - } - - if (false === ($annots = $this->fetchFromCache($cacheKey, $class))) { - $annots = $this->delegate->getPropertyAnnotations($property); - $this->saveToCache($cacheKey, $annots); - } - - return $this->loadedAnnotations[$cacheKey] = $annots; - } - - /** - * {@inheritDoc} - */ - public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName) - { - foreach ($this->getPropertyAnnotations($property) as $annot) { - if ($annot instanceof $annotationName) { - return $annot; - } - } - - return null; - } - - /** - * {@inheritDoc} - */ - public function getMethodAnnotations(\ReflectionMethod $method) - { - $class = $method->getDeclaringClass(); - $cacheKey = $class->getName().'#'.$method->getName(); - - if (isset($this->loadedAnnotations[$cacheKey])) { - return $this->loadedAnnotations[$cacheKey]; - } - - if (false === ($annots = $this->fetchFromCache($cacheKey, $class))) { - $annots = $this->delegate->getMethodAnnotations($method); - $this->saveToCache($cacheKey, $annots); - } - - return $this->loadedAnnotations[$cacheKey] = $annots; - } - - /** - * {@inheritDoc} - */ - public function getMethodAnnotation(\ReflectionMethod $method, $annotationName) - { - foreach ($this->getMethodAnnotations($method) as $annot) { - if ($annot instanceof $annotationName) { - return $annot; - } - } - - return null; - } - - /** - * Clears loaded annotations. - * - * @return void - */ - public function clearLoadedAnnotations() - { - $this->loadedAnnotations = []; - } - - /** - * Fetches a value from the cache. - * - * @param string $cacheKey The cache key. - * @param ReflectionClass $class The related class. - * - * @return mixed The cached value or false when the value is not in cache. - */ - private function fetchFromCache($cacheKey, ReflectionClass $class) - { - if (($data = $this->cache->fetch($cacheKey)) !== false) { - if (!$this->debug || $this->isCacheFresh($cacheKey, $class)) { - return $data; - } - } - - return false; - } - - /** - * Saves a value to the cache. - * - * @param string $cacheKey The cache key. - * @param mixed $value The value. - * - * @return void - */ - private function saveToCache($cacheKey, $value) - { - $this->cache->save($cacheKey, $value); - if ($this->debug) { - $this->cache->save('[C]'.$cacheKey, time()); - } - } - - /** - * Checks if the cache is fresh. - * - * @param string $cacheKey - * @param ReflectionClass $class - * - * @return boolean - */ - private function isCacheFresh($cacheKey, ReflectionClass $class) - { - if (null === $lastModification = $this->getLastModification($class)) { - return true; - } - - return $this->cache->fetch('[C]'.$cacheKey) >= $lastModification; - } - - /** - * Returns the time the class was last modified, testing traits and parents - * - * @param ReflectionClass $class - * @return int - */ - private function getLastModification(ReflectionClass $class) - { - $filename = $class->getFileName(); - $parent = $class->getParentClass(); - - return max(array_merge( - [$filename ? filemtime($filename) : 0], - array_map([$this, 'getTraitLastModificationTime'], $class->getTraits()), - array_map([$this, 'getLastModification'], $class->getInterfaces()), - $parent ? [$this->getLastModification($parent)] : [] - )); - } - - /** - * @param ReflectionClass $reflectionTrait - * @return int - */ - private function getTraitLastModificationTime(ReflectionClass $reflectionTrait) - { - $fileName = $reflectionTrait->getFileName(); - - return max(array_merge( - [$fileName ? filemtime($fileName) : 0], - array_map([$this, 'getTraitLastModificationTime'], $reflectionTrait->getTraits()) - )); - } -} diff --git a/tests/Doctrine/Performance/Annotations/CachedReadPerformanceWithInMemoryBench.php b/tests/Doctrine/Performance/Annotations/CachedReadPerformanceWithInMemoryBench.php deleted file mode 100644 index 8bdd5d95f..000000000 --- a/tests/Doctrine/Performance/Annotations/CachedReadPerformanceWithInMemoryBench.php +++ /dev/null @@ -1,38 +0,0 @@ -reader = new CachedReader(new AnnotationReader(), new ArrayCache()); - $this->method = new ReflectionMethod(Controller::class, 'helloAction'); - } - - /** - * @Revs(500) - * @Iterations(5) - */ - public function bench() : void - { - $this->reader->getMethodAnnotations($this->method); - } -} diff --git a/tests/Doctrine/Tests/Annotations/CachedReaderTest.php b/tests/Doctrine/Tests/Annotations/CachedReaderTest.php deleted file mode 100644 index bc98deb0a..000000000 --- a/tests/Doctrine/Tests/Annotations/CachedReaderTest.php +++ /dev/null @@ -1,162 +0,0 @@ -doTestCacheStale(Fixtures\Controller::class, $cache); - } - - /** - * @group 62 - */ - public function testIgnoresStaleCacheWithParentClass() - { - $cache = time() - 10; - touch(__DIR__.'/Fixtures/ControllerWithParentClass.php', $cache - 10); - touch(__DIR__.'/Fixtures/AbstractController.php', $cache + 10); - - $this->doTestCacheStale(Fixtures\ControllerWithParentClass::class, $cache); - } - - /** - * @group 62 - */ - public function testIgnoresStaleCacheWithTraits() - { - $cache = time() - 10; - touch(__DIR__.'/Fixtures/ControllerWithTrait.php', $cache - 10); - touch(__DIR__.'/Fixtures/Traits/SecretRouteTrait.php', $cache + 10); - - $this->doTestCacheStale(Fixtures\ControllerWithTrait::class, $cache); - } - - /** - * @group 62 - */ - public function testIgnoresStaleCacheWithTraitsThatUseOtherTraits() - { - $cache = time() - 10; - - touch(__DIR__ . '/Fixtures/ClassThatUsesTraitThatUsesAnotherTrait.php', $cache - 10); - touch(__DIR__ . '/Fixtures/Traits/EmptyTrait.php', $cache + 10); - - $this->doTestCacheStale( - Fixtures\ClassThatUsesTraitThatUsesAnotherTrait::class, - $cache - ); - } - - /** - * @group 62 - */ - public function testIgnoresStaleCacheWithInterfacesThatExtendOtherInterfaces() - { - $cache = time() - 10; - - touch(__DIR__ . '/Fixtures/InterfaceThatExtendsAnInterface.php', $cache - 10); - touch(__DIR__ . '/Fixtures/EmptyInterface.php', $cache + 10); - - $this->doTestCacheStale( - Fixtures\InterfaceThatExtendsAnInterface::class, - $cache - ); - } - - /** - * @group 62 - * @group 105 - */ - public function testUsesFreshCacheWithTraitsThatUseOtherTraits() - { - $cacheTime = time(); - - touch(__DIR__ . '/Fixtures/ClassThatUsesTraitThatUsesAnotherTrait.php', $cacheTime - 10); - touch(__DIR__ . '/Fixtures/Traits/EmptyTrait.php', $cacheTime - 10); - - $this->doTestCacheFresh( - 'Doctrine\Tests\Annotations\Fixtures\ClassThatUsesTraitThatUsesAnotherTrait', - $cacheTime - ); - } - - protected function doTestCacheStale($className, $lastCacheModification) - { - $cacheKey = $className; - - /* @var $cache Cache|\PHPUnit_Framework_MockObject_MockObject */ - $cache = $this->createMock(Cache::class); - $cache - ->expects($this->at(0)) - ->method('fetch') - ->with($this->equalTo($cacheKey)) - ->will($this->returnValue([])) // Result was cached, but there was no annotation - ; - $cache - ->expects($this->at(1)) - ->method('fetch') - ->with($this->equalTo('[C]'.$cacheKey)) - ->will($this->returnValue($lastCacheModification)) - ; - $cache - ->expects($this->at(2)) - ->method('save') - ->with($this->equalTo($cacheKey)) - ; - $cache - ->expects($this->at(3)) - ->method('save') - ->with($this->equalTo('[C]'.$cacheKey)) - ; - - $reader = new CachedReader(new AnnotationReader(), $cache, true); - $route = new Route(); - $route->pattern = '/someprefix'; - - self::assertEquals([$route], $reader->getClassAnnotations(new \ReflectionClass($className))); - } - - protected function doTestCacheFresh($className, $lastCacheModification) - { - $cacheKey = $className; - $route = new Route(); - $route->pattern = '/someprefix'; - - /* @var $cache Cache|\PHPUnit_Framework_MockObject_MockObject */ - $cache = $this->createMock('Doctrine\Common\Cache\Cache'); - $cache - ->expects($this->at(0)) - ->method('fetch') - ->with($this->equalTo($cacheKey)) - ->will($this->returnValue([$route])); // Result was cached, but there was an annotation; - $cache - ->expects($this->at(1)) - ->method('fetch') - ->with($this->equalTo('[C]' . $cacheKey)) - ->will($this->returnValue($lastCacheModification)); - $cache->expects(self::never())->method('save'); - - $reader = new CachedReader(new AnnotationReader(), $cache, true); - - $this->assertEquals([$route], $reader->getClassAnnotations(new \ReflectionClass($className))); - } - - protected function getReader() - { - $this->cache = new ArrayCache(); - return new CachedReader(new AnnotationReader(), $this->cache); - } -}