wp/wp-admin/includes/class-wp-site-health.php
changeset 18 be944660c56a
parent 16 a86126ab1dd4
child 19 3d72ae0968f4
equal deleted inserted replaced
17:34716fd837a4 18:be944660c56a
    48 
    48 
    49 		add_filter( 'admin_body_class', array( $this, 'admin_body_class' ) );
    49 		add_filter( 'admin_body_class', array( $this, 'admin_body_class' ) );
    50 
    50 
    51 		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
    51 		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
    52 		add_action( 'wp_site_health_scheduled_check', array( $this, 'wp_cron_scheduled_check' ) );
    52 		add_action( 'wp_site_health_scheduled_check', array( $this, 'wp_cron_scheduled_check' ) );
       
    53 
       
    54 		add_action( 'site_health_tab_content', array( $this, 'show_site_health_tab' ) );
       
    55 	}
       
    56 
       
    57 	/**
       
    58 	 * Output the content of a tab in the Site Health screen.
       
    59 	 *
       
    60 	 * @since 5.8.0
       
    61 	 *
       
    62 	 * @param string $tab Slug of the current tab being displayed.
       
    63 	 */
       
    64 	public function show_site_health_tab( $tab ) {
       
    65 		if ( 'debug' === $tab ) {
       
    66 			require_once ABSPATH . '/wp-admin/site-health-info.php';
       
    67 		}
    53 	}
    68 	}
    54 
    69 
    55 	/**
    70 	/**
    56 	 * Return an instance of the WP_Site_Health class, or create one if none exist yet.
    71 	 * Return an instance of the WP_Site_Health class, or create one if none exist yet.
    57 	 *
    72 	 *
   101 			$issue_counts = json_decode( $issue_counts );
   116 			$issue_counts = json_decode( $issue_counts );
   102 
   117 
   103 			$health_check_js_variables['site_status']['issues'] = $issue_counts;
   118 			$health_check_js_variables['site_status']['issues'] = $issue_counts;
   104 		}
   119 		}
   105 
   120 
   106 		if ( 'site-health' === $screen->id && ! isset( $_GET['tab'] ) ) {
   121 		if ( 'site-health' === $screen->id && ( ! isset( $_GET['tab'] ) || empty( $_GET['tab'] ) ) ) {
   107 			$tests = WP_Site_Health::get_tests();
   122 			$tests = WP_Site_Health::get_tests();
   108 
   123 
   109 			// Don't run https test on localhost.
   124 			// Don't run https test on development environments.
   110 			if ( 'localhost' === preg_replace( '|https?://|', '', get_site_url() ) ) {
   125 			if ( $this->is_development_environment() ) {
   111 				unset( $tests['direct']['https_status'] );
   126 				unset( $tests['async']['https_status'] );
   112 			}
   127 			}
   113 
   128 
   114 			foreach ( $tests['direct'] as $test ) {
   129 			foreach ( $tests['direct'] as $test ) {
   115 				if ( is_string( $test['test'] ) ) {
   130 				if ( is_string( $test['test'] ) ) {
   116 					$test_function = sprintf(
   131 					$test_function = sprintf(
   131 
   146 
   132 			foreach ( $tests['async'] as $test ) {
   147 			foreach ( $tests['async'] as $test ) {
   133 				if ( is_string( $test['test'] ) ) {
   148 				if ( is_string( $test['test'] ) ) {
   134 					$health_check_js_variables['site_status']['async'][] = array(
   149 					$health_check_js_variables['site_status']['async'][] = array(
   135 						'test'      => $test['test'],
   150 						'test'      => $test['test'],
       
   151 						'has_rest'  => ( isset( $test['has_rest'] ) ? $test['has_rest'] : false ),
   136 						'completed' => false,
   152 						'completed' => false,
       
   153 						'headers'   => isset( $test['headers'] ) ? $test['headers'] : array(),
   137 					);
   154 					);
   138 				}
   155 				}
   139 			}
   156 			}
   140 		}
   157 		}
   141 
   158 
   150 	 * @param callable $callback
   167 	 * @param callable $callback
   151 	 * @return mixed|void
   168 	 * @return mixed|void
   152 	 */
   169 	 */
   153 	private function perform_test( $callback ) {
   170 	private function perform_test( $callback ) {
   154 		/**
   171 		/**
   155 		 * Filter the output of a finished Site Health test.
   172 		 * Filters the output of a finished Site Health test.
   156 		 *
   173 		 *
   157 		 * @since 5.3.0
   174 		 * @since 5.3.0
   158 		 *
   175 		 *
   159 		 * @param array $test_result {
   176 		 * @param array $test_result {
   160 		 *     An associative array of test result data.
   177 		 *     An associative array of test result data.
   722 			),
   739 			),
   723 			'description' => sprintf(
   740 			'description' => sprintf(
   724 				'<p>%s</p>',
   741 				'<p>%s</p>',
   725 				sprintf(
   742 				sprintf(
   726 					/* translators: %s: The minimum recommended PHP version. */
   743 					/* translators: %s: The minimum recommended PHP version. */
   727 					__( 'PHP is the programming language used to build and maintain WordPress. Newer versions of PHP are faster and more secure, so staying up to date will help your site&#8217;s overall performance and security. The minimum recommended version of PHP is %s.' ),
   744 					__( 'PHP is the programming language used to build and maintain WordPress. Newer versions of PHP are created with increased performance in mind, so you may see a positive effect on your site&#8217;s performance. The minimum recommended version of PHP is %s.' ),
   728 					$response ? $response['recommended_version'] : ''
   745 					$response ? $response['recommended_version'] : ''
   729 				)
   746 				)
   730 			),
   747 			),
   731 			'actions'     => sprintf(
   748 			'actions'     => sprintf(
   732 				'<p><a href="%s" target="_blank" rel="noopener noreferrer">%s <span class="screen-reader-text">%s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>',
   749 				'<p><a href="%s" target="_blank" rel="noopener">%s <span class="screen-reader-text">%s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>',
   733 				esc_url( wp_get_update_php_url() ),
   750 				esc_url( wp_get_update_php_url() ),
   734 				__( 'Learn more about updating PHP' ),
   751 				__( 'Learn more about updating PHP' ),
   735 				/* translators: Accessibility text. */
   752 				/* translators: Accessibility text. */
   736 				__( '(opens in a new tab)' )
   753 				__( '(opens in a new tab)' )
   737 			),
   754 			),
   839 				sprintf(
   856 				sprintf(
   840 					/* translators: 1: Link to the hosting group page about recommended PHP modules. 2: Additional link attributes. 3: Accessibility text. */
   857 					/* translators: 1: Link to the hosting group page about recommended PHP modules. 2: Additional link attributes. 3: Accessibility text. */
   841 					__( 'The WordPress Hosting Team maintains a list of those modules, both recommended and required, in <a href="%1$s" %2$s>the team handbook%3$s</a>.' ),
   858 					__( 'The WordPress Hosting Team maintains a list of those modules, both recommended and required, in <a href="%1$s" %2$s>the team handbook%3$s</a>.' ),
   842 					/* translators: Localized team handbook, if one exists. */
   859 					/* translators: Localized team handbook, if one exists. */
   843 					esc_url( __( 'https://make.wordpress.org/hosting/handbook/handbook/server-environment/#php-extensions' ) ),
   860 					esc_url( __( 'https://make.wordpress.org/hosting/handbook/handbook/server-environment/#php-extensions' ) ),
   844 					'target="_blank" rel="noopener noreferrer"',
   861 					'target="_blank" rel="noopener"',
   845 					sprintf(
   862 					sprintf(
   846 						' <span class="screen-reader-text">%s</span><span aria-hidden="true" class="dashicons dashicons-external"></span>',
   863 						' <span class="screen-reader-text">%s</span><span aria-hidden="true" class="dashicons dashicons-external"></span>',
   847 						/* translators: Accessibility text. */
   864 						/* translators: Accessibility text. */
   848 						__( '(opens in a new tab)' )
   865 						__( '(opens in a new tab)' )
   849 					)
   866 					)
  1156 			'description' => sprintf(
  1173 			'description' => sprintf(
  1157 				'<p>%s</p>',
  1174 				'<p>%s</p>',
  1158 				__( 'The SQL server is a required piece of software for the database WordPress uses to store all your site&#8217;s content and settings.' )
  1175 				__( 'The SQL server is a required piece of software for the database WordPress uses to store all your site&#8217;s content and settings.' )
  1159 			),
  1176 			),
  1160 			'actions'     => sprintf(
  1177 			'actions'     => sprintf(
  1161 				'<p><a href="%s" target="_blank" rel="noopener noreferrer">%s <span class="screen-reader-text">%s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>',
  1178 				'<p><a href="%s" target="_blank" rel="noopener">%s <span class="screen-reader-text">%s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>',
  1162 				/* translators: Localized version of WordPress requirements if one exists. */
  1179 				/* translators: Localized version of WordPress requirements if one exists. */
  1163 				esc_url( __( 'https://wordpress.org/about/requirements/' ) ),
  1180 				esc_url( __( 'https://wordpress.org/about/requirements/' ) ),
  1164 				__( 'Learn more about what WordPress requires to run.' ),
  1181 				__( 'Learn more about what WordPress requires to run.' ),
  1165 				/* translators: Accessibility text. */
  1182 				/* translators: Accessibility text. */
  1166 				__( '(opens in a new tab)' )
  1183 				__( '(opens in a new tab)' )
  1393 					)
  1410 					)
  1394 				)
  1411 				)
  1395 			);
  1412 			);
  1396 
  1413 
  1397 			$result['actions'] = sprintf(
  1414 			$result['actions'] = sprintf(
  1398 				'<p><a href="%s" target="_blank" rel="noopener noreferrer">%s <span class="screen-reader-text">%s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>',
  1415 				'<p><a href="%s" target="_blank" rel="noopener">%s <span class="screen-reader-text">%s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>',
  1399 				/* translators: Localized Support reference. */
  1416 				/* translators: Localized Support reference. */
  1400 				esc_url( __( 'https://wordpress.org/support' ) ),
  1417 				esc_url( __( 'https://wordpress.org/support' ) ),
  1401 				__( 'Get help resolving this issue.' ),
  1418 				__( 'Get help resolving this issue.' ),
  1402 				/* translators: Accessibility text. */
  1419 				/* translators: Accessibility text. */
  1403 				__( '(opens in a new tab)' )
  1420 				__( '(opens in a new tab)' )
  1431 			'description' => sprintf(
  1448 			'description' => sprintf(
  1432 				'<p>%s</p>',
  1449 				'<p>%s</p>',
  1433 				__( 'Debug mode is often enabled to gather more details about an error or site failure, but may contain sensitive information which should not be available on a publicly available website.' )
  1450 				__( 'Debug mode is often enabled to gather more details about an error or site failure, but may contain sensitive information which should not be available on a publicly available website.' )
  1434 			),
  1451 			),
  1435 			'actions'     => sprintf(
  1452 			'actions'     => sprintf(
  1436 				'<p><a href="%s" target="_blank" rel="noopener noreferrer">%s <span class="screen-reader-text">%s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>',
  1453 				'<p><a href="%s" target="_blank" rel="noopener">%s <span class="screen-reader-text">%s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>',
  1437 				/* translators: Documentation explaining debugging in WordPress. */
  1454 				/* translators: Documentation explaining debugging in WordPress. */
  1438 				esc_url( __( 'https://wordpress.org/support/article/debugging-in-wordpress/' ) ),
  1455 				esc_url( __( 'https://wordpress.org/support/article/debugging-in-wordpress/' ) ),
  1439 				__( 'Learn more about debugging in WordPress.' ),
  1456 				__( 'Learn more about debugging in WordPress.' ),
  1440 				/* translators: Accessibility text. */
  1457 				/* translators: Accessibility text. */
  1441 				__( '(opens in a new tab)' )
  1458 				__( '(opens in a new tab)' )
  1461 
  1478 
  1462 			if ( defined( 'WP_DEBUG_DISPLAY' ) && WP_DEBUG_DISPLAY ) {
  1479 			if ( defined( 'WP_DEBUG_DISPLAY' ) && WP_DEBUG_DISPLAY ) {
  1463 				$result['label'] = __( 'Your site is set to display errors to site visitors' );
  1480 				$result['label'] = __( 'Your site is set to display errors to site visitors' );
  1464 
  1481 
  1465 				$result['status'] = 'critical';
  1482 				$result['status'] = 'critical';
       
  1483 
       
  1484 				// On development environments, set the status to recommended.
       
  1485 				if ( $this->is_development_environment() ) {
       
  1486 					$result['status'] = 'recommended';
       
  1487 				}
  1466 
  1488 
  1467 				$result['description'] .= sprintf(
  1489 				$result['description'] .= sprintf(
  1468 					'<p>%s</p>',
  1490 					'<p>%s</p>',
  1469 					sprintf(
  1491 					sprintf(
  1470 						/* translators: 1: WP_DEBUG_DISPLAY, 2: WP_DEBUG */
  1492 						/* translators: 1: WP_DEBUG_DISPLAY, 2: WP_DEBUG */
  1484 	 *
  1506 	 *
  1485 	 * Many sites have varying degrees of HTTPS support, the most common of which is sites that have it
  1507 	 * Many sites have varying degrees of HTTPS support, the most common of which is sites that have it
  1486 	 * enabled, but only if you visit the right site address.
  1508 	 * enabled, but only if you visit the right site address.
  1487 	 *
  1509 	 *
  1488 	 * @since 5.2.0
  1510 	 * @since 5.2.0
       
  1511 	 * @since 5.7.0 Updated to rely on {@see wp_is_using_https()} and {@see wp_is_https_supported()}.
  1489 	 *
  1512 	 *
  1490 	 * @return array The test results.
  1513 	 * @return array The test results.
  1491 	 */
  1514 	 */
  1492 	public function get_test_https_status() {
  1515 	public function get_test_https_status() {
       
  1516 		// Enforce fresh HTTPS detection results. This is normally invoked by using cron,
       
  1517 		// but for Site Health it should always rely on the latest results.
       
  1518 		wp_update_https_detection_errors();
       
  1519 
       
  1520 		$default_update_url = wp_get_default_update_https_url();
       
  1521 
  1493 		$result = array(
  1522 		$result = array(
  1494 			'label'       => __( 'Your website is using an active HTTPS connection.' ),
  1523 			'label'       => __( 'Your website is using an active HTTPS connection' ),
  1495 			'status'      => 'good',
  1524 			'status'      => 'good',
  1496 			'badge'       => array(
  1525 			'badge'       => array(
  1497 				'label' => __( 'Security' ),
  1526 				'label' => __( 'Security' ),
  1498 				'color' => 'blue',
  1527 				'color' => 'blue',
  1499 			),
  1528 			),
  1500 			'description' => sprintf(
  1529 			'description' => sprintf(
  1501 				'<p>%s</p>',
  1530 				'<p>%s</p>',
  1502 				__( 'An HTTPS connection is a more secure way of browsing the web. Many services now have HTTPS as a requirement. HTTPS allows you to take advantage of new features that can increase site speed, improve search rankings, and gain the trust of your visitors by helping to protect their online privacy.' )
  1531 				__( 'An HTTPS connection is a more secure way of browsing the web. Many services now have HTTPS as a requirement. HTTPS allows you to take advantage of new features that can increase site speed, improve search rankings, and gain the trust of your visitors by helping to protect their online privacy.' )
  1503 			),
  1532 			),
  1504 			'actions'     => sprintf(
  1533 			'actions'     => sprintf(
  1505 				'<p><a href="%s" target="_blank" rel="noopener noreferrer">%s <span class="screen-reader-text">%s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>',
  1534 				'<p><a href="%s" target="_blank" rel="noopener">%s<span class="screen-reader-text"> %s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>',
  1506 				/* translators: Documentation explaining HTTPS and why it should be used. */
  1535 				esc_url( $default_update_url ),
  1507 				esc_url( __( 'https://wordpress.org/support/article/why-should-i-use-https/' ) ),
       
  1508 				__( 'Learn more about why you should use HTTPS' ),
  1536 				__( 'Learn more about why you should use HTTPS' ),
  1509 				/* translators: Accessibility text. */
  1537 				/* translators: Accessibility text. */
  1510 				__( '(opens in a new tab)' )
  1538 				__( '(opens in a new tab)' )
  1511 			),
  1539 			),
  1512 			'test'        => 'https_status',
  1540 			'test'        => 'https_status',
  1513 		);
  1541 		);
  1514 
  1542 
  1515 		if ( is_ssl() ) {
  1543 		if ( ! wp_is_using_https() ) {
  1516 			$wp_url   = get_bloginfo( 'wpurl' );
  1544 			// If the website is not using HTTPS, provide more information
  1517 			$site_url = get_bloginfo( 'url' );
  1545 			// about whether it is supported and how it can be enabled.
  1518 
  1546 			$result['status'] = 'recommended';
  1519 			if ( 'https' !== substr( $wp_url, 0, 5 ) || 'https' !== substr( $site_url, 0, 5 ) ) {
  1547 			$result['label']  = __( 'Your website does not use HTTPS' );
  1520 				$result['status'] = 'recommended';
  1548 
  1521 
  1549 			if ( wp_is_site_url_using_https() ) {
  1522 				$result['label'] = __( 'Only parts of your site are using HTTPS' );
  1550 				if ( is_ssl() ) {
  1523 
  1551 					$result['description'] = sprintf(
  1524 				$result['description'] = sprintf(
  1552 						'<p>%s</p>',
       
  1553 						sprintf(
       
  1554 							/* translators: %s: URL to Settings > General > Site Address. */
       
  1555 							__( 'You are accessing this website using HTTPS, but your <a href="%s">Site Address</a> is not set up to use HTTPS by default.' ),
       
  1556 							esc_url( admin_url( 'options-general.php' ) . '#home' )
       
  1557 						)
       
  1558 					);
       
  1559 				} else {
       
  1560 					$result['description'] = sprintf(
       
  1561 						'<p>%s</p>',
       
  1562 						sprintf(
       
  1563 							/* translators: %s: URL to Settings > General > Site Address. */
       
  1564 							__( 'Your <a href="%s">Site Address</a> is not set up to use HTTPS.' ),
       
  1565 							esc_url( admin_url( 'options-general.php' ) . '#home' )
       
  1566 						)
       
  1567 					);
       
  1568 				}
       
  1569 			} else {
       
  1570 				if ( is_ssl() ) {
       
  1571 					$result['description'] = sprintf(
       
  1572 						'<p>%s</p>',
       
  1573 						sprintf(
       
  1574 							/* translators: 1: URL to Settings > General > WordPress Address, 2: URL to Settings > General > Site Address. */
       
  1575 							__( 'You are accessing this website using HTTPS, but your <a href="%1$s">WordPress Address</a> and <a href="%2$s">Site Address</a> are not set up to use HTTPS by default.' ),
       
  1576 							esc_url( admin_url( 'options-general.php' ) . '#siteurl' ),
       
  1577 							esc_url( admin_url( 'options-general.php' ) . '#home' )
       
  1578 						)
       
  1579 					);
       
  1580 				} else {
       
  1581 					$result['description'] = sprintf(
       
  1582 						'<p>%s</p>',
       
  1583 						sprintf(
       
  1584 							/* translators: 1: URL to Settings > General > WordPress Address, 2: URL to Settings > General > Site Address. */
       
  1585 							__( 'Your <a href="%1$s">WordPress Address</a> and <a href="%2$s">Site Address</a> are not set up to use HTTPS.' ),
       
  1586 							esc_url( admin_url( 'options-general.php' ) . '#siteurl' ),
       
  1587 							esc_url( admin_url( 'options-general.php' ) . '#home' )
       
  1588 						)
       
  1589 					);
       
  1590 				}
       
  1591 			}
       
  1592 
       
  1593 			if ( wp_is_https_supported() ) {
       
  1594 				$result['description'] .= sprintf(
  1525 					'<p>%s</p>',
  1595 					'<p>%s</p>',
  1526 					sprintf(
  1596 					__( 'HTTPS is already supported for your website.' )
  1527 						/* translators: %s: URL to General Settings screen. */
       
  1528 						__( 'You are accessing this website using HTTPS, but your <a href="%s">WordPress Address</a> is not set up to use HTTPS by default.' ),
       
  1529 						esc_url( admin_url( 'options-general.php' ) )
       
  1530 					)
       
  1531 				);
  1597 				);
  1532 
  1598 
  1533 				$result['actions'] .= sprintf(
  1599 				if ( defined( 'WP_HOME' ) || defined( 'WP_SITEURL' ) ) {
  1534 					'<p><a href="%s">%s</a></p>',
  1600 					$result['description'] .= sprintf(
  1535 					esc_url( admin_url( 'options-general.php' ) ),
  1601 						'<p>%s</p>',
  1536 					__( 'Update your site addresses' )
  1602 						sprintf(
  1537 				);
  1603 							/* translators: 1: wp-config.php, 2: WP_HOME, 3: WP_SITEURL */
  1538 			}
  1604 							__( 'However, your WordPress Address is currently controlled by a PHP constant and therefore cannot be updated. You need to edit your %1$s and remove or update the definitions of %2$s and %3$s.' ),
  1539 		} else {
  1605 							'<code>wp-config.php</code>',
  1540 			$result['status'] = 'recommended';
  1606 							'<code>WP_HOME</code>',
  1541 
  1607 							'<code>WP_SITEURL</code>'
  1542 			$result['label'] = __( 'Your site does not use HTTPS' );
  1608 						)
       
  1609 					);
       
  1610 				} elseif ( current_user_can( 'update_https' ) ) {
       
  1611 					$default_direct_update_url = add_query_arg( 'action', 'update_https', wp_nonce_url( admin_url( 'site-health.php' ), 'wp_update_https' ) );
       
  1612 					$direct_update_url         = wp_get_direct_update_https_url();
       
  1613 
       
  1614 					if ( ! empty( $direct_update_url ) ) {
       
  1615 						$result['actions'] = sprintf(
       
  1616 							'<p class="button-container"><a class="button button-primary" href="%1$s" target="_blank" rel="noopener">%2$s<span class="screen-reader-text"> %3$s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>',
       
  1617 							esc_url( $direct_update_url ),
       
  1618 							__( 'Update your site to use HTTPS' ),
       
  1619 							/* translators: Accessibility text. */
       
  1620 							__( '(opens in a new tab)' )
       
  1621 						);
       
  1622 					} else {
       
  1623 						$result['actions'] = sprintf(
       
  1624 							'<p class="button-container"><a class="button button-primary" href="%1$s">%2$s</a></p>',
       
  1625 							esc_url( $default_direct_update_url ),
       
  1626 							__( 'Update your site to use HTTPS' )
       
  1627 						);
       
  1628 					}
       
  1629 				}
       
  1630 			} else {
       
  1631 				// If host-specific "Update HTTPS" URL is provided, include a link.
       
  1632 				$update_url = wp_get_update_https_url();
       
  1633 				if ( $update_url !== $default_update_url ) {
       
  1634 					$result['description'] .= sprintf(
       
  1635 						'<p><a href="%s" target="_blank" rel="noopener">%s<span class="screen-reader-text"> %s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>',
       
  1636 						esc_url( $update_url ),
       
  1637 						__( 'Talk to your web host about supporting HTTPS for your website.' ),
       
  1638 						/* translators: Accessibility text. */
       
  1639 						__( '(opens in a new tab)' )
       
  1640 					);
       
  1641 				} else {
       
  1642 					$result['description'] .= sprintf(
       
  1643 						'<p>%s</p>',
       
  1644 						__( 'Talk to your web host about supporting HTTPS for your website.' )
       
  1645 					);
       
  1646 				}
       
  1647 			}
  1543 		}
  1648 		}
  1544 
  1649 
  1545 		return $result;
  1650 		return $result;
  1546 	}
  1651 	}
  1547 
  1652 
  1852 
  1957 
  1853 		if ( defined( 'WP_ACCESSIBLE_HOSTS' ) ) {
  1958 		if ( defined( 'WP_ACCESSIBLE_HOSTS' ) ) {
  1854 			$hosts = explode( ',', WP_ACCESSIBLE_HOSTS );
  1959 			$hosts = explode( ',', WP_ACCESSIBLE_HOSTS );
  1855 		}
  1960 		}
  1856 
  1961 
  1857 		if ( $blocked && 0 === sizeof( $hosts ) ) {
  1962 		if ( $blocked && 0 === count( $hosts ) ) {
  1858 			$result['status'] = 'critical';
  1963 			$result['status'] = 'critical';
  1859 
  1964 
  1860 			$result['label'] = __( 'HTTP requests are blocked' );
  1965 			$result['label'] = __( 'HTTP requests are blocked' );
  1861 
  1966 
  1862 			$result['description'] .= sprintf(
  1967 			$result['description'] .= sprintf(
  1867 					'<code>WP_HTTP_BLOCK_EXTERNAL</code>'
  1972 					'<code>WP_HTTP_BLOCK_EXTERNAL</code>'
  1868 				)
  1973 				)
  1869 			);
  1974 			);
  1870 		}
  1975 		}
  1871 
  1976 
  1872 		if ( $blocked && 0 < sizeof( $hosts ) ) {
  1977 		if ( $blocked && 0 < count( $hosts ) ) {
  1873 			$result['status'] = 'recommended';
  1978 			$result['status'] = 'recommended';
  1874 
  1979 
  1875 			$result['label'] = __( 'HTTP requests are partially blocked' );
  1980 			$result['label'] = __( 'HTTP requests are partially blocked' );
  1876 
  1981 
  1877 			$result['description'] .= sprintf(
  1982 			$result['description'] .= sprintf(
  2054 				/* translators: 1: post_max_size, 2: upload_max_filesize */
  2159 				/* translators: 1: post_max_size, 2: upload_max_filesize */
  2055 				__( 'The "%1$s" value is smaller than "%2$s".' ),
  2160 				__( 'The "%1$s" value is smaller than "%2$s".' ),
  2056 				'post_max_size',
  2161 				'post_max_size',
  2057 				'upload_max_filesize'
  2162 				'upload_max_filesize'
  2058 			);
  2163 			);
  2059 			$result['status']      = 'recommended';
  2164 			$result['status'] = 'recommended';
  2060 			$result['description'] = sprintf(
  2165 
  2061 				'<p>%s</p>',
  2166 			if ( 0 === wp_convert_hr_to_bytes( $post_max_size ) ) {
  2062 				sprintf(
  2167 				$result['description'] = sprintf(
  2063 					/* translators: 1: post_max_size, 2: upload_max_filesize */
  2168 					'<p>%s</p>',
  2064 					__( 'The setting for %1$s is smaller than %2$s, this could cause some problems when trying to upload files.' ),
  2169 					sprintf(
  2065 					'<code>post_max_size</code>',
  2170 						/* translators: 1: post_max_size, 2: upload_max_filesize */
  2066 					'<code>upload_max_filesize</code>'
  2171 						__( 'The setting for %1$s is currently configured as 0, this could cause some problems when trying to upload files through plugin or theme features that rely on various upload methods. It is recommended to configure this setting to a fixed value, ideally matching the value of %2$s, as some upload methods read the value 0 as either unlimited, or disabled.' ),
  2067 				)
  2172 						'<code>post_max_size</code>',
  2068 			);
  2173 						'<code>upload_max_filesize</code>'
       
  2174 					)
       
  2175 				);
       
  2176 			} else {
       
  2177 				$result['description'] = sprintf(
       
  2178 					'<p>%s</p>',
       
  2179 					sprintf(
       
  2180 						/* translators: 1: post_max_size, 2: upload_max_filesize */
       
  2181 						__( 'The setting for %1$s is smaller than %2$s, this could cause some problems when trying to upload files.' ),
       
  2182 						'<code>post_max_size</code>',
       
  2183 						'<code>upload_max_filesize</code>'
       
  2184 					)
       
  2185 				);
       
  2186 			}
       
  2187 
  2069 			return $result;
  2188 			return $result;
       
  2189 		}
       
  2190 
       
  2191 		return $result;
       
  2192 	}
       
  2193 
       
  2194 	/**
       
  2195 	 * Tests if the Authorization header has the expected values.
       
  2196 	 *
       
  2197 	 * @since 5.6.0
       
  2198 	 *
       
  2199 	 * @return array
       
  2200 	 */
       
  2201 	public function get_test_authorization_header() {
       
  2202 		$result = array(
       
  2203 			'label'       => __( 'The Authorization header is working as expected.' ),
       
  2204 			'status'      => 'good',
       
  2205 			'badge'       => array(
       
  2206 				'label' => __( 'Security' ),
       
  2207 				'color' => 'blue',
       
  2208 			),
       
  2209 			'description' => sprintf(
       
  2210 				'<p>%s</p>',
       
  2211 				__( 'The Authorization header comes from the third-party applications you approve. Without it, those apps cannot connect to your site.' )
       
  2212 			),
       
  2213 			'actions'     => '',
       
  2214 			'test'        => 'authorization_header',
       
  2215 		);
       
  2216 
       
  2217 		if ( ! isset( $_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'] ) ) {
       
  2218 			$result['label'] = __( 'The authorization header is missing.' );
       
  2219 		} elseif ( 'user' !== $_SERVER['PHP_AUTH_USER'] || 'pwd' !== $_SERVER['PHP_AUTH_PW'] ) {
       
  2220 			$result['label'] = __( 'The authorization header is invalid.' );
       
  2221 		} else {
       
  2222 			return $result;
       
  2223 		}
       
  2224 
       
  2225 		$result['status'] = 'recommended';
       
  2226 
       
  2227 		if ( ! function_exists( 'got_mod_rewrite' ) ) {
       
  2228 			require_once ABSPATH . 'wp-admin/includes/misc.php';
       
  2229 		}
       
  2230 
       
  2231 		if ( got_mod_rewrite() ) {
       
  2232 			$result['actions'] .= sprintf(
       
  2233 				'<p><a href="%s">%s</a></p>',
       
  2234 				esc_url( admin_url( 'options-permalink.php' ) ),
       
  2235 				__( 'Flush permalinks' )
       
  2236 			);
       
  2237 		} else {
       
  2238 			$result['actions'] .= sprintf(
       
  2239 				'<p><a href="%s" target="_blank" rel="noopener">%s <span class="screen-reader-text">%s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>',
       
  2240 				__( 'https://developer.wordpress.org/rest-api/frequently-asked-questions/#why-is-authentication-not-working' ),
       
  2241 				__( 'Learn how to configure the Authorization header.' ),
       
  2242 				/* translators: Accessibility text. */
       
  2243 				__( '(opens in a new tab)' )
       
  2244 			);
  2070 		}
  2245 		}
  2071 
  2246 
  2072 		return $result;
  2247 		return $result;
  2073 	}
  2248 	}
  2074 
  2249 
  2078 	 * Each site status test is defined here, they may be `direct` tests, that run on page load, or `async` tests
  2253 	 * Each site status test is defined here, they may be `direct` tests, that run on page load, or `async` tests
  2079 	 * which will run later down the line via JavaScript calls to improve page performance and hopefully also user
  2254 	 * which will run later down the line via JavaScript calls to improve page performance and hopefully also user
  2080 	 * experiences.
  2255 	 * experiences.
  2081 	 *
  2256 	 *
  2082 	 * @since 5.2.0
  2257 	 * @since 5.2.0
       
  2258 	 * @since 5.6.0 Added support for `has_rest` and `permissions`.
  2083 	 *
  2259 	 *
  2084 	 * @return array The list of tests to run.
  2260 	 * @return array The list of tests to run.
  2085 	 */
  2261 	 */
  2086 	public static function get_tests() {
  2262 	public static function get_tests() {
  2087 		$tests = array(
  2263 		$tests = array(
  2120 				),
  2296 				),
  2121 				'utf8mb4_support'           => array(
  2297 				'utf8mb4_support'           => array(
  2122 					'label' => __( 'MySQL utf8mb4 support' ),
  2298 					'label' => __( 'MySQL utf8mb4 support' ),
  2123 					'test'  => 'utf8mb4_support',
  2299 					'test'  => 'utf8mb4_support',
  2124 				),
  2300 				),
  2125 				'https_status'              => array(
       
  2126 					'label' => __( 'HTTPS status' ),
       
  2127 					'test'  => 'https_status',
       
  2128 				),
       
  2129 				'ssl_support'               => array(
  2301 				'ssl_support'               => array(
  2130 					'label' => __( 'Secure communication' ),
  2302 					'label' => __( 'Secure communication' ),
  2131 					'test'  => 'ssl_support',
  2303 					'test'  => 'ssl_support',
  2132 				),
  2304 				),
  2133 				'scheduled_events'          => array(
  2305 				'scheduled_events'          => array(
  2135 					'test'  => 'scheduled_events',
  2307 					'test'  => 'scheduled_events',
  2136 				),
  2308 				),
  2137 				'http_requests'             => array(
  2309 				'http_requests'             => array(
  2138 					'label' => __( 'HTTP Requests' ),
  2310 					'label' => __( 'HTTP Requests' ),
  2139 					'test'  => 'http_requests',
  2311 					'test'  => 'http_requests',
       
  2312 				),
       
  2313 				'rest_availability'         => array(
       
  2314 					'label'     => __( 'REST API availability' ),
       
  2315 					'test'      => 'rest_availability',
       
  2316 					'skip_cron' => true,
  2140 				),
  2317 				),
  2141 				'debug_enabled'             => array(
  2318 				'debug_enabled'             => array(
  2142 					'label' => __( 'Debugging enabled' ),
  2319 					'label' => __( 'Debugging enabled' ),
  2143 					'test'  => 'is_in_debug_mode',
  2320 					'test'  => 'is_in_debug_mode',
  2144 				),
  2321 				),
  2151 					'test'  => 'plugin_theme_auto_updates',
  2328 					'test'  => 'plugin_theme_auto_updates',
  2152 				),
  2329 				),
  2153 			),
  2330 			),
  2154 			'async'  => array(
  2331 			'async'  => array(
  2155 				'dotorg_communication' => array(
  2332 				'dotorg_communication' => array(
  2156 					'label' => __( 'Communication with WordPress.org' ),
  2333 					'label'             => __( 'Communication with WordPress.org' ),
  2157 					'test'  => 'dotorg_communication',
  2334 					'test'              => rest_url( 'wp-site-health/v1/tests/dotorg-communication' ),
       
  2335 					'has_rest'          => true,
       
  2336 					'async_direct_test' => array( WP_Site_Health::get_instance(), 'get_test_dotorg_communication' ),
  2158 				),
  2337 				),
  2159 				'background_updates'   => array(
  2338 				'background_updates'   => array(
  2160 					'label' => __( 'Background updates' ),
  2339 					'label'             => __( 'Background updates' ),
  2161 					'test'  => 'background_updates',
  2340 					'test'              => rest_url( 'wp-site-health/v1/tests/background-updates' ),
       
  2341 					'has_rest'          => true,
       
  2342 					'async_direct_test' => array( WP_Site_Health::get_instance(), 'get_test_background_updates' ),
  2162 				),
  2343 				),
  2163 				'loopback_requests'    => array(
  2344 				'loopback_requests'    => array(
  2164 					'label' => __( 'Loopback request' ),
  2345 					'label'             => __( 'Loopback request' ),
  2165 					'test'  => 'loopback_requests',
  2346 					'test'              => rest_url( 'wp-site-health/v1/tests/loopback-requests' ),
       
  2347 					'has_rest'          => true,
       
  2348 					'async_direct_test' => array( WP_Site_Health::get_instance(), 'get_test_loopback_requests' ),
  2166 				),
  2349 				),
  2167 			),
  2350 				'https_status'         => array(
  2168 		);
  2351 					'label'             => __( 'HTTPS status' ),
  2169 
  2352 					'test'              => rest_url( 'wp-site-health/v1/tests/https-status' ),
  2170 		// Conditionally include REST rules if the function for it exists.
  2353 					'has_rest'          => true,
  2171 		if ( function_exists( 'rest_url' ) ) {
  2354 					'async_direct_test' => array( WP_Site_Health::get_instance(), 'get_test_https_status' ),
  2172 			$tests['direct']['rest_availability'] = array(
  2355 				),
  2173 				'label' => __( 'REST API availability' ),
  2356 			),
  2174 				'test'  => 'rest_availability',
  2357 		);
       
  2358 
       
  2359 		// Conditionally include Authorization header test if the site isn't protected by Basic Auth.
       
  2360 		if ( ! wp_is_site_protected_by_basic_auth() ) {
       
  2361 			$tests['async']['authorization_header'] = array(
       
  2362 				'label'     => __( 'Authorization header' ),
       
  2363 				'test'      => rest_url( 'wp-site-health/v1/tests/authorization-header' ),
       
  2364 				'has_rest'  => true,
       
  2365 				'headers'   => array( 'Authorization' => 'Basic ' . base64_encode( 'user:pwd' ) ),
       
  2366 				'skip_cron' => true,
  2175 			);
  2367 			);
  2176 		}
  2368 		}
  2177 
  2369 
  2178 		/**
  2370 		/**
  2179 		 * Add or modify which site status tests are run on a site.
  2371 		 * Add or modify which site status tests are run on a site.
  2187 		 *
  2379 		 *
  2188 		 * Tests may be added either as direct, or asynchronous ones. Any test that may require some time
  2380 		 * Tests may be added either as direct, or asynchronous ones. Any test that may require some time
  2189 		 * to complete should run asynchronously, to avoid extended loading periods within wp-admin.
  2381 		 * to complete should run asynchronously, to avoid extended loading periods within wp-admin.
  2190 		 *
  2382 		 *
  2191 		 * @since 5.2.0
  2383 		 * @since 5.2.0
       
  2384 		 * @since 5.6.0 Added the `async_direct_test` array key.
       
  2385 		 *              Added the `skip_cron` array key.
  2192 		 *
  2386 		 *
  2193 		 * @param array $test_type {
  2387 		 * @param array $test_type {
  2194 		 *     An associative array, where the `$test_type` is either `direct` or
  2388 		 *     An associative array, where the `$test_type` is either `direct` or
  2195 		 *     `async`, to declare if the test should run via Ajax calls after page load.
  2389 		 *     `async`, to declare if the test should run via Ajax calls after page load.
  2196 		 *
  2390 		 *
  2197 		 *     @type array $identifier {
  2391 		 *     @type array $identifier {
  2198 		 *         `$identifier` should be a unique identifier for the test that should run.
  2392 		 *         `$identifier` should be a unique identifier for the test that should run.
  2199 		 *         Plugins and themes are encouraged to prefix test identifiers with their slug
  2393 		 *         Plugins and themes are encouraged to prefix test identifiers with their slug
  2200 		 *         to avoid any collisions between tests.
  2394 		 *         to avoid any collisions between tests.
  2201 		 *
  2395 		 *
  2202 		 *         @type string $label A friendly label for your test to identify it by.
  2396 		 *         @type string   $label             A friendly label for your test to identify it by.
  2203 		 *         @type mixed  $test  A callable to perform a direct test, or a string Ajax action to be called
  2397 		 *         @type mixed    $test              A callable to perform a direct test, or a string AJAX action
  2204 		 *                             to perform an async test.
  2398 		 *                                           to be called to perform an async test.
       
  2399 		 *         @type boolean  $has_rest          Optional. Denote if `$test` has a REST API endpoint.
       
  2400 		 *         @type boolean  $skip_cron         Whether to skip this test when running as cron.
       
  2401 		 *         @type callable $async_direct_test A manner of directly calling the test marked as asynchronous,
       
  2402 		 *                                           as the scheduled event can not authenticate, and endpoints
       
  2403 		 *                                           may require authentication.
  2205 		 *     }
  2404 		 *     }
  2206 		 * }
  2405 		 * }
  2207 		 */
  2406 		 */
  2208 		$tests = apply_filters( 'site_status_tests', $tests );
  2407 		$tests = apply_filters( 'site_status_tests', $tests );
  2209 
  2408 
  2379 			'package'      => 'https://downloads.wordpress.org/theme/a-fake-theme.9.9.zip',
  2578 			'package'      => 'https://downloads.wordpress.org/theme/a-fake-theme.9.9.zip',
  2380 			'requires'     => '5.0.0',
  2579 			'requires'     => '5.0.0',
  2381 			'requires_php' => '5.6.20',
  2580 			'requires_php' => '5.6.20',
  2382 		);
  2581 		);
  2383 
  2582 
  2384 		$type = 'plugin';
  2583 		$test_plugins_enabled = wp_is_auto_update_forced_for_item( 'plugin', true, $mock_plugin );
  2385 		/** This filter is documented in wp-admin/includes/class-wp-automatic-updater.php */
  2584 		$test_themes_enabled  = wp_is_auto_update_forced_for_item( 'theme', true, $mock_theme );
  2386 		$test_plugins_enabled = apply_filters( "auto_update_{$type}", true, $mock_plugin );
       
  2387 
       
  2388 		$type = 'theme';
       
  2389 		/** This filter is documented in wp-admin/includes/class-wp-automatic-updater.php */
       
  2390 		$test_themes_enabled = apply_filters( "auto_update_{$type}", true, $mock_theme );
       
  2391 
  2585 
  2392 		$ui_enabled_for_plugins = wp_is_auto_update_enabled_for_type( 'plugin' );
  2586 		$ui_enabled_for_plugins = wp_is_auto_update_enabled_for_type( 'plugin' );
  2393 		$ui_enabled_for_themes  = wp_is_auto_update_enabled_for_type( 'theme' );
  2587 		$ui_enabled_for_themes  = wp_is_auto_update_enabled_for_type( 'theme' );
  2394 		$plugin_filter_present  = has_filter( 'auto_update_plugin' );
  2588 		$plugin_filter_present  = has_filter( 'auto_update_plugin' );
  2395 		$theme_filter_present   = has_filter( 'auto_update_theme' );
  2589 		$theme_filter_present   = has_filter( 'auto_update_theme' );
  2437 	 * @since 5.2.0
  2631 	 * @since 5.2.0
  2438 	 *
  2632 	 *
  2439 	 * @return object The test results.
  2633 	 * @return object The test results.
  2440 	 */
  2634 	 */
  2441 	function can_perform_loopback() {
  2635 	function can_perform_loopback() {
       
  2636 		$body    = array( 'site-health' => 'loopback-test' );
  2442 		$cookies = wp_unslash( $_COOKIE );
  2637 		$cookies = wp_unslash( $_COOKIE );
  2443 		$timeout = 10;
  2638 		$timeout = 10;
  2444 		$headers = array(
  2639 		$headers = array(
  2445 			'Cache-Control' => 'no-cache',
  2640 			'Cache-Control' => 'no-cache',
  2446 		);
  2641 		);
  2450 		// Include Basic auth in loopback requests.
  2645 		// Include Basic auth in loopback requests.
  2451 		if ( isset( $_SERVER['PHP_AUTH_USER'] ) && isset( $_SERVER['PHP_AUTH_PW'] ) ) {
  2646 		if ( isset( $_SERVER['PHP_AUTH_USER'] ) && isset( $_SERVER['PHP_AUTH_PW'] ) ) {
  2452 			$headers['Authorization'] = 'Basic ' . base64_encode( wp_unslash( $_SERVER['PHP_AUTH_USER'] ) . ':' . wp_unslash( $_SERVER['PHP_AUTH_PW'] ) );
  2647 			$headers['Authorization'] = 'Basic ' . base64_encode( wp_unslash( $_SERVER['PHP_AUTH_USER'] ) . ':' . wp_unslash( $_SERVER['PHP_AUTH_PW'] ) );
  2453 		}
  2648 		}
  2454 
  2649 
  2455 		$url = admin_url();
  2650 		$url = site_url( 'wp-cron.php' );
  2456 
  2651 
  2457 		$r = wp_remote_get( $url, compact( 'cookies', 'headers', 'timeout', 'sslverify' ) );
  2652 		/*
       
  2653 		 * A post request is used for the wp-cron.php loopback test to cause the file
       
  2654 		 * to finish early without triggering cron jobs. This has two benefits:
       
  2655 		 * - cron jobs are not triggered a second time on the site health page,
       
  2656 		 * - the loopback request finishes sooner providing a quicker result.
       
  2657 		 *
       
  2658 		 * Using a POST request causes the loopback to differ slightly to the standard
       
  2659 		 * GET request WordPress uses for wp-cron.php loopback requests but is close
       
  2660 		 * enough. See https://core.trac.wordpress.org/ticket/52547
       
  2661 		 */
       
  2662 		$r = wp_remote_post( $url, compact( 'body', 'cookies', 'headers', 'timeout', 'sslverify' ) );
  2458 
  2663 
  2459 		if ( is_wp_error( $r ) ) {
  2664 		if ( is_wp_error( $r ) ) {
  2460 			return (object) array(
  2665 			return (object) array(
  2461 				'status'  => 'critical',
  2666 				'status'  => 'critical',
  2462 				'message' => sprintf(
  2667 				'message' => sprintf(
  2517 			'good'        => 0,
  2722 			'good'        => 0,
  2518 			'recommended' => 0,
  2723 			'recommended' => 0,
  2519 			'critical'    => 0,
  2724 			'critical'    => 0,
  2520 		);
  2725 		);
  2521 
  2726 
  2522 		// Don't run https test on localhost.
  2727 		// Don't run https test on development environments.
  2523 		if ( 'localhost' === preg_replace( '|https?://|', '', get_site_url() ) ) {
  2728 		if ( $this->is_development_environment() ) {
  2524 			unset( $tests['direct']['https_status'] );
  2729 			unset( $tests['async']['https_status'] );
  2525 		}
  2730 		}
  2526 
  2731 
  2527 		foreach ( $tests['direct'] as $test ) {
  2732 		foreach ( $tests['direct'] as $test ) {
       
  2733 			if ( ! empty( $test['skip_cron'] ) ) {
       
  2734 				continue;
       
  2735 			}
  2528 
  2736 
  2529 			if ( is_string( $test['test'] ) ) {
  2737 			if ( is_string( $test['test'] ) ) {
  2530 				$test_function = sprintf(
  2738 				$test_function = sprintf(
  2531 					'get_test_%s',
  2739 					'get_test_%s',
  2532 					$test['test']
  2740 					$test['test']
  2542 				$results[] = $this->perform_test( $test['test'] );
  2750 				$results[] = $this->perform_test( $test['test'] );
  2543 			}
  2751 			}
  2544 		}
  2752 		}
  2545 
  2753 
  2546 		foreach ( $tests['async'] as $test ) {
  2754 		foreach ( $tests['async'] as $test ) {
       
  2755 			if ( ! empty( $test['skip_cron'] ) ) {
       
  2756 				continue;
       
  2757 			}
       
  2758 
       
  2759 			// Local endpoints may require authentication, so asynchronous tests can pass a direct test runner as well.
       
  2760 			if ( ! empty( $test['async_direct_test'] ) && is_callable( $test['async_direct_test'] ) ) {
       
  2761 				// This test is callable, do so and continue to the next asynchronous check.
       
  2762 				$results[] = $this->perform_test( $test['async_direct_test'] );
       
  2763 				continue;
       
  2764 			}
       
  2765 
  2547 			if ( is_string( $test['test'] ) ) {
  2766 			if ( is_string( $test['test'] ) ) {
       
  2767 				// Check if this test has a REST API endpoint.
  2548 				if ( isset( $test['has_rest'] ) && $test['has_rest'] ) {
  2768 				if ( isset( $test['has_rest'] ) && $test['has_rest'] ) {
  2549 					$result_fetch = wp_remote_post(
  2769 					$result_fetch = wp_remote_get(
  2550 						rest_url( $test['test'] ),
  2770 						$test['test'],
  2551 						array(
  2771 						array(
  2552 							'body' => array(
  2772 							'body' => array(
  2553 								'_wpnonce' => wp_create_nonce( 'wp_rest' ),
  2773 								'_wpnonce' => wp_create_nonce( 'wp_rest' ),
  2554 							),
  2774 							),
  2555 						)
  2775 						)
  2564 							),
  2784 							),
  2565 						)
  2785 						)
  2566 					);
  2786 					);
  2567 				}
  2787 				}
  2568 
  2788 
  2569 				if ( ! is_wp_error( $result_fetch ) ) {
  2789 				if ( ! is_wp_error( $result_fetch ) && 200 === wp_remote_retrieve_response_code( $result_fetch ) ) {
  2570 					$result = json_decode( wp_remote_retrieve_body( $result_fetch ), true );
  2790 					$result = json_decode( wp_remote_retrieve_body( $result_fetch ), true );
  2571 				} else {
  2791 				} else {
  2572 					$result = false;
  2792 					$result = false;
  2573 				}
  2793 				}
  2574 
  2794 
  2593 			}
  2813 			}
  2594 		}
  2814 		}
  2595 
  2815 
  2596 		set_transient( 'health-check-site-status-result', wp_json_encode( $site_status ) );
  2816 		set_transient( 'health-check-site-status-result', wp_json_encode( $site_status ) );
  2597 	}
  2817 	}
       
  2818 
       
  2819 	/**
       
  2820 	 * Checks if the current environment type is set to 'development' or 'local'.
       
  2821 	 *
       
  2822 	 * @since 5.6.0
       
  2823 	 *
       
  2824 	 * @return bool True if it is a development environment, false if not.
       
  2825 	 */
       
  2826 	public function is_development_environment() {
       
  2827 		return in_array( wp_get_environment_type(), array( 'development', 'local' ), true );
       
  2828 	}
       
  2829 
  2598 }
  2830 }