Completed
Push — update/move_connection_owner_d... ( a0bfdc )
by
unknown
08:37
created

REST_Connector::set_connection_owner()   B

Complexity

Conditions 8
Paths 7

Size

Total Lines 71

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
nc 7
nop 1
dl 0
loc 71
rs 7.3882
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Sets up the Connection REST API endpoints.
4
 *
5
 * @package automattic/jetpack-connection
6
 */
7
8
namespace Automattic\Jetpack\Connection;
9
10
use Automattic\Jetpack\Status;
11
use Automattic\Jetpack\Tracking;
12
use Jetpack_XMLRPC_Server;
13
use WP_Error;
14
use WP_REST_Request;
15
use WP_REST_Response;
16
use WP_REST_Server;
17
18
/**
19
 * Registers the REST routes for Connections.
20
 */
21
class REST_Connector {
22
	/**
23
	 * The Connection Manager.
24
	 *
25
	 * @var Manager
26
	 */
27
	private $connection;
28
29
	/**
30
	 * This property stores the localized "Insufficient Permissions" error message.
31
	 *
32
	 * @var string Generic error message when user is not allowed to perform an action.
33
	 */
34
	private static $user_permissions_error_msg;
35
36
	/**
37
	 * Constructor.
38
	 *
39
	 * @param Manager $connection The Connection Manager.
40
	 */
41
	public function __construct( Manager $connection ) {
42
		$this->connection = $connection;
43
44
		self::$user_permissions_error_msg = esc_html__(
45
			'You do not have the correct user permissions to perform this action.
46
			Please contact your site admin if you think this is a mistake.',
47
			'jetpack'
48
		);
49
50
		if ( ! $this->connection->is_active() ) {
51
			// Register a site.
52
			register_rest_route(
53
				'jetpack/v4',
54
				'/verify_registration',
55
				array(
56
					'methods'             => WP_REST_Server::EDITABLE,
57
					'callback'            => array( $this, 'verify_registration' ),
58
					'permission_callback' => '__return_true',
59
				)
60
			);
61
		}
62
63
		// Authorize a remote user.
64
		register_rest_route(
65
			'jetpack/v4',
66
			'/remote_authorize',
67
			array(
68
				'methods'             => WP_REST_Server::EDITABLE,
69
				'callback'            => __CLASS__ . '::remote_authorize',
70
				'permission_callback' => '__return_true',
71
			)
72
		);
73
74
		// Get current connection status of Jetpack.
75
		register_rest_route(
76
			'jetpack/v4',
77
			'/connection',
78
			array(
79
				'methods'             => WP_REST_Server::READABLE,
80
				'callback'            => __CLASS__ . '::connection_status',
81
				'permission_callback' => '__return_true',
82
			)
83
		);
84
85
		// Get list of plugins that use the Jetpack connection.
86
		register_rest_route(
87
			'jetpack/v4',
88
			'/connection/plugins',
89
			array(
90
				'methods'             => WP_REST_Server::READABLE,
91
				'callback'            => array( $this, 'get_connection_plugins' ),
92
				'permission_callback' => __CLASS__ . '::activate_plugins_permission_check',
93
			)
94
		);
95
96
		// Full or partial reconnect in case of connection issues.
97
		register_rest_route(
98
			'jetpack/v4',
99
			'/connection/reconnect',
100
			array(
101
				'methods'             => WP_REST_Server::EDITABLE,
102
				'callback'            => array( $this, 'connection_reconnect' ),
103
				'permission_callback' => __CLASS__ . '::jetpack_reconnect_permission_check',
104
			)
105
		);
106
107
		// Set the connection owner.
108
		register_rest_route(
109
			'jetpack/v4',
110
			'/connection/owner',
111
			array(
112
				'methods'             => WP_REST_Server::EDITABLE,
113
				'callback'            => array( $this, 'set_connection_owner' ),
114
				'permission_callback' => array( $this, 'set_connection_owner_permission_callback' ),
115
			)
116
		);
117
	}
118
119
	/**
120
	 * Handles verification that a site is registered.
121
	 *
122
	 * @since 5.4.0
123
	 *
124
	 * @param WP_REST_Request $request The request sent to the WP REST API.
125
	 *
126
	 * @return string|WP_Error
127
	 */
128
	public function verify_registration( WP_REST_Request $request ) {
129
		$registration_data = array( $request['secret_1'], $request['state'] );
130
131
		return $this->connection->handle_registration( $registration_data );
132
	}
133
134
	/**
135
	 * Handles verification that a site is registered
136
	 *
137
	 * @since 5.4.0
138
	 *
139
	 * @param WP_REST_Request $request The request sent to the WP REST API.
140
	 *
141
	 * @return array|wp-error
0 ignored issues
show
Documentation introduced by
The doc-type array|wp-error could not be parsed: Unknown type name "wp-error" at position 6. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
142
	 */
143
	public static function remote_authorize( $request ) {
144
		$xmlrpc_server = new Jetpack_XMLRPC_Server();
145
		$result        = $xmlrpc_server->remote_authorize( $request );
146
147
		if ( is_a( $result, 'IXR_Error' ) ) {
148
			$result = new WP_Error( $result->code, $result->message );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with $result->code.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
149
		}
150
151
		return $result;
152
	}
153
154
	/**
155
	 * Get connection status for this Jetpack site.
156
	 *
157
	 * @since 4.3.0
158
	 *
159
	 * @param bool $rest_response Should we return a rest response or a simple array. Default to rest response.
160
	 *
161
	 * @return WP_REST_Response|array Connection information.
162
	 */
163
	public static function connection_status( $rest_response = true ) {
164
		$status     = new Status();
165
		$connection = new Manager();
166
167
		$connection_status = array(
168
			'isActive'     => $connection->is_active(),
169
			'isStaging'    => $status->is_staging_site(),
170
			'isRegistered' => $connection->is_registered(),
171
			'offlineMode'  => array(
172
				'isActive'        => $status->is_offline_mode(),
173
				'constant'        => defined( 'JETPACK_DEV_DEBUG' ) && JETPACK_DEV_DEBUG,
174
				'url'             => $status->is_local_site(),
175
				/** This filter is documented in packages/status/src/class-status.php */
176
				'filter'          => ( apply_filters( 'jetpack_development_mode', false ) || apply_filters( 'jetpack_offline_mode', false ) ), // jetpack_development_mode is deprecated.
177
				'wpLocalConstant' => defined( 'WP_LOCAL_DEV' ) && WP_LOCAL_DEV,
178
			),
179
			'isPublic'     => '1' == get_option( 'blog_public' ), // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
180
		);
181
182
		if ( $rest_response ) {
183
			return rest_ensure_response(
184
				$connection_status
185
			);
186
		} else {
187
			return $connection_status;
188
		}
189
	}
190
191
192
	/**
193
	 * Get plugins connected to the Jetpack.
194
	 *
195
	 * @since 8.6.0
196
	 *
197
	 * @return WP_REST_Response|WP_Error Response or error object, depending on the request result.
198
	 */
199
	public function get_connection_plugins() {
200
		$plugins = $this->connection->get_connected_plugins();
201
202
		if ( is_wp_error( $plugins ) ) {
203
			return $plugins;
204
		}
205
206
		array_walk(
207
			$plugins,
208
			function( &$data, $slug ) {
209
				$data['slug'] = $slug;
210
			}
211
		);
212
213
		return rest_ensure_response( array_values( $plugins ) );
214
	}
215
216
	/**
217
	 * Verify that user can view Jetpack admin page and can activate plugins.
218
	 *
219
	 * @since 8.8.0
220
	 *
221
	 * @return bool|WP_Error Whether user has the capability 'activate_plugins'.
222
	 */
223
	public static function activate_plugins_permission_check() {
224
		if ( current_user_can( 'activate_plugins' ) ) {
225
			return true;
226
		}
227
228
		return new WP_Error( 'invalid_user_permission_activate_plugins', self::get_user_permissions_error_msg(), array( 'status' => rest_authorization_required_code() ) );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'invalid_user_permission_activate_plugins'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
229
	}
230
231
	/**
232
	 * Verify that user is allowed to disconnect Jetpack.
233
	 *
234
	 * @since 8.8.0
235
	 *
236
	 * @return bool|WP_Error Whether user has the capability 'jetpack_disconnect'.
237
	 */
238
	public static function jetpack_reconnect_permission_check() {
239
		if ( current_user_can( 'jetpack_reconnect' ) ) {
240
			return true;
241
		}
242
243
		return new WP_Error( 'invalid_user_permission_jetpack_disconnect', self::get_user_permissions_error_msg(), array( 'status' => rest_authorization_required_code() ) );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'invalid_user_permission_jetpack_disconnect'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
244
	}
245
246
	/**
247
	 * Returns generic error message when user is not allowed to perform an action.
248
	 *
249
	 * @return string The error message.
250
	 */
251
	public static function get_user_permissions_error_msg() {
252
		return self::$user_permissions_error_msg;
253
	}
254
255
	/**
256
	 * The endpoint tried to partially or fully reconnect the website to WP.com.
257
	 *
258
	 * @since 8.8.0
259
	 *
260
	 * @return \WP_REST_Response|WP_Error
261
	 */
262
	public function connection_reconnect() {
263
		$response = array();
264
265
		$next = null;
266
267
		$result = $this->connection->restore();
268
269
		if ( is_wp_error( $result ) ) {
270
			$response = $result;
271
		} elseif ( is_string( $result ) ) {
272
			$next = $result;
273
		} else {
274
			$next = true === $result ? 'completed' : 'failed';
275
		}
276
277
		switch ( $next ) {
278
			case 'authorize':
279
				$response['status']       = 'in_progress';
280
				$response['authorizeUrl'] = $this->connection->get_authorization_url();
281
				break;
282
			case 'completed':
283
				$response['status'] = 'completed';
284
				break;
285
			case 'failed':
286
				$response = new WP_Error( 'Reconnect failed' );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'Reconnect failed'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
287
				break;
288
		}
289
290
		return rest_ensure_response( $response );
291
	}
292
293
	/**
294
	 * Check that user has permission to change the master user.
295
	 *
296
	 * @since 6.2.0
297
	 * @since 7.7.0 Update so that any user with jetpack_disconnect privs can set owner.
298
	 *
299
	 * @return bool|WP_Error True if user is able to change master user.
300
	 */
301 View Code Duplication
	public function set_connection_owner_permission_callback() {
302
		if ( current_user_can( 'jetpack_disconnect' ) ) {
303
			return true;
304
		}
305
306
		return new WP_Error( 'invalid_user_permission_set_connection_owner', self::$user_permissions_error_msg, array( 'status' => rest_authorization_required_code() ) );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'invalid_user_permission_set_connection_owner'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
307
	}
308
309
	/**
310
	 * Change the connection owner.
311
	 *
312
	 * @since 6.2.0
313
	 *
314
	 * @param WP_REST_Request $request The request sent to the WP REST API.
315
	 *
316
	 * @return bool|WP_Error True if owner successfully changed.
317
	 */
318
	public function set_connection_owner( $request ) {
319
		if ( ! isset( $request['owner'] ) ) {
320
			return new WP_Error(
321
				'invalid_param',
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'invalid_param'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
322
				esc_html__( 'Invalid Parameter', 'jetpack' ),
323
				array( 'status' => 400 )
324
			);
325
		}
326
327
		$new_owner_id = $request['owner'];
328
		if ( ! user_can( $new_owner_id, 'administrator' ) ) {
329
			return new WP_Error(
330
				'new_owner_not_admin',
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'new_owner_not_admin'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
331
				esc_html__( 'New owner is not admin', 'jetpack' ),
332
				array( 'status' => 400 )
333
			);
334
		}
335
336
		if ( get_current_user_id() === $new_owner_id ) {
337
			return new WP_Error(
338
				'new_owner_is_current_user',
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'new_owner_is_current_user'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
339
				esc_html__( 'New owner is same as current user', 'jetpack' ),
340
				array( 'status' => 400 )
341
			);
342
		}
343
344
		if ( ! $this->connection->is_user_connected( $new_owner_id ) ) {
345
			return new WP_Error(
346
				'new_owner_not_connected',
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'new_owner_not_connected'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
347
				esc_html__( 'New owner is not connected', 'jetpack' ),
348
				array( 'status' => 400 )
349
			);
350
		}
351
352
		// Update the master user in Jetpack.
353
		$updated = \Jetpack_Options::update_option( 'master_user', $new_owner_id );
354
355
		// Notify WPCOM about the master user change.
356
		$xml = new \Jetpack_IXR_Client(
357
			array(
358
				'user_id' => get_current_user_id(),
359
			)
360
		);
361
		$xml->query(
362
			'jetpack.switchBlogOwner',
363
			array(
364
				'new_blog_owner' => $new_owner_id,
365
			)
366
		);
367
368
		if ( $updated && ! $xml->isError() ) {
369
370
			// Track it.
371
			if ( class_exists( 'Automattic\Jetpack\Tracking' ) ) {
372
				$tracking = new Tracking();
373
				$tracking->record_user_event( 'set_connection_owner_success' );
374
			}
375
376
			return rest_ensure_response(
377
				array(
378
					'code' => 'success',
379
				)
380
			);
381
		}
382
383
		return new WP_Error(
384
			'error_setting_new_owner',
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'error_setting_new_owner'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
385
			esc_html__( 'Could not confirm new owner.', 'jetpack' ),
386
			array( 'status' => 500 )
387
		);
388
	}
389
390
}
391