Completed
Push — update/conversation-remove-par... ( 498b22...5ced53 )
by
unknown
18:38 queued 07:08
created

functions.global.php ➔ jetpack_json_wrap()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 2
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * This file is meant to be the home for any generic & reusable functions
4
 * that can be accessed anywhere within Jetpack.
5
 *
6
 * This file is loaded whether or not Jetpack is active.
7
 *
8
 * Please namespace with jetpack_
9
 *
10
 * @package automattic/jetpack
11
 */
12
13
use Automattic\Jetpack\Connection\Client;
14
use Automattic\Jetpack\Device_Detection;
15
use Automattic\Jetpack\Redirect;
16
use Automattic\Jetpack\Sync\Functions;
17
18
/**
19
 * Disable direct access.
20
 */
21
if ( ! defined( 'ABSPATH' ) ) {
22
	exit;
23
}
24
25
/**
26
 * Hook into Core's _deprecated_function
27
 * Add more details about when a deprecated function will be removed.
28
 *
29
 * @since 8.8.0
30
 *
31
 * @param string $function    The function that was called.
32
 * @param string $replacement Optional. The function that should have been called. Default null.
33
 * @param string $version     The version of Jetpack that deprecated the function.
34
 */
35 View Code Duplication
function jetpack_deprecated_function( $function, $replacement, $version ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
36
	// Bail early for non-Jetpack deprecations.
37
	if ( 0 !== strpos( $version, 'jetpack-' ) ) {
38
		return;
39
	}
40
41
	// Look for when a function will be removed based on when it was deprecated.
42
	$removed_version = jetpack_get_future_removed_version( $version );
43
44
	// If we could find a version, let's log a message about when removal will happen.
45
	if (
46
		! empty( $removed_version )
47
		&& ( defined( 'WP_DEBUG' ) && WP_DEBUG )
48
		/** This filter is documented in core/src/wp-includes/functions.php */
49
		&& apply_filters( 'deprecated_function_trigger_error', true )
50
	) {
51
		error_log( // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
52
			sprintf(
53
				/* Translators: 1. Function name. 2. Jetpack version number. */
54
				__( 'The %1$s function will be removed from the Jetpack plugin in version %2$s.', 'jetpack' ),
55
				$function,
56
				$removed_version
57
			)
58
		);
59
60
	}
61
}
62
add_action( 'deprecated_function_run', 'jetpack_deprecated_function', 10, 3 );
63
64
/**
65
 * Hook into Core's _deprecated_file
66
 * Add more details about when a deprecated file will be removed.
67
 *
68
 * @since 8.8.0
69
 *
70
 * @param string $file        The file that was called.
71
 * @param string $replacement The file that should have been included based on ABSPATH.
72
 * @param string $version     The version of WordPress that deprecated the file.
73
 * @param string $message     A message regarding the change.
74
 */
75 View Code Duplication
function jetpack_deprecated_file( $file, $replacement, $version, $message ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
76
	// Bail early for non-Jetpack deprecations.
77
	if ( 0 !== strpos( $version, 'jetpack-' ) ) {
78
		return;
79
	}
80
81
	// Look for when a file will be removed based on when it was deprecated.
82
	$removed_version = jetpack_get_future_removed_version( $version );
83
84
	// If we could find a version, let's log a message about when removal will happen.
85
	if (
86
		! empty( $removed_version )
87
		&& ( defined( 'WP_DEBUG' ) && WP_DEBUG )
88
		/** This filter is documented in core/src/wp-includes/functions.php */
89
		&& apply_filters( 'deprecated_file_trigger_error', true )
90
	) {
91
		error_log( // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
92
			sprintf(
93
				/* Translators: 1. File name. 2. Jetpack version number. */
94
				__( 'The %1$s file will be removed from the Jetpack plugin in version %2$s.', 'jetpack' ),
95
				$file,
96
				$removed_version
97
			)
98
		);
99
100
	}
101
}
102
add_action( 'deprecated_file_included', 'jetpack_deprecated_file', 10, 4 );
103
104
/**
105
 * Get the major version number of Jetpack 6 months after provided version.
106
 * Useful to indicate when a deprecated function will be removed from Jetpack.
107
 *
108
 * @since 8.8.0
109
 *
110
 * @param string $version The version of WordPress that deprecated the function.
111
 *
112
 * @return bool|float Return a Jetpack Major version number, or false.
113
 */
