Commit ab65ad5b authored by romanb's avatar romanb

Refactorings. Started with new hydrator for 2.0.

parent ff112209
This diff is collapsed.
......@@ -449,7 +449,8 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
}
} else {
// @todo does not take composite keys into account
$list[] = $record->getIncremented();
$ids = $record->identifier();
$list[] = count($ids) > 0 ? array_pop($ids) : null;
}
}
......@@ -564,7 +565,9 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
if ( ! isset($name)) {
foreach ($this->data as $record) {
$value = $record->getIncremented();
// FIXME: composite key support
$ids = $record->identifier();
$value = count($ids) > 0 ? array_pop($ids) : null;
if ($value !== null) {
$list[] = $value;
}
......@@ -583,7 +586,8 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
}
} else {
foreach ($this->data as $record) {
$value = $record->getIncremented();
$ids = $record->identifier();
$value = count($ids) > 0 ? array_pop($ids) : null;
if ($value !== null) {
$list[] = $value;
}
......
This diff is collapsed.
......@@ -20,7 +20,23 @@
*/
/**
* Doctrine_Connection_UnitOfWork
* The UnitOfWork is responsible for writing out changes to the database at
* the correct time and in the correct order.
*
* 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>Dirty entity</b>: ...
*
* <b>Removed entity</b>: ...
*
* <b>Clean entity</b>: ...
*
* @package Doctrine
* @subpackage Connection
......@@ -105,12 +121,19 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
*/
public function registerNew(Doctrine_Record $entity)
{
if (isset($this->_dirtyEntities[$entity->getOid()])) {
if ( ! $entity->identifier()) {
throw new Doctrine_Connection_Exception("Entity without identity "
. "can't be registered as new.");
}
$oid = $entity->getOid();
if (isset($this->_dirtyEntities[$oid])) {
throw new Doctrine_Connection_Exception("Dirty object can't be registered as new.");
} else if (isset($this->_removedEntities[$entity->getOid()])) {
} else if (isset($this->_removedEntities[$oid])) {
throw new Doctrine_Connection_Exception("Removed object can't be registered as new.");
} else if (isset($this->_newEntities[$oid])) {
throw new Doctrine_Connection_Exception("Object already registered as new. Can't register twice.");
}
$this->_newEntities[$entity->getOid()] = $entity;
$this->_newEntities[$oid] = $entity;
}
public function isRegisteredNew(Doctrine_Record $entity)
......@@ -131,12 +154,17 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
*/
public function registerDirty(Doctrine_Record $entity)
{
if ( ! $entity->identifier()) {
throw new Doctrine_Connection_Exception("Entity without identity "
. "can't be registered as dirty.");
}
$oid = $entity->getOid();
if (isset($this->_removedEntities[$entity->getOid()])) {
throw new Doctrine_Connection_Exception("Removed object can't be registered as dirty.");
} else if (isset($this->_newEntities[$entity->getOid()])) {
throw new Doctrine_Connection_Exception("");
}
$this->_dirtyEntities[$entity->getOid()] = $entity;
if ( ! isset($this->_dirtyEntities[$oid], $this->_newEntities[$oid])) {
$this->_dirtyEntities[$entity->getOid()] = $entity;
}
}
public function isRegisteredDirty(Doctrine_Record $entity)
......@@ -149,8 +177,21 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
*/
public function registerRemoved(Doctrine_Record $entity)
{
if ($entity->isTransient()) {
return;
}
$this->unregisterIdentity($entity);
$this->_removedEntities[$entity->getOid()] = $entity;
$oid = $entity->getOid();
if (isset($this->_newEntities[$oid])) {
unset($this->_newEntities[$oid]);
return;
}
if (isset($this->_dirtyEntities[$oid])) {
unset($this->_dirtyEntities[$oid]);
}
if ( ! isset($this->_removedEntities[$oid])) {
$this->_removedEntities[$oid] = $entity;
}
}
public function isRegisteredRemoved(Doctrine_Record $entity)
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* 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
* <http://www.phpdoctrine.org>.
*/
/**
* Base class for all custom user-defined repositories.
* Provides basic finder methods, common to all repositories.
*
* @package Doctrine
* @subpackage EntityRepository
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.phpdoctrine.org
* @since 2.0
* @version $Revision$
* @author Roman Borschel <roman@code-factory.org>
* @todo package:orm
*/
class Doctrine_EntityRepository
{
protected $_entityName;
protected $_conn;
protected $_classMetadata;
public function __construct($entityName, Doctrine_ClassMetadata $classMetadata)
{
$this->_entityName = $entityName;
$this->_conn = $classMetadata->getConnection();
$this->_classMetadata = $classMetadata;
}
/**
* createQuery
* creates a new Doctrine_Query object and adds the component name
* of this table as the query 'from' part
*
* @param string Optional alias name for component aliasing.
*
* @return Doctrine_Query
*/
protected function _createQuery($alias = '')
{
if ( ! empty($alias)) {
$alias = ' ' . trim($alias);
}
return Doctrine_Query::create($this->_conn)->from($this->_entityName . $alias);
}
/**
* clear
* clears the first level cache (identityMap)
*
* @return void
* @todo what about a more descriptive name? clearIdentityMap?
*/
public function clear()
{
$this->_conn->unitOfWork->clearIdentitiesForEntity($this->_classMetadata->getRootClassName());
}
/**
* Finds an entity by its primary key.
*
* @param $id database row id
* @param int $hydrationMode Doctrine::HYDRATE_ARRAY or Doctrine::HYDRATE_RECORD
* @return mixed Array or Doctrine_Record or false if no result
* @todo Remove. Move to EntityRepository.
*/
public function find($id, $hydrationMode = null)
{
if (is_null($id)) {
return false;
}
if (is_array($id) && count($id) > 1) {
// it's a composite key. keys = field names, values = values.
$values = array_values($id);
$keys = array_keys($id);
} else {
$values = is_array($id) ? array_values($id) : array($id);
$keys = $this->_classMetadata->getIdentifier();
}
return $this->_createQuery()
->where(implode(' = ? AND ', $keys) . ' = ?')
->fetchOne($values, $hydrationMode);
}
/**
* Finds all entities of the mapper's class.
* Use with care.
*
* @param int $hydrationMode Doctrine::HYDRATE_ARRAY or Doctrine::HYDRATE_RECORD
* @return Doctrine_Collection
*/
public function findAll($hydrationMode = null)
{
return $this->_createQuery()->execute(array(), $hydrationMode);
}
/**
* findBy
*
* @param string $column
* @param string $value
* @param string $hydrationMode
* @return void
*/
protected function findBy($fieldName, $value, $hydrationMode = null)
{
return $this->_createQuery()->where($fieldName . ' = ?')->execute(array($value), $hydrationMode);
}
/**
* findOneBy
*
* @param string $column
* @param string $value
* @param string $hydrationMode
* @return void
*/
protected function findOneBy($fieldName, $value, $hydrationMode = null)
{
$results = $this->_createQuery()->where($fieldName . ' = ?')->limit(1)->execute(
array($value), $hydrationMode);
return $hydrationMode === Doctrine::HYDRATE_ARRAY ? array_shift($results) : $results->getFirst();
}
/**
* findBySql
* finds records with given SQL where clause
* returns a collection of records
*
* @param string $dql DQL after WHERE clause
* @param array $params query parameters
* @param int $hydrationMode Doctrine::FETCH_ARRAY or Doctrine::FETCH_RECORD
* @return Doctrine_Collection
*
* @todo This actually takes DQL, not SQL, but it requires column names
* instead of field names. This should be fixed to use raw SQL instead.
*/
public function findBySql($dql, array $params = array(), $hydrationMode = null)
{
return $this->_createQuery()->where($dql)->execute($params, $hydrationMode);
}
/**
* findByDql
* finds records with given DQL where clause
* returns a collection of records
*
* @param string $dql DQL after WHERE clause
* @param array $params query parameters
* @param int $hydrationMode Doctrine::FETCH_ARRAY or Doctrine::FETCH_RECORD
* @return Doctrine_Collection
*/
public function findByDql($dql, array $params = array(), $hydrationMode = null)
{
$query = new Doctrine_Query($this->_conn);
$component = $this->getComponentName();
$dql = 'FROM ' . $component . ' WHERE ' . $dql;
return $query->query($dql, $params, $hydrationMode);
}
/**
* Adds support for magic finders.
* findByColumnName, findByRelationAlias
* findById, findByContactId, etc.
*
* @return void
* @throws Doctrine_Mapper_Exception If the method called is an invalid find* method
* or no find* method at all and therefore an invalid
* method call.
*/
public function __call($method, $arguments)
{
if (substr($method, 0, 6) == 'findBy') {
$by = substr($method, 6, strlen($method));
$method = 'findBy';
} else if (substr($method, 0, 9) == 'findOneBy') {
$by = substr($method, 9, strlen($method));
$method = 'findOneBy';
} else {
throw new Doctrine_Mapper_Exception("Undefined method '$method'.");
}
if (isset($by)) {
if ( ! isset($arguments[0])) {
throw new Doctrine_Mapper_Exception('You must specify the value to findBy.');
}
$fieldName = Doctrine::tableize($by);
$hydrationMode = isset($arguments[1]) ? $arguments[1]:null;
if ($this->_classMetadata->hasField($fieldName)) {
return $this->$method($fieldName, $arguments[0], $hydrationMode);
} else if ($this->_classMetadata->hasRelation($by)) {
$relation = $this->_classMetadata->getRelation($by);
if ($relation['type'] === Doctrine_Relation::MANY) {
throw new Doctrine_Mapper_Exception('Cannot findBy many relationship.');
}
return $this->$method($relation['local'], $arguments[0], $hydrationMode);
} else {
throw new Doctrine_Mapper_Exception('Cannot find by: ' . $by . '. Invalid field or relationship alias.');
}
}
}
}
\ No newline at end of file
......@@ -52,13 +52,14 @@ class Doctrine_Hydrator extends Doctrine_Hydrator_Abstract
* 'table' => 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)
* 'map' => Custom index to use as the key in the result (if any),
* 'agg' => List of aggregate values (sql alias => dql alias)
* )
* )
* @return mixed The created object/array graph.
*/
public function hydrateResultSet($stmt, $tableAliases, $hydrationMode = null)
{
{
if ($hydrationMode === null) {
$hydrationMode = $this->_hydrationMode;
}
......@@ -82,7 +83,7 @@ class Doctrine_Hydrator extends Doctrine_Hydrator_Abstract
// Used variables during hydration
reset($this->_queryComponents);
$rootAlias = key($this->_queryComponents);
$rootComponentName = $this->_queryComponents[$rootAlias]['mapper']->getComponentName();
$rootComponentName = $this->_queryComponents[$rootAlias]['table']->getComponentName();
// if only one component is involved we can make our lives easier
$isSimpleQuery = count($this->_queryComponents) <= 1;
// Holds hydration listeners that get called during hydration
......@@ -110,7 +111,7 @@ class Doctrine_Hydrator extends Doctrine_Hydrator_Abstract
foreach ($this->_queryComponents as $dqlAlias => $component) {
// disable lazy-loading of related elements during hydration
$component['table']->setAttribute(Doctrine::ATTR_LOAD_REFERENCES, false);
$componentName = $component['mapper']->getComponentName();
$componentName = $component['table']->getClassName();
$listeners[$componentName] = $component['table']->getRecordListener();
$identifierMap[$dqlAlias] = array();
$prev[$dqlAlias] = array();
......@@ -127,9 +128,8 @@ class Doctrine_Hydrator extends Doctrine_Hydrator_Abstract
//
// hydrate the data of the root entity from the current row
//
$table = $this->_queryComponents[$rootAlias]['table'];
$mapper = $this->_queryComponents[$rootAlias]['mapper'];
$componentName = $mapper->getComponentName();
$class = $this->_queryComponents[$rootAlias]['table'];
$componentName = $class->getComponentName();
// just event stuff
$event->set('data', $rowData[$rootAlias]);
......@@ -175,9 +175,7 @@ class Doctrine_Hydrator extends Doctrine_Hydrator_Abstract
foreach ($rowData as $dqlAlias => $data) {
$index = false;
$map = $this->_queryComponents[$dqlAlias];
$table = $map['table'];
$mapper = $map['mapper'];
$componentName = $mapper->getComponentName();
$componentName = $map['table']->getComponentName();
// just event stuff
$event->set('data', $data);
......@@ -186,7 +184,7 @@ class Doctrine_Hydrator extends Doctrine_Hydrator_Abstract
$parent = $map['parent'];
$relation = $map['relation'];
$relationAlias = $map['relation']->getAlias();
$relationAlias = $relation->getAlias();
$path = $parent . '.' . $dqlAlias;
......@@ -195,16 +193,19 @@ class Doctrine_Hydrator extends Doctrine_Hydrator_Abstract
}
// check the type of the relation
if ( ! $relation->isOneToOne() && $driver->initRelated($prev[$parent], $relationAlias)) {
if ( ! $relation->isOneToOne()) {
$oneToOne = false;
// append element
if (isset($nonemptyComponents[$dqlAlias])) {
$driver->initRelated($prev[$parent], $relationAlias);
if ( ! isset($identifierMap[$path][$id[$parent]][$id[$dqlAlias]])) {
$element = $driver->getElement($data, $componentName);
// just event stuff
$event->set('data', $element);
$listeners[$componentName]->postHydrate($event);
//--
if ($field = $this->_getCustomIndexField($dqlAlias)) {
// TODO: we should check this earlier. Fields used in INDEXBY
// must be unique. Then this can be removed here.
......@@ -223,7 +224,7 @@ class Doctrine_Hydrator extends Doctrine_Hydrator_Abstract
$index = $identifierMap[$path][$id[$parent]][$id[$dqlAlias]];
}
// register collection for later snapshots
$driver->registerCollection($prev[$parent][$relationAlias]);
//$driver->registerCollection($prev[$parent][$relationAlias]);
}
} else {
// 1-1 relation
......@@ -315,11 +316,17 @@ class Doctrine_Hydrator extends Doctrine_Hydrator_Abstract
if ( ! isset($cache[$key])) {
// cache general information like the column name <-> field name mapping
$e = explode('__', $key);
$columnName = strtolower(array_pop($e));
$columnName = strtolower(array_pop($e));
$cache[$key]['dqlAlias'] = $this->_tableAliases[strtolower(implode('__', $e))];
$mapper = $this->_queryComponents[$cache[$key]['dqlAlias']]['mapper'];
$classMetadata = $mapper->getClassMetadata();
$fieldName = $mapper->getFieldName($columnName);
// check whether it's an aggregate value or a regular field
if (isset($this->_queryComponents[$cache[$key]['dqlAlias']]['agg'][$columnName])) {
$fieldName = $this->_queryComponents[$cache[$key]['dqlAlias']]['agg'][$columnName];
} else {
$fieldName = $mapper->getFieldName($columnName);
}
$cache[$key]['fieldName'] = $fieldName;
// cache identifier information
......@@ -343,10 +350,6 @@ class Doctrine_Hydrator extends Doctrine_Hydrator_Abstract
$dqlAlias = $cache[$key]['dqlAlias'];
$fieldName = $cache[$key]['fieldName'];
if (isset($this->_queryComponents[$dqlAlias]['agg'][$fieldName])) {
$fieldName = $this->_queryComponents[$dqlAlias]['agg'][$fieldName];
}
if ($cache[$key]['isIdentifier']) {
$id[$dqlAlias] .= '|' . $value;
}
......
......@@ -71,8 +71,6 @@ class Doctrine_Hydrator_ArrayDriver
if ( ! isset($data[$name])) {
$data[$name] = array();
}
return true;
}
/**
......
......@@ -20,7 +20,7 @@
*/
/**
* Doctrine_Hydrate_RecordDriver
* Doctrine_Hydrator_RecordDriver
* Hydration strategy used for creating graphs of entity objects.
*
* @package Doctrine
......@@ -34,8 +34,13 @@
*/
class Doctrine_Hydrator_RecordDriver
{
/** Collections initialized by the driver */
protected $_collections = array();
/** Mappers */
protected $_mappers = array();
/** Memory for initialized relations */
private $_initializedRelations = array();
/** Null object */
private $_nullObject;
public function __construct()
......@@ -53,54 +58,32 @@ class Doctrine_Hydrator_RecordDriver
public function getLastKey($coll)
{
$coll->end();
return $coll->key();
// check needed because of mixed results
if (is_array($coll)) {
end($coll);
return key($coll);
} else {
$coll->end();
return $coll->key();
}
}
public function initRelated($record, $name)
public function initRelated(Doctrine_Record $record, $name)
{
return true;
/*
if ( ! is_array($record)) {
$record[$name];
return true;
if ( ! isset($this->_initializedRelations[$record->getOid()][$name])) {
$relation = $record->getClassMetadata()->getRelation($name);
$relatedClass = $relation->getTable();
$coll = $this->getElementCollection($relatedClass->getClassName());
$coll->setReference($record, $relation);
$record[$name] = $coll;
$this->_initializedRelations[$record->getOid()][$name] = true;
}
return false;
*/
}
public function registerCollection(Doctrine_Collection $coll)
{
$this->_collections[] = $coll;
}
/**
* isIdentifiable
* returns whether or not a given data row is identifiable (it contains
* all primary key fields specified in the second argument)
*
* @param array $row
* @param Doctrine_Table $table
* @return boolean
*/
/*public function isIdentifiable(array $row, Doctrine_Table $table)
{
$primaryKeys = $table->getIdentifierColumnNames();
if (is_array($primaryKeys)) {
foreach ($primaryKeys as $id) {
if ( ! isset($row[$id])) {
return false;
}
}
} else {
if ( ! isset($row[$primaryKeys])) {
return false;
}
}
return true;
}*/
public function getNullPointer()
{
......@@ -127,6 +110,7 @@ class Doctrine_Hydrator_RecordDriver
}
$this->_collections = array();
$this->_mappers = array();
$this->_initializedRelations = array();
}
/**
......
This diff is collapsed.
......@@ -90,23 +90,6 @@ class Doctrine_Mapper
}
}
/**
* createQuery
* creates a new Doctrine_Query object and adds the component name
* of this table as the query 'from' part
*
* @param string Optional alias name for component aliasing.
*
* @return Doctrine_Query
*/
public function createQuery($alias = '')
{
if ( ! empty($alias)) {
$alias = ' ' . trim($alias);
}
return Doctrine_Query::create($this->_conn)->from($this->getComponentName() . $alias);
}
/**
* sets the connection for this class
*
......@@ -139,7 +122,7 @@ class Doctrine_Mapper
*/
public function create(array $array = array())
{
$record = new $this->_domainClassName($this, true);
$record = new $this->_domainClassName();
$record->fromArray($array);
return $record;
......@@ -177,79 +160,6 @@ class Doctrine_Mapper
{
return $this->_conn->unitOfWork->detach($entity);
}
/**
* Finds an entity by its primary key.
*
* @param $id database row id
* @param int $hydrationMode Doctrine::HYDRATE_ARRAY or Doctrine::HYDRATE_RECORD
* @return mixed Array or Doctrine_Record or false if no result
* @todo Remove. Move to EntityRepository.
*/
public function find($id, $hydrationMode = null)
{
if (is_null($id)) {
return false;
}
$id = is_array($id) ? array_values($id) : array($id);
return $this->createQuery()
->where(implode(' = ? AND ', (array) $this->_classMetadata->getIdentifier()) . ' = ?')
->fetchOne($id, $hydrationMode);
}
/**
* Finds all entities of the mapper's class.
* Use with care.
*
* @param int $hydrationMode Doctrine::HYDRATE_ARRAY or Doctrine::HYDRATE_RECORD
* @return Doctrine_Collection
* @todo Remove. Move to EntityRepository.
*/
public function findAll($hydrationMode = null)
{
return $this->createQuery()->execute(array(), $hydrationMode);
}
/**
* findBySql
* finds records with given SQL where clause
* returns a collection of records
*
* @param string $dql DQL after WHERE clause
* @param array $params query parameters
* @param int $hydrationMode Doctrine::FETCH_ARRAY or Doctrine::FETCH_RECORD
* @return Doctrine_Collection
*
* @todo This actually takes DQL, not SQL, but it requires column names
* instead of field names. This should be fixed to use raw SQL instead.
* @todo Remove. Move to EntityRepository.
*/
public function findBySql($dql, array $params = array(), $hydrationMode = null)
{
return $this->createQuery()->where($dql)->execute($params, $hydrationMode);
}
/**
* findByDql
* finds records with given DQL where clause
* returns a collection of records
*
* @param string $dql DQL after WHERE clause
* @param array $params query parameters
* @param int $hydrationMode Doctrine::FETCH_ARRAY or Doctrine::FETCH_RECORD
* @return Doctrine_Collection
* @todo Remove. Move to EntityRepository.
*/
public function findByDql($dql, array $params = array(), $hydrationMode = null)
{
$query = new Doctrine_Query($this->_conn);
$component = $this->getComponentName();
$dql = 'FROM ' . $component . ' WHERE ' . $dql;
return $query->query($dql, $params, $hydrationMode);
}
/**
* Executes a named query.
......@@ -349,9 +259,7 @@ class Doctrine_Mapper
}
if ($found) {
$record = new $this->_domainClassName($this, true, $data);
$data = array();
return $record;
return new $this->_domainClassName(true, $data);
}
$idHash = $this->_conn->unitOfWork->getIdentifierHash($id);
......@@ -360,12 +268,12 @@ class Doctrine_Mapper
$this->_classMetadata->getRootClassName())) {
$record->hydrate($data);
} else {
$record = new $this->_domainClassName($this, false, $data);
$record = new $this->_domainClassName(false, $data);
$this->_conn->unitOfWork->registerIdentity($record);
}
$data = array();
} else {
$record = new $this->_domainClassName($this, true, $data);
$record = new $this->_domainClassName(true, $data);
}
return $record;
......@@ -545,83 +453,6 @@ class Doctrine_Mapper
return $this->_domainClassName;
}
/**
* findBy
*
* @param string $column
* @param string $value
* @param string $hydrationMode
* @return void
* @todo Remove. Move to EntityRepository.
*/
protected function findBy($fieldName, $value, $hydrationMode = null)
{
return $this->createQuery()->where($fieldName . ' = ?')->execute(array($value), $hydrationMode);
}
/**
* findOneBy
*
* @param string $column
* @param string $value
* @param string $hydrationMode
* @return void
* @todo Remove. Move to EntityRepository.
*/
protected function findOneBy($fieldName, $value, $hydrationMode = null)
{
$results = $this->createQuery()->where($fieldName . ' = ?')->limit(1)->execute(
array($value), $hydrationMode);
return $hydrationMode === Doctrine::HYDRATE_ARRAY ? array_shift($results) : $results->getFirst();
}
/**
* __call
*
* Adds support for magic finders.
* findByColumnName, findByRelationAlias
* findById, findByContactId, etc.
*
* @return void
* @throws Doctrine_Mapper_Exception If the method called is an invalid find* method
* or no find* method at all and therefore an invalid
* method call.
* @todo Remove. Move to EntityRepository.
*/
public function __call($method, $arguments)
{
if (substr($method, 0, 6) == 'findBy') {
$by = substr($method, 6, strlen($method));
$method = 'findBy';
} else if (substr($method, 0, 9) == 'findOneBy') {
$by = substr($method, 9, strlen($method));
$method = 'findOneBy';
} else {
throw new Doctrine_Mapper_Exception("Undefined method '$method'.");
}
if (isset($by)) {
if ( ! isset($arguments[0])) {
throw new Doctrine_Mapper_Exception('You must specify the value to findBy.');
}
$fieldName = Doctrine::tableize($by);
$hydrationMode = isset($arguments[1]) ? $arguments[1]:null;
if ($this->_classMetadata->hasField($fieldName)) {
return $this->$method($fieldName, $arguments[0], $hydrationMode);
} else if ($this->_classMetadata->hasRelation($by)) {
$relation = $this->_classMetadata->getRelation($by);
if ($relation['type'] === Doctrine_Relation::MANY) {
throw new Doctrine_Mapper_Exception('Cannot findBy many relationship.');
}
return $this->$method($relation['local'], $arguments[0], $hydrationMode);
} else {
throw new Doctrine_Mapper_Exception('Cannot find by: ' . $by . '. Invalid field or relationship alias.');
}
}
}
/**
* Saves an entity and all it's related entities.
*
......@@ -795,7 +626,12 @@ class Doctrine_Mapper
$query = 'DELETE FROM ' . $assocTable->getTableName()
. ' WHERE ' . $rel->getForeign() . ' = ?'
. ' AND ' . $rel->getLocal() . ' = ?';
$this->_conn->execute($query, array($r->getIncremented(), $record->getIncremented()));
// FIXME: composite key support
$ids1 = $r->identifier();
$id1 = count($ids1) > 0 ? array_pop($ids1) : null;
$ids2 = $record->identifier();
$id2 = count($ids2) > 0 ? array_pop($ids2) : null;
$this->_conn->execute($query, array($id1, $id2));
}
$assocMapper = $this->_conn->getMapper($assocTable->getComponentName());
......@@ -804,7 +640,6 @@ class Doctrine_Mapper
$assocRecord->set($assocTable->getFieldName($rel->getForeign()), $r);
$assocRecord->set($assocTable->getFieldName($rel->getLocal()), $record);
$assocMapper->save($assocRecord);
//$this->saveSingleRecord($assocRecord);
}
}
}
......@@ -890,19 +725,6 @@ class Doctrine_Mapper
return true;
}
public function hasAttribute($key)
{
switch ($key) {
case Doctrine::ATTR_LOAD_REFERENCES:
case Doctrine::ATTR_QUERY_LIMIT:
case Doctrine::ATTR_COLL_KEY:
case Doctrine::ATTR_VALIDATE:
return true;
default:
return false;
}
}
public function executeQuery(Doctrine_Query $query)
{
......
......@@ -111,7 +111,8 @@ class Doctrine_Mapper_JoinedStrategy extends Doctrine_Mapper_Strategy
if ( ! $value->exists()) {
$value->save();
}
$record->set($field, $value->getIncremented());
$idValues = $value->identifier();
$record->set($field, $idValues[0]);
}
}
......
......@@ -18,7 +18,7 @@
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
Doctrine::autoload('Doctrine_Query_Abstract');
/**
* Doctrine_Query
* A Doctrine_Query object represents a DQL query. It is used to query databases for
......
This diff is collapsed.
......@@ -93,18 +93,15 @@ class Doctrine_Relation_Association extends Doctrine_Relation
* @return Doctrine_Record|Doctrine_Collection
*/
public function fetchRelatedFor(Doctrine_Record $record)
{
$id = $record->getIncremented();
//var_dump($id);
//echo "<br /><br />";
{
// FIXME: composite key support
$ids = $record->identifier();
$id = count($ids) > 0 ? array_pop($ids) : null;
if (empty($id) || ! $this->_foreignMapper->getClassMetadata()->getAttribute(Doctrine::ATTR_LOAD_REFERENCES)) {
//echo "here" . $this->_foreignMapper->getAttribute(Doctrine::ATTR_LOAD_REFERENCES);
$coll = new Doctrine_Collection($this->getForeignComponentName());
} else {
$query = Doctrine_Query::create()->parseQuery($this->getRelationDql(1));
//echo $query->getDql() . "<br />";
//echo $query->getSql() . "<br />";
//echo "<br /><br />";
$coll = Doctrine_Query::create()->query($this->getRelationDql(1), array($id));
}
$coll->setReference($record, $this);
......
......@@ -18,7 +18,7 @@
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
Doctrine::autoload('Doctrine_Relation_Association');
/**
* Doctrine_Relation_Association_Self
*
......@@ -75,8 +75,10 @@ class Doctrine_Relation_Association_Self extends Doctrine_Relation_Association
}
public function fetchRelatedFor(Doctrine_Record $record)
{
$id = $record->getIncremented();
{
// FIXME: composite key support
$ids = $record->identifier();
$id = count($ids) > 0 ? array_pop($ids) : null;
$q = new Doctrine_RawSql();
......
......@@ -74,35 +74,11 @@ class Doctrine_Relation_Nest extends Doctrine_Relation_Association
return $dql;
}
/**
public function fetchRelatedFor(Doctrine_Record $record)
{
$id = $record->getIncremented();
if (empty($id) || ! $this->definition['table']->getAttribute(Doctrine::ATTR_LOAD_REFERENCES)) {
return new Doctrine_Collection($this->getTable());
} else {
$q = new Doctrine_Query();
$c = $this->getTable()->getComponentName();
$a = substr($c, 0, 1);
$c2 = $this->getAssociationTable()->getComponentName();
$a2 = substr($c2, 0, 1);
$q->from($c)
->innerJoin($c . '.' . $c2)
$sub = 'SELECT ' . $this->getForeign()
. ' FROM ' . $c2
. ' WHERE ' . $this->getLocal()
. ' = ?';
}
}
*/
public function fetchRelatedFor(Doctrine_Record $record)
{
$id = $record->getIncremented();
// FIXME: composite key support
$ids = $record->identifier();
$id = count($ids) > 0 ? array_pop($ids) : null;
if (empty($id) || ! $this->_foreignMapper->getClassMetadata()->getAttribute(Doctrine::ATTR_LOAD_REFERENCES)) {
......
......@@ -147,12 +147,6 @@ class Doctrine_Relation_Parser
$this->getRelations();
return $this->getRelation($alias, false);
} else {
/*try {
throw new Exception();
} catch (Exception $e) {
//echo "" . "<br />";
///echo $e->getTraceAsString() . "<br /><br /><br />";
}*/
throw new Doctrine_Relation_Exception("Unknown relation '$alias'.");
}
}
......
......@@ -84,7 +84,8 @@ class Doctrine_Validator
if ($value === Doctrine_Null::$INSTANCE) {
$value = null;
} else if ($value instanceof Doctrine_Record) {
$value = $value->getIncremented();
$ids = $value->identifier();
$value = count($ids) > 0 ? array_pop($ids) : null;
}
$dataType = $classMetadata->getTypeOf($fieldName);
......
This diff is collapsed.
......@@ -18,6 +18,8 @@ class Orm_UnitOfWorkTestCase extends Doctrine_OrmTestCase
public function testRegisterNew()
{
$this->_user->username = 'romanb';
$this->_user->id = 1;
$this->_unitOfWork->registerNew($this->_user);
$this->assertFalse($this->_unitOfWork->contains($this->_user));
$this->assertTrue($this->_unitOfWork->isRegisteredNew($this->_user));
......@@ -35,7 +37,15 @@ class Orm_UnitOfWorkTestCase extends Doctrine_OrmTestCase
$this->assertTrue($this->_unitOfWork->isRegisteredDirty($this->_user));
$this->assertFalse($this->_unitOfWork->isRegisteredNew($this->_user));
$this->assertFalse($this->_unitOfWork->isRegisteredRemoved($this->_user));
}
public function testRegisterRemovedOnTransientEntityIsIgnored()
{
$this->_user->username = 'romanb';
$this->_user->id = 1;
$this->assertFalse($this->_unitOfWork->isRegisteredRemoved($this->_user));
$this->_unitOfWork->registerRemoved($this->_user);
$this->assertFalse($this->_unitOfWork->isRegisteredRemoved($this->_user));
}
/*public function testSavedEntityHasIdentityAndIsManaged()
......
<?php
class CmsPhonenumber extends Doctrine_Record
{
public static function initMetadata($class)
{
$class->mapColumn('user_id', 'integer', 4);
$class->mapColumn('phonenumber', 'string', 50, array('primary' => true));
}
}
......@@ -6,5 +6,8 @@ class CmsUser extends Doctrine_Record
$class->mapColumn('id', 'integer', 4, array('primary' => true, 'autoincrement' => true));
$class->mapColumn('username', 'string', 255);
$class->mapColumn('name', 'string', 255);
$class->hasMany('CmsPhonenumber as phonenumbers', array(
'local' => 'id', 'foreign' => 'user_id'));
}
}
......@@ -77,7 +77,7 @@ class Doctrine_Access_TestCase extends Doctrine_UnitTestCase
$user->save();
$user = $this->connection->getMapper('User')->find($user->identifier());
$user = $this->connection->getRepository('User')->find($user->identifier());
$this->assertEqual($user->name, 'Jack');
$user['name'] = 'Jack';
......@@ -97,7 +97,7 @@ class Doctrine_Access_TestCase extends Doctrine_UnitTestCase
$user->save();
$user = $this->connection->getMapper('User')->find($user->identifier());
$user = $this->connection->getRepository('User')->find($user->identifier());
$this->assertEqual($user->name, 'Jack');
$user->name = 'Jack';
......@@ -115,7 +115,7 @@ class Doctrine_Access_TestCase extends Doctrine_UnitTestCase
$user->save();
$user = $this->connection->getMapper('User')->find($user->identifier());
$user = $this->connection->getRepository('User')->find($user->identifier());
$this->assertEqual($user->get('name'), 'Jack');
......
......@@ -168,7 +168,7 @@ class Doctrine_ClassTableInheritance_TestCase extends Doctrine_UnitTestCase
$profiler = new Doctrine_Connection_Profiler();
$this->conn->addListener($profiler);
$record = $this->conn->getMapper('CTITest')->find(1);
$record = $this->conn->getRepository('CTITest')->find(1);
$record->age = 11;
$record->name = 'Jack';
......@@ -193,7 +193,7 @@ class Doctrine_ClassTableInheritance_TestCase extends Doctrine_UnitTestCase
{
$this->conn->clear();
$record = $this->conn->getMapper('CTITest')->find(1);
$record = $this->conn->getRepository('CTITest')->find(1);
$this->assertEqual($record->id, 1);
$this->assertEqual($record->name, 'Jack');
......@@ -209,7 +209,7 @@ class Doctrine_ClassTableInheritance_TestCase extends Doctrine_UnitTestCase
$profiler = new Doctrine_Connection_Profiler();
$this->conn->addListener($profiler);
$record = $this->conn->getMapper('CTITest')->find(1);
$record = $this->conn->getRepository('CTITest')->find(1);
$record->delete();
......
......@@ -53,7 +53,7 @@ class Doctrine_CustomPrimaryKey_TestCase extends Doctrine_UnitTestCase
$this->assertEqual($c->identifier(), array('uid' => 1));
$this->connection->clear();
$c = $this->connection->getMapper('CustomPK')->find(1);
$c = $this->connection->getRepository('CustomPK')->find(1);
$this->assertEqual($c->identifier(), array('uid' => 1));
}
......
......@@ -60,7 +60,7 @@ class Doctrine_DataType_Boolean_TestCase extends Doctrine_UnitTestCase {
$this->connection->clear();
$test = $test->getMapper()->find($test->id);
$test = $test->getRepository()->find($test->id);
$this->assertIdentical($test->is_working, true);
}
public function testNormalQuerying() {
......
......@@ -172,7 +172,7 @@ class Doctrine_DataType_Enum_TestCase extends Doctrine_UnitTestCase
public function testFailingRefresh()
{
$enum = $this->connection->getMapper('EnumTest')->find(1);
$enum = $this->connection->getRepository('EnumTest')->find(1);
$this->conn->exec('DELETE FROM enum_test WHERE id = 1');
......
......@@ -197,7 +197,7 @@ class Doctrine_UnitTestCase extends UnitTestCase
//echo "exporting : " . var_dump($this->tables);
//echo "<br /><br />";
$this->conn->export->exportClasses($this->tables);
$this->objTable = $this->connection->getMapper('User');
$this->objTable = $this->connection->getRepository('User');
}
public function prepareData()
......
This diff is collapsed.
......@@ -41,9 +41,9 @@ class Doctrine_Query_JoinCondition2_TestCase extends Doctrine_UnitTestCase
public function prepareData()
{
$this->conn->getMapper('User')->clear();
$this->conn->getMapper('Group')->clear();
$this->conn->getMapper('Groupuser')->clear();
$this->conn->clear('User');
$this->conn->clear('Group');
$this->conn->clear('Groupuser');
$zYne = new User();
$zYne->name = 'zYne';
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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