PluginProbe
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF / trunk
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF vtrunk
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 / admin-ui.php

admin-ui.php in Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF trunk, at inc/functions/admin-ui.php

604 lines 17.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 defined( 'ABSPATH' ) || exit;
3
4 /**
5 * Get the optimization data list for a specific media.
6 *
7 * @since 1.0
8 * @since 1.9 Function signature changed.
9 * @author Jonathan Buttigieg
10 *
11 * @param \Imagify\Optimization\Process\ProcessInterface $process The optimization process object.
12 * @return string The output to print.
13 */
14 function get_imagify_attachment_optimization_text( $process ) {
15 if ( ! $process->is_valid() ) {
16 return '';
17 }
18
19 $is_media_page = Imagify_Views::get_instance()->is_media_page();
20 $is_library_page = Imagify_Views::get_instance()->is_wp_library_page();
21 $output = $is_media_page ? '' : '<ul class="imagify-datas-list" id="imagify_data_sum">';
22 $output_before = $is_media_page ? '' : '<li class="imagify-data-item">';
23 $output_after = $is_media_page ? '<br/>' : '</li>';
24 $reoptimize_link = get_imagify_attachment_reoptimize_link( $process );
25 $reoptimize_link .= get_imagify_attachment_optimize_missing_thumbnails_link( $process );
26 $reoptimize_link .= get_imagify_attachment_generate_nextgen_versions_link( $process );
27 $reoptimize_link .= get_imagify_attachment_delete_nextgen_versions_link( $process );
28 $reoptimize_output = $reoptimize_link ? $reoptimize_link : '';
29 $reoptimize_output_before = '<div class="imagify-datas-actions-links">';
30 $reoptimize_output_after = '</div><!-- .imagify-datas-actions-links -->';
31 $error = get_imagify_attachment_error_text( $process );
32 $media = $process->get_media();
33
34 if ( $error ) {
35 if ( ! $is_media_page && $reoptimize_link && $media->has_backup() ) {
36 $reoptimize_output .= '<span class="attachment-has-backup hidden"></span>';
37 }
38
39 $reoptimize_output = $reoptimize_output_before . $reoptimize_output . $reoptimize_output_after;
40
41 return $is_media_page ? $output_before . $error . $reoptimize_output . $output_after : $error . $reoptimize_output;
42 }
43
44 $data = $process->get_data();
45 $optimized_data = $data->get_optimization_data();
46 $attachment_id = $media->get_id();
47 $optimization_level = imagify_get_optimization_level_label( $data->get_optimization_level() );
48
49 if ( ! $is_media_page ) {
50 $output .= $output_before . '<span class="data">' . __( 'New Filesize:', 'imagify' ) . '</span> <strong class="big">' . $data->get_optimized_size() . '</strong>' . $output_after;
51 }
52
53 if ( key_exists( 'message', $optimized_data ) && $optimized_data['message'] ) {
54 $output .= $output_before . '<span class="data">' . __( 'Convert:', 'imagify' ) . '</span> <strong class="big">' . $optimized_data['message'] . '</strong>' . $output_after;
55 }
56
57 $chart = '';
58
59 if ( ! $is_media_page ) {
60 if ( ! $is_library_page ) {
61 // No need to print this on the library page, the event whould be triggered before the handler is attached (the JS file is loaded in the footer).
62 $chart = '<script type="text/javascript">jQuery( window ).trigger( "canvasprinted.imagify", [ ".imagify-consumption-chart-' . $attachment_id . '" ] ); </script>';
63 }
64
65 $chart = '<span class="imagify-chart">
66 <span class="imagify-chart-container">
67 <canvas class="imagify-consumption-chart imagify-consumption-chart-' . $attachment_id . '" width="15" height="15"></canvas>
68 ' . $chart . '
69 </span>
70 </span>';
71 }
72
73 $output .= $output_before;
74 $output .= '<span class="data">' . __( 'Original Saving:', 'imagify' ) . '</span> ';
75 $output .= '<strong>' . $chart . '<span class="imagify-chart-value">' . $data->get_saving_percent() . '</span>%</strong>';
76 $output .= $output_after;
77
78 // More details section.
79 if ( ! $is_media_page ) {
80 // New list.
81 $output .= '</ul>';
82 $output .= '<p class="imagify-datas-more-action">';
83 $output .= '<a href="#imagify-view-details-' . $attachment_id . '" data-close="' . __( 'Close details', 'imagify' ) . '" data-open="' . __( 'View details', 'imagify' ) . '">';
84 $output .= '<span class="the-text">' . __( 'View details', 'imagify' ) . '</span>';
85 $output .= '<span class="dashicons dashicons-arrow-down-alt2"></span>';
86 $output .= '</a>';
87 $output .= '</p>';
88 $output .= '<ul id="imagify-view-details-' . $attachment_id . '" class="imagify-datas-list imagify-datas-details">';
89
90 // Not in metabox.
91 $output .= $output_before . '<span class="data">' . __( 'Original Filesize:', 'imagify' ) . '</span> <strong class="original">' . $data->get_original_size() . '</strong>' . $output_after;
92 }
93
94 $output .= $output_before . '<span class="data">' . __( 'Level:', 'imagify' ) . '</span> <strong>' . $optimization_level . '</strong>' . $output_after;
95
96 if ( $media->is_image() ) {
97 $has_nextgen = $process->has_next_gen() ? __( 'Yes', 'imagify' ) : __( 'No', 'imagify' );
98
99 if ( $process->has_next_gen() ) {
100 $has_nextgen = $process->is_full_next_gen() ? __( 'Yes', 'imagify' ) : __( 'Partially', 'imagify' );
101 }
102 $output .= $output_before . '<span class="data">' . __( 'Next-Gen generated:', 'imagify' ) . '</span> <strong class="big">' . esc_html( $has_nextgen ) . '</strong>' . $output_after;
103
104 // When the API permanently refused the conversion, show the reason it gave.
105 $nextgen_reason = '';
106
107 if ( ! empty( $optimized_data['sizes'] ) && is_array( $optimized_data['sizes'] ) ) {
108 foreach ( $optimized_data['sizes'] as $size_data ) {
109 if ( ! empty( $size_data['permanent_error'] ) && ! empty( $size_data['error'] ) ) {
110 $nextgen_reason = $size_data['error'];
111 break;
112 }
113 }
114 }
115
116 if ( $nextgen_reason ) {
117 $output .= $output_before . '<span class="data">' . __( 'Next-Gen status:', 'imagify' ) . '</span> <strong>' . esc_html( $nextgen_reason ) . '</strong>' . $output_after;
118 }
119
120 $total_optimized_thumbnails = $data->get_optimized_sizes_count();
121
122 if ( $total_optimized_thumbnails ) {
123 $output .= $output_before . '<span class="data">' . __( 'Thumbnails Optimized:', 'imagify' ) . '</span> <strong>' . $total_optimized_thumbnails . '</strong>' . $output_after;
124 $output .= $output_before . '<span class="data">' . __( 'Overall Saving:', 'imagify' ) . '</span> <strong>' . $data->get_overall_saving_percent() . '%</strong>' . $output_after;
125 }
126 }
127
128 // End of list.
129 $output .= $is_media_page ? '' : '</ul>';
130
131 // Actions section.
132 $output .= $is_media_page ? $output_before : '';
133 $output .= $reoptimize_output_before;
134 $output .= $reoptimize_output;
135
136 if ( $media->has_backup() ) {
137 $url = get_imagify_admin_url(
138 'restore',
139 [
140 'attachment_id' => $attachment_id,
141 'context' => $media->get_context(),
142 ]
143 );
144
145 $output .= Imagify_Views::get_instance()->get_template(
146 'button/restore',
147 [
148 'url' => $url,
149 'atts' => [
150 'class' => $is_media_page ? '' : null,
151 ],
152 ]
153 );
154
155 if ( ! $is_library_page ) {
156 $output .= '<input id="imagify-original-src" type="hidden" value="' . esc_url( $media->get_backup_url() ) . '">';
157 $output .= '<input id="imagify-original-size" type="hidden" value="' . $data->get_original_size() . '">';
158 $output .= '<input id="imagify-full-src" type="hidden" value="' . esc_url( $media->get_fullsize_url() ) . '">';
159
160 if ( $media->is_image() ) {
161 $dimensions = $media->get_dimensions();
162
163 $output .= '<input id="imagify-full-width" type="hidden" value="' . $dimensions['width'] . '">';
164 $output .= '<input id="imagify-full-height" type="hidden" value="' . $dimensions['height'] . '">';
165 }
166 }
167 }
168
169 $output .= $reoptimize_output_after;
170
171 return $output;
172 }
173
174 /**
175 * Get the error message for a specific attachment.
176 *
177 * @since 1.0
178 * @since 1.9 Function signature changed.
179 * @author Jonathan Buttigieg
180 *
181 * @param ProcessInterface $process The optimization process object.
182 * @return string The output to print.
183 */
184 function get_imagify_attachment_error_text( $process ) {
185 if ( ! $process->is_valid() ) {
186 return '';
187 }
188
189 $data = $process->get_data()->get_optimization_data();
190
191 if ( ! isset( $data['sizes']['full']['success'] ) || $data['sizes']['full']['success'] ) {
192 return '';
193 }
194
195 $class = 'button';
196 $media = $process->get_media();
197 $url = get_imagify_admin_url(
198 'optimize',
199 [
200 'attachment_id' => $media->get_id(),
201 'context' => $media->get_context(),
202 ]
203 );
204
205 if ( ! Imagify_Views::get_instance()->is_media_page() ) {
206 $class .= ' button-imagify-optimize';
207 }
208
209 return Imagify_Views::get_instance()->get_template(
210 'button/retry-optimize',
211 [
212 'url' => $url,
213 'error' => $data['sizes']['full']['error'],
214 'atts' => [
215 'class' => $class,
216 ],
217 ]
218 );
219 }
220
221 /**
222 * Get the re-optimize link for a specific attachment.
223 *
224 * @since 1.0
225 * @since 1.9 Function signature changed.
226 * @author Jonathan Buttigieg
227 *
228 * @param ProcessInterface $process The optimization process object.
229 * @return string The output to print.
230 */
231 function get_imagify_attachment_reoptimize_link( $process ) {
232 if ( ! $process->is_valid() ) {
233 return '';
234 }
235
236 $data = $process->get_data();
237
238 if ( ! $data->get_optimization_status() ) {
239 // Not optimized yet.
240 return '';
241 }
242
243 // Stop the process if the API key isn't valid.
244 if ( ! Imagify_Requirements::is_api_key_valid() ) {
245 return '';
246 }
247
248 $is_already_optimized = $data->is_already_optimized();
249 $media = $process->get_media();
250 $can_reoptimize = $is_already_optimized || $media->has_backup();
251
252 // Don't display anything if there is no backup or the image has been optimized.
253 if ( ! $can_reoptimize ) {
254 return '';
255 }
256
257 $output = '';
258 $views = Imagify_Views::get_instance();
259 $media_level = $data->get_optimization_level();
260 $data = [];
261 $url_args = [
262 'attachment_id' => $media->get_id(),
263 'context' => $media->get_context(),
264 ];
265
266 if ( Imagify_Views::get_instance()->is_media_page() ) {
267 $data['atts'] = [
268 'class' => '',
269 ];
270 }
271
272 if ( $media_level < 1 ) {
273 $url_args['optimization_level'] = 2;
274 $data['optimization_level'] = 2;
275 $data['url'] = get_imagify_admin_url( 'manual-reoptimize', $url_args );
276
277 $output .= $views->get_template( 'button/re-optimize', $data );
278 } elseif ( $media_level > 0 ) {
279 $url_args['optimization_level'] = 0;
280 $data['optimization_level'] = 0;
281 $data['url'] = get_imagify_admin_url( 'manual-reoptimize', $url_args );
282
283 $output .= $views->get_template( 'button/re-optimize', $data );
284 }
285
286 return $output;
287 }
288
289 /**
290 * Get the link to optimize missing thumbnail sizes for a specific attachment.
291 *
292 * @since 1.6.10
293 * @since 1.9 Function signature changed.
294 * @author Grégory Viguier
295 *
296 * @param ProcessInterface $process The optimization process object.
297 * @return string The output to print.
298 */
299 function get_imagify_attachment_optimize_missing_thumbnails_link( $process ) {
300 if ( ! $process->is_valid() ) {
301 return '';
302 }
303
304 $media = $process->get_media();
305
306 if ( ! $media->is_image() || ! Imagify_Requirements::is_api_key_valid() || ! $media->has_backup() ) {
307 return '';
308 }
309
310 $context = $media->get_context();
311
312 /**
313 * Allow to not display the "Optimize missing thumbnails" link.
314 *
315 * @since 1.6.10
316 * @since 1.9 The $attachment object is replaced by a $process object.
317 * @author Grégory Viguier
318 *
319 * @param bool $display True to display the link. False to not display it.
320 * @param ProcessInterface $process The optimization process object.
321 * @param string $context The context.
322 */
323 $display = apply_filters( 'imagify_display_missing_thumbnails_link', true, $process, $context );
324
325 // Stop the process if the filter is false.
326 if ( ! $display ) {
327 return '';
328 }
329
330 $missing_sizes = $process->get_missing_sizes();
331
332 if ( ! $missing_sizes || is_wp_error( $missing_sizes ) ) {
333 return '';
334 }
335
336 $url = get_imagify_admin_url(
337 'optimize-missing-sizes',
338 [
339 'attachment_id' => $media->get_id(),
340 'context' => $context,
341 ]
342 );
343
344 return Imagify_Views::get_instance()->get_template(
345 'button/optimize-missing-sizes',
346 [
347 'url' => $url,
348 'count' => count( $missing_sizes ),
349 ]
350 );
351 }
352
353 /**
354 * Get the link to generate next-gen versions if they are missing.
355 *
356 * @since 1.9
357 *
358 * @param ProcessInterface $process The optimization process object.
359 *
360 * @return string The output to print.
361 */
362 function get_imagify_attachment_generate_nextgen_versions_link( $process ) {
363 if ( ! $process->is_valid() ) {
364 return '';
365 }
366
367 $formats = imagify_nextgen_images_formats();
368
369 if ( empty( $formats ) ) {
370 return '';
371 }
372
373 $media = $process->get_media();
374
375 if ( ! $media->is_image() || ! Imagify_Requirements::is_api_key_valid() || ! $media->has_backup() ) {
376 return '';
377 }
378
379 $format = get_imagify_option( 'optimization_format' );
380
381 if (
382 'avif' === $format
383 &&
384 'image/avif' === $media->get_mime_type()
385 ) {
386 return '';
387 } elseif ( 'image/webp' === $media->get_mime_type() ) {
388 return '';
389 }
390
391 $data = $process->get_data();
392
393 if ( ! $data->is_optimized() && ! $data->is_already_optimized() ) {
394 return '';
395 }
396
397 if ( $process->has_next_gen() ) {
398 return '';
399 }
400
401 $context = $media->get_context();
402
403 $display = apply_filters_deprecated( 'imagify_display_generate_webp_versions_link', [ true, $process, $context ], '2.2', 'imagify_display_generate_next_gen_versions_link' );
404
405 /**
406 * Allow to not display the "Generate next-gen versions" link.
407 *
408 * @since 1.9
409 * @author Grégory Viguier
410 *
411 * @param bool $display True to display the link. False to not display it.
412 * @param ProcessInterface $process The optimization process object.
413 * @param string $context The context.
414 */
415 $display = apply_filters( 'imagify_display_generate_next_gen_versions_link', $display, $process, $context );
416
417 // Stop the process if the filter is false.
418 if ( ! $display ) {
419 return '';
420 }
421
422 $url = get_imagify_admin_url(
423 'generate-nextgen-versions',
424 [
425 'attachment_id' => $media->get_id(),
426 'context' => $context,
427 ]
428 );
429
430 $output = Imagify_Views::get_instance()->get_template(
431 'button/generate-webp',
432 [
433 'url' => $url,
434 ]
435 );
436
437 return $output . '<br/>';
438 }
439
440 /**
441 * Get the link to delete next-gen versions when the status is "already_optimized".
442 *
443 * @since 1.9.6
444 * @author Grégory Viguier
445 *
446 * @param ProcessInterface $process The optimization process object.
447 * @return string The output to print.
448 */
449 function get_imagify_attachment_delete_nextgen_versions_link( $process ) {
450 if ( ! $process->is_valid() ) {
451 return '';
452 }
453
454 $media = $process->get_media();
455 $context = $media->get_context();
456 $media_id = $media->get_id();
457
458 if ( ! imagify_get_context( $context )->current_user_can( 'manual-restore', $media_id ) ) {
459 imagify_die();
460 }
461
462 $data = $process->get_data();
463
464 if ( ! $data->is_already_optimized() || ! $process->has_next_gen() ) {
465 return '';
466 }
467
468 $class = '';
469 $url = get_imagify_admin_url(
470 'delete-nextgen-versions',
471 [
472 'attachment_id' => $media_id,
473 'context' => $context,
474 ]
475 );
476
477 if ( ! Imagify_Views::get_instance()->is_media_page() ) {
478 $class .= 'button-imagify-delete-webp';
479 }
480
481 return Imagify_Views::get_instance()->get_template(
482 'button/delete-webp',
483 [
484 'url' => $url,
485 'atts' => [
486 'class' => $class,
487 ],
488 ]
489 );
490 }
491
492 /**
493 * Get all data to diplay for a specific media.
494 *
495 * @since 1.2
496 * @since 1.9 Function signature changed.
497 * @author Jonathan Buttigieg
498 *
499 * @param \Imagify\Optimization\Process\ProcessInterface $process The optimization process object.
500 * @param bool $with_container Set to false to not return the HTML container.
501 *
502 * @return string The output to print.
503 */
504 function get_imagify_media_column_content( $process, $with_container = true ) {
505 if ( ! $process->is_valid() ) {
506 return __( 'This media is not valid.', 'imagify' );
507 }
508
509 if ( ! $process->current_user_can( 'manual-optimize' ) ) {
510 return __( 'You are not allowed to optimize this file.', 'imagify' );
511 }
512
513 $media = $process->get_media();
514
515 // Check if the media is supported.
516 if ( ! $media->is_supported() ) {
517 return __( 'This media is not supported.', 'imagify' );
518 }
519
520 // Check if the media has the required WP data.
521 if ( ! $media->has_required_media_data() ) {
522 return __( 'This media lacks the required metadata and cannot be optimized.', 'imagify' );
523 }
524
525 $data = $process->get_data();
526
527 // Check if the API key is valid.
528 if ( ! Imagify_Requirements::is_api_key_valid() && ! $data->is_optimized() ) {
529 $output = __( 'Invalid API key', 'imagify' );
530 $output .= '<br/>';
531 $output .= '<a href="' . esc_url( get_imagify_admin_url() ) . '">' . __( 'Check your Settings', 'imagify' ) . '</a>';
532 return $output;
533 }
534
535 $media_id = $media->get_id();
536 $context = $media->get_context();
537 $views = Imagify_Views::get_instance();
538 $is_locked = $process->is_locked();
539
540 if ( $is_locked ) {
541 switch ( $is_locked ) {
542 case 'optimizing':
543 $lock_label = __( 'Optimizing...', 'imagify' );
544 break;
545 case 'restoring':
546 $lock_label = __( 'Restoring...', 'imagify' );
547 break;
548 default:
549 $lock_label = __( 'Processing...', 'imagify' );
550 }
551
552 if ( ! $with_container ) {
553 return $views->get_template(
554 'button/processing',
555 [ 'label' => $lock_label ]
556 );
557 }
558
559 return $views->get_template(
560 'container/data-actions',
561 [
562 'media_id' => $media_id,
563 'context' => $context,
564 'content' => $views->get_template( 'button/processing', [ 'label' => $lock_label ] ),
565 ]
566 );
567 }
568
569 // Check if the image was optimized.
570 if ( ! $data->get_optimization_status() ) {
571 $output = Imagify_Views::get_instance()->get_template(
572 'button/optimize',
573 [
574 'url' => get_imagify_admin_url(
575 'manual-optimize',
576 [
577 'attachment_id' => $media_id,
578 'context' => $context,
579 ]
580 ),
581 ]
582 );
583
584 if ( $media->has_backup() ) {
585 $output .= '<span class="attachment-has-backup hidden"></span>';
586 }
587 } else {
588 $output = get_imagify_attachment_optimization_text( $process );
589 }
590
591 if ( ! $with_container ) {
592 return $output;
593 }
594
595 return $views->get_template(
596 'container/data-actions',
597 [
598 'media_id' => $media_id,
599 'context' => $context,
600 'content' => $output,
601 ]
602 );
603 }
604