114
function jetpack_get_future_removed_version( $version ) {
115
	/*
116
	 * Extract the version number from a deprecation notice.
117
	 * (let's only keep the first decimal, e.g. 8.8 and not 8.8.0)
118
	 */
119
	preg_match( '#(([0-9]+\.([0-9]+))(?:\.[0-9]+)*)#', $version, $matches );
120
121
	if ( isset( $matches[2], $matches[3] ) ) {
122
		$deprecated_version = (float) $matches[2];
123
		$deprecated_minor   = (float) $matches[3];
124
125
		/*
126
		 * If the detected minor version number
127
		 * (e.g. "7" in "8.7")
128
		 * is higher than 9, we know the version number is malformed.
129
		 * Jetpack does not use semver yet.
130
		 * Bail.
131
		 */
132
		if ( 10 <= $deprecated_minor ) {
133
			return false;
134
		}
135
136
		// We'll remove the function from the code 6 months later, thus 6 major versions later.
137
		$removed_version = $deprecated_version + 0.6;
138
139
		return (float) $removed_version;
140
	}
141
142
	return false;
143
}
144
145
/**
146
 * Set the admin language, based on user language.
147
 *
148
 * @since 4.5.0
149
 * @deprecated 6.6.0 Use Core function instead.
150
 *
151
 * @return string
152
 */
153
function jetpack_get_user_locale() {
154
	_deprecated_function( __FUNCTION__, 'jetpack-6.6.0', 'get_user_locale' );
155
	return get_user_locale();
156
}
157
158
/**
159
 * Determine if this site is an Atomic site or not looking first at the 'at_options' option.
160
 * As a fallback, check for presence of wpcomsh plugin to determine if a current site has undergone AT.
161
 *
162
 * @since 4.8.1
163
 *
164
 * @return bool
165
 */
166
function jetpack_is_atomic_site() {
167
	$at_options = get_option( 'at_options', array() );
168
	return ! empty( $at_options ) || defined( 'WPCOMSH__PLUGIN_FILE' );
169
}
170
171
/**
172
 * Register post type for migration.
173
 *
174
 * @since 5.2
175
 */
176
function jetpack_register_migration_post_type() {
177
	register_post_type(
178
		'jetpack_migration',
179
		array(
180
			'supports'     => array(),
181
			'taxonomies'   => array(),
182
			'hierarchical' => false,
183
			'public'       => false,
184
			'has_archive'  => false,
185
			'can_export'   => true,
186
		)
187
	);
188
}
189
190
/**
191
 * Stores migration data in the database.
192
 *
193
 * @since 5.2
194
 *
195
 * @param string $option_name  Option name.
196
 * @param bool   $option_value Option value.
197
 *
198
 * @return int|WP_Error
199
 */
200
function jetpack_store_migration_data( $option_name, $option_value ) {
201
	jetpack_register_migration_post_type();
202
203
	$insert = array(
204
		'post_title'            => $option_name,
205
		'post_content_filtered' => $option_value,
206
		'post_type'             => 'jetpack_migration',
207
		'post_date'             => gmdate( 'Y-m-d H:i:s', time() ),
208
	);
209
210
	$post = get_page_by_title( $option_name, 'OBJECT', 'jetpack_migration' );
211
212
	if ( null !== $post ) {
213
		$insert['ID'] = $post->ID;
214
	}
215
216
	return wp_insert_post( $insert, true );
217
}
218
219
/**
220
 * Retrieves legacy image widget data.
221
 *
222
 * @since 5.2
223
 *
224
 * @param string $option_name Option name.
225
 *
226
 * @return mixed|null
227
 */
228
function jetpack_get_migration_data( $option_name ) {
229
	$post = get_page_by_title( $option_name, 'OBJECT', 'jetpack_migration' );
230
231
	return null !== $post ? maybe_unserialize( $post->post_content_filtered ) : null;
232
}
233
234
/**
235
 * Prints a TOS blurb used throughout the connection prompts.
236
 *
237
 * @since 5.3
238
 *
239
 * @echo string
240
 */
241
function jetpack_render_tos_blurb() {
242
	printf(
243
		wp_kses(
244
			/* Translators: placeholders are links. */
245
			__( 'By clicking the <strong>Set up Jetpack</strong> button, you agree to our <a href="%1$s" target="_blank" rel="noopener noreferrer">Terms of Service</a> and to <a href="%2$s" target="_blank" rel="noopener noreferrer">share details</a> with WordPress.com.', 'jetpack' ),
246
			array(
247
				'a'      => array(
248
					'href'   => array(),
249
					'target' => array(),
250
					'rel'    => array(),
251
				),
252
				'strong' => true,
253
			)
254
		),
255
		esc_url( Redirect::get_url( 'wpcom-tos' ) ),
256
		esc_url( Redirect::get_url( 'jetpack-support-what-data-does-jetpack-sync' ) )
257
	);
258
}
259
260
/**
261
 * Intervene upgrade process so Jetpack themes are downloaded with credentials.
262
 *
263
 * @since 5.3
264
 *
265
 * @param bool   $preempt Whether to preempt an HTTP request's return value. Default false.
266
 * @param array  $r       HTTP request arguments.
267
 * @param string $url     The request URL.
268
 *
269
 * @return array|bool|WP_Error
270
 */
