Completed
Push — fix/min-php-everywhere ( 582b89...e9c8a1 )
by
unknown
07:08
created

Jetpack_Provision::get_api_host()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php //phpcs:ignore
2
3
use Automattic\Jetpack\Connection\Client;
4
use Automattic\Jetpack\Roles;
5
use Automattic\Jetpack\Sync\Actions;
6
7
class Jetpack_Provision { //phpcs:ignore
8
9
	/**
10
	 * Responsible for checking pre-conditions, registering site, and returning an array of details
11
	 * that can be used to provision a plan for the site.
12
	 *
13
	 * @param array $named_args The array of arguments.
14
	 *
15
	 * @return WP_Error|array
16
	 */
17
	public static function register_and_build_request_body( $named_args ) {
18
		$url_args = array(
19
			'home_url' => 'WP_HOME',
20
			'site_url' => 'WP_SITEURL',
21
		);
22
23
		foreach ( $url_args as $url_arg => $constant_name ) {
24
			if ( isset( $named_args[ $url_arg ] ) ) {
25
				add_filter(
26
					$url_arg,
27
					function() use ( $url_arg, $named_args ) {
28
						return $named_args[ $url_arg ];
29
					},
30
					11
31
				);
32
			}
33
		}
34
35
		// If Jetpack is currently connected, and is not in Safe Mode already, kick off a sync of the current
36
		// functions/callables so that we can test if this site is in IDC.
37
		if ( Jetpack::is_active() && ! Jetpack::validate_sync_error_idc_option() && Actions::sync_allowed() ) {
38
			Actions::do_full_sync( array( 'functions' => true ) );
39
			Actions::$sender->do_full_sync();
40
		}
41
42
		if ( Jetpack::validate_sync_error_idc_option() ) {
43
			return new WP_Error(
44
				'site_in_safe_mode',
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'site_in_safe_mode'.

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...
45
				__( 'Can not provision a plan while in safe mode. See: https://jetpack.com/support/safe-mode/', 'jetpack' )
46
			);
47
		}
48
49
50
		if ( ! Jetpack::connection()->is_registered() || ( isset( $named_args['force_register'] ) && intval( $named_args['force_register'] ) ) ) {
51
			// This code mostly copied from Jetpack::admin_page_load.
52
			Jetpack::maybe_set_version_option();
53
			$registered = Jetpack::try_registration();
54
			if ( is_wp_error( $registered ) ) {
55
				return $registered;
56
			} elseif ( ! $registered ) {
57
				return new WP_Error( 'registration_error', __( 'There was an unspecified error registering the site', 'jetpack' ) );
0 ignored issues
show
Unused Code introduced by
The call to WP_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...
58
			}
59
		}
60
61
		// If the user isn't specified, but we have a current master user, then set that to current user.
62
		$master_user_id = Jetpack_Options::get_option( 'master_user' );
63
		if ( ! get_current_user_id() && $master_user_id ) {
64
			wp_set_current_user( $master_user_id );
65
		}
66
67
		$site_icon = get_site_icon_url();
68
69
		$auto_enable_sso = ( ! Jetpack::is_active() || Jetpack::is_module_active( 'sso' ) );
70
71
		/** This filter is documented in class.jetpack-cli.php */
72 View Code Duplication
		if ( apply_filters( 'jetpack_start_enable_sso', $auto_enable_sso ) ) {
73
			$redirect_uri = add_query_arg(
74
				array(
75
					'action'      => 'jetpack-sso',
76
					'redirect_to' => rawurlencode( admin_url() ),
77
				),
78
				wp_login_url() // TODO: come back to Jetpack dashboard?
79
			);
80
		} else {
81
			$redirect_uri = admin_url();
82
		}
83
84
		$request_body = array(
85
			'jp_version'   => JETPACK__VERSION,
86
			'redirect_uri' => $redirect_uri,
87
		);
88
89
		if ( $site_icon ) {
90
			$request_body['site_icon'] = $site_icon;
91
		}
92
93
		if ( get_current_user_id() ) {
94
			$user = wp_get_current_user();
95
96
			// Role.
97
			$roles       = new Roles();
98
			$role        = $roles->translate_current_user_to_role();
99
			$signed_role = Jetpack::connection()->sign_role( $role );
100
101
			$secrets = Jetpack::init()->generate_secrets( 'authorize' );
102
103
			// Jetpack auth stuff.
104
			$request_body['scope']  = $signed_role;
105
			$request_body['secret'] = $secrets['secret_1'];
106
107
			// User stuff.
108
			$request_body['user_id']    = $user->ID;
109
			$request_body['user_email'] = $user->user_email;
110
			$request_body['user_login'] = $user->user_login;
111
		}
112
113
		// Optional additional params.
114 View Code Duplication
		if ( isset( $named_args['wpcom_user_id'] ) && ! empty( $named_args['wpcom_user_id'] ) ) {
115
			$request_body['wpcom_user_id'] = $named_args['wpcom_user_id'];
116
		}
117
118
		// Override email of selected user.
119 View Code Duplication
		if ( isset( $named_args['wpcom_user_email'] ) && ! empty( $named_args['wpcom_user_email'] ) ) {
120
			$request_body['user_email'] = $named_args['wpcom_user_email'];
121
		}
122
123 View Code Duplication
		if ( isset( $named_args['plan'] ) && ! empty( $named_args['plan'] ) ) {
124
			$request_body['plan'] = $named_args['plan'];
125
		}
126
127 View Code Duplication
		if ( isset( $named_args['onboarding'] ) && ! empty( $named_args['onboarding'] ) ) {
128
			$request_body['onboarding'] = intval( $named_args['onboarding'] );
129
		}
130
131 View Code Duplication
		if ( isset( $named_args['force_connect'] ) && ! empty( $named_args['force_connect'] ) ) {
132
			$request_body['force_connect'] = intval( $named_args['force_connect'] );
133
		}
134
135
		if ( isset( $request_body['onboarding'] ) && (bool) $request_body['onboarding'] ) {
136
			Jetpack::create_onboarding_token();
137
		}
138
139
		return $request_body;
140
	}
141
142
	/**
143
	 * Given an access token and an array of arguments, will provision a plan for this site.
144
	 *
145
	 * @param string $access_token The access token from the partner.
146
	 * @param array  $named_args   The arguments used for registering the site and then provisioning a plan.
147
	 *
148
	 * @return WP_Error|array
149
	 */
150
	public static function partner_provision( $access_token, $named_args ) {
151
		// First, verify the token.
152
		$verify_response = self::verify_token( $access_token );
153
154
		if ( is_wp_error( $verify_response ) ) {
155
			return $verify_response;
156
		}
157
158
		$request_body = self::register_and_build_request_body( $named_args );
159
		if ( is_wp_error( $request_body ) ) {
160
			return $request_body;
161
		}
162
163
		$request = array(
164
			'headers' => array(
165
				'Authorization' => "Bearer $access_token",
166
				'Host'          => 'public-api.wordpress.com',
167
			),
168
			'timeout' => 60,
169
			'method'  => 'POST',
170
			'body'    => wp_json_encode( $request_body ),
171
		);
172
173
		$blog_id = Jetpack_Options::get_option( 'id' );
174
		$url     = esc_url_raw( sprintf(
175
			'https://%s/rest/v1.3/jpphp/%d/partner-provision',
176
			self::get_api_host(),
177
			$blog_id
178
		) );
179 View Code Duplication
		if ( ! empty( $named_args['partner_tracking_id'] ) ) {
180
			$url = esc_url_raw( add_query_arg( 'partner_tracking_id', $named_args['partner_tracking_id'], $url ) );
181
		}
182
183
		// Add calypso env if set.
184
		$calypso_env = Jetpack::get_calypso_env();
185
		if ( ! empty( $calypso_env ) ) {
186
			$url = add_query_arg( array( 'calypso_env' => $calypso_env ), $url );
187
		}
188
189
		$result = Client::_wp_remote_request( $url, $request );
190
191
		if ( is_wp_error( $result ) ) {
192
			return $result;
193
		}
194
195
		$response_code = wp_remote_retrieve_response_code( $result );
196
		$body_json     = json_decode( wp_remote_retrieve_body( $result ) );
197
198 View Code Duplication
		if ( 200 !== $response_code ) {
199
			if ( isset( $body_json->error ) ) {
200
				return new WP_Error( $body_json->error, $body_json->message );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with $body_json->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...
201
			} else {
202
				return new WP_Error(
203
					'server_error',
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'server_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...
204
					/* translators: %s is an HTTP status code retured from an API request. Ex. – 400 */
205
					sprintf( __( 'Request failed with code %s', 'jetpack' ), $response_code )
206
				);
207
			}
208
		}
209
210
		if ( isset( $body_json->access_token ) && is_user_logged_in() ) {
211
			// Check if this matches the existing token before replacing.
212
			$existing_token = Jetpack_Data::get_access_token( get_current_user_id() );
0 ignored issues
show
Deprecated Code introduced by
The method Jetpack_Data::get_access_token() has been deprecated with message: 7.5 Use Connection_Manager instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
213
			if ( empty( $existing_token ) || $existing_token->secret !== $body_json->access_token ) {
214
				self::authorize_user( get_current_user_id(), $body_json->access_token );
215
			}
216
		}
217
218
		return $body_json;
219
	}
220
221
	private static function authorize_user( $user_id, $access_token ) {
222
		// authorize user and enable SSO
223
		Jetpack::update_user_token( $user_id, sprintf( '%s.%d', $access_token, $user_id ), true );
224
225
		/**
226
		 * Auto-enable SSO module for new Jetpack Start connections
227
		 *
228
		 * @since 5.0.0
229
		 *
230
		 * @param bool $enable_sso Whether to enable the SSO module. Default to true.
231
		 */
232
		$other_modules = apply_filters( 'jetpack_start_enable_sso', true )
233
			? array( 'sso' )
234
			: array();
235
236
		if ( $active_modules = Jetpack_Options::get_option( 'active_modules' ) ) {
237
			Jetpack::delete_active_modules();
238
			Jetpack::activate_default_modules( 999, 1, array_merge( $active_modules, $other_modules ), false );
0 ignored issues
show
Documentation introduced by
999 is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
239
		} else {
240
			Jetpack::activate_default_modules( false, false, $other_modules, false );
241
		}
242
	}
243
244
	private static function verify_token( $access_token ) {
245
		$request = array(
246
			'headers' => array(
247
				'Authorization' => "Bearer " . $access_token,
248
				'Host'          => 'public-api.wordpress.com',
249
			),
250
			'timeout' => 10,
251
			'method'  => 'POST',
252
			'body'    => ''
253
		);
254
255
		$url = sprintf( 'https://%s/rest/v1.3/jpphp/partner-keys/verify', self::get_api_host() );
256
		$result = Client::_wp_remote_request( $url, $request );
257
258
		if ( is_wp_error( $result ) ) {
259
			return $result;
260
		}
261
262
		$response_code = wp_remote_retrieve_response_code( $result );
263
		$body_json     = json_decode( wp_remote_retrieve_body( $result ) );
264
265 View Code Duplication
		if( 200 !== $response_code ) {
266
			if ( isset( $body_json->error ) ) {
267
				return new WP_Error( $body_json->error, $body_json->message );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with $body_json->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...
268
			} else {
269
				return new WP_Error( 'server_error', sprintf( __( 'Request failed with code %s', 'jetpack' ), $response_code ) );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'server_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...
270
			}
271
		}
272
273
		return true;
274
	}
275
276
	private static function get_api_host() {
277
		$env_api_host = getenv( 'JETPACK_START_API_HOST', true ); // phpcs:ignore PHPCompatibility.FunctionUse.NewFunctionParameters.getenv_local_onlyFound
278
		return $env_api_host ? $env_api_host : JETPACK__WPCOM_JSON_API_HOST;
279
	}
280
}
281