From 7bbdac1c883000112fcf69b47eb2ffae5d38af10 Mon Sep 17 00:00:00 2001 From: romanb Date: Tue, 3 Nov 2009 18:30:21 +0000 Subject: [PATCH] [2.0][DDC-61][DDC-108] Fixed. Started exception refactoring. --- UPGRADE_TO_2_0 | 6 +- lib/Doctrine/Common/Annotations/Parser.php | 2 +- lib/Doctrine/Common/IsolatedClassLoader.php | 4 +- lib/Doctrine/DBAL/DBALException.php | 8 +- .../DBAL/Platforms/AbstractPlatform.php | 72 +++++----- lib/Doctrine/ORM/Mapping/ClassMetadata.php | 6 + lib/Doctrine/ORM/Mapping/OneToOneMapping.php | 31 ++--- .../Persisters/StandardEntityPersister.php | 13 +- lib/Doctrine/ORM/UnitOfWork.php | 41 +++--- .../Doctrine/Tests/Common/ClassLoaderTest.php | 4 +- .../DBAL/Platforms/OraclePlatformTest.php | 8 +- .../Tests/Models/Company/CompanyEvent.php | 3 +- .../Models/Company/CompanyOrganization.php | 14 ++ .../Doctrine/Tests/ORM/EntityManagerTest.php | 35 ----- .../Tests/ORM/Functional/AllTests.php | 1 + .../Functional/ClassTableInheritanceTest.php | 37 +++++ .../Functional/ClassTableInheritanceTest2.php | 129 ++++++++++++++++++ .../Doctrine/Tests/OrmFunctionalTestCase.php | 1 + 18 files changed, 290 insertions(+), 125 deletions(-) create mode 100644 tests/Doctrine/Tests/ORM/Functional/ClassTableInheritanceTest2.php diff --git a/UPGRADE_TO_2_0 b/UPGRADE_TO_2_0 index 8a7fc65e2..87a48293f 100644 --- a/UPGRADE_TO_2_0 +++ b/UPGRADE_TO_2_0 @@ -6,7 +6,11 @@ This section details the changes made to Doctrine 2.0-ALPHA3 to make it easier for you to upgrade your projects to use this version. - + +## CLI Changes + +The $args variable used in the cli-config.php for configuring the Doctrine CLI has been renamed to $globalArguments. + ## Proxy class changes You are now required to make supply some minimalist configuration with regards to proxy objects. That involves 2 new configuration options. First, the directory where generated proxy classes should be placed needs to be specified. Secondly, you need to configure the namespace used for proxy classes. The following snippet shows an example: diff --git a/lib/Doctrine/Common/Annotations/Parser.php b/lib/Doctrine/Common/Annotations/Parser.php index dbd0b6153..113bd72bf 100644 --- a/lib/Doctrine/Common/Annotations/Parser.php +++ b/lib/Doctrine/Common/Annotations/Parser.php @@ -252,7 +252,7 @@ class Parser (! $this->_isNestedAnnotation && $this->_lexer->lookahead != null && ! $this->_lexer->isNextToken('(') && ! $this->_lexer->isNextToken('@')) || - ! class_exists($name) || + ! class_exists($name, false) || ! is_subclass_of($name, 'Doctrine\Common\Annotations\Annotation') ) { $this->_lexer->skipUntil('@'); diff --git a/lib/Doctrine/Common/IsolatedClassLoader.php b/lib/Doctrine/Common/IsolatedClassLoader.php index c3654630e..519a64d02 100644 --- a/lib/Doctrine/Common/IsolatedClassLoader.php +++ b/lib/Doctrine/Common/IsolatedClassLoader.php @@ -96,9 +96,9 @@ class IsolatedClassLoader */ public function loadClass($className) { - if (class_exists($className, false) || interface_exists($className, false)) { + /*if (class_exists($className, false) || interface_exists($className, false)) { return false; - } + }*/ if (strpos($className, $this->_namespace.$this->_namespaceSeparator) !== 0) { return false; diff --git a/lib/Doctrine/DBAL/DBALException.php b/lib/Doctrine/DBAL/DBALException.php index 5fb4eeaa6..94c83bfc4 100644 --- a/lib/Doctrine/DBAL/DBALException.php +++ b/lib/Doctrine/DBAL/DBALException.php @@ -2,4 +2,10 @@ namespace Doctrine\DBAL; -class DBALException extends \Exception {} \ No newline at end of file +class DBALException extends \Exception +{ + public static function notSupported($method) + { + return new self("Operation '$method' is not supported."); + } +} \ No newline at end of file diff --git a/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php b/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php index 9a389e6a1..d9c39d2aa 100644 --- a/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php +++ b/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php @@ -21,7 +21,7 @@ namespace Doctrine\DBAL\Platforms; -use Doctrine\Common\DoctrineException, +use Doctrine\DBAL\DBALException, Doctrine\DBAL\Connection, Doctrine\DBAL\Types; @@ -103,7 +103,7 @@ abstract class AbstractPlatform */ public function getRegexpExpression() { - throw DoctrineException::regularExpressionOperatorNotSupported($this); + throw DBALException::notSupported(__METHOD__); } /** @@ -374,7 +374,7 @@ abstract class AbstractPlatform $values = $this->getIdentifiers($values); if (count($values) == 0) { - throw DoctrineException::valuesArrayForInOperatorInvalid(); + throw \InvalidArgumentException('Values must not be empty.'); } return $column . ' IN (' . implode(', ', $values) . ')'; } @@ -537,7 +537,7 @@ abstract class AbstractPlatform */ public function getCreateSequenceSql($sequenceName, $start = 1, $allocationSize = 1) { - throw DoctrineException::createSequenceNotSupported($this); + throw DBALException::notSupported(__METHOD__); } /** @@ -591,7 +591,7 @@ abstract class AbstractPlatform public function getCreateIndexSql($table, $name, array $definition) { if ( ! isset($definition['columns'])) { - throw DoctrineException::indexFieldsArrayRequired(); + throw \InvalidArgumentException("Incomplete definition. 'columns' required."); } $type = ''; @@ -601,7 +601,7 @@ abstract class AbstractPlatform $type = strtoupper($definition['type']) . ' '; break; default: - throw DoctrineException::unknownIndexType($definition['type']); + throw \InvalidArgumentException('Unknown type: ' . $definition['type']); } } @@ -658,7 +658,7 @@ abstract class AbstractPlatform */ public function getAlterTableSql($name, array $changes, $check = false) { - throw DoctrineException::alterTableNotSupported($this); + throw DBALException::notSupported(__METHOD__); } /** @@ -870,12 +870,12 @@ abstract class AbstractPlatform if (strtolower($definition['type']) == 'unique') { $type = strtoupper($definition['type']) . ' '; } else { - throw DoctrineException::unknownIndexType($definition['type']); + throw \InvalidArgumentException('Invalid type: ' . $definition['type']); } } if ( ! isset($definition['columns']) || ! is_array($definition['columns'])) { - throw DoctrineException::indexFieldsArrayRequired(); + throw \InvalidArgumentException("Incomplete definition. 'columns' required."); } $query = $type . 'INDEX ' . $name; @@ -931,7 +931,7 @@ abstract class AbstractPlatform */ public function getShowDatabasesSql() { - throw DoctrineException::showDatabasesNotSupported($this); + throw DBALException::notSupported(__METHOD__); } /** @@ -1023,7 +1023,7 @@ abstract class AbstractPlatform return $upper; break; default: - throw DoctrineException::unknownForeignKeyReferentialAction($upper); + throw \InvalidArgumentException('Invalid foreign key action: ' . $upper); } } @@ -1043,13 +1043,13 @@ abstract class AbstractPlatform $sql .= 'FOREIGN KEY ('; if ( ! isset($definition['local'])) { - throw DoctrineException::localReferenceFieldMissing(); + throw new \InvalidArgumentException("Incomplete definition. 'local' required."); } if ( ! isset($definition['foreign'])) { - throw DoctrineException::foreignReferenceFieldMissing(); + throw new \InvalidArgumentException("Incomplete definition. 'foreign' required."); } if ( ! isset($definition['foreignTable'])) { - throw DoctrineException::foreignReferenceTableMissing(); + throw new \InvalidArgumentException("Incomplete definition. 'foreignTable' required."); } if ( ! is_array($definition['local'])) { @@ -1124,7 +1124,7 @@ abstract class AbstractPlatform */ public function getMatchPatternExpression($pattern, $operator = null, $field = null) { - throw DoctrineException::matchPatternExpressionNotSupported($this); + throw DBALException::notSupported(__METHOD__); } /** @@ -1231,88 +1231,88 @@ abstract class AbstractPlatform case Connection::TRANSACTION_SERIALIZABLE: return 'SERIALIZABLE'; default: - throw DoctrineException::isolationLevelNotSupported($isolation); + throw new \InvalidArgumentException('Invalid isolation level:' . $level); } } public function getListDatabasesSql() { - throw DoctrineException::listDatabasesNotSupported($this); + throw DBALException::notSupported(__METHOD__); } public function getListFunctionsSql() { - throw DoctrineException::listFunctionsNotSupported($this); + throw DBALException::notSupported(__METHOD__); } public function getListTriggersSql($table = null) { - throw DoctrineException::listTriggersNotSupported($this); + throw DBALException::notSupported(__METHOD__); } public function getListSequencesSql($database) { - throw DoctrineException::listSequencesNotSupported($this); + throw DBALException::notSupported(__METHOD__); } public function getListTableConstraintsSql($table) { - throw DoctrineException::listTableConstraintsNotSupported($this); + throw DBALException::notSupported(__METHOD__); } public function getListTableColumnsSql($table) { - throw DoctrineException::listTableColumnsNotSupported($this); + throw DBALException::notSupported(__METHOD__); } public function getListTablesSql() { - throw DoctrineException::listTablesNotSupported($this); + throw DBALException::notSupported(__METHOD__); } public function getListUsersSql() { - throw DoctrineException::listUsersNotSupported($this); + throw DBALException::notSupported(__METHOD__); } public function getListViewsSql() { - throw DoctrineException::listViewsNotSupported($this); + throw DBALException::notSupported(__METHOD__); } public function getListTableIndexesSql($table) { - throw DoctrineException::listTableIndexesNotSupported($this); + throw DBALException::notSupported(__METHOD__); } public function getListTableForeignKeysSql($table) { - throw DoctrineException::listTableForeignKeysNotSupported($this); + throw DBALException::notSupported(__METHOD__); } public function getCreateViewSql($name, $sql) { - throw DoctrineException::createViewNotSupported($this); + throw DBALException::notSupported(__METHOD__); } public function getDropViewSql($name) { - throw DoctrineException::dropViewNotSupported($this); + throw DBALException::notSupported(__METHOD__); } public function getDropSequenceSql($sequenceName) { - throw DoctrineException::dropSequenceNotSupported($this); + throw DBALException::notSupported(__METHOD__); } public function getSequenceNextValSql($sequenceName) { - throw DoctrineException::sequenceNotSupported($this); + throw DBALException::notSupported(__METHOD__); } public function getCreateDatabaseSql($database) { - throw DoctrineException::createDatabaseNotSupported($this); + throw DBALException::notSupported(__METHOD__); } /** @@ -1322,7 +1322,7 @@ abstract class AbstractPlatform */ public function getSetTransactionIsolationSql($level) { - throw DoctrineException::setTransactionIsolationLevelNotSupported($this); + throw DBALException::notSupported(__METHOD__); } /** @@ -1335,7 +1335,7 @@ abstract class AbstractPlatform */ public function getCharsetFieldDeclaration($charset) { - throw DoctrineException::getCharsetFieldDeclarationNotSupported($this); + throw DBALException::notSupported(__METHOD__); } /** @@ -1347,7 +1347,7 @@ abstract class AbstractPlatform */ public function getDateTimeTypeDeclarationSql(array $fieldDeclaration) { - throw DoctrineException::getDateTimeTypeDeclarationNotSupported($this); + throw DBALException::notSupported(__METHOD__); } /** @@ -1359,7 +1359,7 @@ abstract class AbstractPlatform */ public function getDateTypeDeclarationSql(array $fieldDeclaration) { - throw DoctrineException::getDateTypeDeclarationNotSupported($this); + throw DBALException::notSupported(__METHOD__); } /** diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadata.php b/lib/Doctrine/ORM/Mapping/ClassMetadata.php index 7bd52574d..89dfed979 100644 --- a/lib/Doctrine/ORM/Mapping/ClassMetadata.php +++ b/lib/Doctrine/ORM/Mapping/ClassMetadata.php @@ -70,6 +70,8 @@ final class ClassMetadata extends ClassMetadataInfo $this->namespace = $this->reflClass->getNamespaceName(); $this->primaryTable['name'] = $this->reflClass->getShortName(); $this->rootEntityName = $entityName; + + //$this->prototype = unserialize(sprintf('O:%d:"%s":0:{}', strlen($this->name), $this->name)); } /** @@ -366,5 +368,9 @@ final class ClassMetadata extends ClassMetadataInfo $this->reflFields[$field] = $this->reflClass->getProperty($field); $this->reflFields[$field]->setAccessible(true); } + + //$this->prototype = unserialize(sprintf('O:%d:"%s":0:{}', strlen($this->name), $this->name)); } + + //public $prototype; } diff --git a/lib/Doctrine/ORM/Mapping/OneToOneMapping.php b/lib/Doctrine/ORM/Mapping/OneToOneMapping.php index a61d448df..b9a720778 100644 --- a/lib/Doctrine/ORM/Mapping/OneToOneMapping.php +++ b/lib/Doctrine/ORM/Mapping/OneToOneMapping.php @@ -214,34 +214,33 @@ class OneToOneMapping extends AssociationMapping */ public function load($sourceEntity, $targetEntity, $em, array $joinColumnValues = array()) { - $sourceClass = $em->getClassMetadata($this->sourceEntityName); $targetClass = $em->getClassMetadata($this->targetEntityName); - - $conditions = array(); if ($this->isOwningSide) { - foreach ($this->sourceToTargetKeyColumns as $sourceKeyColumn => $targetKeyColumn) { - if (isset($sourceClass->fieldNames[$sourceKeyColumn])) { - $conditions[$targetKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity); - } else { - $conditions[$targetKeyColumn] = $joinColumnValues[$sourceKeyColumn]; - } + $inverseField = isset($targetClass->inverseMappings[$this->sourceEntityName][$this->sourceFieldName]) ? + $targetClass->inverseMappings[$this->sourceEntityName][$this->sourceFieldName]->sourceFieldName + : false; + + $hints = array(); + if ($inverseField) { + $hints['fetched'][$targetClass->rootEntityName][$inverseField] = true; } + + $targetEntity = $em->getUnitOfWork()->getEntityPersister($this->targetEntityName)->load($joinColumnValues, $targetEntity, $this, $hints); - $targetEntity = $em->getUnitOfWork()->getEntityPersister($this->targetEntityName)->load($conditions, $targetEntity, $this); - - if ($targetEntity !== null && $targetClass->hasInverseAssociationMapping($this->sourceEntityName, $this->sourceFieldName)) { - $targetClass->setFieldValue($targetEntity, - $targetClass->inverseMappings[$this->sourceEntityName][$this->sourceFieldName]->sourceFieldName, - $sourceEntity); + if ($targetEntity !== null && $inverseField) { + $targetClass->reflFields[$inverseField]->setValue($targetEntity, $sourceEntity); } } else { - $owningAssoc = $em->getClassMetadata($this->targetEntityName)->getAssociationMapping($this->mappedByFieldName); + $conditions = array(); + $sourceClass = $em->getClassMetadata($this->sourceEntityName); + $owningAssoc = $targetClass->getAssociationMapping($this->mappedByFieldName); // TRICKY: since the association is specular source and target are flipped foreach ($owningAssoc->targetToSourceKeyColumns as $sourceKeyColumn => $targetKeyColumn) { if (isset($sourceClass->fieldNames[$sourceKeyColumn])) { $conditions[$targetKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity); } else { + //TODO: Should never happen. Exception? $conditions[$targetKeyColumn] = $joinColumnValues[$sourceKeyColumn]; } } diff --git a/lib/Doctrine/ORM/Persisters/StandardEntityPersister.php b/lib/Doctrine/ORM/Persisters/StandardEntityPersister.php index e51a00898..e04776364 100644 --- a/lib/Doctrine/ORM/Persisters/StandardEntityPersister.php +++ b/lib/Doctrine/ORM/Persisters/StandardEntityPersister.php @@ -406,16 +406,18 @@ class StandardEntityPersister * @param array $criteria The criteria by which to load the entity. * @param object $entity The entity to load the data into. If not specified, * a new entity is created. + * @param $assoc The association that connects the entity to load to another entity, if any. + * @param array $hints Hints for entity creation. * @return The loaded entity instance or NULL if the entity/the data can not be found. */ - public function load(array $criteria, $entity = null, $assoc = null) + public function load(array $criteria, $entity = null, $assoc = null, array $hints = array()) { $stmt = $this->_conn->prepare($this->_getSelectEntitiesSql($criteria, $assoc)); $stmt->execute(array_values($criteria)); $result = $stmt->fetch(Connection::FETCH_ASSOC); $stmt->closeCursor(); - return $this->_createEntity($result, $entity); + return $this->_createEntity($result, $entity, $hints); } /** @@ -557,10 +559,11 @@ class StandardEntityPersister * Creates or fills a single entity object from an SQL result. * * @param $result The SQL result. - * @param $entity The entity object to fill. + * @param object $entity The entity object to fill. + * @param array $hints Hints for entity creation. * @return object The filled and managed entity object. */ - private function _createEntity($result, $entity = null) + private function _createEntity($result, $entity = null, array $hints = array()) { if ($result === false) { return null; @@ -582,8 +585,6 @@ class StandardEntityPersister $joinColumnValues[$column] = $value; } } - - $hints = array(); if ($entity !== null) { $hints[Query::HINT_REFRESH] = true; diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php index 51a86e699..3aa25a221 100644 --- a/lib/Doctrine/ORM/UnitOfWork.php +++ b/lib/Doctrine/ORM/UnitOfWork.php @@ -588,23 +588,18 @@ class UnitOfWork implements PropertyChangedListener $this->addToIdentityMap($entry); } - // Collect the original data and changeset, recursing into associations. - $data = array(); - $changeSet = array(); - foreach ($targetClass->reflFields as $name => $refProp) { - $data[$name] = $refProp->getValue($entry); - $changeSet[$name] = array(null, $data[$name]); - if (isset($targetClass->associationMappings[$name])) { - if ($data[$name] !== null) { - $this->_computeAssociationChanges($targetClass->associationMappings[$name], $data[$name]); - } - } - } - // NEW entities are INSERTed within the current unit of work. $this->_entityInsertions[$oid] = $entry; - $this->_entityChangeSets[$oid] = $changeSet; - $this->_originalEntityData[$oid] = $data; + + $this->_computeEntityChanges($targetClass, $entry); + // Look for changes in associations of the entity + foreach ($targetClass->associationMappings as $assoc2) { + $val = $targetClass->reflFields[$assoc2->sourceFieldName]->getValue($entry); + if ($val !== null) { + $this->_computeAssociationChanges($assoc2, $val); + } + } + } else if ($state == self::STATE_REMOVED) { throw DoctrineException::removedEntityInCollectionDetected(); } @@ -1675,6 +1670,7 @@ class UnitOfWork implements PropertyChangedListener $oid = spl_object_hash($entity); $overrideLocalValues = isset($hints[Query::HINT_REFRESH]); } else { + //$entity = clone $class->prototype; $entity = new $className; $oid = spl_object_hash($entity); $this->_entityIdentifiers[$oid] = $id; @@ -1702,7 +1698,7 @@ class UnitOfWork implements PropertyChangedListener if ( ! isset($hints[Query::HINT_FORCE_PARTIAL_LOAD])) { foreach ($class->associationMappings as $field => $assoc) { // Check if the association is not among the fetch-joined associations already. - if (isset($hints['fetched'][$className][$field])) { + if (isset($hints['fetched'][$class->rootEntityName][$field])) { continue; } @@ -1728,16 +1724,21 @@ class UnitOfWork implements PropertyChangedListener if (isset($this->_identityMap[$targetClass->rootEntityName][$relatedIdHash])) { $newValue = $this->_identityMap[$targetClass->rootEntityName][$relatedIdHash]; } else { - $newValue = $this->_em->getProxyFactory()->getProxy($assoc->targetEntityName, $associatedId); - $this->_entityIdentifiers[spl_object_hash($newValue)] = $associatedId; - $this->_identityMap[$targetClass->rootEntityName][$relatedIdHash] = $newValue; + if ($targetClass->subClasses) { + // If it might be a subtype, it can not be lazy + $newValue = $assoc->load($entity, null, $this->_em, $associatedId); + } else { + $newValue = $this->_em->getProxyFactory()->getProxy($assoc->targetEntityName, $associatedId); + $this->_entityIdentifiers[spl_object_hash($newValue)] = $associatedId; + $this->_identityMap[$targetClass->rootEntityName][$relatedIdHash] = $newValue; + } } $this->_originalEntityData[$oid][$field] = $newValue; $class->reflFields[$field]->setValue($entity, $newValue); } } else { // Inverse side can never be lazy - $targetEntity = $assoc->load($entity, new $assoc->targetEntityName, $this->_em); + $targetEntity = $assoc->load($entity, null, $this->_em); $class->reflFields[$field]->setValue($entity, $targetEntity); } } else { diff --git a/tests/Doctrine/Tests/Common/ClassLoaderTest.php b/tests/Doctrine/Tests/Common/ClassLoaderTest.php index e27b54c09..69a5deb0e 100644 --- a/tests/Doctrine/Tests/Common/ClassLoaderTest.php +++ b/tests/Doctrine/Tests/Common/ClassLoaderTest.php @@ -20,7 +20,7 @@ class ClassLoaderTest extends \Doctrine\Tests\DoctrineTestCase $globalClassLoader->register(); } - public function testIsolatedClassLoaderReturnsFalseOnClassExists() + /*public function testIsolatedClassLoaderReturnsFalseOnClassExists() { $classLoader = new IsolatedClassLoader('ClassLoaderTest'); $classLoader->setBasePath( __DIR__); @@ -30,5 +30,5 @@ class ClassLoaderTest extends \Doctrine\Tests\DoctrineTestCase $this->assertEquals($classLoader->loadClass('ClassLoaderTest_ClassA'), true); $this->assertEquals($classLoader->loadClass('ClassLoaderTest_ClassA'), false); $this->assertEquals($classLoader->loadClass('ClassLoaderTest_ClassC'), true); - } + }*/ } \ No newline at end of file diff --git a/tests/Doctrine/Tests/DBAL/Platforms/OraclePlatformTest.php b/tests/Doctrine/Tests/DBAL/Platforms/OraclePlatformTest.php index 60794b7d3..f70313f96 100644 --- a/tests/Doctrine/Tests/DBAL/Platforms/OraclePlatformTest.php +++ b/tests/Doctrine/Tests/DBAL/Platforms/OraclePlatformTest.php @@ -65,7 +65,7 @@ class OraclePlatformTest extends \Doctrine\Tests\DbalTestCase } /** - * @expectedException Doctrine\Common\DoctrineException + * @expectedException Doctrine\DBAL\DBALException */ public function testRLike() { @@ -80,7 +80,7 @@ class OraclePlatformTest extends \Doctrine\Tests\DbalTestCase } /** - * @expectedException Doctrine\Common\DoctrineException + * @expectedException Doctrine\DBAL\DBALException */ public function testGetCharsetFieldDeclaration() { @@ -108,7 +108,7 @@ class OraclePlatformTest extends \Doctrine\Tests\DbalTestCase } /** - * @expectedException Doctrine\Common\DoctrineException + * @expectedException Doctrine\DBAL\DBALException */ public function testShowDatabasesThrowsException() { @@ -116,7 +116,7 @@ class OraclePlatformTest extends \Doctrine\Tests\DbalTestCase } /** - * @expectedException Doctrine\Common\DoctrineException + * @expectedException Doctrine\DBAL\DBALException */ public function testCreateDatabaseThrowsException() { diff --git a/tests/Doctrine/Tests/Models/Company/CompanyEvent.php b/tests/Doctrine/Tests/Models/Company/CompanyEvent.php index 91a9ddb7f..12252a7d1 100644 --- a/tests/Doctrine/Tests/Models/Company/CompanyEvent.php +++ b/tests/Doctrine/Tests/Models/Company/CompanyEvent.php @@ -16,7 +16,7 @@ class CompanyEvent { private $id; /** - * @OneToOne(targetEntity="CompanyOrganization",cascade={"persist"}) + * @ManyToOne(targetEntity="CompanyOrganization",cascade={"persist"}) * @JoinColumn(name="org_id", referencedColumnName="id") */ private $organization; @@ -32,4 +32,5 @@ class CompanyEvent { public function setOrganization(CompanyOrganization $org) { $this->organization = $org; } + } \ No newline at end of file diff --git a/tests/Doctrine/Tests/Models/Company/CompanyOrganization.php b/tests/Doctrine/Tests/Models/Company/CompanyOrganization.php index 15237274a..ce47e8d9e 100644 --- a/tests/Doctrine/Tests/Models/Company/CompanyOrganization.php +++ b/tests/Doctrine/Tests/Models/Company/CompanyOrganization.php @@ -27,4 +27,18 @@ class CompanyOrganization { $this->events[] = $event; $event->setOrganization($this); } + + /** + * @OneToOne(targetEntity="CompanyEvent", cascade={"persist"}) + * @JoinColumn(name="main_event_id", referencedColumnName="id", nullable=true) + */ + private $mainevent; + + public function getMainEvent() { + return $this->mainevent; + } + + public function setMainEvent($event) { + $this->mainevent = $event; + } } \ No newline at end of file diff --git a/tests/Doctrine/Tests/ORM/EntityManagerTest.php b/tests/Doctrine/Tests/ORM/EntityManagerTest.php index e905c6d70..2d44cf8c9 100644 --- a/tests/Doctrine/Tests/ORM/EntityManagerTest.php +++ b/tests/Doctrine/Tests/ORM/EntityManagerTest.php @@ -59,41 +59,6 @@ class EntityManagerTest extends \Doctrine\Tests\OrmTestCase $this->assertEquals(\Doctrine\ORM\EntityManager::FLUSHMODE_COMMIT, $this->_em->getFlushMode()); } - public function testCommit_FlushModeOnCommit_FlushUnitOfWork() - { - $this->markTestSkipped('_unitOfWork is private, but EntityManager does not use getUnitofWork() all the time'); - - $uow = $this->getMock('\Doctrine\ORM\UnitOfWork', array(), array(), '', false); - $uow->expects($this->once()) - ->method('flush'); - - $this->_em->setUnitOfWork($uow); - $this->_em->setFlushMode(\Doctrine\ORM\EntityManager::FLUSHMODE_COMMIT); - - $this->assertSame($uow, $this->_em->getUnitOfWork()); - - $this->_em->beginTransaction(); - $this->_em->commit(); - } - - - public function testCommit_FlushModeAuto_FlushUnitOfWork() - { - $this->markTestSkipped('_unitOfWork is private, but EntityManager does not use getUnitofWork() all the time'); - - $uow = $this->getMock('\Doctrine\ORM\UnitOfWork', array(), array(), '', false); - $uow->expects($this->once()) - ->method('flush'); - - $this->_em->setUnitOfWork($uow); - $this->_em->setFlushMode(\Doctrine\ORM\EntityManager::FLUSHMODE_AUTO); - - $this->assertSame($uow, $this->_em->getUnitOfWork()); - - $this->_em->beginTransaction(); - $this->_em->commit(); - } - public function testCreateNativeQuery() { $rsm = new \Doctrine\ORM\Query\ResultSetMapping(); diff --git a/tests/Doctrine/Tests/ORM/Functional/AllTests.php b/tests/Doctrine/Tests/ORM/Functional/AllTests.php index 738840a2a..36c8f0872 100644 --- a/tests/Doctrine/Tests/ORM/Functional/AllTests.php +++ b/tests/Doctrine/Tests/ORM/Functional/AllTests.php @@ -24,6 +24,7 @@ class AllTests $suite->addTestSuite('Doctrine\Tests\ORM\Functional\NativeQueryTest'); $suite->addTestSuite('Doctrine\Tests\ORM\Functional\SingleTableInheritanceTest'); $suite->addTestSuite('Doctrine\Tests\ORM\Functional\ClassTableInheritanceTest'); + $suite->addTestSuite('Doctrine\Tests\ORM\Functional\ClassTableInheritanceTest2'); $suite->addTestSuite('Doctrine\Tests\ORM\Functional\DetachedEntityTest'); $suite->addTestSuite('Doctrine\Tests\ORM\Functional\QueryCacheTest'); $suite->addTestSuite('Doctrine\Tests\ORM\Functional\ResultCacheTest'); diff --git a/tests/Doctrine/Tests/ORM/Functional/ClassTableInheritanceTest.php b/tests/Doctrine/Tests/ORM/Functional/ClassTableInheritanceTest.php index 4e36f4920..31c8d2226 100644 --- a/tests/Doctrine/Tests/ORM/Functional/ClassTableInheritanceTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/ClassTableInheritanceTest.php @@ -224,6 +224,7 @@ class ClassTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->assertEquals(1, count($result)); $this->assertTrue($result[0] instanceof CompanyOrganization); + $this->assertNull($result[0]->getMainEvent()); $events = $result[0]->getEvents(); @@ -238,4 +239,40 @@ class ClassTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->assertTrue($events[1] instanceof CompanyAuction); } } + + + public function testLazyLoading2() + { + $org = new CompanyOrganization; + $event1 = new CompanyAuction; + $event1->setData('auction'); + $org->setMainEvent($event1); + + $this->_em->persist($org); + $this->_em->flush(); + $this->_em->clear(); + + $q = $this->_em->createQuery('select a from Doctrine\Tests\Models\Company\CompanyEvent a where a.id = ?1'); + $q->setParameter(1, $event1->getId()); + + $result = $q->getResult(); + $this->assertEquals(1, count($result)); + $this->assertTrue($result[0] instanceof CompanyAuction, sprintf("Is of class %s",get_class($result[0]))); + + $this->_em->clear(); + + $q = $this->_em->createQuery('select a from Doctrine\Tests\Models\Company\CompanyOrganization a where a.id = ?1'); + $q->setParameter(1, $org->getId()); + + $result = $q->getResult(); + + $this->assertEquals(1, count($result)); + $this->assertTrue($result[0] instanceof CompanyOrganization); + + $mainEvent = $result[0]->getMainEvent(); + // mainEvent should have been loaded because it can't be lazy + $this->assertTrue($mainEvent instanceof CompanyAuction); + $this->assertFalse($mainEvent instanceof \Doctrine\ORM\Proxy\Proxy); + } + } diff --git a/tests/Doctrine/Tests/ORM/Functional/ClassTableInheritanceTest2.php b/tests/Doctrine/Tests/ORM/Functional/ClassTableInheritanceTest2.php new file mode 100644 index 000000000..e7585b614 --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Functional/ClassTableInheritanceTest2.php @@ -0,0 +1,129 @@ +_schemaTool->createSchema(array( + $this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\CTIParent'), + $this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\CTIChild'), + $this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\CTIRelated') + )); + } catch (\Exception $e) { + // Swallow all exceptions. We do not test the schema tool here. + } + } + + public function testOneToOneAssocToBaseTypeBidirectional() + { + $child = new CTIChild; + $child->setData('hello'); + + $related = new CTIRelated; + $related->setCTIParent($child); + + $this->_em->persist($related); + $this->_em->persist($child); + + $this->_em->flush(); + $this->_em->clear(); + + $relatedId = $related->getId(); + + $related2 = $this->_em->find('Doctrine\Tests\ORM\Functional\CTIRelated', $relatedId); + + $this->assertTrue($related2 instanceof CTIRelated); + $this->assertTrue($related2->getCTIParent() instanceof CTIChild); + $this->assertFalse($related2->getCTIParent() instanceof \Doctrine\ORM\Proxy\Proxy); + $this->assertEquals('hello', $related2->getCTIParent()->getData()); + + $this->assertSame($related2, $related2->getCTIParent()->getRelated()); + } + +} + +/** + * @Entity @Table(name="cti_parents") + * @InheritanceType("JOINED") + * @DiscriminatorColumn(name="type", type="string") + * @DiscriminatorMap({"parent" = "CTIParent", "child" = "CTIChild"}) + */ +class CTIParent { + /** + * @Id @Column(type="integer") + * @GeneratedValue(strategy="AUTO") + */ + private $id; + + /** @OneToOne(targetEntity="CTIRelated", mappedBy="ctiParent") */ + private $related; + + public function getId() { + return $this->id; + } + + public function getRelated() { + return $this->related; + } + + public function setRelated($related) { + $this->related = $related; + $related->setCTIParent($this); + } +} + +/** + * @Entity @Table(name="cti_children") + */ +class CTIChild extends CTIParent { + /** + * @Column(type="string") + */ + private $data; + + public function getData() { + return $this->data; + } + + public function setData($data) { + $this->data = $data; + } + +} + +/** @Entity */ +class CTIRelated { + /** + * @Id @Column(type="integer") + * @GeneratedValue(strategy="AUTO") + */ + private $id; + + /** + * @OneToOne(targetEntity="CTIParent") + * @JoinColumn(name="ctiparent_id", referencedColumnName="id") + */ + private $ctiParent; + + public function getId() { + return $this->id; + } + + public function getCTIParent() { + return $this->ctiParent; + } + + public function setCTIParent($ctiParent) { + $this->ctiParent = $ctiParent; + } +} diff --git a/tests/Doctrine/Tests/OrmFunctionalTestCase.php b/tests/Doctrine/Tests/OrmFunctionalTestCase.php index 3150c8052..6e9af81d4 100644 --- a/tests/Doctrine/Tests/OrmFunctionalTestCase.php +++ b/tests/Doctrine/Tests/OrmFunctionalTestCase.php @@ -104,6 +104,7 @@ class OrmFunctionalTestCase extends OrmTestCase $conn->executeUpdate('DELETE FROM company_persons'); $conn->executeUpdate('DELETE FROM company_raffles'); $conn->executeUpdate('DELETE FROM company_auctions'); + $conn->executeUpdate('UPDATE company_organizations SET main_event_id = NULL'); $conn->executeUpdate('DELETE FROM company_events'); $conn->executeUpdate('DELETE FROM company_organizations'); }