Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 48 additions & 11 deletions src/wp-includes/canonical.php
Original file line number Diff line number Diff line change
Expand Up @@ -972,10 +972,36 @@ function redirect_guess_404_permalink() {
*/
$strict_guess = apply_filters( 'strict_redirect_guess_404_permalink', false );

$query_args = array(
'post_status' => $publicly_viewable_statuses,
'posts_per_page' => 1,
'no_found_rows' => true,
'ignore_sticky_posts' => true,
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
'fields' => 'ids',
);

// Handle strict vs. loose post_name matching.
if ( $strict_guess ) {
$where = $wpdb->prepare( 'post_name = %s', get_query_var( 'name' ) );
$query_args['name'] = get_query_var( 'name' );
} else {
$where = $wpdb->prepare( 'post_name LIKE %s', $wpdb->esc_like( get_query_var( 'name' ) ) . '%' );
// For loose matching (LIKE), we'll use a posts_where filter.
$post_name_for_filter = get_query_var( 'name' );

// Store the filter callback so we can remove it later.
$post_name_where_filter = static function ( $where, $query ) use ( $post_name_for_filter, $wpdb ) {
// Only apply to our specific query.
if ( isset( $query->query_vars['redirect_guess_404'] ) ) {
$where .= $wpdb->prepare( " AND {$wpdb->posts}.post_name LIKE %s", $wpdb->esc_like( $post_name_for_filter ) . '%' );
}
return $where;
};

add_filter( 'posts_where', $post_name_where_filter, 10, 2 );

// Mark this query so our filter knows to apply the LIKE clause.
$query_args['redirect_guess_404'] = true;
Comment on lines +989 to +1004
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// For loose matching (LIKE), we'll use a posts_where filter.
$post_name_for_filter = get_query_var( 'name' );
// Store the filter callback so we can remove it later.
$post_name_where_filter = static function ( $where, $query ) use ( $post_name_for_filter, $wpdb ) {
// Only apply to our specific query.
if ( isset( $query->query_vars['redirect_guess_404'] ) ) {
$where .= $wpdb->prepare( " AND {$wpdb->posts}.post_name LIKE %s", $wpdb->esc_like( $post_name_for_filter ) . '%' );
}
return $where;
};
add_filter( 'posts_where', $post_name_where_filter, 10, 2 );
// Mark this query so our filter knows to apply the LIKE clause.
$query_args['redirect_guess_404'] = true;
$query_args['s'] = get_query_var( 'name' );
$query_args['search_columns'] = array( 'post_name' );

Currently, WP_Query does not support search column of post name, but it is a very small tweak to make this happen.

}

// If any of post_type, year, monthnum, or day are set, use them to refine the query.
Expand All @@ -985,34 +1011,45 @@ function redirect_guess_404_permalink() {
if ( empty( $post_types ) ) {
return false;
}
$where .= " AND post_type IN ('" . join( "', '", esc_sql( get_query_var( 'post_type' ) ) ) . "')";
$query_args['post_type'] = $post_types;
} else {
if ( ! in_array( get_query_var( 'post_type' ), $publicly_viewable_post_types, true ) ) {
return false;
}
$where .= $wpdb->prepare( ' AND post_type = %s', get_query_var( 'post_type' ) );
$query_args['post_type'] = get_query_var( 'post_type' );
}
} else {
$where .= " AND post_type IN ('" . implode( "', '", esc_sql( $publicly_viewable_post_types ) ) . "')";
$query_args['post_type'] = $publicly_viewable_post_types;
}

// Handle date queries.
$date_query = array();
if ( get_query_var( 'year' ) ) {
$where .= $wpdb->prepare( ' AND YEAR(post_date) = %d', get_query_var( 'year' ) );
$date_query['year'] = get_query_var( 'year' );
}
if ( get_query_var( 'monthnum' ) ) {
$where .= $wpdb->prepare( ' AND MONTH(post_date) = %d', get_query_var( 'monthnum' ) );
$date_query['month'] = get_query_var( 'monthnum' );
}
if ( get_query_var( 'day' ) ) {
$where .= $wpdb->prepare( ' AND DAYOFMONTH(post_date) = %d', get_query_var( 'day' ) );
$date_query['day'] = get_query_var( 'day' );
}
if ( ! empty( $date_query ) ) {
$query_args['date_query'] = array( $date_query );
}

$query = new WP_Query( $query_args );

// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$post_id = $wpdb->get_var( "SELECT ID FROM $wpdb->posts WHERE $where AND post_status IN ('" . implode( "', '", esc_sql( $publicly_viewable_statuses ) ) . "')" );
// Clean up the filter if we added it (remove only our specific callback).
if ( ! $strict_guess && isset( $post_name_where_filter ) ) {
remove_filter( 'posts_where', $post_name_where_filter, 10 );
}
Comment on lines +1042 to +1045
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Clean up the filter if we added it (remove only our specific callback).
if ( ! $strict_guess && isset( $post_name_where_filter ) ) {
remove_filter( 'posts_where', $post_name_where_filter, 10 );
}

Should not be needed once WP_Query is tweaked.


if ( ! $post_id ) {
if ( empty( $query->posts ) ) {
return false;
}

$post_id = $query->posts[0];

if ( get_query_var( 'feed' ) ) {
return get_post_comments_feed_link( $post_id, get_query_var( 'feed' ) );
} elseif ( get_query_var( 'page' ) > 1 ) {
Expand Down
Loading