diff --git a/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php b/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php index 7fd070f82..06c0923a9 100644 --- a/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php +++ b/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php @@ -585,7 +585,8 @@ class BasicEntityPersister implements EntityPersister }, $class->identifier); $this->deleteJoinTableRecords($identifier); - $this->conn->delete($tableName, $id, $types); + + return (bool) $this->conn->delete($tableName, $id, $types); } /** diff --git a/lib/Doctrine/ORM/Persisters/EntityPersister.php b/lib/Doctrine/ORM/Persisters/EntityPersister.php index bc2685852..7a0190a16 100644 --- a/lib/Doctrine/ORM/Persisters/EntityPersister.php +++ b/lib/Doctrine/ORM/Persisters/EntityPersister.php @@ -153,7 +153,7 @@ interface EntityPersister * * @param object $entity The entity to delete. * - * @return void + * @return bool TRUE if the entity got deleted in the database, FALSE otherwise. */ public function delete($entity); @@ -161,6 +161,7 @@ interface EntityPersister * Count entities (optionally filtered by a criteria) * * @param array|\Doctrine\Common\Collections\Criteria $criteria + * * @return int */ public function count($criteria = array()); diff --git a/lib/Doctrine/ORM/Persisters/JoinedSubclassPersister.php b/lib/Doctrine/ORM/Persisters/JoinedSubclassPersister.php index fc90d6cad..d2321dc10 100644 --- a/lib/Doctrine/ORM/Persisters/JoinedSubclassPersister.php +++ b/lib/Doctrine/ORM/Persisters/JoinedSubclassPersister.php @@ -275,15 +275,13 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister $rootClass = $this->em->getClassMetadata($this->class->rootEntityName); $rootTable = $this->quoteStrategy->getTableName($rootClass, $this->platform); - $this->conn->delete($rootTable, $id); - - return; + return (bool) $this->conn->delete($rootTable, $id); } // Delete from all tables individually, starting from this class' table up to the root table. $rootTable = $this->quoteStrategy->getTableName($this->class, $this->platform); - $this->conn->delete($rootTable, $id); + $affectedRows = $this->conn->delete($rootTable, $id); foreach ($this->class->parentClasses as $parentClass) { $parentMetadata = $this->em->getClassMetadata($parentClass); @@ -291,6 +289,8 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister $this->conn->delete($parentTable, $id); } + + return (bool) $affectedRows; } /** diff --git a/lib/Doctrine/ORM/Persisters/ManyToManyPersister.php b/lib/Doctrine/ORM/Persisters/ManyToManyPersister.php index f9e8a7d14..c8ac9d4d5 100644 --- a/lib/Doctrine/ORM/Persisters/ManyToManyPersister.php +++ b/lib/Doctrine/ORM/Persisters/ManyToManyPersister.php @@ -223,7 +223,7 @@ class ManyToManyPersister extends AbstractCollectionPersister $mapping = $coll->getMapping(); $association = $mapping; $class = $this->em->getClassMetadata($mapping['sourceEntity']); - $id = $this->em->getUnitOfWork()->getEntityIdentifier($coll->getOwner()); + $id = $this->uow->getEntityIdentifier($coll->getOwner()); if ( ! $mapping['isOwningSide']) { $targetEntity = $this->em->getClassMetadata($mapping['targetEntity']); @@ -263,9 +263,10 @@ class ManyToManyPersister extends AbstractCollectionPersister */ public function slice(PersistentCollection $coll, $offset, $length = null) { - $mapping = $coll->getMapping(); + $mapping = $coll->getMapping(); + $persister = $this->uow->getEntityPersister($mapping['targetEntity']); - return $this->em->getUnitOfWork()->getEntityPersister($mapping['targetEntity'])->getManyToManyCollection($mapping, $coll->getOwner(), $offset, $length); + return $persister->getManyToManyCollection($mapping, $coll->getOwner(), $offset, $length); } /** * {@inheritdoc} @@ -273,7 +274,9 @@ class ManyToManyPersister extends AbstractCollectionPersister public function containsKey(PersistentCollection $coll, $key) { list($quotedJoinTable, $whereClauses, $params) = $this->getJoinTableRestrictionsWithKey($coll, $key, true); + $sql = 'SELECT 1 FROM ' . $quotedJoinTable . ' WHERE ' . implode(' AND ', $whereClauses); + return (bool) $this->conn->fetchColumn($sql, $params); } @@ -282,17 +285,14 @@ class ManyToManyPersister extends AbstractCollectionPersister */ public function contains(PersistentCollection $coll, $element) { - $uow = $this->em->getUnitOfWork(); - - // Shortcut for new entities - $entityState = $uow->getEntityState($element, UnitOfWork::STATE_NEW); + $entityState = $this->uow->getEntityState($element, UnitOfWork::STATE_NEW); if ($entityState === UnitOfWork::STATE_NEW) { return false; } // Entity is scheduled for inclusion - if ($entityState === UnitOfWork::STATE_MANAGED && $uow->isScheduledForInsert($element)) { + if ($entityState === UnitOfWork::STATE_MANAGED && $this->uow->isScheduledForInsert($element)) { return false; } @@ -308,10 +308,7 @@ class ManyToManyPersister extends AbstractCollectionPersister */ public function removeElement(PersistentCollection $coll, $element) { - $uow = $this->em->getUnitOfWork(); - - // shortcut for new entities - $entityState = $uow->getEntityState($element, UnitOfWork::STATE_NEW); + $entityState = $this->uow->getEntityState($element, UnitOfWork::STATE_NEW); if ($entityState === UnitOfWork::STATE_NEW) { return false; @@ -319,7 +316,7 @@ class ManyToManyPersister extends AbstractCollectionPersister // If Entity is scheduled for inclusion, it is not in this collection. // We can assure that because it would have return true before on array check - if ($entityState === UnitOfWork::STATE_MANAGED && $uow->isScheduledForInsert($element)) { + if ($entityState === UnitOfWork::STATE_MANAGED && $this->uow->isScheduledForInsert($element)) { return false; } @@ -339,11 +336,10 @@ class ManyToManyPersister extends AbstractCollectionPersister */ private function getJoinTableRestrictionsWithKey(PersistentCollection $coll, $key, $addFilters) { - $uow = $this->em->getUnitOfWork(); $filterMapping = $coll->getMapping(); $mapping = $filterMapping; $indexBy = $mapping['indexBy']; - $id = $uow->getEntityIdentifier($coll->getOwner()); + $id = $this->uow->getEntityIdentifier($coll->getOwner()); $targetEntity = $this->em->getClassMetadata($mapping['targetEntity']); @@ -411,22 +407,21 @@ class ManyToManyPersister extends AbstractCollectionPersister */ private function getJoinTableRestrictions(PersistentCollection $coll, $element, $addFilters) { - $uow = $this->em->getUnitOfWork(); $filterMapping = $coll->getMapping(); $mapping = $filterMapping; if ( ! $mapping['isOwningSide']) { $sourceClass = $this->em->getClassMetadata($mapping['targetEntity']); $targetClass = $this->em->getClassMetadata($mapping['sourceEntity']); - $sourceId = $uow->getEntityIdentifier($element); - $targetId = $uow->getEntityIdentifier($coll->getOwner()); + $sourceId = $this->uow->getEntityIdentifier($element); + $targetId = $this->uow->getEntityIdentifier($coll->getOwner()); $mapping = $sourceClass->associationMappings[$mapping['mappedBy']]; } else { $sourceClass = $this->em->getClassMetadata($mapping['sourceEntity']); $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); - $sourceId = $uow->getEntityIdentifier($coll->getOwner()); - $targetId = $uow->getEntityIdentifier($element); + $sourceId = $this->uow->getEntityIdentifier($coll->getOwner()); + $targetId = $this->uow->getEntityIdentifier($element); } $quotedJoinTable = $this->quoteStrategy->getJoinTableName($mapping, $sourceClass, $this->platform); diff --git a/lib/Doctrine/ORM/Persisters/OneToManyPersister.php b/lib/Doctrine/ORM/Persisters/OneToManyPersister.php index ef5703a6a..c1e8a6c38 100644 --- a/lib/Doctrine/ORM/Persisters/OneToManyPersister.php +++ b/lib/Doctrine/ORM/Persisters/OneToManyPersister.php @@ -39,8 +39,7 @@ class OneToManyPersister extends AbstractCollectionPersister public function get(PersistentCollection $coll, $index) { $mapping = $coll->getMapping(); - $uow = $this->em->getUnitOfWork(); - $persister = $uow->getEntityPersister($mapping['targetEntity']); + $persister = $this->uow->getEntityPersister($mapping['targetEntity']); if (!isset($mapping['indexBy'])) { throw new \BadMethodCallException("Selecting a collection by index is only supported on indexed collections."); @@ -115,7 +114,7 @@ class OneToManyPersister extends AbstractCollectionPersister */ protected function getDeleteSQL(PersistentCollection $coll) { - throw new \BadMethodCallException("Update Row SQL is not used for OneToManyPersister"); + throw new \BadMethodCallException("Delete Row SQL is not used for OneToManyPersister"); } /** @@ -125,7 +124,7 @@ class OneToManyPersister extends AbstractCollectionPersister */ protected function getDeleteSQLParameters(PersistentCollection $coll) { - throw new \BadMethodCallException("Update Row SQL is not used for OneToManyPersister"); + throw new \BadMethodCallException("Delete Row SQL is not used for OneToManyPersister"); } /** @@ -133,11 +132,15 @@ class OneToManyPersister extends AbstractCollectionPersister */ public function count(PersistentCollection $coll) { - list($quotedJoinTable, $whereClauses, $params) = $this->getJoinTableRestrictions($coll, true); + $mapping = $coll->getMapping(); + $persister = $this->uow->getEntityPersister($mapping['targetEntity']); - $sql = 'SELECT count(*) FROM ' . $quotedJoinTable . ' WHERE ' . implode(' AND ', $whereClauses); + // only works with single id identifier entities. Will throw an + // exception in Entity Persisters if that is not the case for the + // 'mappedBy' field. + $criteria = new Criteria(Criteria::expr()->eq($mapping['mappedBy'], $coll->getOwner())); - return $this->conn->fetchColumn($sql, $params); + return $persister->count($criteria); } /** @@ -146,8 +149,7 @@ class OneToManyPersister extends AbstractCollectionPersister public function slice(PersistentCollection $coll, $offset, $length = null) { $mapping = $coll->getMapping(); - $uow = $this->em->getUnitOfWork(); - $persister = $uow->getEntityPersister($mapping['targetEntity']); + $persister = $this->uow->getEntityPersister($mapping['targetEntity']); return $persister->getOneToManyCollection($mapping, $coll->getOwner(), $offset, $length); } @@ -157,50 +159,18 @@ class OneToManyPersister extends AbstractCollectionPersister */ public function containsKey(PersistentCollection $coll, $key) { - list($quotedJoinTable, $whereClauses, $params) = $this->getJoinTableRestrictions($coll, true); + $mapping = $coll->getMapping(); + $persister = $this->uow->getEntityPersister($mapping['targetEntity']); - $mapping = $coll->getMapping(); - $sourceClass = $this->em->getClassMetadata($mapping['sourceEntity']); + // only works with single id identifier entities. Will throw an + // exception in Entity Persisters if that is not the case for the + // 'mappedBy' field. + $criteria = new Criteria(); - $whereClauses[] = $sourceClass->getColumnName($mapping['indexBy']) . ' = ?'; - $params[] = $key; + $criteria->andWhere(Criteria::expr()->eq($mapping['mappedBy'], $coll->getOwner())); + $criteria->andWhere(Criteria::expr()->eq($mapping['indexBy'], $key)); - $sql = 'SELECT 1 FROM ' . $quotedJoinTable . ' WHERE ' . implode(' AND ', $whereClauses); - - return (bool) $this->conn->fetchColumn($sql, $params); - } - - private function getJoinTableRestrictions(PersistentCollection $coll, $addFilters) - { - $mapping = $coll->getMapping(); - $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); - $sourceClass = $this->em->getClassMetadata($mapping['sourceEntity']); - $id = $this->em->getUnitOfWork()->getEntityIdentifier($coll->getOwner()); - - $whereClauses = array(); - $params = array(); - - $joinColumns = $targetClass->associationMappings[$mapping['mappedBy']]['joinColumns']; - foreach ($joinColumns as $joinColumn) { - $whereClauses[] = $joinColumn['name'] . ' = ?'; - - $params[] = ($targetClass->containsForeignIdentifier) - ? $id[$sourceClass->getFieldForColumn($joinColumn['referencedColumnName'])] - : $id[$sourceClass->fieldNames[$joinColumn['referencedColumnName']]]; - } - - if ($addFilters) { - $filterTargetClass = $this->em->getClassMetadata($targetClass->rootEntityName); - foreach ($this->em->getFilters()->getEnabledFilters() as $filter) { - if ($filterExpr = $filter->addFilterConstraint($filterTargetClass, 't')) { - $whereClauses[] = '(' . $filterExpr . ')'; - } - } - } - - $quotedJoinTable = $this->quoteStrategy->getTableName($targetClass, $this->platform) . ' t'; - - return array($quotedJoinTable, $whereClauses, $params); + return (bool) $persister->count($criteria); } /** @@ -208,22 +178,19 @@ class OneToManyPersister extends AbstractCollectionPersister */ public function contains(PersistentCollection $coll, $element) { - $mapping = $coll->getMapping(); - $uow = $this->em->getUnitOfWork(); - - // shortcut for new entities - $entityState = $uow->getEntityState($element, UnitOfWork::STATE_NEW); + $entityState = $this->uow->getEntityState($element, UnitOfWork::STATE_NEW); if ($entityState === UnitOfWork::STATE_NEW) { return false; } // Entity is scheduled for inclusion - if ($entityState === UnitOfWork::STATE_MANAGED && $uow->isScheduledForInsert($element)) { + if ($entityState === UnitOfWork::STATE_MANAGED && $this->uow->isScheduledForInsert($element)) { return false; } - $persister = $uow->getEntityPersister($mapping['targetEntity']); + $mapping = $coll->getMapping(); + $persister = $this->uow->getEntityPersister($mapping['targetEntity']); // only works with single id identifier entities. Will throw an // exception in Entity Persisters if that is not the case for the @@ -238,10 +205,7 @@ class OneToManyPersister extends AbstractCollectionPersister */ public function removeElement(PersistentCollection $coll, $element) { - $uow = $this->em->getUnitOfWork(); - - // shortcut for new entities - $entityState = $uow->getEntityState($element, UnitOfWork::STATE_NEW); + $entityState = $this->uow->getEntityState($element, UnitOfWork::STATE_NEW); if ($entityState === UnitOfWork::STATE_NEW) { return false; @@ -249,15 +213,13 @@ class OneToManyPersister extends AbstractCollectionPersister // If Entity is scheduled for inclusion, it is not in this collection. // We can assure that because it would have return true before on array check - if ($entityState === UnitOfWork::STATE_MANAGED && $uow->isScheduledForInsert($element)) { + if ($entityState === UnitOfWork::STATE_MANAGED && $this->uow->isScheduledForInsert($element)) { return false; } - $mapping = $coll->getMapping(); - $class = $this->em->getClassMetadata($mapping['targetEntity']); - $sql = 'DELETE FROM ' . $this->quoteStrategy->getTableName($class, $this->platform) - . ' WHERE ' . implode('= ? AND ', $class->getIdentifierColumnNames()) . ' = ?'; + $mapping = $coll->getMapping(); + $persister = $this->uow->getEntityPersister($mapping['targetEntity']); - return (bool) $this->conn->executeUpdate($sql, $this->getDeleteRowSQLParameters($coll, $element)); + return $persister->delete($element); } } diff --git a/tests/Doctrine/Tests/Models/DDC2504/DDC2504ChildClass.php b/tests/Doctrine/Tests/Models/DDC2504/DDC2504ChildClass.php new file mode 100644 index 000000000..08a4605b6 --- /dev/null +++ b/tests/Doctrine/Tests/Models/DDC2504/DDC2504ChildClass.php @@ -0,0 +1,11 @@ +childClasses = new ArrayCollection(); + } +} diff --git a/tests/Doctrine/Tests/Models/DDC2504/DDC2504RootClass.php b/tests/Doctrine/Tests/Models/DDC2504/DDC2504RootClass.php new file mode 100644 index 000000000..18edd75a3 --- /dev/null +++ b/tests/Doctrine/Tests/Models/DDC2504/DDC2504RootClass.php @@ -0,0 +1,28 @@ +useModelSet('cms'); + $this->useModelSet('ddc2504'); parent::setUp(); $class = $this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); @@ -131,6 +136,17 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->assertEquals(2, count($user->articles)); } + /** + * @group DDC-2504 + */ + public function testCountOneToManyJoinedInheritance() + { + $otherClass = $this->_em->find(DDC2504OtherClass::CLASSNAME, $this->ddc2504OtherClassId); + + $this->assertFalse($otherClass->childClasses->isInitialized(), "Pre-Condition"); + $this->assertEquals(2, count($otherClass->childClasses)); + } + /** * @group DDC-546 */ @@ -279,6 +295,95 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->assertFalse($user->articles->isInitialized(), "Post-Condition: Collection is not initialized."); } + /** + * @group DDC-2504 + */ + public function testLazyOneToManyJoinedInheritanceIsLazilyInitialized() + { + $otherClass = $this->_em->find(DDC2504OtherClass::CLASSNAME, $this->ddc2504OtherClassId); + + $this->assertFalse($otherClass->childClasses->isInitialized(), 'Collection is not initialized.'); + } + + /** + * @group DDC-2504 + */ + public function testContainsOnOneToManyJoinedInheritanceWillNotInitializeCollectionWhenMatchingItemIsFound() + { + $otherClass = $this->_em->find(DDC2504OtherClass::CLASSNAME, $this->ddc2504OtherClassId); + + // Test One to Many existence retrieved from DB + $childClass = $this->_em->find(DDC2504ChildClass::CLASSNAME, $this->ddc2504ChildClassId); + $queryCount = $this->getCurrentQueryCount(); + + $this->assertTrue($otherClass->childClasses->contains($childClass)); + $this->assertFalse($otherClass->childClasses->isInitialized(), 'Collection is not initialized.'); + $this->assertEquals($queryCount + 1, $this->getCurrentQueryCount(), 'Search operation was performed via SQL'); + } + + /** + * @group DDC-2504 + */ + public function testContainsOnOneToManyJoinedInheritanceWillNotCauseQueriesWhenNonPersistentItemIsMatched() + { + $otherClass = $this->_em->find(DDC2504OtherClass::CLASSNAME, $this->ddc2504OtherClassId); + $queryCount = $this->getCurrentQueryCount(); + + $this->assertFalse($otherClass->childClasses->contains(new DDC2504ChildClass())); + $this->assertEquals( + $queryCount, + $this->getCurrentQueryCount(), + 'Checking for contains of new entity should cause no query to be executed.' + ); + } + + /** + * @group DDC-2504 + */ + public function testContainsOnOneToManyJoinedInheritanceWillNotInitializeCollectionWithClearStateMatchingItem() + { + $otherClass = $this->_em->find(DDC2504OtherClass::CLASSNAME, $this->ddc2504OtherClassId); + $childClass = new DDC2504ChildClass(); + + // Test One to Many existence with state clear + $this->_em->persist($childClass); + $this->_em->flush(); + + $queryCount = $this->getCurrentQueryCount(); + $this->assertFalse($otherClass->childClasses->contains($childClass)); + $this->assertEquals($queryCount + 1, $this->getCurrentQueryCount(), "Checking for contains of persisted entity should cause one query to be executed."); + $this->assertFalse($otherClass->childClasses->isInitialized(), "Post-Condition: Collection is not initialized."); + } + + /** + * @group DDC-2504 + */ + public function testContainsOnOneToManyJoinedInheritanceWillNotInitializeCollectionWithNewStateNotMatchingItem() + { + $otherClass = $this->_em->find(DDC2504OtherClass::CLASSNAME, $this->ddc2504OtherClassId); + $childClass = new DDC2504ChildClass(); + + $this->_em->persist($childClass); + + $queryCount = $this->getCurrentQueryCount(); + + $this->assertFalse($otherClass->childClasses->contains($childClass)); + $this->assertEquals($queryCount, $this->getCurrentQueryCount(), "Checking for contains of managed entity (but not persisted) should cause no query to be executed."); + $this->assertFalse($otherClass->childClasses->isInitialized(), "Post-Condition: Collection is not initialized."); + } + + /** + * @group DDC-2504 + */ + public function testCountingOnOneToManyJoinedInheritanceWillNotInitializeCollection() + { + $otherClass = $this->_em->find(DDC2504OtherClass::CLASSNAME, $this->ddc2504OtherClassId); + + $this->assertEquals(2, count($otherClass->childClasses)); + + $this->assertFalse($otherClass->childClasses->isInitialized()); + } + /** * @group DDC-546 */ @@ -405,6 +510,89 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->assertEquals($queryCount, $this->getCurrentQueryCount(), "Removing a managed entity should cause no query to be executed."); } + /** + * @group DDC-2504 + */ + public function testRemovalOfManagedElementFromOneToManyJoinedInheritanceCollectionDoesNotInitializeIt() + { + $otherClass = $this->_em->find(DDC2504OtherClass::CLASSNAME, $this->ddc2504OtherClassId); + $childClass = $this->_em->find(DDC2504ChildClass::CLASSNAME, $this->ddc2504ChildClassId); + + $queryCount = $this->getCurrentQueryCount(); + + $otherClass->childClasses->removeElement($childClass); + + $this->assertFalse($otherClass->childClasses->isInitialized(), 'Collection is not initialized.'); + $this->assertEquals( + $queryCount + 2, + $this->getCurrentQueryCount(), + 'One removal per table in the JTI has been executed' + ); + + $this->assertFalse($otherClass->childClasses->contains($childClass)); + } + + /** + * @group DDC-2504 + */ + public function testRemovalOfNonManagedElementFromOneToManyJoinedInheritanceCollectionDoesNotInitializeIt() + { + $otherClass = $this->_em->find(DDC2504OtherClass::CLASSNAME, $this->ddc2504OtherClassId); + $queryCount = $this->getCurrentQueryCount(); + + $otherClass->childClasses->removeElement(new DDC2504ChildClass()); + + $this->assertEquals( + $queryCount, + $this->getCurrentQueryCount(), + 'Removing an unmanaged entity should cause no query to be executed.' + ); + } + + /** + * @group DDC-2504 + */ + public function testRemovalOfNewElementFromOneToManyJoinedInheritanceCollectionDoesNotInitializeIt() + { + $otherClass = $this->_em->find(DDC2504OtherClass::CLASSNAME, $this->ddc2504OtherClassId); + $childClass = new DDC2504ChildClass(); + + $this->_em->persist($childClass); + + $queryCount = $this->getCurrentQueryCount(); + + $otherClass->childClasses->removeElement($childClass); + + $this->assertEquals( + $queryCount, + $this->getCurrentQueryCount(), + 'Removing a new entity should cause no query to be executed.' + ); + } + + /** + * @group DDC-2504 + */ + public function testRemovalOfNewManagedElementFromOneToManyJoinedInheritanceCollectionDoesNotInitializeIt() + { + $otherClass = $this->_em->find(DDC2504OtherClass::CLASSNAME, $this->ddc2504OtherClassId); + $childClass = new DDC2504ChildClass(); + + $this->_em->persist($childClass); + $this->_em->flush(); + + $queryCount = $this->getCurrentQueryCount(); + + $otherClass->childClasses->removeElement($childClass); + + $this->assertEquals( + $queryCount + 2, + $this->getCurrentQueryCount(), + 'Removing a persisted entity should cause two queries to be executed.' + ); + $this->assertFalse($otherClass->childClasses->isInitialized(), 'Collection is not initialized.'); + } + /** * */ @@ -589,6 +777,22 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->assertEquals($queryCount + 1, $this->getCurrentQueryCount()); } + public function testContainsKeyIndexByOneToManyJoinedInheritance() + { + $class = $this->_em->getClassMetadata(DDC2504OtherClass::CLASSNAME); + $class->associationMappings['childClasses']['indexBy'] = 'id'; + + $otherClass = $this->_em->find(DDC2504OtherClass::CLASSNAME, $this->ddc2504OtherClassId); + + $queryCount = $this->getCurrentQueryCount(); + + $contains = $otherClass->childClasses->containsKey($this->ddc2504ChildClassId); + + $this->assertTrue($contains); + $this->assertFalse($otherClass->childClasses->isInitialized()); + $this->assertEquals($queryCount + 1, $this->getCurrentQueryCount()); + } + public function testContainsKeyIndexByManyToMany() { $user = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $this->userId2); @@ -747,6 +951,21 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase $user1->addPhonenumber($phonenumber1); + // DDC-2504 + $otherClass = new DDC2504OtherClass(); + $childClass1 = new DDC2504ChildClass(); + $childClass2 = new DDC2504ChildClass(); + + $childClass1->other = $otherClass; + $childClass2->other = $otherClass; + + $otherClass->childClasses[] = $childClass1; + $otherClass->childClasses[] = $childClass2; + + $this->_em->persist($childClass1); + $this->_em->persist($childClass2); + $this->_em->persist($otherClass); + $this->_em->flush(); $this->_em->clear(); @@ -757,6 +976,8 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->topic = $article1->topic; $this->phonenumber = $phonenumber1->phonenumber; + $this->ddc2504OtherClassId = $otherClass->id; + $this->ddc2504ChildClassId = $childClass1->id; } } diff --git a/tests/Doctrine/Tests/OrmFunctionalTestCase.php b/tests/Doctrine/Tests/OrmFunctionalTestCase.php index 16d0d2573..65096415a 100644 --- a/tests/Doctrine/Tests/OrmFunctionalTestCase.php +++ b/tests/Doctrine/Tests/OrmFunctionalTestCase.php @@ -186,7 +186,12 @@ abstract class OrmFunctionalTestCase extends OrmTestCase 'tweet' => array( 'Doctrine\Tests\Models\Tweet\User', 'Doctrine\Tests\Models\Tweet\Tweet' - ) + ), + 'ddc2504' => array( + 'Doctrine\Tests\Models\DDC2504\DDC2504RootClass', + 'Doctrine\Tests\Models\DDC2504\DDC2504ChildClass', + 'Doctrine\Tests\Models\DDC2504\DDC2504OtherClass', + ), ); /**