ShortPixel Image Optimizer - Version 2.1.1

Version Description

  • fixed condition in function that validates content by extension
  • fixed bug that prevented files uploaded directly in /uploads dir to be properly processed/saved
  • retry link added besides files that failed to be optimized due to different reasons
Download this release

Release Info

Developer ShortPixel
Plugin Icon 128x128 ShortPixel Image Optimizer
Version 2.1.1
Comparing to
See all releases

Code changes from version 2.1.0 to 2.1.1

Files changed (3) hide show
  1. readme.txt +7 -1
  2. shortpixel_api.php +42 -42
  3. wp-shortpixel.php +108 -74
readme.txt CHANGED
@@ -4,7 +4,7 @@ Contributors: AlexSP
4
  Tags: picture, optimization, image editor, pngout, upload speed, shortpixel, compression, jpegmini, webp, lossless, cwebp, media, tinypng, jpegtran,image, image optimisation, shrink, picture, photo, optimize photos, compress, performance, tinypng, crunch, pngquant, attachment, optimize, pictures,fast, images, image files, image quality, lossy, upload, kraken, resize, seo, smushit, optipng, kraken image optimizer, ewww, photo optimization, gifsicle, image optimizer, images, krakenio, png, gmagick, image optimize, pdf, pdf optimisation, optimise pdf, shrink pdf, jpg, jpeg, jpg optimisation, optimise jpg, shrink jpg, gif, animated gif, optimise gif
5
  Requires at least: 3.0.0 or higher
6
  Tested up to: 4.1.1
7
- Stable tag: 2.1.0
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -107,6 +107,12 @@ The ShortPixel team is here to help. <a href="https://shortpixel.com/contact">Co
107
 
108
  == Changelog ==
109
 
 
 
 
 
 
 
110
  = 2.1.0 =
111
 
112
  * speedier file download from API resource
4
  Tags: picture, optimization, image editor, pngout, upload speed, shortpixel, compression, jpegmini, webp, lossless, cwebp, media, tinypng, jpegtran,image, image optimisation, shrink, picture, photo, optimize photos, compress, performance, tinypng, crunch, pngquant, attachment, optimize, pictures,fast, images, image files, image quality, lossy, upload, kraken, resize, seo, smushit, optipng, kraken image optimizer, ewww, photo optimization, gifsicle, image optimizer, images, krakenio, png, gmagick, image optimize, pdf, pdf optimisation, optimise pdf, shrink pdf, jpg, jpeg, jpg optimisation, optimise jpg, shrink jpg, gif, animated gif, optimise gif
5
  Requires at least: 3.0.0 or higher
6
  Tested up to: 4.1.1
7
+ Stable tag: 2.1.1
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
107
 
108
  == Changelog ==
109
 
110
+ = 2.1.1 =
111
+
112
+ * fixed condition in function that validates content by extension
113
+ * fixed bug that prevented files uploaded directly in /uploads dir to be properly processed/saved
114
+ * retry link added besides files that failed to be optimized due to different reasons
115
+
116
  = 2.1.0 =
117
 
118
  * speedier file download from API resource
shortpixel_api.php CHANGED
@@ -104,7 +104,7 @@ class shortpixel_api {
104
  exit('Timed out while processing. (pass '.$apiRetries.')');
105
  }
106
  }
107
-
108
  $response = $this->doRequests($url, $filePaths, $ID);//send requests to API
109
  if(!$response) return $response;
110
 
