WordPress.org

Make WordPress Core


Ignore:
Timestamp:
10/08/2015 03:17:22 AM (4 years ago)
Author:
boonebgorges
Message:

Allow excluded keywords when searching posts.

Pass a keyword with a leading hyphen to exclude posts containing that keyword.
For example, 'taco -onions' will return posts that contain the word 'taco' but
do not contain the word 'onions'.

Props akibjorklund.
Fixes #33988.

File:
1 edited

Legend:

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

    r34903 r34934  
    15101510     * @since 4.2.0 Introduced the ability to order by specific clauses of a `$meta_query`, by passing the clause's
    15111511     *              array key to `$orderby`.
    1512      * @since 4.4.0 Introduced `$post_name__in` and `$title` parameters.
     1512     * @since 4.4.0 Introduced `$post_name__in` and `$title` parameters. `$s` was updated to support excluded
     1513     *              search terms, by prepending a hyphen.
    15131514     * @access public
    15141515     *
     
    15881589     *                                                 'posts_per_page' when is_archive(), or is_search() are true.
    15891590     *     @type array        $post_name__in           An array of post slugs that results must match.
    1590      *     @type string       $s                       Search keyword.
     1591     *     @type string       $s                       Search keyword(s). Prepending a term with a hyphen will
     1592     *                                                 exclude posts matching that term. Eg, 'pillow -sofa' will
     1593     *                                                 return posts containing 'pillow' but not 'sofa'.
    15911594     *     @type int          $second                  Second of the minute. Default empty. Accepts numbers 0-60.
    15921595     *     @type bool         $sentence                Whether to search by phrase. Default false.
     
    21592162        $q['search_orderby_title'] = array();
    21602163        foreach ( $q['search_terms'] as $term ) {
    2161             if ( $n ) {
     2164            // Terms prefixed with '-' should be excluded.
     2165            $include = '-' !== substr( $term, 0, 1 );
     2166            if ( $include ) {
     2167                $like_op  = 'LIKE';
     2168                $andor_op = 'OR';
     2169            } else {
     2170                $like_op  = 'NOT LIKE';
     2171                $andor_op = 'AND';
     2172                $term     = substr( $term, 1 );
     2173            }
     2174
     2175            if ( $n && $include ) {
    21622176                $like = '%' . $wpdb->esc_like( $term ) . '%';
    21632177                $q['search_orderby_title'][] = $wpdb->prepare( "$wpdb->posts.post_title LIKE %s", $like );
     
    21652179
    21662180            $like = $n . $wpdb->esc_like( $term ) . $n;
    2167             $search .= $wpdb->prepare( "{$searchand}(($wpdb->posts.post_title LIKE %s) OR ($wpdb->posts.post_content LIKE %s))", $like, $like );
     2181            $search .= $wpdb->prepare( "{$searchand}(($wpdb->posts.post_title $like_op %s) $andor_op ($wpdb->posts.post_content $like_op %s))", $like, $like );
    21682182            $searchand = ' AND ';
    21692183        }
     
    22652279        if ( $q['search_terms_count'] > 1 ) {
    22662280            $num_terms = count( $q['search_orderby_title'] );
    2267             $like = '%' . $wpdb->esc_like( $q['s'] ) . '%';
     2281
     2282            // If the search terms contain negative queries, don't bother ordering by sentence matches.
     2283            $like = '';
     2284            if ( ! preg_match( '/(?:\s|^)\-/', $q['s'] ) ) {
     2285                $like = '%' . $wpdb->esc_like( $q['s'] ) . '%';
     2286            }
    22682287
    22692288            $search_orderby = '(CASE ';
     2289
    22702290            // sentence match in 'post_title'
    2271             $search_orderby .= $wpdb->prepare( "WHEN $wpdb->posts.post_title LIKE %s THEN 1 ", $like );
     2291            if ( $like ) {
     2292                $search_orderby .= $wpdb->prepare( "WHEN $wpdb->posts.post_title LIKE %s THEN 1 ", $like );
     2293            }
    22722294
    22732295            // sanity limit, sort as sentence when more than 6 terms
     
    22822304
    22832305            // sentence match in 'post_content'
    2284             $search_orderby .= $wpdb->prepare( "WHEN $wpdb->posts.post_content LIKE %s THEN 4 ", $like );
     2306            if ( $like ) {
     2307                $search_orderby .= $wpdb->prepare( "WHEN $wpdb->posts.post_content LIKE %s THEN 4 ", $like );
     2308            }
    22852309            $search_orderby .= 'ELSE 5 END)';
    22862310        } else {
Note: See TracChangeset for help on using the changeset viewer.