Commit 613d08f9 authored by romanb's avatar romanb

Merged dbal bugfixes from 0.11.

parent 7ffd4140
......@@ -272,14 +272,12 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
*
* @param string $entityName Name of the entity class the metadata info is used for.
*/
public function __construct($entityName, Doctrine_Connection $conn)
public function __construct($entityName, Doctrine_EntityManager $em)
{
$this->_entityName = $entityName;
$this->_rootEntityName = $entityName;
$this->_conn = $conn;
$this->_conn = $em;
$this->_parser = new Doctrine_Relation_Parser($this);
$this->_filters[] = new Doctrine_Record_Filter_Standard();
$this->setConfigurableParent($this->_conn);
}
/**
......@@ -289,6 +287,11 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return $this->_conn;
}
public function getEntityManager()
{
return $this->_conn;
}
/**
* getComponentName
......@@ -598,7 +601,13 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
$this->_columnCount++;
}
/**
* Gets the default length for a field type.
*
* @param unknown_type $type
* @return unknown
*/
private function _getDefaultLength($type)
{
switch ($type) {
......@@ -625,6 +634,16 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
return 25;
}
}
/**
* Maps an embedded value object.
*
* @todo Implementation.
*/
public function mapEmbeddedValue()
{
//...
}
/**
* setColumn
......@@ -956,11 +975,16 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
return $this->getColumnDefinition($columnName);
}
/**
* Gets the mapping information for a field.
*
* @param string $fieldName
* @return array
*/
public function getMappingForField($fieldName)
{
$columnName = $this->getColumnName($fieldName);
return $this->getColumnDefinition($columnName);
}
......@@ -974,7 +998,13 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return $this->getTypeOfColumn($this->getColumnName($fieldName));
}
/**
* Gets the type of a field.
*
* @param string $fieldName
* @return string
*/
public function getTypeOfField($fieldName)
{
return $this->getTypeOfColumn($this->getColumnName($fieldName));
......@@ -1022,7 +1052,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
*/
public function addNamedQuery($name, $query)
{
//...
}
public function bindRelation($args, $type)
......@@ -1622,7 +1652,8 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
*/
public function setTableName($tableName)
{
$this->setTableOption('tableName', $this->_conn->formatter->getTableName($tableName));
$this->setTableOption('tableName', $this->_conn->getConnection()
->formatter->getTableName($tableName));
}
/**
......
......@@ -44,9 +44,9 @@ class Doctrine_ClassMetadata_Factory
* @param $conn The connection to use.
* @param $driver The metadata driver to use.
*/
public function __construct(Doctrine_Connection $conn, $driver)
public function __construct(Doctrine_EntityManager $em, $driver)
{
$this->_conn = $conn;
$this->_conn = $em;
$this->_driver = $driver;
}
......
......@@ -31,9 +31,12 @@
* @since 1.0
* @version $Revision$
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @todo Rename to EntityCollection
*/
class Doctrine_Collection extends Doctrine_Access implements Countable, IteratorAggregate, Serializable
{
protected $_entityBaseType;
/**
* An array containing the records of this collection.
*
......@@ -101,10 +104,11 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
* @param string $keyColumn The field name that will be used as the key
* in the collection.
*/
public function __construct($mapper, $keyField = null)
public function __construct($entityBaseType, $keyField = null)
{
if (is_string($mapper)) {
$mapper = Doctrine_Manager::getInstance()->getMapper($mapper);
if (is_string($entityBaseType)) {
$this->_entityBaseType = $entityBaseType;
$mapper = Doctrine_EntityManager::getManager($entityBaseType)->getEntityPersister($entityBaseType);
}
$this->_mapper = $mapper;
......@@ -204,16 +208,16 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
*/
public function unserialize($serialized)
{
$manager = Doctrine_Manager::getInstance();
$connection = $manager->getCurrentConnection();
$manager = Doctrine_EntityManager::getManager();
$connection = $manager->getConnection();
$array = unserialize($serialized);
foreach ($array as $name => $values) {
$this->$name = $values;
}
$this->_mapper = $connection->getMapper($this->_mapper);
$this->_mapper = $manager->getEntityPersister($this->_entityBaseType);
$keyColumn = isset($array['keyField']) ? $array['keyField'] : null;
if ($keyColumn === null) {
......@@ -506,6 +510,7 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
*/
public function add($record, $key = null)
{
/** @TODO Use raw getters/setters */
if ( ! $record instanceof Doctrine_Entity) {
throw new Doctrine_Record_Exception('Value variable in set is not an instance of Doctrine_Entity.');
}
......
......@@ -58,11 +58,8 @@
* it sits one layer below.
* Right now, this is the unification of these two classes.
*/
abstract class Doctrine_Connection extends Doctrine_Configurable implements Countable, IteratorAggregate
abstract class Doctrine_Connection extends Doctrine_Configurable implements Countable
{
/*
* ----------- Connection attributes ---------------
*/
/**
* The PDO database handle.
*
......@@ -102,7 +99,9 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
protected $supported = array();
/**
* @var array $properties an array of connection properties
* The connection properties.
*
* @var array $properties
*/
protected $properties = array(
'sql_comments' => array(array('start' => '--', 'end' => "\n", 'escape' => false),
......@@ -139,40 +138,6 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
* @var integer
*/
protected $_count = 0;
/*
* ----------- EntityManager attributes ---------------
*/
/**
* Enter description here...
*
* @var array
*/
private static $_ems = array();
/**
* The metadata factory is used to retrieve the metadata of entity classes.
*
* @var Doctrine_ClassMetadata_Factory
* @todo package:orm
*/
protected $_metadataFactory;
/**
* An array of mapper objects currently maintained by this connection.
*
* @var array
* @todo package:orm
*/
protected $_mappers = array();
/**
* The EntityRepository instances.
*
* @var array
*/
private $_repositories = array();
/*
......@@ -232,7 +197,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
* @param PDO|Doctrine_Adapter_Interface $adapter database driver
* @todo Remove the dependency on the Manager for DBAL/ORM separation.
*/
public function __construct(Doctrine_Manager $manager, $adapter, $user = null, $pass = null)
public function __construct($adapter, $user = null, $pass = null)
{
if (is_object($adapter)) {
if ( ! ($adapter instanceof PDO) && ! in_array('Doctrine_Adapter_Interface', class_implements($adapter))) {
......@@ -254,11 +219,8 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
}
$this->setConfigurableParent($manager);
$this->setAttribute(Doctrine::ATTR_CASE, Doctrine::CASE_NATURAL);
$this->setAttribute(Doctrine::ATTR_ERRMODE, Doctrine::ERRMODE_EXCEPTION);
$this->getAttribute(Doctrine::ATTR_LISTENER)->onOpen($this);
}
......@@ -898,6 +860,28 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
$this->rethrowException($e, $this);
}
/**
*
*
* @return string
*/
public function modifyLimitQuery($query, $query, $limit = false, $offset = false, $isManip = false)
{
return $query;
}
/**
* Creates dbms specific LIMIT/OFFSET SQL for the subqueries that are used in the
* context of the limit-subquery algorithm.
*
* @return string
*/
public function modifyLimitSubquery(Doctrine_Table $rootTable, $query, $limit = false,
$offset = false, $isManip = false)
{
return $this->modifyLimitQuery($query, $limit, $offset, $isManip);
}
/**
* rethrowException
......@@ -1141,460 +1125,6 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
* ----------- EntityManager methods ---------------
*/
/**
* Gets the EntityManager that is responsible for the Entity.
*
* @param string $entityName
* @return EntityManager
*/
public static function getManagerForEntity($entityName)
{
// ...
}
/**
* query
* queries the database using Doctrine Query Language
* returns a collection of Doctrine_Entity objects
*
* <code>
* $users = $conn->query('SELECT u.* FROM User u');
*
* $users = $conn->query('SELECT u.* FROM User u WHERE u.name LIKE ?', array('someone'));
* </code>
*
* @param string $query DQL query
* @param array $params query parameters
* @param int $hydrationMode Doctrine::FETCH_ARRAY or Doctrine::FETCH_RECORD
* @see Doctrine_Query
* @return Doctrine_Collection Collection of Doctrine_Entity objects
* @todo package:orm
*/
public function query($query, array $params = array(), $hydrationMode = null)
{
$parser = new Doctrine_Query($this);
return $parser->query($query, $params, $hydrationMode);
}
/**
* query
* queries the database using Doctrine Query Language and returns
* the first record found
*
* <code>
* $user = $conn->queryOne('SELECT u.* FROM User u WHERE u.id = ?', array(1));
*
* $user = $conn->queryOne('SELECT u.* FROM User u WHERE u.name LIKE ? AND u.password = ?',
* array('someone', 'password')
* );
* </code>
*
* @param string $query DQL query
* @param array $params query parameters
* @see Doctrine_Query
* @return Doctrine_Entity|false Doctrine_Entity object on success,
* boolean false on failure
*/
public function queryOne($query, array $params = array())
{
$parser = new Doctrine_Query($this);
$coll = $parser->query($query, $params);
if ( ! $coll->contains(0)) {
return false;
}
return $coll[0];
}
/**
* hasTable
* whether or not this connection has table $name initialized
*
* @param mixed $name
* @return boolean
* @deprecated
* @todo package:orm
*/
public function hasTable($name)
{
return isset($this->tables[$name]);
}
/**
* Returns the metadata for a class.
*
* @return Doctrine_Metadata
* @deprecated Use getClassMetadata()
* @todo package:orm
*/
public function getMetadata($className)
{
return $this->getClassMetadata($className);
}
/**
* Returns the metadata for a class.
*
* @return Doctrine_Metadata
* @todo package:orm
*/
public function getClassMetadata($className)
{
if ( ! $this->_metadataFactory) {
$this->_metadataFactory = new Doctrine_ClassMetadata_Factory($this,
new Doctrine_ClassMetadata_CodeDriver());
}
return $this->_metadataFactory->getMetadataFor($className);
}
/**
* Sets the driver that is used to obtain metadata informations about entity
* classes.
*
* @param $driver The driver to use.
* @todo package:orm
*/
public function setClassMetadataDriver($driver)
{
$this->_metadataFactory->setDriver($driver);
}
/**
* Gets a mapper for the specified domain class that is used to map instances of
* the class between the relational database and their object representation.
*
* @param string $entityClassName The name of the entity class.
* @return Doctrine_Mapper The mapper object.
* @todo package:orm
*/
public function getMapper($entityName)
{
if (isset($this->_mappers[$entityName])) {
return $this->_mappers[$entityName];
}
$metadata = $this->getClassMetadata($entityName);
$customMapperClassName = $metadata->getCustomMapperClass();
if ($customMapperClassName !== null) {
$mapper = new $customMapperClassName($entityName, $metadata);
} else {
$mapper = new Doctrine_Mapper($entityName, $metadata);
}
$this->_mappers[$entityName] = $mapper;
return $mapper;
}
/**
* Gets all mappers that are currently maintained by the connection.
*
* @todo package:orm
*/
public function getMappers()
{
return $this->_mappers;
}
/**
* returns an iterator that iterates through all
* initialized table objects
*
* <code>
* foreach ($conn as $index => $table) {
* print $table; // get a string representation of each table object
* }
* </code>
*
* @return ArrayIterator SPL ArrayIterator object
*/
public function getIterator()
{
return new ArrayIterator($this->_mappers);
}
/**
* create
* creates a record
*
* create creates a record
* @param string $name component name
* @return Doctrine_Entity Doctrine_Entity object
* @todo Any strong reasons why this should not be removed?
* @todo package:orm
*/
public function create($name)
{
return $this->getMapper($name)->create();
}
/**
* Creates a new Doctrine_Query object that operates on this connection.
*
* @return Doctrine_Query
* @todo package:orm
*/
public function createQuery($dql = "")
{
$query = new Doctrine_Query($this);
if ( ! empty($dql)) {
$query->parseQuery($dql);
}
return $query;
}
/**
* flush
* saves all the records from all tables
* this operation is isolated using a transaction
*
* @throws PDOException if something went wrong at database level
* @return void
* @todo package:orm
*/
public function flush()
{
$this->beginInternalTransaction();
$this->unitOfWork->flush();
$this->commit();
}
/**
* clear
* clears all repositories
*
* @return void
* @todo package:orm
*/
public function clear($entityName = null)
{
if ($entityName === null) {
$this->unitOfWork->detachAll();
foreach ($this->_mappers as $mapper) {
$mapper->clear(); // clear identity map of each mapper
}
} else {
$this->getMapper($entityName)->clear();
}
}
/**
* evictTables
* evicts all tables
*
* @return void
* @todo package:orm
* @deprecated
*/
public function evictTables()
{
$this->clear();
$this->tables = array();
$this->_mappers = array();
$this->exported = array();
}
public function save(Doctrine_Entity $entity, $conn = null)
{
$this->getMapper($entity->getClassName())->save($entity, $conn);
}
public function remove(Doctrine_Entity $entity, $conn = null)
{
$this->getMapper($entity->getClassName())->delete($entity, $conn);
}
public function createEntity($entityName, array $data = array())
{
return $this->getMapper($entityName)->create($data);
}
public function detach(Doctrine_Entity $entity)
{
$this->getMapper($entity->getClassName())->detach($entity);
}
public function removeRecord(Doctrine_Entity $entity)
{
$this->getMapper($entity->getClassName())->removeRecord($entity);
}
public function manage(Doctrine_Entity $entity)
{
$this->getMapper($entity->getClassName())->manage($entity);
}
public function executeNamedQuery($name, $params = array(), $hydrationMode = Doctrine::HYDRATE_RECORD)
{
return Doctrine_Manager::getInstance()
->createNamedQuery($name)
->execute($params, $hydrationMode);
}
/**
* Returns the current internal transaction nesting level.
*
* @return integer The nesting level. A value of 0 means theres no active transaction.
* @todo package:orm???
*/
public function getInternalTransactionLevel()
{
return $this->transaction->getInternalTransactionLevel();
}
/**
* getCacheDriver
*
* @return Doctrine_Cache_Interface
* @deprecated Use getResultCacheDriver()
*/
public function getCacheDriver()
{
return $this->getResultCacheDriver();
}
/**
* getResultCacheDriver
*
* @return Doctrine_Cache_Interface
* @todo package:orm
*/
public function getResultCacheDriver()
{
if ( ! $this->getAttribute(Doctrine::ATTR_RESULT_CACHE)) {
throw new Doctrine_Exception('Result Cache driver not initialized.');
}
return $this->getAttribute(Doctrine::ATTR_RESULT_CACHE);
}
/**
* getQueryCacheDriver
*
* @return Doctrine_Cache_Interface
* @todo package:orm
*/
public function getQueryCacheDriver()
{
if ( ! $this->getAttribute(Doctrine::ATTR_QUERY_CACHE)) {
throw new Doctrine_Exception('Query Cache driver not initialized.');
}
return $this->getAttribute(Doctrine::ATTR_QUERY_CACHE);
}
/**
* Initiates a transaction.
*
* This method must only be used by Doctrine itself to initiate transactions.
* Userland-code must use {@link beginTransaction()}.
*
* @todo package:orm???
*/
public function beginInternalTransaction($savepoint = null)
{
return $this->transaction->beginInternalTransaction($savepoint);
}
/**
* Enter description here...
*
* @todo To EntityManager
*/
public function getRepository($entityName)
{
if (isset($this->_repositories[$entityName])) {
return $this->_repositories[$entityName];
}
$metadata = $this->getClassMetadata($entityName);
$customRepositoryClassName = $metadata->getCustomRepositoryClass();
if ($customRepositoryClassName !== null) {
$repository = new $customRepositoryClassName($entityName, $metadata);
} else {
$repository = new Doctrine_EntityRepository($entityName, $metadata);
}
$this->_repositories[$entityName] = $repository;
return $repository;
}
/**
* createEntity
* First checks if record exists in identityMap, if not
* returns a new record.
*
* @return Doctrine_Entity
*/
public function createEntity2($className, array $data)
{
$className = $this->_getClassnameToReturn($data, $className);
$classMetadata = $this->getClassMetadata($className);
if ( ! empty($data)) {
$identifierFieldNames = $classMetadata->getIdentifier();
$isNew = false;
foreach ($identifierFieldNames as $fieldName) {
if ( ! isset($data[$fieldName])) {
// id field not found return new entity
$isNew = true;
break;
}
$id[] = $data[$fieldName];
}
if ($isNew) {
return new $className(true, $data);
}
$idHash = $this->unitOfWork->getIdentifierHash($id);
if ($entity = $this->unitOfWork->tryGetByIdHash($idHash,
$classMetadata->getRootClassName())) {
// @todo return $entity; the one in-memory is the most recent.
$entity->hydrate($data);
} else {
$entity = new $className(false, $data);
$this->unitOfWork->registerIdentity($entity);
}
$data = array();
} else {
$entity = new $className(true, $data);
}
return $entity;
}
/**
* Check the dataset for a discriminator column to determine the correct
* class to instantiate. If no discriminator column is found, the given
* classname will be returned.
*
* @return string The name of the class to instantiate.
* @todo Can be optimized performance-wise.
* @todo Move to EntityManager::createEntity()
*/
protected function _getClassnameToReturn(array $data, $className)
{
$class = $this->getClassMetadata($className);
$discCol = $class->getInheritanceOption('discriminatorColumn');
if ( ! $discCol) {
return $className;
}
$discMap = $class->getInheritanceOption('discriminatorMap');
if (isset($data[$discCol], $discMap[$data[$discCol]])) {
return $discMap[$data[$discCol]];
} else {
return $className;
}
}
/*
* ----------- Mixed methods (need to figure out where they go) ---------------
*/
......@@ -1695,14 +1225,4 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
return $this->modules[$name];
}
/**
* returns the manager that created this connection
*
* @return Doctrine_Manager
*/
public function getManager()
{
return $this->getParent();
}
}
......@@ -55,8 +55,8 @@ class Doctrine_Connection_Db2 extends Doctrine_Connection
$col = explode('select', $select);
$sql = 'WITH OFFSET AS(' . $select . ', ROW_NUMBER() ' .
'OVER(ORDER BY ' . $col[1] . ') AS dctrn_rownum FROM ' . $table . ')' .
$select . 'FROM OFFSET WHERE dctrn_rownum BETWEEN ' . $offset .
'OVER(ORDER BY ' . $col[1] . ') AS doctrine_rownum FROM ' . $table . ')' .
$select . 'FROM OFFSET WHERE doctrine_rownum BETWEEN ' . $offset .
'AND ' . ($offset + $limit - 1);
return $sql;
}
......
......@@ -44,7 +44,7 @@ class Doctrine_Connection_Mock extends Doctrine_Connection_Common
* @param Doctrine_Manager $manager
* @param PDO|Doctrine_Adapter $adapter database handler
*/
public function __construct(Doctrine_Manager $manager, $adapter)
public function __construct()
{
}
......
......@@ -18,7 +18,7 @@
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
Doctrine::autoload('Doctrine_Connection');
/**
* Doctrine_Connection_Oracle
*
......@@ -80,39 +80,59 @@ class Doctrine_Connection_Oracle extends Doctrine_Connection
$this->exec('ALTER SESSION SET NLS_DATE_FORMAT = "' . $format . '"');
}
/**
* Adds an driver-specific LIMIT clause to the query
*
* @param string $query query to modify
* @param integer $limit limit the number of rows
* @param integer $offset start reading from given offset
* @return string the modified query
*/
public function modifyLimitQuery($query, $limit, $offset)
{
/**
$e = explode("select ",strtolower($query));
$e2 = explode(" from ",$e[1]);
$fields = $e2[0];
*/
$limit = (int) $limit;
$offset = (int) $offset;
if (preg_match('/^\s*SELECT/i', $query)) {
if ( ! preg_match('/\sFROM\s/i', $query)) {
$query .= " FROM dual";
}
if ($limit > 0) {
// taken from http://svn.ez.no/svn/ezcomponents/packages/Database
$max = $offset + $limit;
if ($offset > 0) {
$min = $offset + 1;
$query = 'SELECT * FROM (SELECT a.*, ROWNUM dctrn_rownum FROM (' . $query
. ') a WHERE ROWNUM <= ' . $max . ') WHERE dctrn_rownum >= ' . $min;
} else {
$query = 'SELECT a.* FROM (' . $query .') a WHERE ROWNUM <= ' . $max;
}
}
}
return $query;
/**
* Adds an driver-specific LIMIT clause to the query
*
* @param string $query query to modify
* @param integer $limit limit the number of rows
* @param integer $offset start reading from given offset
* @return string the modified query
*/
public function modifyLimitQuery($query, $limit = false, $offset = false, $isManip = false)
{
return $this->_createLimitSubquery($query, $limit, $offset);
}
private function _createLimitSubquery($query, $limit, $offset, $column = null)
{
$limit = (int) $limit;
$offset = (int) $offset;
if (preg_match('/^\s*SELECT/i', $query)) {
if ( ! preg_match('/\sFROM\s/i', $query)) {
$query .= " FROM dual";
}
if ($limit > 0) {
$max = $offset + $limit;
$column = $column === null ? '*' : $column;
if ($offset > 0) {
$min = $offset + 1;
$query = 'SELECT b.'.$column.' FROM ('.
'SELECT a.*, ROWNUM AS doctrine_rownum FROM ('
. $query . ') a '.
') b '.
'WHERE doctrine_rownum BETWEEN ' . $min . ' AND ' . $max;
} else {
$query = 'SELECT a.'.$column.' FROM (' . $query .') a WHERE ROWNUM <= ' . $max;
}
}
}
return $query;
}
/**
* Creates the SQL for Oracle that can be used in the subquery for the limit-subquery
* algorithm.
*/
public function modifyLimitSubquery(Doctrine_ClassMetadata $rootClass, $query, $limit = false,
$offset = false, $isManip = false)
{
// NOTE: no composite key support
$columnNames = $rootClass->getIdentifierColumnNames();
if (count($columnNames) > 1) {
throw new Doctrine_Connection_Exception("Composite keys in LIMIT queries are "
. "currently not supported.");
}
$column = $columnNames[0];
return $this->_createLimitSubquery($query, $limit, $offset, $column);
}
}
\ No newline at end of file
......@@ -25,18 +25,21 @@
*
* Some terminology:
*
* <b>New entity</b>: From the point of view of the unitOfWork is an entity that
* already has an identity but is not yet persisted into the database. This
* is usually the case for all newly saved entities that use a SEQUENCE id
* generator. Entities with an IDENTITY id generator get persisted as soon
* as they're saved in order to obtain the identifier. Therefore entities that
* use an IDENTITY id generator never appear in the list of new entities of the UoW.
* <b>New entity</b>: A new entity is an entity that already has an identity but
* is not yet persisted into the database. This is usually the case for all
* newly saved entities that use a SEQUENCE id generator. Entities with an
* IDENTITY id generator get persisted as soon as they're saved in order to
* obtain the identifier. Therefore entities that use an IDENTITY id generator
* never appear in the list of new entities of the UoW.
*
* <b>Dirty entity</b>: ...
* <b>Dirty entity</b>: A dirty entity is a managed entity whose values have
* been altered.
*
* <b>Removed entity</b>: ...
* <b>Removed entity</b>: A removed entity is a managed entity that is scheduled
* for deletion from the database.
*
* <b>Clean entity</b>: ...
* <b>Clean entity</b>: A clean entity is a managed entity that has been fetched
* from the database and whose values have not yet been altered.
*
* @package Doctrine
* @subpackage Connection
......@@ -226,7 +229,7 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
$index = max(array_keys($tree));
}
$rels = $mapper->getTable()->getRelations();
$rels = $mapper->getClassMetadata()->getRelations();
// group relations
......@@ -355,7 +358,8 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
/**
* @param integer $oid object identifier
* @return boolean whether ot not the operation was successful
* @deprecated
* @deprecated The new implementation of detach() should remove the entity
* from the identity map.
*/
public function detach(Doctrine_Entity $entity)
{
......@@ -371,6 +375,8 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
* Detaches all currently managed entities.
*
* @return integer The number of detached entities.
* @todo Deprecated. The new implementation should remove all entities from
* the identity map.
*/
public function detachAll()
{
......@@ -401,11 +407,24 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
return true;
}
/**
* Enter description here...
*
* @param unknown_type $entityName
* @todo unify with detachAll()
*/
public function clearIdentitiesForEntity($entityName)
{
$this->_identityMap[$entityName] = array();
}
/**
* Removes an entity from the identity map.
*
* @param Doctrine_Entity $entity
* @return unknown
* @todo This will be the new detach().
*/
public function unregisterIdentity(Doctrine_Entity $entity)
{
$idHash = $this->getIdentifierHash($entity->identifier());
......@@ -422,6 +441,13 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
return false;
}
/**
* Finds an entity in the identity map by its identifier hash.
*
* @param unknown_type $idHash
* @param unknown_type $rootClassName
* @return unknown
*/
public function getByIdHash($idHash, $rootClassName)
{
return $this->_identityMap[$rootClassName][$idHash];
......@@ -435,6 +461,12 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
return false;
}
/**
* Gets the identifier hash for a set of identifier values.
*
* @param array $id
* @return string
*/
public function getIdentifierHash(array $id)
{
return implode(' ', $id);
......@@ -448,15 +480,22 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
*/
public function contains(Doctrine_Entity $entity)
{
$id = implode(' ', $entity->identifier());
if ( ! $id) {
$idHash = $this->getIdentifierHash($entity->identifier());
if ( ! $idHash) {
return false;
}
return isset($this->_identityMap[
$entity->getClassMetadata()->getRootClassName()
][$id]);
return isset($this->_identityMap
[$entity->getClassMetadata()->getRootClassName()]
[$idHash]);
}
/**
* Checks whether an identifier hash exists in the identity map.
*
* @param string $idHash
* @param string $rootClassName
* @return boolean
*/
public function containsIdHash($idHash, $rootClassName)
{
return isset($this->_identityMap[$rootClassName][$idHash]);
......
......@@ -115,6 +115,7 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Countable, Ite
* The metadata container that describes the entity class.
*
* @var Doctrine_ClassMetadata
* @todo Lazy initialization.
*/
protected $_class;
......@@ -188,6 +189,7 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Countable, Ite
* The EntityManager that is responsible for the persistence of the entity.
*
* @var Doctrine_EntityManager
* @todo Lazy initialization.
*/
protected $_em;
......@@ -214,8 +216,7 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Countable, Ite
public function __construct($isNewEntry = true, array $data = array())
{
$this->_entityName = get_class($this);
$this->_em = Doctrine_Manager::getInstance()->getCurrentConnection();
// future: $this->_em = Doctrine_EntityManager::getManagerForEntity($this->_entityName);
$this->_em = Doctrine_EntityManager::getManager($this->_entityName);
$this->_class = $this->_em->getClassMetadata($this->_entityName);
$this->_oid = self::$_index++;
......@@ -227,18 +228,15 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Countable, Ite
// get the column count
$count = count($this->_data);
$this->_values = $this->cleanData($this->_data);
$this->_extractIdentifier( ! $isNewEntry);
if ($isNewEntry) {
if ($count > count($this->_values)) {
if ($count > 0) {
$this->_state = Doctrine_Entity::STATE_TDIRTY;
} else {
$this->_state = Doctrine_Entity::STATE_TCLEAN;
}
// set the default values for this record
$this->assignDefaultValues();
} else {
......@@ -251,8 +249,6 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Countable, Ite
//--
self::$_useAutoAccessorOverride = false; // @todo read from attribute the first time
$this->_em->manage($this); // @todo Remove
$this->construct(); // @todo Remove
}
/**
......@@ -509,7 +505,7 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Countable, Ite
$tmp = $data;
$data = array();
$fieldNames = $this->_em->getMapper($this->_entityName)->getFieldNames();
$fieldNames = $this->_em->getEntityPersister($this->_entityName)->getFieldNames();
foreach ($fieldNames as $fieldName) {
if (isset($tmp[$fieldName])) {
$data[$fieldName] = $tmp[$fieldName];
......@@ -650,13 +646,14 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Countable, Ite
$this->preUnserialize($event);
$manager = Doctrine_Manager::getInstance();
$connection = $manager->getConnectionForComponent(get_class($this));
$this->_entityName = get_class($this);
$manager = Doctrine_EntityManager::getManager($this->_entityName);
$connection = $manager->getConnection();
$this->_oid = self::$_index;
self::$_index++;
$this->_em = $connection;
$this->_em = $manager;
$array = unserialize($serialized);
......@@ -664,7 +661,6 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Countable, Ite
$this->$k = $v;
}
$this->_entityName = get_class($this);
$this->_class = $this->_em->getClassMetadata($this->_entityName);
foreach ($this->_data as $k => $v) {
......@@ -683,7 +679,6 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Countable, Ite
}
}
$this->_em->manage($this);
$this->cleanData($this->_data);
$this->_extractIdentifier($this->exists());
......@@ -997,7 +992,7 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Countable, Ite
* @throws Doctrine_Record_Exception if trying to get a value of unknown property / related component
* @return mixed
*/
public function get($fieldName, $load = true)
public function get($fieldName, $load = false)
{
/*// check for custom accessor, if not done yet.
if ( ! isset(self::$_accessorCache[$this->_entityName][$fieldName])) {
......@@ -1020,63 +1015,36 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Countable, Ite
return $this->$getter();
}*/
// Use built-in accessor functionality
// Use built-in accessor functionality
$nullObj = Doctrine_Null::$INSTANCE;
$value = $nullObj;
if (isset($this->_data[$fieldName])) {
if ($this->_data[$fieldName] !== $nullObj) {
return $this->_data[$fieldName];
}
if ($this->_data[$fieldName] === $nullObj && $load) {
$this->load();
$value = $this->_data[$fieldName];
}
if ($value === $nullObj) {
$value = null;
}
return $value;
}
if (isset($this->_values[$fieldName])) {
return $this->_values[$fieldName];
}
try {
if ( ! isset($this->_references[$fieldName]) && $load) {
$rel = $this->_class->getRelation($fieldName);
$this->_references[$fieldName] = $rel->fetchRelatedFor($this);
}
if ($this->_references[$fieldName] === Doctrine_Null::$INSTANCE) {
return null;
}
return $this->_references[$fieldName];
} catch (Doctrine_Relation_Exception $e) {
//echo $e->getTraceAsString();
//echo "<br/><br/>";
foreach ($this->_class->getFilters() as $filter) {
if (($value = $filter->filterGet($this, $fieldName, $value)) !== null) {
return $value;
return $this->_data[$fieldName] !== $nullObj ?
$this->_data[$fieldName] : null;
} else if (isset($this->_references[$fieldName])) {
return $this->_references[$fieldName] !== $nullObj ?
$this->_references[$fieldName] : null;
} else {
if ($this->_class->hasField($fieldName)) {
if ($load) {
$this->load();
return $this->get($fieldName);
} else {
return null;
}
} else if ($this->_class->hasRelation($fieldName)) {
if ($load) {
$rel = $this->_class->getRelation($fieldName);
$this->_references[$fieldName] = $rel->fetchRelatedFor($this);
return $this->_references[$fieldName] !== $nullObj ?
$this->_references[$fieldName] : null;
} else {
return null;
}
} else {
throw Doctrine_Entity_Exception::invalidField($fieldName);
}
}
}
/**
* mapValue
* This simple method is used for mapping values to $values property.
* Usually this method is used internally by Doctrine for the mapping of
* aggregate values.
*
* @param string $name the name of the mapped value
* @param mixed $value mixed value to be mapped
* @return void
* @todo Maybe better placed in the Mapper.
*/
public function mapValue($name, $value)
{
$this->_values[$name] = $value;
}
public function getClassName()
{
......@@ -1097,9 +1065,9 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Countable, Ite
*
* @return Doctrine_Entity
*/
public function set($fieldName, $value, $load = true)
{
if (isset($this->_data[$fieldName])) {
public function set($fieldName, $value, $load = false)
{
if ($this->_class->hasField($fieldName)) {
if ($value instanceof Doctrine_Entity) {
$type = $this->_class->getTypeOf($fieldName);
// FIXME: composite key support
......@@ -1111,16 +1079,12 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Countable, Ite
}
if ($load) {
$old = $this->get($fieldName, $load);
$old = $this->get($fieldName, true);
} else {
$old = $this->_data[$fieldName];
$old = isset($this->_data[$fieldName]) ? $this->_data[$fieldName] : null;
}
if ($old !== $value) {
if ($value === null) {
$value = Doctrine_Null::$INSTANCE;
}
$this->_data[$fieldName] = $value;
$this->_modified[] = $fieldName;
......@@ -1139,18 +1103,10 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Countable, Ite
break;
}
}
} else if ($this->_class->hasRelation($fieldName)) {
$this->rawSetReference($fieldName, $value);
} else {
try {
$this->rawSetReference($fieldName, $value);
} catch (Doctrine_Relation_Exception $e) {
//echo $e->getTraceAsString();
//echo "<br/><br/>";
foreach ($this->_class->getFilters() as $filter) {
if (($value = $filter->filterSet($this, $fieldName, $value)) !== null) {
return $value;
}
}
}
throw Doctrine_Entity_Exception::invalidField($fieldName);
}
}
......@@ -2067,8 +2023,7 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Countable, Ite
public function getEntityManager()
{
if ( ! $this->_em) {
$this->_em = Doctrine_Manager::getInstance()->getCurrentConnection();
// future: $this->_em = Doctrine_EntityManager::getManagerForEntity($this->_entityName);
$this->_em = Doctrine_EntityManager::getManager($this->_entityName);
}
return $this->_em;
}
......@@ -2106,7 +2061,6 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Countable, Ite
{
if ($this->_state != self::STATE_LOCKED) {
$this->_em->detach($this);
$this->_em->removeRecord($this);
$this->_data = array();
$this->_id = array();
......
......@@ -23,6 +23,11 @@ class Doctrine_Entity_Exception extends Doctrine_Exception
return new self("Invalid value. The value of a reference in a ManyToMany "
. "association must be a Collection.");
}
public static function invalidField($field)
{
return new self("Invalid field: '$field'.");
}
}
?>
\ No newline at end of file
......@@ -35,13 +35,13 @@
class Doctrine_EntityRepository
{
protected $_entityName;
protected $_conn;
protected $_em;
protected $_classMetadata;
public function __construct($entityName, Doctrine_ClassMetadata $classMetadata)
{
$this->_entityName = $entityName;
$this->_conn = $classMetadata->getConnection();
$this->_em = $classMetadata->getConnection();
$this->_classMetadata = $classMetadata;
}
......@@ -59,7 +59,7 @@ class Doctrine_EntityRepository
if ( ! empty($alias)) {
$alias = ' ' . trim($alias);
}
return Doctrine_Query::create($this->_conn)->from($this->_entityName . $alias);
return Doctrine_Query::create($this->_em)->from($this->_entityName . $alias);
}
/**
......@@ -69,7 +69,7 @@ class Doctrine_EntityRepository
*/
public function clear()
{
$this->_conn->unitOfWork->clearIdentitiesForEntity($this->_classMetadata->getRootClassName());
$this->_em->unitOfWork->clearIdentitiesForEntity($this->_classMetadata->getRootClassName());
}
/**
......@@ -170,7 +170,7 @@ class Doctrine_EntityRepository
*/
public function findByDql($dql, array $params = array(), $hydrationMode = null)
{
$query = new Doctrine_Query($this->_conn);
$query = new Doctrine_Query($this->_em);
$component = $this->getComponentName();
$dql = 'FROM ' . $component . ' WHERE ' . $dql;
......
......@@ -63,7 +63,7 @@ abstract class Doctrine_Hydrator_Abstract
*
* @param Doctrine_Connection|null $connection
*/
public function __construct(Doctrine_Connection $em)
public function __construct(Doctrine_EntityManager $em)
{
$this->_em = $em;
$this->_nullObject = Doctrine_Null::$INSTANCE;
......
......@@ -43,7 +43,7 @@ class Doctrine_Hydrator_RecordDriver
/** The EntityManager */
private $_em;
public function __construct(Doctrine_Connection $em)
public function __construct(Doctrine_EntityManager $em)
{
$this->_nullObject = Doctrine_Null::$INSTANCE;
$this->_em = $em;
......@@ -93,7 +93,7 @@ class Doctrine_Hydrator_RecordDriver
public function getElement(array $data, $className)
{
return $this->_em->createEntity2($className, $data);
return $this->_em->createEntity($className, $data);
}
public function addRelatedIndexedElement(Doctrine_Entity $entity1, $property,
......
......@@ -375,6 +375,10 @@ class Doctrine_HydratorNew extends Doctrine_Hydrator_Abstract
foreach ($data as $key => $value) {
// Parse each column name only once. Cache the results.
if ( ! isset($cache[$key])) {
// check ignored names. fastest solution for now. if we get more we'll start
// to introduce a list.
if ($key == 'doctrine_rownum') continue;
// cache general information like the column name <-> field name mapping
$e = explode('__', $key);
$columnName = strtolower(array_pop($e));
......
......@@ -680,7 +680,7 @@ class Doctrine_Manager extends Doctrine_Configurable implements Countable, Itera
*/
public function getMapper($componentName)
{
return $this->getConnectionForComponent($componentName)->getMapper($componentName);
return $this->getConnectionForComponent($componentName)->getEntityPersister($componentName);
}
/**
......
......@@ -30,7 +30,6 @@
* @version $Revision: 3406 $
* @link www.phpdoctrine.org
* @since 2.0
* @todo Move all finder stuff to EntityRepository.
* @todo Rename to "EntityPersister" or similar.
*/
class Doctrine_Mapper
......@@ -69,6 +68,12 @@ class Doctrine_Mapper
*/
private $_entityListeners = array();
/**
* Enter description here...
*
* @var unknown_type
* @todo To EntityManager.
*/
private $_dataTemplate = array();
......@@ -121,6 +126,7 @@ class Doctrine_Mapper
* @param $array an array where keys are field names and
* values representing field values
* @return Doctrine_Entity the created record object
* @todo To EntityManager.
*/
public function create(array $array = array())
{
......@@ -158,24 +164,16 @@ class Doctrine_Mapper
}
}
public function detach(Doctrine_Entity $entity)
{
return $this->_conn->unitOfWork->detach($entity);
}
/**
* Executes a named query.
* Enter description here...
*
* @param string $queryName The name that was used when storing the query.
* @param array $params The query parameters.
* @return mixed The result.
* @deprecated
* @param Doctrine_Entity $entity
* @return unknown
* @todo To EntityManager
*/
public function executeNamedQuery($queryName, $params = array(), $hydrationMode = Doctrine::HYDRATE_RECORD)
public function detach(Doctrine_Entity $entity)
{
return Doctrine_Manager::getInstance()
->createNamedQuery($queryName)
->execute($params, $hydrationMode);
return $this->_conn->unitOfWork->detach($entity);
}
/**
......@@ -184,6 +182,7 @@ class Doctrine_Mapper
*
* @return void
* @todo what about a more descriptive name? clearIdentityMap?
* @todo To EntityManager
*/
public function clear()
{
......@@ -197,6 +196,7 @@ class Doctrine_Mapper
* @param Doctrine_Entity $record record to be added
* @return boolean
* @todo Better name? registerRecord? Move elsewhere to the new location of the identity maps.
* @todo Remove.
*/
public function addRecord(Doctrine_Entity $record)
{
......@@ -213,6 +213,7 @@ class Doctrine_Mapper
*
* @return boolean TRUE if the entity was previously not managed and is now managed,
* FALSE otherwise (the entity is already managed).
* @todo Remove.
*/
public function manage(Doctrine_Entity $record)
{
......@@ -244,6 +245,7 @@ class Doctrine_Mapper
* returns a new record.
*
* @return Doctrine_Entity
* @todo To EntityManager.
*/
public function getRecord(array $data)
{
......@@ -310,6 +312,7 @@ class Doctrine_Mapper
* applyInheritance
* @param $where query where part to be modified
* @return string query where part with column aggregation inheritance added
* @todo What to do with this? Remove if possible.
*/
final public function applyInheritance($where)
{
......@@ -357,6 +360,8 @@ class Doctrine_Mapper
* for the field can be skipped. Used i.e. during hydration to
* improve performance on large and/or complex results.
* @return mixed prepared value
* @todo To EntityManager. Make private and use in createEntity().
* .. Or, maybe better: Move to hydrator for performance reasons.
*/
public function prepareValue($fieldName, $value, $typeHint = null)
{
......@@ -398,43 +403,6 @@ class Doctrine_Mapper
}
return $value;
}
/**
* Hydrates the given data into the entity.
*
*/
/*public function hydrate(Doctrine_Entity $entity, array $data)
{
$this->_values = array_merge($this->_values, $this->cleanData($data));
$this->_data = array_merge($this->_data, $data);
$this->_extractIdentifier(true);
}*/
/**
* getTree
*
* getter for associated tree
*
* @return mixed if tree return instance of Doctrine_Tree, otherwise returns false
* @todo Part of the NestedSet Behavior plugin. Move outta here some day...
*/
public function getTree()
{
return $this->_classMetadata->getTree();
}
/**
* isTree
*
* determine if table acts as tree
*
* @return mixed if tree return true, otherwise returns false
* @todo Part of the NestedSet Behavior plugin. Move outta here some day...
*/
public function isTree()
{
return $this->_classMetadata->isTree();
}
/**
* getComponentName
......@@ -729,26 +697,11 @@ class Doctrine_Mapper
return true;
}
public function executeQuery(Doctrine_Query $query)
{
}
public function getTable()
{
return $this->_classMetadata;
}
public function getClassMetadata()
{
return $this->_classMetadata;
}
public function dump()
{
var_dump($this->_invokedMethods);
}
public function free()
{
$this->_mappingStrategy = null;
......@@ -759,8 +712,6 @@ class Doctrine_Mapper
return $this->_mappingStrategy;
}
public function getFieldName($columnName)
{
return $this->_mappingStrategy->getFieldName($columnName);
......
......@@ -1129,7 +1129,6 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Seria
$modifyLimit = true;
if ( ! empty($this->_sqlParts['limit']) || ! empty($this->_sqlParts['offset'])) {
if ($needsSubQuery) {
$subquery = $this->getLimitSubquery();
// what about composite keys?
......@@ -1138,7 +1137,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Seria
switch (strtolower($this->_conn->getDriverName())) {
case 'mysql':
// mysql doesn't support LIMIT in subqueries
$list = $this->_conn->execute($subquery, $params)->fetchAll(Doctrine::FETCH_COLUMN);
$list = $this->_conn->execute($subquery, $params)->fetchAll(Doctrine::FETCH_COLUMN);
$subquery = implode(', ', array_map(array($this->_conn, 'quote'), $list));
break;
case 'pgsql':
......@@ -1192,18 +1191,18 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Seria
*/
public function getLimitSubquery()
{
$map = reset($this->_queryComponents);
$table = $map['table'];
$map = reset($this->_queryComponents);
$table = $map['table'];
$componentAlias = key($this->_queryComponents);
// get short alias
$alias = $this->getTableAlias($componentAlias);
$alias = $this->getTableAlias($componentAlias);
// what about composite keys?
$idFieldNames = (array)$table->getIdentifier();
$primaryKey = $alias . '.' . $table->getColumnName($idFieldNames[0]);
// initialize the base of the subquery
$subquery = 'SELECT DISTINCT ' . $this->_conn->quoteIdentifier($primaryKey);
$subquery = 'SELECT DISTINCT ' . $this->_conn->quoteIdentifier($primaryKey);
$driverName = $this->_conn->getAttribute(Doctrine::ATTR_DRIVER_NAME);
......@@ -1261,7 +1260,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Seria
$subquery .= ( ! empty($this->_sqlParts['orderby']))? ' ORDER BY ' . implode(', ', $this->_sqlParts['orderby']) : '';
// add driver specific limit clause
$subquery = $this->_conn->modifyLimitQuery($subquery, $this->_sqlParts['limit'], $this->_sqlParts['offset']);
$subquery = $this->_conn->modifyLimitSubquery($table, $subquery, $this->_sqlParts['limit'], $this->_sqlParts['offset']);
$parts = $this->_tokenizer->quoteExplode($subquery, ' ', "'", "'");
......@@ -1643,7 +1642,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Seria
$this->_sqlParts['from'][] = $queryPart;
//echo "<br /><br />" . $table->getComponentName() . "---3---" . $name . "<br /><br />";
$this->_queryComponents[$componentAlias] = array(
'table' => $table, 'mapper' => $this->_conn->getMapper($name), 'map' => null);
'table' => $table, 'mapper' => $this->_conn->getEntityPersister($name), 'map' => null);
return $table;
}
......
......@@ -530,7 +530,7 @@ abstract class Doctrine_Query_Abstract
{
$table = $this->_conn->getMetadata($componentName);
$tableAlias = $this->getSqlTableAlias($componentAlias, $table->getTableName());
$customJoins = $this->_conn->getMapper($componentName)->getCustomJoins();
$customJoins = $this->_conn->getEntityPersister($componentName)->getCustomJoins();
$sql = '';
foreach ($customJoins as $componentName => $joinType) {
$joinedTable = $this->_conn->getMetadata($componentName);
......@@ -1051,12 +1051,12 @@ abstract class Doctrine_Query_Abstract
$e = explode('.', $components[0]);
if (count($e) === 1) {
$queryComponents[$alias]['mapper'] = $this->_conn->getMapper($e[0]);
$queryComponents[$alias]['table'] = $queryComponents[$alias]['mapper']->getTable();
$queryComponents[$alias]['table'] = $queryComponents[$alias]['mapper']->getClassMetadata();
} else {
$queryComponents[$alias]['parent'] = $e[0];
$queryComponents[$alias]['relation'] = $queryComponents[$e[0]]['table']->getRelation($e[1]);
$queryComponents[$alias]['mapper'] = $this->_conn->getMapper($queryComponents[$alias]['relation']->getForeignComponentName());
$queryComponents[$alias]['table'] = $queryComponents[$alias]['mapper']->getTable();
$queryComponents[$alias]['table'] = $queryComponents[$alias]['mapper']->getClassMetadata();
}
if (isset($components[1])) {
$queryComponents[$alias]['agg'] = $components[1];
......
......@@ -154,7 +154,7 @@ abstract class Doctrine_Relation implements ArrayAccess
}
}
$this->definition = $def;
$this->_foreignMapper = $this->getTable()->getConnection()->getMapper($def['class']);
$this->_foreignMapper = $this->getTable()->getConnection()->getEntityPersister($def['class']);
}
/**
......@@ -257,9 +257,8 @@ abstract class Doctrine_Relation implements ArrayAccess
*/
final public function getTable()
{
return Doctrine_Manager::getInstance()
->getConnectionForComponent($this->definition['class'])
->getMetadata($this->definition['class']);
return Doctrine_EntityManager::getManager($this->definition['class'])
->getClassMetadata($this->definition['class']);
}
/**
......
......@@ -271,7 +271,7 @@ class Doctrine_Relation_Parser
*/
public function getImpl(array &$def, $key)
{
$conn = $this->_table->getConnection();
$em = $this->_table->getEntityManager();
if (in_array('Doctrine_Template', class_parents($def[$key]))) {
$impl = $this->_table->getImpl($def[$key]);
if ($impl === null) {
......@@ -280,7 +280,7 @@ class Doctrine_Relation_Parser
$def[$key] = $impl;
}
return $conn->getMetadata($def[$key]);
return $em->getClassMetadata($def[$key]);
}
protected function _isTemplate($className)
......
......@@ -41,6 +41,7 @@ class Orm_Component_AccessTest extends Doctrine_OrmTestCase
public function setUp()
{
parent::setUp();
$em = new Doctrine_EntityManager(new Doctrine_Connection_Mock());
$this->user = new ForumUser();
}
......@@ -57,10 +58,10 @@ class Orm_Component_AccessTest extends Doctrine_OrmTestCase
/**
* @test
*/
public function shouldMarkExistingFieldAsSetOnNewRecord()
public function shouldMarkEmptyFieldAsNotSetOnNewRecord()
{
$this->assertTrue(isset($this->user->username));
$this->assertTrue(isset($this->user['username']));
$this->assertFalse(isset($this->user->username));
$this->assertFalse(isset($this->user['username']));
}
/**
......@@ -113,7 +114,7 @@ class Orm_Component_AccessTest extends Doctrine_OrmTestCase
/**
* @test
* @expectedException Doctrine_Record_Exception
* @expectedException Doctrine_Entity_Exception
*/
public function shouldNotBeAbleToSetNonExistantField()
{
......@@ -122,7 +123,7 @@ class Orm_Component_AccessTest extends Doctrine_OrmTestCase
/**
* @test
* @expectedException Doctrine_Record_Exception
* @expectedException Doctrine_Entity_Exception
*/
public function shouldNotBeAbleToSetNonExistantFieldWithOffset()
{
......@@ -131,14 +132,13 @@ class Orm_Component_AccessTest extends Doctrine_OrmTestCase
/**
* @test
* @expectedException Doctrine_Record_Exception
* @expectedException Doctrine_Entity_Exception
*/
public function shouldNotBeAbleToSetNonExistantFieldAsPartInSetArray()
{
$this->user->setArray(array(
'rat' => 'meus',
'id' => 22));
}
......
......@@ -6,7 +6,6 @@ if (!defined('PHPUnit_MAIN_METHOD')) {
require_once 'lib/DoctrineTestInit.php';
// Tests
require_once 'Orm/Component/TestTest.php';
require_once 'Orm/Component/AccessTest.php';
require_once 'Orm/Component/CollectionTest.php';
......@@ -21,7 +20,6 @@ class Orm_Component_AllTests
{
$suite = new Doctrine_TestSuite('Doctrine Orm Component');
$suite->addTestSuite('Orm_Component_TestTest');
$suite->addTestSuite('Orm_Component_AccessTest');
$suite->addTestSuite('Orm_Component_CollectionTest');
......
......@@ -40,6 +40,8 @@ class Orm_Component_CollectionTest extends Doctrine_OrmTestCase
public function setUp()
{
parent::setUp();
$em = new Doctrine_EntityManager(new Doctrine_Connection_Mock());
$this->coll = new Doctrine_Collection('ForumUser');
//we create a CmsUser with username as key column and add a user to it
......
<?php
require_once 'lib/DoctrineTestInit.php';
class Orm_Component_TestTest extends Doctrine_OrmTestCase
{
protected function setUp()
{
parent::setUp();
$this->loadFixtures('forum', 'common', array('users', 'admins'));
}
public function testTest()
{
$this->assertEquals(0, 0);
}
public function testFixture()
{
$forumUsers = $this->sharedFixture['connection']->query("FROM ForumUser u");
$this->assertEquals(2, count($forumUsers));
$forumUsers[0]->delete();
unset($forumUsers[0]);
$this->assertEquals(1, count($forumUsers));
}
public function testFixture2()
{
$forumUsers = $this->sharedFixture['connection']->query("FROM ForumUser u");
$this->assertEquals(2, count($forumUsers));
}
public function testFixture3()
{
$forumAdmins = $this->sharedFixture['connection']->query("FROM ForumAdministrator adm");
$this->assertEquals(1, count($forumAdmins));
$forumAdmins[0]->delete();
}
}
\ No newline at end of file
<?php
require_once 'lib/DoctrineTestInit.php';
class Orm_EntityManagerTest extends Doctrine_OrmTestCase
{
protected function setUp() {
parent::setUp();
}
protected function tearDown() {
Doctrine_EntityManager::unbindAllManagers();
Doctrine_EntityManager::releaseAllManagers();
parent::tearDown();
}
public function testInstantiationRegistersInstanceInStaticMap()
{
$em = new Doctrine_EntityManager(new Doctrine_Connection_Mock());
$this->assertSame($em, Doctrine_EntityManager::getManager('SomeEntity'));
}
public function testStaticGetManagerThrowsExceptionIfNoManagerAvailable()
{
try {
Doctrine_EntityManager::getManager('SomeEntity');
$this->fail("Expected exception not thrown.");
} catch (Doctrine_EntityManager_Exception $ex) {}
}
public function testBindingValidEntityToNamedManager()
{
$em = new Doctrine_EntityManager(new Doctrine_Connection_Mock(null), 'myEM');
Doctrine_EntityManager::bindEntityToManager('SomeEntity', 'myEM');
$this->assertSame($em, Doctrine_EntityManager::getManager('SomeEntity'));
}
public function testBindingEntityToInvalidManagerThrowsExceptionOnRetrieval()
{
// will work. we don't check the existence of the EM during binding
Doctrine_EntityManager::bindEntityToManager('SomeEntity', 'myEM');
// exception on access
try {
Doctrine_EntityManager::getManager('SomeEntity');
$this->fail();
} catch (Doctrine_EntityManager_Exception $ex) {}
}
}
\ No newline at end of file
......@@ -9,7 +9,7 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
protected function setUp()
{
parent::setUp();
$this->_em = $this->sharedFixture['connection'];
$this->_em = new Doctrine_EntityManager(new Doctrine_Connection_Mock());
}
/** Getter for the hydration mode dataProvider */
......@@ -44,8 +44,8 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
// Faked query components
$queryComponents = array(
'u' => array(
'table' => $this->sharedFixture['connection']->getClassMetadata('CmsUser'),
'mapper' => $this->sharedFixture['connection']->getMapper('CmsUser'),
'table' => $this->_em->getClassMetadata('CmsUser'),
'mapper' => $this->_em->getEntityPersister('CmsUser'),
'parent' => null,
'relation' => null,
'map' => null
......@@ -105,18 +105,18 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
// Faked query components
$queryComponents = array(
'u' => array(
'table' => $this->sharedFixture['connection']->getClassMetadata('CmsUser'),
'mapper' => $this->sharedFixture['connection']->getMapper('CmsUser'),
'table' => $this->_em->getClassMetadata('CmsUser'),
'mapper' => $this->_em->getEntityPersister('CmsUser'),
'parent' => null,
'relation' => null,
'map' => null,
'agg' => array('0' => 'nameUpper')
),
'p' => array(
'table' => $this->sharedFixture['connection']->getClassMetadata('CmsPhonenumber'),
'mapper' => $this->sharedFixture['connection']->getMapper('CmsPhonenumber'),
'table' => $this->_em->getClassMetadata('CmsPhonenumber'),
'mapper' => $this->_em->getEntityPersister('CmsPhonenumber'),
'parent' => 'u',
'relation' => $this->sharedFixture['connection']->getClassMetadata('CmsUser')->getRelation('phonenumbers'),
'relation' => $this->_em->getClassMetadata('CmsUser')->getRelation('phonenumbers'),
'map' => null
)
);
......@@ -155,14 +155,16 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
$result = $hydrator->hydrateResultSet($this->_createParserResult(
$stmt, $queryComponents, $tableAliasMap, $hydrationMode, true));
//var_dump($result);
if ($hydrationMode == Doctrine::HYDRATE_ARRAY) {
//var_dump($result);
}
$this->assertEquals(2, count($result));
$this->assertTrue(is_array($result));
$this->assertTrue(is_array($result[0]));
$this->assertTrue(is_array($result[1]));
$this->assertEquals(3, count($result[0][0]));
// first user => 2 phonenumbers
$this->assertEquals(2, count($result[0][0]['phonenumbers']));
$this->assertEquals('ROMANB', $result[0]['nameUpper']);
......@@ -198,17 +200,17 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
// Faked query components
$queryComponents = array(
'u' => array(
'table' => $this->sharedFixture['connection']->getClassMetadata('CmsUser'),
'mapper' => $this->sharedFixture['connection']->getMapper('CmsUser'),
'table' => $this->_em->getClassMetadata('CmsUser'),
'mapper' => $this->_em->getEntityPersister('CmsUser'),
'parent' => null,
'relation' => null,
'map' => null
),
'p' => array(
'table' => $this->sharedFixture['connection']->getClassMetadata('CmsPhonenumber'),
'mapper' => $this->sharedFixture['connection']->getMapper('CmsPhonenumber'),
'table' => $this->_em->getClassMetadata('CmsPhonenumber'),
'mapper' => $this->_em->getEntityPersister('CmsPhonenumber'),
'parent' => 'u',
'relation' => $this->sharedFixture['connection']->getClassMetadata('CmsUser')->getRelation('phonenumbers'),
'relation' => $this->_em->getClassMetadata('CmsUser')->getRelation('phonenumbers'),
'map' => null,
'agg' => array('0' => 'numPhones')
)
......@@ -273,18 +275,18 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
// Faked query components
$queryComponents = array(
'u' => array(
'table' => $this->sharedFixture['connection']->getClassMetadata('CmsUser'),
'mapper' => $this->sharedFixture['connection']->getMapper('CmsUser'),
'table' => $this->_em->getClassMetadata('CmsUser'),
'mapper' => $this->_em->getEntityPersister('CmsUser'),
'parent' => null,
'relation' => null,
'agg' => array('0' => 'nameUpper'),
'map' => 'id'
),
'p' => array(
'table' => $this->sharedFixture['connection']->getClassMetadata('CmsPhonenumber'),
'mapper' => $this->sharedFixture['connection']->getMapper('CmsPhonenumber'),
'table' => $this->_em->getClassMetadata('CmsPhonenumber'),
'mapper' => $this->_em->getEntityPersister('CmsPhonenumber'),
'parent' => 'u',
'relation' => $this->sharedFixture['connection']->getClassMetadata('CmsUser')->getRelation('phonenumbers'),
'relation' => $this->_em->getClassMetadata('CmsUser')->getRelation('phonenumbers'),
'map' => 'phonenumber'
)
);
......@@ -375,25 +377,25 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
// Faked query components
$queryComponents = array(
'u' => array(
'table' => $this->sharedFixture['connection']->getClassMetadata('CmsUser'),
'mapper' => $this->sharedFixture['connection']->getMapper('CmsUser'),
'table' => $this->_em->getClassMetadata('CmsUser'),
'mapper' => $this->_em->getEntityPersister('CmsUser'),
'parent' => null,
'relation' => null,
'map' => null,
'agg' => array('0' => 'nameUpper')
),
'p' => array(
'table' => $this->sharedFixture['connection']->getClassMetadata('CmsPhonenumber'),
'mapper' => $this->sharedFixture['connection']->getMapper('CmsPhonenumber'),
'table' => $this->_em->getClassMetadata('CmsPhonenumber'),
'mapper' => $this->_em->getEntityPersister('CmsPhonenumber'),
'parent' => 'u',
'relation' => $this->sharedFixture['connection']->getClassMetadata('CmsUser')->getRelation('phonenumbers'),
'relation' => $this->_em->getClassMetadata('CmsUser')->getRelation('phonenumbers'),
'map' => null
),
'a' => array(
'table' => $this->sharedFixture['connection']->getClassMetadata('CmsArticle'),
'mapper' => $this->sharedFixture['connection']->getMapper('CmsArticle'),
'table' => $this->_em->getClassMetadata('CmsArticle'),
'mapper' => $this->_em->getEntityPersister('CmsArticle'),
'parent' => 'u',
'relation' => $this->sharedFixture['connection']->getClassMetadata('CmsUser')->getRelation('articles'),
'relation' => $this->_em->getClassMetadata('CmsUser')->getRelation('articles'),
'map' => null
),
);
......@@ -528,32 +530,32 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
// Faked query components
$queryComponents = array(
'u' => array(
'table' => $this->sharedFixture['connection']->getClassMetadata('CmsUser'),
'mapper' => $this->sharedFixture['connection']->getMapper('CmsUser'),
'table' => $this->_em->getClassMetadata('CmsUser'),
'mapper' => $this->_em->getEntityPersister('CmsUser'),
'parent' => null,
'relation' => null,
'map' => null,
'agg' => array('0' => 'nameUpper')
),
'p' => array(
'table' => $this->sharedFixture['connection']->getClassMetadata('CmsPhonenumber'),
'mapper' => $this->sharedFixture['connection']->getMapper('CmsPhonenumber'),
'table' => $this->_em->getClassMetadata('CmsPhonenumber'),
'mapper' => $this->_em->getEntityPersister('CmsPhonenumber'),
'parent' => 'u',
'relation' => $this->sharedFixture['connection']->getClassMetadata('CmsUser')->getRelation('phonenumbers'),
'relation' => $this->_em->getClassMetadata('CmsUser')->getRelation('phonenumbers'),
'map' => null
),
'a' => array(
'table' => $this->sharedFixture['connection']->getClassMetadata('CmsArticle'),
'mapper' => $this->sharedFixture['connection']->getMapper('CmsArticle'),
'table' => $this->_em->getClassMetadata('CmsArticle'),
'mapper' => $this->_em->getEntityPersister('CmsArticle'),
'parent' => 'u',
'relation' => $this->sharedFixture['connection']->getClassMetadata('CmsUser')->getRelation('articles'),
'relation' => $this->_em->getClassMetadata('CmsUser')->getRelation('articles'),
'map' => null
),
'c' => array(
'table' => $this->sharedFixture['connection']->getClassMetadata('CmsComment'),
'mapper' => $this->sharedFixture['connection']->getMapper('CmsComment'),
'table' => $this->_em->getClassMetadata('CmsComment'),
'mapper' => $this->_em->getEntityPersister('CmsComment'),
'parent' => 'a',
'relation' => $this->sharedFixture['connection']->getClassMetadata('CmsArticle')->getRelation('comments'),
'relation' => $this->_em->getClassMetadata('CmsArticle')->getRelation('comments'),
'map' => null
),
);
......@@ -719,17 +721,17 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
// Faked query components
$queryComponents = array(
'c' => array(
'table' => $this->sharedFixture['connection']->getClassMetadata('ForumCategory'),
'mapper' => $this->sharedFixture['connection']->getMapper('ForumCategory'),
'table' => $this->_em->getClassMetadata('ForumCategory'),
'mapper' => $this->_em->getEntityPersister('ForumCategory'),
'parent' => null,
'relation' => null,
'map' => null
),
'b' => array(
'table' => $this->sharedFixture['connection']->getClassMetadata('ForumBoard'),
'mapper' => $this->sharedFixture['connection']->getMapper('ForumBoard'),
'table' => $this->_em->getClassMetadata('ForumBoard'),
'mapper' => $this->_em->getEntityPersister('ForumBoard'),
'parent' => 'c',
'relation' => $this->sharedFixture['connection']->getClassMetadata('ForumCategory')->getRelation('boards'),
'relation' => $this->_em->getClassMetadata('ForumCategory')->getRelation('boards'),
'map' => null
),
);
......
......@@ -8,8 +8,9 @@ class Orm_UnitOfWorkTestCase extends Doctrine_OrmTestCase
protected function setUp() {
parent::setUp();
$em = new Doctrine_EntityManager(new Doctrine_Connection_Mock());
$this->_user = new ForumUser();
$this->_unitOfWork = $this->sharedFixture['connection']->unitOfWork;
$this->_unitOfWork = $em->getUnitOfWork();
}
protected function tearDown() {
......
......@@ -5,8 +5,10 @@ require_once 'Doctrine_TestCase.php';
require_once 'Doctrine_TestUtil.php';
require_once 'Doctrine_DbalTestCase.php';
require_once 'Doctrine_OrmTestCase.php';
require_once 'Doctrine_OrmFunctionalTestCase.php';
require_once 'Doctrine_TestSuite.php';
require_once 'Doctrine_OrmTestSuite.php';
require_once 'Doctrine_OrmFunctionalTestSuite.php';
require_once 'Doctrine_DbalTestSuite.php';
require_once '../lib/Doctrine.php';
......
......@@ -5,118 +5,5 @@
*/
class Doctrine_OrmTestCase extends Doctrine_TestCase
{
/**
* The currently loaded model names of the fixtures for the testcase.
*/
private $_loadedFixtures = array();
/**
* All loaded fixtures during test execution. Common fixture cache.
*/
private static $_fixtures = array();
/**
* The names of all tables that were already exported. Each table is exported
* only once. Then it's just filled & erased for each testmethod in a testcase
* that uses one or more fixtures.
*/
private static $_exportedTables = array();
/**
* setUp()
*
* Note: This setUp() and the one of DbalTestCase currently look identical. However,
* please dont pull this method up. In the future with a separation of Dbal/Orm
* this setUp() will take care of a ORM connection/session/manager initialization
* and the DBAL setUp() will take care of just a DBAL connection.
*/
protected function setUp()
{
// Setup a db connection if there is none, yet. This makes it possible
// to run tests that use a connection standalone.
if ( ! isset($this->sharedFixture['connection'])) {
$this->sharedFixture['connection'] = Doctrine_TestUtil::getConnection();
}
}
/**
* Loads a data fixture into the database. This method must only be called
* from within the setUp() method of testcases. The database will then be
* populated with fresh data of all loaded fixtures for each test method.
*
* WARNING: A single testcase should never load fixtures from different scenarios of
* the same package as the concistency and uniqueness of keys is not guaranteed.
*
* @param string $package The package name. Must be one of Doctrine's test model packages
* (forum, cms or ecommerce).
* @param string $scenario The fixture scenario. A model package can have many fixture
* scenarios. Within a scenario all primary keys and foreign keys
* of fixtures are consistent and unique.
* @param string $name The name of the fixture to load from the specified package.
*/
protected function loadFixture($package, $scenario, $name)
{
$uniqueName = $package . '/' . $scenario . '/' . $name;
if ( ! isset(self::$_fixtures[$uniqueName])) {
// load fixture file
$fixtureFile = 'fixtures'
. DIRECTORY_SEPARATOR . $package
. DIRECTORY_SEPARATOR . $scenario
. DIRECTORY_SEPARATOR . $name
. '.php';
require $fixtureFile;
self::$_fixtures[$uniqueName] = $fixture;
}
$fixture = self::$_fixtures[$uniqueName];
$this->_loadedFixtures[] = $fixture['model'];
$conn = $this->sharedFixture['connection'];
$classMetadata = $conn->getClassMetadata($fixture['model']);
$tableName = $classMetadata->getTableName();
if ( ! in_array($tableName, self::$_exportedTables)) {
$conn->export->exportClasses(array($fixture['model']));
self::$_exportedTables[] = $tableName;
}
foreach ($fixture['rows'] as $row) {
$conn->insert($tableName, $row);
}
}
/**
* Loads multiple fixtures of the same package and scenario.
* This method must only be called from within the setUp() method of testcases.
* The database will then be populated with fresh data of all loaded fixtures for each
* test method.
*
* WARNING: A single testcase should never load fixtures from different scenarios of
* the same package as the concistency and uniqueness of keys is not guaranteed.
*
* @param string $package The package name. Must be one of Doctrine's test model packages
* (forum, cms or ecommerce).
* @param string $scenario The fixture scenario. A model package can have many fixture
* scenarios. Within a scenario all primary keys and foreign keys
* of fixtures are consistent and unique.
* @param array $names The names of the fixtures to load from the specified package.
*/
protected function loadFixtures($package, $scenario, array $names)
{
foreach ($names as $name) {
$this->loadFixture($package, $scenario, $name);
}
}
/**
* Sweeps the database tables of all used fixtures.
*/
protected function tearDown()
{
$conn = $this->sharedFixture['connection'];
foreach (array_reverse($this->_loadedFixtures) as $model) {
$conn->exec("DELETE FROM " . $conn->getClassMetadata($model)->getTableName());
}
}
}
\ No newline at end of file
......@@ -8,11 +8,5 @@
*/
class Doctrine_OrmTestSuite extends Doctrine_TestSuite
{
protected function setUp()
{
$this->sharedFixture['connection'] = Doctrine_TestUtil::getConnection();
}
protected function tearDown()
{}
}
\ No newline at end of file
......@@ -4,6 +4,7 @@ class CmsUser extends Doctrine_Entity
public static function initMetadata($class)
{
$class->mapColumn('id', 'integer', 4, array('primary' => true, 'autoincrement' => true));
$class->mapColumn('status', 'string', 50);
$class->mapColumn('username', 'string', 255);
$class->mapColumn('name', 'string', 255);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment