PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 6.1
MainWP Dashboard: Self-hosted WordPress Management for Agencies v6.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 5.2.2 5.3 All 153 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.1, at pages/page-mainwp-server-information-handler.php

2,967 lines 111.5 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 return $issues;
1075 }
1076
1077 /**
1078 * Add English export labels to localized report rows.
1079 *
1080 * @param array<int,array<string,mixed>> $rows Report rows.
1081 * @param array<int,string> $english_labels English labels to map.
1082 *
1083 * @return array<int,array<string,mixed>>
1084 */
1085 private static function add_export_labels_to_rows( $rows, $english_labels ) {
1086 if ( empty( $rows ) || empty( $english_labels ) ) {
1087 return $rows;
1088 }
1089
1090 $localized_map = array();
1091 foreach ( $english_labels as $english_label ) {
1092 $localized_map[ esc_html__( $english_label, 'mainwp' ) ] = $english_label;
1093 }
1094
1095 foreach ( $rows as $index => $row ) {
1096 if ( ! is_array( $row ) || empty( $row['label'] ) || ! empty( $row['export_label'] ) ) {
1097 continue;
1098 }
1099
1100 if ( isset( $localized_map[ $row['label'] ] ) ) {
1101 $rows[ $index ]['export_label'] = $localized_map[ $row['label'] ];
1102 }
1103 }
1104
1105 return $rows;
1106 }
1107
1108 /**
1109 * Get English export label for notification type.
1110 *
1111 * @param string $type Notification type.
1112 * @param string $fallback_label Fallback localized label.
1113 *
1114 * @return string
1115 */
1116 private static function get_notification_type_export_label( $type, $fallback_label ) {
1117 $labels = array(
1118 'daily_digest' => 'Daily Digest Email',
1119 'uptime' => 'Uptime Monitoring Email',
1120 'site_health' => 'Site Health Monitoring Email',
1121 'deactivated_license_alert' => 'Extension License Deactivation Notification Email',
1122 'http_check' => 'After Updates HTTP Check Email',
1123 );
1124
1125 /**
1126 * Filter: mainwp_notification_type_export_labels
1127 *
1128 * Filters English export labels for notification types used in the Server Information report export.
1129 *
1130 * @since 6.1
1131 *
1132 * @param array $labels Notification type => English export label map.
1133 * @param string $type Notification type currently being resolved.
1134 * @param string $fallback_label Localized fallback label.
1135 */
1136 $labels = apply_filters( 'mainwp_notification_type_export_labels', $labels, $type, $fallback_label );
1137 if ( ! is_array( $labels ) ) {
1138 $labels = array();
1139 }
1140
1141 return isset( $labels[ $type ] ) ? $labels[ $type ] : $fallback_label;
1142 }
1143
1144 /**
1145 * Get MainWP overview rows.
1146 *
1147 * @return array<int,array<string,mixed>>
1148 */
1149 public static function get_mainwp_overview_report_rows() {
1150 $current_version = static::get_current_version();
1151 $latest_version = static::get_mainwp_version();
1152 $version_value = false !== $latest_version
1153 ? sprintf(
1154 /* translators: 1: latest version, 2: current version */
1155 esc_html__( 'Latest: %1$s | Detected: %2$s', 'mainwp' ),
1156 $latest_version,
1157 $current_version
1158 )
1159 : sprintf(
1160 /* translators: %s: current version */
1161 esc_html__( 'Detected: %s', 'mainwp' ),
1162 $current_version
1163 );
1164
1165 $upload_directory = static::get_mainwp_upload_directory_data();
1166
1167 return self::add_export_labels_to_rows(
1168 array(
1169 array(
1170 'label' => esc_html__( 'MainWP Dashboard Version', 'mainwp' ),
1171 'value' => $version_value,
1172 'status' => ( false !== $latest_version && $current_version === $latest_version ) ? 'pass' : 'warning',
1173 ),
1174 array(
1175 'label' => esc_html__( 'Number of connected sites', 'mainwp' ),
1176 'value' => (string) MainWP_DB::instance()->get_websites_count(),
1177 ),
1178 array(
1179 'label' => esc_html__( 'MainWP upload directory', 'mainwp' ),
1180 'value' => $upload_directory['value'],
1181 'status' => $upload_directory['status'],
1182 ),
1183 array(
1184 'label' => esc_html__( 'MainWP REST API enabled', 'mainwp' ),
1185 'value' => static::format_boolean_label( Rest_Api_V1::instance()->is_rest_api_enabled() ),
1186 'status' => Rest_Api_V1::instance()->is_rest_api_enabled() ? 'pass' : 'warning',
1187 ),
1188 ),
1189 array(
1190 'MainWP Dashboard Version',
1191 'Number of connected sites',
1192 'MainWP upload directory',
1193 'MainWP REST API enabled',
1194 )
1195 );
1196 }
1197
1198 /**
1199 * Get connectivity rows.
1200 *
1201 * @return array<int,array<string,mixed>>
1202 */
1203 public static function get_connectivity_report_rows() {
1204 $permalink = static::get_permalink_structure_data();
1205 $rest_api = static::get_rest_api_reachability_data();
1206 $self_connect = static::get_server_self_connect_data();
1207 $public_ip = static::get_public_dashboard_ip_data();
1208 $ssl_verify = ( false === get_option( 'mainwp_sslVerifyCertificate' ) ) || 1 === (int) get_option( 'mainwp_sslVerifyCertificate', 1 );
1209 $verify_con = (int) get_option( 'mainwp_verify_connection_method', 1 );
1210 $signature = static::get_signature_algorithm_label();
1211
1212 return self::add_export_labels_to_rows(
1213 array(
1214 array(
1215 'label' => esc_html__( 'Dashboard home URL', 'mainwp' ),
1216 'value' => home_url( '/' ),
1217 'visibility' => 'full_only',
1218 ),
1219 array(
1220 'label' => esc_html__( 'Dashboard site URL', 'mainwp' ),
1221 'value' => site_url( '/' ),
1222 'visibility' => 'full_only',
1223 ),
1224 array(
1225 'label' => esc_html__( 'Public Dashboard IP', 'mainwp' ),
1226 'value' => $public_ip['value'],
1227 'status' => $public_ip['status'],
1228 'visibility' => 'community_masked',
1229 'community_value' => $public_ip['community_value'],
1230 ),
1231 array(
1232 'label' => esc_html__( 'HTTPS', 'mainwp' ),
1233 'value' => is_ssl() ? esc_html__( 'Enabled', 'mainwp' ) : esc_html__( 'Disabled', 'mainwp' ),
1234 ),
1235 array(
1236 'label' => esc_html__( 'Permalink structure', 'mainwp' ),
1237 'value' => $permalink['value'],
1238 'status' => $permalink['status'],
1239 ),
1240 array(
1241 'label' => esc_html__( 'WordPress REST API endpoint', 'mainwp' ),
1242 'value' => rest_url(),
1243 'visibility' => 'full_only',
1244 ),
1245 array(
1246 'label' => esc_html__( 'WordPress REST API reachability', 'mainwp' ),
1247 'value' => $rest_api['value'],
1248 'status' => $rest_api['status'],
1249 ),
1250 array(
1251 'label' => esc_html__( 'Server self connect', 'mainwp' ),
1252 'value' => $self_connect['value'],
1253 'status' => $self_connect['status'],
1254 ),
1255 array(
1256 'label' => esc_html__( 'Verify SSL certificate', 'mainwp' ),
1257 'value' => static::format_boolean_label( $ssl_verify ),
1258 ),
1259 array(
1260 'label' => esc_html__( 'Verify connection method', 'mainwp' ),
1261 'value' => 2 === $verify_con ? esc_html__( 'PHPSECLIB (fallback)', 'mainwp' ) : esc_html__( 'OpenSSL (default)', 'mainwp' ),
1262 ),
1263 array(
1264 'label' => esc_html__( 'OpenSSL signature algorithm', 'mainwp' ),
1265 'value' => $signature,
1266 ),
1267 array(
1268 'label' => esc_html__( 'Force IPv4', 'mainwp' ),
1269 'value' => static::format_boolean_label( (int) get_option( 'mainwp_forceUseIPv4', 0 ) ),
1270 ),
1271 ),
1272 array(
1273 'Dashboard home URL',
1274 'Dashboard site URL',
1275 'Public Dashboard IP',
1276 'HTTPS',
1277 'Permalink structure',
1278 'WordPress REST API endpoint',
1279 'WordPress REST API reachability',
1280 'Server self connect',
1281 'Verify SSL certificate',
1282 'Verify connection method',
1283 'OpenSSL signature algorithm',
1284 'Force IPv4',
1285 )
1286 );
1287 }
1288
1289 /**
1290 * Get scheduler rows.
1291 *
1292 * @return array<int,array<string,mixed>>
1293 */
1294 public static function get_scheduler_report_rows() {
1295 $daily_frequency = (int) get_option( 'mainwp_frequencyDailyUpdate', 2 );
1296 if ( $daily_frequency <= 0 ) {
1297 $daily_frequency = 1;
1298 }
1299
1300 $rows = array(
1301 array(
1302 'label' => esc_html__( 'Use WP Cron', 'mainwp' ),
1303 'value' => static::format_boolean_label( ( false === get_option( 'mainwp_wp_cron' ) ) || 1 === (int) get_option( 'mainwp_wp_cron', 1 ) ),
1304 ),
1305 array(
1306 'label' => esc_html__( 'Daily update frequency', 'mainwp' ),
1307 'value' => MainWP_Server_Information::get_schedule_auto_update_label( $daily_frequency ),
1308 ),
1309 array(
1310 'label' => esc_html__( 'Daily update time', 'mainwp' ),
1311 'value' => (string) get_option( 'mainwp_timeDailyUpdate', '00:00' ),
1312 ),
1313 array(
1314 'label' => esc_html__( 'Advanced automatic updates schedule', 'mainwp' ),
1315 'value' => static::get_automatic_updates_schedule_label(),
1316 ),
1317 );
1318
1319 $updates_check = static::get_cron_job_summary( 'mainwp_updatescheck_start_last_timestamp', 'mainwp_cronupdatescheck_action', '' );
1320 $rows[] = array(
1321 'label' => esc_html__( 'Check for available updates', 'mainwp' ),
1322 'value' => sprintf(
1323 /* translators: 1: last run, 2: next run */
1324 esc_html__( 'Last run: %1$s | Next run: %2$s', 'mainwp' ),
1325 $updates_check['last'],
1326 $updates_check['next']
1327 ),
1328 );
1329
1330 $reconnect = static::get_cron_job_summary( 'mainwp_cron_last_stats', 'mainwp_cronreconnect_action', 'hourly' );
1331 $rows[] = array(
1332 'label' => esc_html__( 'Reconnect sites', 'mainwp' ),
1333 'value' => sprintf(
1334 /* translators: 1: last run, 2: next run */
1335 esc_html__( 'Last run: %1$s | Next run: %2$s', 'mainwp' ),
1336 $reconnect['last'],
1337 $reconnect['next']
1338 ),
1339 );
1340
1341 $monitoring = static::get_uptime_monitoring_summary();
1342 if ( ! empty( $monitoring ) ) {
1343 $rows[] = $monitoring;
1344 }
1345
1346 return self::add_export_labels_to_rows(
1347 $rows,
1348 array(
1349 'Use WP Cron',
1350 'Daily update frequency',
1351 'Daily update time',
1352 'Advanced automatic updates schedule',
1353 'Check for available updates',
1354 'Reconnect sites',
1355 'Uptime monitoring schedule',
1356 )
1357 );
1358 }
1359
1360 /**
1361 * Get general settings rows.
1362 *
1363 * @return array<int,array<string,mixed>>
1364 */
1365 public static function get_general_settings_report_rows() {
1366 $default_setting = MainWP_Settings_Indicator::get_defaults_value();
1367 $sidebar = get_user_option( 'mainwp_sidebarPosition' );
1368 if ( false === $sidebar ) {
1369 $sidebar = 1;
1370 }
1371
1372 $time_auto_update = get_option( 'mainwp_time_AutoUpdate', '00:00' );
1373 $frequency_auto_update = get_option( 'mainwp_frequency_AutoUpdate', 'daily' );
1374 if ( empty( $time_auto_update ) ) {
1375 $time_auto_update = '00:00';
1376 }
1377 if ( ! in_array( $frequency_auto_update, array( 'daily', 'weekly', 'monthly' ), true ) ) {
1378 $frequency_auto_update = 'daily';
1379 }
1380
1381 $show_widgets = get_user_option( 'mainwp_settings_show_widgets', array() );
1382 if ( ! is_array( $show_widgets ) ) {
1383 $show_widgets = array();
1384 }
1385
1386 return self::add_export_labels_to_rows(
1387 array(
1388 array(
1389 'label' => esc_html__( 'Timezone', 'mainwp' ),
1390 'value' => static::get_timezone_label(),
1391 ),
1392 array(
1393 'label' => esc_html__( 'Date format', 'mainwp' ),
1394 'value' => (string) get_option( 'date_format', $default_setting['date_format'] ),
1395 ),
1396 array(
1397 'label' => esc_html__( 'Time format', 'mainwp' ),
1398 'value' => (string) get_option( 'time_format', $default_setting['time_format'] ),
1399 ),
1400 array(
1401 'label' => esc_html__( 'Sidebar position', 'mainwp' ),
1402 'value' => 0 === (int) $sidebar ? esc_html__( 'Left', 'mainwp' ) : esc_html__( 'Right', 'mainwp' ),
1403 ),
1404 array(
1405 'label' => esc_html__( 'Hide Update Everything', 'mainwp' ),
1406 'value' => static::format_boolean_label( (int) get_option( 'mainwp_hide_update_everything', $default_setting['mainwp_hide_update_everything'] ) ),
1407 ),
1408 array(
1409 'label' => esc_html__( 'Dashboard widgets shown', 'mainwp' ),
1410 'value' => sprintf(
1411 /* translators: %d: visible widget count */
1412 esc_html__( '%d visible', 'mainwp' ),
1413 count( $show_widgets )
1414 ),
1415 ),
1416 array(
1417 'label' => esc_html__( 'WP Core advanced automatic updates', 'mainwp' ),
1418 'value' => static::get_trusted_update_mode_label( get_option( 'mainwp_automaticDailyUpdate', $default_setting['mainwp_automaticDailyUpdate'] ) ),
1419 ),
1420 array(
1421 'label' => esc_html__( 'Plugin advanced automatic updates', 'mainwp' ),
1422 'value' => static::get_trusted_update_mode_label( get_option( 'mainwp_pluginAutomaticDailyUpdate', $default_setting['mainwp_pluginAutomaticDailyUpdate'] ) ),
1423 ),
1424 array(
1425 'label' => esc_html__( 'Theme advanced automatic updates', 'mainwp' ),
1426 'value' => static::get_trusted_update_mode_label( get_option( 'mainwp_themeAutomaticDailyUpdate', $default_setting['mainwp_themeAutomaticDailyUpdate'] ) ),
1427 ),
1428 array(
1429 'label' => esc_html__( 'Translation advanced automatic updates', 'mainwp' ),
1430 'value' => static::get_trusted_update_mode_label( get_option( 'mainwp_transAutomaticDailyUpdate', 0 ) ),
1431 ),
1432 array(
1433 'label' => esc_html__( 'Automatic updates frequency', 'mainwp' ),
1434 'value' => ucfirst( (string) $frequency_auto_update ),
1435 ),
1436 array(
1437 'label' => esc_html__( 'Automatic updates time', 'mainwp' ),
1438 'value' => (string) $time_auto_update,
1439 ),
1440 array(
1441 'label' => esc_html__( 'Automatic updates day', 'mainwp' ),
1442 'value' => static::get_automatic_updates_day_label( $frequency_auto_update ),
1443 ),
1444 array(
1445 'label' => esc_html__( 'Advanced automatic updates delay', 'mainwp' ),
1446 'value' => static::format_delay_label( (int) get_option( 'mainwp_delay_autoupdate', 1 ) ),
1447 ),
1448 array(
1449 'label' => esc_html__( 'Show language updates', 'mainwp' ),
1450 'value' => static::format_boolean_label( (int) get_option( 'mainwp_show_language_updates', $default_setting['mainwp_show_language_updates'] ) ),
1451 ),
1452 array(
1453 'label' => esc_html__( 'Disable update confirmations', 'mainwp' ),
1454 'value' => static::format_boolean_label( (int) get_option( 'mainwp_disable_update_confirmations', $default_setting['mainwp_disable_update_confirmations'] ) ),
1455 ),
1456 array(
1457 'label' => esc_html__( 'After updates HTTP response check', 'mainwp' ),
1458 'value' => static::format_boolean_label( (int) get_option( 'mainwp_check_http_response', $default_setting['mainwp_check_http_response'] ) ),
1459 ),
1460 array(
1461 'label' => esc_html__( 'After updates HTTP response method', 'mainwp' ),
1462 'value' => strtoupper( (string) get_option( 'mainwp_check_http_response_method', $default_setting['mainwp_check_http_response_method'] ) ),
1463 ),
1464 array(
1465 'label' => esc_html__( 'Backup before update', 'mainwp' ),
1466 'value' => static::format_boolean_label( (int) get_option( 'mainwp_backup_before_upgrade', $default_setting['mainwp_backup_before_upgrade'] ) ),
1467 ),
1468 array(
1469 'label' => esc_html__( 'Full backup tolerance before update', 'mainwp' ),
1470 'value' => sprintf(
1471 /* translators: %d: days */
1472 esc_html__( '%d days', 'mainwp' ),
1473 (int) get_option( 'mainwp_backup_before_upgrade_days', $default_setting['mainwp_backup_before_upgrade_days'] )
1474 ),
1475 ),
1476 array(
1477 'label' => esc_html__( 'Abandoned plugins/themes tolerance', 'mainwp' ),
1478 'value' => sprintf(
1479 /* translators: %d: days */
1480 esc_html__( '%d days', 'mainwp' ),
1481 (int) get_option( 'mainwp_numberdays_Outdate_Plugin_Theme', $default_setting['mainwp_numberdays_Outdate_Plugin_Theme'] )
1482 ),
1483 ),
1484 array(
1485 'label' => esc_html__( 'Primary backup system', 'mainwp' ),
1486 'value' => static::get_primary_backup_method_label(),
1487 ),
1488 array(
1489 'label' => esc_html__( 'MainWP legacy backups enabled', 'mainwp' ),
1490 'value' => static::format_boolean_label( (int) get_option( 'mainwp_enableLegacyBackupFeature', 0 ) ),
1491 ),
1492 array(
1493 'label' => esc_html__( 'Backups kept on server', 'mainwp' ),
1494 'value' => (string) ( false === get_option( 'mainwp_backupsOnServer' ) ? 1 : intval( get_option( 'mainwp_backupsOnServer' ) ) ),
1495 ),
1496 array(
1497 'label' => esc_html__( 'Backup to external sources', 'mainwp' ),
1498 'value' => static::format_boolean_label( (int) get_option( 'mainwp_backupOnExternalSources', 0 ) ),
1499 ),
1500 array(
1501 'label' => esc_html__( 'Archive format', 'mainwp' ),
1502 'value' => static::format_archive_format_label( get_option( 'mainwp_archiveFormat', 'tar.gz' ) ),
1503 ),
1504 array(
1505 'label' => esc_html__( 'Auto detect maximum file descriptors on child sites', 'mainwp' ),
1506 'value' => static::format_boolean_label( (int) get_option( 'mainwp_maximumFileDescriptorsAuto', 1 ) ),
1507 ),
1508 array(
1509 'label' => esc_html__( 'Maximum file descriptors fallback value', 'mainwp' ),
1510 'value' => (string) ( false === get_option( 'mainwp_maximumFileDescriptors' ) ? 150 : intval( get_option( 'mainwp_maximumFileDescriptors' ) ) ),
1511 ),
1512 array(
1513 'label' => esc_html__( 'Load files in memory before zipping', 'mainwp' ),
1514 'value' => static::format_boolean_label( (int) get_option( 'mainwp_options_loadFilesBeforeZip', 1 ) ),
1515 ),
1516 array(
1517 'label' => esc_html__( 'Send email when backup fails', 'mainwp' ),
1518 'value' => static::format_boolean_label( (int) get_option( 'mainwp_notificationOnBackupFail', 1 ) ),
1519 ),
1520 array(
1521 'label' => esc_html__( 'Send email when backup starts', 'mainwp' ),
1522 'value' => static::format_boolean_label( (int) get_option( 'mainwp_notificationOnBackupStart', 1 ) ),
1523 ),
1524 array(
1525 'label' => esc_html__( 'Execute backup tasks in chunks', 'mainwp' ),
1526 'value' => static::format_boolean_label( (int) get_option( 'mainwp_chunkedBackupTasks', 1 ) ),
1527 ),
1528 ),
1529 array(
1530 'Timezone',
1531 'Date format',
1532 'Time format',
1533 'Sidebar position',
1534 'Hide Update Everything',
1535 'Dashboard widgets shown',
1536 'WP Core advanced automatic updates',
1537 'Plugin advanced automatic updates',
1538 'Theme advanced automatic updates',
1539 'Translation advanced automatic updates',
1540 'Automatic updates frequency',
1541 'Automatic updates time',
1542 'Automatic updates day',
1543 'Advanced automatic updates delay',
1544 'Show language updates',
1545 'Disable update confirmations',
1546 'After updates HTTP response check',
1547 'After updates HTTP response method',
1548 'Backup before update',
1549 'Full backup tolerance before update',
1550 'Abandoned plugins/themes tolerance',
1551 'Primary backup system',
1552 'MainWP legacy backups enabled',
1553 'Backups kept on server',
1554 'Backup to external sources',
1555 'Archive format',
1556 'Auto detect maximum file descriptors on child sites',
1557 'Maximum file descriptors fallback value',
1558 'Load files in memory before zipping',
1559 'Send email when backup fails',
1560 'Send email when backup starts',
1561 'Execute backup tasks in chunks',
1562 )
1563 );
1564 }
1565
1566 /**
1567 * Get advanced settings rows.
1568 *
1569 * @return array<int,array<string,mixed>>
1570 */
1571 public static function get_advanced_settings_report_rows() {
1572 $default_setting = MainWP_Settings_Indicator::get_defaults_value();
1573 $sign_algs = MainWP_System_Utility::get_open_ssl_sign_algos();
1574 $signature_algo = (int) get_option( 'mainwp_connect_signature_algo', $default_setting['mainwp_connect_signature_algo'] );
1575 $sync_defaults = MainWP_Settings::get_data_sync_default();
1576 $sync_data = get_option( 'mainwp_settings_sync_data', array() );
1577 $sync_data = ! empty( $sync_data ) ? json_decode( (string) $sync_data, true ) : array();
1578 if ( ! is_array( $sync_data ) ) {
1579 $sync_data = array();
1580 }
1581
1582 $enabled_sync = 0;
1583 foreach ( array_keys( $sync_defaults ) as $sync_name ) {
1584 if ( ! isset( $sync_data[ $sync_name ] ) || ! empty( $sync_data[ $sync_name ] ) ) {
1585 ++$enabled_sync;
1586 }
1587 }
1588
1589 return self::add_export_labels_to_rows(
1590 array(
1591 array(
1592 'label' => esc_html__( 'Maximum simultaneous requests', 'mainwp' ),
1593 'value' => (string) ( false === get_option( 'mainwp_maximumRequests' ) ? 4 : intval( get_option( 'mainwp_maximumRequests' ) ) ),
1594 ),
1595 array(
1596 'label' => esc_html__( 'Minimum delay between requests', 'mainwp' ),
1597 'value' => sprintf(
1598 /* translators: %d: milliseconds */
1599 esc_html__( '%d ms', 'mainwp' ),
1600 (int) ( false === get_option( 'mainwp_minimumDelay' ) ? 200 : intval( get_option( 'mainwp_minimumDelay' ) ) )
1601 ),
1602 ),
1603 array(
1604 'label' => esc_html__( 'Maximum simultaneous requests per IP', 'mainwp' ),
1605 'value' => (string) ( false === get_option( 'mainwp_maximumIPRequests' ) ? 1 : intval( get_option( 'mainwp_maximumIPRequests' ) ) ),
1606 ),
1607 array(
1608 'label' => esc_html__( 'Minimum delay between requests to the same IP', 'mainwp' ),
1609 'value' => sprintf(
1610 /* translators: %d: milliseconds */
1611 esc_html__( '%d ms', 'mainwp' ),
1612 (int) ( false === get_option( 'mainwp_minimumIPDelay' ) ? 1000 : intval( get_option( 'mainwp_minimumIPDelay' ) ) )
1613 ),
1614 ),
1615 array(
1616 'label' => esc_html__( 'Maximum simultaneous sync requests', 'mainwp' ),
1617 'value' => (string) ( false === get_option( 'mainwp_maximumSyncRequests' ) ? 8 : intval( get_option( 'mainwp_maximumSyncRequests' ) ) ),
1618 ),
1619 array(
1620 'label' => esc_html__( 'Maximum simultaneous install and update requests', 'mainwp' ),
1621 'value' => (string) ( false === get_option( 'mainwp_maximumInstallUpdateRequests' ) ? 3 : intval( get_option( 'mainwp_maximumInstallUpdateRequests' ) ) ),
1622 ),
1623 array(
1624 'label' => esc_html__( 'Maximum simultaneous uptime monitoring requests', 'mainwp' ),
1625 'value' => (string) ( false === get_option( 'mainwp_maximum_uptime_monitoring_requests' ) ? 10 : intval( get_option( 'mainwp_maximum_uptime_monitoring_requests' ) ) ),
1626 ),
1627 array(
1628 'label' => esc_html__( 'Sites processed per sync batch', 'mainwp' ),
1629 'value' => (string) ( false === get_option( 'mainwp_chunksitesnumber' ) ? 10 : intval( get_option( 'mainwp_chunksitesnumber' ) ) ),
1630 ),
1631 array(
1632 'label' => esc_html__( 'Sync batch sleep interval', 'mainwp' ),
1633 'value' => sprintf(
1634 /* translators: %d: seconds */
1635 esc_html__( '%d seconds', 'mainwp' ),
1636 (int) ( false === get_option( 'mainwp_chunksleepinterval' ) ? 5 : intval( get_option( 'mainwp_chunksleepinterval' ) ) )
1637 ),
1638 ),
1639 array(
1640 'label' => esc_html__( 'Optimize data loading', 'mainwp' ),
1641 'value' => static::format_boolean_label( (int) get_option( 'mainwp_optimize', $default_setting['mainwp_optimize'] ) ),
1642 ),
1643 array(
1644 'label' => esc_html__( 'Browser cache expiration time', 'mainwp' ),
1645 'value' => sprintf(
1646 /* translators: %d: minutes */
1647 esc_html__( '%d minutes', 'mainwp' ),
1648 (int) get_option( 'mainwp_warm_cache_pages_ttl', 10 )
1649 ),
1650 ),
1651 array(
1652 'label' => esc_html__( 'Verify SSL certificate', 'mainwp' ),
1653 'value' => static::format_boolean_label( ( false === get_option( 'mainwp_sslVerifyCertificate' ) ) || 1 === (int) get_option( 'mainwp_sslVerifyCertificate', 1 ) ),
1654 ),
1655 array(
1656 'label' => esc_html__( 'Verify connection method', 'mainwp' ),
1657 'value' => 2 === (int) get_option( 'mainwp_verify_connection_method', 1 ) ? esc_html__( 'PHPSECLIB (fallback)', 'mainwp' ) : esc_html__( 'OpenSSL (default)', 'mainwp' ),
1658 ),
1659 array(
1660 'label' => esc_html__( 'OpenSSL signature algorithm', 'mainwp' ),
1661 'value' => isset( $sign_algs[ $signature_algo ] ) ? $sign_algs[ $signature_algo ] : (string) $signature_algo,
1662 ),
1663 array(
1664 'label' => esc_html__( 'Force IPv4', 'mainwp' ),
1665 'value' => static::format_boolean_label( (int) get_option( 'mainwp_forceUseIPv4', 0 ) ),
1666 ),
1667 array(
1668 'label' => esc_html__( 'Selected data to sync', 'mainwp' ),
1669 'value' => sprintf(
1670 /* translators: 1: enabled count, 2: total count */
1671 esc_html__( '%1$d of %2$d enabled', 'mainwp' ),
1672 $enabled_sync,
1673 count( $sync_defaults )
1674 ),
1675 ),
1676 ),
1677 array(
1678 'Maximum simultaneous requests',
1679 'Minimum delay between requests',
1680 'Maximum simultaneous requests per IP',
1681 'Minimum delay between requests to the same IP',
1682 'Maximum simultaneous sync requests',
1683 'Maximum simultaneous install and update requests',
1684 'Maximum simultaneous uptime monitoring requests',
1685 'Sites processed per sync batch',
1686 'Sync batch sleep interval',
1687 'Optimize data loading',
1688 'Browser cache expiration time',
1689 'Verify SSL certificate',
1690 'Verify connection method',
1691 'OpenSSL signature algorithm',
1692 'Force IPv4',
1693 'Selected data to sync',
1694 )
1695 );
1696 }
1697
1698 /**
1699 * Get monitoring settings rows.
1700 *
1701 * @return array<int,array<string,mixed>>
1702 */
1703 public static function get_monitoring_settings_report_rows() {
1704 $monitoring_settings = MainWP_Uptime_Monitoring_Handle::get_global_monitoring_settings();
1705 $global_option = get_option( 'mainwp_global_uptime_monitoring_settings', array() );
1706 if ( ! is_array( $global_option ) ) {
1707 $global_option = array();
1708 }
1709
1710 $interval_values = MainWP_Uptime_Monitoring_Edit::get_interval_values( false );
1711 $timeout_values = MainWP_Uptime_Monitoring_Edit::get_timeout_values( false );
1712 $interval_key = $monitoring_settings['interval'] ?? 60;
1713 $timeout_key = $monitoring_settings['timeout'] ?? 60;
1714 $interval_value = isset( $interval_values[ $interval_key ] ) ? $interval_values[ $interval_key ] : $interval_key;
1715 $timeout_value = isset( $timeout_values[ $timeout_key ] ) ? $timeout_values[ $timeout_key ] : $timeout_key;
1716 $retention_days = isset( $global_option['retention_limits'] ) ? intval( $global_option['retention_limits'] ) : 180;
1717 $site_health = empty( get_option( 'mainwp_disableSitesHealthMonitoring', 1 ) );
1718 $threshold = (int) get_option( 'mainwp_sitehealthThreshold', 80 );
1719
1720 return self::add_export_labels_to_rows(
1721 array(
1722 array(
1723 'label' => esc_html__( 'Enable uptime monitoring', 'mainwp' ),
1724 'value' => static::format_boolean_label( ! empty( $monitoring_settings['active'] ) ),
1725 ),
1726 array(
1727 'label' => esc_html__( 'Monitor type', 'mainwp' ),
1728 'value' => static::format_monitor_type_label( $monitoring_settings['type'] ?? 'http' ),
1729 ),
1730 array(
1731 'label' => esc_html__( 'Method', 'mainwp' ),
1732 'value' => strtoupper( (string) ( $monitoring_settings['method'] ?? 'get' ) ),
1733 ),
1734 array(
1735 'label' => esc_html__( 'Interval', 'mainwp' ),
1736 'value' => (string) $interval_value,
1737 ),
1738 array(
1739 'label' => esc_html__( 'Timeout', 'mainwp' ),
1740 'value' => (string) $timeout_value,
1741 ),
1742 array(
1743 'label' => esc_html__( 'Up HTTP codes', 'mainwp' ),
1744 'value' => ! empty( $monitoring_settings['up_status_codes'] ) ? (string) $monitoring_settings['up_status_codes'] : esc_html__( 'Default', 'mainwp' ),
1745 ),
1746 array(
1747 'label' => esc_html__( 'Down confirmation check', 'mainwp' ),
1748 'value' => ! empty( $monitoring_settings['maxretries'] ) ? esc_html__( 'Enabled', 'mainwp' ) : esc_html__( 'Disabled', 'mainwp' ),
1749 ),
1750 array(
1751 'label' => esc_html__( 'Keyword monitoring value', 'mainwp' ),
1752 'value' => ! empty( $monitoring_settings['keyword'] ) ? (string) $monitoring_settings['keyword'] : esc_html__( 'Not configured', 'mainwp' ),
1753 ),
1754 array(
1755 'label' => esc_html__( 'Monitoring data retention', 'mainwp' ),
1756 'value' => static::format_retention_days_label( $retention_days ),
1757 ),
1758 array(
1759 'label' => esc_html__( 'Enable site health monitoring', 'mainwp' ),
1760 'value' => static::format_boolean_label( $site_health ),
1761 ),
1762 array(
1763 'label' => esc_html__( 'Site Health threshold', 'mainwp' ),
1764 'value' => 100 === $threshold ? esc_html__( 'Good', 'mainwp' ) : esc_html__( 'Should be improved', 'mainwp' ),
1765 ),
1766 ),
1767 array(
1768 'Enable uptime monitoring',
1769 'Monitor type',
1770 'Method',
1771 'Interval',
1772 'Timeout',
1773 'Up HTTP codes',
1774 'Down confirmation check',
1775 'Keyword monitoring value',
1776 'Monitoring data retention',
1777 'Enable site health monitoring',
1778 'Site Health threshold',
1779 )
1780 );
1781 }
1782
1783 /**
1784 * Get email settings rows.
1785 *
1786 * @return array<int,array<string,mixed>>
1787 */
1788 public static function get_email_settings_report_rows() {
1789 $rows = array();
1790 $types = MainWP_Notification_Settings::get_notification_types();
1791
1792 foreach ( $types as $type => $label ) {
1793 $settings = MainWP_Notification_Settings::get_general_email_settings( $type );
1794 $recipients = isset( $settings['recipients'] ) ? trim( (string) $settings['recipients'] ) : '';
1795 $recipient_count = static::count_recipients( $recipients );
1796 $subject_config = ! empty( $settings['subject'] ) ? esc_html__( 'Subject set', 'mainwp' ) : esc_html__( 'Subject empty', 'mainwp' );
1797 $heading_config = ! empty( $settings['heading'] ) ? esc_html__( 'Heading set', 'mainwp' ) : esc_html__( 'Heading empty', 'mainwp' );
1798 $enabled_disabled = empty( $settings['disable'] ) ? esc_html__( 'Enabled', 'mainwp' ) : esc_html__( 'Disabled', 'mainwp' );
1799
1800 $value = sprintf(
1801 /* translators: 1: enabled state, 2: recipients count, 3: subject state, 4: heading state */
1802 esc_html__( '%1$s | %2$d recipient(s) | %3$s | %4$s', 'mainwp' ),
1803 $enabled_disabled,
1804 $recipient_count,
1805 $subject_config,
1806 $heading_config
1807 );
1808
1809 $rows[] = array(
1810 'label' => $label,
1811 'export_label' => self::get_notification_type_export_label( $type, $label ),
1812 'value' => $value,
1813 );
1814 }
1815
1816 return $rows;
1817 }
1818
1819 /**
1820 * Get cost tracker rows.
1821 *
1822 * @return array<int,array<string,mixed>>
1823 */
1824 public static function get_cost_tracker_report_rows() {
1825 if ( ! class_exists( '\MainWP\Dashboard\Module\CostTracker\Cost_Tracker_Utility' ) || ! class_exists( '\MainWP\Dashboard\Module\CostTracker\Cost_Tracker_Admin' ) ) {
1826 return array();
1827 }
1828
1829 $selected_currency = \MainWP\Dashboard\Module\CostTracker\Cost_Tracker_Utility::get_instance()->get_option( 'currency', 'USD' );
1830 $currency_format = \MainWP\Dashboard\Module\CostTracker\Cost_Tracker_Utility::get_instance()->get_option( 'currency_format', array() );
1831 $currency_format = array_merge( \MainWP\Dashboard\Module\CostTracker\Cost_Tracker_Utility::default_currency_settings(), is_array( $currency_format ) ? $currency_format : array() );
1832 $custom_payment_methods = \MainWP\Dashboard\Module\CostTracker\Cost_Tracker_Utility::get_instance()->get_option( 'custom_payment_methods', array(), true );
1833 $product_types = \MainWP\Dashboard\Module\CostTracker\Cost_Tracker_Admin::get_product_type_icons();
1834
1835 if ( ! is_array( $custom_payment_methods ) ) {
1836 $custom_payment_methods = array();
1837 }
1838 if ( ! is_array( $product_types ) ) {
1839 $product_types = array();
1840 }
1841
1842 return self::add_export_labels_to_rows(
1843 array(
1844 array(
1845 'label' => esc_html__( 'Currency', 'mainwp' ),
1846 'value' => (string) $selected_currency,
1847 ),
1848 array(
1849 'label' => esc_html__( 'Currency position', 'mainwp' ),
1850 'value' => (string) $currency_format['currency_position'],
1851 ),
1852 array(
1853 'label' => esc_html__( 'Thousand separator', 'mainwp' ),
1854 'value' => '' === (string) $currency_format['thousand_separator'] ? esc_html__( 'None', 'mainwp' ) : (string) $currency_format['thousand_separator'],
1855 ),
1856 array(
1857 'label' => esc_html__( 'Decimal separator', 'mainwp' ),
1858 'value' => (string) $currency_format['decimal_separator'],
1859 ),
1860 array(
1861 'label' => esc_html__( 'Decimals', 'mainwp' ),
1862 'value' => (string) intval( $currency_format['decimals'] ),
1863 ),
1864 array(
1865 'label' => esc_html__( 'Product categories', 'mainwp' ),
1866 'value' => sprintf(
1867 /* translators: %d: count */
1868 esc_html__( '%d configured', 'mainwp' ),
1869 count( $product_types )
1870 ),
1871 ),
1872 array(
1873 'label' => esc_html__( 'Payment methods', 'mainwp' ),
1874 'value' => sprintf(
1875 /* translators: %d: count */
1876 esc_html__( '%d configured', 'mainwp' ),
1877 count( $custom_payment_methods )
1878 ),
1879 ),
1880 ),
1881 array(
1882 'Currency',
1883 'Currency position',
1884 'Thousand separator',
1885 'Decimal separator',
1886 'Decimals',
1887 'Product categories',
1888 'Payment methods',
1889 )
1890 );
1891 }
1892
1893 /**
1894 * Get insights rows.
1895 *
1896 * @return array<int,array<string,mixed>>
1897 */
1898 public static function get_insights_report_rows() {
1899 $options = get_option( 'mainwp_module_log_settings', array() );
1900 if ( ! is_array( $options ) ) {
1901 $options = array();
1902 }
1903
1904 $dashboard_disabled = 0;
1905 $child_disabled = 0;
1906 $changes_disabled = 0;
1907
1908 if ( class_exists( '\MainWP\Dashboard\Module\Log\Log_Settings' ) ) {
1909 $dashboard_disabled = count( \MainWP\Dashboard\Module\Log\Log_Settings::get_disabled_logs_type( 'dashboard' ) );
1910 $child_disabled = count( \MainWP\Dashboard\Module\Log\Log_Settings::get_disabled_logs_type( 'nonmainwpchanges' ) );
1911 $changes_disabled = count( \MainWP\Dashboard\Module\Log\Log_Settings::get_disabled_logs_type( 'changeslogs' ) );
1912 }
1913
1914 return self::add_export_labels_to_rows(
1915 array(
1916 array(
1917 'label' => esc_html__( 'Enable Network Activity logging', 'mainwp' ),
1918 'value' => static::format_boolean_label( ! empty( $options['enabled'] ) ),
1919 ),
1920 array(
1921 'label' => esc_html__( 'Automatically archive logs', 'mainwp' ),
1922 'value' => static::format_boolean_label( ! empty( $options['auto_archive'] ) ),
1923 ),
1924 array(
1925 'label' => esc_html__( 'Data retention period', 'mainwp' ),
1926 'value' => static::format_log_retention_label( isset( $options['records_logs_ttl'] ) ? intval( $options['records_logs_ttl'] ) : 3 * YEAR_IN_SECONDS ),
1927 ),
1928 array(
1929 'label' => esc_html__( 'Child-site Network Activity retention', 'mainwp' ),
1930 'value' => static::format_retention_days_label( isset( $options['child_logs_ttl'] ) ? intval( $options['child_logs_ttl'] ) : 7 ),
1931 ),
1932 array(
1933 'label' => esc_html__( 'Disabled dashboard event types', 'mainwp' ),
1934 'value' => (string) $dashboard_disabled,
1935 ),
1936 array(
1937 'label' => esc_html__( 'Disabled child-site event types', 'mainwp' ),
1938 'value' => (string) $child_disabled,
1939 ),
1940 array(
1941 'label' => esc_html__( 'Disabled change-log event types', 'mainwp' ),
1942 'value' => (string) $changes_disabled,
1943 ),
1944 ),
1945 array(
1946 'Enable Network Activity logging',
1947 'Automatically archive logs',
1948 'Data retention period',
1949 'Child-site Network Activity retention',
1950 'Disabled dashboard event types',
1951 'Disabled child-site event types',
1952 'Disabled change-log event types',
1953 )
1954 );
1955 }
1956
1957 /**
1958 * Get API backups rows.
1959 *
1960 * @return array<int,array<string,mixed>>
1961 */
1962 public static function get_api_backups_report_rows() {
1963 if ( ! class_exists( '\MainWP\Dashboard\Module\ApiBackups\Api_Backups_3rd_Party' ) ) {
1964 return array();
1965 }
1966
1967 $definitions = array(
1968 'cloudways' => array(
1969 'label' => 'Cloudways',
1970 'enabled_option' => 'mainwp_enable_cloudways_api',
1971 'options' => array( 'mainwp_cloudways_api_account_email' ),
1972 'secrets' => array( array( '\MainWP\Dashboard\Module\ApiBackups\Api_Backups_3rd_Party', 'get_cloudways_api_key' ) ),
1973 ),
1974 'gridpane' => array(
1975 'label' => 'GridPane',
1976 'enabled_option' => 'mainwp_enable_gridpane_api',
1977 'options' => array(),
1978 'secrets' => array( array( '\MainWP\Dashboard\Module\ApiBackups\Api_Backups_3rd_Party', 'get_gridpane_api_key' ) ),
1979 ),
1980 'vultr' => array(
1981 'label' => 'Vultr',
1982 'enabled_option' => 'mainwp_enable_vultr_api',
1983 'options' => array(),
1984 'secrets' => array( array( '\MainWP\Dashboard\Module\ApiBackups\Api_Backups_3rd_Party', 'get_vultr_api_key' ) ),
1985 ),
1986 'linode' => array(
1987 'label' => 'Akamai (Linode)',
1988 'enabled_option' => 'mainwp_enable_linode_api',
1989 'options' => array(),
1990 'secrets' => array( array( '\MainWP\Dashboard\Module\ApiBackups\Api_Backups_3rd_Party', 'get_linode_api_key' ) ),
1991 ),
1992 'digitalocean' => array(
1993 'label' => 'DigitalOcean',
1994 'enabled_option' => 'mainwp_enable_digitalocean_api',
1995 'options' => array(),
1996 'secrets' => array( array( '\MainWP\Dashboard\Module\ApiBackups\Api_Backups_3rd_Party', 'get_digitalocean_api_key' ) ),
1997 ),
1998 'cpanel' => array(
1999 'label' => 'cPanel (WP Toolkit)',
2000 'enabled_option' => 'mainwp_enable_cpanel_api',
2001 'options' => array( 'mainwp_cpanel_url', 'mainwp_cpanel_site_path', 'mainwp_cpanel_account_username' ),
2002 'secrets' => array(),
2003 ),
2004 'plesk' => array(
2005 'label' => 'Plesk',
2006 'enabled_option' => 'mainwp_enable_plesk_api',
2007 'options' => array( 'mainwp_plesk_api_url' ),
2008 'secrets' => array( array( '\MainWP\Dashboard\Module\ApiBackups\Api_Backups_3rd_Party', 'get_plesk_api_key' ) ),
2009 ),
2010 'kinsta' => array(
2011 'label' => 'Kinsta',
2012 'enabled_option' => 'mainwp_enable_kinsta_api',
2013 'options' => array( 'mainwp_kinsta_api_account_email', 'mainwp_kinsta_company_id' ),
2014 'secrets' => array( array( '\MainWP\Dashboard\Module\ApiBackups\Api_Backups_3rd_Party', 'get_kinsta_api_key' ) ),
2015 ),
2016 );
2017
2018 $rows = array();
2019
2020 foreach ( $definitions as $provider ) {
2021 $enabled = ! empty( get_option( $provider['enabled_option'], 0 ) );
2022 $details = array();
2023
2024 foreach ( $provider['options'] as $option_name ) {
2025 if ( '' !== trim( (string) get_option( $option_name, '' ) ) ) {
2026 $details[] = esc_html__( 'profile configured', 'mainwp' );
2027 break;
2028 }
2029 }
2030
2031 foreach ( $provider['secrets'] as $secret_callback ) {
2032 $secret = call_user_func( $secret_callback );
2033 if ( ! empty( $secret ) ) {
2034 $details[] = esc_html__( 'secret configured', 'mainwp' );
2035 break;
2036 }
2037 }
2038
2039 $summary = $enabled ? esc_html__( 'Enabled', 'mainwp' ) : esc_html__( 'Disabled', 'mainwp' );
2040 if ( ! empty( $details ) ) {
2041 $summary .= ' | ' . implode( ', ', array_unique( $details ) );
2042 }
2043
2044 $rows[] = array(
2045 'label' => $provider['label'],
2046 'value' => $summary,
2047 );
2048 }
2049
2050 return $rows;
2051 }
2052
2053 /**
2054 * Get tools rows.
2055 *
2056 * @return array<int,array<string,mixed>>
2057 */
2058 public static function get_tools_report_rows() {
2059 return self::add_export_labels_to_rows(
2060 array(
2061 array(
2062 'label' => esc_html__( 'Current MainWP theme', 'mainwp' ),
2063 'value' => MainWP_Settings::get_instance()->get_current_user_theme(),
2064 ),
2065 array(
2066 'label' => esc_html__( 'Guided tours', 'mainwp' ),
2067 'value' => static::format_boolean_label( (int) get_option( 'mainwp_enable_guided_tours', 0 ) ),
2068 ),
2069 array(
2070 'label' => esc_html__( 'Chatbase', 'mainwp' ),
2071 'value' => static::format_boolean_label( (int) get_option( 'mainwp_enable_guided_chatbase', 0 ) ),
2072 ),
2073 array(
2074 'label' => esc_html__( 'Guided video', 'mainwp' ),
2075 'value' => static::format_boolean_label( (int) get_option( 'mainwp_enable_guided_video', 0 ) ),
2076 ),
2077 ),
2078 array(
2079 'Current MainWP theme',
2080 'Guided tours',
2081 'Chatbase',
2082 'Guided video',
2083 )
2084 );
2085 }
2086
2087 /**
2088 * Get debug rows.
2089 *
2090 * @return array<int,array<string,mixed>>
2091 */
2092 public static function get_debug_report_rows() {
2093 $error_log_path = ini_get( 'error_log' );
2094 $log_readable = ! empty( $error_log_path ) && file_exists( $error_log_path ) ? is_readable( $error_log_path ) : false;
2095
2096 return self::add_export_labels_to_rows(
2097 array(
2098 array(
2099 'label' => esc_html__( 'WP_DEBUG', 'mainwp' ),
2100 'value' => static::format_boolean_label( defined( 'WP_DEBUG' ) && WP_DEBUG ),
2101 ),
2102 array(
2103 'label' => esc_html__( 'WP_DEBUG_LOG', 'mainwp' ),
2104 'value' => static::format_boolean_label( defined( 'WP_DEBUG_LOG' ) && WP_DEBUG_LOG ),
2105 ),
2106 array(
2107 'label' => esc_html__( 'WP_DEBUG_DISPLAY', 'mainwp' ),
2108 'value' => static::format_boolean_label( defined( 'WP_DEBUG_DISPLAY' ) && WP_DEBUG_DISPLAY ),
2109 ),
2110 array(
2111 'label' => esc_html__( 'PHP log_errors', 'mainwp' ),
2112 'value' => static::format_boolean_label( filter_var( ini_get( 'log_errors' ), FILTER_VALIDATE_BOOLEAN ) ),
2113 ),
2114 array(
2115 'label' => esc_html__( 'PHP error_log path', 'mainwp' ),
2116 'value' => ! empty( $error_log_path ) ? $error_log_path : esc_html__( 'Not set', 'mainwp' ),
2117 'visibility' => 'community_masked',
2118 'community_value' => ! empty( $error_log_path ) ? esc_html__( 'Configured', 'mainwp' ) : esc_html__( 'Not set', 'mainwp' ),
2119 ),
2120 array(
2121 'label' => esc_html__( 'PHP error_log readable', 'mainwp' ),
2122 'value' => static::format_boolean_label( $log_readable ),
2123 ),
2124 ),
2125 array(
2126 'WP_DEBUG',
2127 'WP_DEBUG_LOG',
2128 'WP_DEBUG_DISPLAY',
2129 'PHP log_errors',
2130 'PHP error_log path',
2131 'PHP error_log readable',
2132 )
2133 );
2134 }
2135
2136 /**
2137 * Get conflict signal rows.
2138 *
2139 * @return array<int,array<string,mixed>>
2140 */
2141 public static function get_conflict_signal_report_rows() {
2142 $caching_plugins = static::get_active_plugins_by_keyword_group(
2143 array(
2144 'cache',
2145 'rocket',
2146 'litespeed',
2147 'autoptimize',
2148 'wp-optimize',
2149 'perfmatters',
2150 'flyingpress',
2151 'sg optimizer',
2152 'breeze',
2153 'nitropack',
2154 'hummingbird',
2155 )
2156 );
2157 $security_plugins = static::get_active_plugins_by_keyword_group(
2158 array(
2159 'wordfence',
2160 'sucuri',
2161 'solid security',
2162 'ithemes security',
2163 'all-in-one wp security',
2164 'shield security',
2165 'disable rest api',
2166 'rest api control',
2167 'wp hide',
2168 'cloudflare',
2169 'limit login',
2170 )
2171 );
2172 $maintenance_plugins = static::get_active_plugins_by_keyword_group(
2173 array(
2174 'maintenance',
2175 'coming soon',
2176 'seedprod',
2177 'lightstart',
2178 )
2179 );
2180 $maintenance_mode = static::get_maintenance_mode_indicators();
2181 $dropins = static::get_dropin_conflict_indicators();
2182
2183 return self::add_export_labels_to_rows(
2184 array(
2185 array(
2186 'label' => esc_html__( 'Caching / performance plugins', 'mainwp' ),
2187 'value' => static::format_conflict_items_label( $caching_plugins ),
2188 ),
2189 array(
2190 'label' => esc_html__( 'Security / access-control plugins', 'mainwp' ),
2191 'value' => static::format_conflict_items_label( $security_plugins ),
2192 ),
2193 array(
2194 'label' => esc_html__( 'Maintenance mode indicators', 'mainwp' ),
2195 'value' => static::format_conflict_items_label( $maintenance_mode ),
2196 'status' => empty( $maintenance_mode ) ? '' : 'warning',
2197 ),
2198 array(
2199 'label' => esc_html__( 'Drop-ins / object cache', 'mainwp' ),
2200 'value' => static::format_conflict_items_label( $dropins ),
2201 ),
2202 ),
2203 array(
2204 'Caching / performance plugins',
2205 'Security / access-control plugins',
2206 'Maintenance mode indicators',
2207 'Drop-ins / object cache',
2208 )
2209 );
2210 }
2211
2212 /**
2213 * Format boolean label.
2214 *
2215 * @param mixed $value True-ish value.
2216 *
2217 * @return string
2218 */
2219 private static function format_boolean_label( $value ) {
2220 return ! empty( $value ) ? esc_html__( 'Yes', 'mainwp' ) : esc_html__( 'No', 'mainwp' );
2221 }
2222
2223 /**
2224 * Get timezone label.
2225 *
2226 * @return string
2227 */
2228 private static function get_timezone_label() {
2229 $timezone = wp_timezone_string();
2230 if ( ! empty( $timezone ) ) {
2231 return $timezone;
2232 }
2233
2234 $gmt_offset = (float) get_option( 'gmt_offset', 0 );
2235 $tz_sign = $gmt_offset >= 0 ? '+' : '-';
2236 $tz_value = (string) abs( $gmt_offset );
2237
2238 return sprintf( 'UTC%s%s', $tz_sign, $tz_value );
2239 }
2240
2241 /**
2242 * Get trusted update mode label.
2243 *
2244 * @param mixed $value Setting value.
2245 *
2246 * @return string
2247 */
2248 private static function get_trusted_update_mode_label( $value ) {
2249 return 1 === (int) $value ? esc_html__( 'Install Trusted Updates', 'mainwp' ) : esc_html__( 'Disabled', 'mainwp' );
2250 }
2251
2252 /**
2253 * Get archive format label.
2254 *
2255 * @param mixed $format Archive format.
2256 *
2257 * @return string
2258 */
2259 private static function format_archive_format_label( $format ) {
2260 $format = empty( $format ) ? 'tar.gz' : (string) $format;
2261 return $format;
2262 }
2263
2264 /**
2265 * Get delay label.
2266 *
2267 * @param int $days Days.
2268 *
2269 * @return string
2270 */
2271 private static function format_delay_label( $days ) {
2272 if ( $days <= 0 ) {
2273 return esc_html__( 'Delay off', 'mainwp' );
2274 }
2275
2276 return sprintf(
2277 /* translators: %d: day count */
2278 _n( '%d day', '%d days', $days, 'mainwp' ),
2279 $days
2280 );
2281 }
2282
2283 /**
2284 * Get automatic update day label.
2285 *
2286 * @param string $frequency Frequency.
2287 *
2288 * @return string
2289 */
2290 private static function get_automatic_updates_day_label( $frequency ) {
2291 switch ( $frequency ) {
2292 case 'weekly':
2293 $days = array(
2294 0 => esc_html__( 'Mon', 'mainwp' ),
2295 1 => esc_html__( 'Tue', 'mainwp' ),
2296 2 => esc_html__( 'Wed', 'mainwp' ),
2297 3 => esc_html__( 'Thu', 'mainwp' ),
2298 4 => esc_html__( 'Fri', 'mainwp' ),
2299 5 => esc_html__( 'Sat', 'mainwp' ),
2300 6 => esc_html__( 'Sun', 'mainwp' ),
2301 );
2302 $day = (int) get_option( 'mainwp_dayinweek_AutoUpdate', 0 );
2303 return isset( $days[ $day ] ) ? $days[ $day ] : esc_html__( 'Mon', 'mainwp' );
2304 case 'monthly':
2305 return sprintf(
2306 /* translators: %d: day of month */
2307 esc_html__( 'Day %d of the month', 'mainwp' ),
2308 (int) get_option( 'mainwp_dayinmonth_AutoUpdate', 1 )
2309 );
2310 default:
2311 return esc_html__( 'Every day', 'mainwp' );
2312 }
2313 }
2314
2315 /**
2316 * Get automatic updates schedule label.
2317 *
2318 * @return string
2319 */
2320 private static function get_automatic_updates_schedule_label() {
2321 $frequency = (string) get_option( 'mainwp_frequency_AutoUpdate', 'daily' );
2322 $time = (string) get_option( 'mainwp_time_AutoUpdate', '00:00' );
2323 if ( empty( $time ) ) {
2324 $time = '00:00';
2325 }
2326
2327 if ( 'weekly' === $frequency ) {
2328 return sprintf(
2329 /* translators: 1: day label, 2: time */
2330 esc_html__( 'Weekly on %1$s at %2$s', 'mainwp' ),
2331 static::get_automatic_updates_day_label( 'weekly' ),
2332 $time
2333 );
2334 }
2335
2336 if ( 'monthly' === $frequency ) {
2337 return sprintf(
2338 /* translators: 1: day label, 2: time */
2339 esc_html__( 'Monthly on %1$s at %2$s', 'mainwp' ),
2340 static::get_automatic_updates_day_label( 'monthly' ),
2341 $time
2342 );
2343 }
2344
2345 return sprintf(
2346 /* translators: %s: time */
2347 esc_html__( 'Daily at %s', 'mainwp' ),
2348 $time
2349 );
2350 }
2351
2352 /**
2353 * Count recipients.
2354 *
2355 * @param string $recipients Recipients string.
2356 *
2357 * @return int
2358 */
2359 private static function count_recipients( $recipients ) {
2360 if ( empty( $recipients ) ) {
2361 return 0;
2362 }
2363
2364 $emails = preg_split( '/\s*,\s*/', trim( $recipients ) );
2365 $emails = array_filter( (array) $emails );
2366
2367 return count( $emails );
2368 }
2369
2370 /**
2371 * Get public dashboard IP data.
2372 *
2373 * @return array<string,string>
2374 */
2375 private static function get_public_dashboard_ip_data() {
2376 $server_ip = static::get_server_ip_value();
2377
2378 if ( static::is_public_ip_address( $server_ip ) ) {
2379 return array(
2380 'value' => $server_ip,
2381 'status' => 'pass',
2382 'community_value' => esc_html__( 'Detected', 'mainwp' ),
2383 );
2384 }
2385
2386 $cached_data = get_transient( 'mainwp_public_dashboard_ip_data' );
2387 if ( is_array( $cached_data ) && isset( $cached_data['value'], $cached_data['status'], $cached_data['community_value'] ) ) {
2388 return $cached_data;
2389 }
2390
2391 $response = wp_safe_remote_get(
2392 'https://api.ipify.org?format=json',
2393 array(
2394 'timeout' => 3,
2395 'sslverify' => true,
2396 )
2397 );
2398
2399 if ( ! is_wp_error( $response ) ) {
2400 $response_code = (int) wp_remote_retrieve_response_code( $response );
2401 $body = json_decode( (string) wp_remote_retrieve_body( $response ), true );
2402 $public_ip = is_array( $body ) && isset( $body['ip'] ) ? trim( (string) $body['ip'] ) : '';
2403
2404 if ( $response_code >= 200 && $response_code < 300 && static::is_public_ip_address( $public_ip ) ) {
2405 $data = array(
2406 'value' => $public_ip,
2407 'status' => 'pass',
2408 'community_value' => esc_html__( 'Detected', 'mainwp' ),
2409 );
2410 set_transient( 'mainwp_public_dashboard_ip_data', $data, 12 * HOUR_IN_SECONDS );
2411
2412 return $data;
2413 }
2414 }
2415
2416 $data = array(
2417 'value' => esc_html__( 'Unavailable. Contact your host if the Server IP is local or private.', 'mainwp' ),
2418 'status' => 'warning',
2419 'community_value' => esc_html__( 'Unavailable', 'mainwp' ),
2420 );
2421 set_transient( 'mainwp_public_dashboard_ip_data', $data, HOUR_IN_SECONDS );
2422
2423 return $data;
2424 }
2425
2426 /**
2427 * Get server IP value.
2428 *
2429 * @return string
2430 */
2431 private static function get_server_ip_value() {
2432 return isset( $_SERVER['SERVER_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['SERVER_ADDR'] ) ) : '';
2433 }
2434
2435 /**
2436 * Check if IP address is public.
2437 *
2438 * @param string $ip_address IP address.
2439 *
2440 * @return bool
2441 */
2442 private static function is_public_ip_address( $ip_address ) {
2443 return ! empty( $ip_address ) && false !== filter_var( $ip_address, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE );
2444 }
2445
2446 /**
2447 * Get active plugins matching a keyword group.
2448 *
2449 * @param array<int,string> $keywords Keywords.
2450 *
2451 * @return array<int,string>
2452 */
2453 private static function get_active_plugins_by_keyword_group( $keywords ) {
2454 $matches = array();
2455 $plugins = get_plugins();
2456
2457 foreach ( $plugins as $slug => $plugin ) {
2458 if ( ! is_plugin_active( $slug ) ) {
2459 continue;
2460 }
2461
2462 $plugin_name = isset( $plugin['Name'] ) ? (string) $plugin['Name'] : '';
2463 $haystack = strtolower( $slug . ' ' . $plugin_name );
2464
2465 if ( false !== strpos( $haystack, 'mainwp' ) ) {
2466 continue;
2467 }
2468
2469 foreach ( $keywords as $keyword ) {
2470 if ( false !== strpos( $haystack, strtolower( $keyword ) ) ) {
2471 $matches[] = ! empty( $plugin_name ) ? $plugin_name : $slug;
2472 break;
2473 }
2474 }
2475 }
2476
2477 return array_values( array_unique( $matches ) );
2478 }
2479
2480 /**
2481 * Get maintenance mode indicators.
2482 *
2483 * @return array<int,string>
2484 */
2485 private static function get_maintenance_mode_indicators() {
2486 $indicators = static::get_active_plugins_by_keyword_group(
2487 array(
2488 'maintenance',
2489 'coming soon',
2490 'seedprod',
2491 'lightstart',
2492 )
2493 );
2494
2495 if ( file_exists( ABSPATH . '.maintenance' ) ) {
2496 $indicators[] = esc_html__( '.maintenance file present', 'mainwp' );
2497 }
2498
2499 return array_values( array_unique( $indicators ) );
2500 }
2501
2502 /**
2503 * Get drop-in conflict indicators.
2504 *
2505 * @return array<int,string>
2506 */
2507 private static function get_dropin_conflict_indicators() {
2508 $dropins = array();
2509
2510 if ( function_exists( 'get_dropins' ) ) {
2511 $dropin_files = get_dropins();
2512 if ( is_array( $dropin_files ) ) {
2513 $dropins = array_keys( $dropin_files );
2514 }
2515 }
2516
2517 if ( wp_using_ext_object_cache() && ! in_array( 'object-cache.php', $dropins, true ) ) {
2518 $dropins[] = 'object-cache.php';
2519 }
2520
2521 return array_values( array_unique( $dropins ) );
2522 }
2523
2524 /**
2525 * Format conflict items label.
2526 *
2527 * @param array<int,string> $items Items.
2528 *
2529 * @return string
2530 */
2531 private static function format_conflict_items_label( $items ) {
2532 if ( empty( $items ) ) {
2533 return esc_html__( 'None detected', 'mainwp' );
2534 }
2535
2536 return implode( ', ', $items );
2537 }
2538
2539 /**
2540 * Get permalink structure data.
2541 *
2542 * @return array<string,string>
2543 */
2544 private static function get_permalink_structure_data() {
2545 $structure = (string) get_option( 'permalink_structure', '' );
2546
2547 if ( empty( $structure ) ) {
2548 return array(
2549 'value' => esc_html__( 'Plain', 'mainwp' ),
2550 'status' => 'warning',
2551 );
2552 }
2553
2554 return array(
2555 'value' => $structure,
2556 'status' => 'pass',
2557 );
2558 }
2559
2560 /**
2561 * Get REST API reachability data.
2562 *
2563 * @return array<string,string>
2564 */
2565 private static function get_rest_api_reachability_data() {
2566 static $cached_data = null;
2567 if ( null !== $cached_data ) {
2568 return $cached_data;
2569 }
2570
2571 $url = rest_url();
2572 $response = wp_remote_get(
2573 esc_url_raw( $url ),
2574 array(
2575 'blocking' => true,
2576 'sslverify' => apply_filters( 'https_local_ssl_verify', true ),
2577 'timeout' => 15,
2578 )
2579 );
2580
2581 if ( is_wp_error( $response ) ) {
2582 $cached_data = array(
2583 'value' => sprintf(
2584 /* translators: %s: error message */
2585 esc_html__( 'Request failed: %s', 'mainwp' ),
2586 $response->get_error_message()
2587 ),
2588 'status' => 'error',
2589 'code' => 'request_failed',
2590 );
2591 return $cached_data;
2592 }
2593
2594 $response_code = (int) wp_remote_retrieve_response_code( $response );
2595 $body = wp_remote_retrieve_body( $response );
2596 $data = json_decode( $body, true );
2597
2598 if ( $response_code >= 200 && $response_code < 300 && is_array( $data ) && isset( $data['namespaces'] ) ) {
2599 $cached_data = array(
2600 'value' => sprintf(
2601 /* translators: %d: HTTP status code */
2602 esc_html__( 'Reachable (HTTP %d)', 'mainwp' ),
2603 $response_code
2604 ),
2605 'status' => 'pass',
2606 );
2607 return $cached_data;
2608 }
2609
2610 if ( $response_code >= 200 && $response_code < 300 ) {
2611 $cached_data = array(
2612 'value' => sprintf(
2613 /* translators: %d: HTTP status code */
2614 esc_html__( 'Unexpected non-REST response (HTTP %d)', 'mainwp' ),
2615 $response_code
2616 ),
2617 'status' => 'warning',
2618 );
2619 return $cached_data;
2620 }
2621
2622 if ( 401 === $response_code ) {
2623 $cached_data = array(
2624 'value' => esc_html__( 'Auth challenge detected (HTTP 401)', 'mainwp' ),
2625 'status' => 'error',
2626 );
2627 return $cached_data;
2628 }
2629
2630 if ( 403 === $response_code ) {
2631 $cached_data = array(
2632 'value' => esc_html__( 'Forbidden or blocked (HTTP 403)', 'mainwp' ),
2633 'status' => 'error',
2634 );
2635 return $cached_data;
2636 }
2637
2638 if ( 404 === $response_code ) {
2639 $cached_data = array(
2640 'value' => esc_html__( 'Not found (HTTP 404)', 'mainwp' ),
2641 'status' => 'error',
2642 );
2643 return $cached_data;
2644 }
2645
2646 $cached_data = array(
2647 'value' => sprintf(
2648 /* translators: %d: HTTP status code */
2649 esc_html__( 'Unexpected response (HTTP %d)', 'mainwp' ),
2650 $response_code
2651 ),
2652 'status' => 'warning',
2653 );
2654
2655 return $cached_data;
2656 }
2657
2658 /**
2659 * Get self-connect data.
2660 *
2661 * @return array<string,string>
2662 */
2663 private static function get_server_self_connect_data() {
2664 static $cached_data = null;
2665 if ( null !== $cached_data ) {
2666 return $cached_data;
2667 }
2668
2669 $url = site_url( 'wp-cron.php' );
2670 $query_args = array( 'mainwp_run' => 'test' );
2671 $url = esc_url_raw( add_query_arg( $query_args, $url ) );
2672 $response = wp_remote_post(
2673 $url,
2674 array(
2675 'blocking' => true,
2676 'sslverify' => apply_filters( 'https_local_ssl_verify', true ),
2677 'timeout' => 15,
2678 )
2679 );
2680
2681 if ( is_wp_error( $response ) ) {
2682 $cached_data = array(
2683 'value' => sprintf(
2684 /* translators: %s: error message */
2685 esc_html__( 'Request failed: %s', 'mainwp' ),
2686 $response->get_error_message()
2687 ),
2688 'status' => 'error',
2689 );
2690 return $cached_data;
2691 }
2692
2693 $response_code = (int) wp_remote_retrieve_response_code( $response );
2694 if ( 401 === $response_code ) {
2695 $cached_data = array(
2696 'value' => esc_html__( 'Auth challenge detected (HTTP 401)', 'mainwp' ),
2697 'status' => 'error',
2698 'code' => 'auth_challenge',
2699 );
2700 return $cached_data;
2701 }
2702 if ( 403 === $response_code ) {
2703 $cached_data = array(
2704 'value' => esc_html__( 'Forbidden or blocked (HTTP 403)', 'mainwp' ),
2705 'status' => 'error',
2706 'code' => 'forbidden',
2707 );
2708 return $cached_data;
2709 }
2710 if ( $response_code < 200 || $response_code > 204 ) {
2711 $cached_data = array(
2712 'value' => sprintf(
2713 /* translators: %d: HTTP status code */
2714 esc_html__( 'Unexpected response (HTTP %d)', 'mainwp' ),
2715 $response_code
2716 ),
2717 'status' => 'warning',
2718 'code' => 'unexpected_status',
2719 );
2720 return $cached_data;
2721 }
2722
2723 $response_body = wp_remote_retrieve_body( $response );
2724 if ( false === strstr( $response_body, 'MainWP Test' ) ) {
2725 $cached_data = array(
2726 'value' => esc_html__( 'Unexpected response body. Note: This is common and usually not a problem unless WP-Cron or loopback requests are failing.', 'mainwp' ),
2727 'status' => 'warning',
2728 'code' => 'unexpected_body',
2729 );
2730 return $cached_data;
2731 }
2732
2733 $cached_data = array(
2734 'value' => sprintf(
2735 /* translators: %d: HTTP status code */
2736 esc_html__( 'Response test O.K. (HTTP %d)', 'mainwp' ),
2737 $response_code
2738 ),
2739 'status' => 'pass',
2740 'code' => 'pass',
2741 );
2742
2743 return $cached_data;
2744 }
2745
2746 /**
2747 * Get upload directory data.
2748 *
2749 * @return array<string,string>
2750 */
2751 private static function get_mainwp_upload_directory_data() {
2752 $dirs = MainWP_System_Utility::get_mainwp_dir();
2753 $path = isset( $dirs[0] ) ? $dirs[0] : '';
2754
2755 if ( empty( $path ) || ! is_dir( dirname( $path ) ) || ! is_dir( $path ) ) {
2756 return array(
2757 'value' => esc_html__( 'Not found', 'mainwp' ),
2758 'status' => 'error',
2759 );
2760 }
2761
2762 if ( is_writable( $path ) ) {
2763 return array(
2764 'value' => esc_html__( 'Writable', 'mainwp' ),
2765 'status' => 'pass',
2766 );
2767 }
2768
2769 return array(
2770 'value' => esc_html__( 'Not writable', 'mainwp' ),
2771 'status' => 'error',
2772 );
2773 }
2774
2775 /**
2776 * Get primary backup method label.
2777 *
2778 * @return string
2779 */
2780 private static function get_primary_backup_method_label() {
2781 $primary_backup = get_option( 'mainwp_primaryBackup' );
2782 $primary_methods = apply_filters_deprecated( 'mainwp-getprimarybackup-methods', array( array() ), '4.0.7.2', 'mainwp_getprimarybackup_methods' ); // NOSONAR - not IP.
2783 $primary_methods = apply_filters( 'mainwp_getprimarybackup_methods', $primary_methods );
2784
2785 if ( is_array( $primary_methods ) ) {
2786 foreach ( $primary_methods as $method ) {
2787 if ( isset( $method['value'], $method['title'] ) && $primary_backup === $method['value'] ) {
2788 return (string) $method['title'];
2789 }
2790 }
2791 }
2792
2793 return esc_html__( 'Native backups', 'mainwp' );
2794 }
2795
2796 /**
2797 * Get signature algorithm label.
2798 *
2799 * @return string
2800 */
2801 private static function get_signature_algorithm_label() {
2802 $default_setting = MainWP_Settings_Indicator::get_defaults_value();
2803 $sign_algs = MainWP_System_Utility::get_open_ssl_sign_algos();
2804 $signature_algo = (int) get_option( 'mainwp_connect_signature_algo', $default_setting['mainwp_connect_signature_algo'] );
2805
2806 return isset( $sign_algs[ $signature_algo ] ) ? $sign_algs[ $signature_algo ] : (string) $signature_algo;
2807 }
2808
2809 /**
2810 * Get cron job summary.
2811 *
2812 * @param string $last_run_option Last run option name.
2813 * @param string $hook Cron hook.
2814 * @param string $fallback_freq Fallback frequency.
2815 *
2816 * @return array<string,string>
2817 */
2818 private static function get_cron_job_summary( $last_run_option, $hook, $fallback_freq ) {
2819 $local_timestamp = MainWP_Utility::get_timestamp();
2820 $use_wp_cron = ( false === get_option( 'mainwp_wp_cron' ) ) || ( 1 === (int) get_option( 'mainwp_wp_cron', 1 ) );
2821
2822 if ( 'mainwp_updatescheck_start_last_timestamp' === $last_run_option ) {
2823 $update_time = MainWP_Settings::get_websites_automatic_update_time();
2824 return array(
2825 'last' => isset( $update_time['last'] ) ? $update_time['last'] : esc_html__( 'Never', 'mainwp' ),
2826 'next' => isset( $update_time['next'] ) ? $update_time['next'] : esc_html__( 'Unknown', 'mainwp' ),
2827 );
2828 }
2829
2830 $lasttime_run = get_option( $last_run_option );
2831 if ( false === $lasttime_run || empty( $lasttime_run ) ) {
2832 $last_run = esc_html__( 'Never', 'mainwp' );
2833 } elseif ( 'mainwp_uptimecheck_auto_main_counter_lasttime_started' === $last_run_option ) {
2834 $last_run = MainWP_Utility::format_timestamp( $lasttime_run );
2835 } else {
2836 $last_run = MainWP_Utility::format_timestamp( MainWP_Utility::get_timestamp( $lasttime_run ) );
2837 }
2838
2839 $next_run = '';
2840 if ( $use_wp_cron ) {
2841 $scheduled = wp_next_scheduled( $hook );
2842 if ( ! empty( $scheduled ) ) {
2843 $next_run = MainWP_Utility::format_timestamp( MainWP_Utility::get_timestamp( $scheduled ) );
2844 }
2845 }
2846
2847 if ( empty( $next_run ) && ! empty( $fallback_freq ) ) {
2848 $nexttime_run = MainWP_Server_Information::get_schedule_next_time_to_show( $fallback_freq, is_numeric( $lasttime_run ) ? (int) $lasttime_run : 0, $local_timestamp );
2849 if ( $nexttime_run < $local_timestamp + 3 * MINUTE_IN_SECONDS ) {
2850 $next_run = esc_html__( 'Any minute', 'mainwp' );
2851 } else {
2852 $next_run = MainWP_Utility::format_timestamp( MainWP_Utility::get_timestamp( $nexttime_run ) );
2853 }
2854 }
2855
2856 if ( empty( $next_run ) ) {
2857 $next_run = esc_html__( 'Unknown', 'mainwp' );
2858 }
2859
2860 return array(
2861 'last' => $last_run,
2862 'next' => $next_run,
2863 );
2864 }
2865
2866 /**
2867 * Get uptime monitoring summary row.
2868 *
2869 * @return array<string,string>|array<mixed>
2870 */
2871 private static function get_uptime_monitoring_summary() {
2872 $global = MainWP_Uptime_Monitoring_Handle::get_global_monitoring_settings();
2873 if ( empty( $global['active'] ) && ! get_option( 'mainwp_individual_uptime_monitoring_schedule_enabled' ) ) {
2874 return array();
2875 }
2876
2877 $summary = static::get_cron_job_summary( 'mainwp_uptimecheck_auto_main_counter_lasttime_started', 'mainwp_cronuptimemonitoringcheck_action', 'minutely' );
2878
2879 return array(
2880 'label' => esc_html__( 'Uptime monitoring schedule', 'mainwp' ),
2881 'value' => sprintf(
2882 /* translators: 1: last run, 2: next run */
2883 esc_html__( 'Last run: %1$s | Next run: %2$s', 'mainwp' ),
2884 $summary['last'],
2885 $summary['next']
2886 ),
2887 );
2888 }
2889
2890 /**
2891 * Format retention label from days.
2892 *
2893 * @param int $days Days.
2894 *
2895 * @return string
2896 */
2897 private static function format_retention_days_label( $days ) {
2898 if ( $days <= 0 ) {
2899 return esc_html__( 'Keep forever', 'mainwp' );
2900 }
2901
2902 return sprintf(
2903 /* translators: %d: days */
2904 _n( '%d day', '%d days', $days, 'mainwp' ),
2905 $days
2906 );
2907 }
2908
2909 /**
2910 * Format monitoring type label.
2911 *
2912 * @param string $type Monitor type.
2913 *
2914 * @return string
2915 */
2916 private static function format_monitor_type_label( $type ) {
2917 switch ( $type ) {
2918 case 'ping':
2919 return esc_html__( 'Ping', 'mainwp' );
2920 case 'keyword':
2921 return esc_html__( 'Keyword Monitoring', 'mainwp' );
2922 default:
2923 return esc_html__( 'HTTP(s)', 'mainwp' );
2924 }
2925 }
2926
2927 /**
2928 * Format log retention label.
2929 *
2930 * @param int $seconds Retention in seconds.
2931 *
2932 * @return string
2933 */
2934 private static function format_log_retention_label( $seconds ) {
2935 if ( $seconds <= 0 ) {
2936 return esc_html__( 'Forever', 'mainwp' );
2937 }
2938 if ( 3 * YEAR_IN_SECONDS === $seconds ) {
2939 return esc_html__( 'Three years', 'mainwp' );
2940 }
2941 if ( 2 * YEAR_IN_SECONDS === $seconds ) {
2942 return esc_html__( 'Two years', 'mainwp' );
2943 }
2944 if ( YEAR_IN_SECONDS === $seconds ) {
2945 return esc_html__( 'Year', 'mainwp' );
2946 }
2947 if ( 6 * MONTH_IN_SECONDS === $seconds ) {
2948 return esc_html__( 'Half a year', 'mainwp' );
2949 }
2950 if ( 3 * MONTH_IN_SECONDS === $seconds ) {
2951 return esc_html__( 'Three months', 'mainwp' );
2952 }
2953 if ( 2 * MONTH_IN_SECONDS === $seconds ) {
2954 return esc_html__( 'Two months', 'mainwp' );
2955 }
2956 if ( MONTH_IN_SECONDS === $seconds ) {
2957 return esc_html__( 'One month', 'mainwp' );
2958 }
2959
2960 return sprintf(
2961 /* translators: %d: days */
2962 _n( '%d day', '%d days', max( 1, (int) floor( $seconds / DAY_IN_SECONDS ) ), 'mainwp' ),
2963 max( 1, (int) floor( $seconds / DAY_IN_SECONDS ) )
2964 );
2965 }
2966 }
2967