PluginProbe ʕ •ᴥ•ʔ
TinyPNG – JPEG, PNG & WebP image compression / 3.6.8
TinyPNG – JPEG, PNG & WebP image compression v3.6.8
3.7.0 3.6.14 trunk 1.0.0 1.1.0 1.2.0 1.2.1 1.3.0 1.3.1 1.3.2 1.4.0 1.5.0 1.6.0 1.7.0 1.7.1 1.7.2 2.0.0 2.0.1 2.0.2 2.1.0 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 3.0.0 3.0.1 3.1.0 3.2.0 3.2.1 3.3 3.4 3.4.1 3.4.2 3.4.4 3.4.5 3.4.6 3.5.0 3.5.1 3.5.2 3.6.0 3.6.1 3.6.10 3.6.11 3.6.12 3.6.13 3.6.2 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.6.8 3.6.9
tiny-compress-images / src / class-tiny-settings.php
tiny-compress-images / src Last commit date
compatibility 5 months ago config 5 months ago css 5 months ago data 4 years ago images 4 years ago js 5 months ago vendor 1 year ago views 5 months ago class-tiny-bulk-optimization.php 5 months ago class-tiny-cli.php 5 months ago class-tiny-compress-client.php 5 months ago class-tiny-compress-fopen.php 5 months ago class-tiny-compress.php 5 months ago class-tiny-diagnostics.php 5 months ago class-tiny-exception.php 5 months ago class-tiny-helpers.php 5 months ago class-tiny-image-size.php 5 months ago class-tiny-image.php 5 months ago class-tiny-logger.php 5 months ago class-tiny-notices.php 5 months ago class-tiny-php.php 5 months ago class-tiny-picture.php 5 months ago class-tiny-plugin.php 5 months ago class-tiny-settings.php 5 months ago class-tiny-source-base.php 5 months ago class-tiny-source-image.php 5 months ago class-tiny-source-picture.php 5 months ago class-tiny-wp-base.php 5 months ago
class-tiny-settings.php
1113 lines
1 <?php
2 /*
3 * Tiny Compress Images - WordPress plugin.
4 * Copyright (C) 2015-2018 Tinify B.V.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc., 51
18 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20 class Tiny_Settings extends Tiny_WP_Base {
21
22
23 const DUMMY_SIZE = '_tiny_dummy';
24
25 private $sizes;
26 private $tinify_sizes;
27 private $compressor;
28 private $notices;
29
30 public function __construct() {
31 parent::__construct();
32 $this->notices = new Tiny_Notices();
33 new Tiny_Diagnostics( $this );
34 }
35
36 private function init_compressor() {
37 $this->compressor = Tiny_Compress::create(
38 $this->get_api_key(),
39 $this->get_method( 'after_compress_callback' )
40 );
41 }
42
43 public function get_absolute_url() {
44 return get_admin_url( null, 'options-general.php?page=tinify' );
45 }
46
47 public function xmlrpc_init() {
48 try {
49 $this->init_compressor();
50 } catch ( Tiny_Exception $e ) {
51 }
52 }
53
54 public function cli_init() {
55 try {
56 $this->init_compressor();
57 } catch ( Tiny_Exception $e ) {
58 }
59 }
60
61 public function ajax_init() {
62 try {
63 $this->init_compressor();
64 } catch ( Tiny_Exception $e ) {
65 }
66
67 add_action(
68 'wp_ajax_tiny_image_sizes_notice',
69 $this->get_method( 'image_sizes_notice' )
70 );
71
72 add_action(
73 'wp_ajax_tiny_account_status',
74 $this->get_method( 'account_status' )
75 );
76
77 add_action(
78 'wp_ajax_tiny_settings_create_api_key',
79 $this->get_method( 'create_api_key' )
80 );
81
82 add_action(
83 'wp_ajax_tiny_settings_update_api_key',
84 $this->get_method( 'update_api_key' )
85 );
86 }
87
88 public function rest_init() {
89 try {
90 $this->init_compressor();
91 } catch ( Tiny_Exception $e ) {
92 }
93 }
94
95 public function admin_init() {
96 try {
97 $this->init_compressor();
98 } catch ( Tiny_Exception $e ) {
99 $this->notices->show(
100 'compressor_exception',
101 esc_html( $e->getMessage(), 'tiny-compress-images' ),
102 'error',
103 false
104 );
105 }
106
107 if ( current_user_can( 'manage_options' ) ) {
108 $this->setup_incomplete_checks();
109 }
110
111 $field = self::get_prefixed_name( 'api_key' );
112 register_setting( 'tinify', $field );
113
114 $field = self::get_prefixed_name( 'api_key_pending' );
115 register_setting( 'tinify', $field );
116
117 $field = self::get_prefixed_name( 'compression_timing' );
118 register_setting( 'tinify', $field );
119
120 $field = self::get_prefixed_name( 'sizes' );
121 register_setting( 'tinify', $field );
122
123 $field = self::get_prefixed_name( 'resize_original' );
124 register_setting( 'tinify', $field );
125
126 $field = self::get_prefixed_name( 'preserve_data' );
127 register_setting( 'tinify', $field );
128
129 $field = self::get_prefixed_name( 'convert_format' );
130 register_setting( 'tinify', $field );
131
132 $field = self::get_prefixed_name( 'logging_enabled' );
133 register_setting( 'tinify', $field );
134 }
135
136 public function admin_menu() {
137 /* Create link to new settings page from media settings page. */
138 add_settings_section(
139 'section_end',
140 '',
141 $this->get_method( 'render_settings_moved' ),
142 'media'
143 );
144
145 add_options_page(
146 __( 'TinyPNG - JPEG, PNG & WebP image compression', 'tiny-compress-images' ),
147 esc_html__( 'TinyPNG', 'tiny-compress-images' ),
148 'manage_options',
149 'tinify',
150 array( $this, 'add_options_to_page' )
151 );
152 }
153
154 public function add_options_to_page() {
155 include __DIR__ . '/views/settings.php';
156 }
157
158 public function image_sizes_notice() {
159 if ( current_user_can( 'manage_options' ) ) {
160 $this->render_size_checkboxes_description(
161 $_GET['image_sizes_selected'],
162 isset( $_GET['resize_original'] ),
163 isset( $_GET['compress_wr2x'] ),
164 self::get_conversion_enabled()
165 );
166 }
167 exit();
168 }
169
170 public function account_status() {
171 if ( current_user_can( 'manage_options' ) ) {
172 $this->render_account_status();
173 }
174 exit();
175 }
176
177 public function get_compressor() {
178 return $this->compressor;
179 }
180
181 public function set_compressor( $compressor ) {
182 $this->compressor = $compressor;
183 }
184
185 public function get_status() {
186 return intval( get_option( self::get_prefixed_name( 'status' ) ) );
187 }
188
189 public function disabled_required_functions() {
190 $required_functions = array( 'curl_exec' );
191 $disabled_required_functions = array();
192 $disabled_functions = explode( ',', ini_get( 'disable_functions' ) );
193
194 foreach ( $required_functions as $required_function ) {
195 if ( in_array( $required_function, $disabled_functions, true ) ) {
196 array_push( $disabled_required_functions, $required_function );
197 }
198 }
199
200 return $disabled_required_functions;
201 }
202
203 protected function get_api_key() {
204 if ( defined( 'TINY_API_KEY' ) ) {
205 return TINY_API_KEY;
206 } else {
207 return get_option( self::get_prefixed_name( 'api_key' ) );
208 }
209 }
210
211 protected function get_api_key_pending() {
212 if ( defined( 'TINY_API_KEY' ) ) {
213 return false;
214 } else {
215 return get_option( self::get_prefixed_name( 'api_key_pending' ) );
216 }
217 }
218
219 protected function clear_api_key_pending() {
220 delete_option( self::get_prefixed_name( 'api_key_pending' ) );
221 }
222
223 protected static function get_intermediate_size( $size ) {
224 /* Inspired by
225 http://codex.wordpress.org/Function_Reference/get_intermediate_image_sizes */
226 global $_wp_additional_image_sizes;
227
228 $width = get_option( $size . '_size_w' );
229 $height = get_option( $size . '_size_h' );
230
231 /* Note: dimensions might be 0 to indicate no limit. */
232 if ( $width || $height ) {
233 return array( $width, $height );
234 }
235
236 if ( isset( $_wp_additional_image_sizes[ $size ] ) ) {
237 $sizes = $_wp_additional_image_sizes[ $size ];
238 return array(
239 isset( $sizes['width'] ) ? $sizes['width'] : null,
240 isset( $sizes['height'] ) ? $sizes['height'] : null,
241 );
242 }
243 return array( null, null );
244 }
245
246 /**
247 * Retrieves image sizes as a map of size and width, height and tinify meta data
248 * The first entry will always be '0', aka the original uploaded image.
249 *
250 * @return array{string: array{width: int|null, height: int|null, tinify: array{}}} $sizes
251 */
252 public function get_sizes() {
253 if ( is_array( $this->sizes ) ) {
254 return $this->sizes;
255 }
256
257 $setting = get_option( self::get_prefixed_name( 'sizes' ) );
258
259 $size = Tiny_Image::ORIGINAL;
260 $this->sizes = array(
261 $size => array(
262 'width' => null,
263 'height' => null,
264 'tinify' => ! is_array( $setting ) ||
265 ( isset( $setting[ $size ] ) && 'on' === $setting[ $size ] ),
266 ),
267 );
268
269 foreach ( get_intermediate_image_sizes() as $size ) {
270 if ( self::DUMMY_SIZE === $size ) {
271 continue;
272 }
273
274 list($width, $height) = self::get_intermediate_size( $size );
275 if ( $width || $height ) {
276 $this->sizes[ $size ] = array(
277 'width' => $width,
278 'height' => $height,
279 'tinify' => ! is_array( $setting ) ||
280 ( isset( $setting[ $size ] ) && 'on' === $setting[ $size ] ),
281 );
282 }
283 }
284
285 return $this->sizes;
286 }
287
288 public function get_active_tinify_sizes() {
289 if ( is_array( $this->tinify_sizes ) ) {
290 return $this->tinify_sizes;
291 }
292
293 $this->tinify_sizes = array();
294 foreach ( $this->get_sizes() as $size => $values ) {
295 if ( $values['tinify'] ) {
296 $this->tinify_sizes[] = $size;
297 }
298 }
299 return $this->tinify_sizes;
300 }
301
302 public function new_plugin_install() {
303 /* We merely have to check whether a newly added setting is already stored. */
304 $compression_timing = get_option( self::get_prefixed_name( 'compression_timing' ) );
305 return ! $compression_timing;
306 }
307
308 public function get_resize_enabled() {
309 /* This only applies if the original is being resized. */
310 $sizes = $this->get_sizes();
311 if ( ! $sizes[ Tiny_Image::ORIGINAL ]['tinify'] ) {
312 return false;
313 }
314
315 $setting = get_option( self::get_prefixed_name( 'resize_original' ) );
316 return isset( $setting['enabled'] ) && 'on' === $setting['enabled'];
317 }
318
319 public function get_compression_timing() {
320 $setting = get_option( self::get_prefixed_name( 'compression_timing' ) );
321 if ( isset( $setting ) && $setting ) {
322 return $setting;
323 } elseif ( $this->new_plugin_install() ) {
324 update_option( self::get_prefixed_name( 'compression_timing' ), 'background' );
325 return 'background';
326 } else {
327 update_option( self::get_prefixed_name( 'compression_timing' ), 'auto' );
328 return 'auto';
329 }
330 }
331
332 public function auto_compress_enabled() {
333 return $this->get_compression_timing() === 'auto' ||
334 $this->get_compression_timing() === 'background';
335 }
336
337 public function background_compress_enabled() {
338 return $this->get_compression_timing() === 'background';
339 }
340
341 public function get_preserve_enabled( $name ) {
342 $setting = get_option( self::get_prefixed_name( 'preserve_data' ) );
343 return isset( $setting[ $name ] ) && 'on' === $setting[ $name ];
344 }
345
346 public function get_preserve_options( $size_name ) {
347 if ( ! Tiny_Image::is_original( $size_name ) ) {
348 return false;
349 }
350 $options = array();
351 $settings = get_option( self::get_prefixed_name( 'preserve_data' ) );
352 if ( $settings ) {
353 $keys = array_keys( $settings );
354 foreach ( $keys as &$key ) {
355 if ( 'on' === $settings[ $key ] ) {
356 array_push( $options, $key );
357 }
358 }
359 }
360 return $options;
361 }
362
363 public function get_resize_options( $size_name ) {
364 if ( ! Tiny_Image::is_original( $size_name ) ) {
365 return false;
366 }
367 if ( ! $this->get_resize_enabled() ) {
368 return false;
369 }
370 $setting = get_option( self::get_prefixed_name( 'resize_original' ) );
371 $width = intval( $setting['width'] );
372 $height = intval( $setting['height'] );
373 $method = $width > 0 && $height > 0 ? 'fit' : 'scale';
374 $options['method'] = $method;
375 if ( $width > 0 ) {
376 $options['width'] = $width;
377 }
378 if ( $height > 0 ) {
379 $options['height'] = $height;
380 }
381 return sizeof( $options ) >= 2 ? $options : false;
382 }
383
384 /**
385 * Retrieves the configured settings for conversion.
386 *
387 * @return array{ convert: bool, convert_to: array{string} } The conversion options.
388 */
389 public function get_conversion_options() {
390 return array(
391 'convert' => $this->get_conversion_enabled(),
392 'convert_to' => $this->get_convertto_mimetype(),
393 );
394 }
395
396 /**
397 * Checks wether converting to optimized file format is enabled
398 *
399 * @return bool true if conversion is enabled, false otherwise
400 */
401 public function get_conversion_enabled() {
402 $conversion_enabled = self::get_convert_format_option( 'convert', 'off' );
403
404 return 'on' === $conversion_enabled;
405 }
406
407 /**
408 * Retrieve the mimetypes to convert to
409 *
410 * @return array{string} mimetypes to convert to
411 */
412 private function get_convertto_mimetype() {
413 $convert_to = self::get_convert_format_option( 'convert_to', 'smallest' );
414 if ( 'webp' == $convert_to ) {
415 return array( 'image/webp' );
416 }
417 if ( 'avif' == $convert_to ) {
418 return array( 'image/avif' );
419 }
420 return array( 'image/avif', 'image/webp' );
421 }
422
423 private function setup_incomplete_checks() {
424 if ( ! $this->get_api_key() ) {
425 $this->notices->api_key_missing_notice();
426 } elseif ( $this->get_api_key_pending() ) {
427 $this->notices->get_api_key_pending_notice();
428 }
429 }
430
431 public function render_settings_moved() {
432 echo '<div class="tinify-settings"><h3>';
433 esc_html_e( 'TinyPNG - JPEG, PNG & WebP image compression', 'tiny-compress-images' );
434 echo '</h3>';
435 $url = admin_url( 'options-general.php?page=tinify' );
436 $link = "<a href='" . $url . "'>";
437 $link .= esc_html__( 'settings', 'tiny-compress-images' );
438 $link .= '</a>';
439 printf(
440 wp_kses(
441 /* translators: %s: link saying settings */
442 __( 'The %s have moved.', 'tiny-compress-images' ),
443 array(
444 'a' => array(
445 'href' => array(),
446 ),
447 )
448 ),
449 $link
450 );
451 echo '</div>';
452 }
453
454 public function render_compression_timing_settings() {
455 $heading = esc_html__(
456 'When should new images be compressed?',
457 'tiny-compress-images'
458 );
459 echo '<h4>' . $heading . '</h4>';
460 echo '<div class="optimization-options">';
461
462 $name = self::get_prefixed_name( 'compression_timing' );
463 $compression_timing = $this->get_compression_timing();
464
465 $id = self::get_prefixed_name( 'background_compress_enabled' );
466 $checked = ( 'background' === $compression_timing ? ' checked="checked"' : '' );
467
468 $label = esc_html__(
469 'Compress new images in the background (Recommended)',
470 'tiny-compress-images'
471 );
472 $description = esc_html__(
473 'This is the fastest method, but can cause issues with some image related plugins.',
474 'tiny-compress-images'
475 );
476
477 $this->render_compression_timing_radiobutton(
478 $name,
479 $label,
480 $description,
481 'background',
482 $checked,
483 false
484 );
485
486 $id = self::get_prefixed_name( 'auto_compress_enabled' );
487 $checked = ( 'auto' === $compression_timing ? ' checked="checked"' : '' );
488
489 $label = esc_html__(
490 'Compress new images during upload',
491 'tiny-compress-images'
492 );
493 $description = esc_html__(
494 'Uploads will take longer, but provides higher compatibility with other plugins.',
495 'tiny-compress-images'
496 );
497
498 $this->render_compression_timing_radiobutton(
499 $name,
500 $label,
501 $description,
502 'auto',
503 $checked,
504 false
505 );
506
507 $id = self::get_prefixed_name( 'auto_compress_disabled' );
508 $checked = ( 'manual' === $compression_timing ? ' checked="checked"' : '' );
509
510 $label = esc_html__(
511 'Do not compress new images automatically',
512 'tiny-compress-images'
513 );
514 $description = esc_html__(
515 'Manually select the images you want to compress in the media library.',
516 'tiny-compress-images'
517 );
518
519 $this->render_compression_timing_radiobutton(
520 $name,
521 $label,
522 $description,
523 'manual',
524 $checked,
525 false
526 );
527
528 echo '</div>';
529 }
530
531 public function render_sizes() {
532 echo '<input type="hidden" name="' .
533 self::get_prefixed_name( 'sizes[' . self::DUMMY_SIZE . ']' ) . '" value="on"/>';
534
535 foreach ( $this->get_sizes() as $size => $option ) {
536 $this->render_size_checkboxes( $size, $option );
537 }
538 if ( self::wr2x_active() ) {
539 $this->render_size_checkboxes( 'wr2x', $this->get_wr2x_option() );
540 }
541 echo '<br>';
542 echo '<div id="tiny-image-sizes-notice">';
543
544 $this->render_size_checkboxes_description(
545 count( self::get_active_tinify_sizes() ),
546 self::get_resize_enabled(),
547 self::compress_wr2x_images(),
548 self::get_conversion_enabled()
549 );
550
551 echo '</div>';
552 }
553
554 private function render_size_checkboxes( $size, $option ) {
555 $id = self::get_prefixed_name( "sizes_$size" );
556 $name = self::get_prefixed_name( 'sizes[' . $size . ']' );
557 $checked = ( $option['tinify'] ? ' checked="checked"' : '' );
558 if ( Tiny_Image::is_original( $size ) ) {
559 $label = esc_html__( 'Original image', 'tiny-compress-images' ) . ' (' .
560 esc_html__(
561 'overwritten by compressed image',
562 'tiny-compress-images'
563 ) . ')';
564 } elseif ( Tiny_Image::is_retina( $size ) ) {
565 $label = esc_html__( 'WP Retina 2x sizes', 'tiny-compress-images' );
566 } else {
567 $width = $option['width'];
568 if ( ! $width ) {
569 $width = '?';
570 }
571
572 $height = $option['height'];
573 if ( ! $height ) {
574 $height = '?';
575 }
576
577 $label = esc_html( ucfirst( str_replace( '_', ' ', $size ) ) )
578 . ' - ' . $width . 'x' . $height;
579 }
580 echo '<p>';
581 echo '<input type="checkbox" id="' . $id . '" name="' . $name .
582 '" value="on" ' . $checked . '/>';
583 echo '<label for="' . $id . '">' . $label . '</label>';
584 echo '</p>';
585 }
586
587 public function render_size_checkboxes_description(
588 $active_sizes_count,
589 $resize_original_enabled,
590 $compress_wr2x,
591 $conversion_enabled
592 ) {
593 echo '<p>';
594 esc_html_e(
595 'Remember each selected size counts as a compression.',
596 'tiny-compress-images'
597 );
598 echo '</p>';
599 echo '<p>';
600 if ( $resize_original_enabled ) {
601 ++$active_sizes_count;
602 }
603 if ( $compress_wr2x ) {
604 $active_sizes_count *= 2;
605 }
606
607 if ( $conversion_enabled ) {
608 $active_sizes_count *= 2;
609 }
610
611 if ( $active_sizes_count < 1 ) {
612 esc_html_e(
613 'With these settings no images will be compressed.',
614 'tiny-compress-images'
615 );
616 } else {
617 $free_images_per_month = floor(
618 Tiny_Config::MONTHLY_FREE_COMPRESSIONS / $active_sizes_count
619 );
620
621 $strong = array(
622 'strong' => array(),
623 );
624
625 printf(
626 wp_kses(
627 /* translators: %1$s: number of images */
628 __(
629 // phpcs:ignore Generic.Files.LineLength
630 'With these settings you can compress <strong>at least %1$s images</strong> for free each month.',
631 'tiny-compress-images'
632 ),
633 $strong
634 ),
635 $free_images_per_month
636 );
637
638 if ( self::wr2x_active() ) {
639 echo '</p>';
640 echo '<p>';
641 esc_html_e(
642 'If selected, retina sizes will be compressed when generated by WP Retina 2x',
643 'tiny-compress-images'
644 );
645 echo '<br>';
646 esc_html_e(
647 'Each retina size will count as an additional compression.',
648 'tiny-compress-images'
649 );
650 }
651 } // End if().
652 echo '</p>';
653 }
654
655 public function render_resize() {
656 $strong = array(
657 'strong' => array(),
658 );
659
660 echo '<div class="tiny-resize-unavailable" style="display: none">';
661 esc_html_e(
662 'Enable compression of the original image size for more options.',
663 'tiny-compress-images'
664 );
665 echo '</div>';
666
667 $id = self::get_prefixed_name( 'resize_original_enabled' );
668 $name = self::get_prefixed_name( 'resize_original[enabled]' );
669 $checked = ( $this->get_resize_enabled() ? ' checked="checked"' : '' );
670
671 $label = esc_html__(
672 'Resize the original image',
673 'tiny-compress-images'
674 );
675
676 echo '<div class="tiny-resize-available">';
677 echo '<input type="checkbox" id="' . $id . '" name="' . $name .
678 '" value="on" ' . $checked . '/>';
679 echo '<label for="' . $id . '">' . $label . '</label><br>';
680
681 echo '<div class="tiny-resize-available tiny-resize-resolution">';
682 echo '<span>';
683 echo wp_kses(
684 __(
685 // phpcs:ignore Generic.Files.LineLength
686 '<strong>Save space</strong> by setting a maximum width and height for all images uploaded.',
687 'tiny-compress-images'
688 ),
689 $strong
690 );
691 echo '<br>';
692 echo wp_kses(
693 __(
694 // phpcs:ignore Generic.Files.LineLength
695 'Resizing takes <strong>1 additional compression</strong> for each image that is larger.',
696 'tiny-compress-images'
697 ),
698 $strong
699 );
700 echo '</span>';
701 echo '<div class="tiny-resize-inputs">';
702 printf( '%s: ', esc_html__( 'Max Width', 'tiny-compress-images' ) );
703 $this->render_resize_input( 'width' );
704 printf( '%s: ', esc_html__( 'Max Height', 'tiny-compress-images' ) );
705 $this->render_resize_input( 'height' );
706 echo '</div></div></div>';
707
708 $this->render_preserve_input(
709 'creation',
710 esc_html__(
711 'Preserve creation date and time in the original image',
712 'tiny-compress-images'
713 )
714 );
715
716 $this->render_preserve_input(
717 'copyright',
718 esc_html__(
719 'Preserve copyright information in the original image',
720 'tiny-compress-images'
721 )
722 );
723
724 $this->render_preserve_input(
725 'location',
726 esc_html__(
727 'Preserve GPS location in the original image',
728 'tiny-compress-images'
729 ) . ' ' .
730 esc_html__( '(JPEG only)', 'tiny-compress-images' )
731 );
732 }
733
734 public function render_compression_timing_radiobutton(
735 $name,
736 $label,
737 $desc,
738 $value,
739 $checked
740 ) {
741 $as3cf_local_files_present = Tiny_AS3CF::is_active()
742 && Tiny_AS3CF::remove_local_files_setting_enabled();
743 if ( 'background' == $value && $as3cf_local_files_present && $checked ) {
744 echo '<div class="notice notice-warning inline"><p>';
745 echo '<strong>' . esc_html__( 'Warning', 'tiny-compress-images' ) . '</strong> — ';
746 $message = esc_html__(
747 // phpcs:ignore Generic.Files.LineLength
748 'For compression to work you will need to configure WP Offload S3 to keep a copy of the images on the server.',
749 'tiny-compress-images'
750 );
751 echo $message;
752 echo '</p></div>';
753 echo '<p class="tiny-radio disabled">';
754 } else {
755 echo '<p class="tiny-radio">';
756 }
757
758 $id = sprintf( self::get_prefixed_name( 'compression_timing_%s' ), $value );
759 $label = esc_html( $label, 'tiny-compress-images' );
760 $desc = esc_html( $desc, 'tiny-compress-images' );
761 echo '<input type="radio" id="' . $id . '" name="' . $name .
762 '" value="' . $value . '" ' . $checked . '/>';
763 echo '<label for="' . $id . '">' . $label . '</label>';
764 echo '<br>';
765 echo '<span>' . $desc . '</span>';
766 echo '</p>';
767 }
768
769 public function render_preserve_input( $name, $description ) {
770 echo '<p class="tiny-preserve">';
771 $id = sprintf( self::get_prefixed_name( 'preserve_data_%s' ), $name );
772 $field = sprintf( self::get_prefixed_name( 'preserve_data[%s]' ), $name );
773 $checked = ( $this->get_preserve_enabled( $name ) ? ' checked="checked"' : '' );
774 $label = esc_html( $description, 'tiny-compress-images' );
775 echo '<input type="checkbox" id="' . $id . '" name="' . $field .
776 '" value="on" ' . $checked . '/>';
777 echo '<label for="' . $id . '">' . $label . '</label>';
778 echo '<br>';
779 echo '</p>';
780 }
781
782 public function render_resize_input( $name ) {
783 $id = sprintf( self::get_prefixed_name( 'resize_original_%s' ), $name );
784 $field = sprintf( self::get_prefixed_name( 'resize_original[%s]' ), $name );
785 $settings = get_option( self::get_prefixed_name( 'resize_original' ) );
786 $value = isset( $settings[ $name ] ) ? $settings[ $name ] : '2048';
787 echo '<input type="number" id="' . $id . '" name="' . $field .
788 '" value="' . $value . '" size="5" />';
789 }
790
791 public function get_compression_count() {
792 $field = self::get_prefixed_name( 'status' );
793 return get_option( $field );
794 }
795
796 public function limit_reached() {
797 $this->compressor->get_compression_count();
798 return $this->compressor->limit_reached();
799 }
800
801 public function get_remaining_credits() {
802 $field = self::get_prefixed_name( 'remaining_credits' );
803 return get_option( $field );
804 }
805
806 public function get_paying_state() {
807 $field = self::get_prefixed_name( 'paying_state' );
808 return get_option( $field );
809 }
810
811 public function is_on_free_plan() {
812 return self::get_paying_state() === 'free';
813 }
814
815 public function get_email_address() {
816 $field = self::get_prefixed_name( 'email_address' );
817 return get_option( $field );
818 }
819
820 public function after_compress_callback( $compressor ) {
821 $count = $compressor->get_compression_count();
822 if ( ! is_null( $count ) ) {
823 $field = self::get_prefixed_name( 'status' );
824 update_option( $field, $count );
825 }
826 $remaining_credits = $compressor->get_remaining_credits();
827 if ( ! is_null( $remaining_credits ) ) {
828 $field = self::get_prefixed_name( 'remaining_credits' );
829 update_option( $field, $remaining_credits );
830 }
831 $paying_state = $compressor->get_paying_state();
832 if ( ! is_null( $paying_state ) ) {
833 $field = self::get_prefixed_name( 'paying_state' );
834 update_option( $field, $paying_state );
835 }
836 $email_address = $compressor->get_email_address();
837 if ( ! is_null( $email_address ) ) {
838 $field = self::get_prefixed_name( 'email_address' );
839 update_option( $field, $email_address );
840 }
841 if ( $compressor->limit_reached() ) {
842 $this->notices->add_limit_reached_notice( $email_address );
843 } else {
844 $this->notices->remove( 'limit-reached' );
845 }
846 }
847
848 public function render_account_status() {
849 $key = $this->get_api_key();
850 if ( empty( $key ) ) {
851 $compressor = $this->get_compressor();
852 if ( $compressor->can_create_key() ) {
853 include __DIR__ . '/views/account-status-create-advanced.php';
854 } else {
855 include __DIR__ . '/views/account-status-create-simple.php';
856 }
857 } else {
858 $status = $this->compressor->get_status();
859 $status->pending = false;
860 if ( $status->ok ) {
861 if ( $this->get_api_key_pending() ) {
862 $this->clear_api_key_pending();
863 }
864 } else {
865 if ( $this->get_api_key_pending() ) {
866 $status->ok = true;
867 $status->pending = true;
868 $status->message = (
869 'An email has been sent to activate your account'
870 );
871 }
872 }
873 include __DIR__ . '/views/account-status-connected.php';
874 }
875 }
876
877 public function render_pending_status() {
878 $key = $this->get_api_key();
879 if ( empty( $key ) ) {
880 $compressor = $this->get_compressor();
881 if ( $compressor->can_create_key() ) {
882 include __DIR__ . '/views/account-status-create-advanced.php';
883 } else {
884 include __DIR__ . '/views/account-status-create-simple.php';
885 }
886 } else {
887 include __DIR__ . '/views/account-status-loading.php';
888 }
889 }
890
891 public function create_api_key() {
892 if ( ! $this->check_ajax_referer() ) {
893 exit;
894 }
895 $compressor = $this->get_compressor();
896 if ( ! current_user_can( 'manage_options' ) ) {
897 $status = (object) array(
898 'ok' => false,
899 'message' => 'This feature requires certain user capabilities',
900 );
901 } elseif ( $compressor->can_create_key() ) {
902 if ( ! isset( $_POST['name'] ) || ! $_POST['name'] ) {
903 $status = (object) array(
904 'ok' => false,
905 'message' => __(
906 'Please enter your name',
907 'tiny-compress-images'
908 ),
909 );
910 echo json_encode( $status );
911 exit();
912 }
913
914 if ( ! isset( $_POST['email'] ) || ! $_POST['email'] ) {
915 $status = (object) array(
916 'ok' => false,
917 'message' => __(
918 'Please enter your email address',
919 'tiny-compress-images'
920 ),
921 );
922 echo json_encode( $status );
923 exit();
924 }
925
926 try {
927 $site = str_replace(
928 array( 'http://', 'https://' ),
929 '',
930 get_bloginfo( 'url' )
931 );
932 $identifier = 'WordPress plugin for ' . $site;
933 $link = $this->get_absolute_url();
934 $compressor->create_key(
935 $_POST['email'],
936 array(
937 'name' => $_POST['name'],
938 'identifier' => $identifier,
939 'link' => $link,
940 )
941 );
942
943 update_option( self::get_prefixed_name( 'api_key_pending' ), true );
944 update_option( self::get_prefixed_name( 'api_key' ), $compressor->get_key() );
945 update_option( self::get_prefixed_name( 'status' ), 0 );
946
947 $status = (object) array(
948 'ok' => true,
949 'message' => null,
950 );
951 } catch ( Tiny_Exception $err ) {
952 list($message) = explode( ' (HTTP', $err->getMessage(), 2 );
953 $status = (object) array(
954 'ok' => false,
955 'message' => $message,
956 );
957 }
958 } else {
959 $status = (object) array(
960 'ok' => false,
961 'message' => 'This feature is not available on your platform',
962 );
963 } // End if().
964
965 echo json_encode( $status );
966 exit();
967 }
968
969 public function update_api_key() {
970 $key = $_POST['key'];
971 if ( ! $this->check_ajax_referer() ) {
972 exit;
973 }
974 if ( ! current_user_can( 'manage_options' ) ) {
975 $status = (object) array(
976 'ok' => false,
977 'message' => 'This feature requires certain user capabilities',
978 );
979 } elseif ( empty( $key ) ) {
980 /* Always save if key is blank, so the key can be deleted. */
981 $status = (object) array(
982 'ok' => true,
983 'message' => null,
984 );
985 } else {
986 $status = Tiny_Compress::create( $key )->get_status();
987 }
988 if ( $status->ok ) {
989 update_option( self::get_prefixed_name( 'api_key_pending' ), false );
990 update_option( self::get_prefixed_name( 'api_key' ), $key );
991 }
992 echo json_encode( $status );
993 exit();
994 }
995
996 public static function wr2x_active() {
997 return function_exists( 'wr2x_get_retina' );
998 }
999
1000 public function get_wr2x_option() {
1001 $setting = get_option( self::get_prefixed_name( 'sizes' ) );
1002 return array(
1003 'width' => null,
1004 'height' => null,
1005 'tinify' => ( isset( $setting['wr2x'] ) && 'on' === $setting['wr2x'] ),
1006 );
1007 }
1008
1009 public function compress_wr2x_images() {
1010 $option = $this->get_wr2x_option();
1011 return self::wr2x_active() && $option['tinify'];
1012 }
1013
1014
1015 public function render_format_conversion() {
1016 echo '<div class="conversion-options">';
1017
1018 $convertopts_convert = self::get_prefixed_name( 'convert_format[convert]' );
1019 $convertopts_convert_id = self::get_prefixed_name( 'conversion_convert' );
1020 $convertopts_convert_checked = $this->get_conversion_enabled() ?
1021 ' checked="checked"' : '';
1022
1023 echo '<p class="tiny-check">';
1024 echo '<input type="checkbox" id="' . $convertopts_convert_id . '" ';
1025 echo 'name="' . $convertopts_convert . '" ';
1026 echo 'value="on"' . $convertopts_convert_checked . '/>';
1027 echo '<label for="' . $convertopts_convert_id . '">' .
1028 esc_html__( 'Generate optimized image formats', 'tiny-compress-images' ) .
1029 '</label>';
1030 echo '</p>';
1031
1032 $convertopts_convert_to_name =
1033 self::get_prefixed_name( 'convert_format[convert_to]' );
1034 $convertopts_convert_subfields_classname =
1035 self::get_prefixed_name( 'convert_fields' );
1036 $convertopts_convert_to_id = self::get_prefixed_name( 'convert_convert_to' );
1037 $convertopts_convert_value =
1038 self::get_convert_format_option( 'convert_to', 'smallest' );
1039 $convertopts_convert_disabled =
1040 self::get_conversion_enabled() ? '' : ' disabled="disabled"';
1041 echo sprintf(
1042 '<fieldset class="%s" id="%s" %s>',
1043 $convertopts_convert_subfields_classname,
1044 $convertopts_convert_to_id,
1045 $convertopts_convert_disabled
1046 );
1047 echo '<h4>' . __( 'Conversion output', 'tiny-compress-images' ) . '</h4>';
1048 self::render_convert_to_radiobutton(
1049 $convertopts_convert_to_name,
1050 sprintf( self::get_prefixed_name( 'convert_convert_to_%s' ), 'smallest' ),
1051 'smallest',
1052 $convertopts_convert_value,
1053 __( 'Convert to smallest file type (Recommended)', 'tiny-compress-images' ),
1054 __(
1055 'We will calculate what is the best format for your image.',
1056 'tiny-compress-images'
1057 )
1058 );
1059 self::render_convert_to_radiobutton(
1060 $convertopts_convert_to_name,
1061 sprintf( self::get_prefixed_name( 'convert_convert_to_%s' ), 'webp' ),
1062 'webp',
1063 $convertopts_convert_value,
1064 __( 'Convert to WebP', 'tiny-compress-images' ),
1065 __(
1066 'WebP balances a small file size with good visual quality,
1067 supporting transparency and animation.',
1068 'tiny-compress-images'
1069 )
1070 );
1071 self::render_convert_to_radiobutton(
1072 $convertopts_convert_to_name,
1073 sprintf( self::get_prefixed_name( 'convert_convert_to_%s' ), 'avif' ),
1074 'avif',
1075 $convertopts_convert_value,
1076 __( 'Convert to AVIF', 'tiny-compress-images' ),
1077 __(
1078 'AVIF delivers even better compression and image quality than WebP.
1079 Browser support is not as good as WebP.',
1080 'tiny-compress-images'
1081 )
1082 );
1083 echo '</fieldset>';
1084 echo '</div>';
1085 }
1086
1087 private static function render_convert_to_radiobutton(
1088 $name,
1089 $id,
1090 $value,
1091 $current,
1092 $label,
1093 $descr
1094 ) {
1095 $checked = ( $current === $value ? ' checked="checked"' : '' );
1096 echo '<p class="tiny-radio">';
1097 echo '<input type="radio" id="' . $id . '" name="' . $name .
1098 '" value="' . $value . '" ' . $checked . '/>';
1099 echo '<label for="' . $id . '">' . $label;
1100 echo '<span>' . $descr . '</span>';
1101 echo '</label>';
1102 echo '</p>';
1103 }
1104
1105 private static function get_convert_format_option( $option, $default_value ) {
1106 $setting = get_option( self::get_prefixed_name( 'convert_format' ) );
1107 if ( isset( $setting[ $option ] ) && $setting[ $option ] ) {
1108 return $setting[ $option ];
1109 }
1110 return $default_value;
1111 }
1112 }
1113