WordPress.org

Make WordPress Core

Ticket #18877: 18877.5.diff

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

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

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