WordPress.org

Make WordPress Core

Ticket #18877: 18877.3.diff

File 18877.3.diff, 12.1 KB (added by ericlewis, 5 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 $req_uri 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( $request, $req_uri, $rewrite_rules ) {
     1956                $found_match = false;
     1957                // Look for matches.
     1958                $request_match = $request;
     1959                if ( empty( $request_match ) ) {
     1960                        // An empty request could only match against ^$ regex
     1961                        if ( isset( $rewrite_rules['$'] ) ) {
     1962                                $this->matched_rule = '$';
     1963                                $query = $rewrite_rules['$'];
     1964                                $matches = array('');
     1965                        }
     1966                } else {
     1967                        foreach ( (array) $rewrite_rules as $match => $query ) {
     1968                                // If the requesting file is the anchor of the match, prepend it to the path info.
     1969                                if ( ! empty($req_uri) && strpos($match, $req_uri) === 0 && $req_uri != $request )
     1970                                        $request_match = $req_uri . '/' . $request;
     1971
     1972                                if ( preg_match("#^$match#", $request_match, $matches) ||
     1973                                        preg_match("#^$match#", 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                                        $found_match = true;
     1991                                        break;
     1992                                }
     1993                        }
     1994                }
     1995
     1996                if ( $found_match ) {
     1997                        // Trim the query of everything up to the '?'.
     1998                        $query = preg_replace("!^.+\?!", '', $query);
     1999
     2000                        // Substitute the substring matches into the query.
     2001                        $query = addslashes(WP_MatchesMapRegex::apply($query, $matches));
     2002
     2003                        return array( $match, $query );
     2004                } else {
     2005                        return false;
     2006                }
     2007        }
     2008
     2009        /**
    19412010         * Constructor - Calls init(), which runs setup.
    19422011         *
    19432012         * @since 1.5.0
  • src/wp-includes/class-wp.php

     
    200200
    201201                        $this->request = $request;
    202202
    203                         // Look for matches.
    204                         $request_match = $request;
    205                         if ( empty( $request_match ) ) {
    206                                 // An empty request could only match against ^$ regex
    207                                 if ( isset( $rewrite['$'] ) ) {
    208                                         $this->matched_rule = '$';
    209                                         $query = $rewrite['$'];
    210                                         $matches = array('');
    211                                 }
    212                         } else {
    213                                 foreach ( (array) $rewrite as $match => $query ) {
    214                                         // If the requesting file is the anchor of the match, prepend it to the path info.
    215                                         if ( ! empty($req_uri) && strpos($match, $req_uri) === 0 && $req_uri != $request )
    216                                                 $request_match = $req_uri . '/' . $request;
     203                        $result = $wp_rewrite->find_match( $request, $req_uri, $rewrite );
    217204
    218                                         if ( preg_match("#^$match#", $request_match, $matches) ||
    219                                                 preg_match("#^$match#", urldecode($request_match), $matches) ) {
     205                        if ( $result ) {
     206                                $this->matched_rule = $result[0];
     207                                $this->matched_query = $result[1];
    220208
    221                                                 if ( $wp_rewrite->use_verbose_page_rules && preg_match( '/pagename=\$matches\[([0-9]+)\]/', $query, $varmatch ) ) {
    222                                                         // This is a verbose page match, let's check to be sure about it.
    223                                                         $page = get_page_by_path( $matches[ $varmatch[1] ] );
    224                                                         if ( ! $page ) {
    225                                                                 continue;
    226                                                         }
    227 
    228                                                         $post_status_obj = get_post_status_object( $page->post_status );
    229                                                         if ( ! $post_status_obj->public && ! $post_status_obj->protected
    230                                                                 && ! $post_status_obj->private && $post_status_obj->exclude_from_search ) {
    231                                                                 continue;
    232                                                         }
    233                                                 }
    234 
    235                                                 // Got a match.
    236                                                 $this->matched_rule = $match;
    237                                                 break;
    238                                         }
    239                                 }
    240                         }
    241 
    242                         if ( isset( $this->matched_rule ) ) {
    243                                 // Trim the query of everything up to the '?'.
    244                                 $query = preg_replace("!^.+\?!", '', $query);
    245 
    246                                 // Substitute the substring matches into the query.
    247                                 $query = addslashes(WP_MatchesMapRegex::apply($query, $matches));
    248 
    249                                 $this->matched_query = $query;
    250 
    251209                                // Parse the query.
    252                                 parse_str($query, $perma_query_vars);
     210                                parse_str($this->matched_query, $perma_query_vars);
    253211
    254212                                // If we're processing a 404 request, clear the error var since we found something.
    255213                                if ( '404' == $error )
  • src/wp-includes/rewrite.php

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

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