WordPress.org

Make WordPress Core

Ticket #18877: 18877.6.diff

File 18877.6.diff, 13.4 KB (added by ericlewis, 4 years ago)
  • src/wp-includes/class-wp-rewrite.php

     
    19381938        }
    19391939
    19401940        /**
     1941         * Get the rewrite rule that matches a request.
     1942         *
     1943         * @since 4.6.0
     1944         *
     1945         * @param string $requested_path  The URL path to match against.
     1946         * @param string $requested_file  The requested file, for PATHINFO links.
     1947         * @return array|false $rewritten If a rule matches, an array containing
     1948         *                                the match and the query.
     1949         *                                False otherwise.
     1950         */
     1951        public function get_rewrite_rule_for_request( $requested_path, $requested_file ) {
     1952                $rewrite_rules = $this->wp_rewrite_rules();
     1953                if ( empty( $rewrite_rules ) ) {
     1954                        return false;
     1955                }
     1956
     1957                // Look for matches.
     1958                $request_match = $requested_path;
     1959                if ( empty( $request_match ) ) {
     1960                        // An empty request could only match against ^$ regex
     1961                        if ( isset( $rewrite_rules['$'] ) ) {
     1962                                $matched_regex = '$';
     1963                                $query = $rewrite_rules['$'];
     1964                                $matches = array('');
     1965                        }
     1966                } else {
     1967                        foreach ( (array) $rewrite_rules as $regex => $query ) {
     1968                                // If the requesting file is the anchor of the match, prepend it to the path info.
     1969                                if ( ! empty($requested_file) && strpos($regex, $requested_file) === 0 && $requested_file != $requested_path )
     1970                                        $request_match = $requested_file . '/' . $requested_path;
     1971
     1972                                if ( preg_match("#^$regex#", $request_match, $matches) ||
     1973                                        preg_match("#^$regex#", urldecode($request_match), $matches) ) {
     1974
     1975                                        if ( $this->use_verbose_page_rules && preg_match( '/pagename=\$matches\[([0-9]+)\]/', $query, $varmatch ) ) {
     1976                                                // This is a verbose page match, let's check to be sure about it.
     1977                                                $page = get_page_by_path( $matches[ $varmatch[1] ] );
     1978                                                if ( ! $page ) {
     1979                                                        continue;
     1980                                                }
     1981
     1982                                                $post_status_obj = get_post_status_object( $page->post_status );
     1983                                                if ( ! $post_status_obj->public && ! $post_status_obj->protected
     1984                                                        && ! $post_status_obj->private && $post_status_obj->exclude_from_search ) {
     1985                                                        continue;
     1986                                                }
     1987                                        }
     1988
     1989                                        // Got a match.
     1990                                        $matched_regex = $regex;
     1991                                        break;
     1992                                }
     1993                        }
     1994                }
     1995                if ( isset( $matched_regex ) ) {
     1996                        // Trim the query of everything up to the '?'.
     1997                        $query = preg_replace("!^.+\?!", '', $query);
     1998
     1999                        // Substitute the substring matches into the query.
     2000                        $query = addslashes(WP_MatchesMapRegex::apply($query, $matches));
     2001
     2002                        return array( $matched_regex, $query );
     2003                } else {
     2004                        return false;
     2005                }
     2006        }
     2007
     2008        /**
    19412009         * Constructor - Calls init(), which runs setup.
    19422010         *
    19432011         * @since 1.5.0
  • src/wp-includes/class-wp.php

     
    212212                        $requested_file = $req_uri;
    213213
    214214                        $this->request = $requested_path;
     215                        $rewrite_match = $wp_rewrite->get_rewrite_rule_for_request( $requested_path, $requested_file );
    215216
    216                         // Look for matches.
    217                         $request_match = $requested_path;
    218                         if ( empty( $request_match ) ) {
    219                                 // An empty request could only match against ^$ regex
    220                                 if ( isset( $rewrite['$'] ) ) {
    221                                         $this->matched_rule = '$';
    222                                         $query = $rewrite['$'];
    223                                         $matches = array('');
    224                                 }
    225                         } else {
    226                                 foreach ( (array) $rewrite as $match => $query ) {
    227                                         // If the requested file is the anchor of the match, prepend it to the path info.
    228                                         if ( ! empty($requested_file) && strpos($match, $requested_file) === 0 && $requested_file != $requested_path )
    229                                                 $request_match = $requested_file . '/' . $requested_path;
    230 
    231                                         if ( preg_match("#^$match#", $request_match, $matches) ||
    232                                                 preg_match("#^$match#", urldecode($request_match), $matches) ) {
    233 
    234                                                 if ( $wp_rewrite->use_verbose_page_rules && preg_match( '/pagename=\$matches\[([0-9]+)\]/', $query, $varmatch ) ) {
    235                                                         // This is a verbose page match, let's check to be sure about it.
    236                                                         $page = get_page_by_path( $matches[ $varmatch[1] ] );
    237                                                         if ( ! $page ) {
    238                                                                 continue;
    239                                                         }
    240 
    241                                                         $post_status_obj = get_post_status_object( $page->post_status );
    242                                                         if ( ! $post_status_obj->public && ! $post_status_obj->protected
    243                                                                 && ! $post_status_obj->private && $post_status_obj->exclude_from_search ) {
    244                                                                 continue;
    245                                                         }
    246                                                 }
    247 
    248                                                 // Got a match.
    249                                                 $this->matched_rule = $match;
    250                                                 break;
    251                                         }
    252                                 }
    253                         }
    254 
    255                         if ( isset( $this->matched_rule ) ) {
    256                                 // Trim the query of everything up to the '?'.
    257                                 $query = preg_replace("!^.+\?!", '', $query);
    258 
    259                                 // Substitute the substring matches into the query.
    260                                 $query = addslashes(WP_MatchesMapRegex::apply($query, $matches));
    261 
    262                                 $this->matched_query = $query;
    263 
     217                        if ( $rewrite_match ) {
     218                                $this->matched_rule = $rewrite_match[0];
     219                                $this->matched_query = $rewrite_match[1];
    264220                                // Parse the query.
    265                                 parse_str($query, $perma_query_vars);
     221                                parse_str($this->matched_query, $perma_query_vars);
    266222
    267223                                // If we're processing a 404 request, clear the error var since we found something.
    268224                                if ( '404' == $error )
  • src/wp-includes/rewrite.php

     
    539539        }
    540540
    541541        // Look for matches.
    542         $request_match = $request;
    543         foreach ( (array)$rewrite as $match => $query) {
     542        $rewrite_match = $wp_rewrite->get_rewrite_rule_for_request( $request, $url );
     543        if ( $rewrite_match ) {
     544                $match = $rewrite_match[0];
     545                $query = $rewrite_match[1];
    544546
    545                 // If the requesting file is the anchor of the match, prepend it
    546                 // to the path info.
    547                 if ( !empty($url) && ($url != $request) && (strpos($match, $url) === 0) )
    548                         $request_match = $url . '/' . $request;
    549 
    550                 if ( preg_match("#^$match#", $request_match, $matches) ) {
    551 
    552                         if ( $wp_rewrite->use_verbose_page_rules && preg_match( '/pagename=\$matches\[([0-9]+)\]/', $query, $varmatch ) ) {
    553                                 // This is a verbose page match, let's check to be sure about it.
    554                                 $page = get_page_by_path( $matches[ $varmatch[1] ] );
    555                                 if ( ! $page ) {
    556                                         continue;
     547                // Filter out non-public query vars
     548                global $wp;
     549                parse_str( $query, $query_vars );
     550                $query = array();
     551                foreach ( (array) $query_vars as $key => $value ) {
     552                        if ( in_array( $key, $wp->public_query_vars ) ){
     553                                $query[$key] = $value;
     554                                if ( isset( $post_type_query_vars[$key] ) ) {
     555                                        $query['post_type'] = $post_type_query_vars[$key];
     556                                        $query['name'] = $value;
    557557                                }
    558 
    559                                 $post_status_obj = get_post_status_object( $page->post_status );
    560                                 if ( ! $post_status_obj->public && ! $post_status_obj->protected
    561                                         && ! $post_status_obj->private && $post_status_obj->exclude_from_search ) {
    562                                         continue;
    563                                 }
    564558                        }
     559                }
    565560
    566                         // Got a match.
    567                         // Trim the query of everything up to the '?'.
    568                         $query = preg_replace("!^.+\?!", '', $query);
     561                // Resolve conflicts between posts with numeric slugs and date archive queries.
     562                $query = wp_resolve_numeric_slug_conflicts( $query );
    569563
    570                         // Substitute the substring matches into the query.
    571                         $query = addslashes(WP_MatchesMapRegex::apply($query, $matches));
    572 
    573                         // Filter out non-public query vars
    574                         global $wp;
    575                         parse_str( $query, $query_vars );
    576                         $query = array();
    577                         foreach ( (array) $query_vars as $key => $value ) {
    578                                 if ( in_array( $key, $wp->public_query_vars ) ){
    579                                         $query[$key] = $value;
    580                                         if ( isset( $post_type_query_vars[$key] ) ) {
    581                                                 $query['post_type'] = $post_type_query_vars[$key];
    582                                                 $query['name'] = $value;
    583                                         }
    584                                 }
    585                         }
    586 
    587                         // Resolve conflicts between posts with numeric slugs and date archive queries.
    588                         $query = wp_resolve_numeric_slug_conflicts( $query );
    589 
    590                         // Do the query
    591                         $query = new WP_Query( $query );
    592                         if ( ! empty( $query->posts ) && $query->is_singular )
    593                                 return $query->post->ID;
    594                         else
    595                                 return 0;
    596                 }
     564                // Do the query
     565                $query = new WP_Query( $query );
     566                if ( ! empty( $query->posts ) && $query->is_singular )
     567                        return $query->post->ID;
     568                else
     569                        return 0;
    597570        }
    598571        return 0;
    599572}
  • tests/phpunit/tests/rewrite/getRewriteRuleForRequest.php

     
     1<?php
     2
     3/**
     4 * @group rewrite
     5 */
     6class Tests_Rewrite_FindMatch extends WP_UnitTestCase {
     7
     8        public function test_get_rewrite_rule_for_request_for_front_page() {
     9                global $wp_rewrite;
     10
     11                $rules = array( '$' => 'index.php?page=home' );
     12                update_option( 'rewrite_rules', $rules );
     13                $match = $wp_rewrite->get_rewrite_rule_for_request( '', '' );
     14                $this->assertSame( 'page=home', $match[1] );
     15        }
     16
     17        public function test_get_rewrite_rule_for_request() {
     18                global $wp_rewrite;
     19
     20                $rules = array(
     21                        'page/?([0-9]{1,})/?$' => 'index.php?paged=$matches[1]',
     22                        'search/(.+)/?$' => 'index.php?s=$matches[1]',
     23                        'blog/author/([^/]+)/page/?([0-9]{1,})/?$' => 'index.php?author_name=$matches[1]&paged=$matches[2]',
     24                        'blog/([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})/?$' => 'index.php?year=$matches[1]&monthnum=$matches[2]&day=$matches[3]',
     25                );
     26                update_option( 'rewrite_rules', $rules );
     27
     28                $match = $wp_rewrite->get_rewrite_rule_for_request( 'page/2', '' );
     29                $this->assertSame( 'paged=2', $match[1] );
     30
     31                $match = $wp_rewrite->get_rewrite_rule_for_request( 'search/kombucha', '' );
     32                $this->assertSame( 's=kombucha', $match[1] );
     33
     34                $match = $wp_rewrite->get_rewrite_rule_for_request( 'blog/author/glerf/page/29', '' );
     35                $this->assertSame( 'author_name=glerf&paged=29', $match[1] );
     36
     37                $match = $wp_rewrite->get_rewrite_rule_for_request( 'blog/2015/06/29', '', $rules );
     38                $this->assertSame( 'year=2015&monthnum=06&day=29', $match[1] );
     39        }
     40
     41        public function test_match_page_with_verbose_page_rules_on() {
     42                global $wp_rewrite;
     43                $this->set_permalink_structure( '/%postname%/' );
     44
     45                $page = self::factory()->post->create( array(
     46                        'post_type' => 'page',
     47                        'post_status' => 'publish',
     48                        'post_name' => 'how-to-brew-kombucha',
     49                ) );
     50
     51                $rules = array(
     52                        '(.?.+?)(?:/([0-9]+))?/?$' => 'index.php?pagename=$matches[1]&page=$matches[2]',
     53                        '([^/]+)(?:/([0-9]+))?/?$' => 'index.php?name=$matches[1]&page=$matches[2]',
     54                );
     55                update_option( 'rewrite_rules', $rules );
     56
     57                $match = $wp_rewrite->get_rewrite_rule_for_request( 'how-to-brew-kombucha', 'how-to-brew-kombucha' );
     58                $expected = 'pagename=how-to-brew-kombucha&page=';
     59                $this->assertSame( $expected, $match[1] );
     60
     61                $this->set_permalink_structure();
     62        }
     63
     64        public function test_skip_page_rule_if_page_doesnt_exist_with_verbose_page_rules_on() {
     65                global $wp_rewrite;
     66                $this->set_permalink_structure( '/%postname%/' );
     67
     68                $page = self::factory()->post->create( array(
     69                        'post_type' => 'page',
     70                        'post_status' => 'publish',
     71                        'post_name' => 'how-to-brew-kombucha',
     72                ) );
     73
     74                $rules = array(
     75                        '(.?.+?)(?:/([0-9]+))?/?$' => 'index.php?pagename=$matches[1]&page=$matches[2]',
     76                        '([^/]+)(?:/([0-9]+))?/?$' => 'index.php?name=$matches[1]&page=$matches[2]',
     77                );
     78                update_option( 'rewrite_rules', $rules );
     79
     80                $match = $wp_rewrite->get_rewrite_rule_for_request( 'a-vertical-garden-design-for-urban-living', 'a-vertical-garden-design-for-urban-living' );
     81                $expected = 'name=a-vertical-garden-design-for-urban-living&page=';
     82                $this->assertSame( $expected, $match[1] );
     83
     84                $this->set_permalink_structure();
     85        }
     86
     87        public function test_skip_page_rule_for_a_trashed_page_with_verbose_page_rules_on() {
     88                global $wp_rewrite;
     89                $this->set_permalink_structure( '/%postname%/' );
     90
     91                $trashed_page = self::factory()->post->create( array(
     92                        'post_type' => 'page',
     93                        'post_status' => 'trash',
     94                        'post_name' => 'how-to-brew-kombucha',
     95                ) );
     96
     97                $rules = array(
     98                        '(.?.+?)(?:/([0-9]+))?/?$' => 'index.php?pagename=$matches[1]&page=$matches[2]',
     99                        '([^/]+)(?:/([0-9]+))?/?$' => 'index.php?name=$matches[1]&page=$matches[2]',
     100                );
     101                update_option( 'rewrite_rules', $rules );
     102
     103                $match = $wp_rewrite->get_rewrite_rule_for_request( 'how-to-brew-kombucha', 'how-to-brew-kombucha' );
     104                $expected = 'name=how-to-brew-kombucha&page=';
     105                $this->assertSame( $expected, $match[1] );
     106
     107                $this->set_permalink_structure();
     108        }
     109
     110        public function test_get_rewrite_rule_for_request_with_path_info_links() {
     111                global $wp_rewrite;
     112
     113                $rules = array(
     114                        'index.php/page/?([0-9]{1,})/?$' => 'index.php?paged=$matches[1]',
     115                        'index.php/search/(.+)/?$' => 'index.php?s=$matches[1]',
     116                        'index.php/blog/author/([^/]+)/page/?([0-9]{1,})/?$' => 'index.php?author_name=$matches[1]&paged=$matches[2]',
     117                        'index.php/blog/([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})/?$' => 'index.php?year=$matches[1]&monthnum=$matches[2]&day=$matches[3]',
     118                );
     119                update_option( 'rewrite_rules', $rules );
     120
     121                $match = $wp_rewrite->get_rewrite_rule_for_request( 'page/2', 'index.php' );
     122                $this->assertSame( 'paged=2', $match[1] );
     123
     124                $match = $wp_rewrite->get_rewrite_rule_for_request( 'search/kombucha', 'index.php' );
     125                $this->assertSame( 's=kombucha', $match[1] );
     126
     127                $match = $wp_rewrite->get_rewrite_rule_for_request( 'blog/author/glerf/page/29', 'index.php' );
     128                $this->assertSame( 'author_name=glerf&paged=29', $match[1] );
     129
     130                $match = $wp_rewrite->get_rewrite_rule_for_request( 'blog/2015/06/29', 'index.php' );
     131                $this->assertSame( 'year=2015&monthnum=06&day=29', $match[1] );
     132        }
     133}