|
|
@@ -70,6 +70,7 @@ abstract class Zend_Db_Table_Abstract
|
|
|
const ON_UPDATE = 'onUpdate';
|
|
|
|
|
|
const CASCADE = 'cascade';
|
|
|
+ const CASCADE_RECURSE = 'cascadeRecurse';
|
|
|
const RESTRICT = 'restrict';
|
|
|
const SET_NULL = 'setNull';
|
|
|
|
|
|
@@ -1193,27 +1194,56 @@ abstract class Zend_Db_Table_Abstract
|
|
|
*/
|
|
|
public function _cascadeDelete($parentTableClassname, array $primaryKey)
|
|
|
{
|
|
|
+ // setup metadata
|
|
|
$this->_setupMetadata();
|
|
|
+
|
|
|
+ // get this class name
|
|
|
+ $thisClass = get_class($this);
|
|
|
+ if ($thisClass === 'Zend_Db_Table') {
|
|
|
+ $thisClass = $this->_definitionConfigName;
|
|
|
+ }
|
|
|
+
|
|
|
$rowsAffected = 0;
|
|
|
+
|
|
|
foreach ($this->_getReferenceMapNormalized() as $map) {
|
|
|
if ($map[self::REF_TABLE_CLASS] == $parentTableClassname && isset($map[self::ON_DELETE])) {
|
|
|
- switch ($map[self::ON_DELETE]) {
|
|
|
- case self::CASCADE:
|
|
|
- $where = array();
|
|
|
- for ($i = 0; $i < count($map[self::COLUMNS]); ++$i) {
|
|
|
- $col = $this->_db->foldCase($map[self::COLUMNS][$i]);
|
|
|
- $refCol = $this->_db->foldCase($map[self::REF_COLUMNS][$i]);
|
|
|
- $type = $this->_metadata[$col]['DATA_TYPE'];
|
|
|
- $where[] = $this->_db->quoteInto(
|
|
|
- $this->_db->quoteIdentifier($col, true) . ' = ?',
|
|
|
- $primaryKey[$refCol], $type);
|
|
|
+
|
|
|
+ $where = array();
|
|
|
+
|
|
|
+ // CASCADE or CASCADE_RECURSE
|
|
|
+ if (in_array($map[self::ON_DELETE], array(self::CASCADE, self::CASCADE_RECURSE))) {
|
|
|
+ for ($i = 0; $i < count($map[self::COLUMNS]); ++$i) {
|
|
|
+ $col = $this->_db->foldCase($map[self::COLUMNS][$i]);
|
|
|
+ $refCol = $this->_db->foldCase($map[self::REF_COLUMNS][$i]);
|
|
|
+ $type = $this->_metadata[$col]['DATA_TYPE'];
|
|
|
+ $where[] = $this->_db->quoteInto(
|
|
|
+ $this->_db->quoteIdentifier($col, true) . ' = ?',
|
|
|
+ $primaryKey[$refCol], $type);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // CASCADE_RECURSE
|
|
|
+ if ($map[self::ON_DELETE] == self::CASCADE_RECURSE) {
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Execute cascading deletes against dependent tables
|
|
|
+ */
|
|
|
+ $depTables = $this->getDependentTables();
|
|
|
+ if (!empty($depTables)) {
|
|
|
+ foreach ($depTables as $tableClass) {
|
|
|
+ $t = self::getTableFromString($tableClass, $this);
|
|
|
+ foreach ($this->fetchAll($where) as $depRow) {
|
|
|
+ $rowsAffected += $t->_cascadeDelete($thisClass, $depRow->getPrimaryKey());
|
|
|
+ }
|
|
|
}
|
|
|
- $rowsAffected += $this->delete($where);
|
|
|
- break;
|
|
|
- default:
|
|
|
- // no action
|
|
|
- break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // CASCADE or CASCADE_RECURSE
|
|
|
+ if (in_array($map[self::ON_DELETE], array(self::CASCADE, self::CASCADE_RECURSE))) {
|
|
|
+ $rowsAffected += $this->delete($where);
|
|
|
}
|
|
|
+
|
|
|
}
|
|
|
}
|
|
|
return $rowsAffected;
|
|
|
@@ -1531,4 +1561,38 @@ abstract class Zend_Db_Table_Abstract
|
|
|
return $data;
|
|
|
}
|
|
|
|
|
|
+ public static function getTableFromString($tableName, Zend_Db_Table_Abstract $referenceTable = null)
|
|
|
+ {
|
|
|
+ if ($referenceTable instanceof Zend_Db_Table_Abstract) {
|
|
|
+ $tableDefinition = $referenceTable->getDefinition();
|
|
|
+
|
|
|
+ if ($tableDefinition !== null && $tableDefinition->hasTableConfig($tableName)) {
|
|
|
+ return new Zend_Db_Table($tableName, $tableDefinition);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // assume the tableName is the class name
|
|
|
+ if (!class_exists($tableName)) {
|
|
|
+ try {
|
|
|
+ require_once 'Zend/Loader.php';
|
|
|
+ Zend_Loader::loadClass($tableName);
|
|
|
+ } catch (Zend_Exception $e) {
|
|
|
+ require_once 'Zend/Db/Table/Row/Exception.php';
|
|
|
+ throw new Zend_Db_Table_Row_Exception($e->getMessage(), $e->getCode(), $e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ $options = array();
|
|
|
+
|
|
|
+ if ($referenceTable instanceof Zend_Db_Table_Abstract) {
|
|
|
+ $options['db'] = $referenceTable->getAdapter();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (isset($tableDefinition) && $tableDefinition !== null) {
|
|
|
+ $options[Zend_Db_Table_Abstract::DEFINITION] = $tableDefinition;
|
|
|
+ }
|
|
|
+
|
|
|
+ return new $tableName($options);
|
|
|
+ }
|
|
|
+
|
|
|
}
|