From e9ef25d9f6189af27891d2dd937665bbda284bc1 Mon Sep 17 00:00:00 2001 From: Boone Gorges Date: Fri, 14 Oct 2016 20:05:40 +0000 Subject: [PATCH] Query: Allow the hyphen-prefix-for-search-exclusion feature to be disabled by filter. WordPress 4.4 introduced "hyphen exclusion" for search terms, so that "foo -bar" would return posts containing "foo" AND not containing "bar". The new filter 'wp_query_use_hyphen_for_exclusion' allows developers to disable this feature when it's known that their content will contain semantically important leading hyphens. Props chriseverson, choongsavvii. Fixes #38099. git-svn-id: https://develop.svn.wordpress.org/trunk@38792 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/class-wp-query.php | 16 ++++++++++++++-- tests/phpunit/tests/query/search.php | 22 ++++++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/wp-includes/class-wp-query.php b/src/wp-includes/class-wp-query.php index 226170ee7d..9e7883f6c5 100644 --- a/src/wp-includes/class-wp-query.php +++ b/src/wp-includes/class-wp-query.php @@ -721,7 +721,9 @@ class WP_Query { * @type array $post_name__in An array of post slugs that results must match. * @type string $s Search keyword(s). Prepending a term with a hyphen will * exclude posts matching that term. Eg, 'pillow -sofa' will - * return posts containing 'pillow' but not 'sofa'. + * return posts containing 'pillow' but not 'sofa'. This feature + * can be disabled using the + * 'wp_query_use_hyphen_for_exclusion' filter. * @type int $second Second of the minute. Default empty. Accepts numbers 0-60. * @type bool $sentence Whether to search by phrase. Default false. * @type bool $suppress_filters Whether to suppress filters. Default false. @@ -1318,10 +1320,20 @@ class WP_Query { $n = ! empty( $q['exact'] ) ? '' : '%'; $searchand = ''; $q['search_orderby_title'] = array(); + + /** + * Filters whether search terms preceded by hyphens should excluded from results. + * + * @since 4.7.0 + * + * @param bool Whether the query should exclude terms preceded with a hyphen. + */ + $hyphen_exclusion = apply_filters( 'wp_query_use_hyphen_for_exclusion', true ); + foreach ( $q['search_terms'] as $term ) { // Terms prefixed with '-' should be excluded. $include = '-' !== substr( $term, 0, 1 ); - if ( $include ) { + if ( $include || ! $hyphen_exclusion ) { $like_op = 'LIKE'; $andor_op = 'OR'; } else { diff --git a/tests/phpunit/tests/query/search.php b/tests/phpunit/tests/query/search.php index 2931a1a731..43c5da4caa 100644 --- a/tests/phpunit/tests/query/search.php +++ b/tests/phpunit/tests/query/search.php @@ -59,6 +59,28 @@ class Tests_Query_Search extends WP_UnitTestCase { return array(); } + /** + * @ticket 38099 + */ + function test_filter_wp_query_use_hyphen_for_exclusion() { + $title = '-HYPHENATION_TEST'; + + // Create a post with a title which starts with a hyphen + $post_id = self::factory()->post->create( array( + 'post_content' => $title, 'post_type' => $this->post_type + ) ); + + // By default, we can use the hyphen prefix to exclude results + $this->assertEquals( array(), $this->get_search_results( $title ) ); + + // After we disable the feature using the filter, we should get the result + add_filter( 'wp_query_use_hyphen_for_exclusion', '__return_false' ); + $result = $this->get_search_results( $title ); + $post = array_pop( $result ); + $this->assertEquals( $post->ID, $post_id ); + remove_filter( 'wp_query_use_hyphen_for_exclusion', '__return_false' ); + } + /** * @ticket 33988 */