PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 6.2.1
MainWP Dashboard: Self-hosted WordPress Management for Agencies v6.2.1
6.2.2 6.2.1 6.2 6.1.8 6.1.7 6.1.6 6.1.5 6.1.4 6.1.3 6.1.2 6.1.1 6.1 6.0.12 6.0.11 4.6.0.1 5.0 5.0.1 5.0.2 5.0.3 5.0.3.1 5.0.3.2 5.1 5.1.1 5.2 5.2.1 All 155 releases
mainwp / pages / page-mainwp-server-information-handler.php

page-mainwp-server-information-handler.php in MainWP Dashboard: Self-hosted WordPress Management for Agencies 6.2.1, at pages/page-mainwp-server-information-handler.php

3,137 lines 121.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * MainWP Server Information Page Handler
4 *
5 * @package MainWP/Dashboard
6 */
7
8 namespace MainWP\Dashboard;
9
10 // Exit if accessed directly.
11 if ( ! defined( 'ABSPATH' ) ) {
12 exit;
13 }
14
15 /**
16 * Class MainWP Server_Information_Handler
17 */
18 class MainWP_Server_Information_Handler { // phpcs:ignore Generic.Classes.OpeningBraceSameLine.ContentAfterBrace -- NOSONAR.
19
20 // phpcs:disable WordPress.WP.AlternativeFunctions -- use system functions.
21
22 /**
23 * Gets Class Name.
24 *
25 * @return string __CLASS__
26 */
27 public static function get_class_name() {
28 return __CLASS__;
29 }
30
31 /**
32 * Gets current MainWP Plugin version.
33 *
34 * @return mixed $currentVersion verion number/
35 */
36 public static function get_current_version() {
37 return get_option( 'mainwp_plugin_version' );
38 }
39
40 /**
41 * Gets current MainWP Dashboard version.
42 *
43 * @return mixed false|version
44 */
45 public static function get_mainwp_version() {
46
47 if ( isset( $_SESSION['cachedVersion'] ) && isset( $_SESSION['cachedTime'] ) && ( null !== $_SESSION['cachedVersion'] ) && ( ( $_SESSION['cachedTime'] + ( 60 * 30 ) ) > time() ) ) { //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized,WordPress.Security.NonceVerification.Recommended
48 return $_SESSION['cachedVersion']; //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized,WordPress.Security.NonceVerification.Recommended
49 }
50 include_once ABSPATH . '/wp-admin/includes/plugin-install.php'; // NOSONAR - WP compatible.
51 $api = MainWP_System_Utility::get_plugin_theme_info(
52 'plugin',
53 array(
54 'slug' => 'mainwp',
55 'fields' => array( 'sections' => false ),
56 'timeout' => 60,
57 )
58 );
59 if ( is_object( $api ) && isset( $api->version ) ) {
60 $_SESSION['cachedTime'] = time();
61 $_SESSION['cachedVersion'] = $api->version; //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized,WordPress.Security.NonceVerification.Recommended
62 return $_SESSION['cachedVersion']; //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized,WordPress.Security.NonceVerification.Recommended
63 }
64 return false;
65 }
66
67 /**
68 * Checks if WP environment is Mutisilte or not.
69 *
70 * @return bool true|false.
71 */
72 public static function check_if_multisite() {
73 return ! is_multisite() ? true : false;
74 }
75
76 /**
77 * Compares filesize.
78 *
79 * @param mixed $value1 First file size.
80 * @param mixed $value2 Second file size.
81 * @param null $operator Comparison operator.
82 *
83 * @return mixed version_compare() value.
84 */
85 public static function filesize_compare( $value1, $value2, $operator = null ) {
86 if ( false !== strpos( $value1, 'G' ) ) {
87 $value1 = preg_replace( '/[A-Za-z]/', '', $value1 );
88 $value1 = intval( $value1 ) * 1024;
89 } else {
90 $value1 = preg_replace( '/[A-Za-z]/', '', $value1 );
91 }
92
93 if ( false !== strpos( $value2, 'G' ) ) {
94 $value2 = preg_replace( '/[A-Za-z]/', '', $value2 );
95 $value2 = intval( $value2 ) * 1024;
96 } else {
97 $value2 = preg_replace( '/[A-Za-z]/', '', $value2 );
98 }
99
100 return version_compare( $value1, $value2, $operator );
101 }
102
103 /**
104 * Compares cURL SSL Version.
105 *
106 * @param mixed $version CURL SSL version number.
107 * @param null $operator Comparison operator.
108 *
109 * @return mixed false|version
110 */
111 public static function curlssl_compare( $version, $operator ) {
112 if ( function_exists( 'curl_version' ) ) {
113 $ver = static::get_curl_ssl_version();
114 return version_compare( static::extract_version( $ver ), static::extract_version( $version ), $operator );
115 }
116 return false;
117 }
118
119 /**
120 * Method extract_version()
121 *
122 * Function to extract version from string for both OpenSSL and LibreSSL
123 *
124 * @param string $version_string Version OpenSSL and LibreSSL.
125 *
126 * @return mixed null|string
127 */
128 public static function extract_version( $version_string ) {
129 if ( preg_match( '/(?:LibreSSL|OpenSSL)[\/ ]([\d.]+)/', $version_string, $matches ) ) {
130 return $matches[1];
131 }
132 return null;
133 }
134
135 /**
136 * Gets file system method.
137 *
138 * @return string $fs File System Method.
139 */
140 public static function get_file_system_method() {
141 return get_filesystem_method();
142 }
143
144 /**
145 * Gets loaded PHP Extensions.
146 */
147 public static function get_loaded_php_extensions() {
148 $extensions = get_loaded_extensions();
149 sort( $extensions );
150 echo esc_html( implode( ', ', $extensions ) );
151 }
152
153 /**
154 * Gets the WP_MEMORY_LIMIT value.
155 *
156 * @return mixed WP_MEMORY_LIMIT WordPress Memmory Limit.
157 */
158 public static function get_wordpress_memory_limit() {
159 return WP_MEMORY_LIMIT;
160 }
161
162 /**
163 * Method get_curl_version()
164 *
165 * Get current cURL Version.
166 *
167 * @return mixed $curlversion['version'] Currently installed cURL Version.
168 */
169 public static function get_curl_version() {
170 $curlversion = curl_version();
171
172 return $curlversion['version'];
173 }
174
175 /**
176 * Method get_curl_ssl_version()
177 *
178 * Get current SSL Version installed.
179 *
180 * @return mixed $curlversion['ssl_version'] Currently installed SSL version.
181 */
182 public static function get_curl_ssl_version() {
183 $curlversion = curl_version();
184
185 return $curlversion['ssl_version'];
186 }
187
188 /**
189 * Method get_wordpress_version()
190 *
191 * Get current WordPress Version
192 *
193 * @return mixed $wp_version Current installed WordPress version
194 */
195 public static function get_wordpress_version() {
196
197 /**
198 * WordPress version.
199 *
200 * @global string
201 */
202 global $wp_version;
203
204 return $wp_version;
205 }
206
207 /**
208 * Method get_ssl_support()
209 *
210 * Get SSL Support.
211 *
212 * @return mixed Open SSL Extentions loaded.
213 */
214 public static function get_ssl_support() {
215 return extension_loaded( 'openssl' );
216 }
217
218 /**
219 * Method get_ssl_warning()
220 *
221 * Get any SSL Warning Messages.
222 *
223 * @return string SSL Error message.
224 *
225 * @uses \MainWP\Dashboard\MainWP_System_Utility::get_openssl_conf()
226 */
227 public static function get_ssl_warning() {
228 $conf = array( 'private_key_bits' => 2048 );
229 $conf_loc = MainWP_System_Utility::get_openssl_conf();
230 if ( ! empty( $conf_loc ) ) {
231 $conf['config'] = $conf_loc;
232 }
233 $errors = array();
234
235 $general_verify_con = (int) get_option( 'mainwp_verify_connection_method', 0 );
236
237 if ( 2 !== $general_verify_con && function_exists( 'openssl_pkey_new' ) ) {
238 $res = openssl_pkey_new( $conf );
239 openssl_pkey_export( $res, $privkey, null, $conf );
240
241 $error = '';
242 while ( ( $errorRow = openssl_error_string() ) !== false ) {
243 $error = $errorRow . "\n" . $error;
244 }
245 if ( ! empty( $error ) ) {
246 $errors[] = $error;
247 }
248 }
249
250 return empty( $errors ) ? '' : implode( ' - ', $errors );
251 }
252
253 /**
254 * To verify openssl working.
255 *
256 * @return bool Working status.
257 */
258 public static function get_openssl_working_status() {
259
260 $ok = false;
261 $general_verify_con = (int) get_option( 'mainwp_verify_connection_method', 0 );
262 if ( 2 === $general_verify_con ) {
263 $ok = 1;
264 } elseif ( function_exists( 'openssl_verify' ) && function_exists( 'openssl_pkey_new' ) ) {
265
266 $conf = array(
267 'private_key_bits' => 2048,
268 );
269
270 $conf_loc = MainWP_System_Utility::get_openssl_conf();
271 if ( ! empty( $conf_loc ) ) {
272 $conf['config'] = $conf_loc;
273 }
274
275 $res = openssl_pkey_new( $conf );
276
277 @openssl_pkey_export( $res, $privkey, null, $conf ); // phpcs:ignore -- prevent warning.
278 $details = openssl_pkey_get_details( $res );
279
280 if ( is_array( $details ) && isset( $details['key'] ) ) {
281 $publicKey = $details['key'];
282 $data = 'working status';
283 openssl_sign( $data, $signature, $privkey ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
284 if ( ! empty( $signature ) ) {
285 $ok = openssl_verify( $data, $signature, $publicKey );
286 }
287 }
288 }
289
290 return 1 === $ok;
291 }
292
293 /**
294 * Method is_openssl_config_warning()
295 *
296 * Check if open ssl is configured correctly.
297 *
298 * @return boolean true|false.
299 */
300 public static function is_openssl_config_warning() {
301 $ssl_warning = static::get_ssl_warning();
302 if ( '' !== $ssl_warning && ( false !== stristr( $ssl_warning, 'No such file or directory found', 'mainwp' ) || false !== stristr( $ssl_warning, 'No such process', 'mainwp' ) || false !== stristr( $ssl_warning, 'no such file', 'mainwp' ) ) ) {
303 return true;
304 }
305 return false;
306 }
307
308 /**
309 * Method get_curl_support()
310 *
311 * Get cURL Version.
312 *
313 * @return string cURL Version.
314 */
315 public static function get_curl_support() {
316 return function_exists( 'curl_version' );
317 }
318
319 /**
320 * Method get_curl_timeout()
321 *
322 * Get cURL_Timeout value.
323 *
324 * @return string cURL_Timeout value.
325 */
326 public static function get_curl_timeout() {
327 return ini_get( 'default_socket_timeout' );
328 }
329
330 /**
331 * Method get_php_version()
332 *
333 * Get PHP Version.
334 *
335 * @return string phpversion().
336 */
337 public static function get_php_version() {
338 return phpversion();
339 }
340
341 /**
342 * Method get_max_execution_time()
343 *
344 * Get MAX_EXECUTION_TIME.
345 *
346 * @return string MAX_EXECUTION_TIME.
347 */
348 public static function get_max_execution_time() {
349 return ini_get( 'max_execution_time' );
350 }
351
352 /**
353 * Method get_max_execution_time()
354 *
355 * Get MAX_INPUT_TIME.
356 *
357 * @return string MAX_EXECUTION_TIME.
358 */
359 public static function get_max_input_time() {
360 return ini_get( 'max_input_time' );
361 }
362
363 /**
364 * Method get_max_execution_time()
365 *
366 * Get MAX_UPLOAD_FILESIZE.
367 *
368 * @return string MAX_UPLOAD_FILESIZE.
369 */
370 public static function get_upload_max_filesize() {
371 return ini_get( 'upload_max_filesize' );
372 }
373
374 /**
375 * Method get_max_execution_time()
376 *
377 * Get MAX_POST_SIZE.
378 *
379 * @return string MAX_POST_SIZE.
380 */
381 public static function get_post_max_size() {
382 return ini_get( 'post_max_size' );
383 }
384
385 /**
386 * Method get_mysql_version()
387 *
388 * Get MySql Version.
389 *
390 * @return string MySQL Version.
391 *
392 * @uses \MainWP\Dashboard\MainWP_DB::get_my_sql_version()
393 */
394 public static function get_mysql_version() {
395 return MainWP_DB::instance()->get_my_sql_version();
396 }
397
398 /**
399 * Method get_php_memory_limit()
400 *
401 * Get PHP_MEMORY_LIMIT.
402 *
403 * @return string PHP_MEMORY_LIMIT.
404 */
405 public static function get_php_memory_limit() {
406 return ini_get( 'memory_limit' );
407 }
408
409 /**
410 * Method get_os()
411 *
412 * Get Host OS.
413 *
414 * @param bool $return_value = false.
415 *
416 * @return mixed PHP_OS.
417 */
418 public static function get_os( $return_value = false ) {
419 if ( $return_value ) {
420 return PHP_OS;
421 } else {
422 echo esc_html( PHP_OS );
423 }
424 }
425
426 /**
427 * Method get_architecture()
428 *
429 * Get PHP_INT_SIZE * 8bit.
430 */
431 public static function get_architecture() {
432 echo esc_html( PHP_INT_SIZE * 8 );
433 ?>
434 &nbsp;bit
435 <?php
436 }
437
438 /**
439 * Method memory_usage()
440 *
441 * Get currently used memory.
442 */
443 public static function memory_usage() {
444 if ( function_exists( 'memory_get_usage' ) ) {
445 $memory_usage = round( memory_get_usage() / 1024 / 1024, 2 ) . ' MB';
446 } else {
447 $memory_usage = 'N/A';
448 }
449 echo esc_html( $memory_usage );
450 }
451
452 /**
453 * Method get_output_buffer_size()
454 *
455 * Get putput buffer size.
456 *
457 * @return string Current output buffer Size.
458 */
459 public static function get_output_buffer_size() {
460 return ini_get( 'pcre.backtrack_limit' );
461 }
462
463 /**
464 * Method get_sql_mode()
465 *
466 * Get SQL Mode.
467 */
468 public static function get_sql_mode() {
469
470 /**
471 * WordPress database instance.
472 *
473 * @global object
474 */
475 global $wpdb;
476
477 $sql_mode = '';
478 $cache_key = 'mainwp_sql_mode';
479 $mysqlinfo = wp_cache_get( $cache_key );
480 if ( false === $mysqlinfo ) {
481 $mysqlinfo = $wpdb->get_results( "SHOW VARIABLES LIKE 'sql_mode'" ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- ok.
482 wp_cache_set( $cache_key, $mysqlinfo, '', DAY_IN_SECONDS );
483 }
484 if ( is_array( $mysqlinfo ) ) {
485 $sql_mode = $mysqlinfo[0]->Value;
486 }
487 if ( empty( $sql_mode ) ) {
488 $sql_mode = esc_html__( 'NOT SET', 'mainwp' );
489 }
490 echo esc_html( $sql_mode );
491 }
492
493 /**
494 * Checks if PHP url fopen is allowed.
495 */
496 public static function get_php_allow_url_fopen() {
497 $allow = ini_get( 'allow_url_fopen' );
498 if ( is_numeric( $allow ) ) {
499 $allow = intval( $allow );
500 if ( $allow ) {
501 esc_html_e( 'YES', 'mainwp' );
502 } else {
503 esc_html_e( 'NO', 'mainwp' );
504 }
505 } elseif ( is_string( $allow ) ) {
506 echo esc_html( $allow );
507 }
508 }
509
510 /**
511 * Method get_php_exif()
512 *
513 * Check if PHP Exif is enabled.
514 */
515 public static function get_php_exif() {
516 if ( is_callable( 'exif_read_data' ) ) {
517 esc_html_e( 'YES', 'mainwp' ) . ' ( V' . esc_html( substr( phpversion( 'exif' ), 0, 4 ) ) . ')';
518 } else {
519 esc_html_e( 'NO', 'mainwp' );
520 }
521 }
522
523 /**
524 * Method get_php_iptc()
525 *
526 * Check if iptcparse is enabled.
527 */
528 public static function get_php_iptc() {
529 if ( is_callable( 'iptcparse' ) ) {
530 esc_html_e( 'YES', 'mainwp' );
531 } else {
532 esc_html_e( 'NO', 'mainwp' );
533 }
534 }
535
536 /**
537 * Method get_php_xml()
538 *
539 * Check if PHP XML Parser is enabled.
540 */
541 public static function get_php_xml() {
542 if ( is_callable( 'xml_parser_create' ) ) {
543 esc_html_e( 'YES', 'mainwp' );
544 } else {
545 esc_html_e( 'NO', 'mainwp' );
546 }
547 }
548
549 /**
550 * Method get_server_gateway_interface()
551 *
552 * Get server gateway interface.
553 */
554 public static function get_server_gateway_interface() {
555 echo isset( $_SERVER['GATEWAY_INTERFACE'] ) ? esc_html( sanitize_text_field( wp_unslash( $_SERVER['GATEWAY_INTERFACE'] ) ) ) : '';
556 }
557
558 /**
559 * Method get_server_ip()
560 *
561 * Get server IP address.
562 */
563 public static function get_server_ip() {
564 echo isset( $_SERVER['SERVER_ADDR'] ) ? esc_html( sanitize_text_field( wp_unslash( $_SERVER['SERVER_ADDR'] ) ) ) : '';
565 }
566
567 /**
568 * Method get_server_name()
569 *
570 * Get server name.
571 *
572 * @param bool $return_value Return or not.
573 *
574 * @return string $_SERVER['SERVER_NAME'].
575 */
576 public static function get_server_name( $return_value = false ) {
577 if ( $return_value ) {
578 return isset( $_SERVER['SERVER_NAME'] ) ? esc_html( sanitize_text_field( wp_unslash( $_SERVER['SERVER_NAME'] ) ) ) : '';
579 } else {
580 echo isset( $_SERVER['SERVER_NAME'] ) ? esc_html( sanitize_text_field( wp_unslash( $_SERVER['SERVER_NAME'] ) ) ) : '';
581 }
582 }
583
584 /**
585 * Method get_server_software()
586 *
587 * Get server software.
588 *
589 * @param bool $return_value Return or not.
590 *
591 * @return string $_SERVER['SERVER_SOFTWARE'].
592 */
593 public static function get_server_software( $return_value = false ) {
594 if ( $return_value ) {
595 return isset( $_SERVER['SERVER_SOFTWARE'] ) ? esc_html( sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ) ) : '';
596 } else {
597 echo isset( $_SERVER['SERVER_SOFTWARE'] ) ? esc_html( sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ) ) : '';
598 }
599 }
600
601 /**
602 * Method is_apache_server_software()
603 *
604 * Check if server software is apache.
605 *
606 * @return bool True|false.
607 */
608 public static function is_apache_server_software() {
609 $server = static::get_server_software( true );
610 return ( false !== stripos( $server, 'apache' ) ) ? true : false;
611 }
612
613 /**
614 * Gets server protocol.
615 */
616 public static function get_server_protocol() {
617 echo isset( $_SERVER['SERVER_PROTOCOL'] ) ? esc_html( sanitize_text_field( wp_unslash( $_SERVER['SERVER_PROTOCOL'] ) ) ) : '';
618 }
619
620 /**
621 * Gets server request time.
622 */
623 public static function get_server_request_time() {
624 echo isset( $_SERVER['REQUEST_TIME'] ) ? esc_html( sanitize_text_field( wp_unslash( $_SERVER['REQUEST_TIME'] ) ) ) : '';
625 }
626
627
628 /**
629 * Gets server HTTP accept.
630 */
631 public static function get_server_http_accept() {
632 echo isset( $_SERVER['HTTP_ACCEPT'] ) ? esc_html( sanitize_text_field( wp_unslash( $_SERVER['HTTP_ACCEPT'] ) ) ) : '';
633 }
634
635 /**
636 * Gets server accepted character set.
637 */
638 public static function get_server_accept_charset() {
639 // phpcs:disable WordPress.Security.EscapeOutput
640 echo ( ! isset( $_SERVER['HTTP_ACCEPT_CHARSET'] ) || empty( $_SERVER['HTTP_ACCEPT_CHARSET'] ) ) ? esc_html__( 'N/A', 'mainwp' ) : esc_html( sanitize_text_field( wp_unslash( $_SERVER['HTTP_ACCEPT_CHARSET'] ) ) );
641 // phpcs:enable
642 }
643
644 /**
645 * Gets HTTP host.
646 */
647 public static function get_http_host() {
648 echo isset( $_SERVER['HTTP_HOST'] ) ? esc_html( sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) ) ) : '';
649 }
650
651 /**
652 * Gets complete URL.
653 */
654 public static function get_complete_url() {
655 echo isset( $_SERVER['HTTP_REFERER'] ) ? esc_url( sanitize_text_field( wp_unslash( $_SERVER['HTTP_REFERER'] ) ) ) : '';
656 }
657
658 /**
659 * Gets user agent.
660 */
661 public static function get_user_agent() {
662 echo isset( $_SERVER['HTTP_USER_AGENT'] ) ? esc_html( sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) ) : '';
663 }
664
665 /**
666 * Checks if HTTPS is enabled.
667 */
668 public static function get_https() {
669 if ( isset( $_SERVER['HTTPS'] ) && '' !== $_SERVER['HTTPS'] ) {
670 esc_html_e( 'ON', 'mainwp' ) . ' - ' . esc_html( sanitize_text_field( wp_unslash( $_SERVER['HTTPS'] ) ) );
671 } else {
672 esc_html_e( 'OFF', 'mainwp' );
673 }
674 }
675
676 /**
677 * Method server_self_connect()
678 *
679 * Check if server self-connect is possible.
680 */
681 public static function server_self_connect() {
682 $url = site_url( 'wp-cron.php' );
683 $query_args = array( 'mainwp_run' => 'test' );
684 $url = esc_url_raw( add_query_arg( $query_args, $url ) );
685
686 /**
687 * Filter: https_local_ssl_verify
688 *
689 * Filters whether the server-self check shoul verify SSL Cert.
690 *
691 * @since Unknown
692 */
693 $args = array(
694 'blocking' => true,
695 'sslverify' => apply_filters( 'https_local_ssl_verify', true ),
696 'timeout' => 15,
697 );
698 $response = wp_remote_post( $url, $args );
699 $test_result = '';
700 if ( is_wp_error( $response ) ) {
701 /* translators: %s: error message */
702 $test_result .= sprintf( esc_html__( 'The HTTP response test get an error "%s"', 'mainwp' ), $response->get_error_message() );
703 }
704 $response_code = wp_remote_retrieve_response_code( $response );
705 if ( 200 > $response_code && 204 < $response_code ) {
706 /* translators: %s: HTTP status code */
707 $test_result .= sprintf( esc_html__( 'The HTTP response test get a false http status (%s)', 'mainwp' ), wp_remote_retrieve_response_code( $response ) );
708 } else {
709 $response_body = wp_remote_retrieve_body( $response );
710 if ( false === strstr( $response_body, 'MainWP Test' ) ) {
711 /* translators: %s: response body */
712 $test_result .= sprintf( esc_html__( 'Not expected HTTP response body: %s', 'mainwp' ), esc_attr( wp_strip_all_tags( $response_body ) ) );
713 }
714 }
715 if ( empty( $test_result ) ) {
716 esc_html_e( 'Response Test O.K.', 'mainwp' );
717 } else {
718 echo esc_html( $test_result );
719 }
720 }
721
722 /**
723 * Gets server remote address.
724 */
725 public static function get_remote_address() {
726 echo isset( $_SERVER['REMOTE_ADDR'] ) ? esc_html( sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) ) : '';
727 }
728
729 /**
730 * Gets server remote host.
731 */
732 public static function get_remote_host() {
733 if ( ! isset( $_SERVER['REMOTE_HOST'] ) || ( '' === $_SERVER['REMOTE_HOST'] ) ) {
734 esc_html_e( 'N/A', 'mainwp' );
735 } else {
736 echo isset( $_SERVER['REMOTE_HOST'] ) ? esc_html( sanitize_text_field( wp_unslash( $_SERVER['REMOTE_HOST'] ) ) ) : '';
737 }
738 }
739
740 /**
741 * Gets server remote port.
742 */
743 public static function get_remote_port() {
744 echo isset( $_SERVER['REMOTE_PORT'] ) ? esc_html( sanitize_text_field( wp_unslash( $_SERVER['REMOTE_PORT'] ) ) ) : '';
745 }
746
747 /**
748 * Gets server script filename.
749 */
750 public static function get_script_file_name() {
751 echo isset( $_SERVER['SCRIPT_FILENAME'] ) ? esc_html( sanitize_text_field( wp_unslash( $_SERVER['SCRIPT_FILENAME'] ) ) ) : '';
752 }
753
754 /**
755 * Method get_server_port()
756 *
757 * Get server port.
758 */
759 public static function get_server_port() {
760 echo isset( $_SERVER['SERVER_PORT'] ) ? esc_html( sanitize_text_field( wp_unslash( $_SERVER['SERVER_PORT'] ) ) ) : '';
761 }
762
763 /**
764 * Method get_current_page_uri()
765 *
766 * Get current page URI.
767 */
768 public static function get_current_page_uri() {
769 echo isset( $_SERVER['REQUEST_URI'] ) ? esc_html( sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) ) : '';
770 }
771
772 /**
773 * Method get_wp_root()
774 *
775 * Get WP Root Path.
776 */
777 public static function get_wp_root() {
778 echo esc_html( ABSPATH );
779 }
780
781 /**
782 * Compares time.
783 *
784 * @param mixed $a first time to compare.
785 * @param mixed $b second time to compare.
786 */
787 public static function time_compare( $a, $b ) {
788
789 if ( $a === $b ) {
790 return 0;
791 }
792
793 return ( strtotime( $a['time'] ) > strtotime( $b['time'] ) ) ? - 1 : 1;
794 }
795
796 /**
797 * Gets line count.
798 *
799 * @param mixed $path the error log file location.
800 * @param int $line_count number of lines in the error log.
801 * @param int $block_size block size.
802 *
803 * @return string Line Count.
804 */
805 public static function last_lines( $path, $line_count, $block_size = 512 ) {
806 //phpcs:disable WordPress.WP.AlternativeFunctions
807 $lines = array();
808 $leftover = '';
809 $fh = fopen( $path, 'r' );
810
811 fseek( $fh, 0, SEEK_END );
812
813 do {
814 $can_read = $block_size;
815
816 if ( ftell( $fh ) <= $block_size ) {
817 $can_read = ftell( $fh );
818 }
819
820 if ( empty( $can_read ) ) {
821 break;
822 }
823
824 fseek( $fh, - $can_read, SEEK_CUR );
825 $data = fread( $fh, $can_read );
826 $data .= $leftover;
827 fseek( $fh, - $can_read, SEEK_CUR );
828
829 $split_data = array_reverse( explode( "\n", $data ) );
830 $new_lines = array_slice( $split_data, 0, - 1 );
831 $lines = array_merge( $lines, $new_lines );
832 $leftover = $split_data[ count( $split_data ) - 1 ];
833 $count = count( $lines );
834 } while ( $count < $line_count && ! empty( ftell( $fh ) ) );
835
836 if ( empty( ftell( $fh ) ) ) {
837 $lines[] = $leftover;
838 }
839
840 fclose( $fh );
841 //phpcs:enable
842
843 return array_slice( $lines, 0, $line_count );
844 }
845
846 /**
847 * Gets MainWP Set Options.
848 *
849 * @return array $options_value MainWP Options array.
850 *
851 * @uses \MainWP\Dashboard\MainWP_DB_Common::get_user_extension()
852 * @uses \MainWP\Dashboard\MainWP_DB::get_websites_count()
853 */
854 public static function mainwp_options() { // phpcs:ignore -- NOSONAR - current complexity required to achieve desired results. Pull request solutions appreaciated.
855 $mainwp_options = array(
856 'mainwp_number_of_child_sites' => esc_html__( 'Number of connected sites', 'mainwp' ),
857 'mainwp_wp_cron' => esc_html__( 'Use WP Cron', 'mainwp' ),
858 'mainwp_optimize' => esc_html__( 'Optimize data loading', 'mainwp' ),
859 'mainwp_automaticDailyUpdate' => esc_html__( 'WP Core advanced automatic updates enabled', 'mainwp' ),
860 'mainwp_pluginAutomaticDailyUpdate' => esc_html__( 'Plugin advanced automatic updates enabled', 'mainwp' ),
861 'mainwp_themeAutomaticDailyUpdate' => esc_html__( 'Theme advanced automatic updates enabled', 'mainwp' ),
862 'mainwp_numberdays_Outdate_Plugin_Theme' => esc_html__( 'Abandoned plugins/themes tolerance', 'mainwp' ),
863 'mainwp_maximumPosts' => esc_html__( 'Maximum number of posts to return', 'mainwp' ),
864 'mainwp_maximumPages' => esc_html__( 'Maximum number of pages to return', 'mainwp' ),
865 'mainwp_maximumComments' => esc_html__( 'Maximum number of comments', 'mainwp' ),
866 'mainwp_enableLegacyBackupFeature' => esc_html__( 'MainWP legacy backups enabled', 'mainwp' ),
867 'mainwp_primaryBackup' => esc_html__( 'Primary backup system', 'mainwp' ),
868 'is_enable_automatic_check_uptime_monitoring' => esc_html__( 'Enable Uptime Monitoring', 'mainwp' ),
869 'mainwp_disableSitesHealthMonitoring' => esc_html__( 'Site health monitoring enabled', 'mainwp' ),
870 'mainwp_maximumRequests' => esc_html__( 'Maximum simultaneous requests', 'mainwp' ),
871 'mainwp_minimumDelay' => esc_html__( 'Minimum delay between requests', 'mainwp' ),
872 'mainwp_maximumIPRequests' => esc_html__( 'Maximum simultaneous requests per ip', 'mainwp' ),
873 'mainwp_minimumIPDelay' => esc_html__( 'Minimum delay between requests to the same ip', 'mainwp' ),
874 'mainwp_maximumSyncRequests' => esc_html__( 'Maximum simultaneous sync requests', 'mainwp' ),
875 'mainwp_maximumInstallUpdateRequests' => esc_html__( 'Maximum simultaneous install and update requests', 'mainwp' ),
876 'mainwp_maximum_uptime_monitoring_requests' => esc_html__( 'Maximum simultaneous uptime monitoring requests (Default: 10)', 'mainwp' ),
877 'mainwp_auto_purge_cache' => esc_html__( 'Cache control enabled', 'mainwp' ),
878 );
879
880 if ( ! is_plugin_active( 'mainwp-comments-extension/mainwp-comments-extension.php' ) ) {
881 unset( $mainwp_options['mainwp_maximumComments'] );
882 }
883
884 $options_value = array();
885 foreach ( $mainwp_options as $opt => $label ) {
886 if ( 'is_enable_automatic_check_uptime_monitoring' === $opt ) {
887 $global = MainWP_Uptime_Monitoring_Handle::get_global_monitoring_settings();
888 $value = $global['active'];
889 } else {
890 $value = get_option( $opt, false );
891 }
892 $save_value = $value;
893 switch ( $opt ) {
894 case 'mainwp_number_of_child_sites':
895 $value = MainWP_DB::instance()->get_websites_count();
896 break;
897 case 'mainwp_primaryBackup':
898 $value = esc_html__( 'MainWP Legacy Backups', 'mainwp' );
899 break;
900 case 'mainwp_numberdays_Outdate_Plugin_Theme':
901 case 'mainwp_maximumPosts':
902 case 'mainwp_maximumPages':
903 case 'mainwp_maximumComments':
904 break;
905 case 'mainwp_maximumRequests':
906 $value = ( false === $value ) ? 4 : $value;
907 break;
908 case 'mainwp_maximumIPRequests':
909 $value = ( false === $value ) ? 1 : $value;
910 break;
911 case 'mainwp_minimumIPDelay':
912 $value = ( false === $value ) ? 1000 : $value;
913 break;
914 case 'mainwp_minimumDelay':
915 $value = ( false === $value ) ? 200 : $value;
916 break;
917 case 'mainwp_maximumSyncRequests':
918 $value = ( false === $value ) ? 8 : $value;
919 break;
920 case 'mainwp_maximumInstallUpdateRequests':
921 $value = ( false === $value ) ? 3 : $value;
922 break;
923 case 'mainwp_maximum_uptime_monitoring_requests':
924 $value = ( false === $value ) ? 10 : $value;
925 break;
926 case 'is_enable_automatic_check_uptime_monitoring':
927 $value = ! empty( $value ) ? esc_html__( 'Yes', 'mainwp' ) : esc_html__( 'No', 'mainwp' );
928 break;
929 case 'mainwp_disableSitesHealthMonitoring':
930 $value = empty( $value ) ? esc_html__( 'Yes', 'mainwp' ) : esc_html__( 'No', 'mainwp' );
931 break;
932 default:
933 $value = empty( $value ) ? esc_html__( 'No', 'mainwp' ) : esc_html__( 'Yes', 'mainwp' );
934 break;
935 }
936 $options_value[ $opt ] = array(
937 'label' => $label,
938 'value' => $value,
939 'save_value' => $save_value,
940 'name' => $opt,
941 );
942 }
943
944 $options_value['mainwp_rest_api_enabled'] = array(
945 'label' => esc_html__( 'REST API enabled', 'mainwp' ),
946 'value' => Rest_Api_V1::instance()->is_rest_api_enabled() ? esc_html__( 'Yes', 'mainwp' ) : esc_html__( 'No', 'mainwp' ),
947 'save_value' => '',
948 'name' => 'mainwp_rest_api_enabled',
949 );
950
951 /**
952 * Filter: mainwp_getprimarybackup_methods
953 *
954 * Filters the primary backup options for the select menu in Settings.
955 *
956 * @since 4.0
957 */
958 $primaryBackup = get_option( 'mainwp_primaryBackup' );
959 $primary_methods = array();
960 $primary_methods = apply_filters_deprecated( 'mainwp-getprimarybackup-methods', array( $primary_methods ), '4.0.7.2', 'mainwp_getprimarybackup_methods' ); // @deprecated Use 'mainwp_getprimarybackup_methods' instead. NOSONAR - not IP.
961 $primaryBackupMethods = apply_filters( 'mainwp_getprimarybackup_methods', $primary_methods );
962
963 if ( ! is_array( $primaryBackupMethods ) ) {
964 $primaryBackupMethods = array();
965 }
966
967 if ( ! empty( $primaryBackupMethods ) ) {
968 $chk = false;
969 foreach ( $primaryBackupMethods as $method ) {
970 if ( $primaryBackup === $method['value'] ) {
971 $value = $method['title'];
972 $chk = true;
973 break;
974 }
975 }
976 if ( $chk ) {
977 $options_value['mainwp_primaryBackup'] = array(
978 'label' => esc_html__( 'Primary Backup System', 'mainwp' ),
979 'value' => $value,
980 'save_value' => $primaryBackup,
981 'name' => 'mainwp_primaryBackup',
982 );
983 }
984 }
985 return $options_value;
986 }
987
988 /**
989 * Get primary issues summary.
990 *
991 * @return array<int,array<string,string>>
992 */
993 public static function get_primary_issues() {
994 $issues = array();
995
996 if ( ! static::filesize_compare( static::get_wordpress_memory_limit(), '64M', '>=' ) ) {
997 $issues[] = array(
998 'severity' => 'warning',
999 'title' => esc_html__( 'Low WordPress memory limit', 'mainwp' ),
1000 'detail' => sprintf(
1001 /* translators: 1: detected memory limit, 2: recommended memory limit */
1002 esc_html__( 'Detected %1$s. MainWP recommends at least %2$s.', 'mainwp' ),
1003 static::get_wordpress_memory_limit(),
1004 '64M'
1005 ),
1006 'anchor' => 'mainwp-system-report-wordpress-table',
1007 'kb_url' => 'https://docs.mainwp.com/troubleshooting/resolve-system-requirement-issues/',
1008 );
1009 }
1010
1011 if ( ! version_compare( (string) static::get_curl_timeout(), '300', '>=' ) ) {
1012 $issues[] = array(
1013 'severity' => 'warning',
1014 'title' => esc_html__( 'Low cURL timeout', 'mainwp' ),
1015 'detail' => sprintf(
1016 /* translators: 1: detected timeout, 2: recommended timeout */
1017 esc_html__( 'Detected %1$s seconds. MainWP recommends at least %2$s seconds.', 'mainwp' ),
1018 (string) static::get_curl_timeout(),
1019 '300'
1020 ),
1021 'anchor' => 'mainwp-system-report-php-table',
1022 'kb_url' => 'https://docs.mainwp.com/troubleshooting/resolve-system-requirement-issues/',
1023 );
1024 }
1025
1026 $rest_api = static::get_rest_api_reachability_data();
1027 if ( 'pass' !== $rest_api['status'] ) {
1028 $issues[] = array(
1029 'severity' => $rest_api['status'],
1030 'title' => esc_html__( 'WordPress REST API is not fully reachable', 'mainwp' ),
1031 'detail' => $rest_api['value'],
1032 'anchor' => 'mainwp-system-report-connectivity-table',
1033 'kb_url' => 'https://docs.mainwp.com/troubleshooting/wordpress-rest-api-does-not-respond/',
1034 );
1035 }
1036
1037 $permalink = static::get_permalink_structure_data();
1038 if ( 'pass' !== $permalink['status'] ) {
1039 $issues[] = array(
1040 'severity' => $permalink['status'],
1041 'title' => esc_html__( 'Plain permalinks detected', 'mainwp' ),
1042 'detail' => esc_html__( 'MainWP features that depend on the WordPress REST API may not work correctly with plain permalinks.', 'mainwp' ),
1043 'anchor' => 'mainwp-system-report-connectivity-table',
1044 'kb_url' => 'https://docs.mainwp.com/troubleshooting/wordpress-rest-api-does-not-respond/',
1045 );
1046 }
1047
1048 $self_connect = static::get_server_self_connect_data();
1049 if ( 'pass' !== $self_connect['status'] ) {
1050 $issue_title = esc_html__( 'Dashboard self-connect check failed', 'mainwp' );
1051 $issue_detail = $self_connect['value'];
1052 $issue_html = '';
1053
1054 if ( isset( $self_connect['code'] ) && 'unexpected_body' === $self_connect['code'] ) {
1055 $issue_title = esc_html__( 'Dashboard self-connect returned an unexpected body', 'mainwp' );
1056 $issue_detail = esc_html__( 'Unexpected response body. Note: This is common and usually not a problem unless WP-Cron or loopback requests are failing.', 'mainwp' );
1057 $issue_html = sprintf(
1058 '%1$s <em>%2$s</em>',
1059 esc_html__( 'Unexpected response body.', 'mainwp' ),
1060 esc_html__( 'Note: This is common and usually not a problem unless WP-Cron or loopback requests are failing.', 'mainwp' )
1061 );
1062 }
1063
1064 $issues[] = array(
1065 'severity' => $self_connect['status'],
1066 'title' => $issue_title,
1067 'detail' => $issue_detail,
1068 'detail_html' => $issue_html,
1069 'anchor' => 'mainwp-system-report-connectivity-table',
1070 'kb_url' => ( isset( $self_connect['code'] ) && 'unexpected_body' === $self_connect['code'] ) ? '' : 'https://docs.mainwp.com/troubleshooting/potential-issues/',
1071 );
1072 }
1073
1074 $db_issues = MainWP_Database_Schema_Checker::get_detected_db_issues();
1075
1076 return array_merge( $issues, is_array( $db_issues ) ? $db_issues : array() );
1077 }
1078
1079 /**
1080 * Add English export labels to localized report rows.
1081 *
1082 * @param array<int,array<string,mixed>> $rows Report rows.
1083 * @param array<int,string> $english_labels English labels to map.
1084 *
1085 * @return array<int,array<string,mixed>>
1086 */
1087 private static function add_export_labels_to_rows( $rows, $english_labels ) {
1088 if ( empty( $rows ) || empty( $english_labels ) ) {
1089 return $rows;
1090 }
1091
1092 $localized_map = array();
1093 foreach ( $english_labels as $english_label ) {
1094 $localized_map[ esc_html__( $english_label, 'mainwp' ) ] = $english_label;
1095 }
1096
1097 foreach ( $rows as $index => $row ) {
1098 if ( ! is_array( $row ) || empty( $row['label'] ) || ! empty( $row['export_label'] ) ) {
1099 continue;
1100 }
1101
1102 if ( isset( $localized_map[ $row['label'] ] ) ) {
1103 $rows[ $index ]['export_label'] = $localized_map[ $row['label'] ];
1104 }
1105 }
1106
1107 return $rows;
1108 }
1109
1110 /**
1111 * Get English export label for notification type.
1112 *
1113 * @param string $type Notification type.
1114 * @param string $fallback_label Fallback localized label.
1115 *
1116 * @return string
1117 */
1118 private static function get_notification_type_export_label( $type, $fallback_label ) {
1119 $labels = array(
1120 'daily_digest' => 'Daily Digest Email',
1121 'uptime' => 'Uptime Monitoring Email',
1122 'site_health' => 'Site Health Monitoring Email',
1123 'deactivated_license_alert' => 'Extension License Deactivation Notification Email',
1124 'http_check' => 'After Updates HTTP Check Email',
1125 );
1126
1127 /**
1128 * Filter: mainwp_notification_type_export_labels
1129 *
1130 * Filters English export labels for notification types used in the Server Information report export.
1131 *
1132 * @since 6.1
1133 *
1134 * @param array $labels Notification type => English export label map.
1135 * @param string $type Notification type currently being resolved.
1136 * @param string $fallback_label Localized fallback label.
1137 */
1138 $labels = apply_filters( 'mainwp_notification_type_export_labels', $labels, $type, $fallback_label );
1139 if ( ! is_array( $labels ) ) {
1140 $labels = array();
1141 }
1142
1143 return isset( $labels[ $type ] ) ? $labels[ $type ] : $fallback_label;
1144 }
1145
1146 /**
1147 * Get MainWP overview rows.
1148 *
1149 * @return array<int,array<string,mixed>>
1150 */
1151 public static function get_mainwp_overview_report_rows() {
1152 $current_version = static::get_current_version();
1153 $latest_version = static::get_mainwp_version();
1154 $version_value = false !== $latest_version
1155 ? sprintf(
1156 /* translators: 1: latest version, 2: current version */
1157 esc_html__( 'Latest: %1$s | Detected: %2$s', 'mainwp' ),
1158 $latest_version,
1159 $current_version
1160 )
1161 : sprintf(
1162 /* translators: %s: current version */
1163 esc_html__( 'Detected: %s', 'mainwp' ),
1164 $current_version
1165 );
1166
1167 $upload_directory = static::get_mainwp_upload_directory_data();
1168
1169 return self::add_export_labels_to_rows(
1170 array(
1171 array(
1172 'label' => esc_html__( 'MainWP Dashboard Version', 'mainwp' ),
1173 'value' => $version_value,
1174 'status' => ( false !== $latest_version && $current_version === $latest_version ) ? 'pass' : 'warning',
1175 ),
1176 array(
1177 'label' => esc_html__( 'Number of connected sites', 'mainwp' ),
1178 'value' => (string) MainWP_DB::instance()->get_websites_count(),
1179 ),
1180 array(
1181 'label' => esc_html__( 'MainWP upload directory', 'mainwp' ),
1182 'value' => $upload_directory['value'],
1183 'status' => $upload_directory['status'],
1184 ),
1185 array(
1186 'label' => esc_html__( 'MainWP REST API enabled', 'mainwp' ),
1187 'value' => static::format_boolean_label( Rest_Api_V1::instance()->is_rest_api_enabled() ),
1188 'status' => Rest_Api_V1::instance()->is_rest_api_enabled() ? 'pass' : 'warning',
1189 ),
1190 ),
1191 array(
1192 'MainWP Dashboard Version',
1193 'Number of connected sites',
1194 'MainWP upload directory',
1195 'MainWP REST API enabled',
1196 )
1197 );
1198 }
1199
1200 /**
1201 * Get connectivity rows.
1202 *
1203 * @return array<int,array<string,mixed>>
1204 */
1205 public static function get_connectivity_report_rows() {
1206 $permalink = static::get_permalink_structure_data();
1207 $rest_api = static::get_rest_api_reachability_data();
1208 $self_connect = static::get_server_self_connect_data();
1209 $public_ip = static::get_public_dashboard_ip_data();
1210 $ssl_verify = ( false === get_option( 'mainwp_sslVerifyCertificate' ) ) || 1 === (int) get_option( 'mainwp_sslVerifyCertificate', 1 );
1211 $verify_con = (int) get_option( 'mainwp_verify_connection_method', 1 );
1212 $signature = static::get_signature_algorithm_label();
1213
1214 return self::add_export_labels_to_rows(
1215 array(
1216 array(
1217 'label' => esc_html__( 'Dashboard home URL', 'mainwp' ),
1218 'value' => home_url( '/' ),
1219 'visibility' => 'full_only',
1220 ),
1221 array(
1222 'label' => esc_html__( 'Dashboard site URL', 'mainwp' ),
1223 'value' => site_url( '/' ),
1224 'visibility' => 'full_only',
1225 ),
1226 array(
1227 'label' => esc_html__( 'Public Dashboard IP', 'mainwp' ),
1228 'value' => $public_ip['value'],
1229 'status' => $public_ip['status'],
1230 'visibility' => 'community_masked',
1231 'community_value' => $public_ip['community_value'],
1232 ),
1233 array(
1234 'label' => esc_html__( 'HTTPS', 'mainwp' ),
1235 'value' => is_ssl() ? esc_html__( 'Enabled', 'mainwp' ) : esc_html__( 'Disabled', 'mainwp' ),
1236 ),
1237 array(
1238 'label' => esc_html__( 'Permalink structure', 'mainwp' ),
1239 'value' => $permalink['value'],
1240 'status' => $permalink['status'],
1241 ),
1242 array(
1243 'label' => esc_html__( 'WordPress REST API endpoint', 'mainwp' ),
1244 'value' => rest_url(),
1245 'visibility' => 'full_only',
1246 ),
1247 array(
1248 'label' => esc_html__( 'WordPress REST API reachability', 'mainwp' ),
1249 'value' => $rest_api['value'],
1250 'status' => $rest_api['status'],
1251 ),
1252 array(
1253 'label' => esc_html__( 'Server self connect', 'mainwp' ),
1254 'value' => $self_connect['value'],
1255 'status' => $self_connect['status'],
1256 ),
1257 array(
1258 'label' => esc_html__( 'Verify SSL certificate', 'mainwp' ),
1259 'value' => static::format_boolean_label( $ssl_verify ),
1260 ),
1261 array(
1262 'label' => esc_html__( 'Verify connection method', 'mainwp' ),
1263 'value' => 2 === $verify_con ? esc_html__( 'PHPSECLIB (fallback)', 'mainwp' ) : esc_html__( 'OpenSSL (default)', 'mainwp' ),
1264 ),
1265 array(
1266 'label' => esc_html__( 'OpenSSL signature algorithm', 'mainwp' ),
1267 'value' => $signature,
1268 ),
1269 array(
1270 'label' => esc_html__( 'Force IPv4', 'mainwp' ),
1271 'value' => static::format_boolean_label( (int) get_option( 'mainwp_forceUseIPv4', 0 ) ),
1272 ),
1273 ),
1274 array(
1275 'Dashboard home URL',
1276 'Dashboard site URL',
1277 'Public Dashboard IP',
1278 'HTTPS',
1279 'Permalink structure',
1280 'WordPress REST API endpoint',
1281 'WordPress REST API reachability',
1282 'Server self connect',
1283 'Verify SSL certificate',
1284 'Verify connection method',
1285 'OpenSSL signature algorithm',
1286 'Force IPv4',
1287 )
1288 );
1289 }
1290
1291 /**
1292 * Get scheduler rows.
1293 *
1294 * @return array<int,array<string,mixed>>
1295 */
1296 public static function get_scheduler_report_rows() {
1297 $daily_frequency = (int) get_option( 'mainwp_frequencyDailyUpdate', 2 );
1298 if ( $daily_frequency <= 0 ) {
1299 $daily_frequency = 1;
1300 }
1301
1302 $rows = array(
1303 array(
1304 'label' => esc_html__( 'Use WP Cron', 'mainwp' ),
1305 'value' => static::format_boolean_label( ( false === get_option( 'mainwp_wp_cron' ) ) || 1 === (int) get_option( 'mainwp_wp_cron', 1 ) ),
1306 ),
1307 array(
1308 'label' => esc_html__( 'Daily update frequency', 'mainwp' ),
1309 'value' => MainWP_Server_Information::get_schedule_auto_update_label( $daily_frequency ),
1310 ),
1311 array(
1312 'label' => esc_html__( 'Daily update time', 'mainwp' ),
1313 'value' => (string) get_option( 'mainwp_timeDailyUpdate', '00:00' ),
1314 ),
1315 array(
1316 'label' => esc_html__( 'Advanced automatic updates schedule', 'mainwp' ),
1317 'value' => static::get_automatic_updates_schedule_label(),
1318 ),
1319 );
1320
1321 $updates_check = static::get_cron_job_summary( 'mainwp_updatescheck_start_last_timestamp', 'mainwp_cronupdatescheck_action', '' );
1322 $rows[] = array(
1323 'label' => esc_html__( 'Check for available updates', 'mainwp' ),
1324 'value' => sprintf(
1325 /* translators: 1: last run, 2: next run */
1326 esc_html__( 'Last run: %1$s | Next run: %2$s', 'mainwp' ),
1327 $updates_check['last'],
1328 $updates_check['next']
1329 ),
1330 );
1331
1332 $reconnect = static::get_cron_job_summary( 'mainwp_cron_last_stats', 'mainwp_cronreconnect_action', 'hourly' );
1333 $rows[] = array(
1334 'label' => esc_html__( 'Reconnect sites', 'mainwp' ),
1335 'value' => sprintf(
1336 /* translators: 1: last run, 2: next run */
1337 esc_html__( 'Last run: %1$s | Next run: %2$s', 'mainwp' ),
1338 $reconnect['last'],
1339 $reconnect['next']
1340 ),
1341 );
1342
1343 $monitoring = static::get_uptime_monitoring_summary();
1344 if ( ! empty( $monitoring ) ) {
1345 $rows[] = $monitoring;
1346 }
1347
1348 return self::add_export_labels_to_rows(
1349 $rows,
1350 array(
1351 'Use WP Cron',
1352 'Daily update frequency',
1353 'Daily update time',
1354 'Advanced automatic updates schedule',
1355 'Check for available updates',
1356 'Reconnect sites',
1357 'Uptime monitoring schedule',
1358 )
1359 );
1360 }
1361
1362 /**
1363 * Get general settings rows.
1364 *
1365 * @return array<int,array<string,mixed>>
1366 */
1367 public static function get_general_settings_report_rows() {
1368 $default_setting = MainWP_Settings_Indicator::get_defaults_value();
1369 $sidebar = get_user_option( 'mainwp_sidebarPosition' );
1370 if ( false === $sidebar ) {
1371 $sidebar = 1;
1372 }
1373
1374 $time_auto_update = get_option( 'mainwp_time_AutoUpdate', '00:00' );
1375 $frequency_auto_update = get_option( 'mainwp_frequency_AutoUpdate', 'daily' );
1376 if ( empty( $time_auto_update ) ) {
1377 $time_auto_update = '00:00';
1378 }
1379 if ( ! in_array( $frequency_auto_update, array( 'daily', 'weekly', 'monthly' ), true ) ) {
1380 $frequency_auto_update = 'daily';
1381 }
1382
1383 $show_widgets = get_user_option( 'mainwp_settings_show_widgets' );
1384 if ( ! is_array( $show_widgets ) ) {
1385 $show_widgets = array();
1386 }
1387
1388 return self::add_export_labels_to_rows(
1389 array(
1390 array(
1391 'label' => esc_html__( 'Timezone', 'mainwp' ),
1392 'value' => static::get_timezone_label(),
1393 ),
1394 array(
1395 'label' => esc_html__( 'Date format', 'mainwp' ),
1396 'value' => (string) get_option( 'date_format', $default_setting['date_format'] ),
1397 ),
1398 array(
1399 'label' => esc_html__( 'Time format', 'mainwp' ),
1400 'value' => (string) get_option( 'time_format', $default_setting['time_format'] ),
1401 ),
1402 array(
1403 'label' => esc_html__( 'Sidebar position', 'mainwp' ),
1404 'value' => 0 === (int) $sidebar ? esc_html__( 'Left', 'mainwp' ) : esc_html__( 'Right', 'mainwp' ),
1405 ),
1406 array(
1407 'label' => esc_html__( 'Hide Update Everything', 'mainwp' ),
1408 'value' => static::format_boolean_label( (int) get_option( 'mainwp_hide_update_everything', $default_setting['mainwp_hide_update_everything'] ) ),
1409 ),
1410 array(
1411 'label' => esc_html__( 'Dashboard widgets shown', 'mainwp' ),
1412 'value' => sprintf(
1413 /* translators: %d: visible widget count */
1414 esc_html__( '%d visible', 'mainwp' ),
1415 count( $show_widgets )
1416 ),
1417 ),
1418 array(
1419 'label' => esc_html__( 'WP Core advanced automatic updates', 'mainwp' ),
1420 'value' => static::get_trusted_update_mode_label( get_option( 'mainwp_automaticDailyUpdate', $default_setting['mainwp_automaticDailyUpdate'] ) ),
1421 ),
1422 array(
1423 'label' => esc_html__( 'Plugin advanced automatic updates', 'mainwp' ),
1424 'value' => static::get_trusted_update_mode_label( get_option( 'mainwp_pluginAutomaticDailyUpdate', $default_setting['mainwp_pluginAutomaticDailyUpdate'] ) ),
1425 ),
1426 array(
1427 'label' => esc_html__( 'Theme advanced automatic updates', 'mainwp' ),
1428 'value' => static::get_trusted_update_mode_label( get_option( 'mainwp_themeAutomaticDailyUpdate', $default_setting['mainwp_themeAutomaticDailyUpdate'] ) ),
1429 ),
1430 array(
1431 'label' => esc_html__( 'Translation advanced automatic updates', 'mainwp' ),
1432 'value' => static::get_trusted_update_mode_label( get_option( 'mainwp_transAutomaticDailyUpdate', 0 ) ),
1433 ),
1434 array(
1435 'label' => esc_html__( 'Automatic updates frequency', 'mainwp' ),
1436 'value' => ucfirst( (string) $frequency_auto_update ),
1437 ),
1438 array(
1439 'label' => esc_html__( 'Automatic updates time', 'mainwp' ),
1440 'value' => (string) $time_auto_update,
1441 ),
1442 array(
1443 'label' => esc_html__( 'Automatic updates day', 'mainwp' ),
1444 'value' => static::get_automatic_updates_day_label( $frequency_auto_update ),
1445 ),
1446 array(
1447 'label' => esc_html__( 'Advanced automatic updates delay', 'mainwp' ),
1448 'value' => static::format_delay_label( (int) get_option( 'mainwp_delay_autoupdate', 1 ) ),
1449 ),
1450 array(
1451 'label' => esc_html__( 'Show language updates', 'mainwp' ),
1452 'value' => static::format_boolean_label( (int) get_option( 'mainwp_show_language_updates', $default_setting['mainwp_show_language_updates'] ) ),
1453 ),
1454 array(
1455 'label' => esc_html__( 'Disable update confirmations', 'mainwp' ),
1456 'value' => static::format_boolean_label( (int) get_option( 'mainwp_disable_update_confirmations', $default_setting['mainwp_disable_update_confirmations'] ) ),
1457 ),
1458 array(
1459 'label' => esc_html__( 'After updates HTTP response check', 'mainwp' ),
1460 'value' => static::format_boolean_label( (int) get_option( 'mainwp_check_http_response', $default_setting['mainwp_check_http_response'] ) ),
1461 ),
1462 array(
1463 'label' => esc_html__( 'After updates HTTP response method', 'mainwp' ),
1464 'value' => strtoupper( (string) get_option( 'mainwp_check_http_response_method', $default_setting['mainwp_check_http_response_method'] ) ),
1465 ),
1466 array(
1467 'label' => esc_html__( 'Backup before update', 'mainwp' ),
1468 'value' => static::format_boolean_label( (int) get_option( 'mainwp_backup_before_upgrade', $default_setting['mainwp_backup_before_upgrade'] ) ),
1469 ),
1470 array(
1471 'label' => esc_html__( 'Full backup tolerance before update', 'mainwp' ),
1472 'value' => sprintf(
1473 /* translators: %d: days */
1474 esc_html__( '%d days', 'mainwp' ),
1475 (int) get_option( 'mainwp_backup_before_upgrade_days', $default_setting['mainwp_backup_before_upgrade_days'] )
1476 ),
1477 ),
1478 array(
1479 'label' => esc_html__( 'Abandoned plugins/themes tolerance', 'mainwp' ),
1480 'value' => sprintf(
1481 /* translators: %d: days */
1482 esc_html__( '%d days', 'mainwp' ),
1483 (int) get_option( 'mainwp_numberdays_Outdate_Plugin_Theme', $default_setting['mainwp_numberdays_Outdate_Plugin_Theme'] )
1484 ),
1485 ),
1486 array(
1487 'label' => esc_html__( 'Primary backup system', 'mainwp' ),
1488 'value' => static::get_primary_backup_method_label(),
1489 ),
1490 array(
1491 'label' => esc_html__( 'MainWP legacy backups enabled', 'mainwp' ),
1492 'value' => static::format_boolean_label( (int) get_option( 'mainwp_enableLegacyBackupFeature', 0 ) ),
1493 ),
1494 array(
1495 'label' => esc_html__( 'Backups kept on server', 'mainwp' ),
1496 'value' => (string) ( false === get_option( 'mainwp_backupsOnServer' ) ? 1 : intval( get_option( 'mainwp_backupsOnServer' ) ) ),
1497 ),
1498 array(
1499 'label' => esc_html__( 'Backup to external sources', 'mainwp' ),
1500 'value' => static::format_boolean_label( (int) get_option( 'mainwp_backupOnExternalSources', 0 ) ),
1501 ),
1502 array(
1503 'label' => esc_html__( 'Archive format', 'mainwp' ),
1504 'value' => static::format_archive_format_label( get_option( 'mainwp_archiveFormat', 'tar.gz' ) ),
1505 ),
1506 array(
1507 'label' => esc_html__( 'Auto detect maximum file descriptors on child sites', 'mainwp' ),
1508 'value' => static::format_boolean_label( (int) get_option( 'mainwp_maximumFileDescriptorsAuto', 1 ) ),
1509 ),
1510 array(
1511 'label' => esc_html__( 'Maximum file descriptors fallback value', 'mainwp' ),
1512 'value' => (string) ( false === get_option( 'mainwp_maximumFileDescriptors' ) ? 150 : intval( get_option( 'mainwp_maximumFileDescriptors' ) ) ),
1513 ),
1514 array(
1515 'label' => esc_html__( 'Load files in memory before zipping', 'mainwp' ),
1516 'value' => static::format_boolean_label( (int) get_option( 'mainwp_options_loadFilesBeforeZip', 1 ) ),
1517 ),
1518 array(
1519 'label' => esc_html__( 'Send email when backup fails', 'mainwp' ),
1520 'value' => static::format_boolean_label( (int) get_option( 'mainwp_notificationOnBackupFail', 1 ) ),
1521 ),
1522 array(
1523 'label' => esc_html__( 'Send email when backup starts', 'mainwp' ),
1524 'value' => static::format_boolean_label( (int) get_option( 'mainwp_notificationOnBackupStart', 1 ) ),
1525 ),
1526 array(
1527 'label' => esc_html__( 'Execute backup tasks in chunks', 'mainwp' ),
1528 'value' => static::format_boolean_label( (int) get_option( 'mainwp_chunkedBackupTasks', 1 ) ),
1529 ),
1530 ),
1531 array(
1532 'Timezone',
1533 'Date format',
1534 'Time format',
1535 'Sidebar position',
1536 'Hide Update Everything',
1537 'Dashboard widgets shown',
1538 'WP Core advanced automatic updates',
1539 'Plugin advanced automatic updates',
1540 'Theme advanced automatic updates',
1541 'Translation advanced automatic updates',
1542 'Automatic updates frequency',
1543 'Automatic updates time',
1544 'Automatic updates day',
1545 'Advanced automatic updates delay',
1546 'Show language updates',
1547 'Disable update confirmations',
1548 'After updates HTTP response check',
1549 'After updates HTTP response method',
1550 'Backup before update',
1551 'Full backup tolerance before update',
1552 'Abandoned plugins/themes tolerance',
1553 'Primary backup system',
1554 'MainWP legacy backups enabled',
1555 'Backups kept on server',
1556 'Backup to external sources',
1557 'Archive format',
1558 'Auto detect maximum file descriptors on child sites',
1559 'Maximum file descriptors fallback value',
1560 'Load files in memory before zipping',
1561 'Send email when backup fails',
1562 'Send email when backup starts',
1563 'Execute backup tasks in chunks',
1564 )
1565 );
1566 }
1567
1568 /**
1569 * Get advanced settings rows.
1570 *
1571 * @return array<int,array<string,mixed>>
1572 */
1573 public static function get_advanced_settings_report_rows() {
1574 $default_setting = MainWP_Settings_Indicator::get_defaults_value();
1575 $sign_algs = MainWP_System_Utility::get_open_ssl_sign_algos();
1576 $signature_algo = (int) get_option( 'mainwp_connect_signature_algo', $default_setting['mainwp_connect_signature_algo'] );
1577 $sync_defaults = MainWP_Settings::get_data_sync_default();
1578 $sync_data = get_option( 'mainwp_settings_sync_data', array() );
1579 $sync_data = ! empty( $sync_data ) ? json_decode( (string) $sync_data, true ) : array();
1580 if ( ! is_array( $sync_data ) ) {
1581 $sync_data = array();
1582 }
1583
1584 $enabled_sync = 0;
1585 foreach ( array_keys( $sync_defaults ) as $sync_name ) {
1586 if ( ! isset( $sync_data[ $sync_name ] ) || ! empty( $sync_data[ $sync_name ] ) ) {
1587 ++$enabled_sync;
1588 }
1589 }
1590
1591 return self::add_export_labels_to_rows(
1592 array(
1593 array(
1594 'label' => esc_html__( 'Maximum simultaneous requests', 'mainwp' ),
1595 'value' => (string) ( false === get_option( 'mainwp_maximumRequests' ) ? 4 : intval( get_option( 'mainwp_maximumRequests' ) ) ),
1596 ),
1597 array(
1598 'label' => esc_html__( 'Minimum delay between requests', 'mainwp' ),
1599 'value' => sprintf(
1600 /* translators: %d: milliseconds */
1601 esc_html__( '%d ms', 'mainwp' ),
1602 (int) ( false === get_option( 'mainwp_minimumDelay' ) ? 200 : intval( get_option( 'mainwp_minimumDelay' ) ) )
1603 ),
1604 ),
1605 array(
1606 'label' => esc_html__( 'Maximum simultaneous requests per IP', 'mainwp' ),
1607 'value' => (string) ( false === get_option( 'mainwp_maximumIPRequests' ) ? 1 : intval( get_option( 'mainwp_maximumIPRequests' ) ) ),
1608 ),
1609 array(
1610 'label' => esc_html__( 'Minimum delay between requests to the same IP', 'mainwp' ),
1611 'value' => sprintf(
1612 /* translators: %d: milliseconds */
1613 esc_html__( '%d ms', 'mainwp' ),
1614 (int) ( false === get_option( 'mainwp_minimumIPDelay' ) ? 1000 : intval( get_option( 'mainwp_minimumIPDelay' ) ) )
1615 ),
1616 ),
1617 array(
1618 'label' => esc_html__( 'Maximum simultaneous sync requests', 'mainwp' ),
1619 'value' => (string) ( false === get_option( 'mainwp_maximumSyncRequests' ) ? 8 : intval( get_option( 'mainwp_maximumSyncRequests' ) ) ),
1620 ),
1621 array(
1622 'label' => esc_html__( 'Maximum simultaneous install and update requests', 'mainwp' ),
1623 'value' => (string) ( false === get_option( 'mainwp_maximumInstallUpdateRequests' ) ? 3 : intval( get_option( 'mainwp_maximumInstallUpdateRequests' ) ) ),
1624 ),
1625 array(
1626 'label' => esc_html__( 'Maximum simultaneous uptime monitoring requests', 'mainwp' ),
1627 'value' => (string) ( false === get_option( 'mainwp_maximum_uptime_monitoring_requests' ) ? 10 : intval( get_option( 'mainwp_maximum_uptime_monitoring_requests' ) ) ),
1628 ),
1629 array(
1630 'label' => esc_html__( 'Sites processed per sync batch', 'mainwp' ),
1631 'value' => (string) ( false === get_option( 'mainwp_chunksitesnumber' ) ? 10 : intval( get_option( 'mainwp_chunksitesnumber' ) ) ),
1632 ),
1633 array(
1634 'label' => esc_html__( 'Sync batch sleep interval', 'mainwp' ),
1635 'value' => sprintf(
1636 /* translators: %d: seconds */
1637 esc_html__( '%d seconds', 'mainwp' ),
1638 (int) ( false === get_option( 'mainwp_chunksleepinterval' ) ? 5 : intval( get_option( 'mainwp_chunksleepinterval' ) ) )
1639 ),
1640 ),
1641 array(
1642 'label' => esc_html__( 'Optimize data loading', 'mainwp' ),
1643 'value' => static::format_boolean_label( (int) get_option( 'mainwp_optimize', $default_setting['mainwp_optimize'] ) ),
1644 ),
1645 array(
1646 'label' => esc_html__( 'Browser cache expiration time', 'mainwp' ),
1647 'value' => sprintf(
1648 /* translators: %d: minutes */
1649 esc_html__( '%d minutes', 'mainwp' ),
1650 (int) get_option( 'mainwp_warm_cache_pages_ttl', 10 )
1651 ),
1652 ),
1653 array(
1654 'label' => esc_html__( 'Verify SSL certificate', 'mainwp' ),
1655 'value' => static::format_boolean_label( ( false === get_option( 'mainwp_sslVerifyCertificate' ) ) || 1 === (int) get_option( 'mainwp_sslVerifyCertificate', 1 ) ),
1656 ),
1657 array(
1658 'label' => esc_html__( 'Verify connection method', 'mainwp' ),
1659 'value' => 2 === (int) get_option( 'mainwp_verify_connection_method', 1 ) ? esc_html__( 'PHPSECLIB (fallback)', 'mainwp' ) : esc_html__( 'OpenSSL (default)', 'mainwp' ),
1660 ),
1661 array(
1662 'label' => esc_html__( 'OpenSSL signature algorithm', 'mainwp' ),
1663 'value' => isset( $sign_algs[ $signature_algo ] ) ? $sign_algs[ $signature_algo ] : (string) $signature_algo,
1664 ),
1665 array(
1666 'label' => esc_html__( 'Force IPv4', 'mainwp' ),
1667 'value' => static::format_boolean_label( (int) get_option( 'mainwp_forceUseIPv4', 0 ) ),
1668 ),
1669 array(
1670 'label' => esc_html__( 'Selected data to sync', 'mainwp' ),
1671 'value' => sprintf(
1672 /* translators: 1: enabled count, 2: total count */
1673 esc_html__( '%1$d of %2$d enabled', 'mainwp' ),
1674 $enabled_sync,
1675 count( $sync_defaults )
1676 ),
1677 ),
1678 ),
1679 array(
1680 'Maximum simultaneous requests',
1681 'Minimum delay between requests',
1682 'Maximum simultaneous requests per IP',
1683 'Minimum delay between requests to the same IP',
1684 'Maximum simultaneous sync requests',
1685 'Maximum simultaneous install and update requests',
1686 'Maximum simultaneous uptime monitoring requests',
1687 'Sites processed per sync batch',
1688 'Sync batch sleep interval',
1689 'Optimize data loading',
1690 'Browser cache expiration time',
1691 'Verify SSL certificate',
1692 'Verify connection method',
1693 'OpenSSL signature algorithm',
1694 'Force IPv4',
1695 'Selected data to sync',
1696 )
1697 );
1698 }
1699
1700 /**
1701 * Get monitoring settings rows.
1702 *
1703 * @return array<int,array<string,mixed>>
1704 */
1705 public static function get_monitoring_settings_report_rows() {
1706 $monitoring_settings = MainWP_Uptime_Monitoring_Handle::get_global_monitoring_settings();
1707 $global_option = get_option( 'mainwp_global_uptime_monitoring_settings', array() );
1708 if ( ! is_array( $global_option ) ) {
1709 $global_option = array();
1710 }
1711
1712 $interval_values = MainWP_Uptime_Monitoring_Edit::get_interval_values( false );
1713 $timeout_values = MainWP_Uptime_Monitoring_Edit::get_timeout_values( false );
1714 $interval_key = $monitoring_settings['interval'] ?? 60;
1715 $timeout_key = $monitoring_settings['timeout'] ?? 60;
1716 $interval_value = isset( $interval_values[ $interval_key ] ) ? $interval_values[ $interval_key ] : $interval_key;
1717 $timeout_value = isset( $timeout_values[ $timeout_key ] ) ? $timeout_values[ $timeout_key ] : $timeout_key;
1718 $retention_days = isset( $global_option['retention_limits'] ) ? intval( $global_option['retention_limits'] ) : 180;
1719 $site_health = empty( get_option( 'mainwp_disableSitesHealthMonitoring', 1 ) );
1720 $threshold = (int) get_option( 'mainwp_sitehealthThreshold', 80 );
1721
1722 return self::add_export_labels_to_rows(
1723 array(
1724 array(
1725 'label' => esc_html__( 'Enable uptime monitoring', 'mainwp' ),
1726 'value' => static::format_boolean_label( ! empty( $monitoring_settings['active'] ) ),
1727 ),
1728 array(
1729 'label' => esc_html__( 'Monitor type', 'mainwp' ),
1730 'value' => static::format_monitor_type_label( $monitoring_settings['type'] ?? 'http' ),
1731 ),
1732 array(
1733 'label' => esc_html__( 'Method', 'mainwp' ),
1734 'value' => strtoupper( (string) ( $monitoring_settings['method'] ?? 'get' ) ),
1735 ),
1736 array(
1737 'label' => esc_html__( 'Interval', 'mainwp' ),
1738 'value' => (string) $interval_value,
1739 ),
1740 array(
1741 'label' => esc_html__( 'Timeout', 'mainwp' ),
1742 'value' => (string) $timeout_value,
1743 ),
1744 array(
1745 'label' => esc_html__( 'Up HTTP codes', 'mainwp' ),
1746 'value' => ! empty( $monitoring_settings['up_status_codes'] ) ? (string) $monitoring_settings['up_status_codes'] : esc_html__( 'Default', 'mainwp' ),
1747 ),
1748 array(
1749 'label' => esc_html__( 'Down confirmation check', 'mainwp' ),
1750 'value' => ! empty( $monitoring_settings['maxretries'] ) ? esc_html__( 'Enabled', 'mainwp' ) : esc_html__( 'Disabled', 'mainwp' ),
1751 ),
1752 array(
1753 'label' => esc_html__( 'Keyword monitoring value', 'mainwp' ),
1754 'value' => ! empty( $monitoring_settings['keyword'] ) ? (string) $monitoring_settings['keyword'] : esc_html__( 'Not configured', 'mainwp' ),
1755 ),
1756 array(
1757 'label' => esc_html__( 'Monitoring data retention', 'mainwp' ),
1758 'value' => static::format_retention_days_label( $retention_days ),
1759 ),
1760 array(
1761 'label' => esc_html__( 'Enable site health monitoring', 'mainwp' ),
1762 'value' => static::format_boolean_label( $site_health ),
1763 ),
1764 array(
1765 'label' => esc_html__( 'Site Health threshold', 'mainwp' ),
1766 'value' => 100 === $threshold ? esc_html__( 'Good', 'mainwp' ) : esc_html__( 'Should be improved', 'mainwp' ),
1767 ),
1768 ),
1769 array(
1770 'Enable uptime monitoring',
1771 'Monitor type',
1772 'Method',
1773 'Interval',
1774 'Timeout',
1775 'Up HTTP codes',
1776 'Down confirmation check',
1777 'Keyword monitoring value',
1778 'Monitoring data retention',
1779 'Enable site health monitoring',
1780 'Site Health threshold',
1781 )
1782 );
1783 }
1784
1785 /**
1786 * Get email settings rows.
1787 *
1788 * @return array<int,array<string,mixed>>
1789 */
1790 public static function get_email_settings_report_rows() {
1791 $rows = array();
1792 $types = MainWP_Notification_Settings::get_notification_types();
1793
1794 foreach ( $types as $type => $label ) {
1795 $settings = MainWP_Notification_Settings::get_general_email_settings( $type );
1796 $recipients = isset( $settings['recipients'] ) ? trim( (string) $settings['recipients'] ) : '';
1797 $recipient_count = static::count_recipients( $recipients );
1798 $subject_config = ! empty( $settings['subject'] ) ? esc_html__( 'Subject set', 'mainwp' ) : esc_html__( 'Subject empty', 'mainwp' );
1799 $heading_config = ! empty( $settings['heading'] ) ? esc_html__( 'Heading set', 'mainwp' ) : esc_html__( 'Heading empty', 'mainwp' );
1800 $enabled_disabled = empty( $settings['disable'] ) ? esc_html__( 'Enabled', 'mainwp' ) : esc_html__( 'Disabled', 'mainwp' );
1801
1802 $value = sprintf(
1803 /* translators: 1: enabled state, 2: recipients count, 3: subject state, 4: heading state */
1804 esc_html__( '%1$s | %2$d recipient(s) | %3$s | %4$s', 'mainwp' ),
1805 $enabled_disabled,
1806 $recipient_count,
1807 $subject_config,
1808 $heading_config
1809 );
1810
1811 $rows[] = array(
1812 'label' => $label,
1813 'export_label' => self::get_notification_type_export_label( $type, $label ),
1814 'value' => $value,
1815 );
1816 }
1817
1818 return $rows;
1819 }
1820
1821 /**
1822 * Get cost tracker rows.
1823 *
1824 * @return array<int,array<string,mixed>>
1825 */
1826 public static function get_cost_tracker_report_rows() {
1827 if ( ! class_exists( '\MainWP\Dashboard\Module\CostTracker\Cost_Tracker_Utility' ) || ! class_exists( '\MainWP\Dashboard\Module\CostTracker\Cost_Tracker_Admin' ) ) {
1828 return array();
1829 }
1830
1831 $selected_currency = \MainWP\Dashboard\Module\CostTracker\Cost_Tracker_Utility::get_instance()->get_option( 'currency', 'USD' );
1832 $currency_format = \MainWP\Dashboard\Module\CostTracker\Cost_Tracker_Utility::get_instance()->get_option( 'currency_format', array() );
1833 $currency_format = array_merge( \MainWP\Dashboard\Module\CostTracker\Cost_Tracker_Utility::default_currency_settings(), is_array( $currency_format ) ? $currency_format : array() );
1834 $custom_payment_methods = \MainWP\Dashboard\Module\CostTracker\Cost_Tracker_Utility::get_instance()->get_option( 'custom_payment_methods', array(), true );
1835 $product_types = \MainWP\Dashboard\Module\CostTracker\Cost_Tracker_Admin::get_product_type_icons();
1836
1837 if ( ! is_array( $custom_payment_methods ) ) {
1838 $custom_payment_methods = array();
1839 }
1840 if ( ! is_array( $product_types ) ) {
1841 $product_types = array();
1842 }
1843
1844 return self::add_export_labels_to_rows(
1845 array(
1846 array(
1847 'label' => esc_html__( 'Currency', 'mainwp' ),
1848 'value' => (string) $selected_currency,
1849 ),
1850 array(
1851 'label' => esc_html__( 'Currency position', 'mainwp' ),
1852 'value' => (string) $currency_format['currency_position'],
1853 ),
1854 array(
1855 'label' => esc_html__( 'Thousand separator', 'mainwp' ),
1856 'value' => '' === (string) $currency_format['thousand_separator'] ? esc_html__( 'None', 'mainwp' ) : (string) $currency_format['thousand_separator'],
1857 ),
1858 array(
1859 'label' => esc_html__( 'Decimal separator', 'mainwp' ),
1860 'value' => (string) $currency_format['decimal_separator'],
1861 ),
1862 array(
1863 'label' => esc_html__( 'Decimals', 'mainwp' ),
1864 'value' => (string) intval( $currency_format['decimals'] ),
1865 ),
1866 array(
1867 'label' => esc_html__( 'Product categories', 'mainwp' ),
1868 'value' => sprintf(
1869 /* translators: %d: count */
1870 esc_html__( '%d configured', 'mainwp' ),
1871 count( $product_types )
1872 ),
1873 ),
1874 array(
1875 'label' => esc_html__( 'Payment methods', 'mainwp' ),
1876 'value' => sprintf(
1877 /* translators: %d: count */
1878 esc_html__( '%d configured', 'mainwp' ),
1879 count( $custom_payment_methods )
1880 ),
1881 ),
1882 ),
1883 array(
1884 'Currency',
1885 'Currency position',
1886 'Thousand separator',
1887 'Decimal separator',
1888 'Decimals',
1889 'Product categories',
1890 'Payment methods',
1891 )
1892 );
1893 }
1894
1895 /**
1896 * Get insights rows.
1897 *
1898 * @return array<int,array<string,mixed>>
1899 */
1900 public static function get_insights_report_rows() {
1901 $options = get_option( 'mainwp_module_log_settings', array() );
1902 if ( ! is_array( $options ) ) {
1903 $options = array();
1904 }
1905
1906 $dashboard_disabled = 0;
1907 $child_disabled = 0;
1908 $changes_disabled = 0;
1909
1910 if ( class_exists( '\MainWP\Dashboard\Module\Log\Log_Settings' ) ) {
1911 $dashboard_disabled = count( \MainWP\Dashboard\Module\Log\Log_Settings::get_disabled_logs_type( 'dashboard' ) );
1912 $child_disabled = count( \MainWP\Dashboard\Module\Log\Log_Settings::get_disabled_logs_type( 'nonmainwpchanges' ) );
1913 $changes_disabled = count( \MainWP\Dashboard\Module\Log\Log_Settings::get_disabled_logs_type( 'changeslogs' ) );
1914 }
1915
1916 return self::add_export_labels_to_rows(
1917 array(
1918 array(
1919 'label' => esc_html__( 'Enable Network Activity logging', 'mainwp' ),
1920 'value' => static::format_boolean_label( ! empty( $options['enabled'] ) ),
1921 ),
1922 array(
1923 'label' => esc_html__( 'Automatically archive logs', 'mainwp' ),
1924 'value' => static::format_boolean_label( ! empty( $options['auto_archive'] ) ),
1925 ),
1926 array(
1927 'label' => esc_html__( 'Data retention period', 'mainwp' ),
1928 'value' => static::format_log_retention_label( isset( $options['records_logs_ttl'] ) ? intval( $options['records_logs_ttl'] ) : 3 * YEAR_IN_SECONDS ),
1929 ),
1930 array(
1931 'label' => esc_html__( 'Child-site Network Activity retention', 'mainwp' ),
1932 'value' => static::format_retention_days_label( isset( $options['child_logs_ttl'] ) ? intval( $options['child_logs_ttl'] ) : 7 ),
1933 ),
1934 array(
1935 'label' => esc_html__( 'Disabled dashboard event types', 'mainwp' ),
1936 'value' => (string) $dashboard_disabled,
1937 ),
1938 array(
1939 'label' => esc_html__( 'Disabled child-site event types', 'mainwp' ),
1940 'value' => (string) $child_disabled,
1941 ),
1942 array(
1943 'label' => esc_html__( 'Disabled change-log event types', 'mainwp' ),
1944 'value' => (string) $changes_disabled,
1945 ),
1946 ),
1947 array(
1948 'Enable Network Activity logging',
1949 'Automatically archive logs',
1950 'Data retention period',
1951 'Child-site Network Activity retention',
1952 'Disabled dashboard event types',
1953 'Disabled child-site event types',
1954 'Disabled change-log event types',
1955 )
1956 );
1957 }
1958
1959 /**
1960 * Get API backups rows.
1961 *
1962 * @return array<int,array<string,mixed>>
1963 */
1964 public static function get_api_backups_report_rows() {
1965 if ( ! class_exists( '\MainWP\Dashboard\Module\ApiBackups\Api_Backups_3rd_Party' ) ) {
1966 return array();
1967 }
1968
1969 $definitions = array(
1970 'cloudways' => array(
1971 'label' => 'Cloudways',
1972 'enabled_option' => 'mainwp_enable_cloudways_api',
1973 'options' => array( 'mainwp_cloudways_api_account_email' ),
1974 'secrets' => array( array( '\MainWP\Dashboard\Module\ApiBackups\Api_Backups_3rd_Party', 'get_cloudways_api_key' ) ),
1975 ),
1976 'gridpane' => array(
1977 'label' => 'GridPane',
1978 'enabled_option' => 'mainwp_enable_gridpane_api',
1979 'options' => array(),
1980 'secrets' => array( array( '\MainWP\Dashboard\Module\ApiBackups\Api_Backups_3rd_Party', 'get_gridpane_api_key' ) ),
1981 ),
1982 'vultr' => array(
1983 'label' => 'Vultr',
1984 'enabled_option' => 'mainwp_enable_vultr_api',
1985 'options' => array(),
1986 'secrets' => array( array( '\MainWP\Dashboard\Module\ApiBackups\Api_Backups_3rd_Party', 'get_vultr_api_key' ) ),
1987 ),
1988 'linode' => array(
1989 'label' => 'Akamai (Linode)',
1990 'enabled_option' => 'mainwp_enable_linode_api',
1991 'options' => array(),
1992 'secrets' => array( array( '\MainWP\Dashboard\Module\ApiBackups\Api_Backups_3rd_Party', 'get_linode_api_key' ) ),
1993 ),
1994 'digitalocean' => array(
1995 'label' => 'DigitalOcean',
1996 'enabled_option' => 'mainwp_enable_digitalocean_api',
1997 'options' => array(),
1998 'secrets' => array( array( '\MainWP\Dashboard\Module\ApiBackups\Api_Backups_3rd_Party', 'get_digitalocean_api_key' ) ),
1999 ),
2000 'cpanel' => array(
2001 'label' => 'cPanel (WP Toolkit)',
2002 'enabled_option' => 'mainwp_enable_cpanel_api',
2003 'options' => array( 'mainwp_cpanel_url', 'mainwp_cpanel_site_path', 'mainwp_cpanel_account_username' ),
2004 'secrets' => array(),
2005 ),
2006 'plesk' => array(
2007 'label' => 'Plesk',
2008 'enabled_option' => 'mainwp_enable_plesk_api',
2009 'options' => array( 'mainwp_plesk_api_url' ),
2010 'secrets' => array( array( '\MainWP\Dashboard\Module\ApiBackups\Api_Backups_3rd_Party', 'get_plesk_api_key' ) ),
2011 ),
2012 'kinsta' => array(
2013 'label' => 'Kinsta',
2014 'enabled_option' => 'mainwp_enable_kinsta_api',
2015 'options' => array( 'mainwp_kinsta_api_account_email', 'mainwp_kinsta_company_id' ),
2016 'secrets' => array( array( '\MainWP\Dashboard\Module\ApiBackups\Api_Backups_3rd_Party', 'get_kinsta_api_key' ) ),
2017 ),
2018 );
2019
2020 $rows = array();
2021
2022 foreach ( $definitions as $provider ) {
2023 $enabled = ! empty( get_option( $provider['enabled_option'], 0 ) );
2024 $details = array();
2025
2026 foreach ( $provider['options'] as $option_name ) {
2027 if ( '' !== trim( (string) get_option( $option_name, '' ) ) ) {
2028 $details[] = esc_html__( 'profile configured', 'mainwp' );
2029 break;
2030 }
2031 }
2032
2033 foreach ( $provider['secrets'] as $secret_callback ) {
2034 $secret = call_user_func( $secret_callback );
2035 if ( ! empty( $secret ) ) {
2036 $details[] = esc_html__( 'secret configured', 'mainwp' );
2037 break;
2038 }
2039 }
2040
2041 $summary = $enabled ? esc_html__( 'Enabled', 'mainwp' ) : esc_html__( 'Disabled', 'mainwp' );
2042 if ( ! empty( $details ) ) {
2043 $summary .= ' | ' . implode( ', ', array_unique( $details ) );
2044 }
2045
2046 $rows[] = array(
2047 'label' => $provider['label'],
2048 'value' => $summary,
2049 );
2050 }
2051
2052 return $rows;
2053 }
2054
2055 /**
2056 * Get tools rows.
2057 *
2058 * @return array<int,array<string,mixed>>
2059 */
2060 public static function get_tools_report_rows() {
2061 return self::add_export_labels_to_rows(
2062 array(
2063 array(
2064 'label' => esc_html__( 'Current MainWP theme', 'mainwp' ),
2065 'value' => MainWP_Settings::get_instance()->get_current_user_theme(),
2066 ),
2067 array(
2068 'label' => esc_html__( 'Guided tours', 'mainwp' ),
2069 'value' => static::format_boolean_label( (int) get_option( 'mainwp_enable_guided_tours', 0 ) ),
2070 ),
2071 array(
2072 'label' => esc_html__( 'Chatbase', 'mainwp' ),
2073 'value' => static::format_boolean_label( (int) get_option( 'mainwp_enable_guided_chatbase', 0 ) ),
2074 ),
2075 array(
2076 'label' => esc_html__( 'Guided video', 'mainwp' ),
2077 'value' => static::format_boolean_label( (int) get_option( 'mainwp_enable_guided_video', 0 ) ),
2078 ),
2079 ),
2080 array(
2081 'Current MainWP theme',
2082 'Guided tours',
2083 'Chatbase',
2084 'Guided video',
2085 )
2086 );
2087 }
2088
2089 /**
2090 * Get debug rows.
2091 *
2092 * @return array<int,array<string,mixed>>
2093 */
2094 public static function get_debug_report_rows() {
2095 $error_log_path = ini_get( 'error_log' );
2096 $log_readable = ! empty( $error_log_path ) && file_exists( $error_log_path ) ? is_readable( $error_log_path ) : false;
2097
2098 return self::add_export_labels_to_rows(
2099 array(
2100 array(
2101 'label' => esc_html__( 'WP_DEBUG', 'mainwp' ),
2102 'value' => static::format_boolean_label( defined( 'WP_DEBUG' ) && WP_DEBUG ),
2103 ),
2104 array(
2105 'label' => esc_html__( 'WP_DEBUG_LOG', 'mainwp' ),
2106 'value' => static::format_boolean_label( defined( 'WP_DEBUG_LOG' ) && WP_DEBUG_LOG ),
2107 ),
2108 array(
2109 'label' => esc_html__( 'WP_DEBUG_DISPLAY', 'mainwp' ),
2110 'value' => static::format_boolean_label( defined( 'WP_DEBUG_DISPLAY' ) && WP_DEBUG_DISPLAY ),
2111 ),
2112 array(
2113 'label' => esc_html__( 'PHP log_errors', 'mainwp' ),
2114 'value' => static::format_boolean_label( filter_var( ini_get( 'log_errors' ), FILTER_VALIDATE_BOOLEAN ) ),
2115 ),
2116 array(
2117 'label' => esc_html__( 'PHP error_log path', 'mainwp' ),
2118 'value' => ! empty( $error_log_path ) ? $error_log_path : esc_html__( 'Not set', 'mainwp' ),
2119 'visibility' => 'community_masked',
2120 'community_value' => ! empty( $error_log_path ) ? esc_html__( 'Configured', 'mainwp' ) : esc_html__( 'Not set', 'mainwp' ),
2121 ),
2122 array(
2123 'label' => esc_html__( 'PHP error_log readable', 'mainwp' ),
2124 'value' => static::format_boolean_label( $log_readable ),
2125 ),
2126 ),
2127 array(
2128 'WP_DEBUG',
2129 'WP_DEBUG_LOG',
2130 'WP_DEBUG_DISPLAY',
2131 'PHP log_errors',
2132 'PHP error_log path',
2133 'PHP error_log readable',
2134 )
2135 );
2136 }
2137
2138 /**
2139 * Get conflict signal rows.
2140 *
2141 * @return array<int,array<string,mixed>>
2142 */
2143 public static function get_conflict_signal_report_rows() {
2144 $caching_plugins = static::get_active_plugins_by_keyword_group(
2145 array(
2146 'cache',
2147 'rocket',
2148 'litespeed',
2149 'autoptimize',
2150 'wp-optimize',
2151 'perfmatters',
2152 'flyingpress',
2153 'sg optimizer',
2154 'breeze',
2155 'nitropack',
2156 'hummingbird',
2157 )
2158 );
2159 $security_plugins = static::get_active_plugins_by_keyword_group(
2160 array(
2161 'wordfence',
2162 'sucuri',
2163 'solid security',
2164 'ithemes security',
2165 'all-in-one wp security',
2166 'shield security',
2167 'disable rest api',
2168 'rest api control',
2169 'wp hide',
2170 'cloudflare',
2171 'limit login',
2172 )
2173 );
2174
2175 $maintenance_mode = static::get_maintenance_mode_indicators();
2176 $dropins = static::get_dropin_conflict_indicators();
2177
2178 return self::add_export_labels_to_rows(
2179 array(
2180 array(
2181 'label' => esc_html__( 'Caching / performance plugins', 'mainwp' ),
2182 'value' => static::format_conflict_items_label( $caching_plugins ),
2183 ),
2184 array(
2185 'label' => esc_html__( 'Security / access-control plugins', 'mainwp' ),
2186 'value' => static::format_conflict_items_label( $security_plugins ),
2187 ),
2188 array(
2189 'label' => esc_html__( 'Maintenance mode indicators', 'mainwp' ),
2190 'value' => static::format_conflict_items_label( $maintenance_mode ),
2191 'status' => empty( $maintenance_mode ) ? '' : 'warning',
2192 ),
2193 array(
2194 'label' => esc_html__( 'Drop-ins / object cache', 'mainwp' ),
2195 'value' => static::format_conflict_items_label( $dropins ),
2196 ),
2197 ),
2198 array(
2199 'Caching / performance plugins',
2200 'Security / access-control plugins',
2201 'Maintenance mode indicators',
2202 'Drop-ins / object cache',
2203 )
2204 );
2205 }
2206
2207
2208 /**
2209 * Get database rows.
2210 *
2211 * @return array<int,array<string,mixed>>
2212 */
2213 public static function get_database_report_rows() { // phpcs:ignore -- NOSONAR - complex function.
2214
2215 $db_info = MainWP_Database_Schema_Checker::get_database_info();
2216
2217 $database_size = isset( $db_info['database_size'] ) ? $db_info['database_size'] : array();
2218
2219 $data_size = isset( $database_size['data'] ) ? $database_size['data'] : 0;
2220 $index_size = isset( $database_size['index'] ) ? $database_size['index'] : 0;
2221
2222 $db_privileges_info = MainWP_Database_Schema_Checker::get_database_privileges();
2223
2224 $db_privileges = ! empty( $db_privileges_info['database_grants'] ) && is_array( $db_privileges_info['database_grants'] ) ? implode( ', ', $db_privileges_info['database_grants'] ) . '.' : '';
2225
2226 $db_privileges_status = 'pass';
2227 if ( ! empty( $db_privileges_info['database_missing_privileges'] ) && is_array( $db_privileges_info['database_missing_privileges'] ) ) {
2228 $db_privileges .= ' ' . esc_html__( 'Missing database privileges:', 'mainwp' ) . ' ' . implode( ', ', $db_privileges_info['database_missing_privileges'] );
2229 $db_privileges_status = 'error';
2230 }
2231
2232 $db_rows_info = array(
2233 array(
2234 'label' => esc_html__( 'MainWP database version', 'mainwp' ),
2235 'value' => $db_info['mainwp_database_version'],
2236 ),
2237 array(
2238 'label' => esc_html__( 'Database prefix', 'mainwp' ),
2239 'value' => $db_info['database_prefix'],
2240 ),
2241 array(
2242 'label' => esc_html__( 'Total Database Size', 'mainwp' ),
2243 'value' => esc_html( sprintf( __( '%sMB', 'mainwp' ), $data_size + $index_size ) ),
2244 ),
2245 array(
2246 'label' => esc_html__( 'Database Data Size', 'mainwp' ),
2247 'value' => esc_html( sprintf( __( '%sMB', 'mainwp' ), $data_size ) ),
2248 ),
2249 array(
2250 'label' => esc_html__( 'Database Index Size', 'mainwp' ),
2251 'value' => esc_html( sprintf( __( '%sMB', 'mainwp' ), $index_size ) ),
2252 ),
2253 array(
2254 'status' => $db_privileges_status,
2255 'label' => esc_html__( 'Database privileges', 'mainwp' ),
2256 'value' => $db_privileges,
2257 ),
2258 );
2259
2260 $db_rows = array();
2261 $db_rows_missing = array();
2262
2263 if ( isset( $db_info['database_tables'] ) && is_array( $db_info['database_tables'] ) ) {
2264
2265 $missing_db_tables = MainWP_Database_Schema_Checker::detect_missing_tables( $db_info['database_tables'] );
2266
2267 if ( is_array( $missing_db_tables ) ) {
2268 foreach ( array( 'core', 'extensions' ) as $type ) {
2269 $miss_tables = isset( $missing_db_tables[ $type ] ) ? $missing_db_tables[ $type ] : array();
2270 if ( ! empty( $miss_tables ) && is_array( $miss_tables ) ) {
2271 if ( 'core' === $type ) {
2272 foreach ( $miss_tables as $tb_name ) {
2273 $db_rows_missing[] = array(
2274 'label' => $tb_name,
2275 'value' => esc_html__( 'Missing core table', 'mainwp' ),
2276 'status' => 'error',
2277 );
2278 }
2279 } else {
2280 foreach ( $miss_tables as $ext_slug => $miss_ext_tables ) {
2281 $title = MainWP_Database_Schema_Checker::get_loaded_extension_title( $ext_slug );
2282 foreach ( $miss_ext_tables as $tb_name ) {
2283 $db_rows_missing[] = array(
2284 'label' => $tb_name,
2285 'value' => sprintf( esc_html__( 'Missing extension table: %1s', 'mainwp' ), $title ),
2286 'status' => 'error',
2287 );
2288 }
2289 }
2290 }
2291 }
2292 }
2293 }
2294
2295 foreach ( array( 'core', 'other' ) as $type ) {
2296 $type_tables = isset( $db_info['database_tables'][ $type ] ) ? $db_info['database_tables'][ $type ] : array();
2297 if ( is_array( $type_tables ) ) {
2298 foreach ( $type_tables as $tb_name => $info ) {
2299
2300 if ( empty( $info ) ) {
2301 continue; // Missing table, so skip column detection.
2302 }
2303
2304 $status = 'pass';
2305
2306 $detect_cols_issues = array();
2307
2308 /**
2309 * Filter to disable detection of missing table columns. Useful for slow hosts.
2310 *
2311 * @since 6.1.3.
2312 */
2313 if ( apply_filters( 'mainwp_detect_table_column_issues', true ) ) {
2314 $detect_cols_issues = MainWP_Database_Schema_Checker::detect_table_columns_issues( $tb_name, $type );
2315 }
2316
2317 $missing_cols = is_array( $detect_cols_issues ) && isset( $detect_cols_issues['missing_columns'] ) ? $detect_cols_issues['missing_columns'] : array();
2318 $invalid_cols = is_array( $detect_cols_issues ) && isset( $detect_cols_issues['invalid_columns'] ) ? $detect_cols_issues['invalid_columns'] : array();
2319
2320 $issues_cols_info = array();
2321
2322 if ( ! empty( $missing_cols ) && is_array( $missing_cols ) ) {
2323 $issues_cols_info[] = sprintf( esc_html__( 'Missing columns: %1s;', 'mainwp' ), implode( ', ', $missing_cols ) );
2324 $status = 'error';
2325 }
2326
2327 if ( ! empty( $invalid_cols ) && is_array( $invalid_cols ) && isset( $invalid_cols[0]['column'] ) ) {
2328
2329 $issues_string = implode(
2330 '; ',
2331 array_map(
2332 static function ( $issue ) {
2333 return sprintf(
2334 'column: "%s" - expected: "%s" - actual: "%s"',
2335 $issue['column'],
2336 $issue['expected'],
2337 $issue['actual']
2338 );
2339 },
2340 $invalid_cols
2341 )
2342 );
2343
2344 $issues_cols_info[] = sprintf(
2345 esc_html__( 'Incorrect column definitions found: %s;', 'mainwp' ),
2346 $issues_string
2347 );
2348
2349 if ( 'pass' === $status ) {
2350 $status = 'error'; // warning - incorrect column definition.
2351 }
2352 }
2353
2354 $tbl_info = '';
2355 if ( is_array( $info ) && isset( $info['data'] ) ) {
2356 $tbl_info = sprintf( __( 'Data: %sMB + Index: %sMB + Engine %s', 'mainwp' ), $info['data'], $info['index'], $info['engine'] );
2357 }
2358
2359 $db_rows[] = array(
2360 'label' => esc_html( $tb_name ),
2361 'value' => esc_html(
2362 $tbl_info . ( ! empty( $issues_cols_info ) ? ' (' . implode( '; ', $issues_cols_info ) . ') ' : '' ),
2363 ),
2364 'status' => $status,
2365 );
2366
2367 }
2368 }
2369 }
2370
2371 MainWP_Database_Schema_Checker::prepare_db_and_tables_issues( $missing_db_tables );
2372 }
2373
2374 return self::add_export_labels_to_rows(
2375 array_merge( $db_rows_info, $db_rows_missing, $db_rows ),
2376 array(
2377 'Database',
2378 'Database privileges',
2379 'MainWP database version',
2380 'Database prefix',
2381 'Total Database Size',
2382 'Database Data Size',
2383 'Database Index Size',
2384 'Missing core table',
2385 )
2386 );
2387 }
2388
2389
2390 /**
2391 * Format boolean label.
2392 *
2393 * @param mixed $value True-ish value.
2394 *
2395 * @return string
2396 */
2397 private static function format_boolean_label( $value ) {
2398 return ! empty( $value ) ? esc_html__( 'Yes', 'mainwp' ) : esc_html__( 'No', 'mainwp' );
2399 }
2400
2401 /**
2402 * Get timezone label.
2403 *
2404 * @return string
2405 */
2406 private static function get_timezone_label() {
2407 $timezone = wp_timezone_string();
2408 if ( ! empty( $timezone ) ) {
2409 return $timezone;
2410 }
2411
2412 $gmt_offset = (float) get_option( 'gmt_offset', 0 );
2413 $tz_sign = $gmt_offset >= 0 ? '+' : '-';
2414 $tz_value = (string) abs( $gmt_offset );
2415
2416 return sprintf( 'UTC%s%s', $tz_sign, $tz_value );
2417 }
2418
2419 /**
2420 * Get trusted update mode label.
2421 *
2422 * @param mixed $value Setting value.
2423 *
2424 * @return string
2425 */
2426 private static function get_trusted_update_mode_label( $value ) {
2427 return 1 === (int) $value ? esc_html__( 'Install Trusted Updates', 'mainwp' ) : esc_html__( 'Disabled', 'mainwp' );
2428 }
2429
2430 /**
2431 * Get archive format label.
2432 *
2433 * @param mixed $format Archive format.
2434 *
2435 * @return string
2436 */
2437 private static function format_archive_format_label( $format ) {
2438 $format = empty( $format ) ? 'tar.gz' : (string) $format;
2439 return $format;
2440 }
2441
2442 /**
2443 * Get delay label.
2444 *
2445 * @param int $days Days.
2446 *
2447 * @return string
2448 */
2449 private static function format_delay_label( $days ) {
2450 if ( $days <= 0 ) {
2451 return esc_html__( 'Delay off', 'mainwp' );
2452 }
2453
2454 return sprintf(
2455 /* translators: %d: day count */
2456 _n( '%d day', '%d days', $days, 'mainwp' ),
2457 $days
2458 );
2459 }
2460
2461 /**
2462 * Get automatic update day label.
2463 *
2464 * @param string $frequency Frequency.
2465 *
2466 * @return string
2467 */
2468 private static function get_automatic_updates_day_label( $frequency ) {
2469 switch ( $frequency ) {
2470 case 'weekly':
2471 $days = array(
2472 0 => esc_html__( 'Mon', 'mainwp' ),
2473 1 => esc_html__( 'Tue', 'mainwp' ),
2474 2 => esc_html__( 'Wed', 'mainwp' ),
2475 3 => esc_html__( 'Thu', 'mainwp' ),
2476 4 => esc_html__( 'Fri', 'mainwp' ),
2477 5 => esc_html__( 'Sat', 'mainwp' ),
2478 6 => esc_html__( 'Sun', 'mainwp' ),
2479 );
2480 $day = (int) get_option( 'mainwp_dayinweek_AutoUpdate', 0 );
2481 return isset( $days[ $day ] ) ? $days[ $day ] : esc_html__( 'Mon', 'mainwp' );
2482 case 'monthly':
2483 return sprintf(
2484 /* translators: %d: day of month */
2485 esc_html__( 'Day %d of the month', 'mainwp' ),
2486 (int) get_option( 'mainwp_dayinmonth_AutoUpdate', 1 )
2487 );
2488 default:
2489 return esc_html__( 'Every day', 'mainwp' );
2490 }
2491 }
2492
2493 /**
2494 * Get automatic updates schedule label.
2495 *
2496 * @return string
2497 */
2498 private static function get_automatic_updates_schedule_label() {
2499 $frequency = (string) get_option( 'mainwp_frequency_AutoUpdate', 'daily' );
2500 $time = (string) get_option( 'mainwp_time_AutoUpdate', '00:00' );
2501 if ( empty( $time ) ) {
2502 $time = '00:00';
2503 }
2504
2505 if ( 'weekly' === $frequency ) {
2506 return sprintf(
2507 /* translators: 1: day label, 2: time */
2508 esc_html__( 'Weekly on %1$s at %2$s', 'mainwp' ),
2509 static::get_automatic_updates_day_label( 'weekly' ),
2510 $time
2511 );
2512 }
2513
2514 if ( 'monthly' === $frequency ) {
2515 return sprintf(
2516 /* translators: 1: day label, 2: time */
2517 esc_html__( 'Monthly on %1$s at %2$s', 'mainwp' ),
2518 static::get_automatic_updates_day_label( 'monthly' ),
2519 $time
2520 );
2521 }
2522
2523 return sprintf(
2524 /* translators: %s: time */
2525 esc_html__( 'Daily at %s', 'mainwp' ),
2526 $time
2527 );
2528 }
2529
2530 /**
2531 * Count recipients.
2532 *
2533 * @param string $recipients Recipients string.
2534 *
2535 * @return int
2536 */
2537 private static function count_recipients( $recipients ) {
2538 if ( empty( $recipients ) ) {
2539 return 0;
2540 }
2541
2542 $emails = preg_split( '/\s*,\s*/', trim( $recipients ) );
2543 $emails = array_filter( (array) $emails );
2544
2545 return count( $emails );
2546 }
2547
2548 /**
2549 * Get public dashboard IP data.
2550 *
2551 * @return array<string,string>
2552 */
2553 private static function get_public_dashboard_ip_data() {
2554 $server_ip = static::get_server_ip_value();
2555
2556 if ( static::is_public_ip_address( $server_ip ) ) {
2557 return array(
2558 'value' => $server_ip,
2559 'status' => 'pass',
2560 'community_value' => esc_html__( 'Detected', 'mainwp' ),
2561 );
2562 }
2563
2564 $cached_data = get_transient( 'mainwp_public_dashboard_ip_data' );
2565 if ( is_array( $cached_data ) && isset( $cached_data['value'], $cached_data['status'], $cached_data['community_value'] ) ) {
2566 return $cached_data;
2567 }
2568
2569 $response = wp_safe_remote_get(
2570 'https://api.ipify.org?format=json',
2571 array(
2572 'timeout' => 3,
2573 'sslverify' => true,
2574 )
2575 );
2576
2577 if ( ! is_wp_error( $response ) ) {
2578 $response_code = (int) wp_remote_retrieve_response_code( $response );
2579 $body = json_decode( (string) wp_remote_retrieve_body( $response ), true );
2580 $public_ip = is_array( $body ) && isset( $body['ip'] ) ? trim( (string) $body['ip'] ) : '';
2581
2582 if ( $response_code >= 200 && $response_code < 300 && static::is_public_ip_address( $public_ip ) ) {
2583 $data = array(
2584 'value' => $public_ip,
2585 'status' => 'pass',
2586 'community_value' => esc_html__( 'Detected', 'mainwp' ),
2587 );
2588 set_transient( 'mainwp_public_dashboard_ip_data', $data, 12 * HOUR_IN_SECONDS );
2589
2590 return $data;
2591 }
2592 }
2593
2594 $data = array(
2595 'value' => esc_html__( 'Unavailable. Contact your host if the Server IP is local or private.', 'mainwp' ),
2596 'status' => 'warning',
2597 'community_value' => esc_html__( 'Unavailable', 'mainwp' ),
2598 );
2599 set_transient( 'mainwp_public_dashboard_ip_data', $data, HOUR_IN_SECONDS );
2600
2601 return $data;
2602 }
2603
2604 /**
2605 * Get server IP value.
2606 *
2607 * @return string
2608 */
2609 private static function get_server_ip_value() {
2610 return isset( $_SERVER['SERVER_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['SERVER_ADDR'] ) ) : '';
2611 }
2612
2613 /**
2614 * Check if IP address is public.
2615 *
2616 * @param string $ip_address IP address.
2617 *
2618 * @return bool
2619 */
2620 private static function is_public_ip_address( $ip_address ) {
2621 return ! empty( $ip_address ) && false !== filter_var( $ip_address, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE );
2622 }
2623
2624 /**
2625 * Get active plugins matching a keyword group.
2626 *
2627 * @param array<int,string> $keywords Keywords.
2628 *
2629 * @return array<int,string>
2630 */
2631 private static function get_active_plugins_by_keyword_group( $keywords ) {
2632 $matches = array();
2633 $plugins = get_plugins();
2634
2635 foreach ( $plugins as $slug => $plugin ) {
2636 if ( ! is_plugin_active( $slug ) ) {
2637 continue;
2638 }
2639
2640 $plugin_name = isset( $plugin['Name'] ) ? (string) $plugin['Name'] : '';
2641 $haystack = strtolower( $slug . ' ' . $plugin_name );
2642
2643 if ( false !== strpos( $haystack, 'mainwp' ) ) {
2644 continue;
2645 }
2646
2647 foreach ( $keywords as $keyword ) {
2648 if ( false !== strpos( $haystack, strtolower( $keyword ) ) ) {
2649 $matches[] = ! empty( $plugin_name ) ? $plugin_name : $slug;
2650 break;
2651 }
2652 }
2653 }
2654
2655 return array_values( array_unique( $matches ) );
2656 }
2657
2658 /**
2659 * Get maintenance mode indicators.
2660 *
2661 * @return array<int,string>
2662 */
2663 private static function get_maintenance_mode_indicators() {
2664 $indicators = static::get_active_plugins_by_keyword_group(
2665 array(
2666 'maintenance',
2667 'coming soon',
2668 'seedprod',
2669 'lightstart',
2670 )
2671 );
2672
2673 if ( file_exists( ABSPATH . '.maintenance' ) ) {
2674 $indicators[] = esc_html__( '.maintenance file present', 'mainwp' );
2675 }
2676
2677 return array_values( array_unique( $indicators ) );
2678 }
2679
2680 /**
2681 * Get drop-in conflict indicators.
2682 *
2683 * @return array<int,string>
2684 */
2685 private static function get_dropin_conflict_indicators() {
2686 $dropins = array();
2687
2688 if ( function_exists( 'get_dropins' ) ) {
2689 $dropin_files = get_dropins();
2690 if ( is_array( $dropin_files ) ) {
2691 $dropins = array_keys( $dropin_files );
2692 }
2693 }
2694
2695 if ( wp_using_ext_object_cache() && ! in_array( 'object-cache.php', $dropins, true ) ) {
2696 $dropins[] = 'object-cache.php';
2697 }
2698
2699 return array_values( array_unique( $dropins ) );
2700 }
2701
2702 /**
2703 * Format conflict items label.
2704 *
2705 * @param array<int,string> $items Items.
2706 *
2707 * @return string
2708 */
2709 private static function format_conflict_items_label( $items ) {
2710 if ( empty( $items ) ) {
2711 return esc_html__( 'None detected', 'mainwp' );
2712 }
2713
2714 return implode( ', ', $items );
2715 }
2716
2717 /**
2718 * Get permalink structure data.
2719 *
2720 * @return array<string,string>
2721 */
2722 private static function get_permalink_structure_data() {
2723 $structure = (string) get_option( 'permalink_structure', '' );
2724
2725 if ( empty( $structure ) ) {
2726 return array(
2727 'value' => esc_html__( 'Plain', 'mainwp' ),
2728 'status' => 'warning',
2729 );
2730 }
2731
2732 return array(
2733 'value' => $structure,
2734 'status' => 'pass',
2735 );
2736 }
2737
2738 /**
2739 * Get REST API reachability data.
2740 *
2741 * @return array<string,string>
2742 */
2743 private static function get_rest_api_reachability_data() {
2744 static $cached_data = null;
2745 if ( null !== $cached_data ) {
2746 return $cached_data;
2747 }
2748
2749 $url = rest_url();
2750 $response = wp_remote_get(
2751 esc_url_raw( $url ),
2752 array(
2753 'blocking' => true,
2754 'sslverify' => apply_filters( 'https_local_ssl_verify', true ),
2755 'timeout' => 15,
2756 )
2757 );
2758
2759 if ( is_wp_error( $response ) ) {
2760 $cached_data = array(
2761 'value' => sprintf(
2762 /* translators: %s: error message */
2763 esc_html__( 'Request failed: %s', 'mainwp' ),
2764 $response->get_error_message()
2765 ),
2766 'status' => 'error',
2767 'code' => 'request_failed',
2768 );
2769 return $cached_data;
2770 }
2771
2772 $response_code = (int) wp_remote_retrieve_response_code( $response );
2773 $body = wp_remote_retrieve_body( $response );
2774 $data = json_decode( $body, true );
2775
2776 if ( $response_code >= 200 && $response_code < 300 && is_array( $data ) && isset( $data['namespaces'] ) ) {
2777 $cached_data = array(
2778 'value' => sprintf(
2779 /* translators: %d: HTTP status code */
2780 esc_html__( 'Reachable (HTTP %d)', 'mainwp' ),
2781 $response_code
2782 ),
2783 'status' => 'pass',
2784 );
2785 return $cached_data;
2786 }
2787
2788 if ( $response_code >= 200 && $response_code < 300 ) {
2789 $cached_data = array(
2790 'value' => sprintf(
2791 /* translators: %d: HTTP status code */
2792 esc_html__( 'Unexpected non-REST response (HTTP %d)', 'mainwp' ),
2793 $response_code
2794 ),
2795 'status' => 'warning',
2796 );
2797 return $cached_data;
2798 }
2799
2800 if ( 401 === $response_code ) {
2801 $cached_data = array(
2802 'value' => esc_html__( 'Auth challenge detected (HTTP 401)', 'mainwp' ),
2803 'status' => 'error',
2804 );
2805 return $cached_data;
2806 }
2807
2808 if ( 403 === $response_code ) {
2809 $cached_data = array(
2810 'value' => esc_html__( 'Forbidden or blocked (HTTP 403)', 'mainwp' ),
2811 'status' => 'error',
2812 );
2813 return $cached_data;
2814 }
2815
2816 if ( 404 === $response_code ) {
2817 $cached_data = array(
2818 'value' => esc_html__( 'Not found (HTTP 404)', 'mainwp' ),
2819 'status' => 'error',
2820 );
2821 return $cached_data;
2822 }
2823
2824 $cached_data = array(
2825 'value' => sprintf(
2826 /* translators: %d: HTTP status code */
2827 esc_html__( 'Unexpected response (HTTP %d)', 'mainwp' ),
2828 $response_code
2829 ),
2830 'status' => 'warning',
2831 );
2832
2833 return $cached_data;
2834 }
2835
2836 /**
2837 * Get self-connect data.
2838 *
2839 * @return array<string,string>
2840 */
2841 private static function get_server_self_connect_data() {
2842 static $cached_data = null;
2843 if ( null !== $cached_data ) {
2844 return $cached_data;
2845 }
2846
2847 $url = admin_url( 'admin-ajax.php' );
2848
2849 $response = MainWP_System_Utility::test_self_connect( $url );
2850
2851 if ( is_wp_error( $response ) ) {
2852 $cached_data = array(
2853 'value' => sprintf(
2854 /* translators: %s: error message */
2855 esc_html__( 'Request failed: %s', 'mainwp' ),
2856 $response->get_error_message()
2857 ),
2858 'status' => 'error',
2859 );
2860 return $cached_data;
2861 }
2862
2863 $response_code = (int) wp_remote_retrieve_response_code( $response );
2864 if ( 401 === $response_code ) {
2865 $cached_data = array(
2866 'value' => esc_html__( 'Auth challenge detected (HTTP 401)', 'mainwp' ),
2867 'status' => 'error',
2868 'code' => 'auth_challenge',
2869 );
2870 return $cached_data;
2871 }
2872 if ( 403 === $response_code ) {
2873 $cached_data = array(
2874 'value' => esc_html__( 'Forbidden or blocked (HTTP 403)', 'mainwp' ),
2875 'status' => 'error',
2876 'code' => 'forbidden',
2877 );
2878 return $cached_data;
2879 }
2880 if ( $response_code < 200 || $response_code > 204 ) {
2881 $cached_data = array(
2882 'value' => sprintf(
2883 /* translators: %d: HTTP status code */
2884 esc_html__( 'Unexpected response (HTTP %d)', 'mainwp' ),
2885 $response_code
2886 ),
2887 'status' => 'warning',
2888 'code' => 'unexpected_status',
2889 );
2890 return $cached_data;
2891 }
2892
2893 $response_body = wp_remote_retrieve_body( $response );
2894 if ( 'MainWP Self Connect OK' !== trim( $response_body ) ) {
2895 $cached_data = array(
2896 'value' => esc_html__( 'Unexpected response body. Note: This is common and usually not a problem unless WP-Cron or loopback requests are failing.', 'mainwp' ),
2897 'status' => 'warning',
2898 'code' => 'unexpected_body',
2899 );
2900 return $cached_data;
2901 }
2902
2903 $cached_data = array(
2904 'value' => sprintf(
2905 /* translators: %d: HTTP status code */
2906 esc_html__( 'Response test O.K. (HTTP %d)', 'mainwp' ),
2907 $response_code
2908 ),
2909 'status' => 'pass',
2910 'code' => 'pass',
2911 );
2912
2913 return $cached_data;
2914 }
2915
2916 /**
2917 * Get upload directory data.
2918 *
2919 * @return array<string,string>
2920 */
2921 private static function get_mainwp_upload_directory_data() {
2922 $dirs = MainWP_System_Utility::get_mainwp_dir();
2923 $path = isset( $dirs[0] ) ? $dirs[0] : '';
2924
2925 if ( empty( $path ) || ! is_dir( dirname( $path ) ) || ! is_dir( $path ) ) {
2926 return array(
2927 'value' => esc_html__( 'Not found', 'mainwp' ),
2928 'status' => 'error',
2929 );
2930 }
2931
2932 if ( is_writable( $path ) ) {
2933 return array(
2934 'value' => esc_html__( 'Writable', 'mainwp' ),
2935 'status' => 'pass',
2936 );
2937 }
2938
2939 return array(
2940 'value' => esc_html__( 'Not writable', 'mainwp' ),
2941 'status' => 'error',
2942 );
2943 }
2944
2945 /**
2946 * Get primary backup method label.
2947 *
2948 * @return string
2949 */
2950 private static function get_primary_backup_method_label() {
2951 $primary_backup = get_option( 'mainwp_primaryBackup' );
2952 $primary_methods = apply_filters_deprecated( 'mainwp-getprimarybackup-methods', array( array() ), '4.0.7.2', 'mainwp_getprimarybackup_methods' ); // NOSONAR - not IP.
2953 $primary_methods = apply_filters( 'mainwp_getprimarybackup_methods', $primary_methods );
2954
2955 if ( is_array( $primary_methods ) ) {
2956 foreach ( $primary_methods as $method ) {
2957 if ( isset( $method['value'], $method['title'] ) && $primary_backup === $method['value'] ) {
2958 return (string) $method['title'];
2959 }
2960 }
2961 }
2962
2963 return esc_html__( 'Native backups', 'mainwp' );
2964 }
2965
2966 /**
2967 * Get signature algorithm label.
2968 *
2969 * @return string
2970 */
2971 private static function get_signature_algorithm_label() {
2972 $default_setting = MainWP_Settings_Indicator::get_defaults_value();
2973 $sign_algs = MainWP_System_Utility::get_open_ssl_sign_algos();
2974 $signature_algo = (int) get_option( 'mainwp_connect_signature_algo', $default_setting['mainwp_connect_signature_algo'] );
2975
2976 return isset( $sign_algs[ $signature_algo ] ) ? $sign_algs[ $signature_algo ] : (string) $signature_algo;
2977 }
2978
2979 /**
2980 * Get cron job summary.
2981 *
2982 * @param string $last_run_option Last run option name.
2983 * @param string $hook Cron hook.
2984 * @param string $fallback_freq Fallback frequency.
2985 *
2986 * @return array<string,string>
2987 */
2988 private static function get_cron_job_summary( $last_run_option, $hook, $fallback_freq ) {
2989 $local_timestamp = MainWP_Utility::get_timestamp();
2990 $use_wp_cron = ( false === get_option( 'mainwp_wp_cron' ) ) || ( 1 === (int) get_option( 'mainwp_wp_cron', 1 ) );
2991
2992 if ( 'mainwp_updatescheck_start_last_timestamp' === $last_run_option ) {
2993 $update_time = MainWP_Settings::get_websites_automatic_update_time();
2994 return array(
2995 'last' => isset( $update_time['last'] ) ? $update_time['last'] : esc_html__( 'Never', 'mainwp' ),
2996 'next' => isset( $update_time['next'] ) ? $update_time['next'] : esc_html__( 'Unknown', 'mainwp' ),
2997 );
2998 }
2999
3000 $lasttime_run = get_option( $last_run_option );
3001 if ( false === $lasttime_run || empty( $lasttime_run ) ) {
3002 $last_run = esc_html__( 'Never', 'mainwp' );
3003 } elseif ( 'mainwp_uptimecheck_auto_main_counter_lasttime_started' === $last_run_option ) {
3004 $last_run = MainWP_Utility::format_timestamp( $lasttime_run );
3005 } else {
3006 $last_run = MainWP_Utility::format_timestamp( MainWP_Utility::get_timestamp( $lasttime_run ) );
3007 }
3008
3009 $next_run = '';
3010 if ( $use_wp_cron ) {
3011 $scheduled = wp_next_scheduled( $hook );
3012 if ( ! empty( $scheduled ) ) {
3013 $next_run = MainWP_Utility::format_timestamp( MainWP_Utility::get_timestamp( $scheduled ) );
3014 }
3015 }
3016
3017 if ( empty( $next_run ) && ! empty( $fallback_freq ) ) {
3018 $nexttime_run = MainWP_Server_Information::get_schedule_next_time_to_show( $fallback_freq, is_numeric( $lasttime_run ) ? (int) $lasttime_run : 0, $local_timestamp );
3019 if ( $nexttime_run < $local_timestamp + 3 * MINUTE_IN_SECONDS ) {
3020 $next_run = esc_html__( 'Any minute', 'mainwp' );
3021 } else {
3022 $next_run = MainWP_Utility::format_timestamp( MainWP_Utility::get_timestamp( $nexttime_run ) );
3023 }
3024 }
3025
3026 if ( empty( $next_run ) ) {
3027 $next_run = esc_html__( 'Unknown', 'mainwp' );
3028 }
3029
3030 return array(
3031 'last' => $last_run,
3032 'next' => $next_run,
3033 );
3034 }
3035
3036 /**
3037 * Get uptime monitoring summary row.
3038 *
3039 * @return array<string,string>|array<mixed>
3040 */
3041 private static function get_uptime_monitoring_summary() {
3042 $global = MainWP_Uptime_Monitoring_Handle::get_global_monitoring_settings();
3043 if ( empty( $global['active'] ) && ! get_option( 'mainwp_individual_uptime_monitoring_schedule_enabled' ) ) {
3044 return array();
3045 }
3046
3047 $summary = static::get_cron_job_summary( 'mainwp_uptimecheck_auto_main_counter_lasttime_started', 'mainwp_cronuptimemonitoringcheck_action', 'minutely' );
3048
3049 return array(
3050 'label' => esc_html__( 'Uptime monitoring schedule', 'mainwp' ),
3051 'value' => sprintf(
3052 /* translators: 1: last run, 2: next run */
3053 esc_html__( 'Last run: %1$s | Next run: %2$s', 'mainwp' ),
3054 $summary['last'],
3055 $summary['next']
3056 ),
3057 );
3058 }
3059
3060 /**
3061 * Format retention label from days.
3062 *
3063 * @param int $days Days.
3064 *
3065 * @return string
3066 */
3067 private static function format_retention_days_label( $days ) {
3068 if ( $days <= 0 ) {
3069 return esc_html__( 'Keep forever', 'mainwp' );
3070 }
3071
3072 return sprintf(
3073 /* translators: %d: days */
3074 _n( '%d day', '%d days', $days, 'mainwp' ),
3075 $days
3076 );
3077 }
3078
3079 /**
3080 * Format monitoring type label.
3081 *
3082 * @param string $type Monitor type.
3083 *
3084 * @return string
3085 */
3086 private static function format_monitor_type_label( $type ) {
3087 switch ( $type ) {
3088 case 'ping':
3089 return esc_html__( 'Ping', 'mainwp' );
3090 case 'keyword':
3091 return esc_html__( 'Keyword Monitoring', 'mainwp' );
3092 default:
3093 return esc_html__( 'HTTP(s)', 'mainwp' );
3094 }
3095 }
3096
3097 /**
3098 * Format log retention label.
3099 *
3100 * @param int $seconds Retention in seconds.
3101 *
3102 * @return string
3103 */
3104 private static function format_log_retention_label( $seconds ) {
3105 if ( $seconds <= 0 ) {
3106 return esc_html__( 'Forever', 'mainwp' );
3107 }
3108 if ( 3 * YEAR_IN_SECONDS === $seconds ) {
3109 return esc_html__( 'Three years', 'mainwp' );
3110 }
3111 if ( 2 * YEAR_IN_SECONDS === $seconds ) {
3112 return esc_html__( 'Two years', 'mainwp' );
3113 }
3114 if ( YEAR_IN_SECONDS === $seconds ) {
3115 return esc_html__( 'Year', 'mainwp' );
3116 }
3117 if ( 6 * MONTH_IN_SECONDS === $seconds ) {
3118 return esc_html__( 'Half a year', 'mainwp' );
3119 }
3120 if ( 3 * MONTH_IN_SECONDS === $seconds ) {
3121 return esc_html__( 'Three months', 'mainwp' );
3122 }
3123 if ( 2 * MONTH_IN_SECONDS === $seconds ) {
3124 return esc_html__( 'Two months', 'mainwp' );
3125 }
3126 if ( MONTH_IN_SECONDS === $seconds ) {
3127 return esc_html__( 'One month', 'mainwp' );
3128 }
3129
3130 return sprintf(
3131 /* translators: %d: days */
3132 _n( '%d day', '%d days', max( 1, (int) floor( $seconds / DAY_IN_SECONDS ) ), 'mainwp' ),
3133 max( 1, (int) floor( $seconds / DAY_IN_SECONDS ) )
3134 );
3135 }
3136 }
3137