Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like Jetpack_Cxn_Tests often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Jetpack_Cxn_Tests, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
21 | class Jetpack_Cxn_Tests extends Jetpack_Cxn_Test_Base { |
||
22 | |||
23 | /** |
||
24 | * Jetpack_Cxn_Tests constructor. |
||
25 | */ |
||
26 | public function __construct() { |
||
65 | |||
66 | /** |
||
67 | * Helper function to look up the expected master user and return the local WP_User. |
||
68 | * |
||
69 | * @return WP_User Jetpack's expected master user. |
||
70 | */ |
||
71 | protected function helper_retrieve_local_master_user() { |
||
75 | |||
76 | /** |
||
77 | * Is Jetpack even connected and supposed to be talking to WP.com? |
||
78 | */ |
||
79 | protected function helper_is_jetpack_connected() { |
||
82 | |||
83 | /** |
||
84 | * Retrieve the `blog_token` if it exists. |
||
85 | * |
||
86 | * @return object|false |
||
87 | */ |
||
88 | protected function helper_get_blog_token() { |
||
91 | |||
92 | /** |
||
93 | * Returns a support url based on using a development version. |
||
94 | */ |
||
95 | protected function helper_get_support_url() { |
||
100 | |||
101 | /** |
||
102 | * Returns the url to reconnect Jetpack. |
||
103 | * |
||
104 | * @return string The reconnect url. |
||
105 | */ |
||
106 | protected static function helper_get_reconnect_url() { |
||
109 | |||
110 | /** |
||
111 | * Gets translated support text. |
||
112 | */ |
||
113 | protected function helper_get_support_text() { |
||
116 | |||
117 | /** |
||
118 | * Returns the translated text to reconnect Jetpack. |
||
119 | * |
||
120 | * @return string The translated reconnect text. |
||
121 | */ |
||
122 | protected static function helper_get_reconnect_text() { |
||
125 | |||
126 | /** |
||
127 | * Returns the translated text for failing tests due to timeouts. |
||
128 | * |
||
129 | * @return string The translated timeout text. |
||
130 | */ |
||
131 | protected static function helper_get_timeout_text() { |
||
134 | |||
135 | /** |
||
136 | * Gets translated reconnect long description. |
||
137 | * |
||
138 | * @param string $connection_error The connection specific error. |
||
139 | * @param string $recommendation The recommendation for resolving the connection error. |
||
140 | * |
||
141 | * @return string The translated long description for reconnection recommendations. |
||
142 | */ |
||
143 | protected static function helper_get_reconnect_long_description( $connection_error, $recommendation ) { |
||
155 | |||
156 | /** |
||
157 | * Helper function to return consistent responses for a connection failing test. |
||
158 | * |
||
159 | * @param string $name The raw method name that runs the test. Default unnamed_test. |
||
160 | * @param string $connection_error The connection specific error. Default 'Your site is not connected to Jetpack.'. |
||
161 | * @param string $recommendation The recommendation for resolving the connection error. Default 'We recommend reconnecting Jetpack.'. |
||
162 | * |
||
163 | * @return array Test results. |
||
164 | */ |
||
165 | public static function connection_failing_test( $name, $connection_error = '', $recommendation = '' ) { |
||
179 | |||
180 | /** |
||
181 | * Gets translated text to enable outbound requests. |
||
182 | * |
||
183 | * @param string $protocol Either 'HTTP' or 'HTTPS'. |
||
184 | * |
||
185 | * @return string The translated text. |
||
186 | */ |
||
187 | protected function helper_enable_outbound_requests( $protocol ) { |
||
198 | |||
199 | /** |
||
200 | * Returns 30 for use with a filter. |
||
201 | * |
||
202 | * To allow time for WP.com to run upstream testing, this function exists to increase the http_request_timeout value |
||
203 | * to 30. |
||
204 | * |
||
205 | * @return int 30 |
||
206 | */ |
||
207 | public static function increase_timeout() { |
||
210 | |||
211 | /** |
||
212 | * The test verifies the blog token exists. |
||
213 | * |
||
214 | * @return array |
||
215 | */ |
||
216 | protected function test__blog_token_if_exists() { |
||
217 | $name = __FUNCTION__; |
||
218 | |||
219 | View Code Duplication | if ( ! $this->helper_is_jetpack_connected() ) { |
|
220 | return self::skipped_test( |
||
221 | array( |
||
222 | 'name' => $name, |
||
223 | 'short_description' => __( 'Jetpack is not connected. No blog token to check.', 'jetpack' ), |
||
224 | ) |
||
225 | ); |
||
226 | } |
||
227 | $blog_token = $this->helper_get_blog_token(); |
||
228 | |||
229 | if ( $blog_token ) { |
||
230 | $result = self::passing_test( array( 'name' => $name ) ); |
||
231 | } else { |
||
232 | $connection_error = __( 'Blog token is missing.', 'jetpack' ); |
||
233 | |||
234 | $result = self::connection_failing_test( $name, $connection_error ); |
||
235 | } |
||
236 | |||
237 | return $result; |
||
238 | } |
||
239 | |||
240 | /** |
||
241 | * Test if Jetpack is connected. |
||
242 | */ |
||
243 | protected function test__check_if_connected() { |
||
244 | $name = __FUNCTION__; |
||
245 | |||
246 | View Code Duplication | if ( ! $this->helper_get_blog_token() ) { |
|
247 | return self::skipped_test( |
||
248 | array( |
||
249 | 'name' => $name, |
||
250 | 'short_description' => __( 'Blog token is missing.', 'jetpack' ), |
||
251 | ) |
||
252 | ); |
||
253 | } |
||
254 | |||
255 | if ( $this->helper_is_jetpack_connected() ) { |
||
256 | $result = self::passing_test( |
||
257 | array( |
||
258 | 'name' => $name, |
||
259 | 'label' => __( 'Your site is connected to Jetpack', 'jetpack' ), |
||
260 | 'long_description' => sprintf( |
||
261 | '<p>%1$s</p>' . |
||
262 | '<p><span class="dashicons pass"><span class="screen-reader-text">%2$s</span></span> %3$s</p>', |
||
263 | __( 'A healthy connection ensures Jetpack essential services are provided to your WordPress site, such as Stats and Site Security.', 'jetpack' ), |
||
264 | /* translators: Screen reader text indicating a test has passed */ |
||
265 | __( 'Passed', 'jetpack' ), |
||
266 | __( 'Your site is connected to Jetpack.', 'jetpack' ) |
||
267 | ), |
||
268 | ) |
||
269 | ); |
||
270 | } elseif ( ( new Status() )->is_offline_mode() ) { |
||
271 | $result = self::skipped_test( |
||
272 | array( |
||
273 | 'name' => $name, |
||
274 | 'short_description' => __( 'Jetpack is in Offline Mode:', 'jetpack' ) . ' ' . Jetpack::development_mode_trigger_text(), |
||
275 | ) |
||
276 | ); |
||
277 | } else { |
||
278 | $connection_error = __( 'Your site is not connected to Jetpack', 'jetpack' ); |
||
279 | |||
280 | $result = self::connection_failing_test( $name, $connection_error ); |
||
281 | } |
||
282 | |||
283 | return $result; |
||
284 | } |
||
285 | |||
286 | /** |
||
287 | * Test that the master user still exists on this site. |
||
288 | * |
||
289 | * @return array Test results. |
||
290 | */ |
||
291 | protected function test__master_user_exists_on_site() { |
||
292 | $name = __FUNCTION__; |
||
293 | View Code Duplication | if ( ! $this->helper_is_jetpack_connected() ) { |
|
294 | return self::skipped_test( |
||
295 | array( |
||
296 | 'name' => $name, |
||
297 | 'short_description' => __( 'Jetpack is not connected. No master user to check.', 'jetpack' ), |
||
298 | ) |
||
299 | ); |
||
300 | } |
||
301 | View Code Duplication | if ( ! ( new Connection_Manager() )->get_connection_owner_id() && ( new Status() )->is_no_user_testing_mode() ) { |
|
302 | return self::skipped_test( |
||
303 | array( |
||
304 | 'name' => $name, |
||
305 | 'short_description' => __( 'Jetpack is running in userless mode. No master user to check.', 'jetpack' ), |
||
306 | ) |
||
307 | ); |
||
308 | } |
||
309 | $local_user = $this->helper_retrieve_local_master_user(); |
||
310 | |||
311 | if ( $local_user->exists() ) { |
||
312 | $result = self::passing_test( array( 'name' => $name ) ); |
||
313 | } else { |
||
314 | $connection_error = __( 'The user who setup the Jetpack connection no longer exists on this site.', 'jetpack' ); |
||
315 | |||
316 | $result = self::connection_failing_test( $name, $connection_error ); |
||
317 | } |
||
318 | |||
319 | return $result; |
||
320 | } |
||
321 | |||
322 | /** |
||
323 | * Test that the master user has the manage options capability (e.g. is an admin). |
||
324 | * |
||
325 | * Generic calls from WP.com execute on Jetpack as the master user. If it isn't an admin, random things will fail. |
||
326 | * |
||
327 | * @return array Test results. |
||
328 | */ |
||
329 | protected function test__master_user_can_manage_options() { |
||
330 | $name = __FUNCTION__; |
||
331 | View Code Duplication | if ( ! $this->helper_is_jetpack_connected() ) { |
|
332 | return self::skipped_test( |
||
333 | array( |
||
334 | 'name' => $name, |
||
335 | 'short_description' => __( 'Jetpack is not connected.', 'jetpack' ), |
||
336 | ) |
||
337 | ); |
||
338 | } |
||
339 | View Code Duplication | if ( ! ( new Connection_Manager() )->get_connection_owner_id() && ( new Status() )->is_no_user_testing_mode() ) { |
|
340 | return self::skipped_test( |
||
341 | array( |
||
342 | 'name' => $name, |
||
343 | 'short_description' => __( 'Jetpack is running in userless mode. No master user to check.', 'jetpack' ), |
||
344 | ) |
||
345 | ); |
||
346 | } |
||
347 | $master_user = $this->helper_retrieve_local_master_user(); |
||
348 | |||
349 | if ( user_can( $master_user, 'manage_options' ) ) { |
||
350 | $result = self::passing_test( array( 'name' => $name ) ); |
||
351 | } else { |
||
352 | /* translators: a WordPress username */ |
||
353 | $connection_error = sprintf( __( 'The user (%s) who setup the Jetpack connection is not an administrator.', 'jetpack' ), $master_user->user_login ); |
||
354 | /* translators: a WordPress username */ |
||
355 | $recommendation = sprintf( __( 'We recommend either upgrading the user (%s) or reconnecting Jetpack.', 'jetpack' ), $master_user->user_login ); |
||
356 | |||
357 | $result = self::connection_failing_test( $name, $connection_error, $recommendation ); |
||
358 | } |
||
359 | |||
360 | return $result; |
||
361 | } |
||
362 | |||
363 | /** |
||
364 | * Test that the PHP's XML library is installed. |
||
365 | * |
||
366 | * While it should be installed by default, increasingly in PHP 7, some OSes require an additional php-xml package. |
||
367 | * |
||
368 | * @return array Test results. |
||
369 | */ |
||
370 | protected function test__xml_parser_available() { |
||
387 | |||
388 | /** |
||
389 | * Test that the server is able to send an outbound http communication. |
||
390 | * |
||
391 | * @return array Test results. |
||
392 | */ |
||
393 | View Code Duplication | protected function test__outbound_http() { |
|
411 | |||
412 | /** |
||
413 | * Test that the server is able to send an outbound https communication. |
||
414 | * |
||
415 | * @return array Test results. |
||
416 | */ |
||
417 | View Code Duplication | protected function test__outbound_https() { |
|
435 | |||
436 | /** |
||
437 | * Check for an IDC. |
||
438 | * |
||
439 | * @return array Test results. |
||
440 | */ |
||
441 | protected function test__identity_crisis() { |
||
472 | |||
473 | /** |
||
474 | * Tests the health of the Connection tokens. |
||
475 | * |
||
476 | * This will always check the blog token health. It will also check the user token health if |
||
477 | * a user is logged in and connected, or if there's a connected owner. |
||
478 | * |
||
479 | * @since 9.0.0 |
||
480 | * @since 9.6.0 Checks only blog token if current user not connected or site does not have a connected owner. |
||
481 | * |
||
482 | * @return array Test results. |
||
483 | */ |
||
484 | protected function test__connection_token_health() { |
||
508 | |||
509 | /** |
||
510 | * Tests blog and user's token against wp.com's check-token-health endpoint. |
||
511 | * |
||
512 | * @since 9.6.0 |
||
513 | * |
||
514 | * @return array Test results. |
||
515 | */ |
||
516 | protected function check_blog_token_health() { |
||
526 | |||
527 | /** |
||
528 | * Tests blog token against wp.com's check-token-health endpoint. |
||
529 | * |
||
530 | * @since 9.6.0 |
||
531 | * |
||
532 | * @param int $user_id The user ID to check the tokens for. |
||
533 | * |
||
534 | * @return array Test results. |
||
535 | */ |
||
536 | protected function check_tokens_health( $user_id ) { |
||
565 | |||
566 | /** |
||
567 | * Tests connection status against wp.com's test-connection endpoint. |
||
568 | * |
||
569 | * @todo: Compare with the wpcom_self_test. We only need one of these. |
||
570 | * |
||
571 | * @return array Test results. |
||
572 | */ |
||
573 | protected function test__wpcom_connection_test() { |
||
639 | |||
640 | /** |
||
641 | * Tests the port number to ensure it is an expected value. |
||
642 | * |
||
643 | * We expect that sites on be on one of: |
||
644 | * port 80, |
||
645 | * port 443 (https sites only), |
||
646 | * the value of JETPACK_SIGNATURE__HTTP_PORT, |
||
647 | * unless the site is intentionally on a different port (e.g. example.com:8080 is the site's URL). |
||
648 | * |
||
649 | * If the value isn't one of those and the site's URL doesn't include a port, then the signature verification will fail. |
||
650 | * |
||
651 | * This happens most commonly on sites with reverse proxies, so the edge (e.g. Varnish) is running on 80/443, but nginx |
||
652 | * or Apache is responding internally on a different port (e.g. 81). |
||
653 | * |
||
654 | * @return array Test results |
||
655 | */ |
||
656 | protected function test__server_port_value() { |
||
709 | |||
710 | /** |
||
711 | * Full Sync Health Test. |
||
712 | * |
||
713 | * Sync Disabled: Results in a skipped test |
||
714 | * Not In Progress : Results in a skipped test |
||
715 | * In Progress: Results in skipped test w/ status in CLI |
||
716 | */ |
||
717 | protected function test__full_sync_health() { |
||
781 | |||
782 | /** |
||
783 | * Sync Health Tests. |
||
784 | * |
||
785 | * Disabled: Results in a failing test (recommended) |
||
786 | * Delayed: Results in failing test (recommended) |
||
787 | * Error: Results in failing test (critical) |
||
788 | */ |
||
789 | protected function test__sync_health() { |
||
930 | |||
931 | /** |
||
932 | * Calls to WP.com to run the connection diagnostic testing suite. |
||
933 | * |
||
934 | * Intentionally added last as it will be skipped if any local failed conditions exist. |
||
935 | * |
||
936 | * @since 7.1.0 |
||
937 | * @since 7.9.0 Timeout waiting for a WP.com response no longer fails the test. Test is marked skipped instead. |
||
938 | * |
||
939 | * @return array Test results. |
||
940 | */ |
||
941 | protected function last__wpcom_self_test() { |
||
986 | } |
||
987 |
In PHP, under loose comparison (like
==
, or!=
, orswitch
conditions), values of different types might be equal.For
string
values, the empty string''
is a special case, in particular the following results might be unexpected: