diff options
Diffstat (limited to 'plugins/jetpack/modules/search')
-rw-r--r-- | plugins/jetpack/modules/search/class.jetpack-search-helpers.php | 6 | ||||
-rw-r--r-- | plugins/jetpack/modules/search/class.jetpack-search.php | 513 |
2 files changed, 352 insertions, 167 deletions
diff --git a/plugins/jetpack/modules/search/class.jetpack-search-helpers.php b/plugins/jetpack/modules/search/class.jetpack-search-helpers.php index 27526b4c..39a89c53 100644 --- a/plugins/jetpack/modules/search/class.jetpack-search-helpers.php +++ b/plugins/jetpack/modules/search/class.jetpack-search-helpers.php @@ -7,6 +7,8 @@ * @since 5.8.0 */ +use Automattic\Jetpack\Constants; + /** * Various helper functions for reuse throughout the Jetpack Search code. * @@ -659,8 +661,8 @@ class Jetpack_Search_Helpers { */ public static function site_has_vip_index() { $has_vip_index = ( - Jetpack_Constants::is_defined( 'JETPACK_SEARCH_VIP_INDEX' ) && - Jetpack_Constants::get_constant( 'JETPACK_SEARCH_VIP_INDEX' ) + Constants::is_defined( 'JETPACK_SEARCH_VIP_INDEX' ) && + Constants::get_constant( 'JETPACK_SEARCH_VIP_INDEX' ) ); /** diff --git a/plugins/jetpack/modules/search/class.jetpack-search.php b/plugins/jetpack/modules/search/class.jetpack-search.php index 40867589..1271afc6 100644 --- a/plugins/jetpack/modules/search/class.jetpack-search.php +++ b/plugins/jetpack/modules/search/class.jetpack-search.php @@ -1,4 +1,4 @@ -<?php +<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName /** * Jetpack Search: Main Jetpack_Search class * @@ -7,6 +7,9 @@ * @since 5.0.0 */ +use Automattic\Jetpack\Connection\Client; +use Automattic\Jetpack\Constants; + /** * The main class for the Jetpack Search module. * @@ -151,12 +154,24 @@ class Jetpack_Search { */ public function setup() { if ( ! Jetpack::is_active() || ! Jetpack_Plan::supports( 'search' ) ) { + /** + * Fires when the Jetpack Search fails and would fallback to MySQL. + * + * @module search + * @since 7.9.0 + * + * @param string $reason Reason for Search fallback. + * @param mixed $data Data associated with the request, such as attempted search parameters. + */ + do_action( 'jetpack_search_abort', 'inactive', null ); return; } $this->jetpack_blog_id = Jetpack::get_option( 'id' ); if ( ! $this->jetpack_blog_id ) { + /** This action is documented in modules/search/class.jetpack-search.php */ + do_action( 'jetpack_search_abort', 'no_blog_id', null ); return; } @@ -184,6 +199,7 @@ class Jetpack_Search { add_action( 'init', array( $this, 'set_filters_from_widgets' ) ); add_action( 'pre_get_posts', array( $this, 'maybe_add_post_type_as_var' ) ); + add_action( 'wp_enqueue_scripts', array( $this, 'load_assets' ) ); } else { add_action( 'update_option', array( $this, 'track_widget_updates' ), 10, 3 ); } @@ -192,6 +208,100 @@ class Jetpack_Search { } /** + * Loads assets for Jetpack Instant Search Prototype featuring Search As You Type experience. + */ + public function load_assets() { + if ( Constants::is_true( 'JETPACK_SEARCH_PROTOTYPE' ) ) { + $script_relative_path = '_inc/build/instant-search/jp-search.bundle.js'; + if ( file_exists( JETPACK__PLUGIN_DIR . $script_relative_path ) ) { + $script_version = self::get_asset_version( $script_relative_path ); + $script_path = plugins_url( $script_relative_path, JETPACK__PLUGIN_FILE ); + wp_enqueue_script( 'jetpack-instant-search', $script_path, array(), $script_version, true ); + $this->load_and_initialize_tracks(); + + $widget_options = Jetpack_Search_Helpers::get_widgets_from_option(); + if ( is_array( $widget_options ) ) { + $widget_options = end( $widget_options ); + } + + $filters = Jetpack_Search_Helpers::get_filters_from_widgets(); + $widgets = array(); + foreach ( $filters as $key => $filter ) { + if ( ! isset( $widgets[ $filter['widget_id'] ] ) ) { + $widgets[ $filter['widget_id'] ]['filters'] = array(); + $widgets[ $filter['widget_id'] ]['widget_id'] = $filter['widget_id']; + } + $new_filter = $filter; + $new_filter['filter_id'] = $key; + $widgets[ $filter['widget_id'] ]['filters'][] = $new_filter; + } + + $post_type_objs = get_post_types( array(), 'objects' ); + $post_type_labels = array(); + foreach ( $post_type_objs as $key => $obj ) { + $post_type_labels[ $key ] = array( + 'singular_name' => $obj->labels->singular_name, + 'name' => $obj->labels->name, + ); + } + // This is probably a temporary filter for testing the prototype. + $options = array( + 'enableLoadOnScroll' => false, + 'homeUrl' => home_url(), + 'locale' => str_replace( '_', '-', get_locale() ), + 'postTypeFilters' => $widget_options['post_types'], + 'postTypes' => $post_type_labels, + 'siteId' => Jetpack::get_option( 'id' ), + 'sort' => $widget_options['sort'], + 'widgets' => array_values( $widgets ), + ); + /** + * Customize Instant Search Options. + * + * @module search + * + * @since 7.7.0 + * + * @param array $options Array of parameters used in Instant Search queries. + */ + $options = apply_filters( 'jetpack_instant_search_options', $options ); + + wp_localize_script( + 'jetpack-instant-search', + 'JetpackInstantSearchOptions', + $options + ); + } + + $style_relative_path = '_inc/build/instant-search/instant-search.min.css'; + if ( file_exists( JETPACK__PLUGIN_DIR . $script_relative_path ) ) { + $style_version = self::get_asset_version( $style_relative_path ); + $style_path = plugins_url( $style_relative_path, JETPACK__PLUGIN_FILE ); + wp_enqueue_style( 'jetpack-instant-search', $style_path, array(), $style_version ); + } + } + } + + /** + * Loads scripts for Tracks analytics library + */ + public function load_and_initialize_tracks() { + wp_enqueue_script( 'jp-tracks', '//stats.wp.com/w.js', array(), gmdate( 'YW' ), true ); + } + + /** + * Get the version number to use when loading the file. Allows us to bypass cache when developing. + * + * @param string $file Path of the file we are looking for. + * @return string $script_version Version number. + */ + public static function get_asset_version( $file ) { + return Jetpack::is_development_version() && file_exists( JETPACK__PLUGIN_DIR . $file ) + ? filemtime( JETPACK__PLUGIN_DIR . $file ) + : JETPACK__VERSION; + } + + /** * When an Elasticsearch query fails, this stores it and enqueues some debug information in the footer. * * @since 5.6.0 @@ -244,10 +354,10 @@ class Jetpack_Search { esc_html( $this->last_query_info['es_time'] ) ); - if ( isset( $_GET['searchdebug'] ) ) { + if ( isset( $_GET['searchdebug'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended printf( '<!-- Query response data: %s -->', - esc_html( print_r( $this->last_query_info, 1 ) ) + esc_html( print_r( $this->last_query_info, 1 ) ) // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r ); } } @@ -315,16 +425,17 @@ class Jetpack_Search { * @param WP_Query $query A WP_Query instance. */ public function maybe_add_post_type_as_var( WP_Query $query ) { - if ( $this->should_handle_query( $query ) && ! empty( $_GET['post_type'] ) ) { - $post_types = ( is_string( $_GET['post_type'] ) && false !== strpos( $_GET['post_type'], ',' ) ) - ? $post_type = explode( ',', $_GET['post_type'] ) - : (array) $_GET['post_type']; + $post_type = ( ! empty( $_GET['post_type'] ) ) ? $_GET['post_type'] : false; // phpcs:ignore WordPress.Security.NonceVerification.Recommended + if ( $this->should_handle_query( $query ) && $post_type ) { + $post_types = ( is_string( $post_type ) && false !== strpos( $post_type, ',' ) ) + ? explode( ',', $post_type ) + : (array) $post_type; $post_types = array_map( 'sanitize_key', $post_types ); $query->set( 'post_type', $post_types ); } } - /* + /** * Run a search on the WordPress.com public API. * * @since 5.0.0 @@ -339,7 +450,7 @@ class Jetpack_Search { $do_authenticated_request = false; - if ( class_exists( 'Jetpack_Client' ) && + if ( class_exists( 'Automattic\\Jetpack\\Connection\\Client' ) && isset( $es_args['authenticated_request'] ) && true === $es_args['authenticated_request'] ) { $do_authenticated_request = true; @@ -348,7 +459,7 @@ class Jetpack_Search { unset( $es_args['authenticated_request'] ); $request_args = array( - 'headers' => array( + 'headers' => array( 'Content-Type' => 'application/json', ), 'timeout' => 10, @@ -362,11 +473,14 @@ class Jetpack_Search { if ( $do_authenticated_request ) { $request_args['method'] = 'POST'; - $request = Jetpack_Client::wpcom_json_api_request_as_blog( $endpoint, Jetpack_Client::WPCOM_JSON_API_VERSION, $request_args, $request_body ); + $request = Client::wpcom_json_api_request_as_blog( $endpoint, Client::WPCOM_JSON_API_VERSION, $request_args, $request_body ); } else { - $request_args = array_merge( $request_args, array( - 'body' => $request_body, - ) ); + $request_args = array_merge( + $request_args, + array( + 'body' => $request_body, + ) + ); $request = wp_remote_post( $service_url, $request_args ); } @@ -425,10 +539,13 @@ class Jetpack_Search { * * @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, - ) ); + 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 ); } @@ -450,16 +567,19 @@ class Jetpack_Search { */ public function filter__posts_pre_query( $posts, $query ) { if ( ! $this->should_handle_query( $query ) ) { + // Intentionally not adding the 'jetpack_search_abort' action since this should fire for every request except for search. return $posts; } $this->do_search( $query ); if ( ! is_array( $this->search_result ) ) { + /** This action is documented in modules/search/class.jetpack-search.php */ + do_action( 'jetpack_search_abort', 'no_search_results_array', $this->search_result ); return $posts; } - // If no results, nothing to do + // If no results, nothing to do. if ( ! count( $this->search_result['results']['hits'] ) ) { return array(); } @@ -470,7 +590,7 @@ class Jetpack_Search { $post_ids[] = (int) $result['fields']['post_id']; } - // Query all posts now + // Query all posts now. $args = array( 'post__in' => $post_ids, 'orderby' => 'post__in', @@ -498,6 +618,9 @@ class Jetpack_Search { */ public function do_search( WP_Query $query ) { if ( ! $this->should_handle_query( $query ) ) { + // If we make it here, either 'filter__posts_pre_query' somehow allowed it or a different entry to do_search. + /** This action is documented in modules/search/class.jetpack-search.php */ + do_action( 'jetpack_search_abort', 'search_attempted_non_search_query', $query ); return; } @@ -567,7 +690,7 @@ class Jetpack_Search { // Convert the WP-style args into ES args. $es_query_args = $this->convert_wp_es_to_es_args( $es_wp_query_args ); - //Only trust ES to give us IDs, not the content since it is a mirror + // Only trust ES to give us IDs, not the content since it is a mirror. $es_query_args['fields'] = array( 'post_id', ); @@ -647,7 +770,6 @@ class Jetpack_Search { return $args; } - if ( ! $the_tax_query instanceof WP_Tax_Query || empty( $the_tax_query->queried_terms ) || ! is_array( $the_tax_query->queried_terms ) ) { return $args; } @@ -655,7 +777,7 @@ class Jetpack_Search { $args = array(); foreach ( $the_tax_query->queries as $tax_query ) { - // Right now we only support slugs...see note above + // Right now we only support slugs...see note above. if ( ! is_array( $tax_query ) || 'slug' !== $tax_query['field'] ) { continue; } @@ -688,9 +810,13 @@ class Jetpack_Search { // If we're searching 'any', we want to only pass searchable post types to Elasticsearch. if ( 'any' === $post_types ) { - $post_types = array_values( get_post_types( array( - 'exclude_from_search' => false, - ) ) ); + $post_types = array_values( + get_post_types( + array( + 'exclude_from_search' => false, + ) + ) + ); } if ( ! is_array( $post_types ) ) { @@ -748,11 +874,11 @@ class Jetpack_Search { public function filter__add_date_filter_to_query( array $es_wp_query_args, WP_Query $query ) { if ( $query->get( 'year' ) ) { if ( $query->get( 'monthnum' ) ) { - // Padding + // Padding. $date_monthnum = sprintf( '%02d', $query->get( 'monthnum' ) ); if ( $query->get( 'day' ) ) { - // Padding + // Padding. $date_day = sprintf( '%02d', $query->get( 'day' ) ); $date_start = $query->get( 'year' ) . '-' . $date_monthnum . '-' . $date_day . ' 00:00:00'; @@ -792,14 +918,14 @@ class Jetpack_Search { $defaults = array( 'blog_id' => get_current_blog_id(), - 'query' => null, // Search phrase - 'query_fields' => array(), // list of fields to search - 'excess_boost' => array(), // map of field to excess boost values (multiply) - 'post_type' => null, // string or an array - 'terms' => array(), // ex: array( 'taxonomy-1' => array( 'slug' ), 'taxonomy-2' => array( 'slug-a', 'slug-b' ) ) - 'author' => null, // id or an array of ids - 'author_name' => array(), // string or an array - 'date_range' => null, // array( 'field' => 'date', 'gt' => 'YYYY-MM-dd', 'lte' => 'YYYY-MM-dd' ); date formats: 'YYYY-MM-dd' or 'YYYY-MM-dd HH:MM:SS' + 'query' => null, // Search phrase. + 'query_fields' => array(), // list of fields to search. + 'excess_boost' => array(), // map of field to excess boost values (multiply). + 'post_type' => null, // string or an array. + 'terms' => array(), // ex: array( 'taxonomy-1' => array( 'slug' ), 'taxonomy-2' => array( 'slug-a', 'slug-b' ) ). phpcs:ignore Squiz.PHP.CommentedOutCode.Found. + 'author' => null, // id or an array of ids. + 'author_name' => array(), // string or an array. + 'date_range' => null, // array( 'field' => 'date', 'gt' => 'YYYY-MM-dd', 'lte' => 'YYYY-MM-dd' ); date formats: 'YYYY-MM-dd' or 'YYYY-MM-dd HH:MM:SS'. phpcs:ignore Squiz.PHP.CommentedOutCode.Found. 'orderby' => null, // Defaults to 'relevance' if query is set, otherwise 'date'. Pass an array for multiple orders. 'order' => 'DESC', 'posts_per_page' => 10, @@ -817,11 +943,23 @@ class Jetpack_Search { $args = wp_parse_args( $args, $defaults ); - $parser = new Jetpack_WPES_Search_Query_Parser( $args['query'], array( get_locale() ) ); + $parser = new Jetpack_WPES_Search_Query_Parser( + $args['query'], + /** + * Filter the languages used by Jetpack Search's Query Parser. + * + * @module search + * + * @since 7.9.0 + * + * @param array $languages The array of languages. Default is value of get_locale(). + */ + apply_filters( 'jetpack_search_query_languages', array( get_locale() ) ) + ); if ( empty( $args['query_fields'] ) ) { if ( defined( 'JETPACK_SEARCH_VIP_INDEX' ) && JETPACK_SEARCH_VIP_INDEX ) { - // VIP indices do not have per language fields + // VIP indices do not have per language fields. $match_fields = $this->_get_caret_boosted_fields( array( 'title' => 0.1, @@ -835,13 +973,16 @@ class Jetpack_Search { ); $boost_fields = $this->_get_caret_boosted_fields( - $this->_apply_boosts_multiplier( array( - 'title' => 2, - 'tag.name' => 1, - 'category.name' => 1, - 'author_login' => 1, - 'author' => 1, - ), $args['excess_boost'] ) + $this->_apply_boosts_multiplier( + array( + 'title' => 2, + 'tag.name' => 1, + 'category.name' => 1, + 'author_login' => 1, + 'author' => 1, + ), + $args['excess_boost'] + ) ); $boost_phrase_fields = $this->_get_caret_boosted_fields( @@ -863,22 +1004,32 @@ class Jetpack_Search { 'tag.name' => 0.1, 'category.name' => 0.1, ), - $this->_get_caret_boosted_fields( array( - 'author_login' => 0.1, - 'author' => 0.1, - ) ) + $this->_get_caret_boosted_fields( + array( + 'author_login' => 0.1, + 'author' => 0.1, + ) + ) ); $boost_fields = $parser->merge_ml_fields( - $this->_apply_boosts_multiplier( array( - 'title' => 2, - 'tag.name' => 1, - 'category.name' => 1, - ), $args['excess_boost'] ), - $this->_get_caret_boosted_fields( $this->_apply_boosts_multiplier( array( - 'author_login' => 1, - 'author' => 1, - ), $args['excess_boost'] ) ) + $this->_apply_boosts_multiplier( + array( + 'title' => 2, + 'tag.name' => 1, + 'category.name' => 1, + ), + $args['excess_boost'] + ), + $this->_get_caret_boosted_fields( + $this->_apply_boosts_multiplier( + array( + 'author_login' => 1, + 'author' => 1, + ), + $args['excess_boost'] + ) + ) ); $boost_phrase_fields = $parser->merge_ml_fields( @@ -889,9 +1040,11 @@ class Jetpack_Search { 'tag.name' => 1, 'category.name' => 1, ), - $this->_get_caret_boosted_fields( array( - 'author' => 1, - ) ) + $this->_get_caret_boosted_fields( + array( + 'author' => 1, + ) + ) ); } } else { @@ -901,20 +1054,26 @@ class Jetpack_Search { $boost_fields = null; } - $parser->phrase_filter( array( - 'must_query_fields' => $match_fields, - 'boost_query_fields' => null, - ) ); - $parser->remaining_query( array( - 'must_query_fields' => $match_fields, - 'boost_query_fields' => $boost_fields, - ) ); + $parser->phrase_filter( + array( + 'must_query_fields' => $match_fields, + 'boost_query_fields' => null, + ) + ); + $parser->remaining_query( + array( + 'must_query_fields' => $match_fields, + 'boost_query_fields' => $boost_fields, + ) + ); - // Boost on phrase matches - $parser->remaining_query( array( - 'boost_query_fields' => $boost_phrase_fields, - 'boost_query_type' => 'phrase', - ) ); + // Boost on phrase matches. + $parser->remaining_query( + array( + 'boost_query_fields' => $boost_phrase_fields, + 'boost_query_type' => 'phrase', + ) + ); /** * Modify the recency decay parameters for the search query. @@ -945,10 +1104,13 @@ class Jetpack_Search { ); if ( ! empty( $decay_params ) ) { - // Newer content gets weighted slightly higher - $parser->add_decay( 'gauss', array( - 'date_gmt' => $decay_params - ) ); + // Newer content gets weighted slightly higher. + $parser->add_decay( + 'gauss', + array( + 'date_gmt' => $decay_params, + ) + ); } $es_query_args = array( @@ -956,7 +1118,7 @@ class Jetpack_Search { 'size' => absint( $args['posts_per_page'] ), ); - // ES "from" arg (offset) + // ES "from" arg (offset). if ( $args['offset'] ) { $es_query_args['from'] = absint( $args['offset'] ); } elseif ( $args['paged'] ) { @@ -969,7 +1131,7 @@ class Jetpack_Search { $args['author_name'] = array( $args['author_name'] ); } - // ES stores usernames, not IDs, so transform + // ES stores usernames, not IDs, so transform. if ( ! empty( $args['author'] ) ) { if ( ! is_array( $args['author'] ) ) { $args['author'] = array( $args['author'] ); @@ -984,30 +1146,35 @@ class Jetpack_Search { } } - ////////////////////////////////////////////////// - // Build the filters from the query elements. - // Filters rock because they are cached from one query to the next - // but they are cached as individual filters, rather than all combined together. - // May get performance boost by also caching the top level boolean filter too. + /* + * Build the filters from the query elements. + * Filters rock because they are cached from one query to the next + * but they are cached as individual filters, rather than all combined together. + * May get performance boost by also caching the top level boolean filter too. + */ if ( $args['post_type'] ) { if ( ! is_array( $args['post_type'] ) ) { $args['post_type'] = array( $args['post_type'] ); } - $parser->add_filter( array( - 'terms' => array( - 'post_type' => $args['post_type'], - ), - ) ); + $parser->add_filter( + array( + 'terms' => array( + 'post_type' => $args['post_type'], + ), + ) + ); } if ( $args['author_name'] ) { - $parser->add_filter( array( - 'terms' => array( - 'author_login' => $args['author_name'], - ), - ) ); + $parser->add_filter( + array( + 'terms' => array( + 'author_login' => $args['author_name'], + ), + ) + ); } if ( ! empty( $args['date_range'] ) && isset( $args['date_range']['field'] ) ) { @@ -1015,11 +1182,13 @@ class Jetpack_Search { unset( $args['date_range']['field'] ); - $parser->add_filter( array( - 'range' => array( - $field => $args['date_range'], - ), - ) ); + $parser->add_filter( + array( + 'range' => array( + $field => $args['date_range'], + ), + ) + ); } if ( is_array( $args['terms'] ) ) { @@ -1045,11 +1214,13 @@ class Jetpack_Search { } foreach ( $terms as $term ) { - $parser->add_filter( array( - 'term' => array( - $tax_fld => $term, - ), - ) ); + $parser->add_filter( + array( + 'term' => array( + $tax_fld => $term, + ), + ) + ); } } } @@ -1063,7 +1234,7 @@ class Jetpack_Search { } } - // Validate the "order" field + // Validate the "order" field. switch ( strtolower( $args['order'] ) ) { case 'asc': $args['order'] = 'asc'; @@ -1078,10 +1249,10 @@ class Jetpack_Search { $es_query_args['sort'] = array(); foreach ( (array) $args['orderby'] as $orderby ) { - // Translate orderby from WP field to ES field + // Translate orderby from WP field to ES field. switch ( $orderby ) { - case 'relevance' : - //never order by score ascending + case 'relevance': + // never order by score ascending. $es_query_args['sort'][] = array( '_score' => array( 'order' => 'desc', @@ -1090,7 +1261,7 @@ class Jetpack_Search { break; - case 'date' : + case 'date': $es_query_args['sort'][] = array( 'date' => array( 'order' => $args['order'], @@ -1099,7 +1270,7 @@ class Jetpack_Search { break; - case 'ID' : + case 'ID': $es_query_args['sort'][] = array( 'id' => array( 'order' => $args['order'], @@ -1108,7 +1279,7 @@ class Jetpack_Search { break; - case 'author' : + case 'author': $es_query_args['sort'][] = array( 'author.raw' => array( 'order' => $args['order'], @@ -1116,14 +1287,14 @@ class Jetpack_Search { ); break; - } // End switch(). - } // End foreach(). + } // End switch. + } // End foreach. if ( empty( $es_query_args['sort'] ) ) { unset( $es_query_args['sort'] ); } - // Aggregations + // Aggregations. if ( ! empty( $args['aggregations'] ) ) { $this->add_aggregations_to_es_query_builder( $args['aggregations'], $parser ); } @@ -1190,12 +1361,15 @@ class Jetpack_Search { break; } - $builder->add_aggs( $label, array( - 'terms' => array( - 'field' => $field . '.slug', - 'size' => min( (int) $aggregation['count'], $this->max_aggregations_count ), - ), - ) ); + $builder->add_aggs( + $label, + array( + 'terms' => array( + 'field' => $field . '.slug', + 'size' => min( (int) $aggregation['count'], $this->max_aggregations_count ), + ), + ) + ); } /** @@ -1208,12 +1382,15 @@ class Jetpack_Search { * @param Jetpack_WPES_Query_Builder $builder The builder instance that is creating the Elasticsearch query. */ public function add_post_type_aggregation_to_es_query_builder( array $aggregation, $label, Jetpack_WPES_Query_Builder $builder ) { - $builder->add_aggs( $label, array( - 'terms' => array( - 'field' => 'post_type', - 'size' => min( (int) $aggregation['count'], $this->max_aggregations_count ), - ), - ) ); + $builder->add_aggs( + $label, + array( + 'terms' => array( + 'field' => 'post_type', + 'size' => min( (int) $aggregation['count'], $this->max_aggregations_count ), + ), + ) + ); } /** @@ -1228,7 +1405,7 @@ class Jetpack_Search { 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', + 'field' => ( ! empty( $aggregation['field'] ) && 'post_date_gmt' === $aggregation['field'] ) ? 'date_gmt' : 'date', ); if ( isset( $aggregation['min_doc_count'] ) ) { @@ -1237,9 +1414,12 @@ class Jetpack_Search { $args['min_doc_count'] = 1; } - $builder->add_aggs( $label, array( - 'date_histogram' => $args, - ) ); + $builder->add_aggs( + $label, + array( + 'date_histogram' => $args, + ) + ); } /** @@ -1284,7 +1464,7 @@ class Jetpack_Search { * * @since 5.0.0 * - * @param array $aggregations Array of filters (aggregations) to apply to the search + * @param array $aggregations Array of filters (aggregations) to apply to the search. */ public function set_filters( array $aggregations ) { foreach ( (array) $aggregations as $key => $agg ) { @@ -1380,7 +1560,7 @@ class Jetpack_Search { return $aggregation_data; } - // NOTE - Looping over the _results_, not the original configured aggregations, so we get the 'real' data from ES + // NOTE - Looping over the _results_, not the original configured aggregations, so we get the 'real' data from ES. foreach ( $aggregation_results as $label => $aggregation ) { if ( empty( $aggregation ) ) { continue; @@ -1394,15 +1574,15 @@ class Jetpack_Search { $tax_query_var = null; - // Figure out which terms are active in the query, for this taxonomy + // Figure out which terms are active in the query, for this taxonomy. if ( 'taxonomy' === $this->aggregations[ $label ]['type'] ) { $tax_query_var = $this->get_taxonomy_query_var( $this->aggregations[ $label ]['taxonomy'] ); 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 ( is_array( $tax_query ) && $this->aggregations[ $label ]['taxonomy'] === $tax_query['taxonomy'] && - 'slug' === $tax_query['field'] && - is_array( $tax_query['terms'] ) ) { + 'slug' === $tax_query['field'] && + is_array( $tax_query['terms'] ) ) { $existing_term_slugs = array_merge( $existing_term_slugs, $tax_query['terms'] ); } } @@ -1416,12 +1596,12 @@ class Jetpack_Search { $buckets = (array) $aggregation['buckets']; } - if ( 'date_histogram' == $type ) { - //re-order newest to oldest + if ( 'date_histogram' === $type ) { + // re-order newest to oldest. $buckets = array_reverse( $buckets ); } - // Some aggregation types like date_histogram don't support the max results parameter + // Some aggregation types like date_histogram don't support the max results parameter. if ( is_int( $this->aggregations[ $label ]['count'] ) && count( $buckets ) > $this->aggregations[ $label ]['count'] ) { $buckets = array_slice( $buckets, 0, $this->aggregations[ $label ]['count'] ); } @@ -1440,7 +1620,7 @@ class Jetpack_Search { $term = get_term_by( 'slug', $item['key'], $taxonomy ); if ( ! $term || ! $tax_query_var ) { - continue 2; // switch() is considered a looping structure + continue 2; // switch() is considered a looping structure. } $query_vars = array( @@ -1449,7 +1629,7 @@ class Jetpack_Search { $name = $term->name; - // Let's determine if this term is active or not + // Let's determine if this term is active or not. if ( in_array( $item['key'], $existing_term_slugs, true ) ) { $active = true; @@ -1472,7 +1652,7 @@ class Jetpack_Search { $post_type = get_post_type_object( $item['key'] ); if ( ! $post_type || $post_type->exclude_from_search ) { - continue 2; // switch() is considered a looping structure + continue 2; // switch() is considered a looping structure. } $query_vars = array( @@ -1488,12 +1668,12 @@ class Jetpack_Search { $post_types = array( $post_types ); } - if ( in_array( $item['key'], $post_types ) ) { + if ( in_array( $item['key'], $post_types, true ) ) { $active = true; $post_type_count = count( $post_types ); - // For the right 'remove filter' url, we need to remove the post type from the array, or remove the param entirely if it's the only one + // For the right 'remove filter' url, we need to remove the post type from the array, or remove the param entirely if it's the only one. if ( $post_type_count > 1 ) { $remove_url = Jetpack_Search_Helpers::add_query_arg( 'post_type', @@ -1548,7 +1728,7 @@ class Jetpack_Search { // Is this month currently selected? if ( ! empty( $current_year ) && (int) $current_year === $year && - ! empty( $current_month ) && (int) $current_month === $month ) { + ! empty( $current_month ) && (int) $current_month === $month ) { $active = true; $remove_url = Jetpack_Search_Helpers::remove_query_arg( array( 'year', 'monthnum' ) ); @@ -1571,8 +1751,8 @@ class Jetpack_Search { // Is this day currently selected? if ( ! empty( $current_year ) && (int) $current_year === $year && - ! empty( $current_month ) && (int) $current_month === $month && - ! empty( $current_day ) && (int) $current_day === $day ) { + ! empty( $current_month ) && (int) $current_month === $month && + ! empty( $current_day ) && (int) $current_day === $day ) { $active = true; $remove_url = Jetpack_Search_Helpers::remove_query_arg( array( 'day' ) ); @@ -1581,16 +1761,16 @@ class Jetpack_Search { break; default: - continue 3; // switch() is considered a looping structure - } // End switch(). + continue 3; // switch() is considered a looping structure. + } // End switch. break; default: - //continue 2; // switch() is considered a looping structure - } // End switch(). + // continue 2; // switch() is considered a looping structure. + } // End switch. - // Need to urlencode param values since add_query_arg doesn't + // Need to urlencode param values since add_query_arg doesn't. $url_params = urlencode_deep( $query_vars ); $aggregation_data[ $label ]['buckets'][] = array( @@ -1602,10 +1782,10 @@ class Jetpack_Search { 'remove_url' => $remove_url, 'type' => $type, 'type_label' => $aggregation_data[ $label ]['name'], - 'widget_id' => ! empty( $aggregation_data[ $label ]['widget_id'] ) ? $aggregation_data[ $label ]['widget_id'] : 0 + 'widget_id' => ! empty( $aggregation_data[ $label ]['widget_id'] ) ? $aggregation_data[ $label ]['widget_id'] : 0, ); - } // End foreach(). - } // End foreach(). + } // End foreach. + } // End foreach. /** * Modify the aggregation filters returned by get_filters(). @@ -1762,7 +1942,8 @@ class Jetpack_Search { return; } - jetpack_tracks_record_event( + $tracking = new Automattic\Jetpack\Tracking(); + $tracking->tracks_record_event( wp_get_current_user(), sprintf( 'jetpack_search_widget_%s', $event['action'] ), $event['widget'] @@ -1796,7 +1977,7 @@ class Jetpack_Search { if ( is_array( $widgets ) ) { foreach ( $widgets as $key => $widget ) { - if ( _get_widget_id_base( $widget ) == Jetpack_Search_Helpers::FILTER_WIDGET_BASE ) { + if ( _get_widget_id_base( $widget ) === Jetpack_Search_Helpers::FILTER_WIDGET_BASE ) { $changed = true; array_unshift( $sidebars_widgets['wp_inactive_widgets'], $widget ); @@ -1836,11 +2017,11 @@ class Jetpack_Search { * Transforms an array with fields name as keys and boosts as value into * shorthand "caret" format. * - * @param array $fields_boost [ "title" => "2", "content" => "1" ] + * @param array $fields_boost [ "title" => "2", "content" => "1" ]. * * @return array [ "title^2", "content^1" ] */ - private function _get_caret_boosted_fields( array $fields_boost ) { + private function _get_caret_boosted_fields( array $fields_boost ) { // phpcs:ignore PSR2.Methods.MethodDeclaration.Underscore $caret_boosted_fields = array(); foreach ( $fields_boost as $field => $boost ) { $caret_boosted_fields[] = "$field^$boost"; @@ -1851,21 +2032,23 @@ class Jetpack_Search { /** * Apply a multiplier to boost values. * - * @param array $fields_boost [ "title" => 2, "content" => 1 ] - * @param array $fields_boost_multiplier [ "title" => 0.1234 ] + * @param array $fields_boost [ "title" => 2, "content" => 1 ]. + * @param array $fields_boost_multiplier [ "title" => 0.1234 ]. * * @return array [ "title" => "0.247", "content" => "1.000" ] */ - private function _apply_boosts_multiplier( array $fields_boost, array $fields_boost_multiplier ) { - foreach( $fields_boost as $field_name => $field_boost ) { + private function _apply_boosts_multiplier( array $fields_boost, array $fields_boost_multiplier ) { // phpcs:ignore PSR2.Methods.MethodDeclaration.Underscore + foreach ( $fields_boost as $field_name => $field_boost ) { if ( isset( $fields_boost_multiplier[ $field_name ] ) ) { $fields_boost[ $field_name ] *= $fields_boost_multiplier[ $field_name ]; } - // Set a floor and format the number as string + // Set a floor and format the number as string. $fields_boost[ $field_name ] = number_format( max( 0.001, $fields_boost[ $field_name ] ), - 3, '.', '' + 3, + '.', + '' ); } |