From d6095a2420403f2409907b51b46037e3f5ea5404 Mon Sep 17 00:00:00 2001 From: zYne Date: Thu, 14 Jun 2007 18:15:33 +0000 Subject: [PATCH] added IntegrityMapper for future emulation purposes --- lib/Doctrine/IntegrityMapper.php | 142 +++++++++++++++++++++++++++++++ lib/Doctrine/Manager.php | 27 ++++++ lib/Doctrine/Relation/Parser.php | 11 ++- 3 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 lib/Doctrine/IntegrityMapper.php diff --git a/lib/Doctrine/IntegrityMapper.php b/lib/Doctrine/IntegrityMapper.php new file mode 100644 index 000000000..d9858a978 --- /dev/null +++ b/lib/Doctrine/IntegrityMapper.php @@ -0,0 +1,142 @@ +. + */ +Doctrine::autoload('Doctrine_Connection_Module'); +/** + * Doctrine_Connection_UnitOfWork + * + * @package Doctrine + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @category Object Relational Mapping + * @link www.phpdoctrine.com + * @since 1.0 + * @version $Revision: 1495 $ + * @author Konsta Vesterinen + */ +class Doctrine_IntegrityMapper +{ + public function processDeleteIntegrity(Doctrine_Record $record) + { + $coll = $this->buildIntegrityRelationQuery($record); + + $this->invokeIntegrityActions($record); + } + public function invokeIntegrityActions(Doctrine_Record $record) + { + $deleteActions = Doctrine_Manager::getInstance() + ->getDeleteActions($record->getTable()->getComponentName()); + + foreach ($record->getTable()->getRelations() as $relation) { + $componentName = $relation->getTable()->getComponentName(); + + foreach($record->get($relation->getAlias()) as $coll) { + if ( ! ($coll instanceof Doctrine_Collection)) { + $coll = array($coll); + } + foreach ($coll as $record) { + $this->invokeIntegrityActions($record); + + if (isset($deleteActions[$componentName])) { + if ($deleteActions[$componentName] === 'SET NULL') { + $record->set($relation->getForeign(), null); + } elseif ($deleteActions[$componentName] === 'CASCADE') { + $this->conn->transaction->addDelete($record); + } + } + + } + } + } + } + public function buildIntegrityRelationQuery(Doctrine_Record $record) + { + $q = new Doctrine_Query(); + + $aliases = array(); + $indexes = array(); + + $root = $record->getTable()->getComponentName(); + $rootAlias = strtolower(substr($root, 0, 1)); + $aliases[$rootAlias] = $root; + + foreach ((array) $record->getTable()->getIdentifier() as $id) { + $field = $rootAlias . '.' . $id; + $cond[] = $field . ' = ?'; + $fields[] = $field; + $params = $record->get($id); + } + $fields = implode(', ', $fields); + $components[] = $root; + $this->buildIntegrityRelations($record->getTable(), $aliases, $fields, $indexes, $components); + + $q->select($fields)->from($root. ' ' . $rootAlias); + + foreach ($aliases as $alias => $name) { + $q->leftJoin($rootAlias . '.' . $name . ' ' . $alias); + } + $q->where(implode(' AND ', $cond)); + + return $q->execute(array($params)); + } + public function buildIntegrityRelations(Doctrine_Table $table, &$aliases, &$fields, &$indexes, &$components) + { + $deleteActions = Doctrine_Manager::getInstance() + ->getDeleteActions($table->getComponentName()); + + foreach ($table->getRelations() as $relation) { + $componentName = $relation->getTable()->getComponentName(); + if (in_array($componentName, $components)) { + continue; + } + $components[] = $componentName; + + $alias = strtolower(substr($relation->getAlias(), 0, 1)); + + if ( ! isset($indexes[$alias])) { + $indexes[$alias] = 1; + } + + if (isset($deleteActions[$componentName])) { + if (isset($aliases[$alias])) { + $alias = $alias . ++$indexes[$alias]; + } + $aliases[$alias] = $relation->getAlias(); + + if ($deleteActions[$componentName] === 'SET NULL') { + if ($relation instanceof Doctrine_Relation_ForeignKey) { + foreach ((array) $relation->getForeign() as $foreign) { + $fields .= ', ' . $alias . '.' . $foreign; + } + } elseif ($relation instanceof Doctrine_Relation_LocalKey) { + foreach ((array) $relation->getLocal() as $foreign) { + $fields .= ', ' . $alias . '.' . $foreign; + } + } + } + foreach ((array) $relation->getTable()->getIdentifier() as $id) { + $fields .= ', ' . $alias . '.' . $id; + } + if ($deleteActions[$componentName] === 'CASCADE') { + $this->buildIntegrityRelations($relation->getTable(), $aliases, $fields, $indexes, $components); + } + } + } + } +} diff --git a/lib/Doctrine/Manager.php b/lib/Doctrine/Manager.php index 84dc182f0..8664c966a 100644 --- a/lib/Doctrine/Manager.php +++ b/lib/Doctrine/Manager.php @@ -65,6 +65,9 @@ class Doctrine_Manager extends Doctrine_Configurable implements Countable, Itera 'oci' => 'oci8', 'sqlite2' => 'sqlite', 'sqlite3' => 'sqlite'); + + + protected $_integrityActionsMap = array(); /** * constructor * @@ -79,6 +82,30 @@ class Doctrine_Manager extends Doctrine_Configurable implements Countable, Itera Doctrine_Validator::initNullObject($this->_null); Doctrine_Object::initNullObject($this->_null); } + public function addDeleteAction($componentName, $foreignComponent, $action) + { + $this->_integrityActions[$componentName]['onDelete'][$foreignComponent] = $action; + } + public function addUpdateAction($componentName, $foreignComponent, $action) + { + $this->_integrityActions[$componentName]['onUpdate'][$foreignComponent] = $action; + } + public function getDeleteActions($componentName) + { + if ( ! isset($this->_integrityActions[$componentName]['onDelete'])) { + return null; + } + + return $this->_integrityActions[$componentName]['onDelete']; + } + public function getUpdateActions($componentName) + { + if ( ! isset($this->_integrityActions[$componentName]['onUpdate'])) { + return null; + } + + return $this->_integrityActions[$componentName]['onUpdate']; + } /** * @return Doctrine_Null */ diff --git a/lib/Doctrine/Relation/Parser.php b/lib/Doctrine/Relation/Parser.php index 134564c00..aca885c68 100644 --- a/lib/Doctrine/Relation/Parser.php +++ b/lib/Doctrine/Relation/Parser.php @@ -102,7 +102,16 @@ class Doctrine_Relation_Parser } $this->_pending[$alias] = array_merge($options, array('class' => $name, 'alias' => $alias)); + + $m = Doctrine_Manager::getInstance(); + if (isset($options['onDelete'])) { + $m->addDeleteAction($name, $this->_table->getComponentName(), $options['onDelete']); + } + if (isset($options['onUpdate'])) { + $m->addUpdateAction($name, $this->_table->getComponentName(), $options['onUpdate']); + } + return $this->_pending[$alias]; } /** @@ -126,7 +135,7 @@ class Doctrine_Relation_Parser $localClasses = array_merge($this->_table->getOption('parents'), array($this->_table->getComponentName())); if ( ! isset($this->_pending[$def['refClass']]) && - ! isset($this->_relations[$def['refClass']])) { + ! isset($this->_relations[$def['refClass']])) { $def['refTable']->getRelationParser()->bind($this->_table->getComponentName(), array('type' => Doctrine_Relation::ONE,