Completed
Push — upgrade/calypso-build-5-0 ( cfdf44...a97a40 )
by Bernhard
06:13
created

Jetpack_XMLRPC_Server::provision_xmlrpc_methods()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Jetpack XMLRPC Server.
4
 *
5
 * @package automattic/jetpack-connection
6
 */
7
8
use Automattic\Jetpack\Connection\Client;
9
use Automattic\Jetpack\Connection\Manager as Connection_Manager;
10
use Automattic\Jetpack\Connection\Utils as Connection_Utils;
11
use Automattic\Jetpack\Roles;
12
use Automattic\Jetpack\Sync\Modules;
13
use Automattic\Jetpack\Sync\Functions;
14
use Automattic\Jetpack\Sync\Sender;
15
use Automattic\Jetpack\Tracking;
16
17
/**
18
 * Just a sack of functions.  Not actually an IXR_Server
19
 */
20
class Jetpack_XMLRPC_Server {
21
	/**
22
	 * The current error object
23
	 *
24
	 * @var \WP_Error
25
	 */
26
	public $error = null;
27
28
	/**
29
	 * The current user
30
	 *
31
	 * @var \WP_User
32
	 */
33
	public $user = null;
34
35
	/**
36
	 * The tracking manager object.
37
	 *
38
	 * @var Automattic\Jetpack\Tracking
39
	 */
40
	private $tracking;
41
42
	/**
43
	 * The connection manager object.
44
	 *
45
	 * @var Automattic\Jetpack\Connection\Manager
46
	 */
47
	private $connection;
48
49
	/**
50
	 * Creates a new XMLRPC server object.
51
	 *
52
	 * @param Automattic\Jetpack\Connection\Manager $manager the connection manager object.
0 ignored issues
show
Documentation introduced by
Should the type for parameter $manager not be Connection_Manager|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
53
	 */
54
	public function __construct( $manager = null ) {
55
		$this->connection = is_null( $manager ) ? new Connection_Manager() : $manager;
56
		$this->tracking   = new Tracking( 'jetpack', $manager );
0 ignored issues
show
Bug introduced by
It seems like $manager defined by parameter $manager on line 54 can also be of type object<Automattic\Jetpack\Connection\Manager>; however, Automattic\Jetpack\Tracking::__construct() does only seem to accept object<Automattic\Jetpac...onnection\Manager>|null, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
57
	}
58
59
	/**
60
	 * Whitelist of the XML-RPC methods available to the Jetpack Server. If the
61
	 * user is not authenticated (->login()) then the methods are never added,
62
	 * so they will get a "does not exist" error.
63
	 *
64
	 * @param array $core_methods Core XMLRPC methods.
65
	 */
66
	public function xmlrpc_methods( $core_methods ) {
67
		$jetpack_methods = array(
68
			'jetpack.jsonAPI'         => array( $this, 'json_api' ),
69
			'jetpack.verifyAction'    => array( $this, 'verify_action' ),
70
			'jetpack.getUser'         => array( $this, 'get_user' ),
71
			'jetpack.remoteRegister'  => array( $this, 'remote_register' ),
72
			'jetpack.remoteProvision' => array( $this, 'remote_provision' ),
73
		);
74
75
		$this->user = $this->login();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->login() can also be of type boolean. However, the property $user is declared as type object<WP_User>. Maybe add an additional type check?

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 the id property of an instance of the Account 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.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
76
77
		if ( $this->user ) {
78
			$jetpack_methods = array_merge(
79
				$jetpack_methods,
80
				array(
81
					'jetpack.testConnection'    => array( $this, 'test_connection' ),
82
					'jetpack.testAPIUserCode'   => array( $this, 'test_api_user_code' ),
83
					'jetpack.featuresAvailable' => array( $this, 'features_available' ),
84
					'jetpack.featuresEnabled'   => array( $this, 'features_enabled' ),
85
					'jetpack.disconnectBlog'    => array( $this, 'disconnect_blog' ),
86
					'jetpack.unlinkUser'        => array( $this, 'unlink_user' ),
87
					'jetpack.idcUrlValidation'  => array( $this, 'validate_urls_for_idc_mitigation' ),
88
				)
89
			);
90
91
			if ( isset( $core_methods['metaWeblog.editPost'] ) ) {
92
				$jetpack_methods['metaWeblog.newMediaObject']      = $core_methods['metaWeblog.newMediaObject'];
93
				$jetpack_methods['jetpack.updateAttachmentParent'] = array( $this, 'update_attachment_parent' );
94
			}
95
96
			/**
97
			 * Filters the XML-RPC methods available to Jetpack for authenticated users.
98
			 *
99
			 * @since 1.1.0
100
			 *
101
			 * @param array    $jetpack_methods XML-RPC methods available to the Jetpack Server.
102
			 * @param array    $core_methods    Available core XML-RPC methods.
103
			 * @param \WP_User $user            Information about a given WordPress user.
104
			 */
105
			$jetpack_methods = apply_filters( 'jetpack_xmlrpc_methods', $jetpack_methods, $core_methods, $this->user );
106
		}
107
108
		/**
109
		 * Filters the XML-RPC methods available to Jetpack for unauthenticated users.
110
		 *
111
		 * @since 3.0.0
112
		 *
113
		 * @param array $jetpack_methods XML-RPC methods available to the Jetpack Server.
114
		 * @param array $core_methods    Available core XML-RPC methods.
115
		 */
116
		return apply_filters( 'jetpack_xmlrpc_unauthenticated_methods', $jetpack_methods, $core_methods );
117
	}
118
119
	/**
120
	 * Whitelist of the bootstrap XML-RPC methods
121
	 */
122
	public function bootstrap_xmlrpc_methods() {
123
		return array(
124
			'jetpack.remoteAuthorize' => array( $this, 'remote_authorize' ),
125
			'jetpack.remoteRegister'  => array( $this, 'remote_register' ),
126
		);
127
	}
128
129
	/**
130
	 * Additional method needed for authorization calls.
131
	 */
132
	public function authorize_xmlrpc_methods() {
133
		return array(
134
			'jetpack.remoteAuthorize' => array( $this, 'remote_authorize' ),
135
		);
136
	}
137
138
	/**
139
	 * Remote provisioning methods.
140
	 */
141
	public function provision_xmlrpc_methods() {
142
		return array(
143
			'jetpack.remoteRegister'  => array( $this, 'remote_register' ),
144
			'jetpack.remoteProvision' => array( $this, 'remote_provision' ),
145
			'jetpack.remoteConnect'   => array( $this, 'remote_connect' ),
146
			'jetpack.getUser'         => array( $this, 'get_user' ),
147
		);
148
	}
149
150
	/**
151
	 * Used to verify whether a local user exists and what role they have.
152
	 *
153
	 * @param int|string|array $request One of:
154
	 *                         int|string The local User's ID, username, or email address.
155
	 *                         array      A request array containing:
156
	 *                                    0: int|string The local User's ID, username, or email address.
157
	 *
158
	 * @return array|\IXR_Error Information about the user, or error if no such user found:
159
	 *                          roles:     string[] The user's rols.
160
	 *                          login:     string   The user's username.
161
	 *                          email_hash string[] The MD5 hash of the user's normalized email address.
162
	 *                          caps       string[] The user's capabilities.
163
	 *                          allcaps    string[] The user's granular capabilities, merged from role capabilities.
164
	 *                          token_key  string   The Token Key of the user's Jetpack token. Empty string if none.
165
	 */
166
	public function get_user( $request ) {
167
		$user_id = is_array( $request ) ? $request[0] : $request;
168
169
		if ( ! $user_id ) {
170
			return $this->error(
171
				new Jetpack_Error(
172
					'invalid_user',
0 ignored issues
show
Unused Code introduced by
The call to Jetpack_Error::__construct() has too many arguments starting with 'invalid_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...
173
					__( 'Invalid user identifier.', 'jetpack' ),
174
					400
175
				),
176
				'jpc_get_user_fail'
177
			);
178
		}
179
180
		$user = $this->get_user_by_anything( $user_id );
181
182
		if ( ! $user ) {
183
			return $this->error(
184
				new Jetpack_Error(
185
					'user_unknown',
0 ignored issues
show
Unused Code introduced by
The call to Jetpack_Error::__construct() has too many arguments starting with 'user_unknown'.

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...
186
					__( 'User not found.', 'jetpack' ),
187
					404
188
				),
189
				'jpc_get_user_fail'
190
			);
191
		}
192
193
		$user_token = $this->connection->get_access_token( $user->ID );
194
195
		if ( $user_token ) {
196
			list( $user_token_key ) = explode( '.', $user_token->secret );
197
			if ( $user_token_key === $user_token->secret ) {
198
				$user_token_key = '';
199
			}
200
		} else {
201
			$user_token_key = '';
202
		}
203
204
		return array(
205
			'id'         => $user->ID,
206
			'login'      => $user->user_login,
207
			'email_hash' => md5( strtolower( trim( $user->user_email ) ) ),
208
			'roles'      => $user->roles,
209
			'caps'       => $user->caps,
210
			'allcaps'    => $user->allcaps,
211
			'token_key'  => $user_token_key,
212
		);
213
	}
214
215
	/**
216
	 * Remote authorization XMLRPC method handler.
217
	 *
218
	 * @param array $request the request.
219
	 */
220
	public function remote_authorize( $request ) {
221
		$user = get_user_by( 'id', $request['state'] );
222
		$this->tracking->record_user_event( 'jpc_remote_authorize_begin', array(), $user );
223
224
		foreach ( array( 'secret', 'state', 'redirect_uri', 'code' ) as $required ) {
225
			if ( ! isset( $request[ $required ] ) || empty( $request[ $required ] ) ) {
226
				return $this->error( new Jetpack_Error( 'missing_parameter', 'One or more parameters is missing from the request.', 400 ), 'jpc_remote_authorize_fail' );
0 ignored issues
show
Unused Code introduced by
The call to Jetpack_Error::__construct() has too many arguments starting with 'missing_parameter'.

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...
227
			}
228
		}
229
230
		if ( ! $user ) {
231
			return $this->error( new Jetpack_Error( 'user_unknown', 'User not found.', 404 ), 'jpc_remote_authorize_fail' );
0 ignored issues
show
Unused Code introduced by
The call to Jetpack_Error::__construct() has too many arguments starting with 'user_unknown'.

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...
232
		}
233
234
		if ( $this->connection->is_active() && $this->connection->is_user_connected( $request['state'] ) ) {
235
			return $this->error( new Jetpack_Error( 'already_connected', 'User already connected.', 400 ), 'jpc_remote_authorize_fail' );
0 ignored issues
show
Unused Code introduced by
The call to Jetpack_Error::__construct() has too many arguments starting with 'already_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...
236
		}
237
238
		$verified = $this->verify_action( array( 'authorize', $request['secret'], $request['state'] ) );
239
240
		if ( is_a( $verified, 'IXR_Error' ) ) {
241
			return $this->error( $verified, 'jpc_remote_authorize_fail' );
242
		}
243
244
		wp_set_current_user( $request['state'] );
245
246
		$client_server = new Jetpack_Client_Server();
247
		$result        = $client_server->authorize( $request );
248
249
		if ( is_wp_error( $result ) ) {
250
			return $this->error( $result, 'jpc_remote_authorize_fail' );
0 ignored issues
show
Bug introduced by
It seems like $result defined by $client_server->authorize($request) on line 247 can also be of type string; however, Jetpack_XMLRPC_Server::error() does only seem to accept object<WP_Error>|object<IXR_Error>|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
251
		}
252
253
		$this->tracking->record_user_event( 'jpc_remote_authorize_success' );
254
255
		return array(
256
			'result' => $result,
257
		);
258
	}
259
260
	/**
261
	 * This XML-RPC method is called from the /jpphp/provision endpoint on WPCOM in order to
262
	 * register this site so that a plan can be provisioned.
263
	 *
264
	 * @param array $request An array containing at minimum nonce and local_user keys.
265
	 *
266
	 * @return \WP_Error|array
267
	 */
268
	public function remote_register( $request ) {
269
		$this->tracking->record_user_event( 'jpc_remote_register_begin', array() );
270
271
		$user = $this->fetch_and_verify_local_user( $request );
272
273
		if ( ! $user ) {
274
			return $this->error( new WP_Error( 'input_error', __( 'Valid user is required', 'jetpack' ), 400 ), 'jpc_remote_register_fail' );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'input_error'.

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...
275
		}
276
277
		if ( is_wp_error( $user ) || is_a( $user, 'IXR_Error' ) ) {
278
			return $this->error( $user, 'jpc_remote_register_fail' );
279
		}
280
281
		if ( empty( $request['nonce'] ) ) {
282
			return $this->error(
283
				new Jetpack_Error(
284
					'nonce_missing',
0 ignored issues
show
Unused Code introduced by
The call to Jetpack_Error::__construct() has too many arguments starting with 'nonce_missing'.

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...
285
					__( 'The required "nonce" parameter is missing.', 'jetpack' ),
286
					400
287
				),
288
				'jpc_remote_register_fail'
289
			);
290
		}
291
292
		$nonce = sanitize_text_field( $request['nonce'] );
293
		unset( $request['nonce'] );
294
295
		$api_url  = Connection_Utils::fix_url_for_bad_hosts(
296
			$this->connection->api_url( 'partner_provision_nonce_check' )
297
		);
298
		$response = Client::_wp_remote_request(
299
			esc_url_raw( add_query_arg( 'nonce', $nonce, $api_url ) ),
300
			array( 'method' => 'GET' ),
301
			true
302
		);
303
304
		if (
305
			200 !== wp_remote_retrieve_response_code( $response ) ||
306
			'OK' !== trim( wp_remote_retrieve_body( $response ) )
307
		) {
308
			return $this->error(
309
				new Jetpack_Error(
310
					'invalid_nonce',
0 ignored issues
show
Unused Code introduced by
The call to Jetpack_Error::__construct() has too many arguments starting with 'invalid_nonce'.

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...
311
					__( 'There was an issue validating this request.', 'jetpack' ),
312
					400
313
				),
314
				'jpc_remote_register_fail'
315
			);
316
		}
317
318
		if ( ! Jetpack_Options::get_option( 'id' ) || ! $this->connection->get_access_token() || ! empty( $request['force'] ) ) {
319
			wp_set_current_user( $user->ID );
320
321
			// This code mostly copied from Jetpack::admin_page_load.
322
			Jetpack::maybe_set_version_option();
323
			$registered = Jetpack::try_registration();
324
			if ( is_wp_error( $registered ) ) {
325
				return $this->error( $registered, 'jpc_remote_register_fail' );
326
			} elseif ( ! $registered ) {
327
				return $this->error(
328
					new Jetpack_Error(
329
						'registration_error',
0 ignored issues
show
Unused Code introduced by
The call to Jetpack_Error::__construct() has too many arguments starting with 'registration_error'.

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...
330
						__( 'There was an unspecified error registering the site', 'jetpack' ),
331
						400
332
					),
333
					'jpc_remote_register_fail'
334
				);
335
			}
336
		}
337
338
		$this->tracking->record_user_event( 'jpc_remote_register_success' );
339
340
		return array(
341
			'client_id' => Jetpack_Options::get_option( 'id' ),
342
		);
343
	}
344
345
	/**
346
	 * This XML-RPC method is called from the /jpphp/provision endpoint on WPCOM in order to
347
	 * register this site so that a plan can be provisioned.
348
	 *
349
	 * @param array $request An array containing at minimum a nonce key and a local_username key.
350
	 *
351
	 * @return \WP_Error|array
352
	 */
353
	public function remote_provision( $request ) {
354
		$user = $this->fetch_and_verify_local_user( $request );
355
356
		if ( ! $user ) {
357
			return $this->error( new WP_Error( 'input_error', __( 'Valid user is required', 'jetpack' ), 400 ), 'jpc_remote_provision_fail' );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'input_error'.

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...
358
		}
359
360
		if ( is_wp_error( $user ) || is_a( $user, 'IXR_Error' ) ) {
361
			return $this->error( $user, 'jpc_remote_provision_fail' );
362
		}
363
364
		$site_icon = get_site_icon_url();
365
366
		$auto_enable_sso = ( ! $this->connection->is_active() || Jetpack::is_module_active( 'sso' ) );
367
368
		/** This filter is documented in class.jetpack-cli.php */
369 View Code Duplication
		if ( apply_filters( 'jetpack_start_enable_sso', $auto_enable_sso ) ) {
370
			$redirect_uri = add_query_arg(
371
				array(
372
					'action'      => 'jetpack-sso',
373
					'redirect_to' => rawurlencode( admin_url() ),
374
				),
375
				wp_login_url() // TODO: come back to Jetpack dashboard?
376
			);
377
		} else {
378
			$redirect_uri = admin_url();
379
		}
380
381
		// Generate secrets.
382
		$roles   = new Roles();
383
		$role    = $roles->translate_user_to_role( $user );
384
		$secrets = $this->connection->generate_secrets( 'authorize', $user->ID );
385
386
		$response = array(
387
			'jp_version'   => JETPACK__VERSION,
388
			'redirect_uri' => $redirect_uri,
389
			'user_id'      => $user->ID,
390
			'user_email'   => $user->user_email,
391
			'user_login'   => $user->user_login,
392
			'scope'        => $this->connection->sign_role( $role, $user->ID ),
393
			'secret'       => $secrets['secret_1'],
394
			'is_active'    => $this->connection->is_active(),
395
		);
396
397
		if ( $site_icon ) {
398
			$response['site_icon'] = $site_icon;
399
		}
400
401
		if ( ! empty( $request['onboarding'] ) ) {
402
			Jetpack::create_onboarding_token();
403
			$response['onboarding_token'] = Jetpack_Options::get_option( 'onboarding' );
404
		}
405
406
		return $response;
407
	}
408
409
	/**
410
	 * Given an array containing a local user identifier and a nonce, will attempt to fetch and set
411
	 * an access token for the given user.
412
	 *
413
	 * @param array       $request    An array containing local_user and nonce keys at minimum.
414
	 * @param \IXR_Client $ixr_client The client object, optional.
0 ignored issues
show
Documentation introduced by
Should the type for parameter $ixr_client not be false|IXR_Client?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
415
	 * @return mixed
416
	 */
417
	public function remote_connect( $request, $ixr_client = false ) {
418
		if ( $this->connection->is_active() ) {
419
			return $this->error(
420
				new WP_Error(
421
					'already_connected',
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'already_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...
422
					__( 'Jetpack is already connected.', 'jetpack' ),
423
					400
424
				),
425
				'jpc_remote_connect_fail'
426
			);
427
		}
428
429
		$user = $this->fetch_and_verify_local_user( $request );
430
431
		if ( ! $user || is_wp_error( $user ) || is_a( $user, 'IXR_Error' ) ) {
432
			return $this->error(
433
				new WP_Error(
434
					'input_error',
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'input_error'.

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...
435
					__( 'Valid user is required.', 'jetpack' ),
436
					400
437
				),
438
				'jpc_remote_connect_fail'
439
			);
440
		}
441
442
		if ( empty( $request['nonce'] ) ) {
443
			return $this->error(
444
				new WP_Error(
445
					'input_error',
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'input_error'.

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...
446
					__( 'A non-empty nonce must be supplied.', 'jetpack' ),
447
					400
448
				),
449
				'jpc_remote_connect_fail'
450
			);
451
		}
452
453
		if ( ! $ixr_client ) {
454
			$ixr_client = new Jetpack_IXR_Client();
455
		}
456
		$ixr_client->query(
457
			'jetpack.getUserAccessToken',
458
			array(
459
				'nonce'            => sanitize_text_field( $request['nonce'] ),
460
				'external_user_id' => $user->ID,
461
			)
462
		);
463
464
		$token = $ixr_client->isError() ? false : $ixr_client->getResponse();
465
		if ( empty( $token ) ) {
466
			return $this->error(
467
				new WP_Error(
468
					'token_fetch_failed',
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'token_fetch_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...
469
					__( 'Failed to fetch user token from WordPress.com.', 'jetpack' ),
470
					400
471
				),
472
				'jpc_remote_connect_fail'
473
			);
474
		}
475
		$token = sanitize_text_field( $token );
476
477
		Jetpack::update_user_token( $user->ID, sprintf( '%s.%d', $token, $user->ID ), true );
478
479
		$this->do_post_authorization();
480
481
		return $this->connection->is_active();
482
	}
483
484
	/**
485
	 * Getter for the local user to act as.
486
	 *
487
	 * @param array $request the current request data.
488
	 */
489
	private function fetch_and_verify_local_user( $request ) {
490
		if ( empty( $request['local_user'] ) ) {
491
			return $this->error(
492
				new Jetpack_Error(
493
					'local_user_missing',
0 ignored issues
show
Unused Code introduced by
The call to Jetpack_Error::__construct() has too many arguments starting with 'local_user_missing'.

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...
494
					__( 'The required "local_user" parameter is missing.', 'jetpack' ),
495
					400
496
				),
497
				'jpc_remote_provision_fail'
498
			);
499
		}
500
501
		// Local user is used to look up by login, email or ID.
502
		$local_user_info = $request['local_user'];
503
504
		return $this->get_user_by_anything( $local_user_info );
505
	}
506
507
	/**
508
	 * Gets the user object by its data.
509
	 *
510
	 * @param string $user_id can be any identifying user data.
511
	 */
512
	private function get_user_by_anything( $user_id ) {
513
		$user = get_user_by( 'login', $user_id );
514
515
		if ( ! $user ) {
516
			$user = get_user_by( 'email', $user_id );
517
		}
518
519
		if ( ! $user ) {
520
			$user = get_user_by( 'ID', $user_id );
521
		}
522
523
		return $user;
524
	}
525
526
	/**
527
	 * Track an error.
528
	 *
529
	 * @param string               $name  Event name.
530
	 * @param \WP_Error|\IXR_Error $error The error object.
531
	 * @param \WP_User             $user  The user object.
0 ignored issues
show
Documentation introduced by
Should the type for parameter $user not be WP_User|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
532
	 */
533
	private function tracks_record_error( $name, $error, $user = null ) {
534
		if ( is_wp_error( $error ) ) {
535
			$this->tracking->record_user_event(
536
				$name,
537
				array(
538
					'error_code'    => $error->get_error_code(),
0 ignored issues
show
Bug introduced by
The method get_error_code() does not seem to exist on object<WP_Error>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
539
					'error_message' => $error->get_error_message(),
0 ignored issues
show
Bug introduced by
The method get_error_message() does not seem to exist on object<WP_Error>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
540
				),
541
				$user
542
			);
543
		} elseif ( is_a( $error, '\\IXR_Error' ) ) {
544
			$this->tracking->record_user_event(
545
				$name,
546
				array(
547
					'error_code'    => $error->code,
548
					'error_message' => $error->message,
549
				),
550
				$user
551
			);
552
		}
553
554
		return $error;
555
	}
556
557
	/**
558
	 * Possible error_codes:
559
	 *
560
	 * - verify_secret_1_missing
561
	 * - verify_secret_1_malformed
562
	 * - verify_secrets_missing: verification secrets are not found in database
563
	 * - verify_secrets_incomplete: verification secrets are only partially found in database
564
	 * - verify_secrets_expired: verification secrets have expired
565
	 * - verify_secrets_mismatch: stored secret_1 does not match secret_1 sent by Jetpack.WordPress.com
566
	 * - state_missing: required parameter of state not found
567
	 * - state_malformed: state is not a digit
568
	 * - invalid_state: state in request does not match the stored state
569
	 *
570
	 * The 'authorize' and 'register' actions have additional error codes
571
	 *
572
	 * state_missing: a state ( user id ) was not supplied
573
	 * state_malformed: state is not the correct data type
574
	 * invalid_state: supplied state does not match the stored state
575
	 *
576
	 * @param array $params action An array of 3 parameters:
577
	 *     [0]: string action. Possible values are `authorize`, `publicize` and `register`.
578
	 *     [1]: string secret_1.
579
	 *     [2]: int state.
580
	 * @return \IXR_Error|string IXR_Error on failure, secret_2 on success.
581
	 */
582
	public function verify_action( $params ) {
583
		$action        = isset( $params[0] ) ? $params[0] : '';
584
		$verify_secret = isset( $params[1] ) ? $params[1] : '';
585
		$state         = isset( $params[2] ) ? $params[2] : '';
586
587
		$result = $this->connection->verify_secrets( $action, $verify_secret, $state );
588
589
		if ( is_wp_error( $result ) ) {
590
			return $this->error( $result );
0 ignored issues
show
Bug introduced by
It seems like $result defined by $this->connection->verif...$verify_secret, $state) on line 587 can also be of type string; however, Jetpack_XMLRPC_Server::error() does only seem to accept object<WP_Error>|object<IXR_Error>|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
591
		}
592
593
		return $result;
594
	}
595
596
	/**
597
	 * Wrapper for wp_authenticate( $username, $password );
598
	 *
599
	 * @return \WP_User|bool
600
	 */
601
	public function login() {
602
		$this->connection->require_jetpack_authentication();
603
		$user = wp_authenticate( 'username', 'password' );
604
		if ( is_wp_error( $user ) ) {
605
			if ( 'authentication_failed' === $user->get_error_code() ) { // Generic error could mean most anything.
606
				$this->error = new Jetpack_Error( 'invalid_request', 'Invalid Request', 403 );
0 ignored issues
show
Unused Code introduced by
The call to Jetpack_Error::__construct() has too many arguments starting with 'invalid_request'.

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...
607
			} else {
608
				$this->error = $user;
609
			}
610
			return false;
611
		} elseif ( ! $user ) { // Shouldn't happen.
612
			$this->error = new Jetpack_Error( 'invalid_request', 'Invalid Request', 403 );
0 ignored issues
show
Unused Code introduced by
The call to Jetpack_Error::__construct() has too many arguments starting with 'invalid_request'.

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...
613
			return false;
614
		}
615
616
		return $user;
617
	}
618
619
	/**
620
	 * Returns the current error as an \IXR_Error
621
	 *
622
	 * @param \WP_Error|\IXR_Error $error             The error object, optional.
0 ignored issues
show
Documentation introduced by
Should the type for parameter $error not be WP_Error|IXR_Error|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
623
	 * @param string               $tracks_event_name The event name.
0 ignored issues
show
Documentation introduced by
Should the type for parameter $tracks_event_name not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
624
	 * @param \WP_User             $user              The user object.
0 ignored issues
show
Documentation introduced by
Should the type for parameter $user not be WP_User|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
625
	 * @return bool|\IXR_Error
626
	 */
627
	public function error( $error = null, $tracks_event_name = null, $user = null ) {
628
		// Record using Tracks.
629
		if ( null !== $tracks_event_name ) {
630
			$this->tracks_record_error( $tracks_event_name, $error, $user );
0 ignored issues
show
Bug introduced by
It seems like $error defined by parameter $error on line 627 can also be of type null; however, Jetpack_XMLRPC_Server::tracks_record_error() does only seem to accept object<WP_Error>|object<IXR_Error>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
631
		}
632
633
		if ( ! is_null( $error ) ) {
634
			$this->error = $error;
0 ignored issues
show
Documentation Bug introduced by
It seems like $error can also be of type object<IXR_Error>. However, the property $error is declared as type object<WP_Error>. Maybe add an additional type check?

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 the id property of an instance of the Account 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.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
635
		}
636
637
		if ( is_wp_error( $this->error ) ) {
638
			$code = $this->error->get_error_data();
0 ignored issues
show
Bug introduced by
The method get_error_data() does not seem to exist on object<WP_Error>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
639
			if ( ! $code ) {
640
				$code = -10520;
641
			}
642
			$message = sprintf( 'Jetpack: [%s] %s', $this->error->get_error_code(), $this->error->get_error_message() );
0 ignored issues
show
Bug introduced by
The method get_error_code() does not seem to exist on object<WP_Error>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method get_error_message() does not seem to exist on object<WP_Error>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
643
			return new \IXR_Error( $code, $message );
644
		} elseif ( is_a( $this->error, 'IXR_Error' ) ) {
645
			return $this->error;
646
		}
647
648
		return false;
649
	}
