Completed
Push — add/sync-health-progress-bar ( fdf29e )
by
unknown
08:06 queued 01:19
created

Jetpack_Cxn_Tests::increase_timeout()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Collection of tests to run on the Jetpack connection locally.
4
 *
5
 * @package Jetpack
6
 */
7
8
use Automattic\Jetpack\Connection\Client;
9
use Automattic\Jetpack\Status;
10
use Automattic\Jetpack\Connection\Utils as Connection_Utils;
11
use Automattic\Jetpack\Sync\Modules;
12
use Automattic\Jetpack\Sync\Settings as Sync_Settings;
13
14
/**
15
 * Class Jetpack_Cxn_Tests contains all of the actual tests.
16
 */
17
class Jetpack_Cxn_Tests extends Jetpack_Cxn_Test_Base {
18
19
	/**
20
	 * Jetpack_Cxn_Tests constructor.
21
	 */
22
	public function __construct() {
23
		parent::__construct();
24
25
		$methods = get_class_methods( 'Jetpack_Cxn_Tests' );
26
27
		foreach ( $methods as $method ) {
28
			if ( false === strpos( $method, 'test__' ) ) {
29
				continue;
30
			}
31
			$this->add_test( array( $this, $method ), $method, 'direct' );
32
		}
33
34
		/**
35
		 * Fires after loading default Jetpack Connection tests.
36
		 *
37
		 * @since 7.1.0
38
		 * @since 8.3.0 Passes the Jetpack_Cxn_Tests instance.
39
		 */
40
		do_action( 'jetpack_connection_tests_loaded', $this );
41
42
		/**
43
		 * Determines if the WP.com testing suite should be included.
44
		 *
45
		 * @since 7.1.0
46
		 * @since 8.1.0 Default false.
47
		 *
48
		 * @param bool $run_test To run the WP.com testing suite. Default false.
49
		 */
50
		if ( apply_filters( 'jetpack_debugger_run_self_test', false ) ) {
51
			/**
52
			 * Intentionally added last as it checks for an existing failure state before attempting.
53
			 * Generally, any failed location condition would result in the WP.com check to fail too, so
54
			 * we will skip it to avoid confusing error messages.
55
			 *
56
			 * Note: This really should be an 'async' test.
57
			 */
58
			$this->add_test( array( $this, 'last__wpcom_self_test' ), 'test__wpcom_self_test', 'direct' );
59
		}
60
	}
61
62
	/**
63
	 * Helper function to look up the expected master user and return the local WP_User.
64
	 *
65
	 * @return WP_User Jetpack's expected master user.
66
	 */
67
	protected function helper_retrieve_local_master_user() {
68
		$master_user = Jetpack_Options::get_option( 'master_user' );
69
		return new WP_User( $master_user );
70
	}
71
72
	/**
73
	 * Is Jetpack even connected and supposed to be talking to WP.com?
74
	 */
75
	protected function helper_is_jetpack_connected() {
76
		return ( Jetpack::is_active() && ! ( new Status() )->is_development_mode() );
77
	}
78
79
	/**
80
	 * Returns a support url based on development mode.
81
	 */
82
	protected function helper_get_support_url() {
83
		return Jetpack::is_development_version()
84
			? 'https://jetpack.com/contact-support/beta-group/'
85
			: 'https://jetpack.com/contact-support/';
86
	}
87
88
	/**
89
	 * Gets translated support text.
90
	 */
91
	protected function helper_get_support_text() {
92
		return __( 'Please contact Jetpack support.', 'jetpack' );
93
	}
94
95
	/**
96
	 * Gets translated text to enable outbound requests.
97
	 *
98
	 * @param string $protocol Either 'HTTP' or 'HTTPS'.
99
	 *
100
	 * @return string The translated text.
101
	 */
102
	protected function helper_enable_outbound_requests( $protocol ) {
103
		return sprintf(
104
			/* translators: %1$s - request protocol, either http or https */
105
			__(
106
				'Your server did not successfully connect to the Jetpack server using %1$s
107
				Please ask your hosting provider to confirm your server can make outbound requests to jetpack.com.',
108
				'jetpack'
109
			),
110
			$protocol
111
		);
112
	}
113
114
	/**
115
	 * Returns 30 for use with a filter.
116
	 *
117
	 * To allow time for WP.com to run upstream testing, this function exists to increase the http_request_timeout value
118
	 * to 30.
119
	 *
120
	 * @return int 30
121
	 */
122
	public static function increase_timeout() {
123
		return 30; // seconds.
124
	}
125
126
	/**
127
	 * Test if Jetpack is connected.
128
	 */
129
	protected function test__check_if_connected() {
130
		$name = __FUNCTION__;
131
		if ( $this->helper_is_jetpack_connected() ) {
132
			$result = self::passing_test(
133
				array(
134
					'name'             => $name,
135
					'label'            => __( 'Your site is connected to Jetpack', 'jetpack' ),
136
					'long_description' => sprintf(
137
						'<p>%1$s</p>' .
138
						'<p><span class="dashicons pass"><span class="screen-reader-text">%2$s</span></span> %3$s</p>',
139
						__( 'A healthy connection ensures Jetpack essential services are provided to your WordPress site, such as Stats and Site Security.', 'jetpack' ),
140
						/* translators: Screen reader text indicating a test has passed */
141
						__( 'Passed', 'jetpack' ),
142
						__( 'Your site is connected to Jetpack.', 'jetpack' )
143
					),
144
				)
145
			);
146
		} elseif ( ( new Status() )->is_development_mode() ) {
147
			$result = self::skipped_test(
148
				array(
149
					'name'              => $name,
150
					'short_description' => __( 'Jetpack is in Development Mode:', 'jetpack' ) . ' ' . Jetpack::development_mode_trigger_text(),
151
				)
152
			);
153
		} else {
154
			$result = self::failing_test(
155
				array(
156
					'name'             => $name,
157
					'label'            => __( 'Your site is not connected to Jetpack', 'jetpack' ),
158
					'action'           => admin_url( 'admin.php?page=jetpack#/dashboard' ),
159
					'action_label'     => __( 'Reconnect your site now', 'jetpack' ),
160
					'long_description' => sprintf(
161
						'<p>%1$s</p>' .
162
						'<p><span class="dashicons fail"><span class="screen-reader-text">%2$s</span></span> %3$s<strong> %4$s</strong></p>',
163
						__( 'A healthy connection ensures Jetpack essential services are provided to your WordPress site, such as Stats and Site Security.', 'jetpack' ),
164
						/* translators: screen reader text indicating a test failed */
165
						__( 'Error', 'jetpack' ),
166
						__( 'Your site is not connected to Jetpack.', 'jetpack' ),
167
						__( 'We recommend reconnecting Jetpack.', 'jetpack' )
168
					),
169
				)
170
			);
171
		}
172
173
		return $result;
174
	}
175
176
	/**
177
	 * Test that the master user still exists on this site.
178
	 *
179
	 * @return array Test results.
180
	 */
181
	protected function test__master_user_exists_on_site() {
182
		$name = __FUNCTION__;
183 View Code Duplication
		if ( ! $this->helper_is_jetpack_connected() ) {
184
			return self::skipped_test(
185
				array(
186
					'name'              => $name,
187
					'short_description' => __( 'Jetpack is not connected. No master user to check.', 'jetpack' ),
188
				)
189
			);
190
		}
191
		$local_user = $this->helper_retrieve_local_master_user();
192
193
		if ( $local_user->exists() ) {
194
			$result = self::passing_test( array( 'name' => $name ) );
195 View Code Duplication
		} else {
196
			$result = self::failing_test(
197
				array(
198
					'name'              => $name,
199
					'short_description' => __( 'The user who setup the Jetpack connection no longer exists on this site.', 'jetpack' ),
200
					'action_label'      => __( 'Please disconnect and reconnect Jetpack.', 'jetpack' ),
201
					'action'            => 'https://jetpack.com/support/reconnecting-reinstalling-jetpack/',
202
				)
203
			);
204
		}
205
206
		return $result;
207
	}
208
209
	/**
210
	 * Test that the master user has the manage options capability (e.g. is an admin).
211
	 *
212
	 * Generic calls from WP.com execute on Jetpack as the master user. If it isn't an admin, random things will fail.
213
	 *
214
	 * @return array Test results.
215
	 */
216
	protected function test__master_user_can_manage_options() {
217
		$name = __FUNCTION__;
218 View Code Duplication
		if ( ! $this->helper_is_jetpack_connected() ) {
219
			return self::skipped_test(
220
				array(
221
					'name'              => $name,
222
					'short_description' => __( 'Jetpack is not connected.', 'jetpack' ),
223
				)
224
			);
225
		}
226
		$master_user = $this->helper_retrieve_local_master_user();
227
228
		if ( user_can( $master_user, 'manage_options' ) ) {
229
			$result = self::passing_test( array( 'name' => $name ) );
230 View Code Duplication
		} else {
231
			$result = self::failing_test(
232
				array(
233
					'name'              => $name,
234
					/* translators: a WordPress username */
235
					'short_description' => sprintf( __( 'The user (%s) who setup the Jetpack connection is not an administrator.', 'jetpack' ), $master_user->user_login ),
236
					'action_label'      => __( 'Either upgrade the user or disconnect and reconnect Jetpack.', 'jetpack' ),
237
					'action'            => 'https://jetpack.com/support/reconnecting-reinstalling-jetpack/',
238
				)
239
			);
240
		}
241
242
		return $result;
243
	}
244
245
	/**
246
	 * Test that the PHP's XML library is installed.
247
	 *
248
	 * While it should be installed by default, increasingly in PHP 7, some OSes require an additional php-xml package.
249
	 *
250
	 * @return array Test results.
251
	 */
252
	protected function test__xml_parser_available() {
253
		$name = __FUNCTION__;
254
		if ( function_exists( 'xml_parser_create' ) ) {
255
			$result = self::passing_test( array( 'name' => $name ) );
256
		} else {
257
			$result = self::failing_test(
258
				array(
259
					'name'              => $name,
260
					'label'             => __( 'PHP XML manipulation libraries are not available.', 'jetpack' ),
261
					'short_description' => __( 'Please ask your hosting provider to refer to our server requirements and enable PHP\'s XML module.', 'jetpack' ),
262
					'action_label'      => __( 'View our server requirements', 'jetpack' ),
263
					'action'            => 'https://jetpack.com/support/server-requirements/',
264
				)
265
			);
266
		}
267
		return $result;
268
	}
269
270
	/**
271
	 * Test that the server is able to send an outbound http communication.
272
	 *
273
	 * @return array Test results.
274
	 */
275 View Code Duplication
	protected function test__outbound_http() {
276
		$name    = __FUNCTION__;
277
		$request = wp_remote_get( preg_replace( '/^https:/', 'http:', JETPACK__API_BASE ) . 'test/1/' );
278
		$code    = wp_remote_retrieve_response_code( $request );
279
280
		if ( 200 === intval( $code ) ) {
281
			$result = self::passing_test( array( 'name' => $name ) );
282
		} else {
283
			$result = self::failing_test(
284
				array(
285
					'name'              => $name,
286
					'short_description' => $this->helper_enable_outbound_requests( 'HTTP' ),
287
				)
288
			);
289
		}
290
291
		return $result;
292
	}
293
294
	/**
295
	 * Test that the server is able to send an outbound https communication.
296
	 *
297
	 * @return array Test results.
298
	 */
299 View Code Duplication
	protected function test__outbound_https() {
300
		$name    = __FUNCTION__;
301
		$request = wp_remote_get( preg_replace( '/^http:/', 'https:', JETPACK__API_BASE ) . 'test/1/' );
302
		$code    = wp_remote_retrieve_response_code( $request );
303
304
		if ( 200 === intval( $code ) ) {
305
			$result = self::passing_test( array( 'name' => $name ) );
306
		} else {
307
			$result = self::failing_test(
308
				array(
309
					'name'              => $name,
310
					'short_description' => $this->helper_enable_outbound_requests( 'HTTPS' ),
311
				)
312
			);
313
		}
314
315
		return $result;
316
	}
317
318
	/**
319
	 * Check for an IDC.
320
	 *
321
	 * @return array Test results.
322
	 */
323
	protected function test__identity_crisis() {
324
		$name = __FUNCTION__;
325 View Code Duplication
		if ( ! $this->helper_is_jetpack_connected() ) {
326
			return self::skipped_test(
327
				array(
328
					'name'              => $name,
329
					'short_description' => __( 'Jetpack is not connected.', 'jetpack' ),
330
				)
331
			);
332
		}
333
		$identity_crisis = Jetpack::check_identity_crisis();
334
335
		if ( ! $identity_crisis ) {
336
			$result = self::passing_test( array( 'name' => $name ) );
337
		} else {
338
			$result = self::failing_test(
339
				array(
340
					'name'              => $name,
341
					'short_description' => sprintf(
342
						/* translators: Two URLs. The first is the locally-recorded value, the second is the value as recorded on WP.com. */
343
						__( 'Your url is set as `%1$s`, but your WordPress.com connection lists it as `%2$s`!', 'jetpack' ),
344
						$identity_crisis['home'],
345
						$identity_crisis['wpcom_home']
346
					),
347
					'action_label'      => $this->helper_get_support_text(),
348
					'action'            => $this->helper_get_support_url(),
349
				)
350
			);
351
		}
352
		return $result;
353
	}
354
355
	/**
356
	 * Tests connection status against wp.com's test-connection endpoint.
357
	 *
358
	 * @todo: Compare with the wpcom_self_test. We only need one of these.
359
	 *
360
	 * @return array Test results.
361
	 */
362
	protected function test__wpcom_connection_test() {
363
		$name = __FUNCTION__;
364
365
		$status = new Status();
366 View Code Duplication
		if ( ! Jetpack::is_active() || $status->is_development_mode() || $status->is_staging_site() || ! $this->pass ) {
367
			return self::skipped_test( array( 'name' => $name ) );
368
		}
369
370
		add_filter( 'http_request_timeout', array( 'Jetpack_Cxn_Tests', 'increase_timeout' ) );
371
		$response = Client::wpcom_json_api_request_as_blog(
372
			sprintf( '/jetpack-blogs/%d/test-connection', Jetpack_Options::get_option( 'id' ) ),
373
			Client::WPCOM_JSON_API_VERSION
374
		);
375
		remove_filter( 'http_request_timeout', array( 'Jetpack_Cxn_Tests', 'increase_timeout' ) );
376
377 View Code Duplication
		if ( is_wp_error( $response ) ) {
378
			return self::failing_test(
379
				array(
380
					'name'              => $name,
381
					/* translators: %1$s is the error code, %2$s is the error message */
382
					'short_description' => sprintf( __( 'Connection test failed (#%1$s: %2$s)', 'jetpack' ), $response->get_error_code(), $response->get_error_message() ),
0 ignored issues
show
Bug introduced by
The method get_error_code() does not seem to exist on object<WP_Error>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method get_error_message() does not seem to exist on object<WP_Error>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
383
					'action_label'      => $this->helper_get_support_text(),
384
					'action'            => $this->helper_get_support_url(),
385
				)
386
			);
387
		}
388
389
		$body = wp_remote_retrieve_body( $response );
390 View Code Duplication
		if ( ! $body ) {
391
			return self::failing_test(
392
				array(
393
					'name'              => $name,
394
					'short_description' => __( 'Connection test failed (empty response body)', 'jetpack' ) . wp_remote_retrieve_response_code( $response ),
395
					'action_label'      => $this->helper_get_support_text(),
396
					'action'            => $this->helper_get_support_url(),
397
				)
398
			);
399
		}
400
401 View Code Duplication
		if ( 404 === wp_remote_retrieve_response_code( $response ) ) {
402
			return self::skipped_test(
403
				array(
404
					'name'              => $name,
405
					'short_description' => __( 'The WordPress.com API returned a 404 error.', 'jetpack' ),
406
				)
407
			);
408
		}
409
410
		$result       = json_decode( $body );
411
		$is_connected = (bool) $result->connected;
412
		$message      = $result->message . ': ' . wp_remote_retrieve_response_code( $response );
413
414
		if ( $is_connected ) {
415
			return self::passing_test( array( 'name' => $name ) );
416
		} else {
417
			return self::failing_test(
418
				array(
419
					'name'              => $name,
420
					'short_description' => $message,
421
					'action_label'      => $this->helper_get_support_text(),
422
					'action'            => $this->helper_get_support_url(),
423
				)
424
			);
425
		}
426
	}
427
428
	/**
429
	 * Tests the port number to ensure it is an expected value.
430
	 *
431
	 * We expect that sites on be on one of:
432
	 * port 80,
433
	 * port 443 (https sites only),
434
	 * the value of JETPACK_SIGNATURE__HTTP_PORT,
435
	 * unless the site is intentionally on a different port (e.g. example.com:8080 is the site's URL).
436
	 *
437
	 * If the value isn't one of those and the site's URL doesn't include a port, then the signature verification will fail.
438
	 *
439
	 * This happens most commonly on sites with reverse proxies, so the edge (e.g. Varnish) is running on 80/443, but nginx
440
	 * or Apache is responding internally on a different port (e.g. 81).
441
	 *
442
	 * @return array Test results
443
	 */
444
	protected function test__server_port_value() {
445
		$name = __FUNCTION__;
446
		if ( ! isset( $_SERVER['HTTP_X_FORWARDED_PORT'] ) && ! isset( $_SERVER['SERVER_PORT'] ) ) {
447
			return self::skipped_test(
448
				array(
449
					'name'              => $name,
450
					'short_description' => __( 'The server port values are not defined. This is most common when running PHP via a CLI.', 'jetpack' ),
451
				)
452
			);
453
		}
454
		$site_port   = wp_parse_url( home_url(), PHP_URL_PORT );
455
		$server_port = isset( $_SERVER['HTTP_X_FORWARDED_PORT'] ) ? (int) $_SERVER['HTTP_X_FORWARDED_PORT'] : (int) $_SERVER['SERVER_PORT'];
456
		$http_ports  = array( 80 );
457
		$https_ports = array( 80, 443 );
458
459
		if ( defined( 'JETPACK_SIGNATURE__HTTP_PORT' ) ) {
460
			$http_ports[] = JETPACK_SIGNATURE__HTTP_PORT;
461
		}
462
463
		if ( defined( 'JETPACK_SIGNATURE__HTTPS_PORT' ) ) {
464
			$https_ports[] = JETPACK_SIGNATURE__HTTPS_PORT;
465
		}
466
467
		if ( $site_port ) {
468
			return self::skipped_test( array( 'name' => $name ) ); // Not currently testing for this situation.
469
		}
470
471
		if ( is_ssl() && in_array( $server_port, $https_ports, true ) ) {
472
			return self::passing_test( array( 'name' => $name ) );
473
		} elseif ( in_array( $server_port, $http_ports, true ) ) {
474
			return self::passing_test( array( 'name' => $name ) );
475
		} else {
476
			if ( is_ssl() ) {
477
				$needed_constant = 'JETPACK_SIGNATURE__HTTPS_PORT';
478
			} else {
479
				$needed_constant = 'JETPACK_SIGNATURE__HTTP_PORT';
480
			}
481
			return self::failing_test(
482
				array(
483
					'name'              => $name,
484
					'short_description' => sprintf(
485
						/* translators: %1$s - a PHP code snippet */
486
						__(
487
							'The server port value is unexpected.
488
						Try adding the following to your wp-config.php file: %1$s',
489
							'jetpack'
490
						),
491
						"define( '$needed_constant', $server_port )"
492
					),
493
				)
494
			);
495
		}
496
	}
497
498
	/**
499
	 * If Sync is enabled, this test will be skipped. If Sync is disabled, the test will fail.
500
	 * Eventually, we'll make this test more robust with additional states. Here is the plan for possible Sync states,
501
	 * including states that are planned but not yet implemented.
502
	 *
503
	 * Enabled: Skips test
504
	 * Disabled: Results in a failing test
505
	 * Healthy: @todo
506
	 * In Progress: @todo
507
	 * Delayed: @todo
508
	 * Error: @todo
509
	 */
510
	protected function test__sync_health() {
511
		$name = __FUNCTION__;
512
		if ( ! $this->helper_is_jetpack_connected() ) {
513
			// If the site is not connected, there is no point in testing Sync health.
514
			return self::skipped_test(
515
				array(
516
					'name'                => $name,
517
					'show_in_site_health' => false,
518
				)
519
			);
520
		}
521
522
		if ( ! Sync_Settings::is_sync_enabled() ) {
523
			// If sync is not enabled, show a warning in test results.
524
			return self::failing_test(
525
				array(
526
					'name'              => $name,
527
					'label'             => __( 'Jetpack Sync has been disabled on your site.', 'jetpack' ),
528
					'severity'          => 'recommended',
529
					'action'            => 'https://github.com/Automattic/jetpack/blob/master/packages/sync/src/class-settings.php',
530
					'action_label'      => __( 'See Github for more on Sync Settings', 'jetpack' ),
531
					'short_description' => __( 'Jetpack Sync has been disabled on your site.', 'jetpack' ),
532
					'long_description'  => sprintf(
533
						'<p>%1$s</p>' .
534
						'<p>%2$s</p>' .
535
						'<p><span class="dashicons fail"><span class="screen-reader-text">%3$s</span></span> %4$s<strong> %5$s</strong></p>',
536
						__( 'The information synced by Jetpack ensures that Jetpack Search, Related Posts and other features are aligned with your site’s current content.', 'jetpack' ),
537
						__( 'Developers may enable / disable syncing using the Sync Settings API.', 'jetpack' ),
538
						/* translators: screen reader text indicating a test failed */
539
						__( 'Error', 'jetpack' ),
540
						__( 'Jetpack Sync has been disabled on your site. Without it, certain Jetpack features will not work.', 'jetpack' ),
541
						__( 'We recommend enabling Sync.', 'jetpack' )
542
					),
543
				)
544
			);
545
		}
546
547
		$full_sync_module = Modules::get_module( 'full-sync' );
548
		$progress_percent = $full_sync_module ? $full_sync_module->get_sync_progress_percentage() : null;
549
		if ( $progress_percent ) {
550
			return self::failing_test(
551
				array(
552
					'name'              => $name,
553
					'label'             => __( 'Jetpack is performing a sync of your site', 'jetpack' ) . " - $progress_percent %",
554
					'severity'          => 'recommended',
555
					'short_description' => __( 'Jetpack is performing a sync of your site', 'jetpack' ),
556
					'long_description'  => sprintf(
557
						'<p>%1$s</p>' .
558
						'<p><span class="dashicons dashicons-update"><span class="screen-reader-text">%2$s</span></span> %3$s</p>' .
559
						'<div class="jetpack-sync-progress"><span class="percent">%4$d%%</span><span class="progress-bar"></span></div>',
560
						__( 'The information synced by Jetpack ensures that Jetpack Search, Related Posts and other features are aligned with your site’s current content.', 'jetpack' ),
561
						/* translators: screen reader text indicating data is updating. */
562
						__( 'Updating', 'jetpack' ),
563
						__( 'Jetpack is currently performing a full sync of your site data.', 'jetpack' ),
564
						$progress_percent
565
					),
566
				)
567
			);
568
		}
569
570
		// If we've reached this point, we know that:
571
		// 1) Sync is enabled
572
		// 2) There is not a full sync in progress
573
		// We cannot yet return a passing test. We'll still need to test for lag and data loss.
574
		// We'll address those in future iterations, for now we'll just skip the test.
575
		// See p6TEKc-3t2-p2 for more information.
576
		return self::skipped_test(
577
			array(
578
				'name'                => $name,
579
				'show_in_site_health' => false,
580
			)
581
		);
582
	}
583
584
	/**
585
	 * Calls to WP.com to run the connection diagnostic testing suite.
586
	 *
587
	 * Intentionally added last as it will be skipped if any local failed conditions exist.
588
	 *
589
	 * @since 7.1.0
590
	 * @since 7.9.0 Timeout waiting for a WP.com response no longer fails the test. Test is marked skipped instead.
591
	 *
592
	 * @return array Test results.
593
	 */
594
	protected function last__wpcom_self_test() {
595
		$name = 'test__wpcom_self_test';
596
597
		$status = new Status();
598 View Code Duplication
		if ( ! Jetpack::is_active() || $status->is_development_mode() || $status->is_staging_site() || ! $this->pass ) {
599
			return self::skipped_test( array( 'name' => $name ) );
600
		}
601
602
		$self_xml_rpc_url = site_url( 'xmlrpc.php' );
603
604
		$testsite_url = Connection_Utils::fix_url_for_bad_hosts( JETPACK__API_BASE . 'testsite/1/?url=' );
605
606
		add_filter( 'http_request_timeout', array( 'Jetpack_Cxn_Tests', 'increase_timeout' ) );
607
608
		$response = wp_remote_get( $testsite_url . $self_xml_rpc_url );
609
610
		remove_filter( 'http_request_timeout', array( 'Jetpack_Cxn_Tests', 'increase_timeout' ) );
611
612
		if ( 200 === wp_remote_retrieve_response_code( $response ) ) {
613
			return self::passing_test( array( 'name' => $name ) );
614
		} elseif ( is_wp_error( $response ) && false !== strpos( $response->get_error_message(), 'cURL error 28' ) ) { // Timeout.
615
			return self::skipped_test(
616
				array(
617
					'name'              => $name,
618
					'short_description' => __( 'The test timed out which may sometimes indicate a failure or may be a false failure.', 'jetpack' ),
619
				)
620
			);
621
		} else {
622
			return self::failing_test(
623
				array(
624
					'name'              => $name,
625
					'short_description' => sprintf(
626
						/* translators: %1$s - A debugging url */
627
						__( 'Jetpack.com detected an error on the WP.com Self Test. Visit the Jetpack Debug page for more info: %1$s, or contact support.', 'jetpack' ),
628
						esc_url( add_query_arg( 'url', rawurlencode( site_url() ), 'https://jetpack.com/support/debug/' ) )
629
					),
630
					'action_label'      => $this->helper_get_support_text(),
631
					'action'            => $this->helper_get_support_url(),
632
				)
633
			);
634
		}
635
	}
636
}
637