Skip to content

Commit ae6a847

Browse files
refactor: replace direct SQL with WP_Query in redirect_guess_404_permalink()
1 parent 33c8d7e commit ae6a847

File tree

1 file changed

+48
-11
lines changed

1 file changed

+48
-11
lines changed

src/wp-includes/canonical.php

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -972,10 +972,35 @@ function redirect_guess_404_permalink() {
972972
*/
973973
$strict_guess = apply_filters( 'strict_redirect_guess_404_permalink', false );
974974

975+
// Build WP_Query arguments.
976+
$query_args = array(
977+
'post_status' => $publicly_viewable_statuses,
978+
'posts_per_page' => 1,
979+
'no_found_rows' => true,
980+
'ignore_sticky_posts' => true,
981+
'fields' => 'ids',
982+
);
983+
984+
// Handle strict vs. loose post_name matching.
975985
if ( $strict_guess ) {
976-
$where = $wpdb->prepare( 'post_name = %s', get_query_var( 'name' ) );
986+
$query_args['name'] = get_query_var( 'name' );
977987
} else {
978-
$where = $wpdb->prepare( 'post_name LIKE %s', $wpdb->esc_like( get_query_var( 'name' ) ) . '%' );
988+
// For loose matching (LIKE), we'll use a posts_where filter.
989+
$post_name_for_filter = get_query_var( 'name' );
990+
991+
// Store the filter callback so we can remove it later.
992+
$post_name_where_filter = function ( $where, $query ) use ( $post_name_for_filter, $wpdb ) {
993+
// Only apply to our specific query.
994+
if ( isset( $query->query_vars['redirect_guess_404'] ) && $query->query_vars['redirect_guess_404'] ) {
995+
$where .= $wpdb->prepare( " AND {$wpdb->posts}.post_name LIKE %s", $wpdb->esc_like( $post_name_for_filter ) . '%' );
996+
}
997+
return $where;
998+
};
999+
1000+
add_filter( 'posts_where', $post_name_where_filter, 10, 2 );
1001+
1002+
// Mark this query so our filter knows to apply the LIKE clause.
1003+
$query_args['redirect_guess_404'] = true;
9791004
}
9801005

9811006
// If any of post_type, year, monthnum, or day are set, use them to refine the query.
@@ -985,34 +1010,46 @@ function redirect_guess_404_permalink() {
9851010
if ( empty( $post_types ) ) {
9861011
return false;
9871012
}
988-
$where .= " AND post_type IN ('" . join( "', '", esc_sql( get_query_var( 'post_type' ) ) ) . "')";
1013+
$query_args['post_type'] = $post_types;
9891014
} else {
9901015
if ( ! in_array( get_query_var( 'post_type' ), $publicly_viewable_post_types, true ) ) {
9911016
return false;
9921017
}
993-
$where .= $wpdb->prepare( ' AND post_type = %s', get_query_var( 'post_type' ) );
1018+
$query_args['post_type'] = get_query_var( 'post_type' );
9941019
}
9951020
} else {
996-
$where .= " AND post_type IN ('" . implode( "', '", esc_sql( $publicly_viewable_post_types ) ) . "')";
1021+
$query_args['post_type'] = $publicly_viewable_post_types;
9971022
}
9981023

1024+
// Handle date queries.
1025+
$date_query = array();
9991026
if ( get_query_var( 'year' ) ) {
1000-
$where .= $wpdb->prepare( ' AND YEAR(post_date) = %d', get_query_var( 'year' ) );
1027+
$date_query['year'] = get_query_var( 'year' );
10011028
}
10021029
if ( get_query_var( 'monthnum' ) ) {
1003-
$where .= $wpdb->prepare( ' AND MONTH(post_date) = %d', get_query_var( 'monthnum' ) );
1030+
$date_query['month'] = get_query_var( 'monthnum' );
10041031
}
10051032
if ( get_query_var( 'day' ) ) {
1006-
$where .= $wpdb->prepare( ' AND DAYOFMONTH(post_date) = %d', get_query_var( 'day' ) );
1033+
$date_query['day'] = get_query_var( 'day' );
10071034
}
1035+
if ( ! empty( $date_query ) ) {
1036+
$query_args['date_query'] = array( $date_query );
1037+
}
1038+
1039+
// Execute the query.
1040+
$query = new WP_Query( $query_args );
10081041

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

1012-
if ( ! $post_id ) {
1047+
if ( empty( $query->posts ) ) {
10131048
return false;
10141049
}
10151050

1051+
$post_id = $query->posts[0];
1052+
10161053
if ( get_query_var( 'feed' ) ) {
10171054
return get_post_comments_feed_link( $post_id, get_query_var( 'feed' ) );
10181055
} elseif ( get_query_var( 'page' ) > 1 ) {

0 commit comments

Comments
 (0)