--- a/web/lib/Zend/Db/Table/Abstract.php Thu Mar 21 17:31:31 2013 +0100
+++ b/web/lib/Zend/Db/Table/Abstract.php Thu Mar 21 19:50:53 2013 +0100
@@ -15,9 +15,9 @@
* @category Zend
* @package Zend_Db
* @subpackage Table
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Abstract.php 21078 2010-02-18 18:07:16Z tech13 $
+ * @version $Id: Abstract.php 24958 2012-06-15 13:44:04Z adamlundrigan $
*/
/**
@@ -41,7 +41,7 @@
* @category Zend
* @package Zend_Db
* @subpackage Table
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Db_Table_Abstract
@@ -70,6 +70,7 @@
const ON_UPDATE = 'onUpdate';
const CASCADE = 'cascade';
+ const CASCADE_RECURSE = 'cascadeRecurse';
const RESTRICT = 'restrict';
const SET_NULL = 'setNull';
@@ -744,6 +745,7 @@
* Initialize database adapter.
*
* @return void
+ * @throws Zend_Db_Table_Exception
*/
protected function _setupDatabaseAdapter()
{
@@ -807,12 +809,23 @@
//get db configuration
$dbConfig = $this->_db->getConfig();
+ $port = isset($dbConfig['options']['port'])
+ ? ':'.$dbConfig['options']['port']
+ : (isset($dbConfig['port'])
+ ? ':'.$dbConfig['port']
+ : null);
+
+ $host = isset($dbConfig['options']['host'])
+ ? ':'.$dbConfig['options']['host']
+ : (isset($dbConfig['host'])
+ ? ':'.$dbConfig['host']
+ : null);
+
// Define the cache identifier where the metadata are saved
$cacheId = md5( // port:host/dbname:schema.table (based on availabilty)
- (isset($dbConfig['options']['port']) ? ':'.$dbConfig['options']['port'] : null)
- . (isset($dbConfig['options']['host']) ? ':'.$dbConfig['options']['host'] : null)
- . '/'.$dbConfig['dbname'].':'.$this->_schema.'.'.$this->_name
- );
+ $port . $host . '/'. $dbConfig['dbname'] . ':'
+ . $this->_schema. '.' . $this->_name
+ );
}
// If $this has no metadata cache or metadata cache misses
@@ -873,7 +886,7 @@
// then throw an exception.
if (empty($this->_primary)) {
require_once 'Zend/Db/Table/Exception.php';
- throw new Zend_Db_Table_Exception('A table must have a primary key, but none was found');
+ throw new Zend_Db_Table_Exception("A table must have a primary key, but none was found for table '{$this->_name}'");
}
} else if (!is_array($this->_primary)) {
$this->_primary = array(1 => $this->_primary);
@@ -961,8 +974,9 @@
* You can elect to return only a part of this information by supplying its key name,
* otherwise all information is returned as an array.
*
- * @param $key The specific info part to return OPTIONAL
+ * @param string $key The specific info part to return OPTIONAL
* @return mixed
+ * @throws Zend_Db_Table_Exception
*/
public function info($key = null)
{
@@ -1035,14 +1049,24 @@
*/
if (is_string($this->_sequence) && !isset($data[$pkIdentity])) {
$data[$pkIdentity] = $this->_db->nextSequenceId($this->_sequence);
+ $pkSuppliedBySequence = true;
}
/**
* If the primary key can be generated automatically, and no value was
* specified in the user-supplied data, then omit it from the tuple.
+ *
+ * Note: this checks for sensible values in the supplied primary key
+ * position of the data. The following values are considered empty:
+ * null, false, true, '', array()
*/
- if (array_key_exists($pkIdentity, $data) && $data[$pkIdentity] === null) {
- unset($data[$pkIdentity]);
+ if (!isset($pkSuppliedBySequence) && array_key_exists($pkIdentity, $data)) {
+ if ($data[$pkIdentity] === null // null
+ || $data[$pkIdentity] === '' // empty string
+ || is_bool($data[$pkIdentity]) // boolean
+ || (is_array($data[$pkIdentity]) && empty($data[$pkIdentity]))) { // empty array
+ unset($data[$pkIdentity]);
+ }
}
/**
@@ -1157,6 +1181,22 @@
*/
public function delete($where)
{
+ $depTables = $this->getDependentTables();
+ if (!empty($depTables)) {
+ $resultSet = $this->fetchAll($where);
+ if (count($resultSet) > 0 ) {
+ foreach ($resultSet as $row) {
+ /**
+ * Execute cascading deletes against dependent tables
+ */
+ foreach ($depTables as $tableClass) {
+ $t = self::getTableFromString($tableClass, $this);
+ $t->_cascadeDelete($tableClass, $row->getPrimaryKey());
+ }
+ }
+ }
+ }
+
$tableSpec = ($this->_schema ? $this->_schema . '.' : '') . $this->_name;
return $this->_db->delete($tableSpec, $where);
}
@@ -1170,27 +1210,56 @@
*/
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;
@@ -1342,10 +1411,11 @@
*
* @param string|array|Zend_Db_Table_Select $where OPTIONAL An SQL WHERE clause or Zend_Db_Table_Select object.
* @param string|array $order OPTIONAL An SQL ORDER clause.
+ * @param int $offset OPTIONAL An SQL OFFSET value.
* @return Zend_Db_Table_Row_Abstract|null The row results per the
* Zend_Db_Adapter fetch mode, or null if no row found.
*/
- public function fetchRow($where = null, $order = null)
+ public function fetchRow($where = null, $order = null, $offset = null)
{
if (!($where instanceof Zend_Db_Table_Select)) {
$select = $this->select();
@@ -1358,10 +1428,10 @@
$this->_order($select, $order);
}
- $select->limit(1);
+ $select->limit(1, ((is_numeric($offset)) ? (int) $offset : null));
} else {
- $select = $where->limit(1);
+ $select = $where->limit(1, $where->getPart(Zend_Db_Select::LIMIT_OFFSET));
}
$rows = $this->_fetch($select);
@@ -1507,4 +1577,38 @@
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);
+ }
+
}