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