@@ -221,35 +221,35 @@ class shortpixel_api {
221
 
222
 
223
  //if backup is enabled
224
- if(get_option('wp-short-backup_images'))
225
  {
226
  $imageIndex = 0;
227
  $uploadDir = wp_upload_dir();
228
-
 
229
  if(!file_exists(SP_BACKUP_FOLDER) && !mkdir(SP_BACKUP_FOLDER, 0777, true)) {
230
  return sprintf("Backup folder does not exist and it could not be created");
231
  }
 
232
  $meta = wp_get_attachment_metadata($ID);
233
- $SubDir = ( isset($meta['file']) ) ? trim(substr($meta['file'],0,strrpos($meta['file'],"/")+1)) : "";
234
- $source = $filePath;
 
 
 
 
 
 
 
 
235
 
236
- if ( empty($SubDir) ) //its a PDF?
237
- {
238
- $uploadFilePath = get_attached_file($ID);
239
- $tmp = str_replace($uploadDir['basedir'],"", $uploadFilePath);
240
- $SubDir = trim(substr($tmp,0,strrpos($tmp,"/")));
241
-
242
- //create destination dir if it isn't already created
243
- @mkdir( SP_BACKUP_FOLDER . $SubDir, 0777, true);
244
- $destination[$imageIndex] = SP_BACKUP_FOLDER . $SubDir . DIRECTORY_SEPARATOR . basename($uploadFilePath);
245
-
246
- }
247
- else //it is not PDF, its an image
248
  {
249
- @mkdir( SP_BACKUP_FOLDER . DIRECTORY_SEPARATOR. $SubDir, 0777, true);
250
- $destination[$imageIndex] = SP_BACKUP_FOLDER . DIRECTORY_SEPARATOR . $SubDir . basename($source[$imageIndex]);//for main file
251
-
252
- foreach ( $meta['sizes'] as $pictureDetails )
253
  {
254
  $imageIndex++;
255
  $source[$imageIndex] = $uploadDir['basedir'] . DIRECTORY_SEPARATOR . $SubDir . $pictureDetails['file'];
@@ -257,8 +257,9 @@ class shortpixel_api {
257
  }
258
  }
259
 
 
260
  if(is_writable(SP_BACKUP_FOLDER)) {
261
- if(!file_exists($destination[0]))
262
  {
263
  foreach ( $source as $imageIndex => $fileSource )
264
  {
@@ -272,30 +273,13 @@ class shortpixel_api {
272
 
273
  }//end backup section
274
 
 
275
  $counter = 0;
276
- $meta = wp_get_attachment_metadata($ID);//we'll need the metadata for subdir
277
- if ( !isset($meta['file']) )//it is likely a PDF file so we treat this differently
278
- {
279
- global $wpdb;
280
- $qry = "SELECT * FROM " . $wpdb->prefix . "postmeta
281
- WHERE (
282
- post_id = $ID AND
283
- meta_key = '_wp_attached_file'
284
- )";
285
- $idList = $wpdb->get_results($qry);
286
- $metaPDF = $idList[0];
287
- $SubDir = trim(substr($metaPDF->meta_value,0,strrpos($metaPDF->meta_value,"/")+1));
288
- }
289
- else //its an image
290
- $SubDir = trim(substr($meta['file'],0,strrpos($meta['file'],"/")+1));
291
-
292
-
293
  foreach ( $tempFiles as $tempFile )//overwrite the original files with the optimized ones
294
  {
295
-
296
  $sourceFile = $tempFile;
297
- $destinationFile = WP_CONTENT_DIR . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR . $SubDir . basename($url[$counter]);
298
-
299
  if ( $sourceFile <> "" && file_exists($sourceFile) )//possibly there was an error and the file couldn't have been processed
300
  {
301
  @unlink( $destinationFile );
@@ -345,6 +329,22 @@ class shortpixel_api {
345
  update_option("wp-short-pixel-query-id-start", $ID - 1);//update max ID
346
 
347
  }//end handleSuccess
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
348
 
349
  public function parseJSON($data) {
350
  if ( function_exists('json_decode') ) {
104
  exit('Timed out while processing. (pass '.$apiRetries.')');
105
  }
106
  }
107
+
108
  $response = $this->doRequests($url, $filePaths, $ID);//send requests to API
109
  if(!$response) return $response;
110
 
221
 
222
 
223
  //if backup is enabled
224
+ if( get_option('wp-short-backup_images') )
225
  {
226
  $imageIndex = 0;
227
  $uploadDir = wp_upload_dir();
228
+ $source = $filePath;
229
+
230
  if(!file_exists(SP_BACKUP_FOLDER) && !mkdir(SP_BACKUP_FOLDER, 0777, true)) {
231
  return sprintf("Backup folder does not exist and it could not be created");
232
  }
233
+
234
  $meta = wp_get_attachment_metadata($ID);
235
+ if ( empty($meta['file']) )//file has no metadata attached (like PDF files uploaded before SP plugin)
236
+ {
237
+ $attachedFilePath = get_attached_file($ID);
238
+ $SubDir = $this->returnSubDir($attachedFilePath);
239
+ }
240
+ else
241
+ {
242
+ $SubDir = $this->returnSubDir($meta['file']);
243
+ $source = $filePath;
244
+ }
245
 
246
+
247
+ //create backup dir if needed
248
+ @mkdir( SP_BACKUP_FOLDER . DIRECTORY_SEPARATOR . $SubDir, 0777, true);
249
+ $destination[$imageIndex] = SP_BACKUP_FOLDER . DIRECTORY_SEPARATOR . $SubDir . basename($source[$imageIndex]);//for main file
250
+ if ( !empty($meta['file']) )
 
 
 
 
 
 
 
251
  {
252
+ foreach ( $meta['sizes'] as $pictureDetails )//generate paths for all the version of an image
 
 
 
253
  {
254
  $imageIndex++;
255
  $source[$imageIndex] = $uploadDir['basedir'] . DIRECTORY_SEPARATOR . $SubDir . $pictureDetails['file'];
257
  }
258
  }
259
 
260
+
261
  if(is_writable(SP_BACKUP_FOLDER)) {
262
+ if(!file_exists($destination[0])) //do not overwrite backup files
263
  {
264
  foreach ( $source as $imageIndex => $fileSource )
265
  {
273
 
274
  }//end backup section
275
 
276
+
277
  $counter = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
278
  foreach ( $tempFiles as $tempFile )//overwrite the original files with the optimized ones
279
  {
 
280
  $sourceFile = $tempFile;
281
+ $destinationFile = WP_CONTENT_DIR . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR . $SubDir . basename($url[$counter]);
282
+
283
  if ( $sourceFile <> "" && file_exists($sourceFile) )//possibly there was an error and the file couldn't have been processed
284
  {
285
  @unlink( $destinationFile );
329
  update_option("wp-short-pixel-query-id-start", $ID - 1);//update max ID
330
 
331
  }//end handleSuccess
332
+
333
+ static public function returnSubDir($file)//return subdir for that particular attached file
334
+ {
335
+
336
+ $uploadDir = wp_upload_dir();
337
+
338
+ if ( !isset($file) || strpos($file, "/") === false )
339
+ $SubDir = "";
340
+ else
341
+ $SubDir = trim(substr($file,0,strrpos($file,"/")+1));
342
+
343
+ //remove upload dir from the URL if needed
344
+ $SubDir = str_ireplace($uploadDir['basedir'] . DIRECTORY_SEPARATOR ,"", $SubDir);
345
+
346
+ return $SubDir;
347
+ }
348
 
349
  public function parseJSON($data) {
350
  if ( function_exists('json_decode') ) {
wp-shortpixel.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: ShortPixel Image Optimiser
4
  * Plugin URI: https://shortpixel.com/
5
  * Description: ShortPixel is an image compression tool that helps improve your website performance. The plugin optimises images automatically using both lossy and lossless compression. Resulting, smaller, images are no different in quality from the original. To install: 1) Click the "Activate" link to the left of this description. 2) <a href="https://shortpixel.com/wp-apikey" target="_blank">Free Sign up</a> for your unique API Key . 3) Check your email for your API key. 4) Use your API key to activate ShortPixel plugin in the 'Plugins' menu in WordPress. 5) Done!
6
- * Version: 2.1.0
7
  * Author: ShortPixel
8
  * Author URI: https://shortpixel.com
9
  */
@@ -12,7 +12,7 @@ require_once('shortpixel_api.php');
12
  require_once( ABSPATH . 'wp-admin/includes/image.php' );
13
  require_once( ABSPATH . 'wp-includes/pluggable.php' );
14
 
15
- define('PLUGIN_VERSION', "2.1.0");
16
  define('SP_DEBUG', false);
17
  define('SP_LOG', false);
18
  define('SP_MAX_TIMEOUT', 10);
@@ -115,11 +115,11 @@ class WPShortPixel {
115
  add_option( 'wp-short-pixel-api-retries', 0, '', 'yes' );
116
  }
117
 
118
- if(get_option('wp-short-pixel-query-id-start') === false) {//current query ID used for postmeta
119
  add_option( 'wp-short-pixel-query-id-start', 0, '', 'yes' );
120
  }
121
 
122
- if(get_option('wp-short-pixel-query-id-stop') === false) {//current query ID used for postmeta
123
  add_option( 'wp-short-pixel-query-id-stop', 0, '', 'yes' );
124
  }
125
 
@@ -211,7 +211,7 @@ class WPShortPixel {
211
  self::log("Processing image id {$ID}");
212
  $url = wp_get_attachment_url($ID);
213
  $path = get_attached_file($ID);
214
- if(self::isProcesable($path) != false)
215
  {
216
  if ( empty($meta) && $bulkProcessingStatus <> 'running' )//here's a PDF file most likely, while bulk not running
217
  {
@@ -270,6 +270,12 @@ class WPShortPixel {
270
 
271
  $startQueryID = get_option('wp-short-pixel-query-id-start');
272
  $endQueryID = get_option('wp-short-pixel-query-id-stop');
 
 
 
 
 
 
273
  sleep(1);
274
  $queryPostMeta = "SELECT * FROM " . $wpdb->prefix . "postmeta
275
  WHERE ( post_id <= $startQueryID AND post_id > $endQueryID ) AND (
@@ -279,10 +285,26 @@ class WPShortPixel {
279
  ORDER BY post_id DESC
280
  LIMIT " . SP_MAX_RESULTS_QUERY;
281
  $resultsPostMeta = $wpdb->get_results($queryPostMeta);
 
 
 
 
 
 
 
 
 
282
  $idList = array();
 
283
  foreach ( $resultsPostMeta as $itemMetaData )
284
  {
285
- $meta = wp_get_attachment_metadata($itemMetaData->post_id);
 
 
 
 
 
 
286
  $meta['ShortPixelImprovement'] = ( isset($meta['ShortPixelImprovement']) ) ? $meta['ShortPixelImprovement'] : "";
287
  $filePath = get_attached_file($itemMetaData->post_id);
288
  $fileExtension = strtolower(substr($filePath,strrpos($filePath,".")+1));
@@ -291,43 +313,51 @@ class WPShortPixel {
291
  {
292
  $idList[] = $itemMetaData;
293
  }
 
 
294
  }
295
 
296
  if ( isset($idList[0]) )
297
  {
 
298
  $meta = wp_get_attachment_metadata($idList[0]->post_id);
299
  $filePath = get_attached_file($idList[0]->post_id);
300
  $fileExtension = strtolower(substr($filePath,strrpos($filePath,".")+1));
301
 
302
- if( !empty($meta) && !isset($meta['ShortPixel']['WaitingProcessing']) ) //possibly the file wasn't processed in the first pass so we'll wait for it to be completed
 
 
 
 
 
 
303
  {
304
  $startQueryID = ( $idList[0]->post_id );
305
  update_option("wp-short-pixel-query-id-start", $startQueryID);//update max ID
306
  }
307
  elseif ( empty($meta) && $fileExtension <> "pdf" )//file is not an image or PDF so we just skip to the next batch
308
  {
309
- $startQueryID = $startQueryID - SP_MAX_RESULTS_QUERY;
310
  update_option("wp-short-pixel-query-id-start", $startQueryID);//update max ID
311
  die();
312
  }
313
- elseif ( !self::isProcesable($filePath) )//file has a non-supported extension, we skip it
314
- {
315
- $startQueryID = $idList[0]->post_id - 1;
316
- update_option("wp-short-pixel-query-id-start", $startQueryID);//update max ID
317
- die();
318
- }
319
  else //file was processed in the first pass
320
  {
321
  $startQueryID = $idList[0]->post_id;
322
  update_option("wp-short-pixel-query-id-start", $startQueryID);//update max ID
323
  }
324
  }
325
- elseif ( $startQueryID > $endQueryID )
326
  {
327
- $startQueryID = $startQueryID - 1;
 
 
 
328
  update_option("wp-short-pixel-query-id-start", $startQueryID);//update max ID
329
  die();
330
  }
 
 
331
 
332
  //////////////////////
333
 
@@ -347,6 +377,7 @@ class WPShortPixel {
347
  $this->_apiInterface->doRequests($itemDetails['imageURLs'], $itemDetails['imagePaths']);
348
  }
349
 
 
350
  if ( isset($idList[2]) )
351
  {
352
  $itemDetails = $this->returnURLsAndPaths($idList[1]);
@@ -360,7 +391,7 @@ class WPShortPixel {
360
  $ID = $itemDetails['ID'];
361
  $result = $this->_apiInterface->processImage($itemDetails['imageURLs'], $itemDetails['imagePaths'], $ID);//use the API connection to send processing requests for these files.
362
 
363
- if(is_string($result)) {
364
  if(isset($meta['ShortPixel']['BulkProcessing'])) { unset($meta['ShortPixel']['BulkProcessing']); }
365
  if(isset($meta['ShortPixel']['WaitingProcessing'])) { unset($meta['ShortPixel']['WaitingProcessing']); }
366
  $meta['ShortPixelImprovement'] = $result;
@@ -517,35 +548,30 @@ class WPShortPixel {
517
  public function handleRestoreBackup() {
518
  $attachmentID = intval($_GET['attachment_ID']);
519
 
520
- $uploadFilePath = get_attached_file($attachmentID);
521
  $meta = wp_get_attachment_metadata($attachmentID);
522
  $uploadDir = wp_upload_dir();
523
- $pathInfo = pathinfo($uploadFilePath);
524
- $file = get_attached_file($attachmentID);
525
  $fileExtension = strtolower(substr($file,strrpos($file,".")+1));
526
- if ( $fileExtension <> "pdf" )
527
- $SubDirs = substr($meta['file'],0,strrpos($meta['file'],"/")+1);
528
- else
529
- $SubDirs = substr(str_replace($uploadDir['basedir'],"", $pathInfo['dirname']),1) . "/";//generate subdirs for PDF files
530
-
531
  //sometimes the month of original file and backup can differ
532
- if ( !file_exists(SP_BACKUP_FOLDER . DIRECTORY_SEPARATOR . $SubDirs . basename($uploadFilePath)) )
533
- $SubDirs = date("Y") . "/" . date("m") . "/";
534
-
535
 
536
  try {
537
  //main file
538
- @rename(SP_BACKUP_FOLDER . DIRECTORY_SEPARATOR . $SubDirs . basename($uploadFilePath), $uploadFilePath);
539
 
540
  //overwriting thumbnails
541
- if($fileExtension <> "pdf") {
542
  foreach($meta["sizes"] as $size => $imageData) {
543
- $source = SP_BACKUP_FOLDER . DIRECTORY_SEPARATOR . $SubDirs . $imageData['file'];
544
  $destination = $pathInfo['dirname'] . DIRECTORY_SEPARATOR . $imageData['file'];
545
  @rename($source, $destination);
546
  }
547
  }
548
-
549
  unset($meta["ShortPixelImprovement"]);
550
  wp_update_attachment_metadata($attachmentID, $meta);
551
 
@@ -563,36 +589,26 @@ class WPShortPixel {
563
 
564
 
565
  public function handleDeleteAttachmentInBackup($ID) {
566
- $uploadFilePath = get_attached_file($ID);
567
  $meta = wp_get_attachment_metadata($ID);
568
- if(self::isProcesable($uploadFilePath) != false) {
569
  try {
570
  $uploadDir = wp_upload_dir();
571
- if ( isset($meta['file']) )
572
- $SubDir = substr($meta['file'],0,strrpos($meta['file'],"/")+1);
573
- else
574
- $SubDir = "";
575
 
576
- if ( empty($SubDir) ) //its a PDF?
 
 
577
  {
578
- $uploadFilePath = get_attached_file($ID);
579
- $tmp = str_replace($uploadDir['basedir'],"", $uploadFilePath);
580
- $SubDir = trim(substr($tmp,0,strrpos($tmp,"/")));
581
- @unlink(SP_BACKUP_FOLDER . $SubDir . DIRECTORY_SEPARATOR . basename($uploadFilePath));
582
- }
583
- else
584
- {//remove images
585
  $filesPath = SP_BACKUP_FOLDER . DIRECTORY_SEPARATOR . $SubDir;//base BACKUP path
586
- //remove main imgage/file
587
- @unlink($filesPath . basename($meta['file']));
588
-
589
  //remove thumbs thumbnails
590
  if(isset($meta["sizes"])) {
591
  foreach($meta["sizes"] as $size => $imageData) {
592
  @unlink($filesPath . basename($imageData['file']));//remove thumbs
593
  }
594
  }
595
- }
 
596
  } catch(Exception $e) {
597
  //what to do, what to do?
598
  }
@@ -609,7 +625,6 @@ class WPShortPixel {
609
 
610
  public function bulkProcess() {
611
  global $wpdb;
612
-
613
  echo '<h1>Bulk Image Optimisation by ShortPixel</h1>';
614
 
615
  if(MUST_HAVE_KEY && $this->_verifiedKey == false) {//invalid API Key
@@ -620,9 +635,7 @@ class WPShortPixel {
620
 
621
  if(isset($_GET['cancel']))
622
  {//cancel an ongoing bulk processing, it might be needed sometimes
623
- update_option("wp-short-pixel-query-id-start", 0);
624
- update_option("wp-short-pixel-query-id-stop", 0);
625
- delete_option('bulkProcessingStatus');
626
  }
627
 
628
  if(isset($_POST["bulkProcess"]))
@@ -630,11 +643,11 @@ class WPShortPixel {
630
  $queryMax = "SELECT max(post_id) as startQueryID FROM " . $wpdb->prefix . "postmeta";
631
  $resultQuery = $wpdb->get_results($queryMax);
632
  $startQueryID = $resultQuery[0]->startQueryID;
633
- update_option("wp-short-pixel-query-id-start", $startQueryID);//start downwards from the biggest item ID
634
  update_option("wp-short-pixel-query-id-stop", 0);
635
  update_option("wp-short-pixel-flag-id", $startQueryID);//we use to detect new added files while bulk is running
636
  add_option('bulkProcessingStatus', 'running');//set bulk flag
637
- }//end bulk process was clicked
638
 
639
  $bulkProcessingStatus = get_option('bulkProcessingStatus');
640
  $startQueryID = get_option('wp-short-pixel-query-id-start');
@@ -729,6 +742,14 @@ class WPShortPixel {
729
  ';
730
  }
731
  //end bulk processing
 
 
 
 
 
 
 
 
732
 
733
  public function renderSettingsMenu() {
734
  if ( !current_user_can( 'manage_options' ) ) {
@@ -748,6 +769,7 @@ class WPShortPixel {
748
 
749
  //handle API Key - common for submit and validate
750
  $_POST['key'] = trim($_POST['key']);
 
751
  $validityData = $this->getQuotaInformation($_POST['key'], true);
752
 
753
  $this->_apiKey = $_POST['key'];
@@ -763,12 +785,13 @@ class WPShortPixel {
763
  } else {
764
  if(isset($_POST['validate'])) {
765
  //display notification
766
- printf($noticeHTML, '#dd3d36', $validityData["Message"]);
767
  }
768
  update_option('wp-short-pixel-verifiedKey', false);
769
  $this->_verifiedKey = false;
770
  }
771
 
 
772
  //if save button - we process the rest of the form elements
773
  if(isset($_POST['submit'])) {
774
  update_option('wp-short-pixel-compression', $_POST['compressionType']);
@@ -798,7 +821,7 @@ class WPShortPixel {
798
  //parse all images and set the right flag that the image has no backup
799
  foreach($attachments as $attachment)
800
  {
801
- if(self::isProcesable(get_attached_file($attachment->ID)) == false) continue;
802
 
803
  $meta = wp_get_attachment_metadata($attachment->ID);
804
  $meta['ShortPixel']['NoBackup'] = true;
@@ -987,7 +1010,7 @@ HTML;
987
  );
988
 
989
  if($appendUserAgent) {
990
- $args['body']['useragent'] = urlencode($_SERVER['HTTP_USER_AGENT']);
991
  }
992
 
993
  $response = wp_remote_post($requestURL, $args);
@@ -1050,24 +1073,43 @@ HTML;
1050
  {
1051
  if(isset($meta['ShortPixel']['BulkProcessing'])) {
1052
  print 'Waiting for bulk processing';
 
1053
  return;
1054
  }
1055
 
1056
- print $data['ShortPixelImprovement'];
1057
  if( is_numeric($data['ShortPixelImprovement']) && !isset($data['ShortPixel']['NoBackup']) ) {
1058
- print '%';
1059
  print " | <a href=\"admin.php?action=shortpixel_restore_backup&amp;attachment_ID={$id}\">Restore backup</a>";
1060
  return;
1061
  }
1062
- elseif ( $data['ShortPixelImprovement'] <> "Optimisation N/A" || is_numeric($data['ShortPixelImprovement']) )
 
 
1063
  print '%';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1064
  } elseif(isset($data['ShortPixel']['WaitingProcessing'])) {
1065
  print 'Image waiting to be processed';
 
1066
  return;
1067
  } elseif(isset($data['ShortPixel']['NoFileOnDisk'])) {
1068
  print 'Image does not exist';
1069
  return;
1070
  } else {
 
1071
  if ( wp_attachment_is_image( $id ) ) {
1072
  print 'Image not processed';
1073
  print " | <a href=\"admin.php?action=shortpixel_manual_optimize&amp;attachment_ID={$id}\">Optimize now</a>";
@@ -1078,6 +1120,7 @@ HTML;
1078
  print " | <a href=\"admin.php?action=shortpixel_manual_optimize&amp;attachment_ID={$id}\">Optimize now</a>";
1079
  return;
1080
  }
 
1081
  }
1082
  }
1083
  }
@@ -1116,23 +1159,14 @@ HTML;
1116
 
1117
  return round($bytes, $precision) . ' ' . $units[$pow];
1118
  }
1119
-
1120
- static public function isProcesable($path) {
1121
  $pathParts = pathinfo($path);
1122
- if($pathParts['extension'] == 'pdf') {
1123
- return true;
1124
- }
1125
-
1126
- if(function_exists('exif_imagetype')) {
1127
- return exif_imagetype($path);
1128
- } else {
1129
- if(in_array($pathParts['extension'], array('jpg', 'jpeg', 'gif', 'png'))) {
1130
  return true;
1131
  } else {
1132
  return false;
1133
  }
1134
- }
1135
-
1136
  }
1137
 
1138
  public static function deleteDir($dirPath) {
3
  * Plugin Name: ShortPixel Image Optimiser
4
  * Plugin URI: https://shortpixel.com/
5
  * Description: ShortPixel is an image compression tool that helps improve your website performance. The plugin optimises images automatically using both lossy and lossless compression. Resulting, smaller, images are no different in quality from the original. To install: 1) Click the "Activate" link to the left of this description. 2) <a href="https://shortpixel.com/wp-apikey" target="_blank">Free Sign up</a> for your unique API Key . 3) Check your email for your API key. 4) Use your API key to activate ShortPixel plugin in the 'Plugins' menu in WordPress. 5) Done!
6
+ * Version: 2.1.1
7
  * Author: ShortPixel
8
  * Author URI: https://shortpixel.com
9
  */
12
  require_once( ABSPATH . 'wp-admin/includes/image.php' );
13
  require_once( ABSPATH . 'wp-includes/pluggable.php' );
14
 
15
+ define('PLUGIN_VERSION', "2.1.1");
16
  define('SP_DEBUG', false);
17
  define('SP_LOG', false);
18
  define('SP_MAX_TIMEOUT', 10);
115
  add_option( 'wp-short-pixel-api-retries', 0, '', 'yes' );
116
  }
117
 
118
+ if(get_option('wp-short-pixel-query-id-start') === false) {//current query ID used for postmeta queries
119
  add_option( 'wp-short-pixel-query-id-start', 0, '', 'yes' );
120
  }
121
 
122
+ if(get_option('wp-short-pixel-query-id-stop') === false) {//min ID used for postmeta queries
123
  add_option( 'wp-short-pixel-query-id-stop', 0, '', 'yes' );
124
  }
125
 
211
  self::log("Processing image id {$ID}");
212
  $url = wp_get_attachment_url($ID);
213
  $path = get_attached_file($ID);
214
+ if(self::isProcessable($path) != false)
215
  {
216
  if ( empty($meta) && $bulkProcessingStatus <> 'running' )//here's a PDF file most likely, while bulk not running
217
  {
270
 
271
  $startQueryID = get_option('wp-short-pixel-query-id-start');
272
  $endQueryID = get_option('wp-short-pixel-query-id-stop');
273
+
274
+ if ( $startQueryID <= $endQueryID )
275
+ {
276
+ echo 'Empty queue ' . $startQueryID . '->' . $endQueryID;
277
+ die;
278
+ }
279
  sleep(1);
280
  $queryPostMeta = "SELECT * FROM " . $wpdb->prefix . "postmeta
281
  WHERE ( post_id <= $startQueryID AND post_id > $endQueryID ) AND (
285
  ORDER BY post_id DESC
286
  LIMIT " . SP_MAX_RESULTS_QUERY;
287
  $resultsPostMeta = $wpdb->get_results($queryPostMeta);
288
+
289
+ if ( empty($resultsPostMeta) )
290
+ {
291
+ $startQueryID = 0;
292
+ update_option("wp-short-pixel-query-id-start", $startQueryID);//update max ID
293
+ echo 'Empty results ' . $startQueryID . '->' . $endQueryID;
294
+ die;
295
+ }
296
+
297
  $idList = array();
298
+ $countMeta = 0;
299
  foreach ( $resultsPostMeta as $itemMetaData )
300
  {
301
+ if ( $countMeta == 0 )
302
+ {
303
+ $metaCurrentFile = wp_get_attachment_metadata($itemMetaData->post_id);
304
+ $meta = $metaCurrentFile;
305
+ }
306
+ else
307
+ $meta = wp_get_attachment_metadata($itemMetaData->post_id);
308
  $meta['ShortPixelImprovement'] = ( isset($meta['ShortPixelImprovement']) ) ? $meta['ShortPixelImprovement'] : "";
309
  $filePath = get_attached_file($itemMetaData->post_id);
310
  $fileExtension = strtolower(substr($filePath,strrpos($filePath,".")+1));
313
  {
314
  $idList[] = $itemMetaData;
315
  }
316
+
317
+ $countMeta++;
318
  }
319
 
320
  if ( isset($idList[0]) )
321
  {
322
+ $meta = $metaCurrentFile; //assign the saved meta of the file position [0]
323
  $meta = wp_get_attachment_metadata($idList[0]->post_id);
324
  $filePath = get_attached_file($idList[0]->post_id);
325
  $fileExtension = strtolower(substr($filePath,strrpos($filePath,".")+1));
326
 
327
+ if ( !self::isProcessable($filePath) )//file has a non-supported extension, we skip it
328
+ {
329
+ $startQueryID = $idList[0]->post_id - 1;
330
+ update_option("wp-short-pixel-query-id-start", $startQueryID);//update max ID
331
+ die();
332
+ }
333
+ elseif( !empty($meta) && !isset($meta['ShortPixel']['WaitingProcessing']) ) //possibly the file wasn't processed in the first pass so we'll wait for it to be completed
334
  {
335
  $startQueryID = ( $idList[0]->post_id );
336
  update_option("wp-short-pixel-query-id-start", $startQueryID);//update max ID
337
  }
338
  elseif ( empty($meta) && $fileExtension <> "pdf" )//file is not an image or PDF so we just skip to the next batch
339
  {
340
+ $startQueryID = $startQueryID - 1; //SP_MAX_RESULTS_QUERY;
341
  update_option("wp-short-pixel-query-id-start", $startQueryID);//update max ID
342
  die();
343
  }
 
 
 
 
 
 
344
  else //file was processed in the first pass
345
  {
346
  $startQueryID = $idList[0]->post_id;
347
  update_option("wp-short-pixel-query-id-start", $startQueryID);//update max ID
348
  }
349
  }
350
+ elseif ( $startQueryID > $endQueryID )
351
  {
352
+ if ( isset($resultsPostMeta[2]) && is_numeric($resultsPostMeta[2]->post_id) )
353
+ $startQueryID = $resultsPostMeta[2]->post_id;
354
+ else
355
+ $startQueryID = $startQueryID - 1;
356
  update_option("wp-short-pixel-query-id-start", $startQueryID);//update max ID
357
  die();
358
  }
359
+
360
+
361
 
362
  //////////////////////
363
 
377
  $this->_apiInterface->doRequests($itemDetails['imageURLs'], $itemDetails['imagePaths']);
378
  }
379
 
380
+ //send a couple of pre-process requests (if available/needed)
381
  if ( isset($idList[2]) )
382
  {
383
  $itemDetails = $this->returnURLsAndPaths($idList[1]);
391
  $ID = $itemDetails['ID'];
392
  $result = $this->_apiInterface->processImage($itemDetails['imageURLs'], $itemDetails['imagePaths'], $ID);//use the API connection to send processing requests for these files.
393
 
394
+ if(is_string($result)) {//there was an error?
395
  if(isset($meta['ShortPixel']['BulkProcessing'])) { unset($meta['ShortPixel']['BulkProcessing']); }
396
  if(isset($meta['ShortPixel']['WaitingProcessing'])) { unset($meta['ShortPixel']['WaitingProcessing']); }
397
  $meta['ShortPixelImprovement'] = $result;
548
  public function handleRestoreBackup() {
549
  $attachmentID = intval($_GET['attachment_ID']);
550
 
551
+ $file = get_attached_file($attachmentID);
552
  $meta = wp_get_attachment_metadata($attachmentID);
553
  $uploadDir = wp_upload_dir();
554
+ $pathInfo = pathinfo($file);
555
+
556
  $fileExtension = strtolower(substr($file,strrpos($file,".")+1));
557
+ $SubDir = $this->_apiInterface->returnSubDir($file);
558
+
 
 
 
559
  //sometimes the month of original file and backup can differ
560
+ if ( !file_exists(SP_BACKUP_FOLDER . DIRECTORY_SEPARATOR . $SubDir . basename($file)) )
561
+ $SubDir = date("Y") . "/" . date("m") . "/";
 
562
 
563
  try {
564
  //main file
565
+ @rename(SP_BACKUP_FOLDER . DIRECTORY_SEPARATOR . $SubDir . basename($file), $file);
566
 
567
  //overwriting thumbnails
568
+ if( !empty($meta['file']) ) {
569
  foreach($meta["sizes"] as $size => $imageData) {
570
+ $source = SP_BACKUP_FOLDER . DIRECTORY_SEPARATOR . $SubDir . $imageData['file'];
571
  $destination = $pathInfo['dirname'] . DIRECTORY_SEPARATOR . $imageData['file'];
572
  @rename($source, $destination);
573
  }
574
  }
 
575
  unset($meta["ShortPixelImprovement"]);
576
  wp_update_attachment_metadata($attachmentID, $meta);
577
 
589
 
590
 
591
  public function handleDeleteAttachmentInBackup($ID) {
592
+ $file = get_attached_file($ID);
593
  $meta = wp_get_attachment_metadata($ID);
594
+ if(self::isProcessable($file) != false) {
595
  try {
596
  $uploadDir = wp_upload_dir();
597
+ $SubDir = $this->_apiInterface->returnSubDir($file);
 
 
 
598
 
599
+ @unlink(SP_BACKUP_FOLDER . DIRECTORY_SEPARATOR . $SubDir . basename($file));
600
+
601
+ if ( !empty($meta['file']) )
602
  {
 
 
 
 
 
 
 
603
  $filesPath = SP_BACKUP_FOLDER . DIRECTORY_SEPARATOR . $SubDir;//base BACKUP path
 
 
 
604
  //remove thumbs thumbnails
605
  if(isset($meta["sizes"])) {
606
  foreach($meta["sizes"] as $size => $imageData) {
607
  @unlink($filesPath . basename($imageData['file']));//remove thumbs
608
  }
609
  }
610
+ }
611
+
612
  } catch(Exception $e) {
613
  //what to do, what to do?
614
  }
625
 
626
  public function bulkProcess() {
627
  global $wpdb;
 
628
  echo '<h1>Bulk Image Optimisation by ShortPixel</h1>';
629
 
630
  if(MUST_HAVE_KEY && $this->_verifiedKey == false) {//invalid API Key
635
 
636
  if(isset($_GET['cancel']))
637
  {//cancel an ongoing bulk processing, it might be needed sometimes
638
+ $this->cancelProcessing();
 
 
639
  }
640
 
641
  if(isset($_POST["bulkProcess"]))
643
  $queryMax = "SELECT max(post_id) as startQueryID FROM " . $wpdb->prefix . "postmeta";
644
  $resultQuery = $wpdb->get_results($queryMax);
645
  $startQueryID = $resultQuery[0]->startQueryID;
646
+ update_option("wp-short-pixel-query-id-start", $startQueryID);//start downwards from the biggest item ID
647
  update_option("wp-short-pixel-query-id-stop", 0);
648
  update_option("wp-short-pixel-flag-id", $startQueryID);//we use to detect new added files while bulk is running
649
  add_option('bulkProcessingStatus', 'running');//set bulk flag
650
+ }//end bulk process was clicked
651
 
652
  $bulkProcessingStatus = get_option('bulkProcessingStatus');
653
  $startQueryID = get_option('wp-short-pixel-query-id-start');
742
  ';
743
  }
744
  //end bulk processing
745
+
746
+
747
+ public function cancelProcessing(){
748
+ //cancel an ongoing bulk processing, it might be needed sometimes
749
+ update_option("wp-short-pixel-query-id-start", 0);
750
+ update_option("wp-short-pixel-query-id-stop", 0);
751
+ delete_option('bulkProcessingStatus');
752
+ }
753
 
754
  public function renderSettingsMenu() {
755
  if ( !current_user_can( 'manage_options' ) ) {
769
 
770
  //handle API Key - common for submit and validate
771
  $_POST['key'] = trim($_POST['key']);
772
+
773
  $validityData = $this->getQuotaInformation($_POST['key'], true);
774
 
775
  $this->_apiKey = $_POST['key'];
785
  } else {
786
  if(isset($_POST['validate'])) {
787
  //display notification
788
+ printf($noticeHTML, '#ff0000', $validityData["Message"]);
789
  }
790
  update_option('wp-short-pixel-verifiedKey', false);
791
  $this->_verifiedKey = false;
792
  }
793
 
794
+
795
  //if save button - we process the rest of the form elements
796
  if(isset($_POST['submit'])) {
797
  update_option('wp-short-pixel-compression', $_POST['compressionType']);
821
  //parse all images and set the right flag that the image has no backup
822
  foreach($attachments as $attachment)
823
  {
824
+ if(self::isProcessable(get_attached_file($attachment->ID)) == false) continue;
825
 
826
  $meta = wp_get_attachment_metadata($attachment->ID);
827
  $meta['ShortPixel']['NoBackup'] = true;
1010
  );
1011
 
1012
  if($appendUserAgent) {
1013
+ $args['body']['useragent'] = "Agnt" . urlencode($_SERVER['HTTP_USER_AGENT']);
1014
  }
1015
 
1016
  $response = wp_remote_post($requestURL, $args);
1073
  {
1074
  if(isset($meta['ShortPixel']['BulkProcessing'])) {
1075
  print 'Waiting for bulk processing';
1076
+ print " | <a href=\"admin.php?action=shortpixel_manual_optimize&amp;attachment_ID={$id}\">Optimize now</a>";
1077
  return;
1078
  }
1079
 
 
1080
  if( is_numeric($data['ShortPixelImprovement']) && !isset($data['ShortPixel']['NoBackup']) ) {
1081
+ print $data['ShortPixelImprovement'] . '%';
1082
  print " | <a href=\"admin.php?action=shortpixel_restore_backup&amp;attachment_ID={$id}\">Restore backup</a>";
1083
  return;
1084
  }
1085
+ elseif ( is_numeric($data['ShortPixelImprovement']) )
1086
+ {
1087
+ print $data['ShortPixelImprovement'];
1088
  print '%';
1089
+ return;
1090
+ }
1091
+ elseif ( $data['ShortPixelImprovement'] <> "Optimisation N/A" )
1092
+ {
1093
+ print $data['ShortPixelImprovement'];
1094
+ print " | <a href=\"admin.php?action=shortpixel_manual_optimize&amp;attachment_ID={$id}\">Try again</a>";
1095
+ return;
1096
+ }
1097
+ else
1098
+ {
1099
+ print "Optimisation N/A";
1100
+ return;
1101
+ }
1102
+
1103
+
1104
  } elseif(isset($data['ShortPixel']['WaitingProcessing'])) {
1105
  print 'Image waiting to be processed';
1106
+ print " | <a href=\"admin.php?action=shortpixel_manual_optimize&amp;attachment_ID={$id}\">Optimize now</a>";
1107
  return;
1108
  } elseif(isset($data['ShortPixel']['NoFileOnDisk'])) {
1109
  print 'Image does not exist';
1110
  return;
1111
  } else {
1112
+
1113
  if ( wp_attachment_is_image( $id ) ) {
1114
  print 'Image not processed';
1115
  print " | <a href=\"admin.php?action=shortpixel_manual_optimize&amp;attachment_ID={$id}\">Optimize now</a>";
1120
  print " | <a href=\"admin.php?action=shortpixel_manual_optimize&amp;attachment_ID={$id}\">Optimize now</a>";
1121
  return;
1122
  }
1123
+
1124
  }
1125
  }
1126
  }
1159
 
1160
  return round($bytes, $precision) . ' ' . $units[$pow];
1161
  }
1162
+
1163
+ static public function isProcessable($path) {
1164
  $pathParts = pathinfo($path);
1165
+ if( isset($pathParts['extension']) && in_array(strtolower($pathParts['extension']), array('jpg', 'jpeg', 'gif', 'png', 'pdf'))) {
 
 
 
 
 
 
 
1166
  return true;
1167
  } else {
1168
  return false;
1169
  }
 
 
1170
  }
1171
 
1172
  public static function deleteDir($dirPath) {