Completed
Push — e2e/slack-notification ( 4d0aca...d43a76 )
by
unknown
19:59 queued 10:28
created

Jetpack_XMLRPC_Methods   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 195
Duplicated Lines 9.23 %

Coupling/Cohesion

Components 0
Dependencies 5

Importance

Changes 0
Metric Value
dl 18
loc 195
rs 10
c 0
b 0
f 0
wmc 26
lcom 0
cbo 5

8 Methods

Rating   Name   Duplication   Size   Complexity  
A init() 0 5 1
A xmlrpc_methods() 0 9 1
A features_available() 9 9 2
A features_enabled() 9 9 2
A test_connection() 0 3 1
A disconnect_blog() 0 15 1
F json_api() 0 91 17
A remote_connect_end() 0 5 1

How to fix   Duplicated Code   

Duplicated Code

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:

1
<?php
2
/**
3
 * Jetpack XMLRPC Methods.
4
 *
5
 * Registers the Jetpack specific XMLRPC methods
6
 *
7
 * @package jetpack
8
 */
9
10
use Automattic\Jetpack\Connection\Manager as Connection_Manager;
11
use Automattic\Jetpack\Connection\Tokens;
12
13
/**
14
 * XMLRPC Methods registration and callbacks
15
 */
16
class Jetpack_XMLRPC_Methods {
17
18
	/**
19
	 * Initialize the main hooks.
20
	 */
21
	public static function init() {
22
		add_filter( 'jetpack_xmlrpc_unauthenticated_methods', array( __CLASS__, 'xmlrpc_methods' ) );
23
		add_filter( 'jetpack_xmlrpc_test_connection_response', array( __CLASS__, 'test_connection' ) );
24
		add_action( 'jetpack_remote_connect_end', array( __CLASS__, 'remote_connect_end' ) );
25
	}
26
27
	/**
28
	 * Adds Jetpack specific methods to the methods added by the Connection package.
29
	 *
30
	 * @param array $methods Methods added by the Connection package.
31
	 */
32
	public static function xmlrpc_methods( $methods ) {
33
34
		$methods['jetpack.featuresAvailable'] = array( __CLASS__, 'features_available' );
35
		$methods['jetpack.featuresEnabled']   = array( __CLASS__, 'features_enabled' );
36
		$methods['jetpack.disconnectBlog']    = array( __CLASS__, 'disconnect_blog' );
37
		$methods['jetpack.jsonAPI']           = array( __CLASS__, 'json_api' );
38
39
		return $methods;
40
	}
41
42
	/**
43
	 * Returns what features are available. Uses the slug of the module files.
44
	 *
45
	 * @return array
46
	 */
47 View Code Duplication
	public static function features_available() {
48
		$raw_modules = Jetpack::get_available_modules();
49
		$modules     = array();
50
		foreach ( $raw_modules as $module ) {
51
			$modules[] = Jetpack::get_module_slug( $module );
52
		}
53
54
		return $modules;
55
	}
56
57
	/**
58
	 * Returns what features are enabled. Uses the slug of the modules files.
59
	 *
60
	 * @return array
61
	 */
62 View Code Duplication
	public static function features_enabled() {
63
		$raw_modules = Jetpack::get_active_modules();
64
		$modules     = array();
65
		foreach ( $raw_modules as $module ) {
66
			$modules[] = Jetpack::get_module_slug( $module );
67
		}
68
69
		return $modules;
70
	}
71
72
	/**
73
	 * Filters the result of test_connection XMLRPC method
74
	 *
75
	 * @return string The current Jetpack version number
76
	 */
77
	public static function test_connection() {
78
		return JETPACK__VERSION;
79
	}
80
81
	/**
82
	 * Disconnect this blog from the connected wordpress.com account
83
	 *
84
	 * @return boolean
85
	 */
86
	public static function disconnect_blog() {
87
88
		/**
89
		 * Fired when we want to log an event to the Jetpack event log.
90
		 *
91
		 * @since 7.7.0
92
		 *
93
		 * @param string $code Unique name for the event.
94
		 * @param string $data Optional data about the event.
95
		 */
96
		do_action( 'jetpack_event_log', 'disconnect' );
97
		Jetpack::disconnect();
98
99
		return true;
100
	}
101
102
	/**
103
	 * Serve a JSON API request.
104
	 *
105
	 * @param array $args request arguments.
106
	 */
107
	public static function json_api( $args = array() ) {
108
		$json_api_args        = $args[0];
109
		$verify_api_user_args = $args[1];
110
111
		$method       = (string) $json_api_args[0];
112
		$url          = (string) $json_api_args[1];
113
		$post_body    = is_null( $json_api_args[2] ) ? null : (string) $json_api_args[2];
114
		$user_details = (array) $json_api_args[4];
115
		$locale       = (string) $json_api_args[5];
116
117
		if ( ! $verify_api_user_args ) {
118
			$user_id = 0;
119
		} elseif ( 'internal' === $verify_api_user_args[0] ) {
120
			$user_id = (int) $verify_api_user_args[1];
121
			if ( $user_id ) {
122
				$user = get_user_by( 'id', $user_id );
123
				if ( ! $user || is_wp_error( $user ) ) {
124
					return false;
125
				}
126
			}
127
		} else {
128
			$user_id = call_user_func( array( new Jetpack_XMLRPC_Server(), 'test_api_user_code' ), $verify_api_user_args );
129
			if ( ! $user_id ) {
130
				return false;
131
			}
132
		}
133
134
		if ( 'en' !== $locale ) {
135
			// .org mo files are named slightly different from .com, and all we have is this the locale -- try to guess them.
136
			$new_locale = $locale;
137
			if ( strpos( $locale, '-' ) !== false ) {
138
				$locale_pieces = explode( '-', $locale );
139
				$new_locale    = $locale_pieces[0];
140
				$new_locale   .= ( ! empty( $locale_pieces[1] ) ) ? '_' . strtoupper( $locale_pieces[1] ) : '';
141
			} else {
142
				// .com might pass 'fr' because thats what our language files are named as, where core seems
143
				// to do fr_FR - so try that if we don't think we can load the file.
144
				if ( ! file_exists( WP_LANG_DIR . '/' . $locale . '.mo' ) ) {
145
					$new_locale = $locale . '_' . strtoupper( $locale );
146
				}
147
			}
148
149
			if ( file_exists( WP_LANG_DIR . '/' . $new_locale . '.mo' ) ) {
150
				unload_textdomain( 'default' );
151
				load_textdomain( 'default', WP_LANG_DIR . '/' . $new_locale . '.mo' );
152
			}
153
		}
154
155
		$old_user = wp_get_current_user();
156
		wp_set_current_user( $user_id );
157
158
		if ( $user_id ) {
159
			$token_key = false;
160
		} else {
161
			$verified  = ( new Connection_Manager() )->verify_xml_rpc_signature();
162
			$token_key = $verified['token_key'];
163
		}
164
165
		$token = ( new Tokens() )->get_access_token( $user_id, $token_key );
166
		if ( ! $token || is_wp_error( $token ) ) {
167
			return false;
168
		}
169
170
		define( 'REST_API_REQUEST', true );
171
		define( 'WPCOM_JSON_API__BASE', 'public-api.wordpress.com/rest/v1' );
172
173
		// needed?
174
		require_once ABSPATH . 'wp-admin/includes/admin.php';
175
176
		require_once JETPACK__PLUGIN_DIR . 'class.json-api.php';
177
		$api                        = WPCOM_JSON_API::init( $method, $url, $post_body );
178
		$api->token_details['user'] = $user_details;
179
		require_once JETPACK__PLUGIN_DIR . 'class.json-api-endpoints.php';
180
181
		$display_errors = ini_set( 'display_errors', 0 ); // phpcs:ignore WordPress.PHP.IniSet
182
		ob_start();
183
		$api->serve( false );
184
		$output = ob_get_clean();
185
		ini_set( 'display_errors', $display_errors ); // phpcs:ignore WordPress.PHP.IniSet
186
187
		$nonce = wp_generate_password( 10, false );
188
		$hmac  = hash_hmac( 'md5', $nonce . $output, $token->secret );
189
190
		wp_set_current_user( isset( $old_user->ID ) ? $old_user->ID : 0 );
191
192
		return array(
193
			(string) $output,
194
			(string) $nonce,
195
			(string) $hmac,
196
		);
197
	}
198
199
	/**
200
	 * Hooks into the remote_connect XMLRPC endpoint and triggers Jetpack::handle_post_authorization_actions
201
	 *
202
	 * @since 9.8.0
203
	 * @return void
204
	 */
205
	public static function remote_connect_end() {
206
		/** This filter is documented in class.jetpack-cli.php */
207
		$enable_sso = apply_filters( 'jetpack_start_enable_sso', true );
208
		Jetpack::handle_post_authorization_actions( $enable_sso, false, false );
209
	}
210
}
211