PHP Cross Reference of WordPress Subversion HEAD

[ Index ]     [ Classes ]     [ Functions ]     [ Variables ]     [ Constants ]

title

Body

[close]

/wp-includes/ -> wp-db.php (source)

   1  <?php
   2  //  WordPress DB Class
   3  
   4  //  ORIGINAL CODE FROM:
   5  //  Justin Vincent (justin@visunet.ie)
   6  //    http://php.justinvincent.com
   7  
   8  define('EZSQL_VERSION', 'WP1.25');
   9  define('OBJECT', 'OBJECT', true);
  10  define('ARRAY_A', 'ARRAY_A', false);
  11  define('ARRAY_N', 'ARRAY_N', false);
  12  
  13  if (!defined('SAVEQUERIES'))
  14      define('SAVEQUERIES', false);
  15  
  16  class wpdb {
  17  
  18      var $show_errors = true;
  19      var $num_queries = 0;
  20      var $last_query;
  21      var $col_info;
  22      var $queries;
  23      var $prefix = '';
  24  
  25      // Our tables
  26      var $posts;
  27      var $users;
  28      var $categories;
  29      var $post2cat;
  30      var $comments;
  31      var $links;
  32      var $options;
  33      var $postmeta;
  34      var $usermeta;
  35      var $terms;
  36      var $term_taxonomy;
  37      var $term_relationships;
  38      var $tables = array('users', 'usermeta', 'posts', 'categories', 'post2cat', 'comments', 'links', 'link2cat', 'options',
  39              'postmeta', 'terms', 'term_taxonomy', 'term_relationships');
  40      var $charset;
  41      var $collate;
  42  
  43      /**
  44       * Connects to the database server and selects a database
  45       * @param string $dbuser
  46       * @param string $dbpassword
  47       * @param string $dbname
  48       * @param string $dbhost
  49       */
  50  	function wpdb($dbuser, $dbpassword, $dbname, $dbhost) {
  51          return $this->__construct($dbuser, $dbpassword, $dbname, $dbhost);
  52      }
  53  
  54  	function __construct($dbuser, $dbpassword, $dbname, $dbhost) {
  55          register_shutdown_function(array(&$this, "__destruct"));
  56  
  57          if ( defined('DB_CHARSET') )
  58              $this->charset = DB_CHARSET;
  59  
  60          if ( defined('DB_COLLATE') )
  61              $this->collate = DB_COLLATE;
  62  
  63          $this->dbh = @mysql_connect($dbhost, $dbuser, $dbpassword);
  64          if (!$this->dbh) {
  65              $this->bail("
  66  <h1>Error establishing a database connection</h1>
  67  <p>This either means that the username and password information in your <code>wp-config.php</code> file is incorrect or we can't contact the database server at <code>$dbhost</code>. This could mean your host's database server is down.</p>
  68  <ul>
  69      <li>Are you sure you have the correct username and password?</li>
  70      <li>Are you sure that you have typed the correct hostname?</li>
  71      <li>Are you sure that the database server is running?</li>
  72  </ul>
  73  <p>If you're unsure what these terms mean you should probably contact your host. If you still need help you can always visit the <a href='http://wordpress.org/support/'>WordPress Support Forums</a>.</p>
  74  ");
  75          }
  76  
  77          if ( !empty($this->charset) && version_compare(mysql_get_server_info(), '4.1.0', '>=') )
  78               $this->query("SET NAMES '$this->charset'");
  79  
  80          $this->select($dbname);
  81      }
  82  
  83  	function __destruct() {
  84          return true;
  85      }
  86  
  87  	function set_prefix($prefix) {
  88  
  89          if ( preg_match('|[^a-z0-9_]|i', $prefix) )
  90              return new WP_Error('invalid_db_prefix', 'Invalid database prefix'); // No gettext here
  91  
  92          $old_prefix = $this->prefix;
  93          $this->prefix = $prefix;
  94  
  95          foreach ( $this->tables as $table )
  96              $this->$table = $this->prefix . $table;
  97  
  98          if ( defined('CUSTOM_USER_TABLE') )
  99              $this->users = CUSTOM_USER_TABLE;
 100  
 101          if ( defined('CUSTOM_USER_META_TABLE') )
 102              $this->usermeta = CUSTOM_USER_META_TABLE;
 103  
 104          return $old_prefix;
 105      }
 106  
 107      /**
 108       * Selects a database using the current class's $this->dbh
 109       * @param string $db name
 110       */
 111  	function select($db) {
 112          if (!@mysql_select_db($db, $this->dbh)) {
 113              $this->bail("
 114  <h1>Can&#8217;t select database</h1>
 115  <p>We were able to connect to the database server (which means your username and password is okay) but not able to select the <code>$db</code> database.</p>
 116  <ul>
 117  <li>Are you sure it exists?</li>
 118  <li>On some systems the name of your database is prefixed with your username, so it would be like username_wordpress. Could that be the problem?</li>
 119  </ul>
 120  <p>If you don't know how to setup a database you should <strong>contact your host</strong>. If all else fails you may find help at the <a href='http://wordpress.org/support/'>WordPress Support Forums</a>.</p>");
 121          }
 122      }
 123  
 124      /**
 125       * Escapes content for insertion into the database, for security
 126       *
 127       * @param string $string
 128       * @return string query safe string
 129       */
 130  	function escape($string) {
 131          return addslashes( $string ); // Disable rest for now, causing problems
 132          if( !$this->dbh || version_compare( phpversion(), '4.3.0' ) == '-1' )
 133              return mysql_escape_string( $string );
 134          else
 135              return mysql_real_escape_string( $string, $this->dbh );
 136      }
 137  
 138      /**
 139       * Escapes content by reference for insertion into the database, for security
 140       * @param string $s
 141       */
 142  	function escape_by_ref(&$s) {
 143          $s = $this->escape($s);
 144      }
 145  
 146      /**
 147       * Prepares a SQL query for safe use, using sprintf() syntax
 148       */
 149  	function prepare($args=NULL) {
 150          if ( NULL === $args )
 151              return;
 152          $args = func_get_args();
 153          $query = array_shift($args);
 154          $query = str_replace("'%s'", '%s', $query); // in case someone mistakenly already singlequoted it
 155          $query = str_replace('"%s"', '%s', $query); // doublequote unquoting
 156          $query = str_replace('%s', "'%s'", $query); // quote the strings
 157          array_walk($args, array(&$this, 'escape_by_ref'));
 158          return @vsprintf($query, $args);
 159      }
 160  
 161      // ==================================================================
 162      //    Print SQL/DB error.
 163  
 164  	function print_error($str = '') {
 165          global $EZSQL_ERROR;
 166          if (!$str) $str = mysql_error($this->dbh);
 167          $EZSQL_ERROR[] =
 168          array ('query' => $this->last_query, 'error_str' => $str);
 169  
 170          $str = htmlspecialchars($str, ENT_QUOTES);
 171          $query = htmlspecialchars($this->last_query, ENT_QUOTES);
 172          // Is error output turned on or not..
 173          if ( $this->show_errors ) {
 174              // If there is an error then take note of it
 175              print "<div id='error'>
 176              <p class='wpdberror'><strong>WordPress database error:</strong> [$str]<br />
 177              <code>$query</code></p>
 178              </div>";
 179          } else {
 180              return false;
 181          }
 182      }
 183  
 184      // ==================================================================
 185      //    Turn error handling on or off..
 186  
 187  	function show_errors() {
 188          $this->show_errors = true;
 189      }
 190  
 191  	function hide_errors() {
 192          $this->show_errors = false;
 193      }
 194  
 195      // ==================================================================
 196      //    Kill cached query results
 197  
 198  	function flush() {
 199          $this->last_result = array();
 200          $this->col_info = null;
 201          $this->last_query = null;
 202      }
 203  
 204      // ==================================================================
 205      //    Basic Query    - see docs for more detail
 206  
 207  	function query($query) {
 208          // filter the query, if filters are available
 209          // NOTE: some queries are made before the plugins have been loaded, and thus cannot be filtered with this method
 210          if ( function_exists('apply_filters') )
 211              $query = apply_filters('query', $query);
 212  
 213          // initialise return
 214          $return_val = 0;
 215          $this->flush();
 216  
 217          // Log how the function was called
 218          $this->func_call = "\$db->query(\"$query\")";
 219  
 220          // Keep track of the last query for debug..
 221          $this->last_query = $query;
 222  
 223          // Perform the query via std mysql_query function..
 224          if (SAVEQUERIES)
 225              $this->timer_start();
 226  
 227          $this->result = @mysql_query($query, $this->dbh);
 228          ++$this->num_queries;
 229  
 230          if (SAVEQUERIES)
 231              $this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() );
 232  
 233          // If there is an error then take note of it..
 234          if ( mysql_error($this->dbh) ) {
 235              $this->print_error();
 236              return false;
 237          }
 238  
 239          if ( preg_match("/^\\s*(insert|delete|update|replace) /i",$query) ) {
 240              $this->rows_affected = mysql_affected_rows($this->dbh);
 241              // Take note of the insert_id
 242              if ( preg_match("/^\\s*(insert|replace) /i",$query) ) {
 243                  $this->insert_id = mysql_insert_id($this->dbh);
 244              }
 245              // Return number of rows affected
 246              $return_val = $this->rows_affected;
 247          } else {
 248              $i = 0;
 249              while ($i < @mysql_num_fields($this->result)) {
 250                  $this->col_info[$i] = @mysql_fetch_field($this->result);
 251                  $i++;
 252              }
 253              $num_rows = 0;
 254              while ( $row = @mysql_fetch_object($this->result) ) {
 255                  $this->last_result[$num_rows] = $row;
 256                  $num_rows++;
 257              }
 258  
 259              @mysql_free_result($this->result);
 260  
 261              // Log number of rows the query returned
 262              $this->num_rows = $num_rows;
 263  
 264              // Return number of rows selected
 265              $return_val = $this->num_rows;
 266          }
 267  
 268          return $return_val;
 269      }
 270  
 271      /**
 272       * Insert an array of data into a table
 273       * @param string $table WARNING: not sanitized!
 274       * @param array $data should not already be SQL-escaped
 275       * @return mixed results of $this->query()
 276       */
 277  	function insert($table, $data) {
 278          $data = add_magic_quotes($data);
 279          $fields = array_keys($data);
 280          return $this->query("INSERT INTO $table (`" . implode('`,`',$fields) . "`) VALUES ('".implode("','",$data)."')");
 281      }
 282  
 283      /**
 284       * Update a row in the table with an array of data
 285       * @param string $table WARNING: not sanitized!
 286       * @param array $data should not already be SQL-escaped
 287       * @param array $where a named array of WHERE column => value relationships.  Multiple member pairs will be joined with ANDs.  WARNING: the column names are not currently sanitized!
 288       * @return mixed results of $this->query()
 289       */
 290  	function update($table, $data, $where){
 291          $data = add_magic_quotes($data);
 292          $bits = $wheres = array();
 293          foreach ( array_keys($data) as $k )
 294              $bits[] = "`$k` = '$data[$k]'";
 295  
 296          if ( is_array( $where ) )
 297              foreach ( $where as $c => $v )
 298                  $wheres[] = "$c = '" . $this->escape( $v ) . "'";
 299          else
 300              return false;
 301          return $this->query( "UPDATE $table SET " . implode( ', ', $bits ) . ' WHERE ' . implode( ' AND ', $wheres ) . ' LIMIT 1' );
 302      }
 303  
 304      /**
 305       * Get one variable from the database
 306       * @param string $query (can be null as well, for caching, see codex)
 307       * @param int $x = 0 row num to return
 308       * @param int $y = 0 col num to return
 309       * @return mixed results
 310       */
 311  	function get_var($query=null, $x = 0, $y = 0) {
 312          $this->func_call = "\$db->get_var(\"$query\",$x,$y)";
 313          if ( $query )
 314              $this->query($query);
 315  
 316          // Extract var out of cached results based x,y vals
 317          if ( $this->last_result[$y] ) {
 318              $values = array_values(get_object_vars($this->last_result[$y]));
 319          }
 320  
 321          // If there is a value return it else return null
 322          return (isset($values[$x]) && $values[$x]!=='') ? $values[$x] : null;
 323      }
 324  
 325      /**
 326       * Get one row from the database
 327       * @param string $query
 328       * @param string $output ARRAY_A | ARRAY_N | OBJECT
 329       * @param int $y row num to return
 330       * @return mixed results
 331       */
 332  	function get_row($query = null, $output = OBJECT, $y = 0) {
 333          $this->func_call = "\$db->get_row(\"$query\",$output,$y)";
 334          if ( $query )
 335              $this->query($query);
 336          else
 337              return null;
 338  
 339          if ( !isset($this->last_result[$y]) )
 340              return null;
 341  
 342          if ( $output == OBJECT ) {
 343              return $this->last_result[$y] ? $this->last_result[$y] : null;
 344          } elseif ( $output == ARRAY_A ) {
 345              return $this->last_result[$y] ? get_object_vars($this->last_result[$y]) : null;
 346          } elseif ( $output == ARRAY_N ) {
 347              return $this->last_result[$y] ? array_values(get_object_vars($this->last_result[$y])) : null;
 348          } else {
 349              $this->print_error(" \$db->get_row(string query, output type, int offset) -- Output type must be one of: OBJECT, ARRAY_A, ARRAY_N");
 350          }
 351      }
 352  
 353      /**
 354       * Gets one column from the database
 355       * @param string $query (can be null as well, for caching, see codex)
 356       * @param int $x col num to return
 357       * @return array results
 358       */
 359  	function get_col($query = null , $x = 0) {
 360          if ( $query )
 361              $this->query($query);
 362  
 363          $new_array = array();
 364          // Extract the column values
 365          for ( $i=0; $i < count($this->last_result); $i++ ) {
 366              $new_array[$i] = $this->get_var(null, $x, $i);
 367          }
 368          return $new_array;
 369      }
 370  
 371      /**
 372       * Return an entire result set from the database
 373       * @param string $query (can also be null to pull from the cache)
 374       * @param string $output ARRAY_A | ARRAY_N | OBJECT
 375       * @return mixed results
 376       */
 377  	function get_results($query = null, $output = OBJECT) {
 378          $this->func_call = "\$db->get_results(\"$query\", $output)";
 379  
 380          if ( $query )
 381              $this->query($query);
 382          else
 383              return null;
 384  
 385          // Send back array of objects. Each row is an object
 386          if ( $output == OBJECT ) {
 387              return $this->last_result;
 388          } elseif ( $output == ARRAY_A || $output == ARRAY_N ) {
 389              if ( $this->last_result ) {
 390                  $i = 0;
 391                  foreach( $this->last_result as $row ) {
 392                      $new_array[$i] = (array) $row;
 393                      if ( $output == ARRAY_N ) {
 394                          $new_array[$i] = array_values($new_array[$i]);
 395                      }
 396                      $i++;
 397                  }
 398                  return $new_array;
 399              } else {
 400                  return null;
 401              }
 402          }
 403      }
 404  
 405      /**
 406       * Grabs column metadata from the last query
 407       * @param string $info_type one of name, table, def, max_length, not_null, primary_key, multiple_key, unique_key, numeric, blob, type, unsigned, zerofill
 408       * @param int $col_offset 0: col name. 1: which table the col's in. 2: col's max length. 3: if the col is numeric. 4: col's type
 409       * @return mixed results
 410       */
 411  	function get_col_info($info_type = 'name', $col_offset = -1) {
 412          if ( $this->col_info ) {
 413              if ( $col_offset == -1 ) {
 414                  $i = 0;
 415                  foreach($this->col_info as $col ) {
 416                      $new_array[$i] = $col->{$info_type};
 417                      $i++;
 418                  }
 419                  return $new_array;
 420              } else {
 421                  return $this->col_info[$col_offset]->{$info_type};
 422              }
 423          }
 424      }
 425  
 426      /**
 427       * Starts the timer, for debugging purposes
 428       */
 429  	function timer_start() {
 430          $mtime = microtime();
 431          $mtime = explode(' ', $mtime);
 432          $this->time_start = $mtime[1] + $mtime[0];
 433          return true;
 434      }
 435  
 436      /**
 437       * Stops the debugging timer
 438       * @return int total time spent on the query, in milliseconds
 439       */
 440  	function timer_stop() {
 441          $mtime = microtime();
 442          $mtime = explode(' ', $mtime);
 443          $time_end = $mtime[1] + $mtime[0];
 444          $time_total = $time_end - $this->time_start;
 445          return $time_total;
 446      }
 447  
 448      /**
 449       * Wraps fatal errors in a nice header and footer and dies.
 450       * @param string $message
 451       */
 452  	function bail($message) { // Just wraps errors in a nice header and footer
 453          if ( !$this->show_errors )
 454              return false;
 455          wp_die($message);
 456      }
 457      /**
 458       * Checks wether of not the database version is high enough to support the features WordPress uses
 459       * @global $wp_version
 460       */
 461  	function check_database_version()
 462      {
 463          global $wp_version;
 464          // Make sure the server has MySQL 4.0
 465          $mysql_version = preg_replace('|[^0-9\.]|', '', @mysql_get_server_info());
 466          if ( version_compare($mysql_version, '4.0.0', '<') )
 467              return new WP_Error('database_version',sprintf(__('<strong>ERROR</strong>: WordPress %s requires MySQL 4.0.0 or higher'), $wp_version));
 468      }
 469  
 470      /**
 471       * This function is called when WordPress is generating the table schema to determine wether or not the current database
 472       * supports or needs the collation statements.
 473       */
 474  	function supports_collation()
 475      {
 476          return ( version_compare(mysql_get_server_info(), '4.1.0', '>=') );
 477      }
 478  
 479      /**
 480       * Get the name of the function that called wpdb.
 481       * @return string the name of the calling function
 482       */
 483  	function get_caller() {
 484          // requires PHP 4.3+
 485          if ( !is_callable('debug_backtrace') )
 486              return '';
 487  
 488          $bt = debug_backtrace();
 489          $caller = '';
 490  
 491          foreach ( $bt as $trace ) {
 492              if ( @$trace['class'] == __CLASS__ )
 493                  continue;
 494              elseif ( strtolower(@$trace['function']) == 'call_user_func_array' )
 495                  continue;
 496              elseif ( strtolower(@$trace['function']) == 'apply_filters' )
 497                  continue;
 498              elseif ( strtolower(@$trace['function']) == 'do_action' )