| [ Index ] |
|
Code source de Joomla 1.0.13 |
1 <?php 2 /** 3 * @version $Id: database.mysqli.php 973 2005-11-11 02:18:08Z eddieajau $ 4 * @package Joomla 5 * @subpackage Database 6 * @copyright Copyright (C) 2005 Open Source Matters. All rights reserved. 7 * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL, see LICENSE.php 8 * Joomla! is free software. This version may have been modified pursuant 9 * to the GNU General Public License, and as distributed it includes or 10 * is derivative of works licensed under the GNU General Public License or 11 * other free or open source software licenses. 12 * See COPYRIGHT.php for copyright notices and details. 13 */ 14 15 // no direct access 16 defined( '_VALID_MOS' ) or die( 'Restricted access' ); 17 18 /** 19 * Database connector class 20 * @subpackage Database 21 * @package Joomla 22 */ 23 class database { 24 /** @var string Internal variable to hold the query sql */ 25 var $_sql = ''; 26 /** @var int Internal variable to hold the database error number */ 27 var $_errorNum = 0; 28 /** @var string Internal variable to hold the database error message */ 29 var $_errorMsg = ''; 30 /** @var string Internal variable to hold the prefix used on all database tables */ 31 var $_table_prefix = ''; 32 /** @var Internal variable to hold the connector resource */ 33 var $_resource = ''; 34 /** @var Internal variable to hold the last query cursor */ 35 var $_cursor = null; 36 /** @var boolean Debug option */ 37 var $_debug = 0; 38 /** @var int The limit for the query */ 39 var $_limit = 0; 40 /** @var int The for offset for the limit */ 41 var $_offset = 0; 42 /** @var int A counter for the number of queries performed by the object instance */ 43 var $_ticker = 0; 44 /** @var array A log of queries */ 45 var $_log = null; 46 /** @var string The null/zero date string */ 47 var $_nullDate = '0000-00-00 00:00:00'; 48 /** @var string Quote for named objects */ 49 var $_nameQuote = '`'; 50 51 /** 52 * Database object constructor 53 * @param string Database host 54 * @param string Database user name 55 * @param string Database user password 56 * @param string Database name 57 * @param string Common prefix for all tables 58 * @param boolean If true and there is an error, go offline 59 */ 60 function database( $host='localhost', $user, $pass, $db='', $table_prefix='', $goOffline=true ) { 61 // perform a number of fatality checks, then die gracefully 62 if (!function_exists( 'mysqli_connect' )) { 63 $mosSystemError = 1; 64 if ($goOffline) { 65 $basePath = dirname( __FILE__ ); 66 include $basePath . '/../configuration.php'; 67 include $basePath . '/../offline.php'; 68 exit(); 69 } 70 } 71 if (!($this->_resource = @mysqli_connect( $host, $user, $pass ))) { 72 $mosSystemError = 2; 73 if ($goOffline) { 74 $basePath = dirname( __FILE__ ); 75 include $basePath . '/../configuration.php'; 76 include $basePath . '/../offline.php'; 77 exit(); 78 } 79 } 80 if ($db != '' && !mysqli_select_db($this->_resource, $db)) { 81 $mosSystemError = 3; 82 if ($goOffline) { 83 $basePath = dirname( __FILE__ ); 84 include $basePath . '/../configuration.php'; 85 include $basePath . '/../offline.php'; 86 exit(); 87 } 88 } 89 $this->_table_prefix = $table_prefix; 90 $this->_ticker = 0; 91 $this->_log = array(); 92 93 $this->setSQLMode(); 94 } 95 /** 96 * @param int 97 */ 98 function debug( $level ) { 99 $this->_debug = intval( $level ); 100 } 101 /** 102 * @return int The error number for the most recent query 103 */ 104 function getErrorNum() { 105 return $this->_errorNum; 106 } 107 /** 108 * @return string The error message for the most recent query 109 */ 110 function getErrorMsg() { 111 return str_replace( array( "\n", "'" ), array( '\n', "\'" ), $this->_errorMsg ); 112 } 113 /** 114 * Get a database escaped string 115 * @return string 116 */ 117 function getEscaped( $text ) { 118 return mysqli_real_escape_string( $this->_resource, $text ); 119 } 120 /** 121 * Get a quoted database escaped string 122 * @return string 123 */ 124 function Quote( $text ) { 125 return '\'' . $this->getEscaped( $text ) . '\''; 126 } 127 /** 128 * Quote an identifier name (field, table, etc) 129 * @param string The name 130 * @return string The quoted name 131 */ 132 function NameQuote( $s ) { 133 $q = $this->_nameQuote; 134 if (strlen( $q ) == 1) { 135 return $q . $s . $q; 136 } else { 137 return $q{0} . $s . $q{1}; 138 } 139 } 140 /** 141 * Quote based on field type 142 * @param mixed The value of the field 143 * @param string The field type 144 * @return string The correct field format 145 * @private 146 */ 147 function _quoteField( $value, $type ) { 148 switch ($type) { 149 case 'text': 150 case 'mediumtext': 151 case 'varchar': 152 $result = $this->Quote( $value ); 153 break; 154 155 case 'date': 156 case 'datetime': 157 if (empty( $value )) { 158 $value = $this->_nullDate; 159 } 160 $result = $this->Quote( $value ); 161 break; 162 163 case 'float': 164 case 'double': 165 $result = (double) $value; 166 break; 167 168 case 'int': 169 case 'tinyint': 170 case 'tinyint unsigned': 171 case 'int unsigned': 172 case 'unsigned': 173 default: 174 $result = (int) $value; 175 break; 176 } 177 return $result; 178 } 179 /** 180 * @return string The database prefix 181 */ 182 function getPrefix() { 183 return $this->_table_prefix; 184 } 185 /** 186 * @return string Quoted null/zero date string 187 */ 188 function getNullDate() { 189 return $this->_nullDate; 190 } 191 /** 192 * Sets the SQL query string for later execution. 193 * 194 * This function replaces a string identifier <var>$prefix</var> with the 195 * string held is the <var>_table_prefix</var> class variable. 196 * 197 * @param string The SQL query 198 * @param string The offset to start selection 199 * @param string The number of results to return 200 * @param string The common table prefix 201 */ 202 function setQuery( $sql, $offset = 0, $limit = 0, $prefix='#__' ) { 203 $this->_sql = $this->replacePrefix( $sql, $prefix ); 204 $this->_limit = intval( $limit ); 205 $this->_offset = intval( $offset ); 206 } 207 208 /** 209 * This function replaces a string identifier <var>$prefix</var> with the 210 * string held is the <var>_table_prefix</var> class variable. 211 * 212 * @param string The SQL query 213 * @param string The common table prefix 214 * @author thede, David McKinnis 215 */ 216 function replacePrefix( $sql, $prefix='#__' ) { 217 $sql = trim( $sql ); 218 219 $escaped = false; 220 $quoteChar = ''; 221 222 $n = strlen( $sql ); 223 224 $startPos = 0; 225 $literal = ''; 226 while ($startPos < $n) { 227 $ip = strpos($sql, $prefix, $startPos); 228 if ($ip === false) { 229 break; 230 } 231 232 $j = strpos( $sql, "'", $startPos ); 233 $k = strpos( $sql, '"', $startPos ); 234 if (($k !== FALSE) && (($k < $j) || ($j === FALSE))) { 235 $quoteChar = '"'; 236 $j = $k; 237 } else { 238 $quoteChar = "'"; 239 } 240 241 if ($j === false) { 242 $j = $n; 243 } 244 245 $literal .= str_replace( $prefix, $this->_table_prefix, substr( $sql, $startPos, $j - $startPos ) ); 246 $startPos = $j; 247 248 $j = $startPos + 1; 249 250 if ($j >= $n) { 251 break; 252 } 253 254 // quote comes first, find end of quote 255 while (TRUE) { 256 $k = strpos( $sql, $quoteChar, $j ); 257 $escaped = false; 258 if ($k === false) { 259 break; 260 } 261 $l = $k - 1; 262 while ($l >= 0 && $sql{$l} == '\\') { 263 $l--; 264 $escaped = !$escaped; 265 } 266 if ($escaped) { 267 $j = $k+1; 268 continue; 269 } 270 break; 271 } 272 if ($k === FALSE) { 273 // error in the query - no end quote; ignore it 274 break; 275 } 276 $literal .= substr( $sql, $startPos, $k - $startPos + 1 ); 277 $startPos = $k+1; 278 } 279 if ($startPos < $n) { 280 $literal .= substr( $sql, $startPos, $n - $startPos ); 281 } 282 return $literal; 283 } 284 /** 285 * @return string The current value of the internal SQL vairable 286 */ 287 function getQuery() { 288 return "<pre>" . htmlspecialchars( $this->_sql ) . "</pre>"; 289 } 290 /** 291 * Execute the query 292 * @return mixed A database resource if successful, FALSE if not. 293 */ 294 function query() { 295 global $mosConfig_debug; 296 if ($this->_limit > 0 || $this->_offset > 0) { 297 $this->_sql .= "\nLIMIT $this->_offset, $this->_limit"; 298 } 299 if ($this->_debug) { 300 $this->_ticker++; 301 $this->_log[] = $this->_sql; 302 } 303 $this->_errorNum = 0; 304 $this->_errorMsg = ''; 305 $this->_cursor = mysqli_query( $this->_resource, $this->_sql ); 306 if (!$this->_cursor) { 307 $this->_errorNum = mysqli_errno( $this->_resource ); 308 $this->_errorMsg = mysqli_error( $this->_resource ) . " SQL=$this->_sql"; 309 if ($this->_debug) { 310 trigger_error( mysqli_error( $this->_resource ), E_USER_NOTICE ); 311 //echo "<pre>" . $this->_sql . "</pre>\n"; 312 if (function_exists( 'debug_backtrace' )) { 313 foreach( debug_backtrace() as $back) { 314 if (@$back['file']) { 315 echo '<br />'.$back['file'].':'.$back['line']; 316 } 317 } 318 } 319 } 320 return false; 321 } 322 return $this->_cursor; 323 } 324 325 /** 326 * @return int The number of affected rows in the previous operation 327 */ 328 function getAffectedRows() { 329 return mysqli_affected_rows( $this->_resource ); 330 } 331 332 function query_batch( $abort_on_error=true, $p_transaction_safe = false) { 333 $this->_errorNum = 0; 334 $this->_errorMsg = ''; 335 if ($p_transaction_safe) { 336 $si = mysqli_get_server_info(); 337 preg_match_all( "/(\d+)\.(\d+)\.(\d+)/i", $si, $m ); 338 if ($m[1] >= 4) { 339 $this->_sql = 'START TRANSACTION;' . $this->_sql . '; COMMIT;'; 340 } else if ($m[2] >= 23 && $m[3] >= 19) { 341 $this->_sql = 'BEGIN WORK;' . $this->_sql . '; COMMIT;'; 342 } else if ($m[2] >= 23 && $m[3] >= 17) { 343 $this->_sql = 'BEGIN;' . $this->_sql . '; COMMIT;'; 344 } 345 } 346 $query_split = preg_split ("/[;]+/", $this->_sql); 347 $error = 0; 348 foreach ($query_split as $command_line) { 349 $command_line = trim( $command_line ); 350 if ($command_line != '') { 351 $this->_cursor = mysqli_query( $command_line, $this->_resource ); 352 if (!$this->_cursor) { 353 $error = 1; 354 $this->_errorNum .= mysqli_errno( $this->_resource ) . ' '; 355 $this->_errorMsg .= mysqli_error( $this->_resource )." SQL=$command_line <br />"; 356 if ($abort_on_error) { 357 return $this->_cursor; 358 } 359 } 360 } 361 } 362 return $error ? false : true; 363 } 364 365 /** 366 * Diagnostic function 367 */ 368 function explain() { 369 $temp = $this->_sql; 370 $this->_sql = "EXPLAIN $this->_sql"; 371 $this->query(); 372 373 if (!($cur = $this->query())) { 374 return null; 375 } 376 $first = true; 377 378 $buf = "<table cellspacing=\"1\" cellpadding=\"2\" border=\"0\" bgcolor=\"#000000\" align=\"center\">"; 379 $buf .= $this->getQuery(); 380 while ($row = mysqli_fetch_assoc( $cur )) { 381 if ($first) { 382 $buf .= "<tr>"; 383 foreach ($row as $k=>$v) { 384 $buf .= "<th bgcolor=\"#ffffff\">$k</th>"; 385 } 386 $buf .= "</tr>"; 387 $first = false; 388 } 389 $buf .= "<tr>"; 390 foreach ($row as $k=>$v) { 391 $buf .= "<td bgcolor=\"#ffffff\">$v</td>"; 392 } 393 $buf .= "</tr>"; 394 } 395 $buf .= "</table><br /> "; 396 mysqli_free_result( $cur ); 397 398 $this->_sql = $temp; 399 400 return "<div style=\"background-color:#FFFFCC\" align=\"left\">$buf</div>"; 401 } 402 /** 403 * @return int The number of rows returned from the most recent query. 404 */ 405 function getNumRows( $cur=null ) { 406 return mysqli_num_rows( $cur ? $cur : $this->_cursor ); 407 } 408 409 /** 410 * This method loads the first field of the first row returned by the query. 411 * 412 * @return The value returned in the query or null if the query failed. 413 */ 414 function loadResult() { 415 if (!($cur = $this->query())) { 416 return null; 417 } 418 $ret = null; 419 if ($row = mysqli_fetch_row( $cur )) { 420 $ret = $row[0]; 421 } 422 mysqli_free_result( $cur ); 423 return $ret; 424 } 425 /** 426 * Load an array of single field results into an array 427 */ 428 function loadResultArray($numinarray = 0) { 429 if (!($cur = $this->query())) { 430 return null; 431 } 432 $array = array(); 433 while ($row = mysqli_fetch_row( $cur )) { 434 $array[] = $row[$numinarray]; 435 } 436 mysqli_free_result( $cur ); 437 return $array; 438 } 439 /** 440 * Load a assoc list of database rows 441 * @param string The field name of a primary key 442 * @return array If <var>key</var> is empty as sequential list of returned records. 443 */ 444 function loadAssocList( $key='' ) { 445 if (!($cur = $this->query())) { 446 return null; 447 } 448 $array = array(); 449 while ($row = mysqli_fetch_assoc( $cur )) { 450 if ($key) { 451 $array[$row[$key]] = $row; 452 } else { 453 $array[] = $row; 454 } 455 } 456 mysqli_free_result( $cur ); 457 return $array; 458 } 459 /** 460 * This global function loads the first row of a query into an object 461 * 462 * If an object is passed to this function, the returned row is bound to the existing elements of <var>object</var>. 463 * If <var>object</var> has a value of null, then all of the returned query fields returned in the object. 464 * @param string The SQL query 465 * @param object The address of variable 466 */ 467 function loadObject( &$object ) { 468 if ($object != null) { 469 if (!($cur = $this->query())) { 470 return false; 471 } 472 if ($array = mysqli_fetch_assoc( $cur )) { 473 mysqli_free_result( $cur ); 474 mosBindArrayToObject( $array, $object, null, null, false ); 475 return true; 476 } else { 477 return false; 478 } 479 } else { 480 if ($cur = $this->query()) { 481 if ($object = mysqli_fetch_object( $cur )) { 482 mysqli_free_result( $cur ); 483 return true; 484 } else { 485 $object = null; 486 return false; 487 } 488 } else { 489 return false; 490 } 491 } 492 } 493 /** 494 * Load a list of database objects 495 * @param string The field name of a primary key 496 * @return array If <var>key</var> is empty as sequential list of returned records. 497 * If <var>key</var> is not empty then the returned array is indexed by the value 498 * the database key. Returns <var>null</var> if the query fails. 499 */ 500 function loadObjectList( $key='' ) { 501 if (!($cur = $this->query())) { 502 return null; 503 } 504 $array = array(); 505 while ($row = mysqli_fetch_object( $cur )) { 506 if ($key) { 507 $array[$row->$key] = $row; 508 } else { 509 $array[] = $row; 510 } 511 } 512 mysqli_free_result( $cur ); 513 return $array; 514 } 515 /** 516 * @return The first row of the query. 517 */ 518 function loadRow() { 519 if (!($cur = $this->query())) { 520 return null; 521 } 522 $ret = null; 523 if ($row = mysqli_fetch_row( $cur )) { 524 $ret = $row; 525 } 526 mysqli_free_result( $cur ); 527 return $ret; 528 } 529 /** 530 * Load a list of database rows (numeric column indexing) 531 * @param string The field name of a primary key 532 * @return array If <var>key</var> is empty as sequential list of returned records. 533 * If <var>key</var> is not empty then the returned array is indexed by the value 534 * the database key. Returns <var>null</var> if the query fails. 535 */ 536 function loadRowList( $key='' ) { 537 if (!($cur = $this->query())) { 538 return null; 539 } 540 $array = array(); 541 while ($row = mysqli_fetch_row( $cur )) { 542 if ($key) { 543 $array[$row[$key]] = $row; 544 } else { 545 $array[] = $row; 546 } 547 } 548 mysqli_free_result( $cur ); 549 return $array; 550 } 551 /** 552 * Document::db_insertObject() 553 * 554 * { Description } 555 * 556 * @param string $table This is expected to be a valid (and safe!) table name 557 * @param [type] $keyName 558 * @param [type] $verbose 559 */ 560 function insertObject( $table, &$object, $keyName = NULL, $verbose=false ) { 561 $fmtsql = "INSERT INTO $table ( %s ) VALUES ( %s ) "; 562 $fields = array(); 563 foreach (get_object_vars( $object ) as $k => $v) { 564 if (is_array($v) or is_object($v) or $v === NULL) { 565 continue; 566 } 567 if ($k[0] == '_') { // internal field 568 continue; 569 } 570 $fields[] = $this->NameQuote( $k ); 571 $values[] = $this->_quoteField( $v, $object->_getFieldType( $k ) ); 572 } 573 $this->setQuery( sprintf( $fmtsql, implode( ",", $fields ) , implode( ",", $values ) ) ); 574 ($verbose) && print "$sql<br />\n"; 575 if (!$this->query()) { 576 return false; 577 } 578 $id = mysqli_insert_id( $this->_resource ); 579 ($verbose) && print "id=[$id]<br />\n"; 580 if ($keyName && $id) { 581 $object->$keyName = $id; 582 } 583 return true; 584 } 585 586 /** 587 * Document::db_updateObject() 588 * 589 * { Description } 590 * 591 * @param string $table This is expected to be a valid (and safe!) table name 592 * @param [type] $updateNulls 593 */ 594 function updateObject( $table, &$object, $keyName, $updateNulls=true ) { 595 $fmtsql = "UPDATE $table SET %s WHERE %s"; 596 $tmp = array(); 597 foreach (get_object_vars( $object ) as $k => $v) { 598 if( is_array($v) or is_object($v) or $k[0] == '_' ) { // internal or NA field 599 continue; 600 } 601 if ($k == $keyName) { // PK not to be updated 602 $where = $k . '=' . $this->_quoteField( $v, $object->_getFieldType( $k ) ); 603 continue; 604 } 605 if ($v === NULL && !$updateNulls) { 606 continue; 607 } 608 //if( $v == '' ) { 609 // $val = "''"; 610 //} else { 611 $val = $this->_quoteField( $v, $object->_getFieldType( $k ) ); 612 //} 613 $tmp[] = $this->NameQuote( $k ) . '=' . $val; 614 } 615 $this->setQuery( sprintf( $fmtsql, implode( ",", $tmp ) , $where ) ); 616 return $this->query(); 617 } 618 619 /** 620 * @param boolean If TRUE, displays the last SQL statement sent to the database 621 * @return string A standised error message 622 */ 623 function stderr( $showSQL = false ) { 624 return "DB function failed with error number $this->_errorNum" 625 ."<br /><font color=\"red\">$this->_errorMsg</font>" 626 .($showSQL ? "<br />SQL = <pre>$this->_sql</pre>" : ''); 627 } 628 629 function insertid() { 630 return mysqli_insert_id( $this->_resource ); 631 } 632 633 function getVersion() { 634 return mysqli_get_server_info( $this->_resource ); 635 } 636 637 /** 638 * @return array A list of all the tables in the database 639 */ 640 function getTableList() { 641 $this->setQuery( 'SHOW TABLES' ); 642 return $this->loadResultArray(); 643 } 644 /** 645 * @param array A list of valid (and safe!) table names 646 * @return array A list the create SQL for the tables 647 */ 648 function getTableCreate( $tables ) { 649 $result = array(); 650 651 foreach ($tables as $tblval) { 652 $this->setQuery( 'SHOW CREATE table ' . $this->getEscaped( $tblval ) ); 653 $rows = $this->loadRowList(); 654 foreach ($rows as $row) { 655 $result[$tblval] = $row[1]; 656 } 657 } 658 659 return $result; 660 } 661 /** 662 * @param array A list of valid (and safe!) table names 663 * @return array An array of fields by table 664 */ 665 function getTableFields( $tables ) { 666 $result = array(); 667 668 foreach ($tables as $tblval) { 669 $this->setQuery( 'SHOW FIELDS FROM ' . $tblval ); 670 $fields = $this->loadObjectList(); 671 foreach ($fields as $field) { 672 $result[$tblval][$field->Field] = preg_replace("/[(0-9)]/",'', $field->Type ); 673 } 674 } 675 676 return $result; 677 } 678 679 /** 680 * Fudge method for ADOdb compatibility 681 */ 682 function GenID( $foo1=null, $foo2=null ) { 683 return '0'; 684 } 685 } 686 687 /** 688 * mosDBTable Abstract Class. 689 * @abstract 690 * @package Joomla 691 * @subpackage Database 692 * 693 * Parent classes to all database derived objects. Customisation will generally 694 * not involve tampering with this object. 695 * @package Joomla 696 * @author Andrew Eddie <eddieajau@users.sourceforge.net 697 */ 698 class mosDBTable { 699 /** @var string Name of the table in the db schema relating to child class */ 700 var $_tbl = ''; 701 /** @var string Name of the primary key field in the table */ 702 var $_tbl_key = ''; 703 /** @var string Error message */ 704 var $_error = ''; 705 /** @var mosDatabase Database connector */ 706 var $_db = null; 707 /** @var array schema */ 708 var $_schema = null; 709 710 /** 711 * Object constructor to set table and key field 712 * 713 * Can be overloaded/supplemented by the child class 714 * @param string $table name of the table in the db schema relating to child class 715 * @param string $key name of the primary key field in the table 716 */ 717 function mosDBTable( $table, $key, &$db ) { 718 $this->_tbl = $table; 719 $this->_tbl_key = $key; 720 $this->_db =& $db; 721 } 722 723 /** 724 * Returns an array of public properties 725 * @return array 726 */ 727 function getPublicProperties() { 728 static $cache = null; 729 if (is_null( $cache )) { 730 $cache = array(); 731 foreach (get_class_vars( get_class( $this ) ) as $key=>$val) { 732 if (substr( $key, 0, 1 ) != '_') { 733 $cache[] = $key; 734 } 735 } 736 } 737 return $cache; 738 } 739 740 /** 741 * Sets the named schema array 742 * @private 743 * @since 1.0.6 744 */ 745 function _setSchema( $array=null ) { 746 if (is_array( $array )) { 747 $this->_schema = $array; 748 } else { 749 $tableFields = $this->_db->getTableFields( array( $this->_tbl ) ); 750 $this->_schema = $tableFields[$this->_tbl]; 751 } 752 } 753 754 /** 755 * Gets the schema array 756 * @private 757 * @since 1.0.6 758 */ 759 function _getSchema() { 760 if ($this->_schema == null) { 761 $this->_setSchema(); 762 } 763 return $this->_schema; 764 } 765 766 /** 767 * Returns the [database] type of the field 768 * @param string The name of the field 769 * @return string The field type 770 * @private 771 * @since 1.0.6 772 */ 773 function _getFieldType( $name ) { 774 $schema = $this->_getSchema(); 775 776 if (isset( $schema[$name] )) { 777 $result = $schema[$name]; 778 } else { 779 $result = 'text'; 780 } 781 return $result; 782 } 783 784 /** 785 * Filters public properties 786 * @access protected 787 * @param array List of fields to ignore 788 */ 789 function filter( $ignoreList=null ) { 790 $ignore = is_array( $ignoreList ); 791 792 $iFilter = new InputFilter(); 793 foreach ($this->getPublicProperties() as $k) { 794 if ($ignore && in_array( $k, $ignoreList ) ) { 795 continue; 796 } 797 $this->$k = $iFilter->process( $this->$k ); 798 } 799 } 800 /** 801 * @return string Returns the error message 802 */ 803 function getError() { 804 return $this->_error; 805 } 806 /** 807 * Gets the value of the class variable 808 * @param string The name of the class variable 809 * @return mixed The value of the class var (or null if no var of that name exists) 810 */ 811 function get( $_property ) { 812 if(isset( $this->$_property )) { 813 return $this->$_property; 814 } else { 815 return null; 816 } 817 } 818 819 /** 820 * Set the value of the class variable 821 * @param string The name of the class variable 822 * @param mixed The value to assign to the variable 823 */ 824 function set( $_property, $_value ) { 825 $this->$_property = $_value; 826 } 827 828 /** 829 * Resets public properties 830 * @param mixed The value to set all properties to, default is null 831 */ 832 function reset( $value=null ) { 833 $keys = $this->getPublicProperties(); 834 foreach ($keys as $k) { 835 $this->$k = $value; 836 } 837 } 838 /** 839 * binds a named array/hash to this object 840 * 841 * can be overloaded/supplemented by the child class 842 * @param array $hash named array 843 * @return null|string null is operation was satisfactory, otherwise returns an error 844 */ 845 function bind( $array, $ignore='' ) { 846 if (!is_array( $array )) { 847 $this->_error = strtolower(get_class( $this ))."::bind failed."; 848 return false; 849 } else { 850 return mosBindArrayToObject( $array, $this, $ignore ); 851 } 852 } 853 854 /** 855 * binds an array/hash to this object 856 * @param int $oid optional argument, if not specifed then the value of current key is used 857 * @return any result from the database operation 858 */ 859 function load( $oid=null ) { 860 $k = $this->_tbl_key; 861 862 if ($oid !== null) { 863 $this->$k = $oid; 864 } 865 866 $oid = $this->$k; 867 868 if ($oid === null) { 869 return false; 870 } 871 //Note: Prior to PHP 4.2.0, Uninitialized class variables will not be reported by get_class_vars(). 872 $class_vars = get_class_vars(get_class($this)); 873 foreach ($class_vars as $name => $value) { 874 if (($name != $k) and ($name != "_db") and ($name != "_tbl") and ($name != "_tbl_key")) { 875 $this->$name = $value; 876 } 877 } 878 879 $this->reset(); 880 881 $query = "SELECT *" 882 . "\n FROM $this->_tbl" 883 . "\n WHERE $this->_tbl_key = " . $this->_db->Quote( $oid ) 884 ; 885 $this->_db->setQuery( $query ); 886 887 return $this->_db->loadObject( $this ); 888 } 889 890 /** 891 * generic check method 892 * 893 * can be overloaded/supplemented by the child class 894 * @return boolean True if the object is ok 895 */ 896 function check() { 897 return true; 898 } 899 900 /** 901 * Inserts a new row if id is zero or updates an existing row in the database table 902 * 903 * Can be overloaded/supplemented by the child class 904 * @param boolean If false, null object variables are not updated 905 * @return null|string null if successful otherwise returns and error message 906 */ 907 function store( $updateNulls=false ) { 908 $k = $this->_tbl_key; 909 910 if ($this->$k) { 911 $ret = $this->_db->updateObject( $this->_tbl, $this, $this->_tbl_key, $updateNulls ); 912 } else { 913 $ret = $this->_db->insertObject( $this->_tbl, $this, $this->_tbl_key ); 914 } 915 if( !$ret ) { 916 $this->_error = strtolower(get_class( $this ))."::store failed <br />" . $this->_db->getErrorMsg(); 917 return false; 918 } else { 919 return true; 920 } 921 } 922 /** 923 * @param string $where This is expected to be a valid (and safe!) SQL expression 924 */ 925 function move( $dirn, $where='' ) { 926 $k = $this->_tbl_key; 927 928 $sql = "SELECT $this->_tbl_key, ordering FROM $this->_tbl"; 929 930 if ($dirn < 0) { 931 $sql .= "\n WHERE ordering < " . (int) $this->ordering; 932 $sql .= ($where ? "\n AND $where" : ''); 933 $sql .= "\n ORDER BY ordering DESC"; 934 $sql .= "\n LIMIT 1"; 935 } else if ($dirn > 0) { 936 $sql .= "\n WHERE ordering > " . (int) $this->ordering; 937 $sql .= ($where ? "\n AND $where" : ''); 938 $sql .= "\n ORDER BY ordering"; 939 $sql .= "\n LIMIT 1"; 940 } else { 941 $sql .= "\nWHERE ordering = " . (int) $this->ordering; 942 $sql .= ($where ? "\n AND $where" : ''); 943 $sql .= "\n ORDER BY ordering"; 944 $sql .= "\n LIMIT 1"; 945 } 946 947 $this->_db->setQuery( $sql ); 948 //echo 'A: ' . $this->_db->getQuery(); 949 950 951 $row = null; 952 if ($this->_db->loadObject( $row )) { 953 $query = "UPDATE $this->_tbl" 954 . "\n SET ordering = " . (int) $row->ordering 955 . "\n WHERE $this->_tbl_key = " . $this->_db->Quote( $this->$k ) 956 ; 957 $this->_db->setQuery( $query ); 958 959 if (!$this->_db->query()) { 960 $err = $this->_db->getErrorMsg(); 961 die( $err ); 962 } 963 //echo 'B: ' . $this->_db->getQuery(); 964 965 $query = "UPDATE $this->_tbl" 966 . "\n SET ordering = " . (int) $this->ordering 967 . "\n WHERE $this->_tbl_key = " . $this->_db->Quote( $row->$k ) 968 ; 969 $this->_db->setQuery( $query ); 970 //echo 'C: ' . $this->_db->getQuery(); 971 972 if (!$this->_db->query()) { 973 $err = $this->_db->getErrorMsg(); 974 die( $err ); 975 } 976 977 $this->ordering = $row->ordering; 978 } else { 979 $query = "UPDATE $this->_tbl" 980 . "\n SET ordering = " . (int) $this->ordering 981 . "\n WHERE $this->_tbl_key = " . $this->_db->Quote( $this->$k ) 982 ; 983 $this->_db->setQuery( $query ); 984 //echo 'D: ' . $this->_db->getQuery(); 985 986 987 if (!$this->_db->query()) { 988 $err = $this->_db->getErrorMsg(); 989 die( $err ); 990 } 991 } 992 } 993 /** 994 * Compacts the ordering sequence of the selected records 995 * @param string Additional where query to limit ordering to a particular subset of records. This is expected to be a valid (and safe!) SQL expression 996 */ 997 function updateOrder( $where='' ) { 998 $k = $this->_tbl_key; 999 1000 if (!array_key_exists( 'ordering', get_class_vars( strtolower(get_class( $this )) ) )) { 1001 $this->_error = "WARNING: ".strtolower(get_class( $this ))." does not support ordering."; 1002 return false; 1003 } 1004 1005 if ($this->_tbl == "#__content_frontpage") { 1006 $order2 = ", content_id DESC"; 1007 } else { 1008 $order2 = ''; 1009 } 1010 1011 $query = "SELECT $this->_tbl_key, ordering" 1012 . "\n FROM $this->_tbl" 1013 . ( $where ? "\n WHERE $where" : '' ) 1014 . "\n ORDER BY ordering$order2 " 1015 ; 1016 $this->_db->setQuery( $query ); 1017 if (!($orders = $this->_db->loadObjectList())) { 1018 $this->_error = $this->_db->getErrorMsg(); 1019 return false; 1020 } 1021 // first pass, compact the ordering numbers 1022 for ($i=0, $n=count( $orders ); $i < $n; $i++) { 1023 if ($orders[$i]->ordering >= 0) { 1024 $orders[$i]->ordering = $i+1; 1025 } 1026 } 1027 1028 $shift = 0; 1029 $n=count( $orders ); 1030 for ($i=0; $i < $n; $i++) { 1031 //echo "i=$i id=".$orders[$i]->$k." order=".$orders[$i]->ordering; 1032 if ($orders[$i]->$k == $this->$k) { 1033 // place 'this' record in the desired location 1034 $orders[$i]->ordering = min( $this->ordering, $n ); 1035 $shift = 1; 1036 } else if ($orders[$i]->ordering >= $this->ordering && $this->ordering > 0) { 1037 $orders[$i]->ordering++; 1038 } 1039 } 1040 //echo '<pre>';print_r($orders);echo '</pre>'; 1041 // compact once more until I can find a better algorithm 1042 for ($i=0, $n=count( $orders ); $i < $n; $i++) { 1043 if ($orders[$i]->ordering >= 0) { 1044 $orders[$i]->ordering = $i+1; 1045 $query = "UPDATE $this->_tbl" 1046 . "\n SET ordering = " . (int) $orders[$i]->ordering 1047 . "\n WHERE $k = " . $this->_db->Quote( $orders[$i]->$k ) 1048 ; 1049 $this->_db->setQuery( $query); 1050 $this->_db->query(); 1051 //echo '<br />'.$this->_db->getQuery(); 1052 } 1053 } 1054 1055 // if we didn't reorder the current record, make it last 1056 if ($shift == 0) { 1057 $order = $n+1; 1058 $query = "UPDATE $this->_tbl" 1059 . "\n SET ordering = " . (int) $order 1060 . "\n WHERE $k = " . $this->_db->Quote( $this->$k ) 1061 ; 1062 $this->_db->setQuery( $query ); 1063 $this->_db->query(); 1064 //echo '<br />'.$this->_db->getQuery(); 1065 } 1066 return true; 1067 } 1068 /** 1069 * Generic check for whether dependancies exist for this object in the db schema 1070 * 1071 * can be overloaded/supplemented by the child class 1072 * @param string $msg Error message returned 1073 * @param int Optional key index 1074 * @param array Optional array to compiles standard joins: format [label=>'Label',name=>'table name',idfield=>'field',joinfield=>'field']. This is expected to hold only valid (and safe!) SQL expressions 1075 * @return true|false 1076 */ 1077 function canDelete( $oid=null, $joins=null ) { 1078 $k = $this->_tbl_key; 1079 if ($oid) { 1080 $this->$k = $oid; 1081 } 1082 if (is_array( $joins )) { 1083 $select = $k; 1084 $join = ''; 1085 foreach( $joins as $table ) { 1086 $tblName = $this->getEscaped( $table['name'] ); 1087 $idField = $this->getEscaped( $table['idfield'] ); 1088 $jnField = $this->getEscaped( $table['joinfield'] ); 1089 $select .= ",\n COUNT(DISTINCT `$tblName`.`$idField`) AS `count_".substr($tblName, 3)."_$idField`"; 1090 $join .= "\n LEFT JOIN `$tblName` ON `$tblName`.`$jnField` = `$this->_tbl`.`$k`"; 1091 } 1092 1093 $query = "SELECT $select" 1094 . "\n FROM `$this->_tbl`" 1095 . $join 1096 . "\n WHERE `$this->_tbl`.`$k` = ". (int) $this->$k 1097 . "\n GROUP BY `$this->_tbl`.`$k`" 1098 ; 1099 $this->_db->setQuery( $query ); 1100 1101 $obj = null; 1102 if (!$this->_db->loadObject($obj)) { 1103 $this->_error = $this->_db->getErrorMsg(); 1104 return false; 1105 } 1106 $msg = array(); 1107 foreach( $joins as $table ) { 1108 $tblName = $this->getEscaped( $table['name'] ); 1109 $idField = $this->getEscaped( $table['idfield'] ); 1110 $k = 'count_'.substr($tblName, 3).'_'.$idField; 1111 if ($obj->$k) { 1112 $msg[] = $table['label']; 1113 } 1114 } 1115 1116 if (count( $msg )) { 1117 $this->_error = "noDeleteRecord" . ": " . implode( ', ', $msg ); 1118 return false; 1119 } else { 1120 return true; 1121 } 1122 } 1123 1124 return true; 1125 } 1126 1127 /** 1128 * Default delete method 1129 * 1130 * can be overloaded/supplemented by the child class 1131 * @return true if successful otherwise returns and error message 1132 */ 1133 function delete( $oid=null ) { 1134 //if (!$this->canDelete( $msg )) { 1135 // return $msg; 1136 //} 1137 1138 $k = $this->_tbl_key; 1139 if ($oid) { 1140 $this->$k = intval( $oid ); 1141 } 1142 1143 $query = "DELETE FROM $this->_tbl" 1144 . "\n WHERE $this->_tbl_key = " . $this->_db->Quote( $this->$k ) 1145 ; 1146 $this->_db->setQuery( $query ); 1147 1148 if ($this->_db->query()) { 1149 return true; 1150 } else { 1151 $this->_error = $this->_db->getErrorMsg(); 1152 return false; 1153 } 1154 } 1155 1156 /** 1157 * Checks out an object 1158 * @param int User id 1159 * @param int Object id 1160 */ 1161 function checkout( $user_id, $oid=null ) { 1162 if (!array_key_exists( 'checked_out', get_class_vars( strtolower(get_class( $this )) ) )) { 1163 $this->_error = "WARNING: ".strtolower(get_class( $this ))." does not support checkouts."; 1164 return false; 1165 } 1166 $k = $this->_tbl_key; 1167 if ($oid !== null) { 1168 $this->$k = $oid; 1169 } 1170 1171 $time = date( 'Y-m-d H:i:s' ); 1172 if (intval( $user_id )) { 1173 $user_id = intval( $user_id ); 1174 // new way of storing editor, by id 1175 $query = "UPDATE $this->_tbl" 1176 . "\n SET checked_out = $user_id, checked_out_time = " . $this->_db->Quote( $time ) 1177 . "\n WHERE $this->_tbl_key = " . $this->_db->Quote( $this->$k ) 1178 ; 1179 $this->_db->setQuery( $query ); 1180 1181 $this->checked_out = $user_id; 1182 $this->checked_out_time = $time; 1183 } else { 1184 $user_id = $this->_db->Quote( $user_id ); 1185 // old way of storing editor, by name 1186 $query = "UPDATE $this->_tbl" 1187 . "\n SET checked_out = 1, checked_out_time = " . $this->_db->Quote( $time ) . ", editor = $user_id" 1188 . "\n WHERE $this->_tbl_key = " . $this->_db->Quote( $this->$k ) 1189 ; 1190 $this->_db->setQuery( $query ); 1191 1192 $this->checked_out = 1; 1193 $this->checked_out_time = $time; 1194 $this->checked_out_editor = $user_id; 1195 } 1196 1197 return $this->_db->query(); 1198 } 1199 1200 /** 1201 * Checks in an object 1202 * @param int Object id 1203 */ 1204 function checkin( $oid=null ) { 1205 if (!array_key_exists( 'checked_out', get_class_vars( strtolower(get_class( $this )) ) )) { 1206 $this->_error = "WARNING: ".strtolower(get_class( $this ))." does not support checkin."; 1207 return false; 1208 } 1209 1210 $k = $this->_tbl_key; 1211 $nullDate = $this->_db->getNullDate(); 1212 1213 if ($oid !== null) { 1214 $this->$k = intval( $oid ); 1215 } 1216 if ($this->$k == NULL) { 1217 return false; 1218 } 1219 1220 $query = "UPDATE $this->_tbl" 1221 . "\n SET checked_out = 0, checked_out_time = " . $this->_db->Quote( $nullDate ) 1222 . "\n WHERE $this->_tbl_key = " . $this->_db->Quote( $this->$k ) 1223 ; 1224 $this->_db->setQuery( $query ); 1225 1226 $this->checked_out = 0; 1227 $this->checked_out_time = ''; 1228 1229 return $this->_db->query(); 1230 } 1231 1232 /** 1233 * Increments the hit counter for an object 1234 * @param int Object id 1235 */ 1236 function hit( $oid=null ) { 1237 global $mosConfig_enable_log_items; 1238 1239 $k = $this->_tbl_key; 1240 if ($oid !== null) { 1241 $this->$k = intval( $oid ); 1242 } 1243 1244 $query = "UPDATE $this->_tbl" 1245 . "\n SET hits = ( hits + 1 )" 1246 . "\n WHERE $this->_tbl_key = " . $this->_db->Quote( $this->id ) 1247 ; 1248 $this->_db->setQuery( $query ); 1249 $this->_db->query(); 1250 1251 if (@$mosConfig_enable_log_items) { 1252 $now = date( 'Y-m-d' ); 1253 $query = "SELECT hits" 1254 . "\n FROM #__core_log_items" 1255 . "\n WHERE time_stamp = " . $this->_db->Quote( $now ) 1256 . "\n AND item_table = " . $this->_db->Quote( $this->_tbl ) 1257 . "\n AND item_id = " . $this->_db->Quote( $this->$k ) 1258 ; 1259 $this->_db->setQuery( $query ); 1260 $hits = intval( $this->_db->loadResult() ); 1261 if ($hits) { 1262 $query = "UPDATE #__core_log_items" 1263 . "\n SET hits = ( hits + 1 )" 1264 . "\n WHERE time_stamp = " . $this->_db->Quote( $now ) 1265 . "\n AND item_table = " . $this->_db->Quote( $this->_tbl ) 1266 . "\n AND item_id = " . $this->_db->Quote( $this->$k ) 1267 ; 1268 $this->_db->setQuery( $query ); 1269 $this->_db->query(); 1270 } else { 1271 $query = "INSERT INTO #__core_log_items" 1272 . "\n VALUES ( " . $this->_db->Quote( $now ) . ", " . $this->_db->Quote( $this->_tbl ) . ", " . $this->_db->Quote( $this->$k ) . ", 1 )" 1273 ; 1274 $this->_db->setQuery( $query ); 1275 $this->_db->query(); 1276 } 1277 } 1278 } 1279 1280 /** 1281 * Tests if item is checked out 1282 * @param int A user id 1283 * @return boolean 1284 */ 1285 function isCheckedOut( $user_id=0 ) { 1286 if ($user_id) { 1287 return ($this->checked_out && $this->checked_out != $user_id); 1288 } else { 1289 return $this->checked_out; 1290 } 1291 } 1292 1293 /** 1294 * Generic save function 1295 * @param array Source array for binding to class vars 1296 * @param string Filter for the order updating. This is expected to be a valid (and safe!) SQL expression 1297 * @returns TRUE if completely successful, FALSE if partially or not succesful 1298 * NOTE: Filter will be deprecated in verion 1.1 1299 */ 1300 function save( $source, $order_filter='' ) { 1301 if (!$this->bind( $source )) { 1302 return false; 1303 } 1304 if (!$this->check()) { 1305 return false; 1306 } 1307 if (!$this->store()) { 1308 return false; 1309 } 1310 if (!$this->checkin()) { 1311 return false; 1312 } 1313 1314 if ($order_filter) { 1315 $filter_value = $this->$order_filter; 1316 $this->updateOrder( $order_filter ? "`$order_filter` = " . $this->_db->Quote( $filter_value ) : '' ); 1317 } 1318 $this->_error = ''; 1319 return true; 1320 } 1321 1322 /** 1323 * @deprecated As of 1.0.3, replaced by publish 1324 */ 1325 function publish_array( $cid=null, $publish=1, $user_id=0 ) { 1326 $this->publish( $cid, $publish, $user_id ); 1327 } 1328 1329 /** 1330 * Generic Publish/Unpublish function 1331 * @param array An array of id numbers 1332 * @param integer 0 if unpublishing, 1 if publishing 1333 * @param integer The id of the user performnig the operation 1334 * @since 1.0.4 1335 */ 1336 function publish( $cid=null, $publish=1, $user_id=0 ) { 1337 mosArrayToInts( $cid, array() ); 1338 $user_id = (int) $user_id; 1339 $publish = (int) $publish; 1340 $k = $this->_tbl_key; 1341 1342 if (count( $cid ) < 1) { 1343 $this->_error = "No items selected."; 1344 return false; 1345 } 1346 1347 $cids = $this->_tbl_key . '=' . implode( ' OR ' . $this->_tbl_key . '=', $cid ); 1348 1349 $query = "UPDATE $this->_tbl" 1350 . "\n SET published = " . (int) $publish 1351 . "\n WHERE ($cids)" 1352 . "\n AND (checked_out = 0 OR checked_out = " . (int) $user_id . ")" 1353 ; 1354 $this->_db->setQuery( $query ); 1355 if (!$this->_db->query()) { 1356 $this->_error = $this->_db->getErrorMsg(); 1357 return false; 1358 } 1359 1360 if (count( $cid ) == 1) { 1361 $this->checkin( $cid[0] ); 1362 } 1363 $this->_error = ''; 1364 return true; 1365 } 1366 1367 /** 1368 * Export item list to xml 1369 * @param boolean Map foreign keys to text values 1370 */ 1371 function toXML( $mapKeysToText=false ) { 1372 $xml = '<record table="' . $this->_tbl . '"'; 1373 1374 if ($mapKeysToText) { 1375 $xml .= ' mapkeystotext="true"'; 1376 } 1377 $xml .= '>'; 1378 foreach (get_object_vars( $this ) as $k => $v) { 1379 if (is_array($v) or is_object($v) or $v === NULL) { 1380 continue; 1381 } 1382 if ($k[0] == '_') { // internal field 1383 continue; 1384 } 1385 $xml .= '<' . $k . '><![CDATA[' . $v . ']]></' . $k . '>'; 1386 } 1387 $xml .= '</record>'; 1388 1389 return $xml; 1390 } 1391 } 1392 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Wed Nov 21 14:43:32 2007 | par Balluche grâce à PHPXref 0.7 |
|