271
function jetpack_theme_update( $preempt, $r, $url ) {
272
	if ( 0 === stripos( $url, JETPACK__WPCOM_JSON_API_BASE . '/rest/v1/themes/download' ) ) {
273
		$file = $r['filename'];
274
		if ( ! $file ) {
275
			return new WP_Error( 'problem_creating_theme_file', esc_html__( 'Problem creating file for theme download', 'jetpack' ) );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'problem_creating_theme_file'.

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...
276
		}
277
		$theme = pathinfo( wp_parse_url( $url, PHP_URL_PATH ), PATHINFO_FILENAME );
278
279
		// Remove filter to avoid endless loop since wpcom_json_api_request_as_blog uses this too.
280
		remove_filter( 'pre_http_request', 'jetpack_theme_update' );
281
		$result = Client::wpcom_json_api_request_as_blog(
282
			"themes/download/$theme.zip",
283
			'1.1',
284
			array(
285
				'stream'   => true,
286
				'filename' => $file,
287
			)
288
		);
289
290
		if ( 200 !== wp_remote_retrieve_response_code( $result ) ) {
291
			return new WP_Error( 'problem_fetching_theme', esc_html__( 'Problem downloading theme', 'jetpack' ) );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'problem_fetching_theme'.

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...
292
		}
293
		return $result;
294
	}
295
	return $preempt;
296
}
297
298
/**
299
 * Add the filter when a upgrade is going to be downloaded.
300
 *
301
 * @since 5.3
302
 *
303
 * @param bool $reply Whether to bail without returning the package. Default false.
304
 *
305
 * @return bool
306
 */
307
function jetpack_upgrader_pre_download( $reply ) {
308
	add_filter( 'pre_http_request', 'jetpack_theme_update', 10, 3 );
309
	return $reply;
310
}
311
312
add_filter( 'upgrader_pre_download', 'jetpack_upgrader_pre_download' );
313
314
/**
315
 * Wraps data in a way so that we can distinguish between objects and array and also prevent object recursion.
316
 *
317
 * @since 6.1.0
318
319
 * @deprecated Automattic\Jetpack\Sync\Functions::json_wrap
320
 *
321
 * @param array|obj $any        Source data to be cleaned up.
322
 * @param array     $seen_nodes Built array of nodes.
323
 *
324
 * @return array
325
 */
326
function jetpack_json_wrap( &$any, $seen_nodes = array() ) {
327
	_deprecated_function( __METHOD__, 'jetpack-9.5', 'Automattic\Jetpack\Sync\Functions' );
328
329
	return Functions::json_wrap( $any, $seen_nodes );
330
}
331
332
/**
333
 * Checks if the mime_content_type function is available and return it if so.
334
 *
335
 * The function mime_content_type is enabled by default in PHP, but can be disabled. We attempt to
336
 * enforce this via composer.json, but that won't be checked in majority of cases where
337
 * this would be happening.
338
 *
339
 * @since 7.8.0
340
 *
341
 * @param string $file File location.
342
 *
343
 * @return string|false MIME type or false if functionality is not available.
344
 */
345
function jetpack_mime_content_type( $file ) {
346
	if ( function_exists( 'mime_content_type' ) ) {
347
		return mime_content_type( $file );
348
	}
349
350
	return false;
351
}
352
353
/**
354
 * Checks that the mime type of the specified file is among those in a filterable list of mime types.
355
 *
356
 * @since 7.8.0
357
 *
358
 * @param string $file Path to file to get its mime type.
359
 *
360
 * @return bool
361
 */
