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-plugin.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-plugin.php
765 lines
1 <?php
2 /*
3 * Tiny Compress Images - WordPress plugin.
4 * Copyright (C) 2015-2023 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_Plugin extends Tiny_WP_Base {
21 const VERSION = '3.6.0';
22 const MEDIA_COLUMN = self::NAME;
23 const DATETIME_FORMAT = 'Y-m-d G:i:s';
24
25 private static $version;
26
27 private $settings;
28 private $twig;
29
30 public static function jpeg_quality() {
31 return 85;
32 }
33
34 public static function version() {
35 /* Avoid using get_plugin_data() because it is not loaded early enough
36 in xmlrpc.php. */
37 return self::VERSION;
38 }
39
40 public function __construct() {
41 parent::__construct();
42 $this->settings = new Tiny_Settings();
43 }
44
45 public function set_compressor( $compressor ) {
46 $this->settings->set_compressor( $compressor );
47 }
48
49 public function init() {
50 add_filter( 'jpeg_quality',
51 $this->get_static_method( 'jpeg_quality' )
52 );
53
54 add_filter( 'wp_editor_set_quality',
55 $this->get_static_method( 'jpeg_quality' )
56 );
57
58 add_filter( 'wp_generate_attachment_metadata',
59 $this->get_method( 'process_attachment' ),
60 10, 2
61 );
62
63 add_action( 'delete_attachment', $this->get_method( 'clean_attachment' ), 10, 2 );
64
65 load_plugin_textdomain( self::NAME, false,
66 dirname( plugin_basename( __FILE__ ) ) . '/languages'
67 );
68
69 if ( $this->settings->get_conversion_enabled() ) {
70 new Tiny_Picture( ABSPATH, array( get_site_url() ) );
71 }
72 }
73
74 public function cli_init() {
75 Tiny_CLI::register_command( $this->settings );
76 }
77
78 public function ajax_init() {
79 add_filter( 'wp_ajax_tiny_async_optimize_upload_new_media',
80 $this->get_method( 'compress_on_upload' )
81 );
82
83 add_action( 'wp_ajax_tiny_compress_image_from_library',
84 $this->get_method( 'compress_image_from_library' )
85 );
86
87 add_action( 'wp_ajax_tiny_compress_image_for_bulk',
88 $this->get_method( 'compress_image_for_bulk' )
89 );
90
91 add_action( 'wp_ajax_tiny_get_optimization_statistics',
92 $this->get_method( 'ajax_optimization_statistics' )
93 );
94
95 add_action( 'wp_ajax_tiny_get_compression_status',
96 $this->get_method( 'ajax_compression_status' )
97 );
98
99 /* When touching any functionality linked to image compressions when
100 uploading images make sure it also works with XML-RPC. See README. */
101 add_filter( 'wp_ajax_nopriv_tiny_rpc',
102 $this->get_method( 'process_rpc_request' )
103 );
104
105 if ( $this->settings->compress_wr2x_images() ) {
106 add_action( 'wr2x_upload_retina',
107 $this->get_method( 'compress_original_retina_image' ),
108 10, 2
109 );
110
111 add_action( 'wr2x_retina_file_added',
112 $this->get_method( 'compress_retina_image' ),
113 10, 3
114 );
115
116 add_action( 'wr2x_retina_file_removed',
117 $this->get_method( 'remove_retina_image' ),
118 10, 2
119 );
120 }
121 }
122
123 public function admin_init() {
124 add_action('wp_dashboard_setup',
125 $this->get_method( 'add_dashboard_widget' )
126 );
127
128 add_action( 'admin_enqueue_scripts',
129 $this->get_method( 'enqueue_scripts' )
130 );
131
132 add_action( 'admin_action_tiny_bulk_action',
133 $this->get_method( 'media_library_bulk_action' )
134 );
135
136 add_action( 'admin_action_-1',
137 $this->get_method( 'media_library_bulk_action' )
138 );
139
140 add_filter( 'manage_media_columns',
141 $this->get_method( 'add_media_columns' )
142 );
143
144 add_action( 'manage_media_custom_column',
145 $this->get_method( 'render_media_column' ),
146 10, 2
147 );
148
149 add_action( 'attachment_submitbox_misc_actions',
150 $this->get_method( 'show_media_info' )
151 );
152
153 $plugin = plugin_basename(
154 dirname( dirname( __FILE__ ) ) . '/tiny-compress-images.php'
155 );
156
157 add_filter( "plugin_action_links_$plugin",
158 $this->get_method( 'add_plugin_links' )
159 );
160
161 $this->tiny_compatibility();
162
163 add_thickbox();
164 }
165
166 public function admin_menu() {
167 add_media_page(
168 __( 'Bulk Optimization', 'tiny-compress-images' ),
169 esc_html__( 'Bulk TinyPNG', 'tiny-compress-images' ),
170 'upload_files',
171 'tiny-bulk-optimization',
172 $this->get_method( 'render_bulk_optimization_page' )
173 );
174 }
175
176 public function add_plugin_links( $current_links ) {
177 $additional = array(
178 'settings' => sprintf(
179 '<a href="options-general.php?page=tinify">%s</a>',
180 esc_html__( 'Settings', 'tiny-compress-images' )
181 ),
182 'bulk' => sprintf(
183 '<a href="upload.php?page=tiny-bulk-optimization">%s</a>',
184 esc_html__( 'Bulk TinyPNG', 'tiny-compress-images' )
185 ),
186 );
187 return array_merge( $additional, $current_links );
188 }
189
190 public function tiny_compatibility() {
191 if ( defined( 'ICL_SITEPRESS_VERSION' ) ) {
192 $tiny_wpml_compatibility = new Tiny_WPML();
193 }
194
195 if ( Tiny_AS3CF::is_active() ) {
196 $tiny_as3cf = new Tiny_AS3CF( $this->settings );
197 }
198 }
199
200 public function compress_original_retina_image( $attachment_id, $path ) {
201 $tiny_image = new Tiny_Image( $this->settings, $attachment_id );
202 $tiny_image->compress_retina( 'original_wr2x', $path );
203 }
204
205 public function compress_retina_image( $attachment_id, $path, $size_name ) {
206 $tiny_image = new Tiny_Image( $this->settings, $attachment_id );
207 $tiny_image->compress_retina( $size_name . '_wr2x', $path );
208 }
209
210 public function remove_retina_image( $attachment_id, $path ) {
211 $tiny_image = new Tiny_Image( $this->settings, $attachment_id );
212 $tiny_image->remove_retina_metadata();
213 }
214
215 public function enqueue_scripts( $hook ) {
216 wp_enqueue_style( self::NAME . '_admin',
217 plugins_url( '/css/admin.css', __FILE__ ),
218 array(), self::version()
219 );
220
221 wp_enqueue_style( self::NAME . '_chart',
222 plugins_url( '/css/optimization-chart.css', __FILE__ ),
223 array(), self::version()
224 );
225
226 wp_register_script( self::NAME . '_admin',
227 plugins_url( '/js/admin.js', __FILE__ ),
228 array(), self::version(), true
229 );
230
231 // WordPress < 3.3 does not handle multidimensional arrays
232 wp_localize_script( self::NAME . '_admin', 'tinyCompress', array(
233 'nonce' => wp_create_nonce( 'tiny-compress' ),
234 'wpVersion' => self::wp_version(),
235 'pluginVersion' => self::version(),
236 'L10nAllDone' => __( 'All images are processed', 'tiny-compress-images' ),
237 'L10nNoActionTaken' => __( 'No action taken', 'tiny-compress-images' ),
238 'L10nBulkAction' => __( 'Compress Images', 'tiny-compress-images' ),
239 'L10nCancelled' => __( 'Cancelled', 'tiny-compress-images' ),
240 'L10nCompressing' => __( 'Compressing', 'tiny-compress-images' ),
241 'L10nCompressed' => __( 'compressed', 'tiny-compress-images' ),
242 'L10nConverted' => __( 'converted', 'tiny-compress-images' ),
243 'L10nFile' => __( 'File', 'tiny-compress-images' ),
244 'L10nSizesOptimized' => __( 'Sizes optimized', 'tiny-compress-images' ),
245 'L10nInitialSize' => __( 'Initial size', 'tiny-compress-images' ),
246 'L10nCurrentSize' => __( 'Current size', 'tiny-compress-images' ),
247 'L10nSavings' => __( 'Savings', 'tiny-compress-images' ),
248 'L10nStatus' => __( 'Status', 'tiny-compress-images' ),
249 'L10nShowMoreDetails' => __( 'Show more details', 'tiny-compress-images' ),
250 'L10nError' => __( 'Error', 'tiny-compress-images' ),
251 'L10nLatestError' => __( 'Latest error', 'tiny-compress-images' ),
252 'L10nInternalError' => __( 'Internal error', 'tiny-compress-images' ),
253 'L10nOutOf' => __( 'out of', 'tiny-compress-images' ),
254 'L10nWaiting' => __( 'Waiting', 'tiny-compress-images' ),
255 ));
256
257 wp_enqueue_script( self::NAME . '_admin' );
258
259 if ( 'media_page_tiny-bulk-optimization' == $hook ) {
260 wp_enqueue_style(
261 self::NAME . '_tiny_bulk_optimization',
262 plugins_url( '/css/bulk-optimization.css', __FILE__ ),
263 array(), self::version()
264 );
265
266 wp_enqueue_style( self::NAME . '_chart',
267 plugins_url( '/css/optimization-chart.css', __FILE__ ),
268 array(), self::version()
269 );
270
271 wp_register_script(
272 self::NAME . '_tiny_bulk_optimization',
273 plugins_url( '/js/bulk-optimization.js', __FILE__ ),
274 array(), self::version(), true
275 );
276
277 wp_enqueue_script( self::NAME . '_tiny_bulk_optimization' );
278 }
279 }
280
281 public function process_attachment( $metadata, $attachment_id ) {
282 if ( $this->settings->auto_compress_enabled() ) {
283 if (
284 $this->settings->background_compress_enabled()
285 ) {
286 $this->async_compress_on_upload( $metadata, $attachment_id );
287 } else {
288 return $this->blocking_compress_on_upload( $metadata, $attachment_id );
289 }
290 }
291
292 return $metadata;
293 }
294
295 public function blocking_compress_on_upload( $metadata, $attachment_id ) {
296 if ( ! empty( $metadata ) ) {
297 $tiny_image = new Tiny_Image( $this->settings, $attachment_id, $metadata );
298 $result = $tiny_image->compress();
299 return $tiny_image->get_wp_metadata();
300 } else {
301 return $metadata;
302 }
303 }
304
305 public function async_compress_on_upload( $metadata, $attachment_id ) {
306 $context = 'wp';
307 $action = 'tiny_async_optimize_upload_new_media';
308 $_ajax_nonce = wp_create_nonce( 'new_media-' . $attachment_id );
309 $body = compact( 'action', '_ajax_nonce', 'metadata', 'attachment_id', 'context' );
310
311 $args = array(
312 'timeout' => 0.01,
313 'blocking' => false,
314 'body' => $body,
315 'cookies' => isset( $_COOKIE ) && is_array( $_COOKIE ) ? $_COOKIE : array(),
316 'sslverify' => apply_filters( 'https_local_ssl_verify', false ),
317 );
318
319 if ( defined( 'XMLRPC_REQUEST' ) && get_current_user_id() ) {
320 /* We generate a hash to be used for the transient we use to store the current user. */
321 $rpc_hash = md5( maybe_serialize( $body ) );
322
323 $args['body']['tiny_rpc_action'] = $args['body']['action'];
324 /* We set a different action to make sure that all RPC requests are first validated. */
325 $args['body']['action'] = 'tiny_rpc';
326 $args['body']['tiny_rpc_hash'] = $rpc_hash;
327 $args['body']['tiny_rpc_nonce'] = wp_create_nonce( 'tiny_rpc_' . $rpc_hash );
328
329 /*
330 We can't use cookies here, so we save the user id in a transient
331 so that we can retrieve it again when processing the RPC request.
332 We should be able to use a relatively short timeout, as the request
333 should be processed directly afterwards.
334 */
335 set_transient( 'tiny_rpc_' . $rpc_hash, get_current_user_id(), 10 );
336 }
337
338 if ( getenv( 'WORDPRESS_HOST' ) !== false ) {
339 wp_remote_post( getenv( 'WORDPRESS_HOST' ) . '/wp-admin/admin-ajax.php', $args );
340 } else {
341 wp_remote_post( admin_url( 'admin-ajax.php' ), $args );
342 }
343 }
344
345 public function process_rpc_request() {
346 if (
347 empty( $_POST['tiny_rpc_action'] ) ||
348 empty( $_POST['tiny_rpc_hash'] ) ||
349 32 !== strlen( $_POST['tiny_rpc_hash'] )
350 ) {
351 exit();
352 }
353
354 $rpc_hash = sanitize_key( $_POST['tiny_rpc_hash'] );
355 $user_id = absint( get_transient( 'tiny_rpc_' . $rpc_hash ) );
356 $user = $user_id ? get_userdata( $user_id ) : false;
357
358 /* We no longer need the transient. */
359 delete_transient( 'tiny_rpc_' . $rpc_hash );
360
361 if ( ! $user || ! $user->exists() ) {
362 exit();
363 }
364 wp_set_current_user( $user_id );
365
366 if ( ! check_ajax_referer( 'tiny_rpc_' . $rpc_hash, 'tiny_rpc_nonce', false ) ) {
367 exit();
368 }
369
370 /* Now that everything is checked, perform the actual action. */
371 $action = $_POST['tiny_rpc_action'];
372 unset(
373 $_POST['action'],
374 $_POST['tiny_rpc_action'],
375 $_POST['tiny_rpc_id'],
376 $_POST['tiny_rpc_nonce']
377 );
378 do_action( 'wp_ajax_' . $action );
379 }
380
381 public function compress_on_upload() {
382 if ( ! wp_verify_nonce( $_POST['_ajax_nonce'], 'new_media-' . $_POST['attachment_id'] ) ) {
383 exit;
384 }
385 if ( current_user_can( 'upload_files' ) ) {
386 $attachment_id = intval( $_POST['attachment_id'] );
387 $metadata = $_POST['metadata'];
388 if ( is_array( $metadata ) ) {
389 $tiny_image = new Tiny_Image( $this->settings, $attachment_id, $metadata );
390 $result = $tiny_image->compress();
391 // The wp_update_attachment_metadata call is thrown because the
392 // dimensions of the original image can change. This will then
393 // trigger other plugins and can result in unexpected behaviour and
394 // further changes to the image. This may require another approach.
395 // Note that as of WP 5.3 it is advised to not hook into this filter
396 // anymore, so other plugins are less likely to be triggered.
397 wp_update_attachment_metadata( $attachment_id, $tiny_image->get_wp_metadata() );
398 }
399 }
400 exit();
401 }
402
403 public function compress_image_from_library() {
404 if ( ! $this->check_ajax_referer() ) {
405 exit();
406 }
407 if ( ! current_user_can( 'upload_files' ) ) {
408 $message = esc_html__(
409 "You don't have permission to upload files.",
410 'tiny-compress-images'
411 );
412 echo $message;
413 exit();
414 }
415 if ( empty( $_POST['id'] ) ) {
416 $message = esc_html__(
417 'Not a valid media file.',
418 'tiny-compress-images'
419 );
420 echo $message;
421 exit();
422 }
423 $id = intval( $_POST['id'] );
424 $metadata = wp_get_attachment_metadata( $id );
425 if ( ! is_array( $metadata ) ) {
426 $message = esc_html__(
427 'Could not find metadata of media file.',
428 'tiny-compress-images'
429 );
430 echo $message;
431 exit;
432 }
433
434 $tiny_image = new Tiny_Image( $this->settings, $id, $metadata );
435 $result = $tiny_image->compress();
436
437 // The wp_update_attachment_metadata call is thrown because the
438 // dimensions of the original image can change. This will then
439 // trigger other plugins and can result in unexpected behaviour and
440 // further changes to the image. This may require another approach.
441 // Note that as of WP 5.3 it is advised to not hook into this filter
442 // anymore, so other plugins are less likely to be triggered.
443 wp_update_attachment_metadata( $id, $tiny_image->get_wp_metadata() );
444
445 echo $this->render_compress_details( $tiny_image );
446
447 exit();
448 }
449
450 public function compress_image_for_bulk() {
451 if ( ! $this->check_ajax_referer() ) {
452 exit();
453 }
454 if ( ! current_user_can( 'upload_files' ) ) {
455 $message = esc_html__(
456 "You don't have permission to upload files.",
457 'tiny-compress-images'
458 );
459 echo json_encode( array(
460 'error' => $message,
461 ) );
462 exit();
463 }
464 if ( empty( $_POST['id'] ) ) {
465 $message = esc_html__(
466 'Not a valid media file.',
467 'tiny-compress-images'
468 );
469 echo json_encode( array(
470 'error' => $message,
471 ) );
472 exit();
473 }
474 $id = intval( $_POST['id'] );
475 $metadata = wp_get_attachment_metadata( $id );
476 if ( ! is_array( $metadata ) ) {
477 $message = esc_html__(
478 'Could not find metadata of media file.',
479 'tiny-compress-images'
480 );
481 echo json_encode( array(
482 'error' => $message,
483 ) );
484 exit;
485 }
486
487 $tiny_image_before = new Tiny_Image( $this->settings, $id, $metadata );
488 $image_statistics_before = $tiny_image_before->get_statistics(
489 $this->settings->get_sizes(),
490 $this->settings->get_active_tinify_sizes()
491 );
492 $size_before = $image_statistics_before['compressed_total_size'];
493
494 $tiny_image = new Tiny_Image( $this->settings, $id, $metadata );
495 $result = $tiny_image->compress();
496 $image_statistics = $tiny_image->get_statistics(
497 $this->settings->get_sizes(),
498 $this->settings->get_active_tinify_sizes()
499 );
500 wp_update_attachment_metadata( $id, $tiny_image->get_wp_metadata() );
501
502 $current_library_size = intval( $_POST['current_size'] );
503 $size_after = $image_statistics['compressed_total_size'];
504 $new_library_size = $current_library_size + $size_after - $size_before;
505
506 $result['message'] = $tiny_image->get_latest_error();
507 $result['image_sizes_compressed'] = $image_statistics['image_sizes_compressed'];
508 $result['image_sizes_converted'] = $image_statistics['image_sizes_converted'];
509 $result['image_sizes_optimized'] = $image_statistics['image_sizes_compressed'];
510
511 $result['initial_total_size'] = size_format(
512 $image_statistics['initial_total_size'], 1
513 );
514
515 $result['optimized_total_size'] = size_format(
516 $image_statistics['compressed_total_size'], 1
517 );
518
519 $result['savings'] = $tiny_image->get_savings( $image_statistics );
520 $result['status'] = $this->settings->get_status();
521 $result['thumbnail'] = wp_get_attachment_image(
522 $id, array( '30', '30' ), true, array(
523 'class' => 'pinkynail',
524 'alt' => '',
525 )
526 );
527 $result['size_change'] = $size_after - $size_before;
528 $result['human_readable_library_size'] = size_format( $new_library_size, 2 );
529
530 echo json_encode( $result );
531
532 exit();
533 }
534
535 public function ajax_optimization_statistics() {
536 if ( $this->check_ajax_referer() && current_user_can( 'upload_files' ) ) {
537 $stats = Tiny_Bulk_Optimization::get_optimization_statistics( $this->settings );
538 echo json_encode( $stats );
539 }
540 exit();
541 }
542
543 public function ajax_compression_status() {
544 if ( ! $this->check_ajax_referer() ) {
545 exit();
546 }
547 if ( ! current_user_can( 'upload_files' ) ) {
548 exit();
549 }
550 if ( empty( $_POST['id'] ) ) {
551 $message = esc_html__(
552 'Not a valid media file.',
553 'tiny-compress-images'
554 );
555 echo $message;
556 exit();
557 }
558 $id = intval( $_POST['id'] );
559 $metadata = wp_get_attachment_metadata( $id );
560 if ( ! is_array( $metadata ) ) {
561 $message = esc_html__(
562 'Could not find metadata of media file.',
563 'tiny-compress-images'
564 );
565 echo $message;
566 exit;
567 }
568
569 $tiny_image = new Tiny_Image( $this->settings, $id, $metadata );
570
571 echo $this->render_compress_details( $tiny_image );
572
573 exit();
574 }
575
576 public function media_library_bulk_action() {
577 if ( empty( $_REQUEST['action'] ) || (
578 'tiny_bulk_action' != $_REQUEST['action'] &&
579 'tiny_bulk_action' != $_REQUEST['action2'] ) ) {
580 return;
581 }
582 if ( empty( $_REQUEST['media'] ) || ( ! $_REQUEST['media'] ) ) {
583 $_REQUEST['action'] = '';
584 return;
585 }
586 check_admin_referer( 'bulk-media' );
587 $ids = implode( '-', array_map( 'intval', $_REQUEST['media'] ) );
588 $location = 'upload.php?mode=list&ids=' . $ids;
589
590 if ( ! empty( $_REQUEST['paged'] ) ) {
591 $location = add_query_arg( 'paged', absint( $_REQUEST['paged'] ), $location );
592 }
593 if ( ! empty( $_REQUEST['s'] ) ) {
594 $location = add_query_arg( 's', $_REQUEST['s'], $location );
595 }
596 if ( ! empty( $_REQUEST['m'] ) ) {
597 $location = add_query_arg( 'm', $_REQUEST['m'], $location );
598 }
599
600 wp_redirect( admin_url( $location ) );
601 exit();
602 }
603
604 public function add_media_columns( $columns ) {
605 $columns[ self::MEDIA_COLUMN ] = esc_html__( 'Compression', 'tiny-compress-images' );
606 return $columns;
607 }
608
609 public function render_media_column( $column, $id ) {
610 if ( self::MEDIA_COLUMN === $column ) {
611 $tiny_image = new Tiny_Image( $this->settings, $id );
612 if ( $tiny_image->file_type_allowed() ) {
613 echo '<div class="tiny-ajax-container">';
614 $this->render_compress_details( $tiny_image );
615 echo '</div>';
616 }
617 }
618 }
619
620 public function show_media_info() {
621 global $post;
622 $tiny_image = new Tiny_Image( $this->settings, $post->ID );
623 if ( $tiny_image->file_type_allowed() ) {
624 echo '<div class="misc-pub-section tiny-compress-images">';
625 echo '<h4>';
626 esc_html_e( 'JPEG, PNG, & WebP optimization', 'tiny-compress-images' );
627 echo '</h4>';
628 echo '<div class="tiny-ajax-container">';
629 $this->render_compress_details( $tiny_image );
630 echo '</div>';
631 echo '</div>';
632 }
633 }
634
635 private function render_compress_details( $tiny_image ) {
636 $in_progress = $tiny_image->filter_image_sizes( 'in_progress' );
637 if ( count( $in_progress ) > 0 ) {
638 include( dirname( __FILE__ ) . '/views/compress-details-processing.php' );
639 } else {
640 include( dirname( __FILE__ ) . '/views/compress-details.php' );
641 }
642 }
643
644 public function get_estimated_bulk_cost( $estimated_credit_use ) {
645 return Tiny_Compress::estimate_cost(
646 $estimated_credit_use,
647 $this->settings->get_compression_count()
648 );
649 }
650
651 public function render_bulk_optimization_page() {
652 $stats = Tiny_Bulk_Optimization::get_optimization_statistics( $this->settings );
653
654 $estimated_costs = $this->get_estimated_bulk_cost( $stats['estimated_credit_use'] );
655 $admin_colors = self::retrieve_admin_colors();
656
657 /* This makes sure that up to date information is retrieved from the API. */
658 $this->settings->get_compressor()->get_status();
659
660 $active_tinify_sizes = $this->settings->get_active_tinify_sizes();
661 $remaining_credits = $this->settings->get_remaining_credits();
662 $is_on_free_plan = $this->settings->is_on_free_plan();
663 $email_address = $this->settings->get_email_address();
664
665 include( dirname( __FILE__ ) . '/views/bulk-optimization.php' );
666 }
667
668 public function add_dashboard_widget() {
669 wp_enqueue_style( self::NAME . '_chart',
670 plugins_url( '/css/optimization-chart.css', __FILE__ ),
671 array(), self::version()
672 );
673
674 wp_enqueue_style( self::NAME . '_dashboard_widget',
675 plugins_url( '/css/dashboard-widget.css', __FILE__ ),
676 array(), self::version()
677 );
678
679 wp_register_script( self::NAME . '_dashboard_widget',
680 plugins_url( '/js/dashboard-widget.js', __FILE__ ),
681 array(), self::version(), true
682 );
683
684 /* This might be deduplicated with the admin script localization, but
685 the order of including scripts is sometimes different. So in that
686 case we need to make sure that the order of inclusion is correc.t */
687 wp_localize_script( self::NAME . '_dashboard_widget', 'tinyCompressDashboard', array(
688 'nonce' => wp_create_nonce( 'tiny-compress' ),
689 ));
690
691 wp_enqueue_script( self::NAME . '_dashboard_widget' );
692
693 wp_add_dashboard_widget(
694 $this->get_prefixed_name( 'dashboard_widget' ),
695 esc_html__( 'TinyPNG - JPEG, PNG & WebP image compression', 'tiny-compress-images' ),
696 $this->get_method( 'add_widget_view' )
697 );
698 }
699
700 function add_widget_view() {
701 $admin_colors = self::retrieve_admin_colors();
702 include( dirname( __FILE__ ) . '/views/dashboard-widget.php' );
703 }
704
705 private static function retrieve_admin_colors() {
706 global $_wp_admin_css_colors;
707 $admin_colour_scheme = get_user_option( 'admin_color', get_current_user_id() );
708 $admin_colors = array( '#0074aa', '#1685b5', '#78ca44', '#0086ba' ); // default
709 if ( isset( $_wp_admin_css_colors[ $admin_colour_scheme ] ) ) {
710 if ( isset( $_wp_admin_css_colors[ $admin_colour_scheme ]->colors ) ) {
711 $admin_colors = $_wp_admin_css_colors[ $admin_colour_scheme ]->colors;
712 }
713 }
714 if ( '#e5e5e5' == $admin_colors[0] && '#999' == $admin_colors[1] ) {
715 $admin_colors[0] = '#bbb';
716 }
717 if ( '#5589aa' == $admin_colors[0] && '#cfdfe9' == $admin_colors[1] ) {
718 $admin_colors[1] = '#85aec5';
719 }
720 if ( '#7c7976' == $admin_colors[0] && '#c6c6c6' == $admin_colors[1] ) {
721 $admin_colors[1] = '#adaba9';
722 $admin_colors[2] = '#adaba9';
723 }
724 if ( self::wp_version() > 3.7 ) {
725 if ( 'fresh' == $admin_colour_scheme ) {
726 $admin_colors = array( '#0074aa', '#1685b5', '#78ca44', '#0086ba' ); // better
727 }
728 }
729 return $admin_colors;
730 }
731
732 function friendly_user_name() {
733 $user = wp_get_current_user();
734 $name = ucfirst( empty( $user->first_name ) ? $user->display_name : $user->first_name );
735 return $name;
736 }
737
738 /**
739 * Will clean up converted files (if any) when the original is deleted
740 *
741 * Hooked to the `delete_attachment` action.
742 * @see https://developer.wordpress.org/reference/hooks/deleted_post/
743 *
744 * @param [int] $post_id
745 *
746 * @return void
747 */
748 function clean_attachment( $post_id ) {
749 $tiny_image = new Tiny_Image( $this->settings, $post_id );
750 $tiny_image->delete_converted_image();
751 }
752
753 static function request_review() {
754 $review_url = 'https://wordpress.org/support/plugin/tiny-compress-images/reviews/#new-post';
755 $review_block = esc_html__( 'Enjoying TinyPNG?', 'tiny-compress-images' );
756 $review_block .= ' ';
757 $review_block .= sprintf(
758 '<a href="%s" target="_blank">%s</a>',
759 esc_url( $review_url ),
760 esc_html__( 'Write a review', 'tiny-compress-images' )
761 );
762 return $review_block;
763 }
764 }
765