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/IndexHelper.php +251 -70 4.6.15.3.5 View file →
@@ -1,17 +1,20 @@
1 1 <?php
2 2 /**
3 3 * Index Helper
4 4 *
5 + * NOTE: As explained in the doc linked below, the dashboard sync exits after each output()
6 + * call, to respond to the AJAX request. That means this script will be called several times
7 + * while syncing via dashboard, relying on the index_meta to pick it up where it stopped.
8 + *
5 9 * @since 4.0.0
6 - * @see docs/indexing-process.md
7 - * @see https://elasticpress.zendesk.com/hc/en-us/articles/16672117103501-Sync-Process
10 + * @see https://www.elasticpress.io/resources/articles/sync-process/
8 11 * @package elasticpress
9 12 */
10 13
11 14 namespace ElasticPress;
12 15
13 -use ElasticPress\Utils as Utils;
16 +use ElasticPress\Utils;
14 17
15 18 /**
16 19 * Index Helper Class.
17 20 *
@@ -81,11 +84,15 @@
81 84 */
82 85 $this->args = apply_filters( 'ep_sync_args', $args, $this->index_meta );
83 86
84 87 if ( false === $this->index_meta ) {
88 + $this->maybe_apply_feature_settings();
85 89 $this->build_index_meta();
86 90 }
87 91
92 + // For the dashboard, this will be called and exit the script until the queue is empty again.
93 + $this->flush_messages_queue();
94 +
88 95 while ( $this->has_items_to_be_processed() ) {
89 96 $this->process_sync_item();
90 97 }
91 98
@@ -136,8 +143,10 @@
136 143 'network_alias' => [],
137 144 'start_time' => microtime( true ),
138 145 'start_date_time' => $start_date_time ? $start_date_time->format( DATE_ATOM ) : false,
139 146 'starting_indices' => $starting_indices,
147 + 'messages_queue' => [],
148 + 'trigger' => ! empty( $this->args['trigger'] ) ? sanitize_text_field( $this->args['trigger'] ) : null,
140 149 'totals' => [
141 150 'total' => 0,
142 151 'synced' => 0,
143 152 'skipped' => 0,
@@ -156,15 +165,11 @@
156 165 if ( ! is_numeric( $this->args['network_wide'] ) ) {
157 166 $this->args['network_wide'] = 0;
158 167 }
159 168
160 - $sites = Utils\get_sites( $this->args['network_wide'] );
169 + $sites = Utils\get_sites( $this->args['network_wide'], true );
161 170
162 171 foreach ( $sites as $site ) {
163 - if ( ! Utils\is_site_indexable( $site['blog_id'] ) ) {
164 - continue;
165 - }
166 -
167 172 switch_to_blog( $site['blog_id'] );
168 173
169 174 foreach ( $non_global_indexables as $indexable ) {
170 175 $this->add_sync_item_to_stack(
@@ -244,9 +249,9 @@
244 249 */
245 250 protected function filter_indexables( $indexables ) {
246 251 return array_filter(
247 252 $indexables,
248 - function( $indexable ) {
253 + function ( $indexable ) {
249 254 return empty( $this->args['indexables'] ) || in_array( $indexable, $this->args['indexables'], true );
250 255 }
251 256 );
252 257 }
@@ -566,9 +571,9 @@
566 571 $queued_items = [];
567 572
568 573 foreach ( $this->current_query['objects'] as $object ) {
569 574 if ( $this->should_skip_object_index( $object, $indexable ) ) {
570 - $this->index_meta['current_sync_item']['skipped']++;
575 + ++$this->index_meta['current_sync_item']['skipped'];
571 576 } else {
572 577 $queued_items[ $object->ID ] = true;
573 578 }
574 579 }
@@ -669,9 +674,9 @@
669 674 $failed_objects = array_merge(
670 675 $failed_objects,
671 676 array_filter(
672 677 $return['items'],
673 - function( $item ) {
678 + function ( $item ) {
674 679 return ! empty( $item['index']['error'] );
675 680 }
676 681 )
677 682 );
@@ -695,9 +700,9 @@
695 700 count( $this->index_meta['current_sync_item']['errors'] ),
696 701 $wp_error_messages
697 702 );
698 703
699 - $this->output( implode( "\n", $wp_error_messages ), 'warning' );
704 + $this->queue_message( $wp_error_messages, 'warning' );
700 705 } elseif ( count( $failed_objects ) ) {
701 706 $errors_output = $this->output_index_errors( $failed_objects );
702 707
703 708 $this->index_meta['current_sync_item']['synced'] += count( $queued_items ) - count( $failed_objects );
@@ -708,10 +713,11 @@
708 713 $errors_output
709 714 );
710 715
711 716 $this->index_meta['current_sync_item']['failed'] += count( $failed_objects );
717 + $error_type = ! empty( $this->args['stop_on_error'] ) ? 'error' : 'warning';
712 718
713 - $this->output( $errors_output, 'warning' );
719 + $this->queue_message( $errors_output, $error_type );
714 720 } else {
715 721 $this->index_meta['current_sync_item']['synced'] += count( $queued_items );
716 722 }
717 723 }
@@ -717,21 +723,20 @@
717 723 }
718 724
719 725 $this->index_meta['current_sync_item']['last_processed_object_id'] = end( $this->current_query['objects'] )->ID;
720 726
721 - $this->output(
722 - sprintf(
723 - /* translators: 1. Indexable type 2. Offset start, 3. Offset end, 4. Found items 5. Last object ID */
724 - esc_html__( 'Processed %1$s %2$d - %3$d of %4$d. Last Object ID: %5$d', 'elasticpress' ),
725 - esc_html( strtolower( $indexable->labels['plural'] ) ),
726 - $this->index_meta['from'],
727 - $this->index_meta['offset'],
728 - $this->index_meta['found_items'],
729 - $this->index_meta['current_sync_item']['last_processed_object_id']
730 - ),
731 - 'info',
732 - 'index_next_batch'
727 + $summary = sprintf(
728 + /* translators: 1. Indexable type 2. Offset start, 3. Offset end, 4. Found items 5. Last object ID */
729 + esc_html__( 'Processed %1$s %2$d - %3$d of %4$d. Last Object ID: %5$d', 'elasticpress' ),
730 + esc_html( strtolower( $indexable->labels['plural'] ) ),
731 + $this->index_meta['from'],
732 + $this->index_meta['offset'],
733 + $this->index_meta['found_items'],
734 + $this->index_meta['current_sync_item']['last_processed_object_id']
733 735 );
736 +
737 + $this->queue_message( $summary, 'info', 'index_next_batch' );
738 + $this->flush_messages_queue();
734 739 }
735 740
736 741 /**
737 742 * If the number of errors is greater than the limit, slice the array to the limit.
@@ -816,8 +821,9 @@
816 821
817 822 $current_sync_item = $this->index_meta['current_sync_item'];
818 823
819 824 $this->index_meta['current_sync_item'] = null;
825 + $this->index_meta['offset'] = 0;
820 826
821 827 if ( $current_sync_item['failed'] ) {
822 828 if ( ! empty( $current_sync_item['blog_id'] ) && defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) {
823 829 $message = sprintf(
@@ -838,10 +844,8 @@
838 844
839 845 $this->output( $message, 'warning' );
840 846 }
841 847
842 - $this->index_meta['offset'] = 0;
843 -
844 848 if ( ! empty( $current_sync_item['blog_id'] ) && defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) {
845 849 $message = sprintf(
846 850 /* translators: 1: indexable (plural), 2: Blog ID, 3: number of synced objects */
847 851 esc_html__( 'Number of %1$s indexed on site %2$d: %3$d', 'elasticpress' ),
@@ -864,14 +868,16 @@
864 868 /**
865 869 * Update last sync info.
866 870 *
867 871 * @since 4.2.0
872 + * @param string $final_status Optional final status
868 873 */
869 - protected function update_last_index() {
874 + protected function update_last_index( string $final_status = '' ) {
875 + $is_full_sync = $this->index_meta['put_mapping'];
876 + $method = $this->index_meta['method'];
870 877 $start_time = $this->index_meta['start_time'];
871 878 $totals = $this->index_meta['totals'];
872 - $method = $this->index_meta['method'];
873 - $is_full_sync = $this->index_meta['put_mapping'];
879 + $trigger = $this->index_meta['trigger'];
874 880
875 881 $this->index_meta = null;
876 882
877 883 $end_date_time = date_create( 'now', wp_timezone() );
@@ -876,19 +882,67 @@
876 882
877 883 $end_date_time = date_create( 'now', wp_timezone() );
878 884 $start_time_sec = (int) $start_time;
879 885
886 + // Time related info
880 887 $totals['end_date_time'] = $end_date_time ? $end_date_time->format( DATE_ATOM ) : false;
881 888 $totals['start_date_time'] = $start_time ? wp_date( DATE_ATOM, $start_time_sec ) : false;
882 889 $totals['end_time_gmt'] = time();
883 890 $totals['total_time'] = microtime( true ) - $start_time;
884 - $totals['method'] = $method;
885 - $totals['is_full_sync'] = $is_full_sync;
891 +
892 + // Additional info
893 + $totals['is_full_sync'] = $is_full_sync;
894 + $totals['method'] = $method;
895 + $totals['trigger'] = $trigger;
896 +
897 + // Final status
898 + if ( '' !== $final_status ) {
899 + $totals['final_status'] = $final_status;
900 + } elseif ( ! empty( $totals['failed'] ) ) {
901 + $totals['final_status'] = 'with_errors';
902 + } else {
903 + $totals['final_status'] = 'success';
904 + }
905 +
886 906 Utils\update_option( 'ep_last_cli_index', $totals, false );
887 - Utils\update_option( 'ep_last_index', $totals, false );
907 +
908 + $this->add_last_sync( $totals );
888 909 }
889 910
890 911 /**
912 + * Add a sync to the list of all past syncs
913 + *
914 + * @since 5.0.0
915 + * @param array $last_sync_info The latest sync info to be added to the log
916 + * @return void
917 + */
918 + protected function add_last_sync( array $last_sync_info ) {
919 + // Remove error messages from previous syncs - we only store msgs for the newest one.
920 + $last_syncs = array_map(
921 + function ( $sync ) {
922 + unset( $sync['errors'] );
923 + return $sync;
924 + },
925 + $this->get_sync_history()
926 + );
927 +
928 + /**
929 + * Filter the number of past syncs to keep info
930 + *
931 + * @since 5.0.0
932 + * @hook ep_syncs_to_keep_info
933 + * @param {int} $number Number of past syncs to keep info
934 + * @return {int} New number
935 + */
936 + $syncs_to_keep = (int) apply_filters( 'ep_syncs_to_keep_info', 5 );
937 +
938 + $last_syncs = array_slice( $last_syncs, 0, $syncs_to_keep - 1 );
939 + array_unshift( $last_syncs, $last_sync_info );
940 +
941 + Utils\update_option( 'ep_sync_history', $last_syncs, false );
942 + }
943 +
944 + /**
891 945 * Make the necessary clean up after everything was sync'd.
892 946 *
893 947 * @since 4.0.0
894 948 */
@@ -898,11 +952,12 @@
898 952 /**
899 953 * Fires after executing a reindex
900 954 *
901 955 * @since 4.0.0
956 + * @param array $args Sync arguments.
902 957 * @hook ep_after_sync_index
903 958 */
904 - do_action( 'ep_after_sync_index' );
959 + do_action( 'ep_after_sync_index', $this->args );
905 960
906 961 /**
907 962 * Fires after executing a reindex
908 963 *
@@ -933,16 +988,11 @@
933 988 protected function create_network_alias() {
934 989 $indexes = [];
935 990 $indexable = Indexables::factory()->get( array_shift( $this->index_meta['network_alias'] ) );
936 991
937 - $sites = Utils\get_sites();
992 + $sites = Utils\get_sites( 0, true );
938 993
939 994 foreach ( $sites as $site ) {
940 -
941 - if ( ! Utils\is_site_indexable( $site['blog_id'] ) ) {
942 - continue;
943 - }
944 -
945 995 switch_to_blog( $site['blog_id'] );
946 996 $indexes[] = $indexable->get_index_name();
947 997 restore_current_blog();
948 998 }
@@ -981,9 +1031,9 @@
981 1031 if ( $this->index_meta ) {
982 1032 Utils\update_option( 'ep_index_meta', $this->index_meta );
983 1033 } else {
984 1034 Utils\delete_option( 'ep_index_meta' );
985 - $totals = $this->get_last_index();
1035 + $totals = $this->get_last_sync();
986 1036 }
987 1037
988 1038 $message = [
989 1039 'message' => ( is_array( $message_text ) ) ? implode( "\n", $message_text ) : $message_text,
@@ -991,8 +1041,12 @@
991 1041 'totals' => $totals ?? [],
992 1042 'status' => $type,
993 1043 ];
994 1044
1045 + if ( in_array( $type, [ 'warning', 'error' ], true ) ) {
1046 + $message['errors'] = $this->build_message_errors_data( $message_text );
1047 + }
1048 +
995 1049 if ( is_callable( $this->args['output_method'] ) ) {
996 1050 call_user_func( $this->args['output_method'], $message, $this->args, $this->index_meta, $context );
997 1051 }
998 1052 }
@@ -1037,9 +1091,9 @@
1037 1091 return $error_text;
1038 1092 }
1039 1093
1040 1094 /**
1041 - * Utilitary function to check if the indexable is being fully reindexed, i.e.,
1095 + * Utility function to check if the indexable is being fully reindexed, i.e.,
1042 1096 * the index was deleted, a new mapping was sent and content is being reindexed.
1043 1097 *
1044 1098 * @param string $indexable_slug Indexable slug.
1045 1099 * @param int|null $blog_id Blog ID
@@ -1085,50 +1139,71 @@
1085 1139 return apply_filters( "ep_is_full_reindexing_{$indexable_slug}", $is_full_reindexing );
1086 1140 }
1087 1141
1088 1142 /**
1089 - * Get the last index/sync meta information.
1143 + * Get the previous syncs meta information.
1090 1144 *
1091 - * @since 4.2.0
1145 + * @since 5.0.0
1092 1146 * @return array
1093 1147 */
1094 - public function get_last_index() {
1095 - return Utils\get_option( 'ep_last_index', [] );
1148 + public function get_sync_history(): array {
1149 + return Utils\get_option( 'ep_sync_history', [] );
1096 1150 }
1097 1151
1098 1152 /**
1153 + * Get the last sync meta information.
1154 + *
1155 + * @since 5.0.0
1156 + * @return array
1157 + */
1158 + public function get_last_sync(): array {
1159 + $syncs = $this->get_sync_history();
1160 + if ( empty( $syncs ) ) {
1161 + return [];
1162 + }
1163 + return array_shift( $syncs );
1164 + }
1165 +
1166 + /**
1099 1167 * Check if an object should be indexed or skipped.
1100 1168 *
1101 1169 * We used to have two different filters for this (one for the dashboard, another for CLI),
1102 1170 * this method combines both.
1103 1171 *
1104 - * @param {stdClass} $object Object to be checked
1172 + * @param {stdClass} $indexable_object Object to be checked
1105 1173 * @param {Indexable} $indexable Indexable
1106 1174 * @return boolean
1107 1175 */
1108 - protected function should_skip_object_index( $object, $indexable ) {
1176 + protected function should_skip_object_index( $indexable_object, $indexable ) {
1109 1177 /**
1110 1178 * Filter whether to not sync specific item in dashboard or not
1111 1179 *
1112 1180 * @since 2.1
1181 + * @deprecated 5.3.3 Use ep_{indexable_slug}_sync_kill instead
1113 1182 * @hook ep_item_sync_kill
1114 1183 * @param {boolean} $kill False means dont sync
1115 - * @param {array} $object Object to sync
1184 + * @param {array} $indexable_object Object to sync
1116 1185 * @return {Indexable} Indexable that object belongs to
1117 1186 */
1118 - $ep_item_sync_kill = apply_filters( 'ep_item_sync_kill', false, $object, $indexable );
1187 + $ep_item_sync_kill = apply_filters_deprecated(
1188 + 'ep_item_sync_kill',
1189 + [ false, $indexable_object, $indexable ],
1190 + 'ElasticPress 5.3.3',
1191 + 'ep_' . $indexable->slug . '_sync_kill'
1192 + );
1119 1193
1120 - /**
1121 - * Conditionally kill indexing for a post
1122 - *
1123 - * @hook ep_{indexable_slug}_index_kill
1124 - * @param {bool} $index True means dont index
1125 - * @param {int} $object_id Object ID
1126 - * @return {bool} New value
1127 - */
1128 - $ep_indexable_sync_kill = apply_filters( 'ep_' . $indexable->slug . '_index_kill', false, $object->ID );
1194 + /** This filter is documented in includes/classes/Indexable.php */
1195 + $ep_indexable_index_kill = apply_filters_deprecated(
1196 + 'ep_' . $indexable->slug . '_index_kill',
1197 + [ false, $indexable_object->ID ],
1198 + 'ElasticPress 5.3.3',
1199 + 'ep_' . $indexable->slug . '_sync_kill'
1200 + );
1129 1201
1130 - return $ep_item_sync_kill || $ep_indexable_sync_kill;
1202 + /** This filter is documented in includes/classes/Indexable.php */
1203 + $ep_indexable_sync_kill = apply_filters( 'ep_' . $indexable->slug . '_sync_kill', false, $indexable_object->ID );
1204 +
1205 + return $ep_item_sync_kill || $ep_indexable_sync_kill || $ep_indexable_index_kill;
1131 1206 }
1132 1207
1133 1208 /**
1134 1209 * Given an array, create a new sync item and add it to the stack.
@@ -1209,16 +1284,14 @@
1209 1284 * in-memory cache for persistent object caches
1210 1285 */
1211 1286 if ( function_exists( 'wp_cache_flush_runtime' ) ) {
1212 1287 wp_cache_flush_runtime();
1213 - } else {
1288 + } elseif ( ! wp_using_ext_object_cache() ) {
1214 1289 /*
1215 1290 * In the case where we're not using an external object cache, we need to call flush on the default
1216 1291 * WordPress object cache class to clear the values from the cache property
1217 1292 */
1218 - if ( ! wp_using_ext_object_cache() ) {
1219 - wp_cache_flush();
1220 - }
1293 + wp_cache_flush();
1221 1294 }
1222 1295
1223 1296 if ( is_object( $wp_object_cache ) ) {
1224 1297 $wp_object_cache->group_ops = [];
@@ -1259,19 +1332,22 @@
1259 1332 do_action( 'ep_stop_the_insanity' );
1260 1333 }
1261 1334
1262 1335 /**
1263 - * Utilitary function to delete the index meta option.
1336 + * Utility function to delete the index meta option.
1264 1337 *
1265 1338 * @since 4.0.0
1266 1339 */
1267 1340 public function clear_index_meta() {
1341 + if ( ! empty( $this->index_meta ) ) {
1342 + $this->update_last_index( 'aborted' );
1343 + }
1268 1344 $this->index_meta = false;
1269 1345 Utils\delete_option( 'ep_index_meta', false );
1270 1346 }
1271 1347
1272 1348 /**
1273 - * Utilitary function to get the index meta option.
1349 + * Utility function to get the index meta option.
1274 1350 *
1275 1351 * @return array
1276 1352 * @since 4.0.0
1277 1353 */
@@ -1323,9 +1399,9 @@
1323 1399 $totals = $this->index_meta['totals'];
1324 1400
1325 1401 $this->index_meta['totals']['errors'][] = $error['message'];
1326 1402 $this->index_meta['totals']['failed'] = $totals['total'] - ( $totals['synced'] + $totals['skipped'] );
1327 - $this->update_last_index();
1403 + $this->update_last_index( 'failed' );
1328 1404
1329 1405 /**
1330 1406 * Fires after a sync failed due to a PHP fatal error.
1331 1407 *
@@ -1341,10 +1417,12 @@
1341 1417 /* translators: Error message */
1342 1418 esc_html__( 'Mapping failed: %s', 'elasticpress' ),
1343 1419 Utils\get_elasticsearch_error_reason( $error['message'] )
1344 1420 );
1345 - $message .= "\n";
1346 - $message .= esc_html__( 'Mapping has failed, which will cause ElasticPress search results to be incorrect. Please click `Delete all Data and Start a Fresh Sync` to retry mapping.', 'elasticpress' );
1421 + if ( $this->should_suggest_retry( $message ) ) {
1422 + $message .= "\n";
1423 + $message .= esc_html__( 'Mapping has failed, which will cause ElasticPress search results to be incorrect. Please click `Delete all Data and Start a Fresh Sync` to retry mapping.', 'elasticpress' );
1424 + }
1347 1425 break;
1348 1426 default:
1349 1427 /* translators: Error message */
1350 1428 $message = sprintf( esc_html__( 'Index failed: %s', 'elasticpress' ), $error['message'] );
@@ -1359,9 +1437,9 @@
1359 1437 *
1360 1438 * @since 4.4.0
1361 1439 * @return integer
1362 1440 */
1363 - public function get_index_default_per_page() : int {
1441 + public function get_index_default_per_page(): int {
1364 1442 /**
1365 1443 * Filter number of items to index per cycle in the dashboard
1366 1444 *
1367 1445 * @since 2.1
@@ -1372,8 +1450,99 @@
1372 1450 return (int) apply_filters( 'ep_index_default_per_page', Utils\get_option( 'ep_bulk_setting', 350 ) );
1373 1451 }
1374 1452
1375 1453 /**
1454 + * Add a message to the queue
1455 + *
1456 + * @since 4.7.0
1457 + * @param string|array $message_text Message to be outputted
1458 + * @param string $type Type of message
1459 + * @param string $context Context of the output
1460 + */
1461 + protected function queue_message( $message_text, string $type, string $context = '' ) {
1462 + $this->index_meta['messages_queue'][] = [
1463 + 'text' => $message_text,
1464 + 'type' => $type,
1465 + 'context' => $context,
1466 + ];
1467 + }
1468 +
1469 + /**
1470 + * Display messages in the queue.
1471 + *
1472 + * NOTE: As the dashboard sync exits after every output call (to respond the AJAX request),
1473 + * this will just output one message. As the method is called every time the script is called,
1474 + * all messages will be displayed but one at a time.
1475 + *
1476 + * @since 4.7.0
1477 + */
1478 + protected function flush_messages_queue() {
1479 + if ( ! is_array( $this->index_meta['messages_queue'] ) ) {
1480 + return;
1481 + }
1482 +
1483 + $messages_count = count( $this->index_meta['messages_queue'] );
1484 + if ( 0 === $messages_count ) {
1485 + return;
1486 + }
1487 +
1488 + for ( $i = 0; $i < $messages_count; $i++ ) {
1489 + $next_message = array_shift( $this->index_meta['messages_queue'] );
1490 + $this->output( $next_message['text'], $next_message['type'], $next_message['context'] );
1491 + }
1492 + }
1493 +
1494 + /**
1495 + * Get data for a given error message(s)
1496 + *
1497 + * @since 5.0.0
1498 + * @param string|array $messages Messages
1499 + * @return array
1500 + */
1501 + protected function build_message_errors_data( $messages ): array {
1502 + $messages = (array) $messages;
1503 + $error_interpreter = new \ElasticPress\ElasticsearchErrorInterpreter();
1504 +
1505 + $errors_list = [];
1506 + foreach ( $messages as $message ) {
1507 + $error = $error_interpreter->maybe_suggest_solution_for_es( $message );
1508 +
1509 + if ( ! isset( $errors_list[ $error['error'] ] ) ) {
1510 + $errors_list[ $error['error'] ] = [
1511 + 'solution' => $error['solution'],
1512 + 'count' => 1,
1513 + ];
1514 + } else {
1515 + ++$errors_list[ $error['error'] ]['count'];
1516 + }
1517 + }
1518 + return $errors_list;
1519 + }
1520 +
1521 + /**
1522 + * If this is a full sync, apply the draft feature settings
1523 + *
1524 + * @since 5.0.0
1525 + */
1526 + protected function maybe_apply_feature_settings() {
1527 + if ( empty( $this->args['put_mapping'] ) ) {
1528 + return;
1529 + }
1530 +
1531 + Features::factory()->apply_draft_feature_settings();
1532 + }
1533 +
1534 + /**
1535 + * Whether to suggest retrying the sync or not.
1536 + *
1537 + * @param string $message The message returned by the hosting server
1538 + * @return boolean
1539 + */
1540 + protected function should_suggest_retry( $message ) {
1541 + return ! preg_match( '/you have reached the limit of indices your plan supports/', $message );
1542 + }
1543 +
1544 + /**
1376 1545 * Return singleton instance of class.
1377 1546 *
1378 1547 * @return self
1379 1548 * @since 4.0.0
@@ -1386,6 +1555,18 @@
1386 1555 $instance->setup();
1387 1556 }
1388 1557
1389 1558 return $instance;
1559 + }
1560 +
1561 + /**
1562 + * DEPRECATED. Get the last index/sync meta information.
1563 + *
1564 + * @since 4.2.0
1565 + * @deprecated 5.0.0
1566 + * @return array
1567 + */
1568 + public function get_last_index() {
1569 + _deprecated_function( __METHOD__, '5.0.0', '\ElasticPress\IndexHelper::get_last_sync' );
1570 + return $this->get_last_sync();
1390 1571 }
1391 1572 }