650
651
	/* API Methods */
652
653
	/**
654
	 * Just authenticates with the given Jetpack credentials.
655
	 *
656
	 * @return string The current Jetpack version number
657
	 */
658
	public function test_connection() {
659
		return JETPACK__VERSION;
660
	}
661
662
	/**
663
	 * Test the API user code.
664
	 *
665
	 * @param array $args arguments identifying the test site.
666
	 */
667
	public function test_api_user_code( $args ) {
668
		$client_id = (int) $args[0];
669
		$user_id   = (int) $args[1];
670
		$nonce     = (string) $args[2];
671
		$verify    = (string) $args[3];
672
673
		if ( ! $client_id || ! $user_id || ! strlen( $nonce ) || 32 !== strlen( $verify ) ) {
674
			return false;
675
		}
676
677
		$user = get_user_by( 'id', $user_id );
678
		if ( ! $user || is_wp_error( $user ) ) {
679
			return false;
680
		}
681
682
		/* phpcs:ignore
683
		 debugging
684
		error_log( "CLIENT: $client_id" );
685
		error_log( "USER:   $user_id" );
686
		error_log( "NONCE:  $nonce" );
687
		error_log( "VERIFY: $verify" );
688
		*/
689
690
		$jetpack_token = $this->connection->get_access_token( $user_id );
691
692
		$api_user_code = get_user_meta( $user_id, "jetpack_json_api_$client_id", true );
693
		if ( ! $api_user_code ) {
694
			return false;
695
		}
696
697
		$hmac = hash_hmac(
698
			'md5',
699
			json_encode( // phpcs:ignore WordPress.WP.AlternativeFunctions.json_encode_json_encode
700
				(object) array(
701
					'client_id' => (int) $client_id,
702
					'user_id'   => (int) $user_id,
703
					'nonce'     => (string) $nonce,
704
					'code'      => (string) $api_user_code,
705
				)
706
			),
707
			$jetpack_token->secret
708
		);
709
710
		if ( ! hash_equals( $hmac, $verify ) ) {
711
			return false;
712
		}
713
714
		return $user_id;
715
	}
