[ Index ]
 

Code source de Joomla 1.0.13

Accédez au Source d'autres logiciels libres

title

Body

[fermer]

/includes/ -> database.php (source)

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


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