Completed
Push — update/eu-cookie-widget-btn-po... ( 230d08 )
by
unknown
25:07 queued 15:04
created

functions.photon.php (11 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
use Automattic\Jetpack\Status;
4
5
/**
6
 * Generic functions using the Photon service.
7
 *
8
 * Some are used outside of the Photon module being active, so intentionally not within the module.
9
 *
10
 * @package jetpack
11
 */
12
13
/**
14
 * Generates a Photon URL.
15
 *
16
 * @see https://developer.wordpress.com/docs/photon/
17
 *
18
 * @param string       $image_url URL to the publicly accessible image you want to manipulate.
19
 * @param array|string $args An array of arguments, i.e. array( 'w' => '300', 'resize' => array( 123, 456 ) ), or in string form (w=123&h=456).
20
 * @param string|null  $scheme URL protocol.
21
 * @return string The raw final URL. You should run this through esc_url() before displaying it.
22
 */
23
function jetpack_photon_url( $image_url, $args = array(), $scheme = null ) {
24
	$image_url = trim( $image_url );
25
26
	if ( ! defined( 'IS_WPCOM' ) || ! IS_WPCOM ) {
27
		/**
28
		 * Disables Photon URL processing for local development
29
		 *
30
		 * @module photon
31
		 *
32
		 * @since 4.1.0
33
		 *
34
		 * @param bool false Result of Automattic\Jetpack\Status->is_offline_mode().
35
		 */
36
		if ( true === apply_filters( 'jetpack_photon_development_mode', ( new Status() )->is_offline_mode() ) ) {
37
			return $image_url;
38
		}
39
	}
40
41
	/**
42
	 * Allow specific image URls to avoid going through Photon.
43
	 *
44
	 * @module photon
45
	 *
46
	 * @since 3.2.0
47
	 *
48
	 * @param bool false Should the image be returned as is, without going through Photon. Default to false.
49
	 * @param string $image_url Image URL.
50
	 * @param array|string $args Array of Photon arguments.
51
	 * @param string|null $scheme Image scheme. Default to null.
52
	 */
53
	if ( false !== apply_filters( 'jetpack_photon_skip_for_url', false, $image_url, $args, $scheme ) ) {
0 ignored issues
show
The call to apply_filters() has too many arguments starting with $image_url.

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...
54
		return $image_url;
55
	}
56
57
	/**
58
	 * Filter the original image URL before it goes through Photon.
59
	 *
60
	 * @module photon
61
	 *
62
	 * @since 1.9.0
63
	 *
64
	 * @param string $image_url Image URL.
65
	 * @param array|string $args Array of Photon arguments.
66
	 * @param string|null $scheme Image scheme. Default to null.
67
	 */
68
	$image_url = apply_filters( 'jetpack_photon_pre_image_url', $image_url, $args, $scheme );
0 ignored issues
show
The call to apply_filters() has too many arguments starting with $args.

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...
69
	/**
70
	 * Filter the original Photon image parameters before Photon is applied to an image.
71
	 *
72
	 * @module photon
73
	 *
74
	 * @since 1.9.0
75
	 *
76
	 * @param array|string $args Array of Photon arguments.
77
	 * @param string $image_url Image URL.
78
	 * @param string|null $scheme Image scheme. Default to null.
79
	 */
80
	$args = apply_filters( 'jetpack_photon_pre_args', $args, $image_url, $scheme );
0 ignored issues
show
The call to apply_filters() has too many arguments starting with $image_url.

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...
81
82
	if ( empty( $image_url ) ) {
83
		return $image_url;
84
	}
85
86
	$image_url_parts = wp_parse_url( $image_url );
87
88
	// Unable to parse.
89
	if ( ! is_array( $image_url_parts ) || empty( $image_url_parts['host'] ) || empty( $image_url_parts['path'] ) ) {
90
		return $image_url;
91
	}
92
93
	if ( is_array( $args ) ) {
94
		// Convert values that are arrays into strings.
95
		foreach ( $args as $arg => $value ) {
96
			if ( is_array( $value ) ) {
97
				$args[ $arg ] = implode( ',', $value );
98
			}
99
		}
100
101
		// Encode values.
102
		// See https://core.trac.wordpress.org/ticket/17923 .
103
		$args = rawurlencode_deep( $args );
104
	}
105
106
	// Don't photon-ize WPCOM hosted images -- we can serve them up from wpcom directly.
107
	$is_wpcom_image = false;
108
	if ( wp_endswith( strtolower( $image_url_parts['host'] ), '.files.wordpress.com' ) ) {
109
		$is_wpcom_image = true;
110
		if ( isset( $args['ssl'] ) ) {
111
			// Do not send the ssl argument to prevent caching issues.
112
			unset( $args['ssl'] );
113
		}
114
	}
115
116
	/** This filter is documented below. */
117
	$custom_photon_url = apply_filters( 'jetpack_photon_domain', '', $image_url );
0 ignored issues
show
The call to apply_filters() has too many arguments starting with $image_url.

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...
118
	$custom_photon_url = esc_url( $custom_photon_url );
119
120
	// You can't run a Photon URL through Photon again because query strings are stripped.
121
	// So if the image is already a Photon URL, append the new arguments to the existing URL.
122
	// Alternately, if it's a *.files.wordpress.com url, then keep the domain as is.
123
	if (
124
		in_array( $image_url_parts['host'], array( 'i0.wp.com', 'i1.wp.com', 'i2.wp.com' ), true )
125
		|| wp_parse_url( $custom_photon_url, PHP_URL_HOST ) === $image_url_parts['host']
0 ignored issues
show
The call to wp_parse_url() has too many arguments starting with PHP_URL_HOST.

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...
126
		|| $is_wpcom_image
127
	) {
128
		/*
129
		 * VideoPress Poster images should only keep one param, ssl.
130
		 */
131
		if (
132
			is_array( $args )
133
			&& 'videos.files.wordpress.com' === strtolower( $image_url_parts['host'] )
134
		) {
135
			$args = array_intersect_key( array( 'ssl' => 1 ), $args );
136
		}
137
138
		$photon_url = add_query_arg( $args, $image_url );
139
		return jetpack_photon_url_scheme( $photon_url, $scheme );
140
	}
141
142
	/**
143
	 * Allow Photon to use query strings as well.
144
	 * By default, Photon doesn't support query strings so we ignore them and look only at the path.
145
	 * This setting is Photon Server dependent.
146
	 *
147
	 * @module photon
148
	 *
149
	 * @since 1.9.0
150
	 *
151
	 * @param bool false Should images using query strings go through Photon. Default is false.
152
	 * @param string $image_url_parts['host'] Image URL's host.
153
	 */
154
	if ( ! apply_filters( 'jetpack_photon_any_extension_for_domain', false, $image_url_parts['host'] ) ) {
0 ignored issues
show
The call to apply_filters() has too many arguments starting with $image_url_parts['host'].

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...
155
		// Photon doesn't support query strings so we ignore them and look only at the path.
156
		// However some source images are served via PHP so check the no-query-string extension.
157
		// For future proofing, this is an excluded list of common issues rather than an allow list.
158
		$extension = pathinfo( $image_url_parts['path'], PATHINFO_EXTENSION );
159
		if ( empty( $extension ) || in_array( $extension, array( 'php', 'ashx' ), true ) ) {
160
			return $image_url;
161
		}
162
	}
163
164
	$image_host_path = $image_url_parts['host'] . $image_url_parts['path'];
165
166
	/*
167
	 * Figure out which CDN subdomain to use.
168
	 *
169
	 * The goal is to have the same subdomain for any particular image to prevent multiple runs resulting in multiple
170
	 * images needing to be downloaded by the browser.
171
	 *
172
	 * We are providing our own generated value by taking the modulus of the crc32 value of the URL.
173
	 *
174
	 * Valid values are 0, 1, and 2.
175
	 */
176
	$subdomain = abs( crc32( $image_host_path ) % 3 );
177
178
	/**
179
	 * Filters the domain used by the Photon module.
180
	 *
181
	 * @module photon
182
	 *
183
	 * @since 3.4.2
184
	 *
185
	 * @param string https://i{$subdomain}.wp.com Domain used by Photon. $subdomain is a random number between 0 and 2.
186
	 * @param string $image_url URL of the image to be photonized.
187
	 */
188
	$photon_domain = apply_filters( 'jetpack_photon_domain', "https://i{$subdomain}.wp.com", $image_url );
0 ignored issues
show
The call to apply_filters() has too many arguments starting with $image_url.

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...
189
	$photon_domain = trailingslashit( esc_url( $photon_domain ) );
190
	$photon_url    = $photon_domain . $image_host_path;
191
192
	/**
193
	 * Add query strings to Photon URL.
194
	 * By default, Photon doesn't support query strings so we ignore them.
195
	 * This setting is Photon Server dependent.
196
	 *
197
	 * @module photon
198
	 *
199
	 * @since 1.9.0
200
	 *
201
	 * @param bool false Should query strings be added to the image URL. Default is false.
202
	 * @param string $image_url_parts['host'] Image URL's host.
203
	 */
204
	if ( isset( $image_url_parts['query'] ) && apply_filters( 'jetpack_photon_add_query_string_to_domain', false, $image_url_parts['host'] ) ) {
0 ignored issues
show
The call to apply_filters() has too many arguments starting with $image_url_parts['host'].

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...
205
		$photon_url .= '?q=' . rawurlencode( $image_url_parts['query'] );
206
	}
207
208
	if ( $args ) {
209
		if ( is_array( $args ) ) {
210
			$photon_url = add_query_arg( $args, $photon_url );
211
		} else {
212
			// You can pass a query string for complicated requests but where you still want CDN subdomain help, etc.
213
			$photon_url .= '?' . $args;
214
		}
215
	}
216
217
	if ( isset( $image_url_parts['scheme'] ) && 'https' === $image_url_parts['scheme'] ) {
218
		$photon_url = add_query_arg( array( 'ssl' => 1 ), $photon_url );
219
	}
220
221
	return jetpack_photon_url_scheme( $photon_url, $scheme );
222
}
223
224
/**
225
 * Add an easy way to photon-ize a URL that is safe to call even if Jetpack isn't active.
226
 *
227
 * See: https://jetpack.com/2013/07/11/photon-and-themes/
228
 */
229
add_filter( 'jetpack_photon_url', 'jetpack_photon_url', 10, 3 );
230
231
/**
232
 * WordPress.com
233
 *
234
 * If a cropped WP.com-hosted image is the source image, have Photon replicate the crop.
235
 */
236
add_filter( 'jetpack_photon_pre_args', 'jetpack_photon_parse_wpcom_query_args', 10, 2 );
237
238
/**
239
 * Parses WP.com-hosted image args to replicate the crop.
240
 *
241
 * @param mixed  $args Args set during Photon's processing.
242
 * @param string $image_url URL of the image.
243
 * @return array|string Args for Photon to use for the URL.
244
 */
245
function jetpack_photon_parse_wpcom_query_args( $args, $image_url ) {
246
	$parsed_url = wp_parse_url( $image_url );
247
248
	if ( ! $parsed_url ) {
249
		return $args;
250
	}
251
252
	$image_url_parts = wp_parse_args(
253
		$parsed_url,
254
		array(
0 ignored issues
show
array('host' => '', 'query' => '') is of type array<string,string,{"ho...ing","query":"string"}>, but the function expects a string.

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...
255
			'host'  => '',
256
			'query' => '',
257
		)
258
	);
259
260
	if ( '.files.wordpress.com' !== substr( $image_url_parts['host'], -20 ) ) {
261
		return $args;
262
	}
263
264
	if ( empty( $image_url_parts['query'] ) ) {
265
		return $args;
266
	}
267
268
	$wpcom_args = wp_parse_args( $image_url_parts['query'] );
269
270
	if ( empty( $wpcom_args['w'] ) || empty( $wpcom_args['h'] ) ) {
271
		return $args;
272
	}
273
274
	// Keep the crop by using "resize".
275
	if ( ! empty( $wpcom_args['crop'] ) ) {
276 View Code Duplication
		if ( is_array( $args ) ) {
277
			$args = array_merge( array( 'resize' => array( $wpcom_args['w'], $wpcom_args['h'] ) ), $args );
278
		} else {
279
			$args = 'resize=' . rawurlencode( absint( $wpcom_args['w'] ) . ',' . absint( $wpcom_args['h'] ) ) . '&' . $args;
280
		}
281 View Code Duplication
	} else {
282
		if ( is_array( $args ) ) {
283
			$args = array_merge( array( 'fit' => array( $wpcom_args['w'], $wpcom_args['h'] ) ), $args );
284
		} else {
285
			$args = 'fit=' . rawurlencode( absint( $wpcom_args['w'] ) . ',' . absint( $wpcom_args['h'] ) ) . '&' . $args;
286
		}
287
	}
288
289
	return $args;
290
}
291
292
/**
293
 * Sets the scheme for a URL
294
 *
295
 * @param string $url URL to set scheme.
296
 * @param string $scheme Scheme to use. Accepts http, https, network_path.
297
 *
298
 * @return string URL.
299
 */
300
function jetpack_photon_url_scheme( $url, $scheme ) {
301
	if ( ! in_array( $scheme, array( 'http', 'https', 'network_path' ), true ) ) {
302
		if ( preg_match( '#^(https?:)?//#', $url ) ) {
303
			return $url;
304
		}
305
306
		$scheme = 'http';
307
	}
308
309
	if ( 'network_path' === $scheme ) {
310
		$scheme_slashes = '//';
311
	} else {
312
		$scheme_slashes = "$scheme://";
313
	}
314
315
	return preg_replace( '#^([a-z:]+)?//#i', $scheme_slashes, $url );
316
}
317
318
/**
319
 * A wrapper for PHP's parse_url, prepending assumed scheme for network path
320
 * URLs. PHP versions 5.4.6 and earlier do not correctly parse without scheme.
321
 *
322
 * WP ships with a wrapper for parse_url, wp_parse_url, that should be used instead.
323
 *
324
 * @see https://php.net/manual/en/function.parse-url.php#refsect1-function.parse-url-changelog
325
 * @deprecated 7.8.0 Use wp_parse_url instead.
326
 *
327
 * @param string  $url The URL to parse.
328
 * @param integer $component Retrieve specific URL component.
329
 * @return mixed Result of parse_url
330
 */
331
function jetpack_photon_parse_url( $url, $component = -1 ) {
332
	_deprecated_function( 'jetpack_photon_parse_url', 'jetpack-7.8.0', 'wp_parse_url' );
333
	return wp_parse_url( $url, $component );
0 ignored issues
show
The call to wp_parse_url() has too many arguments starting with $component.

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...
334
}
335
336
add_filter( 'jetpack_photon_skip_for_url', 'jetpack_photon_banned_domains', 9, 2 );
337
338
/**
339
 * Check to skip Photon for a known domain that shouldn't be Photonized.
340
 *
341
 * @param bool   $skip If the image should be skipped by Photon.
342
 * @param string $image_url URL of the image.
343
 *
344
 * @return bool Should the image be skipped by Photon.
345
 */
346
function jetpack_photon_banned_domains( $skip, $image_url ) {
347
	$banned_host_patterns = array(
348
		'/^chart\.googleapis\.com$/',
349
		'/^chart\.apis\.google\.com$/',
350
		'/^graph\.facebook\.com$/',
351
		'/\.fbcdn\.net$/',
352
		'/\.paypalobjects\.com$/',
353
		'/\.dropbox\.com$/',
354
		'/\.cdninstagram\.com$/',
355
		'/\.wikimedia\.org$/',
356
	);
357
358
	$host = wp_parse_url( $image_url, PHP_URL_HOST );
0 ignored issues
show
The call to wp_parse_url() has too many arguments starting with PHP_URL_HOST.

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...
359
360
	foreach ( $banned_host_patterns as $banned_host_pattern ) {
361
		if ( 1 === preg_match( $banned_host_pattern, $host ) ) {
362
			return true;
363
		}
364
	}
365
366
	return $skip;
367
}
368
369
370
/**
371
 * Jetpack Photon - Support Text Widgets.
372
 *
373
 * @access public
374
 * @param string $content Content from text widget.
375
 * @return string
376
 */
377
function jetpack_photon_support_text_widgets( $content ) {
378
	if ( class_exists( 'Jetpack_Photon' ) && Jetpack::is_module_active( 'photon' ) ) {
379
		return Jetpack_Photon::filter_the_content( $content );
380
	}
381
	return $content;
382
}
383
add_filter( 'widget_text', 'jetpack_photon_support_text_widgets' );
384