362
function jetpack_is_file_supported_for_sideloading( $file ) {
363
	$type = jetpack_mime_content_type( $file );
364
365
	if ( ! $type ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $type of type string|false is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
366
		return false;
367
	}
368
369
	/**
370
	 * Filter the list of supported mime types for media sideloading.
371
	 *
372
	 * @since 4.0.0
373
	 *
374
	 * @module json-api
375
	 *
376
	 * @param array $supported_mime_types Array of the supported mime types for media sideloading.
377
	 */
378
	$supported_mime_types = apply_filters(
379
		'jetpack_supported_media_sideload_types',
380
		array(
381
			'image/png',
382
			'image/jpeg',
383
			'image/gif',
384
			'image/bmp',
385
			'video/quicktime',
386
			'video/mp4',
387
			'video/mpeg',
388
			'video/ogg',
389
			'video/3gpp',
390
			'video/3gpp2',
391
			'video/h261',
392
			'video/h262',
393
			'video/h264',
394
			'video/x-msvideo',
395
			'video/x-ms-wmv',
396
			'video/x-ms-asf',
397
		)
398
	);
399
400
	// If the type returned was not an array as expected, then we know we don't have a match.
401
	if ( ! is_array( $supported_mime_types ) ) {
402
		return false;
403
	}
404
405
	return in_array( $type, $supported_mime_types, true );
406
}
407
408
/**
409
 * Determine if the current User Agent matches the passed $kind
410
 *
411
 * @param string $kind Category of mobile device to check for.
412
 *                         Either: any, dumb, smart.
413
 * @param bool   $return_matched_agent Boolean indicating if the UA should be returned.
414
 *
415
 * @return bool|string Boolean indicating if current UA matches $kind. If
416
 *                              $return_matched_agent is true, returns the UA string
417
 */
418
function jetpack_is_mobile( $kind = 'any', $return_matched_agent = false ) {
419
420
	/**
421
	 * Filter the value of jetpack_is_mobile before it is calculated.
422
	 *
423
	 * Passing a truthy value to the filter will short-circuit determining the
424
	 * mobile type, returning the passed value instead.
425
	 *
426
	 * @since  4.2.0
427
	 *
428
	 * @param bool|string $matches Boolean if current UA matches $kind or not. If
429
	 *                             $return_matched_agent is true, should return the UA string
430
	 * @param string      $kind Category of mobile device being checked
431
	 * @param bool        $return_matched_agent Boolean indicating if the UA should be returned
432
	 */
433
	$pre = apply_filters( 'pre_jetpack_is_mobile', null, $kind, $return_matched_agent );
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $kind.

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...
434
	if ( $pre ) {
435
		return $pre;
436
	}
437
438
	$return      = false;
439
	$device_info = Device_Detection::get_info();
440
441
	if ( 'any' === $kind ) {
442
		$return = $device_info['is_phone'];
443
	} elseif ( 'smart' === $kind ) {
444
		$return = $device_info['is_smartphone'];
445
	} elseif ( 'dumb' === $kind ) {
446
		$return = $device_info['is_phone'] && ! $device_info['is_smartphone'];
447
	}
448
449
	if ( $return_matched_agent && true === $return ) {
450
		$return = $device_info['is_phone_matched_ua'];
451
	}
452
453
	/**
454
	 * Filter the value of jetpack_is_mobile
455
	 *
456
	 * @since  4.2.0
457
	 *
458
	 * @param bool|string $matches Boolean if current UA matches $kind or not. If
459
	 *                             $return_matched_agent is true, should return the UA string
460
	 * @param string      $kind Category of mobile device being checked
461
	 * @param bool        $return_matched_agent Boolean indicating if the UA should be returned
462
	 */
463
	return apply_filters( 'jetpack_is_mobile', $return, $kind, $return_matched_agent );
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $kind.

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...
464
}
465
466
/**
467
 * Determine whether the current request is for accessing the frontend.
468
 *
469
 * @return bool True if it's a frontend request, false otherwise.
470
 */
471
function jetpack_is_frontend() {
472
	$is_frontend = true;
473
474
	if (
475
		is_admin() ||
476
		wp_doing_ajax() ||
477
		wp_doing_cron() ||
478
		wp_is_json_request() ||
479
		wp_is_jsonp_request() ||
480
		wp_is_xml_request() ||
481
		is_feed() ||
482
		( defined( 'REST_REQUEST' ) && REST_REQUEST ) ||
483
		( defined( 'REST_API_REQUEST' ) && REST_API_REQUEST ) ||
484
		( defined( 'WP_CLI' ) && WP_CLI )
485
	) {
486
		$is_frontend = false;
487
	}
488
489
	/**
490
	 * Filter whether the current request is for accessing the frontend.
491
	 *
492
	 * @since  9.0.0
493
	 *
494
	 * @param bool $is_frontend Whether the current request is for accessing the frontend.
495
	 */
496
	return (bool) apply_filters( 'jetpack_is_frontend', $is_frontend );
497
}
498