Complex classes like Jetpack_XMLRPC_Server 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_XMLRPC_Server, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
19 | class Jetpack_XMLRPC_Server { |
||
20 | /** |
||
21 | * The current error object |
||
22 | * |
||
23 | * @var \WP_Error |
||
24 | */ |
||
25 | public $error = null; |
||
26 | |||
27 | /** |
||
28 | * The current user |
||
29 | * |
||
30 | * @var \WP_User |
||
31 | */ |
||
32 | public $user = null; |
||
33 | |||
34 | /** |
||
35 | * The connection manager object. |
||
36 | * |
||
37 | * @var Automattic\Jetpack\Connection\Manager |
||
38 | */ |
||
39 | private $connection; |
||
40 | |||
41 | /** |
||
42 | * Creates a new XMLRPC server object. |
||
43 | */ |
||
44 | public function __construct() { |
||
47 | |||
48 | /** |
||
49 | * Whitelist of the XML-RPC methods available to the Jetpack Server. If the |
||
50 | * user is not authenticated (->login()) then the methods are never added, |
||
51 | * so they will get a "does not exist" error. |
||
52 | * |
||
53 | * @param array $core_methods Core XMLRPC methods. |
||
54 | */ |
||
55 | public function xmlrpc_methods( $core_methods ) { |
||
104 | |||
105 | /** |
||
106 | * Whitelist of the bootstrap XML-RPC methods |
||
107 | */ |
||
108 | public function bootstrap_xmlrpc_methods() { |
||
114 | |||
115 | /** |
||
116 | * Additional method needed for authorization calls. |
||
117 | */ |
||
118 | public function authorize_xmlrpc_methods() { |
||
123 | |||
124 | /** |
||
125 | * Remote provisioning methods. |
||
126 | */ |
||
127 | public function provision_xmlrpc_methods() { |
||
135 | |||
136 | /** |
||
137 | * Used to verify whether a local user exists and what role they have. |
||
138 | * |
||
139 | * @param int|string|array $request One of: |
||
140 | * int|string The local User's ID, username, or email address. |
||
141 | * array A request array containing: |
||
142 | * 0: int|string The local User's ID, username, or email address. |
||
143 | * |
||
144 | * @return array|\IXR_Error Information about the user, or error if no such user found: |
||
145 | * roles: string[] The user's rols. |
||
146 | * login: string The user's username. |
||
147 | * email_hash string[] The MD5 hash of the user's normalized email address. |
||
148 | * caps string[] The user's capabilities. |
||
149 | * allcaps string[] The user's granular capabilities, merged from role capabilities. |
||
150 | * token_key string The Token Key of the user's Jetpack token. Empty string if none. |
||
151 | */ |
||
152 | public function get_user( $request ) { |
||
200 | |||
201 | /** |
||
202 | * Remote authorization XMLRPC method handler. |
||
203 | * |
||
204 | * @param array $request the request. |
||
205 | */ |
||
206 | public function remote_authorize( $request ) { |
||
263 | |||
264 | /** |
||
265 | * This XML-RPC method is called from the /jpphp/provision endpoint on WPCOM in order to |
||
266 | * register this site so that a plan can be provisioned. |
||
267 | * |
||
268 | * @param array $request An array containing at minimum nonce and local_user keys. |
||
269 | * |
||
270 | * @return \WP_Error|array |
||
271 | */ |
||
272 | public function remote_register( $request ) { |
||
353 | |||
354 | /** |
||
355 | * This XML-RPC method is called from the /jpphp/provision endpoint on WPCOM in order to |
||
356 | * register this site so that a plan can be provisioned. |
||
357 | * |
||
358 | * @param array $request An array containing at minimum a nonce key and a local_username key. |
||
359 | * |
||
360 | * @return \WP_Error|array |
||
361 | */ |
||
362 | public function remote_provision( $request ) { |
||
363 | $user = $this->fetch_and_verify_local_user( $request ); |
||
364 | |||
365 | if ( ! $user ) { |
||
366 | return $this->error( |
||
367 | new WP_Error( 'input_error', __( 'Valid user is required', 'jetpack' ), 400 ), |
||
368 | 'remote_provision' |
||
369 | ); |
||
370 | } |
||
371 | |||
372 | if ( is_wp_error( $user ) || is_a( $user, 'IXR_Error' ) ) { |
||
373 | return $this->error( $user, 'remote_provision' ); |
||
374 | } |
||
375 | |||
376 | $site_icon = get_site_icon_url(); |
||
377 | |||
378 | /** |
||
379 | * Filters the Redirect URI returned by the remote_register XMLRPC method |
||
380 | * |
||
381 | * @param string $redirect_uri The Redirect URI |
||
382 | * |
||
383 | * @since 9.8.0 |
||
384 | */ |
||
385 | $redirect_uri = apply_filters( 'jetpack_xmlrpc_remote_register_redirect_uri', admin_url() ); |
||
386 | |||
387 | // Generate secrets. |
||
388 | $roles = new Roles(); |
||
389 | $role = $roles->translate_user_to_role( $user ); |
||
390 | $secrets = ( new Secrets() )->generate( 'authorize', $user->ID ); |
||
391 | |||
392 | $response = array( |
||
393 | 'jp_version' => JETPACK__VERSION, |
||
394 | 'redirect_uri' => $redirect_uri, |
||
395 | 'user_id' => $user->ID, |
||
396 | 'user_email' => $user->user_email, |
||
397 | 'user_login' => $user->user_login, |
||
398 | 'scope' => $this->connection->sign_role( $role, $user->ID ), |
||
399 | 'secret' => $secrets['secret_1'], |
||
400 | 'is_active' => $this->connection->has_connected_owner(), |
||
401 | ); |
||
402 | |||
403 | if ( $site_icon ) { |
||
404 | $response['site_icon'] = $site_icon; |
||
405 | } |
||
406 | |||
407 | /** |
||
408 | * Filters the response of the remote_provision XMLRPC method |
||
409 | * |
||
410 | * @param array $response The response. |
||
411 | * @param array $request An array containing at minimum a nonce key and a local_username key. |
||
412 | * @param \WP_User $user The local authenticated user. |
||
413 | * |
||
414 | * @since 9.8.0 |
||
415 | */ |
||
416 | $response = apply_filters( 'jetpack_remote_xmlrpc_provision_response', $response, $request, $user ); |
||
417 | |||
418 | return $response; |
||
419 | } |
||
420 | |||
421 | /** |
||
422 | * Given an array containing a local user identifier and a nonce, will attempt to fetch and set |
||
423 | * an access token for the given user. |
||
424 | * |
||
425 | * @param array $request An array containing local_user and nonce keys at minimum. |
||
426 | * @param \IXR_Client $ixr_client The client object, optional. |
||
427 | * @return mixed |
||
428 | */ |
||
429 | public function remote_connect( $request, $ixr_client = false ) { |
||
501 | |||
502 | /** |
||
503 | * Getter for the local user to act as. |
||
504 | * |
||
505 | * @param array $request the current request data. |
||
506 | */ |
||
507 | private function fetch_and_verify_local_user( $request ) { |
||
524 | |||
525 | /** |
||
526 | * Gets the user object by its data. |
||
527 | * |
||
528 | * @param string $user_id can be any identifying user data. |
||
529 | */ |
||
530 | private function get_user_by_anything( $user_id ) { |
||
543 | |||
544 | /** |
||
545 | * Possible error_codes: |
||
546 | * |
||
547 | * - verify_secret_1_missing |
||
548 | * - verify_secret_1_malformed |
||
549 | * - verify_secrets_missing: verification secrets are not found in database |
||
550 | * - verify_secrets_incomplete: verification secrets are only partially found in database |
||
551 | * - verify_secrets_expired: verification secrets have expired |
||
552 | * - verify_secrets_mismatch: stored secret_1 does not match secret_1 sent by Jetpack.WordPress.com |
||
553 | * - state_missing: required parameter of state not found |
||
554 | * - state_malformed: state is not a digit |
||
555 | * - invalid_state: state in request does not match the stored state |
||
556 | * |
||
557 | * The 'authorize' and 'register' actions have additional error codes |
||
558 | * |
||
559 | * state_missing: a state ( user id ) was not supplied |
||
560 | * state_malformed: state is not the correct data type |
||
561 | * invalid_state: supplied state does not match the stored state |
||
562 | * |
||
563 | * @param array $params action An array of 3 parameters: |
||
564 | * [0]: string action. Possible values are `authorize`, `publicize` and `register`. |
||
565 | * [1]: string secret_1. |
||
566 | * [2]: int state. |
||
567 | * @return \IXR_Error|string IXR_Error on failure, secret_2 on success. |
||
568 | */ |
||
569 | public function verify_action( $params ) { |
||
582 | |||
583 | /** |
||
584 | * Wrapper for wp_authenticate( $username, $password ); |
||
585 | * |
||
586 | * @return \WP_User|bool |
||
587 | */ |
||
588 | public function login() { |
||
607 | |||
608 | /** |
||
609 | * Returns the current error as an \IXR_Error |
||
610 | * |
||
611 | * @param \WP_Error|\IXR_Error $error The error object, optional. |
||
612 | * @param string $event_name The event name. |
||
613 | * @param \WP_User $user The user object. |
||
614 | * @return bool|\IXR_Error |
||
615 | */ |
||
616 | public function error( $error = null, $event_name = null, $user = null ) { |
||
639 | |||
640 | /* API Methods */ |
||
641 | |||
642 | /** |
||
643 | * Just authenticates with the given Jetpack credentials. |
||
644 | * |
||
645 | * @return string A success string. The Jetpack plugin filters it and make it return the Jetpack plugin version. |
||
646 | */ |
||
647 | public function test_connection() { |
||
655 | |||
656 | /** |
||
657 | * Test the API user code. |
||
658 | * |
||
659 | * @param array $args arguments identifying the test site. |
||
660 | */ |
||
661 | public function test_api_user_code( $args ) { |
||
710 | |||
711 | /** |
||
712 | * Unlink a user from WordPress.com |
||
713 | * |
||
714 | * When the request is done without any parameter, this XMLRPC callback gets an empty array as input. |
||
715 | * |
||
716 | * If $user_id is not provided, it will try to disconnect the current logged in user. This will fail if called by the Master User. |
||
717 | * |
||
718 | * If $user_id is is provided, it will try to disconnect the informed user, even if it's the Master User. |
||
719 | * |
||
720 | * @param mixed $user_id The user ID to disconnect from this site. |
||
721 | */ |
||
722 | public function unlink_user( $user_id = array() ) { |
||
741 | |||
742 | /** |
||
743 | * Returns any object that is able to be synced. |
||
744 | * |
||
745 | * @deprecated since 7.8.0 |
||
746 | * @see Automattic\Jetpack\Sync\Sender::sync_object() |
||
747 | * |
||
748 | * @param array $args the synchronized object parameters. |
||
749 | * @return string Encoded sync object. |
||
750 | */ |
||
751 | public function sync_object( $args ) { |
||
755 | |||
756 | /** |
||
757 | * Returns the home URL and site URL for the current site which can be used on the WPCOM side for |
||
758 | * IDC mitigation to decide whether sync should be allowed if the home and siteurl values differ between WPCOM |
||
759 | * and the remote Jetpack site. |
||
760 | * |
||
761 | * @return array |
||
762 | */ |
||
763 | public function validate_urls_for_idc_mitigation() { |
||
769 | |||
770 | /** |
||
771 | * Updates the attachment parent object. |
||
772 | * |
||
773 | * @param array $args attachment and parent identifiers. |
||
774 | */ |
||
775 | public function update_attachment_parent( $args ) { |
||
786 | |||
787 | /** |
||
788 | * Deprecated: This method is no longer part of the Connection package and now lives on the Jetpack plugin. |
||
789 | * |
||
790 | * Disconnect this blog from the connected wordpress.com account |
||
791 | * |
||
792 | * @deprecated since 9.6.0 |
||
793 | * @see Jetpack_XMLRPC_Methods::disconnect_blog() in the Jetpack plugin |
||
794 | * |
||
795 | * @return boolean |
||
796 | */ |
||
797 | public function disconnect_blog() { |
||
804 | |||
805 | /** |
||
806 | * Deprecated: This method is no longer part of the Connection package and now lives on the Jetpack plugin. |
||
807 | * |
||
808 | * Returns what features are available. Uses the slug of the module files. |
||
809 | * |
||
810 | * @deprecated since 9.6.0 |
||
811 | * @see Jetpack_XMLRPC_Methods::features_available() in the Jetpack plugin |
||
812 | * |
||
813 | * @return array |
||
814 | */ |
||
815 | public function features_available() { |
||
822 | |||
823 | /** |
||
824 | * Deprecated: This method is no longer part of the Connection package and now lives on the Jetpack plugin. |
||
825 | * |
||
826 | * Returns what features are enabled. Uses the slug of the modules files. |
||
827 | * |
||
828 | * @deprecated since 9.6.0 |
||
829 | * @see Jetpack_XMLRPC_Methods::features_enabled() in the Jetpack plugin |
||
830 | * |
||
831 | * @return array |
||
832 | */ |
||
833 | public function features_enabled() { |
||
840 | |||
841 | /** |
||
842 | * Deprecated: This method is no longer part of the Connection package and now lives on the Jetpack plugin. |
||
843 | * |
||
844 | * Serve a JSON API request. |
||
845 | * |
||
846 | * @deprecated since 9.6.0 |
||
847 | * @see Jetpack_XMLRPC_Methods::json_api() in the Jetpack plugin |
||
848 | * |
||
849 | * @param array $args request arguments. |
||
850 | */ |
||
851 | public function json_api( $args = array() ) { |
||
858 | |||
859 | } |
||
860 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.