PluginProbe ʕ •ᴥ•ʔ
Modern Image Formats / 2.7.0
Modern Image Formats v2.7.0
2.7.0 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.1.0 1.1.1 2.0.0 2.0.1 2.0.2 2.1.0 2.2.0 2.3.0 2.4.0 2.5.0 2.5.1 2.6.0 2.6.1
webp-uploads / settings.php
webp-uploads Last commit date
deprecated.php 11 hours ago helper.php 11 hours ago hooks.php 11 hours ago image-edit.php 11 hours ago load.php 11 hours ago picture-element.php 11 hours ago readme.txt 11 hours ago rest-api.php 11 hours ago settings.php 11 hours ago uninstall.php 11 hours ago
settings.php
436 lines
1 <?php
2 /**
3 * Settings for the Modern Image Formats plugin.
4 *
5 * @package webp-uploads
6 *
7 * @since 1.0.0
8 */
9
10 declare( strict_types = 1 );
11
12 // @codeCoverageIgnoreStart
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit; // Exit if accessed directly.
15 }
16 // @codeCoverageIgnoreEnd
17
18 /**
19 * Registers setting for generating JPEG in addition to the selected modern format for image uploads.
20 *
21 * @since 1.0.0
22 * @since 2.0.0 The setting was made more general to cover outputting JPEG as a secondary type. The "webp" option naming
23 * was left unchanged for backward compatibility. Also, the `perflab_modern_image_format` was added to
24 * enable selecting an output format. Currently includes AVIF and WebP.
25 */
26 function webp_uploads_register_media_settings_field(): void {
27 register_setting(
28 'media',
29 'perflab_modern_image_format',
30 array(
31 'sanitize_callback' => 'webp_uploads_sanitize_image_format',
32 'type' => 'string',
33 'default' => 'avif', // AVIF is the default if the editor supports it.
34 'show_in_rest' => false,
35 )
36 );
37
38 register_setting(
39 'media',
40 'perflab_generate_webp_and_jpeg',
41 array(
42 'type' => 'boolean',
43 'default' => current_theme_supports( 'html5', 'picture' ), // If picture element is supported by the theme, default to enabling the JPEG fallback.
44 'show_in_rest' => false,
45 )
46 );
47
48 // Add a setting to generate fallback images in all sizes including custom sizes.
49 register_setting(
50 'media',
51 'perflab_generate_all_fallback_sizes',
52 array(
53 'type' => 'boolean',
54 'default' => false,
55 'show_in_rest' => false,
56 )
57 );
58
59 // Add a setting to use the picture element.
60 register_setting(
61 'media',
62 'webp_uploads_use_picture_element',
63 array(
64 'type' => 'boolean',
65 // Use picture element by default if the theme declares support for it.
66 'default' => current_theme_supports( 'html5', 'picture' ), // Use picture element by default if the theme declares support for it.
67 'show_in_rest' => false,
68 )
69 );
70 }
71 add_action( 'init', 'webp_uploads_register_media_settings_field' );
72
73 /**
74 * Adds media settings field for the 'perflab_generate_webp_and_jpeg' setting.
75 *
76 * @since 1.0.0
77 */
78 function webp_uploads_add_media_settings_fields(): void {
79 add_settings_section(
80 'perflab_modern_image_format_settings',
81 _x( 'Modern Image Formats', 'settings page section name', 'webp-uploads' ),
82 static function (): void {
83 printf(
84 '<p>%s</p>',
85 wp_kses(
86 sprintf(
87 /* translators: %s: URL to the plugin FAQ on WordPress.org */
88 __( 'If modern format images are not being generated after upload, see the <a href="%s">FAQ</a> for common reasons.', 'webp-uploads' ),
89 'https://wordpress.org/plugins/webp-uploads/#faq'
90 ),
91 array( 'a' => array( 'href' => array() ) )
92 )
93 );
94 },
95 'media',
96 array(
97 'before_section' => '<div id="modern-image-formats">',
98 'after_section' => '</div>',
99 )
100 );
101
102 // Add a dropdown to select the output format between AVIF and WebP output.
103 add_settings_field(
104 'perflab_modern_image_format',
105 __( 'Image output format', 'webp-uploads' ),
106 'webp_uploads_generate_avif_webp_setting_callback',
107 'media',
108 'perflab_modern_image_format_settings',
109 array( 'class' => 'perflab-generate-avif-and-webp' )
110 );
111
112 // Only add the remaining settings fields if at least one modern image format is supported.
113 if ( ! webp_uploads_mime_type_supported( 'image/avif' ) && ! webp_uploads_mime_type_supported( 'image/webp' ) ) {
114 return;
115 }
116
117 // Add fallback image output settings field.
118 add_settings_field(
119 'perflab_generate_webp_and_jpeg',
120 __( 'Output fallback images', 'webp-uploads' ),
121 'webp_uploads_generate_webp_jpeg_setting_callback',
122 'media',
123 'perflab_modern_image_format_settings',
124 array( 'class' => 'perflab-generate-webp-and-jpeg' )
125 );
126
127 // Add setting field for generating fallback images in all sizes including custom sizes.
128 add_settings_field(
129 'perflab_generate_all_fallback_sizes',
130 __( 'Generate all fallback image sizes', 'webp-uploads' ),
131 'webp_uploads_generate_all_fallback_sizes_callback',
132 'media',
133 'perflab_modern_image_format_settings',
134 array( 'class' => 'perflab-generate-fallback-all-sizes' )
135 );
136
137 // Add picture element support settings field.
138 add_settings_field(
139 'webp_uploads_use_picture_element',
140 __( 'Picture element', 'webp-uploads' ),
141 'webp_uploads_use_picture_element_callback',
142 'media',
143 'perflab_modern_image_format_settings',
144 array( 'class' => 'webp-uploads-use-picture-element' )
145 );
146 }
147 add_action( 'admin_init', 'webp_uploads_add_media_settings_fields' );
148
149 /**
150 * Renders the settings field for the 'perflab_modern_image_format' setting.
151 *
152 * @since 2.0.0
153 */
154 function webp_uploads_generate_avif_webp_setting_callback(): void {
155
156 $selected = webp_uploads_get_image_output_format();
157 $avif_supported = webp_uploads_avif_supported();
158 $avif_transparency_supported = webp_uploads_avif_transparency_supported();
159 $avif_fully_supported = $avif_supported && $avif_transparency_supported;
160 $webp_supported = webp_uploads_mime_type_supported( 'image/webp' );
161
162 // If neither format is support, the entire field is not shown.
163 if ( ! $avif_fully_supported && ! $webp_supported ) {
164 ?>
165 <br>
166 <div class="notice notice-warning inline">
167 <p><b><?php esc_html_e( 'Modern image support is not available.', 'webp-uploads' ); ?></b></p>
168 <p><?php esc_html_e( 'WebP or AVIF support can only be enabled by your hosting provider, so contact them for more information.', 'webp-uploads' ); ?></p>
169 </div>
170 <?php
171 return;
172 }
173
174 // If only one of the two formats is supported, the dropdown defaults to that type and the other type is disabled.
175 if ( ! $avif_fully_supported && 'avif' === $selected ) {
176 $selected = 'webp';
177 } elseif ( ! $webp_supported && 'webp' === $selected ) {
178 $selected = 'avif';
179 }
180 ?>
181 <select name="perflab_modern_image_format" id="perflab_modern_image_format" aria-describedby="perflab_modern_image_format_description">
182 <option value="webp"<?php selected( 'webp', $selected ); ?><?php disabled( ! $webp_supported ); ?>><?php esc_html_e( 'WebP', 'webp-uploads' ); ?></option>
183 <option value="avif"<?php selected( 'avif', $selected ); ?><?php disabled( ! $avif_fully_supported ); ?>><?php esc_html_e( 'AVIF', 'webp-uploads' ); ?></option>
184 </select>
185 <label for="perflab_modern_image_format">
186 <?php esc_html_e( 'Generate images in this format', 'webp-uploads' ); ?>
187 </label>
188 <p class="description" id="perflab_modern_image_format_description">
189 <?php esc_html_e( 'Select the format to use when generating new images from uploaded images.', 'webp-uploads' ); ?>
190 <?php esc_html_e( 'Generated images may be discarded if the file in the modern format is larger than the originally uploaded image.', 'webp-uploads' ); ?>
191 </p>
192 <?php if ( ! $avif_supported ) : ?>
193 <br>
194 <div class="notice notice-warning inline">
195 <p><b><?php esc_html_e( 'AVIF support is not available.', 'webp-uploads' ); ?></b></p>
196 <p><?php esc_html_e( 'AVIF support can only be enabled by your hosting provider, so contact them for more information.', 'webp-uploads' ); ?></p>
197 </div>
198 <?php elseif ( ! $avif_transparency_supported ) : ?>
199 <br>
200 <div class="notice notice-warning inline">
201 <p><b><?php esc_html_e( 'AVIF is supported, but not fully: transparency support is lacking.', 'webp-uploads' ); ?></b></p>
202 <p><?php esc_html_e( 'Current ImageMagick version does not support transparent AVIF images, so contact your hosting provider for more information.', 'webp-uploads' ); ?></p>
203 </div>
204 <?php endif; ?>
205 <?php if ( ! $webp_supported ) : ?>
206 <br>
207 <div class="notice notice-warning inline">
208 <p><b><?php esc_html_e( 'WebP support is not available.', 'webp-uploads' ); ?></b></p>
209 <p><?php esc_html_e( 'WebP support can only be enabled by your hosting provider, so contact them for more information.', 'webp-uploads' ); ?></p>
210 </div>
211 <?php endif; ?>
212 <?php
213 }
214
215 /**
216 * Renders the settings field for the 'perflab_generate_webp_and_jpeg' setting.
217 *
218 * @since 1.0.0
219 */
220 function webp_uploads_generate_webp_jpeg_setting_callback(): void {
221 ?>
222 <label for="perflab_generate_webp_and_jpeg">
223 <input name="perflab_generate_webp_and_jpeg" type="checkbox" id="perflab_generate_webp_and_jpeg" aria-describedby="perflab_generate_webp_and_jpeg_description" value="1"<?php checked( '1', get_option( 'perflab_generate_webp_and_jpeg' ) ); ?> />
224 <?php esc_html_e( 'Also generate fallback images in the original upload format', 'webp-uploads' ); ?>
225 </label>
226 <p class="description" id="perflab_generate_webp_and_jpeg_description"><?php esc_html_e( 'Enabling fallback image output can improve compatibility, but will increase the filesystem storage use of your images.', 'webp-uploads' ); ?></p>
227 <?php
228 }
229
230
231 /**
232 * Renders the settings field for generating all fallback image sizes.
233 *
234 * @since 2.4.0
235 */
236 function webp_uploads_generate_all_fallback_sizes_callback(): void {
237 $all_fallback_sizes_enabled = webp_uploads_should_generate_all_fallback_sizes();
238 $fallback_enabled = webp_uploads_is_fallback_enabled();
239 $all_fallback_sizes_hidden_id = 'perflab_generate_all_fallback_sizes_hidden';
240
241 ?>
242 <style>
243 #perflab_generate_all_fallback_sizes_fieldset.disabled label,
244 #perflab_generate_all_fallback_sizes_fieldset.disabled p {
245 opacity: 0.7;
246 }
247 </style>
248 <div id="perflab_generate_all_fallback_sizes_notice" class="notice notice-info inline" <?php echo $fallback_enabled ? 'hidden' : ''; ?>>
249 <p><?php esc_html_e( 'This setting requires fallback image output to be enabled.', 'webp-uploads' ); ?></p>
250 </div>
251 <div id="perflab_generate_all_fallback_sizes_fieldset" class="<?php echo ! $fallback_enabled ? 'disabled' : ''; ?>">
252 <label for="perflab_generate_all_fallback_sizes" id="perflab_generate_all_fallback_sizes_label">
253 <input
254 type="checkbox"
255 id="perflab_generate_all_fallback_sizes"
256 name="perflab_generate_all_fallback_sizes"
257 aria-describedby="perflab_generate_all_fallback_sizes_description"
258 value="1"
259 <?php checked( $all_fallback_sizes_enabled ); ?>
260 <?php disabled( ! $fallback_enabled ); ?>
261 >
262 <?php
263 /*
264 * If the checkbox is disabled, but the option is enabled, include a hidden input to continue sending the
265 * same value upon form submission.
266 */
267 if ( ! $fallback_enabled && $all_fallback_sizes_enabled ) {
268 ?>
269 <input
270 type="hidden"
271 id="<?php echo esc_attr( $all_fallback_sizes_hidden_id ); ?>"
272 name="perflab_generate_all_fallback_sizes"
273 value="1"
274 >
275 <?php
276 }
277 esc_html_e( 'Generate all fallback image sizes including custom sizes', 'webp-uploads' );
278 ?>
279 </label>
280 <p class="description" id="perflab_generate_all_fallback_sizes_description"><?php esc_html_e( 'Enabling this option will generate all fallback image sizes including custom sizes. Note: uses even more storage space.', 'webp-uploads' ); ?></p>
281 </div>
282 <script>
283 ( function ( allFallbackSizesHiddenId ) {
284 const fallbackCheckbox = document.getElementById( 'perflab_generate_webp_and_jpeg' );
285 const allFallbackSizesCheckbox = document.getElementById( 'perflab_generate_all_fallback_sizes' );
286 const allFallbackSizesFieldset = document.getElementById( 'perflab_generate_all_fallback_sizes_fieldset' );
287 const allFallbackSizesNotice = document.getElementById( 'perflab_generate_all_fallback_sizes_notice' );
288
289 function toggleAllFallbackSizes() {
290 const fallbackEnabled = fallbackCheckbox.checked;
291 allFallbackSizesFieldset.classList.toggle( 'disabled', ! fallbackEnabled );
292 allFallbackSizesCheckbox.disabled = ! fallbackEnabled;
293 allFallbackSizesNotice.hidden = fallbackEnabled;
294
295 // Remove or inject hidden input to preserve original setting value as needed.
296 if ( fallbackEnabled ) {
297 const hiddenInput = document.getElementById( allFallbackSizesHiddenId );
298 if ( hiddenInput ) {
299 hiddenInput.parentElement.removeChild( hiddenInput );
300 }
301 } else if ( allFallbackSizesCheckbox.checked && ! document.getElementById( allFallbackSizesHiddenId ) ) {
302 // The hidden input is only needed if the value was originally set (i.e., the checkbox enabled).
303 const hiddenInput = document.createElement( 'input' );
304 hiddenInput.type = 'hidden';
305 hiddenInput.id = allFallbackSizesHiddenId;
306 hiddenInput.name = allFallbackSizesCheckbox.name;
307 hiddenInput.value = allFallbackSizesCheckbox.value;
308 allFallbackSizesCheckbox.parentElement.insertBefore( hiddenInput, allFallbackSizesCheckbox.nextSibling );
309 }
310 }
311
312 fallbackCheckbox.addEventListener( 'change', toggleAllFallbackSizes );
313 } )( <?php echo wp_json_encode( $all_fallback_sizes_hidden_id, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ); ?> );
314 </script>
315 <?php
316 }
317
318 /**
319 * Renders the settings field for the 'webp_uploads_use_picture_element' setting.
320 *
321 * @since 2.0.0
322 */
323 function webp_uploads_use_picture_element_callback(): void {
324 // Picture element support requires the JPEG output to be enabled.
325 $picture_element_option = 1 === (int) get_option( 'webp_uploads_use_picture_element', 0 );
326 $jpeg_fallback_enabled = webp_uploads_is_fallback_enabled();
327 $picture_element_hidden_id = 'webp_uploads_use_picture_element_hidden';
328 ?>
329 <style>
330 #webp_uploads_picture_element_fieldset.disabled label,
331 #webp_uploads_picture_element_fieldset.disabled p {
332 opacity: 0.7;
333 }
334 </style>
335 <div id="webp_uploads_picture_element_notice" class="notice notice-info inline" <?php echo $jpeg_fallback_enabled ? 'hidden' : ''; ?>>
336 <p><?php esc_html_e( 'This setting requires fallback image output to be enabled.', 'webp-uploads' ); ?></p>
337 </div>
338 <div id="webp_uploads_picture_element_fieldset" class="<?php echo ! $jpeg_fallback_enabled ? 'disabled' : ''; ?>">
339 <label for="webp_uploads_use_picture_element" id="webp_uploads_use_picture_element_label">
340 <input
341 type="checkbox"
342 id="webp_uploads_use_picture_element"
343 name="webp_uploads_use_picture_element"
344 aria-describedby="webp_uploads_use_picture_element_description"
345 value="1"
346 <?php checked( $picture_element_option ); // Option intentionally used instead of webp_uploads_is_picture_element_enabled() to persist when perflab_generate_webp_and_jpeg is updated. ?>
347 <?php disabled( ! $jpeg_fallback_enabled ); ?>
348 >
349 <?php
350 /*
351 * If the checkbox is disabled, but the option is enabled, include a hidden input to continue sending the
352 * same value upon form submission.
353 */
354 if ( ! $jpeg_fallback_enabled && $picture_element_option ) {
355 ?>
356 <input
357 type="hidden"
358 id="<?php echo esc_attr( $picture_element_hidden_id ); ?>"
359 name="webp_uploads_use_picture_element"
360 value="1"
361 >
362 <?php
363 }
364 esc_html_e( 'Use <picture> Element', 'webp-uploads' );
365 ?>
366 <em><?php esc_html_e( '(experimental)', 'webp-uploads' ); ?></em>
367 </label>
368 <p class="description" id="webp_uploads_use_picture_element_description"><?php esc_html_e( 'The picture element serves a modern image format with a fallback to the original upload format. Warning: Make sure you test your theme and plugins for compatibility. In particular, CSS selectors will not match images when using the child combinator (e.g. figure > img).', 'webp-uploads' ); ?></p>
369 <div id="webp_uploads_jpeg_fallback_notice" class="notice notice-info inline" <?php echo $picture_element_option ? '' : 'hidden'; ?>>
370 <p><?php esc_html_e( 'Picture elements will only be used when fallback images are available. So this will only apply to images you have uploaded while the "Also generate fallback images" setting was enabled.', 'webp-uploads' ); ?></p>
371 </div>
372 </div>
373 <script>
374 ( function ( pictureElementHiddenId ) {
375 document.getElementById( 'webp_uploads_use_picture_element' ).addEventListener( 'change', function () {
376 document.getElementById( 'webp_uploads_jpeg_fallback_notice' ).hidden = ! this.checked;
377 } );
378
379 // Listen for clicks on the fallback output checkbox, enabling/disabling the
380 // picture element checkbox accordingly.
381 document.getElementById( 'perflab_generate_webp_and_jpeg' ).addEventListener( 'change', function () {
382 document.querySelector( '.webp-uploads-use-picture-element' ).classList.toggle( 'webp-uploads-disabled', ! this.checked );
383 document.getElementById( 'webp_uploads_picture_element_notice' ).hidden = this.checked;
384 document.getElementById( 'webp_uploads_picture_element_fieldset' ).classList.toggle( 'disabled', ! this.checked );
385
386 const checkbox = document.getElementById( 'webp_uploads_use_picture_element' );
387 checkbox.disabled = ! this.checked;
388
389 // Remove or inject hidden input to preserve original setting value as needed.
390 if ( this.checked ) {
391 const hiddenInput = document.getElementById( pictureElementHiddenId );
392 if ( hiddenInput ) {
393 hiddenInput.parentElement.removeChild( hiddenInput );
394 }
395 } else if ( checkbox.checked && ! document.getElementById( pictureElementHiddenId ) ) {
396 // The hidden input is only needed if the value was originally set (i.e. the checkbox enabled).
397 const hiddenInput = document.createElement( 'input' );
398 hiddenInput.type = 'hidden';
399 hiddenInput.id = pictureElementHiddenId;
400 hiddenInput.name = checkbox.name;
401 hiddenInput.value = checkbox.value;
402 checkbox.parentElement.insertBefore( hiddenInput, checkbox.nextSibling );
403 }
404 } );
405 } )( <?php echo wp_json_encode( $picture_element_hidden_id, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ); ?> );
406 </script>
407 <?php
408 }
409
410 /**
411 * Adds a settings link to the plugin's action links.
412 *
413 * @since 1.1.0
414 * @since 1.1.1 Renamed from webp_uploads_settings_link() to webp_uploads_add_settings_action_link()
415 *
416 * @param string[]|mixed $links An array of plugin action links.
417 * @return string[]|mixed The modified list of actions.
418 */
419 function webp_uploads_add_settings_action_link( $links ) {
420 if ( ! is_array( $links ) ) {
421 return $links;
422 }
423
424 $settings_link = sprintf(
425 '<a href="%1$s">%2$s</a>',
426 esc_url( admin_url( 'options-media.php#modern-image-formats' ) ),
427 esc_html__( 'Settings', 'webp-uploads' )
428 );
429
430 return array_merge(
431 array( 'settings' => $settings_link ),
432 $links
433 );
434 }
435 add_filter( 'plugin_action_links_' . WEBP_UPLOADS_MAIN_FILE, 'webp_uploads_add_settings_action_link' );
436