From 12c72a790628c83a19f5858d41cf4924cebd2d8a Mon Sep 17 00:00:00 2001 From: Boone Gorges Date: Thu, 20 Oct 2016 18:41:22 +0000 Subject: [PATCH] Query: Allow the prefix used for search term exclusion to be filtered. [38792] allowed `WP_Query`'s hyphen-as-exclusion-prefix feature to be disabled via filter. A more general solution is to allow the prefix to be filtered; returning an empty value from a filter callback works to disable the feature. Props dlh. Fixes #38099. git-svn-id: https://develop.svn.wordpress.org/trunk@38844 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/class-wp-query.php | 27 ++++++++++++----------- tests/phpunit/tests/query/search.php | 33 +++++++++++++++++++++++++--- 2 files changed, 44 insertions(+), 16 deletions(-) diff --git a/src/wp-includes/class-wp-query.php b/src/wp-includes/class-wp-query.php index 9e7883f6c5..a6cd1cf401 100644 --- a/src/wp-includes/class-wp-query.php +++ b/src/wp-includes/class-wp-query.php @@ -721,9 +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'. This feature - * can be disabled using the - * 'wp_query_use_hyphen_for_exclusion' filter. + * return posts containing 'pillow' but not 'sofa'. The + * character used for exclusion can be modified using the + * the 'wp_query_search_exclusion_prefix' 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. @@ -1322,27 +1322,28 @@ class WP_Query { $q['search_orderby_title'] = array(); /** - * Filters whether search terms preceded by hyphens should excluded from results. + * Filters the prefix that indicates that a search term should be excluded from results. * * @since 4.7.0 * - * @param bool Whether the query should exclude terms preceded with a hyphen. + * @param string $exclusion_prefix The prefix. Default '-'. Returning + * an empty value disables exclusions. */ - $hyphen_exclusion = apply_filters( 'wp_query_use_hyphen_for_exclusion', true ); + $exclusion_prefix = apply_filters( 'wp_query_search_exclusion_prefix', '-' ); foreach ( $q['search_terms'] as $term ) { - // Terms prefixed with '-' should be excluded. - $include = '-' !== substr( $term, 0, 1 ); - if ( $include || ! $hyphen_exclusion ) { - $like_op = 'LIKE'; - $andor_op = 'OR'; - } else { + // If there is an $exclusion_prefix, terms prefixed with it should be excluded. + $exclude = $exclusion_prefix && ( $exclusion_prefix === substr( $term, 0, 1 ) ); + if ( $exclude ) { $like_op = 'NOT LIKE'; $andor_op = 'AND'; $term = substr( $term, 1 ); + } else { + $like_op = 'LIKE'; + $andor_op = 'OR'; } - if ( $n && $include ) { + if ( $n && ! $exclude ) { $like = '%' . $wpdb->esc_like( $term ) . '%'; $q['search_orderby_title'][] = $wpdb->prepare( "{$wpdb->posts}.post_title LIKE %s", $like ); } diff --git a/tests/phpunit/tests/query/search.php b/tests/phpunit/tests/query/search.php index 43c5da4caa..dedfa47e26 100644 --- a/tests/phpunit/tests/query/search.php +++ b/tests/phpunit/tests/query/search.php @@ -62,7 +62,7 @@ class Tests_Query_Search extends WP_UnitTestCase { /** * @ticket 38099 */ - function test_filter_wp_query_use_hyphen_for_exclusion() { + function test_disable_search_exclusion_prefix() { $title = '-HYPHENATION_TEST'; // Create a post with a title which starts with a hyphen @@ -74,11 +74,38 @@ class Tests_Query_Search extends WP_UnitTestCase { $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' ); + add_filter( 'wp_query_search_exclusion_prefix', '__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' ); + remove_filter( 'wp_query_search_exclusion_prefix', '__return_false' ); + } + + /** + * @ticket 38099 + */ + function test_change_search_exclusion_prefix() { + $title = '#OCTOTHORPE_TEST'; + + // Create a post with a title that starts with a non-hyphen prefix. + $post_id = self::factory()->post->create( array( + 'post_content' => $title, 'post_type' => $this->post_type + ) ); + + // By default, we should get the result. + $result = $this->get_search_results( $title ); + $post = array_pop( $result ); + $this->assertEquals( $post->ID, $post_id ); + + // After we change the prefix, the result should be excluded. + add_filter( 'wp_query_search_exclusion_prefix', array( $this, 'filter_search_exclusion_prefix_octothorpe' ) ); + $found = $this->get_search_results( $title ); + remove_filter( 'wp_query_search_exclusion_prefix', array( $this, 'filter_search_exclusion_prefix_octothorpe' ) ); + $this->assertEquals( array(), $found ); + } + + function filter_search_exclusion_prefix_octothorpe() { + return '#'; } /**