716
717
	/**
718
	 * Disconnect this blog from the connected wordpress.com account
719
	 *
720
	 * @return boolean
721
	 */
722
	public function disconnect_blog() {
723
724
		// For tracking.
725
		if ( ! empty( $this->user->ID ) ) {
726
			wp_set_current_user( $this->user->ID );
727
		}
728
729
		/**
730
		 * Fired when we want to log an event to the Jetpack event log.
731
		 *
732
		 * @since 7.7.0
733
		 *
734
		 * @param string $code Unique name for the event.
735
		 * @param string $data Optional data about the event.
736
		 */
737
		do_action( 'jetpack_event_log', 'disconnect' );
738
		Jetpack::disconnect();
739
740
		return true;
741
	}
742
743
	/**
744
	 * Unlink a user from WordPress.com
745
	 *
746
	 * This will fail if called by the Master User.
747
	 */
748
	public function unlink_user() {
749
		/**
750
		 * Fired when we want to log an event to the Jetpack event log.
751
		 *
752
		 * @since 7.7.0
753
		 *
754
		 * @param string $code Unique name for the event.
755
		 * @param string $data Optional data about the event.
756
		 */
757
		do_action( 'jetpack_event_log', 'unlink' );
758
		return Connection_Manager::disconnect_user();
759
	}
