diff options
Diffstat (limited to 'plugins/jetpack/modules/search/class.jetpack-search.php')
-rw-r--r-- | plugins/jetpack/modules/search/class.jetpack-search.php | 124 |
1 files changed, 108 insertions, 16 deletions
diff --git a/plugins/jetpack/modules/search/class.jetpack-search.php b/plugins/jetpack/modules/search/class.jetpack-search.php index 5b0e8064..9733d2a2 100644 --- a/plugins/jetpack/modules/search/class.jetpack-search.php +++ b/plugins/jetpack/modules/search/class.jetpack-search.php @@ -19,6 +19,10 @@ class Jetpack_Search { protected $aggregations = array(); protected $max_aggregations_count = 100; + // used to output query meta into page + protected $last_query_info; + protected $last_query_failure_info; + protected static $instance; //Languages with custom analyzers, other languages are supported, @@ -89,6 +93,35 @@ class Jetpack_Search { add_filter( 'posts_pre_query', array( $this, 'filter__posts_pre_query' ), 10, 2 ); add_filter( 'jetpack_search_es_wp_query_args', array( $this, 'filter__add_date_filter_to_query' ), 10, 2 ); + + add_action( 'did_jetpack_search_query', array( $this, 'store_query_success' ) ); + add_action( 'failed_jetpack_search_query', array( $this, 'store_query_failure' ) ); + } + } + + /** + * Print query info as a HTML comment in the footer + */ + + public function store_query_failure( $meta ) { + $this->last_query_failure_info = $meta; + add_action( 'wp_footer', array( $this, 'print_query_failure' ) ); + } + + public function print_query_failure() { + if ( $this->last_query_failure_info ) { + echo '<!-- Jetpack Search failed with code ' . $this->last_query_failure_info['response_code'] . ': ' . $this->last_query_failure_info['json']['error'] . ' - ' . $this->last_query_failure_info['json']['message'] . ' -->'; + } + } + + public function store_query_success( $meta ) { + $this->last_query_info = $meta; + add_action( 'wp_footer', array( $this, 'print_query_success' ) ); + } + + public function print_query_success() { + if ( $this->last_query_info ) { + echo '<!-- Jetpack Search took ' . intval( $this->last_query_info['elapsed_time'] ) . ' ms, ES time ' . $this->last_query_info['es_time'] . ' ms -->'; } } @@ -146,13 +179,22 @@ class Jetpack_Search { } $response_code = wp_remote_retrieve_response_code( $request ); + $response = json_decode( wp_remote_retrieve_body( $request ), true ); if ( ! $response_code || $response_code < 200 || $response_code >= 300 ) { + /** + * Fires after a search query request has failed + * + * @module search + * + * @since 5.6.0 + * + * @param array Array containing the response code and response from the failed search query + */ + do_action( 'failed_jetpack_search_query', array( 'response_code' => $response_code, 'json' => $response ) ); return new WP_Error( 'invalid_search_api_response', 'Invalid response from API - ' . $response_code ); } - $response = json_decode( wp_remote_retrieve_body( $request ), true ); - $took = is_array( $response ) && $response['took'] ? $response['took'] : null; $query = array( @@ -176,7 +218,9 @@ class Jetpack_Search { * float es_time Amount of time Elasticsearch spent running the request, in milliseconds * string url API url that was queried * - * @since 5.0 + * @module search + * + * @since 5.0.0 * * @param array $query Array of information about the query performed */ @@ -198,7 +242,16 @@ class Jetpack_Search { * @return array Array of matching posts */ public function filter__posts_pre_query( $posts, $query ) { - if ( ! $query->is_main_query() || ! $query->is_search() ) { + /** + * Determine whether a given WP_Query should be handled by ElasticSearch + * + * @module search + * + * @since 5.6.0 + * @param bool $should_handle Should be handled by Jetpack Search + * @param WP_Query $query The wp_query object + */ + if ( ! apply_filters( 'jetpack_search_should_handle_query', ( $query->is_main_query() && $query->is_search() ), $query ) ) { return $posts; } @@ -242,10 +295,6 @@ class Jetpack_Search { * @param WP_Query $query The original WP_Query to use for the parameters of our search */ public function do_search( WP_Query $query ) { - if ( ! $query->is_main_query() || ! $query->is_search() ) { - return; - } - $page = ( $query->get( 'paged' ) ) ? absint( $query->get( 'paged' ) ) : 1; $posts_per_page = $query->get( 'posts_per_page' ); @@ -340,6 +389,12 @@ class Jetpack_Search { return; } + // If we have aggregations, fix the ordering to match the input order (ES doesn't + // guarantee the return order) + if ( isset( $this->search_result['results']['aggregations'] ) && ! empty( $this->search_result['results']['aggregations'] ) ) { + $this->search_result['results']['aggregations'] = $this->fix_aggregation_ordering( $this->search_result['results']['aggregations'], $this->aggregations ); + } + // Total number of results for paging purposes. Capped at $this->>max_offset + $posts_per_page, as deep paging // gets quite expensive $this->found_posts = min( $this->search_result['results']['total'], $this->max_offset + $posts_per_page ); @@ -374,7 +429,7 @@ class Jetpack_Search { foreach ( $the_tax_query->queries as $tax_query ) { // Right now we only support slugs...see note above - if ( 'slug' !== $tax_query['field'] ) { + if ( ! is_array( $tax_query ) || 'slug' !== $tax_query['field'] ) { continue; } @@ -426,7 +481,6 @@ class Jetpack_Search { } $post_type_object = get_post_type_object( $post_type ); - if ( ! $post_type_object || $post_type_object->exclude_from_search ) { continue; } @@ -856,11 +910,19 @@ class Jetpack_Search { * @param Jetpack_WPES_Query_Builder $builder The builder instance that is creating the ES query */ public function add_date_histogram_aggregation_to_es_query_builder( array $aggregation, $label, Jetpack_WPES_Query_Builder $builder ) { + $args = array( + 'interval' => $aggregation['interval'], + 'field' => ( ! empty( $aggregation['field'] ) && 'post_date_gmt' == $aggregation['field'] ) ? 'date_gmt' : 'date', + ); + + if ( isset( $aggregation['min_doc_count'] ) ) { + $args['min_doc_count'] = intval( $aggregation['min_doc_count'] ); + } else { + $args['min_doc_count'] = 1; + } + $builder->add_aggs( $label, array( - 'date_histogram' => array( - 'interval' => $aggregation['interval'], - 'field' => ( ! empty( $aggregation['field'] ) && 'post_date_gmt' == $aggregation['field'] ) ? 'date_gmt' : 'date', - ), + 'date_histogram' => $args, )); } @@ -1047,7 +1109,7 @@ class Jetpack_Search { if ( ! empty( $query->tax_query ) && ! empty( $query->tax_query->queries ) && is_array( $query->tax_query->queries ) ) { foreach( $query->tax_query->queries as $tax_query ) { - if ( $this->aggregations[ $label ]['taxonomy'] === $tax_query['taxonomy'] && + if ( is_array( $tax_query ) && $this->aggregations[ $label ]['taxonomy'] === $tax_query['taxonomy'] && 'slug' === $tax_query['field'] && is_array( $tax_query['terms'] ) ) { $existing_term_slugs = array_merge( $existing_term_slugs, $tax_query['terms'] ); @@ -1280,7 +1342,7 @@ class Jetpack_Search { } foreach( $filters as $filter ) { - if ( isset( $filters['buckets'] ) && is_array( $filter['buckets'] ) ) { + if ( isset( $filter['buckets'] ) && is_array( $filter['buckets'] ) ) { foreach( $filter['buckets'] as $item ) { if ( isset( $item['active'] ) && $item['active'] ) { $active_buckets[] = $item; @@ -1335,4 +1397,34 @@ class Jetpack_Search { */ return apply_filters( 'jetpack_search_taxonomy_query_var', $taxonomy->query_var, $taxonomy_name ); } + + /** + * Takes an array of aggregation results, and ensures the array key ordering matches the key order in $desired + * which is the input order + * + * Necessary because ES does not always return Aggs in the same order that you pass them in, and it should be possible + * to control the display order easily + * + * @module search + * + * @param array $aggregations Agg results to be reordered + * @param array $desired Array with keys representing the desired ordering + * + * @return array A new array with reordered keys, matching those in $desired + */ + public function fix_aggregation_ordering( array $aggregations, array $desired ) { + if ( empty( $aggregations ) || empty( $desired ) ) { + return $aggregations; + } + + $reordered = array(); + + foreach( array_keys( $desired ) as $agg_name ) { + if ( isset( $aggregations[ $agg_name ] ) ) { + $reordered[ $agg_name ] = $aggregations[ $agg_name ]; + } + } + + return $reordered; + } } |