PluginProbe
ElasticPress / 4.6.1
ElasticPress v4.6.1
5.3.5 5.3.4 3.6.5 3.6.6 4.0.0 4.0.1 4.1.0 4.2.0 4.2.1 4.2.2 4.3.0 4.3.1 4.4.0 4.4.1 4.5.0 4.5.1 4.5.2 4.6.0 4.6.1 4.7.0 4.7.1 4.7.2 5.0.0 5.0.1 5.0.2 All 108 releases
elasticpress / includes / classes / Feature / Search / Weighting.php

Weighting.php in ElasticPress 4.6.1, at includes/classes/Feature/Search/Weighting.php

731 lines 23.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Weighting dashboard for ElasticPress
4 *
5 * @package elasticpress
6 */
7
8 namespace ElasticPress\Feature\Search;
9
10 use ElasticPress\Features;
11 use ElasticPress\Feature;
12 use ElasticPress\Indexable\Post\Post;
13 use ElasticPress\Utils;
14
15 /**
16 * Controls search weighting and search fields dashboard
17 *
18 * @package ElasticPress\Feature\Search
19 */
20 class Weighting {
21
22 /**
23 * Sets up the weighting module
24 */
25 public function setup() {
26 /**
27 * Filter to disable loading of Search weighting engine.
28 *
29 * @hook ep_disable_search_weighting
30 * @since 4.0
31 * @param bool Whether to disable search weighting engine. Defaults to false.
32 * @return bool Whether to disable search weighting engine.
33 */
34 if ( apply_filters( 'ep_disable_search_weighting', false ) ) {
35 return;
36 }
37
38 add_action( 'admin_menu', [ $this, 'add_weighting_submenu_page' ], 15 );
39 add_action( 'admin_post_ep-weighting', [ $this, 'handle_save' ] );
40 add_filter( 'ep_formatted_args', [ $this, 'do_weighting' ], 20, 2 ); // After date decay, etc are injected
41 add_filter( 'ep_query_weighting_fields', [ $this, 'adjust_weight_for_cross_fields' ], 10, 5 );
42 }
43
44 /**
45 * Returns a grouping of all the fields that support weighting for the post type
46 *
47 * @param string $post_type Post type
48 *
49 * @return array
50 */
51 public function get_weightable_fields_for_post_type( $post_type ) {
52 $fields = array(
53 'attributes' => array(
54 'label' => __( 'Attributes', 'elasticpress' ),
55 'children' => array(
56 'post_title' => array(
57 'key' => 'post_title',
58 'label' => 'Title',
59 ),
60 'post_content' => array(
61 'key' => 'post_content',
62 'label' => 'Content',
63 ),
64 'post_excerpt' => array(
65 'key' => 'post_excerpt',
66 'label' => 'Excerpt',
67 ),
68 'author_name' => array(
69 'key' => 'author_name',
70 'label' => 'Author',
71 ),
72 ),
73 ),
74 );
75
76 $public_taxonomies = get_taxonomies(
77 [
78 'public' => true,
79 ]
80 );
81
82 $post_type_taxonomies = get_object_taxonomies( $post_type );
83
84 $taxonomies = array_intersect( $public_taxonomies, $post_type_taxonomies );
85
86 if ( $taxonomies ) {
87 $fields['taxonomies'] = [
88 'label' => __( 'Taxonomies', 'elasticpress' ),
89 'children' => [],
90 ];
91
92 foreach ( $taxonomies as $taxonomy ) {
93 $key = "terms.{$taxonomy}.name";
94 $taxonomy_object = get_taxonomy( $taxonomy );
95
96 $fields['taxonomies']['children'][ $key ] = [
97 'key' => $key,
98 'label' => $taxonomy_object->labels->name,
99 ];
100 }
101 }
102
103 /**
104 * Filter weighting fields for a post type
105 *
106 * @hook ep_weighting_fields_for_post_type
107 * @param {array} $fields Current weighting fields
108 * @param {string} $post_type Current post type
109 * @return {array} New fields
110 */
111 return apply_filters( 'ep_weighting_fields_for_post_type', $fields, $post_type );
112 }
113
114 /**
115 * Returns default settings for any post type
116 *
117 * Defaults to title, content, excerpt, and author name enabled with zero weight
118 *
119 * @param string $post_type Post Type we need settings for
120 *
121 * @return array Defaults for post type
122 */
123 public function get_post_type_default_settings( $post_type ) {
124 $post_type_defaults = [
125 'post_title' => [
126 'enabled' => true,
127 'weight' => 1,
128 ],
129 'post_content' => [
130 'enabled' => true,
131 'weight' => 1,
132 ],
133 'post_excerpt' => [
134 'enabled' => true,
135 'weight' => 1,
136 ],
137 'author_name' => [
138 'enabled' => true,
139 'weight' => 1,
140 ],
141 ];
142
143 $post_type_taxonomies = get_object_taxonomies( $post_type );
144
145 /**
146 * Filter install status
147 *
148 * Previous behavior had post_tag and category enabled by default, so if this is supported on the post type
149 * we add them as enabled by default
150 *
151 * @hook ep_weighting_default_enabled_taxonomies
152 * @param {array} $enabled_taxonomies Taxonomies that should be enabled by default
153 * @param {string} $post_type Post type slug
154 * @return {array} New taxonomies
155 * @since 3.6.5
156 */
157 $enabled_by_default = apply_filters( 'ep_weighting_default_enabled_taxonomies', [ 'post_tag', 'category' ], $post_type );
158
159 foreach ( $enabled_by_default as $default_tax ) {
160 if ( in_array( $default_tax, $post_type_taxonomies, true ) ) {
161 $post_type_defaults[ 'terms.' . $default_tax . '.name' ] = [
162 'enabled' => true,
163 'weight' => 1,
164 ];
165 }
166 }
167
168 /**
169 * Filter weighting defaults for post type
170 *
171 * @hook ep_weighting_default_post_type_weights
172 * @param {array} $post_type_defaults Current weighting defaults
173 * @param {string} $post_type Current post type
174 * @return {array} New defaults
175 */
176 return apply_filters( 'ep_weighting_default_post_type_weights', $post_type_defaults, $post_type );
177 }
178
179 /**
180 * Returns the current weighting configuration
181 *
182 * @return array
183 */
184 public function get_weighting_configuration() {
185 /**
186 * Filter weighting configuration
187 *
188 * @hook ep_weighting_configuration
189 * @param {array} $config Current configuration
190 * @return {array} New configuration
191 */
192 return apply_filters( 'ep_weighting_configuration', get_option( 'elasticpress_weighting', [] ) );
193 }
194
195 /**
196 * Adds the submenu page for controlling weighting
197 */
198 public function add_weighting_submenu_page() {
199 add_submenu_page(
200 'elasticpress',
201 esc_html__( 'ElasticPress Search Fields & Weighting', 'elasticpress' ),
202 esc_html__( 'Search Fields & Weighting', 'elasticpress' ),
203 Utils\get_capability(),
204 'elasticpress-weighting',
205 [ $this, 'render_settings_page' ]
206 );
207 }
208
209 /**
210 * Renders the settings page that controls weighting
211 */
212 public function render_settings_page() {
213 include EP_PATH . '/includes/partials/header.php'; ?>
214 <div class="wrap">
215
216 <h1><?php esc_html_e( 'Manage Search Fields & Weighting', 'elasticpress' ); ?></h1>
217 <p><?php esc_html_e( 'Adding more weight to an item will mean it will have more presence during searches. Add more weight to the items that are more important and need more prominence during searches.', 'elasticpress' ); ?></p>
218 <p><?php esc_html_e( 'For example, adding more weight to the title attribute will cause search matches on the post title to appear more prominently.', 'elasticpress' ); ?></p>
219
220 <form action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" method="post" class="weighting-settings metabox-holder">
221 <input type="hidden" name="action" value="ep-weighting">
222 <?php wp_nonce_field( 'save-weighting', 'ep-weighting-nonce' ); ?>
223 <?php
224 if ( isset( $_GET['settings-updated'] ) ) : // phpcs:ignore WordPress.Security.NonceVerification, WordPress.Security.ValidatedSanitizedInput
225 if ( sanitize_key( $_GET['settings-updated'] ) ) : // phpcs:ignore WordPress.Security.NonceVerification
226 ?>
227 <div class="notice notice-success is-dismissible">
228 <p><?php esc_html_e( 'Changes Saved!', 'elasticpress' ); ?></p>
229 </div>
230 <?php else : ?>
231 <div class="notice notice-error is-dismissible">
232 <p><?php esc_html_e( 'An error occurred when saving!', 'elasticpress' ); ?></p>
233 </div>
234 <?php
235 endif;
236 endif;
237
238 /** Features Class @var Features $features */
239 $features = Features::factory();
240
241 /** Search Feature @var Feature\Search\Search $search */
242 $search = $features->get_registered_feature( 'search' );
243
244 $post_types = $search->get_searchable_post_types();
245
246 $current_values = $this->get_weighting_configuration();
247
248 foreach ( $post_types as $post_type ) :
249 $fields = $this->get_weightable_fields_for_post_type( $post_type );
250 $post_type_object = get_post_type_object( $post_type );
251 ?>
252 <div class="postbox">
253 <h2 class="hndle"><?php echo esc_html( $post_type_object->labels->menu_name ); ?></h2>
254
255 <?php
256 foreach ( $fields as $field_group ) :
257 $this->render_settings_section( $post_type, $field_group, $current_values );
258 endforeach;
259 ?>
260 </div>
261 <?php
262 endforeach;
263
264 submit_button();
265 ?>
266 </form>
267 </div>
268 <?php
269 }
270
271 /**
272 * Recursively renders each settings section and its children
273 *
274 * @param string $post_type Current post type we're rendering
275 * @param array $field Current field to render
276 * @param array $current_values Current stored weighting values
277 */
278 public function render_settings_section( $post_type, $field, $current_values ) {
279 if ( isset( $field['children'] ) && ! empty( $field['children'] ) ) :
280 ?>
281 <div class="field-group">
282 <h3><?php echo esc_html( $field['label'] ); ?></h3>
283 <div class="fields">
284 <?php
285 foreach ( $field['children'] as $child ) {
286 $this->render_settings_section( $post_type, $child, $current_values );
287 }
288 ?>
289 </div>
290 </div>
291 <?php
292 elseif ( isset( $field['key'] ) ) :
293 $key = $field['key'];
294
295 $post_type_settings = isset( $current_values[ $post_type ] ) ? $current_values[ $post_type ] : $this->get_post_type_default_settings( $post_type );
296
297 $weight = isset( $post_type_settings[ $key ] ) && isset( $post_type_settings[ $key ]['weight'] ) ? (int) $post_type_settings[ $key ]['weight'] : 0;
298
299 $range_disabled = '';
300
301 $enabled = (
302 isset( $post_type_settings ) &&
303 isset( $post_type_settings[ $key ] ) &&
304 isset( $post_type_settings[ $key ]['enabled'] )
305 )
306 ? boolval( $post_type_settings[ $key ]['enabled'] ) : false;
307
308 if ( ! $enabled ) {
309 $range_disabled = 'disabled="disabled" ';
310 $weight = 0;
311 }
312 ?>
313 <fieldset>
314 <legend><?php echo esc_html( $field['label'] ); ?></legend>
315
316 <p class="searchable">
317 <input type="checkbox" value="on" <?php checked( $enabled ); ?> id="<?php echo esc_attr( "{$post_type}-{$key}-enabled" ); ?>" name="weighting[<?php echo esc_attr( $post_type ); ?>][<?php echo esc_attr( $key ); ?>][enabled]">
318 <label for="<?php echo esc_attr( "{$post_type}-{$key}-enabled" ); ?>"><?php esc_html_e( 'Searchable', 'elasticpress' ); ?></label>
319 </p>
320
321 <p class="weighting">
322 <label for="<?php echo esc_attr( "{$post_type}-{$key}-weight" ); ?>">
323 <?php esc_html_e( 'Weight: ', 'elasticpress' ); ?>
324 <span class="weighting-value">
325 <?php echo esc_html( $weight ); ?>
326 </span>
327 </label>
328 <input type="range" min="1" max="100" step="1" value="<?php echo esc_attr( $weight ); ?>" id="<?php echo esc_attr( "{$post_type}-{$key}-weight" ); ?>" name="weighting[<?php echo esc_attr( $post_type ); ?>][<?php echo esc_attr( $key ); ?>][weight]" <?php echo $range_disabled; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
329 </p>
330 </fieldset>
331 <?php
332 endif;
333 }
334
335 /**
336 * Handles processing the new weighting values and saving them to the elasticpress.io service
337 */
338 public function handle_save() {
339 if ( ! isset( $_POST['ep-weighting-nonce'] ) || ! wp_verify_nonce( sanitize_key( $_POST['ep-weighting-nonce'] ), 'save-weighting' ) ) {
340 return;
341 }
342
343 if ( ! current_user_can( Utils\get_capability() ) ) {
344 return;
345 }
346
347 $this->save_weighting_configuration( $_POST );
348
349 $redirect_url = admin_url( 'admin.php?page=elasticpress-weighting' );
350 $redirect_url = add_query_arg( 'settings-updated', true, $redirect_url );
351
352 $this->redirect( $redirect_url );
353 }
354
355 /**
356 * We need this method to test handle_save properly.
357 *
358 * @param string $redirect_url Redirect URL.
359 */
360 protected function redirect( $redirect_url ) {
361 // @codeCoverageIgnoreStart
362 wp_safe_redirect( $redirect_url );
363 exit();
364 // @codeCoverageIgnoreEnd
365 }
366
367 /**
368 * Save weighting configuration for each searchable post_type
369 *
370 * @param array $settings weighting settings
371 *
372 * @return array final settings
373 * @since 3.4.1
374 */
375 public function save_weighting_configuration( $settings ) {
376 $new_config = array();
377 $previous_config_formatted = array();
378 $current_config = $this->get_weighting_configuration();
379
380 foreach ( $current_config as $post_type => $post_type_weighting ) {
381 // This also ensures the string is safe, since this would return false otherwise
382 if ( ! post_type_exists( $post_type ) ) {
383 continue;
384 }
385
386 // We need a way to know if fields have been explicitly set before, let's compare a previous state against $_POST['weighting']
387 foreach ( $post_type_weighting as $weighting_field => $weighting_values ) {
388 $previous_config_formatted[ $post_type ][ sanitize_text_field( $weighting_field ) ] = [
389 'weight' => isset( $settings['weighting'][ $post_type ][ $weighting_field ]['weight'] ) ? intval( $settings['weighting'][ $post_type ][ $weighting_field ]['weight'] ) : 0,
390 'enabled' => isset( $settings['weighting'][ $post_type ][ $weighting_field ]['enabled'] ) && 'on' === $settings['weighting'][ $post_type ][ $weighting_field ]['enabled'] ? true : false,
391 ];
392 }
393 }
394
395 $search = Features::factory()->get_registered_feature( 'search' );
396 $post_types = $search->get_searchable_post_types();
397
398 foreach ( $post_types as $post_type ) {
399 // This also ensures the string is safe, since this would return false otherwise
400 if ( ! post_type_exists( $post_type ) ) {
401 continue;
402 }
403
404 /** override default post_type settings while saving */
405 $new_config[ $post_type ] = array();
406
407 if ( isset( $settings['weighting'][ $post_type ] ) ) {
408 foreach ( $settings['weighting'][ $post_type ] as $weighting_field => $weighting_values ) {
409 $new_config[ $post_type ][ sanitize_text_field( $weighting_field ) ] = [
410 'weight' => isset( $weighting_values['weight'] ) ? intval( $weighting_values['weight'] ) : 0,
411 'enabled' => isset( $weighting_values['enabled'] ) && 'on' === $weighting_values['enabled'] ? true : false,
412 ];
413 }
414 }
415 }
416
417 $final_config = array_replace_recursive( $previous_config_formatted, $new_config );
418
419 update_option( 'elasticpress_weighting', $final_config );
420
421 /**
422 * Fires right after the weighting configuration is saved.
423 *
424 * @since 3.5.x
425 * @hook ep_saved_weighting_configuration
426 */
427 do_action( 'ep_saved_weighting_configuration' );
428
429 return $final_config;
430 }
431
432 /**
433 * Iterates through arrays in the formatted args to find "fields" and injects weighting values
434 *
435 * @param array $fieldset Current subset of formatted ES args
436 * @param array $weights Weight configuration
437 */
438 public function recursively_inject_weights_to_fields( &$fieldset, $weights ) {
439 if ( ! is_array( $fieldset ) ) {
440 return;
441 }
442
443 if ( is_array( $fieldset ) && isset( $fieldset['fields'] ) ) {
444 // Add any fields to the search that aren't already in there (weighting handled in next step)
445 foreach ( $weights as $field => $settings ) {
446 if ( ! in_array( $field, $fieldset['fields'], true ) ) {
447 $fieldset['fields'][] = $field;
448 }
449 }
450
451 foreach ( $fieldset['fields'] as $key => $field ) {
452 if ( isset( $weights[ $field ] ) && false !== $weights[ $field ]['enabled'] ) {
453 $weight = (int) $weights[ $field ]['weight'];
454
455 if ( 0 !== $weight ) {
456 if ( 'author_name' === $field ) {
457 $field = 'post_author.display_name';
458 }
459
460 /**
461 * Filter fields and their weitghting as used in the Elasticsearch query.
462 *
463 * @hook ep_query_weighting_fields
464 * @param {string} $weighted_field The field and its weight as used in the ES query.
465 * @param {string} $field Field name
466 * @param {string} $weight Weight value
467 * @param {array} $fieldset Current subset of formatted ES args
468 * @param {array} $weights Weight configuration
469 * @return {array} New weighted field string
470 *
471 * @since 3.5.5
472 */
473 $fieldset['fields'][ $key ] = apply_filters(
474 'ep_query_weighting_fields',
475 "{$field}^{$weight}",
476 $field,
477 $weight,
478 $fieldset,
479 $weights
480 );
481 }
482 } else {
483 // this handles removing post_author.login field added in Post::format_args() if author search field has being disabled
484 if ( 'author_name' === $field ) {
485 $author_key = array_search( 'post_author.login', $fieldset['fields'], true );
486 if ( false !== $author_key ) {
487 unset( $fieldset['fields'][ $author_key ] );
488 }
489 }
490 unset( $fieldset['fields'][ $key ] );
491 }
492 // else: Leave anything that isn't explicitly disabled alone. Could have been added by search_fields, and if it is not present in the UI, we shouldn't touch it here
493
494 // If fieldset has fuzziness enabled and fuzziness is disabled for this field, unset the field
495 if ( isset( $fieldset['fuzziness'] ) && $fieldset['fuzziness'] && isset( $weights[ $field ]['fuzziness'] ) && false === $weights[ $field ]['fuzziness'] ) {
496 unset( $fieldset['fields'][ $key ] );
497 }
498 }
499
500 // Reindex the array
501 $fieldset['fields'] = array_values( $fieldset['fields'] );
502 } else {
503 foreach ( $fieldset as &$field ) {
504 $this->recursively_inject_weights_to_fields( $field, $weights );
505 }
506 }
507
508 // Most likely to occur with the ordering results not being allowed in fuzzy, and weighting turning off fields for this otherwise
509 if ( isset( $fieldset['fields'] ) && empty( $fieldset['fields'] ) ) {
510 $fieldset = null;
511 }
512 }
513
514 /**
515 * Determine if a post type has any fields enabled for search
516 *
517 * @param string $post_type Post Type
518 * @param array $args WP_Query args
519 * @return boolean true/false depending on any fields enabled == true
520 */
521 public function post_type_has_fields( $post_type, $args = [] ) {
522 $weight_config = $this->get_weighting_configuration();
523
524 /**
525 * Filter weighting configuration for search
526 *
527 * @hook ep_weighting_configuration_for_search
528 * @param {array} $weight_config Current weight config
529 * @param {array} $args WP Query arguments
530 * @return {array} New configutation
531 */
532 $weight_config = apply_filters( 'ep_weighting_configuration_for_search', $weight_config, $args );
533
534 if ( ! isset( $weight_config[ $post_type ] ) ) {
535 $weights = $this->get_post_type_default_settings( $post_type );
536 } else {
537 $weights = $weight_config[ $post_type ];
538 }
539
540 /**
541 * Filter fields considered in weighting
542 *
543 * Define keys which are irrelevant for this consideration, like `terms.ep_custom_result.name`.
544 *
545 * @hook ep_weighting_ignore_fields_in_consideration
546 * @param {array} $fields Current fields
547 * @return {array} New fields
548 */
549 $ignore_keys = apply_filters( 'ep_weighting_ignore_fields_in_consideration', [ 'terms.ep_custom_result.name' => true ] );
550 $fields = array_diff_key( $weights, $ignore_keys );
551
552 $found_enabled = false;
553 foreach ( $fields as $field ) {
554 if ( filter_var( $field['enabled'], FILTER_VALIDATE_BOOLEAN ) ) {
555 $found_enabled = true;
556 break;
557 }
558 }
559
560 return $found_enabled;
561 }
562
563 /**
564 * Adjusts the query for configured weighting values
565 *
566 * @param array $formatted_args Formatted ES args
567 * @param array $args WP_Query args
568 *
569 * @return array Formatted ES args
570 */
571 public function do_weighting( $formatted_args, $args ) {
572
573 /**
574 * If search fields is set on the query, we should use those instead of the weighting, since the query was
575 * overridden by some custom code
576 */
577 if ( isset( $args['search_fields'] ) && ! empty( $args['search_fields'] ) ) {
578 return $formatted_args;
579 }
580
581 $weight_config = $this->get_weighting_configuration();
582
583 /**
584 * Filter weighting configuration for search
585 *
586 * @hook ep_weighting_configuration_for_search
587 * @param {array} $weight_config Current weight config
588 * @param {array} $args WP Query arguments
589 * @return {array} New configuration
590 */
591 $weight_config = apply_filters( 'ep_weighting_configuration_for_search', $weight_config, $args );
592
593 $should_do_weighting = Utils\is_integrated_request( 'weighting', [ 'public', 'rest' ] ) && ! empty( $args['s'] );
594
595 /**
596 * Filter whether to enable weighting configuration
597 *
598 * @hook ep_enable_do_weighting
599 * @since 4.2.2
600 * @param {bool} Whether to enable weight config, defaults to true for search requests that are public or REST
601 * @param {array} $weight_config Current weight config
602 * @param {array} $args WP Query arguments
603 * @param {array} $formatted_args Formatted ES arguments
604 * @return {bool} Whether to use weighting configuration
605 */
606 if ( apply_filters( 'ep_enable_do_weighting', $should_do_weighting, $weight_config, $args, $formatted_args ) ) {
607 $formatted_args = $this->apply_weighting( $formatted_args, $args, $weight_config );
608 }
609
610 return $formatted_args;
611 }
612
613 /**
614 * Applies weighting based on ES args
615 *
616 * @since 4.2.2
617 * @param array $formatted_args Formatted ES args
618 * @param array $args WP_Query args
619 * @param array $weight_config Weight configuration to apply
620 *
621 * @return array $formatted_args Formatted ES args with weightings applied
622 */
623 protected function apply_weighting( $formatted_args, $args, $weight_config ) {
624 /*
625 * This section splits up the single query clause for all post types into separate nested clauses (one for each post type)
626 * which then get combined into one result set. By having separate clauses for each post type, we can then
627 * weight fields such as post_title per post type so that we can have fine grained control over weights by post
628 * type, rather than globally on the query
629 */
630 $new_query = [
631 'bool' => [
632 'should' => [],
633 ],
634 ];
635
636 // grab the query and keep track of whether or not it is nested in a function score
637 $function_score = isset( $formatted_args['query']['function_score'] );
638 $query = $function_score ? $formatted_args['query']['function_score']['query'] : $formatted_args['query'];
639
640 foreach ( (array) $args['post_type'] as $post_type ) {
641 if ( false === $this->post_type_has_fields( $post_type, $args ) ) {
642 continue;
643 }
644 // Copy the query, so we can set specific weight values
645 $current_query = $query;
646
647 if ( isset( $weight_config[ $post_type ] ) ) {
648 // Find all "fields" values and inject weights for the current post type
649 $this->recursively_inject_weights_to_fields( $current_query, $weight_config[ $post_type ] );
650 } else {
651 // Use the default values for the post type
652 $this->recursively_inject_weights_to_fields( $current_query, $this->get_post_type_default_settings( $post_type ) );
653 }
654
655 // Check for any segments with null fields from recursively_inject function and remove them
656 if ( isset( $current_query['bool'] ) && isset( $current_query['bool']['should'] ) ) {
657 foreach ( $current_query['bool']['should'] as $index => $current_bool_should ) {
658 if ( isset( $current_bool_should['multi_match'] ) && null === $current_bool_should['multi_match'] ) {
659 unset( $current_query['bool']['should'][ $index ] );
660 }
661 }
662 }
663
664 /**
665 * Filter weighting query for a post type
666 *
667 * @hook ep_weighted_query_for_post_type
668 * @param {array} $query Weighting query
669 * @param {string} $post_type Post type
670 * @param {array} $args WP Query arguments
671 * @return {array} New query
672 */
673 $new_query['bool']['should'][] = apply_filters(
674 'ep_weighted_query_for_post_type',
675 [
676 'bool' => [
677 'must' => [
678 $current_query,
679 ],
680 'filter' => [
681 [
682 'match' => [
683 'post_type.raw' => $post_type,
684 ],
685 ],
686 ],
687 ],
688 ],
689 $post_type,
690 $args
691 );
692 }
693
694 // put the new query back in the correct location
695 if ( $function_score ) {
696 $formatted_args['query']['function_score']['query'] = $new_query;
697 } else {
698 $formatted_args['query'] = $new_query;
699 }
700
701 /**
702 * Hook after weighting is added to Elasticsearch query
703 *
704 * @hook ep_weighting_added
705 * @param {array} $formatted_args Elasticsearch query
706 * @param {array} $args WP Query arguments
707 */
708 do_action( 'ep_weighting_added', $formatted_args, $args );
709
710 return $formatted_args;
711 }
712
713 /**
714 * Adjust weighting when the type is cross_fields, as it just works with weight = 1.
715 *
716 * @since 4.0.0
717 *
718 * @param string $weighted_field The field and its weight as used in the ES query.
719 * @param string $field Field name
720 * @param string $weight Weight value
721 * @param array $fieldset Current subset of formatted ES args
722 * @return array New weighted field string
723 */
724 public function adjust_weight_for_cross_fields( $weighted_field, $field, $weight, $fieldset ) {
725 if ( ! empty( $fieldset['type'] ) && 'cross_fields' === $fieldset['type'] ) {
726 $weighted_field = "{$field}^1";
727 }
728 return $weighted_field;
729 }
730 }
731