Skip to content

Instantly share code, notes, and snippets.

@r-a-y
Last active April 12, 2022 06:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save r-a-y/f66042d63970a1058a4e380e31f8463b to your computer and use it in GitHub Desktop.
Save r-a-y/f66042d63970a1058a4e380e31f8463b to your computer and use it in GitHub Desktop.
Add support for double-quoted search results in WordPress
<?php
/**
* Add support for double-quoted search results.
*
* Can handle multiple, double-quoted search results as well.
*/
add_action( 'pre_get_posts', function( $q ) {
if ( ! $q->get( 's' ) ) {
return;
}
$q->set( 's', wp_unslash( $q->get( 's' ) ) );
// Remove breaklines. Same as WP_Query::parse_search().
$q->set( 's', str_replace( array( "\r", "\n" ), '', $q->get( 's' ) ) );
// Use same regex as WP_Query::parse_search().
preg_match_all( '/".*?("|$)|((?<=[\t ",+])|^)[^\t ",+]+/', $q->get( 's' ), $matches );
if ( empty( $matches[0] ) ) {
return;
}
$match_quotations = [];
// Save the current search so we can reset it later.
$unmodified_search = $q->get( 's' );
/*
* Remove double-quoted search terms from 's' search field.
*
* We will later append these terms to the end of the SQL query.
*/
foreach ( $matches[0] as $match ) {
if ( 0 === strpos( $match, '"' ) && '"' === substr( $match, -1 ) ) {
$q->set( 's', str_replace( $match, '', $q->get( 's' ) ) );
// Save our quoted search for later.
$match_quotations[] = trim( $match, '"' );
}
}
$q->set( 's', trim( $q->get( 's' ) ) );
// No double-quoted search terms, so bail.
if ( empty( $match_quotations ) ) {
return;
}
/*
* Append our quoted search terms to existing search.
*
* This is mostly a reinterpretation of parse_search() in WP_Query.
*/
$quote_filter = function( $retval, $q ) use ( $match_quotations, $unmodified_search ) {
global $wpdb;
$searchand = ' AND ';
$like_op = 'LIKE';
$andor_op = 'OR';
foreach ( $match_quotations as $term ) {
$like = '%' . $wpdb->esc_like( $term ) . '%';
/*
* Only match against post title and post content.
*
* WP includes post_excerpt in search, but that isn't useful for us.
*/
$retval .= $wpdb->prepare( "{$searchand}(({$wpdb->posts}.post_title $like_op %s) $andor_op ({$wpdb->posts}.post_content $like_op %s))", $like, $like );
}
// Reset 's' field to the original search term.
$q->set( 's', $unmodified_search );
return $retval;
};
// Add our filter.
add_filter( 'posts_search', $quote_filter, 10, 2 );
// Remove our filter afterwards.
add_action( 'posts_selection', function() use ( $quote_filter ) {
remove_filter( 'posts_search', $quote_filter );
} );
} );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment