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