760
761
	/**
762
	 * Returns any object that is able to be synced.
763
	 *
764
	 * @deprecated since 7.8.0
765
	 * @see Automattic\Jetpack\Sync\Sender::sync_object()
766
	 *
767
	 * @param array $args the synchronized object parameters.
768
	 * @return string Encoded sync object.
769
	 */
770
	public function sync_object( $args ) {
771
		_deprecated_function( __METHOD__, 'jetpack-7.8', 'Automattic\\Jetpack\\Sync\\Sender::sync_object' );
772
		return Sender::get_instance()->sync_object( $args );
773
	}
774
775
	/**
776
	 * Returns the home URL and site URL for the current site which can be used on the WPCOM side for
777
	 * IDC mitigation to decide whether sync should be allowed if the home and siteurl values differ between WPCOM
778
	 * and the remote Jetpack site.
779
	 *
780
	 * @return array
781
	 */
782
	public function validate_urls_for_idc_mitigation() {
783
		return array(
784
			'home'    => Functions::home_url(),
785
			'siteurl' => Functions::site_url(),
786
		);
787
	}
788
789
	/**
790
	 * Returns what features are available. Uses the slug of the module files.
791
	 *
792
	 * @return array
793
	 */
794 View Code Duplication
	public function features_available() {
795
		$raw_modules = Jetpack::get_available_modules();
796
		$modules     = array();
797
		foreach ( $raw_modules as $module ) {
798
			$modules[] = Jetpack::get_module_slug( $module );
799
		}
800
801
		return $modules;
802
	}
