PluginProbe
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF / 1.9.13
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF v1.9.13
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 / common.php

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

629 lines 16.3 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 * Get the list of the names of the Imagify context currently in use.
6 *
7 * @since 1.9
8 * @author Grégory Viguier
9 *
10 * @return array An array of strings.
11 */
12 function imagify_get_context_names() {
13 static $contexts;
14
15 if ( isset( $contexts ) ) {
16 return $contexts;
17 }
18
19 /**
20 * Register new contexts.
21 *
22 * @since 1.9
23 * @author Grégory Viguier
24 *
25 * @param array $contexts An array of context names.
26 */
27 $contexts = (array) apply_filters( 'imagify_register_context', [] );
28
29 $contexts = array_filter( $contexts, function( $context ) {
30 return $context && is_string( $context );
31 } );
32 $contexts = array_merge( [ 'wp', 'custom-folders' ], $contexts );
33
34 sort( $contexts );
35
36 return $contexts;
37 }
38
39 /**
40 * Sanitize an optimization context.
41 *
42 * @since 1.6.11
43 * @author Grégory Viguier
44 *
45 * @param string $context The context.
46 * @return string
47 */
48 function imagify_sanitize_context( $context ) {
49 return sanitize_key( $context );
50 }
51
52 /**
53 * Get the Imagify context instance.
54 *
55 * @since 1.9
56 * @author Grégory Viguier
57 *
58 * @param string $context The context name. Default values are 'wp' and 'custom-folders'.
59 * @return ContextInterface The context instance.
60 */
61 function imagify_get_context( $context ) {
62 $class_name = imagify_get_context_class_name( $context );
63 return $class_name::get_instance();
64 }
65
66 /**
67 * Get the Imagify context class name.
68 *
69 * @since 1.9
70 * @author Grégory Viguier
71 *
72 * @param string $context The context name. Default values are 'wp' and 'custom-folders'.
73 * @return string The context class name.
74 */
75 function imagify_get_context_class_name( $context ) {
76 $context = imagify_sanitize_context( $context );
77
78 switch ( $context ) {
79 case 'wp':
80 $class_name = '\\Imagify\\Context\\WP';
81 break;
82
83 case 'custom-folders':
84 $class_name = '\\Imagify\\Context\\CustomFolders';
85 break;
86
87 default:
88 $class_name = '\\Imagify\\Context\\Noop';
89 }
90
91 /**
92 * Filter the name of the class to use to define a context.
93 *
94 * @since 1.9
95 * @author Grégory Viguier
96 *
97 * @param int $class_name The class name.
98 * @param string $context The context name.
99 */
100 $class_name = apply_filters( 'imagify_context_class_name', $class_name, $context );
101
102 return '\\' . ltrim( $class_name, '\\' );
103 }
104
105 /**
106 * Get the Imagify process instance depending on a context.
107 *
108 * @since 1.9
109 * @author Grégory Viguier
110 *
111 * @param int $media_id The media ID.
112 * @param string $context The context name. Default values are 'wp' and 'custom-folders'.
113 * @return ProcessInterface The optimization process instance.
114 */
115 function imagify_get_optimization_process( $media_id, $context ) {
116 $class_name = imagify_get_optimization_process_class_name( $context );
117 return new $class_name( $media_id );
118 }
119
120 /**
121 * Get the Imagify process class name depending on a context.
122 *
123 * @since 1.9
124 * @author Grégory Viguier
125 *
126 * @param string $context The context name. Default values are 'wp' and 'custom-folders'.
127 * @return string The optimization process class name.
128 */
129 function imagify_get_optimization_process_class_name( $context ) {
130 $context = imagify_sanitize_context( $context );
131
132 switch ( $context ) {
133 case 'wp':
134 $class_name = '\\Imagify\\Optimization\\Process\\WP';
135 break;
136
137 case 'custom-folders':
138 $class_name = '\\Imagify\\Optimization\\Process\\CustomFolders';
139 break;
140
141 default:
142 $class_name = '\\Imagify\\Optimization\\Process\\Noop';
143 }
144
145 /**
146 * Filter the name of the class to use for the optimization.
147 *
148 * @since 1.9
149 * @author Grégory Viguier
150 *
151 * @param int $class_name The class name.
152 * @param string $context The context name.
153 */
154 $class_name = apply_filters( 'imagify_process_class_name', $class_name, $context );
155
156 return '\\' . ltrim( $class_name, '\\' );
157 }
158
159 /**
160 * Get WP Direct filesystem object. Also define chmod constants if not done yet.
161 *
162 * @since 1.6.5
163 * @author Grégory Viguier
164 *
165 * @return object A Imagify_Filesystem object.
166 */
167 function imagify_get_filesystem() {
168 return Imagify_Filesystem::get_instance();
169 }
170
171 /**
172 * Convert a path (or URL) to its webp version.
173 * To keep the function simple:
174 * - Not tested if it's an image.
175 * - File existance is not tested.
176 * - If an URL is given, make sure it doesn't contain query args.
177 *
178 * @since 1.9
179 * @author Grégory Viguier
180 *
181 * @param string $path A file path or URL.
182 * @return string
183 */
184 function imagify_path_to_webp( $path ) {
185 return $path . '.webp';
186 }
187
188 /**
189 * Tell if the current user can optimize custom folders.
190 *
191 * @since 1.7
192 * @author Grégory Viguier
193 *
194 * @return bool
195 */
196 function imagify_can_optimize_custom_folders() {
197 static $can;
198
199 if ( isset( $can ) ) {
200 return $can;
201 }
202
203 // Check if the DB tables are ready.
204 if ( ! Imagify_Folders_DB::get_instance()->can_operate() || ! Imagify_Files_DB::get_instance()->can_operate() ) {
205 $can = false;
206 return $can;
207 }
208
209 // Check for user capacity.
210 $can = imagify_get_context( 'custom-folders' )->current_user_can( 'optimize' );
211
212 return $can;
213 }
214
215 /**
216 * Simple helper to get some external URLs, like to the documentation.
217 *
218 * @since 1.6.12
219 * @author Grégory Viguier
220 *
221 * @param string $target What we want.
222 * @param array $query_args An array of query arguments.
223 * @return string The URL.
224 */
225 function imagify_get_external_url( $target, $query_args = array() ) {
226 $site_url = 'https://imagify.io/';
227 $app_url = 'https://app.imagify.io/#/';
228
229 switch ( $target ) {
230 case 'plugin':
231 /* translators: Plugin URI of the plugin/theme */
232 $url = __( 'https://wordpress.org/plugins/imagify/', 'imagify' );
233 break;
234
235 case 'rate':
236 $url = 'https://wordpress.org/support/view/plugin-reviews/imagify?rate=5#postform';
237 break;
238
239 case 'share-twitter':
240 $url = rawurlencode( imagify_get_external_url( 'plugin' ) );
241 $url = 'https://twitter.com/intent/tweet?source=webclient&original_referer=' . $url . '&url=' . $url . '&related=imagify&hastags=performance,web,wordpress';
242 break;
243
244 case 'share-facebook':
245 $url = rawurlencode( imagify_get_external_url( 'plugin' ) );
246 $url = 'https://www.facebook.com/sharer/sharer.php?u=' . $url;
247 break;
248
249 case 'exif':
250 /* translators: URL to a Wikipedia page explaining what EXIF means. */
251 $url = __( 'https://en.wikipedia.org/wiki/Exchangeable_image_file_format', 'imagify' );
252 break;
253
254 case 'contact':
255 $lang = imagify_get_current_lang_in( 'fr' );
256 $paths = array(
257 'en' => 'contact',
258 'fr' => 'fr/contact',
259 );
260
261 $url = $site_url . $paths[ $lang ] . '/';
262 break;
263
264 case 'documentation':
265 $url = $site_url . 'documentation/';
266 break;
267
268 case 'documentation-imagick-gd':
269 $url = $site_url . 'documentation/solve-imagemagick-gd-required/';
270 break;
271
272 case 'register':
273 $partner = imagify_get_partner();
274
275 if ( $partner ) {
276 $query_args['partner'] = $partner;
277 }
278
279 $url = $app_url . 'register';
280 break;
281
282 case 'subscription':
283 $url = $app_url . 'subscription';
284 break;
285
286 case 'get-api-key':
287 $url = $app_url . 'api';
288 break;
289
290 case 'payment':
291 // Don't remove the trailing slash.
292 $url = $app_url . 'plugin/';
293 break;
294
295 default:
296 return '';
297 }
298
299 if ( $query_args ) {
300 $url = add_query_arg( $query_args, $url );
301 }
302
303 return $url;
304 }
305
306 /**
307 * Get the current lang ('fr', 'en', 'de'...), limited to a given list.
308 *
309 * @since 1.6.14
310 * @author Grégory Viguier
311 *
312 * @param array $langs An array of langs, like array( 'de', 'es', 'fr', 'it' ).
313 * @return string The current lang. Default is 'en'.
314 */
315 function imagify_get_current_lang_in( $langs ) {
316 static $locale;
317
318 if ( ! isset( $locale ) ) {
319 $locale = imagify_get_locale();
320 $locale = explode( '_', strtolower( $locale . '_' ) ); // Trailing underscore is to make sure $locale[1] is set.
321 }
322
323 foreach ( (array) $langs as $lang ) {
324 if ( $lang === $locale[0] || $lang === $locale[1] ) {
325 return $lang;
326 }
327 }
328
329 return 'en';
330 }
331
332 /**
333 * Get the current locale.
334 *
335 * @since 1.6.14
336 * @author Grégory Viguier
337 *
338 * @return string The current locale.
339 */
340 function imagify_get_locale() {
341 $locale = function_exists( 'get_user_locale' ) ? get_user_locale() : get_locale();
342 /**
343 * Filter the locale used by Imagify.
344 *
345 * @since 1.6.14
346 * @author Grégory Viguier
347 *
348 * @param string $locale The current locale.
349 */
350 return apply_filters( 'imagify_locale', $locale );
351 }
352
353 /**
354 * Get the label corresponding to the given optimization label.
355 *
356 * @since 1.7
357 * @author Grégory Viguier
358 *
359 * @param int|bool $level Optimization level (between 0 and 2). False if no level.
360 * @param string $format Format to display the label. Use %ICON% for the icon and %s for the label.
361 * @return string The label.
362 */
363 function imagify_get_optimization_level_label( $level, $format = '%s' ) {
364 if ( ! is_numeric( $level ) ) {
365 return '';
366 }
367
368 if ( strpos( $format, '%ICON%' ) !== false ) {
369 $icon = '<svg width="12" height="12" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg"><g fill="#40B1D0" fill-rule="evenodd">';
370
371 switch ( $level ) {
372 case 2:
373 $icon .= '<polygon points="11.6054688 11.6054688 8.7890625 11.6054688 8.7890625 0.39453125 11.6054688 0.39453125"/><polygon points="7.39453125 11.6054688 4.60546875 11.6054688 4.60546875 3.89453125 7.39453125 3.89453125"/><polygon points="3.2109375 11.6054688 0.39453125 11.6054688 0.39453125 6 3.2109375 6"/>';
374 break;
375 case 1:
376 $icon .= '<polygon fill="#CCD1D6" points="11.6054688 11.6054688 8.7890625 11.6054688 8.7890625 0.39453125 11.6054688 0.39453125"/><polygon points="7.39453125 11.6054688 4.60546875 11.6054688 4.60546875 3.89453125 7.39453125 3.89453125"/><polygon points="3.2109375 11.6054688 0.39453125 11.6054688 0.39453125 6 3.2109375 6"/>';
377 break;
378 case 0:
379 $icon .= '<polygon fill="#CCD1D6" points="11.6054688 11.6054688 8.7890625 11.6054688 8.7890625 0.39453125 11.6054688 0.39453125"/><polygon fill="#CCD1D6" points="7.39453125 11.6054688 4.60546875 11.6054688 4.60546875 3.89453125 7.39453125 3.89453125"/><polygon points="3.2109375 11.6054688 0.39453125 11.6054688 0.39453125 6 3.2109375 6"/>';
380 }
381
382 $icon .= '</g></svg>';
383
384 $format = str_replace( '%ICON%', $icon, $format );
385 }
386
387 switch ( $level ) {
388 case 2:
389 return sprintf( $format, __( 'Ultra', 'imagify' ) );
390 case 1:
391 return sprintf( $format, __( 'Aggressive', 'imagify' ) );
392 case 0:
393 return sprintf( $format, __( 'Normal', 'imagify' ) );
394 }
395
396 return '';
397 }
398
399 /**
400 * `array_merge()` + `array_intersect_key()`.
401 *
402 * @since 1.7
403 * @author Grégory Viguier
404 *
405 * @param array $values The array we're interested in.
406 * @param array $default The array we use as boundaries.
407 * @return array
408 */
409 function imagify_merge_intersect( $values, $default ) {
410 $values = array_merge( $default, (array) $values );
411 return array_intersect_key( $values, $default );
412 }
413
414 /**
415 * Returns true.
416 * Useful for returning true to filters easily.
417 * Similar to WP's __return_true() function, it allows to remove it from a filter without removing another one added by another plugin.
418 *
419 * @since 1.9
420 * @author Grégory Viguier
421 *
422 * @return bool True.
423 */
424 function imagify_return_true() {
425 return true;
426 }
427
428 /**
429 * Returns false.
430 * Useful for returning false to filters easily.
431 * Similar to WP's __return_false() function, it allows to remove it from a filter without removing another one added by another plugin.
432 *
433 * @since 1.9
434 * @author Grégory Viguier
435 *
436 * @return bool False.
437 */
438 function imagify_return_false() {
439 return false;
440 }
441
442 /**
443 * Marks a class as deprecated and informs when it has been used.
444 * Similar to _deprecated_constructor(), but with different strings.
445 * The current behavior is to trigger a user error if `WP_DEBUG` is true.
446 *
447 * @since 1.9
448 * @author Grégory Viguier
449 *
450 * @param string $class The class containing the deprecated constructor.
451 * @param string $version The version of WordPress that deprecated the function.
452 * @param string $replacement Optional. The function that should have been called. Default null.
453 * @param string $parent_class Optional. The parent class calling the deprecated constructor. Default empty string.
454 */
455 function imagify_deprecated_class( $class, $version, $replacement = null, $parent_class = '' ) {
456
457 /**
458 * Fires when a deprecated class is called.
459 *
460 * @since 1.9
461 * @author Grégory Viguier
462 *
463 * @param string $class The class containing the deprecated constructor.
464 * @param string $version The version of WordPress that deprecated the function.
465 * @param string $replacement Optional. The function that should have been called.
466 * @param string $parent_class The parent class calling the deprecated constructor.
467 */
468 do_action( 'imagify_deprecated_class_run', $class, $version, $replacement, $parent_class );
469
470 if ( ! WP_DEBUG ) {
471 return;
472 }
473
474 /**
475 * Filters whether to trigger an error for deprecated classes.
476 *
477 * `WP_DEBUG` must be true in addition to the filter evaluating to true.
478 *
479 * @since 1.9
480 * @author Grégory Viguier
481 *
482 * @param bool $trigger Whether to trigger the error for deprecated classes. Default true.
483 */
484 if ( ! apply_filters( 'imagify_deprecated_class_trigger_error', true ) ) {
485 return;
486 }
487
488 if ( function_exists( '__' ) ) {
489 if ( ! empty( $parent_class ) ) {
490 /**
491 * With parent class.
492 */
493 if ( ! empty( $replacement ) ) {
494 /**
495 * With replacement.
496 */
497 call_user_func(
498 'trigger_error',
499 sprintf(
500 /* translators: 1: PHP class name, 2: PHP parent class name, 3: version number, 4: replacement class name. */
501 __( 'The called class %1$s extending %2$s is <strong>deprecated</strong> since version %3$s! Use %4$s instead.', 'imagify' ),
502 '<code>' . $class . '</code>',
503 '<code>' . $parent_class . '</code>',
504 '<strong>' . $version . '</strong>',
505 '<code>' . $replacement . '</code>'
506 )
507 );
508 return;
509 }
510
511 /**
512 * Without replacement.
513 */
514 call_user_func(
515 'trigger_error',
516 sprintf(
517 /* translators: 1: PHP class name, 2: PHP parent class name, 3: version number. */
518 __( 'The called class %1$s extending %2$s is <strong>deprecated</strong> since version %3$s!', 'imagify' ),
519 '<code>' . $class . '</code>',
520 '<code>' . $parent_class . '</code>',
521 '<strong>' . $version . '</strong>'
522 )
523 );
524 return;
525 }
526
527 /**
528 * Without parent class.
529 */
530 if ( ! empty( $replacement ) ) {
531 /**
532 * With replacement.
533 */
534 call_user_func(
535 'trigger_error',
536 sprintf(
537 /* translators: 1: PHP class name, 2: version number, 3: replacement class name. */
538 __( 'The called class %1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.', 'imagify' ),
539 '<code>' . $class . '</code>',
540 '<strong>' . $version . '</strong>',
541 '<code>' . $replacement . '</code>'
542 )
543 );
544 return;
545 }
546
547 /**
548 * Without replacement.
549 */
550 call_user_func(
551 'trigger_error',
552 sprintf(
553 /* translators: 1: PHP class name, 2: version number. */
554 __( 'The called class %1$s is <strong>deprecated</strong> since version %2$s!', 'imagify' ),
555 '<code>' . $class . '</code>',
556 '<strong>' . $version . '</strong>'
557 )
558 );
559 return;
560 }
561
562 if ( ! empty( $parent_class ) ) {
563 /**
564 * With parent class.
565 */
566 if ( ! empty( $replacement ) ) {
567 /**
568 * With replacement.
569 */
570 call_user_func(
571 'trigger_error',
572 sprintf(
573 'The called class %1$s extending %2$s is <strong>deprecated</strong> since version %3$s! Use %4$s instead.',
574 '<code>' . $class . '</code>',
575 '<code>' . $parent_class . '</code>',
576 '<strong>' . $version . '</strong>',
577 '<code>' . $replacement . '</code>'
578 )
579 );
580 return;
581 }
582
583 /**
584 * Without replacement.
585 */
586 call_user_func(
587 'trigger_error',
588 sprintf(
589 'The called class %1$s extending %2$s is <strong>deprecated</strong> since version %3$s!',
590 '<code>' . $class . '</code>',
591 '<code>' . $parent_class . '</code>',
592 '<strong>' . $version . '</strong>'
593 )
594 );
595 return;
596 }
597
598 /**
599 * Without parent class.
600 */
601 if ( ! empty( $replacement ) ) {
602 /**
603 * With replacement.
604 */
605 call_user_func(
606 'trigger_error',
607 sprintf(
608 'The called class %1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.',
609 '<code>' . $class . '</code>',
610 '<strong>' . $version . '</strong>',
611 '<code>' . $replacement . '</code>'
612 )
613 );
614 return;
615 }
616
617 /**
618 * Without replacement.
619 */
620 call_user_func(
621 'trigger_error',
622 sprintf(
623 'The called class %1$s is <strong>deprecated</strong> since version %2$s!',
624 '<code>' . $class . '</code>',
625 '<strong>' . $version . '</strong>'
626 )
627 );
628 }
629