PageRenderTime 70ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 1ms

/extlib/DB/DataObject.php

https://github.com/Br3nda/laconica
PHP | 4165 lines | 2406 code | 629 blank | 1130 comment | 579 complexity | b936d3eb5f82cacf4c45f5c830ce42f6 MD5 | raw file
Possible License(s): AGPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /**
  3. * Object Based Database Query Builder and data store
  4. *
  5. * PHP versions 4 and 5
  6. *
  7. * LICENSE: This source file is subject to version 3.0 of the PHP license
  8. * that is available through the world-wide-web at the following URI:
  9. * http://www.php.net/license/3_0.txt. If you did not receive a copy of
  10. * the PHP License and are unable to obtain it through the web, please
  11. * send a note to license@php.net so we can mail you a copy immediately.
  12. *
  13. * @category Database
  14. * @package DB_DataObject
  15. * @author Alan Knowles <alan@akbkhome.com>
  16. * @copyright 1997-2006 The PHP Group
  17. * @license http://www.php.net/license/3_0.txt PHP License 3.0
  18. * @version CVS: $Id: DataObject.php,v 1.439 2008/01/30 02:14:06 alan_k Exp $
  19. * @link http://pear.php.net/package/DB_DataObject
  20. */
  21. /* ===========================================================================
  22. *
  23. * !!!!!!!!!!!!! W A R N I N G !!!!!!!!!!!
  24. *
  25. * THIS MAY SEGFAULT PHP IF YOU ARE USING THE ZEND OPTIMIZER (to fix it,
  26. * just add "define('DB_DATAOBJECT_NO_OVERLOAD',true);" before you include
  27. * this file. reducing the optimization level may also solve the segfault.
  28. * ===========================================================================
  29. */
  30. /**
  31. * The main "DB_DataObject" class is really a base class for your own tables classes
  32. *
  33. * // Set up the class by creating an ini file (refer to the manual for more details
  34. * [DB_DataObject]
  35. * database = mysql:/username:password@host/database
  36. * schema_location = /home/myapplication/database
  37. * class_location = /home/myapplication/DBTables/
  38. * clase_prefix = DBTables_
  39. *
  40. *
  41. * //Start and initialize...................... - dont forget the &
  42. * $config = parse_ini_file('example.ini',true);
  43. * $options = &PEAR::getStaticProperty('DB_DataObject','options');
  44. * $options = $config['DB_DataObject'];
  45. *
  46. * // example of a class (that does not use the 'auto generated tables data')
  47. * class mytable extends DB_DataObject {
  48. * // mandatory - set the table
  49. * var $_database_dsn = "mysql://username:password@localhost/database";
  50. * var $__table = "mytable";
  51. * function table() {
  52. * return array(
  53. * 'id' => 1, // integer or number
  54. * 'name' => 2, // string
  55. * );
  56. * }
  57. * function keys() {
  58. * return array('id');
  59. * }
  60. * }
  61. *
  62. * // use in the application
  63. *
  64. *
  65. * Simple get one row
  66. *
  67. * $instance = new mytable;
  68. * $instance->get("id",12);
  69. * echo $instance->somedata;
  70. *
  71. *
  72. * Get multiple rows
  73. *
  74. * $instance = new mytable;
  75. * $instance->whereAdd("ID > 12");
  76. * $instance->whereAdd("ID < 14");
  77. * $instance->find();
  78. * while ($instance->fetch()) {
  79. * echo $instance->somedata;
  80. * }
  81. /**
  82. * Needed classes
  83. * - we use getStaticProperty from PEAR pretty extensively (cant remove it ATM)
  84. */
  85. require_once 'PEAR.php';
  86. /**
  87. * We are duping fetchmode constants to be compatible with
  88. * both DB and MDB2
  89. */
  90. define('DB_DATAOBJECT_FETCHMODE_ORDERED',1);
  91. define('DB_DATAOBJECT_FETCHMODE_ASSOC',2);
  92. /**
  93. * these are constants for the get_table array
  94. * user to determine what type of escaping is required around the object vars.
  95. */
  96. define('DB_DATAOBJECT_INT', 1); // does not require ''
  97. define('DB_DATAOBJECT_STR', 2); // requires ''
  98. define('DB_DATAOBJECT_DATE', 4); // is date #TODO
  99. define('DB_DATAOBJECT_TIME', 8); // is time #TODO
  100. define('DB_DATAOBJECT_BOOL', 16); // is boolean #TODO
  101. define('DB_DATAOBJECT_TXT', 32); // is long text #TODO
  102. define('DB_DATAOBJECT_BLOB', 64); // is blob type
  103. define('DB_DATAOBJECT_NOTNULL', 128); // not null col.
  104. define('DB_DATAOBJECT_MYSQLTIMESTAMP' , 256); // mysql timestamps (ignored by update/insert)
  105. /*
  106. * Define this before you include DataObjects.php to disable overload - if it segfaults due to Zend optimizer..
  107. */
  108. //define('DB_DATAOBJECT_NO_OVERLOAD',true)
  109. /**
  110. * Theses are the standard error codes, most methods will fail silently - and return false
  111. * to access the error message either use $table->_lastError
  112. * or $last_error = PEAR::getStaticProperty('DB_DataObject','lastError');
  113. * the code is $last_error->code, and the message is $last_error->message (a standard PEAR error)
  114. */
  115. define('DB_DATAOBJECT_ERROR_INVALIDARGS', -1); // wrong args to function
  116. define('DB_DATAOBJECT_ERROR_NODATA', -2); // no data available
  117. define('DB_DATAOBJECT_ERROR_INVALIDCONFIG', -3); // something wrong with the config
  118. define('DB_DATAOBJECT_ERROR_NOCLASS', -4); // no class exists
  119. define('DB_DATAOBJECT_ERROR_INVALID_CALL' ,-7); // overlad getter/setter failure
  120. /**
  121. * Used in methods like delete() and count() to specify that the method should
  122. * build the condition only out of the whereAdd's and not the object parameters.
  123. */
  124. define('DB_DATAOBJECT_WHEREADD_ONLY', true);
  125. /**
  126. *
  127. * storage for connection and result objects,
  128. * it is done this way so that print_r()'ing the is smaller, and
  129. * it reduces the memory size of the object.
  130. * -- future versions may use $this->_connection = & PEAR object..
  131. * although will need speed tests to see how this affects it.
  132. * - includes sub arrays
  133. * - connections = md5 sum mapp to pear db object
  134. * - results = [id] => map to pear db object
  135. * - resultseq = sequence id for results & results field
  136. * - resultfields = [id] => list of fields return from query (for use with toArray())
  137. * - ini = mapping of database to ini file results
  138. * - links = mapping of database to links file
  139. * - lasterror = pear error objects for last error event.
  140. * - config = aliased view of PEAR::getStaticPropery('DB_DataObject','options') * done for performance.
  141. * - array of loaded classes by autoload method - to stop it doing file access request over and over again!
  142. */
  143. $GLOBALS['_DB_DATAOBJECT']['RESULTS'] = array();
  144. $GLOBALS['_DB_DATAOBJECT']['RESULTSEQ'] = 1;
  145. $GLOBALS['_DB_DATAOBJECT']['RESULTFIELDS'] = array();
  146. $GLOBALS['_DB_DATAOBJECT']['CONNECTIONS'] = array();
  147. $GLOBALS['_DB_DATAOBJECT']['INI'] = array();
  148. $GLOBALS['_DB_DATAOBJECT']['LINKS'] = array();
  149. $GLOBALS['_DB_DATAOBJECT']['SEQUENCE'] = array();
  150. $GLOBALS['_DB_DATAOBJECT']['LASTERROR'] = null;
  151. $GLOBALS['_DB_DATAOBJECT']['CONFIG'] = array();
  152. $GLOBALS['_DB_DATAOBJECT']['CACHE'] = array();
  153. $GLOBALS['_DB_DATAOBJECT']['OVERLOADED'] = false;
  154. $GLOBALS['_DB_DATAOBJECT']['QUERYENDTIME'] = 0;
  155. // this will be horrifically slow!!!!
  156. // NOTE: Overload SEGFAULTS ON PHP4 + Zend Optimizer (see define before..)
  157. // these two are BC/FC handlers for call in PHP4/5
  158. if ( substr(phpversion(),0,1) == 5) {
  159. class DB_DataObject_Overload
  160. {
  161. function __call($method,$args)
  162. {
  163. $return = null;
  164. $this->_call($method,$args,$return);
  165. return $return;
  166. }
  167. function __sleep()
  168. {
  169. return array_keys(get_object_vars($this)) ;
  170. }
  171. }
  172. } else {
  173. if (version_compare(phpversion(),'4.3.10','eq') && !defined('DB_DATAOBJECT_NO_OVERLOAD')) {
  174. trigger_error(
  175. "overload does not work with PHP4.3.10, either upgrade
  176. (snaps.php.net) or more recent version
  177. or define DB_DATAOBJECT_NO_OVERLOAD as per the manual.
  178. ",E_USER_ERROR);
  179. }
  180. if (!function_exists('clone')) {
  181. // emulate clone - as per php_compact, slow but really the correct behaviour..
  182. eval('function clone($t) { $r = $t; if (method_exists($r,"__clone")) { $r->__clone(); } return $r; }');
  183. }
  184. eval('
  185. class DB_DataObject_Overload {
  186. function __call($method,$args,&$return) {
  187. return $this->_call($method,$args,$return);
  188. }
  189. }
  190. ');
  191. }
  192. /*
  193. *
  194. * @package DB_DataObject
  195. * @author Alan Knowles <alan@akbkhome.com>
  196. * @since PHP 4.0
  197. */
  198. class DB_DataObject extends DB_DataObject_Overload
  199. {
  200. /**
  201. * The Version - use this to check feature changes
  202. *
  203. * @access private
  204. * @var string
  205. */
  206. var $_DB_DataObject_version = "1.8.8";
  207. /**
  208. * The Database table (used by table extends)
  209. *
  210. * @access private
  211. * @var string
  212. */
  213. var $__table = ''; // database table
  214. /**
  215. * The Number of rows returned from a query
  216. *
  217. * @access public
  218. * @var int
  219. */
  220. var $N = 0; // Number of rows returned from a query
  221. /* ============================================================= */
  222. /* Major Public Methods */
  223. /* (designed to be optionally then called with parent::method()) */
  224. /* ============================================================= */
  225. /**
  226. * Get a result using key, value.
  227. *
  228. * for example
  229. * $object->get("ID",1234);
  230. * Returns Number of rows located (usually 1) for success,
  231. * and puts all the table columns into this classes variables
  232. *
  233. * see the fetch example on how to extend this.
  234. *
  235. * if no value is entered, it is assumed that $key is a value
  236. * and get will then use the first key in keys()
  237. * to obtain the key.
  238. *
  239. * @param string $k column
  240. * @param string $v value
  241. * @access public
  242. * @return int No. of rows
  243. */
  244. function get($k = null, $v = null)
  245. {
  246. global $_DB_DATAOBJECT;
  247. if (empty($_DB_DATAOBJECT['CONFIG'])) {
  248. DB_DataObject::_loadConfig();
  249. }
  250. $keys = array();
  251. if ($v === null) {
  252. $v = $k;
  253. $keys = $this->keys();
  254. if (!$keys) {
  255. $this->raiseError("No Keys available for {$this->__table}", DB_DATAOBJECT_ERROR_INVALIDCONFIG);
  256. return false;
  257. }
  258. $k = $keys[0];
  259. }
  260. if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) {
  261. $this->debug("$k $v " .print_r($keys,true), "GET");
  262. }
  263. if ($v === null) {
  264. $this->raiseError("No Value specified for get", DB_DATAOBJECT_ERROR_INVALIDARGS);
  265. return false;
  266. }
  267. $this->$k = $v;
  268. return $this->find(1);
  269. }
  270. /**
  271. * An autoloading, caching static get method using key, value (based on get)
  272. *
  273. * Usage:
  274. * $object = DB_DataObject::staticGet("DbTable_mytable",12);
  275. * or
  276. * $object = DB_DataObject::staticGet("DbTable_mytable","name","fred");
  277. *
  278. * or write it into your extended class:
  279. * function &staticGet($k,$v=NULL) { return DB_DataObject::staticGet("This_Class",$k,$v); }
  280. *
  281. * @param string $class class name
  282. * @param string $k column (or value if using keys)
  283. * @param string $v value (optional)
  284. * @access public
  285. * @return object
  286. */
  287. function &staticGet($class, $k, $v = null)
  288. {
  289. $lclass = strtolower($class);
  290. global $_DB_DATAOBJECT;
  291. if (empty($_DB_DATAOBJECT['CONFIG'])) {
  292. DB_DataObject::_loadConfig();
  293. }
  294. $key = "$k:$v";
  295. if ($v === null) {
  296. $key = $k;
  297. }
  298. if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) {
  299. DB_DataObject::debug("$class $key","STATIC GET - TRY CACHE");
  300. }
  301. if (!empty($_DB_DATAOBJECT['CACHE'][$lclass][$key])) {
  302. return $_DB_DATAOBJECT['CACHE'][$lclass][$key];
  303. }
  304. if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) {
  305. DB_DataObject::debug("$class $key","STATIC GET - NOT IN CACHE");
  306. }
  307. $obj = DB_DataObject::factory(substr($class,strlen($_DB_DATAOBJECT['CONFIG']['class_prefix'])));
  308. if (PEAR::isError($obj)) {
  309. DB_DataObject::raiseError("could not autoload $class", DB_DATAOBJECT_ERROR_NOCLASS);
  310. $r = false;
  311. return $r;
  312. }
  313. if (!isset($_DB_DATAOBJECT['CACHE'][$lclass])) {
  314. $_DB_DATAOBJECT['CACHE'][$lclass] = array();
  315. }
  316. if (!$obj->get($k,$v)) {
  317. DB_DataObject::raiseError("No Data return from get $k $v", DB_DATAOBJECT_ERROR_NODATA);
  318. $r = false;
  319. return $r;
  320. }
  321. $_DB_DATAOBJECT['CACHE'][$lclass][$key] = $obj;
  322. return $_DB_DATAOBJECT['CACHE'][$lclass][$key];
  323. }
  324. /**
  325. * find results, either normal or crosstable
  326. *
  327. * for example
  328. *
  329. * $object = new mytable();
  330. * $object->ID = 1;
  331. * $object->find();
  332. *
  333. *
  334. * will set $object->N to number of rows, and expects next command to fetch rows
  335. * will return $object->N
  336. *
  337. * @param boolean $n Fetch first result
  338. * @access public
  339. * @return mixed (number of rows returned, or true if numRows fetching is not supported)
  340. */
  341. function find($n = false)
  342. {
  343. global $_DB_DATAOBJECT;
  344. if ($this->_query === false) {
  345. $this->raiseError(
  346. "You cannot do two queries on the same object (copy it before finding)",
  347. DB_DATAOBJECT_ERROR_INVALIDARGS);
  348. return false;
  349. }
  350. if (empty($_DB_DATAOBJECT['CONFIG'])) {
  351. DB_DataObject::_loadConfig();
  352. }
  353. if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) {
  354. $this->debug($n, "find",1);
  355. }
  356. if (!$this->__table) {
  357. // xdebug can backtrace this!
  358. trigger_error("NO \$__table SPECIFIED in class definition",E_USER_ERROR);
  359. }
  360. $this->N = 0;
  361. $query_before = $this->_query;
  362. $this->_build_condition($this->table()) ;
  363. $quoteIdentifiers = !empty($_DB_DATAOBJECT['CONFIG']['quote_identifiers']);
  364. $this->_connect();
  365. $DB = &$_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5];
  366. /* We are checking for method modifyLimitQuery as it is PEAR DB specific */
  367. $sql = 'SELECT ' .
  368. $this->_query['data_select'] . " \n" .
  369. ' FROM ' . ($quoteIdentifiers ? $DB->quoteIdentifier($this->__table) : $this->__table) . " \n" .
  370. $this->_join . " \n" .
  371. $this->_query['condition'] . " \n" .
  372. $this->_query['group_by'] . " \n" .
  373. $this->_query['having'] . " \n" .
  374. $this->_query['order_by'] . " \n";
  375. if ((!isset($_DB_DATAOBJECT['CONFIG']['db_driver'])) ||
  376. ($_DB_DATAOBJECT['CONFIG']['db_driver'] == 'DB')) {
  377. /* PEAR DB specific */
  378. if (isset($this->_query['limit_start']) && strlen($this->_query['limit_start'] . $this->_query['limit_count'])) {
  379. $sql = $DB->modifyLimitQuery($sql,$this->_query['limit_start'], $this->_query['limit_count']);
  380. }
  381. } else {
  382. /* theoretically MDB2! */
  383. if (isset($this->_query['limit_start']) && strlen($this->_query['limit_start'] . $this->_query['limit_count'])) {
  384. $DB->setLimit($this->_query['limit_count'],$this->_query['limit_start']);
  385. }
  386. }
  387. $this->_query($sql);
  388. if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) {
  389. $this->debug("CHECK autofetchd $n", "find", 1);
  390. }
  391. // find(true)
  392. $ret = $this->N;
  393. if (!$ret && !empty($_DB_DATAOBJECT['RESULTS'][$this->_DB_resultid])) {
  394. // clear up memory if nothing found!?
  395. unset($_DB_DATAOBJECT['RESULTS'][$this->_DB_resultid]);
  396. }
  397. if ($n && $this->N > 0 ) {
  398. if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) {
  399. $this->debug("ABOUT TO AUTOFETCH", "find", 1);
  400. }
  401. $fs = $this->fetch();
  402. // if fetch returns false (eg. failed), then the backend doesnt support numRows (eg. ret=true)
  403. // - hence find() also returns false..
  404. $ret = ($ret === true) ? $fs : $ret;
  405. }
  406. if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) {
  407. $this->debug("DONE", "find", 1);
  408. }
  409. $this->_query = $query_before;
  410. return $ret;
  411. }
  412. /**
  413. * fetches next row into this objects var's
  414. *
  415. * returns 1 on success 0 on failure
  416. *
  417. *
  418. *
  419. * Example
  420. * $object = new mytable();
  421. * $object->name = "fred";
  422. * $object->find();
  423. * $store = array();
  424. * while ($object->fetch()) {
  425. * echo $this->ID;
  426. * $store[] = $object; // builds an array of object lines.
  427. * }
  428. *
  429. * to add features to a fetch
  430. * function fetch () {
  431. * $ret = parent::fetch();
  432. * $this->date_formated = date('dmY',$this->date);
  433. * return $ret;
  434. * }
  435. *
  436. * @access public
  437. * @return boolean on success
  438. */
  439. function fetch()
  440. {
  441. global $_DB_DATAOBJECT;
  442. if (empty($_DB_DATAOBJECT['CONFIG'])) {
  443. DB_DataObject::_loadConfig();
  444. }
  445. if (empty($this->N)) {
  446. if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) {
  447. $this->debug("No data returned from FIND (eg. N is 0)","FETCH", 3);
  448. }
  449. return false;
  450. }
  451. if (empty($_DB_DATAOBJECT['RESULTS'][$this->_DB_resultid]) ||
  452. !is_object($result = &$_DB_DATAOBJECT['RESULTS'][$this->_DB_resultid]))
  453. {
  454. if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) {
  455. $this->debug('fetched on object after fetch completed (no results found)');
  456. }
  457. return false;
  458. }
  459. $array = $result->fetchRow(DB_DATAOBJECT_FETCHMODE_ASSOC);
  460. if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) {
  461. $this->debug(serialize($array),"FETCH");
  462. }
  463. // fetched after last row..
  464. if ($array === null) {
  465. if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) {
  466. $t= explode(' ',microtime());
  467. $this->debug("Last Data Fetch'ed after " .
  468. ($t[0]+$t[1]- $_DB_DATAOBJECT['QUERYENDTIME'] ) .
  469. " seconds",
  470. "FETCH", 1);
  471. }
  472. // reduce the memory usage a bit... (but leave the id in, so count() works ok on it)
  473. unset($_DB_DATAOBJECT['RESULTS'][$this->_DB_resultid]);
  474. // we need to keep a copy of resultfields locally so toArray() still works
  475. // however we dont want to keep it in the global cache..
  476. if (!empty($_DB_DATAOBJECT['RESULTFIELDS'][$this->_DB_resultid])) {
  477. $this->_resultFields = $_DB_DATAOBJECT['RESULTFIELDS'][$this->_DB_resultid];
  478. unset($_DB_DATAOBJECT['RESULTFIELDS'][$this->_DB_resultid]);
  479. }
  480. // this is probably end of data!!
  481. //DB_DataObject::raiseError("fetch: no data returned", DB_DATAOBJECT_ERROR_NODATA);
  482. return false;
  483. }
  484. // make sure resultFields is always empty..
  485. $this->_resultFields = false;
  486. if (!isset($_DB_DATAOBJECT['RESULTFIELDS'][$this->_DB_resultid])) {
  487. // note: we dont declare this to keep the print_r size down.
  488. $_DB_DATAOBJECT['RESULTFIELDS'][$this->_DB_resultid]= array_flip(array_keys($array));
  489. }
  490. foreach($array as $k=>$v) {
  491. $kk = str_replace(".", "_", $k);
  492. $kk = str_replace(" ", "_", $kk);
  493. if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) {
  494. $this->debug("$kk = ". $array[$k], "fetchrow LINE", 3);
  495. }
  496. $this->$kk = $array[$k];
  497. }
  498. // set link flag
  499. $this->_link_loaded=false;
  500. if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) {
  501. $this->debug("{$this->__table} DONE", "fetchrow",2);
  502. }
  503. if (($this->_query !== false) && empty($_DB_DATAOBJECT['CONFIG']['keep_query_after_fetch'])) {
  504. $this->_query = false;
  505. }
  506. return true;
  507. }
  508. /**
  509. * Adds a condition to the WHERE statement, defaults to AND
  510. *
  511. * $object->whereAdd(); //reset or cleaer ewhwer
  512. * $object->whereAdd("ID > 20");
  513. * $object->whereAdd("age > 20","OR");
  514. *
  515. * @param string $cond condition
  516. * @param string $logic optional logic "OR" (defaults to "AND")
  517. * @access public
  518. * @return string|PEAR::Error - previous condition or Error when invalid args found
  519. */
  520. function whereAdd($cond = false, $logic = 'AND')
  521. {
  522. // for PHP5.2.3 - there is a bug with setting array properties of an object.
  523. $_query = $this->_query;
  524. if (!isset($this->_query) || ($_query === false)) {
  525. return $this->raiseError(
  526. "You cannot do two queries on the same object (clone it before finding)",
  527. DB_DATAOBJECT_ERROR_INVALIDARGS);
  528. }
  529. if ($cond === false) {
  530. $r = $this->_query['condition'];
  531. $_query['condition'] = '';
  532. $this->_query = $_query;
  533. return preg_replace('/^\s+WHERE\s+/','',$r);
  534. }
  535. // check input...= 0 or ' ' == error!
  536. if (!trim($cond)) {
  537. return $this->raiseError("WhereAdd: No Valid Arguments", DB_DATAOBJECT_ERROR_INVALIDARGS);
  538. }
  539. $r = $_query['condition'];
  540. if ($_query['condition']) {
  541. $_query['condition'] .= " {$logic} ( {$cond} )";
  542. $this->_query = $_query;
  543. return $r;
  544. }
  545. $_query['condition'] = " WHERE ( {$cond} ) ";
  546. $this->_query = $_query;
  547. return $r;
  548. }
  549. /**
  550. * Adds a order by condition
  551. *
  552. * $object->orderBy(); //clears order by
  553. * $object->orderBy("ID");
  554. * $object->orderBy("ID,age");
  555. *
  556. * @param string $order Order
  557. * @access public
  558. * @return none|PEAR::Error - invalid args only
  559. */
  560. function orderBy($order = false)
  561. {
  562. if ($this->_query === false) {
  563. $this->raiseError(
  564. "You cannot do two queries on the same object (copy it before finding)",
  565. DB_DATAOBJECT_ERROR_INVALIDARGS);
  566. return false;
  567. }
  568. if ($order === false) {
  569. $this->_query['order_by'] = '';
  570. return;
  571. }
  572. // check input...= 0 or ' ' == error!
  573. if (!trim($order)) {
  574. return $this->raiseError("orderBy: No Valid Arguments", DB_DATAOBJECT_ERROR_INVALIDARGS);
  575. }
  576. if (!$this->_query['order_by']) {
  577. $this->_query['order_by'] = " ORDER BY {$order} ";
  578. return;
  579. }
  580. $this->_query['order_by'] .= " , {$order}";
  581. }
  582. /**
  583. * Adds a group by condition
  584. *
  585. * $object->groupBy(); //reset the grouping
  586. * $object->groupBy("ID DESC");
  587. * $object->groupBy("ID,age");
  588. *
  589. * @param string $group Grouping
  590. * @access public
  591. * @return none|PEAR::Error - invalid args only
  592. */
  593. function groupBy($group = false)
  594. {
  595. if ($this->_query === false) {
  596. $this->raiseError(
  597. "You cannot do two queries on the same object (copy it before finding)",
  598. DB_DATAOBJECT_ERROR_INVALIDARGS);
  599. return false;
  600. }
  601. if ($group === false) {
  602. $this->_query['group_by'] = '';
  603. return;
  604. }
  605. // check input...= 0 or ' ' == error!
  606. if (!trim($group)) {
  607. return $this->raiseError("groupBy: No Valid Arguments", DB_DATAOBJECT_ERROR_INVALIDARGS);
  608. }
  609. if (!$this->_query['group_by']) {
  610. $this->_query['group_by'] = " GROUP BY {$group} ";
  611. return;
  612. }
  613. $this->_query['group_by'] .= " , {$group}";
  614. }
  615. /**
  616. * Adds a having clause
  617. *
  618. * $object->having(); //reset the grouping
  619. * $object->having("sum(value) > 0 ");
  620. *
  621. * @param string $having condition
  622. * @access public
  623. * @return none|PEAR::Error - invalid args only
  624. */
  625. function having($having = false)
  626. {
  627. if ($this->_query === false) {
  628. $this->raiseError(
  629. "You cannot do two queries on the same object (copy it before finding)",
  630. DB_DATAOBJECT_ERROR_INVALIDARGS);
  631. return false;
  632. }
  633. if ($having === false) {
  634. $this->_query['having'] = '';
  635. return;
  636. }
  637. // check input...= 0 or ' ' == error!
  638. if (!trim($having)) {
  639. return $this->raiseError("Having: No Valid Arguments", DB_DATAOBJECT_ERROR_INVALIDARGS);
  640. }
  641. if (!$this->_query['having']) {
  642. $this->_query['having'] = " HAVING {$having} ";
  643. return;
  644. }
  645. $this->_query['having'] .= " AND {$having}";
  646. }
  647. /**
  648. * Sets the Limit
  649. *
  650. * $boject->limit(); // clear limit
  651. * $object->limit(12);
  652. * $object->limit(12,10);
  653. *
  654. * Note this will emit an error on databases other than mysql/postgress
  655. * as there is no 'clean way' to implement it. - you should consider refering to
  656. * your database manual to decide how you want to implement it.
  657. *
  658. * @param string $a limit start (or number), or blank to reset
  659. * @param string $b number
  660. * @access public
  661. * @return none|PEAR::Error - invalid args only
  662. */
  663. function limit($a = null, $b = null)
  664. {
  665. if ($this->_query === false) {
  666. $this->raiseError(
  667. "You cannot do two queries on the same object (copy it before finding)",
  668. DB_DATAOBJECT_ERROR_INVALIDARGS);
  669. return false;
  670. }
  671. if ($a === null) {
  672. $this->_query['limit_start'] = '';
  673. $this->_query['limit_count'] = '';
  674. return;
  675. }
  676. // check input...= 0 or ' ' == error!
  677. if ((!is_int($a) && ((string)((int)$a) !== (string)$a))
  678. || (($b !== null) && (!is_int($b) && ((string)((int)$b) !== (string)$b)))) {
  679. return $this->raiseError("limit: No Valid Arguments", DB_DATAOBJECT_ERROR_INVALIDARGS);
  680. }
  681. global $_DB_DATAOBJECT;
  682. $this->_connect();
  683. $DB = &$_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5];
  684. $this->_query['limit_start'] = ($b == null) ? 0 : (int)$a;
  685. $this->_query['limit_count'] = ($b == null) ? (int)$a : (int)$b;
  686. }
  687. /**
  688. * Adds a select columns
  689. *
  690. * $object->selectAdd(); // resets select to nothing!
  691. * $object->selectAdd("*"); // default select
  692. * $object->selectAdd("unixtime(DATE) as udate");
  693. * $object->selectAdd("DATE");
  694. *
  695. * to prepend distict:
  696. * $object->selectAdd('distinct ' . $object->selectAdd());
  697. *
  698. * @param string $k
  699. * @access public
  700. * @return mixed null or old string if you reset it.
  701. */
  702. function selectAdd($k = null)
  703. {
  704. if ($this->_query === false) {
  705. $this->raiseError(
  706. "You cannot do two queries on the same object (copy it before finding)",
  707. DB_DATAOBJECT_ERROR_INVALIDARGS);
  708. return false;
  709. }
  710. if ($k === null) {
  711. $old = $this->_query['data_select'];
  712. $this->_query['data_select'] = '';
  713. return $old;
  714. }
  715. // check input...= 0 or ' ' == error!
  716. if (!trim($k)) {
  717. return $this->raiseError("selectAdd: No Valid Arguments", DB_DATAOBJECT_ERROR_INVALIDARGS);
  718. }
  719. if ($this->_query['data_select']) {
  720. $this->_query['data_select'] .= ', ';
  721. }
  722. $this->_query['data_select'] .= " $k ";
  723. }
  724. /**
  725. * Adds multiple Columns or objects to select with formating.
  726. *
  727. * $object->selectAs(null); // adds "table.colnameA as colnameA,table.colnameB as colnameB,......"
  728. * // note with null it will also clear the '*' default select
  729. * $object->selectAs(array('a','b'),'%s_x'); // adds "a as a_x, b as b_x"
  730. * $object->selectAs(array('a','b'),'ddd_%s','ccc'); // adds "ccc.a as ddd_a, ccc.b as ddd_b"
  731. * $object->selectAdd($object,'prefix_%s'); // calls $object->get_table and adds it all as
  732. * objectTableName.colnameA as prefix_colnameA
  733. *
  734. * @param array|object|null the array or object to take column names from.
  735. * @param string format in sprintf format (use %s for the colname)
  736. * @param string table name eg. if you have joinAdd'd or send $from as an array.
  737. * @access public
  738. * @return void
  739. */
  740. function selectAs($from = null,$format = '%s',$tableName=false)
  741. {
  742. global $_DB_DATAOBJECT;
  743. if ($this->_query === false) {
  744. $this->raiseError(
  745. "You cannot do two queries on the same object (copy it before finding)",
  746. DB_DATAOBJECT_ERROR_INVALIDARGS);
  747. return false;
  748. }
  749. if ($from === null) {
  750. // blank the '*'
  751. $this->selectAdd();
  752. $from = $this;
  753. }
  754. $table = $this->__table;
  755. if (is_object($from)) {
  756. $table = $from->__table;
  757. $from = array_keys($from->table());
  758. }
  759. if ($tableName !== false) {
  760. $table = $tableName;
  761. }
  762. $s = '%s';
  763. if (!empty($_DB_DATAOBJECT['CONFIG']['quote_identifiers'])) {
  764. $this->_connect();
  765. $DB = &$_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5];
  766. $s = $DB->quoteIdentifier($s);
  767. $format = $DB->quoteIdentifier($format);
  768. }
  769. foreach ($from as $k) {
  770. $this->selectAdd(sprintf("{$s}.{$s} as {$format}",$table,$k,$k));
  771. }
  772. $this->_query['data_select'] .= "\n";
  773. }
  774. /**
  775. * Insert the current objects variables into the database
  776. *
  777. * Returns the ID of the inserted element (if auto increment or sequences are used.)
  778. *
  779. * for example
  780. *
  781. * Designed to be extended
  782. *
  783. * $object = new mytable();
  784. * $object->name = "fred";
  785. * echo $object->insert();
  786. *
  787. * @access public
  788. * @return mixed false on failure, int when auto increment or sequence used, otherwise true on success
  789. */
  790. function insert()
  791. {
  792. global $_DB_DATAOBJECT;
  793. // we need to write to the connection (For nextid) - so us the real
  794. // one not, a copyied on (as ret-by-ref fails with overload!)
  795. if (!isset($_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5])) {
  796. $this->_connect();
  797. }
  798. $quoteIdentifiers = !empty($_DB_DATAOBJECT['CONFIG']['quote_identifiers']);
  799. $DB = &$_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5];
  800. $items = isset($_DB_DATAOBJECT['INI'][$this->_database][$this->__table]) ?
  801. $_DB_DATAOBJECT['INI'][$this->_database][$this->__table] : $this->table();
  802. if (!$items) {
  803. $this->raiseError("insert:No table definition for {$this->__table}",
  804. DB_DATAOBJECT_ERROR_INVALIDCONFIG);
  805. return false;
  806. }
  807. $options = &$_DB_DATAOBJECT['CONFIG'];
  808. $datasaved = 1;
  809. $leftq = '';
  810. $rightq = '';
  811. $seqKeys = isset($_DB_DATAOBJECT['SEQUENCE'][$this->_database][$this->__table]) ?
  812. $_DB_DATAOBJECT['SEQUENCE'][$this->_database][$this->__table] :
  813. $this->sequenceKey();
  814. $key = isset($seqKeys[0]) ? $seqKeys[0] : false;
  815. $useNative = isset($seqKeys[1]) ? $seqKeys[1] : false;
  816. $seq = isset($seqKeys[2]) ? $seqKeys[2] : false;
  817. $dbtype = $_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5]->dsn["phptype"];
  818. // nativeSequences or Sequences..
  819. // big check for using sequences
  820. if (($key !== false) && !$useNative) {
  821. if (!$seq) {
  822. $keyvalue = $DB->nextId($this->__table);
  823. } else {
  824. $f = $DB->getOption('seqname_format');
  825. $DB->setOption('seqname_format','%s');
  826. $keyvalue = $DB->nextId($seq);
  827. $DB->setOption('seqname_format',$f);
  828. }
  829. if (PEAR::isError($keyvalue)) {
  830. $this->raiseError($keyvalue->toString(), DB_DATAOBJECT_ERROR_INVALIDCONFIG);
  831. return false;
  832. }
  833. $this->$key = $keyvalue;
  834. }
  835. foreach($items as $k => $v) {
  836. // if we are using autoincrement - skip the column...
  837. if ($key && ($k == $key) && $useNative) {
  838. continue;
  839. }
  840. if (!isset($this->$k)) {
  841. continue;
  842. }
  843. // dont insert data into mysql timestamps
  844. // use query() if you really want to do this!!!!
  845. if ($v & DB_DATAOBJECT_MYSQLTIMESTAMP) {
  846. continue;
  847. }
  848. if ($leftq) {
  849. $leftq .= ', ';
  850. $rightq .= ', ';
  851. }
  852. $leftq .= ($quoteIdentifiers ? ($DB->quoteIdentifier($k) . ' ') : "$k ");
  853. if (is_a($this->$k,'DB_DataObject_Cast')) {
  854. $value = $this->$k->toString($v,$DB);
  855. if (PEAR::isError($value)) {
  856. $this->raiseError($value->toString() ,DB_DATAOBJECT_ERROR_INVALIDARGS);
  857. return false;
  858. }
  859. $rightq .= $value;
  860. continue;
  861. }
  862. if (!isset($options['disable_null_strings']) && is_string($this->$k) && (strtolower($this->$k) === 'null') && !($v & DB_DATAOBJECT_NOTNULL)) {
  863. $rightq .= " NULL ";
  864. continue;
  865. }
  866. // DATE is empty... on a col. that can be null..
  867. // note: this may be usefull for time as well..
  868. if (!$this->$k &&
  869. (($v & DB_DATAOBJECT_DATE) || ($v & DB_DATAOBJECT_TIME)) &&
  870. !($v & DB_DATAOBJECT_NOTNULL)) {
  871. $rightq .= " NULL ";
  872. continue;
  873. }
  874. if ($v & DB_DATAOBJECT_STR) {
  875. $rightq .= $this->_quote((string) (
  876. ($v & DB_DATAOBJECT_BOOL) ?
  877. // this is thanks to the braindead idea of postgres to
  878. // use t/f for boolean.
  879. (($this->$k === 'f') ? 0 : (int)(bool) $this->$k) :
  880. $this->$k
  881. )) . " ";
  882. continue;
  883. }
  884. if (is_numeric($this->$k)) {
  885. $rightq .=" {$this->$k} ";
  886. continue;
  887. }
  888. /* flag up string values - only at debug level... !!!??? */
  889. if (is_object($this->$k) || is_array($this->$k)) {
  890. $this->debug('ODD DATA: ' .$k . ' ' . print_r($this->$k,true),'ERROR');
  891. }
  892. // at present we only cast to integers
  893. // - V2 may store additional data about float/int
  894. $rightq .= ' ' . intval($this->$k) . ' ';
  895. }
  896. // not sure why we let empty insert here.. - I guess to generate a blank row..
  897. if ($leftq || $useNative) {
  898. $table = ($quoteIdentifiers ? $DB->quoteIdentifier($this->__table) : $this->__table);
  899. $r = $this->_query("INSERT INTO {$table} ($leftq) VALUES ($rightq) ");
  900. if (PEAR::isError($r)) {
  901. $this->raiseError($r);
  902. return false;
  903. }
  904. if ($r < 1) {
  905. return 0;
  906. }
  907. // now do we have an integer key!
  908. if ($key && $useNative) {
  909. switch ($dbtype) {
  910. case 'mysql':
  911. case 'mysqli':
  912. $method = "{$dbtype}_insert_id";
  913. $this->$key = $method(
  914. $_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5]->connection
  915. );
  916. break;
  917. case 'mssql':
  918. // note this is not really thread safe - you should wrapp it with
  919. // transactions = eg.
  920. // $db->query('BEGIN');
  921. // $db->insert();
  922. // $db->query('COMMIT');
  923. $db_driver = empty($options['db_driver']) ? 'DB' : $options['db_driver'];
  924. $method = ($db_driver == 'DB') ? 'getOne' : 'queryOne';
  925. $mssql_key = $DB->$method("SELECT @@IDENTITY");
  926. if (PEAR::isError($mssql_key)) {
  927. $this->raiseError($mssql_key);
  928. return false;
  929. }
  930. $this->$key = $mssql_key;
  931. break;
  932. case 'pgsql':
  933. if (!$seq) {
  934. $seq = $DB->getSequenceName(strtolower($this->__table));
  935. }
  936. $db_driver = empty($options['db_driver']) ? 'DB' : $options['db_driver'];
  937. $method = ($db_driver == 'DB') ? 'getOne' : 'queryOne';
  938. $pgsql_key = $DB->$method("SELECT currval('".$seq . "')");
  939. if (PEAR::isError($pgsql_key)) {
  940. $this->raiseError($pgsql_key);
  941. return false;
  942. }
  943. $this->$key = $pgsql_key;
  944. break;
  945. case 'ifx':
  946. $this->$key = array_shift (
  947. ifx_fetch_row (
  948. ifx_query(
  949. "select DBINFO('sqlca.sqlerrd1') FROM systables where tabid=1",
  950. $_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5]->connection,
  951. IFX_SCROLL
  952. ),
  953. "FIRST"
  954. )
  955. );
  956. break;
  957. }
  958. }
  959. if (isset($_DB_DATAOBJECT['CACHE'][strtolower(get_class($this))])) {
  960. $this->_clear_cache();
  961. }
  962. if ($key) {
  963. return $this->$key;
  964. }
  965. return true;
  966. }
  967. $this->raiseError("insert: No Data specifed for query", DB_DATAOBJECT_ERROR_NODATA);
  968. return false;
  969. }
  970. /**
  971. * Updates current objects variables into the database
  972. * uses the keys() to decide how to update
  973. * Returns the true on success
  974. *
  975. * for example
  976. *
  977. * $object = DB_DataObject::factory('mytable');
  978. * $object->get("ID",234);
  979. * $object->email="testing@test.com";
  980. * if(!$object->update())
  981. * echo "UPDATE FAILED";
  982. *
  983. * to only update changed items :
  984. * $dataobject->get(132);
  985. * $original = $dataobject; // clone/copy it..
  986. * $dataobject->setFrom($_POST);
  987. * if ($dataobject->validate()) {
  988. * $dataobject->update($original);
  989. * } // otherwise an error...
  990. *
  991. * performing global updates:
  992. * $object = DB_DataObject::factory('mytable');
  993. * $object->status = "dead";
  994. * $object->whereAdd('age > 150');
  995. * $object->update(DB_DATAOBJECT_WHEREADD_ONLY);
  996. *
  997. * @param object dataobject (optional) | DB_DATAOBJECT_WHEREADD_ONLY - used to only update changed items.
  998. * @access public
  999. * @return int rows affected or false on failure
  1000. */
  1001. function update($dataObject = false)
  1002. {
  1003. global $_DB_DATAOBJECT;
  1004. // connect will load the config!
  1005. $this->_connect();
  1006. $original_query = $this->_query;
  1007. $items = isset($_DB_DATAOBJECT['INI'][$this->_database][$this->__table]) ?
  1008. $_DB_DATAOBJECT['INI'][$this->_database][$this->__table] : $this->table();
  1009. // only apply update against sequence key if it is set?????
  1010. $seq = $this->sequenceKey();
  1011. if ($seq[0] !== false) {
  1012. $keys = array($seq[0]);
  1013. if (empty($this->{$keys[0]}) && $dataObject !== true) {
  1014. $this->raiseError("update: trying to perform an update without
  1015. the key set, and argument to update is not
  1016. DB_DATAOBJECT_WHEREADD_ONLY
  1017. ", DB_DATAOBJECT_ERROR_INVALIDARGS);
  1018. return false;
  1019. }
  1020. } else {
  1021. $keys = $this->keys();
  1022. }
  1023. if (!$items) {
  1024. $this->raiseError("update:No table definition for {$this->__table}", DB_DATAOBJECT_ERROR_INVALIDCONFIG);
  1025. return false;
  1026. }
  1027. $datasaved = 1;
  1028. $settings = '';
  1029. $this->_connect();
  1030. $DB = &$_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5];
  1031. $dbtype = $DB->dsn["phptype"];
  1032. $quoteIdentifiers = !empty($_DB_DATAOBJECT['CONFIG']['quote_identifiers']);
  1033. $options = $_DB_DATAOBJECT['CONFIG'];
  1034. foreach($items as $k => $v) {
  1035. if (!isset($this->$k)) {
  1036. continue;
  1037. }
  1038. // ignore stuff thats
  1039. // dont write things that havent changed..
  1040. if (($dataObject !== false) && isset($dataObject->$k) && ($dataObject->$k === $this->$k)) {
  1041. continue;
  1042. }
  1043. // - dont write keys to left.!!!
  1044. if (in_array($k,$keys)) {
  1045. continue;
  1046. }
  1047. // dont insert data into mysql timestamps
  1048. // use query() if you really want to do this!!!!
  1049. if ($v & DB_DATAOBJECT_MYSQLTIMESTAMP) {
  1050. continue;
  1051. }
  1052. if ($settings) {
  1053. $settings .= ', ';
  1054. }
  1055. $kSql = ($quoteIdentifiers ? $DB->quoteIdentifier($k) : $k);
  1056. if (is_a($this->$k,'DB_DataObject_Cast')) {
  1057. $value = $this->$k->toString($v,$DB);
  1058. if (PEAR::isError($value)) {
  1059. $this->raiseError($value->getMessage() ,DB_DATAOBJECT_ERROR_INVALIDARG);
  1060. return false;
  1061. }
  1062. $settings .= "$kSql = $value ";
  1063. continue;
  1064. }
  1065. // special values ... at least null is handled...
  1066. if (!isset($options['disable_null_strings']) && (strtolower($this->$k) === 'null') && !($v & DB_DATAOBJECT_NOTNULL)) {
  1067. $settings .= "$kSql = NULL ";
  1068. continue;
  1069. }
  1070. // DATE is empty... on a col. that can be null..
  1071. // note: this may be usefull for time as well..
  1072. if (!$this->$k &&
  1073. (($v & DB_DATAOBJECT_DATE) || ($v & DB_DATAOBJECT_TIME)) &&
  1074. !($v & DB_DATAOBJECT_NOTNULL)) {
  1075. $settings .= "$kSql = NULL ";
  1076. continue;
  1077. }
  1078. if ($v & DB_DATAOBJECT_STR) {
  1079. $settings .= "$kSql = ". $this->_quote((string) (
  1080. ($v & DB_DATAOBJECT_BOOL) ?
  1081. // this is thanks to the braindead idea of postgres to
  1082. // use t/f for boolean.
  1083. (($this->$k === 'f') ? 0 : (int)(bool) $this->$k) :
  1084. $this->$k
  1085. )) . ' ';
  1086. continue;
  1087. }
  1088. if (is_numeric($this->$k)) {
  1089. $settings .= "$kSql = {$this->$k} ";
  1090. continue;
  1091. }
  1092. // at present we only cast to integers
  1093. // - V2 may store additional data about float/int
  1094. $settings .= "$kSql = " . intval($this->$k) . ' ';
  1095. }
  1096. if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) {
  1097. $this->debug("got keys as ".serialize($keys),3);
  1098. }
  1099. if ($dataObject !== true) {
  1100. $this->_build_condition($items,$keys);
  1101. } else {
  1102. // prevent wiping out of data!
  1103. if (empty($this->_query['condition'])) {
  1104. $this->raiseError("update: global table update not available
  1105. do \$do->whereAdd('1=1'); if you really want to do that.
  1106. ", DB_DATAOBJECT_ERROR_INVALIDARGS);
  1107. return false;
  1108. }
  1109. }
  1110. // echo " $settings, $this->condition ";
  1111. if ($settings && isset($this->_query) && $this->_query['condition']) {
  1112. $table = ($quoteIdentifiers ? $DB->quoteIdentifier($this->__table) : $this->__table);
  1113. $r = $this->_query("UPDATE {$table} SET {$settings} {$this->_query['condition']} ");
  1114. // restore original query conditions.
  1115. $this->_query = $original_query;
  1116. if (PEAR::isError($r)) {
  1117. $this->raiseError($r);
  1118. return false;
  1119. }
  1120. if ($r < 1) {
  1121. return 0;
  1122. }
  1123. $this->_clear_cache();
  1124. return $r;
  1125. }
  1126. // restore original query conditions.
  1127. $this->_query = $original_query;
  1128. // if you manually specified a dataobject, and there where no changes - then it's ok..
  1129. if ($dataObject !== false) {
  1130. return true;
  1131. }
  1132. $this->raiseError(
  1133. "update: No Data specifed for query $settings , {$this->_query['condition']}",
  1134. DB_DATAOBJECT_ERROR_NODATA);
  1135. return false;
  1136. }
  1137. /**
  1138. * Deletes items from table which match current objects variables
  1139. *
  1140. * Returns the true on success
  1141. *
  1142. * for example
  1143. *
  1144. * Designed to be extended
  1145. *
  1146. * $object = new mytable();
  1147. * $object->ID=123;
  1148. * echo $object->delete(); // builds a conditon
  1149. *
  1150. * $object = new mytable();
  1151. * $object->whereAdd('age > 12');
  1152. * $object->limit(1);
  1153. * $object->orderBy('age DESC');
  1154. * $object->delete(true); // dont use object vars, use the conditions, limit and order.
  1155. *
  1156. * @param bool $useWhere (optional) If DB_DATAOBJECT_WHEREADD_ONLY is passed in then
  1157. * we will build the condition only using the whereAdd's. Default is to
  1158. * build the condition only using the object parameters.
  1159. *
  1160. * @access public
  1161. * @return mixed True on success, false on failure, 0 on no data affected
  1162. */
  1163. function delete($useWhere = false)
  1164. {
  1165. global $_DB_DATAOBJECT;
  1166. // connect will load the config!
  1167. $this->_connect();
  1168. $DB = &$_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5];
  1169. $quoteIdentifiers = !empty($_DB_DATAOBJECT['CONFIG']['quote_identifiers']);
  1170. $extra_cond = ' ' . (isset($this->_query['order_by']) ? $this->_query['order_by'] : '');
  1171. if (!$useWhere) {
  1172. $keys = $this->keys();
  1173. $this->_query = array(); // as it's probably unset!
  1174. $this->_query['condition'] = ''; // default behaviour not to use where condition
  1175. $this->_build_condition($this->table(),$keys);
  1176. // if primary keys are not set then use data from rest of object.
  1177. if (!$this->_query['condition']) {
  1178. $this->_build_condition($this->table(),array(),$keys);
  1179. }
  1180. $extra_cond = '';
  1181. }
  1182. // don't delete without a condition
  1183. if (($this->_query !== false) && $this->_query['condition']) {
  1184. $table = ($quoteIdentifiers ? $DB->quoteIdentifier($this->__table) : $this->__table);
  1185. $sql = "DELETE FROM {$table} {$this->_query['condition']}{$extra_cond}";
  1186. // add limit..
  1187. if (isset($this->_query['limit_start']) && strlen($this->_query['limit_start'] . $this->_query['limit_count'])) {
  1188. if (!isset($_DB_DATAOBJECT['CONFIG']['db_driver']) ||
  1189. ($_DB_DATAOBJECT['CONFIG']['db_driver'] == 'DB')) {
  1190. // pear DB
  1191. $sql = $DB->modifyLimitQuery($sql,$this->_query['limit_start'], $this->_query['limit_count']);
  1192. } else {
  1193. // MDB2
  1194. $DB->setLimit( $this->_query['limit_count'],$this->_query['limit_start']);
  1195. }
  1196. }
  1197. $r = $this->_query($sql);
  1198. if (PEAR::isError($r)) {
  1199. $this->raiseError($r);
  1200. return false;
  1201. }
  1202. if ($r < 1) {
  1203. return 0;
  1204. }
  1205. $this->_clear_cache();
  1206. return $r;
  1207. } else {
  1208. $this->raiseError("delete: No condition specifed for query", DB_DATAOBJECT_ERROR_NODATA);
  1209. return false;
  1210. }
  1211. }
  1212. /**
  1213. * fetches a specific row into this object variables
  1214. *
  1215. * Not recommended - better to use fetch()
  1216. *
  1217. * Returens true on success
  1218. *
  1219. * @param int $row…

Large files files are truncated, but you can click here to view the full file