moved managed record/entity handling to the UnitOfWork. identity maps are the next. started to remove obsolete table stuff.
This commit is contained in:
parent
2739ed843b
commit
072008b65d
@ -31,12 +31,21 @@
|
||||
class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializable
|
||||
{
|
||||
/**
|
||||
* The name of the domain class that is mapped to the database with this metadata.
|
||||
* The name of the entity class that is mapped to the database with this metadata.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_entityName;
|
||||
|
||||
/**
|
||||
* The name of the entity class that is at the root of the entity inheritance
|
||||
* hierarchy. If the entity is not part of an inheritance hierarchy this is the same
|
||||
* as the $_entityName.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_rootEntityName;
|
||||
|
||||
/**
|
||||
* The name of the custom mapper class used for the entity class.
|
||||
*
|
||||
@ -259,6 +268,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
|
||||
public function __construct($entityName, Doctrine_Connection $conn)
|
||||
{
|
||||
$this->_entityName = $entityName;
|
||||
$this->_rootEntityName = $entityName;
|
||||
$this->_conn = $conn;
|
||||
$this->_parser = new Doctrine_Relation_Parser($this);
|
||||
$this->_filters[] = new Doctrine_Record_Filter_Standard();
|
||||
@ -283,6 +293,11 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
|
||||
return $this->_entityName;
|
||||
}
|
||||
|
||||
public function getRootClassName()
|
||||
{
|
||||
return $this->_rootEntityName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
@ -648,12 +663,23 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
|
||||
* Gets the identifier (primary key) field(s) of the mapped class.
|
||||
*
|
||||
* @return mixed
|
||||
* @deprecated Use getIdentifierFieldNames()
|
||||
*/
|
||||
public function getIdentifier()
|
||||
{
|
||||
return $this->_identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the identifier (primary key) field(s) of the mapped class.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getIdentifierFieldNames()
|
||||
{
|
||||
return $this->_identifier;
|
||||
}
|
||||
|
||||
public function setIdentifier(array $identifier)
|
||||
{
|
||||
$this->_identifier = $identifier;
|
||||
@ -1107,6 +1133,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
|
||||
public function setParentClasses(array $classNames)
|
||||
{
|
||||
$this->_options['parents'] = $classNames;
|
||||
$this->_rootEntityName = array_pop($classNames);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -482,7 +482,12 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
|
||||
*/
|
||||
public function set($key, $record)
|
||||
{
|
||||
if( ! $record instanceOf Doctrine_Record) {
|
||||
if ( ! $record instanceOf Doctrine_Record) {
|
||||
try {
|
||||
throw new Exception();
|
||||
} catch (Exception $e) {
|
||||
echo $e->getTraceAsString() . "<br/><br/>";
|
||||
}
|
||||
throw new Doctrine_Record_Exception('Value variable in set is not an instance of Doctrine_Record');
|
||||
}
|
||||
|
||||
|
@ -664,7 +664,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
|
||||
|
||||
$query .= implode(', ', $a) . ')';
|
||||
// prepare and execute the statement
|
||||
|
||||
|
||||
return $this->exec($query, array_values($data));
|
||||
}
|
||||
|
||||
@ -1264,7 +1264,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
|
||||
public function flush()
|
||||
{
|
||||
$this->beginInternalTransaction();
|
||||
$this->unitOfWork->saveAll();
|
||||
$this->unitOfWork->flush();
|
||||
$this->commit();
|
||||
}
|
||||
|
||||
@ -1277,9 +1277,9 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$this->unitOfWork->detachAllManagedEntities();
|
||||
foreach ($this->_mappers as $mapper) {
|
||||
$mapper->getRepository()->evictAll();
|
||||
$mapper->clear();
|
||||
$mapper->clear(); // clear identity map of each mapper
|
||||
}
|
||||
}
|
||||
|
||||
@ -1292,6 +1292,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
|
||||
*/
|
||||
public function evictTables()
|
||||
{
|
||||
$this->clear();
|
||||
$this->tables = array();
|
||||
$this->_mappers = array();
|
||||
$this->exported = array();
|
||||
|
@ -88,20 +88,27 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
|
||||
{
|
||||
// get the flush tree
|
||||
$tree = $this->buildFlushTree($this->conn->getMappers());
|
||||
|
||||
|
||||
$tree = array_combine($tree, array_fill(0, count($tree), array()));
|
||||
|
||||
foreach ($this->_managedEntities as $oid => $entity) {
|
||||
$className = $entity->getClassName();
|
||||
$tree[$className][] = $entity;
|
||||
}
|
||||
|
||||
// save all records
|
||||
foreach ($tree as $name) {
|
||||
$mapper = $this->conn->getMapper($name);
|
||||
foreach ($mapper->getRepository() as $record) {
|
||||
$mapper->saveSingleRecord($record);
|
||||
foreach ($tree as $className => $entities) {
|
||||
$mapper = $this->conn->getMapper($className);
|
||||
foreach ($entities as $entity) {
|
||||
$mapper->saveSingleRecord($entity);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// save all associations
|
||||
foreach ($tree as $name) {
|
||||
$mapper = $this->conn->getMapper($name);
|
||||
foreach ($mapper->getRepository() as $record) {
|
||||
$mapper->saveAssociations($record);
|
||||
foreach ($tree as $className => $entities) {
|
||||
$mapper = $this->conn->getMapper($className);
|
||||
foreach ($entities as $entity) {
|
||||
$mapper->saveAssociations($entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -142,7 +149,7 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
|
||||
}
|
||||
$nm = $mapper->getComponentName();
|
||||
|
||||
$index = array_search($nm, $tree);
|
||||
$index = array_search($nm, $tree);
|
||||
|
||||
if ($index === false) {
|
||||
$tree[] = $nm;
|
||||
@ -162,7 +169,7 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
|
||||
|
||||
foreach ($rels as $rel) {
|
||||
$name = $rel->getTable()->getComponentName();
|
||||
$index2 = array_search($name,$tree);
|
||||
$index2 = array_search($name, $tree);
|
||||
$type = $rel->getType();
|
||||
|
||||
// skip self-referenced relations
|
||||
@ -187,7 +194,7 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
|
||||
continue;
|
||||
|
||||
unset($tree[$index2]);
|
||||
array_splice($tree,$index,0,$name);
|
||||
array_splice($tree, $index, 0, $name);
|
||||
} else {
|
||||
array_unshift($tree,$name);
|
||||
$index++;
|
||||
@ -196,8 +203,9 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
|
||||
$t = $rel->getAssociationFactory();
|
||||
$n = $t->getComponentName();
|
||||
|
||||
if ($index2 !== false)
|
||||
if ($index2 !== false) {
|
||||
unset($tree[$index2]);
|
||||
}
|
||||
|
||||
array_splice($tree, $index, 0, $name);
|
||||
$index++;
|
||||
@ -218,7 +226,7 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
|
||||
}
|
||||
}
|
||||
|
||||
return array_values($tree);
|
||||
return $tree;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -234,4 +242,83 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
|
||||
return $this->flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an entity to the pool of managed entities.
|
||||
*
|
||||
*/
|
||||
public function addManagedEntity(Doctrine_Record $entity)
|
||||
{
|
||||
$oid = $entity->getOid();
|
||||
if ( ! isset($this->_managedEntities[$oid])) {
|
||||
$this->_managedEntities[$oid] = $entity;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* get
|
||||
* @param integer $oid
|
||||
* @throws Doctrine_Table_Repository_Exception
|
||||
*/
|
||||
public function getManagedEntity($oid)
|
||||
{
|
||||
if ( ! isset($this->_managedEntities[$oid])) {
|
||||
throw new Doctrine_Connection_UnitOfWork_Exception("Unknown object identifier '$oid'.");
|
||||
}
|
||||
return $this->_managedEntities[$oid];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer $oid object identifier
|
||||
* @return boolean whether ot not the operation was successful
|
||||
*/
|
||||
public function detachManagedEntity(Doctrine_Record $entity)
|
||||
{
|
||||
$oid = $entity->getOid();
|
||||
if ( ! isset($this->_managedEntities[$oid])) {
|
||||
return false;
|
||||
}
|
||||
unset($this->_managedEntities[$oid]);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return integer number of records evicted
|
||||
*/
|
||||
public function detachAllManagedEntities()
|
||||
{
|
||||
$evicted = 0;
|
||||
foreach ($this->_managedEntities as $entity) {
|
||||
if ($this->detachManagedEntity($entity)) {
|
||||
$evicted++;
|
||||
}
|
||||
}
|
||||
return $evicted;
|
||||
}
|
||||
|
||||
/**
|
||||
* contains
|
||||
* @param integer $oid object identifier
|
||||
*/
|
||||
public function isManagedEntity($oid)
|
||||
{
|
||||
return isset($this->_managedEntities[$oid]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an entity to the identity map.
|
||||
*
|
||||
*/
|
||||
public function addToIdentityMap(Doctrine_Record $entity)
|
||||
{
|
||||
$id = implode(' ', $entity->identifier());
|
||||
$className = $entity->getClassMetadata()->getRootClassName();
|
||||
if (isset($this->_identityMap[$className][$id])) {
|
||||
return false;
|
||||
}
|
||||
$this->_identityMap[$className][$id] = $entity;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -58,15 +58,15 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
|
||||
|
||||
/**
|
||||
* @var array $identityMap first level cache
|
||||
* @todo Proper identity map implementation & move elsewhere?
|
||||
* @todo Move to UnitOfWork.
|
||||
*/
|
||||
protected $_identityMap = array();
|
||||
|
||||
/**
|
||||
* @var Doctrine_Table_Repository $repository record repository
|
||||
* @todo Needed? What is it used for? Does the identity map not suffice?
|
||||
* @todo Move to UnifOfWork together with identity map.
|
||||
*/
|
||||
protected $_repository;
|
||||
//protected $_repository;
|
||||
|
||||
|
||||
/**
|
||||
@ -78,11 +78,19 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
|
||||
*/
|
||||
public function __construct($name, Doctrine_ClassMetadata $classMetadata)
|
||||
{
|
||||
if ($name != $classMetadata->getClassName()) {
|
||||
try {
|
||||
throw new Exception();
|
||||
} catch (Exception $e) {
|
||||
echo $e->getTraceAsString() . "<br/><br/>";
|
||||
}
|
||||
}
|
||||
|
||||
$this->_domainClassName = $name;
|
||||
$this->_conn = $classMetadata->getConnection();
|
||||
$this->_classMetadata = $classMetadata;
|
||||
$this->setParent($this->_conn);
|
||||
$this->_repository = new Doctrine_Table_Repository($this);
|
||||
//$this->_repository = new Doctrine_Table_Repository($this);
|
||||
if ($classMetadata->getInheritanceType() == Doctrine::INHERITANCETYPE_JOINED) {
|
||||
$this->_mappingStrategy = new Doctrine_Mapper_JoinedStrategy($this);
|
||||
} else {
|
||||
@ -141,10 +149,10 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
|
||||
* @return Doctrine_Table_Repository
|
||||
* @todo refactor
|
||||
*/
|
||||
public function getRepository()
|
||||
/*public function getRepository()
|
||||
{
|
||||
return $this->_repository;
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* sets the connection for this class
|
||||
@ -184,6 +192,11 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
|
||||
|
||||
return $record;
|
||||
}
|
||||
|
||||
public function detach(Doctrine_Record $entity)
|
||||
{
|
||||
return $this->_conn->unitOfWork->detachManagedEntity($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds an entity by its primary key.
|
||||
@ -310,7 +323,7 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
|
||||
*/
|
||||
public function manage(Doctrine_Record $record)
|
||||
{
|
||||
return $this->getRepository()->add($record);
|
||||
return $this->_conn->unitOfWork->addManagedEntity($record);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -864,17 +877,6 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an entity.
|
||||
*/
|
||||
/*protected function _doUpdate(Doctrine_Record $record)
|
||||
{
|
||||
$identifier = $this->_convertFieldToColumnNames($record->identifier(), $this->_classMetadata);
|
||||
$data = $this->_convertFieldToColumnNames($record->getPrepared(), $this->_classMetadata);
|
||||
$this->_conn->update($this->_classMetadata->getTableName(), $data, $identifier);
|
||||
$record->assignIdentifier(true);
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Inserts an entity.
|
||||
*
|
||||
@ -900,60 +902,6 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a single entity into the database, without any related entities.
|
||||
*
|
||||
* @param Doctrine_Record $record The entity to insert.
|
||||
*/
|
||||
/*protected function _doInsert(Doctrine_Record $record)
|
||||
{
|
||||
$fields = $record->getPrepared();
|
||||
if (empty($fields)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($record->getClassMetadata() !== $this->_classMetadata) {
|
||||
echo $record->getClassMetadata()->getClassname() . ' != ' . $this->_classMetadata->getClassName() . "<br /><br />";
|
||||
try {
|
||||
throw new Exception();
|
||||
} catch (Exception $e) {
|
||||
echo $e->getTraceAsString() . "<br /><br />";
|
||||
}
|
||||
}
|
||||
|
||||
//$class = $record->getClassMetadata();
|
||||
$class = $this->_classMetadata;
|
||||
$identifier = (array) $class->getIdentifier();
|
||||
$fields = $this->_convertFieldToColumnNames($fields, $class);
|
||||
|
||||
$seq = $class->getTableOption('sequenceName');
|
||||
if ( ! empty($seq)) {
|
||||
$id = $this->_conn->sequence->nextId($seq);
|
||||
$seqName = $class->getIdentifier();
|
||||
$fields[$seqName] = $id;
|
||||
$record->assignIdentifier($id);
|
||||
}
|
||||
|
||||
$this->_conn->insert($class->getTableName(), $fields);
|
||||
|
||||
if (empty($seq) && count($identifier) == 1 && $identifier[0] == $class->getIdentifier() &&
|
||||
$class->getIdentifierType() != Doctrine::IDENTIFIER_NATURAL) {
|
||||
if (strtolower($this->_conn->getName()) == 'pgsql') {
|
||||
$seq = $class->getTableName() . '_' . $identifier[0];
|
||||
}
|
||||
|
||||
$id = $this->_conn->sequence->lastInsertId($seq);
|
||||
|
||||
if ( ! $id) {
|
||||
throw new Doctrine_Mapper_Exception("Couldn't get last insert identifier.");
|
||||
}
|
||||
|
||||
$record->assignIdentifier($id);
|
||||
} else {
|
||||
$record->assignIdentifier(true);
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Deletes given entity and all it's related entities.
|
||||
*
|
||||
@ -999,50 +947,6 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an entity.
|
||||
*/
|
||||
/*protected function _doDelete(Doctrine_Record $record)
|
||||
{
|
||||
try {
|
||||
$this->_conn->beginInternalTransaction();
|
||||
$this->_deleteComposites($record);
|
||||
|
||||
$record->state(Doctrine_Record::STATE_TDIRTY);
|
||||
|
||||
$identifier = $this->_convertFieldToColumnNames($record->identifier(), $this->_classMetadata);
|
||||
$this->_conn->delete($this->_classMetadata->getTableName(), $identifier);
|
||||
$record->state(Doctrine_Record::STATE_TCLEAN);
|
||||
|
||||
$this->removeRecord($record);
|
||||
$this->_conn->commit();
|
||||
} catch (Exception $e) {
|
||||
$this->_conn->rollback();
|
||||
throw $e;
|
||||
}
|
||||
|
||||
}*/
|
||||
|
||||
/**
|
||||
* deletes all related composites
|
||||
* this method is always called internally when a record is deleted
|
||||
*
|
||||
* @throws PDOException if something went wrong at database level
|
||||
* @return void
|
||||
*/
|
||||
/*protected function _deleteComposites(Doctrine_Record $record)
|
||||
{
|
||||
foreach ($this->_classMetadata->getRelations() as $fk) {
|
||||
if ($fk->isComposite()) {
|
||||
$obj = $record->get($fk->getAlias());
|
||||
if ($obj instanceof Doctrine_Record &&
|
||||
$obj->state() != Doctrine_Record::STATE_LOCKED) {
|
||||
$obj->delete($this->_conn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
public function executeQuery(Doctrine_Query $query)
|
||||
{
|
||||
|
||||
@ -1073,16 +977,6 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
|
||||
$this->_mappingStrategy = null;
|
||||
}
|
||||
|
||||
/*public function addToWhere($componentAlias, array &$sqlWhereParts, Doctrine_Query $query)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function addToFrom($sqlString, Doctrine_Query $query)
|
||||
{
|
||||
|
||||
}*/
|
||||
|
||||
public function getFieldName($columnName)
|
||||
{
|
||||
return $this->_mappingStrategy->getFieldName($columnName);
|
||||
|
@ -81,7 +81,9 @@ class Doctrine_Mapper_DefaultStrategy extends Doctrine_Mapper_Strategy
|
||||
$fields[$seqName] = $id;
|
||||
$record->assignIdentifier($id);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//echo $class->getTableName() . "--" . $class->getClassName() . '---' . get_class($record) . "<br/>";
|
||||
$this->_insertRow($class->getTableName(), $fields);
|
||||
|
||||
if (empty($seq) && count($identifier) == 1 &&
|
||||
|
@ -656,7 +656,7 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
|
||||
}
|
||||
}
|
||||
|
||||
$this->_mapper->getRepository()->add($this);
|
||||
$this->_mapper->manage($this);
|
||||
$this->cleanData($this->_data);
|
||||
$this->_extractIdentifier($this->exists());
|
||||
|
||||
@ -928,6 +928,11 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
|
||||
{
|
||||
$this->_values[$name] = $value;
|
||||
}
|
||||
|
||||
public function getClassName()
|
||||
{
|
||||
return $this->_entityName;
|
||||
}
|
||||
|
||||
/**
|
||||
* set
|
||||
@ -1897,7 +1902,7 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
|
||||
*/
|
||||
public function free()
|
||||
{
|
||||
$this->_mapper->getRepository()->evict($this->_oid);
|
||||
$this->_mapper->detach($this);
|
||||
$this->_mapper->removeRecord($this);
|
||||
$this->_data = array();
|
||||
$this->_id = array();
|
||||
|
@ -76,9 +76,6 @@ abstract class Doctrine_Relation implements ArrayAccess
|
||||
'equal' => false,
|
||||
'refClass' => false, // the name of the association class (many-many)
|
||||
'refTable' => false, // the association table object (many-many)
|
||||
'refRelationName' => false,
|
||||
'refReverseRelationName' => false,
|
||||
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -1,41 +0,0 @@
|
||||
<?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>.
|
||||
*/
|
||||
Doctrine::autoload('Doctrine_Exception');
|
||||
/**
|
||||
* thrown when user tries to initialize a new instance of Doctrine_Table,
|
||||
* while there already exists an instance of that table
|
||||
*
|
||||
* @package Doctrine
|
||||
* @subpackage Table
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.phpdoctrine.org
|
||||
* @since 1.0
|
||||
* @version $Revision$
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
*/
|
||||
class Doctrine_Table_Exception extends Doctrine_Exception
|
||||
{
|
||||
public function __construct($message = "Couldn't initialize table. One instance of this
|
||||
table already exists. Always use Doctrine_Session::getTable(\$name)
|
||||
to get on instance of a Doctrine_Table.") {
|
||||
parent::__construct($message);
|
||||
}
|
||||
}
|
@ -1,360 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* A table factory is used to create table objects and load them with meta data.
|
||||
*
|
||||
* @todo Support different drivers for loading the meta data from different sources.
|
||||
* @package Doctrine
|
||||
* @deprecated
|
||||
*/
|
||||
class Doctrine_Table_Factory
|
||||
{
|
||||
protected $_conn;
|
||||
protected $_driver;
|
||||
|
||||
public function __construct(Doctrine_Connection $conn /*Doctrine_Table_Factory_Driver $driver*/)
|
||||
{
|
||||
$this->_conn = $conn;
|
||||
//$this->_driver = $driver;
|
||||
$name = "Doctrine_Table_Factory";
|
||||
//call_user_func_array(array($name, 'foobar'), array());
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the metadata of the class in question and all it's ancestors whose metadata
|
||||
* is still not loaded.
|
||||
*
|
||||
* @param string $name The name of the class for which the metadata should get loaded.
|
||||
* @param array $tables The metadata collection to which the loaded metadata is added.
|
||||
*/
|
||||
public function loadTables($name, array &$tables)
|
||||
{
|
||||
$parentClass = $name;
|
||||
$parentClasses = array();
|
||||
$parentClassWithTable = false;
|
||||
while ($parentClass = get_parent_class($parentClass)) {
|
||||
if ($parentClass == 'Doctrine_Record') {
|
||||
break;
|
||||
}
|
||||
if (isset($tables[$parentClass])) {
|
||||
$parentClassWithTable = $parentClass;
|
||||
break;
|
||||
}
|
||||
$class = new ReflectionClass($parentClass);
|
||||
if ($class->isAbstract()) {
|
||||
continue;
|
||||
}
|
||||
$parentClasses[] = $parentClass;
|
||||
}
|
||||
$parentClasses = array_reverse($parentClasses);
|
||||
$parentClasses[] = $name;
|
||||
|
||||
if ($parentClassWithTable) {
|
||||
$table = $tables[$parentClassWithTable];
|
||||
} else {
|
||||
$rootClassOfHierarchy = count($parentClasses) > 0 ? array_shift($parentClasses) : $name;
|
||||
$table = new Doctrine_Table($rootClassOfHierarchy, $this->_conn);
|
||||
$this->_loadMetaDataFromCode($table, $rootClassOfHierarchy);
|
||||
$tables[$rootClassOfHierarchy] = $table;
|
||||
}
|
||||
|
||||
if (count($parentClasses) == 0) {
|
||||
return $table;
|
||||
}
|
||||
//var_dump($parentClasses);
|
||||
//echo "<br /><br />";
|
||||
|
||||
// load meta data of subclasses
|
||||
if ($table->getInheritanceType() == Doctrine::INHERITANCETYPE_JOINED) {
|
||||
foreach ($parentClasses as $subclass) {
|
||||
$subTable = new Doctrine_Table($subclass, $this->_conn);
|
||||
$subTable->setInheritanceType(Doctrine::INHERITANCETYPE_JOINED);
|
||||
$this->_loadMetaDataFromCode($subTable, $subclass);
|
||||
$tables[$subclass] = $subTable;
|
||||
}
|
||||
} else if ($table->getInheritanceType() == Doctrine::INHERITANCETYPE_SINGLE_TABLE) {
|
||||
foreach ($parentClasses as $subclass) {
|
||||
$this->_mergeInto($table, $subclass);
|
||||
$tables[$subclass] = $table;
|
||||
}
|
||||
} else if ($table->getInheritanceType() == Doctrine::INHERITANCETYPE_TABLE_PER_CLASS) {
|
||||
$parents = array();
|
||||
foreach ($parentClasses as $subclass) {
|
||||
$class = new ReflectionClass($subclass);
|
||||
if ($class->isAbstract()) {
|
||||
$parents[] = $subclass;
|
||||
continue;
|
||||
}
|
||||
$subTable = new Doctrine_Table($subclass, $this->_conn);
|
||||
$subTable->setInheritanceType(Doctrine::INHERITANCETYPE_TABLE_PER_CLASS);
|
||||
$this->_loadMetaDataFromCode($subTable, $subclass);
|
||||
$this->_mergeColumnsInto($table, $subTable, true);
|
||||
foreach ($parents as $parent) {
|
||||
$this->_mergeColumnsInto($this->_conn->getTable($parent), $subTable, true);
|
||||
}
|
||||
// currently relying on parent::setTableDefinition();
|
||||
/*foreach ($abstracts as $abstractParent) {
|
||||
Doctrine_Table_Factory::mergeInto($subTable, $abstractParent);
|
||||
}*/
|
||||
$tables[$subclass] = $subTable;
|
||||
$parents[] = $subclass;
|
||||
}
|
||||
} else {
|
||||
throw new Doctrine_Table_Factory_Exception("Failed to load meta data. Unknown inheritance type "
|
||||
. "or no inheritance type specified for hierarchy.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the in-memory metadata for the domain class this mapper belongs to.
|
||||
* Uses reflection and code setup.
|
||||
*/
|
||||
protected function _loadMetaDataFromCode(Doctrine_Table $table, $name)
|
||||
{
|
||||
if ($name == 'Doctrine_Locator_Injectable') {
|
||||
try {
|
||||
throw new Exception();
|
||||
} catch (Exception $e) {
|
||||
echo $e->getTraceAsString() . "<br /><br />";
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! class_exists($name) || empty($name)) {
|
||||
//try {
|
||||
throw new Doctrine_Exception("Couldn't find class " . $name);
|
||||
//} catch (Exception $e) {
|
||||
// echo $e->getTraceAsString() . "<br /><br />";
|
||||
//}
|
||||
}
|
||||
$record = new $name($table);
|
||||
|
||||
$names = array();
|
||||
$class = $name;
|
||||
// get parent classes
|
||||
do {
|
||||
if ($class === 'Doctrine_Record') {
|
||||
break;
|
||||
}
|
||||
$name = $class;
|
||||
$names[] = $name;
|
||||
} while ($class = get_parent_class($class));
|
||||
|
||||
if ($class === false) {
|
||||
throw new Doctrine_Table_Exception('Unknown component.');
|
||||
}
|
||||
|
||||
// reverse names
|
||||
$names = array_reverse($names);
|
||||
// save parents
|
||||
array_pop($names);
|
||||
$table->setOption('parents', $names);
|
||||
|
||||
/*echo "<br />";
|
||||
var_dump($names);
|
||||
echo "<br /><br />";*/
|
||||
|
||||
// set up metadata mapping
|
||||
if (method_exists($record, 'setTableDefinition')) {
|
||||
$record->setTableDefinition();
|
||||
// get the declaring class of setTableDefinition method
|
||||
$method = new ReflectionMethod($name, 'setTableDefinition');
|
||||
$class = $method->getDeclaringClass();
|
||||
} else {
|
||||
$class = new ReflectionClass($class);
|
||||
}
|
||||
|
||||
if ($table->getInheritanceType() == Doctrine::INHERITANCETYPE_JOINED) {
|
||||
$joinedParents = array();
|
||||
foreach (array_reverse($names) as $parent) {
|
||||
$parentTable = $table->getConnection()->getTable($parent);
|
||||
$parentColumns = $parentTable->getColumns();
|
||||
$thisColumns = $table->getColumns();
|
||||
|
||||
foreach ($parentColumns as $columnName => $definition) {
|
||||
if ( ! isset($definition['primary'])) {
|
||||
if (isset($thisColumns[$columnName])) {
|
||||
continue;
|
||||
} else {
|
||||
/*if ( ! isset($parentColumns[$columnName]['owner'])) {
|
||||
$parentColumns[$columnName]['owner'] = $parentTable->getComponentName();
|
||||
}
|
||||
$joinedParents[] = $parentColumns[$columnName]['owner'];*/
|
||||
$joinedParents[] = $parentTable->getComponentName();
|
||||
}
|
||||
}/* else {
|
||||
//echo "adding primary key $columnName on ".$table->getComponentName().".<br />";
|
||||
unset($definition['autoincrement']);
|
||||
$fullName = $columnName . ' as ' . $parentTable->getFieldName($columnName);
|
||||
$table->setColumn($fullName, $definition['type'], $definition['length'], $definition, true);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
$table->setOption('joinedParents', array_values(array_unique($joinedParents)));
|
||||
}
|
||||
|
||||
$table->setOption('declaringClass', $class);
|
||||
|
||||
// set the table definition for the given tree implementation
|
||||
/*if ($table->isTree()) {
|
||||
$table->getTree()->setTableDefinition();
|
||||
}*/
|
||||
|
||||
$tableName = $table->getOption('tableName');
|
||||
if ( ! isset($tableName)) {
|
||||
$table->setOption('tableName', Doctrine::tableize($class->getName()));
|
||||
}
|
||||
|
||||
$this->_initIdentifier($table);
|
||||
|
||||
// set up domain class relations
|
||||
$record->setUp();
|
||||
|
||||
// if tree, set up tree relations
|
||||
/*if ($table->isTree()) {
|
||||
$table->getTree()->setUp();
|
||||
}*/
|
||||
|
||||
return $table;
|
||||
}
|
||||
|
||||
protected function _mergeInto(Doctrine_Table $table, $domainClassName)
|
||||
{
|
||||
if ( ! class_exists($domainClassName) || empty($domainClassName)) {
|
||||
throw new Doctrine_Exception("Couldn't find class " . $domainClassName);
|
||||
}
|
||||
|
||||
$record = new $domainClassName($table);
|
||||
$record->setTableDefinition();
|
||||
$record->setUp();
|
||||
|
||||
}
|
||||
|
||||
protected function _mergeColumnsInto(Doctrine_Table $sourceTable, Doctrine_Table $targetTable, $skipPk = false)
|
||||
{
|
||||
|
||||
$sourceColumns = $sourceTable->getColumns();
|
||||
foreach ($sourceColumns as $columnName => $definition) {
|
||||
if ($skipPk && isset($definition['primary'])) {
|
||||
continue;
|
||||
}
|
||||
$fullName = $columnName . ' as ' . $sourceTable->getFieldName($columnName);
|
||||
$targetTable->setColumn($fullName, $definition['type'], $definition['length'], $definition);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected function _mergeRelationsInto(Doctrine_Table $table, $domainClassName)
|
||||
{
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the table identifier(s)/primary key(s)
|
||||
*
|
||||
*/
|
||||
protected function _initIdentifier(Doctrine_Table $table)
|
||||
{
|
||||
switch (count($table->getIdentifier())) {
|
||||
case 0:
|
||||
if ($table->getInheritanceType() == Doctrine::INHERITANCETYPE_JOINED &&
|
||||
count($table->getOption('joinedParents')) > 0) {
|
||||
|
||||
$root = current($table->getOption('joinedParents'));
|
||||
|
||||
$rootTable = $table->getConnection()->getTable($root);
|
||||
|
||||
$table->setIdentifier($rootTable->getIdentifier());
|
||||
|
||||
if ($table->getIdentifierType() !== Doctrine::IDENTIFIER_AUTOINC) {
|
||||
$table->setIdentifierType($rootTable->getIdentifierType());
|
||||
} else {
|
||||
$table->setIdentifierType(Doctrine::IDENTIFIER_NATURAL);
|
||||
}
|
||||
|
||||
// add all inherited primary keys
|
||||
foreach ((array) $table->getIdentifier() as $id) {
|
||||
$definition = $rootTable->getDefinitionOf($id);
|
||||
|
||||
// inherited primary keys shouldn't contain autoinc
|
||||
// and sequence definitions
|
||||
unset($definition['autoincrement']);
|
||||
unset($definition['sequence']);
|
||||
|
||||
// add the inherited primary key column
|
||||
$fullName = $rootTable->getColumnName($id) . ' as ' . $id;
|
||||
$table->setColumn($fullName, $definition['type'], $definition['length'],
|
||||
$definition, true);
|
||||
}
|
||||
} else {
|
||||
$definition = array('type' => 'integer',
|
||||
'length' => 20,
|
||||
'autoincrement' => true,
|
||||
'primary' => true);
|
||||
$table->setColumn('id', $definition['type'], $definition['length'], $definition, true);
|
||||
$table->setIdentifier('id');
|
||||
$table->setIdentifierType(Doctrine::IDENTIFIER_AUTOINC);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
foreach ($table->getIdentifier() as $pk) {
|
||||
$columnName = $table->getColumnName($pk);
|
||||
$thisColumns = $table->getColumns();
|
||||
$e = $thisColumns[$columnName];
|
||||
|
||||
$found = false;
|
||||
|
||||
foreach ($e as $option => $value) {
|
||||
if ($found) {
|
||||
break;
|
||||
}
|
||||
|
||||
$e2 = explode(':', $option);
|
||||
|
||||
switch (strtolower($e2[0])) {
|
||||
case 'autoincrement':
|
||||
case 'autoinc':
|
||||
$table->setIdentifierType(Doctrine::IDENTIFIER_AUTOINC);
|
||||
$found = true;
|
||||
break;
|
||||
case 'seq':
|
||||
case 'sequence':
|
||||
$table->setIdentifierType(Doctrine::IDENTIFIER_SEQUENCE);
|
||||
$found = true;
|
||||
|
||||
if ($value) {
|
||||
$table->setOption('sequenceName', $value);
|
||||
} else {
|
||||
if (($sequence = $table->getAttribute(Doctrine::ATTR_DEFAULT_SEQUENCE)) !== null) {
|
||||
$table->setOption('sequenceName', $sequence);
|
||||
} else {
|
||||
$table->setOption('sequenceName', $table->getConnection()
|
||||
->getSequenceName($this->getOption('tableName')));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
$identifierType = $table->getIdentifierType();
|
||||
if ( ! isset($identifierType)) {
|
||||
$table->setIdentifierType(Doctrine::IDENTIFIER_NATURAL);
|
||||
}
|
||||
}
|
||||
|
||||
$table->setIdentifier($pk);
|
||||
|
||||
break;
|
||||
default:
|
||||
$table->setIdentifierType(Doctrine::IDENTIFIER_COMPOSITE);
|
||||
}
|
||||
}
|
||||
|
||||
public static function foobar()
|
||||
{
|
||||
echo "bar!";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,3 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Doctrine_Table_Factory_Exception extends Doctrine_Table_Exception {}
|
@ -1,163 +0,0 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Doctrine_Repository
|
||||
* each record is added into Doctrine_Repository at the same time they are created,
|
||||
* loaded from the database or retrieved from the cache
|
||||
*
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @package Doctrine
|
||||
* @subpackage Table
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.phpdoctrine.org
|
||||
* @since 1.0
|
||||
* @version $Revision$
|
||||
*/
|
||||
class Doctrine_Table_Repository implements Countable, IteratorAggregate
|
||||
{
|
||||
/**
|
||||
* @var object Doctrine_Table $table
|
||||
*/
|
||||
private $table;
|
||||
|
||||
/**
|
||||
* @var array $registry
|
||||
* an array of all records
|
||||
* keys representing record object identifiers
|
||||
*/
|
||||
private $registry = array();
|
||||
|
||||
/**
|
||||
* constructor
|
||||
*
|
||||
* @param Doctrine_Table $table
|
||||
*/
|
||||
public function __construct($mapper)
|
||||
{
|
||||
$this->table = $mapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* getTable
|
||||
*
|
||||
* @return object Doctrine_Table
|
||||
*/
|
||||
public function getTable()
|
||||
{
|
||||
return $this->table;
|
||||
}
|
||||
|
||||
/**
|
||||
* add
|
||||
*
|
||||
* @param Doctrine_Record $record record to be added into registry
|
||||
* @return boolean
|
||||
*/
|
||||
public function add(Doctrine_Record $record)
|
||||
{
|
||||
$oid = $record->getOID();
|
||||
|
||||
if (isset($this->registry[$oid])) {
|
||||
return false;
|
||||
}
|
||||
$this->registry[$oid] = $record;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* get
|
||||
* @param integer $oid
|
||||
* @throws Doctrine_Table_Repository_Exception
|
||||
*/
|
||||
public function get($oid)
|
||||
{
|
||||
if ( ! isset($this->registry[$oid])) {
|
||||
throw new Doctrine_Table_Repository_Exception("Unknown object identifier");
|
||||
}
|
||||
return $this->registry[$oid];
|
||||
}
|
||||
|
||||
/**
|
||||
* count
|
||||
* Doctrine_Registry implements interface Countable
|
||||
* @return integer the number of records this registry has
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return count($this->registry);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer $oid object identifier
|
||||
* @return boolean whether ot not the operation was successful
|
||||
*/
|
||||
public function evict($oid)
|
||||
{
|
||||
if ( ! isset($this->registry[$oid])) {
|
||||
return false;
|
||||
}
|
||||
unset($this->registry[$oid]);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return integer number of records evicted
|
||||
*/
|
||||
public function evictAll()
|
||||
{
|
||||
$evicted = 0;
|
||||
foreach ($this->registry as $oid => $record) {
|
||||
if ($this->evict($oid)) {
|
||||
$evicted++;
|
||||
}
|
||||
}
|
||||
return $evicted;
|
||||
}
|
||||
|
||||
/**
|
||||
* getIterator
|
||||
* @return ArrayIterator
|
||||
*/
|
||||
public function getIterator()
|
||||
{
|
||||
return new ArrayIterator($this->registry);
|
||||
}
|
||||
|
||||
/**
|
||||
* contains
|
||||
* @param integer $oid object identifier
|
||||
*/
|
||||
public function contains($oid)
|
||||
{
|
||||
return isset($this->registry[$oid]);
|
||||
}
|
||||
|
||||
/**
|
||||
* loadAll
|
||||
* @return void
|
||||
*/
|
||||
public function loadAll()
|
||||
{
|
||||
$this->table->findAll();
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
<?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>.
|
||||
*/
|
||||
Doctrine::autoload('Doctrine_Exception');
|
||||
/**
|
||||
* Doctrine_Table_Repository_Exception
|
||||
*
|
||||
* @package Doctrine
|
||||
* @subpackage Table
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.phpdoctrine.org
|
||||
* @since 1.0
|
||||
* @version $Revision$
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
*/
|
||||
class Doctrine_Table_Repository_Exception extends Doctrine_Exception
|
||||
{ }
|
Loading…
x
Reference in New Issue
Block a user