PluginProbe ʕ •ᴥ•ʔ
TinyPNG – JPEG, PNG & WebP image compression / 2.2.6
TinyPNG – JPEG, PNG & WebP image compression v2.2.6
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
config 9 years ago css 8 years ago data 9 years ago images 9 years ago js 8 years ago vendor 9 years ago views 8 years ago class-tiny-compress-client.php 9 years ago class-tiny-compress-fopen.php 9 years ago class-tiny-compress.php 9 years ago class-tiny-exception.php 9 years ago class-tiny-image-size.php 9 years ago class-tiny-image.php 8 years ago class-tiny-notices.php 9 years ago class-tiny-php.php 9 years ago class-tiny-plugin.php 8 years ago class-tiny-settings.php 8 years ago class-tiny-wp-base.php 9 years ago
class-tiny-plugin.php
539 lines
1 <?php
2 /*
3 * Tiny Compress Images - WordPress plugin.
4 * Copyright (C) 2015-2017 Voormedia B.V.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc., 51
18 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20 class Tiny_Plugin extends Tiny_WP_Base {
21 const VERSION = '2.2.6';
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
43 $this->settings = new Tiny_Settings();
44 }
45
46 public function set_compressor( $compressor ) {
47 $this->settings->set_compressor( $compressor );
48 }
49
50 public function init() {
51 add_filter( 'jpeg_quality',
52 $this->get_static_method( 'jpeg_quality' )
53 );
54
55 add_filter( 'wp_editor_set_quality',
56 $this->get_static_method( 'jpeg_quality' )
57 );
58
59 add_filter( 'wp_generate_attachment_metadata',
60 $this->get_method( 'compress_on_upload' ),
61 10, 2
62 );
63
64 load_plugin_textdomain( self::NAME, false,
65 dirname( plugin_basename( __FILE__ ) ) . '/languages'
66 );
67 }
68
69 public function admin_init() {
70 add_action('wp_dashboard_setup',
71 $this->get_method( 'add_dashboard_widget' )
72 );
73
74 add_action( 'admin_enqueue_scripts',
75 $this->get_method( 'enqueue_scripts' )
76 );
77
78 add_action( 'admin_action_tiny_bulk_action',
79 $this->get_method( 'media_library_bulk_action' )
80 );
81
82 add_action( 'admin_action_-1',
83 $this->get_method( 'media_library_bulk_action' )
84 );
85
86 add_filter( 'manage_media_columns',
87 $this->get_method( 'add_media_columns' )
88 );
89
90 add_action( 'manage_media_custom_column',
91 $this->get_method( 'render_media_column' ),
92 10, 2
93 );
94
95 add_action( 'attachment_submitbox_misc_actions',
96 $this->get_method( 'show_media_info' )
97 );
98
99 add_action( 'wp_ajax_tiny_compress_image_from_library',
100 $this->get_method( 'compress_image_from_library' )
101 );
102
103 add_action( 'wp_ajax_tiny_compress_image_for_bulk',
104 $this->get_method( 'compress_image_for_bulk' )
105 );
106
107 add_action( 'wp_ajax_tiny_get_optimization_statistics',
108 $this->get_method( 'ajax_optimization_statistics' )
109 );
110
111 $plugin = plugin_basename(
112 dirname( dirname( __FILE__ ) ) . '/tiny-compress-images.php'
113 );
114
115 add_filter( "plugin_action_links_$plugin",
116 $this->get_method( 'add_plugin_links' )
117 );
118
119 add_action( 'wr2x_retina_file_added',
120 $this->get_method( 'compress_retina_image' ),
121 10, 3
122 );
123
124 add_action( 'wr2x_retina_file_removed',
125 $this->get_method( 'remove_retina_image' ),
126 10, 2
127 );
128
129 add_thickbox();
130 }
131
132 public function admin_menu() {
133 add_media_page(
134 __( 'Bulk Optimization', 'tiny-compress-images' ),
135 esc_html__( 'Bulk Optimization', 'tiny-compress-images' ),
136 'upload_files',
137 'tiny-bulk-optimization',
138 $this->get_method( 'render_bulk_optimization_page' )
139 );
140 }
141
142 public function add_plugin_links( $current_links ) {
143 $additional = array(
144 'settings' => sprintf(
145 '<a href="options-media.php#%s">%s</a>',
146 self::NAME,
147 esc_html__( 'Settings', 'tiny-compress-images' )
148 ),
149 'bulk' => sprintf(
150 '<a href="upload.php?page=tiny-bulk-optimization">%s</a>',
151 esc_html__( 'Bulk Optimization', 'tiny-compress-images' )
152 ),
153 );
154 return array_merge( $additional, $current_links );
155 }
156
157 public function compress_retina_image( $attachment_id, $path, $size_name ) {
158 if ( $this->settings->compress_wr2x_images() ) {
159 $tiny_image = new Tiny_Image( $this->settings, $attachment_id );
160 $tiny_image->compress_retina( $size_name . '_wr2x', $path );
161 }
162 }
163
164 public function remove_retina_image( $attachment_id, $path ) {
165 $tiny_image = new Tiny_Image( $this->settings, $attachment_id );
166 $tiny_image->remove_retina_metadata();
167 }
168
169 public function enqueue_scripts( $hook ) {
170 wp_enqueue_style( self::NAME . '_admin',
171 plugins_url( '/css/admin.css', __FILE__ ),
172 array(), self::version()
173 );
174
175 wp_enqueue_style( self::NAME . '_chart',
176 plugins_url( '/css/chart.css', __FILE__ ),
177 array(), self::version()
178 );
179
180 wp_register_script( self::NAME . '_admin',
181 plugins_url( '/js/admin.js', __FILE__ ),
182 array(), self::version(), true
183 );
184
185 // WordPress < 3.3 does not handle multidimensional arrays
186 wp_localize_script( self::NAME . '_admin', 'tinyCompress', array(
187 'nonce' => wp_create_nonce( 'tiny-compress' ),
188 'wpVersion' => self::wp_version(),
189 'pluginVersion' => self::version(),
190 'L10nAllDone' => __( 'All images are processed', 'tiny-compress-images' ),
191 'L10nNoActionTaken' => __( 'No action taken', 'tiny-compress-images' ),
192 'L10nBulkAction' => __( 'Compress Images', 'tiny-compress-images' ),
193 'L10nCancelled' => __( 'Cancelled', 'tiny-compress-images' ),
194 'L10nCompressing' => __( 'Compressing', 'tiny-compress-images' ),
195 'L10nCompressed' => __( 'compressed', 'tiny-compress-images' ),
196 'L10nFile' => __( 'File', 'tiny-compress-images' ),
197 'L10nSizesOptimized' => __( 'Sizes optimized', 'tiny-compress-images' ),
198 'L10nInitialSize' => __( 'Initial size', 'tiny-compress-images' ),
199 'L10nCurrentSize' => __( 'Current size', 'tiny-compress-images' ),
200 'L10nSavings' => __( 'Savings', 'tiny-compress-images' ),
201 'L10nStatus' => __( 'Status', 'tiny-compress-images' ),
202 'L10nShowMoreDetails' => __( 'Show more details', 'tiny-compress-images' ),
203 'L10nError' => __( 'Error', 'tiny-compress-images' ),
204 'L10nLatestError' => __( 'Latest error', 'tiny-compress-images' ),
205 'L10nInternalError' => __( 'Internal error', 'tiny-compress-images' ),
206 'L10nOutOf' => __( 'out of', 'tiny-compress-images' ),
207 'L10nWaiting' => __( 'Waiting', 'tiny-compress-images' ),
208 ));
209
210 wp_enqueue_script( self::NAME . '_admin' );
211
212 if ( 'media_page_tiny-bulk-optimization' == $hook ) {
213 wp_enqueue_style(
214 self::NAME . '_tiny_bulk_optimization',
215 plugins_url( '/css/bulk-optimization.css', __FILE__ ),
216 array(), self::version()
217 );
218
219 wp_enqueue_style( self::NAME . '_chart',
220 plugins_url( '/css/chart.css', __FILE__ ),
221 array(), self::version()
222 );
223
224 wp_register_script(
225 self::NAME . '_tiny_bulk_optimization',
226 plugins_url( '/js/bulk-optimization.js', __FILE__ ),
227 array(), self::version(), true
228 );
229
230 wp_enqueue_script( self::NAME . '_tiny_bulk_optimization' );
231 }
232
233 }
234
235 public function compress_on_upload( $metadata, $attachment_id ) {
236 if ( ! empty( $metadata ) ) {
237 $tiny_image = new Tiny_Image( $this->settings, $attachment_id, $metadata );
238 $result = $tiny_image->compress( $this->settings );
239 return $tiny_image->get_wp_metadata();
240 } else {
241 return $metadata;
242 }
243 }
244
245 public function compress_image_from_library() {
246 if ( ! $this->check_ajax_referer() ) {
247 exit();
248 }
249 if ( ! current_user_can( 'upload_files' ) ) {
250 $message = esc_html__(
251 "You don't have permission to upload files.",
252 'tiny-compress-images'
253 );
254 echo $message;
255 exit();
256 }
257 if ( empty( $_POST['id'] ) ) {
258 $message = esc_html__(
259 'Not a valid media file.',
260 'tiny-compress-images'
261 );
262 echo $message;
263 exit();
264 }
265 $id = intval( $_POST['id'] );
266 $metadata = wp_get_attachment_metadata( $id );
267 if ( ! is_array( $metadata ) ) {
268 $message = esc_html__(
269 'Could not find metadata of media file.',
270 'tiny-compress-images'
271 );
272 echo $message;
273 exit;
274 }
275
276 $tiny_image = new Tiny_Image( $this->settings, $id, $metadata );
277 $result = $tiny_image->compress( $this->settings );
278
279 // The wp_update_attachment_metadata call is thrown because the
280 // dimensions of the original image can change. This will then
281 // trigger other plugins and can result in unexpected behaviour and
282 // further changes to the image. This may require another approach.
283 wp_update_attachment_metadata( $id, $tiny_image->get_wp_metadata() );
284
285 echo $this->render_compress_details( $tiny_image );
286
287 exit();
288 }
289
290 public function compress_image_for_bulk() {
291 if ( ! $this->check_ajax_referer() ) {
292 exit();
293 }
294 if ( ! current_user_can( 'upload_files' ) ) {
295 $message = esc_html__(
296 "You don't have permission to upload files.",
297 'tiny-compress-images'
298 );
299 echo json_encode( array(
300 'error' => $message,
301 ) );
302 exit();
303 }
304 if ( empty( $_POST['id'] ) ) {
305 $message = esc_html__(
306 'Not a valid media file.',
307 'tiny-compress-images'
308 );
309 echo json_encode( array(
310 'error' => $message,
311 ) );
312 exit();
313 }
314 $id = intval( $_POST['id'] );
315 $metadata = wp_get_attachment_metadata( $id );
316 if ( ! is_array( $metadata ) ) {
317 $message = esc_html__(
318 'Could not find metadata of media file.',
319 'tiny-compress-images'
320 );
321 echo json_encode( array(
322 'error' => $message,
323 ) );
324 exit;
325 }
326
327 $tiny_image_before = new Tiny_Image( $this->settings, $id, $metadata );
328 $image_statistics_before = $tiny_image_before->get_statistics();
329 $size_before = $image_statistics_before['optimized_total_size'];
330
331 $tiny_image = new Tiny_Image( $this->settings, $id, $metadata );
332 $result = $tiny_image->compress( $this->settings );
333 $image_statistics = $tiny_image->get_statistics();
334 wp_update_attachment_metadata( $id, $tiny_image->get_wp_metadata() );
335
336 $current_library_size = intval( $_POST['current_size'] );
337 $size_after = $image_statistics['optimized_total_size'];
338 $new_library_size = $current_library_size + $size_after - $size_before;
339
340 $result['message'] = $tiny_image->get_latest_error();
341 $result['image_sizes_optimized'] = $image_statistics['image_sizes_optimized'];
342
343 $result['initial_total_size'] = size_format(
344 $image_statistics['initial_total_size'], 1
345 );
346
347 $result['optimized_total_size'] = size_format(
348 $image_statistics['optimized_total_size'], 1
349 );
350
351 $result['savings'] = $tiny_image->get_savings( $image_statistics );
352 $result['status'] = $this->settings->get_status();
353 $result['thumbnail'] = wp_get_attachment_image(
354 $id, array( '30', '30' ), true, array(
355 'class' => 'pinkynail',
356 'alt' => '',
357 )
358 );
359 $result['size_change'] = $size_after - $size_before;
360 $result['human_readable_library_size'] = size_format( $new_library_size, 2 );
361
362 echo json_encode( $result );
363
364 exit();
365 }
366
367 public function ajax_optimization_statistics() {
368 if ( ! $this->check_ajax_referer() ) {
369 exit();
370 }
371 $stats = Tiny_Image::get_optimization_statistics( $this->settings );
372 echo json_encode( $stats );
373 exit();
374 }
375
376 public function media_library_bulk_action() {
377
378 if ( empty( $_REQUEST['action'] ) || (
379 'tiny_bulk_action' != $_REQUEST['action'] &&
380 'tiny_bulk_action' != $_REQUEST['action2'] ) ) {
381 return;
382 }
383
384 if ( empty( $_REQUEST['media'] ) || ( ! $_REQUEST['media'] ) ) {
385 return;
386 }
387
388 check_admin_referer( 'bulk-media' );
389 $ids = implode( '-', array_map( 'intval', $_REQUEST['media'] ) );
390 wp_redirect(add_query_arg(
391 '_wpnonce',
392 wp_create_nonce( 'tiny-bulk-optimization' ),
393 admin_url( "upload.php?page=tiny-bulk-optimization&ids=$ids" )
394 ));
395 exit();
396 }
397
398 public function add_media_columns( $columns ) {
399 $columns[ self::MEDIA_COLUMN ] = esc_html__( 'Compression', 'tiny-compress-images' );
400 return $columns;
401 }
402
403 public function render_media_column( $column, $id ) {
404 if ( self::MEDIA_COLUMN === $column ) {
405 $tiny_image = new Tiny_Image( $this->settings, $id );
406 if ( $tiny_image->file_type_allowed() ) {
407 echo '<div class="tiny-ajax-container">';
408 $this->render_compress_details( $tiny_image );
409 echo '</div>';
410 }
411 }
412 }
413
414 public function show_media_info() {
415 global $post;
416 $tiny_image = new Tiny_Image( $this->settings, $post->ID );
417 if ( $tiny_image->file_type_allowed() ) {
418 echo '<div class="misc-pub-section tiny-compress-images">';
419 echo '<h4>';
420 esc_html_e( 'JPEG and PNG optimization', 'tiny-compress-images' );
421 echo '</h4>';
422 echo '<div class="tiny-ajax-container">';
423 $this->render_compress_details( $tiny_image );
424 echo '</div>';
425 echo '</div>';
426 }
427 }
428
429 private function render_compress_details( $tiny_image ) {
430 $in_progress = $tiny_image->filter_image_sizes( 'in_progress' );
431 if ( count( $in_progress ) > 0 ) {
432 include( dirname( __FILE__ ) . '/views/compress-details-processing.php' );
433 } else {
434 include( dirname( __FILE__ ) . '/views/compress-details.php' );
435 }
436 }
437
438 public function render_bulk_optimization_page() {
439 $stats = Tiny_Image::get_optimization_statistics( $this->settings );
440 $estimated_costs = Tiny_Compress::estimate_cost(
441 $stats['available-unoptimised-sizes'],
442 $this->settings->get_compression_count()
443 );
444 $admin_colors = self::retrieve_admin_colors();
445
446 $active_tinify_sizes = $this->settings->get_active_tinify_sizes();
447
448 $auto_start_bulk = isset( $_REQUEST['ids'] );
449
450 include( dirname( __FILE__ ) . '/views/bulk-optimization.php' );
451 }
452
453 public function add_dashboard_widget() {
454 wp_enqueue_style( self::NAME . '_chart',
455 plugins_url( '/css/chart.css', __FILE__ ),
456 array(), self::version()
457 );
458
459 wp_enqueue_style( self::NAME . '_dashboard_widget',
460 plugins_url( '/css/dashboard-widget.css', __FILE__ ),
461 array(), self::version()
462 );
463
464 wp_register_script( self::NAME . '_dashboard_widget',
465 plugins_url( '/js/dashboard-widget.js', __FILE__ ),
466 array(), self::version(), true
467 );
468
469 /* This might be deduplicated with the admin script localization, but
470 the order of including scripts is sometimes different. So in that
471 case we need to make sure that the order of inclusion is correc.t */
472 wp_localize_script( self::NAME . '_dashboard_widget', 'tinyCompressDashboard', array(
473 'nonce' => wp_create_nonce( 'tiny-compress' ),
474 ));
475
476 wp_enqueue_script( self::NAME . '_dashboard_widget' );
477
478 wp_add_dashboard_widget(
479 $this->get_prefixed_name( 'dashboard_widget' ),
480 esc_html__( 'Compress JPEG & PNG images', 'tiny-compress-images' ),
481 $this->get_method( 'add_widget_view' )
482 );
483 }
484
485 function add_widget_view() {
486 $admin_colors = self::retrieve_admin_colors();
487 include( dirname( __FILE__ ) . '/views/dashboard-widget.php' );
488 }
489
490 private static function retrieve_admin_colors() {
491 global $_wp_admin_css_colors;
492 $admin_colour_scheme = get_user_option( 'admin_color', get_current_user_id() );
493 $admin_colors = array( '#0074aa', '#1685b5', '#78ca44', '#0086ba' ); // default
494 if ( isset( $_wp_admin_css_colors[ $admin_colour_scheme ] ) ) {
495 if ( isset( $_wp_admin_css_colors[ $admin_colour_scheme ]->colors ) ) {
496 $admin_colors = $_wp_admin_css_colors[ $admin_colour_scheme ]->colors;
497 }
498 }
499 if ( '#e5e5e5' == $admin_colors[0] && '#999' == $admin_colors[1] ) {
500 $admin_colors[0] = '#bbb';
501 }
502 if ( '#5589aa' == $admin_colors[0] && '#cfdfe9' == $admin_colors[1] ) {
503 $admin_colors[1] = '#85aec5';
504 }
505 if ( '#7c7976' == $admin_colors[0] && '#c6c6c6' == $admin_colors[1] ) {
506 $admin_colors[1] = '#adaba9';
507 $admin_colors[2] = '#adaba9';
508 }
509 if ( self::wp_version() > 3.7 ) {
510 if ( 'fresh' == $admin_colour_scheme ) {
511 $admin_colors = array( '#0074aa', '#1685b5', '#78ca44', '#0086ba' ); // better
512 }
513 }
514 return $admin_colors;
515 }
516
517 function friendly_user_name() {
518 $user = wp_get_current_user();
519 $name = ucfirst( empty( $user->first_name ) ? $user->display_name : $user->first_name );
520 return $name;
521 }
522
523 private function get_ids_to_compress() {
524 if ( empty( $_REQUEST['ids'] ) ) {
525 return array();
526 }
527
528 $ids = implode( ',', array_map( 'intval', explode( '-', $_REQUEST['ids'] ) ) );
529 $condition = "AND ID IN($ids)";
530
531 global $wpdb;
532 return $wpdb->get_results( // WPCS: unprepared SQL OK.
533 "SELECT ID, post_title FROM $wpdb->posts
534 WHERE post_type = 'attachment' $condition
535 AND (post_mime_type = 'image/jpeg' OR post_mime_type = 'image/png')
536 ORDER BY ID DESC", ARRAY_A);
537 }
538 }
539