From 7eb744126ba5081ea51441a893dd950046777383 Mon Sep 17 00:00:00 2001 From: Guilherme Blanco Date: Thu, 13 Jun 2013 21:47:40 -0400 Subject: [PATCH] Implemented support for RepositoryFactory. --- lib/Doctrine/ORM/Configuration.php | 50 ++++++++--- lib/Doctrine/ORM/EntityManager.php | 46 ++++------ .../Repository/DefaultRepositoryFactory.php | 89 +++++++++++++++++++ .../ORM/Repository/RepositoryFactory.php | 47 ++++++++++ .../ORM/Functional/Ticket/DDC2359Test.php | 5 +- 5 files changed, 195 insertions(+), 42 deletions(-) create mode 100644 lib/Doctrine/ORM/Repository/DefaultRepositoryFactory.php create mode 100644 lib/Doctrine/ORM/Repository/RepositoryFactory.php diff --git a/lib/Doctrine/ORM/Configuration.php b/lib/Doctrine/ORM/Configuration.php index 959a206dd..a1535de85 100644 --- a/lib/Doctrine/ORM/Configuration.php +++ b/lib/Doctrine/ORM/Configuration.php @@ -19,20 +19,22 @@ namespace Doctrine\ORM; -use Doctrine\Common\Cache\Cache; -use Doctrine\Common\Cache\ArrayCache; -use Doctrine\Common\Annotations\AnnotationRegistry; use Doctrine\Common\Annotations\AnnotationReader; -use Doctrine\Common\Persistence\Mapping\Driver\MappingDriver; -use Doctrine\ORM\Mapping\Driver\AnnotationDriver; -use Doctrine\ORM\Mapping\QuoteStrategy; -use Doctrine\ORM\Mapping\DefaultQuoteStrategy; -use Doctrine\ORM\Mapping\NamingStrategy; -use Doctrine\ORM\Mapping\DefaultNamingStrategy; -use Doctrine\ORM\Mapping\EntityListenerResolver; -use Doctrine\ORM\Mapping\DefaultEntityListenerResolver; -use Doctrine\Common\Annotations\SimpleAnnotationReader; +use Doctrine\Common\Annotations\AnnotationRegistry; use Doctrine\Common\Annotations\CachedReader; +use Doctrine\Common\Annotations\SimpleAnnotationReader; +use Doctrine\Common\Cache\ArrayCache; +use Doctrine\Common\Cache\Cache; +use Doctrine\Common\Persistence\Mapping\Driver\MappingDriver; +use Doctrine\ORM\Mapping\DefaultEntityListenerResolver; +use Doctrine\ORM\Mapping\DefaultNamingStrategy; +use Doctrine\ORM\Mapping\DefaultQuoteStrategy; +use Doctrine\ORM\Mapping\Driver\AnnotationDriver; +use Doctrine\ORM\Mapping\EntityListenerResolver; +use Doctrine\ORM\Mapping\NamingStrategy; +use Doctrine\ORM\Mapping\QuoteStrategy; +use Doctrine\ORM\Repository\DefaultRepositoryFactory; +use Doctrine\ORM\Repository\RepositoryFactoryInterface; /** * Configuration container for all configuration options of Doctrine. @@ -779,4 +781,28 @@ class Configuration extends \Doctrine\DBAL\Configuration return $this->_attributes['entityListenerResolver']; } + + /** + * Set the entity repository factory. + * + * @since 2.5 + * @param \Doctrine\ORM\Repository\RepositoryFactoryInterface $repositoryFactory + */ + public function setRepositoryFactory(RepositoryFactoryInterface $repositoryFactory) + { + $this->_attributes['repositoryFactory'] = $repositoryFactory; + } + + /** + * Get the entity repository factory. + * + * @since 2.5 + * @return \Doctrine\ORM\Repository\RepositoryFactoryInterface + */ + public function getRepositoryFactory() + { + return isset($this->_attributes['repositoryFactory']) + ? $this->_attributes['repositoryFactory'] + : new DefaultRepositoryFactory(); + } } diff --git a/lib/Doctrine/ORM/EntityManager.php b/lib/Doctrine/ORM/EntityManager.php index bc0d4ef18..8ee39cf06 100644 --- a/lib/Doctrine/ORM/EntityManager.php +++ b/lib/Doctrine/ORM/EntityManager.php @@ -85,13 +85,6 @@ use Doctrine\Common\Util\ClassUtils; */ private $metadataFactory; - /** - * The EntityRepository instances. - * - * @var array - */ - private $repositories = array(); - /** * The UnitOfWork used to coordinate object-level transactions. * @@ -120,6 +113,13 @@ use Doctrine\Common\Util\ClassUtils; */ private $proxyFactory; + /** + * The repository factory used to create dynamic repositories. + * + * @var \Doctrine\ORM\Repository\RepositoryFactory + */ + private $repositoryFactory; + /** * The expression builder instance used to generate query expressions. * @@ -151,9 +151,9 @@ use Doctrine\Common\Util\ClassUtils; */ protected function __construct(Connection $conn, Configuration $config, EventManager $eventManager) { - $this->conn = $conn; - $this->config = $config; - $this->eventManager = $eventManager; + $this->conn = $conn; + $this->config = $config; + $this->eventManager = $eventManager; $metadataFactoryClassName = $config->getClassMetadataFactoryName(); @@ -161,6 +161,11 @@ use Doctrine\Common\Util\ClassUtils; $this->metadataFactory->setEntityManager($this); $this->metadataFactory->setCacheDriver($this->config->getMetadataCacheImpl()); + $repositoryFactory = $config->getRepositoryFactory(); + + $this->repositoryFactory = $repositoryFactory; + $this->repositoryFactory->setEntityManager($this); + $this->unitOfWork = new UnitOfWork($this); $this->proxyFactory = new ProxyFactory( $this, @@ -758,28 +763,11 @@ use Doctrine\Common\Util\ClassUtils; * * @param string $entityName The name of the entity. * - * @return EntityRepository The repository class. + * @return \Doctrine\ORM\EntityRepository The repository class. */ public function getRepository($entityName) { - $entityName = ltrim($entityName, '\\'); - - if (isset($this->repositories[$entityName])) { - return $this->repositories[$entityName]; - } - - $metadata = $this->getClassMetadata($entityName); - $repositoryClassName = $metadata->customRepositoryClassName; - - if ($repositoryClassName === null) { - $repositoryClassName = $this->config->getDefaultRepositoryClassName(); - } - - $repository = new $repositoryClassName($this, $metadata); - - $this->repositories[$entityName] = $repository; - - return $repository; + return $this->repositoryFactory->getRepository($entityName); } /** diff --git a/lib/Doctrine/ORM/Repository/DefaultRepositoryFactory.php b/lib/Doctrine/ORM/Repository/DefaultRepositoryFactory.php new file mode 100644 index 000000000..b97424810 --- /dev/null +++ b/lib/Doctrine/ORM/Repository/DefaultRepositoryFactory.php @@ -0,0 +1,89 @@ +. + */ + +namespace Doctrine\ORM\Repository; + +use Doctrine\ORM\EntityManagerInterface; + +/** + * This factory is used to create default repository objects for entities at runtime. + * + * @author Guilherme Blanco + * @since 2.5 + */ +class DefaultRepositoryFactory implements RepositoryFactory +{ + /** + * The list of EntityRepository instances. + * + * @var array<\Doctrine\ORM\EntityRepository> + */ + private $repositoryList = array(); + + /** + * @var \Doctrine\ORM\EntityManagerInterface + */ + protected $entityManager; + + /** + * {@inheritdoc} + */ + public function setEntityManager(EntityManagerInterface $entityManager) + { + $this->entityManager = $entityManager; + } + + /** + * {@inheritdoc} + */ + public function getRepository($entityName) + { + $entityName = ltrim($entityName, '\\'); + + if (isset($this->repositoryList[$entityName])) { + return $this->repositoryList[$entityName]; + } + + $repository = $this->createRepository($entityName); + + $this->repositoryList[$entityName] = $repository; + + return $repository; + } + + /** + * Create a new repository instance for an entity class. + * + * @param string $entityName The name of the entity. + * + * @return \Doctrine\ORM\EntityRepository + */ + protected function createRepository($entityName) + { + $metadata = $this->entityManager->getClassMetadata($entityName); + $repositoryClassName = $metadata->customRepositoryClassName; + + if ($repositoryClassName === null) { + $configuration = $this->entityManager->getConfiguration(); + $repositoryClassName = $configuration->getDefaultRepositoryClassName(); + } + + return new $repositoryClassName($this->entityManager, $metadata); + } +} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Repository/RepositoryFactory.php b/lib/Doctrine/ORM/Repository/RepositoryFactory.php new file mode 100644 index 000000000..cd3e20a26 --- /dev/null +++ b/lib/Doctrine/ORM/Repository/RepositoryFactory.php @@ -0,0 +1,47 @@ +. + */ + +namespace Doctrine\ORM\Repository; + +use Doctrine\ORM\EntityManagerInterface; + +/** + * Interface for entity repository factory. + * + * @author Guilherme Blanco + * @since 2.5 + */ +interface RepositoryFactory +{ + /** + * Set the entity manager. + * + * @param \Doctrine\ORM\EntityManagerInterface $entityManager + */ + public function setEntityManager(EntityManagerInterface $entityManager); + + /** + * Gets the repository for an entity class. + * + * @param string $entityName The name of the entity. + * + * @return \Doctrine\ORM\EntityRepository + */ + public function getRepository($entityName); +} \ No newline at end of file diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2359Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2359Test.php index b9670d27a..c1189d797 100644 --- a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2359Test.php +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2359Test.php @@ -19,18 +19,21 @@ class DDC2359Test extends \PHPUnit_Framework_TestCase $mockDriver = $this->getMock('Doctrine\\Common\\Persistence\\Mapping\\Driver\\MappingDriver'); $mockMetadata = $this->getMock('Doctrine\\ORM\\Mapping\\ClassMetadata', array(), array(), '', false); $entityManager = $this->getMock('Doctrine\\ORM\\EntityManager', array(), array(), '', false); + /* @var $metadataFactory \Doctrine\ORM\Mapping\ClassMetadataFactory|\PHPUnit_Framework_MockObject_MockObject */ $metadataFactory = $this->getMock( 'Doctrine\\ORM\\Mapping\\ClassMetadataFactory', array('newClassMetadataInstance', 'wakeupReflection') ); - $configuration = $this->getMock('Doctrine\\ORM\\Configuration'); + + $configuration = $this->getMock('Doctrine\\ORM\\Configuration', array('getMetadataDriverImpl')); $connection = $this->getMock('Doctrine\\DBAL\\Connection', array(), array(), '', false); $configuration ->expects($this->any()) ->method('getMetadataDriverImpl') ->will($this->returnValue($mockDriver)); + $entityManager->expects($this->any())->method('getConfiguration')->will($this->returnValue($configuration)); $entityManager->expects($this->any())->method('getConnection')->will($this->returnValue($connection)); $entityManager