Make WordPress Core


Ignore:
Timestamp:
01/28/2012 08:40:55 PM (13 years ago)
Author:
duck_
Message:

Redirect bare category URLs for permalink structures starting with %category%. Fixes #19876.

When using a structure like /%category%/%postname%/ it might be thought that /uncategorized/
(missing the "/category/" base) results in the category archive. Previously this worked due to
$walk_dirs = true for the post permalink structure, but canonical didn't redirect it. Now
there is no rewrite rule to match => 404. The fix is to use a canonical redirect.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-includes/canonical.php

    r19712 r19778  
    9494
    9595        if ( ! $redirect_url )
    96             $redirect_url = redirect_guess_404_permalink();
     96            $redirect_url = redirect_guess_404_permalink( $requested_url );
    9797
    9898    } elseif ( is_object($wp_rewrite) && $wp_rewrite->using_permalinks() ) {
     
    418418
    419419/**
    420  * Attempts to guess correct post based on query vars.
     420 * Attempts to guess the correct URL from the current URL (that produced a 404) or
     421 * the current query variables.
    421422 *
    422423 * @since 2.3.0
    423424 * @uses $wpdb
    424425 *
    425  * @return bool|string Returns False, if it can't find post, returns correct
    426  *      location on success.
     426 * @param string $current_url Optional. The URL that has 404'd.
     427 * @return bool|string The correct URL if one is found. False on failure.
    427428 */
    428 function redirect_guess_404_permalink() {
    429     global $wpdb;
    430 
    431     if ( !get_query_var('name') )
    432         return false;
    433 
    434     $where = $wpdb->prepare("post_name LIKE %s", like_escape( get_query_var('name') ) . '%');
    435 
    436     // if any of post_type, year, monthnum, or day are set, use them to refine the query
    437     if ( get_query_var('post_type') )
    438         $where .= $wpdb->prepare(" AND post_type = %s", get_query_var('post_type'));
    439     if ( get_query_var('year') )
    440         $where .= $wpdb->prepare(" AND YEAR(post_date) = %d", get_query_var('year'));
    441     if ( get_query_var('monthnum') )
    442         $where .= $wpdb->prepare(" AND MONTH(post_date) = %d", get_query_var('monthnum'));
    443     if ( get_query_var('day') )
    444         $where .= $wpdb->prepare(" AND DAYOFMONTH(post_date) = %d", get_query_var('day'));
    445 
    446     $post_id = $wpdb->get_var("SELECT ID FROM $wpdb->posts WHERE $where AND post_status = 'publish'");
    447     if ( !$post_id )
    448         return false;
    449     return get_permalink($post_id);
     429function redirect_guess_404_permalink( $current_url = '' ) {
     430    global $wpdb, $wp_rewrite;
     431
     432    if ( ! empty( $current_url ) )
     433        $parsed_url = @parse_url( $current_url );
     434
     435    // Attempt to redirect bare category slugs if the permalink structure starts
     436    // with the %category% tag.
     437    if ( isset( $parsed_url['path'] )
     438        && preg_match( '#^[^%]+%category%#', $wp_rewrite->permalink_structure )
     439        && $cat = get_category_by_path( $parsed_url['path'] )
     440    ) {
     441        if ( ! is_wp_error( $cat ) )
     442            return get_term_link( $cat );
     443    }
     444
     445    if ( get_query_var('name') ) {
     446        $where = $wpdb->prepare("post_name LIKE %s", like_escape( get_query_var('name') ) . '%');
     447
     448        // if any of post_type, year, monthnum, or day are set, use them to refine the query
     449        if ( get_query_var('post_type') )
     450            $where .= $wpdb->prepare(" AND post_type = %s", get_query_var('post_type'));
     451        if ( get_query_var('year') )
     452            $where .= $wpdb->prepare(" AND YEAR(post_date) = %d", get_query_var('year'));
     453        if ( get_query_var('monthnum') )
     454            $where .= $wpdb->prepare(" AND MONTH(post_date) = %d", get_query_var('monthnum'));
     455        if ( get_query_var('day') )
     456            $where .= $wpdb->prepare(" AND DAYOFMONTH(post_date) = %d", get_query_var('day'));
     457
     458        $post_id = $wpdb->get_var("SELECT ID FROM $wpdb->posts WHERE $where AND post_status = 'publish'");
     459        if ( ! $post_id )
     460            return false;
     461        return get_permalink( $post_id );
     462    }
     463
     464    return false;
    450465}
    451466
Note: See TracChangeset for help on using the changeset viewer.