PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 7.9
Jetpack – WP Security, Backup, Speed, & Growth v7.9
16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 13.9.2 14.0.1 14.1.1 14.2.2 14.3.1 All 501 releases
jetpack / _inc / lib / debugger / class-jetpack-debug-data.php

class-jetpack-debug-data.php in Jetpack – WP Security, Backup, Speed, & Growth 7.9, at _inc/lib/debugger/class-jetpack-debug-data.php

398 lines 12.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Jetpack Debug Data for the legacy Jetpack debugger page and the WP 5.2-era Site Health sections.
4 *
5 * @package jetpack
6 */
7
8 use Automattic\Jetpack\Constants;
9 use Automattic\Jetpack\Sync\Modules;
10 use Automattic\Jetpack\Sync\Functions;
11 use Automattic\Jetpack\Sync\Sender;
12
13 /**
14 * Class Jetpack_Debug_Data
15 *
16 * Collect and return debug data for Jetpack.
17 *
18 * @since 7.3.0
19 */
20 class Jetpack_Debug_Data {
21 /**
22 * Determine the active plan and normalize it for the debugger results.
23 *
24 * @since 7.3.0
25 *
26 * @return string The plan slug.
27 */
28 public static function what_jetpack_plan() {
29 $plan = Jetpack_Plan::get();
30 return ! empty( $plan['class'] ) ? $plan['class'] : 'undefined';
31 }
32
33 /**
34 * Convert seconds to human readable time.
35 *
36 * A dedication function instead of using Core functionality to allow for output in seconds.
37 *
38 * @since 7.3.0
39 *
40 * @param int $seconds Number of seconds to convert to human time.
41 *
42 * @return string Human readable time.
43 */
44 public static function seconds_to_time( $seconds ) {
45 $seconds = intval( $seconds );
46 $units = array(
47 'week' => WEEK_IN_SECONDS,
48 'day' => DAY_IN_SECONDS,
49 'hour' => HOUR_IN_SECONDS,
50 'minute' => MINUTE_IN_SECONDS,
51 'second' => 1,
52 );
53 // specifically handle zero.
54 if ( 0 === $seconds ) {
55 return '0 seconds';
56 }
57 $human_readable = '';
58 foreach ( $units as $name => $divisor ) {
59 $quot = intval( $seconds / $divisor );
60 if ( $quot ) {
61 $human_readable .= "$quot $name";
62 $human_readable .= ( abs( $quot ) > 1 ? 's' : '' ) . ', ';
63 $seconds -= $quot * $divisor;
64 }
65 }
66 return substr( $human_readable, 0, -2 );
67 }
68
69 /**
70 * Return debug data in the format expected by Core's Site Health Info tab.
71 *
72 * @since 7.3.0
73 *
74 * @param array $debug {
75 * The debug information already compiled by Core.
76 *
77 * @type string $label The title for this section of the debug output.
78 * @type string $description Optional. A description for your information section which may contain basic HTML
79 * markup: `em`, `strong` and `a` for linking to documentation or putting emphasis.
80 * @type boolean $show_count Optional. If set to `true` the amount of fields will be included in the title for
81 * this section.
82 * @type boolean $private Optional. If set to `true` the section and all associated fields will be excluded
83 * from the copy-paste text area.
84 * @type array $fields {
85 * An associative array containing the data to be displayed.
86 *
87 * @type string $label The label for this piece of information.
88 * @type string $value The output that is of interest for this field.
89 * @type boolean $private Optional. If set to `true` the field will not be included in the copy-paste text area
90 * on top of the page, allowing you to show, for example, API keys here.
91 * }
92 * }
93 *
94 * @return array $args Debug information in the same format as the initial argument.
95 */
96 public static function core_debug_data( $debug ) {
97 $support_url = Jetpack::is_development_version()
98 ? 'https://jetpack.com/contact-support/beta-group/'
99 : 'https://jetpack.com/contact-support/';
100
101 $jetpack = array(
102 'jetpack' => array(
103 'label' => __( 'Jetpack', 'jetpack' ),
104 'description' => sprintf(
105 /* translators: %1$s is URL to jetpack.com's contact support page. %2$s accessibility text */
106 __(
107 'Diagnostic information helpful to <a href="%1$s" target="_blank" rel="noopener noreferrer">your Jetpack Happiness team<span class="screen-reader-text">%2$s</span></a>',
108 'jetpack'
109 ),
110 esc_url( $support_url ),
111 __( '(opens in a new tab)', 'jetpack' )
112 ),
113 'fields' => self::debug_data(),
114 ),
115 );
116 $debug = array_merge( $debug, $jetpack );
117 return $debug;
118 }
119
120 /**
121 * Compile and return array of debug information.
122 *
123 * @since 7.3.0
124 *
125 * @return array $args {
126 * Associated array of arrays with the following.
127 * @type string $label The label for this piece of information.
128 * @type string $value The output that is of interest for this field.
129 * @type boolean $private Optional. Set to true if data is sensitive (API keys, etc).
130 * }
131 */
132 public static function debug_data() {
133 $debug_info = array();
134
135 /* Add various important Jetpack options */
136 $debug_info['site_id'] = array(
137 'label' => 'Jetpack Site ID',
138 'value' => Jetpack_Options::get_option( 'id' ),
139 'private' => false,
140 );
141 $debug_info['ssl_cert'] = array(
142 'label' => 'Jetpack SSL Verfication Bypass',
143 'value' => ( Jetpack_Options::get_option( 'fallback_no_verify_ssl_certs' ) ) ? 'Yes' : 'No',
144 'private' => false,
145 );
146 $debug_info['time_diff'] = array(
147 'label' => "Offset between Jetpack server's time and this server's time.",
148 'value' => Jetpack_Options::get_option( 'time_diff' ),
149 'private' => false,
150 );
151 $debug_info['version_option'] = array(
152 'label' => 'Current Jetpack Version Option',
153 'value' => Jetpack_Options::get_option( 'version' ),
154 'private' => false,
155 );
156 $debug_info['old_version'] = array(
157 'label' => 'Previous Jetpack Version',
158 'value' => Jetpack_Options::get_option( 'old_version' ),
159 'private' => false,
160 );
161 $debug_info['public'] = array(
162 'label' => 'Jetpack Site Public',
163 'value' => ( Jetpack_Options::get_option( 'public' ) ) ? 'Public' : 'Private',
164 'private' => false,
165 );
166 $debug_info['master_user'] = array(
167 'label' => 'Jetpack Master User',
168 'value' => self::human_readable_master_user(),
169 'private' => false,
170 );
171
172 /**
173 * Token information is private, but awareness if there one is set is helpful.
174 *
175 * To balance out information vs privacy, we only display and include the "key",
176 * which is a segment of the token prior to a period within the token and is
177 * technically not private.
178 *
179 * If a token does not contain a period, then it is malformed and we report it as such.
180 */
181 $user_id = get_current_user_id();
182 $blog_token = Jetpack_Data::get_access_token();
183 $user_token = Jetpack_Data::get_access_token( $user_id );
184
185 $tokenset = '';
186 if ( $blog_token ) {
187 $tokenset = 'Blog ';
188 $blog_key = substr( $blog_token->secret, 0, strpos( $blog_token->secret, '.' ) );
189 // Intentionally not translated since this is helpful when sent to Happiness.
190 $blog_key = ( $blog_key ) ? $blog_key : 'Potentially Malformed Token.';
191 }
192 if ( $user_token ) {
193 $tokenset .= 'User';
194 $user_key = substr( $user_token->secret, 0, strpos( $user_token->secret, '.' ) );
195 // Intentionally not translated since this is helpful when sent to Happiness.
196 $user_key = ( $user_key ) ? $user_key : 'Potentially Malformed Token.';
197 }
198 if ( ! $tokenset ) {
199 $tokenset = 'None';
200 }
201
202 $debug_info['current_user'] = array(
203 'label' => 'Current User',
204 'value' => self::human_readable_user( $user_id ),
205 'private' => false,
206 );
207 $debug_info['tokens_set'] = array(
208 'label' => 'Tokens defined',
209 'value' => $tokenset,
210 'private' => false,
211 );
212 $debug_info['blog_token'] = array(
213 'label' => 'Blog Public Key',
214 'value' => ( $blog_token ) ? $blog_key : 'Not set.',
215 'private' => false,
216 );
217 $debug_info['user_token'] = array(
218 'label' => 'User Public Key',
219 'value' => ( $user_token ) ? $user_key : 'Not set.',
220 'private' => false,
221 );
222
223 /** Jetpack Environmental Information */
224 $debug_info['version'] = array(
225 'label' => 'Jetpack Version',
226 'value' => JETPACK__VERSION,
227 'private' => false,
228 );
229 $debug_info['jp_plugin_dir'] = array(
230 'label' => 'Jetpack Directory',
231 'value' => JETPACK__PLUGIN_DIR,
232 'private' => false,
233 );
234 $debug_info['plan'] = array(
235 'label' => 'Plan Type',
236 'value' => self::what_jetpack_plan(),
237 'private' => false,
238 );
239
240 foreach ( array(
241 'HTTP_HOST',
242 'SERVER_PORT',
243 'HTTPS',
244 'GD_PHP_HANDLER',
245 'HTTP_AKAMAI_ORIGIN_HOP',
246 'HTTP_CF_CONNECTING_IP',
247 'HTTP_CLIENT_IP',
248 'HTTP_FASTLY_CLIENT_IP',
249 'HTTP_FORWARDED',
250 'HTTP_FORWARDED_FOR',
251 'HTTP_INCAP_CLIENT_IP',
252 'HTTP_TRUE_CLIENT_IP',
253 'HTTP_X_CLIENTIP',
254 'HTTP_X_CLUSTER_CLIENT_IP',
255 'HTTP_X_FORWARDED',
256 'HTTP_X_FORWARDED_FOR',
257 'HTTP_X_IP_TRAIL',
258 'HTTP_X_REAL_IP',
259 'HTTP_X_VARNISH',
260 'REMOTE_ADDR',
261 ) as $header ) {
262 if ( isset( $_SERVER[ $header ] ) ) {
263 $debug_info[ $header ] = array(
264 'label' => 'Server Variable ' . $header,
265 'value' => ( $_SERVER[ $header ] ) ? $_SERVER[ $header ] : 'false',
266 'private' => false,
267 );
268 }
269 }
270
271 $debug_info['protect_header'] = array(
272 'label' => 'Trusted IP',
273 'value' => wp_json_encode( get_site_option( 'trusted_ip_header' ) ),
274 'private' => false,
275 );
276
277 /** Sync Debug Information */
278 $sync_module = Modules::get_module( 'full-sync' );
279 if ( $sync_module ) {
280 $sync_statuses = $sync_module->get_status();
281 $human_readable_sync_status = array();
282 foreach ( $sync_statuses as $sync_status => $sync_status_value ) {
283 $human_readable_sync_status[ $sync_status ] =
284 in_array( $sync_status, array( 'started', 'queue_finished', 'send_started', 'finished' ), true )
285 ? date( 'r', $sync_status_value ) : $sync_status_value;
286 }
287 $debug_info['full_sync'] = array(
288 'label' => 'Full Sync Status',
289 'value' => wp_json_encode( $human_readable_sync_status ),
290 'private' => false,
291 );
292 }
293
294 $queue = Sender::get_instance()->get_sync_queue();
295
296 $debug_info['sync_size'] = array(
297 'label' => 'Sync Queue Size',
298 'value' => $queue->size(),
299 'private' => false,
300 );
301 $debug_info['sync_lag'] = array(
302 'label' => 'Sync Queue Lag',
303 'value' => self::seconds_to_time( $queue->lag() ),
304 'private' => false,
305 );
306
307 $full_sync_queue = Sender::get_instance()->get_full_sync_queue();
308
309 $debug_info['full_sync_size'] = array(
310 'label' => 'Full Sync Queue Size',
311 'value' => $full_sync_queue->size(),
312 'private' => false,
313 );
314 $debug_info['full_sync_lag'] = array(
315 'label' => 'Full Sync Queue Lag',
316 'value' => self::seconds_to_time( $full_sync_queue->lag() ),
317 'private' => false,
318 );
319
320 /**
321 * IDC Information
322 *
323 * Must follow sync debug since it depends on sync functionality.
324 */
325 $idc_urls = array(
326 'home' => Functions::home_url(),
327 'siteurl' => Functions::site_url(),
328 'WP_HOME' => Constants::is_defined( 'WP_HOME' ) ? Constants::get_constant( 'WP_HOME' ) : '',
329 'WP_SITEURL' => Constants::is_defined( 'WP_SITEURL' ) ? Constants::get_constant( 'WP_SITEURL' ) : '',
330 );
331
332 $debug_info['idc_urls'] = array(
333 'label' => 'IDC URLs',
334 'value' => wp_json_encode( $idc_urls ),
335 'private' => false,
336 );
337 $debug_info['idc_error_option'] = array(
338 'label' => 'IDC Error Option',
339 'value' => wp_json_encode( Jetpack_Options::get_option( 'sync_error_idc' ) ),
340 'private' => false,
341 );
342 $debug_info['idc_optin'] = array(
343 'label' => 'IDC Opt-in',
344 'value' => Jetpack::sync_idc_optin(),
345 'private' => false,
346 );
347
348 // @todo -- Add testing results?
349 $cxn_tests = new Jetpack_Cxn_Tests();
350 $debug_info['cxn_tests'] = array(
351 'label' => 'Connection Tests',
352 'value' => '',
353 'private' => false,
354 );
355 if ( $cxn_tests->pass() ) {
356 $debug_info['cxn_tests']['value'] = 'All Pass.';
357 } else {
358 $debug_info['cxn_tests']['value'] = wp_json_encode( $cxn_tests->list_fails() );
359 }
360
361 return $debug_info;
362 }
363
364 /**
365 * Returns a human readable string for which user is the master user.
366 *
367 * @return string
368 */
369 private static function human_readable_master_user() {
370 $master_user = Jetpack_Options::get_option( 'master_user' );
371
372 if ( ! $master_user ) {
373 return __( 'No master user set.', 'jetpack' );
374 }
375
376 $user = new WP_User( $master_user );
377
378 if ( ! $user ) {
379 return __( 'Master user no longer exists. Please disconnect and reconnect Jetpack.', 'jetpack' );
380 }
381
382 return self::human_readable_user( $user );
383 }
384
385 /**
386 * Return human readable string for a given user object.
387 *
388 * @param WP_User|int $user Object or ID.
389 *
390 * @return string
391 */
392 private static function human_readable_user( $user ) {
393 $user = new WP_User( $user );
394
395 return sprintf( '#%1$d %2$s (%3$s)', $user->ID, $user->user_login, $user->user_email ); // Format: "#1 username (user@example.com)".
396 }
397 }
398