WordPress.org

Make WordPress Core

Ticket #36292: rewrites.diff

File rewrites.diff, 10.8 KB (added by rmccue, 6 years ago)

Part 1: Introduce WP_Rewrite_Rule

  • src/wp-includes/class-wp-rewrite-rule.php

     
     1<?php
     2
     3/**
     4 * Rewrite rule handler.
     5 */
     6class WP_Rewrite_Rule implements WP_Rewrite_RuleInterface {
     7        /**
     8         * Traditional query string/array.
     9         *
     10         * @var string|array `index.php`-prefixed query string, or query argument map.
     11         */
     12        public $query = null;
     13
     14        /**
     15         * Should this rule skip the main query?
     16         *
     17         * @var bool
     18         */
     19        public $skip_main_query = false;
     20
     21        /**
     22         * Constructor.
     23         *
     24         * @param string|array $query Query string/argument map.
     25         */
     26        public function __construct( $query = null ) {
     27                if ( $query ) {
     28                        $this->query = $query;
     29                }
     30        }
     31
     32        /**
     33         * Get string representation of the rule.
     34         *
     35         * Primarily for backwards compatibility.
     36         *
     37         * @return string String representation of the rewrite rule.
     38         */
     39        public function __toString() {
     40                return is_array( $this->query ) ? 'index.php?' . build_query( $this->query ) : $this->query;
     41        }
     42
     43        /**
     44         * Should this rule have query vars parsed?
     45         *
     46         * @return bool
     47         */
     48        public function should_parse_query() {
     49                return (bool) $this->query;
     50        }
     51
     52        /**
     53         * Should this rule skip the main query?
     54         *
     55         * @return bool
     56         */
     57        public function should_skip_main_query() {
     58                return $this->skip_main_query;
     59        }
     60
     61        /**
     62         * Parse pattern matches into query string.
     63         *
     64         * @param array $matches Regex matched groups from `$this->pattern`
     65         * @return string|array Query vars.
     66         */
     67        public function get_query_vars( $matches ) {
     68                if ( ! $this->query ) {
     69                        return '';
     70                }
     71
     72                // Trim the query of everything up to the '?'.
     73                $query = preg_replace( '!^.+\?!', '', $this->query );
     74
     75                // Substitute the substring matches into the query.
     76                $query = addslashes( WP_MatchesMapRegex::apply( $query, $matches ) );
     77
     78                return $query;
     79        }
     80
     81        /**
     82         * Get verbose page match parameter.
     83         *
     84         * @return int|bool Match offset number, or false if non-verbose page pattern.
     85         */
     86        public function get_verbose_page_match() {
     87                if ( ! $this->query ) {
     88                        return false;
     89                }
     90
     91                $matches = preg_match( '/pagename=\$matches\[([0-9]+)\]/', $this->query, $varmatch );
     92                if ( ! $matches ) {
     93                        return false;
     94                }
     95
     96                return $varmatch;
     97        }
     98}
  • src/wp-includes/class-wp-rewrite-ruleinterface.php

     
     1<?php
     2
     3interface WP_Rewrite_RuleInterface {
     4        /**
     5         * Should this rule have query vars parsed?
     6         *
     7         * @return bool
     8         */
     9        public function should_parse_query();
     10
     11        /**
     12         * Parse pattern matches into query string.
     13         *
     14         * @param array $matches Regex matched groups from `$this->pattern`
     15         * @return string|array Query vars.
     16         */
     17        public function get_query_vars( $matches );
     18
     19        /**
     20         * Get verbose page match parameter.
     21         *
     22         * @return int|bool Match offset number, or false if non-verbose page pattern.
     23         */
     24        public function get_verbose_page_match();
     25}
  • src/wp-includes/class-wp-rewrite.php

     
    14541454                 */
    14551455                $this->rules = apply_filters( 'rewrite_rules_array', $this->rules );
    14561456
     1457                // Upgrade registered rules to Rule objects
     1458                $this->rules = $this->upgrade_rules_to_objects( $this->rules );
     1459
    14571460                return $this->rules;
    14581461        }
    14591462
    14601463        /**
     1464         * Convert string-based query-var rules to objects.
     1465         *
     1466         * @param array $rules Map of pattern => string rule or Rule object.
     1467         * @return array Map of pattern => Rule object.
     1468         */
     1469        protected static function upgrade_rules_to_objects( $rules ) {
     1470                foreach ( $rules as $pattern => &$rule ) {
     1471                        if ( ! is_string( $rule ) && ! is_array( $rule ) ) {
     1472                                continue;
     1473                        }
     1474
     1475                        $rule = new WP_Rewrite_Rule( $rule );
     1476                }
     1477
     1478                return $rules;
     1479        }
     1480
     1481        /**
    14611482         * Retrieves the rewrite rules.
    14621483         *
    14631484         * The difference between this method and WP_Rewrite::rewrite_rules() is that
     
    16371658         *                            or 'bottom'. Default 'bottom'.
    16381659         */
    16391660        public function add_rule( $regex, $query, $after = 'bottom' ) {
    1640                 if ( is_array( $query ) ) {
     1661                if ( $query instanceof WP_Rewrite_RuleInterface ) {
     1662                        // Rule objects are for internal rewrites only.
    16411663                        $external = false;
     1664                } elseif ( is_array( $query ) ) {
     1665                        $external = false;
    16421666                        $query = add_query_arg( $query, 'index.php' );
    16431667                } else {
    16441668                        $index = false === strpos( $query, '?' ) ? strlen( $query ) : strpos( $query, '?' );
     
    16511675                if ( $external ) {
    16521676                        $this->add_external_rule( $regex, $query );
    16531677                } else {
     1678                        // Upgrade to rule object
     1679                        $rule = $query;
     1680                        if ( ! ( $rule instanceof WP_Rewrite_RuleInterface ) ) {
     1681                                $rule = new WP_Rewrite_Rule( $query );
     1682                        }
     1683
    16541684                        if ( 'bottom' == $after ) {
    1655                                 $this->extra_rules = array_merge( $this->extra_rules, array( $regex => $query ) );
     1685                                $this->extra_rules = array_merge( $this->extra_rules, array( $regex => $rule ) );
    16561686                        } else {
    1657                                 $this->extra_rules_top = array_merge( $this->extra_rules_top, array( $regex => $query ) );
     1687                                $this->extra_rules_top = array_merge( $this->extra_rules_top, array( $regex => $rule ) );
    16581688                        }
    16591689                }
    16601690        }
  • src/wp-includes/class-wp.php

     
    6565        public $request;
    6666
    6767        /**
    68          * Rewrite rule the request matched.
     68         * Rewrite rule pattern the request matched.
    6969         *
    7070         * @since 2.0.0
    7171         * @access public
     
    7474        public $matched_rule;
    7575
    7676        /**
     77         * Rewrite rule object the request matched.
     78         *
     79         * @access public
     80         * @var WP_Rewrite_RuleInterface
     81         */
     82        public $matched_rule_object;
     83
     84        /**
    7785         * Rewrite query the request matched.
    7886         *
    7987         * @since 2.0.0
     
    218226                                // An empty request could only match against ^$ regex
    219227                                if ( isset( $rewrite['$'] ) ) {
    220228                                        $this->matched_rule = '$';
    221                                         $query = $rewrite['$'];
     229                                        $this->matched_rule_object = $rule = $rewrite['$'];
    222230                                        $matches = array('');
    223231                                }
    224232                        } else {
    225                                 foreach ( (array) $rewrite as $match => $query ) {
     233                                foreach ( (array) $rewrite as $match => $rule ) {
    226234                                        // If the requesting file is the anchor of the match, prepend it to the path info.
    227235                                        if ( ! empty($req_uri) && strpos($match, $req_uri) === 0 && $req_uri != $request )
    228236                                                $request_match = $req_uri . '/' . $request;
     
    230238                                        if ( preg_match("#^$match#", $request_match, $matches) ||
    231239                                                preg_match("#^$match#", urldecode($request_match), $matches) ) {
    232240
    233                                                 if ( $wp_rewrite->use_verbose_page_rules && preg_match( '/pagename=\$matches\[([0-9]+)\]/', $query, $varmatch ) ) {
     241                                                $varmatch = $rule->get_verbose_page_match();
     242                                                if ( $wp_rewrite->use_verbose_page_rules && $varmatch ) {
    234243                                                        // This is a verbose page match, let's check to be sure about it.
    235244                                                        $page = get_page_by_path( $matches[ $varmatch[1] ] );
    236245                                                        if ( ! $page ) {
     
    246255
    247256                                                // Got a match.
    248257                                                $this->matched_rule = $match;
     258                                                $this->matched_rule_object = $rule;
    249259                                                break;
    250260                                        }
    251261                                }
    252262                        }
    253263
    254                         if ( isset( $this->matched_rule ) ) {
    255                                 // Trim the query of everything up to the '?'.
    256                                 $query = preg_replace("!^.+\?!", '', $query);
    257 
     264                        if ( isset( $this->matched_rule ) && $rule->should_parse_query() ) {
    258265                                // Substitute the substring matches into the query.
    259                                 $query = addslashes(WP_MatchesMapRegex::apply($query, $matches));
     266                                $this->matched_query = $query = $rule->get_query_vars( $matches );
    260267
    261                                 $this->matched_query = $query;
    262 
    263268                                // Parse the query.
    264269                                parse_str($query, $perma_query_vars);
    265270
     
    279284                        }
    280285                }
    281286
     287                if ( ! $rule || $rule->should_parse_query() ) {
     288                        $this->generate_query_vars( $perma_query_vars );
     289                }
     290
    282291                /**
     292                 * Filter the array of parsed query variables.
     293                 *
     294                 * @since 2.1.0
     295                 *
     296                 * @param array $query_vars The array of requested query variables.
     297                 */
     298                $this->query_vars = apply_filters( 'request', $this->query_vars );
     299
     300                /**
     301                 * Fires once all query variables for the current request have been parsed.
     302                 *
     303                 * @since 2.1.0
     304                 *
     305                 * @param WP &$this Current WordPress environment instance (passed by reference).
     306                 */
     307                do_action_ref_array( 'parse_request', array( &$this ) );
     308        }
     309
     310        protected function generate_query_vars( $perma_query_vars ) {
     311                /**
    283312                 * Filter the query variables whitelist before processing.
    284313                 *
    285314                 * Allows (publicly allowed) query vars to be added, removed, or changed prior
     
    365394
    366395                if ( isset($error) )
    367396                        $this->query_vars['error'] = $error;
    368 
    369                 /**
    370                  * Filter the array of parsed query variables.
    371                  *
    372                  * @since 2.1.0
    373                  *
    374                  * @param array $query_vars The array of requested query variables.
    375                  */
    376                 $this->query_vars = apply_filters( 'request', $this->query_vars );
    377 
    378                 /**
    379                  * Fires once all query variables for the current request have been parsed.
    380                  *
    381                  * @since 2.1.0
    382                  *
    383                  * @param WP &$this Current WordPress environment instance (passed by reference).
    384                  */
    385                 do_action_ref_array( 'parse_request', array( &$this ) );
    386397        }
    387398
    388399        /**
     
    605616        public function query_posts() {
    606617                global $wp_the_query;
    607618                $this->build_query_string();
    608                 $wp_the_query->query($this->query_vars);
     619                $wp_the_query->query( $this->query_vars );
    609620        }
    610621
    611622        /**
     
    723734                $this->init();
    724735                $this->parse_request($query_args);
    725736                $this->send_headers();
    726                 $this->query_posts();
    727                 $this->handle_404();
    728                 $this->register_globals();
    729737
     738                $skip = $this->matched_rule_object ? $this->matched_rule_object->should_skip_main_query() : false;
     739
    730740                /**
     741                 * Filter whether the main query should be skipped.
     742                 *
     743                 * @param bool
     744                 */
     745                $skip = apply_filters( 'skip_main_query', $skip, $this->matched_rule );
     746                if ( ! $skip ) {
     747                        $this->query_posts();
     748                        $this->handle_404();
     749                        $this->register_globals();
     750                }
     751
     752                /**
    731753                 * Fires once the WordPress environment has been set up.
    732754                 *
    733755                 * @since 2.1.0
  • src/wp-settings.php

     
    158158require( ABSPATH . WPINC . '/comment-template.php' );
    159159require( ABSPATH . WPINC . '/rewrite.php' );
    160160require( ABSPATH . WPINC . '/class-wp-rewrite.php' );
     161require( ABSPATH . WPINC . '/class-wp-rewrite-ruleinterface.php' );
     162require( ABSPATH . WPINC . '/class-wp-rewrite-rule.php' );
    161163require( ABSPATH . WPINC . '/feed.php' );
    162164require( ABSPATH . WPINC . '/bookmark.php' );
    163165require( ABSPATH . WPINC . '/bookmark-template.php' );