PluginProbe
Squeeze – Image Optimization & Compression, WEBP Conversion / trunk
Squeeze – Image Optimization & Compression, WEBP Conversion vtrunk
1.7.15 1.7.14 1.7.13 1.7.12 1.7.11 1.7.10 trunk 1.0 1.1 1.2 1.3 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5 1.5.1 1.5.2 1.6 All 42 releases
squeeze / inc / settings.php

settings.php in Squeeze – Image Optimization & Compression, WEBP Conversion trunk, at inc/settings.php

2,082 lines 102.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace SqueezeFree;
4
5 // Exit if accessed directly.
6 if ( !defined( 'ABSPATH' ) ) {
7 exit;
8 }
9 class SqueezeSettings extends SqueezeInit {
10 public function __construct() {
11 add_action( 'admin_menu', [$this, 'options_page'] );
12 add_action( 'admin_menu', [$this, 'options_bulk_page'] );
13 add_action( 'admin_init', [$this, 'register_settings'] );
14 add_action(
15 'update_option_squeeze_options',
16 [$this, 'restore_defaults'],
17 10,
18 2
19 );
20 add_action(
21 'update_option_squeeze_options',
22 [$this, 'flush_rewrite_rules'],
23 10,
24 2
25 );
26 add_filter(
27 'attachment_fields_to_edit',
28 [$this, 'add_custom_field_to_attachment'],
29 10,
30 2
31 );
32 add_filter( 'manage_media_columns', [$this, 'add_media_columns'] );
33 add_action(
34 'manage_media_custom_column',
35 [$this, 'media_custom_column'],
36 10,
37 2
38 );
39 add_filter( 'manage_upload_sortable_columns', [$this, 'sortable_columns'] );
40 add_action( 'pre_get_posts', [$this, 'sortable_columns_orderby'] );
41 add_action( 'restrict_manage_posts', [$this, 'media_filter_dropdown'] );
42 add_action( 'pre_get_posts', [$this, 'media_filter_query'] );
43 add_filter(
44 'ajax_query_attachments_args',
45 [$this, 'media_filter_ajax_query'],
46 10,
47 1
48 );
49 add_filter(
50 'posts_results',
51 [$this, 'media_filter_exclude_excluded'],
52 10,
53 2
54 );
55 add_action(
56 'update_option_squeeze_options',
57 [$this, 'handle_excluded_images_option_change'],
58 10,
59 2
60 );
61 add_action( 'admin_footer', [$this, 'svg_sprite_output'] );
62 add_action( 'admin_notices', [$this, 'incompatibility_notices'] );
63 add_action( 'load-settings_page_squeeze', [$this, 'maybe_mod_rewrite_notice'] );
64 add_action( 'edit_form_after_title', [$this, 'add_preview_button_placeholder'], 10 );
65 }
66
67 public function options_page() {
68 add_submenu_page(
69 'options-general.php',
70 __( 'Squeeze Settings', 'squeeze' ),
71 __( 'Squeeze', 'squeeze' ),
72 'manage_options',
73 'squeeze',
74 [$this, 'options_page_html']
75 );
76 }
77
78 public function options_bulk_page() {
79 add_submenu_page(
80 'upload.php',
81 __( 'Bulk / Directory Squeeze', 'squeeze' ),
82 __( 'Bulk / Directory Squeeze', 'squeeze' ),
83 'manage_options',
84 'squeeze-bulk',
85 [$this, 'options_bulk_page_html']
86 );
87 }
88
89 public function options_bulk_page_html() {
90 // check user capabilities
91 if ( !current_user_can( 'manage_options' ) ) {
92 return;
93 }
94 $is_single_page_squeeze = false;
95 $uncompressed_count = self::$SqueezeHelpers->get_uncompressed_images_count();
96 $uncompressed_pages = ceil( $uncompressed_count / self::$MEDIA_PER_PAGE );
97 $total_count = self::$SqueezeHelpers->get_total_images_count();
98 $total_pages = ceil( $total_count / self::$MEDIA_PER_PAGE );
99 $compressed_count = $total_count - $uncompressed_count;
100 $compressed_percentage = ( $total_count > 0 ? round( $compressed_count / $total_count * 100, 2 ) : 0 );
101 //$total_count = array_sum((array)wp_count_attachments("image"));
102 $not_compressed_posts = implode( ",", self::$SqueezeHelpers->get_uncompressed_images() );
103 $all_posts = implode( ",", self::$SqueezeHelpers->get_total_images() );
104 $directory_path = ( get_transient( 'squeeze_bulk_path' ) ? get_transient( 'squeeze_bulk_path' ) : array('/wp-content/uploads/') );
105 $directory_path = array_map( array(self::$SqueezeHelpers, 'normalize_bulk_directory_storage_path'), (array) $directory_path );
106 $directory_path_json = wp_json_encode( $directory_path );
107 $is_direct_webp = self::$SqueezeHelpers->get_option( 'direct_webp' );
108 ?>
109 <div class="wrap">
110 <h1>
111 <?php
112 echo esc_html( get_admin_page_title() );
113 ?>
114 </h1>
115 <?php
116 if ( !$is_single_page_squeeze ) {
117 ?>
118 <p class="squeeze-bulk-lede description">
119 <?php
120 esc_html_e( 'Compress and convert images in bulk. "Squeeze" means optimize file size (and optionally change format) for items in your Media Library or a folder you choose.', 'squeeze' );
121 ?>
122 </p>
123 <?php
124 }
125 ?>
126 <section class="squeeze-box">
127 <div class="squeeze-box-bulk-stack">
128 <?php
129 if ( !$is_single_page_squeeze ) {
130 ?>
131 <div class="squeeze-box-bulk-workflows">
132 <section id="squeeze-bulk-section-library" class="squeeze-bulk-section squeeze-bulk-section--library" aria-labelledby="squeeze-heading-library">
133 <header class="squeeze-bulk-section__head">
134 <h2 id="squeeze-heading-library"><?php
135 esc_html_e( 'Bulk Media Library Squeeze', 'squeeze' );
136 ?></h2>
137 <p class="squeeze-bulk-section__meta"><?php
138 esc_html_e( 'Uses attachments in the library; backups follow your plugin settings.', 'squeeze' );
139 ?></p>
140 </header>
141 <div class="squeeze-bulk-section__body">
142 <?php
143 if ( $is_direct_webp ) {
144 ?>
145 <div class="squeeze-banner squeeze-banner--notice">
146 <svg class="squeeze-icon" aria-hidden="true">
147 <use xlink:href="#info-icon"></use>
148 </svg>
149 <div class="squeeze-banner__content">
150 <p class="squeeze-banner__title"><?php
151 printf( __( 'Direct WebP conversion is on <a href="%s" target="_blank">(change)</a>', 'squeeze' ), esc_url( admin_url( 'options-general.php?page=squeeze#squeeze_basic' ) ) );
152 ?></p>
153 <p><?php
154 esc_html_e( 'After conversion, image URLs may change. Check themes and content for hard-coded .jpg / .png links (image blocks, custom HTML, CSS, or shortcodes) so nothing breaks.', 'squeeze' );
155 ?></p>
156 </div>
157 </div>
158 <?php
159 }
160 ?>
161
162 <div class="squeeze-bulk-media-stats squeeze-bulk-media-stats--linear" style="--squeeze-progress-pct: <?php
163 echo esc_attr( $compressed_percentage );
164 ?>;">
165 <div class="squeeze-bulk-media-stats-linear-head">
166 <div class="squeeze-bulk-media-stats-chart-value squeeze-bulk-media-stats-chart-value--linear">
167 <span class="squeeze-bulk-media-stats-chart-pct"><?php
168 echo esc_html( $compressed_percentage );
169 ?>%</span>
170 <span class="squeeze-bulk-media-stats-chart-pct-label"><?php
171 esc_html_e( 'complete', 'squeeze' );
172 ?></span>
173 </div>
174 <div class="squeeze-bulk-media-stats-item squeeze-bulk-media-stats-item--inline">
175 <span class="squeeze-bulk-media-stats-item-label"><?php
176 esc_html_e( 'Squeezed images', 'squeeze' );
177 ?></span>
178 <span class="squeeze-bulk-media-stats-item-value"><?php
179 echo esc_html( $compressed_count );
180 ?> / <?php
181 echo esc_html( $total_count );
182 ?></span>
183 </div>
184 </div>
185 <div class="squeeze-bulk-media-stats-chart squeeze-bulk-media-stats-chart--linear" aria-hidden="true">
186 <div class="squeeze-bulk-media-stats-chart-track">
187 <div class="squeeze-bulk-media-stats-chart-fill"></div>
188 </div>
189 </div>
190 <div class="squeeze-bulk-media-stats-legend">
191 <span class="squeeze-bulk-media-stats-legend-item">
192 <span class="squeeze-bulk-media-stats-legend-swatch squeeze-bulk-media-stats-legend-swatch--done" aria-hidden="true"></span>
193 <?php
194 esc_html_e( 'Processed (success)', 'squeeze' );
195 ?>
196 </span>
197 <span class="squeeze-bulk-media-stats-legend-item">
198 <span class="squeeze-bulk-media-stats-legend-swatch squeeze-bulk-media-stats-legend-swatch--rest" aria-hidden="true"></span>
199 <?php
200 esc_html_e( 'Remaining or needs attention', 'squeeze' );
201 ?>
202 </span>
203 </div>
204 </div>
205 </div>
206 <div id="squeeze-bulk-paused-banner" class="squeeze-banner squeeze-banner--notice squeeze-bulk-paused-banner" hidden aria-live="polite">
207 <svg class="squeeze-icon" aria-hidden="true">
208 <use xlink:href="#pause-button-icon"></use>
209 </svg>
210 <div class="squeeze-banner__content">
211 <p class="squeeze-banner__title"><?php
212 esc_html_e( 'Bulk squeezing paused', 'squeeze' );
213 ?></p>
214 <p id="squeeze-bulk-paused-banner-text"></p>
215 </div>
216 </div>
217 <div class="squeeze-bulk-section__actions squeeze-bulk-media-actions">
218 <div class="squeeze-bulk-media-actions__item">
219 <button name="squeeze_bulk" class="button button-primary button-hero" type="button" title="<?php
220 esc_attr_e( 'Compress only images that have not been squeezed yet. Click again while running to pause.', 'squeeze' );
221 ?>" <?php
222 echo ( $uncompressed_count === 0 ? 'hidden disabled data-default-hidden="true"' : '' );
223 ?>>
224 <svg class="squeeze-icon" aria-hidden="true">
225 <use xlink:href="#play-button-round-icon"></use>
226 </svg>
227 <?php
228 esc_html_e( 'Squeeze new images', 'squeeze' );
229 ?>
230 </button>
231 <p class="squeeze-bulk-field-hint squeeze-bulk-field-hint--tight"><?php
232 esc_html_e( 'Compress only images that have not been squeezed yet. Click again while running to pause.', 'squeeze' );
233 ?></p>
234 </div>
235 <div class="squeeze-bulk-media-actions__item">
236 <button name="squeeze_bulk_again" class="button button-secondary button-large" type="button" title="<?php
237 esc_attr_e( 'Run compression again on every library image, including ones already squeezed. Use after changing quality or WebP settings.', 'squeeze' );
238 ?>">
239 <svg class="squeeze-icon" aria-hidden="true">
240 <use xlink:href="#repeat-icon"></use>
241 </svg>
242 <?php
243 esc_html_e( 'Re-squeeze all images', 'squeeze' );
244 ?>
245 </button>
246 <p class="squeeze-bulk-field-hint squeeze-bulk-field-hint--tight"><?php
247 esc_html_e( 'Run compression again on every library image, including ones already squeezed. Use after changing quality or WebP settings.', 'squeeze' );
248 ?></p>
249 </div>
250 </div>
251 </section>
252
253 <section id="squeeze-bulk-section-directory" class="squeeze-bulk-section squeeze-bulk-section--directory" aria-labelledby="squeeze-heading-directory">
254 <header class="squeeze-bulk-section__head">
255 <h2 id="squeeze-heading-directory"><?php
256 esc_html_e( 'Directory Squeeze', 'squeeze' );
257 ?></h2>
258 <p class="squeeze-bulk-section__meta"><?php
259 esc_html_e( 'Filesystem folder — not limited to Media Library. No automatic backup in this mode.', 'squeeze' );
260 ?></p>
261 </header>
262 <div class="squeeze-bulk-section__body">
263 <div class="squeeze-banner squeeze-banner--warning">
264 <svg class="squeeze-icon" aria-hidden="true">
265 <use xlink:href="#info-icon"></use>
266 </svg>
267 <div class="squeeze-banner__content">
268 <p class="squeeze-banner__title"><?php
269 esc_html_e( 'Back up before you run', 'squeeze' );
270 ?></p>
271 <p><?php
272 esc_html_e( 'Automatic backup from the plugin is not available here. Manually back up the folder or your site before squeezing.', 'squeeze' );
273 ?></p>
274 <ul>
275 <li><?php
276 esc_html_e( 'Use your host snapshot or a backup plugin.', 'squeeze' );
277 ?></li>
278 <li><?php
279 esc_html_e( 'Test on a copy first if you are unsure.', 'squeeze' );
280 ?></li>
281 </ul>
282 </div>
283 </div>
284
285 <input type="hidden" name="squeeze_bulk_path" value="<?php
286 echo esc_attr( $directory_path_json );
287 ?>" />
288
289 <div class="squeeze-bulk-field">
290 <label class="squeeze-bulk-field-label"><?php
291 esc_html_e( 'Directory path', 'squeeze' );
292 ?></label>
293 <p id="squeeze-directory-path-hint" class="squeeze-bulk-field-hint"><?php
294 esc_html_e( 'Relative to site root.', 'squeeze' );
295 ?></p>
296 <div class="squeeze-path-list" aria-describedby="squeeze-directory-path-hint">
297 <?php
298 $squeeze_bulk_path_count = count( $directory_path );
299 foreach ( $directory_path as $path ) {
300 ?>
301 <div class="squeeze-path-list__item">
302 <input name="squeeze-path-list__item[]" type="text" class="squeeze-path-list__input" value="<?php
303 echo esc_attr( $path );
304 ?>" readonly />
305 <?php
306 if ( $squeeze_bulk_path_count > 1 ) {
307 ?>
308 <button name="squeeze_remove_path_button" class="squeeze-path-list__remove button" type="button" title="<?php
309 esc_attr_e( 'Clear the path field', 'squeeze' );
310 ?>">
311 <?php
312 esc_html_e( 'Clear path', 'squeeze' );
313 ?>
314 </button>
315 <?php
316 }
317 ?>
318 </div>
319 <?php
320 }
321 ?>
322 </div>
323 <p class="squeeze-bulk-field-hint squeeze-bulk-field-hint--tight"><?php
324 esc_html_e( 'Clear path only empties the field — it does not delete files on disk.', 'squeeze' );
325 ?></p>
326 </div>
327
328 <div class="squeeze-bulk-section__secondary-actions">
329 <button name="squeeze_select_path_button" class="button button-secondary button-large" type="button">
330 <svg class="squeeze-icon" aria-hidden="true">
331 <use xlink:href="#open-folder-outline-icon"></use>
332 </svg>
333 <?php
334 esc_attr_e( 'Select Directory', 'squeeze' );
335 ?>
336 </button>
337 </div>
338 <dialog id="squeeze-path-dialog">
339 <div class="squeeze-box-header">
340 <h2><?php
341 esc_html_e( "Select Directory for Squeeze", "squeeze" );
342 ?></h2>
343 <button name="squeeze_close_path_dialog_button" class="button button-link" type="button">
344 <svg class="squeeze-icon" aria-hidden="true">
345 <use xlink:href="#close-round-icon"></use>
346 </svg>
347 </button>
348 </div>
349
350 <div id="squeeze-bulk-directory-list">
351 <svg class="squeeze-icon" aria-hidden="true">
352 <use xlink:href="#reload-sync-icon"></use>
353 </svg>
354 <?php
355 esc_html_e( "Loading directories...", "squeeze" );
356 ?>
357 </div>
358
359 <div class="squeeze-box-footer">
360 <button disabled name="squeeze_save_path_button" class="button button-secondary button-large" type="button">
361 <svg class="squeeze-icon" aria-hidden="true">
362 <use xlink:href="#open-folder-outline-icon"></use>
363 </svg>
364 <?php
365 esc_attr_e( 'Select Directory', 'squeeze' );
366 ?>
367 </button>
368 </div>
369 </dialog>
370 </div>
371 <div class="squeeze-bulk-section__actions squeeze-bulk-media-actions">
372 <button name="squeeze_bulk_path_button" class="button button-primary button-hero" type="button">
373 <svg class="squeeze-icon" aria-hidden="true">
374 <use xlink:href="#play-button-round-icon"></use>
375 </svg>
376 <?php
377 esc_attr_e( 'Run Directory Squeeze', 'squeeze' );
378 ?>
379 </button>
380 </div>
381 </section>
382 </div>
383 <?php
384 }
385 ?>
386
387 <?php
388 ?>
389
390
391 <div class="squeeze-box-bulk-stack__footer">
392 <div class="squeeze-box-content">
393 <p class="squeeze-hint">
394 <?php
395 $images_formats = self::$SqueezeHelpers->get_image_formats();
396 $images_formats = implode( ', ', $images_formats );
397 esc_html_e( 'Processed formats:', 'squeeze' );
398 echo esc_html( '&nbsp;' . $images_formats . '. ' );
399 printf( __( 'You can change the image formats for squeezing on the <a href="%s" target="_blank">settings page.</a>', 'squeeze' ), esc_url( admin_url( 'options-general.php?page=squeeze' ) ) );
400 ?>
401 </p>
402 </div>
403 </div>
404
405 </div>
406 </section>
407 <section class="squeeze-box" name="squeeze_bulk_log" id="squeeze_bulk_log" contenteditable="false">
408 <div class="squeeze-log-placeholder">
409 <?php
410 esc_html_e( 'Start Squeezing your images and watch the progress here.', 'squeeze' );
411 ?>
412 </div>
413 <div id="squeeze-log-data"></div>
414 <div id="squeeze-anchor"></div><!-- to force scroll to the bottom -->
415 <input type="hidden" value="<?php
416 echo wp_kses_data( $not_compressed_posts );
417 ?>" name="squeeze_bulk_ids" />
418 <input type="hidden" value="<?php
419 echo wp_kses_data( $all_posts );
420 ?>" name="squeeze_bulk_all_ids" />
421 <input type="hidden" value="<?php
422 echo wp_kses_data( $total_pages );
423 ?>" name="squeeze_bulk_total_pages" />
424 <input type="hidden" value="<?php
425 echo wp_kses_data( $uncompressed_pages );
426 ?>" name="squeeze_bulk_uncompressed_pages" />
427 <input type="hidden" value="<?php
428 echo wp_kses_data( $total_count );
429 ?>" name="squeeze_bulk_total_images" />
430 <input type="hidden" value="<?php
431 echo wp_kses_data( $uncompressed_count );
432 ?>" name="squeeze_bulk_uncompressed_images" />
433 </section>
434 </div>
435 <?php
436 }
437
438 /**
439 * Queue the mod_rewrite warning before options-head.php prints settings errors.
440 */
441 public function maybe_mod_rewrite_notice() {
442 $modules = self::$SqueezeHelpers->apache_get_modules();
443 // Only warn when PHP can list modules and mod_rewrite is missing. null means
444 // undetectable (CGI/FPM) — do not treat that as "mod_rewrite off".
445 if ( is_array( $modules ) && !in_array( 'mod_rewrite', $modules, true ) ) {
446 $is_auto_webp = self::$SqueezeHelpers->get_option( 'auto_webp' );
447 $is_webp_replace_urls = self::$SqueezeHelpers->get_option( 'webp_replace_urls' );
448 if ( $is_auto_webp && !$is_webp_replace_urls ) {
449 add_settings_error(
450 'squeeze_notices',
451 'squeeze_notices',
452 __( 'The Apache mod_rewrite module is not enabled on your server OR your server is not running Apache.', 'squeeze' ) . '<br>' . __( 'To serve WebP, enable mod_rewrite, or switch to "Rewrite <img> src to WebP URLs in HTML" delivery.', 'squeeze' ),
453 'warning'
454 );
455 }
456 }
457 }
458
459 public function options_page_html() {
460 // check user capabilities
461 if ( !current_user_can( 'manage_options' ) ) {
462 return;
463 }
464 ?>
465 <div class="wrap">
466 <h1>
467 <?php
468 echo esc_html( get_admin_page_title() );
469 ?>
470 </h1>
471 <nav class="nav-tab-wrapper">
472 <a href="#squeeze_basic" class="nav-tab nav-tab-active"><?php
473 esc_html_e( 'Basic Settings', 'squeeze' );
474 ?></a>
475 <a href="#squeeze_jpeg" class="nav-tab"><?php
476 esc_html_e( 'JPEG Settings', 'squeeze' );
477 ?></a>
478 <a href="#squeeze_png" class="nav-tab"><?php
479 esc_html_e( 'PNG Settings', 'squeeze' );
480 ?></a>
481 <a href="#squeeze_webp" class="nav-tab"><?php
482 esc_html_e( 'WEBP Settings', 'squeeze' );
483 ?></a>
484 <a href="#squeeze_avif" class="nav-tab"><?php
485 esc_html_e( 'AVIF Settings', 'squeeze' );
486 ?></a>
487 <a href="#squeeze_docs" class="nav-tab"><?php
488 esc_html_e( 'Documentation', 'squeeze' );
489 ?></a>
490 <?php
491 ?>
492 <a href="#squeeze_upgrade" class="nav-tab"><?php
493 esc_html_e( 'Upgrade', 'squeeze' );
494 ?></a>
495 <?php
496 ?>
497 <?php
498 ?>
499 </nav>
500 <div class="tab-content">
501 <form action="options.php" method="post" class="squeeze-settings-form">
502 <?php
503 settings_fields( 'squeeze_options' );
504 //do_settings_sections( 'squeeze_options' );
505 ?>
506
507 <section id="squeeze_basic" class="squeeze-settings-basic">
508 <div class="squeeze-settings-layout">
509 <div class="squeeze-settings-main">
510 <div class="squeeze-card squeeze-card--settings">
511 <div class="squeeze-card-header">
512 <h2 class="squeeze-card-title"><?php
513 esc_html_e( 'Quick start', 'squeeze' );
514 ?></h2>
515 <p class="squeeze-card-desc"><?php
516 esc_html_e( 'Core options used on most sites.', 'squeeze' );
517 ?></p>
518 </div>
519 <table class="form-table squeeze-form-table--card" role="presentation">
520 <?php
521 do_settings_fields( 'squeeze_options', 'squeeze_basic_quick' );
522 ?>
523 </table>
524 </div>
525 <div class="squeeze-card squeeze-card--settings">
526 <div class="squeeze-card-header">
527 <h2 class="squeeze-card-title"><?php
528 esc_html_e( 'WebP delivery', 'squeeze' );
529 ?></h2>
530 <p class="squeeze-card-desc"><?php
531 esc_html_e( 'Choose how WebP files are stored and served. Pick one strategy.', 'squeeze' );
532 ?></p>
533 </div>
534 <div class="squeeze-webp-delivery-fullwidth" role="group" aria-label="<?php
535 esc_attr_e( 'WebP delivery mode', 'squeeze' );
536 ?>">
537 <?php
538 $this->render_webp_delivery_field();
539 ?>
540 </div>
541 <?php
542 ?>
543 </div>
544 <div class="squeeze-card squeeze-card--settings">
545 <div class="squeeze-card-header">
546 <h2 class="squeeze-card-title"><?php
547 esc_html_e( 'Thumbnails & limits', 'squeeze' );
548 ?></h2>
549 <p class="squeeze-card-desc"><?php
550 esc_html_e( 'Which generated sizes to squeeze, resize limits, and timeout.', 'squeeze' );
551 ?></p>
552 </div>
553 <table class="form-table squeeze-form-table--card" role="presentation">
554 <?php
555 do_settings_fields( 'squeeze_options', 'squeeze_basic_thumbs' );
556 ?>
557 <?php
558 do_settings_fields( 'squeeze_options', 'squeeze_basic_limits' );
559 ?>
560 </table>
561 </div>
562 <div class="squeeze-card squeeze-card--settings">
563 <div class="squeeze-card-header">
564 <h2 class="squeeze-card-title"><?php
565 esc_html_e( 'Exclusions', 'squeeze' );
566 ?></h2>
567 <p class="squeeze-card-desc"><?php
568 esc_html_e( 'Skip matching files during bulk or upload squeeze.', 'squeeze' );
569 ?></p>
570 </div>
571 <table class="form-table squeeze-form-table--card" role="presentation">
572 <?php
573 do_settings_fields( 'squeeze_options', 'squeeze_basic_exclusions' );
574 ?>
575 </table>
576 </div>
577 <table class="form-table squeeze-form-table--hidden" role="presentation" aria-hidden="true">
578 <?php
579 do_settings_fields( 'squeeze_options', 'squeeze_basic_hidden' );
580 ?>
581 </table>
582 </div>
583 <aside class="squeeze-settings-sidebar" aria-label="<?php
584 esc_attr_e( 'Summary and help', 'squeeze' );
585 ?>">
586 <?php
587 $this->render_basic_settings_sidebar();
588 ?>
589 </aside>
590 </div>
591 </section>
592 <section id="squeeze_jpeg">
593 <div class="squeeze-box squeeze-box--settings">
594 <div class="squeeze-box-header">
595 <div class="squeeze-box-header__col">
596 <h2><?php
597 esc_html_e( 'JPEG Settings', 'squeeze' );
598 ?></h2>
599 <?php
600 $this->setting_jpeg_desc();
601 ?>
602 </div>
603 </div>
604 <table class="form-table" role="presentation">
605 <?php
606 do_settings_fields( 'squeeze_options', 'squeeze_jpeg_settings' );
607 ?>
608 </table>
609 </div>
610 <div class="squeeze-box">
611 <div class="squeeze-box-header">
612 <div class="squeeze-box-header__col">
613 <h2><?php
614 esc_html_e( 'JPEG Advanced Settings', 'squeeze' );
615 ?></h2>
616 <?php
617 $this->setting_jpeg_advanced_desc();
618 ?>
619 </div>
620 </div>
621 <table class="form-table" role="presentation">
622 <?php
623 do_settings_fields( 'squeeze_options', 'squeeze_jpeg_advanced_settings' );
624 ?>
625 </table>
626 </div>
627 </section>
628 <section id="squeeze_png">
629 <div class="squeeze-box squeeze-box--settings">
630 <div class="squeeze-box-header">
631 <div class="squeeze-box-header__col">
632 <h2><?php
633 esc_html_e( 'PNG Settings', 'squeeze' );
634 ?></h2>
635 <?php
636 $this->setting_png_desc();
637 ?>
638 </div>
639 </div>
640 <table class="form-table" role="presentation">
641 <?php
642 do_settings_fields( 'squeeze_options', 'squeeze_png_settings' );
643 ?>
644 </table>
645 </div>
646 </section>
647 <section id="squeeze_webp">
648 <div class="squeeze-box squeeze-box--settings">
649 <div class="squeeze-box-header">
650 <div class="squeeze-box-header__col">
651 <h2><?php
652 esc_html_e( 'WEBP Settings', 'squeeze' );
653 ?></h2>
654 <?php
655 $this->setting_webp_desc();
656 ?>
657 </div>
658 </div>
659 <table class="form-table" role="presentation">
660 <?php
661 do_settings_fields( 'squeeze_options', 'squeeze_webp_settings' );
662 ?>
663 </table>
664 </div>
665 </section>
666 <section id="squeeze_avif">
667 <div class="squeeze-box squeeze-box--settings">
668 <div class="squeeze-box-header">
669 <div class="squeeze-box-header__col">
670 <h2><?php
671 esc_html_e( 'AVIF Settings', 'squeeze' );
672 ?></h2>
673 <?php
674 $this->setting_avif_desc();
675 ?>
676 </div>
677 </div>
678 <table class="form-table" role="presentation">
679 <?php
680 do_settings_fields( 'squeeze_options', 'squeeze_avif_settings' );
681 ?>
682 </table>
683 </div>
684 </section>
685 <section id="squeeze_docs">
686 <div class="squeeze-box squeeze-box--settings">
687 <div class="squeeze-box-header">
688 <div class="squeeze-box-header__col">
689 <h2><?php
690 esc_html_e( 'Documentation', 'squeeze' );
691 ?></h2>
692 <?php
693 echo '<p>' . esc_html__( 'Documentation for Squeeze plugin.', 'squeeze' ) . '</p>';
694 ?>
695 </div>
696 </div>
697 <table class="form-table" role="presentation">
698 <tbody>
699 <tr>
700 <th scope="row" colspan="2">
701 <?php
702 echo '<p>' . sprintf( __( 'For more information, please visit the <a href="%s" target="_blank">official documentation website</a>.', 'squeeze' ) . '&nbsp;↗', esc_url( self::$DOCS_URL ) ) . '</p>';
703 ?>
704 </th>
705 </tr>
706 </tbody>
707 </table>
708 </div>
709 </section>
710 <?php
711 ?>
712 <section id="squeeze_upgrade">
713 <div class="squeeze-box squeeze-box--settings">
714 <div class="squeeze-box-header">
715 <div class="squeeze-box-header__col">
716 <h2><?php
717 esc_html_e( 'Upgrade', 'squeeze' );
718 ?></h2>
719 <?php
720 $this->setting_upgrade_desc();
721 ?>
722 </div>
723 </div>
724 <div class="squeeze-upgrade-features">
725 <?php
726 $features = [['icon-compare.svg', __( 'Image Comparison', 'squeeze' ), __( 'Compare original and Squeezed image directly in the Media Library.', 'squeeze' )], ['icon-resize.svg', __( 'Resize Original Image', 'squeeze' ), __( 'Set maximum width and height for the original image.', 'squeeze' )], ['icon-bulk-page.svg', __( 'Bulk Squeeze from a Page', 'squeeze' ), __( 'Compress all images from a specific page.', 'squeeze' )]];
727 foreach ( $features as $feature ) {
728 ?>
729 <div class="squeeze-box--fieldset">
730 <img src="<?php
731 echo esc_url( self::$PLUGIN_URL . 'assets/images/' . $feature[0] );
732 ?>" alt="<?php
733 echo esc_attr( $feature[1] );
734 ?>" />
735 <h3><?php
736 echo esc_html( $feature[1] );
737 ?></h3>
738 <p><?php
739 echo esc_html( $feature[2] );
740 ?></p>
741 </div>
742 <?php
743 }
744 ?>
745 </div>
746 <div class="squeeze-box-footer">
747 <h3 style="text-align: center;">
748 <?php
749 echo sprintf( __( 'To upgrade to the Premium version, <a href="%s" target="_blank">click here</a>.', 'squeeze' ), esc_url( self::CHECKOUT_URL ) );
750 ?>&nbsp;
751 </h3>
752 </div>
753 </div>
754 </section>
755 <?php
756 ?>
757
758 <?php
759 ?>
760
761 <p class="submit squeeze-settings-submit">
762 <input type="submit" name="submit" id="submit" class="button button-primary" value="<?php
763 esc_attr_e( 'Save Changes', 'squeeze' );
764 ?>">
765 <input name="squeeze_restore_button" class="button button-secondary" type="button" value="<?php
766 esc_attr_e( 'Restore defaults', 'squeeze' );
767 ?>" />
768 </p>
769 </form>
770 </div>
771 </div>
772 <?php
773 }
774
775 public function register_settings() {
776 $auto_webp = self::$SqueezeHelpers->get_option( 'auto_webp' );
777 $webp_lossless = self::$SqueezeHelpers->get_option( 'webp_lossless' );
778 register_setting( 'squeeze_options', 'squeeze_options', [$this, 'options_validate'] );
779 add_settings_section(
780 'squeeze_basic_quick',
781 '',
782 '__return_false',
783 'squeeze_options'
784 );
785 add_settings_field(
786 'squeeze_setting_auto_compress',
787 __( 'Squeeze on upload', 'squeeze' ) . self::$SqueezeHelpers->get_hint( __( 'Compresses images in the browser before they are uploaded.', 'squeeze' ) ),
788 [$this, 'options_callback'],
789 'squeeze_options',
790 'squeeze_basic_quick',
791 array(
792 'label_for' => 'auto_compress',
793 'class' => 'squeeze_setting_auto_compress squeeze-settings-row',
794 'type' => 'checkbox',
795 )
796 );
797 add_settings_field(
798 'squeeze_setting_backup_original',
799 __( 'Backup original image', 'squeeze' ),
800 [$this, 'options_callback'],
801 'squeeze_options',
802 'squeeze_basic_quick',
803 array(
804 'label_for' => 'backup_original',
805 'class' => 'squeeze_setting_backup_original squeeze-settings-row',
806 'type' => 'checkbox',
807 )
808 );
809 add_settings_field(
810 'squeeze_setting_clear_data_on_uninstall',
811 __( 'Delete plugin data on uninstall', 'squeeze' ) . self::$SqueezeHelpers->get_hint( __( 'When enabled, uninstalling Squeeze removes its settings, stats, and compression status metadata. Image files are never deleted.', 'squeeze' ) ),
812 [$this, 'options_callback'],
813 'squeeze_options',
814 'squeeze_basic_quick',
815 array(
816 'label_for' => 'clear_data_on_uninstall',
817 'class' => 'squeeze_setting_clear_data_on_uninstall squeeze-settings-row',
818 'type' => 'checkbox',
819 )
820 );
821 add_settings_field(
822 'squeeze_setting_compress_formats',
823 __( 'Image formats', 'squeeze' ) . self::$SqueezeHelpers->get_hint( __( 'Select which image formats you want to be squeezed.', 'squeeze' ) ),
824 [$this, 'options_callback'],
825 'squeeze_options',
826 'squeeze_basic_quick',
827 array(
828 'label_for' => 'compress_formats',
829 'class' => 'squeeze_setting_compress_formats squeeze-settings-row',
830 'type' => 'formats_checkbox_group',
831 )
832 );
833 add_settings_section(
834 'squeeze_basic_webp',
835 '',
836 '__return_false',
837 'squeeze_options'
838 );
839 add_settings_section(
840 'squeeze_basic_thumbs',
841 '',
842 '__return_false',
843 'squeeze_options'
844 );
845 add_settings_field(
846 'squeeze_setting_compress_thumbs',
847 __( 'Squeeze thumbnails', 'squeeze' ) . self::$SqueezeHelpers->get_hint( __( 'Choose which image thumbnail sizes you want to squeeze along with the original image.', 'squeeze' ) ),
848 [$this, 'options_callback'],
849 'squeeze_options',
850 'squeeze_basic_thumbs',
851 array(
852 'label_for' => 'compress_thumbs',
853 'class' => 'squeeze_setting_compress_thumbs squeeze-settings-row',
854 'type' => 'thumbs_checkbox_group',
855 )
856 );
857 add_settings_section(
858 'squeeze_basic_limits',
859 '',
860 '__return_false',
861 'squeeze_options'
862 );
863 add_settings_field(
864 'squeeze_setting_max_width',
865 __( 'Max. image width', 'squeeze' ) . self::$SqueezeHelpers->get_hint( __( 'Limit a width of an original image. Leave this field empty if you do not want to crop the image by width.', 'squeeze' ) ),
866 [$this, 'options_callback'],
867 'squeeze_options',
868 'squeeze_basic_limits',
869 array(
870 'label_for' => 'max_width',
871 'class' => 'squeeze_setting_max_width squeeze-settings-row',
872 'type' => 'placeholder',
873 )
874 );
875 add_settings_field(
876 'squeeze_setting_max_height',
877 __( 'Max. image height', 'squeeze' ) . self::$SqueezeHelpers->get_hint( __( 'Limit a height of an original image. Leave this field empty if you do not want to crop the image by height.', 'squeeze' ) ),
878 [$this, 'options_callback'],
879 'squeeze_options',
880 'squeeze_basic_limits',
881 array(
882 'label_for' => 'max_height',
883 'class' => 'squeeze_setting_max_height squeeze-settings-row',
884 'type' => 'placeholder',
885 )
886 );
887 add_settings_field(
888 'squeeze_setting_timeout',
889 __( 'Squeeze timeout', 'squeeze' ) . self::$SqueezeHelpers->get_hint( __( 'Time limit for squeezing an image. If you get an error during image squeezing, try to increase this value.', 'squeeze' ) ),
890 [$this, 'options_callback'],
891 'squeeze_options',
892 'squeeze_basic_limits',
893 array(
894 'label_for' => 'timeout',
895 'class' => 'squeeze_setting_timeout squeeze-settings-row squeeze-inline-limit',
896 'type' => 'number',
897 'units' => 'sec',
898 'min' => 1,
899 )
900 );
901 add_settings_section(
902 'squeeze_basic_exclusions',
903 '',
904 '__return_false',
905 'squeeze_options'
906 );
907 add_settings_field(
908 'squeeze_setting_excluded_images',
909 __( 'Excluded images', 'squeeze' ) . self::$SqueezeHelpers->get_hint( __( 'Enter a list of images that you want to exclude from squeezing. Both full URLs and partial strings can be used. One URL per line.', 'squeeze' ) ),
910 [$this, 'options_callback'],
911 'squeeze_options',
912 'squeeze_basic_exclusions',
913 array(
914 'label_for' => 'excluded_images',
915 'class' => 'squeeze_setting_excluded_images squeeze-settings-row',
916 'type' => 'textarea',
917 )
918 );
919 add_settings_section(
920 'squeeze_basic_hidden',
921 '',
922 '__return_false',
923 'squeeze_options'
924 );
925 add_settings_field(
926 'squeeze_setting_restore_defaults',
927 '',
928 [$this, 'options_callback'],
929 'squeeze_options',
930 'squeeze_basic_hidden',
931 array(
932 'label_for' => 'restore_defaults',
933 'class' => 'squeeze_setting_restore_defaults',
934 'type' => 'hidden',
935 )
936 );
937 add_settings_section(
938 'squeeze_jpeg_settings',
939 __( 'JPEG Settings', 'squeeze' ),
940 'squeeze_setting_jpeg_desc',
941 'squeeze_options',
942 array(
943 'section_class' => 'squeeze_jpeg',
944 )
945 );
946 add_settings_field(
947 'squeeze_setting_jpeg_quality',
948 __( 'Quality', 'squeeze' ),
949 [$this, 'options_callback'],
950 'squeeze_options',
951 'squeeze_jpeg_settings',
952 array(
953 'label_for' => 'jpeg_quality',
954 'class' => 'squeeze_setting_jpeg_quality',
955 'type' => 'range',
956 )
957 );
958 add_settings_field(
959 'squeeze_setting_jpeg_smoothing',
960 __( 'Smoothing', 'squeeze' ),
961 [$this, 'options_callback'],
962 'squeeze_options',
963 'squeeze_jpeg_settings',
964 array(
965 'label_for' => 'jpeg_smoothing',
966 'class' => 'squeeze_setting_jpeg_smoothing',
967 'type' => 'range',
968 )
969 );
970 add_settings_field(
971 'squeeze_setting_jpeg_baseline',
972 __( 'Pointless spec compliance', 'squeeze' ),
973 [$this, 'options_callback'],
974 'squeeze_options',
975 'squeeze_jpeg_advanced_settings',
976 array(
977 'label_for' => 'jpeg_baseline',
978 'class' => 'squeeze_setting_jpeg_baseline',
979 'type' => 'checkbox',
980 )
981 );
982 // deactivated, because throws error when enabled
983 //add_settings_field('squeeze_setting_jpeg_arithmetic', __('Arithmetic', 'squeeze'), [$this, 'options_callback'], 'squeeze_options', 'squeeze_jpeg_advanced_settings', array('label_for' => 'jpeg_arithmetic', 'class' => 'squeeze_setting_jpeg_arithmetic', 'type' => 'checkbox'));
984 add_settings_field(
985 'squeeze_setting_jpeg_progressive',
986 __( 'Progressive rendering', 'squeeze' ),
987 [$this, 'options_callback'],
988 'squeeze_options',
989 'squeeze_jpeg_advanced_settings',
990 array(
991 'label_for' => 'jpeg_progressive',
992 'class' => 'squeeze_setting_jpeg_progressive',
993 'type' => 'checkbox',
994 )
995 );
996 add_settings_field(
997 'squeeze_setting_jpeg_optimize_coding',
998 __( 'Optimize Huffman table', 'squeeze' ),
999 [$this, 'options_callback'],
1000 'squeeze_options',
1001 'squeeze_jpeg_advanced_settings',
1002 array(
1003 'label_for' => 'jpeg_optimize_coding',
1004 'class' => 'squeeze_setting_jpeg_optimize_coding',
1005 'type' => 'checkbox',
1006 )
1007 );
1008 add_settings_field(
1009 'squeeze_setting_jpeg_color_space',
1010 __( 'Channels', 'squeeze' ),
1011 [$this, 'options_callback'],
1012 'squeeze_options',
1013 'squeeze_jpeg_advanced_settings',
1014 array(
1015 'label_for' => 'jpeg_color_space',
1016 'class' => 'squeeze_setting_jpeg_color_space',
1017 'type' => 'select',
1018 'options' => array(
1019 '3' => 'YCbCr',
1020 '1' => 'Grayscale',
1021 '2' => 'RGB',
1022 ),
1023 )
1024 );
1025 add_settings_field(
1026 'squeeze_setting_jpeg_quant_table',
1027 __( 'Quantization', 'squeeze' ),
1028 [$this, 'options_callback'],
1029 'squeeze_options',
1030 'squeeze_jpeg_advanced_settings',
1031 array(
1032 'label_for' => 'jpeg_quant_table',
1033 'class' => 'squeeze_setting_jpeg_quant_table',
1034 'type' => 'select',
1035 'options' => array(
1036 '0' => 'JPEG Annex K',
1037 '1' => 'Flat',
1038 '2' => 'MSSIM-tuned Kodak',
1039 '3' => 'ImageMagick',
1040 '4' => 'PSNR-HVS-M-tuned Kodak',
1041 '5' => 'Klein et al',
1042 '6' => 'Watson et al',
1043 '7' => 'Ahumada et al',
1044 '8' => 'Peterson et al',
1045 ),
1046 )
1047 );
1048 add_settings_field(
1049 'squeeze_setting_jpeg_trellis_multipass',
1050 __( 'Trellis multipass', 'squeeze' ),
1051 [$this, 'options_callback'],
1052 'squeeze_options',
1053 'squeeze_jpeg_advanced_settings',
1054 array(
1055 'label_for' => 'jpeg_trellis_multipass',
1056 'class' => 'squeeze_setting_jpeg_trellis_multipass',
1057 'type' => 'checkbox',
1058 )
1059 );
1060 add_settings_field(
1061 'squeeze_setting_jpeg_trellis_opt_zero',
1062 __( 'Optimize zero block runs', 'squeeze' ),
1063 [$this, 'options_callback'],
1064 'squeeze_options',
1065 'squeeze_jpeg_advanced_settings',
1066 array(
1067 'label_for' => 'jpeg_trellis_opt_zero',
1068 'class' => 'squeeze_setting_jpeg_trellis_opt_zero',
1069 'type' => 'checkbox',
1070 )
1071 );
1072 add_settings_field(
1073 'squeeze_setting_jpeg_trellis_opt_table',
1074 __( 'Optimize after trellis quantization', 'squeeze' ),
1075 [$this, 'options_callback'],
1076 'squeeze_options',
1077 'squeeze_jpeg_advanced_settings',
1078 array(
1079 'label_for' => 'jpeg_trellis_opt_table',
1080 'class' => 'squeeze_setting_jpeg_trellis_opt_table',
1081 'type' => 'checkbox',
1082 )
1083 );
1084 add_settings_field(
1085 'squeeze_setting_jpeg_trellis_loops',
1086 __( 'Trellis quantization passes', 'squeeze' ),
1087 [$this, 'options_callback'],
1088 'squeeze_options',
1089 'squeeze_jpeg_advanced_settings',
1090 array(
1091 'label_for' => 'jpeg_trellis_loops',
1092 'class' => 'squeeze_setting_jpeg_trellis_loops',
1093 'type' => 'range',
1094 'min' => 1,
1095 'max' => 50,
1096 )
1097 );
1098 add_settings_field(
1099 'squeeze_setting_jpeg_auto_subsample',
1100 __( 'Auto subsample chroma', 'squeeze' ),
1101 [$this, 'options_callback'],
1102 'squeeze_options',
1103 'squeeze_jpeg_advanced_settings',
1104 array(
1105 'label_for' => 'jpeg_auto_subsample',
1106 'class' => 'squeeze_setting_jpeg_auto_subsample',
1107 'type' => 'checkbox',
1108 )
1109 );
1110 add_settings_field(
1111 'squeeze_setting_jpeg_chroma_subsample',
1112 __( 'Subsample chroma by', 'squeeze' ),
1113 [$this, 'options_callback'],
1114 'squeeze_options',
1115 'squeeze_jpeg_advanced_settings',
1116 array(
1117 'label_for' => 'jpeg_chroma_subsample',
1118 'class' => 'squeeze_setting_jpeg_chroma_subsample',
1119 'type' => 'range',
1120 'min' => 1,
1121 'max' => 4,
1122 )
1123 );
1124 add_settings_field(
1125 'squeeze_setting_jpeg_separate_chroma_quality',
1126 __( 'Separate chroma quality', 'squeeze' ),
1127 [$this, 'options_callback'],
1128 'squeeze_options',
1129 'squeeze_jpeg_advanced_settings',
1130 array(
1131 'label_for' => 'jpeg_separate_chroma_quality',
1132 'class' => 'squeeze_setting_jpeg_separate_chroma_quality',
1133 'type' => 'checkbox',
1134 )
1135 );
1136 add_settings_field(
1137 'squeeze_setting_jpeg_chroma_quality',
1138 __( 'Chroma quality', 'squeeze' ),
1139 [$this, 'options_callback'],
1140 'squeeze_options',
1141 'squeeze_jpeg_advanced_settings',
1142 array(
1143 'label_for' => 'jpeg_chroma_quality',
1144 'class' => 'squeeze_setting_jpeg_chroma_quality',
1145 'type' => 'range',
1146 )
1147 );
1148 add_settings_section(
1149 'squeeze_png_settings',
1150 __( 'PNG Settings', 'squeeze' ),
1151 'squeeze_setting_png_desc',
1152 'squeeze_options',
1153 array(
1154 'section_class' => 'squeeze_png',
1155 )
1156 );
1157 add_settings_field(
1158 'squeeze_setting_png_quality',
1159 __( 'Quality', 'squeeze' ),
1160 [$this, 'options_callback'],
1161 'squeeze_options',
1162 'squeeze_png_settings',
1163 array(
1164 'label_for' => 'png_quality',
1165 'class' => 'squeeze_setting_png_quality',
1166 'type' => 'range',
1167 'min' => 0.01,
1168 'max' => 1,
1169 'step' => 0.01,
1170 )
1171 );
1172 add_settings_section(
1173 'squeeze_webp_settings',
1174 __( 'WEBP Settings', 'squeeze' ),
1175 'squeeze_setting_webp_desc',
1176 'squeeze_options',
1177 array(
1178 'section_class' => 'squeeze_webp',
1179 )
1180 );
1181 add_settings_field(
1182 'squeeze_setting_webp_method',
1183 __( 'Effort', 'squeeze' ),
1184 [$this, 'options_callback'],
1185 'squeeze_options',
1186 'squeeze_webp_settings',
1187 array(
1188 'label_for' => 'webp_method',
1189 'class' => 'squeeze_setting_webp_method',
1190 'type' => 'range',
1191 'min' => 0,
1192 'max' => 6,
1193 )
1194 );
1195 add_settings_field(
1196 'squeeze_setting_webp_quality',
1197 __( 'Quality', 'squeeze' ),
1198 [$this, 'options_callback'],
1199 'squeeze_options',
1200 'squeeze_webp_settings',
1201 array(
1202 'label_for' => 'webp_quality',
1203 'class' => 'squeeze_setting_webp_quality',
1204 'type' => 'range',
1205 'min' => 0,
1206 'max' => 100,
1207 'hidden' => ( $webp_lossless ? true : '' ),
1208 )
1209 );
1210 add_settings_field(
1211 'squeeze_setting_webp_lossless',
1212 __( 'Lossless', 'squeeze' ),
1213 [$this, 'options_callback'],
1214 'squeeze_options',
1215 'squeeze_webp_settings',
1216 array(
1217 'label_for' => 'webp_lossless',
1218 'class' => 'squeeze_setting_webp_lossless',
1219 'type' => 'checkbox',
1220 )
1221 );
1222 add_settings_field(
1223 'squeeze_setting_webp_near_lossless',
1224 __( 'Near lossless', 'squeeze' ),
1225 [$this, 'options_callback'],
1226 'squeeze_options',
1227 'squeeze_webp_settings',
1228 array(
1229 'label_for' => 'webp_near_lossless',
1230 'class' => 'squeeze_setting_webp_near_lossless',
1231 'type' => 'range',
1232 'min' => 0,
1233 'max' => 100,
1234 )
1235 );
1236 add_settings_section(
1237 'squeeze_avif_settings',
1238 __( 'AVIF Settings', 'squeeze' ),
1239 'squeeze_setting_avif_desc',
1240 'squeeze_options',
1241 array(
1242 'section_class' => 'squeeze_avif',
1243 )
1244 );
1245 add_settings_field(
1246 'squeeze_setting_avif_cqLevel',
1247 __( 'Quality', 'squeeze' ),
1248 [$this, 'options_callback'],
1249 'squeeze_options',
1250 'squeeze_avif_settings',
1251 array(
1252 'label_for' => 'avif_cqLevel',
1253 'class' => 'squeeze_setting_avif_cqLevel',
1254 'type' => 'range',
1255 'min' => 1,
1256 'max' => 100,
1257 )
1258 );
1259 }
1260
1261 /**
1262 * Map stored options to a single WebP delivery mode for the settings UI.
1263 *
1264 * @param array $options squeeze_options array.
1265 * @return string direct|sidecar|sidecar_replace (internal keys; UI labels use "Separate WebP folder".)
1266 */
1267 protected function get_webp_delivery_mode( $options ) {
1268 $direct = !empty( $options['direct_webp'] );
1269 $auto = !empty( $options['auto_webp'] );
1270 $replace = !empty( $options['webp_replace_urls'] );
1271 if ( $direct ) {
1272 return 'direct';
1273 }
1274 if ( $auto && $replace ) {
1275 return 'sidecar_replace';
1276 }
1277 if ( $auto ) {
1278 return 'sidecar';
1279 }
1280 return 'direct';
1281 }
1282
1283 /**
1284 * Unified WebP delivery control (radios + collapsible examples).
1285 */
1286 public function render_webp_delivery_field() {
1287 $options = get_option( 'squeeze_options' );
1288 if ( !is_array( $options ) ) {
1289 $options = array();
1290 }
1291 $mode = $this->get_webp_delivery_mode( $options );
1292 $advanced_open = 'direct' !== $mode;
1293 ?>
1294 <div class="squeeze-webp-delivery-ui">
1295 <fieldset class="squeeze-webp-modes" role="radiogroup">
1296 <legend class="screen-reader-text"><?php
1297 esc_html_e( 'WebP delivery mode', 'squeeze' );
1298 ?></legend>
1299 <label class="squeeze-webp-mode-card<?php
1300 echo ( $mode === 'direct' ? ' is-selected' : '' );
1301 ?>">
1302 <input type="radio" class="squeeze-webp-mode-input" name="squeeze_options[webp_delivery_mode]" value="direct" <?php
1303 checked( $mode, 'direct' );
1304 ?> />
1305 <span class="squeeze-webp-mode-badge"><?php
1306 esc_html_e( 'Recommended', 'squeeze' );
1307 ?></span>
1308 <span class="squeeze-webp-mode-title"><?php
1309 esc_html_e( 'Direct WebP', 'squeeze' );
1310 ?></span>
1311 <span class="squeeze-webp-mode-desc"><?php
1312 esc_html_e( 'Replace originals with .webp on disk. Lowest storage; URLs change to .webp.', 'squeeze' );
1313 ?></span>
1314 </label>
1315 <details class="squeeze-webp-advanced"<?php
1316 echo ( $advanced_open ? ' open' : '' );
1317 ?>>
1318 <summary class="squeeze-webp-advanced-summary"><?php
1319 esc_html_e( 'Advanced delivery methods', 'squeeze' );
1320 ?></summary>
1321 <div class="squeeze-webp-advanced-body">
1322 <p class="squeeze-webp-advanced-intro"><?php
1323 esc_html_e( 'Keep JPEG/PNG originals and serve WebP via a separate folder. Prefer Direct WebP unless you have a specific hosting constraint.', 'squeeze' );
1324 ?></p>
1325 <div class="squeeze-webp-advanced-modes">
1326 <label class="squeeze-webp-mode-card<?php
1327 echo ( $mode === 'sidecar_replace' ? ' is-selected' : '' );
1328 ?>">
1329 <input type="radio" class="squeeze-webp-mode-input" name="squeeze_options[webp_delivery_mode]" value="sidecar_replace" <?php
1330 checked( $mode, 'sidecar_replace' );
1331 ?> />
1332 <span class="squeeze-webp-mode-badge"><?php
1333 esc_html_e( 'PHP / any host', 'squeeze' );
1334 ?></span>
1335 <span class="squeeze-webp-mode-title"><?php
1336 esc_html_e( 'Rewrite <img> src to WebP URLs in HTML', 'squeeze' );
1337 ?></span>
1338 <span class="squeeze-webp-mode-desc"><?php
1339 esc_html_e( 'Keeps JPEG/PNG in uploads and WebP copies under squeeze-webp. Squeeze changes src and srcset in the page HTML to the WebP path. Best when .htaccess rewrites are missing (Nginx, CDN, etc.).', 'squeeze' );
1340 ?></span>
1341 </label>
1342 <label class="squeeze-webp-mode-card<?php
1343 echo ( $mode === 'sidecar' ? ' is-selected' : '' );
1344 ?>">
1345 <input type="radio" class="squeeze-webp-mode-input" name="squeeze_options[webp_delivery_mode]" value="sidecar" <?php
1346 checked( $mode, 'sidecar' );
1347 ?> />
1348 <span class="squeeze-webp-mode-badge"><?php
1349 esc_html_e( 'Apache / .htaccess', 'squeeze' );
1350 ?></span>
1351 <span class="squeeze-webp-mode-title"><?php
1352 esc_html_e( 'Keep JPEG/PNG URLs — server serves WebP', 'squeeze' );
1353 ?></span>
1354 <span class="squeeze-webp-mode-desc"><?php
1355 esc_html_e( 'Keeps originals in uploads; WebP files go to squeeze-webp. Page HTML still shows .jpg/.png URLs. The server rewrite rules send WebP bytes when the browser supports it — no HTML changes.', 'squeeze' );
1356 ?></span>
1357 </label>
1358 </div>
1359 <?php
1360 if ( class_exists( __NAMESPACE__ . '\\SqueezeOffloadMedia', false ) && SqueezeOffloadMedia::is_active() ) {
1361 ?>
1362 <div class="squeeze-notice squeeze-notice--warning squeeze-offload-htaccess-warning<?php
1363 echo ( $mode !== 'sidecar' ? ' squeeze-notice--hidden' : '' );
1364 ?>" role="alert">
1365 <span class="squeeze-notice-icon" aria-hidden="true">⚠️</span>
1366 <div class="squeeze-notice-body">
1367 <strong><?php
1368 esc_html_e( 'Not compatible with WP Offload Media', 'squeeze' );
1369 ?></strong>
1370 <p><?php
1371 esc_html_e( 'The "Keep JPEG/PNG URLs — server serves WebP" mode relies on Apache .htaccess rewrite rules that only work for requests reaching your origin server. When WP Offload Media is active, image URLs point to an external CDN (S3, GCS, DigitalOcean Spaces, etc.) and those requests never pass through your .htaccess — so WebP files will not be served.', 'squeeze' );
1372 ?></p>
1373 <p><?php
1374 echo wp_kses( __( 'Please switch to <strong>Direct WebP</strong> conversion — it converts images to WebP in-place and WP Offload Media handles uploading automatically.', 'squeeze' ), array(
1375 'strong' => array(),
1376 ) );
1377 ?></p>
1378 </div>
1379 </div>
1380 <div class="squeeze-notice squeeze-notice--warning squeeze-offload-sidecar-warning<?php
1381 echo ( $mode !== 'sidecar_replace' ? ' squeeze-notice--hidden' : '' );
1382 ?>" role="alert">
1383 <span class="squeeze-notice-icon" aria-hidden="true">⚠️</span>
1384 <div class="squeeze-notice-body">
1385 <strong><?php
1386 esc_html_e( 'Not compatible with WP Offload Media', 'squeeze' );
1387 ?></strong>
1388 <p><?php
1389 esc_html_e( 'The "Rewrite <img> src to WebP URLs in HTML" mode is not compatible with WP Offload Media. WebP sidecar files are stored in a local squeeze-webp/ folder and are never pushed to your external storage provider (S3, GCS, DigitalOcean Spaces, etc.), so they cannot be served from your CDN URL.', 'squeeze' );
1390 ?></p>
1391 <p><?php
1392 echo wp_kses( __( 'Please switch to <strong>Direct WebP</strong> conversion — it converts images to WebP in-place and WP Offload Media handles uploading automatically.', 'squeeze' ), array(
1393 'strong' => array(),
1394 ) );
1395 ?></p>
1396 </div>
1397 </div>
1398 <?php
1399 }
1400 ?>
1401 <details class="squeeze-webp-example">
1402 <summary><?php
1403 esc_html_e( 'Show example: Rewrite <img> src to WebP URLs in HTML', 'squeeze' );
1404 ?></summary>
1405 <div class="squeeze-webp-example-inner">
1406 <pre class="squeeze-webp-code-sample"><span class="squeeze-webp-pre-callout"><?php
1407 echo esc_html( __( 'Before: the page outputs a normal uploads URL for the JPEG.', 'squeeze' ) );
1408 ?></span>
1409 &lt;img src="//yoursite.example/wp-content/uploads/2025/07/photo.jpg" alt="" /&gt;
1410
1411 <span class="squeeze-webp-pre-callout"><?php
1412 echo esc_html( __( 'After: the same img tag in the markup, but PHP rewrites src to the WebP path under squeeze-webp when that file exists.', 'squeeze' ) );
1413 ?></span>
1414 &lt;img src="//yoursite.example/wp-content/squeeze-webp/uploads/2025/07/photo.jpg.webp" alt="" /&gt;</pre>
1415 </div>
1416 </details>
1417 <details class="squeeze-webp-example">
1418 <summary><?php
1419 esc_html_e( 'Show example: Keep JPEG/PNG URLs — server serves WebP', 'squeeze' );
1420 ?></summary>
1421 <div class="squeeze-webp-example-inner">
1422 <pre class="squeeze-webp-code-sample"><span class="squeeze-webp-pre-callout"><?php
1423 echo esc_html( __( 'The published HTML keeps the usual uploads URL on the img (still ends in .jpg or .png).', 'squeeze' ) );
1424 ?></span>
1425 &lt;img src="//yoursite.example/wp-content/uploads/2025/07/photo.jpg" alt="" /&gt;
1426
1427 <span class="squeeze-webp-pre-callout"><?php
1428 echo esc_html( __( 'When the browser advertises WebP and your server rewrite rules apply, that same URL can be served as a WebP response from the file under squeeze-webp, without changing the markup.', 'squeeze' ) );
1429 ?></span>
1430
1431 <span class="squeeze-webp-pre-heading"><?php
1432 echo esc_html( __( 'On disk (after optimization)', 'squeeze' ) );
1433 ?></span>
1434 /wp-content/uploads/2025/07/image.jpg <span class="squeeze-webp-size squeeze-webp-size--before">~500 KB</span> <span class="squeeze-webp-pre-note"><?php
1435 echo esc_html( __( 'original', 'squeeze' ) );
1436 ?></span>
1437 /wp-content/squeeze-webp/uploads/2025/07/image.jpg.webp <span class="squeeze-webp-size squeeze-webp-size--after">~50 KB</span> <span class="squeeze-webp-pre-note"><?php
1438 echo esc_html( __( 'sidecar WebP', 'squeeze' ) );
1439 ?></span></pre>
1440 </div>
1441 </details>
1442 </div>
1443 </details>
1444 </fieldset>
1445 <details class="squeeze-webp-example">
1446 <summary><?php
1447 esc_html_e( 'Show example: Direct WebP (file sizes)', 'squeeze' );
1448 ?></summary>
1449 <div class="squeeze-webp-example-inner">
1450 <pre class="squeeze-webp-code-sample"><span class="squeeze-webp-pre-callout"><?php
1451 echo esc_html( __( 'Direct WebP: on disk, files use the .webp extension instead of .jpg / .png for the same attachment paths.', 'squeeze' ) );
1452 ?></span>
1453 <span class="squeeze-webp-pre-heading"><?php
1454 echo esc_html( __( 'Before', 'squeeze' ) );
1455 ?></span>
1456 /wp-content/uploads/2025/07/image.jpg <span class="squeeze-webp-size squeeze-webp-size--before">~500 KB</span>
1457 /wp-content/uploads/2025/07/image-300x300.jpg <span class="squeeze-webp-size squeeze-webp-size--before">~230 KB</span>
1458
1459 <span class="squeeze-webp-pre-heading"><?php
1460 echo esc_html( __( 'After', 'squeeze' ) );
1461 ?></span>
1462 /wp-content/uploads/2025/07/image.webp <span class="squeeze-webp-size squeeze-webp-size--after">~50 KB</span>
1463 /wp-content/uploads/2025/07/image-300x300.webp <span class="squeeze-webp-size squeeze-webp-size--after">~20 KB</span></pre>
1464 </div>
1465 </details>
1466 </div>
1467 <?php
1468 }
1469
1470 /**
1471 * Sidebar summary on Basic settings (read-only hints).
1472 */
1473 public function render_basic_settings_sidebar() {
1474 $options = get_option( 'squeeze_options' );
1475 if ( !is_array( $options ) ) {
1476 $options = array();
1477 }
1478 $mode = $this->get_webp_delivery_mode( $options );
1479 $mode_label = __( 'Direct WebP', 'squeeze' );
1480 if ( 'sidecar' === $mode ) {
1481 $mode_label = __( 'Keep JPEG/PNG URLs — server serves WebP', 'squeeze' );
1482 } elseif ( 'sidecar_replace' === $mode ) {
1483 $mode_label = __( 'Rewrite <img> src to WebP URLs in HTML', 'squeeze' );
1484 }
1485 $upload_on = !empty( $options['auto_compress'] );
1486 $backup_on = !empty( $options['backup_original'] );
1487 ?>
1488 <div class="squeeze-card squeeze-card--aside">
1489 <div class="squeeze-card-header">
1490 <h2 class="squeeze-card-title"><?php
1491 esc_html_e( 'Current profile', 'squeeze' );
1492 ?></h2>
1493 </div>
1494 <div class="squeeze-card-body">
1495 <?php
1496 $profile_bits = array('<strong>' . esc_html( $mode_label ) . '</strong>');
1497 if ( $upload_on ) {
1498 $profile_bits[] = esc_html__( 'Squeeze on upload', 'squeeze' );
1499 }
1500 if ( $backup_on ) {
1501 $profile_bits[] = esc_html__( 'Backup on', 'squeeze' );
1502 }
1503 echo '<p>' . wp_kses( implode( ' · ', $profile_bits ), array(
1504 'strong' => array(),
1505 ) ) . '</p>';
1506 ?>
1507 <ul class="squeeze-aside-list">
1508 <?php
1509 if ( 'direct' === $mode ) {
1510 ?>
1511 <li><?php
1512 esc_html_e( 'Best for storage savings on new uploads.', 'squeeze' );
1513 ?></li>
1514 <li><?php
1515 esc_html_e( 'If you deactivate the plugin, hard-coded .jpg/.png links may need updating.', 'squeeze' );
1516 ?></li>
1517 <?php
1518 } elseif ( 'sidecar' === $mode ) {
1519 ?>
1520 <li><?php
1521 esc_html_e( 'HTML keeps normal .jpg/.png URLs; WebP is chosen by the server when the browser supports it.', 'squeeze' );
1522 ?></li>
1523 <li><?php
1524 esc_html_e( 'Needs working .htaccess rewrite rules (Apache mod_rewrite or equivalent).', 'squeeze' );
1525 ?></li>
1526 <?php
1527 } elseif ( 'sidecar_replace' === $mode ) {
1528 ?>
1529 <li><?php
1530 esc_html_e( 'Originals stay in uploads; page HTML points at WebP under squeeze-webp.', 'squeeze' );
1531 ?></li>
1532 <li><?php
1533 esc_html_e( 'Works without .htaccess — PHP rewrites image URLs on each page load.', 'squeeze' );
1534 ?></li>
1535 <?php
1536 }
1537 ?>
1538 </ul>
1539 </div>
1540 </div>
1541 <div class="squeeze-card squeeze-card--aside">
1542 <div class="squeeze-card-header">
1543 <h2 class="squeeze-card-title"><?php
1544 esc_html_e( 'Documentation', 'squeeze' );
1545 ?></h2>
1546 </div>
1547 <div class="squeeze-card-body">
1548 <p>
1549 <a href="<?php
1550 echo esc_url( self::$DOCS_URL );
1551 ?>" target="_blank" rel="noopener noreferrer"><?php
1552 esc_html_e( 'Squeeze documentation', 'squeeze' );
1553 ?></a>
1554 </p>
1555 </div>
1556 </div>
1557 <?php
1558 }
1559
1560 public function options_validate( $input ) {
1561 $previous_options = get_option( 'squeeze_options' );
1562 if ( !is_array( $previous_options ) ) {
1563 $previous_options = array();
1564 }
1565 $previous_webp_mode = $this->get_webp_delivery_mode( $previous_options );
1566 if ( isset( $input['webp_delivery_mode'] ) && is_string( $input['webp_delivery_mode'] ) ) {
1567 $mode = sanitize_text_field( wp_unslash( $input['webp_delivery_mode'] ) );
1568 unset($input['webp_delivery_mode']);
1569 switch ( $mode ) {
1570 case 'sidecar':
1571 case 'sidecar_picture':
1572 $input['direct_webp'] = false;
1573 $input['auto_webp'] = true;
1574 $input['webp_replace_urls'] = false;
1575 break;
1576 case 'sidecar_replace':
1577 $input['direct_webp'] = false;
1578 $input['auto_webp'] = true;
1579 $input['webp_replace_urls'] = true;
1580 break;
1581 case 'direct':
1582 default:
1583 $input['direct_webp'] = true;
1584 $input['auto_webp'] = false;
1585 $input['webp_replace_urls'] = false;
1586 break;
1587 }
1588 }
1589 $input['jpeg_quality'] = absint( $input['jpeg_quality'] );
1590 $input['jpeg_smoothing'] = ( isset( $input['jpeg_smoothing'] ) ? absint( $input['jpeg_smoothing'] ) : self::$SqueezeHelpers->get_default_value( 'jpeg_smoothing' ) );
1591 $input['jpeg_color_space'] = ( isset( $input['jpeg_color_space'] ) ? absint( $input['jpeg_color_space'] ) : self::$SqueezeHelpers->get_default_value( 'jpeg_color_space' ) );
1592 $input['jpeg_quant_table'] = ( isset( $input['jpeg_quant_table'] ) ? absint( $input['jpeg_quant_table'] ) : self::$SqueezeHelpers->get_default_value( 'jpeg_quant_table' ) );
1593 $input['jpeg_trellis_loops'] = ( isset( $input['jpeg_trellis_loops'] ) ? absint( $input['jpeg_trellis_loops'] ) : self::$SqueezeHelpers->get_default_value( 'jpeg_trellis_loops' ) );
1594 $input['jpeg_chroma_subsample'] = ( isset( $input['jpeg_chroma_subsample'] ) ? absint( $input['jpeg_chroma_subsample'] ) : self::$SqueezeHelpers->get_default_value( 'jpeg_chroma_subsample' ) );
1595 $input['jpeg_chroma_quality'] = ( isset( $input['jpeg_chroma_quality'] ) ? absint( $input['jpeg_chroma_quality'] ) : self::$SqueezeHelpers->get_default_value( 'jpeg_chroma_quality' ) );
1596 $input['png_level'] = ( isset( $input['png_level'] ) ? absint( $input['png_level'] ) : self::$SqueezeHelpers->get_default_value( 'png_level' ) );
1597 $input['png_quality'] = ( isset( $input['png_quality'] ) ? floatval( $input['png_quality'] ) : self::$SqueezeHelpers->get_default_value( 'png_quality' ) );
1598 $input['webp_method'] = ( isset( $input['webp_method'] ) ? absint( $input['webp_method'] ) : self::$SqueezeHelpers->get_default_value( 'webp_method' ) );
1599 $input['webp_quality'] = ( isset( $input['webp_quality'] ) ? absint( $input['webp_quality'] ) : self::$SqueezeHelpers->get_default_value( 'webp_quality' ) );
1600 $input['webp_near_lossless'] = ( isset( $input['webp_near_lossless'] ) ? absint( $input['webp_near_lossless'] ) : self::$SqueezeHelpers->get_default_value( 'webp_near_lossless' ) );
1601 $input['avif_cqLevel'] = ( isset( $input['avif_cqLevel'] ) ? absint( $input['avif_cqLevel'] ) : self::$SqueezeHelpers->get_default_value( 'avif_cqLevel' ) );
1602 $input['jpeg_baseline'] = ( isset( $input['jpeg_baseline'] ) ? boolval( $input['jpeg_baseline'] ) : '0' );
1603 //$input[ 'jpeg_arithmetic' ] = isset($input[ 'jpeg_arithmetic' ]) ? boolval($input[ 'jpeg_arithmetic' ]) : '0';
1604 $input['jpeg_progressive'] = ( isset( $input['jpeg_progressive'] ) ? boolval( $input['jpeg_progressive'] ) : '0' );
1605 $input['jpeg_optimize_coding'] = ( isset( $input['jpeg_optimize_coding'] ) ? boolval( $input['jpeg_optimize_coding'] ) : '0' );
1606 $input['jpeg_trellis_multipass'] = ( isset( $input['jpeg_trellis_multipass'] ) ? boolval( $input['jpeg_trellis_multipass'] ) : '0' );
1607 $input['jpeg_trellis_opt_zero'] = ( isset( $input['jpeg_trellis_opt_zero'] ) ? boolval( $input['jpeg_trellis_opt_zero'] ) : '0' );
1608 $input['jpeg_trellis_opt_table'] = ( isset( $input['jpeg_trellis_opt_table'] ) ? boolval( $input['jpeg_trellis_opt_table'] ) : '0' );
1609 $input['jpeg_auto_subsample'] = ( isset( $input['jpeg_auto_subsample'] ) ? boolval( $input['jpeg_auto_subsample'] ) : '0' );
1610 $input['jpeg_separate_chroma_quality'] = ( isset( $input['jpeg_separate_chroma_quality'] ) ? boolval( $input['jpeg_separate_chroma_quality'] ) : '0' );
1611 $input['png_interlace'] = ( isset( $input['png_interlace'] ) ? boolval( $input['png_interlace'] ) : '0' );
1612 $input['webp_lossless'] = ( isset( $input['webp_lossless'] ) ? boolval( $input['webp_lossless'] ) : '0' );
1613 $input['auto_compress'] = ( isset( $input['auto_compress'] ) ? boolval( $input['auto_compress'] ) : '0' );
1614 // TBD: maybe get default value from the database
1615 $input['auto_webp'] = ( isset( $input['auto_webp'] ) ? boolval( $input['auto_webp'] ) : '0' );
1616 $input['webp_replace_urls'] = ( isset( $input['webp_replace_urls'] ) && $input['auto_webp'] ? boolval( $input['webp_replace_urls'] ) : '0' );
1617 $input['direct_webp'] = ( isset( $input['direct_webp'] ) ? boolval( $input['direct_webp'] ) : '0' );
1618 $new_webp_mode = $this->get_webp_delivery_mode( $input );
1619 if ( $previous_webp_mode !== $new_webp_mode ) {
1620 add_settings_error(
1621 'squeeze_notices',
1622 'webp_delivery_mode_changed',
1623 __( 'WebP delivery mode changed. Existing files are not migrated automatically — re-squeeze images after switching. Leftover JPEG/PNG + WebP pairs or orphaned files under squeeze-webp may remain until cleaned up.', 'squeeze' ),
1624 'warning'
1625 );
1626 }
1627 if ( isset( $input['cdn_url'] ) ) {
1628 $cdn_raw = trim( wp_unslash( (string) $input['cdn_url'] ) );
1629 $input['cdn_url'] = ( $cdn_raw === '' ? '' : esc_url_raw( $cdn_raw ) );
1630 } else {
1631 $input['cdn_url'] = '';
1632 }
1633 $input['backup_original'] = ( isset( $input['backup_original'] ) ? boolval( $input['backup_original'] ) : '0' );
1634 $input['clear_data_on_uninstall'] = ( isset( $input['clear_data_on_uninstall'] ) ? boolval( $input['clear_data_on_uninstall'] ) : '0' );
1635 $input['compress_formats'] = ( isset( $input['compress_formats'] ) && is_array( $input['compress_formats'] ) ? $this->validate_image_formats( $input['compress_formats'], $input['direct_webp'] ) : array() );
1636 $input['compress_thumbs'] = ( isset( $input['compress_thumbs'] ) && is_array( $input['compress_thumbs'] ) ? $input['compress_thumbs'] : array() );
1637 $input['max_width'] = ( isset( $input['max_width'] ) && $input['max_width'] > 0 ? absint( $input['max_width'] ) : '' );
1638 $input['max_height'] = ( isset( $input['max_height'] ) && $input['max_height'] > 0 ? absint( $input['max_height'] ) : '' );
1639 $input['excluded_images'] = ( isset( $input['excluded_images'] ) ? $input['excluded_images'] : '' );
1640 $input['timeout'] = ( isset( $input['timeout'] ) && $input['timeout'] > 0 ? absint( $input['timeout'] ) : 1 );
1641 $input['restore_defaults'] = ( isset( $input['restore_defaults'] ) ? $input['restore_defaults'] : '0' );
1642 if ( !isset( $input['restore_defaults'] ) || $input['restore_defaults'] !== '1' ) {
1643 add_settings_error(
1644 'squeeze_notices',
1645 'settings_updated',
1646 __( 'Settings have been updated.', 'squeeze' ),
1647 'success'
1648 );
1649 }
1650 unset($input['webp_picture_markup']);
1651 return $input;
1652 }
1653
1654 protected function validate_image_formats( $input, $is_direct_webp = false ) {
1655 $formats = self::ALLOWED_IMAGE_FORMATS;
1656 if ( !isset( $input ) || !is_array( $input ) ) {
1657 return array();
1658 }
1659 // remove all formats that are not in the allowed formats list
1660 $input = array_filter( $input, function ( $format ) use($formats) {
1661 //check by key
1662 return array_key_exists( $format, $formats );
1663 }, ARRAY_FILTER_USE_KEY );
1664 // if direct webp conversion is enabled, webp format is mandatory
1665 if ( $is_direct_webp && !array_key_exists( 'webp', $input ) ) {
1666 $input['webp'] = 'on';
1667 }
1668 return $input;
1669 }
1670
1671 public function options_callback( $args ) {
1672 $label_for = ( isset( $args['label_for'] ) ? $args['label_for'] : '' );
1673 if ( empty( $label_for ) ) {
1674 return;
1675 }
1676 $type = ( isset( $args['type'] ) ? $args['type'] : 'text' );
1677 $class = ( isset( $args['class'] ) ? $args['class'] : '' );
1678 $default = self::$SqueezeHelpers->get_default_value( $label_for );
1679 $options = get_option( 'squeeze_options' );
1680 $is_hidden = ( isset( $args['hidden'] ) && $args['hidden'] ? 'hidden' : '' );
1681 $extra_classes = [];
1682 if ( $is_hidden ) {
1683 $extra_classes[] = 'squeeze-hidden';
1684 }
1685 $extra_classes = implode( ' ', $extra_classes );
1686 switch ( $type ) {
1687 case 'text':
1688 $value = ( isset( $options[$label_for] ) ? $options[$label_for] : $default );
1689 $placeholder = ( isset( $args['placeholder'] ) ? $args['placeholder'] : '' );
1690 echo "<input class='" . esc_attr( $extra_classes ) . "' id='squeeze_setting_" . esc_attr( $label_for ) . "' name='squeeze_options[" . esc_attr( $label_for ) . "]' type='text' value='" . esc_attr( $value ) . "' placeholder='" . esc_attr( $placeholder ) . "' />";
1691 break;
1692 case 'number':
1693 $value = ( isset( $options[$label_for] ) ? $options[$label_for] : $default );
1694 $units = ( isset( $args['units'] ) ? $args['units'] : '' );
1695 $min = ( isset( $args['min'] ) ? $args['min'] : '' );
1696 $max = ( isset( $args['max'] ) ? $args['max'] : '' );
1697 echo "<input class='" . esc_attr( $extra_classes ) . "' id='squeeze_setting_" . esc_attr( $label_for ) . "' name='squeeze_options[" . esc_attr( $label_for ) . "]' type='number' value='" . esc_attr( $value ) . "' " . (( $min !== '' && $min !== null ? "min='" . esc_attr( $min ) . "'" : "" )) . " " . (( $max !== '' && $max !== null ? "max='" . esc_attr( $max ) . "'" : "" )) . " />";
1698 if ( $units ) {
1699 echo "<span class='squeeze-setting-units'>" . esc_html( $units ) . "</span>";
1700 }
1701 break;
1702 case 'range':
1703 $value = ( isset( $options[$label_for] ) ? $options[$label_for] : $default );
1704 $min = ( isset( $args['min'] ) ? $args['min'] : 0 );
1705 $max = ( isset( $args['max'] ) ? $args['max'] : 100 );
1706 $step = ( isset( $args['step'] ) ? $args['step'] : 1 );
1707 echo "<input class='" . esc_attr( $extra_classes ) . "' id='squeeze_setting_" . esc_attr( $label_for ) . "' name='squeeze_options[" . esc_attr( $label_for ) . "]' min='" . (int) $min . "' max='" . (int) $max . "' step='" . floatval( $step ) . "' type='range' value='" . esc_attr( $value ) . "' />";
1708 echo '<output id="squeeze_setting_' . esc_attr( $label_for ) . '_value"></output>';
1709 ?>
1710 <script>
1711 (function () {
1712 const value = document.querySelector("#squeeze_setting_<?php
1713 echo esc_attr( $label_for );
1714 ?>_value")
1715 const input = document.querySelector("#squeeze_setting_<?php
1716 echo esc_attr( $label_for );
1717 ?>")
1718 value.textContent = input.value
1719 input.addEventListener("input", (event) => {
1720 value.textContent = event.target.value
1721 })
1722 })()
1723 </script>
1724 <?php
1725 break;
1726 case 'checkbox':
1727 $value = ( isset( $options[$label_for] ) ? (bool) $options[$label_for] : $default );
1728 //echo (bool)$options[ $label_for ];
1729 echo "<input class='squeeze-ios8-switch " . esc_attr( $extra_classes ) . "' id='squeeze_setting_" . esc_attr( $label_for ) . "' name='squeeze_options[" . esc_attr( $label_for ) . "]' type='checkbox' " . checked( $value, true, false ) . " />";
1730 echo '<label for="squeeze_setting_' . esc_attr( $label_for ) . '"></label>';
1731 break;
1732 case 'select':
1733 $value = ( isset( $options[$label_for] ) ? $options[$label_for] : $default );
1734 echo "<select class='" . esc_attr( $extra_classes ) . "' id='squeeze_setting_" . esc_attr( $label_for ) . "' name='squeeze_options[" . esc_attr( $label_for ) . "]'>";
1735 foreach ( $args['options'] as $key => $option ) {
1736 echo "<option value='" . esc_attr( $key ) . "'" . selected( $value, $key, false ) . ">" . esc_html( $option ) . "</option>";
1737 }
1738 echo "</select>";
1739 break;
1740 case 'thumbs_checkbox_group':
1741 $thumbs = array();
1742 $value = ( isset( $options[$label_for] ) ? (array) $options[$label_for] : $default );
1743 $available_sizes = wp_get_registered_image_subsizes();
1744 foreach ( $available_sizes as $key => $size ) {
1745 $thumbs[$key] = ucwords( str_replace( '_', ' ', $key ) ) . ' (' . $size['width'] . 'x' . $size['height'] . ')';
1746 }
1747 // Add the scaled image size option
1748 $big_image_size_threshold = apply_filters( 'big_image_size_threshold', 2560 );
1749 $thumbs['full'] = 'Scaled (' . $big_image_size_threshold . 'x' . $big_image_size_threshold . ')';
1750 echo '<div class="squeeze-thumb-toolbar">';
1751 echo '<button type="button" class="button button-small" id="squeeze-thumbs-select-all">' . esc_html__( 'Select all', 'squeeze' ) . '</button>';
1752 echo '<button type="button" class="button button-small" id="squeeze-thumbs-clear-all">' . esc_html__( 'Clear all', 'squeeze' ) . '</button>';
1753 echo '<button type="button" class="button button-small" id="squeeze-thumbs-wp-defaults">' . esc_html__( 'WordPress defaults', 'squeeze' ) . '</button>';
1754 echo '</div>';
1755 echo '<div class="squeeze-box squeeze-box--fieldset squeeze-thumb-grid-wrap">';
1756 echo '<div class="squeeze-box-content squeeze-thumb-grid">';
1757 foreach ( $thumbs as $key => $option ) {
1758 echo '<div class="squeeze-suboption squeeze-thumb-grid-item">';
1759 echo "<input class='squeeze-ios8-switch' id='squeeze_setting_" . esc_attr( $label_for ) . "_" . esc_attr( $key ) . "' name='squeeze_options[" . esc_attr( $label_for ) . "][" . esc_attr( $key ) . "]' type='checkbox' " . checked( array_key_exists( $key, $value ), true, false ) . " /> ";
1760 echo "<label for='squeeze_setting_" . esc_attr( $label_for ) . "_" . esc_attr( $key ) . "'>" . esc_html( $option ) . "</label>";
1761 echo '</div>';
1762 }
1763 echo '</div>';
1764 echo '</div>';
1765 break;
1766 case 'formats_checkbox_group':
1767 $is_direct_webp = ( isset( $options['direct_webp'] ) ? (bool) $options['direct_webp'] : false );
1768 $formats = self::ALLOWED_IMAGE_FORMATS;
1769 $value = ( isset( $options[$label_for] ) ? (array) $options[$label_for] : $default );
1770 echo '<div class="squeeze-box squeeze-box--fieldset squeeze-format-chips-wrap">';
1771 echo '<div class="squeeze-box-content squeeze-format-chips">';
1772 foreach ( $formats as $key => $option ) {
1773 echo '<div class="squeeze-suboption squeeze-format-chip ' . (( $is_direct_webp && $key === 'webp' ? 'squeeze-disabled' : '' )) . '">';
1774 echo "<input class='squeeze-ios8-switch' id='squeeze_setting_" . esc_attr( $label_for ) . "_" . esc_attr( $key ) . "' name='squeeze_options[" . esc_attr( $label_for ) . "][" . esc_attr( $key ) . "]' type='checkbox' " . checked( array_key_exists( $key, $value ), true, false ) . " /> ";
1775 echo "<label for='squeeze_setting_" . esc_attr( $label_for ) . "_" . esc_attr( $key ) . "'>" . esc_html( $key ) . "</label>";
1776 if ( $is_direct_webp && $key === 'webp' ) {
1777 echo '<span class="squeeze-hint">' . __( '(mandatory when Direct WebP is enabled)', 'squeeze' ) . '</span>';
1778 }
1779 echo '</div>';
1780 }
1781 echo '</div>';
1782 echo '</div>';
1783 break;
1784 case 'hidden':
1785 $value = ( isset( $options[$label_for] ) ? $options[$label_for] : $default );
1786 echo "<input id='squeeze_setting_" . esc_attr( $label_for ) . "' name='squeeze_options[" . esc_attr( $label_for ) . "]' type='hidden' value='" . esc_attr( $value ) . "' />";
1787 break;
1788 case 'textarea':
1789 $value = ( isset( $options[$label_for] ) ? $options[$label_for] : $default );
1790 echo "<textarea class='" . esc_attr( $extra_classes ) . "' id='squeeze_setting_" . esc_attr( $label_for ) . "' name='squeeze_options[" . esc_attr( $label_for ) . "]'>" . esc_textarea( $value ) . "</textarea>";
1791 break;
1792 case 'placeholder':
1793 echo '<p>' . sprintf( __( 'This feature is available only in the <a href="%s">premium version</a>.', 'squeeze' ), esc_url( self::$UPGRADE_URL ) ) . '</p>';
1794 break;
1795 }
1796 }
1797
1798 public function setting_basic_desc() {
1799 echo '<p>' . esc_html__( 'Basic squeezing settings.', 'squeeze' ) . '</p>';
1800 }
1801
1802 public function setting_jpeg_desc() {
1803 echo '<p>' . esc_html__( 'Squeezing settings for JPEG images.', 'squeeze' ) . '</p>';
1804 }
1805
1806 public function setting_jpeg_advanced_desc() {
1807 echo '<p>' . esc_html__( 'More precise settings for experienced users.', 'squeeze' ) . '</p>';
1808 }
1809
1810 public function setting_png_desc() {
1811 echo '<p>' . esc_html__( 'Squeezing settings for PNG images.', 'squeeze' ) . '</p>';
1812 }
1813
1814 public function setting_webp_desc() {
1815 echo '<p>' . esc_html__( 'Squeezing settings for WebP images.', 'squeeze' ) . '</p>';
1816 }
1817
1818 public function setting_avif_desc() {
1819 echo '<p>' . esc_html__( 'Squeezing settings for Avif images.', 'squeeze' ) . '</p>';
1820 }
1821
1822 public function setting_upgrade_desc() {
1823 echo '<p>' . esc_html__( 'Upgrade to premium version for more features.', 'squeeze' ) . '</p>';
1824 }
1825
1826 public function setting_license_desc() {
1827 }
1828
1829 public function restore_defaults( $old_value, $value ) {
1830 if ( isset( $value['restore_defaults'] ) && $value['restore_defaults'] === '1' ) {
1831 $result = delete_option( 'squeeze_options', "" );
1832 if ( $result ) {
1833 add_settings_error(
1834 'squeeze_notices',
1835 'settings_restored',
1836 __( 'Settings have been restored.', 'squeeze' ),
1837 'success'
1838 );
1839 } else {
1840 add_settings_error(
1841 'squeeze_notices',
1842 'settings_not_restored',
1843 __( 'Settings have not been restored.', 'squeeze' ),
1844 'error'
1845 );
1846 }
1847 }
1848 }
1849
1850 public function flush_rewrite_rules( $old_value, $value ) {
1851 if ( isset( $value['auto_webp'] ) && $value['auto_webp'] !== $old_value['auto_webp'] ) {
1852 flush_rewrite_rules();
1853 add_settings_error(
1854 'squeeze_notices',
1855 'rewrite_rules_flushed',
1856 __( 'Rewrite rules have been flushed.', 'squeeze' ),
1857 'success'
1858 );
1859 }
1860 }
1861
1862 public function add_custom_field_to_attachment( $form_fields, $post ) {
1863 $all_formats = self::ALLOWED_IMAGE_FORMATS;
1864 $all_mimes = self::$SqueezeHelpers->get_image_formats( true, $all_formats );
1865 if ( in_array( $post->post_mime_type, $all_mimes ) ) {
1866 $selected_mimes = self::$SqueezeHelpers->get_image_formats( true );
1867 $is_compressed = get_post_meta( $post->ID, 'squeeze_is_compressed', true );
1868 $compression_failed = get_post_meta( $post->ID, 'squeeze_compression_failed', true );
1869 $can_restore = self::$SqueezeHelpers->can_restore( $post->ID );
1870 $is_excluded = false;
1871 $url = wp_get_original_image_url( $post->ID );
1872 if ( $url ) {
1873 $excluded_images = self::$SqueezeHelpers->get_excluded_images();
1874 $is_excluded = self::$SqueezeHelpers->is_excluded_image( $url, $excluded_images );
1875 }
1876 $form_fields['squeeze_is_compressed'] = array(
1877 'label' => __( 'Squeeze', 'squeeze' ),
1878 'input' => 'html',
1879 'html' => ( !in_array( $post->post_mime_type, $selected_mimes ) ? '<span class="squeeze_status"><span style="padding-top: 0; line-height: 1; color: gray;" class="dashicons dashicons-info"></span>&nbsp;' . __( 'Image format is not selected for compression in the plugin settings', 'squeeze' ) . '</span><br>' : (( $is_excluded ? '<span class="squeeze_status"><span style="padding-top: 0; line-height: 1; color: #6c757d;" class="dashicons dashicons-hidden"></span>&nbsp;' . __( 'Image is excluded from compression', 'squeeze' ) . ' (' . esc_html__( 'found substring: ', 'squeeze' ) . $is_excluded['exclude_reason'] . ')</span>' : (( $compression_failed === 'larger_than_original' ? '<p><span class="squeeze_status"><span style="padding-top: 0; line-height: 1; color: #FFA500;" class="dashicons dashicons-warning"></span>&nbsp;' . sprintf( __( 'Could not compress — result was larger than original. Try <a href="%s" target="_blank">adjusting compression settings</a>, then re-squeeze.', 'squeeze' ), self::$SETTINGS_URL . '#squeeze_' . pathinfo( get_attached_file( $post->ID ), PATHINFO_EXTENSION ) ) . '</span></p>' . (( $can_restore ? '<p><button name="squeeze_restore" type="button" class="button button-secondary squeeze-restore-button" data-attachment="' . $post->ID . '">' . __( 'Restore original image', 'squeeze' ) . '</button></p>' : '' )) . '<p><button name="squeeze_compress_single" type="button" class="button button-secondary squeeze-compress-button" data-attachment="' . $post->ID . '">' . __( 'Re-Squeeze image', 'squeeze' ) . '</button></p>' : (( $is_compressed ? '<p><span class="squeeze_status"><span style="padding-top: 0; line-height: 1; color: #6BCB77;" class="dashicons dashicons-performance"></span>&nbsp;' . __( 'Squeezed', 'squeeze' ) . '</span></p>' . (( $can_restore ? '
1880 <p><button name="squeeze_restore" type="button" class="button button-secondary squeeze-restore-button" data-attachment="' . $post->ID . '">' . __( 'Restore original image', 'squeeze' ) . '</button></p>' : '' )) . '
1881 <p><button name="squeeze_compress_again" type="button" class="button button-primary squeeze-compress-button" data-attachment="' . $post->ID . '">' . __( 'Re-Squeeze image', 'squeeze' ) . '</button></p>' : '<p><span class="squeeze_status"><span style="padding-top: 0; line-height: 1; color: #FFD93D; scale: -1 1;" class="dashicons dashicons-performance"></span>&nbsp;' . __( 'Not squeezed', 'squeeze' ) . '</span></p>
1882 <p><button name="squeeze_compress_single" type="button" class="button button-primary squeeze-compress-button" data-attachment="' . $post->ID . '">' . __( 'Squeeze Now', 'squeeze' ) . '</button></p>' )) )) )) ),
1883 );
1884 }
1885 return $form_fields;
1886 }
1887
1888 public function add_media_columns( $posts_columns ) {
1889 $posts_columns['squeeze'] = __( 'Squeeze', 'squeeze' );
1890 return $posts_columns;
1891 }
1892
1893 public function media_custom_column( $column_name, $post_id ) {
1894 if ( 'squeeze' !== $column_name ) {
1895 return;
1896 }
1897 $form_fields = $this->add_custom_field_to_attachment( array(), get_post( $post_id ) );
1898 if ( $form_fields ) {
1899 echo wp_kses_post( $form_fields['squeeze_is_compressed']['html'] );
1900 }
1901 }
1902
1903 public function sortable_columns( $columns ) {
1904 $columns['squeeze'] = 'squeeze';
1905 return $columns;
1906 }
1907
1908 public function sortable_columns_orderby( $query ) {
1909 if ( !is_admin() || !$query->is_main_query() ) {
1910 return;
1911 }
1912 $orderby = $query->get( 'orderby' );
1913 if ( 'squeeze' === $orderby ) {
1914 // Define the allowed image formats
1915 $allowed_formats = self::$SqueezeHelpers->get_image_formats( true );
1916 // include all media
1917 $query->set( 'meta_query', array(
1918 'relation' => 'OR',
1919 array(
1920 'key' => 'squeeze_is_compressed',
1921 'compare' => 'NOT EXISTS',
1922 ),
1923 array(
1924 'key' => 'squeeze_is_compressed',
1925 'compare' => 'EXISTS',
1926 ),
1927 ) );
1928 // Add the meta_query to filter by specific image formats
1929 //$query->set('post_mime_type', $allowed_formats);
1930 $query->set( 'orderby', 'meta_value' );
1931 }
1932 }
1933
1934 public function media_filter_dropdown() {
1935 global $wp_query;
1936 $post_type = 'attachment';
1937 if ( isset( $_GET['post_type'] ) ) {
1938 $post_type = sanitize_text_field( wp_unslash( $_GET['post_type'] ) );
1939 }
1940 if ( 'attachment' !== $post_type ) {
1941 return;
1942 }
1943 $selected = ( isset( $_GET['squeeze_filter'] ) ? sanitize_text_field( wp_unslash( $_GET['squeeze_filter'] ) ) : '' );
1944 $options = array(
1945 'all' => __( 'Squeeze: All images', 'squeeze' ),
1946 'non-squeezed' => __( 'Non Squeezed Images', 'squeeze' ),
1947 );
1948 echo '<select name="squeeze_filter" id="squeeze-filter">';
1949 foreach ( $options as $value => $label ) {
1950 printf(
1951 '<option value="%s"%s>%s</option>',
1952 esc_attr( $value ),
1953 selected( $selected, $value, false ),
1954 esc_html( $label )
1955 );
1956 }
1957 echo '</select>';
1958 }
1959
1960 public function media_filter_query( $query ) {
1961 global $current_screen;
1962 if ( !is_admin() || !empty( $current_screen ) && 'upload' !== $current_screen->base || 'attachment' !== $query->get( 'post_type' ) ) {
1963 return $query;
1964 }
1965 if ( isset( $_GET['squeeze_filter'] ) ) {
1966 $squeeze_filter = sanitize_text_field( wp_unslash( $_GET['squeeze_filter'] ) );
1967 if ( 'non-squeezed' === $squeeze_filter ) {
1968 $query->set( 'meta_query', self::$SqueezeHelpers->get_non_squeezed_media_meta_query() );
1969 $query->set( 'squeeze_exclude_excluded', true );
1970 $query->set( 'orderby', 'meta_value' );
1971 $query->set( 'post_mime_type', self::$SqueezeHelpers->get_image_formats( true ) );
1972 }
1973 }
1974 return $query;
1975 }
1976
1977 public function media_filter_ajax_query( $query ) {
1978 if ( !isset( $_POST['query']['squeeze_filter'] ) ) {
1979 return $query;
1980 }
1981 $squeeze_filter = sanitize_text_field( wp_unslash( $_POST['query']['squeeze_filter'] ) );
1982 if ( 'non-squeezed' === $squeeze_filter ) {
1983 $query['meta_query'] = self::$SqueezeHelpers->get_non_squeezed_media_meta_query();
1984 $query['squeeze_exclude_excluded'] = true;
1985 $query['orderby'] = 'meta_value';
1986 $query['post_mime_type'] = self::$SqueezeHelpers->get_image_formats( true );
1987 }
1988 return $query;
1989 }
1990
1991 public function media_filter_exclude_excluded( $posts, $query ) {
1992 if ( empty( $posts ) || !$query instanceof \WP_Query ) {
1993 return $posts;
1994 }
1995 if ( !$query->get( 'squeeze_exclude_excluded' ) ) {
1996 return $posts;
1997 }
1998 if ( empty( self::$SqueezeHelpers->get_excluded_images() ) ) {
1999 return $posts;
2000 }
2001 return array_values( array_filter( $posts, function ( $post ) {
2002 return !self::$SqueezeHelpers->is_attachment_excluded( $post->ID );
2003 } ) );
2004 }
2005
2006 public function handle_excluded_images_option_change( $old_value, $new_value ) {
2007 $old_excluded = ( isset( $old_value['excluded_images'] ) ? $old_value['excluded_images'] : '' );
2008 $new_excluded = ( isset( $new_value['excluded_images'] ) ? $new_value['excluded_images'] : '' );
2009 if ( $old_excluded === $new_excluded ) {
2010 return;
2011 }
2012 self::$SqueezeHelpers->clear_excluded_images_cache();
2013 self::$SqueezeHelpers->clear_options_cache();
2014 self::$SqueezeHelpers->invalidate_uncompressed_stats_cache();
2015 }
2016
2017 public function svg_sprite_output() {
2018 global $pagenow;
2019 if ( $pagenow === 'upload.php' && isset( $_GET['page'] ) && $_GET['page'] === 'squeeze-bulk' ) {
2020 include self::$PLUGIN_DIR . 'assets/images/sprite.svg';
2021 }
2022 }
2023
2024 public function add_preview_button_placeholder( $post ) {
2025 if ( !wp_attachment_is_image( $post->ID ) ) {
2026 return;
2027 }
2028 echo '<div class="squeeze-preview-button is-placeholder">';
2029 echo '<input type="checkbox" disabled class="squeeze-ios8-switch" id="squeeze-ios8-switch"><label for="squeeze-ios8-switch" title="' . esc_attr__( "Image comparison with Squeeze", "squeeze" ) . '">' . esc_html__( "Compare Squeeze", "squeeze" ) . ' ';
2030 echo sprintf( __( '(<a href="%s" target="_blank">premium only</a>)', 'squeeze' ), esc_url( self::$UPGRADE_URL ) ) . '</label>';
2031 echo '</div>';
2032 }
2033
2034 public function incompatibility_notices() {
2035 // Bail if we're not in the admin or the screen helper isn't available.
2036 if ( !is_admin() || !function_exists( 'get_current_screen' ) ) {
2037 return;
2038 }
2039 $screen = get_current_screen();
2040 // List of screen IDs where we want the warning.
2041 $target_screens = array(
2042 'settings_page_squeeze',
2043 // options-general.php?page=squeeze
2044 'media_page_squeeze-bulk',
2045 // upload.php?page=squeeze-bulk
2046 'upload',
2047 // the core Media → Library (list table)
2048 'media',
2049 // the core Media → Add New
2050 'plugins',
2051 );
2052 if ( !$screen || !in_array( $screen->id, $target_screens, true ) ) {
2053 return;
2054 }
2055 // check if webp-express/webp-express.php plugin is active and show a notice
2056 if ( is_plugin_active( 'webp-express/webp-express.php' ) ) {
2057 ?>
2058 <div class="notice notice-warning is-dismissible">
2059 <p>
2060 <?php
2061 echo __( 'The WebP Express plugin is active. Please deactivate it in order to use correct WebP serving from <strong>Squeeze plugin</strong>.', 'squeeze' );
2062 ?>
2063 </p>
2064 </div>
2065 <?php
2066 }
2067 // check if image-converter-webp/image-converter-webp.php plugin is active and show a notice
2068 if ( is_plugin_active( 'image-converter-webp/image-converter-webp.php' ) ) {
2069 ?>
2070 <div class="notice notice-warning is-dismissible">
2071 <p>
2072 <?php
2073 echo __( 'The Image Converter for WebP plugin is active. Please deactivate it in order to use correct WebP serving from <strong>Squeeze plugin</strong>.', 'squeeze' );
2074 ?>
2075 </p>
2076 </div>
2077 <?php
2078 }
2079 }
2080
2081 }
2082