1
0
mirror of synced 2024-12-14 15:16:04 +03:00
This commit is contained in:
zYne 2007-05-11 00:19:46 +00:00
parent e3b3439415
commit 16a2370e27
2 changed files with 79 additions and 177 deletions

View File

@ -31,7 +31,7 @@ Doctrine::autoload("Doctrine_Access");
* @version $Revision: 1207 $ * @version $Revision: 1207 $
* @author Konsta Vesterinen <kvesteri@cc.hut.fi> * @author Konsta Vesterinen <kvesteri@cc.hut.fi>
*/ */
class Doctrine_Collection2 extends Doctrine_Access implements Countable, IteratorAggregate, Serializable class Doctrine_Collection2 extends Doctrine_Collection implements Countable, IteratorAggregate, Serializable
{ {
/** /**
* @var array $data an array containing the data access objects of this collection * @var array $data an array containing the data access objects of this collection
@ -40,7 +40,7 @@ class Doctrine_Collection2 extends Doctrine_Access implements Countable, Iterato
/** /**
* @var Doctrine_Table $table each collection has only records of specified table * @var Doctrine_Table $table each collection has only records of specified table
*/ */
protected $table; protected $_table;
/** /**
* @var Doctrine_Record $reference collection can belong to a record * @var Doctrine_Record $reference collection can belong to a record
*/ */
@ -75,7 +75,7 @@ class Doctrine_Collection2 extends Doctrine_Access implements Countable, Iterato
$table = Doctrine_Manager::getInstance() $table = Doctrine_Manager::getInstance()
->getTable($table); ->getTable($table);
} }
$this->table = $table; $this->_table = $table;
$name = $table->getAttribute(Doctrine::ATTR_COLL_KEY); $name = $table->getAttribute(Doctrine::ATTR_COLL_KEY);
if ($name !== null) { if ($name !== null) {
@ -100,7 +100,7 @@ class Doctrine_Collection2 extends Doctrine_Access implements Countable, Iterato
*/ */
public function getTable() public function getTable()
{ {
return $this->table; return $this->_table;
} }
/** /**
* this method is automatically called when this Doctrine_Collection is serialized * this method is automatically called when this Doctrine_Collection is serialized
@ -139,12 +139,12 @@ class Doctrine_Collection2 extends Doctrine_Access implements Countable, Iterato
$this->$name = $values; $this->$name = $values;
} }
$this->table = $connection->getTable($this->table); $this->_table = $connection->getTable($this->_table);
$this->expanded = array(); $this->expanded = array();
$this->expandable = true; $this->expandable = true;
$name = $this->table->getAttribute(Doctrine::ATTR_COLL_KEY); $name = $this->_table->getAttribute(Doctrine::ATTR_COLL_KEY);
if ($name !== null) { if ($name !== null) {
$this->keyColumn = $name; $this->keyColumn = $name;
} }
@ -294,8 +294,8 @@ class Doctrine_Collection2 extends Doctrine_Access implements Countable, Iterato
*/ */
public function get($key) public function get($key)
{ {
if ($key === null) { if ($key === null || ! isset($this->data[$key])) {
$record = $this->table->create(); $record = $this->_table->create();
if (isset($this->referenceField)) { if (isset($this->referenceField)) {
$record->set($this->referenceField, $this->reference, false); $record->set($this->referenceField, $this->reference, false);
@ -306,22 +306,6 @@ class Doctrine_Collection2 extends Doctrine_Access implements Countable, Iterato
return $record; return $record;
} }
if ( ! isset($this->data[$key])) {
if ( ! isset($this->data[$key])) {
$this->data[$key] = $this->table->create();
}
if (isset($this->referenceField)) {
$value = $this->reference->get($this->relation->getLocal());
if ($value !== null) {
$this->data[$key]->set($this->referenceField, $value, false);
} else {
$this->data[$key]->set($this->referenceField, $this->reference, false);
}
}
}
return $this->data[$key]; return $this->data[$key];
} }
@ -331,7 +315,7 @@ class Doctrine_Collection2 extends Doctrine_Access implements Countable, Iterato
public function getPrimaryKeys() public function getPrimaryKeys()
{ {
$list = array(); $list = array();
$name = $this->table->getIdentifier(); $name = $this->_table->getIdentifier();
foreach ($this->data as $record) { foreach ($this->data as $record) {
if (is_array($record) && isset($record[$name])) { if (is_array($record) && isset($record[$name])) {
@ -380,7 +364,7 @@ class Doctrine_Collection2 extends Doctrine_Access implements Countable, Iterato
* @param string $key optional key for the record * @param string $key optional key for the record
* @return boolean * @return boolean
*/ */
public function add(Doctrine_Record $record,$key = null) public function add(Doctrine_Record $record, $key = null)
{ {
if (isset($this->referenceField)) { if (isset($this->referenceField)) {
$record->set($this->referenceField, $this->reference, false); $record->set($this->referenceField, $this->reference, false);
@ -424,7 +408,7 @@ class Doctrine_Collection2 extends Doctrine_Access implements Countable, Iterato
public function loadRelated($name = null) public function loadRelated($name = null)
{ {
$list = array(); $list = array();
$query = new Doctrine_Query($this->table->getConnection()); $query = new Doctrine_Query($this->_table->getConnection());
if ( ! isset($name)) { if ( ! isset($name)) {
foreach ($this->data as $record) { foreach ($this->data as $record) {
@ -433,13 +417,13 @@ class Doctrine_Collection2 extends Doctrine_Access implements Countable, Iterato
$list[] = $value; $list[] = $value;
} }
}; };
$query->from($this->table->getComponentName() . '(' . implode(", ",$this->table->getPrimaryKeys()) . ')'); $query->from($this->_table->getComponentName() . '(' . implode(", ",$this->_table->getPrimaryKeys()) . ')');
$query->where($this->table->getComponentName() . '.id IN (' . substr(str_repeat("?, ", count($list)),0,-2) . ')'); $query->where($this->_table->getComponentName() . '.id IN (' . substr(str_repeat("?, ", count($list)),0,-2) . ')');
return $query; return $query;
} }
$rel = $this->table->getRelation($name); $rel = $this->_table->getRelation($name);
if ($rel instanceof Doctrine_Relation_LocalKey || $rel instanceof Doctrine_Relation_ForeignKey) { if ($rel instanceof Doctrine_Relation_LocalKey || $rel instanceof Doctrine_Relation_ForeignKey) {
foreach ($this->data as $record) { foreach ($this->data as $record) {
@ -469,7 +453,7 @@ class Doctrine_Collection2 extends Doctrine_Access implements Countable, Iterato
*/ */
public function populateRelated($name, Doctrine_Collection $coll) public function populateRelated($name, Doctrine_Collection $coll)
{ {
$rel = $this->table->getRelation($name); $rel = $this->_table->getRelation($name);
$table = $rel->getTable(); $table = $rel->getTable();
$foreign = $rel->getForeign(); $foreign = $rel->getForeign();
$local = $rel->getLocal(); $local = $rel->getLocal();
@ -501,7 +485,7 @@ class Doctrine_Collection2 extends Doctrine_Access implements Countable, Iterato
$this->data[$key]->setRelated($name, $sub); $this->data[$key]->setRelated($name, $sub);
} }
} elseif ($rel instanceof Doctrine_Relation_Association) { } elseif ($rel instanceof Doctrine_Relation_Association) {
$identifier = $this->table->getIdentifier(); $identifier = $this->_table->getIdentifier();
$asf = $rel->getAssociationFactory(); $asf = $rel->getAssociationFactory();
$name = $table->getComponentName(); $name = $table->getComponentName();
@ -541,7 +525,7 @@ class Doctrine_Collection2 extends Doctrine_Access implements Countable, Iterato
public function save(Doctrine_Connection $conn = null) public function save(Doctrine_Connection $conn = null)
{ {
if ($conn == null) { if ($conn == null) {
$conn = $this->table->getConnection(); $conn = $this->_table->getConnection();
} }
$conn->beginTransaction(); $conn->beginTransaction();
@ -561,7 +545,7 @@ class Doctrine_Collection2 extends Doctrine_Access implements Countable, Iterato
public function delete(Doctrine_Connection $conn = null) public function delete(Doctrine_Connection $conn = null)
{ {
if ($conn == null) { if ($conn == null) {
$conn = $this->table->getConnection(); $conn = $this->_table->getConnection();
} }
$conn->beginTransaction(); $conn->beginTransaction();

View File

@ -18,7 +18,7 @@
* and is licensed under the LGPL. For more information, see * and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.com>. * <http://www.phpdoctrine.com>.
*/ */
Doctrine::autoload('Doctrine_Access');
/** /**
* Doctrine_Hydrate is a base class for Doctrine_RawSql and Doctrine_Query. * Doctrine_Hydrate is a base class for Doctrine_RawSql and Doctrine_Query.
* Its purpose is to populate object graphs. * Its purpose is to populate object graphs.
@ -32,7 +32,7 @@ Doctrine::autoload('Doctrine_Access');
* @version $Revision: 1255 $ * @version $Revision: 1255 $
* @author Konsta Vesterinen <kvesteri@cc.hut.fi> * @author Konsta Vesterinen <kvesteri@cc.hut.fi>
*/ */
class Doctrine_Hydrate2 extends Doctrine_Access class Doctrine_Hydrate2
{ {
/** /**
* QUERY TYPE CONSTANTS * QUERY TYPE CONSTANTS
@ -77,7 +77,9 @@ class Doctrine_Hydrate2 extends Doctrine_Access
* *
* table table object associated with given alias * table table object associated with given alias
* *
* relation the relation object owned by the parent
* *
* parent the alias of the parent
*/ */
protected $_aliasMap = array(); protected $_aliasMap = array();
@ -320,6 +322,7 @@ class Doctrine_Hydrate2 extends Doctrine_Access
* *
* @param Doctrine_Record $record * @param Doctrine_Record $record
* @param array $row * @param array $row
* @return Doctrine_Record
*/ */
public function mapAggregateValues($record, array $row) public function mapAggregateValues($record, array $row)
{ {
@ -338,6 +341,15 @@ class Doctrine_Hydrate2 extends Doctrine_Access
} }
} }
return $record; return $record;
}
/**
* mapRelated
*
* @return
*/
public function mapRelated()
{
} }
/** /**
* execute * execute
@ -353,10 +365,11 @@ class Doctrine_Hydrate2 extends Doctrine_Access
if (empty($this->_aliasMap)) { if (empty($this->_aliasMap)) {
throw new Doctrine_Hydrate_Exception("Couldn't execute query. Component alias map was empty."); throw new Doctrine_Hydrate_Exception("Couldn't execute query. Component alias map was empty.");
} }
// initialize some variables used within the main loop
$rootMap = current($this->_aliasMap); $rootMap = current($this->_aliasMap);
$coll = new Doctrine_Collection($rootMap['table']); $rootAlias = key($this->_aliasMap);
$prev[key($this->_aliasMap)] = $coll; $coll = new Doctrine_Collection2($rootMap['table']);
$prev[$rootAlias] = $coll;
$prevRow = array(); $prevRow = array();
/** /**
@ -368,47 +381,78 @@ class Doctrine_Hydrate2 extends Doctrine_Access
* remove duplicated data rows and map data into objects * remove duplicated data rows and map data into objects
*/ */
foreach ($data as $tableAlias => $row) { foreach ($data as $tableAlias => $row) {
// skip empty rows (not mappable)
if (empty($row)) { if (empty($row)) {
continue; continue;
} }
// check for validity
if ( ! isset($this->tableAliases[$tableAlias])) { if ( ! isset($this->tableAliases[$tableAlias])) {
throw new Doctrine_Hydrate_Exception('Unknown table alias ' . $tableAlias); throw new Doctrine_Hydrate_Exception('Unknown table alias ' . $tableAlias);
} }
$alias = $this->tableAliases[$tableAlias]; $alias = $this->tableAliases[$tableAlias];
$map = $this->_aliasMap[$alias]; $map = $this->_aliasMap[$alias];
// initialize previous row array if not set
if ( ! isset($prevRow[$tableAlias])) {
$prevRow[$tableAlias] = array();
}
// don't map duplicate rows
if ($prevRow[$tableAlias] !== $row) { if ($prevRow[$tableAlias] !== $row) {
// set internal data // set internal data
$this->tables[$name]->setData($row); $map['table']->setData($row);
// initialize a new record // initialize a new record
$record = $this->tables[$name]->getRecord(); $record = $map['table']->getRecord();
// map aggregate values (if any)
$this->mapAggregateValues($record, $row); $this->mapAggregateValues($record, $row);
if ($name == $root) { if ($alias == $rootAlias) {
// add record into root collection // add record into root collection
$coll->add($record); $coll->add($record);
unset($previd); unset($prevRow);
} else { } else {
$prev = $this->addRelated($prev, $name, $record);
$relation = $map['relation'];
$parentAlias = $map['parent'];
$parentMap = $this->_aliasMap[$parentAlias];
$parent = $prev[$parentAlias]->getLast();
// check the type of the relation
if ($relation->isOneToOne()) {
$prev[$alias] = $record;
} else {
// one-to-many relation or many-to-many relation
if ( ! $prev[$parentAlias]->getLast()->hasReference($relation->getAlias())) {
// initialize a new collection
$prev[$alias] = new Doctrine_Collection2($parentMap['table']);
$prev[$alias]->setReference($parent, $relation);
} else {
// previous entry found from memory
$prev[$alias] = $prev[$parentAlias]->getLast()->get($relation->getAlias());
}
// add record to the current collection
$prev[$alias]->add($record);
}
// initialize the relation from parent to the current collection/record
$parent->set($relation->getAlias(), $prev[$alias]);
} }
// following statement is needed to ensure that mappings // following statement is needed to ensure that mappings
// are being done properly when the result set doesn't // are being done properly when the result set doesn't
// contain the rows in 'right order' // contain the rows in 'right order'
if ($prev[$name] !== $record) { if ($prev[$alias] !== $record) {
$prev[$name] = $record; $prev[$alias] = $record;
} }
} }
$prevRow[$tableAlias] = $row; $prevRow[$tableAlias] = $row;
} }
} }
return $coll;
} }
/** /**
* execute * execute
@ -418,12 +462,6 @@ class Doctrine_Hydrate2 extends Doctrine_Access
* @return Doctrine_Collection the root collection * @return Doctrine_Collection the root collection
*/ */
public function execute2($params = array(), $return = Doctrine::FETCH_RECORD) { public function execute2($params = array(), $return = Doctrine::FETCH_RECORD) {
$array = $this->_fetch($params = array(), $return = Doctrine::FETCH_RECORD);
$keys = array_keys($this->tables);
$root = $keys[0];
$previd = array();
/** /**
* iterate over the fetched data * iterate over the fetched data
* here $data is a two dimensional array * here $data is a two dimensional array
@ -488,131 +526,11 @@ class Doctrine_Hydrate2 extends Doctrine_Access
continue; continue;
} }
if ( ! isset($previd[$name])) {
$previd[$name] = array();
}
if ($previd[$name] !== $row) {
// set internal data
$this->tables[$name]->setData($row);
// initialize a new record
$record = $this->tables[$name]->getRecord();
// aggregate values have numeric keys
if (isset($row[0])) {
$path = array_search($name, $this->tableAliases);
$alias = $this->getPathAlias($path);
// map each aggregate value
foreach ($row as $index => $value) {
$agg = false;
if (isset($this->pendingAggregates[$alias][$index])) {
$agg = $this->pendingAggregates[$alias][$index][3];
} elseif (isset($this->subqueryAggregates[$alias][$index])) {
$agg = $this->subqueryAggregates[$alias][$index];
}
$record->mapValue($agg, $value);
}
}
if ($name == $root) {
// add record into root collection
$coll->add($record);
unset($previd);
} else {
$prev = $this->addRelated($prev, $name, $record);
}
// following statement is needed to ensure that mappings
// are being done properly when the result set doesn't
// contain the rows in 'right order'
if ($prev[$name] !== $record) {
$prev[$name] = $record;
}
}
$previd[$name] = $row;
} }
} }
return $coll; return $coll;
} }
/**
* initRelation
*
* @param array $prev
* @param string $name
* @return array
*/
public function initRelated(array $prev, $name)
{
$pointer = $this->joins[$name];
$path = array_search($name, $this->tableAliases);
$tmp = explode('.', $path);
$alias = end($tmp);
if ( ! isset($prev[$pointer]) ) {
return $prev;
}
$fk = $this->tables[$pointer]->getRelation($alias);
if ( ! $fk->isOneToOne()) {
if ($prev[$pointer]->getLast() instanceof Doctrine_Record) {
if ( ! $prev[$pointer]->getLast()->hasReference($alias)) {
$prev[$name] = $this->getCollection($name);
$prev[$pointer]->getLast()->initReference($prev[$name],$fk);
} else {
$prev[$name] = $prev[$pointer]->getLast()->get($alias);
}
}
}
return $prev;
}
/**
* addRelated
*
* @param array $prev
* @param string $name
* @return array
*/
public function addRelated(array $prev, $name, Doctrine_Record $record)
{
$pointer = $this->joins[$name];
$path = array_search($name, $this->tableAliases);
$tmp = explode('.', $path);
$alias = end($tmp);
$fk = $this->tables[$pointer]->getRelation($alias);
if ($fk->isOneToOne()) {
$prev[$pointer]->getLast()->set($fk->getAlias(), $record);
$prev[$name] = $record;
} else {
// one-to-many relation or many-to-many relation
if ( ! $prev[$pointer]->getLast()->hasReference($alias)) {
$prev[$name] = $this->getCollection($name);
$prev[$pointer]->getLast()->initReference($prev[$name], $fk);
} else {
// previous entry found from memory
$prev[$name] = $prev[$pointer]->getLast()->get($alias);
}
$prev[$pointer]->getLast()->addReference($record, $fk);
}
return $prev;
}
/** /**
* isIdentifiable * isIdentifiable
* returns whether or not a given data row is identifiable (it contains * returns whether or not a given data row is identifiable (it contains