WordPress.org

Make WordPress Core

Ticket #18877: 18877.4.diff

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

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

     
    210210                                $requested_path = $req_uri;
    211211                        }
    212212                        $requested_file = $req_uri;
    213 
    214213                        $this->request = $requested_path;
     214                        $rewrite_match = $wp_rewrite->find_match( $requested_path, $requested_file, $rewrite );
    215215
    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 
     216                        if ( $rewrite_match ) {
     217                                $this->matched_rule = $rewrite_match[0];
     218                                $this->matched_query = $rewrite_match[1];
    264219                                // Parse the query.
    265                                 parse_str($query, $perma_query_vars);
     220                                parse_str($this->matched_query, $perma_query_vars);
    266221
    267222                                // If we're processing a 404 request, clear the error var since we found something.
    268223                                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 * @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}