803
804
	/**
805
	 * Returns what features are enabled. Uses the slug of the modules files.
806
	 *
807
	 * @return array
808
	 */
809 View Code Duplication
	public function features_enabled() {
810
		$raw_modules = Jetpack::get_active_modules();
811
		$modules     = array();
812
		foreach ( $raw_modules as $module ) {
813
			$modules[] = Jetpack::get_module_slug( $module );
814
		}
815
816
		return $modules;
817
	}
818
819
	/**
820
	 * Updates the attachment parent object.
821
	 *
822
	 * @param array $args attachment and parent identifiers.
823
	 */
824
	public function update_attachment_parent( $args ) {
825
		$attachment_id = (int) $args[0];
826
		$parent_id     = (int) $args[1];
827
828
		return wp_update_post(
829
			array(
830
				'ID'          => $attachment_id,
831
				'post_parent' => $parent_id,
832
			)
833
		);
834
	}
835
836
	/**
837
	 * Serve a JSON API request.
838
	 *
839
	 * @param array $args request arguments.
840
	 */
841
	public function json_api( $args = array() ) {
842
		$json_api_args        = $args[0];
843
		$verify_api_user_args = $args[1];
844
845
		$method       = (string) $json_api_args[0];
846
		$url          = (string) $json_api_args[1];
847
		$post_body    = is_null( $json_api_args[2] ) ? null : (string) $json_api_args[2];
848
		$user_details = (array) $json_api_args[4];
849
		$locale       = (string) $json_api_args[5];
850
851
		if ( ! $verify_api_user_args ) {
852
			$user_id = 0;
853
		} elseif ( 'internal' === $verify_api_user_args[0] ) {
854
			$user_id = (int) $verify_api_user_args[1];
855
			if ( $user_id ) {
856
				$user = get_user_by( 'id', $user_id );
857
				if ( ! $user || is_wp_error( $user ) ) {
858
					return false;
859
				}
860
			}
861
		} else {
862
			$user_id = call_user_func( array( $this, 'test_api_user_code' ), $verify_api_user_args );
863
			if ( ! $user_id ) {
864
				return false;
865
			}
866
		}
867
868
		/* phpcs:ignore
869
		 debugging
870
		error_log( "-- begin json api via jetpack debugging -- " );
871
		error_log( "METHOD: $method" );
872
		error_log( "URL: $url" );
873
		error_log( "POST BODY: $post_body" );
874
		error_log( "VERIFY_ARGS: " . print_r( $verify_api_user_args, 1 ) );
875
		error_log( "VERIFIED USER_ID: " . (int) $user_id );
876
		error_log( "-- end json api via jetpack debugging -- " );
877
		*/
878
879
		if ( 'en' !== $locale ) {
880
			// .org mo files are named slightly different from .com, and all we have is this the locale -- try to guess them.
881
			$new_locale = $locale;
882
			if ( strpos( $locale, '-' ) !== false ) {
883
				$locale_pieces = explode( '-', $locale );
884
				$new_locale    = $locale_pieces[0];
885
				$new_locale   .= ( ! empty( $locale_pieces[1] ) ) ? '_' . strtoupper( $locale_pieces[1] ) : '';
886
			} else {
887
				// .com might pass 'fr' because thats what our language files are named as, where core seems
888
				// to do fr_FR - so try that if we don't think we can load the file.
889
				if ( ! file_exists( WP_LANG_DIR . '/' . $locale . '.mo' ) ) {
890
					$new_locale = $locale . '_' . strtoupper( $locale );
891
				}
892
			}
893
894
			if ( file_exists( WP_LANG_DIR . '/' . $new_locale . '.mo' ) ) {
895
				unload_textdomain( 'default' );
896
				load_textdomain( 'default', WP_LANG_DIR . '/' . $new_locale . '.mo' );
897
			}
898
		}
899
900
		$old_user = wp_get_current_user();
901
		wp_set_current_user( $user_id );
902
903
		if ( $user_id ) {
904
			$token_key = false;
905
		} else {
906
			$verified  = $this->connection->verify_xml_rpc_signature();
907
			$token_key = $verified['token_key'];
908
		}
909
910
		$token = $this->connection->get_access_token( $user_id, $token_key );
911
		if ( ! $token || is_wp_error( $token ) ) {
912
			return false;
913
		}
914
915
		define( 'REST_API_REQUEST', true );
916
		define( 'WPCOM_JSON_API__BASE', 'public-api.wordpress.com/rest/v1' );
917
918
		// needed?
919
		require_once ABSPATH . 'wp-admin/includes/admin.php';
920
921
		require_once JETPACK__PLUGIN_DIR . 'class.json-api.php';
922
		$api                        = WPCOM_JSON_API::init( $method, $url, $post_body );
923
		$api->token_details['user'] = $user_details;
924
		require_once JETPACK__PLUGIN_DIR . 'class.json-api-endpoints.php';
925
926
		$display_errors = ini_set( 'display_errors', 0 ); // phpcs:ignore WordPress.PHP.IniSet
927
		ob_start();
928
		$api->serve( false );
929
		$output = ob_get_clean();
930
		ini_set( 'display_errors', $display_errors ); // phpcs:ignore WordPress.PHP.IniSet
931
932
		$nonce = wp_generate_password( 10, false );
933
		$hmac  = hash_hmac( 'md5', $nonce . $output, $token->secret );
934
935
		wp_set_current_user( isset( $old_user->ID ) ? $old_user->ID : 0 );
936
937
		return array(
938
			(string) $output,
939
			(string) $nonce,
940
			(string) $hmac,
941
		);
942
	}
943
944
	/**
945
	 * Handles authorization actions after connecting a site, such as enabling modules.
946
	 *
947
	 * This do_post_authorization() is used in this class, as opposed to calling
948
	 * Jetpack::handle_post_authorization_actions() directly so that we can mock this method as necessary.
949
	 *
950
	 * @return void
951
	 */
952
	public function do_post_authorization() {
953
		/** This filter is documented in class.jetpack-cli.php */
954
		$enable_sso = apply_filters( 'jetpack_start_enable_sso', true );
955
		Jetpack::handle_post_authorization_actions( $enable_sso, false, false );
956
	}
957
}
958