PluginProbe
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF / 2.2.2
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF v2.2.2
2.3.4 2.3.3 2.3.2 2.3.1 2.3.0 2.2.9 2.2.8 trunk 1.10 1.3.3 1.3.4 1.3.5 1.3.5.1 1.3.5.2 1.3.6 1.3.6.1 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.5 All 103 releases
imagify / inc / classes / class-imagify-settings.php

class-imagify-settings.php in Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF 2.2.2, at inc/classes/class-imagify-settings.php

995 lines 29.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 use Imagify\Notices\Notices;
3
4 /**
5 * Class that handles the plugin settings.
6 *
7 * @since 1.7
8 */
9 class Imagify_Settings {
10
11 /**
12 * Class version.
13 *
14 * @since 1.7
15 * @var string
16 */
17 const VERSION = '1.0.1';
18
19 /**
20 * The settings group.
21 *
22 * @since 1.7
23 * @var string
24 */
25 protected $settings_group;
26
27 /**
28 * The option name.
29 *
30 * @since 1.7
31 * @var string
32 */
33 protected $option_name;
34
35 /**
36 * The options instance.
37 *
38 * @since 1.7
39 * @var object
40 */
41 protected $options;
42
43 /**
44 * The single instance of the class.
45 *
46 * @since 1.7
47 * @var object
48 */
49 protected static $_instance;
50
51 /**
52 * The constructor.
53 *
54 * @since 1.7
55 */
56 protected function __construct() {
57 $this->options = Imagify_Options::get_instance();
58 $this->option_name = $this->options->get_option_name();
59 $this->settings_group = IMAGIFY_SLUG;
60 }
61
62 /**
63 * Get the main Instance.
64 *
65 * @since 1.7
66 * @return object Main instance.
67 */
68 public static function get_instance() {
69 if ( ! isset( self::$_instance ) ) {
70 self::$_instance = new self();
71 }
72
73 return self::$_instance;
74 }
75
76 /**
77 * Launch the hooks.
78 *
79 * @since 1.7
80 */
81 public function init() {
82 add_filter( 'sanitize_option_' . $this->option_name, [ $this, 'populate_values_on_save' ], 5 );
83 add_action( 'admin_init', [ $this, 'register' ] );
84 add_filter( 'option_page_capability_' . $this->settings_group, [ $this, 'get_capability' ] );
85
86 if ( imagify_is_active_for_network() ) {
87 add_filter( 'pre_update_site_option_' . $this->option_name, [
88 $this,
89 'maybe_set_redirection',
90 ], 10, 2 );
91 add_action( 'update_site_option_' . $this->option_name, [
92 $this,
93 'after_save_network_options',
94 ], 10, 3 );
95 add_action( 'admin_post_update', [ $this, 'update_site_option_on_network' ] );
96 } else {
97 add_filter( 'pre_update_option_' . $this->option_name, [ $this, 'maybe_set_redirection' ], 10, 2 );
98 add_action( 'update_option_' . $this->option_name, [ $this, 'after_save_options' ], 10, 2 );
99 }
100 }
101
102
103 /** ----------------------------------------------------------------------------------------- */
104 /** VARIOUS HELPERS ========================================================================= */
105 /** ----------------------------------------------------------------------------------------- */
106
107 /**
108 * Get the name of the settings group.
109 *
110 * @since 1.7
111 * @return string
112 */
113 public function get_settings_group() {
114 return $this->settings_group;
115 }
116
117 /**
118 * Get the URL to use as form action.
119 *
120 * @since 1.7
121 * @return string
122 */
123 public function get_form_action() {
124 return imagify_is_active_for_network() ? admin_url( 'admin-post.php' ) : admin_url( 'options.php' );
125 }
126
127 /**
128 * Tell if we're submitting the settings form.
129 *
130 * @since 1.7
131 * @return bool
132 */
133 public function is_form_submit() {
134 if ( ! isset( $_POST['option_page'], $_POST['action'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
135 return false;
136 }
137
138 return htmlspecialchars( wp_unslash( $_POST['option_page'] ) ) === $this->settings_group && htmlspecialchars( wp_unslash( $_POST['action'] ) ) === 'update'; // phpcs:ignore WordPress.Security.NonceVerification.Missing
139 }
140
141 /** ----------------------------------------------------------------------------------------- */
142 /** ON FORM SUBMIT ========================================================================== */
143 /** ----------------------------------------------------------------------------------------- */
144
145 /**
146 * On form submit, handle some specific values.
147 * This must be hooked before Imagify_Options::sanitize_and_validate_on_update().
148 *
149 * @since 1.7
150 *
151 * @param array $values The option values.
152 *
153 * @return array
154 */
155 public function populate_values_on_save( $values ) {
156 if ( ! $this->is_form_submit() ) {
157 return $values;
158 }
159
160 $values = is_array( $values ) ? $values : [];
161
162 /**
163 * Disabled thumbnail sizes.
164 */
165 $values = $this->populate_disallowed_sizes( $values );
166
167 /**
168 * Custom folders.
169 */
170 $values = $this->populate_custom_folders( $values );
171
172 /**
173 * Filter settings when saved via the settings page.
174 *
175 * @since 1.9
176 *
177 * @param array $values The option values.
178 */
179 $values = apply_filters( 'imagify_settings_on_save', $values );
180
181 return (array) $values;
182 }
183
184 /**
185 * On form submit, handle disallowed thumbnail sizes.
186 *
187 * @since 1.7
188 *
189 * @param array $values The option values.
190 *
191 * @return array
192 */
193 protected function populate_disallowed_sizes( $values ) {
194 $values['disallowed-sizes'] = [];
195
196 if ( isset( $values['disallowed-sizes-reversed'] ) && is_array( $values['disallowed-sizes-reversed'] ) ) {
197 $checked = ! empty( $values['disallowed-sizes-checked'] ) && is_array( $values['disallowed-sizes-checked'] ) ? array_flip( $values['disallowed-sizes-checked'] ) : [];
198
199 if ( ! empty( $values['disallowed-sizes-reversed'] ) ) {
200 foreach ( $values['disallowed-sizes-reversed'] as $size_key ) {
201 if ( ! isset( $checked[ $size_key ] ) ) {
202 // The checkbox is not checked: the size is disabled.
203 $values['disallowed-sizes'][ $size_key ] = 1;
204 }
205 }
206 }
207 }
208
209 unset( $values['disallowed-sizes-reversed'], $values['disallowed-sizes-checked'] );
210
211 return $values;
212 }
213
214 /**
215 * On form submit, handle the custom folders.
216 *
217 * @since 1.7
218 *
219 * @param array $values The option values.
220 *
221 * @return array
222 */
223 protected function populate_custom_folders( $values ) {
224 if ( ! imagify_can_optimize_custom_folders() ) {
225 // The databases are not ready or the user has not the permission.
226 unset( $values['custom_folders'] );
227
228 return $values;
229 }
230
231 if ( ! isset( $values['custom_folders'] ) ) {
232 // No selected folders: set them all inactive.
233 Imagify_Custom_Folders::deactivate_all_folders();
234 // Remove files that are in inactive folders and are not optimized.
235 Imagify_Custom_Folders::remove_unoptimized_files_from_inactive_folders();
236 // Remove empty inactive folders.
237 Imagify_Custom_Folders::remove_empty_inactive_folders();
238
239 return $values;
240 }
241
242 if ( ! is_array( $values['custom_folders'] ) ) {
243 // Invalid value.
244 unset( $values['custom_folders'] );
245
246 return $values;
247 }
248
249 $selected = array_filter( $values['custom_folders'] );
250 unset( $values['custom_folders'] );
251
252 if ( ! $selected ) {
253 // No selected folders: set them all inactive.
254 Imagify_Custom_Folders::deactivate_all_folders();
255 // Remove files that are in inactive folders and are not optimized.
256 Imagify_Custom_Folders::remove_unoptimized_files_from_inactive_folders();
257 // Remove empty inactive folders.
258 Imagify_Custom_Folders::remove_empty_inactive_folders();
259
260 return $values;
261 }
262
263 // Normalize the paths, remove duplicates, and remove sub-paths.
264 $selected = array_map( 'sanitize_text_field', $selected );
265 $selected = array_map( 'wp_normalize_path', $selected );
266 $selected = array_map( 'trailingslashit', $selected );
267 $selected = array_flip( array_flip( $selected ) );
268 $selected = Imagify_Custom_Folders::remove_sub_paths( $selected );
269
270 // Remove the active status from the folders that are not selected.
271 Imagify_Custom_Folders::deactivate_not_selected_folders( $selected );
272
273 // Add the active status to the folders that are selected (and already in the DB).
274 $selected = Imagify_Custom_Folders::activate_selected_folders( $selected );
275
276 // If we still have paths here, they need to be added to the DB with an active status.
277 Imagify_Custom_Folders::insert_folders( $selected );
278
279 // Remove files that are in inactive folders and are not optimized.
280 Imagify_Custom_Folders::remove_unoptimized_files_from_inactive_folders();
281
282 // Reassign files to active folders.
283 Imagify_Custom_Folders::reassign_inactive_files();
284
285 // Remove empty inactive folders.
286 Imagify_Custom_Folders::remove_empty_inactive_folders();
287
288 return $values;
289 }
290
291
292 /** ----------------------------------------------------------------------------------------- */
293 /** SETTINGS API ============================================================================ */
294 /** ----------------------------------------------------------------------------------------- */
295
296 /**
297 * Add Imagify' settings to the settings API whitelist.
298 *
299 * @since 1.7
300 */
301 public function register() {
302 register_setting( $this->settings_group, $this->option_name );
303 }
304
305 /**
306 * Set the user capacity needed to save Imagify's main options from the settings page.
307 *
308 * @since 1.7
309 */
310 public function get_capability() {
311 return imagify_get_context( 'wp' )->get_capacity( 'manage' );
312 }
313
314 /**
315 * If the user clicked the "Save & Go to Bulk Optimizer" button, set a redirection to the bulk optimizer.
316 * We use this hook because it can be triggered even if the option value hasn't changed.
317 *
318 * @since 1.7
319 *
320 * @param mixed $value The new, unserialized option value.
321 * @param mixed $old_value The old option value.
322 *
323 * @return mixed The option value.
324 */
325 public function maybe_set_redirection( $value, $old_value ) {
326 if ( isset( $_POST['submit-goto-bulk'] ) ) { // WPCS: CSRF ok.
327 $_REQUEST['_wp_http_referer'] = esc_url_raw( get_admin_url( get_current_blog_id(), 'upload.php?page=imagify-bulk-optimization' ) );
328 }
329
330 return $value;
331 }
332
333 /**
334 * Used to launch some actions after saving the network options.
335 *
336 * @since 1.7
337 *
338 * @param string $option Name of the network option.
339 * @param mixed $value Current value of the network option.
340 * @param mixed $old_value Old value of the network option.
341 */
342 public function after_save_network_options( $option, $value, $old_value ) {
343 $this->after_save_options( $old_value, $value );
344 }
345
346 /**
347 * Used to launch some actions after saving the options.
348 *
349 * @since 1.7
350 *
351 * @param mixed $old_value The old option value.
352 * @param mixed $value The new option value.
353 */
354 public function after_save_options( $old_value, $value ) {
355 $old_key = isset( $old_value['api_key'] ) ? $old_value['api_key'] : '';
356 $new_key = isset( $value['api_key'] ) ? $value['api_key'] : '';
357
358 if ( $old_key === $new_key ) {
359 return;
360 }
361
362 // Handle API key validation cache and notices.
363 if ( Imagify_Requirements::is_api_key_valid( true ) ) {
364 Notices::dismiss_notice( 'wrong-api-key' );
365 } else {
366 Notices::renew_notice( 'wrong-api-key' );
367 }
368 }
369
370 /**
371 * `options.php` does not handle network options. Let's use `admin-post.php` for multisite installations.
372 *
373 * @since 1.9.11 deprecate 'whitelist_options' filter.
374 * @since 1.7
375 *
376 * @return void
377 */
378 public function update_site_option_on_network() {
379 global $wp_version;
380
381 if ( empty( $_POST['option_page'] ) || $_POST['option_page'] !== $this->settings_group ) { // WPCS: CSRF ok.
382 return;
383 }
384
385 /** This filter is documented in /wp-admin/options.php. */
386 $capability = apply_filters( 'option_page_capability_' . $this->settings_group, 'manage_network_options' );
387
388 if ( ! current_user_can( $capability ) ) {
389 imagify_die();
390
391 return;
392 }
393
394 if ( ! imagify_check_nonce( $this->settings_group . '-options' ) ) {
395 return;
396 }
397
398 if ( version_compare( $wp_version, '5.5', '>=' ) ) {
399 $allowed_options = apply_filters_deprecated(
400 'whitelist_options',
401 [ [] ],
402 '5.5.0',
403 'allowed_options',
404 __( 'Please consider writing more inclusive code.' )
405 );
406 } else {
407 $allowed_options = apply_filters( 'whitelist_options', [] );
408 }
409
410 $allowed_options = apply_filters( 'allowed_options', $allowed_options );
411
412 if ( ! isset( $allowed_options[ $this->settings_group ] ) ) {
413 imagify_die( __( '<strong>ERROR</strong>: options page not found.' ) );
414
415 return;
416 }
417
418 $options = $allowed_options[ $this->settings_group ];
419
420 if ( $options ) {
421 foreach ( $options as $option ) {
422 $option = trim( $option );
423 $value = null;
424
425 if ( isset( $_POST[ $option ] ) ) {
426 $value = wp_unslash( $_POST[ $option ] );
427 if ( ! is_array( $value ) ) {
428 $value = trim( $value );
429 }
430 $value = wp_unslash( $value );
431 }
432
433 update_site_option( $option, $value );
434 }
435 }
436
437 /**
438 * Redirect back to the settings page that was submitted.
439 */
440 imagify_maybe_redirect( false, [ 'settings-updated' => 'true' ] );
441 }
442
443
444 /** ----------------------------------------------------------------------------------------- */
445 /** FIELDS ================================================================================== */
446 /** ----------------------------------------------------------------------------------------- */
447
448 /**
449 * Display a single checkbox.
450 *
451 * @since 1.7
452 *
453 * @param array $args Arguments:
454 * {option_name} string The option name. E.g. 'disallowed-sizes'. Mandatory.
455 * {label} string The label to use.
456 * {info} string Text to display in an "Info box" after the field. A 'aria-describedby' attribute will automatically be created.
457 * {attributes} array A list of HTML attributes, as 'attribute' => 'value'.
458 * {current_value} int|bool USE ONLY WHEN DEALING WITH DATA THAT IS NOT SAVED IN THE PLUGIN OPTIONS. If not provided, the field will automatically get the value from the options.
459 */
460 public function field_checkbox( $args ) {
461 $args = array_merge( [
462 'option_name' => '',
463 'label' => '',
464 'info' => '',
465 'attributes' => [],
466 // To not use the plugin settings: use an integer.
467 'current_value' => null,
468 ], $args );
469
470 if ( ! $args['option_name'] || ! $args['label'] ) {
471 return;
472 }
473
474 if ( is_numeric( $args['current_value'] ) || is_bool( $args['current_value'] ) ) {
475 // We don't use the plugin settings.
476 $current_value = (int) (bool) $args['current_value'];
477 } else {
478 // This is a normal plugin setting.
479 $current_value = $this->options->get( $args['option_name'] );
480 }
481
482 $option_name_class = sanitize_html_class( $args['option_name'] );
483 $attributes = [
484 'name' => $this->option_name . '[' . $args['option_name'] . ']',
485 'id' => 'imagify_' . $option_name_class,
486 ];
487
488 if ( $args['info'] && empty( $attributes['aria-describedby'] ) ) {
489 $attributes['aria-describedby'] = 'describe-' . $option_name_class;
490 }
491
492 $attributes = array_merge( $attributes, $args['attributes'] );
493 $args['attributes'] = self::build_attributes( $attributes );
494 ?>
495 <input type="checkbox" value="1" <?php
496 checked( $current_value, 1 );
497 ?><?php
498 echo $args['attributes'];
499 ?> />
500 <!-- Empty onclick attribute to make clickable labels on iTruc & Mac -->
501 <label for="<?php
502 echo $attributes['id'];
503 ?>" onclick=""><?php
504 echo $args['label'];
505 ?></label>
506 <?php
507 if ( ! $args['info'] ) {
508 return;
509 }
510 ?>
511 <span id="<?php
512 echo $attributes['aria-describedby'];
513 ?>" class="imagify-info">
514 <span class="dashicons dashicons-info"></span>
515 <?php
516 echo $args['info'];
517 ?>
518 </span>
519 <?php
520 }
521
522 /**
523 * Display a checkbox group.
524 *
525 * @since 1.7
526 *
527 * @param array $args Arguments:
528 * {option_name} string The option name. E.g. 'disallowed-sizes'. Mandatory.
529 * {legend} string Label to use for the <legend> tag.
530 * {values} array List of values to display, in the form of 'value' => 'Label'. Mandatory.
531 * {disabled_values} array Values to be disabled. Values are the array keys.
532 * {reverse_check} bool If true, the values that will be stored in the option are the ones that are unchecked. It requires special treatment when saving (detect what values are unchecked).
533 * {attributes} array A list of HTML attributes, as 'attribute' => 'value'.
534 * {current_values} array USE ONLY WHEN DEALING WITH DATA THAT IS NOT SAVED IN THE PLUGIN OPTIONS. If not provided, the field will automatically get the value from the options.
535 */
536 public function field_checkbox_list( $args ) {
537 $args = array_merge( [
538 'option_name' => '',
539 'legend' => '',
540 'values' => [],
541 'disabled_values' => [],
542 'reverse_check' => false,
543 'attributes' => [],
544 // To not use the plugin settings: use an array.
545 'current_values' => false,
546 ], $args );
547
548 if ( ! $args['option_name'] || ! $args['values'] ) {
549 return;
550 }
551
552 if ( is_array( $args['current_values'] ) ) {
553 // We don't use the plugin settings.
554 $current_values = $args['current_values'];
555 } else {
556 // This is a normal plugin setting.
557 $current_values = $this->options->get( $args['option_name'] );
558 }
559
560 $option_name_class = sanitize_html_class( $args['option_name'] );
561 $attributes = array_merge( [
562 'name' => $this->option_name . '[' . $args['option_name'] . ( $args['reverse_check'] ? '-checked' : '' ) . '][]',
563 'id' => 'imagify_' . $option_name_class . '_%s',
564 'class' => 'imagify-row-check',
565 ], $args['attributes'] );
566
567 $id_attribute = $attributes['id'];
568 unset( $attributes['id'] );
569 $args['attributes'] = self::build_attributes( $attributes );
570
571 $current_values = array_diff_key( $current_values, $args['disabled_values'] );
572 $nb_of_values = count( $args['values'] );
573 $display_check_all = $nb_of_values > 3;
574 $nb_of_checked = 0;
575 ?>
576 <fieldset class="imagify-check-group<?php
577 echo $nb_of_values > 5 ? ' imagify-is-scrollable' : '';
578 ?>">
579 <?php
580 if ( $args['legend'] ) {
581 ?>
582 <legend class="screen-reader-text"><?php
583 echo $args['legend'];
584 ?></legend>
585 <?php
586 }
587
588 foreach ( $args['values'] as $value => $label ) {
589 $input_id = sprintf( $id_attribute, sanitize_html_class( $value ) );
590 $disabled = isset( $args['disabled_values'][ $value ] );
591
592 if ( $args['reverse_check'] ) {
593 $checked = ! $disabled && ! isset( $current_values[ $value ] );
594 } else {
595 $checked = ! $disabled && isset( $current_values[ $value ] );
596 }
597
598 $nb_of_checked = $checked ? $nb_of_checked + 1 : $nb_of_checked;
599
600 if ( $args['reverse_check'] ) {
601 echo '<input type="hidden" name="' . $this->option_name . '[' . $args['option_name'] . '-reversed][]" value="' . esc_attr( $value ) . '" />';
602 }
603 ?>
604 <p>
605 <input type="checkbox" value="<?php
606 echo esc_attr( $value );
607 ?>" id="<?php
608 echo $input_id;
609 ?>"<?php
610 echo $args['attributes'];
611 ?> <?php
612 checked( $checked );
613 ?> <?php
614 disabled( $disabled );
615 ?>/>
616 <label for="<?php
617 echo $input_id;
618 ?>" onclick=""><?php
619 echo $label;
620 ?></label>
621 </p>
622 <?php
623 }
624 ?>
625 </fieldset>
626 <?php
627 if ( $display_check_all ) {
628 if ( $args['reverse_check'] ) {
629 $all_checked = ! array_intersect_key( $args['values'], $current_values );
630 } else {
631 $all_checked = ! array_diff_key( $args['values'], $current_values );
632 }
633 ?>
634 <p class="hide-if-no-js imagify-select-all-buttons">
635 <button type="button" class="imagify-link-like imagify-select-all<?php
636 echo $all_checked ? ' imagify-is-inactive" aria-disabled="true' : '';
637 ?>" data-action="select"><?php
638 _e( 'Select All', 'imagify' );
639 ?></button>
640
641 <span class="imagify-pipe"></span>
642
643 <button type="button" class="imagify-link-like imagify-select-all<?php
644 echo $nb_of_checked ? '' : ' imagify-is-inactive" aria-disabled="true';
645 ?>" data-action="unselect"><?php
646 _e( 'Unselect All', 'imagify' );
647 ?></button>
648 </p>
649 <?php
650 }
651 }
652
653 /**
654 * Display a radio list group.
655 *
656 * @since 1.9
657 *
658 * @param array $args {
659 * Arguments.
660 *
661 * @type string $option_name The option name. E.g. 'disallowed-sizes'. Mandatory.
662 * @type string $legend Label to use for the <legend> tag.
663 * @type string $info Text to display in an "Info box" after the field. A 'aria-describedby' attribute will automatically be created.
664 * @type array $values List of values to display, in the form of 'value' => 'Label'. Mandatory.
665 * @type array $attributes A list of HTML attributes, as 'attribute' => 'value'.
666 * @type array $current_value USE ONLY WHEN DEALING WITH DATA THAT IS NOT SAVED IN THE PLUGIN OPTIONS. If not provided, the field will automatically get the value from the options.
667 * }
668 */
669 public function field_radio_list( $args ) {
670 $args = array_merge( [
671 'option_name' => '',
672 'legend' => '',
673 'info' => '',
674 'values' => [],
675 'attributes' => [],
676 // To not use the plugin settings: use an array.
677 'current_value' => false,
678 ], $args );
679
680 if ( ! $args['option_name'] || ! $args['values'] ) {
681 return;
682 }
683
684 if ( is_array( $args['current_value'] ) ) {
685 // We don't use the plugin settings.
686 $current_value = $args['current_value'];
687 } else {
688 // This is a normal plugin setting.
689 $current_value = $this->options->get( $args['option_name'] );
690 }
691
692 $option_name_class = sanitize_html_class( $args['option_name'] );
693 $attributes = array_merge( [
694 'name' => $this->option_name . '[' . $args['option_name'] . ']',
695 'id' => 'imagify_' . $option_name_class . '_%s',
696 'class' => 'imagify-row-radio',
697 ], $args['attributes'] );
698
699 $id_attribute = $attributes['id'];
700 unset( $attributes['id'] );
701 $args['attributes'] = self::build_attributes( $attributes );
702 ?>
703 <fieldset class="imagify-radio-group">
704 <?php
705 if ( $args['legend'] ) {
706 ?>
707 <legend class="screen-reader-text"><?php
708 echo $args['legend'];
709 ?></legend>
710 <?php
711 }
712
713 foreach ( $args['values'] as $value => $label ) {
714 $input_id = sprintf( $id_attribute, sanitize_html_class( $value ) );
715 ?>
716 <input type="radio" value="<?php
717 echo esc_attr( $value );
718 ?>" id="<?php
719 echo $input_id;
720 ?>"<?php
721 echo $args['attributes'];
722 ?> <?php
723 checked( $current_value, $value );
724 ?>/>
725 <label for="<?php
726 echo $input_id;
727 ?>" onclick=""><?php
728 echo $label;
729 ?></label>
730 <br/>
731 <?php
732 }
733 ?>
734 </fieldset>
735 <?php
736 if ( ! $args['info'] ) {
737 return;
738 }
739 ?>
740 <span id="<?php
741 echo $attributes['aria-describedby'];
742 ?>" class="imagify-info">
743 <span class="dashicons dashicons-info"></span>
744 <?php
745 echo $args['info'];
746 ?>
747 </span>
748 <?php
749 }
750
751 /**
752 * Display styled radio list group.
753 *
754 * @param array $args Arguments:
755 * {option_name} string The option name. E.g. 'disallowed-sizes'. Mandatory.
756 * {values} array List of values to display, in the form of 'value' => 'Label'. Mandatory.
757 * {attributes} array A list of HTML attributes, as 'attribute' => 'value'.
758 * {current_value} int|bool USE ONLY WHEN DEALING WITH DATA THAT IS NOT SAVED IN THE PLUGIN OPTIONS. If not provided, the field will automatically get the value from the options.
759 *
760 * @return void
761 */
762 public function field_inline_radio_list( $args ) {
763 $args = array_merge(
764 [
765 'option_name' => '',
766 'values' => [],
767 'info' => '',
768 'attributes' => [],
769 'current_value' => false,
770 ],
771 $args
772 );
773
774 if ( ! $args['option_name'] || ! $args['values'] ) {
775 return;
776 }
777
778 if ( is_numeric( $args['current_value'] ) || is_string( $args['current_value'] ) ) {
779 $current_value = $args['current_value'];
780 } else {
781 $current_value = $this->options->get( $args['option_name'] );
782 }
783
784 $option_name_class = sanitize_html_class( $args['option_name'] );
785 $attributes = array_merge( [
786 'name' => $this->option_name . '[' . $args['option_name'] . ']',
787 'id' => 'imagify_' . $option_name_class . '_%s',
788 'class' => 'imagify-row-radio',
789 ], $args['attributes'] );
790
791 $id_attribute = $attributes['id'];
792 unset( $attributes['id'] );
793 $args['attributes'] = self::build_attributes( $attributes );
794 ?>
795 <div class="imagify-setting-optim-level">
796 <p class="imagify-inline-options imagify-inline-options-<?php echo esc_attr( $args['info_class'] ); ?>">
797 <?php
798 foreach ( $args['values'] as $value => $label ) {
799 $input_id = sprintf( $id_attribute, sanitize_html_class( $value ) );
800 ?>
801 <input type="radio" value="<?php echo esc_attr( $value ); ?>" id="<?php echo $input_id; ?>"<?php echo $args['attributes']; ?> <?php checked( $current_value, $value ); ?> />
802 <label for="<?php echo $input_id; ?>" onclick=""><?php echo $label; ?></label>
803 <?php
804 }
805 ?>
806 </p>
807 <span id="<?php
808 echo $attributes['aria-describedby'];
809 ?>" class="imagify-<?php echo esc_attr( $args['info_class'] ); ?>">
810 <span class="dashicons dashicons-info"></span>
811 <?php
812 echo $args['info'];
813 ?>
814 </span>
815 </div>
816 <?php
817 }
818
819 /**
820 * Display a text box.
821 *
822 * @since 1.9.3
823 *
824 * @param array $args Arguments:
825 * {option_name} string The option name. E.g. 'disallowed-sizes'. Mandatory.
826 * {label} string The label to use.
827 * {info} string Text to display in an "Info box" after the field. A 'aria-describedby' attribute will automatically be created.
828 * {attributes} array A list of HTML attributes, as 'attribute' => 'value'.
829 * {current_value} int|bool USE ONLY WHEN DEALING WITH DATA THAT IS NOT SAVED IN THE PLUGIN OPTIONS. If not provided, the field will automatically get the value from the options.
830 */
831 public function field_text_box( $args ) {
832 $args = array_merge( [
833 'option_name' => '',
834 'label' => '',
835 'info' => '',
836 'attributes' => [],
837 // To not use the plugin settings.
838 'current_value' => null,
839 ], $args );
840
841 if ( ! $args['option_name'] || ! $args['label'] ) {
842 return;
843 }
844
845 if ( is_numeric( $args['current_value'] ) || is_string( $args['current_value'] ) ) {
846 // We don't use the plugin settings.
847 $current_value = $args['current_value'];
848 } else {
849 // This is a normal plugin setting.
850 $current_value = $this->options->get( $args['option_name'] );
851 }
852
853 $option_name_class = sanitize_html_class( $args['option_name'] );
854 $attributes = [
855 'name' => $this->option_name . '[' . $args['option_name'] . ']',
856 'id' => 'imagify_' . $option_name_class,
857 ];
858
859 if ( $args['info'] && empty( $attributes['aria-describedby'] ) ) {
860 $attributes['aria-describedby'] = 'describe-' . $option_name_class;
861 }
862
863 $attributes = array_merge( $attributes, $args['attributes'] );
864 $args['attributes'] = self::build_attributes( $attributes );
865 ?>
866 <!-- Empty onclick attribute to make clickable labels on iTruc & Mac -->
867 <label for="<?php
868 echo $attributes['id'];
869 ?>" onclick=""><?php
870 echo $args['label'];
871 ?></label>
872 <input type="text" value="<?php
873 echo esc_attr( $current_value );
874 ?>"<?php
875 echo $args['attributes'];
876 ?> />
877 <?php
878 if ( ! $args['info'] ) {
879 return;
880 }
881 ?>
882 <span id="<?php
883 echo $attributes['aria-describedby'];
884 ?>" class="imagify-info">
885 <span class="dashicons dashicons-info"></span>
886 <?php
887 echo $args['info'];
888 ?>
889 </span>
890 <?php
891 }
892
893 /**
894 * Display a simple hidden input.
895 *
896 * @since 1.9.3
897 *
898 * @param array $args Arguments:
899 * {option_name} string The option name. E.g. 'disallowed-sizes'. Mandatory.
900 * {attributes} array A list of HTML attributes, as 'attribute' => 'value'.
901 * {current_value} int|bool USE ONLY WHEN DEALING WITH DATA THAT IS NOT SAVED IN THE PLUGIN OPTIONS. If not provided, the field will automatically get the value from the options.
902 */
903 public function field_hidden( $args ) {
904 $args = array_merge( [
905 'option_name' => '',
906 'attributes' => [],
907 // To not use the plugin settings.
908 'current_value' => null,
909 ], $args );
910
911 if ( ! $args['option_name'] ) {
912 return;
913 }
914
915 if ( is_numeric( $args['current_value'] ) || is_string( $args['current_value'] ) ) {
916 // We don't use the plugin settings.
917 $current_value = $args['current_value'];
918 } else {
919 // This is a normal plugin setting.
920 $current_value = $this->options->get( $args['option_name'] );
921 }
922
923 $option_name_class = sanitize_html_class( $args['option_name'] );
924 $attributes = [
925 'name' => $this->option_name . '[' . $args['option_name'] . ']',
926 'id' => 'imagify_' . $option_name_class,
927 ];
928
929 $attributes = array_merge( $attributes, $args['attributes'] );
930 $args['attributes'] = self::build_attributes( $attributes );
931 ?>
932 <input type="hidden" value="<?php
933 echo esc_attr( $current_value );
934 ?>"<?php
935 echo $args['attributes'];
936 ?> />
937 <?php
938 }
939
940
941 /** ----------------------------------------------------------------------------------------- */
942 /** FIELD VALUES ============================================================================ */
943 /** ----------------------------------------------------------------------------------------- */
944
945 /**
946 * Get the thumbnail sizes.
947 *
948 * @since 1.7
949 * @return array A list of thumbnail sizes in the form of 'medium' => 'medium - 300 × 300'.
950 */
951 public static function get_thumbnail_sizes() {
952 static $sizes;
953
954 if ( isset( $sizes ) ) {
955 return $sizes;
956 }
957
958 $sizes = get_imagify_thumbnail_sizes();
959
960 foreach ( $sizes as $size_key => $size_data ) {
961 $sizes[ $size_key ] = sprintf( '%s - %d &times; %d', esc_html( stripslashes( $size_data['name'] ) ), $size_data['width'], $size_data['height'] );
962 }
963
964 return $sizes;
965 }
966
967
968 /** ----------------------------------------------------------------------------------------- */
969 /** TOOLS =================================================================================== */
970 /** ----------------------------------------------------------------------------------------- */
971
972 /**
973 * Create HTML attributes from an array.
974 *
975 * @since 1.7
976 *
977 * @param array $attributes A list of attribute pairs.
978 *
979 * @return string HTML attributes.
980 */
981 public static function build_attributes( $attributes ) {
982 if ( ! $attributes || ! is_array( $attributes ) ) {
983 return '';
984 }
985
986 $out = '';
987
988 foreach ( $attributes as $attribute => $value ) {
989 $out .= ' ' . $attribute . '="' . esc_attr( $value ) . '"';
990 }
991
992 return $out;
993 }
994 }
995