2007-10-23 01:47:05 +04:00
|
|
|
<?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.com>.
|
|
|
|
*/
|
|
|
|
Doctrine::autoload('Doctrine_Connection_Module');
|
|
|
|
/**
|
|
|
|
* Doctrine_Connection_UnitOfWork
|
|
|
|
*
|
|
|
|
* @package Doctrine
|
|
|
|
* @subpackage Connection
|
|
|
|
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
|
|
|
* @link www.phpdoctrine.com
|
|
|
|
* @since 1.0
|
|
|
|
* @version $Revision$
|
|
|
|
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
|
|
|
*/
|
|
|
|
class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
|
|
|
|
{
|
2008-01-05 22:55:56 +03:00
|
|
|
protected $_autoflush = true;
|
|
|
|
protected $_inserts = array();
|
|
|
|
protected $_updates = array();
|
|
|
|
protected $_deletes = array();
|
|
|
|
|
|
|
|
public function flush()
|
|
|
|
{
|
|
|
|
return $this->saveAll();
|
|
|
|
}
|
|
|
|
|
|
|
|
public function addInsert()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public function addUpdate()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public function addDelete()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-23 01:47:05 +04:00
|
|
|
/**
|
|
|
|
* buildFlushTree
|
|
|
|
* builds a flush tree that is used in transactions
|
|
|
|
*
|
|
|
|
* The returned array has all the initialized components in
|
|
|
|
* 'correct' order. Basically this means that the records of those
|
|
|
|
* components can be saved safely in the order specified by the returned array.
|
|
|
|
*
|
|
|
|
* @param array $tables an array of Doctrine_Table objects or component names
|
|
|
|
* @return array an array of component names in flushing order
|
|
|
|
*/
|
|
|
|
public function buildFlushTree(array $tables)
|
|
|
|
{
|
|
|
|
$tree = array();
|
|
|
|
foreach ($tables as $k => $table) {
|
2008-01-12 22:49:11 +03:00
|
|
|
if ( ! ($table instanceof Doctrine_Mapper_Abstract)) {
|
2008-01-05 22:55:56 +03:00
|
|
|
$table = $this->conn->getMapper($table);
|
2007-10-23 01:47:05 +04:00
|
|
|
}
|
|
|
|
$nm = $table->getComponentName();
|
|
|
|
|
|
|
|
$index = array_search($nm, $tree);
|
|
|
|
|
|
|
|
if ($index === false) {
|
|
|
|
$tree[] = $nm;
|
|
|
|
$index = max(array_keys($tree));
|
|
|
|
}
|
|
|
|
|
2008-01-05 22:55:56 +03:00
|
|
|
$rels = $table->getTable()->getRelations();
|
2007-10-23 01:47:05 +04:00
|
|
|
|
|
|
|
// group relations
|
|
|
|
|
|
|
|
foreach ($rels as $key => $rel) {
|
|
|
|
if ($rel instanceof Doctrine_Relation_ForeignKey) {
|
|
|
|
unset($rels[$key]);
|
|
|
|
array_unshift($rels, $rel);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach ($rels as $rel) {
|
|
|
|
$name = $rel->getTable()->getComponentName();
|
|
|
|
$index2 = array_search($name,$tree);
|
|
|
|
$type = $rel->getType();
|
|
|
|
|
|
|
|
// skip self-referenced relations
|
|
|
|
if ($name === $nm) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($rel instanceof Doctrine_Relation_ForeignKey) {
|
|
|
|
if ($index2 !== false) {
|
|
|
|
if ($index2 >= $index)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
unset($tree[$index]);
|
|
|
|
array_splice($tree,$index2,0,$nm);
|
|
|
|
$index = $index2;
|
|
|
|
} else {
|
|
|
|
$tree[] = $name;
|
|
|
|
}
|
|
|
|
|
2008-01-05 22:55:56 +03:00
|
|
|
} else if ($rel instanceof Doctrine_Relation_LocalKey) {
|
2007-10-23 01:47:05 +04:00
|
|
|
if ($index2 !== false) {
|
|
|
|
if ($index2 <= $index)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
unset($tree[$index2]);
|
|
|
|
array_splice($tree,$index,0,$name);
|
|
|
|
} else {
|
|
|
|
array_unshift($tree,$name);
|
|
|
|
$index++;
|
|
|
|
}
|
2008-01-05 22:55:56 +03:00
|
|
|
} else if ($rel instanceof Doctrine_Relation_Association) {
|
2007-10-23 01:47:05 +04:00
|
|
|
$t = $rel->getAssociationFactory();
|
|
|
|
$n = $t->getComponentName();
|
|
|
|
|
|
|
|
if ($index2 !== false)
|
|
|
|
unset($tree[$index2]);
|
|
|
|
|
|
|
|
array_splice($tree, $index, 0, $name);
|
|
|
|
$index++;
|
|
|
|
|
|
|
|
$index3 = array_search($n, $tree);
|
|
|
|
|
|
|
|
if ($index3 !== false) {
|
|
|
|
if ($index3 >= $index)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
unset($tree[$index]);
|
|
|
|
array_splice($tree, $index3, 0, $n);
|
|
|
|
$index = $index2;
|
|
|
|
} else {
|
|
|
|
$tree[] = $n;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return array_values($tree);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* saves the given record
|
|
|
|
*
|
|
|
|
* @param Doctrine_Record $record
|
|
|
|
* @return void
|
|
|
|
*/
|
2008-01-05 22:55:56 +03:00
|
|
|
/*public function saveGraph(Doctrine_Record $record)
|
2007-10-23 01:47:05 +04:00
|
|
|
{
|
|
|
|
$conn = $this->getConnection();
|
|
|
|
|
|
|
|
$state = $record->state();
|
|
|
|
if ($state === Doctrine_Record::STATE_LOCKED) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
$record->state(Doctrine_Record::STATE_LOCKED);
|
2007-11-18 19:06:37 +03:00
|
|
|
|
2007-12-12 18:52:12 +03:00
|
|
|
$conn->beginInternalTransaction();
|
2007-10-23 01:47:05 +04:00
|
|
|
$saveLater = $this->saveRelated($record);
|
|
|
|
|
|
|
|
$record->state($state);
|
|
|
|
|
|
|
|
if ($record->isValid()) {
|
|
|
|
$event = new Doctrine_Event($record, Doctrine_Event::RECORD_SAVE);
|
|
|
|
|
|
|
|
$record->preSave($event);
|
2007-11-18 19:06:37 +03:00
|
|
|
|
2007-10-23 01:47:05 +04:00
|
|
|
$record->getTable()->getRecordListener()->preSave($event);
|
2007-10-24 00:21:22 +04:00
|
|
|
$state = $record->state();
|
2007-10-23 01:47:05 +04:00
|
|
|
|
|
|
|
if ( ! $event->skipOperation) {
|
|
|
|
switch ($state) {
|
|
|
|
case Doctrine_Record::STATE_TDIRTY:
|
|
|
|
$this->insert($record);
|
|
|
|
break;
|
|
|
|
case Doctrine_Record::STATE_DIRTY:
|
|
|
|
case Doctrine_Record::STATE_PROXY:
|
|
|
|
$this->update($record);
|
|
|
|
break;
|
|
|
|
case Doctrine_Record::STATE_CLEAN:
|
|
|
|
case Doctrine_Record::STATE_TCLEAN:
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$record->getTable()->getRecordListener()->postSave($event);
|
2007-11-18 19:06:37 +03:00
|
|
|
|
2007-10-23 01:47:05 +04:00
|
|
|
$record->postSave($event);
|
|
|
|
} else {
|
|
|
|
$conn->transaction->addInvalid($record);
|
|
|
|
}
|
|
|
|
|
|
|
|
$state = $record->state();
|
|
|
|
|
|
|
|
$record->state(Doctrine_Record::STATE_LOCKED);
|
|
|
|
|
|
|
|
foreach ($saveLater as $fk) {
|
|
|
|
$alias = $fk->getAlias();
|
|
|
|
|
|
|
|
if ($record->hasReference($alias)) {
|
|
|
|
$obj = $record->$alias;
|
2007-11-18 19:06:37 +03:00
|
|
|
|
2007-10-23 01:47:05 +04:00
|
|
|
// check that the related object is not an instance of Doctrine_Null
|
|
|
|
if ( ! ($obj instanceof Doctrine_Null)) {
|
|
|
|
$obj->save($conn);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// save the MANY-TO-MANY associations
|
|
|
|
$this->saveAssociations($record);
|
|
|
|
|
|
|
|
$record->state($state);
|
2007-11-18 19:06:37 +03:00
|
|
|
|
2007-10-23 01:47:05 +04:00
|
|
|
$conn->commit();
|
|
|
|
|
|
|
|
return true;
|
2008-01-05 22:55:56 +03:00
|
|
|
}*/
|
|
|
|
|
2007-10-23 01:47:05 +04:00
|
|
|
/**
|
|
|
|
* saves the given record
|
|
|
|
*
|
|
|
|
* @param Doctrine_Record $record
|
|
|
|
* @return void
|
|
|
|
*/
|
2008-01-05 22:55:56 +03:00
|
|
|
/*public function save(Doctrine_Record $record)
|
2007-10-23 01:47:05 +04:00
|
|
|
{
|
|
|
|
$event = new Doctrine_Event($record, Doctrine_Event::RECORD_SAVE);
|
|
|
|
|
|
|
|
$record->preSave($event);
|
|
|
|
|
|
|
|
$record->getTable()->getRecordListener()->preSave($event);
|
|
|
|
|
|
|
|
if ( ! $event->skipOperation) {
|
|
|
|
switch ($record->state()) {
|
|
|
|
case Doctrine_Record::STATE_TDIRTY:
|
|
|
|
$this->insert($record);
|
|
|
|
break;
|
|
|
|
case Doctrine_Record::STATE_DIRTY:
|
|
|
|
case Doctrine_Record::STATE_PROXY:
|
|
|
|
$this->update($record);
|
|
|
|
break;
|
|
|
|
case Doctrine_Record::STATE_CLEAN:
|
|
|
|
case Doctrine_Record::STATE_TCLEAN:
|
|
|
|
// do nothing
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$record->getTable()->getRecordListener()->postSave($event);
|
|
|
|
|
|
|
|
$record->postSave($event);
|
2008-01-05 22:55:56 +03:00
|
|
|
}*/
|
2007-10-23 01:47:05 +04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* deletes given record and all the related composites
|
|
|
|
* this operation is isolated by a transaction
|
|
|
|
*
|
|
|
|
* this event can be listened by the onPreDelete and onDelete listeners
|
|
|
|
*
|
|
|
|
* @return boolean true on success, false on failure
|
2008-01-05 22:55:56 +03:00
|
|
|
* @todo Move to Doctrine_Table (which will become Doctrine_Mapper).
|
2007-10-23 01:47:05 +04:00
|
|
|
*/
|
2008-01-12 22:49:11 +03:00
|
|
|
/*public function delete(Doctrine_Record $record)
|
2007-10-23 01:47:05 +04:00
|
|
|
{
|
2008-01-05 22:55:56 +03:00
|
|
|
if ( ! $this->_autoflush) {
|
|
|
|
return true;
|
|
|
|
}
|
2007-10-23 01:47:05 +04:00
|
|
|
if ( ! $record->exists()) {
|
|
|
|
return false;
|
|
|
|
}
|
2007-12-12 18:52:12 +03:00
|
|
|
$this->conn->beginInternalTransaction();
|
2007-10-23 01:47:05 +04:00
|
|
|
|
|
|
|
$event = new Doctrine_Event($record, Doctrine_Event::RECORD_DELETE);
|
|
|
|
|
|
|
|
$record->preDelete($event);
|
|
|
|
|
2007-11-10 16:21:40 +03:00
|
|
|
$table = $record->getTable();
|
|
|
|
|
|
|
|
$table->getRecordListener()->preDelete($event);
|
2007-10-23 01:47:05 +04:00
|
|
|
|
|
|
|
$state = $record->state();
|
|
|
|
|
|
|
|
$record->state(Doctrine_Record::STATE_LOCKED);
|
|
|
|
|
|
|
|
$this->deleteComposites($record);
|
|
|
|
|
|
|
|
if ( ! $event->skipOperation) {
|
|
|
|
$record->state(Doctrine_Record::STATE_TDIRTY);
|
2008-01-05 22:55:56 +03:00
|
|
|
|
|
|
|
if ($table->getInheritanceType() == Doctrine::INHERITANCETYPE_JOINED) {
|
2007-11-10 16:21:40 +03:00
|
|
|
foreach ($table->getOption('joinedParents') as $parent) {
|
|
|
|
$parentTable = $table->getConnection()->getTable($parent);
|
2007-11-18 19:06:37 +03:00
|
|
|
$this->conn->delete($parentTable, $record->identifier());
|
2007-11-10 16:21:40 +03:00
|
|
|
}
|
|
|
|
}
|
2008-01-05 22:55:56 +03:00
|
|
|
|
2007-11-18 19:06:37 +03:00
|
|
|
$this->conn->delete($table, $record->identifier());
|
2007-10-23 01:47:05 +04:00
|
|
|
$record->state(Doctrine_Record::STATE_TCLEAN);
|
|
|
|
} else {
|
|
|
|
// return to original state
|
|
|
|
$record->state($state);
|
|
|
|
}
|
|
|
|
|
2007-11-10 16:21:40 +03:00
|
|
|
$table->getRecordListener()->postDelete($event);
|
2007-10-23 01:47:05 +04:00
|
|
|
|
|
|
|
$record->postDelete($event);
|
2007-11-09 01:35:55 +03:00
|
|
|
|
2008-01-05 22:55:56 +03:00
|
|
|
$record->getMapper()->removeRecord($record);
|
2007-10-23 01:47:05 +04:00
|
|
|
|
|
|
|
$this->conn->commit();
|
|
|
|
|
|
|
|
return true;
|
2008-01-12 22:49:11 +03:00
|
|
|
}*/
|
2007-10-23 01:47:05 +04:00
|
|
|
|
2007-11-19 13:00:44 +03:00
|
|
|
/**
|
|
|
|
* @todo Description. See also the todo for deleteMultiple().
|
|
|
|
*/
|
2008-01-05 22:55:56 +03:00
|
|
|
/*public function deleteRecord(Doctrine_Record $record)
|
2007-10-23 01:47:05 +04:00
|
|
|
{
|
|
|
|
$ids = $record->identifier();
|
|
|
|
$tmp = array();
|
|
|
|
|
|
|
|
foreach (array_keys($ids) as $id) {
|
|
|
|
$tmp[] = $id . ' = ? ';
|
|
|
|
}
|
|
|
|
|
|
|
|
$params = array_values($ids);
|
|
|
|
|
|
|
|
$query = 'DELETE FROM '
|
|
|
|
. $this->conn->quoteIdentifier($record->getTable()->getTableName())
|
|
|
|
. ' WHERE ' . implode(' AND ', $tmp);
|
|
|
|
|
|
|
|
|
|
|
|
return $this->conn->exec($query, $params);
|
2008-01-05 22:55:56 +03:00
|
|
|
}*/
|
2007-10-23 01:47:05 +04:00
|
|
|
|
|
|
|
/**
|
2008-01-12 22:49:11 +03:00
|
|
|
* DOESNT SEEM TO BE USED ANYWHERE.
|
|
|
|
*
|
2007-10-23 01:47:05 +04:00
|
|
|
* deleteMultiple
|
|
|
|
* deletes all records from the pending delete list
|
|
|
|
*
|
|
|
|
* @return void
|
2007-11-19 13:00:44 +03:00
|
|
|
* @todo Refactor. Maybe move to the Connection class? Sometimes UnitOfWork constructs
|
|
|
|
* queries itself and sometimes it leaves the sql construction to Connection.
|
|
|
|
* This should be changed.
|
2007-10-23 01:47:05 +04:00
|
|
|
*/
|
2008-01-12 22:49:11 +03:00
|
|
|
/*public function deleteMultiple(array $records)
|
2007-11-19 13:00:44 +03:00
|
|
|
{
|
2007-10-23 01:47:05 +04:00
|
|
|
foreach ($this->delete as $name => $deletes) {
|
|
|
|
$record = false;
|
2007-11-19 13:00:44 +03:00
|
|
|
$ids = array();
|
|
|
|
|
|
|
|
// Note: Why is the last element's table identifier checked here and then
|
|
|
|
// the table object from $deletes[0] used???
|
|
|
|
if (is_array($deletes[count($deletes)-1]->getTable()->getIdentifier()) &&
|
|
|
|
count($deletes) > 0) {
|
|
|
|
$table = $deletes[0]->getTable();
|
|
|
|
$query = 'DELETE FROM '
|
|
|
|
. $this->conn->quoteIdentifier($table->getTableName())
|
|
|
|
. ' WHERE ';
|
|
|
|
|
|
|
|
$params = array();
|
|
|
|
$cond = array();
|
|
|
|
foreach ($deletes as $k => $record) {
|
|
|
|
$ids = $record->identifier();
|
|
|
|
$tmp = array();
|
|
|
|
foreach (array_keys($ids) as $id) {
|
|
|
|
$tmp[] = $table->getColumnName($id) . ' = ? ';
|
2007-10-23 01:47:05 +04:00
|
|
|
}
|
2007-11-19 13:00:44 +03:00
|
|
|
$params = array_merge($params, array_values($ids));
|
|
|
|
$cond[] = '(' . implode(' AND ', $tmp) . ')';
|
2007-10-23 01:47:05 +04:00
|
|
|
}
|
2007-11-19 13:00:44 +03:00
|
|
|
$query .= implode(' OR ', $cond);
|
|
|
|
|
|
|
|
$this->conn->execute($query, $params);
|
2007-10-23 01:47:05 +04:00
|
|
|
} else {
|
|
|
|
foreach ($deletes as $k => $record) {
|
|
|
|
$ids[] = $record->getIncremented();
|
|
|
|
}
|
2007-11-19 13:00:44 +03:00
|
|
|
// looks pretty messy. $record should be already out of scope. ugly php behaviour.
|
|
|
|
// even the php manual agrees on that and recommends to unset() the last element
|
|
|
|
// immediately after the loop ends.
|
|
|
|
$table = $record->getTable();
|
2007-10-23 01:47:05 +04:00
|
|
|
if ($record instanceof Doctrine_Record) {
|
|
|
|
$params = substr(str_repeat('?, ', count($ids)), 0, -2);
|
|
|
|
|
|
|
|
$query = 'DELETE FROM '
|
|
|
|
. $this->conn->quoteIdentifier($record->getTable()->getTableName())
|
|
|
|
. ' WHERE '
|
2007-11-19 13:00:44 +03:00
|
|
|
. $table->getColumnName($table->getIdentifier())
|
2007-10-23 01:47:05 +04:00
|
|
|
. ' IN(' . $params . ')';
|
|
|
|
|
|
|
|
$this->conn->execute($query, $ids);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-01-12 22:49:11 +03:00
|
|
|
}*/
|
2007-10-23 01:47:05 +04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* saveRelated
|
|
|
|
* saves all related records to $record
|
|
|
|
*
|
|
|
|
* @throws PDOException if something went wrong at database level
|
|
|
|
* @param Doctrine_Record $record
|
|
|
|
*/
|
2008-01-05 22:55:56 +03:00
|
|
|
/*public function saveRelated(Doctrine_Record $record)
|
2007-10-23 01:47:05 +04:00
|
|
|
{
|
|
|
|
$saveLater = array();
|
|
|
|
foreach ($record->getReferences() as $k => $v) {
|
|
|
|
$rel = $record->getTable()->getRelation($k);
|
|
|
|
|
|
|
|
$local = $rel->getLocal();
|
|
|
|
$foreign = $rel->getForeign();
|
|
|
|
|
|
|
|
if ($rel instanceof Doctrine_Relation_ForeignKey) {
|
|
|
|
$saveLater[$k] = $rel;
|
2007-11-19 13:00:44 +03:00
|
|
|
} else if ($rel instanceof Doctrine_Relation_LocalKey) {
|
2007-10-23 01:47:05 +04:00
|
|
|
// ONE-TO-ONE relationship
|
|
|
|
$obj = $record->get($rel->getAlias());
|
|
|
|
|
|
|
|
// Protection against infinite function recursion before attempting to save
|
2007-11-19 13:00:44 +03:00
|
|
|
if ($obj instanceof Doctrine_Record && $obj->isModified()) {
|
2007-10-23 01:47:05 +04:00
|
|
|
$obj->save($this->conn);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $saveLater;
|
2008-01-05 22:55:56 +03:00
|
|
|
}*/
|
2007-10-23 01:47:05 +04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* saveAssociations
|
|
|
|
*
|
|
|
|
* this method takes a diff of one-to-many / many-to-many original and
|
|
|
|
* current collections and applies the changes
|
|
|
|
*
|
|
|
|
* for example if original many-to-many related collection has records with
|
|
|
|
* primary keys 1,2 and 3 and the new collection has records with primary keys
|
|
|
|
* 3, 4 and 5, this method would first destroy the associations to 1 and 2 and then
|
|
|
|
* save new associations to 4 and 5
|
|
|
|
*
|
|
|
|
* @throws Doctrine_Connection_Exception if something went wrong at database level
|
|
|
|
* @param Doctrine_Record $record
|
|
|
|
* @return void
|
|
|
|
*/
|
2008-01-05 22:55:56 +03:00
|
|
|
/*public function saveAssociations(Doctrine_Record $record)
|
2007-10-23 01:47:05 +04:00
|
|
|
{
|
|
|
|
foreach ($record->getReferences() as $k => $v) {
|
|
|
|
$rel = $record->getTable()->getRelation($k);
|
|
|
|
|
|
|
|
if ($rel instanceof Doctrine_Relation_Association) {
|
|
|
|
$v->save($this->conn);
|
|
|
|
|
|
|
|
$assocTable = $rel->getAssociationTable();
|
|
|
|
foreach ($v->getDeleteDiff() as $r) {
|
|
|
|
$query = 'DELETE FROM ' . $assocTable->getTableName()
|
|
|
|
. ' WHERE ' . $rel->getForeign() . ' = ?'
|
|
|
|
. ' AND ' . $rel->getLocal() . ' = ?';
|
|
|
|
|
|
|
|
$this->conn->execute($query, array($r->getIncremented(), $record->getIncremented()));
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach ($v->getInsertDiff() as $r) {
|
|
|
|
$assocRecord = $assocTable->create();
|
2007-11-20 17:26:42 +03:00
|
|
|
$assocRecord->set($assocTable->getFieldName($rel->getForeign()), $r);
|
|
|
|
$assocRecord->set($assocTable->getFieldName($rel->getLocal()), $record);
|
2007-10-23 01:47:05 +04:00
|
|
|
|
|
|
|
$this->saveGraph($assocRecord);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-01-05 22:55:56 +03:00
|
|
|
}*/
|
2007-10-23 01:47:05 +04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 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
|
|
|
|
*/
|
2008-01-12 22:49:11 +03:00
|
|
|
/*public function deleteComposites(Doctrine_Record $record)
|
2007-10-23 01:47:05 +04:00
|
|
|
{
|
|
|
|
foreach ($record->getTable()->getRelations() as $fk) {
|
|
|
|
if ($fk->isComposite()) {
|
|
|
|
$obj = $record->get($fk->getAlias());
|
2007-11-19 13:00:44 +03:00
|
|
|
if ($obj instanceof Doctrine_Record &&
|
|
|
|
$obj->state() != Doctrine_Record::STATE_LOCKED) {
|
2007-10-23 01:47:05 +04:00
|
|
|
$obj->delete($this->conn);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-01-12 22:49:11 +03:00
|
|
|
}*/
|
2007-10-23 01:47:05 +04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* saveAll
|
|
|
|
* persists all the pending records from all tables
|
|
|
|
*
|
|
|
|
* @throws PDOException if something went wrong at database level
|
|
|
|
* @return void
|
|
|
|
*/
|
2008-01-05 22:55:56 +03:00
|
|
|
/*public function saveAll()
|
2007-10-23 01:47:05 +04:00
|
|
|
{
|
|
|
|
// get the flush tree
|
|
|
|
$tree = $this->buildFlushTree($this->conn->getTables());
|
|
|
|
|
|
|
|
// save all records
|
|
|
|
foreach ($tree as $name) {
|
|
|
|
$table = $this->conn->getTable($name);
|
|
|
|
|
|
|
|
foreach ($table->getRepository() as $record) {
|
2008-01-05 22:55:56 +03:00
|
|
|
$table->save($record);
|
2007-10-23 01:47:05 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// save all associations
|
|
|
|
foreach ($tree as $name) {
|
|
|
|
$table = $this->conn->getTable($name);
|
|
|
|
|
|
|
|
foreach ($table->getRepository() as $record) {
|
2008-01-05 22:55:56 +03:00
|
|
|
$table->saveAssociations($record);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* saveAll
|
|
|
|
* persists all the pending records from all tables
|
|
|
|
*
|
|
|
|
* @throws PDOException if something went wrong at database level
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
public function saveAll()
|
|
|
|
{
|
|
|
|
//echo "<br /><br />flushin all.<br /><br />";
|
|
|
|
// get the flush tree
|
|
|
|
$tree = $this->buildFlushTree($this->conn->getMappers());
|
|
|
|
|
|
|
|
// save all records
|
|
|
|
foreach ($tree as $name) {
|
|
|
|
$mapper = $this->conn->getMapper($name);
|
|
|
|
foreach ($mapper->getRepository() as $record) {
|
|
|
|
//echo $record->getOid() . "<br />";
|
2008-01-12 22:49:11 +03:00
|
|
|
$mapper->saveSingleRecord($record);
|
2008-01-05 22:55:56 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// save all associations
|
|
|
|
foreach ($tree as $name) {
|
|
|
|
$mapper = $this->conn->getMapper($name);
|
|
|
|
foreach ($mapper->getRepository() as $record) {
|
|
|
|
$mapper->saveAssociations($record);
|
2007-10-23 01:47:05 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2007-11-10 16:21:40 +03:00
|
|
|
* updates given record
|
2007-10-23 01:47:05 +04:00
|
|
|
*
|
|
|
|
* @param Doctrine_Record $record record to be updated
|
|
|
|
* @return boolean whether or not the update was successful
|
2008-01-05 22:55:56 +03:00
|
|
|
* @todo Move to Doctrine_Table (which will become Doctrine_Mapper).
|
2007-10-23 01:47:05 +04:00
|
|
|
*/
|
2008-01-05 22:55:56 +03:00
|
|
|
/*public function update(Doctrine_Record $record)
|
2007-10-23 01:47:05 +04:00
|
|
|
{
|
2008-01-05 22:55:56 +03:00
|
|
|
if ( ! $this->_autoflush) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2007-10-23 01:47:05 +04:00
|
|
|
$event = new Doctrine_Event($record, Doctrine_Event::RECORD_UPDATE);
|
|
|
|
|
|
|
|
$record->preUpdate($event);
|
|
|
|
|
2007-11-10 16:21:40 +03:00
|
|
|
$table = $record->getTable();
|
|
|
|
|
|
|
|
$table->getRecordListener()->preUpdate($event);
|
2007-10-23 01:47:05 +04:00
|
|
|
|
|
|
|
if ( ! $event->skipOperation) {
|
2007-11-10 16:21:40 +03:00
|
|
|
$identifier = $record->identifier();
|
2007-10-23 01:47:05 +04:00
|
|
|
|
2008-01-05 22:55:56 +03:00
|
|
|
if ($table->getInheritanceType() == Doctrine::INHERITANCETYPE_JOINED
|
|
|
|
&& count($table->getOption('joinedParents')) > 0) {
|
2007-11-10 16:21:40 +03:00
|
|
|
$dataSet = $this->formatDataSet($record);
|
|
|
|
|
|
|
|
$component = $table->getComponentName();
|
|
|
|
|
|
|
|
$classes = $table->getOption('joinedParents');
|
|
|
|
$classes[] = $component;
|
|
|
|
|
|
|
|
foreach ($record as $field => $value) {
|
2007-10-23 01:47:05 +04:00
|
|
|
if ($value instanceof Doctrine_Record) {
|
|
|
|
if ( ! $value->exists()) {
|
2007-11-10 16:21:40 +03:00
|
|
|
$value->save();
|
2007-10-23 01:47:05 +04:00
|
|
|
}
|
2007-11-10 16:21:40 +03:00
|
|
|
$record->set($field, $value->getIncremented());
|
2007-10-23 01:47:05 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-11-10 16:21:40 +03:00
|
|
|
foreach ($classes as $class) {
|
|
|
|
$parentTable = $this->conn->getTable($class);
|
2008-01-05 22:55:56 +03:00
|
|
|
$this->conn->update($parentTable, $dataSet[$class], $identifier);
|
2007-11-10 16:21:40 +03:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$array = $record->getPrepared();
|
|
|
|
|
2007-11-18 19:06:37 +03:00
|
|
|
$this->conn->update($table, $array, $identifier);
|
2007-10-23 01:47:05 +04:00
|
|
|
}
|
|
|
|
$record->assignIdentifier(true);
|
|
|
|
}
|
|
|
|
|
2007-11-10 16:21:40 +03:00
|
|
|
$table->getRecordListener()->postUpdate($event);
|
2007-10-23 01:47:05 +04:00
|
|
|
|
|
|
|
$record->postUpdate($event);
|
|
|
|
|
|
|
|
return true;
|
2008-01-05 22:55:56 +03:00
|
|
|
}*/
|
2007-11-19 13:00:44 +03:00
|
|
|
|
2007-10-23 01:47:05 +04:00
|
|
|
/**
|
|
|
|
* inserts a record into database
|
|
|
|
*
|
|
|
|
* @param Doctrine_Record $record record to be inserted
|
|
|
|
* @return boolean
|
2008-01-05 22:55:56 +03:00
|
|
|
* @todo Move to Doctrine_Table (which will become Doctrine_Mapper).
|
2007-10-23 01:47:05 +04:00
|
|
|
*/
|
2008-01-05 22:55:56 +03:00
|
|
|
/*public function insert(Doctrine_Record $record)
|
2007-10-23 01:47:05 +04:00
|
|
|
{
|
2008-01-05 22:55:56 +03:00
|
|
|
if ( ! $this->_autoflush) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// listen the onPreInsert event
|
2007-10-23 01:47:05 +04:00
|
|
|
$event = new Doctrine_Event($record, Doctrine_Event::RECORD_INSERT);
|
|
|
|
|
|
|
|
$record->preInsert($event);
|
|
|
|
|
2007-11-09 02:03:28 +03:00
|
|
|
$table = $record->getTable();
|
|
|
|
|
|
|
|
$table->getRecordListener()->preInsert($event);
|
2007-10-23 01:47:05 +04:00
|
|
|
|
|
|
|
if ( ! $event->skipOperation) {
|
2008-01-05 22:55:56 +03:00
|
|
|
if ($table->getInheritanceType() == Doctrine::INHERITANCETYPE_JOINED &&
|
|
|
|
count($table->getOption('joinedParents')) > 0) {
|
2007-11-10 16:21:40 +03:00
|
|
|
$dataSet = $this->formatDataSet($record);
|
|
|
|
|
2007-11-09 02:03:28 +03:00
|
|
|
$component = $table->getComponentName();
|
|
|
|
|
|
|
|
$classes = $table->getOption('joinedParents');
|
|
|
|
$classes[] = $component;
|
|
|
|
|
|
|
|
foreach ($classes as $k => $parent) {
|
|
|
|
if ($k === 0) {
|
|
|
|
$rootRecord = new $parent();
|
|
|
|
|
|
|
|
$rootRecord->merge($dataSet[$parent]);
|
|
|
|
|
|
|
|
$this->processSingleInsert($rootRecord);
|
2007-12-28 14:51:48 +03:00
|
|
|
|
|
|
|
$record->assignIdentifier($rootRecord->identifier());
|
2007-11-09 02:03:28 +03:00
|
|
|
} else {
|
|
|
|
foreach ((array) $rootRecord->identifier() as $id => $value) {
|
|
|
|
$dataSet[$parent][$id] = $value;
|
|
|
|
}
|
|
|
|
|
2007-11-18 19:06:37 +03:00
|
|
|
$this->conn->insert($this->conn->getTable($parent), $dataSet[$parent]);
|
2007-11-09 02:03:28 +03:00
|
|
|
}
|
2007-10-23 01:47:05 +04:00
|
|
|
}
|
|
|
|
} else {
|
2007-11-09 02:03:28 +03:00
|
|
|
$this->processSingleInsert($record);
|
2007-10-23 01:47:05 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-11-09 02:03:28 +03:00
|
|
|
$table->addRecord($record);
|
|
|
|
|
|
|
|
$table->getRecordListener()->postInsert($event);
|
2007-10-23 01:47:05 +04:00
|
|
|
|
|
|
|
$record->postInsert($event);
|
|
|
|
|
|
|
|
return true;
|
2008-01-05 22:55:56 +03:00
|
|
|
}*/
|
2007-11-18 19:06:37 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @todo DESCRIBE WHAT THIS METHOD DOES, PLEASE!
|
|
|
|
*/
|
2008-01-05 22:55:56 +03:00
|
|
|
/*public function formatDataSet(Doctrine_Record $record)
|
2007-11-10 16:21:40 +03:00
|
|
|
{
|
|
|
|
$table = $record->getTable();
|
|
|
|
|
|
|
|
$dataSet = array();
|
|
|
|
|
|
|
|
$component = $table->getComponentName();
|
|
|
|
|
|
|
|
$array = $record->getPrepared();
|
|
|
|
|
2007-11-18 19:06:37 +03:00
|
|
|
foreach ($table->getColumns() as $columnName => $definition) {
|
|
|
|
$fieldName = $table->getFieldName($columnName);
|
2007-11-10 16:21:40 +03:00
|
|
|
if (isset($definition['primary']) && $definition['primary']) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isset($definition['owner'])) {
|
2007-11-18 19:06:37 +03:00
|
|
|
$dataSet[$definition['owner']][$fieldName] = $array[$fieldName];
|
2007-11-10 16:21:40 +03:00
|
|
|
} else {
|
2007-11-18 19:06:37 +03:00
|
|
|
$dataSet[$component][$fieldName] = $array[$fieldName];
|
2007-11-10 16:21:40 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $dataSet;
|
2008-01-05 22:55:56 +03:00
|
|
|
}*/
|
2007-11-18 19:06:37 +03:00
|
|
|
|
2007-10-23 01:47:05 +04:00
|
|
|
}
|