changeset 18 | be944660c56a |
parent 16 | a86126ab1dd4 |
child 19 | 3d72ae0968f4 |
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’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’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’s content and settings.' ) |
1175 __( 'The SQL server is a required piece of software for the database WordPress uses to store all your site’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 } |