From deb095f2c8497eb26597f163f3af220d88cee423 Mon Sep 17 00:00:00 2001 From: romanb Date: Thu, 5 Feb 2009 17:34:44 +0000 Subject: [PATCH] Some cleanups, docblocks, and a small needed refactoring of ClassMetadataFactory. --- LICENSE | 2 +- .../DBAL/Platforms/AbstractPlatform.php | 84 ++++- .../DBAL/Platforms/SqlitePlatform.php | 24 +- .../DBAL/Schema/AbstractSchemaManager.php | 4 +- .../DBAL/Schema/SqliteSchemaManager.php | 2 +- lib/Doctrine/ORM/Entity.php | 35 --- lib/Doctrine/ORM/Export/ClassExporter.php | 6 +- lib/Doctrine/ORM/Id/Assigned.php | 2 +- .../ORM/Internal/Hydration/ArrayDriver.php | 168 ---------- .../ORM/Internal/Hydration/ObjectDriver.php | 257 --------------- .../Internal/Hydration/StandardHydrator.php | 294 ------------------ lib/Doctrine/ORM/Internal/Null.php | 65 ---- lib/Doctrine/ORM/Mapping/ClassMetadata.php | 15 +- .../ORM/Mapping/ClassMetadataFactory.php | 116 +++---- .../ORM/Mapping/Driver/AnnotationDriver.php | 16 + lib/Doctrine/ORM/Mapping/OneToManyMapping.php | 4 +- lib/Doctrine/ORM/Mapping/OneToOneMapping.php | 2 + lib/Doctrine/ORM/PersistentCollection.php | 2 - .../ORM/Persisters/ManyToManyPersister.php | 21 +- .../ORM/Persisters/OneToManyPersister.php | 21 ++ lib/Doctrine/ORM/Query.php | 5 +- lib/Doctrine/ORM/Query/SqlWalker.php | 13 +- .../Tests/Mocks/EntityManagerMock.php | 19 ++ .../Tests/Mocks/MetadataDriverMock.php | 6 +- tests/Doctrine/Tests/ORM/UnitOfWorkTest.php | 5 - 25 files changed, 241 insertions(+), 947 deletions(-) delete mode 100644 lib/Doctrine/ORM/Entity.php delete mode 100644 lib/Doctrine/ORM/Internal/Hydration/ArrayDriver.php delete mode 100644 lib/Doctrine/ORM/Internal/Hydration/ObjectDriver.php delete mode 100644 lib/Doctrine/ORM/Internal/Hydration/StandardHydrator.php delete mode 100644 lib/Doctrine/ORM/Internal/Null.php diff --git a/LICENSE b/LICENSE index 5e4900d99..657534976 100644 --- a/LICENSE +++ b/LICENSE @@ -13,4 +13,4 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. This software consists of voluntary contributions made by many individuals -and is licensed under the LGPL. For more information, see . \ No newline at end of file +and is licensed under the LGPL. For more information, see . \ No newline at end of file diff --git a/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php b/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php index 04d5f335c..161d743b6 100644 --- a/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php +++ b/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php @@ -54,12 +54,20 @@ abstract class AbstractPlatform * Constructor. */ public function __construct() {} - + + /** + * Sets whether to quote identifiers. + */ public function setQuoteIdentifiers($bool) { $this->_quoteIdentifiers = (bool)$bool; } - + + /** + * Gets whether to quote identifiers. + * + * @return boolean + */ public function getQuoteIdentifiers() { return $this->_quoteIdentifiers; @@ -1752,7 +1760,7 @@ abstract class AbstractPlatform * @return string * @todo Remove the ORM dependency */ - public function writeLimitClauseInSubquery(Doctrine_ClassMetadata $rootClass, + public function writeLimitClauseInSubquery(\Doctrine\ORM\Mapping\ClassMetadata $rootClass, $query, $limit = false, $offset = false) { return $this->modifyLimitQuery($query, $limit, $offset); @@ -1778,7 +1786,6 @@ abstract class AbstractPlatform * Default conversion defined here converts to integers. * * @param array $item - * @return void */ public function convertBooleans($item) { @@ -1797,9 +1804,9 @@ abstract class AbstractPlatform } /** - * Enter description here... + * Gets the SQL statement specific for the platform to set the charset. * - * @param unknown_type $charset + * @param string $charset * @return string */ public function getSetCharsetSql($charset) @@ -1810,7 +1817,7 @@ abstract class AbstractPlatform /** * Enter description here... * - * @param unknown_type $level + * @param integer $level */ protected function _getTransactionIsolationLevelSql($level) { @@ -1831,7 +1838,7 @@ abstract class AbstractPlatform /** * Enter description here... * - * @param unknown_type $level + * @param integer $level */ public function getSetTransactionIsolationSql($level) { @@ -1842,7 +1849,7 @@ abstract class AbstractPlatform * Gets the default transaction isolation level of the platform. * * @return integer The default isolation level. - * @see Doctrine::DBAL::Connection::TRANSACTION_* constants. + * @see Doctrine\DBAL\Connection\TRANSACTION_* constants. */ public function getDefaultTransactionIsolationLevel() { @@ -1851,42 +1858,85 @@ abstract class AbstractPlatform /* supports*() metods */ - + + /** + * Whether the platform supports sequences. + * + * @return boolean + */ public function supportsSequences() { return false; } - + + /** + * Whether the platform supports identity columns. + * Identity columns are columns that recieve an auto-generated value from the + * database on insert of a row. + * + * @return boolean + */ public function supportsIdentityColumns() { return false; } - + + /** + * Whether the platform supports indexes. + * + * @return boolean + */ public function supportsIndexes() { return true; } - + + /** + * Whether the platform supports transactions. + * + * @return boolean + */ public function supportsTransactions() { return true; } - + + /** + * Whether the platform supports savepoints. + * + * @return boolean + */ public function supportsSavepoints() { return true; } - + + /** + * Whether the platform supports primary key constraints. + * + * @return boolean + */ public function supportsPrimaryConstraints() { return true; } - + + /** + * Whether the platform supports foreign key constraints. + * + * @return boolean + */ public function supportsForeignKeyConstraints() { return true; } - + + /** + * Whether the platform supports getting the affected rows or a recent + * update/delete type query. + * + * @return boolean + */ public function supportsGettingAffectedRows() { return true; diff --git a/lib/Doctrine/DBAL/Platforms/SqlitePlatform.php b/lib/Doctrine/DBAL/Platforms/SqlitePlatform.php index 30e3df91f..c8ca3b318 100644 --- a/lib/Doctrine/DBAL/Platforms/SqlitePlatform.php +++ b/lib/Doctrine/DBAL/Platforms/SqlitePlatform.php @@ -1,9 +1,29 @@ . + */ namespace Doctrine\DBAL\Platforms; /** - * Enter description here... + * The SqlitePlatform class describes the specifics and dialects of the SQLite + * database platform. * * @since 2.0 */ @@ -537,7 +557,7 @@ class SqlitePlatform extends AbstractPlatform * This really limits their usefulness and requires SQLite specific handling, so * we simply say that SQLite does NOT support foreign keys for now... * - * @return boolean + * @return boolean FALSE * @override */ public function supportsForeignKeyConstraints() diff --git a/lib/Doctrine/DBAL/Schema/AbstractSchemaManager.php b/lib/Doctrine/DBAL/Schema/AbstractSchemaManager.php index cc1b3c5f2..d27b19c7a 100644 --- a/lib/Doctrine/DBAL/Schema/AbstractSchemaManager.php +++ b/lib/Doctrine/DBAL/Schema/AbstractSchemaManager.php @@ -16,14 +16,14 @@ * * This software consists of voluntary contributions made by many individuals * and is licensed under the LGPL. For more information, see - * . + * . */ namespace Doctrine\DBAL\Schema; /** * Base class for schema managers. Schema managers are used to inspect and/or - * modify the database schema. + * modify the database schema/structure. * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @author Konsta Vesterinen diff --git a/lib/Doctrine/DBAL/Schema/SqliteSchemaManager.php b/lib/Doctrine/DBAL/Schema/SqliteSchemaManager.php index f3c93628d..04f221d1f 100644 --- a/lib/Doctrine/DBAL/Schema/SqliteSchemaManager.php +++ b/lib/Doctrine/DBAL/Schema/SqliteSchemaManager.php @@ -16,7 +16,7 @@ * * This software consists of voluntary contributions made by many individuals * and is licensed under the LGPL. For more information, see - * . + * . */ namespace Doctrine\DBAL\Schema; diff --git a/lib/Doctrine/ORM/Entity.php b/lib/Doctrine/ORM/Entity.php deleted file mode 100644 index ced9de006..000000000 --- a/lib/Doctrine/ORM/Entity.php +++ /dev/null @@ -1,35 +0,0 @@ -. - */ - -#namespace Doctrine\ORM; - -/** - * Entity marker interface. - * - * @author Roman Borschel - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.org - * @since 2.0 - * @version $Revision: 4342 $ - * @DEPRECATED - */ -interface Doctrine_ORM_Entity -{} diff --git a/lib/Doctrine/ORM/Export/ClassExporter.php b/lib/Doctrine/ORM/Export/ClassExporter.php index 523c1d2d2..d66a9e580 100644 --- a/lib/Doctrine/ORM/Export/ClassExporter.php +++ b/lib/Doctrine/ORM/Export/ClassExporter.php @@ -1,6 +1,6 @@ . + * . */ namespace Doctrine\ORM\Export; @@ -27,8 +27,6 @@ use Doctrine\ORM\EntityManager; * The ClassExporter can generate database schemas/structures from ClassMetadata * class descriptors. * - * @package Doctrine - * @subpackage Export * @author Konsta Vesterinen * @author Lukas Smith (PEAR MDB2 library) * @author Roman Borschel diff --git a/lib/Doctrine/ORM/Id/Assigned.php b/lib/Doctrine/ORM/Id/Assigned.php index ed718cda3..9174b27b3 100644 --- a/lib/Doctrine/ORM/Id/Assigned.php +++ b/lib/Doctrine/ORM/Id/Assigned.php @@ -34,7 +34,7 @@ class Assigned extends AbstractIdGenerator /** * Returns the identifier assigned to the given entity. * - * @param Doctrine\ORM\Entity $entity + * @param object $entity * @return mixed * @override */ diff --git a/lib/Doctrine/ORM/Internal/Hydration/ArrayDriver.php b/lib/Doctrine/ORM/Internal/Hydration/ArrayDriver.php deleted file mode 100644 index 36575ad2f..000000000 --- a/lib/Doctrine/ORM/Internal/Hydration/ArrayDriver.php +++ /dev/null @@ -1,168 +0,0 @@ -. - */ - -#namespace Doctrine\ORM\Internal\Hydration; - -/** - * Defines an array hydration strategy. - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.phpdoctrine.org - * @since 1.0 - * @version $Revision$ - * @author Konsta Vesterinen - * @author Roman Borschel - * @DEPRECATED - */ -class Doctrine_ORM_Internal_Hydration_ArrayDriver -{ - /** - * - */ - public function getElementCollection($component) - { - return array(); - } - - /** - * - */ - public function getElement(array $data, $component) - { - return $data; - } - - /** - * - */ - public function registerCollection($coll) - { /* Nothing to do */ } - - /** - * - */ - public function initRelatedCollection(array &$data, $name) - { - if ( ! isset($data[$name])) { - $data[$name] = array(); - } - } - - public function addRelatedIndexedElement(array &$entity1, $property, array &$entity2, $indexField) - { - $entity1[$property][$entity2[$indexField]] = $entity2; - } - - public function addRelatedElement(array &$entity1, $property, array &$entity2) - { - $entity1[$property][] = $entity2; - } - - public function setRelatedElement(array &$entity1, $property, &$entity2) - { - $entity1[$property] = $entity2; - } - - public function isIndexKeyInUse(array &$entity, $assocField, $indexField) - { - return isset($entity[$assocField][$indexField]); - } - - public function isFieldSet(array &$entity, $field) - { - return isset($entity[$field]); - } - - public function getFieldValue(array &$entity, $field) - { - return $entity[$field]; - } - - public function &getReferenceValue(array &$entity, $field) - { - return $entity[$field]; - } - - public function addElementToIndexedCollection(array &$coll, array &$entity, $keyField) - { - $coll[$entity[$keyField]] = $entity; - } - - public function addElementToCollection(array &$coll, array &$entity) - { - $coll[] = $entity; - } - - /** - * - */ - public function getNullPointer() - { - return null; - } - - /** - * - */ - public function getLastKey(&$data) - { - end($data); - return key($data); - } - - /** - * Updates the result pointer for an Entity. The result pointers point to the - * last seen instance of each Entity type. This is used for graph construction. - * - * @param array $resultPointers The result pointers. - * @param array $coll The element. - * @param boolean|integer $index Index of the element in the collection. - * @param string $dqlAlias - * @param boolean $oneToOne Whether it is a single-valued association or not. - */ - public function updateResultPointer(&$resultPointers, &$coll, $index, $dqlAlias, $oneToOne) - { - if ($coll === null) { - unset($resultPointers[$dqlAlias]); // Ticket #1228 - return; - } - - if ($index !== false) { - $resultPointers[$dqlAlias] =& $coll[$index]; - return; - } - - if ($coll) { - if ($oneToOne) { - $resultPointers[$dqlAlias] =& $coll; - } else { - end($coll); - $resultPointers[$dqlAlias] =& $coll[key($coll)]; - } - } - } - - /** - * - */ - public function flush() - { /* Nothing to do */ } -} diff --git a/lib/Doctrine/ORM/Internal/Hydration/ObjectDriver.php b/lib/Doctrine/ORM/Internal/Hydration/ObjectDriver.php deleted file mode 100644 index c17dc687c..000000000 --- a/lib/Doctrine/ORM/Internal/Hydration/ObjectDriver.php +++ /dev/null @@ -1,257 +0,0 @@ -. - */ - -#namespace Doctrine\ORM\Internal\Hydration; - -/** - * Defines the object hydration strategy. - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.org - * @since 1.0 - * @version $Revision$ - * @author Konsta Vesterinen - * @author Roman Borschel - * @internal All the methods in this class are performance-sentitive. - * @DEPRECATED - */ -class Doctrine_ORM_Internal_Hydration_ObjectDriver -{ - /** Collections initialized by the driver */ - protected $_collections = array(); - /** Memory for initialized relations */ - private $_initializedRelations = array(); - /** Null object */ - //private $_nullObject; - /** The EntityManager */ - private $_em; - private $_uow; - private $_metadataMap = array(); - private $_entityData = array(); - - public function __construct(Doctrine_ORM_EntityManager $em) - { - //$this->_nullObject = Doctrine_ORM_Internal_Null::$INSTANCE; - $this->_em = $em; - $this->_uow = $this->_em->getUnitOfWork(); - } - - public function getElementCollection($component) - { - $coll = new Doctrine_ORM_Collection($this->_em, $component); - $this->_collections[] = $coll; - return $coll; - } - - public function getLastKey($coll) - { - // check needed because of mixed results. - // is_object instead of is_array because is_array is slow on large arrays. - if (is_object($coll)) { - $coll->last(); - return $coll->key(); - } else { - end($coll); - return key($coll); - } - } - - public function initRelatedCollection($entity, $name) - { - $oid = spl_object_hash($entity); - $classMetadata = $this->_metadataMap[$oid]; - if ( ! isset($this->_initializedRelations[$oid][$name])) { - $relation = $classMetadata->getAssociationMapping($name); - $relatedClass = $this->_em->getClassMetadata($relation->getTargetEntityName()); - $coll = $this->getElementCollection($relatedClass->getClassName()); - $coll->_setOwner($entity, $relation); - $coll->_setHydrationFlag(true); - $classMetadata->getReflectionProperty($name)->setValue($entity, $coll); - $this->_initializedRelations[$oid][$name] = true; - $this->_uow->setOriginalEntityProperty($oid, $name, $coll); - } - } - - public function registerCollection(Doctrine_ORM_Collection $coll) - { - $this->_collections[] = $coll; - } - - public function getNullPointer() - { - //TODO: Return VirtualProxy if lazy association - return null; - } - - public function getElement(array $data, $className) - { - $entity = $this->_em->getUnitOfWork()->createEntity($className, $data); - $oid = spl_object_hash($entity); - $this->_metadataMap[$oid] = $this->_em->getClassMetadata($className); - return $entity; - } - - /** - * Adds an element to an indexed collection-valued property. - * - * @param $entity1 - * @param $property - * @param $entity2 - * @param $indexField - */ - public function addRelatedIndexedElement($entity1, $property, $entity2, $indexField) - { - $classMetadata1 = $this->_metadataMap[spl_object_hash($entity1)]; - $classMetadata2 = $this->_metadataMap[spl_object_hash($entity2)]; - $indexValue = $classMetadata2->getReflectionProperty($indexField)->getValue($entity2); - $classMetadata1->getReflectionProperty($property)->getValue($entity1)->set($indexValue, $entity2); - } - - /** - * Adds an element to a collection-valued property. - * - * @param $entity1 - * @param $property - * @param $entity2 - */ - public function addRelatedElement($entity1, $property, $entity2) - { - $classMetadata1 = $this->_metadataMap[spl_object_hash($entity1)]; - $classMetadata1->getReflectionProperty($property)->getValue($entity1)->add($entity2); - } - - /** - * Sets a related element. - * - * @param $entity1 - * @param $property - * @param $entity2 - */ - public function setRelatedElement($entity1, $property, $entity2) - { - $oid = spl_object_hash($entity1); - $classMetadata1 = $this->_metadataMap[$oid]; - $classMetadata1->getReflectionProperty($property)->setValue($entity1, $entity2); - $this->_uow->setOriginalEntityProperty($oid, $property, $entity2); - $relation = $classMetadata1->getAssociationMapping($property); - if ($relation->isOneToOne()) { - $targetClass = $this->_em->getClassMetadata($relation->getTargetEntityName()); - if ($relation->isOwningSide()) { - // If there is an inverse mapping on the target class its bidirectional - if ($targetClass->hasInverseAssociationMapping($property)) { - $oid2 = spl_object_hash($entity2); - $sourceProp = $targetClass->getInverseAssociationMapping($fieldName)->getSourceFieldName(); - $targetClass->getReflectionProperty($sourceProp)->setValue($entity2, $entity1); - //$this->_entityData[$oid2][$sourceProp] = $entity1; - } - } else { - // for sure bidirectional, as there is no inverse side in unidirectional - $mappedByProp = $relation->getMappedByFieldName(); - $targetClass->getReflectionProperty($mappedByProp)->setValue($entity2, $entity1); - //$this->_entityData[spl_object_hash($entity2)][$mappedByProp] = $entity1; - } - } - } - - public function isIndexKeyInUse($entity, $assocField, $indexField) - { - return $this->_metadataMap[spl_object_hash($entity)]->getReflectionProperty($assocField) - ->getValue($entity)->containsKey($indexField); - } - - public function isFieldSet($entity, $field) - { - return $this->_metadataMap[spl_object_hash($entity)]->getReflectionProperty($field) - ->getValue($entity) !== null; - } - - public function getFieldValue($entity, $field) - { - return $this->_metadataMap[spl_object_hash($entity)]->getReflectionProperty($field) - ->getValue($entity); - } - - public function getReferenceValue($entity, $field) - { - return $this->_metadataMap[spl_object_hash($entity)]->getReflectionProperty($field) - ->getValue($entity); - } - - public function addElementToIndexedCollection($coll, $entity, $keyField) - { - $coll->set($entity, $this->getFieldValue($keyField, $entity)); - } - - public function addElementToCollection($coll, $entity) - { - $coll->add($entity); - } - - /** - * Updates the result pointer for an Entity. The result pointers point to the - * last seen instance of each Entity type. This is used for graph construction. - * - * @param array $resultPointers The result pointers. - * @param Collection $coll The element. - * @param boolean|integer $index Index of the element in the collection. - * @param string $dqlAlias - * @param boolean $oneToOne Whether it is a single-valued association or not. - */ - public function updateResultPointer(&$resultPointers, &$coll, $index, $dqlAlias, $oneToOne) - { - if ($coll === null) { - unset($resultPointers[$dqlAlias]); // Ticket #1228 - return; - } - - if ($index !== false) { - $resultPointers[$dqlAlias] = $coll[$index]; - return; - } - - if ( ! is_object($coll)) { - end($coll); - $resultPointers[$dqlAlias] =& $coll[key($coll)]; - } else if ($coll instanceof Doctrine_ORM_Collection) { - if (count($coll) > 0) { - $resultPointers[$dqlAlias] = $coll->last(); - } - } else { - $resultPointers[$dqlAlias] = $coll; - } - } - - public function flush() - { - // take snapshots from all initialized collections - foreach ($this->_collections as $coll) { - $coll->_takeSnapshot(); - $coll->_setHydrationFlag(false); - $this->_uow->addManagedCollection($coll); - } - // clean up - $this->_collections = array(); - $this->_initializedRelations = array(); - $this->_metadataMap = array(); - $this->_entityData = array(); - } - -} diff --git a/lib/Doctrine/ORM/Internal/Hydration/StandardHydrator.php b/lib/Doctrine/ORM/Internal/Hydration/StandardHydrator.php deleted file mode 100644 index 88fd3554a..000000000 --- a/lib/Doctrine/ORM/Internal/Hydration/StandardHydrator.php +++ /dev/null @@ -1,294 +0,0 @@ -. - */ - -#namespace Doctrine\ORM\Internal\Hydration; - -/** - * The hydrator has the tedious task to process result sets returned by the database - * and turn them into useable structures. - * - * Runtime complexity: The following gives the overall number of iterations - * required to process a result set when using identity hydration - * (HYDRATE_IDENTITY_OBJECT or HYDRATE_IDENTITY_ARRAY). - * - * numRowsInResult * numColumnsInResult + numRowsInResult * numClassesInQuery - * - * This comes down to: - * - * (numRowsInResult * (numColumnsInResult + numClassesInQuery)) - * - * For scalar hydration (HYDRATE_SCALAR) it's: - * - * numRowsInResult * numColumnsInResult - * - * Note that this is only a crude definition as it also heavily - * depends on the complexity of all the single operations that are performed in - * each iteration. - * - * As can be seen, the number of columns in the result has the most impact on - * the overall performance (apart from the row count, of course), since numClassesInQuery - * is usually pretty low. - * That's why the performance of the _gatherRowData() methods which are responsible - * for the "numRowsInResult * numColumnsInResult" part is crucial to fast hydration. - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.org - * @since 1.0 - * @version $Revision: 3192 $ - * @author Konsta Vesterinen - * @author Roman Borschel - * @DEPRECATED - */ -class Doctrine_ORM_Internal_Hydration_StandardHydrator extends Doctrine_ORM_Internal_Hydration_AbstractHydrator -{ - /** - * Parses the data returned by statement object. - * - * This is method defines the core of Doctrine's object population algorithm. - * - * @param array $aliasMap Array that maps DQL aliases to their components - * (DQL alias => array( - * 'metadata' => Table object, - * 'parent' => Parent DQL alias (if any), - * 'relation' => Relation object (if any), - * 'map' => Custom index to use as the key in the result (if any), - * 'agg' => List of aggregate value names (sql alias => dql alias) - * ) - * ) - * @return mixed The created object/array graph. - * @throws Doctrine_Hydrator_Exception If the hydration process failed. - */ - public function hydrateResultSet($parserResult) - { - if ($parserResult->getHydrationMode() === null) { - $hydrationMode = $this->_hydrationMode; - } else { - $hydrationMode = $parserResult->getHydrationMode(); - } - - $stmt = $parserResult->getDatabaseStatement(); - - if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_NONE) { - return $stmt->fetchAll(PDO::FETCH_NUM); - } - - $this->_tableAliases = $parserResult->getTableToClassAliasMap(); - $this->_queryComponents = $parserResult->getQueryComponents(); - - if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY) { - $driver = new Doctrine_ORM_Internal_Hydration_ArrayDriver(); - } else { - $driver = new Doctrine_ORM_Internal_Hydration_ObjectDriver($this->_em); - } - - $s = microtime(true); - - reset($this->_queryComponents); - $rootAlias = key($this->_queryComponents); - $rootEntityName = $this->_queryComponents[$rootAlias]['metadata']->getClassName(); - // if only one class is involved we can make our lives easier - $isSimpleQuery = count($this->_queryComponents) <= 1; - // Lookup map to quickly discover/lookup existing entities in the result - // It's the identifier "memory" - $identifierMap = array(); - // Holds for each class a pointer to the last previously seen element in the result set - $resultPointers = array(); - // Holds the values of the identifier/primary key fields of entities, - // separated by a pipe '|' and grouped by DQL class alias (r, u, i, ... whatever) - // The $idTemplate is a prepared template. $id is set to a fresh template when - // starting to process a row. - $id = array(); - $idTemplate = array(); - - if ($parserResult->isMixedQuery() || $hydrationMode == Doctrine_ORM_Query::HYDRATE_SCALAR) { - $result = array(); - } else { - $result = $driver->getElementCollection($rootEntityName); - } - - if ($stmt === false || $stmt === 0) { - return $result; - } - - // Initialize - foreach ($this->_queryComponents as $dqlAlias => $component) { - $identifierMap[$dqlAlias] = array(); - $resultPointers[$dqlAlias] = array(); - $idTemplate[$dqlAlias] = ''; - } - - $cache = array(); - // Evaluate HYDRATE_SINGLE_SCALAR - if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_SINGLE_SCALAR) { - $result = $stmt->fetchAll(PDO::FETCH_ASSOC); - //TODO: Let this exception be raised by Query as QueryException - if (count($result) > 1 || count($result[0]) > 1) { - throw Doctrine_ORM_Exceptions_HydrationException::nonUniqueResult(); - } - $result = $this->_gatherScalarRowData($result[0], $cache); - return array_shift($result); - } - - $resultCounter = 0; - // Process result set - while ($data = $stmt->fetch(PDO::FETCH_ASSOC)) { - // Evaluate HYDRATE_SCALAR - if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_SCALAR) { - $result[] = $this->_gatherScalarRowData($data, $cache); - continue; - } - - // From here on its all about graph construction - - // 1) Initialize - $id = $idTemplate; // initialize the id-memory - $nonemptyComponents = array(); - $rowData = $this->_gatherRowData($data, $cache, $id, $nonemptyComponents); - - // 2) Hydrate the data of the root entity from the current row - // Check for an existing element - $index = false; - if ($isSimpleQuery || ! isset($identifierMap[$rootAlias][$id[$rootAlias]])) { - $element = $driver->getElement($rowData[$rootAlias], $rootEntityName); - if ($field = $this->_getCustomIndexField($rootAlias)) { - if ($parserResult->isMixedQuery()) { - $result[] = array( - $driver->getFieldValue($element, $field) => $element - ); - ++$resultCounter; - } else { - $driver->addElementToIndexedCollection($result, $element, $field); - } - } else { - if ($parserResult->isMixedQuery()) { - $result[] = array($element); - ++$resultCounter; - } else { - $driver->addElementToCollection($result, $element); - } - } - $identifierMap[$rootAlias][$id[$rootAlias]] = $driver->getLastKey($result); - } else { - $index = $identifierMap[$rootAlias][$id[$rootAlias]]; - } - $driver->updateResultPointer($resultPointers, $result, $index, $rootAlias, false); - unset($rowData[$rootAlias]); - // end hydrate data of the root component for the current row - - // Extract scalar values. They're appended at the end. - if (isset($rowData['scalars'])) { - $scalars = $rowData['scalars']; - unset($rowData['scalars']); - } - - // 3) Now hydrate the rest of the data found in the current row, that - // belongs to other (related) entities. - foreach ($rowData as $dqlAlias => $data) { - $index = false; - $map = $this->_queryComponents[$dqlAlias]; - $entityName = $map['metadata']->getClassName(); - $parent = $map['parent']; - $relation = $map['relation']; - $relationAlias = $relation->getSourceFieldName(); - $path = $parent . '.' . $dqlAlias; - - // Get a reference to the right element in the result tree. - // This element will get the associated element attached. - if ($parserResult->isMixedQuery() && $parent == $rootAlias) { - $key = key(reset($resultPointers)); - // TODO: Exception if $key === null ? - $baseElement =& $resultPointers[$parent][$key]; - } else if (isset($resultPointers[$parent])) { - $baseElement =& $resultPointers[$parent]; - } else { - unset($resultPointers[$dqlAlias]); // Ticket #1228 - continue; - } - - // Check the type of the relation (many or single-valued) - if ( ! $relation->isOneToOne()) { - // x-to-many relation - $oneToOne = false; - if (isset($nonemptyComponents[$dqlAlias])) { - $driver->initRelatedCollection($baseElement, $relationAlias); - $indexExists = isset($identifierMap[$path][$id[$parent]][$id[$dqlAlias]]); - $index = $indexExists ? $identifierMap[$path][$id[$parent]][$id[$dqlAlias]] : false; - $indexIsValid = $index !== false ? $driver->isIndexKeyInUse($baseElement, $relationAlias, $index) : false; - if ( ! $indexExists || ! $indexIsValid) { - $element = $driver->getElement($data, $entityName); - if ($field = $this->_getCustomIndexField($dqlAlias)) { - $driver->addRelatedIndexedElement($baseElement, $relationAlias, $element, $field); - } else { - $driver->addRelatedElement($baseElement, $relationAlias, $element); - } - $identifierMap[$path][$id[$parent]][$id[$dqlAlias]] = $driver->getLastKey( - $driver->getReferenceValue($baseElement, $relationAlias)); - } - } else if ( ! $driver->isFieldSet($baseElement, $relationAlias)) { - if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY) { - $baseElement[$relationAlias] = array(); - } else { - $driver->setRelatedElement($baseElement, $relationAlias, - $driver->getElementCollection($entityName)); - } - } - } else { - // x-to-one relation - $oneToOne = true; - if ( ! isset($nonemptyComponents[$dqlAlias]) && - ! $driver->isFieldSet($baseElement, $relationAlias)) { - $driver->setRelatedElement($baseElement, $relationAlias, - $driver->getNullPointer()); - } else if ( ! $driver->isFieldSet($baseElement, $relationAlias)) { - $driver->setRelatedElement($baseElement, $relationAlias, - $driver->getElement($data, $entityName)); - } - } - - if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY) { - $coll =& $baseElement[$relationAlias]; - } else { - $coll = $driver->getReferenceValue($baseElement, $relationAlias); - } - - if ($coll !== null) { - $driver->updateResultPointer($resultPointers, $coll, $index, $dqlAlias, $oneToOne); - } - } - - // Append scalar values to mixed result sets - if (isset($scalars)) { - foreach ($scalars as $name => $value) { - $result[$resultCounter - 1][$name] = $value; - } - } - } - - $stmt->closeCursor(); - $driver->flush(); - - $e = microtime(true); - echo 'Hydration took: ' . ($e - $s) . PHP_EOL; - - return $result; - } - -} diff --git a/lib/Doctrine/ORM/Internal/Null.php b/lib/Doctrine/ORM/Internal/Null.php deleted file mode 100644 index 0747f2161..000000000 --- a/lib/Doctrine/ORM/Internal/Null.php +++ /dev/null @@ -1,65 +0,0 @@ -. - */ - -#namespace Doctrine\ORM\Internal; - -/** - * Null class representing a null value that has been fetched from - * the database or a fetched, empty association. This is for internal use only. - * User code should never deal with this null object. - * - * Semantics are as follows: - * - * Regular PHP null : Value is undefined. When a field with that value is accessed - * and lazy loading is used the database is queried. - * - * Null object: Null valued of a field or empty association that has already been loaded. - * On access, the database is not queried. - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.phpdoctrine.org - * @since 1.0 - * @version $Revision: 4723 $ - * @author Konsta Vesterinen - * @todo No longer needed? - * @DEPRECATED - */ -// static initializer -Doctrine_ORM_Internal_Null::$INSTANCE = new Doctrine_ORM_Internal_Null(); -final class Doctrine_ORM_Internal_Null -{ - public static $INSTANCE; - public function __construct() {} - - public static function getInstance() - { - return self::$INSTANCE; - } - - public function exists() - { - return false; - } - public function __toString() - { - return ''; - } -} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadata.php b/lib/Doctrine/ORM/Mapping/ClassMetadata.php index c6ce2fc00..016638110 100644 --- a/lib/Doctrine/ORM/Mapping/ClassMetadata.php +++ b/lib/Doctrine/ORM/Mapping/ClassMetadata.php @@ -23,6 +23,7 @@ namespace Doctrine\ORM\Mapping; use \ReflectionClass; use Doctrine\Common\DoctrineException; +use Doctrine\ORM\Exceptions\MappingException; /** * A ClassMetadata instance holds all the information (metadata) of an entity and @@ -506,7 +507,7 @@ class ClassMetadata public function getFieldMapping($fieldName) { if ( ! isset($this->_fieldMappings[$fieldName])) { - throw Doctrine_MappingException::mappingNotFound($fieldName); + throw MappingException::mappingNotFound($fieldName); } return $this->_fieldMappings[$fieldName]; } @@ -620,10 +621,10 @@ class ClassMetadata { // Check mandatory fields if ( ! isset($mapping['fieldName'])) { - throw Doctrine_ORM_Exceptions_MappingException::missingFieldName(); + throw MappingException::missingFieldName(); } if ( ! isset($mapping['type'])) { - throw Doctrine_ORM_Exceptions_MappingException::missingType(); + throw MappingException::missingType(); } if ( ! is_object($mapping['type'])) { @@ -648,9 +649,9 @@ class ClassMetadata if (isset($mapping['idGenerator'])) { if ( ! $this->_isIdGeneratorType($mapping['idGenerator'])) { //TODO: check if the idGenerator specifies an existing generator by name - throw Doctrine_MappingException::invalidGeneratorType($mapping['idGenerator']); + throw MappingException::invalidGeneratorType($mapping['idGenerator']); } else if (count($this->_identifier) > 1) { - throw Doctrine_MappingException::generatorNotAllowedWithCompositeId(); + throw MappingException::generatorNotAllowedWithCompositeId(); } $this->_generatorType = $mapping['idGenerator']; } @@ -1055,12 +1056,12 @@ class ClassMetadata public function setInheritanceType($type) { if ($parentClassNames = $this->getParentClasses()) { - throw new Doctrine_MappingException("All classes in an inheritance hierarchy" + throw new MappingException("All classes in an inheritance hierarchy" . " must share the same inheritance mapping type and this type must be set" . " in the root class of the hierarchy."); } if ( ! $this->_isInheritanceType($type)) { - throw Doctrine_MappingException::invalidInheritanceType($type); + throw MappingException::invalidInheritanceType($type); } $this->_inheritanceType = $type; } diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php b/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php index 995ca5084..eb8bca9fc 100644 --- a/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php +++ b/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php @@ -16,7 +16,7 @@ * * This software consists of voluntary contributions made by many individuals * and is licensed under the LGPL. For more information, see - * . + * . */ namespace Doctrine\ORM\Mapping; @@ -28,7 +28,6 @@ use Doctrine\DBAL\Platforms\AbstractPlatform; * metadata mapping informations of a class which describes how a class should be mapped * to a relational database. * - * @author Konsta Vesterinen * @author Roman Borschel * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @version $Revision$ @@ -58,7 +57,7 @@ class ClassMetadataFactory /** * Sets the cache driver used by the factory to cache ClassMetadata instances. * - * @param object $cacheDriver + * @param Doctrine\ORM\Cache\Cache $cacheDriver */ public function setCacheDriver($cacheDriver) { @@ -68,7 +67,7 @@ class ClassMetadataFactory /** * Gets the cache driver used by the factory to cache ClassMetadata instances. * - * @return object + * @return Doctrine\ORM\Cache\Cache */ public function getCacheDriver() { @@ -108,51 +107,43 @@ class ClassMetadataFactory */ protected function _loadMetadata($name) { + // Collect parent classes, ignoring transient (not-mapped) classes. $parentClass = $name; $parentClasses = array(); - $loadedParentClass = false; while ($parentClass = get_parent_class($parentClass)) { - if (isset($this->_loadedMetadata[$parentClass])) { - $loadedParentClass = $parentClass; - break; + if ( ! $this->_driver->isTransient($parentClass)) { + $parentClasses[] = $parentClass; } - $parentClasses[] = $parentClass; } $parentClasses = array_reverse($parentClasses); $parentClasses[] = $name; - if ($loadedParentClass) { - $class = $this->_loadedMetadata[$loadedParentClass]; - } else { - $rootClassOfHierarchy = count($parentClasses) > 0 ? array_shift($parentClasses) : $name; - $class = $this->_newClassMetadataInstance($rootClassOfHierarchy); - $this->_loadClassMetadata($class, $rootClassOfHierarchy); - $this->_loadedMetadata[$rootClassOfHierarchy] = $class; - } - - if (count($parentClasses) == 0) { - return $class; - } - - // load metadata of subclasses - // -> child1 -> child2 -> $name - // Move down the hierarchy of parent classes, starting from the topmost class - $parent = $class; - foreach ($parentClasses as $subclassName) { - $subClass = $this->_newClassMetadataInstance($subclassName); - $subClass->setInheritanceType($parent->getInheritanceType()); - $subClass->setDiscriminatorMap($parent->getDiscriminatorMap()); - $subClass->setDiscriminatorColumn($parent->getDiscriminatorColumn()); - $subClass->setIdGeneratorType($parent->getIdGeneratorType()); - $this->_addInheritedFields($subClass, $parent); - $this->_addInheritedRelations($subClass, $parent); - $this->_loadClassMetadata($subClass, $subclassName); - if ($parent->isInheritanceTypeSingleTable()) { - $subClass->setTableName($parent->getTableName()); + $parent = null; + $visited = array(); + foreach ($parentClasses as $className) { + $class = $this->_newClassMetadataInstance($className); + if ($parent) { + $class->setInheritanceType($parent->getInheritanceType()); + $class->setDiscriminatorMap($parent->getDiscriminatorMap()); + $class->setDiscriminatorColumn($parent->getDiscriminatorColumn()); + $class->setIdGeneratorType($parent->getIdGeneratorType()); + $this->_addInheritedFields($class, $parent); + $this->_addInheritedRelations($class, $parent); } - $this->_loadedMetadata[$subclassName] = $subClass; - $parent = $subClass; + + // Invoke driver + $this->_driver->loadMetadataForClass($className, $class); + $this->_completeIdGeneratorMapping($class); + + if ($parent && $parent->isInheritanceTypeSingleTable()) { + $class->setTableName($parent->getTableName()); + } + + $this->_loadedMetadata[$className] = $class; + $parent = $class; + $class->setParentClasses($visited); + array_unshift($visited, $className); } } @@ -173,7 +164,7 @@ class ClassMetadataFactory * @param Doctrine\ORM\Mapping\ClassMetadata $subClass * @param Doctrine\ORM\Mapping\ClassMetadata $parentClass */ - private function _addInheritedFields($subClass, $parentClass) + private function _addInheritedFields(ClassMetadata $subClass, ClassMetadata $parentClass) { foreach ($parentClass->getFieldMappings() as $fieldName => $mapping) { if ( ! isset($mapping['inherited'])) { @@ -189,55 +180,30 @@ class ClassMetadataFactory * @param Doctrine\ORM\Mapping\ClassMetadata $subClass * @param Doctrine\ORM\Mapping\ClassMetadata $parentClass */ - private function _addInheritedRelations($subClass, $parentClass) + private function _addInheritedRelations(ClassMetadata $subClass, ClassMetadata $parentClass) { foreach ($parentClass->getAssociationMappings() as $mapping) { $subClass->addAssociationMapping($mapping); } } - + /** - * Loads the metadata of a specified class. + * Completes the ID generator mapping. If "auto" is specified we choose the generator + * most appropriate for the targeted database platform. * - * @param Doctrine_ClassMetadata $class The container for the metadata. - * @param string $name The name of the class for which the metadata will be loaded. + * @param Doctrine\ORM\Mapping\ClassMetadata $class */ - private function _loadClassMetadata(ClassMetadata $class, $name) + private function _completeIdGeneratorMapping(ClassMetadata $class) { - if ( ! class_exists($name) || empty($name)) { - throw new DoctrineException("Couldn't find class " . $name . "."); - } - - $names = array(); - $className = $name; - // get parent classes - //TODO: Skip Entity types MappedSuperclass/Transient - do { - if ($className == $name) { - continue; - } - $names[] = $className; - } while ($className = get_parent_class($className)); - - // save parents - $class->setParentClasses($names); - - // load user-specified mapping metadata through the driver - $this->_driver->loadMetadataForClass($name, $class); - - // Complete Id generator mapping. If AUTO is specified we choose the generator - // most appropriate for the target platform. - if ($class->getIdGeneratorType() == \Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_AUTO) { + if ($class->getIdGeneratorType() == ClassMetadata::GENERATOR_TYPE_AUTO) { if ($this->_targetPlatform->prefersSequences()) { - $class->setIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_SEQUENCE); + $class->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_SEQUENCE); } else if ($this->_targetPlatform->prefersIdentityColumns()) { - $class->setIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_IDENTITY); + $class->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_IDENTITY); } else { - $class->setIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_TABLE); + $class->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_TABLE); } } - - return $class; } } diff --git a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php index db1a151e3..0556881d2 100644 --- a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php +++ b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php @@ -153,4 +153,20 @@ class AnnotationDriver } } + + /** + * Whether the class with the specified name should have its metadata loaded. + * This is only the case if it is annotated with either @DoctrineEntity or + * @DoctrineMappedSuperclass in the class doc block. + * + * @param string $className + * @return boolean + */ + public function isTransient($className) + { + $refClass = new \ReflectionClass($className); + $docComment = $refClass->getDocComment(); + return strpos($docComment, '@DoctrineEntity') === false && + strpos($docComment, '@DoctrineMappedSuperclass') === false; + } } diff --git a/lib/Doctrine/ORM/Mapping/OneToManyMapping.php b/lib/Doctrine/ORM/Mapping/OneToManyMapping.php index 748ae6f77..35e654170 100644 --- a/lib/Doctrine/ORM/Mapping/OneToManyMapping.php +++ b/lib/Doctrine/ORM/Mapping/OneToManyMapping.php @@ -21,6 +21,8 @@ namespace Doctrine\ORM\Mapping; +use Doctrine\ORM\Exceptions\MappingException; + /** * Represents a one-to-many mapping. * @@ -76,7 +78,7 @@ class OneToManyMapping extends AssociationMapping // one-side MUST be inverse (must have mappedBy) if ( ! isset($mapping['mappedBy'])) { - throw Doctrine_MappingException::oneToManyRequiresMappedBy($mapping['fieldName']); + throw MappingException::oneToManyRequiresMappedBy($mapping['fieldName']); } $this->_deleteOrphans = isset($mapping['deleteOrphans']) ? diff --git a/lib/Doctrine/ORM/Mapping/OneToOneMapping.php b/lib/Doctrine/ORM/Mapping/OneToOneMapping.php index eb9f20eb5..5adb7029d 100644 --- a/lib/Doctrine/ORM/Mapping/OneToOneMapping.php +++ b/lib/Doctrine/ORM/Mapping/OneToOneMapping.php @@ -21,6 +21,8 @@ namespace Doctrine\ORM\Mapping; +use Doctrine\ORM\Exceptions\MappingException; + /** * A one-to-one mapping describes a uni-directional mapping from one entity * to another entity. diff --git a/lib/Doctrine/ORM/PersistentCollection.php b/lib/Doctrine/ORM/PersistentCollection.php index 07d3a27fe..c869b9f60 100644 --- a/lib/Doctrine/ORM/PersistentCollection.php +++ b/lib/Doctrine/ORM/PersistentCollection.php @@ -24,8 +24,6 @@ namespace Doctrine\ORM; use Doctrine\ORM\Mapping\AssociationMapping; /** - * A persistent collection wrapper. - * * A PersistentCollection represents a collection of elements that have persistent state. * Collections of entities represent only the associations (links) to those entities. * That means, if the collection is part of a many-many mapping and you remove diff --git a/lib/Doctrine/ORM/Persisters/ManyToManyPersister.php b/lib/Doctrine/ORM/Persisters/ManyToManyPersister.php index c9b494f08..49b071481 100644 --- a/lib/Doctrine/ORM/Persisters/ManyToManyPersister.php +++ b/lib/Doctrine/ORM/Persisters/ManyToManyPersister.php @@ -1,7 +1,22 @@ . */ namespace Doctrine\ORM\Persisters; diff --git a/lib/Doctrine/ORM/Persisters/OneToManyPersister.php b/lib/Doctrine/ORM/Persisters/OneToManyPersister.php index 4ae0e6338..c03b0a570 100644 --- a/lib/Doctrine/ORM/Persisters/OneToManyPersister.php +++ b/lib/Doctrine/ORM/Persisters/OneToManyPersister.php @@ -1,4 +1,23 @@ . + */ namespace Doctrine\ORM\Persisters; @@ -6,6 +25,8 @@ use Doctrine\ORM\PersistentCollection; /** * Persister for one-to-many collections. + * + * @since 2.0 */ class OneToManyPersister extends AbstractCollectionPersister { diff --git a/lib/Doctrine/ORM/Query.php b/lib/Doctrine/ORM/Query.php index 6de9ba1ac..0eefaa0fb 100644 --- a/lib/Doctrine/ORM/Query.php +++ b/lib/Doctrine/ORM/Query.php @@ -1,7 +1,6 @@ . + * . */ namespace Doctrine\ORM; diff --git a/lib/Doctrine/ORM/Query/SqlWalker.php b/lib/Doctrine/ORM/Query/SqlWalker.php index 727e89838..f02b5cfe0 100644 --- a/lib/Doctrine/ORM/Query/SqlWalker.php +++ b/lib/Doctrine/ORM/Query/SqlWalker.php @@ -9,9 +9,13 @@ namespace Doctrine\ORM\Query; use Doctrine\ORM\Query\AST; /** - * Description of SqlWalker + * The SqlWalker walks over an AST that represents a DQL query and constructs + * the corresponding SQL. The walking can start at any node, not only at some root + * node. Therefore it is possible to only generate SQL parts by simply walking over + * certain subtrees of the AST. * * @author robo + * @since 2.0 */ class SqlWalker { @@ -27,6 +31,9 @@ class SqlWalker private $_dqlToSqlAliasMap = array(); private $_scalarAliasCounter = 0; + /** + * Initializes a new SqlWalker instance. + */ public function __construct($em, $parserResult) { $this->_em = $em; @@ -157,9 +164,9 @@ class SqlWalker $sql .= $sqlTableAlias . '.' . $class->getColumnName($fieldName) . ' AS ' . $sqlTableAlias . '__' . $class->getColumnName($fieldName); } else if ($pathExpression->isSimpleStateFieldAssociationPathExpression()) { - throw new Doctrine_Exception("Not yet implemented."); + throw new DoctrineException("Not yet implemented."); } else { - throw new Doctrine_ORM_Query_Exception("Encountered invalid PathExpression during SQL construction."); + throw new DoctrineException("Encountered invalid PathExpression during SQL construction."); } } else if ($selectExpression->getExpression() instanceof AST\AggregateExpression) { diff --git a/tests/Doctrine/Tests/Mocks/EntityManagerMock.php b/tests/Doctrine/Tests/Mocks/EntityManagerMock.php index b09e1f8ca..91fcd3434 100644 --- a/tests/Doctrine/Tests/Mocks/EntityManagerMock.php +++ b/tests/Doctrine/Tests/Mocks/EntityManagerMock.php @@ -1,4 +1,23 @@ . + */ namespace Doctrine\Tests\Mocks; diff --git a/tests/Doctrine/Tests/Mocks/MetadataDriverMock.php b/tests/Doctrine/Tests/Mocks/MetadataDriverMock.php index fec51b2b5..ba0a7ce2f 100644 --- a/tests/Doctrine/Tests/Mocks/MetadataDriverMock.php +++ b/tests/Doctrine/Tests/Mocks/MetadataDriverMock.php @@ -11,9 +11,13 @@ namespace Doctrine\Tests\Mocks; * * @author robo */ -class MetadataDriverMock { +class MetadataDriverMock +{ public function loadMetadataForClass($className, \Doctrine\ORM\Mapping\ClassMetadata $metadata) { return; } + public function isTransient($className) { + return false; + } } diff --git a/tests/Doctrine/Tests/ORM/UnitOfWorkTest.php b/tests/Doctrine/Tests/ORM/UnitOfWorkTest.php index ff179a30a..a00e1e1ee 100644 --- a/tests/Doctrine/Tests/ORM/UnitOfWorkTest.php +++ b/tests/Doctrine/Tests/ORM/UnitOfWorkTest.php @@ -13,11 +13,6 @@ use Doctrine\Tests\Models\Forum\ForumAvatar; require_once __DIR__ . '/../TestInit.php'; -#require_once 'lib/mocks/Doctrine_EntityManagerMock.php'; -#require_once 'lib/mocks/Doctrine_ConnectionMock.php'; -#require_once 'lib/mocks/Doctrine_UnitOfWorkMock.php'; -#require_once 'lib/mocks/Doctrine_IdentityIdGeneratorMock.php'; - /** * UnitOfWork tests. */