cb.database.php
上传用户:stephen_wu
上传日期:2008-07-05
资源大小:1757k
文件大小:35k
源码类别:

网络

开发平台:

Unix_Linux

  1. <?php
  2. /**
  3. * @version $Id: cb.database.php 344 2007-07-25 02:25:39Z beat $
  4. * @package Community Builder
  5. * @subpackage cb.database.php
  6. * @author Beat and various
  7. * @copyright (C) Beat and various, www.joomlapolis.com
  8. * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html GNU/GPL version 2
  9. */
  10. // no direct access
  11. if ( ! ( defined( '_VALID_CB' ) || defined( '_JEXEC' ) || defined( '_VALID_MOS' ) ) ) { die( 'Direct Access to this location is not allowed.' ); }
  12. /* MAMBO 4.5.2.3 FIXES + EXTENSIONS: */
  13. /**
  14. * Corrects bugs in mambo core database class and implements independant CB database layer ! :
  15. * 1) NULL values from SQL tables are not loaded !
  16. * 2) updateOrder method is buggy and does not allow to specify modified row ids to force them into the right position !
  17. */
  18. class comprofilerDBTable {
  19. var $_tbl;
  20. var $_tbl_key;
  21. /** Database object:
  22.  * @var CBdatabase */
  23. var $_db;
  24. var $_error = '';
  25. /**
  26. * Constructor to set table and key field
  27. * Can be overloaded/supplemented by the child class
  28. *
  29. * @param string      $table name of the table in the db schema relating to child class
  30. * @param string      $key name of the primary key field in the table
  31. * @param CBdatabase  $db  CB Database object
  32. */
  33. function comprofilerDBTable( $table, $key, &$db ) {
  34. $this->_tbl = $table;
  35. $this->_tbl_key = $key;
  36. $this->_db =& $db;
  37. }
  38. /**
  39. * Binds an array/hash from database to this object
  40. *
  41. * @param  int $oid  optional argument, if not specifed then the value of current key is used
  42. * @return mixed     any result from the database operation
  43. */
  44. function load( $oid = null ) {
  45. $k = $this->_tbl_key;
  46. if ($oid !== null) {
  47. $this->$k = $oid;
  48. }
  49. $oid = $this->$k;
  50. if ($oid === null) {
  51. return false;
  52. }
  53. //BB fix : resets default values to all object variables, because NULL SQL fields do not overide existing variables !
  54. //Note: Prior to PHP 4.2.0, Uninitialized class variables will not be reported by get_class_vars().
  55. $class_vars = get_class_vars(get_class($this));
  56. foreach ($class_vars as $name => $value) {
  57. if ( ($name != $k) and ($name != "_db") and ($name != "_tbl") and ($name != "_tbl_key") and ( substr( $name, 0 , 10 ) != "_history__" ) ) {
  58. $this->$name = $value;
  59. }
  60. }
  61. $this->reset();
  62. //end of BB fix.
  63. $query = "SELECT *"
  64. . "n FROM " . $this->_db->NameQuote( $this->_tbl )
  65. . "n WHERE " . $this->_db->NameQuote( $this->_tbl_key ) . " = " . $this->_db->Quote( $oid )
  66. ;
  67. $this->_db->setQuery( $query );
  68. return $this->_db->loadObject( $this );
  69. }
  70. /**
  71. * If table key (id) is NULL : inserts a new row
  72. * otherwise updates existing row in the database table
  73. *
  74. * Can be overridden or overloaded by the child class
  75. *
  76. * @param  boolean  $updateNulls  TRUE: null object variables are also updated, FALSE: not.
  77. * @return boolean                TRUE if successful otherwise FALSE
  78. */
  79. function store( $updateNulls = false ) {
  80. $k = $this->_tbl_key;
  81. if ( $this->$k != 0 ) {
  82. $ok = $this->_db->updateObject( $this->_tbl, $this, $this->_tbl_key, $updateNulls );
  83. } else {
  84. $ok = $this->_db->insertObject( $this->_tbl, $this, $this->_tbl_key );
  85. }
  86. if ( ! $ok ) {
  87. $this->_error = strtolower(get_class($this))."::store failed: " . $this->_db->getErrorMsg();
  88. }
  89. return $ok;
  90. }
  91. /**
  92. * @param string $where This is expected to be a valid (and safe!) SQL expression
  93. */
  94. function move( $dirn, $where = '', $ordering = 'ordering' ) {
  95. $k = $this->_tbl_key;
  96. $sql = "SELECT $this->_tbl_key, $ordering FROM $this->_tbl";
  97. if ($dirn < 0) {
  98. $sql .= "n WHERE $ordering < " . (int) $this->$ordering;
  99. $sql .= ($where ? "n AND $where" : '');
  100. $sql .= "n ORDER BY $ordering DESC";
  101. $sql .= "n LIMIT 1";
  102. } else if ($dirn > 0) {
  103. $sql .= "n WHERE $ordering > " . (int) $this->$ordering;
  104. $sql .= ($where ? "n AND $where" : '');
  105. $sql .= "n ORDER BY $ordering";
  106. $sql .= "n LIMIT 1";
  107. } else {
  108. $sql .= "nWHERE $ordering = " . (int) $this->$ordering;
  109. $sql .= ($where ? "n AND $where" : '');
  110. $sql .= "n ORDER BY $ordering";
  111. $sql .= "n LIMIT 1";
  112. }
  113. $this->_db->setQuery( $sql );
  114. $row = null;
  115. if ($this->_db->loadObject( $row )) {
  116. $query = "UPDATE $this->_tbl"
  117. . "n SET $ordering = " . (int) $row->$ordering
  118. . "n WHERE $this->_tbl_key = " . $this->_db->Quote( $this->$k )
  119. ;
  120. $this->_db->setQuery( $query );
  121. if (!$this->_db->query()) {
  122. $err = $this->_db->getErrorMsg();
  123. die( $err );
  124. }
  125. $query = "UPDATE $this->_tbl"
  126. . "n SET $ordering = " . (int) $this->$ordering
  127. . "n WHERE $this->_tbl_key = " . $this->_db->Quote( $row->$k )
  128. ;
  129. $this->_db->setQuery( $query );
  130. if (!$this->_db->query()) {
  131. $err = $this->_db->getErrorMsg();
  132. die( $err );
  133. }
  134. $this->$ordering = $row->$ordering;
  135. } else {
  136. $query = "UPDATE $this->_tbl"
  137. . "n SET $ordering = " . (int) $this->$ordering
  138. . "n WHERE $this->_tbl_key = " . $this->_db->Quote( $this->$k )
  139. ;
  140. $this->_db->setQuery( $query );
  141. if (!$this->_db->query()) {
  142. $err = $this->_db->getErrorMsg();
  143. die( $err );
  144. }
  145. }
  146. }
  147. /**
  148. * Private utility method for updateOrder() back-called by usort() for comparing orderings
  149. */
  150. function _cmp_obj($a, $b) {
  151. $k = $this->_cbc_cbc_ordering_tmp;
  152. if ( $a->$k == $b->$k ) {
  153.            return 0;
  154.        }
  155.        return ( $a->$k > $b->$k ) ? +1 : -1;
  156.    }
  157. /**
  158. * Compacts the ordering sequence of the selected records
  159. *
  160. * @param  string  $where     Additional where query to limit ordering to a particular subset of records
  161. * @param  array   $cids      of table key ids which should preserve their position (in addition of the negative positions) 
  162. * @param  string  $ordering  name of ordering column in table
  163. * @return boolean TRUE success, FALSE failed, with error of database updated.
  164. */
  165. function updateOrder( $where = '' , $cids = null, $ordering = 'ordering' ) {
  166. $k = $this->_tbl_key;
  167. if (!array_key_exists( $ordering, get_class_vars( strtolower(get_class( $this )) ) )) {
  168. $this->_error = "WARNING: ".strtolower(get_class( $this ))." does not support ordering field" . $ordering . ".";
  169. return false;
  170. }
  171. if ($this->_tbl == "#__content_frontpage") {
  172. $order2 = ", content_id DESC";
  173. } else {
  174. $order2 = "";
  175. }
  176. $this->_db->setQuery( "SELECT $this->_tbl_key, $ordering FROM $this->_tbl"
  177. . ($where ? "nWHERE $where" : '')
  178. . "nORDER BY " . $ordering . $order2
  179. );
  180. if (!($orders = $this->_db->loadObjectList())) {
  181. $this->_error = $this->_db->getErrorMsg();
  182. return false;
  183. }
  184. $n=count( $orders );
  185. $iOfThis = null;
  186. if($cids !== null) {
  187. $cidsOrderings = array(); // determine list of reserved/changed ordering numbers
  188. for ($i=0; $i < $n; $i++) {
  189. if (in_array($orders[$i]->$k, $cids)) {
  190. $cidsOrderings[$orders[$i]->$k] = $orders[$i]->$ordering;
  191. }
  192. }
  193. $j = 1; // change ordering numbers outside of reserved and negative ordering numbers list
  194. for ($i=0; $i < $n; $i++) {
  195. if ($orders[$i]->$k == $this->$k) {
  196. // place 'this' record in the desired location at the end !
  197. $iOfThis = $i;
  198. if ($orders[$i]->$ordering == $j) {
  199. $j++;
  200. }
  201. } else if (in_array($orders[$i]->$k, $cids)) {
  202. if ($orders[$i]->$ordering == $j) {
  203. $j++;
  204. }
  205. } else {
  206. if ($orders[$i]->$ordering >= 0) {
  207. $orders[$i]->$ordering = $j++;
  208. }
  209. while (in_array($orders[$i]->$ordering, $cidsOrderings)) {
  210. $orders[$i]->$ordering = $j++;
  211. }
  212. }
  213. }
  214. } else {
  215. $j = 1;
  216. for ($i=0; $i < $n; $i++) {
  217. if ($orders[$i]->$k == $this->$k) {
  218. // place 'this' record in the desired location at the end !
  219. $iOfThis = $i;
  220. if ($orders[$i]->$ordering == $j) {
  221. $j++;
  222. }
  223. } else if ($orders[$i]->$ordering != $this->$ordering && $this->$ordering > 0 && $orders[$i]->$ordering >= 0) {
  224. $orders[$i]->$ordering = $j++;
  225. } else if ($orders[$i]->$ordering == $this->$ordering && $this->$ordering > 0 && $orders[$i]->$ordering >= 0) {
  226. if ($orders[$i]->$ordering == $j) {
  227. $j++;
  228. }
  229. $orders[$i]->$ordering = $j++;
  230. }
  231. }
  232. }
  233. if ($iOfThis !== null) {
  234. $orders[$iOfThis]->$ordering = min( $this->$ordering, $j );
  235. }
  236. // sort entries by ->$ordering:
  237. $this->_cbc_cbc_ordering_tmp = $ordering;
  238. usort($orders, array( $this, "_cmp_obj" ));
  239. unset( $this->_cbc_cbc_ordering_tmp );
  240. // compact ordering:
  241. $j = 1;
  242. for ($i=0; $i < $n; $i++) {
  243. if ($orders[$i]->$ordering >= 0) {
  244. $orders[$i]->$ordering = $j++;
  245. }
  246. }
  247. for ($i=0; $i < $n; $i++) {
  248. if (($orders[$i]->$ordering >= 0) or ($orders[$i]->$k == $this->$k)) {
  249. $this->_db->setQuery( "UPDATE $this->_tbl"
  250. . "nSET $ordering='".$orders[$i]->$ordering."' WHERE $k='".$orders[$i]->$k."'"
  251. );
  252. $this->_db->query();
  253. }
  254. }
  255. // if we didn't find to reorder the current record, make it last
  256. if (($iOfThis === null) && ($this->$ordering > 0)) {
  257. $order = $n+1;
  258. $this->_db->setQuery( "UPDATE $this->_tbl"
  259. . "nSET $ordering='$order' WHERE $k='".$this->$k."'"
  260. );
  261. $this->_db->query();
  262. }
  263. return true;
  264. }
  265. /**
  266. * Resets public properties
  267. *
  268. * @param  mixed  $value  The value to set all properties to, default is null
  269. */
  270. function reset( $value=null ) {
  271. $keys = $this->getPublicProperties();
  272. foreach ( $keys as $k ) {
  273. $this->$k = $value;
  274. }
  275. }
  276. /**
  277. * Gets the value of the class variable
  278. *
  279. * @param  string  $var  The name of the class variable
  280. * @return mixed         The value of the class var (or null if no var of that name exists)
  281. */
  282. function get( $var ) {
  283. if ( isset( $this->$var ) ) {
  284. return $this->$var;
  285. } else {
  286. return null;
  287. }
  288. }
  289. /**
  290. * Sets the new value of the class variable
  291. *
  292. * @param  string  $var     The name of the class variable
  293. * @param  mixed   $newVal  The new value to assign to the variable
  294. */
  295. function set( $var, $newVal ) {
  296. $this->$var = $newVal;
  297. }
  298. /**
  299.  * Returns an array of public properties
  300.  *
  301.  * @return array
  302.  */
  303. function getPublicProperties() {
  304. static $keys = null;
  305. if ( $keys === null ) {
  306. $keys = array();
  307. foreach ( array_keys( get_class_vars( get_class( $this ) ) ) as $k ) {
  308. if (substr( $k, 0, 1 ) != '_') {
  309. $keys[] = $k;
  310. }
  311. }
  312. }
  313. return $keys;
  314. }
  315. /**
  316. * Generic check for whether dependancies exist for this object in the db schema
  317. * OVERRIDE !
  318. *
  319. * @param  int  $oid  key index
  320. * @return boolean
  321. */
  322. function canDelete( $oid = null ) {
  323. return true;
  324. }
  325. /**
  326. * Deletes this record (no checks)
  327. *
  328. * @param  int      $oid   Key id of row to delete (otherwise it's the one of $this)
  329. * @return boolean         TRUE if OK, FALSE if error
  330. */
  331. function delete( $oid = null ) {
  332. $k = $this->_tbl_key;
  333. if ( $oid ) {
  334. $this->$k = (int) $oid;
  335. }
  336. $query = "DELETE FROM " . $this->_db->NameQuote( $this->_tbl )
  337. . "n WHERE " . $this->_db->NameQuote( $this->_tbl_key )
  338. . " = "
  339. . ( is_int( $this->$k ) ? (int) $this->$k : $this->_db->Quote( $this->$k ) )
  340. ;
  341. $this->_db->setQuery( $query );
  342. if ($this->_db->query()) {
  343. return true;
  344. } else {
  345. $this->_error = $this->_db->getErrorMsg();
  346. return false;
  347. }
  348. }
  349. /**
  350. * Tests if item is checked out
  351. * @param  int      A user id
  352. * @return boolean
  353.  */
  354. function isCheckedOut( $user_id = 0 ) {
  355. if ( $user_id ) {
  356. return ( $this->checked_out && ( $this->checked_out != $user_id ) );
  357. } else {
  358. return $this->checked_out;
  359. }
  360. }
  361. /**
  362.  * Checkout object from database
  363.  *
  364.  * @param  int  $who
  365.  * @param  int  $oid
  366.  * @return unknown
  367.  */
  368. function checkout( $who, $oid = null ) {
  369. if ( ! array_key_exists( 'checked_out', get_class_vars( strtolower( get_class( $this ) ) ) ) ) {
  370. $this->_error = "WARNING: " . strtolower( get_class( $this ) ) . " does not support checkouts.";
  371. return false;
  372. }
  373. $k = $this->_tbl_key;
  374. if ( $oid !== null ) {
  375. $this->$k = $oid;
  376. }
  377. $time = date( "Y-m-d H:i:s" );
  378. $query = "UPDATE " . $this->_db->NameQuote( $this->_tbl )
  379. . "n SET checked_out = " . (int) $who . ", checked_out_time = " . $this->_db->Quote( $time )
  380. . "n WHERE " . $this->_db->NameQuote( $this->_tbl_key ) . " = " . $this->_db->Quote( $this->$k )
  381. ;
  382. $this->_db->setQuery( $query );
  383. return $this->_db->query();
  384. }
  385. function checkin( $oid = null ) {
  386. if ( ! array_key_exists( 'checked_out', get_class_vars( strtolower( get_class( $this ) ) ) ) ) {
  387. $this->_error = "WARNING: " . strtolower( get_class( $this ) ) . " does not support checkins.";
  388. return false;
  389. }
  390. $k = $this->_tbl_key;
  391. if ( $oid !== null ) {
  392. $this->$k = $oid;
  393. }
  394. $query = "UPDATE " . $this->_db->NameQuote( $this->_tbl )
  395. . "n SET checked_out = 0, checked_out_time = " . $this->_db->Quote( $this->_db->getNullDate() )
  396. . "n WHERE " . $this->_db->NameQuote( $this->_tbl_key ) . " = " . $this->_db->Quote( $this->$k )
  397. ;
  398. $this->_db->setQuery( $query );
  399. return $this->_db->query();
  400. }
  401. // EXTENSIONS: EXPERIMENTAL IN CB 1.2, NOT PART OF API:
  402. /**
  403. * Loads an array of typed objects of a given class (same class as current object by default)
  404. * which inherit from this class.
  405. * @access private
  406. *
  407. * @param  string  $class          [optional] class name
  408. * @param  string  $key            [optional] key name in db to use as key of array
  409. * @param  array   $additionalVars [optional] array of string additional key names to add as vars to object
  410. * @return array   of objects of the same class (empty array if no objects)
  411. */
  412. function & loadTrueObjects( $class = null, $key = "", $additionalVars = array() ) {
  413. $objectsArray = array();
  414. $resultsArray = $this->_db->loadAssocList( $key );
  415. if ( is_array($resultsArray) ) {
  416. if ( $class == null ) {
  417. $class = get_class($this);
  418. }
  419. foreach ( $resultsArray as $k => $value ) {
  420. $objectsArray[$k] =& new $class( $this->_db );
  421. // mosBindArrayToObject( $value, $objectsArray[$k], null, null, false );
  422. $objectsArray[$k]->bind( $value, null, null, false );
  423. foreach ( $additionalVars as $index ) {
  424. if ( array_key_exists( $index, $value ) ) {
  425. $objectsArray[$k]->$index = $value[$index];
  426. }
  427. }
  428. }
  429. }
  430. return $objectsArray;
  431. }
  432. /**
  433. * Check values before store method  (override if needed)
  434. * @return boolean  TRUE if the object is safe for saving
  435. */
  436. function check( ) {
  437. return true;
  438. }
  439. /**
  440. * Copy the named array or object content into this object as vars
  441. * only existing vars of object are filled.
  442. * When undefined in array, object variables are kept.
  443. * WARNING: DOES addslashes / escape BY DEFAULT
  444. * Can be overridden or overloaded.
  445. *
  446. * @param  array|object  $array         The input array or object
  447. * @param  string        $ignore        Fields to ignore
  448. * @param  string        $prefix        Prefix for the array keys
  449. * @param  boolean       $checkSlashes  TRUE: if magic_quotes are ON, remove slashes (TRUE BY DEFAULT !)
  450. * @return boolean                      TRUE: ok, FALSE: error on array binding
  451. */
  452. function bind( $array, $ignore='', $prefix = null, $checkSlashes = true  ) {
  453. if ( is_array( $array ) || is_object( $array ) ) {
  454. $ignore = ' ' . $ignore . ' ';
  455. foreach ( get_object_vars( $this ) as $k => $v ) {
  456. if( substr( $k, 0, 1 ) != '_' ) {
  457. if ( strpos( $ignore, ' ' . $k . ' ') === false) {
  458. $ak = $prefix . $k;
  459. if ( is_array( $array ) && isset( $array[$ak] ) ) {
  460. $this->$k = ( ( $checkSlashes && get_magic_quotes_gpc() ) ? cbStripslashes( $array[$ak] ) : $array[$ak] );
  461. } elseif ( isset( $array->$ak ) ) {
  462. $this->$k = ( ( $checkSlashes && get_magic_quotes_gpc() ) ? cbStripslashes( $array->$ak ) : $array->$ak );
  463. }
  464. }
  465. }
  466. }
  467. } else {
  468. $this->_error = get_class( $this ) . "::bind failed: not an array.";
  469. return false;
  470. }
  471. return true;
  472. }
  473. /**
  474.  * @return string Returns the error message
  475.  */
  476. function getError() {
  477. return $this->_error;
  478. }
  479. } // end class comprofilerDBTable
  480. /**
  481. * Provides CMS database independance and
  482. * Corrects bugs and backwards compatibility issues in mambo core database class ! :
  483. * 1) empty lists return empty arrays and not NULL values !
  484. * 2) gives a coherent interface to CB, independant of various CMS flavors
  485. */
  486. class CBdatabase {
  487. /**  Host CMS database class
  488. * @var database */
  489. var $_db;
  490. /* @var string  Holds database prefix replacer (replacing the $prefix (default '#__')). */
  491. var $_table_prefix = '';
  492. /**
  493. * Database object constructor
  494. */
  495. function CBdatabase( &$_CB_database ) {
  496. $this->_db =& $_CB_database;
  497. if ( isset( $_CB_database->_table_prefix ) ) {
  498. $this->_table_prefix = $_CB_database->_table_prefix;
  499. } else {
  500. global $_CB_framework;
  501. $this->_table_prefix = $_CB_framework->getCfg( 'dbprefix' );
  502. }
  503. }
  504. /**
  505. * Sets debug level
  506. * @param int
  507. */
  508. function debug( $level ) {
  509. $this->_db->debug( $level );
  510. }
  511. /**
  512. * @return int The error number for the most recent query
  513. */
  514. function getErrorNum( ) {
  515. return $this->_db->getErrorNum();
  516. }
  517. /**
  518. * @return string The error message for the most recent query
  519. */
  520. function getErrorMsg( ) {
  521. return stripslashes( $this->_db->getErrorMsg() );
  522. }
  523. /**
  524. * @param int      $errorNum  The error number for the most recent query
  525. */
  526. function setErrorNum( $errorNum) {
  527. $this->_db->_errorNum = $errorNum;
  528. }
  529. /**
  530. * @param  string  $errorMsg  The error message for the most recent query
  531. */
  532. function setErrorMsg( $errorMsg ) {
  533. $this->_db->_errorMsg = $errorMsg;
  534. }
  535. /**
  536. * Get a database escaped string
  537. *
  538. * @param  string  $text
  539. * @return string
  540. */
  541. function getEscaped( $text ) {
  542. return $this->_db->getEscaped( $text );
  543. }
  544. /**
  545. * Get a quoted database escaped string
  546. *
  547. * @param  string  $text
  548. * @return string
  549. */
  550. function Quote( $text ) {
  551. return ''' . $this->_db->getEscaped( $text ) . ''';
  552. }
  553. /**
  554. * Quote an identifier name (field, table, etc)
  555. *
  556. * @param  string  $s  The name
  557. * @return string      The quoted name
  558. */
  559. function NameQuote( $s ) {
  560. return '`' . $s . '`';
  561. }
  562. /**
  563. * Returns the zero date/time
  564. *
  565. * @param  string  $dateTime  'datetime', 'date', 'time'
  566. * @return string  Quoted null/zero date string
  567. */
  568. function getNullDate( $dateTime = 'datetime' ) {
  569. if ( $dateTime == 'datetime' ) {
  570. return '0000-00-00 00:00:00';
  571. } elseif ( $dateTime == 'date' ) {
  572. return '0000-00-00';
  573. } else {
  574. return '00:00:00';
  575. }
  576. }
  577. /**
  578. * Sets the SQL query string for later execution.
  579. *
  580. * This function replaces a string identifier $prefix with the
  581. * string held is the _table_prefix class variable.
  582. *
  583. * @param string $sql     The SQL query
  584. * @param int    $offset  The offset to start selection
  585. * @param int    $limit   The number of results to return
  586. * @param string $prefix  The common table prefix search for replacement string
  587. */
  588. function setQuery( $sql, $offset = 0, $limit = 0, $prefix='#__' ) {
  589. if ( in_array( checkJversion( 'product' ), array( 'Mambo', 'Elxis', 'MiaCMS' ) ) ) {
  590. if ( $offset || $limit ) {
  591. $sql .= " LIMIT ";
  592. if ( $offset ) {
  593. $sql .= ( (int) $offset ) . ', ';
  594. }
  595. $sql .= ( (int) $limit );
  596. }
  597. $this->_db->setQuery( $sql, $prefix );
  598. } else {
  599. $this->_db->setQuery( $sql, $offset, $limit, $prefix );
  600. }
  601. }
  602. /**
  603.  * Replace $prefix with $this->_table_prefix
  604.  *
  605.  * @param  string  $sql      SQL query
  606.  * @param  string  $prefix   Common table prefix
  607.  */
  608. function replacePrefix( $sql, $prefix='#__' ) {
  609. return $this->_db->replacePrefix( $sql, $prefix );
  610. }
  611. /**
  612. * @return string The current value of the internal SQL vairable
  613. */
  614. function getQuery( ) {
  615. return $this->_db->getQuery();
  616. }
  617. /**
  618. * Execute the query
  619. * @param  string  the query (optional, it will use the setQuery one otherwise)
  620. * @return mixed A database resource if successful, FALSE if not.
  621. */
  622. function query( $sql = null ) {
  623. if ( $sql ) {
  624. $this->setQuery( $sql );
  625. }
  626. return $this->_db->query();
  627. }
  628. /**
  629.  * Executes a series of SQL orders, optionally as a transaction
  630.  *
  631.  * @param  boolean $abort_on_error      Aborts on error (true by default)
  632.  * @param  boolean $p_transaction_safe  Encloses all in a single transaction (false by default)
  633.  * @return boolean true: success, false: error(s)
  634.  */
  635. function query_batch( $abort_on_error = true, $p_transaction_safe = false) {
  636. return $this->_db->query_batch( $abort_on_error, $p_transaction_safe );
  637. }
  638. /** for compatibility only: */
  639. function queryBatch( $abort_on_error = true, $p_transaction_safe = false) {
  640. return $this->query_batch( $abort_on_error, $p_transaction_safe );
  641. }
  642. /**
  643. * @return int The number of affected rows in the previous operation
  644. */
  645. function getAffectedRows( ) {
  646. if ( is_callable( array( $this->_db, 'getAffectedRows' ) ) ) {
  647. $affected = $this->_db->getAffectedRows();
  648. } elseif ( get_resource_type( $this->_db->_resource ) == 'mysql link' ) {
  649. $affected = mysql_affected_rows( $this->_db->_resource );
  650. } else {
  651. $affected = mysqli_affected_rows( $this->_db->_resource );
  652. }
  653. return $affected;
  654. }
  655. /**
  656. * Returns the number of rows returned from the most recent query.
  657. * @return int
  658. */
  659. function getNumRows( $cur = null ) {
  660. return $this->_db->getNumRows( $cur );
  661. }
  662. /**
  663.  * Explain of SQL
  664.  * 
  665.  * @return string
  666.  */
  667. function explain( ) {
  668. return $this->_db->explain();
  669. }
  670. /**
  671. * This method loads the first field of the first row returned by the query.
  672. *
  673. * @return The value returned in the query or null if the query failed.
  674. */
  675. function loadResult( ) {
  676. return $this->_db->loadResult();
  677. }
  678. function & _nullToArray( &$resultArray ) {
  679. if ( $resultArray === null ) { // mambo strangeness
  680. $resultArray = array();
  681. }
  682. return $resultArray;
  683. }
  684. /**
  685. * Load an array of single field results into an array
  686. */
  687. function loadResultArray( $numinarray = 0 ) {
  688. $resultArray = $this->_db->loadResultArray( $numinarray );
  689. return $this->_nullToArray( $resultArray );
  690. }
  691. /**
  692. * Fetch a result row as an associative array
  693. *
  694. * @return array
  695. */
  696. function loadAssoc( ) {
  697. if ( is_callable( array( $this->_db, 'loadAssoc' ) ) ) {
  698. return $this->_db->loadAssoc( );
  699. } else {
  700. // new independant efficient implementation:
  701. if ( ! ( $cur = $this->query() ) ) {
  702. $result = null;
  703. } else {
  704. $result = $this->m_fetch_assoc( $cur );
  705. if ( ! $result ) {
  706. $result = null;
  707. }
  708. $this->m_free_result( $cur );
  709. }
  710. return $result;
  711. }
  712. }
  713. /**
  714. * Load a assoc list of database rows
  715. * @param string The field name of a primary key
  716. * @return array If <var>key</var> is empty as sequential list of returned records.
  717. */
  718. function loadAssocList( $key = null ) {
  719. if ( ( $key == '' ) || ( checkJversion() >= 0 ) ) {
  720. $resultArray = $this->_db->loadAssocList( $key );
  721. return $this->_nullToArray( $resultArray );
  722. } else {
  723. // mambo 4.5.2 - 4.6.2 has a bug in key:
  724. if ( ! ( $cur = $this->query() ) ) {
  725. return null;
  726. }
  727. $array = array();
  728. while ( is_array( $row = $this->m_fetch_assoc( $cur ) ) ) {
  729. if ( $key ) {
  730. $array[$row[$key]] = $row; //  $row->key is not an object, but an array
  731. } else {
  732. $array[] = $row;
  733. }
  734. }
  735. $this->m_free_result( $cur );
  736. return $array;
  737. }
  738. }
  739. /**
  740. * This global function loads the first row of a query into an object
  741. *
  742. * If an object is passed to this function, the returned row is bound to the existing elements of <var>object</var>.
  743. * If <var>object</var> has a value of null, then all of the returned query fields returned in the object.
  744. * @param  stdClass  $object
  745. * @return boolean            Success
  746. */
  747. function loadObject( &$object ) {
  748. // return $this->_db->loadObject( $object );
  749. $cur = $this->query();
  750. if ( ! $cur ) {
  751. return false;
  752. }
  753. if ( $object != null ) {
  754. $array = $this->m_fetch_assoc( $cur );
  755. $this->m_free_result( $cur );
  756. if ( is_array( $array ) ) {
  757. foreach ( get_object_vars( $object ) as $k => $v) {
  758. if( substr( $k, 0, 1 ) != '_' ) {
  759. if ( isset( $array[$k] ) ) {
  760. $object->$k = $array[$k];
  761. }
  762. }
  763. }
  764. return true;
  765. }
  766. } else {
  767. $object = $this->m_fetch_object( $cur );
  768. $this->m_free_result( $cur );
  769. if ( is_object( $object ) ) {
  770. return true;
  771. } else {
  772. $object = null;
  773. }
  774. }
  775. return false;
  776. }
  777. /**
  778. * Load a list of database objects
  779. * If $key is not empty then the returned array is indexed by the value
  780. * the database key.  Returns NULL if the query fails.
  781. *
  782. * @param  string       $key          The field name of a primary key
  783. * @param  string|null  $className    The name of the class to instantiate, set the properties of and return. If not specified, a stdClass object is returned
  784. * @param  array|null   $ctor_params  An optional array of parameters to pass to the constructor for class_name objects
  785. * @return array                      If $key is empty as sequential list of returned records.
  786. */
  787. function loadObjectList( $key = null, $className = null, $ctor_params = null ) {
  788. if ( ! ( $cur = $this->query() ) ) {
  789. return null;
  790. }
  791. $array = array();
  792. while ( is_object( $row = $this->m_fetch_object( $cur, $className, $ctor_params ) ) ) {
  793. if ( $key ) {
  794. $array[$row->$key] = $row;
  795. } else {
  796. $array[] = $row;
  797. }
  798. }
  799. $this->m_free_result( $cur );
  800. return $array;
  801. }
  802. /**
  803. * @return The first row of the query.
  804. */
  805. function loadRow( ) {
  806. return $this->_db->loadRow();
  807. }
  808. /**
  809. * Load a list of database rows (numeric column indexing)
  810. * @param string The field name of a primary key
  811. * @return array If <var>key</var> is empty as sequential list of returned records.
  812. * If <var>key</var> is not empty then the returned array is indexed by the value
  813. * the database key.  Returns <var>null</var> if the query fails.
  814. */
  815. function loadRowList( $key = null ) {
  816. $resultArray = $this->_db->loadRowList( $key );
  817. return $this->_nullToArray( $resultArray );
  818. }
  819. /**
  820. * Insert an object into database
  821. *
  822. * @param string   $table This is expected to be a valid (and safe!) table name
  823. * @param stdClass $object
  824. * @param string   $keyName
  825. * @param boolean  $verbose
  826. * @param boolean  TRUE if insert succeeded, FALSE when error
  827. */
  828. function insertObject( $table, &$object, $keyName = NULL, $verbose=false ) {
  829. return $this->_db->insertObject( $table, $object, $keyName, $verbose );
  830. }
  831. /**
  832. * Updates an object into a database
  833. *
  834. * @param  string   $table        This is expected to be a valid (and safe!) table name
  835. * @param  stdClass $object
  836. * @param  string   $keyName
  837. * @param  boolean  $updateNulls
  838. * @return mixed    A database resource if successful, FALSE if not.
  839. */
  840. function updateObject( $table, &$object, $keyName, $updateNulls=true ) {
  841. // return $this->_db->updateObject( $table, $object, $keyName, $updateNulls );
  842. $fmtsql = "UPDATE $table SET %s WHERE %s";
  843. $tmp = array();
  844. foreach (get_object_vars( $object ) as $k => $v) {
  845. if( is_array($v) or is_object($v) or $k[0] == '_' ) { // internal or NA field
  846. continue;
  847. }
  848. if( $k == $keyName ) { // PK not to be updated
  849. $where = $keyName . '=' . $this->Quote( $v );
  850. continue;
  851. }
  852. if ($v === NULL && !$updateNulls) {
  853. continue;
  854. }
  855. if( $v === NULL ) {
  856. $val = "NULL"; // this case was missing in Mambo
  857. } elseif( $v == '' ) {
  858. $val = "''";
  859. } else {
  860. $val = $this->Quote( $v );
  861. }
  862. $tmp[] = $this->NameQuote( $k ) . '=' . $val;
  863. }
  864. $this->setQuery( sprintf( $fmtsql, implode( ",", $tmp ) , $where ) );
  865. return $this->query();
  866. }
  867. /**
  868. * Returns the formatted standard error message of SQL
  869. * @param  boolean $showSQL  If TRUE, displays the last SQL statement sent to the database
  870. * @return string  A standised error message
  871. */
  872. function stderr( $showSQL = false ) {
  873. return $this->_db->stderr( $showSQL );
  874. }
  875. /**
  876. * Returns the insert_id() from Mysql
  877. *
  878. * @return int
  879. */
  880. function insertid( ) {
  881. return $this->_db->insertid();
  882. }
  883. /**
  884. * Returns the version of MySQL
  885. *
  886. * @return string
  887. */
  888. function getVersion( ) {
  889. return $this->_db->getVersion();
  890. }
  891. /**
  892. * Returns a list of tables, with the prefix changed if needed.
  893. *
  894. * @param  string  $tableName  Name of table (SQL LIKE pattern), null: all tables
  895. * @param  string  $prefix     Prefix to change back
  896. * @return array               A list of all the tables in the database
  897. */
  898. function getTableList( $tableName = null, $prefix = '#__' ) {
  899. $this->setQuery( 'SHOW TABLES' . ( $tableName ? ' LIKE ' . $this->Quote( $tableName ) : '' ) );
  900. $tables = $this->loadResultArray();
  901. if ( $prefix ) {
  902. foreach ( $tables as $k => $n ) {
  903. $tables[$k] = preg_replace( '/^(' . $this->_table_prefix . ')/', $prefix, $n );
  904. }
  905. }
  906. return $tables;
  907. }
  908. /**
  909. * Returns the status of all tables, with the prefix changed if needed.
  910. *
  911. * @param  string  $tableName  Name of table (SQL LIKE pattern), null: all tables
  912. * @param  string  $prefix     Prefix to change back
  913. * @return array               A list of all the table statuses in the database
  914. */
  915. function getTableStatus( $tableName = null, $prefix = '#__' ) {
  916. $this->setQuery( 'SHOW TABLE STATUS' . ( $tableName ? ' LIKE ' . $this->Quote( $this->replacePrefix( $tableName, $prefix ) ) : '' ) );
  917. $tables = $this->loadObjectList();
  918. if ( $prefix ) {
  919. foreach ( $tables as $k => $n ) {
  920. $tables[$k]->Name = preg_replace( '/^(' . $this->_table_prefix . ')/', $prefix, $n->Name );
  921. }
  922. }
  923. return $tables;
  924. }
  925. /**
  926.  * @param array A list of valid (and safe!) table names
  927.  * @return array A list the create SQL for the tables
  928.  */
  929. function getTableCreate( $tables ) {
  930. $createQueries = array();
  931. foreach ( $tables as $tableName ) {
  932. $this->setQuery( 'SHOW CREATE table ' . $this->NameQuote( $tableName ) );
  933. $this->query();
  934. $createQueries[$tableName] = $this->loadResultArray( 1 );
  935. }
  936. return $createQueries;
  937. }
  938. /**
  939.  * Gets the fields as in DESCRIBE of MySQL
  940.  *
  941.  * @param  array|string  $tables    A (list of) table names
  942.  * @param  boolean       $onlyType  TRUE: only type without size, FALSE: full DESCRIBE MySql
  943.  * @return array                    EITHER: array( tablename => array( fieldname => fieldtype ) ) or of => fieldDESCRIBE
  944.  */
  945. function getTableFields( $tables, $onlyType = true ) {
  946. $result = array();
  947. $tables = (array) $tables;
  948. foreach ( $tables as $tbl ) {
  949. $this->setQuery( 'SHOW COLUMNS FROM ' . $this->NameQuote( $tbl ) );
  950. $result[$tbl] = $this->loadObjectList( 'Field' );
  951. if ( is_array( $result[$tbl] ) && $onlyType ) {
  952. foreach ( $result[$tbl] as $k => $fld ) {
  953. $result[$tbl][$k] = preg_replace( '/[(0-9)]/','', $fld->Type );
  954. }
  955. }
  956. }
  957. return $result;
  958. }
  959. /**
  960.  * Gets the index of the table
  961.  *
  962.  * @param  array|string  $tables    A (list of) table names
  963.  * @return array                    As
  964.  */
  965. function getTableIndex( $table, $prefix = '#__' ) {
  966. $this->setQuery( 'SHOW INDEX FROM ' . $this->NameQuote( $table ) );
  967. $indexes = $this->loadObjectList();
  968. if ( $prefix ) {
  969. foreach ( $indexes as $k => $n ) {
  970. $indexes[$k]->Table = preg_replace( '/^(' . $this->_table_prefix . ')/', $prefix, $n->Table );
  971. }
  972. }
  973. return $indexes;
  974. }
  975. /**
  976. * Fudge method for ADOdb compatibility
  977. */
  978. function GenID( $foo1=null, $foo2=null ) {
  979. return '0';
  980. }
  981. /**
  982.  * Checks if database's collation is case-INsensitive
  983.  * WARNING: individual table's fields might have a different collation
  984.  *
  985.  * @return boolean  TRUE if case INsensitive
  986.  */
  987. function isDbCollationCaseInsensitive( ) {
  988. static $result = null;
  989. if ( $result === null ) {
  990. $query = "SELECT IF('a'='A', 1, 0);";
  991. $this->setQuery( $query );
  992. $result = $this->loadResult();
  993. }
  994. return ( $result == 1 );
  995. }
  996. /**
  997.  * mysql/mysqli_fetch_assoc function
  998.  *
  999.  * @param  mysql_result  $cur  The result resource that is being evaluated. This result comes from a call to mysql_query().
  1000.  * @return array|boolean|null         False OR null if no more
  1001.  */
  1002. function m_fetch_assoc( &$cur ) {
  1003. if ( is_object( $cur ) && get_class( $cur ) == 'mysqli_result' ) {
  1004. return mysqli_fetch_assoc( $cur );
  1005. } else {
  1006. return mysql_fetch_assoc( $cur );
  1007. }
  1008. }
  1009. /**
  1010.  * mysql / mysqli fetch_object
  1011.  *
  1012.  * @param  mysql_result  $cur          The result resource that is being evaluated. This result comes from a call to mysql_query()
  1013.  * @param  string|null   $className    The name of the class to instantiate, set the properties of and return. If not specified, a stdClass object is returned
  1014.  * @param  array|null    $ctor_params  An optional array of parameters to pass to the constructor for class_name objects
  1015.  * @return object|boolean|null         False OR null if no more
  1016.  */
  1017. function m_fetch_object( &$cur, $className = null, $ctor_params = null ) {
  1018. if ( is_object( $cur ) && ( get_class( $cur ) == 'mysqli_result' ) ) {
  1019. // MySqli is PHP 5 only:
  1020. if ( $className === null ) {
  1021. return mysqli_fetch_object( $cur );
  1022. } else {
  1023. return mysqli_fetch_object( $cur, $className, $ctor_params );
  1024. }
  1025. } else {
  1026. // MySql:
  1027. if ( $className === null ) {
  1028. return mysql_fetch_object( $cur );
  1029. } elseif ( version_compare( phpversion(), '5.0.0', '>=' ) ) {
  1030. return mysql_fetch_object( $cur, $className, $ctor_params );
  1031. } else {
  1032. $objArr = $this->m_fetch_assoc( $cur );
  1033. if ( ! is_array( $objArr ) ) {
  1034. return $objArr;
  1035. }
  1036. $obj = $this->_m_new_class( $className, $ctor_params );
  1037. foreach ( $objArr as $k => $v) {
  1038. $obj->$k = $v;
  1039. }
  1040. return $obj;
  1041. }
  1042. }
  1043. }
  1044. /**
  1045.  * Emulation of a Reflection class for PHP 4 only
  1046.  *
  1047.  * In PHP 5.1.3+ that could be made as:
  1048.  * $reflectionObj = new ReflectionClass($className);
  1049.  * $obj = $reflectionObj->newInstanceArgs($cp); 
  1050.  * But as mysql_fetch_object handles it already in PHP 5.0, it's not needed.
  1051.  *
  1052.  * @param  string  $className
  1053.  * @param  array   $cp
  1054.  * @return object
  1055.  */
  1056. function _m_new_class( $className, &$cp ) {
  1057. if ( $cp === null ) {
  1058. return new $className();
  1059. } elseif ( is_array( $cp ) ) {
  1060. switch ( count( $cp ) ) {
  1061. case 0:
  1062. return new $className();
  1063. break;
  1064. case 1:
  1065. return new $className( $cp[0] );
  1066. break;
  1067. case 2:
  1068. return new $className( $cp[0], $cp[1] );
  1069. break;
  1070. case 3:
  1071. return new $className( $cp[0], $cp[1], $cp[2] );
  1072. break;
  1073. case 4:
  1074. return new $className( $cp[0], $cp[1], $cp[2], $cp[3] );
  1075. break;
  1076. case 5:
  1077. return new $className( $cp[0], $cp[1], $cp[2], $cp[3], $cp[4] );
  1078. break;
  1079. case 6:
  1080. return new $className( $cp[0], $cp[1], $cp[2], $cp[3], $cp[4], $cp[5] );
  1081. break;
  1082. case 7:
  1083. return new $className( $cp[0], $cp[1], $cp[2], $cp[3], $cp[4], $cp[5], $cp[6] );
  1084. break;
  1085. case 8:
  1086. return new $className( $cp[0], $cp[1], $cp[2], $cp[3], $cp[4], $cp[5], $cp[6], $cp[7] );
  1087. break;
  1088. case 9:
  1089. return new $className( $cp[0], $cp[1], $cp[2], $cp[3], $cp[4], $cp[5], $cp[6], $cp[7], $cp[8] );
  1090. break;
  1091. case 10:
  1092. return new $className( $cp[0], $cp[1], $cp[2], $cp[3], $cp[4], $cp[5], $cp[6], $cp[7], $cp[8], $cp[9] );
  1093. break;
  1094. default:
  1095. trigger_error( 'CBdatabase::m_fetch_object: constructor parameters count to large', E_USER_ERROR );
  1096. exit;
  1097. break;
  1098. }
  1099. }
  1100. }
  1101. function m_free_result( &$cur ) {
  1102. if ( is_object( $cur ) && get_class( $cur ) == 'mysqli_result' ) {
  1103. mysqli_free_result( $cur );
  1104. } else {
  1105. mysql_free_result( $cur );
  1106. }
  1107. }
  1108. } // class CBdatabase
  1109. // ----- NO MORE CLASSES OR FUNCTIONS PASSED THIS POINT -----
  1110. // Post class declaration initialisations
  1111. // some version of PHP don't allow the instantiation of classes
  1112. // before they are defined
  1113. global $_CB_database, $_CB_framework;
  1114. /** @global CBdatabase $_CB_Database */
  1115. $_CB_database = new CBdatabase( $_CB_framework->_cmsDatabase );
  1116. ?>