* @author Alan Knowles <alan@akbkhome.com>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
- * @version CVS: $Id: DataObject.php 284150 2009-07-15 23:27:59Z alan_k $
+ * @version CVS: $Id: DataObject.php 301030 2010-07-07 02:26:31Z alan_k $
* @link http://pear.php.net/package/DB_DataObject
*/
* @access private
* @var string
*/
- var $_DB_DataObject_version = "1.8.12";
+ var $_DB_DataObject_version = "1.9.5";
/**
* The Database table (used by table extends)
/**
* An autoloading, caching static get method using key, value (based on get)
- *
+ * (depreciated - use ::get / and your own caching method)
+ *
* Usage:
* $object = DB_DataObject::staticGet("DbTable_mytable",12);
* or
return $_DB_DATAOBJECT['CACHE'][$lclass][$key];
}
+ /**
+ * build the basic select query.
+ *
+ * @access private
+ */
+
+ function _build_select()
+ {
+ global $_DB_DATAOBJECT;
+ $quoteIdentifiers = !empty($_DB_DATAOBJECT['CONFIG']['quote_identifiers']);
+ if ($quoteIdentifiers) {
+ $this->_connect();
+ $DB = &$_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5];
+ }
+ $sql = 'SELECT ' .
+ $this->_query['data_select'] . " \n" .
+ ' FROM ' . ($quoteIdentifiers ? $DB->quoteIdentifier($this->__table) : $this->__table) . " \n" .
+ $this->_join . " \n" .
+ $this->_query['condition'] . " \n" .
+ $this->_query['group_by'] . " \n" .
+ $this->_query['having'] . " \n";
+
+ return $sql;
+ }
+
+
/**
* find results, either normal or crosstable
*
$query_before = $this->_query;
$this->_build_condition($this->table()) ;
- $quoteIdentifiers = !empty($_DB_DATAOBJECT['CONFIG']['quote_identifiers']);
+
$this->_connect();
$DB = &$_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5];
- /* We are checking for method modifyLimitQuery as it is PEAR DB specific */
- $sql = 'SELECT ' .
- $this->_query['data_select'] . " \n" .
- ' FROM ' . ($quoteIdentifiers ? $DB->quoteIdentifier($this->__table) : $this->__table) . " \n" .
- $this->_join . " \n" .
- $this->_query['condition'] . " \n" .
- $this->_query['group_by'] . " \n" .
- $this->_query['having'] . " \n" .
- $this->_query['order_by'] . " \n";
+ $sql = $this->_build_select();
+
+ foreach ($this->_query['unions'] as $union_ar) {
+ $sql .= $union_ar[1] . $union_ar[0]->_build_select() . " \n";
+ }
+
+ $sql .= $this->_query['order_by'] . " \n";
+
+
+ /* We are checking for method modifyLimitQuery as it is PEAR DB specific */
if ((!isset($_DB_DATAOBJECT['CONFIG']['db_driver'])) ||
($_DB_DATAOBJECT['CONFIG']['db_driver'] == 'DB')) {
/* PEAR DB specific */
return true;
}
+
+ /**
+ * fetches all results as an array,
+ *
+ * return format is dependant on args.
+ * if selectAdd() has not been called on the object, then it will add the correct columns to the query.
+ *
+ * A) Array of values (eg. a list of 'id')
+ *
+ * $x = DB_DataObject::factory('mytable');
+ * $x->whereAdd('something = 1')
+ * $ar = $x->fetchAll('id');
+ * -- returns array(1,2,3,4,5)
+ *
+ * B) Array of values (not from table)
+ *
+ * $x = DB_DataObject::factory('mytable');
+ * $x->whereAdd('something = 1');
+ * $x->selectAdd();
+ * $x->selectAdd('distinct(group_id) as group_id');
+ * $ar = $x->fetchAll('group_id');
+ * -- returns array(1,2,3,4,5)
+ * *
+ * C) A key=>value associative array
+ *
+ * $x = DB_DataObject::factory('mytable');
+ * $x->whereAdd('something = 1')
+ * $ar = $x->fetchAll('id','name');
+ * -- returns array(1=>'fred',2=>'blogs',3=> .......
+ *
+ * D) array of objects
+ * $x = DB_DataObject::factory('mytable');
+ * $x->whereAdd('something = 1');
+ * $ar = $x->fetchAll();
+ *
+ * E) array of arrays (for example)
+ * $x = DB_DataObject::factory('mytable');
+ * $x->whereAdd('something = 1');
+ * $ar = $x->fetchAll(false,false,'toArray');
+ *
+ *
+ * @param string|false $k key
+ * @param string|false $v value
+ * @param string|false $method method to call on each result to get array value (eg. 'toArray')
+ * @access public
+ * @return array format dependant on arguments, may be empty
+ */
+ function fetchAll($k= false, $v = false, $method = false)
+ {
+ // should it even do this!!!?!?
+ if ($k !== false &&
+ ( // only do this is we have not been explicit..
+ empty($this->_query['data_select']) ||
+ ($this->_query['data_select'] == '*')
+ )
+ ) {
+ $this->selectAdd();
+ $this->selectAdd($k);
+ if ($v !== false) {
+ $this->selectAdd($v);
+ }
+ }
+
+ $this->find();
+ $ret = array();
+ while ($this->fetch()) {
+ if ($v !== false) {
+ $ret[$this->$k] = $this->$v;
+ continue;
+ }
+ $ret[] = $k === false ?
+ ($method == false ? clone($this) : $this->$method())
+ : $this->$k;
+ }
+ return $ret;
+
+ }
+
+
/**
* Adds a condition to the WHERE statement, defaults to AND
*
return $r;
}
+ /**
+ * Adds a 'IN' condition to the WHERE statement
+ *
+ * $object->whereAddIn('id', $array, 'int'); //minimal usage
+ * $object->whereAddIn('price', $array, 'float', 'OR'); // cast to float, and call whereAdd with 'OR'
+ * $object->whereAddIn('name', $array, 'string'); // quote strings
+ *
+ * @param string $key key column to match
+ * @param array $list list of values to match
+ * @param string $type string|int|integer|float|bool cast to type.
+ * @param string $logic optional logic to call whereAdd with eg. "OR" (defaults to "AND")
+ * @access public
+ * @return string|PEAR::Error - previous condition or Error when invalid args found
+ */
+ function whereAddIn($key, $list, $type, $logic = 'AND')
+ {
+ $not = '';
+ if ($key[0] == '!') {
+ $not = 'NOT ';
+ $key = substr($key, 1);
+ }
+ // fix type for short entry.
+ $type = $type == 'int' ? 'integer' : $type;
+
+ if ($type == 'string') {
+ $this->_connect();
+ }
+
+ $ar = array();
+ foreach($list as $k) {
+ settype($k, $type);
+ $ar[] = $type =='string' ? $this->_quote($k) : $k;
+ }
+ if (!$ar) {
+ return $not ? $this->_query['condition'] : $this->whereAdd("1=0");
+ }
+ return $this->whereAdd("$key $not IN (". implode(',', $ar). ')', $logic );
+ }
+
+
+
/**
* Adds a order by condition
*
}
$this->$key = $keyvalue;
}
-
-
-
+
+ // if we haven't set disable_null_strings to "full"
+ $ignore_null = !isset($options['disable_null_strings'])
+ || !is_string($options['disable_null_strings'])
+ || strtolower($options['disable_null_strings']) !== 'full' ;
+
+
foreach($items as $k => $v) {
// if we are using autoincrement - skip the column...
}
- if (!isset($this->$k)) {
+
+
+ // Ignore variables which aren't set to a value
+ if ( !isset($this->$k) && $ignore_null) {
continue;
}
// dont insert data into mysql timestamps
}
-
- if (!isset($options['disable_null_strings']) && is_string($this->$k) && (strtolower($this->$k) === 'null') && !($v & DB_DATAOBJECT_NOTNULL)) {
+ if (!($v & DB_DATAOBJECT_NOTNULL) && DB_DataObject::_is_null($this,$k)) {
$rightq .= " NULL ";
continue;
}
$seq = $this->sequenceKey();
if ($seq[0] !== false) {
$keys = array($seq[0]);
- if (empty($this->{$keys[0]}) && $dataObject !== true) {
+ if (!isset($this->{$keys[0]}) && $dataObject !== true) {
$this->raiseError("update: trying to perform an update without
the key set, and argument to update is not
DB_DATAOBJECT_WHEREADD_ONLY
$options = $_DB_DATAOBJECT['CONFIG'];
+ $ignore_null = !isset($options['disable_null_strings'])
+ || !is_string($options['disable_null_strings'])
+ || strtolower($options['disable_null_strings']) !== 'full' ;
+
+
foreach($items as $k => $v) {
- if (!isset($this->$k)) {
+
+ if (!isset($this->$k) && $ignore_null) {
continue;
}
// ignore stuff thats
}
// special values ... at least null is handled...
- if (!isset($options['disable_null_strings']) && (strtolower($this->$k) === 'null') && !($v & DB_DATAOBJECT_NOTNULL)) {
+ if (!($v & DB_DATAOBJECT_NOTNULL) && DB_DataObject::_is_null($this,$k)) {
$settings .= "$kSql = NULL ";
continue;
}
'limit_start' => '', // the LIMIT condition
'limit_count' => '', // the LIMIT condition
'data_select' => '*', // the columns to be SELECTed
+ 'unions' => array(), // the added unions
);
}
-
+ $_DB_DATAOBJECT['INI'][$this->_database] = array();
foreach ($schemas as $ini) {
if (file_exists($ini) && is_file($ini)) {
- $_DB_DATAOBJECT['INI'][$this->_database] = parse_ini_file($ini, true);
+
+ $_DB_DATAOBJECT['INI'][$this->_database] = array_merge(
+ $_DB_DATAOBJECT['INI'][$this->_database],
+ parse_ini_file($ini, true)
+ );
+
if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) {
if (!is_readable ($ini)) {
$this->debug("ini file is not readable: $ini","databaseStructure",1);
$seqname = false;
if (!empty($_DB_DATAOBJECT['CONFIG']['sequence_'.$this->__table])) {
- $usekey = $_DB_DATAOBJECT['CONFIG']['sequence_'.$this->__table];
- if (strpos($usekey,':') !== false) {
- list($usekey,$seqname) = explode(':',$usekey);
+ $seqname = $_DB_DATAOBJECT['CONFIG']['sequence_'.$this->__table];
+ if (strpos($seqname,':') !== false) {
+ list($usekey,$seqname) = explode(':',$seqname);
}
}
$x = new DB_DataObject;
$this->_query= $x->_query;
}
-
+
+
foreach($keys as $k => $v) {
// index keys is an indexed array
/* these filter checks are a bit suspicious..
continue;
}
- if (!isset($options['disable_null_strings']) && (strtolower($this->$k) === 'null') && !($v & DB_DATAOBJECT_NOTNULL)) {
+ if (!($v & DB_DATAOBJECT_NOTNULL) && DB_DataObject::_is_null($this,$k)) {
$this->whereAdd(" $kSql IS NULL");
continue;
}
}
// does this need multi db support??
- $p = isset($_DB_DATAOBJECT['CONFIG']['class_prefix']) ?
- $_DB_DATAOBJECT['CONFIG']['class_prefix'] : '';
- $class = $p . preg_replace('/[^A-Z0-9]/i','_',ucfirst($table));
- $ce = substr(phpversion(),0,1) > 4 ? class_exists($class,false) : class_exists($class);
+ $cp = isset($_DB_DATAOBJECT['CONFIG']['class_prefix']) ?
+ explode(PATH_SEPARATOR, $_DB_DATAOBJECT['CONFIG']['class_prefix']) : '';
+
+ // multiprefix support.
+ $tbl = preg_replace('/[^A-Z0-9]/i','_',ucfirst($table));
+ if (is_array($cp)) {
+ $class = array();
+ foreach($cp as $cpr) {
+ $ce = substr(phpversion(),0,1) > 4 ? class_exists($cpr . $tbl,false) : class_exists($cpr . $tbl);
+ if ($ce) {
+ $class = $cpr . $tbl;
+ break;
+ }
+ $class[] = $cpr . $tbl;
+ }
+ } else {
+ $class = $tbl;
+ $ce = substr(phpversion(),0,1) > 4 ? class_exists($class,false) : class_exists($class);
+ }
- $class = $ce ? $class : DB_DataObject::_autoloadClass($class);
+
+ $rclass = $ce ? $class : DB_DataObject::_autoloadClass($class, $table);
// proxy = full|light
- if (!$class && isset($_DB_DATAOBJECT['CONFIG']['proxy'])) {
+ if (!$rclass && isset($_DB_DATAOBJECT['CONFIG']['proxy'])) {
DB_DataObject::debug("FAILED TO Autoload $database.$table - using proxy.","FACTORY",1);
return $x->$proxyMethod( $d->_database, $table);
}
- if (!$class) {
+ if (!$rclass) {
return DB_DataObject::raiseError(
- "factory could not find class $class from $table",
+ "factory could not find class " .
+ (is_array($class) ? implode(PATH_SEPARATOR, $class) : $class ).
+ "from $table",
DB_DATAOBJECT_ERROR_INVALIDCONFIG);
}
- $ret = new $class;
+ $ret = new $rclass;
if (!empty($database)) {
DB_DataObject::debug("Setting database to $database","FACTORY",1);
$ret->database($database);
/**
* autoload Class
*
- * @param string $class Class
+ * @param string|array $class Class
+ * @param string $table Table trying to load.
* @access private
* @return string classname on Success
*/
- function _autoloadClass($class)
+ function _autoloadClass($class, $table=false)
{
global $_DB_DATAOBJECT;
$class_prefix = empty($_DB_DATAOBJECT['CONFIG']['class_prefix']) ?
'' : $_DB_DATAOBJECT['CONFIG']['class_prefix'];
- $table = substr($class,strlen($class_prefix));
+ $table = $table ? $table : substr($class,strlen($class_prefix));
// only include the file if it exists - and barf badly if it has parse errors :)
if (!empty($_DB_DATAOBJECT['CONFIG']['proxy']) || empty($_DB_DATAOBJECT['CONFIG']['class_location'])) {
return false;
}
+ // support for:
+ // class_location = mydir/ => maps to mydir/Tablename.php
+ // class_location = mydir/myfile_%s.php => maps to mydir/myfile_Tablename
+ // with directory sepr
+ // class_location = mydir/:mydir2/: => tries all of thes locations.
+ $cl = $_DB_DATAOBJECT['CONFIG']['class_location'];
- if (strpos($_DB_DATAOBJECT['CONFIG']['class_location'],'%s') !== false) {
- $file = sprintf($_DB_DATAOBJECT['CONFIG']['class_location'], preg_replace('/[^A-Z0-9]/i','_',ucfirst($table)));
- } else {
- $file = $_DB_DATAOBJECT['CONFIG']['class_location'].'/'.preg_replace('/[^A-Z0-9]/i','_',ucfirst($table)).".php";
+ switch (true) {
+ case (strpos($cl ,'%s') !== false):
+ $file = sprintf($cl , preg_replace('/[^A-Z0-9]/i','_',ucfirst($table)));
+ break;
+
+ case (strpos($cl , PATH_SEPARATOR) !== false):
+ $file = array();
+ foreach(explode(PATH_SEPARATOR, $cl ) as $p) {
+ $file[] = $p .'/'.preg_replace('/[^A-Z0-9]/i','_',ucfirst($table)).".php";
+ }
+ break;
+ default:
+ $file = $cl .'/'.preg_replace('/[^A-Z0-9]/i','_',ucfirst($table)).".php";
+ break;
}
- if (!file_exists($file)) {
+ $cls = is_array($class) ? $class : array($class);
+
+ if (is_array($file) || !file_exists($file)) {
$found = false;
- foreach(explode(PATH_SEPARATOR, ini_get('include_path')) as $p) {
- if (file_exists("$p/$file")) {
- $file = "$p/$file";
- $found = true;
+
+ $file = is_array($file) ? $file : array($file);
+ $search = implode(PATH_SEPARATOR, $file);
+ foreach($file as $f) {
+ foreach(explode(PATH_SEPARATOR, '' . PATH_SEPARATOR . ini_get('include_path')) as $p) {
+ $ff = empty($p) ? $f : "$p/$f";
+
+ if (file_exists($ff)) {
+ $file = $ff;
+ $found = true;
+ break;
+ }
+ }
+ if ($found) {
break;
}
}
if (!$found) {
DB_DataObject::raiseError(
- "autoload:Could not find class {$class} using class_location value",
+ "autoload:Could not find class " . implode(',', $cls) .
+ " using class_location value :" . $search .
+ " using include_path value :" . ini_get('include_path'),
DB_DATAOBJECT_ERROR_INVALIDCONFIG);
return false;
}
include_once $file;
-
- $ce = substr(phpversion(),0,1) > 4 ? class_exists($class,false) : class_exists($class);
-
+
+ $ce = false;
+ foreach($cls as $c) {
+ $ce = substr(phpversion(),0,1) > 4 ? class_exists($c,false) : class_exists($c);
+ if ($ce) {
+ $class = $c;
+ break;
+ }
+ }
if (!$ce) {
DB_DataObject::raiseError(
- "autoload:Could not autoload {$class}",
+ "autoload:Could not autoload " . implode(',', $cls) ,
DB_DATAOBJECT_ERROR_INVALIDCONFIG);
return false;
}
}
-
+ $_DB_DATAOBJECT['LINKS'][$this->_database] = array();
foreach ($schemas as $ini) {
$links =
$_DB_DATAOBJECT['CONFIG']["links_{$this->_database}"] :
str_replace('.ini','.links.ini',$ini);
- if (empty($_DB_DATAOBJECT['LINKS'][$this->_database]) && file_exists($links) && is_file($links)) {
+ if (file_exists($links) && is_file($links)) {
/* not sure why $links = ... here - TODO check if that works */
- $_DB_DATAOBJECT['LINKS'][$this->_database] = parse_ini_file($links, true);
+ $_DB_DATAOBJECT['LINKS'][$this->_database] = array_merge(
+ $_DB_DATAOBJECT['LINKS'][$this->_database],
+ parse_ini_file($links, true)
+ );
+
if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) {
$this->debug("Loaded links.ini file: $links","links",1);
}
}
if ($link) {
if ($obj->get($link, $this->$row)) {
- $obj->free();
return $obj;
}
return false;
}
if ($obj->get($this->$row)) {
- $obj->free();
return $obj;
}
return false;
}
/**
- * IS THIS SUPPORTED/USED ANYMORE????
- *return a list of options for a linked table
- *
+ * getLinkArray
+ * Fetch an array of related objects. This should be used in conjunction with a <dbname>.links.ini file configuration (see the introduction on linking for details on this).
+ * You may also use this with all parameters to specify, the column and related table.
* This is highly dependant on naming columns 'correctly' :)
* using colname = xxxxx_yyyyyy
* xxxxxx = related table; (yyyyy = user defined..)
* stores it in $this->_xxxxx_yyyyy
*
* @access public
- * @return array of results (empty array on failure)
+ * @param string $column - either column or column.xxxxx
+ * @param string $table - name of table to look up value in
+ * @return array - array of results (empty array on failure)
+ *
+ * Example - Getting the related objects
+ *
+ * $person = new DataObjects_Person;
+ * $person->get(12);
+ * $children = $person->getLinkArray('children');
+ *
+ * echo 'There are ', count($children), ' descendant(s):<br />';
+ * foreach ($children as $child) {
+ * echo $child->name, '<br />';
+ * }
+ *
*/
function &getLinkArray($row, $table = null)
{
return $ret;
}
+ /**
+ * unionAdd - adds another dataobject to this, building a unioned query.
+ *
+ * usage:
+ * $doTable1 = DB_DataObject::factory("table1");
+ * $doTable2 = DB_DataObject::factory("table2");
+ *
+ * $doTable1->selectAdd();
+ * $doTable1->selectAdd("col1,col2");
+ * $doTable1->whereAdd("col1 > 100");
+ * $doTable1->orderBy("col1");
+ *
+ * $doTable2->selectAdd();
+ * $doTable2->selectAdd("col1, col2");
+ * $doTable2->whereAdd("col2 = 'v'");
+ *
+ * $doTable1->unionAdd($doTable2);
+ * $doTable1->find();
+ *
+ * Note: this model may be a better way to implement joinAdd?, eg. do the building in find?
+ *
+ *
+ * @param $obj object|false the union object or false to reset
+ * @param optional $is_all string 'ALL' to do all.
+ * @returns $obj object|array the added object, or old list if reset.
+ */
+
+ function unionAdd($obj,$is_all= '')
+ {
+ if ($obj === false) {
+ $ret = $this->_query['unions'];
+ $this->_query['unions'] = array();
+ return $ret;
+ }
+ $this->_query['unions'][] = array($obj, 'UNION ' . $is_all . ' ') ;
+ return $obj;
+ }
+
+
+
/**
* The JOIN condition
*
/* otherwise see if there are any links from this table to the obj. */
//print_r($this->links());
if (($ofield === false) && ($links = $this->links())) {
- foreach ($links as $k => $v) {
- /* link contains {this column} = {linked table}:{linked column} */
- $ar = explode(':', $v);
- // Feature Request #4266 - Allow joins with multiple keys
- if (strpos($k, ',') !== false) {
- $k = explode(',', $k);
- }
- if (strpos($ar[1], ',') !== false) {
- $ar[1] = explode(',', $ar[1]);
+ // this enables for support for arrays of links in ini file.
+ // link contains this_column[] = linked_table:linked_column
+ // or standard way.
+ // link contains this_column = linked_table:linked_column
+ foreach ($links as $k => $linkVar) {
+
+ if (!is_array($linkVar)) {
+ $linkVar = array($linkVar);
}
+ foreach($linkVar as $v) {
- if ($ar[0] == $obj->__table) {
+
+
+ /* link contains {this column} = {linked table}:{linked column} */
+ $ar = explode(':', $v);
+ // Feature Request #4266 - Allow joins with multiple keys
+ if (strpos($k, ',') !== false) {
+ $k = explode(',', $k);
+ }
+ if (strpos($ar[1], ',') !== false) {
+ $ar[1] = explode(',', $ar[1]);
+ }
+
+ if ($ar[0] != $obj->__table) {
+ continue;
+ }
if ($joinCol !== false) {
if ($k == $joinCol) {
+ // got it!?
$tfield = $k;
$ofield = $ar[1];
break;
- } else {
- continue;
- }
- } else {
- $tfield = $k;
- $ofield = $ar[1];
- break;
- }
+ }
+ continue;
+
+ }
+ $tfield = $k;
+ $ofield = $ar[1];
+ break;
+
}
}
}
//print_r($obj->links());
if (!$ofield && ($olinks = $obj->links())) {
- foreach ($olinks as $k => $v) {
- /* link contains {this column} = {linked table}:{linked column} */
- $ar = explode(':', $v);
-
- // Feature Request #4266 - Allow joins with multiple keys
-
- $links_key_array = strpos($k,',');
- if ($links_key_array !== false) {
- $k = explode(',', $k);
- }
-
- $ar_array = strpos($ar[1],',');
- if ($ar_array !== false) {
- $ar[1] = explode(',', $ar[1]);
+ foreach ($olinks as $k => $linkVar) {
+ /* link contains {this column} = array ( {linked table}:{linked column} )*/
+ if (!is_array($linkVar)) {
+ $linkVar = array($linkVar);
}
-
- if ($ar[0] == $this->__table) {
+ foreach($linkVar as $v) {
+
+ /* link contains {this column} = {linked table}:{linked column} */
+ $ar = explode(':', $v);
+
+ // Feature Request #4266 - Allow joins with multiple keys
+ $links_key_array = strpos($k,',');
+ if ($links_key_array !== false) {
+ $k = explode(',', $k);
+ }
+
+ $ar_array = strpos($ar[1],',');
+ if ($ar_array !== false) {
+ $ar[1] = explode(',', $ar[1]);
+ }
+
+ if ($ar[0] != $this->__table) {
+ continue;
+ }
// you have explictly specified the column
// and the col is listed here..
$ofield = $k;
$tfield = $ar[1];
break;
+
}
}
}
DB_DATAOBJECT_ERROR_INVALIDCONFIG);
return false;
}
+
+ $ignore_null = !isset($options['disable_null_strings'])
+ || !is_string($options['disable_null_strings'])
+ || strtolower($options['disable_null_strings']) !== 'full' ;
+
foreach($items as $k => $v) {
- if (!isset($obj->$k)) {
+ if (!isset($obj->$k) && $ignore_null) {
continue;
}
$kSql = ($quoteIdentifiers ? $DB->quoteIdentifier($k) : $k);
+ if (DB_DataObject::_is_null($obj,$k)) {
+ $obj->whereAdd("{$joinAs}.{$kSql} IS NULL");
+ continue;
+ }
if ($v & DB_DATAOBJECT_STR) {
$obj->whereAdd("{$joinAs}.{$kSql} = " . $this->_quote((string) (
if (PEAR::isError($value)) {
$this->raiseError($value->getMessage() ,DB_DATAOBJECT_ERROR_INVALIDARG);
return false;
- }
- if (!isset($options['disable_null_strings']) && strtolower($value) === 'null') {
- $obj->whereAdd("{$joinAs}.{$kSql} IS NULL");
- continue;
- } else {
- $obj->whereAdd("{$joinAs}.{$kSql} = $value");
- continue;
- }
+ }
+ $obj->whereAdd("{$joinAs}.{$kSql} = $value");
+ continue;
}
if (!$k) {
continue; // ignore empty keys!!! what
}
- if (is_object($from) && isset($from->{sprintf($format,$k)})) {
+
+ $chk = is_object($from) &&
+ (version_compare(phpversion(), "5.1.0" , ">=") ?
+ property_exists($from, sprintf($format,$k)) : // php5.1
+ array_key_exists( sprintf($format,$k), get_class_vars($from)) //older
+ );
+ // if from has property ($format($k)
+ if ($chk) {
$kk = (strtolower($k) == 'from') ? '_from' : $k;
if (method_exists($this,'set'.$kk)) {
$ret = $this->{'set'.$kk}($from->{sprintf($format,$k)});
continue;
}
- if (!isset($from[sprintf($format,$k)])) {
+ if (!isset($from[sprintf($format,$k)]) && !DB_DataObject::_is_null($from, sprintf($format,$k))) {
continue;
}
// if not null - and it's not set.......
- if (!isset($this->$key) && ($val & DB_DATAOBJECT_NOTNULL)) {
+ if ($val & DB_DATAOBJECT_NOTNULL && DB_DataObject::_is_null($this, $key)) {
// dont check empty sequence key values..
if (($key == $seq[0]) && ($seq[1] == true)) {
continue;
}
- if (!isset($options['disable_null_strings']) && is_string($this->$key) && (strtolower($this->$key) == 'null')) {
+ if (DB_DataObject::_is_null($this, $key)) {
if ($val & DB_DATAOBJECT_NOTNULL) {
$this->debug("'null' field used for '$key', but it is defined as NOT NULL", 'VALIDATION', 4);
$ret[$key] = false;
//echo "FROM VALUE $col, {$cols[$col]}, $value\n";
switch (true) {
// set to null and column is can be null...
- case (!isset($options['disable_null_strings']) && (strtolower($value) == 'null') && (!($cols[$col] & DB_DATAOBJECT_NOTNULL))):
+ case ((!($cols[$col] & DB_DATAOBJECT_NOTNULL)) && DB_DataObject::_is_null($value, false)):
case (is_object($value) && is_a($value,'DB_DataObject_Cast')):
$this->$col = $value;
return true;
// fail on setting null on a not null field..
- case (!isset($options['disable_null_strings']) && (strtolower($value) == 'null') && ($cols[$col] & DB_DATAOBJECT_NOTNULL)):
+ case (($cols[$col] & DB_DATAOBJECT_NOTNULL) && DB_DataObject::_is_null($value,false)):
+
return false;
case (($cols[$col] & DB_DATAOBJECT_DATE) && ($cols[$col] & DB_DATAOBJECT_TIME)):
if (isset($_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5])) {
$_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5]->num_rows = array();
}
+
+ if (is_array($this->_link_loaded)) {
+ foreach ($this->_link_loaded as $do) {
+ $do->free();
+ }
+ }
+
}
+ /**
+ * Evaluate whether or not a value is set to null, taking the 'disable_null_strings' option into account.
+ * If the value is a string set to "null" and the "disable_null_strings" option is not set to
+ * true, then the value is considered to be null.
+ * If the value is actually a PHP NULL value, and "disable_null_strings" has been set to
+ * the value "full", then it will also be considered null. - this can not differenticate between not set
+ *
+ *
+ * @param object|array $obj_or_ar
+ * @param string|false $prop prperty
+ * @access private
+ * @return bool object
+ */
+ function _is_null($obj_or_ar , $prop)
+ {
+ global $_DB_DATAOBJECT;
+
+
+ $isset = $prop === false ? isset($obj_or_ar) :
+ (is_array($obj_or_ar) ? isset($obj_or_ar[$prop]) : isset($obj_or_ar->$prop));
+
+ $value = $isset ?
+ ($prop === false ? $obj_or_ar :
+ (is_array($obj_or_ar) ? $obj_or_ar[$prop] : $obj_or_ar->$prop))
+ : null;
+
+
+
+ $options = $_DB_DATAOBJECT['CONFIG'];
+
+ $null_strings = !isset($options['disable_null_strings'])
+ || $options['disable_null_strings'] === false;
+
+ $crazy_null = isset($options['disable_null_strings'])
+ && is_string($options['disable_null_strings'])
+ && strtolower($options['disable_null_strings'] === 'full');
+
+ if ( $null_strings && $isset && is_string($value) && (strtolower($value) === 'null') ) {
+ return true;
+ }
+
+ if ( $crazy_null && !$isset ) {
+ return true;
+ }
+
+ return false;
+
+
+ }
/* ---- LEGACY BC METHODS - NOT DOCUMENTED - See Documentation on New Methods. ---*/
}
}
+