[ Index ]
 

Code source de Joomla 1.0.13

Accédez au Source d'autres logiciels libres

title

Body

[fermer]

/includes/ -> database.mysql5.php (source)

   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 />&nbsp;";
 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  ?>


Généré le : Wed Nov 21 14:43:32 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics