WordPress.org

Make WordPress Core

Ticket #42352: 42352.2.diff

File 42352.2.diff, 17.0 KB (added by dd32, 4 years ago)
  • src/wp-includes/wp-db.php

    class wpdb { 
    11961196         *
    11971197         * The following placeholders can be used in the query string:
    11981198         *   %d (integer)
    11991199         *   %f (float)
    12001200         *   %s (string)
    12011201         *
    12021202         * All placeholders MUST be left unquoted in the query string. A corresponding argument MUST be passed for each placeholder.
    12031203         *
    12041204         * Literal percentage signs (%) in the query string must be written as %%. Percentage wildcards (for example,
    12051205         * to use in LIKE syntax) must be passed via a substitution argument containing the complete LIKE string, these
    12061206         * cannot be inserted directly in the query string. Also see {@see esc_like()}.
    12071207         *
    12081208         * This method DOES NOT support sign, padding, alignment, width or precision specifiers.
    12091209         * This method DOES NOT support argument numbering or swapping.
    12101210         *
    1211          * Arguments may be passed as individual arguments to the method, or as a single array containing all arguments. A combination 
     1211         * Arguments may be passed as individual arguments to the method, or as a single array containing all arguments. A combination
    12121212         * of the two is not supported.
    12131213         *
    12141214         * Examples:
    12151215         *     $wpdb->prepare( "SELECT * FROM `table` WHERE `column` = %s AND `field` = %d OR `other_field` LIKE %s", array( 'foo', 1337, '%bar' ) );
    12161216         *     $wpdb->prepare( "SELECT DATE_FORMAT(`field`, '%%c') FROM `table` WHERE `column` = %s", 'foo' );
    12171217         *
    12181218         * @link https://secure.php.net/sprintf Description of syntax.
    12191219         * @since 2.3.0
    12201220         *
    12211221         * @param string      $query    Query statement with sprintf()-like placeholders
    12221222         * @param array|mixed $args     The array of variables to substitute into the query's placeholders if being called with an array of arguments,
    12231223         *                              or the first variable to substitute into the query's placeholders if being called with individual arguments.
    12241224         * @param mixed       $args,... further variables to substitute into the query's placeholders if being called wih individual arguments.
    12251225         * @return string|void Sanitized query string, if there is a query to prepare.
    12261226         */
    class wpdb { 
    17191719
    17201720                // Call dead_db() if bail didn't die, because this database is no more. It has ceased to be (at least temporarily).
    17211721                dead_db();
    17221722        }
    17231723
    17241724        /**
    17251725         * Perform a MySQL database query, using current database connection.
    17261726         *
    17271727         * More information can be found on the codex page.
    17281728         *
    17291729         * @since 0.71
    17301730         *
    17311731         * @param string $query Database query
    17321732         * @return int|false Number of rows affected/selected or false on error
    17331733         */
    1734         public function query( $query ) {
     1734        public function query( $query, $prepare_values = false ) {
    17351735                if ( ! $this->ready ) {
    17361736                        $this->check_current_query = true;
    17371737                        return false;
    17381738                }
    17391739
    17401740                /**
    17411741                 * Filters the database query.
    17421742                 *
    17431743                 * Some queries are made before the plugins have been loaded,
    17441744                 * and thus cannot be filtered with this method.
    17451745                 *
    17461746                 * @since 2.1.0
    17471747                 *
    17481748                 * @param string $query Database query.
    17491749                 */
    class wpdb { 
    17591759                        $stripped_query = $this->strip_invalid_text_from_query( $query );
    17601760                        // strip_invalid_text_from_query() can perform queries, so we need
    17611761                        // to flush again, just to make sure everything is clear.
    17621762                        $this->flush();
    17631763                        if ( $stripped_query !== $query ) {
    17641764                                $this->insert_id = 0;
    17651765                                return false;
    17661766                        }
    17671767                }
    17681768
    17691769                $this->check_current_query = true;
    17701770
    17711771                // Keep track of the last query for debug.
    17721772                $this->last_query = $query;
    17731773
    1774                 $this->_do_query( $query );
     1774                $this->_do_query( $query, $prepare_values );
    17751775
    17761776                // MySQL server has gone away, try to reconnect.
    17771777                $mysql_errno = 0;
    17781778                if ( ! empty( $this->dbh ) ) {
    17791779                        if ( $this->use_mysqli ) {
    17801780                                if ( $this->dbh instanceof mysqli ) {
    17811781                                        $mysql_errno = mysqli_errno( $this->dbh );
    17821782                                } else {
    17831783                                        // $dbh is defined, but isn't a real connection.
    17841784                                        // Something has gone horribly wrong, let's try a reconnect.
    17851785                                        $mysql_errno = 2006;
    17861786                                }
    17871787                        } else {
    17881788                                if ( is_resource( $this->dbh ) ) {
    17891789                                        $mysql_errno = mysql_errno( $this->dbh );
    17901790                                } else {
    17911791                                        $mysql_errno = 2006;
    17921792                                }
    17931793                        }
    17941794                }
    17951795
    17961796                if ( empty( $this->dbh ) || 2006 == $mysql_errno ) {
    17971797                        if ( $this->check_connection() ) {
    1798                                 $this->_do_query( $query );
     1798                                $this->_do_query( $query, $prepare_values );
    17991799                        } else {
    18001800                                $this->insert_id = 0;
    18011801                                return false;
    18021802                        }
    18031803                }
    18041804
    18051805                // If there is an error then take note of it.
    18061806                if ( $this->use_mysqli ) {
    18071807                        if ( $this->dbh instanceof mysqli ) {
    18081808                                $this->last_error = mysqli_error( $this->dbh );
    18091809                        } else {
    18101810                                $this->last_error = __( 'Unable to retrieve the error message from MySQL' );
    18111811                        }
    18121812                } else {
    18131813                        if ( is_resource( $this->dbh ) ) {
    class wpdb { 
    18341834                        } else {
    18351835                                $this->rows_affected = mysql_affected_rows( $this->dbh );
    18361836                        }
    18371837                        // Take note of the insert_id
    18381838                        if ( preg_match( '/^\s*(insert|replace)\s/i', $query ) ) {
    18391839                                if ( $this->use_mysqli ) {
    18401840                                        $this->insert_id = mysqli_insert_id( $this->dbh );
    18411841                                } else {
    18421842                                        $this->insert_id = mysql_insert_id( $this->dbh );
    18431843                                }
    18441844                        }
    18451845                        // Return number of rows affected
    18461846                        $return_val = $this->rows_affected;
    18471847                } else {
    18481848                        $num_rows = 0;
    1849                         if ( $this->use_mysqli && $this->result instanceof mysqli_result ) {
     1849                        if ( $this->use_mysqli && $this->result instanceof mysqli_stmt ) {
     1850                                $row = array();
     1851                                $mysqli_stmt_bind_result_args = array( $this->result );
     1852
     1853                                foreach ( mysqli_fetch_fields( mysqli_stmt_result_metadata( $this->result ) ) as $field ) {
     1854                                        $row[ $field->name ] = null;
     1855                                        $mysqli_stmt_bind_result_args[] = &$row[ $field->name ];
     1856                                }
     1857                                call_user_func_array( 'mysqli_stmt_bind_result', $mysqli_stmt_bind_result_args );
     1858
     1859                                while ( mysqli_stmt_fetch( $this->result ) ) {
     1860                                        $this->last_result[$num_rows] = $row;
     1861                                        $num_rows++;
     1862                                }
     1863                        } elseif ( $this->use_mysqli && $this->result instanceof mysqli_result ) {
    18501864                                while ( $row = mysqli_fetch_object( $this->result ) ) {
    18511865                                        $this->last_result[$num_rows] = $row;
    18521866                                        $num_rows++;
    18531867                                }
    18541868                        } elseif ( is_resource( $this->result ) ) {
    18551869                                while ( $row = mysql_fetch_object( $this->result ) ) {
    18561870                                        $this->last_result[$num_rows] = $row;
    18571871                                        $num_rows++;
    18581872                                }
    18591873                        }
    18601874
    18611875                        // Log number of rows the query returned
    18621876                        // and return number of rows selected
    18631877                        $this->num_rows = $num_rows;
    18641878                        $return_val     = $num_rows;
    18651879                }
    18661880
    18671881                return $return_val;
    18681882        }
    18691883
    18701884        /**
    18711885         * Internal function to perform the mysql_query() call.
    18721886         *
    18731887         * @since 3.9.0
    18741888         *
    18751889         * @see wpdb::query()
    18761890         *
    18771891         * @param string $query The query to run.
    18781892         */
    1879         private function _do_query( $query ) {
     1893        private function _do_query( $query, $prepared_query_data = false ) {
    18801894                if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) {
    18811895                        $this->timer_start();
    18821896                }
    18831897
    1884                 if ( ! empty( $this->dbh ) && $this->use_mysqli ) {
     1898                if ( ! empty( $this->dbh ) && $this->use_mysqli && $prepared_query_data !== false ) {
     1899                        $prepared_value_types = '';
     1900                        $prepared_values = array();
     1901                        $valid_data_types = array( 's', 'd', 'i' );
     1902                        foreach ( $prepared_query_data as $v ) {
     1903                                if ( is_array( $v ) && isset( $v['type'] ) ) {
     1904                                        if ( in_array( $v['type'], $valid_data_types, true ) ) {
     1905                                                $prepared_value_types .= $v['type'];
     1906                                        } else {
     1907                                                $prepared_value_types .= 's';
     1908                                        }
     1909                                        $prepared_values[] = $v['value'];
     1910                                } else {
     1911                                        // Strings can be passed without the data type.
     1912                                        $prepared_value_types .= 's';
     1913                                        $prepared_values[] = $v;
     1914                                }
     1915                        }
     1916
     1917                        $prepared_query = mysqli_prepare( $this->dbh, $query );
     1918                        if ( ! $prepared_query ) {
     1919                                // TODO: Handling of a invalid query
     1920                                // $this->result = false;
     1921                        }
     1922
     1923                        /*if ( $prepared_query->param_count != count( $__raw_prepared_data ) ) {
     1924                                // TODO Catch this before a PHP Warning is hit and yell even louder than a Warning at the developer?
     1925                                _doing_it_completely_wrong( "Incorrect parameter count!" );
     1926                                throw new Exception( 'Incorrect parameter count!' );
     1927                        }*/
     1928
     1929                        $mysqli_stmt_bind_param_args = array(
     1930                                $prepared_query,
     1931                                $prepared_value_types
     1932                                // ... args by ref:
     1933                        );
     1934                        foreach ( $prepared_values as $i => $v ) {
     1935                                $mysqli_stmt_bind_param_args[] = & $prepared_values[$i];
     1936                        }
     1937                        call_user_func_array( 'mysqli_stmt_bind_param', $mysqli_stmt_bind_param_args );
     1938
     1939                        mysqli_stmt_execute( $prepared_query );
     1940
     1941                        // $this->result = mysqli_stmt_get_result( $prepared_query ); // PHP 5.3+ only
     1942                        $this->result = $prepared_query;
     1943
     1944                } elseif ( ! empty( $this->dbh ) && $this->use_mysqli ) {
    18851945                        $this->result = mysqli_query( $this->dbh, $query );
    18861946                } elseif ( ! empty( $this->dbh ) ) {
     1947                        if ( $prepared_query_data !== false ) {
     1948                                // TODO: Oh noes, it's a prepared query which we don't support!
     1949                                //       form it into a real query before passing to mysql_query() using $this->prepare() or something?
     1950                                //       This will likely require an actual SQL parser rather than regular expressions.
     1951                        }
    18871952                        $this->result = mysql_query( $query, $this->dbh );
    18881953                }
    18891954                $this->num_queries++;
    18901955
    18911956                if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) {
    18921957                        $this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() );
    18931958                }
    18941959        }
    18951960
    18961961        /**
    18971962         * Insert a row into a table.
    18981963         *
    18991964         *     wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 'bar' ) )
    19001965         *     wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( '%s', '%d' ) )
    19011966         *
    class wpdb { 
    20522117                }
    20532118                foreach ( $where as $field => $value ) {
    20542119                        if ( is_null( $value['value'] ) ) {
    20552120                                $conditions[] = "`$field` IS NULL";
    20562121                                continue;
    20572122                        }
    20582123
    20592124                        $conditions[] = "`$field` = " . $value['format'];
    20602125                        $values[] = $value['value'];
    20612126                }
    20622127
    20632128                $fields = implode( ', ', $fields );
    20642129                $conditions = implode( ' AND ', $conditions );
    20652130
    20662131                $sql = "UPDATE `$table` SET $fields WHERE $conditions";
    2067                
     2132
    20682133                $this->check_current_query = false;
    20692134                return $this->query( $this->prepare( $sql, $values ) );
    20702135        }
    20712136
    20722137        /**
    20732138         * Delete a row in the table
    20742139         *
    20752140         *     wpdb::delete( 'table', array( 'ID' => 1 ) )
    20762141         *     wpdb::delete( 'table', array( 'ID' => 1 ), array( '%d' ) )
    20772142         *
    20782143         * @since 3.4.0
    20792144         * @see wpdb::prepare()
    20802145         * @see wpdb::$field_types
    20812146         * @see wp_set_wpdb_vars()
    20822147         *
    class wpdb { 
    22602325
    22612326        /**
    22622327         * Retrieve one variable from the database.
    22632328         *
    22642329         * Executes a SQL query and returns the value from the SQL result.
    22652330         * 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.
    22662331         * If $query is null, this function returns the value in the specified column and row from the previous SQL result.
    22672332         *
    22682333         * @since 0.71
    22692334         *
    22702335         * @param string|null $query Optional. SQL query. Defaults to null, use the result from the previous query.
    22712336         * @param int         $x     Optional. Column of value to return. Indexed from 0.
    22722337         * @param int         $y     Optional. Row of value to return. Indexed from 0.
    22732338         * @return string|null Database query result (as string), or null on failure
    22742339         */
    2275         public function get_var( $query = null, $x = 0, $y = 0 ) {
     2340        public function get_var( $query = null, $prepared_query = false, $x = 0, $y = 0 ) {
     2341                // Back-compat.
     2342                if ( ! is_array( $prepared_query ) && func_num_args() > 1 ) {
     2343                        switch( func_num_args() ) { // zero indexed args
     2344                                case 3:
     2345                                        $y = func_get_arg( 2 );
     2346                                case 2:
     2347                                        $x = func_get_arg( 1 );
     2348                        }
     2349                        $prepared_query = false;
     2350                }
     2351
    22762352                $this->func_call = "\$db->get_var(\"$query\", $x, $y)";
    22772353
    22782354                if ( $this->check_current_query && $this->check_safe_collation( $query ) ) {
    22792355                        $this->check_current_query = false;
    22802356                }
    22812357
    22822358                if ( $query ) {
    2283                         $this->query( $query );
     2359                        $this->query( $query, $prepared_query );
    22842360                }
    22852361
    22862362                // Extract var out of cached results based x,y vals
    22872363                if ( !empty( $this->last_result[$y] ) ) {
    22882364                        $values = array_values( get_object_vars( $this->last_result[$y] ) );
    22892365                }
    22902366
    22912367                // If there is a value return it else return null
    22922368                return ( isset( $values[$x] ) && $values[$x] !== '' ) ? $values[$x] : null;
    22932369        }
    22942370
    22952371        /**
    22962372         * Retrieve one row from the database.
    22972373         *
    22982374         * Executes a SQL query and returns the row from the SQL result.
    22992375         *
    23002376         * @since 0.71
    23012377         *
    23022378         * @param string|null $query  SQL query.
    23032379         * @param string      $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which correspond to
    23042380         *                            an stdClass object, an associative array, or a numeric array, respectively. Default OBJECT.
    23052381         * @param int         $y      Optional. Row to return. Indexed from 0.
    23062382         * @return array|object|null|void Database query result in format specified by $output or null on failure
    23072383         */
    2308         public function get_row( $query = null, $output = OBJECT, $y = 0 ) {
     2384        public function get_row( $query = null, $prepared_query = false, $output = OBJECT, $y = 0 ) {
     2385                // Back-compat.
     2386                if ( ! is_array( $prepared_query ) && func_num_args() > 1 ) {
     2387                        switch( func_num_args() ) { // zero indexed args
     2388                                case 3:
     2389                                        $y = func_get_arg( 2 );
     2390                                case 2:
     2391                                        $output = func_get_arg( 1 );
     2392                        }
     2393                        $prepared_query = false;
     2394                }
     2395
     2396
    23092397                $this->func_call = "\$db->get_row(\"$query\",$output,$y)";
    23102398
    23112399                if ( $this->check_current_query && $this->check_safe_collation( $query ) ) {
    23122400                        $this->check_current_query = false;
    23132401                }
    23142402
    23152403                if ( $query ) {
    2316                         $this->query( $query );
     2404                        $this->query( $query, $prepared_query );
    23172405                } else {
    23182406                        return null;
    23192407                }
    23202408
    23212409                if ( !isset( $this->last_result[$y] ) )
    23222410                        return null;
    23232411
    23242412                if ( $output == OBJECT ) {
    23252413                        return $this->last_result[$y] ? $this->last_result[$y] : null;
    23262414                } elseif ( $output == ARRAY_A ) {
    23272415                        return $this->last_result[$y] ? get_object_vars( $this->last_result[$y] ) : null;
    23282416                } elseif ( $output == ARRAY_N ) {
    23292417                        return $this->last_result[$y] ? array_values( get_object_vars( $this->last_result[$y] ) ) : null;
    23302418                } elseif ( strtoupper( $output ) === OBJECT ) {
    23312419                        // Back compat for OBJECT being previously case insensitive.
    class wpdb { 
    23362424        }
    23372425
    23382426        /**
    23392427         * Retrieve one column from the database.
    23402428         *
    23412429         * Executes a SQL query and returns the column from the SQL result.
    23422430         * If the SQL result contains more than one column, this function returns the column specified.
    23432431         * If $query is null, this function returns the specified column from the previous SQL result.
    23442432         *
    23452433         * @since 0.71
    23462434         *
    23472435         * @param string|null $query Optional. SQL query. Defaults to previous query.
    23482436         * @param int         $x     Optional. Column to return. Indexed from 0.
    23492437         * @return array Database query result. Array indexed from 0 by SQL result row number.
    23502438         */
    2351         public function get_col( $query = null , $x = 0 ) {
     2439        public function get_col( $query = null, $prepared_query = false, $x = 0 ) {
     2440                // Back-compat.
     2441                if ( ! is_array( $prepared_query ) && func_num_args() > 1 ) {
     2442                        $x = func_get_arg( 1 );
     2443                        $prepared_query = false;
     2444                }
     2445
    23522446                if ( $this->check_current_query && $this->check_safe_collation( $query ) ) {
    23532447                        $this->check_current_query = false;
    23542448                }
    23552449
    23562450                if ( $query ) {
    2357                         $this->query( $query );
     2451                        $this->query( $query, $prepared_query );
    23582452                }
    23592453
    23602454                $new_array = array();
    23612455                // Extract the column values
    23622456                for ( $i = 0, $j = count( $this->last_result ); $i < $j; $i++ ) {
    23632457                        $new_array[$i] = $this->get_var( null, $x, $i );
    23642458                }
    23652459                return $new_array;
    23662460        }
    23672461
    23682462        /**
    23692463         * Retrieve an entire SQL result set from the database (i.e., many rows)
    23702464         *
    23712465         * Executes a SQL query and returns the entire SQL result.
    23722466         *
    23732467         * @since 0.71
    23742468         *
    23752469         * @param string $query  SQL query.
    23762470         * @param string $output Optional. Any of ARRAY_A | ARRAY_N | OBJECT | OBJECT_K constants.
    23772471         *                       With one of the first three, return an array of rows indexed from 0 by SQL result row number.
    23782472         *                       Each row is an associative array (column => value, ...), a numerically indexed array (0 => value, ...), or an object. ( ->column = value ), respectively.
    23792473         *                       With OBJECT_K, return an associative array of row objects keyed by the value of each row's first column's value.
    23802474         *                       Duplicate keys are discarded.
    23812475         * @return array|object|null Database query results
    23822476         */
    2383         public function get_results( $query = null, $output = OBJECT ) {
     2477        public function get_results( $query = null, $prepared_query = false, $output = OBJECT ) {
     2478                // Back-compat.
     2479                if ( ! is_array( $prepared_query ) && func_num_args() > 1 ) {
     2480                        $output = func_get_arg( 1 );
     2481                        $prepared_query = false;
     2482                }
     2483
    23842484                $this->func_call = "\$db->get_results(\"$query\", $output)";
    23852485
    23862486                if ( $this->check_current_query && $this->check_safe_collation( $query ) ) {
    23872487                        $this->check_current_query = false;
    23882488                }
    23892489
    23902490                if ( $query ) {
    2391                         $this->query( $query );
     2491                        $this->query( $query, $prepared_query );
    23922492                } else {
    23932493                        return null;
    23942494                }
    23952495
    23962496                $new_array = array();
    23972497                if ( $output == OBJECT ) {
    23982498                        // Return an integer-keyed array of row objects
    23992499                        return $this->last_result;
    24002500                } elseif ( $output == OBJECT_K ) {
    24012501                        // Return an array of row objects with keys from column 1
    24022502                        // (Duplicates are discarded)
    24032503                        foreach ( $this->last_result as $row ) {
    24042504                                $var_by_ref = get_object_vars( $row );
    24052505                                $key = array_shift( $var_by_ref );
    24062506                                if ( ! isset( $new_array[ $key ] ) )