Make WordPress Core

Changeset 32647


Ignore:
Timestamp:
05/29/2015 12:52:17 PM (10 years ago)
Author:
boonebgorges
Message:

Disallow post slugs that will result in permalinks that conflict with date archive URLs.

On certain permalink structures, a numeric post slug will result in a post
permalink that conflicts with a date archive URL. For example, with permastruct
/%year%/%monthnum%/%postname%/, a post published in May 2015 with slug
'15' will result in a URL (/2015/05/15/) that conflicts with the archive
for May 15, 2015.

To avoid this problem, wp_unique_post_slug() rejects a requested slug when it
would generate a conflict of this type. Thus, in our example, '15' would
become '15-2'.

Props valendesigns, boonebgorges, Denis-de-Bernardy, loushou.
See #5305.

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/post.php

    r32621 r32647  
    37913791        $post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $slug, $post_type, $post_ID ) );
    37923792
     3793        // Prevent post slugs that could result in URLs that conflict with date archives.
     3794        $conflicts_with_date_archive = false;
     3795        if ( 'post' === $post_type && preg_match( '/^[0-9]+$/', $slug ) && $slug_num = intval( $slug ) ) {
     3796            $permastructs   = array_values( array_filter( explode( '/', get_option( 'permalink_structure' ) ) ) );
     3797            $postname_index = array_search( '%postname%', $permastructs );
     3798
     3799            /*
     3800             * Potential date clashes are as follows:
     3801             *
     3802             * - Any integer in the first permastruct position could be a year.
     3803             * - An integer between 1 and 12 that follows 'year' conflicts with 'monthnum'.
     3804             * - An integer between 1 and 31 that follows 'monthnum' conflicts with 'day'.
     3805             */
     3806            if ( 0 === $postname_index ||
     3807                ( $postname_index && '%year%' === $permastructs[ $postname_index - 1 ] && 13 > $slug_num ) ||
     3808                ( $postname_index && '%monthnum%' === $permastructs[ $postname_index - 1 ] && 32 > $slug_num )
     3809            ) {
     3810                $conflicts_with_date_archive = true;
     3811            }
     3812        }
     3813
    37933814        /**
    37943815         * Filter whether the post slug would be bad as a flat slug.
     
    38003821         * @param string $post_type Post type.
    38013822         */
    3802         if ( $post_name_check || in_array( $slug, $feeds ) || apply_filters( 'wp_unique_post_slug_is_bad_flat_slug', false, $slug, $post_type ) ) {
     3823        if ( $post_name_check || in_array( $slug, $feeds ) || $conflicts_with_date_archive || apply_filters( 'wp_unique_post_slug_is_bad_flat_slug', false, $slug, $post_type ) ) {
    38033824            $suffix = 2;
    38043825            do {
  • trunk/tests/phpunit/tests/admin/includesPost.php

    r32002 r32647  
    314314        flush_rewrite_rules();
    315315    }
     316
     317    /**
     318     * @ticket 5305
     319     */
     320    public function test_get_sample_permalink_should_avoid_slugs_that_would_create_clashes_with_year_archives() {
     321        global $wp_rewrite;
     322        $wp_rewrite->init();
     323        $wp_rewrite->set_permalink_structure( '/%postname%/' );
     324        $wp_rewrite->flush_rules();
     325
     326        $p = $this->factory->post->create( array(
     327            'post_name' => '2015',
     328        ) );
     329
     330        $found = get_sample_permalink( $p );
     331        $this->assertEquals( '2015-2', $found[1] );
     332
     333        $wp_rewrite->set_permalink_structure( '' );
     334        flush_rewrite_rules();
     335    }
     336
     337    /**
     338     * @ticket 5305
     339     */
     340    public function test_get_sample_permalink_should_allow_yearlike_slugs_if_permastruct_does_not_cause_an_archive_conflict() {
     341        global $wp_rewrite;
     342        $wp_rewrite->init();
     343        $wp_rewrite->set_permalink_structure( '/%year%/%postname%/' );
     344        $wp_rewrite->flush_rules();
     345
     346        $p = $this->factory->post->create( array(
     347            'post_name' => '2015',
     348        ) );
     349
     350        $found = get_sample_permalink( $p );
     351        $this->assertEquals( '2015', $found[1] );
     352
     353        $wp_rewrite->set_permalink_structure( '' );
     354        flush_rewrite_rules();
     355    }
     356
     357    /**
     358     * @ticket 5305
     359     */
     360    public function test_get_sample_permalink_should_avoid_slugs_that_would_create_clashes_with_month_archives() {
     361        global $wp_rewrite;
     362        $wp_rewrite->init();
     363        $wp_rewrite->set_permalink_structure( '/%year%/%postname%/' );
     364        $wp_rewrite->flush_rules();
     365
     366        $p = $this->factory->post->create( array(
     367            'post_name' => '11',
     368        ) );
     369
     370        $found = get_sample_permalink( $p );
     371        $this->assertEquals( '11-2', $found[1] );
     372
     373        $wp_rewrite->set_permalink_structure( '' );
     374        flush_rewrite_rules();
     375    }
     376
     377    /**
     378     * @ticket 5305
     379     */
     380    public function test_get_sample_permalink_should_ignore_potential_month_conflicts_for_invalid_monthnum() {
     381        global $wp_rewrite;
     382        $wp_rewrite->init();
     383        $wp_rewrite->set_permalink_structure( '/%year%/%postname%/' );
     384        $wp_rewrite->flush_rules();
     385
     386        $p = $this->factory->post->create( array(
     387            'post_name' => '13',
     388        ) );
     389
     390        $found = get_sample_permalink( $p );
     391        $this->assertEquals( '13', $found[1] );
     392
     393        $wp_rewrite->set_permalink_structure( '' );
     394        flush_rewrite_rules();
     395    }
     396
     397    /**
     398     * @ticket 5305
     399     */
     400    public function test_get_sample_permalink_should_avoid_slugs_that_would_create_clashes_with_day_archives() {
     401        global $wp_rewrite;
     402        $wp_rewrite->init();
     403        $wp_rewrite->set_permalink_structure( '/%year%/%monthnum%/%postname%/' );
     404        $wp_rewrite->flush_rules();
     405
     406        $p = $this->factory->post->create( array(
     407            'post_name' => '30',
     408        ) );
     409
     410        $found = get_sample_permalink( $p );
     411        $this->assertEquals( '30-2', $found[1] );
     412
     413        $wp_rewrite->set_permalink_structure( '' );
     414        flush_rewrite_rules();
     415    }
     416
     417    /**
     418     * @ticket 5305
     419     */
     420    public function test_get_sample_permalink_should_iterate_slug_suffix_when_a_date_conflict_is_found() {
     421        global $wp_rewrite;
     422        $wp_rewrite->init();
     423        $wp_rewrite->set_permalink_structure( '/%year%/%monthnum%/%postname%/' );
     424        $wp_rewrite->flush_rules();
     425
     426        $this->factory->post->create( array(
     427            'post_name' => '30-2',
     428        ) );
     429
     430        $p = $this->factory->post->create( array(
     431            'post_name' => '30',
     432        ) );
     433
     434        $found = get_sample_permalink( $p );
     435        $this->assertEquals( '30-3', $found[1] );
     436
     437        $wp_rewrite->set_permalink_structure( '' );
     438        flush_rewrite_rules();
     439    }
     440
     441    /**
     442     * @ticket 5305
     443     */
     444    public function test_get_sample_permalink_should_ignore_potential_day_conflicts_for_invalid_day() {
     445        global $wp_rewrite;
     446        $wp_rewrite->init();
     447        $wp_rewrite->set_permalink_structure( '/%year%/%monthnum%/%postname%/' );
     448        $wp_rewrite->flush_rules();
     449
     450        $p = $this->factory->post->create( array(
     451            'post_name' => '32',
     452        ) );
     453
     454        $found = get_sample_permalink( $p );
     455        $this->assertEquals( '32', $found[1] );
     456
     457        $wp_rewrite->set_permalink_structure( '' );
     458        flush_rewrite_rules();
     459    }
     460
     461    /**
     462     * @ticket 5305
     463     */
     464    public function test_get_sample_permalink_should_allow_daylike_slugs_if_permastruct_does_not_cause_an_archive_conflict() {
     465        global $wp_rewrite;
     466        $wp_rewrite->init();
     467        $wp_rewrite->set_permalink_structure( '/%year%/%month%/%day%/%postname%/' );
     468        $wp_rewrite->flush_rules();
     469
     470        $p = $this->factory->post->create( array(
     471            'post_name' => '30',
     472        ) );
     473
     474        $found = get_sample_permalink( $p );
     475        $this->assertEquals( '30', $found[1] );
     476
     477        $wp_rewrite->set_permalink_structure( '' );
     478        flush_rewrite_rules();
     479    }
    316480}
  • trunk/tests/phpunit/tests/post/wpUniquePostSlug.php

    r32604 r32647  
    165165        $this->assertSame( 'foo', $actual );
    166166    }
     167
     168    /**
     169     * @ticket 5305
     170     */
     171    public function test_slugs_resulting_in_permalinks_that_resemble_year_archives_should_be_suffixed() {
     172        global $wp_rewrite;
     173        $wp_rewrite->init();
     174        $wp_rewrite->set_permalink_structure( '/%postname%/' );
     175        $wp_rewrite->flush_rules();
     176
     177        $p = $this->factory->post->create( array(
     178            'post_type' => 'post',
     179            'post_name' => 'foo',
     180        ) );
     181
     182        $found = wp_unique_post_slug( '2015', $p, 'publish', 'post', 0 );
     183        $this->assertEquals( '2015-2', $found );
     184
     185        $wp_rewrite->set_permalink_structure( '' );
     186        flush_rewrite_rules();
     187    }
     188
     189    /**
     190     * @ticket 5305
     191     */
     192    public function test_yearlike_slugs_should_not_be_suffixed_if_permalink_structure_does_not_result_in_a_clash_with_year_archives() {
     193        global $wp_rewrite;
     194        $wp_rewrite->init();
     195        $wp_rewrite->set_permalink_structure( '/%year%/%postname%/' );
     196        $wp_rewrite->flush_rules();
     197
     198        $p = $this->factory->post->create( array(
     199            'post_type' => 'post',
     200            'post_name' => 'foo',
     201        ) );
     202
     203        $found = wp_unique_post_slug( '2015', $p, 'publish', 'post', 0 );
     204        $this->assertEquals( '2015', $found );
     205
     206        $wp_rewrite->set_permalink_structure( '' );
     207        flush_rewrite_rules();
     208    }
     209
     210    /**
     211     * @ticket 5305
     212     */
     213    public function test_slugs_resulting_in_permalinks_that_resemble_month_archives_should_be_suffixed() {
     214        global $wp_rewrite;
     215        $wp_rewrite->init();
     216        $wp_rewrite->set_permalink_structure( '/%year%/%postname%/' );
     217        $wp_rewrite->flush_rules();
     218
     219        $p = $this->factory->post->create( array(
     220            'post_type' => 'post',
     221            'post_name' => 'foo',
     222        ) );
     223
     224        $found = wp_unique_post_slug( '11', $p, 'publish', 'post', 0 );
     225        $this->assertEquals( '11-2', $found );
     226
     227        $wp_rewrite->set_permalink_structure( '' );
     228        flush_rewrite_rules();
     229    }
     230
     231    /**
     232     * @ticket 5305
     233     */
     234    public function test_monthlike_slugs_should_not_be_suffixed_if_permalink_structure_does_not_result_in_a_clash_with_month_archives() {
     235        global $wp_rewrite;
     236        $wp_rewrite->init();
     237        $wp_rewrite->set_permalink_structure( '/%year%/foo/%postname%/' );
     238        $wp_rewrite->flush_rules();
     239
     240        $p = $this->factory->post->create( array(
     241            'post_type' => 'post',
     242            'post_name' => 'foo',
     243        ) );
     244
     245        $found = wp_unique_post_slug( '11', $p, 'publish', 'post', 0 );
     246        $this->assertEquals( '11', $found );
     247
     248        $wp_rewrite->set_permalink_structure( '' );
     249        flush_rewrite_rules();
     250    }
     251
     252    /**
     253     * @ticket 5305
     254     */
     255    public function test_monthlike_slugs_should_not_be_suffixed_for_invalid_month_numbers() {
     256        global $wp_rewrite;
     257        $wp_rewrite->init();
     258        $wp_rewrite->set_permalink_structure( '/%year%/%postname%/' );
     259        $wp_rewrite->flush_rules();
     260
     261        $p = $this->factory->post->create( array(
     262            'post_type' => 'post',
     263            'post_name' => 'foo',
     264        ) );
     265
     266        $found = wp_unique_post_slug( '13', $p, 'publish', 'post', 0 );
     267        $this->assertEquals( '13', $found );
     268
     269        $wp_rewrite->set_permalink_structure( '' );
     270        flush_rewrite_rules();
     271    }
     272
     273    /**
     274     * @ticket 5305
     275     */
     276    public function test_slugs_resulting_in_permalinks_that_resemble_day_archives_should_be_suffixed() {
     277        global $wp_rewrite;
     278        $wp_rewrite->init();
     279        $wp_rewrite->set_permalink_structure( '/%year%/%monthnum%/%postname%/' );
     280        $wp_rewrite->flush_rules();
     281
     282        $p = $this->factory->post->create( array(
     283            'post_type' => 'post',
     284            'post_name' => 'foo',
     285        ) );
     286
     287        $found = wp_unique_post_slug( '30', $p, 'publish', 'post', 0 );
     288        $this->assertEquals( '30-2', $found );
     289
     290        $wp_rewrite->set_permalink_structure( '' );
     291        flush_rewrite_rules();
     292    }
     293
     294    /**
     295     * @ticket 5305
     296     */
     297    public function test_daylike_slugs_should_not_be_suffixed_if_permalink_structure_does_not_result_in_a_clash_with_day_archives() {
     298        global $wp_rewrite;
     299        $wp_rewrite->init();
     300        $wp_rewrite->set_permalink_structure( '/%year%/%monthnum%/%day%/%postname%/' );
     301        $wp_rewrite->flush_rules();
     302
     303        $p = $this->factory->post->create( array(
     304            'post_type' => 'post',
     305            'post_name' => 'foo',
     306        ) );
     307
     308        $found = wp_unique_post_slug( '30', $p, 'publish', 'post', 0 );
     309        $this->assertEquals( '30', $found );
     310
     311        $wp_rewrite->set_permalink_structure( '' );
     312        flush_rewrite_rules();
     313    }
     314
     315    /**
     316     * @ticket 5305
     317     */
     318    public function test_daylike_slugs_should_not_be_suffixed_for_invalid_day_numbers() {
     319        global $wp_rewrite;
     320        $wp_rewrite->init();
     321        $wp_rewrite->set_permalink_structure( '/%year%/%monthnum%/%postname%/' );
     322        $wp_rewrite->flush_rules();
     323
     324        $p = $this->factory->post->create( array(
     325            'post_type' => 'post',
     326            'post_name' => 'foo',
     327        ) );
     328
     329        $found = wp_unique_post_slug( '32', $p, 'publish', 'post', 0 );
     330        $this->assertEquals( '32', $found );
     331
     332        $wp_rewrite->set_permalink_structure( '' );
     333        flush_rewrite_rules();
     334    }
    167335}
Note: See TracChangeset for help on using the changeset viewer.