Make WordPress Core

Ticket #42352: 42352.3.diff

File 42352.3.diff, 24.5 KB (added by dd32, 8 years ago)
  • src/wp-includes/wp-db.php

    class wpdb { 
    535535         * Whether to use mysqli over mysql.
    536536         *
    537537         * @since 3.9.0
    538538         * @var bool
    539539         */
    540540        private $use_mysqli = false;
    541541
    542542        /**
    543543         * Whether we've managed to successfully connect at some point
    544544         *
    545545         * @since 3.9.0
    546546         * @var bool
    547547         */
    548548        private $has_connected = false;
    549549
     550        // Used for prepared statements
     551        protected $valid_mysqli_prepare_placeholders = array(
     552                's' => '%s',
     553                'i' => '%d',
     554                'd' => '%f',
     555        );
     556
    550557        /**
    551558         * Connects to the database server and selects a database
    552559         *
    553560         * PHP5 style constructor for compatibility with PHP5. Does
    554561         * the actual setting up of the class properties and connection
    555562         * to the database.
    556563         *
    557564         * @link https://core.trac.wordpress.org/ticket/3354
    558565         * @since 2.0.8
    559566         *
    560567         * @global string $wp_version
    561568         *
    562569         * @param string $dbuser     MySQL database user
    563570         * @param string $dbpassword MySQL database password
    564571         * @param string $dbname     MySQL database name
    class wpdb { 
    11961203         *
    11971204         * The following placeholders can be used in the query string:
    11981205         *   %d (integer)
    11991206         *   %f (float)
    12001207         *   %s (string)
    12011208         *
    12021209         * All placeholders MUST be left unquoted in the query string. A corresponding argument MUST be passed for each placeholder.
    12031210         *
    12041211         * Literal percentage signs (%) in the query string must be written as %%. Percentage wildcards (for example,
    12051212         * to use in LIKE syntax) must be passed via a substitution argument containing the complete LIKE string, these
    12061213         * cannot be inserted directly in the query string. Also see {@see esc_like()}.
    12071214         *
    12081215         * This method DOES NOT support sign, padding, alignment, width or precision specifiers.
    12091216         * This method DOES NOT support argument numbering or swapping.
    12101217         *
    1211          * Arguments may be passed as individual arguments to the method, or as a single array containing all arguments. A combination 
     1218         * Arguments may be passed as individual arguments to the method, or as a single array containing all arguments. A combination
    12121219         * of the two is not supported.
    12131220         *
    12141221         * Examples:
    12151222         *     $wpdb->prepare( "SELECT * FROM `table` WHERE `column` = %s AND `field` = %d OR `other_field` LIKE %s", array( 'foo', 1337, '%bar' ) );
    12161223         *     $wpdb->prepare( "SELECT DATE_FORMAT(`field`, '%%c') FROM `table` WHERE `column` = %s", 'foo' );
    12171224         *
    12181225         * @link https://secure.php.net/sprintf Description of syntax.
    12191226         * @since 2.3.0
    12201227         *
    12211228         * @param string      $query    Query statement with sprintf()-like placeholders
    12221229         * @param array|mixed $args     The array of variables to substitute into the query's placeholders if being called with an array of arguments,
    12231230         *                              or the first variable to substitute into the query's placeholders if being called with individual arguments.
    12241231         * @param mixed       $args,... further variables to substitute into the query's placeholders if being called wih individual arguments.
    12251232         * @return string|void Sanitized query string, if there is a query to prepare.
    12261233         */
    class wpdb { 
    17191726
    17201727                // Call dead_db() if bail didn't die, because this database is no more. It has ceased to be (at least temporarily).
    17211728                dead_db();
    17221729        }
    17231730
    17241731        /**
    17251732         * Perform a MySQL database query, using current database connection.
    17261733         *
    17271734         * More information can be found on the codex page.
    17281735         *
    17291736         * @since 0.71
    17301737         *
    17311738         * @param string $query Database query
    17321739         * @return int|false Number of rows affected/selected or false on error
    17331740         */
    1734         public function query( $query ) {
     1741        public function query( $query, $prepare_values = false ) {
    17351742                if ( ! $this->ready ) {
    17361743                        $this->check_current_query = true;
    17371744                        return false;
    17381745                }
    17391746
    17401747                /**
    17411748                 * Filters the database query.
    17421749                 *
    17431750                 * Some queries are made before the plugins have been loaded,
    17441751                 * and thus cannot be filtered with this method.
    17451752                 *
    17461753                 * @since 2.1.0
    17471754                 *
    17481755                 * @param string $query Database query.
    17491756                 */
    class wpdb { 
    17591766                        $stripped_query = $this->strip_invalid_text_from_query( $query );
    17601767                        // strip_invalid_text_from_query() can perform queries, so we need
    17611768                        // to flush again, just to make sure everything is clear.
    17621769                        $this->flush();
    17631770                        if ( $stripped_query !== $query ) {
    17641771                                $this->insert_id = 0;
    17651772                                return false;
    17661773                        }
    17671774                }
    17681775
    17691776                $this->check_current_query = true;
    17701777
    17711778                // Keep track of the last query for debug.
    17721779                $this->last_query = $query;
    17731780
    1774                 $this->_do_query( $query );
     1781                $this->_do_query( $query, $prepare_values );
    17751782
    17761783                // MySQL server has gone away, try to reconnect.
    17771784                $mysql_errno = 0;
    17781785                if ( ! empty( $this->dbh ) ) {
    17791786                        if ( $this->use_mysqli ) {
    17801787                                if ( $this->dbh instanceof mysqli ) {
    17811788                                        $mysql_errno = mysqli_errno( $this->dbh );
    17821789                                } else {
    17831790                                        // $dbh is defined, but isn't a real connection.
    17841791                                        // Something has gone horribly wrong, let's try a reconnect.
    17851792                                        $mysql_errno = 2006;
    17861793                                }
    17871794                        } else {
    17881795                                if ( is_resource( $this->dbh ) ) {
    17891796                                        $mysql_errno = mysql_errno( $this->dbh );
    17901797                                } else {
    17911798                                        $mysql_errno = 2006;
    17921799                                }
    17931800                        }
    17941801                }
    17951802
    17961803                if ( empty( $this->dbh ) || 2006 == $mysql_errno ) {
    17971804                        if ( $this->check_connection() ) {
    1798                                 $this->_do_query( $query );
     1805                                $this->_do_query( $query, $prepare_values );
    17991806                        } else {
    18001807                                $this->insert_id = 0;
    18011808                                return false;
    18021809                        }
    18031810                }
    18041811
    18051812                // If there is an error then take note of it.
    18061813                if ( $this->use_mysqli ) {
    18071814                        if ( $this->dbh instanceof mysqli ) {
    18081815                                $this->last_error = mysqli_error( $this->dbh );
    18091816                        } else {
    18101817                                $this->last_error = __( 'Unable to retrieve the error message from MySQL' );
    18111818                        }
    18121819                } else {
    18131820                        if ( is_resource( $this->dbh ) ) {
    class wpdb { 
    18341841                        } else {
    18351842                                $this->rows_affected = mysql_affected_rows( $this->dbh );
    18361843                        }
    18371844                        // Take note of the insert_id
    18381845                        if ( preg_match( '/^\s*(insert|replace)\s/i', $query ) ) {
    18391846                                if ( $this->use_mysqli ) {
    18401847                                        $this->insert_id = mysqli_insert_id( $this->dbh );
    18411848                                } else {
    18421849                                        $this->insert_id = mysql_insert_id( $this->dbh );
    18431850                                }
    18441851                        }
    18451852                        // Return number of rows affected
    18461853                        $return_val = $this->rows_affected;
    18471854                } else {
    18481855                        $num_rows = 0;
    1849                         if ( $this->use_mysqli && $this->result instanceof mysqli_result ) {
     1856                        if ( $this->use_mysqli && $this->result instanceof mysqli_stmt ) {
     1857                                $db_row = array();
     1858                                $mysqli_stmt_bind_result_args = array( $this->result );
     1859
     1860                                foreach ( mysqli_fetch_fields( mysqli_stmt_result_metadata( $this->result ) ) as $field ) {
     1861                                        $db_row[ $field->name ] = null;
     1862                                        $mysqli_stmt_bind_result_args[] = &$db_row[ $field->name ];
     1863                                }
     1864                                call_user_func_array( 'mysqli_stmt_bind_result', $mysqli_stmt_bind_result_args );
     1865
     1866                                while ( mysqli_stmt_fetch( $this->result ) ) {
     1867                                        // Copy values out, as $db_row fields are bound to the current result set.
     1868                                        $row = new stdClass();
     1869                                        foreach ( $db_row as $field => $value ) {
     1870                                                $row->{$field} = $value;
     1871                                        }
     1872                                        $this->last_result[$num_rows] = $row;
     1873                                        $num_rows++;
     1874                                }
     1875                        } elseif ( $this->use_mysqli && $this->result instanceof mysqli_result ) {
    18501876                                while ( $row = mysqli_fetch_object( $this->result ) ) {
    18511877                                        $this->last_result[$num_rows] = $row;
    18521878                                        $num_rows++;
    18531879                                }
    18541880                        } elseif ( is_resource( $this->result ) ) {
    18551881                                while ( $row = mysql_fetch_object( $this->result ) ) {
    18561882                                        $this->last_result[$num_rows] = $row;
    18571883                                        $num_rows++;
    18581884                                }
    18591885                        }
    18601886
    18611887                        // Log number of rows the query returned
    18621888                        // and return number of rows selected
    18631889                        $this->num_rows = $num_rows;
    18641890                        $return_val     = $num_rows;
    18651891                }
    18661892
    18671893                return $return_val;
    18681894        }
    18691895
    18701896        /**
    18711897         * Internal function to perform the mysql_query() call.
    18721898         *
    18731899         * @since 3.9.0
    18741900         *
    18751901         * @see wpdb::query()
    18761902         *
    18771903         * @param string $query The query to run.
    18781904         */
    1879         private function _do_query( $query ) {
     1905        private function _do_query( $query, $prepared_query_data = false ) {
    18801906                if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) {
    18811907                        $this->timer_start();
    18821908                }
    18831909
    1884                 if ( ! empty( $this->dbh ) && $this->use_mysqli ) {
     1910                if ( ! empty( $this->dbh ) && $this->use_mysqli && $prepared_query_data !== false ) {
     1911
     1912                        $prepared_value_types = '';
     1913                        $prepared_values = array();
     1914                        foreach ( $prepared_query_data as $v ) {
     1915                                if ( ! is_array( $v ) || ! isset( $v['type'] ) ) {
     1916                                        $v = array( 'type' => 's', 'value' => $v );
     1917                                }
     1918                                if ( isset( $this->valid_mysqli_prepare_placeholders[ $v['type'] ] ) ) {
     1919                                        $prepared_value_types .= $v['type'];
     1920                                } else {
     1921                                        $prepared_value_types .= 's';
     1922                                }
     1923
     1924                                $prepared_values[] = $v['value'];
     1925                        }
     1926
     1927                        $prepared_query = mysqli_prepare( $this->dbh, $query );
     1928                        if ( ! $prepared_query ) {
     1929
     1930                                // TODO: Handling of a invalid query
     1931                                $this->result = false;
     1932                                return false;
     1933                        }
     1934
     1935                        if ( $prepared_query->param_count != count( $prepared_query_data ) ) {
     1936                                // Inform the developer they passed an invalid query (or args)
     1937                                throw new Exception( "Invalid query, incorrect parameter count" );
     1938                        }
     1939
     1940                        $mysqli_stmt_bind_param_args = array(
     1941                                $prepared_query,
     1942                                $prepared_value_types
     1943                                // ... args by ref:
     1944                        );
     1945                        foreach ( $prepared_values as $i => $v ) {
     1946                                $mysqli_stmt_bind_param_args[] = & $prepared_values[$i];
     1947                        }
     1948                        call_user_func_array( 'mysqli_stmt_bind_param', $mysqli_stmt_bind_param_args );
     1949
     1950                        mysqli_stmt_execute( $prepared_query );
     1951                        $this->result = $prepared_query;
     1952
     1953                } elseif ( ! empty( $this->dbh ) && $this->use_mysqli ) {
    18851954                        $this->result = mysqli_query( $this->dbh, $query );
     1955
     1956                } elseif ( ! empty( $this->dbh ) && $prepared_query_data !== false ) {
     1957                        // TODO: TESTING NEEDED
     1958                        // TODO: Use a weak prepare (printf) to handle it when MySQLi isn't available.
     1959                        $prepared_value_types = array();
     1960                        $prepared_values = array();
     1961                        foreach ( $prepared_query_data as $v ) {
     1962                                if ( ! is_array( $v ) || ! isset( $v['type'] ) ) {
     1963                                        $v = array( 'type' => 's', 'value' => $v );
     1964                                }
     1965                                if ( isset( $this->valid_mysqli_prepare_placeholders[ $v['type'] ] ) ) {
     1966                                        $prepared_value_types[] = $this->valid_mysqli_prepare_placeholders[ $v['type'] ];
     1967                                } else {
     1968                                        $prepared_value_types[] = '%s';
     1969                                }
     1970                                $prepared_values[] = $v['value'];
     1971                        }
     1972
     1973                        // TODO: this attempts to prevent issues when ? is present in a non-placeholder context, which shouldn't happen (but might)
     1974                        if ( count( $prepared_values ) !== substr_count( $query, '?' ) ) {
     1975                                // Inform the developer they passed an invalid query (or args)
     1976                                throw new Exception( "Invalid query, incorrect parameter count" );
     1977                        }
     1978
     1979                        // TODO PHP 5.2 compat
     1980                        // NOTE: $_query used to record non-prepare'd query with SAVEQUERIES
     1981                        $_query = preg_replace_callback( '/\?/', function() use( $prepared_value_types ) {
     1982                                static $i = 0;
     1983                                return $prepared_value_types[ $i++ ];
     1984                        }, $query );
     1985
     1986                        $_query = $this->prepare( $_query, $prepared_values );
     1987                        $this->result = mysql_query( $_query, $this->dbh );
     1988
    18861989                } elseif ( ! empty( $this->dbh ) ) {
    18871990                        $this->result = mysql_query( $query, $this->dbh );
    18881991                }
    18891992                $this->num_queries++;
    18901993
    18911994                if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) {
    18921995                        $this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() );
    18931996                }
    18941997        }
    18951998
    18961999        /**
    18972000         * Insert a row into a table.
    18982001         *
    18992002         *     wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 'bar' ) )
    19002003         *     wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( '%s', '%d' ) )
    class wpdb { 
    19642067         * @param string $type         Optional. What type of operation is this? INSERT or REPLACE. Defaults to INSERT.
    19652068         * @return int|false The number of rows affected, or false on error.
    19662069         */
    19672070        function _insert_replace_helper( $table, $data, $format = null, $type = 'INSERT' ) {
    19682071                $this->insert_id = 0;
    19692072
    19702073                if ( ! in_array( strtoupper( $type ), array( 'REPLACE', 'INSERT' ) ) ) {
    19712074                        return false;
    19722075                }
    19732076
    19742077                $data = $this->process_fields( $table, $data, $format );
    19752078                if ( false === $data ) {
    19762079                        return false;
    19772080                }
    19782081
     2082                $formats_to_placeholders = array_flip( $this->valid_mysqli_prepare_placeholders );
     2083
    19792084                $formats = $values = array();
    19802085                foreach ( $data as $value ) {
    19812086                        if ( is_null( $value['value'] ) ) {
    19822087                                $formats[] = 'NULL';
    19832088                                continue;
    19842089                        }
    19852090
    1986                         $formats[] = $value['format'];
    1987                         $values[]  = $value['value'];
     2091                        $formats[] = '?';
     2092                        $values[]  = array(
     2093                                'value' => $value['value'],
     2094                                'type' => isset( $formats_to_placeholders[ $value['format'] ] ) ?
     2095                                                 $formats_to_placeholders[ $value['format'] ] :
     2096                                                 's',
     2097                        );
    19882098                }
    19892099
    19902100                $fields  = '`' . implode( '`, `', array_keys( $data ) ) . '`';
    19912101                $formats = implode( ', ', $formats );
    19922102
    19932103                $sql = "$type INTO `$table` ($fields) VALUES ($formats)";
    19942104
    19952105                $this->check_current_query = false;
    1996                 return $this->query( $this->prepare( $sql, $values ) );
     2106                return $this->query( $sql, $values );
    19972107        }
    19982108
    19992109        /**
    20002110         * Update a row in the table
    20012111         *
    20022112         *     wpdb::update( 'table', array( 'column' => 'foo', 'field' => 'bar' ), array( 'ID' => 1 ) )
    20032113         *     wpdb::update( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( 'ID' => 1 ), array( '%s', '%d' ), array( '%d' ) )
    20042114         *
    20052115         * @since 2.5.0
    20062116         * @see wpdb::prepare()
    20072117         * @see wpdb::$field_types
    20082118         * @see wp_set_wpdb_vars()
    20092119         *
    20102120         * @param string       $table        Table name
    20112121         * @param array        $data         Data to update (in column => value pairs).
    class wpdb { 
    20282138         */
    20292139        public function update( $table, $data, $where, $format = null, $where_format = null ) {
    20302140                if ( ! is_array( $data ) || ! is_array( $where ) ) {
    20312141                        return false;
    20322142                }
    20332143
    20342144                $data = $this->process_fields( $table, $data, $format );
    20352145                if ( false === $data ) {
    20362146                        return false;
    20372147                }
    20382148                $where = $this->process_fields( $table, $where, $where_format );
    20392149                if ( false === $where ) {
    20402150                        return false;
    20412151                }
    20422152
     2153                $formats_to_placeholders = array_flip( $this->valid_mysqli_prepare_placeholders );
     2154
    20432155                $fields = $conditions = $values = array();
    20442156                foreach ( $data as $field => $value ) {
    20452157                        if ( is_null( $value['value'] ) ) {
    20462158                                $fields[] = "`$field` = NULL";
    20472159                                continue;
    20482160                        }
    20492161
    2050                         $fields[] = "`$field` = " . $value['format'];
    2051                         $values[] = $value['value'];
     2162                        $fields[] = "`$field` = ?";
     2163                        $values[]  = array(
     2164                                'value' => $value['value'],
     2165                                'type' => isset( $formats_to_placeholders[ $value['format'] ] ) ?
     2166                                                 $formats_to_placeholders[ $value['format'] ] :
     2167                                                 's',
     2168                        );
    20522169                }
    20532170                foreach ( $where as $field => $value ) {
    20542171                        if ( is_null( $value['value'] ) ) {
    20552172                                $conditions[] = "`$field` IS NULL";
    20562173                                continue;
    20572174                        }
    20582175
    2059                         $conditions[] = "`$field` = " . $value['format'];
    2060                         $values[] = $value['value'];
     2176                        $conditions[] = "`$field` = ?";
     2177                        $values[]  = array(
     2178                                'value' => $value['value'],
     2179                                'type' => isset( $formats_to_placeholders[ $value['format'] ] ) ?
     2180                                                 $formats_to_placeholders[ $value['format'] ] :
     2181                                                 's',
     2182                        );
    20612183                }
    20622184
    20632185                $fields = implode( ', ', $fields );
    20642186                $conditions = implode( ' AND ', $conditions );
    20652187
    20662188                $sql = "UPDATE `$table` SET $fields WHERE $conditions";
    2067                
     2189
    20682190                $this->check_current_query = false;
    2069                 return $this->query( $this->prepare( $sql, $values ) );
     2191                if ( empty( $values ) ) {
     2192                        $values = false; // nothing to prepare
     2193                }
     2194                return $this->query( $sql, $values );
    20702195        }
    20712196
    20722197        /**
    20732198         * Delete a row in the table
    20742199         *
    20752200         *     wpdb::delete( 'table', array( 'ID' => 1 ) )
    20762201         *     wpdb::delete( 'table', array( 'ID' => 1 ), array( '%d' ) )
    20772202         *
    20782203         * @since 3.4.0
    20792204         * @see wpdb::prepare()
    20802205         * @see wpdb::$field_types
    20812206         * @see wp_set_wpdb_vars()
    20822207         *
    20832208         * @param string       $table        Table name
    20842209         * @param array        $where        A named array of WHERE clauses (in column => value pairs).
    class wpdb { 
    20892214         *                                   If string, that format will be used for all of the items in $where.
    20902215         *                                   A format is one of '%d', '%f', '%s' (integer, float, string).
    20912216         *                                   If omitted, all values in $where will be treated as strings unless otherwise specified in wpdb::$field_types.
    20922217         * @return int|false The number of rows updated, or false on error.
    20932218         */
    20942219        public function delete( $table, $where, $where_format = null ) {
    20952220                if ( ! is_array( $where ) ) {
    20962221                        return false;
    20972222                }
    20982223
    20992224                $where = $this->process_fields( $table, $where, $where_format );
    21002225                if ( false === $where ) {
    21012226                        return false;
    21022227                }
    21032228
     2229                $formats_to_placeholders = array_flip( $this->valid_mysqli_prepare_placeholders );
     2230
    21042231                $conditions = $values = array();
    21052232                foreach ( $where as $field => $value ) {
    21062233                        if ( is_null( $value['value'] ) ) {
    21072234                                $conditions[] = "`$field` IS NULL";
    21082235                                continue;
    21092236                        }
    21102237
    2111                         $conditions[] = "`$field` = " . $value['format'];
    2112                         $values[] = $value['value'];
     2238                        $conditions[] = "`$field` = ?";
     2239                        $values[]  = array(
     2240                                'value' => $value['value'],
     2241                                'type' => isset( $formats_to_placeholders[ $value['format'] ] ) ?
     2242                                                 $formats_to_placeholders[ $value['format'] ] :
     2243                                                 's',
     2244                        );
    21132245                }
    21142246
    21152247                $conditions = implode( ' AND ', $conditions );
    21162248
    21172249                $sql = "DELETE FROM `$table` WHERE $conditions";
    21182250
    21192251                $this->check_current_query = false;
    2120                 return $this->query( $this->prepare( $sql, $values ) );
     2252                if ( empty( $values ) ) {
     2253                        $values = false; // Nothing to prepare
     2254                }
     2255                return $this->query( $sql, $values );
    21212256        }
    21222257
    21232258        /**
    21242259         * Processes arrays of field/value pairs and field formats.
    21252260         *
    21262261         * This is a helper method for wpdb's CRUD methods, which take field/value
    21272262         * pairs for inserts, updates, and where clauses. This method first pairs
    21282263         * each value with a format. Then it determines the charset of that field,
    21292264         * using that to determine if any invalid text would be stripped. If text is
    21302265         * stripped, then field processing is rejected and the query fails.
    21312266         *
    21322267         * @since 4.2.0
    21332268         *
    21342269         * @param string $table  Table name.
    21352270         * @param array  $data   Field/value pair.
    class wpdb { 
    22602395
    22612396        /**
    22622397         * Retrieve one variable from the database.
    22632398         *
    22642399         * Executes a SQL query and returns the value from the SQL result.
    22652400         * 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.
    22662401         * If $query is null, this function returns the value in the specified column and row from the previous SQL result.
    22672402         *
    22682403         * @since 0.71
    22692404         *
    22702405         * @param string|null $query Optional. SQL query. Defaults to null, use the result from the previous query.
    22712406         * @param int         $x     Optional. Column of value to return. Indexed from 0.
    22722407         * @param int         $y     Optional. Row of value to return. Indexed from 0.
    22732408         * @return string|null Database query result (as string), or null on failure
    22742409         */
    2275         public function get_var( $query = null, $x = 0, $y = 0 ) {
     2410        public function get_var( $query = null, $prepared_query = false, $x = 0, $y = 0 ) {
     2411                // Back-compat.
     2412                if ( ! is_array( $prepared_query ) && func_num_args() > 1 ) {
     2413                        switch( func_num_args() ) { // zero indexed args
     2414                                case 3:
     2415                                        $y = func_get_arg( 2 );
     2416                                case 2:
     2417                                        $x = func_get_arg( 1 );
     2418                        }
     2419                        $prepared_query = false;
     2420                }
     2421
    22762422                $this->func_call = "\$db->get_var(\"$query\", $x, $y)";
    22772423
    22782424                if ( $this->check_current_query && $this->check_safe_collation( $query ) ) {
    22792425                        $this->check_current_query = false;
    22802426                }
    22812427
    22822428                if ( $query ) {
    2283                         $this->query( $query );
     2429                        $this->query( $query, $prepared_query );
    22842430                }
    22852431
    22862432                // Extract var out of cached results based x,y vals
    22872433                if ( !empty( $this->last_result[$y] ) ) {
    22882434                        $values = array_values( get_object_vars( $this->last_result[$y] ) );
    22892435                }
    22902436
    22912437                // If there is a value return it else return null
    22922438                return ( isset( $values[$x] ) && $values[$x] !== '' ) ? $values[$x] : null;
    22932439        }
    22942440
    22952441        /**
    22962442         * Retrieve one row from the database.
    22972443         *
    22982444         * Executes a SQL query and returns the row from the SQL result.
    22992445         *
    23002446         * @since 0.71
    23012447         *
    23022448         * @param string|null $query  SQL query.
    23032449         * @param string      $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which correspond to
    23042450         *                            an stdClass object, an associative array, or a numeric array, respectively. Default OBJECT.
    23052451         * @param int         $y      Optional. Row to return. Indexed from 0.
    23062452         * @return array|object|null|void Database query result in format specified by $output or null on failure
    23072453         */
    2308         public function get_row( $query = null, $output = OBJECT, $y = 0 ) {
     2454        public function get_row( $query = null, $prepared_query = false, $output = OBJECT, $y = 0 ) {
     2455                // Back-compat.
     2456                if ( ! is_array( $prepared_query ) && func_num_args() > 1 ) {
     2457                        switch( func_num_args() ) { // zero indexed args
     2458                                case 3:
     2459                                        $y = func_get_arg( 2 );
     2460                                case 2:
     2461                                        $output = func_get_arg( 1 );
     2462                        }
     2463                        $prepared_query = false;
     2464                }
     2465
     2466
    23092467                $this->func_call = "\$db->get_row(\"$query\",$output,$y)";
    23102468
    23112469                if ( $this->check_current_query && $this->check_safe_collation( $query ) ) {
    23122470                        $this->check_current_query = false;
    23132471                }
    23142472
    23152473                if ( $query ) {
    2316                         $this->query( $query );
     2474                        $this->query( $query, $prepared_query );
    23172475                } else {
    23182476                        return null;
    23192477                }
    23202478
    23212479                if ( !isset( $this->last_result[$y] ) )
    23222480                        return null;
    23232481
    23242482                if ( $output == OBJECT ) {
    23252483                        return $this->last_result[$y] ? $this->last_result[$y] : null;
    23262484                } elseif ( $output == ARRAY_A ) {
    23272485                        return $this->last_result[$y] ? get_object_vars( $this->last_result[$y] ) : null;
    23282486                } elseif ( $output == ARRAY_N ) {
    23292487                        return $this->last_result[$y] ? array_values( get_object_vars( $this->last_result[$y] ) ) : null;
    23302488                } elseif ( strtoupper( $output ) === OBJECT ) {
    23312489                        // Back compat for OBJECT being previously case insensitive.
    class wpdb { 
    23362494        }
    23372495
    23382496        /**
    23392497         * Retrieve one column from the database.
    23402498         *
    23412499         * Executes a SQL query and returns the column from the SQL result.
    23422500         * If the SQL result contains more than one column, this function returns the column specified.
    23432501         * If $query is null, this function returns the specified column from the previous SQL result.
    23442502         *
    23452503         * @since 0.71
    23462504         *
    23472505         * @param string|null $query Optional. SQL query. Defaults to previous query.
    23482506         * @param int         $x     Optional. Column to return. Indexed from 0.
    23492507         * @return array Database query result. Array indexed from 0 by SQL result row number.
    23502508         */
    2351         public function get_col( $query = null , $x = 0 ) {
     2509        public function get_col( $query = null, $prepared_query = false, $x = 0 ) {
     2510                // Back-compat.
     2511                if ( ! is_array( $prepared_query ) && func_num_args() > 1 ) {
     2512                        $x = func_get_arg( 1 );
     2513                        $prepared_query = false;
     2514                }
     2515
    23522516                if ( $this->check_current_query && $this->check_safe_collation( $query ) ) {
    23532517                        $this->check_current_query = false;
    23542518                }
    23552519
    23562520                if ( $query ) {
    2357                         $this->query( $query );
     2521                        $this->query( $query, $prepared_query );
    23582522                }
    23592523
    23602524                $new_array = array();
    23612525                // Extract the column values
    23622526                for ( $i = 0, $j = count( $this->last_result ); $i < $j; $i++ ) {
    23632527                        $new_array[$i] = $this->get_var( null, $x, $i );
    23642528                }
    23652529                return $new_array;
    23662530        }
    23672531
    23682532        /**
    23692533         * Retrieve an entire SQL result set from the database (i.e., many rows)
    23702534         *
    23712535         * Executes a SQL query and returns the entire SQL result.
    23722536         *
    23732537         * @since 0.71
    23742538         *
    23752539         * @param string $query  SQL query.
    23762540         * @param string $output Optional. Any of ARRAY_A | ARRAY_N | OBJECT | OBJECT_K constants.
    23772541         *                       With one of the first three, return an array of rows indexed from 0 by SQL result row number.
    23782542         *                       Each row is an associative array (column => value, ...), a numerically indexed array (0 => value, ...), or an object. ( ->column = value ), respectively.
    23792543         *                       With OBJECT_K, return an associative array of row objects keyed by the value of each row's first column's value.
    23802544         *                       Duplicate keys are discarded.
    23812545         * @return array|object|null Database query results
    23822546         */
    2383         public function get_results( $query = null, $output = OBJECT ) {
     2547        public function get_results( $query = null, $prepared_query = false, $output = OBJECT ) {
     2548                // Back-compat.
     2549                if ( ! is_array( $prepared_query ) && func_num_args() > 1 ) {
     2550                        $output = func_get_arg( 1 );
     2551                        $prepared_query = false;
     2552                }
     2553
    23842554                $this->func_call = "\$db->get_results(\"$query\", $output)";
    23852555
    23862556                if ( $this->check_current_query && $this->check_safe_collation( $query ) ) {
    23872557                        $this->check_current_query = false;
    23882558                }
    23892559
    23902560                if ( $query ) {
    2391                         $this->query( $query );
     2561                        $this->query( $query, $prepared_query );
    23922562                } else {
    23932563                        return null;
    23942564                }
    23952565
    23962566                $new_array = array();
    23972567                if ( $output == OBJECT ) {
    23982568                        // Return an integer-keyed array of row objects
    23992569                        return $this->last_result;
    24002570                } elseif ( $output == OBJECT_K ) {
    24012571                        // Return an array of row objects with keys from column 1
    24022572                        // (Duplicates are discarded)
    24032573                        foreach ( $this->last_result as $row ) {
    24042574                                $var_by_ref = get_object_vars( $row );
    24052575                                $key = array_shift( $var_by_ref );
    24062576                                if ( ! isset( $new_array[ $key ] ) )