Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
75.00% covered (warning)
75.00%
54 / 72
60.00% covered (warning)
60.00%
3 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
Site_Health
75.00% covered (warning)
75.00%
54 / 72
60.00% covered (warning)
60.00%
3 / 5
18.52
0.00% covered (danger)
0.00%
0 / 1
 init
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 maybe_register_site_health
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 register_site_health_tests
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
2
 make_site_health_callback
72.34% covered (warning)
72.34%
34 / 47
0.00% covered (danger)
0.00%
0 / 1
8.04
 ajax_local_testing_suite
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2/**
3 * WordPress Site Health integration for the Jetpack Connection package.
4 *
5 * @package automattic/jetpack-connection
6 */
7
8namespace Automattic\Jetpack\Connection;
9
10/**
11 * Integrates connection health tests into WordPress Site Health.
12 *
13 * This class defers to the Jetpack plugin's own debugger integration when it
14 * is present (old Jetpack versions). When no legacy integration is detected,
15 * it registers the connection health tests directly.
16 *
17 * @since 8.5.0
18 */
19class Site_Health {
20
21    /**
22     * Whether the class has been initialized.
23     *
24     * @var bool
25     */
26    private static $initialized = false;
27
28    /**
29     * Initialize Site Health integration.
30     *
31     * Should be called once, typically from the package's actions.php via a plugins_loaded hook.
32     *
33     * @since 8.5.0
34     */
35    public static function init() {
36        if ( self::$initialized ) {
37            return;
38        }
39        self::$initialized = true;
40
41        add_action( 'admin_init', array( __CLASS__, 'maybe_register_site_health' ), 1 );
42    }
43
44    /**
45     * Conditionally register Site Health hooks.
46     *
47     * Checks whether the legacy Jetpack debugger has already registered its
48     * Site Health hooks. If so, we defer to avoid duplicate tests.
49     *
50     * @since 8.5.0
51     */
52    public static function maybe_register_site_health() {
53        // Defer to the old Jetpack plugin's debugger if it has already registered
54        // its Site Health filter. Old Jetpack versions add this filter during plugin
55        // loading, so by admin_init it is already present.
56        if ( has_filter( 'site_status_tests', 'jetpack_debugger_site_status_tests' ) ) {
57            return;
58        }
59
60        add_filter( 'site_status_tests', array( __CLASS__, 'register_site_health_tests' ) );
61        add_action( 'wp_ajax_health-check-jetpack-connection-health', array( __CLASS__, 'ajax_local_testing_suite' ) );
62    }
63
64    /**
65     * Register connection tests with WordPress Site Health.
66     *
67     * @since 8.5.0
68     *
69     * @param array $core_tests Array of tests from Core's Site Health.
70     *
71     * @return array Modified array of tests.
72     */
73    public static function register_site_health_tests( $core_tests ) {
74        $cxn_tests = new Connection_Health_Tests();
75        $tests     = $cxn_tests->list_tests( 'direct' );
76
77        foreach ( $tests as $test ) {
78            $core_tests['direct'][ $test['name'] ] = array(
79                'label' => __( 'Jetpack: ', 'jetpack-connection' ) . $test['name'],
80                'test'  => self::make_site_health_callback( $test, $cxn_tests ),
81            );
82        }
83
84        $core_tests['async']['jetpack_connection_test_suite'] = array(
85            'label' => __( 'Jetpack Connection Tests', 'jetpack-connection' ),
86            'test'  => 'jetpack-connection-health',
87        );
88
89        return $core_tests;
90    }
91
92    /**
93     * Create a closure for a Site Health direct test.
94     *
95     * @since 8.5.0
96     *
97     * @param array                   $test      Test definition array.
98     * @param Connection_Health_Tests $cxn_tests Test suite instance.
99     *
100     * @return callable The Site Health test callback.
101     */
102    private static function make_site_health_callback( $test, $cxn_tests ) {
103        return function () use ( $test, $cxn_tests ) {
104            $results = $cxn_tests->run_test( $test['name'] );
105            if ( is_wp_error( $results ) ) {
106                return;
107            }
108
109            $label = $results['label'] ?
110                $results['label'] :
111                ucwords(
112                    str_replace(
113                        '_',
114                        ' ',
115                        str_replace( 'test__', '', $test['name'] )
116                    )
117                );
118
119            if ( $results['long_description'] ) {
120                $description = $results['long_description'];
121            } elseif ( $results['short_description'] ) {
122                $description = sprintf(
123                    '<p>%s</p>',
124                    $results['short_description']
125                );
126            } else {
127                $description = sprintf(
128                    '<p>%s</p>',
129                    __( 'This test successfully passed!', 'jetpack-connection' )
130                );
131            }
132
133            $badge_label = $cxn_tests->get_site_health_badge_label();
134
135            $return = array(
136                'label'       => $label,
137                'status'      => 'good',
138                'badge'       => array(
139                    'label' => $badge_label,
140                    'color' => 'green',
141                ),
142                'description' => $description,
143                'actions'     => '',
144                'test'        => 'jetpack_' . $test['name'],
145            );
146
147            if ( false === $results['pass'] ) {
148                $return['status'] = $results['severity'];
149                if ( ! empty( $results['action'] ) ) {
150                    $return['actions'] = sprintf(
151                        '<a href="%1$s" target="_blank" rel="noopener noreferrer">%2$s <span class="screen-reader-text">%3$s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a>',
152                        esc_url( $results['action'] ),
153                        $results['action_label'],
154                        /* translators: accessibility text */
155                        __( '(opens in a new tab)', 'jetpack-connection' )
156                    );
157                }
158            }
159
160            return $return;
161        };
162    }
163
164    /**
165     * AJAX handler for async Site Health tests.
166     *
167     * @since 8.5.0
168     */
169    public static function ajax_local_testing_suite() {
170        check_ajax_referer( 'health-check-site-status' );
171        if ( ! current_user_can( 'manage_options' ) ) {
172            // @phan-suppress-next-line PhanTypeMismatchArgumentProbablyReal
173            wp_send_json_error( null, null, JSON_UNESCAPED_SLASHES );
174        }
175        $tests = new Connection_Health_Tests();
176        // @phan-suppress-next-line PhanTypeMismatchArgumentProbablyReal
177        wp_send_json_success( $tests->output_results_for_core_async_site_health(), null, JSON_UNESCAPED_SLASHES );
178    }
179}