PluginProbe ʕ •ᴥ•ʔ
TinyPNG – JPEG, PNG & WebP image compression / 2.1.0
TinyPNG – JPEG, PNG & WebP image compression v2.1.0
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
config 9 years ago css 9 years ago data 9 years ago images 9 years ago js 9 years ago vendor 9 years ago views 9 years ago class-tiny-compress-client.php 9 years ago class-tiny-compress-fopen.php 9 years ago class-tiny-compress.php 9 years ago class-tiny-exception.php 9 years ago class-tiny-image-size.php 9 years ago class-tiny-image.php 9 years ago class-tiny-notices.php 9 years ago class-tiny-php.php 9 years ago class-tiny-plugin.php 9 years ago class-tiny-settings.php 9 years ago class-tiny-wp-base.php 9 years ago
class-tiny-settings.php
705 lines
1 <?php
2 /*
3 * Tiny Compress Images - WordPress plugin.
4 * Copyright (C) 2015-2016 Voormedia 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 const DUMMY_SIZE = '_tiny_dummy';
22
23 private $sizes;
24 private $tinify_sizes;
25 private $compressor;
26 private $notices;
27
28 public function __construct() {
29 parent::__construct();
30 $this->notices = new Tiny_Notices();
31 }
32
33 private function init_compressor() {
34 $this->compressor = Tiny_Compress::create(
35 $this->get_api_key(),
36 $this->get_method( 'after_compress_callback' )
37 );
38 }
39
40 public function get_absolute_url() {
41 return get_admin_url( null, 'options-media.php#' . self::NAME );
42 }
43
44 public function xmlrpc_init() {
45 try {
46 $this->init_compressor();
47 } catch (Tiny_Exception $e) {
48 }
49 }
50
51 public function admin_init() {
52 if ( current_user_can( 'manage_options' ) ) {
53 if ( ! $this->get_api_key() ) {
54 $notice_class = 'error';
55 $notice = esc_html__(
56 'Please register or provide an API key to start compressing images',
57 'tiny-compress-images'
58 );
59 } else if ( $this->get_api_key_pending() ) {
60 $notice_class = 'notice-warning';
61 $notice = esc_html__(
62 'Please activate your account to start compressing images',
63 'tiny-compress-images'
64 );
65 }
66
67 if ( isset( $notice ) && $notice ) {
68 $link = sprintf(
69 '<a href="options-media.php#%s">%s</a>', self::NAME, $notice
70 );
71 $this->notices->show( 'setting', $link, $notice_class, false );
72 }
73
74 if ( ! Tiny_PHP::client_supported() ) {
75 $details = 'PHP ' . PHP_VERSION;
76 if ( extension_loaded( 'curl' ) ) {
77 $curlinfo = curl_version();
78 $details .= ' with curl ' . $curlinfo['version'];
79 } else {
80 $details .= ' without curl';
81 }
82 $message = esc_html__(
83 'You are using an outdated platform (' . $details .
84 ') – some features are disabled', 'tiny-compress-images'
85 );
86 $this->notices->show( 'deprecated', $message, 'notice-warning', false );
87 }
88 }
89
90 try {
91 $this->init_compressor();
92 } catch (Tiny_Exception $e) {
93 $this->notices->show(
94 'compressor_exception',
95 esc_html__( $e->getMessage(), 'tiny-compress-images' ),
96 'error', false
97 );
98 }
99
100 $section = self::get_prefixed_name( 'settings' );
101 add_settings_section( $section,
102 esc_html__( 'JPEG and PNG optimization', 'tiny-compress-images' ),
103 $this->get_method( 'render_section' ),
104 'media'
105 );
106
107 $field = self::get_prefixed_name( 'api_key' );
108 register_setting( 'media', $field );
109 add_settings_field( $field,
110 esc_html__( 'TinyPNG account', 'tiny-compress-images' ),
111 $this->get_method( 'render_pending_status' ),
112 'media',
113 $section
114 );
115
116 $field = self::get_prefixed_name( 'api_key_pending' );
117 register_setting( 'media', $field );
118
119 $field = self::get_prefixed_name( 'sizes' );
120 register_setting( 'media', $field );
121 add_settings_field( $field,
122 esc_html__( 'File compression', 'tiny-compress-images' ),
123 $this->get_method( 'render_sizes' ),
124 'media',
125 $section
126 );
127
128 $field = self::get_prefixed_name( 'resize_original' );
129 register_setting( 'media', $field );
130 add_settings_field( $field,
131 esc_html__( 'Original image', 'tiny-compress-images' ),
132 $this->get_method( 'render_resize' ),
133 'media',
134 $section
135 );
136
137 $field = self::get_prefixed_name( 'preserve_data' );
138 register_setting( 'media', $field );
139
140 add_settings_section( 'section_end', '',
141 $this->get_method( 'render_section_end' ),
142 'media'
143 );
144
145 add_action(
146 'wp_ajax_tiny_image_sizes_notice',
147 $this->get_method( 'image_sizes_notice' )
148 );
149
150 add_action(
151 'wp_ajax_tiny_account_status',
152 $this->get_method( 'account_status' )
153 );
154
155 add_action(
156 'wp_ajax_tiny_settings_create_api_key',
157 $this->get_method( 'create_api_key' )
158 );
159
160 add_action(
161 'wp_ajax_tiny_settings_update_api_key',
162 $this->get_method( 'update_api_key' )
163 );
164 }
165
166 public function image_sizes_notice() {
167 $this->render_image_sizes_notice(
168 $_GET['image_sizes_selected'],
169 isset( $_GET['resize_original'] ),
170 isset( $_GET['compress_wr2x'] )
171 );
172 exit();
173 }
174
175 public function account_status() {
176 $this->render_account_status();
177 exit();
178 }
179
180 public function get_compressor() {
181 return $this->compressor;
182 }
183
184 public function set_compressor( $compressor ) {
185 $this->compressor = $compressor;
186 }
187
188 public function get_status() {
189 return intval( get_option( self::get_prefixed_name( 'status' ) ) );
190 }
191
192 protected function get_api_key() {
193 if ( defined( 'TINY_API_KEY' ) ) {
194 return TINY_API_KEY;
195 } else {
196 return get_option( self::get_prefixed_name( 'api_key' ) );
197 }
198 }
199
200 protected function get_api_key_pending() {
201 if ( defined( 'TINY_API_KEY' ) ) {
202 return false;
203 } else {
204 return get_option( self::get_prefixed_name( 'api_key_pending' ) );
205 }
206 }
207
208 protected function clear_api_key_pending() {
209 delete_option( self::get_prefixed_name( 'api_key_pending' ) );
210 }
211
212 protected static function get_intermediate_size( $size ) {
213 /* Inspired by
214 http://codex.wordpress.org/Function_Reference/get_intermediate_image_sizes */
215 global $_wp_additional_image_sizes;
216
217 $width = get_option( $size . '_size_w' );
218 $height = get_option( $size . '_size_h' );
219 if ( $width && $height ) {
220 return array( $width, $height );
221 }
222
223 if ( isset( $_wp_additional_image_sizes[ $size ] ) ) {
224 $sizes = $_wp_additional_image_sizes[ $size ];
225 return array(
226 isset( $sizes['width'] ) ? $sizes['width'] : null,
227 isset( $sizes['height'] ) ? $sizes['height'] : null,
228 );
229 }
230 return array( null, null );
231 }
232
233 public function get_sizes() {
234 if ( is_array( $this->sizes ) ) {
235 return $this->sizes;
236 }
237
238 $setting = get_option( self::get_prefixed_name( 'sizes' ) );
239
240 $size = Tiny_Image::ORIGINAL;
241 $this->sizes = array(
242 $size => array(
243 'width' => null,
244 'height' => null,
245 'tinify' => ! is_array( $setting ) ||
246 ( isset( $setting[ $size ] ) && 'on' === $setting[ $size ] ),
247 ),
248 );
249
250 foreach ( get_intermediate_image_sizes() as $size ) {
251 if ( self::DUMMY_SIZE === $size ) {
252 continue;
253 }
254
255 list($width, $height) = self::get_intermediate_size( $size );
256 if ( $width || $height ) {
257 $this->sizes[ $size ] = array(
258 'width' => $width,
259 'height' => $height,
260 'tinify' => ! is_array( $setting ) ||
261 ( isset( $setting[ $size ] ) && 'on' === $setting[ $size ] ),
262 );
263 }
264 }
265
266 return $this->sizes;
267 }
268
269 public function get_active_tinify_sizes() {
270 if ( is_array( $this->tinify_sizes ) ) {
271 return $this->tinify_sizes;
272 }
273
274 $this->tinify_sizes = array();
275 foreach ( $this->get_sizes() as $size => $values ) {
276 if ( $values['tinify'] ) {
277 $this->tinify_sizes[] = $size;
278 }
279 }
280 return $this->tinify_sizes;
281 }
282
283 public function get_resize_enabled() {
284 /* This only applies if the original is being resized. */
285 $sizes = $this->get_sizes();
286 if ( ! $sizes[ Tiny_Image::ORIGINAL ]['tinify'] ) {
287 return false;
288 }
289
290 $setting = get_option( self::get_prefixed_name( 'resize_original' ) );
291 return isset( $setting['enabled'] ) && 'on' === $setting['enabled'];
292 }
293
294 public function get_preserve_enabled( $name ) {
295 $setting = get_option( self::get_prefixed_name( 'preserve_data' ) );
296 return isset( $setting[ $name ] ) && 'on' === $setting[ $name ];
297 }
298
299 public function get_preserve_options( $size_name ) {
300 if ( ! Tiny_Image::is_original( $size_name ) ) {
301 return false;
302 }
303 $options = array();
304 $settings = get_option( self::get_prefixed_name( 'preserve_data' ) );
305 if ( $settings ) {
306 $keys = array_keys( $settings );
307 foreach ( $keys as &$key ) {
308 if ( 'on' === $settings[ $key ] ) {
309 array_push( $options, $key );
310 }
311 }
312 }
313 return $options;
314 }
315
316 public function get_resize_options( $size_name ) {
317 if ( ! Tiny_Image::is_original( $size_name ) ) {
318 return false;
319 }
320 if ( ! $this->get_resize_enabled() ) {
321 return false;
322 }
323 $setting = get_option( self::get_prefixed_name( 'resize_original' ) );
324 $width = intval( $setting['width'] );
325 $height = intval( $setting['height'] );
326 $method = $width > 0 && $height > 0 ? 'fit' : 'scale';
327 $options['method'] = $method;
328 if ( $width > 0 ) {
329 $options['width'] = $width;
330 }
331 if ( $height > 0 ) {
332 $options['height'] = $height;
333 }
334 return sizeof( $options ) >= 2 ? $options : false;
335 }
336
337 public function render_section_end() {
338 echo '</div>';
339 }
340
341 public function render_section() {
342 echo '<div class="' . self::NAME . '">';
343 echo '<span id="' . self::NAME . '"></span>';
344 }
345
346 public function render_sizes() {
347 echo '<p>';
348 esc_html_e(
349 'Choose sizes to compress. Remember each selected size counts as a compression.',
350 'tiny-compress-images'
351 );
352 echo '</p>';
353 echo '<input type="hidden" name="' .
354 self::get_prefixed_name( 'sizes[' . self::DUMMY_SIZE . ']' ) . '" value="on"/>';
355
356 foreach ( $this->get_sizes() as $size => $option ) {
357 $this->render_size_checkbox( $size, $option );
358 }
359 if ( self::wr2x_active() ) {
360 $this->render_size_checkbox( 'wr2x', $this->get_wr2x_option() );
361 }
362 echo '<br>';
363 echo '<div id="tiny-image-sizes-notice">';
364
365 $this->render_image_sizes_notice(
366 count( self::get_active_tinify_sizes() ),
367 self::get_resize_enabled(),
368 self::compress_wr2x_images()
369 );
370
371 echo '</div>';
372 }
373
374 private function render_size_checkbox( $size, $option ) {
375 $id = self::get_prefixed_name( "sizes_$size" );
376 $name = self::get_prefixed_name( 'sizes[' . $size . ']' );
377 $checked = ( $option['tinify'] ? ' checked="checked"' : '' );
378 if ( Tiny_Image::is_original( $size ) ) {
379 $label = esc_html__( 'Original image', 'tiny-compress-images' ) . ' (' .
380 esc_html__( 'overwritten by compressed image', 'tiny-compress-images' ) . ')';
381 } else if ( Tiny_Image::is_retina( $size ) ) {
382 $label = esc_html__( 'WP Retina 2x sizes', 'tiny-compress-images' );
383 } else {
384 $label = esc_html__( ucfirst( $size ) )
385 . ' - ' . $option['width'] . 'x' . $option['height'];
386 }
387 echo '<p>';
388 echo '<input type="checkbox" id="' . $id . '" name="' . $name .
389 '" value="on" ' . $checked . '/>';
390 echo '<label for="' . $id . '">' . $label . '</label>';
391 echo '</p>';
392 }
393
394 public function render_image_sizes_notice(
395 $active_sizes_count, $resize_original_enabled, $compress_wr2x ) {
396 echo '<p>';
397 if ( $resize_original_enabled ) {
398 $active_sizes_count++;
399 }
400 if ( $compress_wr2x ) {
401 $active_sizes_count *= 2;
402 }
403
404 if ( $active_sizes_count < 1 ) {
405 esc_html_e(
406 'With these settings no images will be compressed.',
407 'tiny-compress-images'
408 );
409 } else {
410 $free_images_per_month = floor(
411 Tiny_Config::MONTHLY_FREE_COMPRESSIONS / $active_sizes_count
412 );
413 printf( wp_kses( __(
414 'With these settings you can compress ' .
415 '<strong> at least %s images </strong> for free each month.',
416 'tiny-compress-images'
417 ), array( 'strong' => array() ) ), $free_images_per_month );
418
419 if ( self::wr2x_active() ) {
420 echo '</p>';
421 echo '<p>';
422 esc_html_e(
423 'If selected, retina sizes will be compressed when generated by WP Retina 2x',
424 'tiny-compress-images'
425 );
426 echo '<br>';
427 esc_html_e(
428 'Each retina size will count as an additional compression.',
429 'tiny-compress-images'
430 );
431 }
432 }
433 echo '</p>';
434 }
435
436 public function render_resize() {
437 echo '<p class="tiny-resize-unavailable" style="display: none">';
438 esc_html_e(
439 'Enable compression of the original image size for more options.',
440 'tiny-compress-images'
441 );
442 echo '</p>';
443
444 $id = self::get_prefixed_name( 'resize_original_enabled' );
445 $name = self::get_prefixed_name( 'resize_original[enabled]' );
446 $checked = ( $this->get_resize_enabled() ? ' checked="checked"' : '' );
447
448 $label = esc_html__(
449 'Resize and compress the original image',
450 'tiny-compress-images'
451 );
452
453 echo '<p class="tiny-resize-available">';
454 echo '<input type="checkbox" id="' . $id . '" name="' . $name .
455 '" value="on" '. $checked . '/>';
456 echo '<label for="' . $id . '">' . $label . '</label>';
457 echo '<br>';
458 echo '</p>';
459
460 echo '<p class="tiny-resize-available tiny-resize-resolution">';
461 printf( '%s ', esc_html__( 'Max Width' ) );
462 $this->render_resize_input( 'width' );
463 printf( '%s ', esc_html__( 'Max Height' ) );
464 $this->render_resize_input( 'height' );
465 echo '</p>';
466
467 echo '<p class="tiny-resize-available tiny-resize-resolution">';
468
469 esc_html_e(
470 'Resizing takes 1 additional compression for each image that is larger.',
471 'tiny-compress-images'
472 );
473
474 echo '</p><br>';
475
476 $this->render_preserve_input(
477 'creation',
478 esc_html__(
479 'Preserve creation date and time in the original image',
480 'tiny-compress-images'
481 ) . ' ' .
482 esc_html__( '(JPEG only)', 'tiny-compress-images' )
483 );
484
485 $this->render_preserve_input(
486 'copyright',
487 esc_html__(
488 'Preserve copyright information in the original image',
489 'tiny-compress-images'
490 )
491 );
492
493 $this->render_preserve_input(
494 'location',
495 esc_html__(
496 'Preserve GPS location in the original image',
497 'tiny-compress-images'
498 ) . ' ' .
499 esc_html__( '(JPEG only)', 'tiny-compress-images' )
500 );
501 }
502
503 public function render_preserve_input( $name, $description ) {
504 echo '<p class="tiny-preserve">';
505 $id = sprintf( self::get_prefixed_name( 'preserve_data_%s' ), $name );
506 $field = sprintf( self::get_prefixed_name( 'preserve_data[%s]' ), $name );
507 $checked = ( $this->get_preserve_enabled( $name ) ? ' checked="checked"' : '' );
508 $label = esc_html__( $description, 'tiny-compress-images' );
509 echo '<input type="checkbox" id="' . $id . '" name="' . $field .
510 '" value="on" ' . $checked . '/>';
511 echo '<label for="' . $id . '">' . $label . '</label>';
512 echo '<br>';
513 echo '</p>';
514 }
515
516 public function render_resize_input( $name ) {
517 $id = sprintf( self::get_prefixed_name( 'resize_original_%s' ), $name );
518 $field = sprintf( self::get_prefixed_name( 'resize_original[%s]' ), $name );
519 $settings = get_option( self::get_prefixed_name( 'resize_original' ) );
520 $value = isset( $settings[ $name ] ) ? $settings[ $name ] : '2048';
521 echo '<input type="number" id="'. $id .'" name="' . $field .
522 '" value="' . $value . '" size="5" />';
523 }
524
525 public function get_compression_count() {
526 $field = self::get_prefixed_name( 'status' );
527 return get_option( $field );
528 }
529
530 public function after_compress_callback( $compressor ) {
531 if ( ! is_null( $count = $compressor->get_compression_count() ) ) {
532 $field = self::get_prefixed_name( 'status' );
533 update_option( $field, $count );
534 }
535 if ( $compressor->limit_reached() ) {
536 $link = '<a href="https://tinypng.com/developers" target="_blank">' .
537 esc_html__( 'TinyPNG API account', 'tiny-compress-images' ) . '</a>';
538
539 $this->notices->add('limit-reached',
540 sprintf(
541 esc_html__(
542 'You have reached your limit of %s compressions this month.',
543 'tiny-compress-images'
544 ),
545 $count
546 ) .
547 sprintf(
548 esc_html__(
549 'Upgrade your %s if you like to compress more images.',
550 'tiny-compress-images'
551 ),
552 $link
553 )
554 );
555 } else {
556 $this->notices->remove( 'limit-reached' );
557 }
558 }
559
560 public function render_account_status() {
561 $key = $this->get_api_key();
562 if ( empty( $key ) ) {
563 $compressor = $this->get_compressor();
564 if ( $compressor->can_create_key() ) {
565 include( dirname( __FILE__ ) . '/views/account-status-create-advanced.php' );
566 } else {
567 include( dirname( __FILE__ ) . '/views/account-status-create-simple.php' );
568 }
569 } else {
570 $status = $this->compressor->get_status();
571 $status->pending = false;
572
573 if ( $status->ok ) {
574 if ( $this->get_api_key_pending() ) {
575 $this->clear_api_key_pending();
576 }
577 } else {
578 if ( $this->get_api_key_pending() ) {
579 $status->ok = true;
580 $status->pending = true;
581 $status->message = (
582 'An email has been sent with a link to activate your account'
583 );
584 }
585 }
586
587 include( dirname( __FILE__ ) . '/views/account-status-connected.php' );
588 }
589 }
590
591 public function render_pending_status() {
592 $key = $this->get_api_key();
593 if ( empty( $key ) ) {
594 $compressor = $this->get_compressor();
595 if ( $compressor->can_create_key() ) {
596 include( dirname( __FILE__ ) . '/views/account-status-create-advanced.php' );
597 } else {
598 include( dirname( __FILE__ ) . '/views/account-status-create-simple.php' );
599 }
600 } else {
601 include( dirname( __FILE__ ) . '/views/account-status-loading.php' );
602 }
603 }
604
605 public function create_api_key() {
606 $compressor = $this->get_compressor();
607 if ( $compressor->can_create_key() ) {
608 if ( ! isset( $_POST['name'] ) || ! $_POST['name'] ) {
609 $status = (object) array(
610 'ok' => false,
611 'message' => __(
612 'Please enter your name', 'tiny-compress-images'
613 ),
614 );
615 echo json_encode( $status );
616 exit();
617 }
618
619 if ( ! isset( $_POST['email'] ) || ! $_POST['email'] ) {
620 $status = (object) array(
621 'ok' => false,
622 'message' => __(
623 'Please enter your email address', 'tiny-compress-images'
624 ),
625 );
626 echo json_encode( $status );
627 exit();
628 }
629
630 try {
631 $site = str_replace( array( 'http://', 'https://' ), '', get_bloginfo( 'url' ) );
632 $identifier = 'WordPress plugin for ' . $site;
633 $link = $this->get_absolute_url();
634 $compressor->create_key( $_POST['email'], array(
635 'name' => $_POST['name'],
636 'identifier' => $identifier,
637 'link' => $link,
638 ) );
639
640 update_option( self::get_prefixed_name( 'api_key_pending' ), true );
641 update_option( self::get_prefixed_name( 'api_key' ), $compressor->get_key() );
642 update_option( self::get_prefixed_name( 'status' ), 0 );
643
644 $status = (object) array(
645 'ok' => true,
646 'message' => null,
647 );
648 } catch (Tiny_Exception $err) {
649 list( $message ) = explode( ' (HTTP', $err->getMessage(), 2 );
650 $status = (object) array(
651 'ok' => false,
652 'message' => $message,
653 );
654 }
655 } else {
656 $status = (object) array(
657 'ok' => false,
658 'message' => 'This feature is not available on your platform',
659 );
660 }
661
662 $status->message = __( $status->message, 'tiny-compress-images' );
663 echo json_encode( $status );
664 exit();
665 }
666
667 public function update_api_key() {
668 $key = $_POST['key'];
669 if ( empty( $key ) ) {
670 /* Always save if key is blank, so the key can be deleted. */
671 $status = (object) array(
672 'ok' => true,
673 'message' => null,
674 );
675 } else {
676 $status = Tiny_Compress::create( $key )->get_status();
677 }
678 if ( $status->ok ) {
679 update_option( self::get_prefixed_name( 'api_key_pending' ), false );
680 update_option( self::get_prefixed_name( 'api_key' ), $key );
681 }
682 $status->message = __( $status->message, 'tiny-compress-images' );
683 echo json_encode( $status );
684 exit();
685 }
686
687 public static function wr2x_active() {
688 return is_plugin_active( 'wp-retina-2x/wp-retina-2x.php' );
689 }
690
691 public function get_wr2x_option() {
692 $setting = get_option( self::get_prefixed_name( 'sizes' ) );
693 return array(
694 'width' => null,
695 'height' => null,
696 'tinify' => ( isset( $setting['wr2x'] ) && 'on' === $setting['wr2x'] ),
697 );
698 }
699
700 public function compress_wr2x_images() {
701 $option = $this->get_wr2x_option();
702 return self::wr2x_active() && $option['tinify'];
703 }
704 }
705