PluginProbe ʕ •ᴥ•ʔ
reSmush.it : The original free image compressor and optimizer plugin / 0.4.4
reSmush.it : The original free image compressor and optimizer plugin v0.4.4
1.0.6 trunk 0.1.1 0.1.10 0.1.11 0.1.12 0.1.13 0.1.14 0.1.15 0.1.16 0.1.17 0.1.18 0.1.19 0.1.2 0.1.20 0.1.21 0.1.22 0.1.23 0.1.3 0.1.4 0.1.5 0.1.6 0.1.7 0.1.8 0.1.9 0.2.0 0.2.1 0.2.2 0.2.3 0.2.4 0.2.5 0.3.0 0.3.1 0.3.10 0.3.11 0.3.12 0.3.2 0.3.3 0.3.4 0.3.5 0.3.6 0.3.7 0.3.8 0.3.9 0.4.0 0.4.1 0.4.10 0.4.11 0.4.12 0.4.13 0.4.14 0.4.2 0.4.3 0.4.4 0.4.5 0.4.6 0.4.7 0.4.8 0.4.9 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5
resmushit-image-optimizer / resmushit.php
resmushit-image-optimizer Last commit date
classes 3 years ago css 3 years ago images 6 years ago js 5 years ago languages 3 years ago readme.txt 3 years ago resmushit.admin.php 5 years ago resmushit.inc.php 5 years ago resmushit.php 3 years ago resmushit.settings.php 3 years ago
resmushit.php
531 lines
1 <?php
2 /**
3 * @package resmushit
4 * @author Charles Bourgeaux <hello@resmush.it>
5 * @license GPL-2.0+
6 * @link http://www.resmush.it
7 * @copyright 2022 Resmush.it
8 *
9 * @wordpress-plugin
10 * Plugin Name: reSmush.it Image Optimizer
11 * Plugin URI: https://wordpress.org/plugins/resmushit-image-optimizer/
12 * Description: Image Optimization API. Provides image size optimization
13 * Version: 0.4.4
14 * Timestamp: 2022.08.10
15 * Author: reSmush.it
16 * Author URI: https://resmush.it
17 * Author: Charles Bourgeaux
18 * License: GPL-2.0+
19 * License URI: http://www.gnu.org/licenses/gpl-2.0.txt
20 * Domain Path: /languages
21 * Text Domain: resmushit-image-optimizer
22 */
23
24 require('resmushit.inc.php');
25
26
27 /**
28 *
29 * Registering language plugin
30 *
31 * @param none
32 * @return none
33 */
34 function resmushit_load_plugin_textdomain() {
35 load_plugin_textdomain( 'resmushit', FALSE, plugin_basename( dirname( __FILE__ ) ) . '/languages' );
36 }
37 add_action( 'plugins_loaded', 'resmushit_load_plugin_textdomain' );
38
39
40
41
42
43 /**
44 *
45 * Registering settings on plugin installation
46 *
47 * @param none
48 * @return none
49 */
50 function resmushit_activate() {
51 if ( is_super_admin() ) {
52 if(get_option('resmushit_qlty') === false)
53 update_option( 'resmushit_qlty', RESMUSHIT_DEFAULT_QLTY );
54 if(get_option('resmushit_on_upload') === false)
55 update_option( 'resmushit_on_upload', '1' );
56 if(get_option('resmushit_statistics') === false)
57 update_option( 'resmushit_statistics', '1' );
58 if(get_option('resmushit_total_optimized') === false || get_option('resmushit_total_optimized') == "")
59 update_option( 'resmushit_total_optimized', '0' );
60 if(get_option('resmushit_cron') === false || get_option('resmushit_cron') == "")
61 update_option( 'resmushit_cron', 0 );
62 if(get_option('resmushit_cron_lastaction') === false || get_option('resmushit_cron_lastaction') == "")
63 update_option( 'resmushit_cron_lastaction', 0 );
64 if(get_option('resmushit_cron_lastrun') === false || get_option('resmushit_cron_lastrun') == "")
65 update_option( 'resmushit_cron_lastrun', 0 );
66 if(get_option('resmushit_cron_firstactivation') === false || get_option('resmushit_cron_firstactivation') == "")
67 update_option( 'resmushit_cron_firstactivation', 0 );
68 if(get_option('resmushit_preserve_exif') === false || get_option('resmushit_preserve_exif') == "")
69 update_option( 'resmushit_preserve_exif', 0 );
70 if(get_option('resmushit_remove_unsmushed') === false || get_option('resmushit_remove_unsmushed') == "")
71 update_option( 'resmushit_remove_unsmushed', 0 );
72 if(get_option('resmushit_has_no_backup_files') === false || get_option('resmushit_has_no_backup_files') == "")
73 update_option( 'resmushit_has_no_backup_files', 0 );
74 }
75 }
76 register_activation_hook( __FILE__, 'resmushit_activate' );
77 add_action( 'admin_init', 'resmushit_activate' );
78
79
80 /**
81 * Run using the 'init' action.
82 */
83 function resmushit_init() {
84 load_plugin_textdomain( 'resmushit-image-optimizer', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' );
85 }
86 add_action( 'admin_init', 'resmushit_init' );
87
88
89 /**
90 *
91 * Call resmush.it optimization for attachments
92 *
93 * @param attachment object
94 * @param boolean preserve original file
95 * @return attachment object
96 */
97 function resmushit_process_images($attachments, $force_keep_original = TRUE) {
98 global $attachment_id;
99 $cumulated_original_sizes = 0;
100 $cumulated_optimized_sizes = 0;
101 $error = FALSE;
102
103 if(reSmushit::getDisabledState($attachment_id))
104 return $attachments;
105
106 if(empty($attachments)) {
107 rlog("Error! Attachment #$attachment_id has no corresponding file on disk.", 'WARNING');
108 return $attachments;
109 }
110
111 $fileInfo = pathinfo(get_attached_file( $attachment_id ));
112 $basepath = $fileInfo['dirname'] . '/';
113 $extension = isset($fileInfo['extension']) ? $fileInfo['extension'] : NULL;
114 $basefile = basename($attachments[ 'file' ]);
115
116 // Optimize only pictures/files accepted by the API
117 if( !in_array(strtolower($extension), resmushit::authorizedExtensions()) ) {
118 return $attachments;
119 }
120
121 $statistics[] = reSmushit::optimize($basepath . $basefile, $force_keep_original );
122
123 foreach($attachments['sizes'] as $image_style)
124 $statistics[] = reSmushit::optimize($basepath . $image_style['file'], FALSE );
125
126 $count = 0;
127 foreach($statistics as $stat){
128 if($stat && !isset($stat->error)){
129 $cumulated_original_sizes += $stat->src_size;
130 $cumulated_optimized_sizes += $stat->dest_size;
131 $count++;
132 } else
133 $error = TRUE;
134 }
135 if(!$error) {
136 $optimizations_successful_count = get_option('resmushit_total_optimized');
137 update_option( 'resmushit_total_optimized', $optimizations_successful_count + $count );
138 update_post_meta($attachment_id,'resmushed_quality', resmushit::getPictureQualitySetting());
139 update_post_meta($attachment_id,'resmushed_cumulated_original_sizes', $cumulated_original_sizes);
140 update_post_meta($attachment_id,'resmushed_cumulated_optimized_sizes', $cumulated_optimized_sizes);
141 }
142 return $attachments;
143 }
144 //Automatically optimize images if option is checked
145 if(get_option('resmushit_on_upload') OR ( isset($_POST['action']) AND ($_POST['action'] === "resmushit_bulk_process_image" OR $_POST['action'] === "resmushit_optimize_single_attachment" )) OR (defined( 'WP_CLI' ) && WP_CLI ) OR ($is_cron) )
146 add_filter('wp_generate_attachment_metadata', 'resmushit_process_images');
147
148
149
150
151
152
153 /**
154 *
155 * Delete also -unsmushed file (ie. Original file) when deleting an attachment
156 *
157 * @param int postID
158 * @return none
159 */
160 function resmushit_delete_attachment($postid) {
161 reSmushit::deleteOriginalFile($postid);
162 }
163 add_action( 'delete_attachment', 'resmushit_delete_attachment' );
164
165
166
167
168
169 /**
170 *
171 * Make current attachment available
172 *
173 * @param attachment object
174 * @return attachment object
175 */
176 function resmushit_get_meta_id($result){
177 global $attachment_id;
178 $attachment_id = $result;
179 }
180 //Automatically retrieve image attachment ID if option is checked
181 if(get_option('resmushit_on_upload'))
182 add_filter('add_attachment', 'resmushit_get_meta_id');
183
184
185
186
187
188 /**
189 *
190 * add Ajax action to fetch all unsmushed pictures
191 *
192 * @param none
193 * @return json object
194 */
195 function resmushit_bulk_get_images() {
196 if(!is_super_admin() && !current_user_can('administrator')) {
197 return(json_encode(array('error' => 'User must be at least administrator to retrieve these data')));
198 die();
199 }
200 echo reSmushit::getNonOptimizedPictures();
201 die();
202 }
203 add_action( 'wp_ajax_resmushit_bulk_get_images', 'resmushit_bulk_get_images' );
204
205
206
207
208 /**
209 *
210 * add Ajax action to change disabled state for an attachment
211 *
212 * @param none
213 * @return json object
214 */
215 function resmushit_update_disabled_state() {
216 if(!is_super_admin() && !current_user_can('administrator')) {
217 return(json_encode(array('error' => 'User must be at least administrator to retrieve these data')));
218 die();
219 }
220 if(isset($_POST['data']['id']) && $_POST['data']['id'] != null && isset($_POST['data']['disabled'])){
221 echo reSmushit::updateDisabledState(sanitize_text_field((int)$_POST['data']['id']), sanitize_text_field($_POST['data']['disabled']));
222 }
223 die();
224 }
225 add_action( 'wp_ajax_resmushit_update_disabled_state', 'resmushit_update_disabled_state' );
226
227
228
229
230
231 /**
232 *
233 * add Ajax action to optimize a single attachment in the library
234 *
235 * @param none
236 * @return json object
237 */
238 function resmushit_optimize_single_attachment() {
239 if(!is_super_admin() && !current_user_can('administrator')) {
240 return(json_encode(array('error' => 'User must be at least administrator to retrieve these data')));
241 die();
242 }
243 if(isset($_POST['data']['id']) && $_POST['data']['id'] != null){
244 reSmushit::revert(sanitize_text_field((int)$_POST['data']['id']));
245 echo json_encode(reSmushit::getStatistics(sanitize_text_field((int)$_POST['data']['id'])));
246 }
247 die();
248 }
249 add_action( 'wp_ajax_resmushit_optimize_single_attachment', 'resmushit_optimize_single_attachment' );
250
251
252
253
254
255 /**
256 *
257 * add Ajax action to optimize a picture according to attachment ID
258 *
259 * @param none
260 * @return boolean
261 */
262 function resmushit_bulk_process_image() {
263 if(!is_super_admin() && !current_user_can('administrator')) {
264 return(json_encode(array('error' => 'User must be at least administrator to retrieve these data')));
265 die();
266 }
267 rlog('Bulk optimization launched for file : ' . get_attached_file( sanitize_text_field((int)$_POST['data']['ID']) ));
268 echo reSmushit::revert(sanitize_text_field((int)$_POST['data']['ID']));
269 die();
270 }
271 add_action( 'wp_ajax_resmushit_bulk_process_image', 'resmushit_bulk_process_image' );
272
273
274
275
276
277 /**
278 *
279 * add Ajax action to update statistics
280 *
281 * @param none
282 * @return json object
283 */
284 function resmushit_update_statistics() {
285 if(!is_super_admin() && !current_user_can('administrator')) {
286 return(json_encode(array('error' => 'User must be at least administrator to retrieve these data')));
287 die();
288 }
289 $output = reSmushit::getStatistics();
290 $output['total_saved_size_formatted'] = reSmushitUI::sizeFormat($output['total_saved_size']);
291 echo json_encode($output);
292 die();
293 }
294 add_action( 'wp_ajax_resmushit_update_statistics', 'resmushit_update_statistics' );
295
296
297
298
299
300 /**
301 * add 'Settings' link to options page from Plugins
302 * @param array $links
303 * @return string
304 */
305 function resmushit_add_plugin_page_settings_link($links) {
306 if(is_string($links)) {
307 $oneLink = $links;
308 $links = array();
309 $links[] = $oneLink;
310 }
311 $links[] = '<a href="' . admin_url( 'upload.php?page=resmushit_options' ) . '">' . __('Settings', "resmushit-image-optimizer") . '</a>';
312 return $links;
313 }
314 add_filter('plugin_action_links_'.plugin_basename(__FILE__), 'resmushit_add_plugin_page_settings_link');
315
316
317
318 /**
319 * Trigger when the cron are activated for the first time
320 * @param mixed old value for cron_activation option
321 * @param mixed new value for cron_activation option
322 */
323
324 function resmushit_on_cron_activation($old_value, $value) {
325 if($value == 1 && (!get_option('resmushit_cron_firstactivation') || get_option('resmushit_cron_firstactivation') === 0)) {
326 update_option( 'resmushit_cron_firstactivation', time() );
327 }
328 }
329 add_action('update_option_resmushit_cron', 'resmushit_on_cron_activation', 100, 2);
330
331
332
333 /**
334 * Declare a new time interval to run Cron
335 * @param array $schedules
336 * @return array
337 */
338 function resmushit_add_cron_interval( $schedules ) {
339 $schedules['resmushit_interval'] = array(
340 'interval' => RESMUSHIT_CRON_FREQUENCY,
341 'display' => esc_html__( __('Every', 'resmushit-image-optimizer') . ' ' . time_elapsed_string(RESMUSHIT_CRON_FREQUENCY) ),
342 );
343 return $schedules;
344 }
345 add_filter( 'cron_schedules', 'resmushit_add_cron_interval' );
346
347 if(!get_option('resmushit_cron') || get_option('resmushit_cron') === 0) {
348 if (wp_next_scheduled ( 'resmushit_optimize' )) {
349 wp_clear_scheduled_hook('resmushit_optimize');
350 }
351 } else {
352 if (! wp_next_scheduled ( 'resmushit_optimize' )) {
353 wp_schedule_event(time(), 'resmushit_interval', 'resmushit_optimize');
354 }
355 }
356
357
358
359 /**
360 * Declare a new crontask for optimization bulk
361 */
362 function resmushit_cron_process() {
363 global $is_cron;
364 $is_cron = TRUE;
365
366 if((time() - get_option('resmushit_cron_lastaction')) < RESMUSHIT_CRON_TIMEOUT) {
367 rlog('Another CRON process is running, process aborted.', 'WARNING');
368 return FALSE;
369 }
370 update_option( 'resmushit_cron_lastrun', time() );
371 update_option( 'resmushit_cron_lastaction', time() );
372
373 // required if launch through wp-cron.php
374 include_once( ABSPATH . 'wp-admin/includes/image.php' );
375
376 add_filter('wp_generate_attachment_metadata', 'resmushit_process_images');
377 rlog('Gathering unoptimized pictures from CRON');
378 $unoptimized_pictures = json_decode(reSmushit::getNonOptimizedPictures(TRUE));
379 rlog('Found ' . count($unoptimized_pictures->nonoptimized) . ' attachments');
380
381 foreach($unoptimized_pictures->nonoptimized as $el) {
382 if (wp_next_scheduled ( 'resmushit_optimize' )) {
383 //avoid to collapse two crons
384 wp_unschedule_event(wp_next_scheduled('resmushit_optimize'), 'resmushit_optimize');
385 }
386 rlog('CRON Processing attachments #' . $el->ID);
387 update_option( 'resmushit_cron_lastaction', time() );
388 reSmushit::revert((int)$el->ID);
389 }
390 }
391 add_action('resmushit_optimize', 'resmushit_cron_process');
392
393
394
395 /**
396 * Return the RESMUSHIT CRON status according to last_execution variables
397 * @return string
398 */
399 function resmushit_get_cron_status() {
400 if(get_option('resmushit_cron') == 0) {
401 return 'DISABLED';
402 }
403 if(!defined('DISABLE_WP_CRON') OR DISABLE_WP_CRON == false) {
404 return 'MISCONFIGURED';
405 }
406
407 if(get_option('resmushit_cron_lastrun') == 0 && (time() - get_option('resmushit_cron_firstactivation') > 2*RESMUSHIT_CRON_FREQUENCY)) {
408 return 'NEVER_RUN';
409 }
410 if(get_option('resmushit_cron_lastrun') != 0 && (time() - get_option('resmushit_cron_lastrun') > 2*RESMUSHIT_CRON_FREQUENCY)) {
411 return 'NO_LATELY_RUN';
412 }
413 return 'OK';
414 }
415
416
417 /**
418 * Trigger when the cron are activated for the first time
419 * @param mixed old value for cron_activation option
420 * @param mixed new value for cron_activation option
421 */
422
423 function resmushit_on_remove_unsmushed_change($old_value, $value) {
424 $old_value = (boolean)$old_value;
425 $value = (boolean)$value;
426 if($old_value == $value) {
427 return TRUE;
428 } else {
429 //if remove backup is activated
430 if($value === TRUE) {
431 if(!resmushit::hasAlreadyRunOnce()) {
432 update_option( 'resmushit_has_no_backup_files', 1);
433 } else {
434 update_option( 'resmushit_has_no_backup_files', 0);
435 }
436 } else {
437 update_option( 'resmushit_has_no_backup_files', 0);
438 }
439 }
440 }
441 add_action('update_option_resmushit_remove_unsmushed', 'resmushit_on_remove_unsmushed_change', 100, 2);
442
443
444
445
446 /**
447 *
448 * add Ajax action to remove backups (-unsmushed) of the filesystem
449 *
450 * @param none
451 * @return json object
452 */
453 function resmushit_remove_backup_files() {
454 $return = array('success' => 0);
455 if(!is_super_admin() && !current_user_can('administrator')) {
456 return(json_encode(array('error' => 'User must be at least administrator to retrieve these data')));
457 die();
458 }
459
460 $files=detect_unsmushed_files();
461
462 foreach($files as $f) {
463 if(unlink($f)) {
464 $return['success']++;
465 }
466 }
467 echo json_encode($return);
468 update_option( 'resmushit_has_no_backup_files', 1);
469
470 die();
471 }
472 add_action( 'wp_ajax_resmushit_remove_backup_files', 'resmushit_remove_backup_files' );
473
474
475 /**
476 *
477 * retrieve Attachment ID from Path
478 * from : https://pippinsplugins.com/retrieve-attachment-id-from-image-url/
479 *
480 * @param imageURL
481 * @return json object
482 */
483 function resmushit_get_image_id($image_url) {
484 global $wpdb;
485 $attachment = $wpdb->get_col($wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE guid='%s';", $image_url ));
486 return $attachment[0];
487 }
488
489 /**
490 *
491 * add Ajax action to restore backups (-unsmushed) from the filesystem
492 *
493 * @param none
494 * @return json object
495 */
496 function resmushit_restore_backup_files() {
497 if(!is_super_admin() && !current_user_can('administrator')) {
498 return(json_encode(array('error' => 'User must be at least administrator to retrieve these data')));
499 die();
500 }
501 $files=detect_unsmushed_files();
502 $return = array('success' => 0);
503 $wp_upload_dir=wp_upload_dir();
504
505 foreach($files as $f) {
506 $dest = str_replace('-unsmushed', '', $f);
507 $pictureURL = str_replace($wp_upload_dir['basedir'], $wp_upload_dir['baseurl'], $dest);
508 $attachementID = resmushit_get_image_id($pictureURL);
509
510 if(reSmushit::revert($attachementID, true)) {
511 if(unlink($f)) {
512 $return['success']++;
513 }
514 }
515 }
516 echo json_encode($return);
517 die();
518 }
519 add_action( 'wp_ajax_resmushit_restore_backup_files', 'resmushit_restore_backup_files' );
520
521
522
523 /**
524 *
525 * Declares WPCLI extension if in WP_CLI context
526 *
527 */
528 if( defined( 'WP_CLI' ) && WP_CLI ) {
529 WP_CLI::add_command( 'resmushit', 'reSmushitWPCLI' );
530 }
531