WordPress.org

Make WordPress Core

Ticket #42352: 42352.diff

File 42352.diff, 14.7 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 );
    class wpdb { 
    18641864                        $return_val     = $num_rows;
    18651865                }
    18661866
    18671867                return $return_val;
    18681868        }
    18691869
    18701870        /**
    18711871         * Internal function to perform the mysql_query() call.
    18721872         *
    18731873         * @since 3.9.0
    18741874         *
    18751875         * @see wpdb::query()
    18761876         *
    18771877         * @param string $query The query to run.
    18781878         */
    1879         private function _do_query( $query ) {
     1879        private function _do_query( $query, $prepared_query_data = false ) {
    18801880                if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) {
    18811881                        $this->timer_start();
    18821882                }
    18831883
    1884                 if ( ! empty( $this->dbh ) && $this->use_mysqli ) {
     1884                if ( ! empty( $this->dbh ) && $this->use_mysqli && $prepared_query_data !== false ) {
     1885                        $prepared_value_types = '';
     1886                        $prepared_values = array();
     1887                        $valid_data_types = array( 's', 'd', 'i' );
     1888                        foreach ( $prepared_query_data as $v ) {
     1889                                if ( is_array( $v ) && isset( $v['type'] ) ) {
     1890                                        if ( in_array( $v['type'], $valid_data_types, true ) ) {
     1891                                                $prepared_value_types .= $v['type'];
     1892                                        } else {
     1893                                                $prepared_value_types .= 's';
     1894                                        }
     1895                                        $prepared_values[] = $v['value'];
     1896                                } else {
     1897                                        // Strings can be passed without the data type.
     1898                                        $prepared_value_types .= 's';
     1899                                        $prepared_values[] = $v;
     1900                                }
     1901                        }
     1902
     1903                        $prepared_query = mysqli_prepare( $this->dbh, $query );
     1904                        if ( ! $prepared_query ) {
     1905                                // TODO: Handling of a invalid query
     1906                                // $this->result = false;
     1907                        }
     1908
     1909                        /*if ( $prepared_query->param_count != count( $__raw_prepared_data ) ) {
     1910                                // Catch this before a PHP Warning is hit and yell even louder than a Warning at the developer?
     1911                                _doing_it_completely_wrong( "Incorrect parameter count!" );
     1912                                throw new Exception( 'Incorrect parameter count!' );
     1913                        }*/
     1914
     1915                        $mysqli_stmt_bind_param_args = array(
     1916                                $prepared_query,
     1917                                $prepared_value_types
     1918                                // ... args by ref:
     1919                        );
     1920                        foreach ( $prepared_values as $i => $v ) {
     1921                                $mysqli_stmt_bind_param_args[] = & $prepared_values[$i];
     1922                        }
     1923                        call_user_func_array( 'mysqli_stmt_bind_param', $mysqli_stmt_bind_param_args );
     1924
     1925                        mysqli_stmt_execute( $prepared_query );
     1926
     1927                        $this->result = mysqli_stmt_get_result( $prepared_query );
     1928                } elseif ( ! empty( $this->dbh ) && $this->use_mysqli ) {
    18851929                        $this->result = mysqli_query( $this->dbh, $query );
    18861930                } elseif ( ! empty( $this->dbh ) ) {
     1931                        if ( $prepared_query_data !== false ) {
     1932                                // TODO: Oh noes, it's a prepared query which we don't support!
     1933                                //       form it into a real query before passing to mysql_query() using $this->prepare() or something?
     1934                                //       This will likely require an actual SQL parser rather than regular expressions.
     1935                        }
    18871936                        $this->result = mysql_query( $query, $this->dbh );
    18881937                }
    18891938                $this->num_queries++;
    18901939
    18911940                if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) {
    18921941                        $this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() );
    18931942                }
    18941943        }
    18951944
    18961945        /**
    18971946         * Insert a row into a table.
    18981947         *
    18991948         *     wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 'bar' ) )
    19001949         *     wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( '%s', '%d' ) )
    19011950         *
    class wpdb { 
    20522101                }
    20532102                foreach ( $where as $field => $value ) {
    20542103                        if ( is_null( $value['value'] ) ) {
    20552104                                $conditions[] = "`$field` IS NULL";
    20562105                                continue;
    20572106                        }
    20582107
    20592108                        $conditions[] = "`$field` = " . $value['format'];
    20602109                        $values[] = $value['value'];
    20612110                }
    20622111
    20632112                $fields = implode( ', ', $fields );
    20642113                $conditions = implode( ' AND ', $conditions );
    20652114
    20662115                $sql = "UPDATE `$table` SET $fields WHERE $conditions";
    2067                
     2116
    20682117                $this->check_current_query = false;
    20692118                return $this->query( $this->prepare( $sql, $values ) );
    20702119        }
    20712120
    20722121        /**
    20732122         * Delete a row in the table
    20742123         *
    20752124         *     wpdb::delete( 'table', array( 'ID' => 1 ) )
    20762125         *     wpdb::delete( 'table', array( 'ID' => 1 ), array( '%d' ) )
    20772126         *
    20782127         * @since 3.4.0
    20792128         * @see wpdb::prepare()
    20802129         * @see wpdb::$field_types
    20812130         * @see wp_set_wpdb_vars()
    20822131         *
    class wpdb { 
    22602309
    22612310        /**
    22622311         * Retrieve one variable from the database.
    22632312         *
    22642313         * Executes a SQL query and returns the value from the SQL result.
    22652314         * 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.
    22662315         * If $query is null, this function returns the value in the specified column and row from the previous SQL result.
    22672316         *
    22682317         * @since 0.71
    22692318         *
    22702319         * @param string|null $query Optional. SQL query. Defaults to null, use the result from the previous query.
    22712320         * @param int         $x     Optional. Column of value to return. Indexed from 0.
    22722321         * @param int         $y     Optional. Row of value to return. Indexed from 0.
    22732322         * @return string|null Database query result (as string), or null on failure
    22742323         */
    2275         public function get_var( $query = null, $x = 0, $y = 0 ) {
     2324        public function get_var( $query = null, $prepared_query = false, $x = 0, $y = 0 ) {
     2325                // Back-compat.
     2326                if ( ! is_array( $prepared_query ) && func_num_args() > 1 ) {
     2327                        switch( func_num_args() ) { // zero indexed args
     2328                                case 3:
     2329                                        $y = func_get_arg( 2 );
     2330                                case 2:
     2331                                        $x = func_get_arg( 1 );
     2332                        }
     2333                        $prepared_query = false;
     2334                }
     2335
    22762336                $this->func_call = "\$db->get_var(\"$query\", $x, $y)";
    22772337
    22782338                if ( $this->check_current_query && $this->check_safe_collation( $query ) ) {
    22792339                        $this->check_current_query = false;
    22802340                }
    22812341
    22822342                if ( $query ) {
    2283                         $this->query( $query );
     2343                        $this->query( $query, $prepared_query );
    22842344                }
    22852345
    22862346                // Extract var out of cached results based x,y vals
    22872347                if ( !empty( $this->last_result[$y] ) ) {
    22882348                        $values = array_values( get_object_vars( $this->last_result[$y] ) );
    22892349                }
    22902350
    22912351                // If there is a value return it else return null
    22922352                return ( isset( $values[$x] ) && $values[$x] !== '' ) ? $values[$x] : null;
    22932353        }
    22942354
    22952355        /**
    22962356         * Retrieve one row from the database.
    22972357         *
    22982358         * Executes a SQL query and returns the row from the SQL result.
    22992359         *
    23002360         * @since 0.71
    23012361         *
    23022362         * @param string|null $query  SQL query.
    23032363         * @param string      $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which correspond to
    23042364         *                            an stdClass object, an associative array, or a numeric array, respectively. Default OBJECT.
    23052365         * @param int         $y      Optional. Row to return. Indexed from 0.
    23062366         * @return array|object|null|void Database query result in format specified by $output or null on failure
    23072367         */
    2308         public function get_row( $query = null, $output = OBJECT, $y = 0 ) {
     2368        public function get_row( $query = null, $prepared_query = false, $output = OBJECT, $y = 0 ) {
     2369                // Back-compat.
     2370                if ( ! is_array( $prepared_query ) && func_num_args() > 1 ) {
     2371                        switch( func_num_args() ) { // zero indexed args
     2372                                case 3:
     2373                                        $y = func_get_arg( 2 );
     2374                                case 2:
     2375                                        $output = func_get_arg( 1 );
     2376                        }
     2377                        $prepared_query = false;
     2378                }
     2379
     2380
    23092381                $this->func_call = "\$db->get_row(\"$query\",$output,$y)";
    23102382
    23112383                if ( $this->check_current_query && $this->check_safe_collation( $query ) ) {
    23122384                        $this->check_current_query = false;
    23132385                }
    23142386
    23152387                if ( $query ) {
    2316                         $this->query( $query );
     2388                        $this->query( $query, $prepared_query );
    23172389                } else {
    23182390                        return null;
    23192391                }
    23202392
    23212393                if ( !isset( $this->last_result[$y] ) )
    23222394                        return null;
    23232395
    23242396                if ( $output == OBJECT ) {
    23252397                        return $this->last_result[$y] ? $this->last_result[$y] : null;
    23262398                } elseif ( $output == ARRAY_A ) {
    23272399                        return $this->last_result[$y] ? get_object_vars( $this->last_result[$y] ) : null;
    23282400                } elseif ( $output == ARRAY_N ) {
    23292401                        return $this->last_result[$y] ? array_values( get_object_vars( $this->last_result[$y] ) ) : null;
    23302402                } elseif ( strtoupper( $output ) === OBJECT ) {
    23312403                        // Back compat for OBJECT being previously case insensitive.
    class wpdb { 
    23362408        }
    23372409
    23382410        /**
    23392411         * Retrieve one column from the database.
    23402412         *
    23412413         * Executes a SQL query and returns the column from the SQL result.
    23422414         * If the SQL result contains more than one column, this function returns the column specified.
    23432415         * If $query is null, this function returns the specified column from the previous SQL result.
    23442416         *
    23452417         * @since 0.71
    23462418         *
    23472419         * @param string|null $query Optional. SQL query. Defaults to previous query.
    23482420         * @param int         $x     Optional. Column to return. Indexed from 0.
    23492421         * @return array Database query result. Array indexed from 0 by SQL result row number.
    23502422         */
    2351         public function get_col( $query = null , $x = 0 ) {
     2423        public function get_col( $query = null, $prepared_query = false, $x = 0 ) {
     2424                // Back-compat.
     2425                if ( ! is_array( $prepared_query ) && func_num_args() > 1 ) {
     2426                        $x = func_get_arg( 1 );
     2427                        $prepared_query = false;
     2428                }
     2429
    23522430                if ( $this->check_current_query && $this->check_safe_collation( $query ) ) {
    23532431                        $this->check_current_query = false;
    23542432                }
    23552433
    23562434                if ( $query ) {
    2357                         $this->query( $query );
     2435                        $this->query( $query, $prepared_query );
    23582436                }
    23592437
    23602438                $new_array = array();
    23612439                // Extract the column values
    23622440                for ( $i = 0, $j = count( $this->last_result ); $i < $j; $i++ ) {
    23632441                        $new_array[$i] = $this->get_var( null, $x, $i );
    23642442                }
    23652443                return $new_array;
    23662444        }
    23672445
    23682446        /**
    23692447         * Retrieve an entire SQL result set from the database (i.e., many rows)
    23702448         *
    23712449         * Executes a SQL query and returns the entire SQL result.
    23722450         *
    23732451         * @since 0.71
    23742452         *
    23752453         * @param string $query  SQL query.
    23762454         * @param string $output Optional. Any of ARRAY_A | ARRAY_N | OBJECT | OBJECT_K constants.
    23772455         *                       With one of the first three, return an array of rows indexed from 0 by SQL result row number.
    23782456         *                       Each row is an associative array (column => value, ...), a numerically indexed array (0 => value, ...), or an object. ( ->column = value ), respectively.
    23792457         *                       With OBJECT_K, return an associative array of row objects keyed by the value of each row's first column's value.
    23802458         *                       Duplicate keys are discarded.
    23812459         * @return array|object|null Database query results
    23822460         */
    2383         public function get_results( $query = null, $output = OBJECT ) {
     2461        public function get_results( $query = null, $prepared_query = false, $output = OBJECT ) {
     2462                // Back-compat.
     2463                if ( ! is_array( $prepared_query ) && func_num_args() > 1 ) {
     2464                        $output = func_get_arg( 1 );
     2465                        $prepared_query = false;
     2466                }
     2467
    23842468                $this->func_call = "\$db->get_results(\"$query\", $output)";
    23852469
    23862470                if ( $this->check_current_query && $this->check_safe_collation( $query ) ) {
    23872471                        $this->check_current_query = false;
    23882472                }
    23892473
    23902474                if ( $query ) {
    2391                         $this->query( $query );
     2475                        $this->query( $query, $prepared_query );
    23922476                } else {
    23932477                        return null;
    23942478                }
    23952479
    23962480                $new_array = array();
    23972481                if ( $output == OBJECT ) {
    23982482                        // Return an integer-keyed array of row objects
    23992483                        return $this->last_result;
    24002484                } elseif ( $output == OBJECT_K ) {
    24012485                        // Return an array of row objects with keys from column 1
    24022486                        // (Duplicates are discarded)
    24032487                        foreach ( $this->last_result as $row ) {
    24042488                                $var_by_ref = get_object_vars( $row );
    24052489                                $key = array_shift( $var_by_ref );
    24062490                                if ( ! isset( $new_array[ $key ] ) )