WordPress.org

Make WordPress Core

Ticket #25559: wp-db_mods.patch

File wp-db_mods.patch, 4.9 KB (added by cannona, 7 years ago)

A first stab at a patch.

  • wp-includes/wp-db.php

     
    953953        }
    954954
    955955        /**
    956          * Prepares a SQL query for safe execution. Uses sprintf()-like syntax.
     956         * Flattens an array, removing any nested arrays and bringing all their
     957         * non-array items up to the top level.
    957958         *
     959         * This method processes the passed array depth-first.
     960         * It will flatten arrays inside arrays, no matter how deeply nested, limited
     961         * only by PHP's recursion limit.
     962         *
     963         * @access private
     964         * @param array $array The array to flatten.
     965         * @return array|mixed The flattened array if an array was passed, otherwise whatever was passed is returned unmodified.
     966         */
     967        function _flatten_array( $array ) {
     968                if ( !is_array( $array ) )
     969                        return $array;
     970                $new_array = array();
     971                foreach ( $array as $item ) {
     972                        if ( is_array( $item ) )
     973                                $new_array = array_merge( $new_array, $this->_flatten_array( $item ) );
     974                        else
     975                                $new_array[] = $item;
     976                }
     977                return $new_array;
     978        }
     979
     980        /**
     981         * A callback function to replace repeated tokens via a regular expression.
     982         *
     983         * For example:
     984         * %#3s would be replaced with %s,%s,%s
     985         * %#1d would be replaced with %d
     986         * %#0f would be replaced with an empty string, or in other words, it would be removed.
     987         *
     988         * @access private
     989         * @param array $matches The matches array from preg_replace_callback
     990         * @return string The replacement string
     991         */
     992        function _expand_repeated_params( $matches ) {
     993                $replacement = '%' . $matches[2];
     994                $replacements = array_fill( 0, $matches[1], $replacement );
     995                return implode( ',', $replacements );
     996        }
     997
     998        /**
     999         * Prepares an SQL query for safe execution. Uses sprintf()-like syntax.
     1000         *
    9581001         * The following directives can be used in the query format string:
    9591002         *   %d (integer)
    9601003         *   %f (float)
    9611004         *   %s (string)
     1005         * %#<num>d (num integers)
     1006         * %#<num>f (num floats)
     1007         * %#<num>s (num strings)
    9621008         *   %% (literal percentage sign - no argument needed)
     1009         * Where num is an integer >= 0.
    9631010         *
    964          * All of %d, %f, and %s are to be left unquoted in the query string and they need an argument passed for them.
     1011         * All of %d, %f, and %s are to be left unquoted in the query string, and they need an argument passed for them.
     1012         * Repeated integers, floats, or strings must have as many arguments as their number specifies, and must also be left unquoted.
    9651013         * Literals (%) as parts of the query must be properly written as %%.
    9661014         *
    9671015         * This function only supports a small subset of the sprintf syntax; it only supports %d (integer), %f (float), and %s (string).
     1016         * It also supports repeated forms of the above, which are not supported by sprintf.
    9681017         * Does not support sign, padding, alignment, width or precision specifiers.
    9691018         * Does not support argument numbering/swapping.
    9701019         *
    9711020         * May be called like {@link http://php.net/sprintf sprintf()} or like {@link http://php.net/vsprintf vsprintf()}.
     1021         * Any arrays inside the arguments passed will be flattened, so you can pass
     1022         * multiple arrays or even arrays containing arrays, and it will be the same
     1023         * as just passing the integer, float or string values from those arrays.
    9721024         *
    973          * Both %d and %s should be left unquoted in the query string.
     1025         * All integer, float and string directives should be left unquoted.
    9741026         *
    9751027         * <code>
    976          * wpdb::prepare( "SELECT * FROM `table` WHERE `column` = %s AND `field` = %d", 'foo', 1337 )
     1028         * wpdb::prepare( "SELECT * FROM `table` WHERE `column` = %s AND `field` = %d", 'foo', 1337 );
     1029         * wpdb::prepare( "SELECT * FROM `table` WHERE `column` in (%#3d) AND `field` = %s", array( 1, 2, 3 ), 'foo' );
    9771030         * wpdb::prepare( "SELECT DATE_FORMAT(`field`, '%%c') FROM `table` WHERE `column` = %s", 'foo' );
    9781031         * </code>
    9791032         *
     
    9951048
    9961049                $args = func_get_args();
    9971050                array_shift( $args );
    998                 // If args were passed as an array (as in vsprintf), move them up
    999                 if ( isset( $args[0] ) && is_array($args[0]) )
    1000                         $args = $args[0];
    1001                 $query = str_replace( "'%s'", '%s', $query ); // in case someone mistakenly already singlequoted it
    1002                 $query = str_replace( '"%s"', '%s', $query ); // doublequote unquoting
    1003                 $query = preg_replace( '|(?<!%)%f|' , '%F', $query ); // Force floats to be locale unaware
     1051                // Flatten the args passed to bring all items out of arrays.
     1052                $args = $this->_flatten_array( $args );
     1053                $query = preg_replace( '|([\'"])(%(?:#\d+)?s)\1|', '$2', $query ); // in case someone mistakenly already single or double quoted it
     1054                $query = preg_replace( '|(?<!%)%f|', '%F', $query ); // Force floats to be locale unaware
     1055                $query = preg_replace_callback( '|(?<!%)%#(\d+)([dfs])|', array($this, '_expand_repeated_params'), $query ); // Expand the repeated parameters.
    10041056                $query = preg_replace( '|(?<!%)%s|', "'%s'", $query ); // quote the strings, avoiding escaped strings like %%s
    10051057                array_walk( $args, array( $this, 'escape_by_ref' ) );
    10061058                return @vsprintf( $query, $args );