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