PluginProbe
ElasticPress / 5.3.5
ElasticPress v5.3.5
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
← All changes | includes/classes/Indexable/Post/QueryIntegration.php +79 -29 4.5.15.3.5 View file →
@@ -7,11 +7,11 @@
7 7 */
8 8
9 9 namespace ElasticPress\Indexable\Post;
10 10
11 -use ElasticPress\Indexables as Indexables;
12 -use \WP_Query as WP_Query;
13 -use ElasticPress\Utils as Utils;
11 +use WP_Query;
12 +use ElasticPress\Indexables;
13 +use ElasticPress\Utils;
14 14
15 15 if ( ! defined( 'ABSPATH' ) ) {
16 16 // @codeCoverageIgnoreStart
17 17 exit; // Exit if accessed directly.
@@ -38,11 +38,23 @@
38 38 * @since 0.9
39 39 * @since 3.6.0 Added $indexable_slug
40 40 */
41 41 public function __construct( $indexable_slug = 'post' ) {
42 + /**
43 + * Filter whether to enable query integration during indexing
44 + *
45 + * @since 4.5.2
46 + * @hook ep_enable_query_integration_during_indexing
47 + *
48 + * @param {bool} $enable To allow query integration during indexing
49 + * @param {string} $indexable_slug Indexable slug
50 + * @return {bool} New value
51 + */
52 + $allow_query_integration_during_indexing = apply_filters( 'ep_enable_query_integration_during_indexing', false, $indexable_slug );
53 +
42 54 // Ensure that we are currently allowing ElasticPress to override the normal WP_Query
43 55 // Indexable->is_full_reindexing() is not available at this point yet, so using the IndexHelper version of it.
44 - if ( \ElasticPress\IndexHelper::factory()->is_full_reindexing( $indexable_slug, get_current_blog_id() ) ) {
56 + if ( \ElasticPress\IndexHelper::factory()->is_full_reindexing( $indexable_slug, get_current_blog_id() ) && ! $allow_query_integration_during_indexing ) {
45 57 return;
46 58 }
47 59
48 60 // Add header
@@ -51,9 +63,9 @@
51 63 // Query ES for posts
52 64 add_filter( 'posts_pre_query', array( $this, 'get_es_posts' ), 10, 2 );
53 65
54 66 // Properly restore blog if necessary
55 - add_action( 'loop_end', array( $this, 'maybe_restore_blog' ), 10, 1 );
67 + add_action( 'loop_end', array( $this, 'maybe_restore_blog' ), 10 );
56 68
57 69 // Properly switch to blog if necessary
58 70 add_action( 'the_post', array( $this, 'maybe_switch_to_blog' ), 10, 2 );
59 71
@@ -85,9 +97,9 @@
85 97 return $query->num_posts;
86 98 }
87 99
88 100 /**
89 - * Disables cache_results, adds header.
101 + * Adds header.
90 102 *
91 103 * @param WP_Query $query WP_Query instance
92 104 * @since 0.9
93 105 */
@@ -103,18 +115,8 @@
103 115 if ( ! Indexables::factory()->get( 'post' )->elasticpress_enabled( $query ) || apply_filters( 'ep_skip_query_integration', false, $query ) ) {
104 116 return;
105 117 }
106 118
107 - /**
108 - * `cache_results` defaults to false but can be enabled.
109 - *
110 - * @since 1.5
111 - */
112 - $query->set( 'cache_results', false );
113 - if ( ! empty( $query->query['cache_results'] ) ) {
114 - $query->set( 'cache_results', true );
115 - }
116 -
117 119 if ( ! headers_sent() ) {
118 120 /**
119 121 * Manually setting a header as $wp_query isn't yet initialized when we
120 122 * call: add_filter('wp_headers', 'filter_wp_headers');
@@ -176,18 +178,18 @@
176 178
177 179 $this->switched = false;
178 180 }
179 181 }
180 -
181 182 }
182 183
183 184 /**
184 185 * Make sure the correct blog is restored
185 186 *
186 - * @param WP_Query $query WP_Query instance
187 + * @param WP_Query $query WP_Query instance
188 + *
187 189 * @since 0.9
188 190 */
189 - public function maybe_restore_blog( $query ) {
191 + public function maybe_restore_blog( $query ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found
190 192 if ( ! is_multisite() ) {
191 193 // @codeCoverageIgnoreStart
192 194 return;
193 195 // @codeCoverageIgnoreEnd
@@ -208,10 +210,8 @@
208 210 * @since 3.0
209 211 * @return string
210 212 */
211 213 public function get_es_posts( $posts, $query ) {
212 - global $wpdb;
213 -
214 214 /**
215 215 * Filter to skip WP Query integration
216 216 *
217 217 * @hook ep_skip_query_integration
@@ -233,9 +233,9 @@
233 233 * @param {string|array} $post_types Post types
234 234 * @param {WP_Query} $query WP Query object
235 235 * @return {string|array} New post types
236 236 */
237 - $query_vars['post_type'] = apply_filters( 'ep_query_post_type', $query_vars['post_type'], $query );
237 + $query_vars['post_type'] = apply_filters( 'ep_query_post_type', $query_vars['post_type'] ?? '', $query );
238 238
239 239 if ( 'any' === $query_vars['post_type'] ) {
240 240 unset( $query_vars['post_type'] );
241 241 }
@@ -240,13 +240,15 @@
240 240 unset( $query_vars['post_type'] );
241 241 }
242 242
243 243 /**
244 - * If not search and not set default to post. If not set and is search, use searchable post types
244 + * If not search and not set, default to post. If not set and is search, use searchable post types.
245 245 */
246 246 if ( empty( $query_vars['post_type'] ) ) {
247 - if ( $query->is_tax() ) {
248 - $query_vars['post_type'] = get_taxonomy( $query->get_queried_object()->taxonomy )->object_type;
247 + $tax_post_type = Utils\get_post_types_for_tax_query( $query );
248 +
249 + if ( ! empty( $tax_post_type ) ) {
250 + $query_vars['post_type'] = $tax_post_type;
249 251 } elseif ( empty( $query_vars['s'] ) ) {
250 252 $query_vars['post_type'] = 'post';
251 253 } else {
252 254 $query_vars['post_type'] = array_values( get_post_types( array( 'exclude_from_search' => false ) ) );
@@ -314,8 +316,16 @@
314 316 $scope = 'current';
315 317 // @codeCoverageIgnoreEnd
316 318 }
317 319
320 + /**
321 + * Disable the post cache when using a persistent object cache or querying
322 + * across sites, where identical post IDs can cause cache collisions.
323 + */
324 + if ( wp_using_ext_object_cache() || 'all' === $scope || ! empty( $site__in ) || ! empty( $site__not_in ) ) {
325 + $query->set( 'cache_results', false );
326 + }
327 +
318 328 $index = null;
319 329
320 330 if ( 'all' === $scope ) {
321 331 $index = Indexables::factory()->get( 'post' )->get_network_alias();
@@ -328,9 +338,9 @@
328 338
329 339 $index = implode( ',', $index );
330 340 } elseif ( ! empty( $site__not_in ) ) {
331 341
332 - $sites = get_sites(
342 + $sites = \get_sites(
333 343 array(
334 344 'fields' => 'ids',
335 345 'site__not_in' => $site__not_in,
336 346 )
@@ -357,9 +367,10 @@
357 367
358 368 $found_documents = is_array( $ep_query['found_documents'] ) ? $ep_query['found_documents']['value'] : $ep_query['found_documents']; // 7.0+ have this as an array rather than int
359 369 $query->found_posts = $found_documents;
360 370 $query->num_posts = $query->found_posts;
361 - $query->max_num_pages = ceil( $found_documents / $query->get( 'posts_per_page' ) );
371 + $query->max_num_pages = -1 === $query->get( 'posts_per_page' ) ? 0 : ceil( $found_documents / $query->get( 'posts_per_page' ) );
372 + $query->suggested_terms = $this->maybe_sanitize_suggestion( $ep_query );
362 373 $query->elasticsearch_success = true;
363 374
364 375 // Determine how we should format the results from ES based on the fields parameter.
365 376 $fields = $query->get( 'fields', '' );
@@ -469,11 +480,17 @@
469 480 );
470 481
471 482 foreach ( $post_return_args as $key ) {
472 483 if ( 'post_author' === $key ) {
473 - $post->$key = $post_array[ $key ]['id'];
484 + if ( isset( $post_array[ $key ]['id'] ) ) {
485 + $post->$key = $post_array[ $key ]['id'];
486 + }
474 487 } elseif ( isset( $post_array[ $key ] ) ) {
475 - $post->$key = $post_array[ $key ];
488 + if ( in_array( $key, [ 'terms', 'meta', 'post_meta' ], true ) && is_array( $post_array[ $key ] ) ) {
489 + $post->$key = wp_json_encode( $post_array[ $key ] );
490 + } else {
491 + $post->$key = $post_array[ $key ];
492 + }
476 493 }
477 494 }
478 495
479 496 /**
@@ -547,6 +564,39 @@
547 564 $post->elasticsearch = true; // Super useful for debugging
548 565 $new_posts[] = $post;
549 566 }
550 567 return $new_posts;
568 + }
569 +
570 + /**
571 + * Remove any suggestion that has a score lower than the minimum score.
572 + *
573 + * @since 4.6.0
574 + * @param array $ep_query The query array.
575 + * @return array
576 + */
577 + protected function maybe_sanitize_suggestion( $ep_query ) {
578 + if ( ! isset( $ep_query['suggest']['ep_suggestion'], $ep_query['suggest']['ep_suggestion'][0] ) ) {
579 + return [];
580 + }
581 +
582 + $suggestion = $ep_query['suggest']['ep_suggestion'][0];
583 +
584 + /**
585 + * Filter the score for a suggestion. If the score is lower than this, it will be removed.
586 + *
587 + * @since 4.6.0
588 + * @param float $min_score The minimum score allowed.
589 + * @return float
590 + */
591 + $min_score = (float) apply_filters( 'ep_suggestion_minimum_score', 0.0001 );
592 +
593 + $suggestion['options'] = array_filter(
594 + $suggestion['options'],
595 + function ( $option ) use ( $min_score ) {
596 + return number_format( $option['score'], 10 ) > $min_score;
597 + }
598 + );
599 +
600 + return $suggestion;
551 601 }
552 602 }