Completed
Push — update/base-styles-210 ( 2e278b...ad767b )
by Jeremy
22:25 queued 13:15
created

REST_Connector   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 289
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 4

Importance

Changes 0
Metric Value
dl 0
loc 289
rs 10
c 0
b 0
f 0
wmc 28
lcom 2
cbo 4

9 Methods

Rating   Name   Duplication   Size   Complexity  
B __construct() 0 72 2
A verify_registration() 0 5 1
A remote_authorize() 0 10 2
A connection_status() 0 27 5
A get_connection_plugins() 0 16 2
A activate_plugins_permission_check() 0 7 2
A get_user_permissions_error_msg() 0 3 1
B connection_reconnect() 0 49 11
A jetpack_reconnect_permission_check() 0 7 2
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 Jetpack_XMLRPC_Server;
12
use WP_Error;
13
use WP_REST_Request;
14
use WP_REST_Response;
15
use WP_REST_Server;
16
17
/**
18
 * Registers the REST routes for Connections.
19
 */
20
class REST_Connector {
21
	/**
22
	 * The Connection Manager.
23
	 *
24
	 * @var Manager
25
	 */
26
	private $connection;
27
28
	/**
29
	 * This property stores the localized "Insufficient Permissions" error message.
30
	 *
31
	 * @var string Generic error message when user is not allowed to perform an action.
32
	 */
33
	private static $user_permissions_error_msg;
34
35
	/**
36
	 * Constructor.
37
	 *
38
	 * @param Manager $connection The Connection Manager.
39
	 */
40
	public function __construct( Manager $connection ) {
41
		$this->connection = $connection;
42
43
		self::$user_permissions_error_msg = esc_html__(
44
			'You do not have the correct user permissions to perform this action.
45
			Please contact your site admin if you think this is a mistake.',
46
			'jetpack'
47
		);
48
49
		if ( ! $this->connection->is_active() ) {
50
			// Register a site.
51
			register_rest_route(
52
				'jetpack/v4',
53
				'/verify_registration',
54
				array(
55
					'methods'             => WP_REST_Server::EDITABLE,
56
					'callback'            => array( $this, 'verify_registration' ),
57
					'permission_callback' => '__return_true',
58
				)
59
			);
60
		}
61
62
		// Authorize a remote user.
63
		register_rest_route(
64
			'jetpack/v4',
65
			'/remote_authorize',
66
			array(
67
				'methods'             => WP_REST_Server::EDITABLE,
68
				'callback'            => __CLASS__ . '::remote_authorize',
69
				'permission_callback' => '__return_true',
70
			)
71
		);
72
73
		// Get current connection status of Jetpack.
74
		register_rest_route(
75
			'jetpack/v4',
76
			'/connection',
77
			array(
78
				'methods'             => WP_REST_Server::READABLE,
79
				'callback'            => __CLASS__ . '::connection_status',
80
				'permission_callback' => '__return_true',
81
			)
82
		);
83
84
		// Get list of plugins that use the Jetpack connection.
85
		register_rest_route(
86
			'jetpack/v4',
87
			'/connection/plugins',
88
			array(
89
				'methods'             => WP_REST_Server::READABLE,
90
				'callback'            => array( $this, 'get_connection_plugins' ),
91
				'permission_callback' => __CLASS__ . '::activate_plugins_permission_check',
92
			)
93
		);
94
95
		// Full or partial reconnect in case of connection issues.
96
		register_rest_route(
97
			'jetpack/v4',
98
			'/connection/reconnect',
99
			array(
100
				'methods'             => WP_REST_Server::EDITABLE,
101
				'callback'            => array( $this, 'connection_reconnect' ),
102
				'args'                => array(
103
					'action' => array(
104
						'type'     => 'string',
105
						'required' => true,
106
					),
107
				),
108
				'permission_callback' => __CLASS__ . '::jetpack_reconnect_permission_check',
109
			)
110
		);
111
	}
112
113
	/**
114
	 * Handles verification that a site is registered.
115
	 *
116
	 * @since 5.4.0
117
	 *
118
	 * @param WP_REST_Request $request The request sent to the WP REST API.
119
	 *
120
	 * @return string|WP_Error
121
	 */
122
	public function verify_registration( WP_REST_Request $request ) {
123
		$registration_data = array( $request['secret_1'], $request['state'] );
124
125
		return $this->connection->handle_registration( $registration_data );
126
	}
127
128
	/**
129
	 * Handles verification that a site is registered
130
	 *
131
	 * @since 5.4.0
132
	 *
133
	 * @param WP_REST_Request $request The request sent to the WP REST API.
134
	 *
135
	 * @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...
136
	 */
137
	public static function remote_authorize( $request ) {
138
		$xmlrpc_server = new Jetpack_XMLRPC_Server();
139
		$result        = $xmlrpc_server->remote_authorize( $request );
140
141
		if ( is_a( $result, 'IXR_Error' ) ) {
142
			$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...
143
		}
144
145
		return $result;
146
	}
147
148
	/**
149
	 * Get connection status for this Jetpack site.
150
	 *
151
	 * @since 4.3.0
152
	 *
153
	 * @param bool $rest_response Should we return a rest response or a simple array. Default to rest response.
154
	 *
155
	 * @return WP_REST_Response|array Connection information.
156
	 */
157
	public static function connection_status( $rest_response = true ) {
158
		$status     = new Status();
159
		$connection = new Manager();
160
161
		$connection_status = array(
162
			'isActive'     => $connection->is_active(),
163
			'isStaging'    => $status->is_staging_site(),
164
			'isRegistered' => $connection->is_registered(),
165
			'offlineMode'  => array(
166
				'isActive'        => $status->is_offline_mode(),
167
				'constant'        => defined( 'JETPACK_DEV_DEBUG' ) && JETPACK_DEV_DEBUG,
168
				'url'             => $status->is_local_site(),
169
				/** This filter is documented in packages/status/src/class-status.php */
170
				'filter'          => ( apply_filters( 'jetpack_development_mode', false ) || apply_filters( 'jetpack_offline_mode', false ) ), // jetpack_development_mode is deprecated.
171
				'wpLocalConstant' => defined( 'WP_LOCAL_DEV' ) && WP_LOCAL_DEV,
172
			),
173
			'isPublic'     => '1' == get_option( 'blog_public' ), // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
174
		);
175
176
		if ( $rest_response ) {
177
			return rest_ensure_response(
178
				$connection_status
179
			);
180
		} else {
181
			return $connection_status;
182
		}
183
	}
184
185
186
	/**
187
	 * Get plugins connected to the Jetpack.
188
	 *
189
	 * @since 8.6.0
190
	 *
191
	 * @return WP_REST_Response|WP_Error Response or error object, depending on the request result.
192
	 */
193
	public function get_connection_plugins() {
194
		$plugins = $this->connection->get_connected_plugins();
195
196
		if ( is_wp_error( $plugins ) ) {
197
			return $plugins;
198
		}
199
200
		array_walk(
201
			$plugins,
202
			function( &$data, $slug ) {
203
				$data['slug'] = $slug;
204
			}
205
		);
206
207
		return rest_ensure_response( array_values( $plugins ) );
208
	}
209
210
	/**
211
	 * Verify that user can view Jetpack admin page and can activate plugins.
212
	 *
213
	 * @since 8.8.0
214
	 *
215
	 * @return bool|WP_Error Whether user has the capability 'activate_plugins'.
216
	 */
217
	public static function activate_plugins_permission_check() {
218
		if ( current_user_can( 'activate_plugins' ) ) {
219
			return true;
220
		}
221
222
		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...
223
	}
224
225
	/**
226
	 * Verify that user is allowed to disconnect Jetpack.
227
	 *
228
	 * @since 8.8.0
229
	 *
230
	 * @return bool|WP_Error Whether user has the capability 'jetpack_disconnect'.
231
	 */
232
	public static function jetpack_reconnect_permission_check() {
233
		if ( current_user_can( 'jetpack_reconnect' ) ) {
234
			return true;
235
		}
236
237
		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...
238
	}
239
240
	/**
241
	 * Returns generic error message when user is not allowed to perform an action.
242
	 *
243
	 * @return string The error message.
244
	 */
245
	public static function get_user_permissions_error_msg() {
246
		return self::$user_permissions_error_msg;
247
	}
248
249
	/**
250
	 * The endpoint tried to partially or fully reconnect the website to WP.com.
251
	 *
252
	 * @since 8.8.0
253
	 *
254
	 * @param WP_REST_Request $request The request sent to the WP REST API.
255
	 *
256
	 * @return \WP_REST_Response|WP_Error
257
	 */
258
	public function connection_reconnect( WP_REST_Request $request ) {
259
		$params = $request->get_json_params();
260
261
		$response = array();
262
263
		$next = null;
264
265
		switch ( $params['action'] ) {
266
			case 'reconnect':
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
				break;
278
			case 'reconnect_force':
279
				$result = $this->connection->reconnect();
280
281
				if ( true === $result ) {
282
					$next = 'authorize';
283
				} elseif ( is_wp_error( $result ) ) {
284
					$response = $result;
285
				}
286
				break;
287
			default:
288
				$response = new WP_Error( 'Unknown action' );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'Unknown action'.

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...
289
				break;
290
		}
291
292
		switch ( $next ) {
293
			case 'authorize':
294
				$response['status']       = 'in_progress';
295
				$response['authorizeUrl'] = $this->connection->get_authorization_url();
296
				break;
297
			case 'completed':
298
				$response['status'] = 'completed';
299
				break;
300
			case 'failed':
301
				$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...
302
				break;
303
		}
304
305
		return rest_ensure_response( $response );
306
	}
307
308
}
309