WordPress.org

Make WordPress Core

Ticket #5305: 5305.6.diff

File 5305.6.diff, 10.5 KB (added by valendesigns, 5 years ago)
  • src/wp-includes/default-filters.php

    diff --git src/wp-includes/default-filters.php src/wp-includes/default-filters.php
    index c28594f..52e2339 100644
    add_action( 'end_fetch_post_thumbnail_html', '_wp_post_thumbnail_class_filter_ 
    276276add_action( 'template_redirect', 'wp_old_slug_redirect'              );
    277277add_action( 'post_updated',      'wp_check_for_changed_slugs', 12, 3 );
    278278
     279// Resolve Numeric Slugs
     280add_action( 'pre_get_posts',     'wp_resolve_numeric_slugs',    1, 1 );
     281
    279282// Nonce check for Post Previews
    280283add_action( 'init', '_show_post_preview' );
    281284
  • src/wp-includes/query.php

    diff --git src/wp-includes/query.php src/wp-includes/query.php
    index 27d8c26..a287156 100644
    function setup_postdata( $post ) { 
    47234723
    47244724        return false;
    47254725}
     4726
     4727/**
     4728 * Resolves numeric slugs that collide with date permalinks.
     4729 *
     4730 * @since 4.2.0
     4731 * @uses $wp_query
     4732 *
     4733 * @param object $query The WP_Query instance.
     4734 */
     4735function wp_resolve_numeric_slugs( $query ) {
     4736
     4737        // Only attempt to resolve date queries for non administrative requests
     4738        if ( ! is_admin() && $query->is_date() ) {
     4739
     4740                // Setup tokens
     4741                preg_match_all( '/%.+?%/', get_option( 'permalink_structure' ), $tokens );
     4742                $token_index = 1;
     4743
     4744                // Loop over the offending permalink structures and attempt to resolve them.
     4745                foreach ( (array) $tokens[0] as $token ) {
     4746
     4747                        // Only resolve the '%postname%' token
     4748                        if ( '%postname%' == $token ) {
     4749
     4750                                // Boolean check for date tokens
     4751                                $date_tokens = count( array_intersect( $tokens[0], array( '%year%', '%monthnum%', '%day%' ) ) ) > 0;
     4752                               
     4753                                /**
     4754                                 * Filter the post types that should resolve numeric slug date collisions.
     4755                                 *
     4756                                 * @since 4.2.0
     4757                                 *
     4758                                 * @param string|array $post_type Post type or array of post types. Default 'post'.
     4759                                 */
     4760                                $post_type = apply_filters( 'wp_resolve_numeric_slugs', 'post' );
     4761
     4762                                // Resolve '%day%' segment for '%monthnum%'
     4763                                if ( $date_tokens && $token_index == 3 && $tokens[0][1] == '%monthnum%' ) {
     4764
     4765                                        _wp_resolve_numeric_slug( $query, array( 'var' => 'day', 'condition' => 'is_day', 'post_type' => $post_type ) );
     4766
     4767                                // Resolve '%monthnum%' segment for '%year%'
     4768                                } else if ( $date_tokens && $token_index == 2 && $tokens[0][0] == '%year%' ) {
     4769
     4770                                        _wp_resolve_numeric_slug( $query, array( 'var' => 'monthnum', 'condition' => 'is_month', 'post_type' => $post_type ) );
     4771
     4772                                // Resolve the lone '%postname%'
     4773                                } else if ( $token_index == 1 ) {
     4774
     4775                                        _wp_resolve_numeric_slug( $query, array( 'post_type' => $post_type ) );
     4776
     4777                                }
     4778
     4779                        }
     4780
     4781                        $token_index++;
     4782
     4783                }
     4784
     4785        }
     4786
     4787}
     4788
     4789/**
     4790 * Helper function to resolve specific numeric slug segments that collide with date permalinks.
     4791 *
     4792 * @since 4.2.0
     4793 * @access private
     4794 * @uses $wp_query
     4795 *
     4796 * @param object $query The WP_Query instance.
     4797 * @param array $args {
     4798 *     Optional. Array of query arguments.
     4799 *
     4800 *     @type string       $var       The variable key to retrieve. Default 'year'.
     4801 *     @type string       $condition The query condition that should return false. Default 'is_year'.
     4802 *     @type string|array $post_type Post type or array of post types. Default 'post'.
     4803 * }
     4804 */
     4805function _wp_resolve_numeric_slug( $query, $args = array() ) {
     4806
     4807        // Defaults
     4808        $defaults = array(
     4809                'var'            => 'year',
     4810                'condition'      => 'is_year',
     4811                'post_type'      => 'post'
     4812        );
     4813
     4814        $args = wp_parse_args( $args, $defaults );
     4815        extract( $args, EXTR_SKIP );
     4816
     4817        // Supported query vars
     4818        $supported = array( 'year', 'monthnum', 'day' );
     4819
     4820        /*
     4821         * If we have a WP_Query object and our condition is true or the var is supported,
     4822         * attempt to resolve the slug.
     4823         */
     4824        if ( is_object( $query ) && is_a( $query, 'WP_Query' ) && ( $query->$condition() || in_array( $var, $supported ) ) ) {
     4825
     4826                // Get the query var
     4827                $get = $query->get( $var );
     4828
     4829                // Maybe add a leading zero
     4830                if ( 'year' != $var ) {
     4831                        $get = zeroise( $get, 2 );
     4832                }
     4833
     4834                // Look for a post using the numeric slug
     4835                $post = get_page_by_path( $get, OBJECT, 'post' );
     4836
     4837                // Didn't find a post so treat the slug var as an ID for posts without titles.
     4838                if ( null == $post ) {
     4839                        $no_title_post = get_post( $get );
     4840                        if ( isset( $no_title_post->post_title ) && '' === $no_title_post->post_title ) {
     4841                                $post = $no_title_post;
     4842                        }
     4843                }
     4844
     4845                // Check that we found a WP_Post object.
     4846                if ( is_object( $post ) && is_a( $post, 'WP_Post' ) ) {
     4847
     4848                        // Set the resolve flag
     4849                        $resolve = true;
     4850
     4851                        // Set the page number search needle
     4852                        $needle = '<!--nextpage-->';
     4853
     4854                        // Set the page number search haystack
     4855                        $haystack = $post->post_content;
     4856
     4857                        // Set page number args for years
     4858                        if ( 'year' == $var ) {
     4859
     4860                                $page_args = array( 'var' => 'monthnum', 'condition' => 'is_month' );
     4861                       
     4862                        // Set page number args for months
     4863                        } else if ( 'monthnum' == $var ) {
     4864
     4865                                $page_args = array( 'var' => 'day', 'condition' => 'is_day' );
     4866
     4867                        }
     4868
     4869                        // Attempt to resolve page numbers
     4870                        if ( ! empty( $page_args ) && false !== strpos( $haystack, $needle ) ) {
     4871
     4872                                // Get the page query var
     4873                                $page = $query->get( $page_args['var'] );
     4874
     4875                                // Has pages to resolve
     4876                                if ( '' !== $page && ( $page - 1 ) <= substr_count( $haystack, $needle ) ) {
     4877
     4878                                        // Unset date var
     4879                                        unset($query->query[$page_args['var']]);
     4880                                        $query->set( $page_args['var'], '' );
     4881
     4882                                        // Update page var
     4883                                        $query->set( 'page', "$page" );
     4884                                        $query->query['page'] = "$page";
     4885
     4886                                        // Set global
     4887                                        $query->$page_args['condition'] = false;
     4888
     4889                                // Don't resolve none existent pages
     4890                                } else {
     4891
     4892                                        $resolve = false;
     4893
     4894                                }
     4895
     4896                        // Don't resolve page numbers for posts that aren't using them
     4897                        } else if ( ! empty( $page_args ) && $query->get( $page_args['var'] ) ) {
     4898
     4899                                $resolve = false;
     4900
     4901                        }
     4902
     4903                        // Highjack the query args
     4904                        if ( true === $resolve ) {
     4905
     4906                                // Remove old query var
     4907                                unset($query->query[$var]);
     4908                                $query->set( $var, '' );
     4909
     4910                                // Update name query var
     4911                                $query->set( 'name', $get );
     4912                                $query->query['name'] = $get;
     4913
     4914                                // Set globals
     4915                                $query->is_date     = false;
     4916                                $query->$condition  = false;
     4917                                $query->is_archive  = false;
     4918                                $query->is_single   = true;
     4919                                $query->is_singular = true;
     4920
     4921                        }
     4922
     4923                }
     4924
     4925        }
     4926
     4927}
  • tests/phpunit/tests/post.php

    diff --git tests/phpunit/tests/post.php tests/phpunit/tests/post.php
    index ae549e0..3af7640 100644
    class Tests_Post extends WP_UnitTestCase { 
    470470        }
    471471
    472472        /**
     473         * @ticket 5305
     474         */
     475        function test_permalink_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_permalink_year_segment_collision_with_title() {
     511                global $wp_rewrite;
     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'   => '2015',
     521                        'post_date'    => '2015-02-01 01:00:00',
     522                ) );
     523
     524                $this->assertEquals( $id, url_to_postid( get_permalink( $id ) ) );
     525
     526                $wp_rewrite->set_permalink_structure('');
     527        }
     528
     529        /**
     530         * @ticket 5305
     531         */
     532        function test_permalink_month_segment_collision_without_title() {
     533                global $wp_rewrite;
     534                $wp_rewrite->init();
     535                $wp_rewrite->set_permalink_structure( '/%year%/%postname%/' );
     536                $wp_rewrite->flush_rules();
     537
     538                $id = $this->factory->post->create( array(
     539                        'post_author'  => $this->author_id,
     540                        'post_status'  => 'publish',
     541                        'post_content' => rand_str(),
     542                        'post_title'   => '',
     543                        'post_name'    => '02',
     544                        'post_date'    => '2015-02-01 01:00:00',
     545                ) );
     546
     547                $this->go_to( get_permalink( $id ) );
     548
     549                $this->assertQueryTrue( 'is_single', 'is_singular' );
     550
     551                $wp_rewrite->set_permalink_structure('');
     552        }
     553
     554        /**
     555         * @ticket 5305
     556         */
     557        function test_permalink_month_segment_collision_with_title() {
     558                global $wp_rewrite;
     559                $wp_rewrite->init();
     560                $wp_rewrite->set_permalink_structure( '/%year%/%postname%/' );
     561                $wp_rewrite->flush_rules();
     562
     563                $id = $this->factory->post->create( array(
     564                        'post_author'  => $this->author_id,
     565                        'post_status'  => 'publish',
     566                        'post_content' => rand_str(),
     567                        'post_title'   => '02',
     568                        'post_date'    => '2015-02-01 01:00:00',
     569                ) );
     570
     571                $this->assertEquals( $id, url_to_postid( get_permalink( $id ) ) );
     572
     573                $wp_rewrite->set_permalink_structure('');
     574        }
     575
     576        /**
     577         * @ticket 5305
     578         */
     579        function test_permalink_day_segment_collision_without_title() {
     580                global $wp_rewrite;
     581                $wp_rewrite->init();
     582                $wp_rewrite->set_permalink_structure( '/%year%/%monthnum%/%postname%/' );
     583                $wp_rewrite->flush_rules();
     584
     585                $id = $this->factory->post->create( array(
     586                        'post_author'  => $this->author_id,
     587                        'post_status'  => 'publish',
     588                        'post_content' => rand_str(),
     589                        'post_title'   => '',
     590                        'post_name'    => '01',
     591                        'post_date'    => '2015-02-01 01:00:00',
     592                ) );
     593
     594                $this->go_to( get_permalink( $id ) );
     595
     596                $this->assertQueryTrue( 'is_single', 'is_singular' );
     597
     598                $wp_rewrite->set_permalink_structure('');
     599        }
     600
     601        /**
     602         * @ticket 5305
     603         */
     604        function test_permalink_day_segment_collision_with_title() {
     605                global $wp_rewrite;
     606                $wp_rewrite->init();
     607                $wp_rewrite->set_permalink_structure( '/%year%/%monthnum%/%postname%/' );
     608                $wp_rewrite->flush_rules();
     609
     610                $id = $this->factory->post->create( array(
     611                        'post_author'  => $this->author_id,
     612                        'post_status'  => 'publish',
     613                        'post_content' => rand_str(),
     614                        'post_title'   => '01',
     615                        'post_date'    => '2015-02-01 01:00:00',
     616                ) );
     617
     618                $this->assertEquals( $id, url_to_postid( get_permalink( $id ) ) );
     619
     620                $wp_rewrite->set_permalink_structure('');
     621        }
     622
     623        /**
    473624         * @ticket 21013
    474625         */
    475626        function test_wp_unique_post_slug_with_non_latin_slugs() {