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