WordPress.org

Make WordPress Core

Ticket #5305: 5305.11.diff

File 5305.11.diff, 18.6 KB (added by valendesigns, 5 years ago)
  • src/wp-includes/class-wp.php

    diff --git src/wp-includes/class-wp.php src/wp-includes/class-wp.php
    index a079c12..5bb6883 100644
    class WP { 
    306306                        }
    307307                }
    308308
     309                // Resolve conflicts between posts with numeric slugs and date archive queries.
     310                $this->query_vars = _resolve_numeric_slug_conflicts( $this->query_vars );
     311
    309312                foreach ( (array) $this->private_query_vars as $var) {
    310313                        if ( isset($this->extra_query_vars[$var]) )
    311314                                $this->query_vars[$var] = $this->extra_query_vars[$var];
  • src/wp-includes/rewrite.php

    diff --git src/wp-includes/rewrite.php src/wp-includes/rewrite.php
    index 2529228..115254d 100644
    function _wp_filter_taxonomy_base( $base ) { 
    275275}
    276276
    277277/**
     278 * Resolve numeric slugs that collide with date permalinks.
     279 *
     280 * Permalinks of posts with numeric slugs can sometimes look to `WP_Query::parse_query()` like a date archive,
     281 * as when your permalink structure is `/%year%/%postname%/` and a post with post_name '05' has the URL
     282 * `/2015/05/`. This function detects these conflicts and resolves conflicts in favor of the post permalink.
     283 *
     284 * @since 4.2.0
     285 * @access private
     286 *
     287 * @param array $query_vars Query variables for setting up the WordPress Query Loop.
     288 * @return array
     289 */
     290function _resolve_numeric_slug_conflicts( $query_vars = array() ) {
     291        if ( ! isset( $query_vars['year'] ) && ! isset( $query_vars['monthnum'] ) && ! isset( $query_vars['day'] ) ) {
     292                return $query_vars;
     293        }
     294
     295        // Identify the 'postname' position in the permastruct array.
     296        $permastructs   = array_values( array_filter( explode( '/', get_option( 'permalink_structure' ) ) ) );
     297        $postname_index = array_search( '%postname%', $permastructs );
     298
     299        if ( false === $postname_index ) {
     300                return $query_vars;
     301        }
     302
     303        /*
     304         * A numeric slug could be confused with a year, month, or day, depending on position. To account for
     305         * the possibility of post pagination (eg 2015/2 for the second page of a post called '2015'), our
     306         * `is_*` checks are generous: check for year-slug clashes when `is_year` *or* `is_month`, and check
     307         * for month-slug clashes when `is_month` *or* `is_day`.
     308         */
     309        $compare = '';
     310        if ( 0 === $postname_index && ( isset( $query_vars['year'] ) || isset( $query_vars['monthnum'] ) ) ) {
     311                $compare = 'year';
     312        } else if ( '%year%' === $permastructs[ $postname_index - 1 ] && ( isset( $query_vars['monthnum'] ) || isset( $query_vars['day'] ) ) ) {
     313                $compare = 'monthnum';
     314        } else if ( '%monthnum%' === $permastructs[ $postname_index - 1 ] && isset( $query_vars['day'] ) ) {
     315                $compare = 'day';
     316        }
     317
     318        if ( ! $compare ) {
     319                return $query_vars;
     320        }
     321
     322        // This is the potentially clashing slug.
     323        $value = $query_vars[$compare];
     324
     325        $post = get_page_by_path( $value, OBJECT, 'post' );
     326        if ( ! ( $post instanceof WP_Post ) ) {
     327                return $query_vars;
     328        }
     329
     330        /*
     331         * If the located post contains nextpage pagination, then the URL chunk following postname may be
     332         * intended as the page number. Verify that it's a valid page before resolving to it.
     333         */
     334        $maybe_page = '';
     335        if ( 'year' === $compare && isset( $query_vars['monthnum'] ) ) {
     336                $maybe_page = $query_vars['monthnum'];
     337        } else if ( 'monthnum' === $compare && isset( $query_vars['day'] ) ) {
     338                $maybe_page = $query_vars['day'];
     339        }
     340
     341        $post_page_count = substr_count( $post->post_content, '<!--nextpage-->' ) + 1;
     342
     343        // If the post doesn't have multiple pages, but a 'page' candidate is found, resolve to the date archive.
     344        if ( 1 === $post_page_count && $maybe_page ) {
     345                return $query_vars;
     346        }
     347
     348        // If the post has multiple pages and the 'page' number isn't valid, resolve to the date archive.
     349        if ( $post_page_count > 1 && $maybe_page > $post_page_count ) {
     350                return $query_vars;
     351        }
     352
     353        // If we've gotten to this point, we have a slug/date clash. First, adjust for nextpage.
     354        if ( '' !== $maybe_page ) {
     355                $query_vars['page'] = intval( $maybe_page );
     356        }
     357
     358        // Next, unset autodetected date-related query vars.
     359        unset( $query_vars['year'] );
     360        unset( $query_vars['monthnum'] );
     361        unset( $query_vars['day'] );
     362
     363        // Then, set the identified post.
     364        $query_vars['name'] = $post->post_name;
     365
     366        // Finally, return the modified query vars.
     367        return $query_vars;
     368}
     369
     370/**
    278371 * Examine a url and try to determine the post ID it represents.
    279372 *
    280373 * Checks are supposedly from the hosted site blog.
    function url_to_postid($url) { 
    388481                                        }
    389482                                }
    390483                        }
     484                       
     485                        // Resolve conflicts between posts with numeric slugs and date archive queries.
     486                        $query = _resolve_numeric_slug_conflicts( $query );
    391487
    392488                        // Do the query
    393489                        $query = new WP_Query( $query );
  • tests/phpunit/tests/post.php

    diff --git tests/phpunit/tests/post.php tests/phpunit/tests/post.php
    index ae549e0..ca24646 100644
    class Tests_Post extends WP_UnitTestCase { 
    470470        }
    471471
    472472        /**
     473         * @ticket 5305
     474         */
     475        function test_go_to_year_segment_collision_without_title() {
     476                global $wp_rewrite, $wpdb;
     477                $wp_rewrite->init();
     478                $wp_rewrite->set_permalink_structure( '/%postname%/' );
     479                $wp_rewrite->flush_rules();
     480
     481                $id = $this->factory->post->create( array(
     482                        'post_author'  => $this->author_id,
     483                        'post_status'  => 'publish',
     484                        'post_content' => rand_str(),
     485                        'post_title'   => '',
     486                        'post_name'    => '2015',
     487                        'post_date'    => '2015-02-01 01:00:00'
     488                ) );
     489
     490                // Force an ID that resembles a year format
     491                $wpdb->update(
     492                        $wpdb->posts,
     493                        array(
     494                                'ID'   => '2015',
     495                                'guid' => 'http://example.org/?p=2015'
     496                        ),
     497                        array( 'ID' => $id )
     498                );
     499
     500                $this->go_to( get_permalink( '2015' ) );
     501
     502                $this->assertQueryTrue( 'is_single', 'is_singular' );
     503
     504                $wp_rewrite->set_permalink_structure('');
     505        }
     506
     507        /**
     508         * @ticket 5305
     509         */
     510        function test_url_to_postid_year_segment_collision_without_title() {
     511                global $wp_rewrite, $wpdb;
     512                $wp_rewrite->init();
     513                $wp_rewrite->set_permalink_structure( '/%postname%/' );
     514                $wp_rewrite->flush_rules();
     515
     516                $id = $this->factory->post->create( array(
     517                        'post_author'  => $this->author_id,
     518                        'post_status'  => 'publish',
     519                        'post_content' => rand_str(),
     520                        'post_title'   => '',
     521                        'post_name'    => '2015',
     522                        'post_date'    => '2015-02-01 01:00:00'
     523                ) );
     524
     525                // Force an ID that resembles a year format
     526                $wpdb->update(
     527                        $wpdb->posts,
     528                        array(
     529                                'ID'   => '2015',
     530                                'guid' => 'http://example.org/?p=2015'
     531                        ),
     532                        array( 'ID' => $id )
     533                );
     534
     535                $this->assertEquals( '2015', url_to_postid( get_permalink( '2015' ) ) );
     536
     537                $wp_rewrite->set_permalink_structure('');
     538        }
     539
     540        /**
     541         * @ticket 5305
     542         */
     543        function test_go_to_year_segment_collision_with_title() {
     544                global $wp_rewrite;
     545                $wp_rewrite->init();
     546                $wp_rewrite->set_permalink_structure( '/%postname%/' );
     547                $wp_rewrite->flush_rules();
     548
     549                $id = $this->factory->post->create( array(
     550                        'post_author'  => $this->author_id,
     551                        'post_status'  => 'publish',
     552                        'post_content' => rand_str(),
     553                        'post_title'   => '2015',
     554                        'post_date'    => '2015-02-01 01:00:00',
     555                ) );
     556
     557                $this->go_to( get_permalink( $id ) );
     558
     559                $this->assertQueryTrue( 'is_single', 'is_singular' );
     560
     561                $wp_rewrite->set_permalink_structure('');
     562        }
     563       
     564        /**
     565         * @ticket 5305
     566         */
     567        function test_url_to_postid_year_segment_collision_with_title() {
     568                global $wp_rewrite;
     569                $wp_rewrite->init();
     570                $wp_rewrite->set_permalink_structure( '/%postname%/' );
     571                $wp_rewrite->flush_rules();
     572
     573                $id = $this->factory->post->create( array(
     574                        'post_author'  => $this->author_id,
     575                        'post_status'  => 'publish',
     576                        'post_content' => rand_str(),
     577                        'post_title'   => '2015',
     578                        'post_date'    => '2015-02-01 01:00:00',
     579                ) );
     580
     581                $this->assertEquals( $id, url_to_postid( get_permalink( $id ) ) );
     582
     583                $wp_rewrite->set_permalink_structure('');
     584        }
     585
     586        /**
     587         * @ticket 5305
     588         */
     589        function test_go_to_month_segment_collision_without_title() {
     590                global $wp_rewrite;
     591                $wp_rewrite->init();
     592                $wp_rewrite->set_permalink_structure( '/%year%/%postname%/' );
     593                $wp_rewrite->flush_rules();
     594
     595                $id = $this->factory->post->create( array(
     596                        'post_author'  => $this->author_id,
     597                        'post_status'  => 'publish',
     598                        'post_content' => rand_str(),
     599                        'post_title'   => '',
     600                        'post_name'    => '02',
     601                        'post_date'    => '2015-02-01 01:00:00',
     602                ) );
     603
     604                $this->go_to( get_permalink( $id ) );
     605
     606                $this->assertQueryTrue( 'is_single', 'is_singular' );
     607
     608                $wp_rewrite->set_permalink_structure('');
     609        }
     610
     611        /**
     612         * @ticket 5305
     613         */
     614        function test_url_to_postid_month_segment_collision_without_title() {
     615                global $wp_rewrite;
     616                $wp_rewrite->init();
     617                $wp_rewrite->set_permalink_structure( '/%year%/%postname%/' );
     618                $wp_rewrite->flush_rules();
     619
     620                $id = $this->factory->post->create( array(
     621                        'post_author'  => $this->author_id,
     622                        'post_status'  => 'publish',
     623                        'post_content' => rand_str(),
     624                        'post_title'   => '',
     625                        'post_name'    => '02',
     626                        'post_date'    => '2015-02-01 01:00:00',
     627                ) );
     628
     629                $this->assertEquals( $id, url_to_postid( get_permalink( $id ) ) );
     630
     631                $wp_rewrite->set_permalink_structure('');
     632        }
     633
     634        /**
     635         * @ticket 5305
     636         */
     637        function test_go_to_month_segment_collision_without_title_no_leading_zero() {
     638                global $wp_rewrite;
     639                $wp_rewrite->init();
     640                $wp_rewrite->set_permalink_structure( '/%year%/%postname%/' );
     641                $wp_rewrite->flush_rules();
     642
     643                $id = $this->factory->post->create( array(
     644                        'post_author'  => $this->author_id,
     645                        'post_status'  => 'publish',
     646                        'post_content' => rand_str(),
     647                        'post_title'   => '',
     648                        'post_name'    => '2',
     649                        'post_date'    => '2015-02-01 01:00:00',
     650                ) );
     651
     652                $this->go_to( get_permalink( $id ) );
     653
     654                $this->assertQueryTrue( 'is_single', 'is_singular' );
     655
     656                $wp_rewrite->set_permalink_structure('');
     657        }
     658
     659        /**
     660         * @ticket 5305
     661         */
     662        function test_url_to_postid_month_segment_collision_without_title_no_leading_zero() {
     663                global $wp_rewrite;
     664                $wp_rewrite->init();
     665                $wp_rewrite->set_permalink_structure( '/%year%/%postname%/' );
     666                $wp_rewrite->flush_rules();
     667
     668                $id = $this->factory->post->create( array(
     669                        'post_author'  => $this->author_id,
     670                        'post_status'  => 'publish',
     671                        'post_content' => rand_str(),
     672                        'post_title'   => '',
     673                        'post_name'    => '2',
     674                        'post_date'    => '2015-02-01 01:00:00',
     675                ) );
     676
     677                $this->assertEquals( $id, url_to_postid( get_permalink( $id ) ) );
     678
     679                $wp_rewrite->set_permalink_structure('');
     680        }
     681
     682        /**
     683         * @ticket 5305
     684         */
     685        function test_go_to_month_segment_collision_with_title() {
     686                global $wp_rewrite;
     687                $wp_rewrite->init();
     688                $wp_rewrite->set_permalink_structure( '/%year%/%postname%/' );
     689                $wp_rewrite->flush_rules();
     690
     691                $id = $this->factory->post->create( array(
     692                        'post_author'  => $this->author_id,
     693                        'post_status'  => 'publish',
     694                        'post_content' => rand_str(),
     695                        'post_title'   => '02',
     696                        'post_date'    => '2015-02-01 01:00:00',
     697                ) );
     698
     699                $this->go_to( get_permalink( $id ) );
     700
     701                $this->assertQueryTrue( 'is_single', 'is_singular' );
     702
     703                $wp_rewrite->set_permalink_structure('');
     704        }
     705
     706        /**
     707         * @ticket 5305
     708         */
     709        function test_url_to_postid_month_segment_collision_with_title() {
     710                global $wp_rewrite;
     711                $wp_rewrite->init();
     712                $wp_rewrite->set_permalink_structure( '/%year%/%postname%/' );
     713                $wp_rewrite->flush_rules();
     714
     715                $id = $this->factory->post->create( array(
     716                        'post_author'  => $this->author_id,
     717                        'post_status'  => 'publish',
     718                        'post_content' => rand_str(),
     719                        'post_title'   => '02',
     720                        'post_date'    => '2015-02-01 01:00:00',
     721                ) );
     722
     723                $this->assertEquals( $id, url_to_postid( get_permalink( $id ) ) );
     724
     725                $wp_rewrite->set_permalink_structure('');
     726        }
     727
     728        /**
     729         * @ticket 5305
     730         */
     731        function test_go_to_month_segment_collision_with_title_no_leading_zero() {
     732                global $wp_rewrite;
     733                $wp_rewrite->init();
     734                $wp_rewrite->set_permalink_structure( '/%year%/%postname%/' );
     735                $wp_rewrite->flush_rules();
     736
     737                $id = $this->factory->post->create( array(
     738                        'post_author'  => $this->author_id,
     739                        'post_status'  => 'publish',
     740                        'post_content' => rand_str(),
     741                        'post_title'   => '2',
     742                        'post_date'    => '2015-02-01 01:00:00',
     743                ) );
     744
     745                $this->go_to( get_permalink( $id ) );
     746
     747                $this->assertQueryTrue( 'is_single', 'is_singular' );
     748
     749                $wp_rewrite->set_permalink_structure('');
     750        }
     751
     752        /**
     753         * @ticket 5305
     754         */
     755        function test_url_to_postid_month_segment_collision_with_title_no_leading_zero() {
     756                global $wp_rewrite;
     757                $wp_rewrite->init();
     758                $wp_rewrite->set_permalink_structure( '/%year%/%postname%/' );
     759                $wp_rewrite->flush_rules();
     760
     761                $id = $this->factory->post->create( array(
     762                        'post_author'  => $this->author_id,
     763                        'post_status'  => 'publish',
     764                        'post_content' => rand_str(),
     765                        'post_title'   => '2',
     766                        'post_date'    => '2015-02-01 01:00:00',
     767                ) );
     768
     769                $this->assertEquals( $id, url_to_postid( get_permalink( $id ) ) );
     770
     771                $wp_rewrite->set_permalink_structure('');
     772        }
     773
     774        /**
     775         * @ticket 5305
     776         */
     777        function test_go_to_day_segment_collision_without_title() {
     778                global $wp_rewrite;
     779                $wp_rewrite->init();
     780                $wp_rewrite->set_permalink_structure( '/%year%/%monthnum%/%postname%/' );
     781                $wp_rewrite->flush_rules();
     782
     783                $id = $this->factory->post->create( array(
     784                        'post_author'  => $this->author_id,
     785                        'post_status'  => 'publish',
     786                        'post_content' => rand_str(),
     787                        'post_title'   => '',
     788                        'post_name'    => '01',
     789                        'post_date'    => '2015-02-01 01:00:00',
     790                ) );
     791
     792                $this->go_to( get_permalink( $id ) );
     793
     794                $this->assertQueryTrue( 'is_single', 'is_singular' );
     795
     796                $wp_rewrite->set_permalink_structure('');
     797        }
     798
     799        /**
     800         * @ticket 5305
     801         */
     802        function test_url_to_postid_day_segment_collision_without_title() {
     803                global $wp_rewrite;
     804                $wp_rewrite->init();
     805                $wp_rewrite->set_permalink_structure( '/%year%/%monthnum%/%postname%/' );
     806                $wp_rewrite->flush_rules();
     807
     808                $id = $this->factory->post->create( array(
     809                        'post_author'  => $this->author_id,
     810                        'post_status'  => 'publish',
     811                        'post_content' => rand_str(),
     812                        'post_title'   => '',
     813                        'post_name'    => '01',
     814                        'post_date'    => '2015-02-01 01:00:00',
     815                ) );
     816
     817                $this->assertEquals( $id, url_to_postid( get_permalink( $id ) ) );
     818
     819                $wp_rewrite->set_permalink_structure('');
     820        }
     821
     822        /**
     823         * @ticket 5305
     824         */
     825        function test_go_to_day_segment_collision_with_title() {
     826                global $wp_rewrite;
     827                $wp_rewrite->init();
     828                $wp_rewrite->set_permalink_structure( '/%year%/%monthnum%/%postname%/' );
     829                $wp_rewrite->flush_rules();
     830
     831                $id = $this->factory->post->create( array(
     832                        'post_author'  => $this->author_id,
     833                        'post_status'  => 'publish',
     834                        'post_content' => rand_str(),
     835                        'post_title'   => '01',
     836                        'post_date'    => '2015-02-01 01:00:00',
     837                ) );
     838
     839                $this->go_to( get_permalink( $id ) );
     840
     841                $this->assertQueryTrue( 'is_single', 'is_singular' );
     842
     843                $wp_rewrite->set_permalink_structure('');
     844        }
     845
     846        /**
     847         * @ticket 5305
     848         */
     849        function test_url_to_postid_day_segment_collision_with_title() {
     850                global $wp_rewrite;
     851                $wp_rewrite->init();
     852                $wp_rewrite->set_permalink_structure( '/%year%/%monthnum%/%postname%/' );
     853                $wp_rewrite->flush_rules();
     854
     855                $id = $this->factory->post->create( array(
     856                        'post_author'  => $this->author_id,
     857                        'post_status'  => 'publish',
     858                        'post_content' => rand_str(),
     859                        'post_title'   => '01',
     860                        'post_date'    => '2015-02-01 01:00:00',
     861                ) );
     862
     863                $this->assertEquals( $id, url_to_postid( get_permalink( $id ) ) );
     864
     865                $wp_rewrite->set_permalink_structure('');
     866        }
     867
     868        /**
     869         * @ticket 5305
     870         */
     871        public function test_numeric_slug_permalink_conflicts_should_only_be_resolved_for_the_main_query() {
     872                global $wp_rewrite;
     873                $wp_rewrite->init();
     874                $wp_rewrite->set_permalink_structure( '/%year%/%monthnum%/%postname%/' );
     875                $wp_rewrite->flush_rules();
     876
     877                $id = $this->factory->post->create( array(
     878                        'post_author'  => $this->author_id,
     879                        'post_status'  => 'publish',
     880                        'post_content' => rand_str(),
     881                        'post_title'   => '01',
     882                        'post_date'    => '2015-02-01 01:00:00',
     883                ) );
     884
     885                $q = new WP_Query( array(
     886                        'year'     => '2015',
     887                        'monthnum' => '02',
     888                        'day'      => '01',
     889                ) );
     890
     891                $this->assertTrue( $q->is_day );
     892                $this->assertFalse( $q->is_single );
     893
     894                $wp_rewrite->set_permalink_structure('');
     895        }
     896
     897        /**
     898         * @ticket 5305
     899         */
     900        public function test_date_slug_collision_should_distinguish_valid_pagination_from_date() {
     901                global $wp_rewrite;
     902                $wp_rewrite->init();
     903                $wp_rewrite->set_permalink_structure( '/%year%/%postname%/' );
     904                $wp_rewrite->flush_rules();
     905
     906                $id = $this->factory->post->create( array(
     907                        'post_author'  => $this->author_id,
     908                        'post_status'  => 'publish',
     909                        'post_content' => 'Page 0<!--nextpage-->Page 1<!--nextpage-->Page 2<!--nextpage-->Page 3',
     910                        'post_title'   => '02',
     911                        'post_date'    => '2015-02-01 01:00:00',
     912                ) );
     913
     914                $this->go_to( get_permalink( $id ) . '1' );
     915
     916                $this->assertFalse( is_day() );
     917        }
     918
     919        /**
     920         * @ticket 5305
     921         */
     922        public function test_date_slug_collision_should_distinguish_too_high_pagination_from_date() {
     923                global $wp_rewrite;
     924                $wp_rewrite->init();
     925                $wp_rewrite->set_permalink_structure( '/%year%/%postname%/' );
     926                $wp_rewrite->flush_rules();
     927
     928                $id = $this->factory->post->create( array(
     929                        'post_author'  => $this->author_id,
     930                        'post_status'  => 'publish',
     931                        'post_content' => 'Page 0<!--nextpage-->Page 1<!--nextpage-->Page 2<!--nextpage-->Page 3',
     932                        'post_title'   => '02',
     933                        'post_date'    => '2015-02-05 01:00:00',
     934                ) );
     935
     936                $this->go_to( get_permalink( $id ) . '5' );
     937
     938                $this->assertTrue( is_day() );
     939        }
     940
     941        /**
     942         * @ticket 5305
     943         */
     944        public function test_date_slug_collision_should_not_require_pagination_query_var() {
     945                global $wp_rewrite;
     946                $wp_rewrite->init();
     947                $wp_rewrite->set_permalink_structure( '/%year%/%postname%/' );
     948                $wp_rewrite->flush_rules();
     949
     950                $id = $this->factory->post->create( array(
     951                        'post_author'  => $this->author_id,
     952                        'post_status'  => 'publish',
     953                        'post_content' => 'Page 0<!--nextpage-->Page 1<!--nextpage-->Page 2<!--nextpage-->Page 3',
     954                        'post_title'   => '02',
     955                        'post_date'    => '2015-02-05 01:00:00',
     956                ) );
     957
     958                $this->go_to( get_permalink( $id ) );
     959
     960                $this->assertQueryTrue( 'is_single', 'is_singular' );
     961                $this->assertFalse( is_date() );
     962        }
     963
     964        /**
     965         * @ticket 5305
     966         */
     967        public function test_date_slug_collision_should_be_ignored_when_pagination_var_is_present_but_post_does_not_have_multiple_pages() {
     968                global $wp_rewrite;
     969                $wp_rewrite->init();
     970                $wp_rewrite->set_permalink_structure( '/%year%/%postname%/' );
     971                $wp_rewrite->flush_rules();
     972
     973                $id = $this->factory->post->create( array(
     974                        'post_author'  => $this->author_id,
     975                        'post_status'  => 'publish',
     976                        'post_content' => 'This post does not have pagination.',
     977                        'post_title'   => '02',
     978                        'post_date'    => '2015-02-05 01:00:00',
     979                ) );
     980
     981                $this->go_to( get_permalink( $id ) . '5' );
     982
     983                $this->assertTrue( is_day() );
     984        }
     985
     986        /**
    473987         * @ticket 21013
    474988         */
    475989        function test_wp_unique_post_slug_with_non_latin_slugs() {