PluginProbe
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF / 1.7
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF v1.7
2.3.4 2.3.3 2.3.2 2.3.1 2.3.0 2.2.9 2.2.8 trunk 1.10 1.3.3 1.3.4 1.3.5 1.3.5.1 1.3.5.2 1.3.6 1.3.6.1 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.5 All 103 releases
imagify / inc / functions / compat.php

compat.php in Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF 1.7, at inc/functions/compat.php

648 lines 20.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 defined( 'ABSPATH' ) || die( 'Cheatin\' uh?' );
3
4 /** --------------------------------------------------------------------------------------------- */
5 /** PHP ========================================================================================= */
6 /** --------------------------------------------------------------------------------------------- */
7
8 if ( ! function_exists( 'curl_file_create' ) ) :
9 /**
10 * PHP-agnostic version of curl_file_create(): create a CURLFile object.
11 *
12 * @since 1.0
13 * @since PHP 5.5
14 * @source http://dk2.php.net/manual/en/function.curl-file-create.php
15 *
16 * @param string $filename Path to the file which will be uploaded.
17 * @param string $mimetype Mimetype of the file.
18 * @param string $postname Name of the file to be used in the upload data.
19 * @return string The CURLFile object.
20 */
21 function curl_file_create( $filename, $mimetype = '', $postname = '' ) {
22 return "@$filename;filename="
23 . ( $postname ? $postname : basename( $filename ) )
24 . ( $mimetype ? ";type=$mimetype" : '' );
25 }
26 endif;
27
28 if ( ! function_exists( 'array_replace' ) ) :
29 /**
30 * PHP-agnostic version of array_replace(): replaces elements from passed arrays into the first array.
31 *
32 * @since 1.6.9
33 * @since PHP 5.3
34 * @source http://dk2.php.net/manual/en/function.array-replace.php
35 *
36 * @param array $target The array in which elements are replaced.
37 * @param array $replacements The array from which elements will be extracted.
38 * More arrays from which elements will be extracted. Values from later arrays overwrite the previous values.
39 * @return array|null The resulting array. Null if an error occurs.
40 */
41 function array_replace( $target = array(), $replacements = array() ) {
42 $replacements = func_get_args();
43 array_shift( $replacements );
44
45 foreach ( $replacements as $i => $add ) {
46 if ( ! is_array( $add ) ) {
47 trigger_error( __FUNCTION__ . '(): Argument #' . ( $i + 2 ) . ' is not an array', E_USER_WARNING );
48 return null;
49 }
50
51 foreach ( $add as $k => $v ) {
52 $target[ $k ] = $v;
53 }
54 }
55
56 return $target;
57 }
58 endif;
59
60 if ( ! function_exists( 'hash_equals' ) ) :
61 /**
62 * Timing attack safe string comparison
63 *
64 * Compares two strings using the same time whether they're equal or not.
65 *
66 * This function was added in PHP 5.6.
67 *
68 * Note: It can leak the length of a string when arguments of differing length are supplied.
69 *
70 * @since 1.7
71 * @since PHP 5.6.0
72 * @since WP 3.9.2
73 *
74 * @param string $a Expected string.
75 * @param string $b Actual, user supplied, string.
76 * @return bool Whether strings are equal.
77 */
78 function hash_equals( $a, $b ) {
79 $a_length = strlen( $a );
80 if ( strlen( $b ) !== $a_length ) {
81 return false;
82 }
83 $result = 0;
84
85 // Do not attempt to "optimize" this.
86 for ( $i = 0; $i < $a_length; $i++ ) {
87 $result |= ord( $a[ $i ] ) ^ ord( $b[ $i ] );
88 }
89
90 return 0 === $result;
91 }
92 endif;
93
94 // SPL can be disabled on PHP 5.2.
95 if ( ! function_exists( 'spl_autoload_register' ) ) :
96 require_once IMAGIFY_FUNCTIONS_PATH . 'compat-spl-autoload.php';
97 endif;
98
99 /** --------------------------------------------------------------------------------------------- */
100 /** WORDPRESS =================================================================================== */
101 /** --------------------------------------------------------------------------------------------- */
102
103 if ( ! function_exists( 'wp_json_encode' ) ) :
104 /**
105 * Encode a variable into JSON, with some sanity checks.
106 *
107 * @since 1.6.5
108 * @since WP 4.1.0
109 *
110 * @param mixed $data Variable (usually an array or object) to encode as JSON.
111 * @param int $options Optional. Options to be passed to json_encode(). Default 0.
112 * @param int $depth Optional. Maximum depth to walk through $data. Must be greater than 0. Default 512.
113 * @return string|false The JSON encoded string, or false if it cannot be encoded.
114 */
115 function wp_json_encode( $data, $options = 0, $depth = 512 ) {
116 /*
117 * json_encode() has had extra params added over the years.
118 * $options was added in 5.3, and $depth in 5.5.
119 * We need to make sure we call it with the correct arguments.
120 */
121 if ( version_compare( PHP_VERSION, '5.5', '>=' ) ) {
122 $args = array( $data, $options, $depth );
123 } elseif ( version_compare( PHP_VERSION, '5.3', '>=' ) ) {
124 $args = array( $data, $options );
125 } else {
126 $args = array( $data );
127 }
128
129 // Prepare the data for JSON serialization.
130 $args[0] = _wp_json_prepare_data( $data );
131
132 $json = @call_user_func_array( 'json_encode', $args );
133
134 // If json_encode() was successful, no need to do more sanity checking.
135 // ... unless we're in an old version of PHP, and json_encode() returned
136 // a string containing 'null'. Then we need to do more sanity checking.
137 if ( false !== $json && ( version_compare( PHP_VERSION, '5.5', '>=' ) || false === strpos( $json, 'null' ) ) ) {
138 return $json;
139 }
140
141 try {
142 $args[0] = _wp_json_sanity_check( $data, $depth );
143 } catch ( Exception $e ) {
144 return false;
145 }
146
147 return call_user_func_array( 'json_encode', $args );
148 }
149 endif;
150
151 if ( ! function_exists( '_wp_json_prepare_data' ) ) :
152 /**
153 * Prepares response data to be serialized to JSON.
154 *
155 * This supports the JsonSerializable interface for PHP 5.2-5.3 as well.
156 *
157 * @since 1.6.5
158 * @since WP 4.4.0
159 * @access private
160 *
161 * @param mixed $data Native representation.
162 * @return bool|int|float|null|string|array Data ready for `json_encode()`.
163 */
164 function _wp_json_prepare_data( $data ) {
165 if ( ! defined( 'WP_JSON_SERIALIZE_COMPATIBLE' ) || WP_JSON_SERIALIZE_COMPATIBLE === false ) {
166 return $data;
167 }
168
169 switch ( gettype( $data ) ) {
170 case 'boolean':
171 case 'integer':
172 case 'double':
173 case 'string':
174 case 'NULL':
175 // These values can be passed through.
176 return $data;
177
178 case 'array':
179 // Arrays must be mapped in case they also return objects.
180 return array_map( '_wp_json_prepare_data', $data );
181
182 case 'object':
183 // If this is an incomplete object (__PHP_Incomplete_Class), bail.
184 if ( ! is_object( $data ) ) {
185 return null;
186 }
187
188 if ( $data instanceof JsonSerializable ) {
189 $data = $data->jsonSerialize();
190 } else {
191 $data = get_object_vars( $data );
192 }
193
194 // Now, pass the array (or whatever was returned from jsonSerialize through).
195 return _wp_json_prepare_data( $data );
196
197 default:
198 return null;
199 }
200 }
201 endif;
202
203 if ( ! function_exists( '_wp_json_sanity_check' ) ) :
204 /**
205 * Perform sanity checks on data that shall be encoded to JSON.
206 *
207 * @since 1.6.5
208 * @since WP 4.1.0
209 * @access private
210 * @throws Exception If the depth limit is reached.
211 *
212 * @see wp_json_encode()
213 *
214 * @param mixed $data Variable (usually an array or object) to encode as JSON.
215 * @param int $depth Maximum depth to walk through $data. Must be greater than 0.
216 * @return mixed The sanitized data that shall be encoded to JSON.
217 */
218 function _wp_json_sanity_check( $data, $depth ) {
219 if ( $depth < 0 ) {
220 throw new Exception( 'Reached depth limit' );
221 }
222
223 if ( is_array( $data ) ) {
224 $output = array();
225 foreach ( $data as $id => $el ) {
226 // Don't forget to sanitize the ID!
227 if ( is_string( $id ) ) {
228 $clean_id = _wp_json_convert_string( $id );
229 } else {
230 $clean_id = $id;
231 }
232
233 // Check the element type, so that we're only recursing if we really have to.
234 if ( is_array( $el ) || is_object( $el ) ) {
235 $output[ $clean_id ] = _wp_json_sanity_check( $el, $depth - 1 );
236 } elseif ( is_string( $el ) ) {
237 $output[ $clean_id ] = _wp_json_convert_string( $el );
238 } else {
239 $output[ $clean_id ] = $el;
240 }
241 }
242 } elseif ( is_object( $data ) ) {
243 $output = new stdClass();
244 foreach ( $data as $id => $el ) {
245 if ( is_string( $id ) ) {
246 $clean_id = _wp_json_convert_string( $id );
247 } else {
248 $clean_id = $id;
249 }
250
251 if ( is_array( $el ) || is_object( $el ) ) {
252 $output->$clean_id = _wp_json_sanity_check( $el, $depth - 1 );
253 } elseif ( is_string( $el ) ) {
254 $output->$clean_id = _wp_json_convert_string( $el );
255 } else {
256 $output->$clean_id = $el;
257 }
258 }
259 } elseif ( is_string( $data ) ) {
260 return _wp_json_convert_string( $data );
261 } else {
262 return $data;
263 } // End if().
264
265 return $output;
266 }
267 endif;
268
269 if ( ! function_exists( '_wp_json_convert_string' ) ) :
270 /**
271 * Convert a string to UTF-8, so that it can be safely encoded to JSON.
272 *
273 * @since 1.6.5
274 * @since WP 4.1.0
275 * @access private
276 *
277 * @see _wp_json_sanity_check()
278 *
279 * @staticvar bool $use_mb
280 *
281 * @param string $string The string which is to be converted.
282 * @return string The checked string.
283 */
284 function _wp_json_convert_string( $string ) {
285 static $use_mb = null;
286 if ( is_null( $use_mb ) ) {
287 $use_mb = function_exists( 'mb_convert_encoding' );
288 }
289
290 if ( $use_mb ) {
291 $encoding = mb_detect_encoding( $string, mb_detect_order(), true );
292 if ( $encoding ) {
293 return mb_convert_encoding( $string, 'UTF-8', $encoding );
294 } else {
295 return mb_convert_encoding( $string, 'UTF-8', 'UTF-8' );
296 }
297 } else {
298 return wp_check_invalid_utf8( $string, true );
299 }
300 }
301 endif;
302
303 if ( ! function_exists( 'wp_normalize_path' ) ) :
304 /**
305 * Normalize a filesystem path.
306 *
307 * On windows systems, replaces backslashes with forward slashes
308 * and forces upper-case drive letters.
309 * Allows for two leading slashes for Windows network shares, but
310 * ensures that all other duplicate slashes are reduced to a single.
311 *
312 * @since 1.6.7
313 * @since WP 3.9.0
314 * @since WP 4.4.0 Ensures upper-case drive letters on Windows systems.
315 * @since WP 4.5.0 Allows for Windows network shares.
316 *
317 * @param string $path Path to normalize.
318 * @return string Normalized path.
319 */
320 function wp_normalize_path( $path ) {
321 $path = str_replace( '\\', '/', $path );
322 $path = preg_replace( '|(?<=.)/+|', '/', $path );
323 if ( ':' === substr( $path, 1, 1 ) ) {
324 $path = ucfirst( $path );
325 }
326 return $path;
327 }
328 endif;
329
330 if ( ! function_exists( 'wp_parse_url' ) ) :
331 /**
332 * A wrapper for PHP's parse_url() function that handles consistency in the return
333 * values across PHP versions.
334 *
335 * PHP 5.4.7 expanded parse_url()'s ability to handle non-absolute url's, including
336 * schemeless and relative url's with :// in the path. This function works around
337 * those limitations providing a standard output on PHP 5.2~5.4+.
338 *
339 * Secondly, across various PHP versions, schemeless URLs starting containing a ":"
340 * in the query are being handled inconsistently. This function works around those
341 * differences as well.
342 *
343 * Error suppression is used as prior to PHP 5.3.3, an E_WARNING would be generated
344 * when URL parsing failed.
345 *
346 * @since 1.6.9
347 * @since WP 4.4.0
348 * @since WP 4.7.0 The $component parameter was added for parity with PHP's parse_url().
349 *
350 * @param (string) $url The URL to parse.
351 * @param (int) $component The specific component to retrieve. Use one of the PHP
352 * predefined constants to specify which one.
353 * Defaults to -1 (= return all parts as an array).
354 * @see http://php.net/manual/en/function.parse-url.php
355 *
356 * @return (mixed) False on parse failure; Array of URL components on success;
357 * When a specific component has been requested: null if the component
358 * doesn't exist in the given URL; a sting or - in the case of
359 * PHP_URL_PORT - integer when it does. See parse_url()'s return values.
360 */
361 function wp_parse_url( $url, $component = -1 ) {
362 $to_unset = array();
363 $url = strval( $url );
364
365 if ( '//' === substr( $url, 0, 2 ) ) {
366 $to_unset[] = 'scheme';
367 $url = 'placeholder:' . $url;
368 } elseif ( '/' === substr( $url, 0, 1 ) ) {
369 $to_unset[] = 'scheme';
370 $to_unset[] = 'host';
371 $url = 'placeholder://placeholder' . $url;
372 }
373
374 $parts = @parse_url( $url );
375
376 if ( false === $parts ) {
377 // Parsing failure.
378 return $parts;
379 }
380
381 // Remove the placeholder values.
382 if ( $to_unset ) {
383 foreach ( $to_unset as $key ) {
384 unset( $parts[ $key ] );
385 }
386 }
387
388 return _get_component_from_parsed_url_array( $parts, $component );
389 }
390 endif;
391
392 if ( ! function_exists( '_get_component_from_parsed_url_array' ) ) :
393 /**
394 * Retrieve a specific component from a parsed URL array.
395 *
396 * @since 1.6.9
397 * @since WP 4.7.0
398 *
399 * @param (array|false) $url_parts The parsed URL. Can be false if the URL failed to parse.
400 * @param (int) $component The specific component to retrieve. Use one of the PHP
401 * predefined constants to specify which one.
402 * Defaults to -1 (= return all parts as an array).
403 * @see http://php.net/manual/en/function.parse-url.php
404 *
405 * @return (mixed) False on parse failure; Array of URL components on success;
406 * When a specific component has been requested: null if the component
407 * doesn't exist in the given URL; a sting or - in the case of
408 * PHP_URL_PORT - integer when it does. See parse_url()'s return values.
409 */
410 function _get_component_from_parsed_url_array( $url_parts, $component = -1 ) {
411 if ( -1 === $component ) {
412 return $url_parts;
413 }
414
415 $key = _wp_translate_php_url_constant_to_key( $component );
416
417 if ( false !== $key && is_array( $url_parts ) && isset( $url_parts[ $key ] ) ) {
418 return $url_parts[ $key ];
419 } else {
420 return null;
421 }
422 }
423 endif;
424
425 if ( ! function_exists( '_wp_translate_php_url_constant_to_key' ) ) :
426 /**
427 * Translate a PHP_URL_* constant to the named array keys PHP uses.
428 *
429 * @since 1.6.9
430 * @since WP 4.7.0
431 * @see http://php.net/manual/en/url.constants.php
432 *
433 * @param (int) $constant PHP_URL_* constant.
434 *
435 * @return (string|bool) The named key or false.
436 */
437 function _wp_translate_php_url_constant_to_key( $constant ) {
438 $translation = array(
439 PHP_URL_SCHEME => 'scheme',
440 PHP_URL_HOST => 'host',
441 PHP_URL_PORT => 'port',
442 PHP_URL_USER => 'user',
443 PHP_URL_PASS => 'pass',
444 PHP_URL_PATH => 'path',
445 PHP_URL_QUERY => 'query',
446 PHP_URL_FRAGMENT => 'fragment',
447 );
448
449 if ( isset( $translation[ $constant ] ) ) {
450 return $translation[ $constant ];
451 } else {
452 return false;
453 }
454 }
455 endif;
456
457 if ( ! function_exists( 'wp_get_additional_image_sizes' ) ) :
458 /**
459 * Retrieve additional image sizes.
460 *
461 * @since 1.6.10
462 * @since WP 4.7.0
463 *
464 * @global array $_wp_additional_image_sizes
465 *
466 * @return array Additional images size data.
467 */
468 function wp_get_additional_image_sizes() {
469 global $_wp_additional_image_sizes;
470 if ( ! $_wp_additional_image_sizes ) {
471 $_wp_additional_image_sizes = array(); // WPCS: override ok.
472 }
473 return $_wp_additional_image_sizes;
474 }
475 endif;
476
477 if ( ! function_exists( 'doing_filter' ) ) :
478 /**
479 * Retrieve the name of a filter currently being processed.
480 *
481 * The function current_filter() only returns the most recent filter or action
482 * being executed. did_action() returns true once the action is initially
483 * processed.
484 *
485 * This function allows detection for any filter currently being
486 * executed (despite not being the most recent filter to fire, in the case of
487 * hooks called from hook callbacks) to be verified.
488 *
489 * @since 1.6.11
490 * @since WP 3.9.0
491 *
492 * @see current_filter()
493 * @see did_action()
494 * @global array $wp_current_filter Current filter.
495 *
496 * @param null|string $filter Optional. Filter to check. Defaults to null, which
497 * checks if any filter is currently being run.
498 * @return bool Whether the filter is currently in the stack.
499 */
500 function doing_filter( $filter = null ) {
501 global $wp_current_filter;
502
503 if ( null === $filter ) {
504 return ! empty( $wp_current_filter );
505 }
506
507 return in_array( $filter, $wp_current_filter, true );
508 }
509 endif;
510
511 if ( ! function_exists( 'wp_scripts' ) ) :
512 /**
513 * Initialize $wp_scripts if it has not been set.
514 *
515 * @global WP_Scripts $wp_scripts
516 *
517 * @since 1.6.11
518 * @since WP 4.2.0
519 *
520 * @return WP_Scripts WP_Scripts instance.
521 */
522 function wp_scripts() {
523 global $wp_scripts;
524 if ( ! ( $wp_scripts instanceof WP_Scripts ) ) {
525 $wp_scripts = new WP_Scripts(); // WPCS: override ok.
526 }
527 return $wp_scripts;
528 }
529 endif;
530
531 if ( ! function_exists( 'wp_doing_ajax' ) ) :
532 /**
533 * Determines whether the current request is a WordPress Ajax request.
534 *
535 * @since 1.7
536 * @since WP 4.7.0
537 *
538 * @return bool True if it's a WordPress Ajax request, false otherwise.
539 */
540 function wp_doing_ajax() {
541 /**
542 * Filters whether the current request is a WordPress Ajax request.
543 *
544 * @since 1.7
545 * @since WP 4.7.0
546 *
547 * @param bool $wp_doing_ajax Whether the current request is a WordPress Ajax request.
548 */
549 return apply_filters( 'wp_doing_ajax', defined( 'DOING_AJAX' ) && DOING_AJAX );
550 }
551 endif;
552
553 if ( ! function_exists( '_deprecated_hook' ) ) :
554 /**
555 * Marks a deprecated action or filter hook as deprecated and throws a notice.
556 *
557 * Use the {@see 'deprecated_hook_run'} action to get the backtrace describing where
558 * the deprecated hook was called.
559 *
560 * Default behavior is to trigger a user error if `WP_DEBUG` is true.
561 *
562 * This function is called by the do_action_deprecated() and apply_filters_deprecated()
563 * functions, and so generally does not need to be called directly.
564 *
565 * @since 1.7
566 * @since WP 4.6.0
567 * @access private
568 *
569 * @param string $hook The hook that was used.
570 * @param string $version The version of WordPress that deprecated the hook.
571 * @param string $replacement Optional. The hook that should have been used.
572 * @param string $message Optional. A message regarding the change.
573 */
574 function _deprecated_hook( $hook, $version, $replacement = null, $message = null ) {
575 /**
576 * Fires when a deprecated hook is called.
577 *
578 * @since 1.7
579 * @since WP 4.6.0
580 *
581 * @param string $hook The hook that was called.
582 * @param string $replacement The hook that should be used as a replacement.
583 * @param string $version The version of WordPress that deprecated the argument used.
584 * @param string $message A message regarding the change.
585 */
586 do_action( 'deprecated_hook_run', $hook, $replacement, $version, $message );
587
588 /**
589 * Filters whether to trigger deprecated hook errors.
590 *
591 * @since 1.7
592 * @since WP 4.6.0
593 *
594 * @param bool $trigger Whether to trigger deprecated hook errors. Requires
595 * `WP_DEBUG` to be defined true.
596 */
597 if ( WP_DEBUG && apply_filters( 'deprecated_hook_trigger_error', true ) ) {
598 $message = empty( $message ) ? '' : ' ' . $message;
599 if ( ! is_null( $replacement ) ) {
600 /* translators: 1: WordPress hook name, 2: version number, 3: alternative hook name */
601 trigger_error( sprintf( __( '%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.', 'imagify' ), $hook, $version, $replacement ) . $message );
602 } else {
603 /* translators: 1: WordPress hook name, 2: version number */
604 trigger_error( sprintf( __( '%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.', 'imagify' ), $hook, $version ) . $message );
605 }
606 }
607 }
608 endif;
609
610 if ( ! function_exists( 'apply_filters_deprecated' ) ) :
611 /**
612 * Fires functions attached to a deprecated filter hook.
613 *
614 * When a filter hook is deprecated, the apply_filters() call is replaced with
615 * apply_filters_deprecated(), which triggers a deprecation notice and then fires
616 * the original filter hook.
617 *
618 * Note: the value and extra arguments passed to the original apply_filters() call
619 * must be passed here to `$args` as an array. For example:
620 *
621 * // Old filter.
622 * return apply_filters( 'wpdocs_filter', $value, $extra_arg );
623 *
624 * // Deprecated.
625 * return apply_filters_deprecated( 'wpdocs_filter', array( $value, $extra_arg ), '4.9', 'wpdocs_new_filter' );
626 *
627 * @since 1.7
628 * @since WP 4.6.0
629 *
630 * @see _deprecated_hook()
631 *
632 * @param string $tag The name of the filter hook.
633 * @param array $args Array of additional function arguments to be passed to apply_filters().
634 * @param string $version The version of WordPress that deprecated the hook.
635 * @param string $replacement Optional. The hook that should have been used. Default false.
636 * @param string $message Optional. A message regarding the change. Default null.
637 */
638 function apply_filters_deprecated( $tag, $args, $version, $replacement = false, $message = null ) {
639 if ( ! has_filter( $tag ) ) {
640 return $args[0];
641 }
642
643 _deprecated_hook( $tag, $version, $replacement, $message );
644
645 return apply_filters_ref_array( $tag, $args );
646 }
647 endif;
648