diff --git a/UPGRADE.md b/UPGRADE.md index 43e7ae92c..f1e3c242b 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -71,6 +71,11 @@ As of PHP 5.6, instantiation of new entities is deferred to the [`doctrine/instantiator`](https://github.com/doctrine/instantiator) library, which will avoid calling `__clone` or any public API on instantiated objects. +## BC BREAK: `Doctrine\ORM\Repository\DefaultRepositoryFactory` is now `final` + +Please implement the `Doctrine\ORM\Repository\RepositoryFactory` interface instead of extending +the `Doctrine\ORM\Repository\DefaultRepositoryFactory`. + # Upgrade to 2.4 ## BC BREAK: Compatibility Bugfix in PersistentCollection#matching() diff --git a/lib/Doctrine/ORM/Repository/DefaultRepositoryFactory.php b/lib/Doctrine/ORM/Repository/DefaultRepositoryFactory.php index b9afbfabf..12163eff6 100644 --- a/lib/Doctrine/ORM/Repository/DefaultRepositoryFactory.php +++ b/lib/Doctrine/ORM/Repository/DefaultRepositoryFactory.php @@ -27,7 +27,7 @@ use Doctrine\ORM\EntityManagerInterface; * @author Guilherme Blanco * @since 2.4 */ -class DefaultRepositoryFactory implements RepositoryFactory +final class DefaultRepositoryFactory implements RepositoryFactory { /** * The list of EntityRepository instances. @@ -41,13 +41,13 @@ class DefaultRepositoryFactory implements RepositoryFactory */ public function getRepository(EntityManagerInterface $entityManager, $entityName) { - $className = $entityManager->getClassMetadata($entityName)->getName(); + $repositoryHash = $entityManager->getClassMetadata($entityName)->getName() . spl_object_hash($entityManager); - if (isset($this->repositoryList[$className])) { - return $this->repositoryList[$className]; + if (isset($this->repositoryList[$repositoryHash])) { + return $this->repositoryList[$repositoryHash]; } - return $this->repositoryList[$className] = $this->createRepository($entityManager, $entityName); + return $this->repositoryList[$repositoryHash] = $this->createRepository($entityManager, $entityName); } /** @@ -58,7 +58,7 @@ class DefaultRepositoryFactory implements RepositoryFactory * * @return \Doctrine\Common\Persistence\ObjectRepository */ - protected function createRepository(EntityManagerInterface $entityManager, $entityName) + private function createRepository(EntityManagerInterface $entityManager, $entityName) { /* @var $metadata \Doctrine\ORM\Mapping\ClassMetadata */ $metadata = $entityManager->getClassMetadata($entityName); diff --git a/tests/Doctrine/Tests/ORM/Repository/DefaultRepositoryFactoryTest.php b/tests/Doctrine/Tests/ORM/Repository/DefaultRepositoryFactoryTest.php new file mode 100644 index 000000000..bfe5179a0 --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Repository/DefaultRepositoryFactoryTest.php @@ -0,0 +1,151 @@ +configuration = $this->getMock('Doctrine\\ORM\\Configuration'); + $this->entityManager = $this->createEntityManager(); + $this->repositoryFactory = new DefaultRepositoryFactory(); + + $this + ->configuration + ->expects($this->any()) + ->method('getDefaultRepositoryClassName') + ->will($this->returnValue('Doctrine\\Tests\\Models\\DDC869\\DDC869PaymentRepository')); + } + + public function testCreatesRepositoryFromDefaultRepositoryClass() + { + $this + ->entityManager + ->expects($this->any()) + ->method('getClassMetadata') + ->will($this->returnCallback(array($this, 'buildClassMetadata'))); + + $this->assertInstanceOf( + 'Doctrine\\Tests\\Models\\DDC869\\DDC869PaymentRepository', + $this->repositoryFactory->getRepository($this->entityManager, __CLASS__) + ); + } + + public function testCreatedRepositoriesAreCached() + { + $this + ->entityManager + ->expects($this->any()) + ->method('getClassMetadata') + ->will($this->returnCallback(array($this, 'buildClassMetadata'))); + + $this->assertSame( + $this->repositoryFactory->getRepository($this->entityManager, __CLASS__), + $this->repositoryFactory->getRepository($this->entityManager, __CLASS__) + ); + } + + public function testCreatesRepositoryFromCustomClassMetadata() + { + $customMetadata = $this->buildClassMetadata(__DIR__); + + $customMetadata->customRepositoryClassName = 'Doctrine\\Tests\\Models\\DDC753\\DDC753DefaultRepository'; + + $this + ->entityManager + ->expects($this->any()) + ->method('getClassMetadata') + ->will($this->returnValue($customMetadata)); + + $this->assertInstanceOf( + 'Doctrine\\Tests\\Models\\DDC753\\DDC753DefaultRepository', + $this->repositoryFactory->getRepository($this->entityManager, __CLASS__) + ); + } + + public function testCachesDistinctRepositoriesPerDistinctEntityManager() + { + $em1 = $this->createEntityManager(); + $em2 = $this->createEntityManager(); + + $em1 + ->expects($this->any()) + ->method('getClassMetadata') + ->will($this->returnCallback(array($this, 'buildClassMetadata'))); + $em2 + ->expects($this->any()) + ->method('getClassMetadata') + ->will($this->returnCallback(array($this, 'buildClassMetadata'))); + + $repo1 = $this->repositoryFactory->getRepository($em1, __CLASS__); + $repo2 = $this->repositoryFactory->getRepository($em2, __CLASS__); + + $this->assertSame($repo1, $this->repositoryFactory->getRepository($em1, __CLASS__)); + $this->assertSame($repo2, $this->repositoryFactory->getRepository($em2, __CLASS__)); + + $this->assertNotSame($repo1, $repo2); + } + + /** + * @private + * + * @param string $className + * + * @return \PHPUnit_Framework_MockObject_MockObject|\Doctrine\ORM\Mapping\ClassMetadata + */ + public function buildClassMetadata($className) + { + /* @var $metadata \Doctrine\ORM\Mapping\ClassMetadata|\PHPUnit_Framework_MockObject_MockObject */ + $metadata = $this + ->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadata') + ->disableOriginalConstructor() + ->getMock(); + + $metadata->expects($this->any())->method('getName')->will($this->returnValue($className)); + + $metadata->customRepositoryClassName = null; + + return $metadata; + } + + /** + * @return \Doctrine\ORM\EntityManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private function createEntityManager() + { + $entityManager = $this->getMock('Doctrine\\ORM\\EntityManagerInterface'); + + $entityManager + ->expects($this->any()) + ->method('getConfiguration') + ->will($this->returnValue($this->configuration)); + + return $entityManager; + } +}