diff --git a/lib/Doctrine/ORM/Cache/DefaultCacheFactory.php b/lib/Doctrine/ORM/Cache/DefaultCacheFactory.php index 69d2fd1c1..82843d359 100644 --- a/lib/Doctrine/ORM/Cache/DefaultCacheFactory.php +++ b/lib/Doctrine/ORM/Cache/DefaultCacheFactory.php @@ -180,13 +180,7 @@ class DefaultCacheFactory implements CacheFactory */ public function buildCollectionHydrator(EntityManagerInterface $em, array $mapping) { - /* @var $targetPersister \Doctrine\ORM\Cache\Persister\CachedPersister */ - $targetPersister = $em->getUnitOfWork()->getEntityPersister($mapping['targetEntity']); - - return new DefaultCollectionHydrator( - $em, - $targetPersister->getCacheRegion() - ); + return new DefaultCollectionHydrator($em); } /** diff --git a/lib/Doctrine/ORM/Event/LoadClassMetadataEventArgs.php b/lib/Doctrine/ORM/Event/LoadClassMetadataEventArgs.php index 5bebf7541..95e75616e 100644 --- a/lib/Doctrine/ORM/Event/LoadClassMetadataEventArgs.php +++ b/lib/Doctrine/ORM/Event/LoadClassMetadataEventArgs.php @@ -26,6 +26,11 @@ use Doctrine\Common\Persistence\Event\LoadClassMetadataEventArgs as BaseLoadClas * * @author Jonathan H. Wage * @since 2.0 + * + * Note: method annotations are used instead of method overrides (due to BC policy) + * + * @method __construct(\Doctrine\ORM\Mapping\ClassMetadata $classMetadata, \Doctrine\ORM\EntityManager $objectManager) + * @method \Doctrine\ORM\EntityManager getClassMetadata() */ class LoadClassMetadataEventArgs extends BaseLoadClassMetadataEventArgs { diff --git a/tests/Doctrine/Tests/EventListener/CacheMetadataListener.php b/tests/Doctrine/Tests/EventListener/CacheMetadataListener.php index f9e2616c6..7a7caf18e 100644 --- a/tests/Doctrine/Tests/EventListener/CacheMetadataListener.php +++ b/tests/Doctrine/Tests/EventListener/CacheMetadataListener.php @@ -3,33 +3,87 @@ namespace Doctrine\Tests\EventListener; use Doctrine\Common\Persistence\Event\LoadClassMetadataEventArgs; +use Doctrine\ORM\EntityManager; use Doctrine\ORM\Mapping\ClassMetadata; class CacheMetadataListener { + + /** + * Tracks which entities we have already forced caching enabled on. This is + * important to avoid some potential infinite-recursion issues. + * + * Key is the name of the entity, payload is unimportant. + * + * @var array + */ + protected $enabledItems = array(); + /** * @param \Doctrine\Common\Persistence\Event\LoadClassMetadataEventArgs $event */ public function loadClassMetadata(LoadClassMetadataEventArgs $event) { $metadata = $event->getClassMetadata(); - $cache = array( - 'usage' => ClassMetadata::CACHE_USAGE_NONSTRICT_READ_WRITE - ); + $em = $event->getObjectManager(); /** @var $metadata \Doctrine\ORM\Mapping\ClassMetadata */ if (strstr($metadata->name, 'Doctrine\Tests\Models\Cache')) { return; } + $this->enableCaching($metadata, $em); + } + + /** + * @param ClassMetadata $metadata + * + * @return bool + */ + private function isVisited(ClassMetaData $metadata) + { + return isset($this->enabledItems[$metadata->getName()]); + } + + /** + * @param ClassMetadata $metadata + */ + private function recordVisit(ClassMetaData $metadata) + { + $this->enabledItems[$metadata->getName()] = true; + } + + /** + * @param ClassMetadata $metadata + * @param EntityManager $em + */ + protected function enableCaching(ClassMetadata $metadata, EntityManager $em) + { + if ($this->isVisited($metadata)) { + return; // Already handled in the past + } + + $cache = array( + 'usage' => ClassMetadata::CACHE_USAGE_NONSTRICT_READ_WRITE + ); + if ($metadata->isVersioned) { return; } $metadata->enableCache($cache); + $this->recordVisit($metadata); + + // only enable association-caching when the target has already been + // given caching settings foreach ($metadata->associationMappings as $mapping) { - $metadata->enableAssociationCache($mapping['fieldName'], $cache); + $targetMeta = $em->getClassMetadata($mapping['targetEntity']); + $this->enableCaching($targetMeta, $em); + + if ($this->isVisited($targetMeta)) { + $metadata->enableAssociationCache($mapping['fieldName'], $cache); + } } } }