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/Elasticsearch.php +189 -86 4.4.05.3.5 View file →
@@ -7,11 +7,11 @@
7 7 */
8 8
9 9 namespace ElasticPress;
10 10
11 -use ElasticPress\Utils as Utils;
11 +use WP_Error;
12 12 use ElasticPress\Indexables;
13 -use \WP_Error as WP_Error;
13 +use ElasticPress\Utils;
14 14
15 15 if ( ! defined( 'ABSPATH' ) ) {
16 16 exit; // Exit if accessed directly.
17 17 }
@@ -77,9 +77,9 @@
77 77 * @param string $type Index type. Previously this was used for index type. Now it's just passed to hooks for legacy reasons.
78 78 * @param array $document Formatted Elasticsearch document.
79 79 * @param boolean $blocking Blocking HTTP request or not.
80 80 * @since 3.0
81 - * @return boolean|array
81 + * @return boolean|object
82 82 */
83 83 public function index_document( $index, $type, $document, $blocking = true ) {
84 84 /**
85 85 * Filter Elasticsearch index document request path
@@ -91,9 +91,9 @@
91 91 * @param {string} $type Type of document
92 92 * @return {string} New path
93 93 * @since 3.0
94 94 */
95 - if ( version_compare( $this->get_elasticsearch_version(), '7.0', '<' ) ) {
95 + if ( version_compare( (string) $this->get_elasticsearch_version(), '7.0', '<' ) ) {
96 96 $path = apply_filters( 'ep_index_' . $type . '_request_path', $index . '/' . $type . '/' . $document['ID'], $document, $type );
97 97 } else {
98 98 $path = apply_filters( 'ep_index_' . $type . '_request_path', $index . '/_doc/' . $document['ID'], $document, $type );
99 99 }
@@ -283,9 +283,9 @@
283 283 * @since 3.0
284 284 * @return bool|array
285 285 */
286 286 public function query( $index, $type, $query, $query_args, $query_object = null ) {
287 - if ( version_compare( $this->get_elasticsearch_version(), '7.0', '<' ) ) {
287 + if ( version_compare( (string) $this->get_elasticsearch_version(), '7.0', '<' ) ) {
288 288 $path = $index . '/' . $type . '/_search';
289 289 } else {
290 290 $path = $index . '/_search';
291 291 }
@@ -403,8 +403,16 @@
403 403 * @param {string} $scope Backwards compat for scope parameter.
404 404 * @param {array} $query_args Current WP Query arguments
405 405 */
406 406 do_action( 'ep_retrieve_aggregations', $response['aggregations'], $query, '', $query_args );
407 +
408 + if ( is_object( $query_object ) ) {
409 + if ( method_exists( $query_object, 'set' ) ) {
410 + $query_object->set( 'ep_aggregations', $response['aggregations'] );
411 + } else {
412 + $query_object->query_vars['ep_aggregations'] = $response['aggregations'];
413 + }
414 + }
407 415 }
408 416
409 417 /**
410 418 * Fires after valid Elasticsearch query
@@ -455,13 +463,17 @@
455 463 * Filter Elasticsearch query results
456 464 *
457 465 * @hook ep_es_query_results
458 466 * @param {array} $results Results from Elasticsearch
459 - * @param {response} $response Raw response from Elasticsearch
460 - * @param {array} $query Raw Elasticsearch query
461 - * @param {array} $query_args Query arguments
462 - * @param {mixed} $query_object Could be WP_Query, WP_User_Query, etc.
463 - * @return {array} New results
467 + * @param {int} $results.found_documents Total number of documents.
468 + * @param {array} $results.documents Array of documents.
469 + * @param {array} $results.aggregations Array of aggregations.
470 + * @param {array} $results.suggest Array of suggestions.
471 + * @param {response} $response Raw response from Elasticsearch
472 + * @param {array} $query Raw Elasticsearch query
473 + * @param {array} $query_args Query arguments
474 + * @param {mixed} $query_object Could be WP_Query, WP_User_Query, etc.
475 + * @return {array} New results
464 476 */
465 477 return apply_filters(
466 478 'ep_es_query_results',
467 479 [
@@ -467,8 +479,9 @@
467 479 [
468 480 'found_documents' => $total_hits,
469 481 'documents' => $documents,
470 482 'aggregations' => $response['aggregations'] ?? [],
483 + 'suggest' => $response['suggest'] ?? [],
471 484 ],
472 485 $response,
473 486 $query,
474 487 $query_args,
@@ -570,9 +583,9 @@
570 583 * @since 3.0
571 584 * @return boolean
572 585 */
573 586 public function delete_document( $index, $type, $document_id, $blocking = true ) {
574 - if ( version_compare( $this->get_elasticsearch_version(), '7.0', '<' ) ) {
587 + if ( version_compare( (string) $this->get_elasticsearch_version(), '7.0', '<' ) ) {
575 588 $path = $index . '/' . $type . '/' . $document_id;
576 589 } else {
577 590 $path = $index . '/_doc/' . $document_id;
578 591 }
@@ -626,8 +639,13 @@
626 639 $headers['Authorization'] = 'Basic ' . base64_encode( $shield );
627 640 // phpcs:enable
628 641 }
629 642
643 + $request_id = Utils\generate_request_id();
644 + if ( ! empty( $request_id ) ) {
645 + $headers['X-ElasticPress-Request-ID'] = $request_id;
646 + }
647 +
630 648 /**
631 649 * Filter Elasticsearch request headers
632 650 *
633 651 * @hook ep_format_request_headers
@@ -648,9 +666,9 @@
648 666 * @since 3.0
649 667 * @return boolean|array
650 668 */
651 669 public function get_document( $index, $type, $document_id ) {
652 - if ( version_compare( $this->get_elasticsearch_version(), '7.0', '<' ) ) {
670 + if ( version_compare( (string) $this->get_elasticsearch_version(), '7.0', '<' ) ) {
653 671 $path = $index . '/' . $type . '/' . $document_id;
654 672 } else {
655 673 $path = $index . '/_doc/' . $document_id;
656 674 }
@@ -706,9 +724,9 @@
706 724 * @since 3.6.0
707 725 * @return boolean|array
708 726 */
709 727 public function get_documents( $index, $type, $document_ids ) {
710 - if ( version_compare( $this->get_elasticsearch_version(), '7.0', '<' ) ) {
728 + if ( version_compare( (string) $this->get_elasticsearch_version(), '7.0', '<' ) ) {
711 729 $path = apply_filters( 'ep_index_' . $type . '_request_path', $index . '/' . $type . '/_mget', $document_ids, $type );
712 730 } else {
713 731 $path = apply_filters( 'ep_index_' . $type . '_request_path', $index . '/_mget', $document_ids, $type );
714 732 }
@@ -808,12 +826,13 @@
808 826 * Put a mapping into Elasticsearch
809 827 *
810 828 * @param string $index Index name.
811 829 * @param array $mapping Mapping array.
830 + * @param string $return_type Desired return type. Can be either 'bool' or 'raw'
812 831 * @since 3.0
813 - * @return boolean
832 + * @return boolean|WP_Error
814 833 */
815 - public function put_mapping( $index, $mapping ) {
834 + public function put_mapping( $index, $mapping, $return_type = 'bool' ) {
816 835 /**
817 836 * Filter Elasticsearch mapping before put mapping
818 837 *
819 838 * @hook ep_config_mapping
@@ -841,17 +860,43 @@
841 860 * @return {array} New response
842 861 */
843 862 $request = apply_filters( 'ep_config_mapping_request', $request, $index, $mapping );
844 863
845 - $response_body = wp_remote_retrieve_body( $request );
864 + $response_code = wp_remote_retrieve_response_code( $request );
846 865
847 - if ( ! is_wp_error( $request ) && 200 === wp_remote_retrieve_response_code( $request ) ) {
848 - $response_body = wp_remote_retrieve_body( $request );
866 + /**
867 + * Fires after sending a put mapping request
868 + *
869 + * @hook ep_after_put_mapping
870 + * @since 4.7.0
871 + * @param {string} $index Index name
872 + * @param {WP_Error|array} $request The response or WP_Error on failure.
873 + */
874 + do_action( 'ep_after_put_mapping', $index, $request );
849 875
850 - return true;
876 + // If WP_Error or not 200, return false or error message depends on attribute.
877 + if ( is_wp_error( $request ) || 200 !== $response_code ) {
878 + if ( 'bool' === $return_type ) {
879 + return false;
880 + }
881 +
882 + if ( is_wp_error( $request ) ) {
883 + return $request;
884 + }
885 +
886 + $response_body = wp_remote_retrieve_body( $request );
887 + $parsed_response = json_decode( $response_body, true );
888 + if ( is_array( $parsed_response ) ) {
889 + $status = $parsed_response['status'] ?? 'status-not-set';
890 + $error = $parsed_response['error'] ?? 'error-not-set';
891 + } else {
892 + $status = $response_code;
893 + $error = $response_body;
894 + }
895 + return new \WP_Error( $status, $error );
851 896 }
852 897
853 - return false;
898 + return true;
854 899 }
855 900
856 901 /**
857 902 * Get current index mapping from Elasticsearch.
@@ -921,30 +966,81 @@
921 966 return ( ! is_wp_error( $request ) && 200 === wp_remote_retrieve_response_code( $request ) );
922 967 }
923 968
924 969 /**
925 - * Get index settings.
970 + * Get index settings
926 971 *
927 - * @param string $index Index name.
928 - * @since 4.4.0
972 + * @param string $index Index name
973 + * @param bool $force_refresh Whether to use or not a cached value. Default false, use cached.
974 + * @since 4.4.0, 4.7.0 added the $force_refresh parameter
929 975 * @return array|WP_Error Raw ES response from the $index/_settings?flat_settings=true endpoint
930 976 */
931 - public function get_index_settings( string $index ) {
977 + public function get_index_settings( string $index, bool $force_refresh = false ) {
978 + $transient_key = "ep_index_settings_{$index}";
979 +
980 + if ( ! $force_refresh ) {
981 + $cache = Utils\get_transient( $transient_key );
982 + if ( false !== $cache ) {
983 + return $cache;
984 + }
985 + }
986 +
932 987 $endpoint = trailingslashit( $index ) . '_settings?flat_settings=true';
933 988 $request = $this->remote_request( $endpoint, [], [], 'get_index_settings' );
934 989
935 990 if ( is_wp_error( $request ) ) {
991 + Utils\set_transient( $transient_key, $request, MINUTE_IN_SECONDS );
936 992 return $request;
937 993 }
938 994
995 + if ( wp_remote_retrieve_response_code( $request ) !== 200 ) {
996 + Utils\set_transient( $transient_key, $request, MINUTE_IN_SECONDS );
997 + return new \WP_Error(
998 + 'ep_get_index_settings_failed',
999 + esc_html__( 'Error while getting the index settings.', 'elasticpress' ),
1000 + $request
1001 + );
1002 + }
1003 +
939 1004 $response_body = wp_remote_retrieve_body( $request );
940 1005
941 1006 $settings = json_decode( $response_body, true );
942 1007
1008 + Utils\set_transient( $transient_key, $settings, DAY_IN_SECONDS );
1009 +
943 1010 return $settings;
944 1011 }
945 1012
946 1013 /**
1014 + * Get a particular index setting
1015 + *
1016 + * @param string $index Index name
1017 + * @param string $setting Setting name
1018 + * @param bool $force_refresh Whether to use or not a cached value. Default false, use cached.
1019 + * @return mixed
1020 + */
1021 + public function get_index_setting( string $index, string $setting, bool $force_refresh = false ) {
1022 + $settings = $this->get_index_settings( $index, $force_refresh );
1023 +
1024 + if ( is_wp_error( $settings ) || empty( $settings[ $index ]['settings'][ $setting ] ) ) {
1025 + return null;
1026 + }
1027 +
1028 + return $settings[ $index ]['settings'][ $setting ];
1029 + }
1030 +
1031 + /**
1032 + * Given an index return its total fields limit
1033 + *
1034 + * @since 4.4.0, 4.7.0 wrapper of get_index_setting()
1035 + * @param string $index_name The index name
1036 + * @return int|null
1037 + */
1038 + public function get_index_total_fields_limit( $index_name ) {
1039 + return $this->get_index_setting( $index_name, 'index.mapping.total_fields.limit' );
1040 + }
1041 +
1042 + /**
947 1043 * Update index settings.
948 1044 *
949 1045 * @param string $index Index name.
950 1046 * @param array $settings Setting update array.
@@ -1074,9 +1170,9 @@
1074 1170 * @param {string} $body Bulk index request body
1075 1171 * @param {string} $type Index type
1076 1172 * @return {string} New path
1077 1173 */
1078 - if ( version_compare( $this->get_elasticsearch_version(), '7.0', '<' ) ) {
1174 + if ( version_compare( (string) $this->get_elasticsearch_version(), '7.0', '<' ) ) {
1079 1175 $path = apply_filters( 'ep_bulk_index_request_path', $index . '/' . $type . '/_bulk', $body, $type );
1080 1176 } else {
1081 1177 $path = apply_filters( 'ep_bulk_index_request_path', $index . '/_bulk', $body, $type );
1082 1178 }
@@ -1108,9 +1204,17 @@
1108 1204 * @since 1.8
1109 1205 * @return array
1110 1206 */
1111 1207 public function get_query_log() {
1112 - return $this->queries;
1208 + /**
1209 + * Filter the query log
1210 + *
1211 + * @hook ep_get_query_log
1212 + * @since 5.3.0
1213 + * @param {array} $queries The query log
1214 + * @return {array} The query log
1215 + */
1216 + return apply_filters( 'ep_get_query_log', $this->queries );
1113 1217 }
1114 1218
1115 1219 /**
1116 1220 * Wrapper for wp_remote_request
@@ -1125,9 +1229,9 @@
1125 1229 * @param string $type Type of request, used for debugging.
1126 1230 *
1127 1231 * @return WP_Error|array The response or WP_Error on failure.
1128 1232 */
1129 - public function remote_request( $path, $args = [], $query_args = [], $type = null ) {
1233 + public function remote_request( $path, $args = [], $query_args = [], $type = '' ) {
1130 1234
1131 1235 if ( empty( $args['method'] ) ) {
1132 1236 $args['method'] = 'GET';
1133 1237 }
@@ -1203,9 +1307,9 @@
1203 1307 * @hook ep_intercept_remote_request
1204 1308 * @param {boolean} $intercept True to intercept
1205 1309 * @return {boolean} New value
1206 1310 */
1207 - if ( true === apply_filters( 'ep_intercept_remote_request', false ) ) {
1311 + if ( true === apply_filters( 'ep_intercept_remote_request', false ) || ! empty( $query_args['ep_intercept_request'] ) ) {
1208 1312 /**
1209 1313 * Filter intercepted request
1210 1314 *
1211 1315 * @hook ep_do_intercept_request
@@ -1228,9 +1332,9 @@
1228 1332 $is_valid_res = ( $request_response_code >= 200 && $request_response_code <= 299 );
1229 1333 $is_non_blocking_request = ( 0 === $request_response_code );
1230 1334
1231 1335 if ( false === $request || is_wp_error( $request ) || ( ! $is_valid_res && ! $is_non_blocking_request ) ) {
1232 - $failures++;
1336 + ++$failures;
1233 1337
1234 1338 /**
1235 1339 * Filter max number of times to attempt remote requests
1236 1340 *
@@ -1255,8 +1359,17 @@
1255 1359 $query['blocking'] = true;
1256 1360 $query['request'] = $request;
1257 1361 $this->add_query_log( $query );
1258 1362
1363 + /**
1364 + * Fires after Elasticsearch remote request
1365 + *
1366 + * @hook ep_remote_request
1367 + * @param {array} $query Remote request arguments
1368 + * @param {string} $type Request type
1369 + */
1370 + do_action( 'ep_remote_request', $query, $type );
1371 +
1259 1372 return $request;
1260 1373 }
1261 1374
1262 1375 $query['time_finish'] = microtime( true );
@@ -1262,19 +1375,12 @@
1262 1375 $query['time_finish'] = microtime( true );
1263 1376 $query['request'] = $request;
1264 1377 $this->add_query_log( $query );
1265 1378
1266 - /**
1267 - * Fires after Elasticsearch remote request
1268 - *
1269 - * @hook ep_remote_request
1270 - * @param {array} $query Remote request arguments
1271 - * @param {string} $type Request type
1272 - */
1379 + // This action is documented above
1273 1380 do_action( 'ep_remote_request', $query, $type );
1274 1381
1275 1382 return $request;
1276 -
1277 1383 }
1278 1384
1279 1385 /**
1280 1386 * Parse response from Elasticsearch
@@ -1322,9 +1428,8 @@
1322 1428 return array(
1323 1429 'status' => true,
1324 1430 'data' => $response->_all->primaries->indexing,
1325 1431 );
1326 -
1327 1432 }
1328 1433
1329 1434 /**
1330 1435 * Set ES plugins and version, detect server type, and cache everything
@@ -1398,20 +1503,24 @@
1398 1503 $node = end( $response['nodes'] );
1399 1504 // Save version of last node. We assume all nodes are same version.
1400 1505 $this->elasticsearch_version = $node['version'];
1401 1506
1507 + // Elasticsearch calls "modules" all default plugins that can't be uninstalled
1508 + if ( isset( $node['modules'] ) && is_array( $node['modules'] ) ) {
1509 + foreach ( $node['modules'] as $plugin ) {
1510 + $this->elasticsearch_plugins[ $plugin['name'] ] = $plugin['version'];
1511 + }
1512 +
1513 + if ( ! empty( $node['modules'] ) && ! empty( $node['modules'][0]['opensearch_version'] ) ) {
1514 + $this->server_type = 'opensearch';
1515 + }
1516 + }
1517 +
1402 1518 if ( isset( $node['plugins'] ) && is_array( $node['plugins'] ) ) {
1403 1519 foreach ( $node['plugins'] as $plugin ) {
1404 1520 $this->elasticsearch_plugins[ $plugin['name'] ] = $plugin['version'];
1405 1521 }
1406 1522 }
1407 - if ( isset( $node['modules'] )
1408 - && is_array( $node['modules'] )
1409 - && ! empty( $node['modules'] )
1410 - && ! empty( $node['modules'][0]['opensearch_version'] )
1411 - ) {
1412 - $this->server_type = 'opensearch';
1413 - }
1414 1523 }
1415 1524
1416 1525 /**
1417 1526 * Cache ES info
@@ -1610,9 +1719,9 @@
1610 1719 /**
1611 1720 * Filter the User Agent header when submitting requests to Elasticsearch.
1612 1721 *
1613 1722 * @hook ep_remote_request_add_ep_user_agent
1614 - * @param {bool} $should_add_ep_verion Whether the ElasticPress version should be added to the User Agent string.
1723 + * @param {bool} $should_add_ep_version Whether the ElasticPress version should be added to the User Agent string.
1615 1724 * @return {bool} New value
1616 1725 * @since 3.6.1
1617 1726 */
1618 1727 if ( apply_filters( 'ep_remote_request_add_ep_user_agent', Utils\is_epio() ) ) {
@@ -1629,14 +1738,27 @@
1629 1738 /**
1630 1739 * Query logging. Don't log anything to the queries property when
1631 1740 * WP_DEBUG is not enabled. Calls action 'ep_add_query_log' if you
1632 1741 * want to access the query outside of the ElasticPress plugin. This
1633 - * runs regardless of debufg settings.
1742 + * runs regardless of debug settings.
1634 1743 *
1635 1744 * @param array $query Query to log.
1636 1745 */
1637 1746 protected function add_query_log( $query ) {
1638 - if ( ( defined( 'WP_DEBUG' ) && WP_DEBUG ) || ( defined( 'WP_EP_DEBUG' ) && WP_EP_DEBUG ) ) {
1747 + $wp_debug = defined( 'WP_DEBUG' ) && WP_DEBUG;
1748 + $wp_ep_debug = defined( 'WP_EP_DEBUG' ) && WP_EP_DEBUG;
1749 +
1750 + /**
1751 + * Filter query logging. Don't log anything to the queries property when true.
1752 + *
1753 + * @hook ep_disable_query_logging
1754 + * @param {bool} Whether to log to the queries property. Defaults to false.
1755 + * @return {bool} New value
1756 + * @since 5.1.4
1757 + */
1758 + $disable_query_logging = apply_filters( 'ep_disable_query_logging', false );
1759 +
1760 + if ( ! $disable_query_logging && ( $wp_debug || $wp_ep_debug ) ) {
1639 1761 $this->queries[] = $query;
1640 1762 }
1641 1763
1642 1764 /**
@@ -1650,15 +1772,18 @@
1650 1772
1651 1773 /**
1652 1774 * Get all index names.
1653 1775 *
1654 - * @since 4.4.0
1776 + * @param string $status Whether to return active indexables or all registered.
1777 + * @since 4.4.0, 4.5.0 Added $status
1655 1778 * @return array
1656 1779 */
1657 - public function get_index_names() {
1658 - $sites = ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) ? Utils\get_sites() : array( array( 'blog_id' => get_current_blog_id() ) );
1780 + public function get_index_names( $status = 'active' ) {
1781 + $sites = ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) ?
1782 + Utils\get_sites( 0, true ) :
1783 + array( array( 'blog_id' => get_current_blog_id() ) );
1659 1784
1660 - $all_indexables = Indexables::factory()->get_all();
1785 + $all_indexables = Indexables::factory()->get_all( null, false, $status );
1661 1786
1662 1787 $global_indexes = [];
1663 1788 $non_global_indexes = [];
1664 1789 foreach ( $all_indexables as $indexable ) {
@@ -1667,11 +1792,8 @@
1667 1792 continue;
1668 1793 }
1669 1794
1670 1795 foreach ( $sites as $site ) {
1671 - if ( ! Utils\is_site_indexable( $site['blog_id'] ) ) {
1672 - continue;
1673 - }
1674 1796 $non_global_indexes[] = $indexable->get_index_name( $site['blog_id'] );
1675 1797 }
1676 1798 }
1677 1799
@@ -1683,9 +1805,9 @@
1683 1805 *
1684 1806 * @since 4.4.0
1685 1807 * @return array Array of indices in Elasticsearch
1686 1808 */
1687 - public function get_cluster_indices() : array {
1809 + public function get_cluster_indices(): array {
1688 1810 $path = '_cat/indices?format=json';
1689 1811
1690 1812 $response = $this->remote_request( $path );
1691 1813
@@ -1692,40 +1814,21 @@
1692 1814 return (array) json_decode( wp_remote_retrieve_body( $response ), true );
1693 1815 }
1694 1816
1695 1817 /**
1696 - * Given an index return its total fields limit
1818 + * Return a comparison between which indices should be and are present in the ES server.
1697 1819 *
1698 - * @since 4.4.0
1699 - * @param string $index_name The index name
1700 - * @return int|null
1820 + * @since 4.6.0
1821 + * @return array Array with `missing_indices` and `present_indices` keys.
1701 1822 */
1702 - public function get_index_total_fields_limit( $index_name ) {
1703 - $cache_key = 'ep_total_fields_limit_' . $index_name;
1823 + public function get_indices_comparison() {
1824 + $all_index_names = $this->get_index_names();
1825 + $cluster_indices = $this->get_cluster_indices();
1704 1826
1705 - $is_network = defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK;
1706 - if ( $is_network ) {
1707 - $cached = get_site_transient( $cache_key );
1708 - } else {
1709 - $cached = get_transient( $cache_key );
1710 - }
1711 - if ( ! empty( $cached ) ) {
1712 - return $cached;
1713 - }
1827 + $cluster_index_names = wp_list_pluck( $cluster_indices, 'index' );
1714 1828
1715 - $index_settings = $this->get_index_settings( $index_name );
1716 - if ( is_wp_error( $index_settings ) || empty( $index_settings[ $index_name ]['settings']['index.mapping.total_fields.limit'] ) ) {
1717 - return null;
1718 - }
1719 -
1720 - $es_field_limit = $index_settings[ $index_name ]['settings']['index.mapping.total_fields.limit'];
1721 -
1722 - if ( $is_network ) {
1723 - set_site_transient( $cache_key, $es_field_limit, DAY_IN_SECONDS );
1724 - } else {
1725 - set_transient( $cache_key, $es_field_limit, DAY_IN_SECONDS );
1726 - }
1727 -
1728 - return (int) $es_field_limit;
1829 + return [
1830 + 'missing_indices' => array_diff( $all_index_names, $cluster_index_names ),
1831 + 'present_indices' => array_intersect( $all_index_names, $cluster_index_names ),
1832 + ];
1729 1833 }
1730 -
1731 1834 }