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