[ Index ] |
PHP Cross Reference of BackPress |
[Summary view] [Print] [Text view]
1 <?php 2 // backPress DB Class 3 4 // ORIGINAL CODE FROM: 5 // Justin Vincent (justin@visunet.ie) 6 // http://php.justinvincent.com 7 8 define( 'EZSQL_VERSION', 'BP1.25' ); 9 define( 'OBJECT', 'OBJECT' ); 10 define( 'OBJECT_K', 'OBJECT_K' ); 11 define( 'ARRAY_A', 'ARRAY_A' ); 12 define( 'ARRAY_K', 'ARRAY_K' ); 13 define( 'ARRAY_N', 'ARRAY_N' ); 14 15 if ( !defined( 'SAVEQUERIES' ) ) { 16 define( 'SAVEQUERIES', false ); 17 } 18 19 if ( !defined( 'BPDB__ERROR_STRING' ) ) { 20 define( 'BPDB__ERROR_STRING', 'DB Error: %s, %s: %s' ); 21 } 22 if ( !defined( 'BPDB__ERROR_HTML' ) ) { 23 define( 'BPDB__ERROR_HTML', '<div class="error"><p><strong>DB Error in %3$s:</strong> %1$s</p><pre>%2$s</pre></div>' ); 24 } 25 if ( !defined( 'BPDB__CONNECT_ERROR_MESSAGE' ) ) { 26 define( 'BPDB__CONNECT_ERROR_MESSAGE', 'DB Error: cannot connect' ); 27 } 28 if ( !defined( 'BPDB__SELECT_ERROR_MESSAGE' ) ) { 29 define( 'BPDB__SELECT_ERROR_MESSAGE', 'DB Error: cannot select' ); 30 } 31 if ( !defined( 'BPDB__DB_VERSION_ERROR' ) ) { 32 define( 'BPDB__DB_VERSION_ERROR', 'DB Requires MySQL version 4.0 or higher' ); 33 } 34 if ( !defined( 'BPDB__PHP_EXTENSION_MISSING' ) ) { 35 define( 'BPDB__PHP_EXTENSION_MISSING', 'DB Requires The MySQL PHP extension' ); 36 } 37 38 class BPDB 39 { 40 /** 41 * Whether to show SQL/DB errors 42 * 43 * @since 1.0 44 * @access private 45 * @var bool 46 */ 47 var $show_errors = false; 48 49 /** 50 * Whether to suppress errors during the DB bootstrapping. 51 * 52 * @access private 53 * @since 1.0 54 * @var bool 55 */ 56 var $suppress_errors = false; 57 58 /** 59 * The last error during query. 60 * 61 * @since 1.0 62 * @var string 63 */ 64 var $last_error = ''; 65 66 /** 67 * Amount of queries made 68 * 69 * @since 1.0 70 * @access private 71 * @var int 72 */ 73 var $num_queries = 0; 74 75 /** 76 * The last query made 77 * 78 * @since 1.0 79 * @access private 80 * @var string 81 */ 82 var $last_query = null; 83 84 /** 85 * Saved info on the table column 86 * 87 * @since 1.0 88 * @access private 89 * @var array 90 */ 91 var $col_info = array(); 92 93 /** 94 * Saved queries that were executed 95 * 96 * @since 1.0 97 * @access private 98 * @var array 99 */ 100 var $queries = array(); 101 102 /** 103 * Whether to use the query log 104 * 105 * @since 1.0 106 * @access private 107 * @var bool 108 */ 109 var $save_queries = false; 110 111 /** 112 * Table prefix 113 * 114 * You can set this to have multiple installations 115 * in a single database. The second reason is for possible 116 * security precautions. 117 * 118 * @since 1.0 119 * @access private 120 * @var string 121 */ 122 var $prefix = ''; 123 124 /** 125 * Whether the database queries are ready to start executing. 126 * 127 * @since 1.0 128 * @access private 129 * @var bool 130 */ 131 var $ready = false; 132 133 /** 134 * The currently connected MySQL connection resource. 135 * 136 * @since 1.0 137 * @access private 138 * @var bool|resource 139 */ 140 var $dbh = false; 141 142 /** 143 * List of tables 144 * 145 * @since 1.0 146 * @access private 147 * @var array 148 */ 149 var $tables = array(); 150 151 /** 152 * Whether to use mysql_real_escape_string 153 * 154 * @since 1.0 155 * @access public 156 * @var bool 157 */ 158 var $real_escape = false; 159 160 /** 161 * PHP4 style constructor 162 * 163 * @since 1.0 164 * 165 * @return unknown Returns the result of bpdb::__construct() 166 */ 167 function BPDB() 168 { 169 $args = func_get_args(); 170 register_shutdown_function( array( &$this, '__destruct' ) ); 171 return call_user_func_array( array( &$this, '__construct' ), $args ); 172 } 173 174 /** 175 * PHP5 style constructor 176 * 177 * Grabs the arguments, calls bpdb::_init() and then connects to the database 178 * 179 * @since 1.0 180 * 181 * @return void 182 */ 183 function __construct() 184 { 185 $args = func_get_args(); 186 $args = call_user_func_array( array( &$this, '_init' ), $args ); 187 188 $this->db_connect_host( $args ); 189 } 190 191 /** 192 * Initialises the class variables based on provided arguments 193 * 194 * @since 1.0 195 * 196 * @param array $args The provided connection settings 197 * @return array The current connection settings after processing by init 198 */ 199 function _init( $args ) 200 { 201 if ( !extension_loaded( 'mysql' ) ) { 202 $this->show_errors(); 203 $this->bail( BPDB__PHP_EXTENSION_MISSING ); 204 return; 205 } 206 207 if ( 4 == func_num_args() ) { 208 $args = array( 209 'user' => $args, 210 'password' => func_get_arg( 1 ), 211 'name' => func_get_arg( 2 ), 212 'host' => func_get_arg( 3 ) 213 ); 214 } 215 216 $defaults = array( 217 'user' => false, 218 'password' => false, 219 'name' => false, 220 'host' => 'localhost', 221 'charset' => false, 222 'collate' => false, 223 'errors' => false 224 ); 225 226 $args = wp_parse_args( $args, $defaults ); 227 228 switch ( $args['errors'] ) { 229 case 'show' : 230 $this->show_errors( true ); 231 break; 232 case 'suppress' : 233 $this->suppress_errors( true ); 234 break; 235 } 236 237 return $args; 238 } 239 240 /** 241 * PHP5 style destructor, registered as shutdown function in PHP4 242 * 243 * @since 1.0 244 * 245 * @return bool Always returns true 246 */ 247 function __destruct() 248 { 249 return true; 250 } 251 252 /** 253 * Figure out which database server should handle the query, and connect to it. 254 * 255 * @since 1.0 256 * 257 * @param string query 258 * @return resource mysql database connection 259 */ 260 function &db_connect( $query = '' ) 261 { 262 $false = false; 263 if ( empty( $query ) ) { 264 return $false; 265 } 266 return $this->dbh; 267 } 268 269 /** 270 * Connects to the database server and selects a database 271 * 272 * @since 1.0 273 * 274 * @param array args 275 * name => string DB name (required) 276 * user => string DB user (optional: false) 277 * password => string DB user password (optional: false) 278 * host => string DB hostname (optional: 'localhost') 279 * charset => string DB default charset. Used in a SET NAMES query. (optional) 280 * collate => string DB default collation. If charset supplied, optionally added to the SET NAMES query (optional) 281 * @return void|bool void if cannot connect, false if cannot select, true if success 282 */ 283 function db_connect_host( $args ) 284 { 285 extract( $args, EXTR_SKIP ); 286 287 unset( $this->dbh ); // De-reference before re-assigning 288 $this->dbh = @mysql_connect( $host, $user, $password, true ); 289 290 if ( !$this->dbh ) { 291 if ( !$this->suppress_errors ) { 292 $this->show_errors(); 293 } 294 $this->bail( BPDB__CONNECT_ERROR_MESSAGE ); 295 return; 296 } 297 298 $this->ready = true; 299 300 if ( $this->has_cap( 'collation' ) ) { 301 if ( !empty( $charset ) ) { 302 if ( function_exists( 'mysql_set_charset' ) ) { 303 mysql_set_charset( $charset, $this->dbh ); 304 $this->real_escape = true; 305 } else { 306 $collation_query = "SET NAMES '{$charset}'"; 307 if ( !empty( $collate ) ) { 308 $collation_query .= " COLLATE '{$collate}'"; 309 } 310 $this->query( $collation_query, true ); 311 } 312 } 313 } 314 315 return $this->select( $name, $this->dbh ); 316 } 317 318 /** 319 * Sets the table prefix for the WordPress tables. 320 * 321 * @since 1.0 322 * 323 * @param string prefix 324 * @param false|array tables (optional: false) 325 * table identifiers are array keys 326 * array values 327 * empty: set prefix: array( 'posts' => false, 'users' => false, ... ) 328 * string: set to that array value: array( 'posts' => 'my_posts', 'users' => 'my_users' ) 329 * OR array values (with numeric keys): array( 'posts', 'users', ... ) 330 * 331 * @return string the previous prefix (mostly only meaningful if all $table parameter was false) 332 */ 333 function set_prefix( $prefix, $tables = false ) 334 { 335 if ( !$prefix ) { 336 return false; 337 } 338 if ( preg_match( '|[^a-z0-9_]|i', $prefix ) ) { 339 return new WP_Error( 'invalid_db_prefix', 'Invalid database prefix' ); // No gettext here 340 } 341 342 $old_prefix = $this->prefix; 343 344 if ( $tables && is_array( $tables ) ) { 345 $_tables =& $tables; 346 } else { 347 $_tables =& $this->tables; 348 $this->prefix = $prefix; 349 } 350 351 foreach ( $_tables as $key => $value ) { 352 if ( is_numeric( $key ) ) { // array( 'posts', 'users', ... ) 353 $this->$value = $prefix . $value; 354 } elseif ( !$value ) { 355 $this->$key = $prefix . $key; // array( 'posts' => false, 'users' => false, ... ) 356 } elseif ( is_string( $value ) ) { // array( 'posts' => 'my_posts', 'users' => 'my_users' ) 357 $this->$key = $value; 358 } 359 } 360 361 return $old_prefix; 362 } 363 364 /** 365 * Selects a database using the current database connection. 366 * 367 * The database name will be changed based on the current database 368 * connection. On failure, the execution will bail and display an DB error. 369 * 370 * @since 1.0 371 * 372 * @param string $db MySQL database name 373 * @return bool True on success, false on failure. 374 */ 375 function select( $db, &$dbh ) 376 { 377 if ( !@mysql_select_db( $db, $dbh ) ) { 378 $this->ready = false; 379 $this->show_errors(); 380 $this->bail( BPDB__SELECT_ERROR_MESSAGE ); 381 return false; 382 } 383 return true; 384 } 385 386 function _weak_escape( $string ) 387 { 388 return addslashes( $string ); 389 } 390 391 function _real_escape( $string ) 392 { 393 if ( $this->dbh && $this->real_escape ) { 394 return mysql_real_escape_string( $string, $this->dbh ); 395 } else { 396 return addslashes( $string ); 397 } 398 } 399 400 function _escape( $data ) 401 { 402 if ( is_array( $data ) ) { 403 foreach ( (array) $data as $k => $v ) { 404 if ( is_array( $v ) ) { 405 $data[$k] = $this->_escape( $v ); 406 } else { 407 $data[$k] = $this->_real_escape( $v ); 408 } 409 } 410 } else { 411 $data = $this->_real_escape( $data ); 412 } 413 414 return $data; 415 } 416 417 /** 418 * Escapes content for insertion into the database using addslashes(), for security 419 * 420 * @since 1.0 421 * 422 * @param string|array $data 423 * @return string query safe string 424 */ 425 function escape( $data ) 426 { 427 if ( is_array( $data ) ) { 428 foreach ( (array) $data as $k => $v ) { 429 if ( is_array( $v ) ) { 430 $data[$k] = $this->escape( $v ); 431 } else { 432 $data[$k] = $this->_weak_escape( $v ); 433 } 434 } 435 } else { 436 $data = $this->_weak_escape( $data ); 437 } 438 439 return $data; 440 } 441 442 /** 443 * Escapes content by reference for insertion into the database, for security 444 * 445 * @since 1.0 446 * 447 * @param string $s 448 */ 449 function escape_by_ref( &$string ) 450 { 451 $string = $this->_real_escape( $string ); 452 } 453 454 /** 455 * Escapes array recursively for insertion into the database, for security 456 * @param array $array 457 */ 458 function escape_deep( $array ) 459 { 460 return $this->_escape( $array ); 461 } 462 463 /** 464 * Prepares a SQL query for safe execution. Uses sprintf()-like syntax. 465 * 466 * This function only supports a small subset of the sprintf syntax; it only supports %d (decimal number), %s (string). 467 * Does not support sign, padding, alignment, width or precision specifiers. 468 * Does not support argument numbering/swapping. 469 * 470 * May be called like {@link http://php.net/sprintf sprintf()} or like {@link http://php.net/vsprintf vsprintf()}. 471 * 472 * Both %d and %s should be left unquoted in the query string. 473 * 474 * <code> 475 * wpdb::prepare( "SELECT * FROM `table` WHERE `column` = %s AND `field` = %d", "foo", 1337 ) 476 * </code> 477 * 478 * @link http://php.net/sprintf Description of syntax. 479 * @since 1.0 480 * 481 * @param string $query Query statement with sprintf()-like placeholders 482 * @param array|mixed $args The array of variables to substitute into the query's placeholders if being called like {@link http://php.net/vsprintf vsprintf()}, or the first variable to substitute into the query's placeholders if being called like {@link http://php.net/sprintf sprintf()}. 483 * @param mixed $args,... further variables to substitute into the query's placeholders if being called like {@link http://php.net/sprintf sprintf()}. 484 * @return null|string Sanitized query string 485 */ 486 function prepare( $query = null ) // ( $query, *$args ) 487 { 488 if ( is_null( $query ) ) { 489 return; 490 } 491 $args = func_get_args(); 492 array_shift( $args ); 493 // If args were passed as an array (as in vsprintf), move them up 494 if ( isset( $args[0] ) && is_array( $args[0] ) ) { 495 $args = $args[0]; 496 } 497 $query = str_replace( "'%s'", '%s', $query ); // in case someone mistakenly already singlequoted it 498 $query = str_replace( '"%s"', '%s', $query ); // doublequote unquoting 499 $query = str_replace( '%s', "'%s'", $query ); // quote the strings 500 array_walk( $args, array( &$this, 'escape_by_ref' ) ); 501 return @vsprintf( $query, $args ); 502 } 503 504 /** 505 * Get SQL/DB error 506 * 507 * @since 1.0 508 * 509 * @param string $str Error string 510 */ 511 function get_error( $str = '' ) 512 { 513 if ( empty( $str ) ) { 514 if ( $this->last_error ) { 515 $str = $this->last_error; 516 } else { 517 return false; 518 } 519 } 520 521 $caller = $this->get_caller(); 522 $error_str = sprintf( BPDB__ERROR_STRING, $str, $this->last_query, $caller ); 523 524 if ( class_exists( 'WP_Error' ) ) { 525 return new WP_Error( 'db_query', $error_str, array( 'query' => $this->last_query, 'error' => $str, 'caller' => $caller ) ); 526 } else { 527 return array( 'query' => $this->last_query, 'error' => $str, 'caller' => $caller, 'error_str' => $error_str ); 528 } 529 } 530 531 /** 532 * Print SQL/DB error. 533 * 534 * @since 1.0 535 * 536 * @param string $str The error to display 537 * @return bool False if the showing of errors is disabled. 538 */ 539 function print_error( $str = '' ) 540 { 541 if ( $this->suppress_errors ) { 542 return false; 543 } 544 545 $error = $this->get_error( $str ); 546 if ( is_object( $error ) && is_a( $error, 'WP_Error' ) ) { 547 $err = $error->get_error_data(); 548 $err['error_str'] = $error->get_error_message(); 549 } else { 550 $err =& $error; 551 } 552 553 $log_file = ini_get( 'error_log' ); 554 if ( !empty( $log_file ) && ( 'syslog' != $log_file ) && is_writable( $log_file ) && function_exists( 'error_log' ) ) { 555 error_log($err['error_str'], 0); 556 } 557 558 // Is error output turned on or not 559 if ( !$this->show_errors ) { 560 return false; 561 } 562 563 $str = htmlspecialchars( $err['error'], ENT_QUOTES ); 564 $query = htmlspecialchars( $err['query'], ENT_QUOTES ); 565 $caller = htmlspecialchars( $err['caller'], ENT_QUOTES ); 566 567 // If there is an error then take note of it 568 569 printf( BPDB__ERROR_HTML, $str, $query, $caller ); 570 } 571 572 /** 573 * Enables showing of database errors. 574 * 575 * This function should be used only to enable showing of errors. 576 * bpdb::hide_errors() should be used instead for hiding of errors. However, 577 * this function can be used to enable and disable showing of database 578 * errors. 579 * 580 * @since 1.0 581 * 582 * @param bool $show Whether to show or hide errors 583 * @return bool Old value for showing errors. 584 */ 585 function show_errors( $show = true ) 586 { 587 $errors = $this->show_errors; 588 $this->show_errors = $show; 589 return $errors; 590 } 591 592 /** 593 * Disables showing of database errors. 594 * 595 * @since 1.0 596 * 597 * @return bool Whether showing of errors was active or not 598 */ 599 function hide_errors() 600 { 601 return $this->show_errors( false ); 602 } 603 604 /** 605 * Whether to suppress database errors. 606 * 607 * @since 1.0 608 * 609 * @param bool $suppress 610 * @return bool previous setting 611 */ 612 function suppress_errors( $suppress = true ) 613 { 614 $errors = $this->suppress_errors; 615 $this->suppress_errors = $suppress; 616 return $errors; 617 } 618 619 /** 620 * Kill cached query results. 621 * 622 * @since 1.0 623 */ 624 function flush() 625 { 626 $this->last_result = array(); 627 $this->col_info = array(); 628 $this->last_query = null; 629 $this->last_error = ''; 630 $this->num_rows = 0; 631 } 632 633 /** 634 * Perform a MySQL database query, using current database connection. 635 * 636 * More information can be found on the codex page. 637 * 638 * @since 1.0 639 * 640 * @param string $query 641 * @return int|false Number of rows affected/selected or false on error 642 */ 643 function query( $query, $use_current = false ) 644 { 645 if ( !$this->ready ) { 646 return false; 647 } 648 649 // filter the query, if filters are available 650 // NOTE: some queries are made before the plugins have been loaded, and thus cannot be filtered with this method 651 if ( function_exists( 'apply_filters' ) ) { 652 $query = apply_filters( 'query', $query ); 653 } 654 655 // initialise return 656 $return_val = 0; 657 $this->flush(); 658 659 // Log how the function was called 660 $this->func_call = "\$db->query(\"$query\")"; 661 662 // Keep track of the last query for debug.. 663 $this->last_query = $query; 664 665 // Perform the query via std mysql_query function.. 666 if ( SAVEQUERIES ) { 667 $this->timer_start(); 668 } 669 670 if ( $use_current ) { 671 $dbh =& $this->dbh; 672 } else { 673 $dbh = $this->db_connect( $query ); 674 } 675 676 $this->result = @mysql_query( $query, $dbh ); 677 ++$this->num_queries; 678 679 if ( SAVEQUERIES ) { 680 $this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() ); 681 } 682 683 // If there is an error then take note of it.. 684 if ( is_resource( $dbh ) && $this->last_error = mysql_error( $dbh ) ) { 685 return $this->print_error( $this->last_error ); 686 } 687 688 if ( preg_match( "/^\\s*(insert|delete|update|replace|alter) /i", $query ) ) { 689 $this->rows_affected = mysql_affected_rows( $dbh ); 690 // Take note of the insert_id 691 if ( preg_match( "/^\\s*(insert|replace) /i", $query ) ) { 692 $this->insert_id = mysql_insert_id( $dbh ); 693 } 694 // Return number of rows affected 695 $return_val = $this->rows_affected; 696 } else { 697 $i = 0; 698 while ( $i < @mysql_num_fields( $this->result ) ) { 699 $this->col_info[$i] = @mysql_fetch_field( $this->result ); 700 $i++; 701 } 702 $num_rows = 0; 703 while ( $row = @mysql_fetch_object( $this->result ) ) { 704 $this->last_result[$num_rows] = $row; 705 $num_rows++; 706 } 707 708 @mysql_free_result( $this->result ); 709 710 // Log number of rows the query returned 711 $this->num_rows = $num_rows; 712 713 // Return number of rows selected 714 $return_val = $this->num_rows; 715 } 716 717 return $return_val; 718 } 719 720 /** 721 * Insert a row into a table. 722 * 723 * <code> 724 * wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( '%s', '%d' ) ) 725 * </code> 726 * 727 * @since 1.0 728 * @see bpdb::prepare() 729 * 730 * @param string $table table name 731 * @param array $data Data to insert (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped). 732 * @param array|string $format (optional) An array of formats to be mapped to each of the value in $data. If string, that format will be used for all of the values in $data. A format is one of '%d', '%s' (decimal number, string). If omitted, all values in $data will be treated as strings. 733 * @return int|false The number of rows inserted, or false on error. 734 */ 735 function insert( $table, $data, $format = null ) 736 { 737 $formats = $format = (array) $format; 738 $fields = array_keys( $data ); 739 $formatted_fields = array(); 740 foreach ( $fields as $field ) { 741 if ( !empty( $format ) ) { 742 $form = ( $form = array_shift( $formats ) ) ? $form : $format[0]; 743 } elseif ( isset( $this->field_types[$field] ) ) { 744 $form = $this->field_types[$field]; 745 } elseif ( is_null( $data[$field] ) ) { 746 $form = 'NULL'; 747 unset( $data[$field] ); 748 } else { 749 $form = '%s'; 750 } 751 $formatted_fields[] = $form; 752 } 753 $sql = "INSERT INTO `$table` (`" . implode( '`,`', $fields ) . "`) VALUES (" . implode( ",", $formatted_fields ) . ")"; 754 return $this->query( $this->prepare( $sql, $data ) ); 755 } 756 757 /** 758 * Update a row in the table 759 * 760 * <code> 761 * wpdb::update( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( 'ID' => 1 ), array( '%s', '%d' ), array( '%d' ) ) 762 * </code> 763 * 764 * @since 1.0 765 * @see bpdb::prepare() 766 * 767 * @param string $table table name 768 * @param array $data Data to update (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped). 769 * @param array $where A named array of WHERE clauses (in column => value pairs). Multiple clauses will be joined with ANDs. Both $where columns and $where values should be "raw". 770 * @param array|string $format (optional) An array of formats to be mapped to each of the values in $data. If string, that format will be used for all of the values in $data. A format is one of '%d', '%s' (decimal number, string). If omitted, all values in $data will be treated as strings. 771 * @param array|string $format_where (optional) An array of formats to be mapped to each of the values in $where. If string, that format will be used for all of the items in $where. A format is one of '%d', '%s' (decimal number, string). If omitted, all values in $where will be treated as strings. 772 * @return int|false The number of rows updated, or false on error. 773 */ 774 function update( $table, $data, $where, $format = null, $where_format = null ) 775 { 776 if ( !is_array( $where ) ) { 777 return false; 778 } 779 780 $formats = $format = (array) $format; 781 $bits = $wheres = array(); 782 foreach ( (array) array_keys( $data ) as $field ) { 783 if ( !empty( $format ) ) { 784 $form = ( $form = array_shift( $formats ) ) ? $form : $format[0]; 785 } elseif ( isset( $this->field_types[$field] ) ) { 786 $form = $this->field_types[$field]; 787 } elseif ( is_null( $data[$field] ) ) { 788 $form = 'NULL'; 789 unset( $data[$field] ); 790 } else { 791 $form = '%s'; 792 } 793 $bits[] = "`$field` = {$form}"; 794 } 795 796 $where_formats = $where_format = (array) $where_format; 797 foreach ( (array) array_keys( $where ) as $field ) { 798 if ( !empty( $where_format ) ) { 799 $form = ( $form = array_shift( $where_formats ) ) ? $form : $where_format[0]; 800 } elseif ( isset( $this->field_types[$field] ) ) { 801 $form = $this->field_types[$field]; 802 } elseif ( is_null( $where[$field] ) ) { 803 unset( $where[$field] ); 804 $wheres[] = "`$field` IS NULL"; 805 continue; 806 } else { 807 $form = '%s'; 808 } 809 $wheres[] = "`$field` = {$form}"; 810 } 811 812 $sql = "UPDATE `$table` SET " . implode( ', ', $bits ) . ' WHERE ' . implode( ' AND ', $wheres ); 813 return $this->query( $this->prepare( $sql, array_merge( array_values( $data ), array_values( $where ) ) ) ); 814 } 815 816 /** 817 * Retrieve one variable from the database. 818 * 819 * Executes a SQL query and returns the value from the SQL result. 820 * If the SQL result contains more than one column and/or more than one row, this function returns the value in the column and row specified. 821 * If $query is null, this function returns the value in the specified column and row from the previous SQL result. 822 * 823 * @since 1.0 824 * 825 * @param string|null $query SQL query. If null, use the result from the previous query. 826 * @param int $x (optional) Column of value to return. Indexed from 0. 827 * @param int $y (optional) Row of value to return. Indexed from 0. 828 * @return string Database query result 829 */ 830 function get_var( $query=null, $x = 0, $y = 0 ) 831 { 832 $this->func_call = "\$db->get_var(\"$query\",$x,$y)"; 833 if ( $query ) { 834 $this->query( $query ); 835 } 836 837 // Extract var out of cached results based x,y vals 838 if ( !empty( $this->last_result[$y] ) ) { 839 $values = array_values( get_object_vars( $this->last_result[$y] ) ); 840 } 841 842 // If there is a value return it else return null 843 return ( isset($values[$x]) && $values[$x]!=='' ) ? $values[$x] : null; 844 } 845 846 /** 847 * Retrieve one row from the database. 848 * 849 * Executes a SQL query and returns the row from the SQL result. 850 * 851 * @since 1.0 852 * 853 * @param string|null $query SQL query. 854 * @param string $output (optional) one of ARRAY_A | ARRAY_N | OBJECT constants. Return an associative array (column => value, ...), a numerically indexed array (0 => value, ...) or an object ( ->column = value ), respectively. 855 * @param int $y (optional) Row to return. Indexed from 0. 856 * @return mixed Database query result in format specifed by $output 857 */ 858 function get_row( $query = null, $output = OBJECT, $y = 0 ) 859 { 860 $this->func_call = "\$db->get_row(\"$query\",$output,$y)"; 861 if ( $query ) { 862 $this->query( $query ); 863 } else { 864 return null; 865 } 866 867 if ( !isset( $this->last_result[$y] ) ) { 868 return null; 869 } 870 871 if ( $output == OBJECT ) { 872 return $this->last_result[$y] ? $this->last_result[$y] : null; 873 } elseif ( $output == ARRAY_A ) { 874 return $this->last_result[$y] ? get_object_vars( $this->last_result[$y] ) : null; 875 } elseif ( $output == ARRAY_N ) { 876 return $this->last_result[$y] ? array_values( get_object_vars( $this->last_result[$y] ) ) : null; 877 } else { 878 $this->print_error( " \$db->get_row(string query, output type, int offset) -- Output type must be one of: OBJECT, ARRAY_A, ARRAY_N" ); 879 } 880 } 881 882 /** 883 * Retrieve one column from the database. 884 * 885 * Executes a SQL query and returns the column from the SQL result. 886 * If the SQL result contains more than one column, this function returns the column specified. 887 * If $query is null, this function returns the specified column from the previous SQL result. 888 * 889 * @since 1.0 890 * 891 * @param string|null $query SQL query. If null, use the result from the previous query. 892 * @param int $x Column to return. Indexed from 0. 893 * @return array Database query result. Array indexed from 0 by SQL result row number. 894 */ 895 function get_col( $query = null , $x = 0 ) 896 { 897 if ( $query ) { 898 $this->query( $query ); 899 } 900 901 $new_array = array(); 902 // Extract the column values 903 for ( $i=0; $i < count( $this->last_result ); $i++ ) { 904 $new_array[$i] = $this->get_var( null, $x, $i ); 905 } 906 return $new_array; 907 } 908 909 /** 910 * Retrieve an entire SQL result set from the database (i.e., many rows) 911 * 912 * Executes a SQL query and returns the entire SQL result. 913 * 914 * @since 1.0 915 * 916 * @param string $query SQL query. 917 * @param string $output (optional) ane of ARRAY_A | ARRAY_N | OBJECT | OBJECT_K | ARRAY_K constants. With one of the first three, return an array of rows indexed from 0 by SQL result row number. Each row is an associative array (column => value, ...), a numerically indexed array (0 => value, ...), or an object. ( ->column = value ), respectively. With OBJECT_K and ARRAY_K, return an associative array of row objects keyed by the value of each row's first column's value. Duplicate keys are discarded. 918 * @return mixed Database query results 919 */ 920 function get_results( $query = null, $output = OBJECT ) 921 { 922 $this->func_call = "\$db->get_results(\"$query\", $output)"; 923 924 if ( $query ) { 925 $this->query($query); 926 } else { 927 return null; 928 } 929 930 if ( $output == OBJECT ) { 931 // Return an integer-keyed array of row objects 932 return $this->last_result; 933 } elseif ( $output == OBJECT_K || $output == ARRAY_K ) { 934 // Return an array of row objects with keys from column 1 935 // (Duplicates are discarded) 936 $key = $this->col_info[0]->name; 937 foreach ( $this->last_result as $row ) { 938 if ( !isset( $new_array[ $row->$key ] ) ) { 939 $new_array[ $row->$key ] = $row; 940 } 941 } 942 if ( $output == ARRAY_K ) { 943 return array_map( 'get_object_vars', $new_array ); 944 } 945 return $new_array; 946 } elseif ( $output == ARRAY_A || $output == ARRAY_N ) { 947 // Return an integer-keyed array of... 948 if ( $this->last_result ) { 949 $i = 0; 950 foreach( $this->last_result as $row ) { 951 if ( $output == ARRAY_N ) { 952 // ...integer-keyed row arrays 953 $new_array[$i] = array_values( get_object_vars( $row ) ); 954 } else { 955 // ...column name-keyed row arrays 956 $new_array[$i] = get_object_vars( $row ); 957 } 958 ++$i; 959 } 960 return $new_array; 961 } 962 } 963 } 964 965 /** 966 * Retrieve column metadata from the last query. 967 * 968 * @since 1.0 969 * 970 * @param string $info_type one of name, table, def, max_length, not_null, primary_key, multiple_key, unique_key, numeric, blob, type, unsigned, zerofill 971 * @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 972 * @return mixed Column Results 973 */ 974 function get_col_info( $info_type = 'name', $col_offset = -1 ) 975 { 976 if ( $this->col_info ) { 977 if ( $col_offset == -1 ) { 978 $i = 0; 979 foreach( (array) $this->col_info as $col ) { 980 $new_array[$i] = $col->{$info_type}; 981 $i++; 982 } 983 return $new_array; 984 } else { 985 return $this->col_info[$col_offset]->{$info_type}; 986 } 987 } 988 } 989 990 /** 991 * Starts the timer, for debugging purposes. 992 * 993 * @since 1.0 994 * 995 * @return true 996 */ 997 function timer_start() 998 { 999 $mtime = microtime(); 1000 $mtime = explode( ' ', $mtime ); 1001 $this->time_start = $mtime[1] + $mtime[0]; 1002 return true; 1003 } 1004 1005 /** 1006 * Stops the debugging timer. 1007 * 1008 * @since 1.0 1009 * 1010 * @return int Total time spent on the query, in milliseconds 1011 */ 1012 function timer_stop() 1013 { 1014 $mtime = microtime(); 1015 $mtime = explode( ' ', $mtime ); 1016 $time_end = $mtime[1] + $mtime[0]; 1017 $time_total = $time_end - $this->time_start; 1018 return $time_total; 1019 } 1020 1021 /** 1022 * Wraps errors in a nice header and footer and dies. 1023 * 1024 * Will not die if bpdb::$show_errors is true 1025 * 1026 * @since 1.0 1027 * 1028 * @param string $message 1029 * @return false|void 1030 */ 1031 function bail( $message ) 1032 { 1033 if ( !$this->show_errors ) { 1034 if ( class_exists( 'WP_Error' ) ) 1035 $this->error = new WP_Error( '500', $message ); 1036 else 1037 $this->error = $message; 1038 return false; 1039 } 1040 backpress_die( $message ); 1041 } 1042 1043 /** 1044 * Whether or not MySQL database is at least the required minimum version. 1045 * 1046 * @since 1.0 1047 * 1048 * @return WP_Error 1049 */ 1050 function check_database_version( $dbh_or_table = false ) 1051 { 1052 // Make sure the server has MySQL 4.0 1053 if ( version_compare( $this->db_version( $dbh_or_table ), '4.0.0', '<' ) ) { 1054 return new WP_Error( 'database_version', BPDB__DB_VERSION_ERROR ); 1055 } 1056 } 1057 1058 /** 1059 * Whether of not the database supports collation. 1060 * 1061 * Called when BackPress is generating the table scheme. 1062 * 1063 * @since 1.0 1064 * 1065 * @return bool True if collation is supported, false if version does not 1066 */ 1067 function supports_collation() 1068 { 1069 return $this->has_cap( 'collation' ); 1070 } 1071 1072 /** 1073 * Generic function to determine if a database supports a particular feature 1074 * 1075 * @since 1.0 1076 * 1077 * @param string $db_cap the feature 1078 * @param false|string|resource $dbh_or_table Which database to test. False = the currently selected database, string = the database containing the specified table, resource = the database corresponding to the specified mysql resource. 1079 * @return bool 1080 */ 1081 function has_cap( $db_cap, $dbh_or_table = false ) 1082 { 1083 $version = $this->db_version( $dbh_or_table ); 1084 1085 switch ( strtolower( $db_cap ) ) { 1086 case 'collation' : 1087 case 'group_concat' : 1088 case 'subqueries' : 1089 return version_compare( $version, '4.1', '>=' ); 1090 break; 1091 1092 case 'index_hint_for_join' : 1093 return version_compare( $version, '5.0', '>=' ); 1094 break; 1095 1096 case 'index_hint_lists' : 1097 case 'index_hint_for_any' : 1098 return version_compare( $version, '5.1', '>=' ); 1099 break; 1100 } 1101 1102 return false; 1103 } 1104 1105 /** 1106 * The database version number 1107 * 1108 * @since 1.0 1109 * 1110 * @param false|string|resource $dbh_or_table Which database to test. False = the currently selected database, string = the database containing the specified table, resource = the database corresponding to the specified mysql resource. 1111 * @return false|string false on failure, version number on success 1112 */ 1113 function db_version( $dbh_or_table = false ) 1114 { 1115 if ( !$dbh_or_table ) { 1116 $dbh =& $this->dbh; 1117 } elseif ( is_resource( $dbh_or_table ) ) { 1118 $dbh =& $dbh_or_table; 1119 } else { 1120 $dbh = $this->db_connect( "DESCRIBE $dbh_or_table" ); 1121 } 1122 1123 if ( $dbh ) { 1124 return preg_replace( '|[^0-9\.]|', '', mysql_get_server_info( $dbh ) ); 1125 } 1126 return false; 1127 } 1128 1129 /** 1130 * Retrieve the name of the function that called bpdb. 1131 * 1132 * Requires PHP 4.3 and searches up the list of functions until it reaches 1133 * the one that would most logically had called this method. 1134 * 1135 * @since 1.0 1136 * 1137 * @return string The name of the calling function 1138 */ 1139 function get_caller() 1140 { 1141 // requires PHP 4.3+ 1142 if ( !is_callable( 'debug_backtrace' ) ) { 1143 return ''; 1144 } 1145 1146 $bt = debug_backtrace(); 1147 $caller = array(); 1148 1149 $bt = array_reverse( $bt ); 1150 foreach ( (array) $bt as $call ) { 1151 if ( @$call['class'] == __CLASS__ ) { 1152 continue; 1153 } 1154 $function = $call['function']; 1155 if ( isset( $call['class'] ) ) { 1156 $function = $call['class'] . "->$function"; 1157 } 1158 $caller[] = $function; 1159 } 1160 $caller = join( ', ', $caller ); 1161 1162 return $caller; 1163 } 1164 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Dec 26 01:01:01 2024 | Cross-referenced by PHPXref 0.7.1 |