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.php +133 -34 4.7.25.3.5 View file →
@@ -75,9 +75,12 @@
75 75 *
76 76 * @since 4.5.0
77 77 * @var array
78 78 */
79 - public $labels = [];
79 + public $labels = [
80 + 'plural' => '',
81 + 'singular' => '',
82 + ];
80 83
81 84 /**
82 85 * Get number of bulk items to index per page
83 86 *
@@ -259,12 +262,16 @@
259 262 *
260 263 * @param int $object_id Object to index.
261 264 * @param boolean $blocking Blocking HTTP request or not.
262 265 * @since 3.0
263 - * @return boolean
266 + * @return object|boolean
264 267 */
265 268 public function index( $object_id, $blocking = false ) {
266 - $document = $this->prepare_document( $object_id );
269 + try {
270 + $document = $this->prepare_document( $object_id );
271 + } catch ( \Throwable $th ) {
272 + return false;
273 + }
267 274
268 275 if ( false === $document ) {
269 276 return false;
270 277 }
@@ -271,8 +278,9 @@
271 278
272 279 /**
273 280 * Conditionally kill indexing on a specific object
274 281 *
282 + * @deprecated 5.3.3 Use ep_{indexable_slug}_sync_kill instead
275 283 * @hook ep_{indexable_slug}_index_kill
276 284 * @param {bool} $kill True to not index
277 285 * @param {int} $object_id Id of object to index
278 286 * @since 3.0
@@ -277,13 +285,26 @@
277 285 * @param {int} $object_id Id of object to index
278 286 * @since 3.0
279 287 * @return {bool} New kill value
280 288 */
281 - if ( apply_filters( 'ep_' . $this->slug . '_index_kill', false, $object_id ) ) {
289 + if ( apply_filters_deprecated( 'ep_' . $this->slug . '_index_kill', [ false, $object_id ], 'ElasticPress 5.3.3', 'ep_' . $this->slug . '_sync_kill' ) ) {
282 290 return false;
283 291 }
284 292
285 293 /**
294 + * Conditionally kill indexing for an object.
295 + *
296 + * @hook ep_{$this->slug}_sync_kill
297 + * @param {bool} $kill True means dont sync
298 + * @param {int} $object_id Object ID
299 + * @return {bool} New value
300 + */
301 + $ep_indexable_sync_kill = apply_filters( 'ep_' . $this->slug . '_sync_kill', false, $object_id );
302 + if ( $ep_indexable_sync_kill ) {
303 + return false;
304 + }
305 +
306 + /**
286 307 * Filter document before index
287 308 *
288 309 * @hook ep_pre_index_{indexable_slug}
289 310 * @param {array} $document Document to index
@@ -298,9 +319,9 @@
298 319 * Fires after document is indexed
299 320 *
300 321 * @hook ep_after_index_{indexable_slug}
301 322 * @param {array} $document Document to index
302 - * @param {array|boolean} $return ES response on success, false on failure
323 + * @param {object|boolean} $return ES response on success, false on failure
303 324 * @since 3.0
304 325 */
305 326 do_action( 'ep_after_index_' . $this->slug, $document, $return );
306 327
@@ -327,8 +348,10 @@
327 348 */
328 349 public function bulk_index( $object_ids ) {
329 350 $body = '';
330 351
352 + $non_es_errors = [];
353 +
331 354 foreach ( $object_ids as $object_id ) {
332 355 $action_args = array(
333 356 'index' => array(
334 357 '_id' => absint( $object_id ),
@@ -334,9 +357,22 @@
334 357 '_id' => absint( $object_id ),
335 358 ),
336 359 );
337 360
338 - $document = $this->prepare_document( $object_id );
361 + try {
362 + $document = $this->prepare_document( $object_id );
363 + } catch ( \Throwable $th ) {
364 + $non_es_errors[] = [
365 + 'index' => [
366 + '_id' => absint( $object_id ),
367 + 'error' => [
368 + 'type' => 'prepare_document_error',
369 + 'reason' => $th->getMessage(),
370 + ],
371 + ],
372 + ];
373 + continue;
374 + }
339 375
340 376 /**
341 377 * Conditionally kill indexing on a specific object
342 378 *
@@ -353,8 +389,13 @@
353 389 }
354 390
355 391 $result = Elasticsearch::factory()->bulk_index( $this->get_index_name(), $this->slug, $body );
356 392
393 + if ( ! empty( $non_es_errors ) ) {
394 + $result['errors'] = true;
395 + $result['items'] = isset( $result['items'] ) ? array_merge( $result['items'], $non_es_errors ) : $non_es_errors;
396 + }
397 +
357 398 /**
358 399 * Perform actions after a bulk indexing is completed
359 400 *
360 401 * @hook ep_after_bulk_index
@@ -376,8 +417,10 @@
376 417 */
377 418 public function bulk_index_dynamically( $object_ids ) {
378 419 $documents = [];
379 420
421 + $non_es_errors = [];
422 +
380 423 foreach ( $object_ids as $object_id ) {
381 424 $action_args = array(
382 425 'index' => array(
383 426 '_id' => absint( $object_id ),
@@ -383,10 +426,27 @@
383 426 '_id' => absint( $object_id ),
384 427 ),
385 428 );
386 429
387 - $document = $this->prepare_document( $object_id );
430 + try {
431 + $document = $this->prepare_document( $object_id );
432 + } catch ( \Throwable $th ) {
433 + $non_es_errors[] = [
434 + 'index' => [
435 + '_id' => absint( $object_id ),
436 + 'error' => [
437 + 'type' => 'prepare_document_error',
438 + 'reason' => $th->getMessage(),
439 + ],
440 + ],
441 + ];
442 + continue;
443 + }
388 444
445 + if ( empty( $document ) ) {
446 + continue;
447 + }
448 +
389 449 /**
390 450 * Conditionally kill indexing on a specific object
391 451 *
392 452 * @hook ep_bulk_index_action_args
@@ -401,10 +461,35 @@
401 461
402 462 $documents[] = $document_str;
403 463 }
404 464
465 + if ( empty( $documents ) ) {
466 + return ( ! empty( $non_es_errors ) ? [
467 + [
468 + 'errors' => true,
469 + 'items' => $non_es_errors,
470 + ],
471 + ] : [
472 + new \WP_Error(
473 + 'ep_bulk_index_no_documents',
474 + esc_html__( 'It was not possible to create a body request with the document IDs provided.', 'elasticpress' ),
475 + $object_ids
476 + ),
477 + ] );
478 + }
479 +
405 480 $results = $this->send_bulk_index_request( $documents );
406 481
482 + if ( ! empty( $non_es_errors ) ) {
483 + $results = [
484 + [
485 + 'errors' => true,
486 + 'items' => $non_es_errors,
487 + ],
488 + ...$results,
489 + ];
490 + }
491 +
407 492 /**
408 493 * Perform actions after a dynamic bulk indexing is completed
409 494 *
410 495 * @hook ep_after_bulk_index_dynamically
@@ -477,12 +562,12 @@
477 562 }
478 563
479 564 $results = [];
480 565
481 - $body = [];
566 + $body = [];
567 + $current_body_size = 0;
568 + $requests = 0;
482 569
483 - $requests = 0;
484 -
485 570 /*
486 571 * This script will use two main arrays: $body and $documents, being $body the
487 572 * documents to be sent in the next request and $documents the list of docs to be indexed.
488 573 * The do-while loop will stop if all documents are sent or if a request fails even sending
@@ -488,16 +573,18 @@
488 573 * The do-while loop will stop if all documents are sent or if a request fails even sending
489 574 * a buffer as small as possible.
490 575 */
491 576 do {
492 - $next_document = array_shift( $documents );
577 + $next_document = array_shift( $documents );
578 + $next_document_size = mb_strlen( $next_document );
579 + $has_buffered_documents = count( $body ) > 0;
493 580
494 581 // If the next document alone takes the entire current buffer size,
495 582 // let's add it back to the pipe and send what we have first
496 - if ( mb_strlen( $next_document ) > $current_buffer_size && count( $body ) > 0 ) {
583 + if ( $next_document_size > $current_buffer_size && $has_buffered_documents ) {
497 584 array_unshift( $documents, $next_document );
498 585 } else {
499 - if ( mb_strlen( $next_document ) > $max_buffer_size ) {
586 + if ( $next_document_size > $max_buffer_size ) {
500 587 /**
501 588 * Perform actions when a post is bigger than the max buffer size.
502 589 *
503 590 * @hook ep_dynamic_bulk_post_too_big
@@ -507,15 +594,22 @@
507 594 do_action( 'ep_dynamic_bulk_post_too_big', $next_document );
508 595 $results[] = new \WP_Error( 'ep_too_big_request_skipped', 'Indexable too big. Request not sent.' );
509 596 continue;
510 597 }
511 - $body[] = $next_document;
512 - if ( mb_strlen( implode( '', $body ) ) < $current_buffer_size && ! empty( $documents ) ) {
598 +
599 + $body[] = $next_document;
600 + $current_body_size += $next_document_size;
601 +
602 + $can_add_more_documents = ( $current_body_size < $current_buffer_size && ! empty( $documents ) );
603 + if ( $can_add_more_documents ) {
513 604 continue;
514 605 }
515 - if ( mb_strlen( implode( '', $body ) ) > $max_buffer_size ) {
606 +
607 + if ( $current_body_size > $max_buffer_size ) {
516 608 // The last document added to body made it too big, so let's give it back.
517 - array_unshift( $documents, array_pop( $body ) );
609 + $removed_document = array_pop( $body );
610 + $current_body_size -= mb_strlen( $removed_document );
611 + array_unshift( $documents, $removed_document );
518 612 }
519 613 }
520 614
521 615 // Try the request.
@@ -521,9 +615,9 @@
521 615 // Try the request.
522 616 timer_start();
523 617 $result = Elasticsearch::factory()->bulk_index( $this->get_index_name(), $this->slug, implode( '', $body ) );
524 618 $request_time = timer_stop();
525 - $requests++;
619 + ++$requests;
526 620
527 621 /**
528 622 * Perform actions before a new batch of documents is processed.
529 623 *
@@ -540,37 +634,42 @@
540 634 do_action( 'ep_after_send_dynamic_bulk_request', $result, $body, $documents, $min_buffer_size, $max_buffer_size, $current_buffer_size, $request_time );
541 635
542 636 // It failed, possibly adjust the buffer size and try again.
543 637 if ( is_wp_error( $result ) ) {
638 + $error_code = $result->get_error_code();
639 +
544 640 // Too many requests, wait and try again.
545 - if ( 429 === $result->get_error_code() ) {
641 + if ( 429 === $error_code ) {
546 642 sleep( 2 );
547 643 }
548 644
549 645 // If the error is not a "Request too big" then we really fail this batch of documents.
550 - if ( 413 !== $result->get_error_code() ) {
646 + if ( 413 !== $error_code ) {
551 647 $results[] = $result;
552 648 continue;
553 649 }
554 650
555 651 if ( count( $body ) === 1 ) {
556 - $max_buffer_size = min( $max_buffer_size, mb_strlen( implode( '', $body ) ) );
557 - $results[] = $result;
558 - $body = [];
652 + $max_buffer_size = min( $max_buffer_size, $current_body_size );
653 + $results[] = $result;
654 + $body = [];
655 + $current_body_size = 0;
559 656 continue;
560 657 }
561 658
562 659 // As the buffer is as small as possible, return the error.
563 - if ( mb_strlen( implode( '', $body ) ) === $min_buffer_size ) {
660 + if ( $current_body_size === $min_buffer_size ) {
564 661 $results[] = $result;
565 662 continue;
566 663 }
567 664
568 665 // We have a too big buffer. Remove one doc from the body, and set both max and current as its size.
569 - array_unshift( $documents, array_pop( $body ) );
666 + $removed_document = array_pop( $body );
667 + $current_body_size -= mb_strlen( $removed_document );
668 + array_unshift( $documents, $removed_document );
570 669
571 670 $max_buffer_size = count( $body ) ?
572 - max( $min_buffer_size, mb_strlen( implode( '', $body ) ) ) :
671 + max( $min_buffer_size, $current_body_size ) :
573 672 $min_buffer_size;
574 673
575 674 $current_buffer_size = $max_buffer_size;
576 675 continue;
@@ -576,15 +675,16 @@
576 675 continue;
577 676 }
578 677
579 678 // Things worked so we can try to bump the buffer size.
580 - if ( $current_buffer_size < $max_buffer_size && mb_strlen( implode( '', $body ) ) > $current_buffer_size ) {
679 + if ( $current_buffer_size < $max_buffer_size && $current_body_size > $current_buffer_size ) {
581 680 $current_buffer_size = min( ( $current_buffer_size + $incremental_step ), $max_buffer_size );
582 681 }
583 682
584 683 $results[] = $result;
585 684
586 - $body = [];
685 + $body = [];
686 + $current_body_size = 0;
587 687 } while ( ! empty( $documents ) );
588 688
589 689 /**
590 690 * Perform actions after a batch of documents was processed.
@@ -667,9 +767,8 @@
667 767 $prepared_meta[ $meta_key ] = array_map( array( $this, 'prepare_meta_value_types' ), $meta_values );
668 768 }
669 769
670 770 return $prepared_meta;
671 -
672 771 }
673 772
674 773 /**
675 774 * Prepare meta types for meta value
@@ -1104,9 +1203,9 @@
1104 1203 return ( (string) $new_mapping['settings']['index.number_of_shards'] === $stored_mapping[ $this->get_index_name() ]['settings']['index']['number_of_shards'] );
1105 1204 }
1106 1205
1107 1206 /**
1108 - * Utilitary function to check if the indexable is being fully reindexed, i.e.,
1207 + * Utility function to check if the indexable is being fully reindexed, i.e.,
1109 1208 * the index was deleted, a new mapping was sent and content is being reindexed.
1110 1209 *
1111 1210 * @param int|null $blog_id Blog ID
1112 1211 * @return boolean
@@ -1172,9 +1271,9 @@
1172 1271 * @param array $search_fields Search fields
1173 1272 * @param array $query_vars Query vars
1174 1273 * @return SearchAlgorithm Instance of search algorithm to be used
1175 1274 */
1176 - public function get_search_algorithm( string $search_text, array $search_fields, array $query_vars ) : \ElasticPress\SearchAlgorithm {
1275 + public function get_search_algorithm( string $search_text, array $search_fields, array $query_vars ): \ElasticPress\SearchAlgorithm {
1177 1276 /**
1178 1277 * Filter the search algorithm to be used
1179 1278 *
1180 1279 * @hook ep_{$indexable_slug}_search_algorithm
@@ -1202,11 +1301,11 @@
1202 1301 $mapping = $this->get_mapping();
1203 1302
1204 1303 try {
1205 1304 if ( version_compare( (string) Elasticsearch::factory()->get_elasticsearch_version(), '7.0', '<' ) ) {
1206 - $meta_fields = $mapping[ $this->get_index_name( $blog_id ) ]['mappings']['post']['properties']['meta']['properties'];
1305 + $meta_fields = (array) $mapping[ $this->get_index_name( $blog_id ) ]['mappings']['post']['properties']['meta']['properties'];
1207 1306 } else {
1208 - $meta_fields = $mapping[ $this->get_index_name( $blog_id ) ]['mappings']['properties']['meta']['properties'];
1307 + $meta_fields = (array) $mapping[ $this->get_index_name( $blog_id ) ]['mappings']['properties']['meta']['properties'];
1209 1308 }
1210 1309 $meta_keys = array_values( array_keys( $meta_fields ) );
1211 1310 sort( $meta_keys );
1212 1311 } catch ( \Throwable $th ) {
@@ -1277,9 +1376,9 @@
1277 1376 * @since 4.5.0
1278 1377 * @param array $mapping The mapping
1279 1378 * @return array
1280 1379 */
1281 - public function add_ngram_analyzer( array $mapping ) : array {
1380 + public function add_ngram_analyzer( array $mapping ): array {
1282 1381 $mapping['settings']['analysis']['analyzer']['edge_ngram_analyzer'] = array(
1283 1382 'type' => 'custom',
1284 1383 'tokenizer' => 'standard',
1285 1384 'filter' => array(