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