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
elasticpress / includes / classes / AdminNotices.php

AdminNotices.php in ElasticPress 5.3.5, at includes/classes/AdminNotices.php

926 lines 24.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * ElasticPress admin notice handler
4 *
5 * phpcs:disable WordPress.WP.I18n.MissingTranslatorsComment
6 *
7 * @since 3.0
8 * @package elasticpress
9 */
10
11 namespace ElasticPress;
12
13 use ElasticPress\Utils;
14 use ElasticPress\Elasticsearch;
15 use ElasticPress\Screen;
16 use ElasticPress\Features;
17 use ElasticPress\Indexables;
18 use ElasticPress\Stats;
19
20 if ( ! defined( 'ABSPATH' ) ) {
21 exit; // Exit if accessed directly.
22 }
23
24 /**
25 * Admin notices class
26 */
27 class AdminNotices {
28
29 /**
30 * Notice keys
31 *
32 * @since 3.0
33 * @var array
34 */
35 protected $notice_keys = [
36 'host_error',
37 'es_below_compat',
38 'es_above_compat',
39 'different_server_type',
40 'need_setup',
41 'no_sync',
42 'upgrade_sync',
43 'auto_activate_sync',
44 'using_autosuggest_defaults',
45 'maybe_wrong_mapping',
46 'yellow_health',
47 'too_many_fields',
48 ];
49
50 /**
51 * Notices that should be shown on a screen
52 *
53 * @var array
54 * @since 3.0
55 */
56 protected $notices = [];
57
58 /**
59 * Process all notifications and prepare ones that should be displayed
60 *
61 * @since 3.0
62 */
63 public function process_notices() {
64 $this->notices = [];
65
66 foreach ( $this->notice_keys as $notice ) {
67 $output = call_user_func( [ $this, 'process_' . $notice . '_notice' ] );
68
69 if ( ! empty( $output ) ) {
70 $this->notices[ $notice ] = $output;
71 }
72 }
73 }
74
75 /**
76 * Autosuggest defaults are being used. Feature must be active.
77 *
78 * Type: notice
79 * Dismiss: Everywhere
80 * Show: Settings and dashboard only
81 *
82 * @since 3.0
83 * @return array|bool
84 */
85 protected function process_using_autosuggest_defaults_notice() {
86 $feature = Features::factory()->get_registered_feature( 'autosuggest' );
87 if ( ! $feature instanceof Feature ) {
88 return false;
89 }
90
91 if ( ! $feature->is_active() ) {
92 return false;
93 }
94
95 $last_sync = Utils\get_option( 'ep_last_sync', false );
96
97 if ( empty( $last_sync ) ) {
98 return false;
99 }
100
101 $host = Utils\get_host();
102
103 if ( empty( $host ) ) {
104 return false;
105 }
106
107 $dismiss = Utils\get_option( 'ep_hide_using_autosuggest_defaults_notice', false );
108
109 if ( $dismiss ) {
110 return false;
111 }
112
113 $screen = Screen::factory()->get_current_screen();
114
115 if ( ! in_array( $screen, [ 'dashboard', 'settings' ], true ) ) {
116 return false;
117 }
118
119 return [
120 'html' => sprintf( esc_html__( 'Autosuggest feature is enabled. If documents feature is enabled, your media will also become searchable in the frontend.', 'elasticpress' ) ),
121 'type' => 'info',
122 'dismiss' => true,
123 ];
124 }
125
126 /**
127 * An EP feature was auto-activated that requires a sync.
128 *
129 * Type: warning
130 * Dismiss: Everywhere except ep dash and settings
131 * Show: All screens except install. Dont show during sync ever
132 *
133 * @since 3.0
134 * @return array|bool
135 */
136 protected function process_auto_activate_sync_notice() {
137 $need_upgrade_sync = Utils\get_option( 'ep_need_upgrade_sync', false );
138
139 // need_upgrade_sync takes priority over this notice
140 if ( $need_upgrade_sync ) {
141 return false;
142 }
143
144 $auto_activate_sync = Utils\get_option( 'ep_feature_auto_activated_sync', false );
145
146 if ( ! $auto_activate_sync ) {
147 return false;
148 }
149
150 $last_sync = Utils\get_option( 'ep_last_sync', false );
151
152 if ( empty( $last_sync ) ) {
153 return false;
154 }
155
156 $host = Utils\get_host();
157
158 if ( empty( $host ) ) {
159 return false;
160 }
161
162 $dismiss = Utils\get_option( 'ep_hide_auto_activate_sync_notice', false );
163
164 $screen = Screen::factory()->get_current_screen();
165
166 if ( 'install' === $screen ) {
167 return false;
168 }
169
170 if ( $dismiss && ! in_array( $screen, [ 'dashboard', 'settings' ], true ) ) {
171 return false;
172 }
173
174 if ( Utils\isset_do_sync_parameter() ) {
175 return false;
176 }
177
178 $url = Utils\get_sync_url( 'features' );
179
180 $feature = Features::factory()->get_registered_feature( $auto_activate_sync );
181
182 if ( defined( 'EP_DASHBOARD_SYNC' ) && ! EP_DASHBOARD_SYNC ) {
183 $html = sprintf(
184 /* translators: Feature name */
185 esc_html__( 'Dashboard sync is disabled. The ElasticPress %s feature has been auto-activated! You will need to reindex using WP-CLI for it to work.', 'elasticpress' ),
186 esc_html( is_object( $feature ) ? $feature->get_short_title() : '' )
187 );
188 } else {
189 $html = sprintf(
190 /* translators: 1. Feature name; 2: Sync page URL */
191 __( 'The ElasticPress %1$s feature has been auto-activated! You will need to <a href="%2$s">run a sync</a> for it to work.', 'elasticpress' ),
192 esc_html( is_object( $feature ) ? $feature->get_short_title() : '' ),
193 esc_url( $url )
194 );
195 }
196
197 return [
198 'html' => $html,
199 'type' => 'warning',
200 'dismiss' => ! in_array( $screen, [ 'dashboard', 'settings' ], true ),
201 ];
202 }
203
204 /**
205 * EP was upgraded to or past a version that requires a sync.
206 *
207 * Type: warning
208 * Dismiss: Everywhere except ep dash and settings
209 * Show: All screens except install. Dont show during sync ever
210 *
211 * @since 3.0
212 * @return array|bool
213 */
214 protected function process_upgrade_sync_notice() {
215 $need_upgrade_sync = Utils\get_option( 'ep_need_upgrade_sync', false );
216
217 if ( ! $need_upgrade_sync ) {
218 return false;
219 }
220
221 $last_sync = Utils\get_option( 'ep_last_sync', false );
222
223 if ( empty( $last_sync ) ) {
224 return false;
225 }
226
227 $host = Utils\get_host();
228
229 if ( empty( $host ) ) {
230 return false;
231 }
232
233 $dismiss = Utils\get_option( 'ep_hide_upgrade_sync_notice', false );
234
235 $screen = Screen::factory()->get_current_screen();
236
237 if ( 'install' === $screen ) {
238 return false;
239 }
240
241 if ( $dismiss && ! in_array( $screen, [ 'dashboard', 'settings' ], true ) ) {
242 return false;
243 }
244
245 if ( Utils\isset_do_sync_parameter() ) {
246 return false;
247 }
248
249 $url = Utils\get_sync_url( 'upgrade' );
250
251 if ( defined( 'EP_DASHBOARD_SYNC' ) && ! EP_DASHBOARD_SYNC ) {
252 $html = esc_html__( 'Dashboard sync is disabled. The new version of ElasticPress requires that you delete all data and start a fresh sync using WP-CLI.', 'elasticpress' );
253 } else {
254 $html = sprintf(
255 /* translators: Sync Page URL */
256 __( 'The new version of ElasticPress requires that you <a href="%s">delete all data and start a fresh sync</a>.', 'elasticpress' ),
257 esc_url( $url )
258 );
259 }
260
261 $notice = esc_html__( 'Please note that some ElasticPress functionality may be impaired and/or content may not be searchable until the full sync has been performed.', 'elasticpress' );
262
263 return [
264 'html' => '<span class="dashicons dashicons-warning"></span> ' . $html . ' ' . $notice,
265 'type' => 'error',
266 'dismiss' => ! in_array( $screen, [ 'dashboard', 'settings' ], true ),
267 ];
268 }
269
270 /**
271 * EP has no never had a sync. We assume the user is on step 3 of the install.
272 *
273 * Type: notice
274 * Dismiss: Everywhere except ep dash and settings
275 * Show: All screens except install. Dont show during sync ever
276 *
277 * @since 3.0
278 * @return array|bool
279 */
280 protected function process_no_sync_notice() {
281 $last_sync = Utils\get_option( 'ep_last_sync', false );
282
283 if ( ! empty( $last_sync ) ) {
284 return false;
285 }
286
287 $host = Utils\get_host();
288
289 if ( empty( $host ) ) {
290 return false;
291 }
292
293 $dismiss = Utils\get_option( 'ep_hide_no_sync_notice', false );
294
295 $screen = Screen::factory()->get_current_screen();
296
297 if ( 'install' === $screen ) {
298 return false;
299 }
300
301 if ( $dismiss && ! in_array( $screen, [ 'dashboard', 'settings' ], true ) ) {
302 return false;
303 }
304
305 if ( Utils\isset_do_sync_parameter() ) {
306 return false;
307 }
308
309 if ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) {
310 $url = admin_url( 'network/admin.php?page=elasticpress-sync' );
311 } else {
312 $url = admin_url( 'admin.php?page=elasticpress-sync' );
313 }
314
315 if ( defined( 'EP_DASHBOARD_SYNC' ) && ! EP_DASHBOARD_SYNC ) {
316 $html = esc_html__( 'Dashboard sync is disabled, but ElasticPress is almost ready to go. Trigger a sync from WP-CLI.', 'elasticpress' );
317 } else {
318 $html = sprintf(
319 /* translators: Sync Page URL */
320 __( 'ElasticPress is almost ready to go. You just need to <a href="%s">sync your content</a>.', 'elasticpress' ),
321 esc_url( $url )
322 );
323 }
324
325 return [
326 'html' => $html,
327 'type' => 'info',
328 'dismiss' => ! in_array( $screen, [ 'dashboard', 'settings' ], true ),
329 ];
330 }
331
332 /**
333 * EP has no host set. We assume the user needs to run an install.
334 *
335 * Type: notice
336 * Dismiss: Anywhere except EP dashboard
337 * Show: All screens except settings and install
338 *
339 * @since 3.0
340 * @return array|bool
341 */
342 protected function process_need_setup_notice() {
343 $host = Utils\get_host();
344
345 if ( ! empty( $host ) ) {
346 return false;
347 }
348
349 $dismiss = Utils\get_option( 'ep_hide_need_setup_notice', false );
350
351 $screen = Screen::factory()->get_current_screen();
352
353 if ( in_array( $screen, [ 'settings', 'install' ], true ) ) {
354 return false;
355 }
356
357 if ( $dismiss && 'dashboard' !== $screen ) {
358 return false;
359 }
360
361 if ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) {
362 $url = admin_url( 'network/admin.php?page=elasticpress-settings' );
363 } else {
364 $url = admin_url( 'admin.php?page=elasticpress-settings' );
365 }
366
367 return [
368 'type' => 'info',
369 'dismiss' => 'dashboard' !== $screen,
370 'html' => sprintf(
371 /* translators: Sync Page URL */
372 __( 'ElasticPress is almost ready to go. You just need to <a href="%s">enter your settings</a>.', 'elasticpress' ),
373 esc_url( $url )
374 ),
375 ];
376 }
377
378 /**
379 * Below ES compat error.
380 *
381 * Type: error
382 * Dismiss: Anywhere
383 * Show: All screens
384 *
385 * @since 3.0
386 * @return array|bool
387 */
388 protected function process_es_below_compat_notice() {
389 if ( Utils\is_epio() ) {
390 return false;
391 }
392
393 $host = Utils\get_host();
394
395 if ( empty( $host ) ) {
396 return false;
397 }
398
399 $es_version = Elasticsearch::factory()->get_elasticsearch_version();
400
401 if ( false === $es_version ) {
402 return false;
403 }
404
405 $dismiss = Utils\get_option( 'ep_hide_es_below_compat_notice', false );
406
407 if ( $dismiss ) {
408 return false;
409 }
410
411 // First reduce version to major version i.e. 7.10 not 7.10.1.
412 $major_es_version = preg_replace( '#^([0-9]+\.[0-9]+).*#', '$1', $es_version );
413
414 // pad a version to have at least two parts (7 -> 7.0)
415 $parts = explode( '.', $major_es_version );
416
417 if ( 1 === count( $parts ) ) {
418 $parts[] = 0;
419 }
420
421 $major_es_version = implode( '.', $parts );
422
423 if ( 1 === version_compare( EP_ES_VERSION_MIN, $major_es_version ) ) {
424 return [
425 'type' => 'error',
426 'dismiss' => true,
427 'html' => sprintf(
428 /* translators: 1. Current Elasticsearch version; 2. Minimum required ES version */
429 __( 'Your Elasticsearch version %1$s is below the minimum required Elasticsearch version %2$s. ElasticPress may or may not work properly.', 'elasticpress' ),
430 esc_html( $es_version ),
431 esc_html( EP_ES_VERSION_MIN )
432 ),
433 ];
434 }
435
436 return false;
437 }
438
439 /**
440 * Above ES compat error.
441 *
442 * Type: error
443 * Dismiss: Anywhere
444 * Show: All screens
445 *
446 * @since 3.0
447 * @return array|bool
448 */
449 protected function process_es_above_compat_notice() {
450 if ( Utils\is_epio() ) {
451 return false;
452 }
453
454 $host = Utils\get_host();
455
456 if ( empty( $host ) ) {
457 return false;
458 }
459
460 $es_version = Elasticsearch::factory()->get_elasticsearch_version();
461
462 if ( false === $es_version ) {
463 return false;
464 }
465
466 $dismiss = Utils\get_option( 'ep_hide_es_above_compat_notice', false );
467
468 if ( $dismiss ) {
469 return false;
470 }
471
472 // First reduce version to major version i.e. 7.10 not 7.10.1.
473 $major_es_version = preg_replace( '#^([0-9]+\.[0-9]+).*#', '$1', $es_version );
474
475 if ( -1 === version_compare( EP_ES_VERSION_MAX, $major_es_version ) ) {
476 return [
477 'type' => 'warning',
478 'dismiss' => true,
479 'html' => sprintf(
480 /* translators: 1. Current Elasticsearch version; 2. Maximum supported ES version */
481 __( 'Your Elasticsearch version %1$s is above the maximum required Elasticsearch version %2$s. ElasticPress may or may not work properly.', 'elasticpress' ),
482 esc_html( $es_version ),
483 esc_html( EP_ES_VERSION_MAX )
484 ),
485 ];
486 }
487 }
488
489 /**
490 * Server software different from Elasticsearch warning.
491 *
492 * Type: warning
493 * Dismiss: Anywhere
494 * Show: All screens
495 *
496 * @since 4.2.1
497 * @return array|bool
498 */
499 protected function process_different_server_type_notice() {
500 if ( Utils\is_epio() ) {
501 return false;
502 }
503
504 $host = Utils\get_host();
505
506 if ( empty( $host ) ) {
507 return false;
508 }
509
510 $server_type = Elasticsearch::factory()->get_server_type();
511
512 if ( false === $server_type || 'elasticsearch' === $server_type ) {
513 return false;
514 }
515
516 $dismiss = Utils\get_option( 'ep_hide_different_server_type_notice', false );
517
518 if ( $dismiss ) {
519 return false;
520 }
521
522 $doc_url = 'https://www.elasticpress.io/resources/articles/compatibility/';
523 $html = sprintf(
524 /* translators: Document page URL */
525 __( 'Your server software is not supported. To learn more about server compatibility please <a href="%s">visit our documentation</a>.', 'elasticpress' ),
526 esc_url( $doc_url )
527 );
528
529 return [
530 'html' => $html,
531 'type' => 'warning',
532 'dismiss' => true,
533 ];
534 }
535
536 /**
537 * Host error notification. Shows when EP can't reach ES host.
538 *
539 * Type: error
540 * Dismiss: Only on non-EP screens
541 * Show: All screens except install
542 *
543 * @since 3.0
544 * @return array|bool
545 */
546 protected function process_host_error_notice() {
547 $host = Utils\get_host();
548
549 if ( empty( $host ) ) {
550 return false;
551 }
552
553 $screen = Screen::factory()->get_current_screen();
554
555 if ( 'install' === $screen ) {
556 return false;
557 }
558
559 $es_version = Elasticsearch::factory()->get_elasticsearch_version( false );
560
561 if ( false !== $es_version ) {
562 return false;
563 }
564
565 // Only dismissable on non-EP screens
566 if ( ! in_array( $screen, [ 'settings', 'dashboard' ], true ) ) {
567 $dismiss = Utils\get_option( 'ep_hide_host_error_notice', false );
568
569 if ( $dismiss ) {
570 return false;
571 }
572 }
573
574 if ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) {
575 $url = admin_url( 'network/admin.php?page=elasticpress-settings' );
576 $response_code = get_site_transient( 'ep_es_info_response_code' );
577 $response_error = get_site_transient( 'ep_es_info_response_error' );
578 } else {
579 $url = admin_url( 'admin.php?page=elasticpress-settings' );
580 $response_code = get_transient( 'ep_es_info_response_code' );
581 $response_error = get_transient( 'ep_es_info_response_error' );
582 }
583
584 $retry_url = add_query_arg(
585 [
586 'ep-retry' => 1,
587 'ep_retry_nonce' => wp_create_nonce( 'ep_retry_nonce' ),
588 ]
589 );
590
591 $html = sprintf(
592 /* translators: 1. Current URL with retry parameter; 2. Settings Page URL */
593 __( 'There is a problem with connecting to your Elasticsearch host. ElasticPress can <a href="%1$s">try your host again</a>, or you may need to <a href="%2$s">change your settings</a>.', 'elasticpress' ),
594 esc_url( $retry_url ),
595 esc_url( $url )
596 );
597
598 if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
599 if ( ! empty( $response_code ) ) {
600 /* translators: Response Code Number */
601 $html .= '<span class="notice-error-es-response-code"> ' . sprintf( __( 'Response Code: %s', 'elasticpress' ), esc_html( $response_code ) ) . '</span>';
602 }
603
604 if ( ! empty( $response_error ) ) {
605 /* translators: Response Code Message */
606 $html .= '<span class="notice-error-es-response-error"> ' . sprintf( __( 'Response error: %s', 'elasticpress' ), esc_html( $response_error ) ) . '</span>';
607 }
608 }
609
610 return [
611 'html' => $html,
612 'type' => 'error',
613 'dismiss' => ( ! in_array( Screen::factory()->get_current_screen(), [ 'settings', 'dashboard' ], true ) ) ? true : false,
614 ];
615 }
616
617 /**
618 * Determine if the wrong mapping might be installed
619 *
620 * Type: error
621 * Dismiss: Always dismissable per es_version as custom mapping could exist
622 * Show: All screens
623 *
624 * @since 3.6.2
625 * @return array|bool
626 */
627 protected function process_maybe_wrong_mapping_notice() {
628 $screen = Screen::factory()->get_current_screen();
629
630 if ( 'install' === $screen ) {
631 return false;
632 }
633
634 // we might have this dismissed
635 $dismiss = Utils\get_option( 'ep_hide_maybe_wrong_mapping_notice', false );
636
637 // we need a host
638 $host = Utils\get_host();
639 if ( empty( $host ) ) {
640 return false;
641 }
642
643 // we also need a version
644 $es_version = Elasticsearch::factory()->get_elasticsearch_version( false );
645
646 if ( false === $es_version || $dismiss === $es_version ) {
647 return false;
648 }
649
650 // we also likely need a sync to have a mapping
651 $last_sync = Utils\get_option( 'ep_last_sync', false );
652
653 if ( empty( $last_sync ) ) {
654 return false;
655 }
656
657 $post_indexable = Indexables::factory()->get( 'post' );
658
659 $mapping_file_wanted = $post_indexable->get_mapping_name();
660 $mapping_file_current = $post_indexable->determine_mapping_version();
661 if ( is_wp_error( $mapping_file_current ) ) {
662 return false;
663 }
664
665 if ( ! $mapping_file_current || $mapping_file_wanted !== $mapping_file_current ) {
666 $html = sprintf(
667 /* translators: 1. <em>; 2. </em> */
668 esc_html__( 'It seems the mapping data in your index does not match the Elasticsearch version used. We recommend to reindex your content using the sync button on the top of the screen or through wp-cli by adding the %1$s--setup%2$s flag', 'elasticpress' ),
669 '<em>',
670 '</em>'
671 );
672
673 if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
674 /* translators: 1. Current mapping file; 2. Mapping file that should be used */
675 $html .= '<span class="notice-error-es-response-code"> ' . sprintf( esc_html__( 'Current mapping: %1$s. Expected mapping: %2$s', 'elasticpress' ), esc_html( $mapping_file_current ), esc_html( $mapping_file_wanted ) ) . '</span>';
676 }
677
678 return [
679 'html' => $html,
680 'type' => 'error',
681 'dismiss' => true,
682 ];
683
684 }
685 }
686
687 /**
688 * Single node notification. Shows when index health is yellow.
689 *
690 * Type: warning
691 * Dismiss: Anywhere
692 * Show: All screens except install
693 *
694 * @since 3.2
695 * @return array|bool
696 */
697 protected function process_yellow_health_notice() {
698 $host = Utils\get_host();
699
700 if ( empty( $host ) ) {
701 return false;
702 }
703
704 $last_sync = Utils\get_option( 'ep_last_sync', false );
705
706 if ( empty( $last_sync ) ) {
707 return false;
708 }
709
710 $dismiss = Utils\get_option( 'ep_hide_yellow_health_notice', false );
711
712 $screen = Screen::factory()->get_current_screen();
713
714 if ( ! in_array( $screen, [ 'dashboard', 'settings' ], true ) || $dismiss ) {
715 return false;
716 }
717
718 $nodes = Stats::factory()->get_nodes();
719
720 if ( false !== $nodes && $nodes < 2 && $nodes > 0 ) {
721 if ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) {
722 $url = network_admin_url( 'admin.php?page=elasticpress-health' );
723 } else {
724 $url = admin_url( 'admin.php?page=elasticpress-health' );
725 }
726
727 return [
728 'type' => 'warning',
729 'dismiss' => true,
730 'html' => sprintf(
731 /* translators: Index Health URL */
732 __( 'It looks like one or more of your indices are running on a single node. While this won\'t prevent you from using ElasticPress, depending on your site\'s specific needs this can represent a performance issue. Please check the <a href="%s">Index Health</a> page where you can check the health of all of your indices.', 'elasticpress' ),
733 $url
734 ),
735 ];
736 }
737 }
738
739 /**
740 * Too many fields notification. Shows when the site has potentially more fields than ES could handle.
741 *
742 * Type: warning|error
743 * Dismiss: Anywhere
744 * Show: Sync and Install page
745 *
746 * @since 4.4.0
747 * @return array|bool
748 */
749 protected function process_too_many_fields_notice() {
750 $host = Utils\get_host();
751
752 if ( empty( $host ) ) {
753 return false;
754 }
755
756 $dismiss = Utils\get_option( 'ep_hide_too_many_fields_notice', false );
757
758 $screen = Screen::factory()->get_current_screen();
759
760 if ( ! in_array( $screen, [ 'install', 'sync' ], true ) || $dismiss ) {
761 return false;
762 }
763
764 $has_error = false;
765 $has_warning = false;
766
767 if ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) {
768 $sites = Utils\get_sites( 0, true );
769 foreach ( $sites as $site ) {
770 switch_to_blog( $site['blog_id'] );
771
772 list( $has_error, $site_has_warning ) = $this->check_field_count();
773
774 restore_current_blog();
775
776 $has_warning = $has_warning || $site_has_warning;
777 if ( $has_error ) {
778 break;
779 }
780 }
781 } else {
782 list( $has_error, $has_warning ) = $this->check_field_count();
783 }
784
785 if ( $has_error ) {
786 $message = sprintf(
787 /* translators: Elasticsearch or ElasticPress.io; 2. Link to article; 3. Link to article */
788 __( 'Your website content has more public custom fields than %1$s is able to store. Check our articles about <a href="%2$s">Elasticsearch field limitations</a> and <a href="%3$s">how to index just the custom fields you need</a> before trying to sync.', 'elasticpress' ),
789 Utils\is_epio() ? __( 'ElasticPress.io', 'elasticpress' ) : __( 'Elasticsearch', 'elasticpress' ),
790 'https://www.elasticpress.io/resources/articles/i-get-the-error-limit-of-total-fields-in-index-has-been-exceeded/',
791 'https://www.elasticpress.io/resources/articles/how-to-exclude-metadata-from-indexing/'
792 );
793
794 return [
795 'type' => 'error',
796 'dismiss' => true,
797 'html' => $message,
798 ];
799 }
800
801 if ( $has_warning ) {
802 $message = sprintf(
803 /* translators: Elasticsearch or ElasticPress.io; 2. Link to article; 3. Link to article */
804 __( 'Your website content seems to have more public custom fields than %1$s is able to store. Check our articles about <a href="%2$s">Elasticsearch field limitations</a> and <a href="%3$s">how to index just the custom fields you need</a> if you receive any errors while syncing.', 'elasticpress' ),
805 Utils\is_epio() ? __( 'ElasticPress.io', 'elasticpress' ) : __( 'Elasticsearch', 'elasticpress' ),
806 'https://www.elasticpress.io/resources/articles/i-get-the-error-limit-of-total-fields-in-index-has-been-exceeded/',
807 'https://www.elasticpress.io/resources/articles/how-to-exclude-metadata-from-indexing/'
808 );
809
810 return [
811 'type' => 'warning',
812 'dismiss' => true,
813 'html' => $message,
814 ];
815 }
816
817 return false;
818 }
819
820 /**
821 * Get notices that should be displayed
822 *
823 * @since 3.0
824 * @return array
825 */
826 public function get_notices() {
827 /**
828 * Filter admin notices
829 *
830 * @hook ep_admin_notices
831 * @param {array} $notices Admin notices
832 * @return {array} New notices
833 */
834 $notices = apply_filters( 'ep_admin_notices', $this->notices );
835
836 if ( ! is_array( $notices ) ) {
837 _doing_it_wrong(
838 __METHOD__,
839 sprintf(
840 /* translators: %s: Detected variable type. */
841 esc_html__( 'Callbacks of filter hook `ep_admin_notices` must return a value of type array, %s detected.', 'elasticpress' ),
842 esc_html( gettype( $notices ) )
843 ),
844 'ElasticPress 5.3.3'
845 );
846
847 $notices = [];
848 }
849
850 // If the plugin is network-activated and not in the network admin, return the notices whose scope is site.
851 if ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK && ! is_network_admin() ) {
852 $notices = array_filter(
853 $notices,
854 function ( $notice ) {
855 return isset( $notice['scope'] ) && 'site' === $notice['scope'];
856 }
857 );
858 }
859
860 return $notices;
861 }
862
863 /**
864 * Dismiss a notice given a notice key.
865 *
866 * @param string $notice Notice key
867 * @since 3.0
868 */
869 public function dismiss_notice( $notice ) {
870 $value = true;
871 // allow version dependent dismissal
872 if ( in_array( $notice, [ 'maybe_wrong_mapping' ], true ) ) {
873 $value = Elasticsearch::factory()->get_elasticsearch_version( false );
874 }
875
876 Utils\update_option( 'ep_hide_' . $notice . '_notice', $value );
877 }
878
879 /**
880 * Return singleton instance of class
881 *
882 * @return object
883 * @since 0.1.0
884 */
885 public static function factory() {
886 static $instance = false;
887
888 if ( ! $instance ) {
889 $instance = new self();
890 }
891
892 return $instance;
893 }
894
895 /**
896 * Compare the number of fields in the site and the number of allowed fields in ES
897 *
898 * @since 4.4.0
899 * @return array
900 */
901 protected function check_field_count() {
902 $post_indexable = Indexables::factory()->get( 'post' );
903
904 $search = Features::factory()->get_registered_feature( 'search' );
905 if ( $search && ! empty( $search->weighting ) && 'manual' === $search->weighting->get_meta_mode() ) {
906 $indexable_fields = $post_indexable->get_all_allowed_metas_manual();
907 $count_fields_db = count( $indexable_fields );
908 } else {
909 $indexable_fields = $post_indexable->get_predicted_indexable_meta_keys();
910 $count_fields_db = count( $indexable_fields );
911 }
912
913 $index_name = $post_indexable->get_index_name();
914 $es_field_limit = Elasticsearch::factory()->get_index_total_fields_limit( $index_name );
915 $es_field_limit = $es_field_limit ? $es_field_limit : 5000;
916 $es_field_limit = apply_filters( 'ep_total_field_limit', $es_field_limit );
917
918 $predicted_es_field_count = $count_fields_db * 8;
919
920 return [
921 $predicted_es_field_count > $es_field_limit,
922 $predicted_es_field_count * 1.2 > $es_field_limit,
923 ];
924 }
925 }
926