ShortPixel Image Optimizer - Version 4.3.0

Version Description

  • a new level of optimization intermediate between lossy and lossless: glossy
  • bulk restore for Media Library
  • fix warning when activating plugin in some situations
  • empty backups button always visible (also when the backup option is unchecked)
Download this release

Release Info

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

Code changes from version 4.2.9 to 4.3.0

class/db/shortpixel-custom-meta-dao.php CHANGED
@@ -414,6 +414,7 @@ class ShortPixelCustomMetaDao {
414
  public function countAllProcessableFiles() {
415
  $sql = "SELECT count(*) totalFiles, sum(CASE WHEN status = 2 THEN 1 ELSE 0 END) totalProcessedFiles,"
416
  ." sum(CASE WHEN status = 2 AND compression_type = 1 THEN 1 ELSE 0 END) totalProcLossyFiles,"
 
417
  ." sum(CASE WHEN status = 2 AND compression_type = 0 THEN 1 ELSE 0 END) totalProcLosslessFiles"
418
  ." FROM {$this->db->getPrefix()}shortpixel_meta WHERE status <> -1";
419
  $rows = $this->db->query($sql);
@@ -429,10 +430,12 @@ class ShortPixelCustomMetaDao {
429
  return array("totalFiles" => $rows[0]->totalFiles, "mainFiles" => $rows[0]->totalFiles,
430
  "totalProcessedFiles" => $rows[0]->totalProcessedFiles, "mainProcessedFiles" => $rows[0]->totalProcessedFiles,
431
  "totalProcLossyFiles" => $rows[0]->totalProcLossyFiles, "mainProcLossyFiles" => $rows[0]->totalProcLossyFiles,
 
432
  "totalProcLosslessFiles" => $rows[0]->totalProcLosslessFiles, "mainProcLosslessFiles" => $rows[0]->totalProcLosslessFiles,
433
  "totalCustomFiles" => $rows[0]->totalFiles, "mainCustomFiles" => $rows[0]->totalFiles,
434
  "totalProcessedCustomFiles" => $rows[0]->totalProcessedFiles, "mainProcessedCustomFiles" => $rows[0]->totalProcessedFiles,
435
  "totalProcLossyCustomFiles" => $rows[0]->totalProcLossyFiles, "mainProcLossyCustomFiles" => $rows[0]->totalProcLossyFiles,
 
436
  "totalProcLosslessCustomFiles" => $rows[0]->totalProcLosslessFiles, "mainProcLosslessCustomFiles" => $rows[0]->totalProcLosslessFiles,
437
  "filesWithErrors" => $filesWithErrors
438
  );
414
  public function countAllProcessableFiles() {
415
  $sql = "SELECT count(*) totalFiles, sum(CASE WHEN status = 2 THEN 1 ELSE 0 END) totalProcessedFiles,"
416
  ." sum(CASE WHEN status = 2 AND compression_type = 1 THEN 1 ELSE 0 END) totalProcLossyFiles,"
417
+ ." sum(CASE WHEN status = 2 AND compression_type = 2 THEN 1 ELSE 0 END) totalProcGlossyFiles,"
418
  ." sum(CASE WHEN status = 2 AND compression_type = 0 THEN 1 ELSE 0 END) totalProcLosslessFiles"
419
  ." FROM {$this->db->getPrefix()}shortpixel_meta WHERE status <> -1";
420
  $rows = $this->db->query($sql);
430
  return array("totalFiles" => $rows[0]->totalFiles, "mainFiles" => $rows[0]->totalFiles,
431
  "totalProcessedFiles" => $rows[0]->totalProcessedFiles, "mainProcessedFiles" => $rows[0]->totalProcessedFiles,
432
  "totalProcLossyFiles" => $rows[0]->totalProcLossyFiles, "mainProcLossyFiles" => $rows[0]->totalProcLossyFiles,
433
+ "totalProcGlossyFiles" => $rows[0]->totalProcGlossyFiles, "mainProcGlossyFiles" => $rows[0]->totalProcGlossyFiles,
434
  "totalProcLosslessFiles" => $rows[0]->totalProcLosslessFiles, "mainProcLosslessFiles" => $rows[0]->totalProcLosslessFiles,
435
  "totalCustomFiles" => $rows[0]->totalFiles, "mainCustomFiles" => $rows[0]->totalFiles,
436
  "totalProcessedCustomFiles" => $rows[0]->totalProcessedFiles, "mainProcessedCustomFiles" => $rows[0]->totalProcessedFiles,
437
  "totalProcLossyCustomFiles" => $rows[0]->totalProcLossyFiles, "mainProcLossyCustomFiles" => $rows[0]->totalProcLossyFiles,
438
+ "totalProcGlossyCustomFiles" => $rows[0]->totalProcGlossyFiles, "mainProcGlossyCustomFiles" => $rows[0]->totalProcGlossyFiles,
439
  "totalProcLosslessCustomFiles" => $rows[0]->totalProcLosslessFiles, "mainProcLosslessCustomFiles" => $rows[0]->totalProcLosslessFiles,
440
  "filesWithErrors" => $filesWithErrors
441
  );
class/db/shortpixel-meta-facade.php CHANGED
@@ -54,14 +54,17 @@ class ShortPixelMetaFacade {
54
  "webPath" => (isset($rawMeta["file"]) ? $rawMeta["file"] : null),
55
  "thumbs" => (isset($rawMeta["sizes"]) ? $rawMeta["sizes"] : array()),
56
  "message" =>(isset($rawMeta["ShortPixelImprovement"]) ? $rawMeta["ShortPixelImprovement"] : null),
57
- "compressionType" =>(isset($rawMeta["ShortPixel"]["type"]) ? ($rawMeta["ShortPixel"]["type"] == "lossy" ? 1 : 0) : null),
 
 
58
  "thumbsOpt" =>(isset($rawMeta["ShortPixel"]["thumbsOpt"]) ? $rawMeta["ShortPixel"]["thumbsOpt"] : null),
59
  "thumbsMissing" =>(isset($rawMeta["ShortPixel"]["thumbsMissing"]) ? $rawMeta["ShortPixel"]["thumbsMissing"] : null),
60
  "retinasOpt" =>(isset($rawMeta["ShortPixel"]["retinasOpt"]) ? $rawMeta["ShortPixel"]["retinasOpt"] : null),
61
  "thumbsTodo" =>(isset($rawMeta["ShortPixel"]["thumbsTodo"]) ? $rawMeta["ShortPixel"]["thumbsTodo"] : false),
62
  "backup" => !isset($rawMeta['ShortPixel']['NoBackup']),
63
  "status" => (!isset($rawMeta["ShortPixel"]) ? 0
64
- : (isset($rawMeta["ShortPixelImprovement"]) && is_numeric($rawMeta["ShortPixelImprovement"]) ? 2
 
65
  : (isset($rawMeta["ShortPixel"]["WaitingProcessing"]) ? 1
66
  : (isset($rawMeta["ShortPixel"]['ErrCode']) ? $rawMeta["ShortPixel"]['ErrCode'] : -500)))),
67
  "retries" =>(isset($rawMeta["ShortPixel"]["Retries"]) ? $rawMeta["ShortPixel"]["Retries"] : 0),
@@ -79,7 +82,8 @@ class ShortPixelMetaFacade {
79
 
80
  function sanitizeMeta($rawMeta){
81
  if(!is_array($rawMeta)) {
82
- return array("previous_meta" => $rawMeta, 'ShortPixel' => array());
 
83
  }
84
  return $rawMeta;
85
  }
@@ -99,7 +103,7 @@ class ShortPixelMetaFacade {
99
  foreach($duplicates as $_ID) {
100
  $rawMeta = $this->sanitizeMeta(wp_get_attachment_metadata($_ID));
101
 
102
- if(is_array($rawMeta['sizes'])) {
103
  if($replaceThumbs) {
104
  $rawMeta['sizes'] = $this->meta->getThumbs();
105
  } else {
@@ -115,7 +119,7 @@ class ShortPixelMetaFacade {
115
  if(null === $this->meta->getCompressionType()) {
116
  unset($rawMeta['ShortPixel']['type']);
117
  } else {
118
- $rawMeta['ShortPixel']['type'] = ($this->meta->getCompressionType() == 1 ? "lossy" : "lossless");
119
  }
120
 
121
  if(null === $this->meta->getKeepExif()) {
@@ -421,7 +425,8 @@ class ShortPixelMetaFacade {
421
 
422
  public function getWebpSizeMeta($path) {
423
  $meta = $this->getMeta();
424
- foreach($meta->getThumbs() as $thumbKey => $thumbMeta) {
 
425
  if(isset($thumbMeta['file']) && strpos($path, $thumbMeta['file']) !== false) {
426
  $thumbMeta['file'] = preg_replace( '/\.' . pathinfo($path, PATHINFO_EXTENSION) . '$/', '.webp', $thumbMeta['file']);
427
  $thumbMeta['mime-type'] = 'image/webp';
54
  "webPath" => (isset($rawMeta["file"]) ? $rawMeta["file"] : null),
55
  "thumbs" => (isset($rawMeta["sizes"]) ? $rawMeta["sizes"] : array()),
56
  "message" =>(isset($rawMeta["ShortPixelImprovement"]) ? $rawMeta["ShortPixelImprovement"] : null),
57
+ "compressionType" =>(isset($rawMeta["ShortPixel"]["type"])
58
+ ? ($rawMeta["ShortPixel"]["type"] == 'glossy' ? 2 : ($rawMeta["ShortPixel"]["type"] == "lossy" ? 1 : 0) )
59
+ : null),
60
  "thumbsOpt" =>(isset($rawMeta["ShortPixel"]["thumbsOpt"]) ? $rawMeta["ShortPixel"]["thumbsOpt"] : null),
61
  "thumbsMissing" =>(isset($rawMeta["ShortPixel"]["thumbsMissing"]) ? $rawMeta["ShortPixel"]["thumbsMissing"] : null),
62
  "retinasOpt" =>(isset($rawMeta["ShortPixel"]["retinasOpt"]) ? $rawMeta["ShortPixel"]["retinasOpt"] : null),
63
  "thumbsTodo" =>(isset($rawMeta["ShortPixel"]["thumbsTodo"]) ? $rawMeta["ShortPixel"]["thumbsTodo"] : false),
64
  "backup" => !isset($rawMeta['ShortPixel']['NoBackup']),
65
  "status" => (!isset($rawMeta["ShortPixel"]) ? 0
66
+ : (isset($rawMeta["ShortPixelImprovement"]) && is_numeric($rawMeta["ShortPixelImprovement"])
67
+ && !($rawMeta['ShortPixelImprovement'] == 0 && isset($rawMeta['ShortPixel']['WaitingProcessing'])) ? 2
68
  : (isset($rawMeta["ShortPixel"]["WaitingProcessing"]) ? 1
69
  : (isset($rawMeta["ShortPixel"]['ErrCode']) ? $rawMeta["ShortPixel"]['ErrCode'] : -500)))),
70
  "retries" =>(isset($rawMeta["ShortPixel"]["Retries"]) ? $rawMeta["ShortPixel"]["Retries"] : 0),
82
 
83
  function sanitizeMeta($rawMeta){
84
  if(!is_array($rawMeta)) {
85
+ if($rawMeta == '') { return array('ShortPixel' => array()); }
86
+ else { return array("previous_meta" => $rawMeta, 'ShortPixel' => array()); }
87
  }
88
  return $rawMeta;
89
  }
103
  foreach($duplicates as $_ID) {
104
  $rawMeta = $this->sanitizeMeta(wp_get_attachment_metadata($_ID));
105
 
106
+ if(isset($rawMeta['sizes']) && is_array($rawMeta['sizes'])) {
107
  if($replaceThumbs) {
108
  $rawMeta['sizes'] = $this->meta->getThumbs();
109
  } else {
119
  if(null === $this->meta->getCompressionType()) {
120
  unset($rawMeta['ShortPixel']['type']);
121
  } else {
122
+ $rawMeta['ShortPixel']['type'] = ShortPixelAPI::getCompressionTypeName($this->meta->getCompressionType());
123
  }
124
 
125
  if(null === $this->meta->getKeepExif()) {
425
 
426
  public function getWebpSizeMeta($path) {
427
  $meta = $this->getMeta();
428
+ $thumbs = $meta->getThumbs(); $thumbs = is_array($thumbs) ? $thumbs : array();
429
+ foreach($thumbs as $thumbKey => $thumbMeta) {
430
  if(isset($thumbMeta['file']) && strpos($path, $thumbMeta['file']) !== false) {
431
  $thumbMeta['file'] = preg_replace( '/\.' . pathinfo($path, PATHINFO_EXTENSION) . '$/', '.webp', $thumbMeta['file']);
432
  $thumbMeta['mime-type'] = 'image/webp';
class/db/wp-shortpixel-media-library-adapter.php CHANGED
@@ -7,7 +7,7 @@ class WpShortPixelMediaLbraryAdapter {
7
  global $wpdb;
8
 
9
  $totalFiles = $mainFiles = $processedMainFiles = $processedTotalFiles =
10
- $procLossyMainFiles = $procLossyTotalFiles = $procLosslessMainFiles = $procLosslessTotalFiles = $procUndefMainFiles = $procUndefTotalFiles = $mainUnprocessedThumbs = 0;
11
  $filesMap = $processedFilesMap = array();
12
  $limit = self::getOptimalChunkSize();
13
  $pointer = 0;
@@ -68,15 +68,22 @@ class WpShortPixelMediaLbraryAdapter {
68
  $processedMainFiles++;
69
  $processedTotalFiles++;
70
  $type = isset($attachment['ShortPixel']['type']) ? $attachment['ShortPixel']['type'] : null;
71
- if($type == 'lossy') {
72
- $procLossyMainFiles++;
73
- $procLossyTotalFiles++;
74
- } elseif($type == 'lossless') {
75
- $procLosslessMainFiles++;
76
- $procLosslessTotalFiles++;
77
- } else {
78
- $procUndefMainFiles++;
79
- $procUndefTotalFiles++;
 
 
 
 
 
 
 
80
  }
81
 
82
  //get the thumbs processed for that attachment
@@ -95,7 +102,9 @@ class WpShortPixelMediaLbraryAdapter {
95
 
96
  //increment with thumbs processed
97
  $processedTotalFiles += $thumbs;
98
- if($type == 'lossy') {
 
 
99
  $procLossyTotalFiles += $thumbs;
100
  } else {
101
  $procLosslessTotalFiles += $thumbs;
@@ -121,10 +130,12 @@ class WpShortPixelMediaLbraryAdapter {
121
  return array("totalFiles" => $totalFiles, "mainFiles" => $mainFiles,
122
  "totalProcessedFiles" => $processedTotalFiles, "mainProcessedFiles" => $processedMainFiles,
123
  "totalProcLossyFiles" => $procLossyTotalFiles, "mainProcLossyFiles" => $procLossyMainFiles,
 
124
  "totalProcLosslessFiles" => $procLosslessTotalFiles, "mainProcLosslessFiles" => $procLosslessMainFiles,
125
  "totalMlFiles" => $totalFiles, "mainMlFiles" => $mainFiles,
126
  "totalProcessedMlFiles" => $processedTotalFiles, "mainProcessedMlFiles" => $processedMainFiles,
127
  "totalProcLossyMlFiles" => $procLossyTotalFiles, "mainProcLossyMlFiles" => $procLossyMainFiles,
 
128
  "totalProcLosslessMlFiles" => $procLosslessTotalFiles, "mainProcLosslessMlFiles" => $procLosslessMainFiles,
129
  "totalProcUndefMlFiles" => $procUndefTotalFiles, "mainProcUndefMlFiles" => $procUndefMainFiles,
130
  "mainUnprocessedThumbs" => $mainUnprocessedThumbs,
@@ -132,6 +143,16 @@ class WpShortPixelMediaLbraryAdapter {
132
  );
133
  }
134
 
 
 
 
 
 
 
 
 
 
 
135
  public static function countNonWebpSizes($sizes) {
136
  $count = 0;
137
  foreach($sizes as $key => $val) {
7
  global $wpdb;
8
 
9
  $totalFiles = $mainFiles = $processedMainFiles = $processedTotalFiles =
10
+ $procGlossyMainFiles = $procGlossyTotalFiles = $procLossyMainFiles = $procLossyTotalFiles = $procLosslessMainFiles = $procLosslessTotalFiles = $procUndefMainFiles = $procUndefTotalFiles = $mainUnprocessedThumbs = 0;
11
  $filesMap = $processedFilesMap = array();
12
  $limit = self::getOptimalChunkSize();
13
  $pointer = 0;
68
  $processedMainFiles++;
69
  $processedTotalFiles++;
70
  $type = isset($attachment['ShortPixel']['type']) ? $attachment['ShortPixel']['type'] : null;
71
+ switch($type) {
72
+ case 'lossy' :
73
+ $procLossyMainFiles++;
74
+ $procLossyTotalFiles++;
75
+ break;
76
+ case 'glossy':
77
+ $procGlossyMainFiles++;
78
+ $procGlossyTotalFiles++;
79
+ break;
80
+ case 'lossless':
81
+ $procLosslessMainFiles++;
82
+ $procLosslessTotalFiles++;
83
+ break;
84
+ default:
85
+ $procUndefMainFiles++;
86
+ $procUndefTotalFiles++;
87
  }
88
 
89
  //get the thumbs processed for that attachment
102
 
103
  //increment with thumbs processed
104
  $processedTotalFiles += $thumbs;
105
+ if($type == 'glossy') {
106
+ $procGlossyTotalFiles += $thumbs;
107
+ } elseif ($type == 'lossy') {
108
  $procLossyTotalFiles += $thumbs;
109
  } else {
110
  $procLosslessTotalFiles += $thumbs;
130
  return array("totalFiles" => $totalFiles, "mainFiles" => $mainFiles,
131
  "totalProcessedFiles" => $processedTotalFiles, "mainProcessedFiles" => $processedMainFiles,
132
  "totalProcLossyFiles" => $procLossyTotalFiles, "mainProcLossyFiles" => $procLossyMainFiles,
133
+ "totalProcGlossyFiles" => $procGlossyTotalFiles, "mainProcGlossyFiles" => $procGlossyMainFiles,
134
  "totalProcLosslessFiles" => $procLosslessTotalFiles, "mainProcLosslessFiles" => $procLosslessMainFiles,
135
  "totalMlFiles" => $totalFiles, "mainMlFiles" => $mainFiles,
136
  "totalProcessedMlFiles" => $processedTotalFiles, "mainProcessedMlFiles" => $processedMainFiles,
137
  "totalProcLossyMlFiles" => $procLossyTotalFiles, "mainProcLossyMlFiles" => $procLossyMainFiles,
138
+ "totalProcGlossyMlFiles" => $procGlossyTotalFiles, "mainProcGlossyMlFiles" => $procGlossyMainFiles,
139
  "totalProcLosslessMlFiles" => $procLosslessTotalFiles, "mainProcLosslessMlFiles" => $procLosslessMainFiles,
140
  "totalProcUndefMlFiles" => $procUndefTotalFiles, "mainProcUndefMlFiles" => $procUndefMainFiles,
141
  "mainUnprocessedThumbs" => $mainUnprocessedThumbs,
143
  );
144
  }
145
 
146
+ public static function getPostMetaSlice($startId, $endId, $limit) {
147
+ global $wpdb;
148
+ $queryPostMeta = "SELECT * FROM " . $wpdb->prefix . "postmeta
149
+ WHERE ( post_id <= $startId AND post_id >= $endId )
150
+ AND ( meta_key = '_wp_attached_file' OR meta_key = '_wp_attachment_metadata' )
151
+ ORDER BY post_id DESC
152
+ LIMIT " . $limit;
153
+ return $wpdb->get_results($queryPostMeta);
154
+ }
155
+
156
  public static function countNonWebpSizes($sizes) {
157
  $count = 0;
158
  foreach($sizes as $key => $val) {
class/shortpixel_queue.php CHANGED
@@ -5,6 +5,10 @@ class ShortPixelQueue {
5
  private $ctrl;
6
  private $settings;
7
 
 
 
 
 
8
  const BULK_NEVER = 0; //bulk never ran
9
  const BULK_RUNNING = 1; //bulk is running
10
  const BULK_PAUSED = 2; //bulk is paused
@@ -247,7 +251,20 @@ class ShortPixelQueue {
247
  $this->settings->bulkCount = $res["mainFiles"];
248
 
249
  //if compression type changed, add also the images with the other compression type
250
- $this->settings->bulkAlreadyDoneCount = $res["mainProcessedFiles"] - $res["mainProc".((0 + $this->ctrl->getCompressionType() == 1) ? "Lossless" : "Lossy")."Files"];
 
 
 
 
 
 
 
 
 
 
 
 
 
251
  // if the thumbnails are to be processed, add also the images that have thumbs not processed
252
  if($this->settings->processThumbnails) {
253
  $this->settings->bulkAlreadyDoneCount -= $res["mainUnprocessedThumbs"];
@@ -266,12 +283,21 @@ class ShortPixelQueue {
266
  $this->settings->bulkProcessingStatus = 'running';//set bulk flag
267
  }
268
 
269
- public function startBulk() {
 
 
 
 
 
 
 
 
270
  $this->resetStartBulkId(); //start downwards from the biggest item ID
271
  $this->resetStopBulkId();
272
  $this->flagBulkStart(); //we use this to detect new added files while bulk is running
273
  $this->setBulkPreviousPercent();
274
  $this->resetBulkCurrentlyProcessed();
 
275
  $this->settings->bulkEverRan = 1;
276
  }
277
 
@@ -326,6 +352,7 @@ class ShortPixelQueue {
326
  }
327
 
328
  public static function resetBulk() {
 
329
  delete_option('bulkProcessingStatus');
330
  delete_option( 'wp-short-pixel-cancel-pointer');
331
  delete_option( "wp-short-pixel-flag-id");
5
  private $ctrl;
6
  private $settings;
7
 
8
+ const BULK_TYPE_OPTIMIZE = 0;
9
+ const BULK_TYPE_RESTORE = 1;
10
+ const BULK_TYPE_CLEANUP = 2;
11
+
12
  const BULK_NEVER = 0; //bulk never ran
13
  const BULK_RUNNING = 1; //bulk is running
14
  const BULK_PAUSED = 2; //bulk is paused
251
  $this->settings->bulkCount = $res["mainFiles"];
252
 
253
  //if compression type changed, add also the images with the other compression type
254
+ switch (0 + $this->ctrl->getCompressionType()) {
255
+ case 2:
256
+ $this->settings->bulkAlreadyDoneCount = $res["mainProcessedFiles"] - $res["mainProcLossyFiles"] - $res["mainProcLosslessFiles"];
257
+ break;
258
+ case 1:
259
+ $this->settings->bulkAlreadyDoneCount = $res["mainProcessedFiles"] - $res["mainProcGlossyFiles"] - $res["mainProcLosslessFiles"];
260
+ break;
261
+ default: //lossless
262
+ $this->settings->bulkAlreadyDoneCount = $res["mainProcessedFiles"] - $res["mainProcLossyFiles"] - $res["mainProcGlossyFiles"];
263
+ break;
264
+
265
+ }
266
+ //$this->settings->bulkAlreadyDoneCount = $res["mainProcessedFiles"] - $res["mainProc".((0 + $this->ctrl->getCompressionType() == 1) ? "Lossless" : "Lossy")."Files"];
267
+
268
  // if the thumbnails are to be processed, add also the images that have thumbs not processed
269
  if($this->settings->processThumbnails) {
270
  $this->settings->bulkAlreadyDoneCount -= $res["mainUnprocessedThumbs"];
283
  $this->settings->bulkProcessingStatus = 'running';//set bulk flag
284
  }
285
 
286
+ public function setBulkType($type) {
287
+ $this->settings->bulkType = $type;
288
+ }
289
+
290
+ public function getBulkType() {
291
+ return $this->settings->bulkType;
292
+ }
293
+
294
+ public function startBulk($type = self::BULK_TYPE_OPTIMIZE) {
295
  $this->resetStartBulkId(); //start downwards from the biggest item ID
296
  $this->resetStopBulkId();
297
  $this->flagBulkStart(); //we use this to detect new added files while bulk is running
298
  $this->setBulkPreviousPercent();
299
  $this->resetBulkCurrentlyProcessed();
300
+ $this->setBulkType($type);
301
  $this->settings->bulkEverRan = 1;
302
  }
303
 
352
  }
353
 
354
  public static function resetBulk() {
355
+ delete_option('wp-short-pixel-bulk-type');
356
  delete_option('bulkProcessingStatus');
357
  delete_option( 'wp-short-pixel-cancel-pointer');
358
  delete_option( "wp-short-pixel-flag-id");
class/view/shortpixel-list-table.php CHANGED
@@ -56,12 +56,15 @@ class ShortPixelListTable extends WP_List_Table {
56
  'restore' => sprintf( '<a href="?page=%s&action=%s&image=%s&_wpnonce=%s&noheader=true">%s</a>',
57
  esc_attr( $_REQUEST['page'] ), 'restore', absint( $item->id ), wp_create_nonce( 'sp_restore_image' ),
58
  __('Restore','shortpixel-image-optimiser')),
59
- 'redolossless' => sprintf( '<a href="?page=%s&action=%s&image=%s&_wpnonce=%s&noheader=true">%s</a>',
60
- esc_attr( $_REQUEST['page'] ), 'redo', absint( $item->id ), wp_create_nonce( 'sp_redo_image' ),
61
  __('Re-optimize lossless','shortpixel-image-optimiser')),
62
- 'redolossy' => sprintf( '<a href="?page=%s&action=%s&image=%s&_wpnonce=%s&noheader=true">%s</a>',
63
- esc_attr( $_REQUEST['page'] ), 'redo', absint( $item->id ), wp_create_nonce( 'sp_redo_image' ),
64
  __('Re-optimize lossy','shortpixel-image-optimiser')),
 
 
 
65
  'quota' => sprintf( '<a href="?page=%s&action=%s&image=%s&_wpnonce=%s&noheader=true">%s</a>',
66
  esc_attr( $_REQUEST['page'] ), 'quota', absint( $item->id ), wp_create_nonce( 'sp_check_quota' ),
67
  __('Check quota','shortpixel-image-optimiser')),
@@ -75,7 +78,17 @@ class ShortPixelListTable extends WP_List_Table {
75
  $actionsEnabled['optimize'] = true;
76
  } elseif($item->status == 2) {
77
  $actionsEnabled['restore'] = true;
78
- $actionsEnabled['redo'.($item->compression_type == 1 ? "lossless" : "lossy")] = true;
 
 
 
 
 
 
 
 
 
 
79
  } elseif($item->status == 3 || $item->status < 0) {
80
  $actionsEnabled['retry'] = true;
81
  }
@@ -108,7 +121,7 @@ class ShortPixelListTable extends WP_List_Table {
108
  return "<div id='sp-cust-msg-C-" . $item->id . "'>" . $msg . "</div>";
109
  break;
110
  case 'options':
111
- return ($item->compression_type == 1 ? __('Lossy','shortpixel-image-optimiser') : __('Lossless','shortpixel-image-optimiser'))
112
  . ($item->keep_exif == 1 ? "": ", " . __('Keep EXIF','shortpixel-image-optimiser'))
113
  . ($item->cmyk2rgb ? "": ", " . __('Preserve CMYK','shortpixel-image-optimiser'));
114
  case 'media_type':
@@ -178,8 +191,8 @@ class ShortPixelListTable extends WP_List_Table {
178
  $this->ctrl->doCustomRestore($id);
179
  }
180
 
181
- public function action_redo_image( $id ) {
182
- $this->ctrl->redo('C-' . $id);
183
  }
184
 
185
  public function process_actions() {
@@ -209,7 +222,7 @@ class ShortPixelListTable extends WP_List_Table {
209
  if (!wp_verify_nonce($nonce, 'sp_redo_image')) {
210
  die('Error.');
211
  } else {
212
- $this->action_redo_image(absint($_GET['image']));
213
  wp_redirect(esc_url(remove_query_arg(array('action', 'image', '_wpnonce'))));
214
  exit;
215
  }
56
  'restore' => sprintf( '<a href="?page=%s&action=%s&image=%s&_wpnonce=%s&noheader=true">%s</a>',
57
  esc_attr( $_REQUEST['page'] ), 'restore', absint( $item->id ), wp_create_nonce( 'sp_restore_image' ),
58
  __('Restore','shortpixel-image-optimiser')),
59
+ 'redolossless' => sprintf( '<a href="?page=%s&action=%s&type=%s&image=%s&_wpnonce=%s&noheader=true">%s</a>',
60
+ esc_attr( $_REQUEST['page'] ), 'redo', 'lossless', absint( $item->id ), wp_create_nonce( 'sp_redo_image' ),
61
  __('Re-optimize lossless','shortpixel-image-optimiser')),
62
+ 'redolossy' => sprintf( '<a href="?page=%s&action=%s&type=%s&image=%s&_wpnonce=%s&noheader=true">%s</a>',
63
+ esc_attr( $_REQUEST['page'] ), 'redo', 'lossy', absint( $item->id ), wp_create_nonce( 'sp_redo_image' ),
64
  __('Re-optimize lossy','shortpixel-image-optimiser')),
65
+ 'redoglossy' => sprintf( '<a href="?page=%s&action=%s&type=%s&image=%s&_wpnonce=%s&noheader=true">%s</a>',
66
+ esc_attr( $_REQUEST['page'] ), 'redo', 'glossy', absint( $item->id ), wp_create_nonce( 'sp_redo_image' ),
67
+ __('Re-optimize glossy','shortpixel-image-optimiser')),
68
  'quota' => sprintf( '<a href="?page=%s&action=%s&image=%s&_wpnonce=%s&noheader=true">%s</a>',
69
  esc_attr( $_REQUEST['page'] ), 'quota', absint( $item->id ), wp_create_nonce( 'sp_check_quota' ),
70
  __('Check quota','shortpixel-image-optimiser')),
78
  $actionsEnabled['optimize'] = true;
79
  } elseif($item->status == 2) {
80
  $actionsEnabled['restore'] = true;
81
+ switch($item->compression_type) {
82
+ case 2:
83
+ $actionsEnabled['redolossy'] = $actionsEnabled['redolossless'] = true;
84
+ break;
85
+ case 1:
86
+ $actionsEnabled['redoglossy'] = $actionsEnabled['redolossless'] = true;
87
+ break;
88
+ default:
89
+ $actionsEnabled['redolossy'] = $actionsEnabled['redoglossy'] = true;
90
+ }
91
+ //$actionsEnabled['redo'.($item->compression_type == 1 ? "lossless" : "lossy")] = true;
92
  } elseif($item->status == 3 || $item->status < 0) {
93
  $actionsEnabled['retry'] = true;
94
  }
121
  return "<div id='sp-cust-msg-C-" . $item->id . "'>" . $msg . "</div>";
122
  break;
123
  case 'options':
124
+ return __($item->compression_type == 2 ? 'Glossy' : ($item->compression_type == 1 ? 'Lossy' : 'Lossless'),'shortpixel-image-optimiser')
125
  . ($item->keep_exif == 1 ? "": ", " . __('Keep EXIF','shortpixel-image-optimiser'))
126
  . ($item->cmyk2rgb ? "": ", " . __('Preserve CMYK','shortpixel-image-optimiser'));
127
  case 'media_type':
191
  $this->ctrl->doCustomRestore($id);
192
  }
193
 
194
+ public function action_redo_image( $id, $type = false ) {
195
+ $this->ctrl->redo('C-' . $id, $type);
196
  }
197
 
198
  public function process_actions() {
222
  if (!wp_verify_nonce($nonce, 'sp_redo_image')) {
223
  die('Error.');
224
  } else {
225
+ $this->action_redo_image(absint($_GET['image']), $_GET['type']);
226
  wp_redirect(esc_url(remove_query_arg(array('action', 'image', '_wpnonce'))));
227
  exit;
228
  }
class/view/shortpixel_view.php CHANGED
@@ -329,26 +329,46 @@ class ShortPixelView {
329
  </p>
330
  <?php }
331
  $settings = $this->ctrl->getSettings();
332
- $optType = $settings->compressionType == '1' ? 'lossy' : 'lossless';
333
- $otherType = $settings->compressionType == '1' ? 'lossless' : 'lossy';
 
 
 
334
  if( !$this->ctrl->backupFolderIsEmpty()
335
- && ( ($quotaData['totalProcLossyFiles'] > 0 && $settings->compressionType == 0)
336
- || ($quotaData['totalProcLosslessFiles'] > 0 && $settings->compressionType == 1)))
 
337
  {
338
  $todo = $reopt = true;
339
- $statType = $settings->compressionType == '1' ? 'Lossless' : 'Lossy';
340
  $thumbsCount = $quotaData['totalProc'.$statType.'Files'] - $quotaData['mainProc'.$statType.'Files'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
341
  ?>
342
  <p id="with-thumbs" <?php echo(!$settings->processThumbnails ? 'style="display:none;"' : "");?>>
343
- <?php printf(__('%s images and %s thumbnails were optimized <strong>%s</strong>. You can re-optimize <strong>%s</strong> the ones that have backup.','shortpixel-image-optimiser'),
 
344
  number_format($quotaData['mainProc'.$statType.'Files']),
345
  number_format($thumbsCount), $otherType, $optType);?>
346
  </p>
347
  <p id="without-thumbs" <?php echo($settings->processThumbnails ? 'style="display:none;"' : "");?>>
348
- <?php printf(__('%s images were optimized <strong>%s</strong>. You can re-optimize <strong>%s</strong> the ones that have backup. ','shortpixel-image-optimiser'),
 
349
  number_format($quotaData['mainProc'.$statType.'Files']),
350
  $otherType, $optType);?>
351
- <?php echo($thumbsCount ? number_format($thumbsCount) . __(' thumbnails will be restored to originals.','shortpixel-image-optimiser') : '');?>
352
  </p>
353
  <?php
354
  } ?>
@@ -368,6 +388,7 @@ class ShortPixelView {
368
  <input type='checkbox' id='bulk-thumbnails' name='thumbnails' <?php echo($this->ctrl->processThumbnails() ? "checked":"");?>
369
  onchange="ShortPixel.onBulkThumbsCheck(this)"> <?php _e('Include thumbnails','shortpixel-image-optimiser');?><br><br>
370
  <input type='submit' name='bulkProcess' id='bulkProcess' class='button button-primary' value='<?php _e('Restart Optimizing','shortpixel-image-optimiser');?>'>
 
371
  </form>
372
  </div>
373
  <?php } ?>
@@ -471,12 +492,21 @@ class ShortPixelView {
471
  </script>
472
  </div>
473
  </div>
474
- <?php if($running) { ?>
475
- <div class="sp-h2"><?php echo($type & 1 ? __('Media Library','shortpixel-image-optimiser') . " " : "");
476
- echo($type & 3 == 3 ? __('and','shortpixel-image-optimiser') . " " : "");
477
- echo($type & 2 ? __('Custom folders','shortpixel-image-optimiser') . " " : ""); _e('optimization in progress ...','shortpixel-image-optimiser');?></div>
478
- <p style="margin: 0 0 18px;"><?php _e('Bulk optimization has started.','shortpixel-image-optimiser');?><br>
479
- <?php printf(__('This process will take some time, depending on the number of images in your library. In the meantime, you can continue using
 
 
 
 
 
 
 
 
 
480
  the admin as usual, <a href="%s" target="_blank">in a different browser window or tab</a>.<br>
481
  However, <strong>if you close this window, the bulk processing will pause</strong> until you open the media gallery or the ShortPixel bulk page again.','shortpixel-image-optimiser'), get_admin_url());?>
482
  </p>
@@ -687,13 +717,17 @@ class ShortPixelView {
687
  <td>
688
  <input type="radio" name="compressionType" value="1" <?php echo( $this->ctrl->getCompressionType() == 1 ? "checked" : "" );?>><?php
689
  _e('Lossy (recommended)','shortpixel-image-optimiser');?></br>
690
- <p class="settings-info"><?php _e('<b>Lossy compression: </b>lossy has a better compression rate than lossless compression.</br>The resulting image is identical with the original to the human eye. You can run a test for free ','shortpixel-image-optimiser');?>
691
  <a href="https://shortpixel.com/online-image-compression" target="_blank"><?php _e('here','shortpixel-image-optimiser');?></a>.</p></br>
692
- <input type="radio" name="compressionType" value="0" <?php echo( $this->ctrl->getCompressionType() != 1 ? "checked" : "" );?>><?php
 
 
 
 
693
  _e('Lossless','shortpixel-image-optimiser');?>
694
  <p class="settings-info">
695
- <?php _e('<b>Lossless compression: </b> the shrunk image will be identical with the original and smaller in size.</br>In some rare cases you will need to use
696
- this type of compression. Some technical drawings or images from vector graphics are possible situations.','shortpixel-image-optimiser');?>
697
  </p>
698
  </td>
699
  </tr>
@@ -1020,7 +1054,7 @@ class ShortPixelView {
1020
  <th scope="row"><label for="totalFiles"><?php _e('Total number of processed files:','shortpixel-image-optimiser');?></label></th>
1021
  <td><?php echo($fileCount);?></td>
1022
  </tr>
1023
- <?php if($this->ctrl->backupImages()) { ?>
1024
  <tr>
1025
  <th scope="row"><label for="sizeBackup"><?php _e('Original images are stored in a backup folder. Your backup folder size is now:','shortpixel-image-optimiser');?></label></th>
1026
  <td>
@@ -1102,7 +1136,7 @@ class ShortPixelView {
1102
  . $missingThumbs;
1103
  }
1104
  $this->renderListCell($id, $data['showActions'],
1105
- !$data['thumbsOpt'] && $data['thumbsTotal'], $data['thumbsTotal'], $data['backup'], $data['type'], $successText);
1106
 
1107
  break;
1108
  }
@@ -1124,7 +1158,7 @@ class ShortPixelView {
1124
  .($retinasOpt ? '<br>' . sprintf(__('+%s Retina images optimized','shortpixel-image-optimiser') , $retinasOpt) : '' ) ;
1125
  }
1126
 
1127
- public function renderListCell($id, $showActions, $optimizeThumbs, $thumbsTotal, $backup, $type, $message) {
1128
  if($showActions) { ?>
1129
  <div class='sp-column-actions'>
1130
  <?php if($optimizeThumbs) { ?>
@@ -1134,7 +1168,7 @@ class ShortPixelView {
1134
  <?php }
1135
  if($backup) {
1136
  if($type) {
1137
- $invType = $type == 'lossy' ? 'lossless' : 'lossy'; ?>
1138
  <a class='button button-smaller' href="javascript:reoptimize('<?php echo($id)?>', '<?php echo($invType)?>');"
1139
  title="<?php _e('Reoptimize from the backed-up image','shortpixel-image-optimiser');?>">
1140
  <?php _e('Re-optimize','shortpixel-image-optimiser');?> <?php echo($invType)?>
329
  </p>
330
  <?php }
331
  $settings = $this->ctrl->getSettings();
332
+ $optType = ShortPixelAPI::getCompressionTypeName($settings->compressionType);
333
+ $otherType = ShortPixelAPI::getCompressionTypeName($this->ctrl->getOtherCompressionType($settings->compressionType));
334
+ $otherType2 = array_diff(array('lossy', 'glossy', 'lossless'), array($optType, $otherType));
335
+ $otherType2 = reset($otherType2);
336
+ $extraW = $extraO = '';
337
  if( !$this->ctrl->backupFolderIsEmpty()
338
+ && ( ($quotaData['totalProcLossyFiles'] > 0 && $settings->compressionType != 1)
339
+ || ($quotaData['totalProcGlossyFiles'] > 0 && $settings->compressionType != 2)
340
+ || ($quotaData['totalProcLosslessFiles'] > 0 && $settings->compressionType != 0)))
341
  {
342
  $todo = $reopt = true;
343
+ $statType = ucfirst($otherType);
344
  $thumbsCount = $quotaData['totalProc'.$statType.'Files'] - $quotaData['mainProc'.$statType.'Files'];
345
+
346
+ $statType2 = ucfirst($otherType2);
347
+ $thumbsCount2 = $quotaData['totalProc'.$statType2.'Files'] - $quotaData['mainProc'.$statType2.'Files'];
348
+ if($quotaData['totalProc'.$statType2.'Files'] > 0 ) {
349
+ if($quotaData['totalProc'.$statType.'Files'] > 0) {
350
+ $extraW = sprintf(__('%s images and %s thumbnails were optimized <strong>%s</strong>. ','shortpixel-image-optimiser'),
351
+ number_format($quotaData['mainProc'.$statType2.'Files']),
352
+ number_format($thumbsCount2), $otherType2);
353
+ $extraO = sprintf(__('%s images were optimized <strong>%s</strong>. ','shortpixel-image-optimiser'),
354
+ number_format($quotaData['mainProc'.$statType2.'Files']), $otherType2);
355
+ } else {
356
+ $extraW = $extraO = ''; $otherType = $otherType2; $statType = $statType2;
357
+ }
358
+ }
359
  ?>
360
  <p id="with-thumbs" <?php echo(!$settings->processThumbnails ? 'style="display:none;"' : "");?>>
361
+ <?php echo($extraW);
362
+ printf(__('%s images and %s thumbnails were optimized <strong>%s</strong>. You can re-optimize <strong>%s</strong> the ones that have backup.','shortpixel-image-optimiser'),
363
  number_format($quotaData['mainProc'.$statType.'Files']),
364
  number_format($thumbsCount), $otherType, $optType);?>
365
  </p>
366
  <p id="without-thumbs" <?php echo($settings->processThumbnails ? 'style="display:none;"' : "");?>>
367
+ <?php echo($extraO);
368
+ printf(__('%s images were optimized <strong>%s</strong>. You can re-optimize <strong>%s</strong> the ones that have backup. ','shortpixel-image-optimiser'),
369
  number_format($quotaData['mainProc'.$statType.'Files']),
370
  $otherType, $optType);?>
371
+ <?php echo($thumbsCount + $thumbsCount2 ? number_format($thumbsCount + $thumbsCount2) . __(' thumbnails will be restored to originals.','shortpixel-image-optimiser') : '');?>
372
  </p>
373
  <?php
374
  } ?>
388
  <input type='checkbox' id='bulk-thumbnails' name='thumbnails' <?php echo($this->ctrl->processThumbnails() ? "checked":"");?>
389
  onchange="ShortPixel.onBulkThumbsCheck(this)"> <?php _e('Include thumbnails','shortpixel-image-optimiser');?><br><br>
390
  <input type='submit' name='bulkProcess' id='bulkProcess' class='button button-primary' value='<?php _e('Restart Optimizing','shortpixel-image-optimiser');?>'>
391
+ <input type='submit' name='bulkRestore' id='bulkRestore' class='button' value='<?php _e('Bulk Restore Media Library','shortpixel-image-optimiser');?>' style="float: right;">
392
  </form>
393
  </div>
394
  <?php } ?>
492
  </script>
493
  </div>
494
  </div>
495
+ <?php if($running) {
496
+ if($type) { ?>
497
+ <div class="sp-h2"><?php
498
+ echo($type & 1 ? __('Media Library','shortpixel-image-optimiser') . " " : "");
499
+ echo($type & 3 == 3 ? __('and','shortpixel-image-optimiser') . " " : "");
500
+ echo($type & 2 ? __('Custom folders','shortpixel-image-optimiser') . " " : "");
501
+ _e('optimization in progress ...','shortpixel-image-optimiser');?></div>
502
+ <p style="margin: 0 0 18px;"><?php _e('Bulk optimization has started.','shortpixel-image-optimiser');?><br>
503
+ <?php
504
+ } else { // restore ?>
505
+ <div class="sp-h2"><?php
506
+ _e('Media Library restore in progress ...','shortpixel-image-optimiser');?></div>
507
+ <p style="margin: 0 0 18px;"><?php _e('Bulk restore has started.','shortpixel-image-optimiser');?><br>
508
+ <?php }
509
+ printf(__('This process will take some time, depending on the number of images in your library. In the meantime, you can continue using
510
  the admin as usual, <a href="%s" target="_blank">in a different browser window or tab</a>.<br>
511
  However, <strong>if you close this window, the bulk processing will pause</strong> until you open the media gallery or the ShortPixel bulk page again.','shortpixel-image-optimiser'), get_admin_url());?>
512
  </p>
717
  <td>
718
  <input type="radio" name="compressionType" value="1" <?php echo( $this->ctrl->getCompressionType() == 1 ? "checked" : "" );?>><?php
719
  _e('Lossy (recommended)','shortpixel-image-optimiser');?></br>
720
+ <p class="settings-info"><?php _e('<b>Lossy compression: </b>offers the best compression rate.</br> This is the recommended option for most users, producing results that look the same as the original to the human eye. You can run a test for free ','shortpixel-image-optimiser');?>
721
  <a href="https://shortpixel.com/online-image-compression" target="_blank"><?php _e('here','shortpixel-image-optimiser');?></a>.</p></br>
722
+ <input type="radio" name="compressionType" value="2" <?php echo( $this->ctrl->getCompressionType() == 2 ? "checked" : "" );?>><?php
723
+ _e('Glossy','shortpixel-image-optimiser');?></br>
724
+ <p class="settings-info"><?php _e('<b>Glossy compression: </b>creates images that are almost pixel-perfect identical to the originals.</br> Best option for photographers and other professionals that use very high quality images on their sites and want best compression while keeping the quality untouched.','shortpixel-image-optimiser');?>
725
+ </p></br>
726
+ <input type="radio" name="compressionType" value="0" <?php echo( $this->ctrl->getCompressionType() == 0 ? "checked" : "" );?>><?php
727
  _e('Lossless','shortpixel-image-optimiser');?>
728
  <p class="settings-info">
729
+ <?php _e('<b>Lossless compression: </b> the resulting image is pixel-identical with the original image.</br>Make sure not a single pixel looks different in the optimized image compared with the original.
730
+ In some rare cases you will need to use this type of compression. Some technical drawings or images from vector graphics are possible situations.','shortpixel-image-optimiser');?>
731
  </p>
732
  </td>
733
  </tr>
1054
  <th scope="row"><label for="totalFiles"><?php _e('Total number of processed files:','shortpixel-image-optimiser');?></label></th>
1055
  <td><?php echo($fileCount);?></td>
1056
  </tr>
1057
+ <?php if(true || $this->ctrl->backupImages()) { ?>
1058
  <tr>
1059
  <th scope="row"><label for="sizeBackup"><?php _e('Original images are stored in a backup folder. Your backup folder size is now:','shortpixel-image-optimiser');?></label></th>
1060
  <td>
1136
  . $missingThumbs;
1137
  }
1138
  $this->renderListCell($id, $data['showActions'],
1139
+ !$data['thumbsOpt'] && $data['thumbsTotal'], $data['thumbsTotal'], $data['backup'], $data['type'], $data['invType'], $successText);
1140
 
1141
  break;
1142
  }
1158
  .($retinasOpt ? '<br>' . sprintf(__('+%s Retina images optimized','shortpixel-image-optimiser') , $retinasOpt) : '' ) ;
1159
  }
1160
 
1161
+ public function renderListCell($id, $showActions, $optimizeThumbs, $thumbsTotal, $backup, $type, $invType, $message) {
1162
  if($showActions) { ?>
1163
  <div class='sp-column-actions'>
1164
  <?php if($optimizeThumbs) { ?>
1168
  <?php }
1169
  if($backup) {
1170
  if($type) {
1171
+ //$invType = $type == 'lossy' ? 'lossless' : 'lossy'; ?>
1172
  <a class='button button-smaller' href="javascript:reoptimize('<?php echo($id)?>', '<?php echo($invType)?>');"
1173
  title="<?php _e('Reoptimize from the backed-up image','shortpixel-image-optimiser');?>">
1174
  <?php _e('Re-optimize','shortpixel-image-optimiser');?> <?php echo($invType)?>
class/wp-short-pixel.php CHANGED
@@ -261,6 +261,7 @@ class WPShortPixel {
261
  WP_PLUGIN_URL: '<?php echo plugins_url( '', SHORTPIXEL_PLUGIN_FILE ); ?>',
262
  WP_ADMIN_URL: '<?php echo admin_url(); ?>',
263
  API_KEY: "<?php echo $this->_settings->apiKey; ?>",
 
264
  MEDIA_ALERT: '<?php echo $this->_settings->mediaAlert ? "done" : "todo"; ?>',
265
  FRONT_BOOTSTRAP: <?php echo $this->_settings->frontBootstrap && (!isset($this->_settings->lastBackAction) || (time() - $this->_settings->lastBackAction > 600)) ? 1 : 0; ?>,
266
  AJAX_URL: '<?php echo admin_url('admin-ajax.php'); ?>'
@@ -495,6 +496,48 @@ class WPShortPixel {
495
  $this->prioQ->push('C-' . $id);
496
  }
497
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
498
 
499
  //TODO muta in bulkProvider
500
  public function getBulkItemsFromDb(){
@@ -514,12 +557,14 @@ class WPShortPixel {
514
 
515
  self::log("GETDB: current StartID: " . $crtStartQueryID);
516
 
517
- $queryPostMeta = "SELECT * FROM " . $wpdb->prefix . "postmeta
518
  WHERE ( post_id <= $crtStartQueryID AND post_id >= $endQueryID )
519
  AND ( meta_key = '_wp_attached_file' OR meta_key = '_wp_attachment_metadata' )
520
  ORDER BY post_id DESC
521
  LIMIT " . SP_MAX_RESULTS_QUERY;
522
  $resultsPostMeta = $wpdb->get_results($queryPostMeta);
 
 
523
 
524
  if ( empty($resultsPostMeta) ) {
525
  $crtStartQueryID -= SP_MAX_RESULTS_QUERY;
@@ -585,13 +630,8 @@ class WPShortPixel {
585
  }
586
  return $items;
587
  }
588
-
589
- public function handleImageProcessing($ID = null) {
590
- //if(rand(1,2) == 2) {
591
- // header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error', true, 500);
592
- // die("za stop");
593
- //}
594
- //0: check key
595
  if( $this->_settings->verifiedKey == false) {
596
  if($ID == null){
597
  $ids = $this->getFromPrioAndCheck();
@@ -600,7 +640,30 @@ class WPShortPixel {
600
  $response = array("Status" => ShortPixelAPI::STATUS_NO_KEY, "ImageID" => $itemHandler ? $itemHandler->getId() : "-1", "Message" => __('Missing API Key','shortpixel-image-optimiser'));
601
  $this->_settings->bulkLastStatus = $response;
602
  die(json_encode($response));
603
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
604
 
605
  if($this->_settings->frontBootstrap && is_admin() && !ShortPixelTools::requestIsFrontendAjax()) {
606
  //if in backend, and front-end is activated, mark processing from backend to shut off the front-end for 10 min.
@@ -610,6 +673,20 @@ class WPShortPixel {
610
  self::log("HIP: 0 Priority Queue: ".json_encode($this->prioQ->get()));
611
  //self::log("HIP: 0 Bulk running? " . $this->prioQ->bulkRunning() . " START " . $this->_settings->startBulkId . " STOP " . $this->_settings->stopBulkId);
612
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
613
  //1: get 3 ids to process. Take them with priority from the queue
614
  $ids = $this->getFromPrioAndCheck();
615
  if(count($ids) < 3 ) { //take from bulk if bulk processing active
@@ -679,17 +756,7 @@ class WPShortPixel {
679
  //in this case the queue is really empty
680
  self::log("HIP: 1 STOP BULK");
681
  $bulkEverRan = $this->prioQ->stopBulk();
682
- $avg = $this->getAverageCompression();
683
- $fileCount = $this->_settings->fileCount;
684
- $response = array("Status" => self::BULK_EMPTY_QUEUE,
685
- /* translators: console message Empty queue 1234 -> 1234 */
686
- "Message" => __('Empty queue ','shortpixel-image-optimiser') . $this->prioQ->getStartBulkId() . '->' . $this->prioQ->getStopBulkId(),
687
- "BulkStatus" => ($this->prioQ->bulkRunning()
688
- ? "1" : ($this->prioQ->bulkPaused() ? "2" : "0")),
689
- "AverageCompression" => $avg,
690
- "FileCount" => $fileCount,
691
- "BulkPercent" => $this->prioQ->getBulkPercent());
692
- die(json_encode($response));
693
  }
694
 
695
  self::log("HIP: 2 Prio Queue: ".json_encode($this->prioQ->get()));
@@ -886,6 +953,7 @@ class WPShortPixel {
886
  $foundThumbs = WpShortPixelMediaLbraryAdapter::findThumbs($mainFile);
887
  //first identify which thumbs are not in the sizes
888
  $sizes = $meta->getThumbs();
 
889
  foreach($foundThumbs as $id => $found) {
890
  //get the mime-type from one of the thumbs metas
891
  foreach($sizes as $size) {
@@ -922,8 +990,10 @@ class WPShortPixel {
922
  }
923
 
924
  //find any missing thumbs files and mark them as such
 
 
925
  if( isset($URLsAndPATHs['sizesMissing']) && count($URLsAndPATHs['sizesMissing'])
926
- && (null === $meta->getThumbsMissing() || count(array_diff_key($meta->getThumbsMissing(), array_merge($URLsAndPATHs['sizesMissing'], $meta->getThumbsMissing()))))) {
927
  //fix missing thumbs in the metadata before sending to processing
928
  $meta->setThumbsMissing($URLsAndPATHs['sizesMissing']);
929
  $itemHandler->updateMeta();
@@ -972,7 +1042,7 @@ class WPShortPixel {
972
  if(self::isProcessable($imageId)) {
973
  $this->prioQ->push($imageId);
974
  $itemHandler = new ShortPixelMetaFacade($imageId);
975
- $path = get_attached_file($ID);//get the full file PATH
976
  if(!$manual && 'pdf' === pathinfo($path, PATHINFO_EXTENSION) && !$this->_settings->optimizePdfs) {
977
  $ret = array("Status" => ShortPixelAPI::STATUS_SKIP, "Message" => $imageId);
978
  } else {
@@ -1075,7 +1145,7 @@ class WPShortPixel {
1075
  }
1076
  $pathInfo = pathinfo($file);
1077
 
1078
- $bkFolder = $this->getBackupFolderAny($file, $meta["sizes"]);
1079
  $bkFile = trailingslashit($bkFolder) . ShortPixelAPI::MB_basename($file);
1080
 
1081
  //first check if the file is readable by the current user - otherwise it will be unaccessible for the web browser
@@ -1194,11 +1264,13 @@ class WPShortPixel {
1194
  }
1195
 
1196
  public function redo($qID, $type = false) {
 
 
1197
  if(ShortPixelMetaFacade::isCustomQueuedId($qID)) {
1198
  $ID = ShortPixelMetaFacade::stripQueuedIdType($qID);
1199
  $meta = $this->doCustomRestore($ID);
1200
  if($meta) {
1201
- $meta->setCompressionType(1 - $meta->getCompressionType());
1202
  $meta->setStatus(1);
1203
  $this->spMetaDao->update($meta);
1204
  $this->prioQ->push($qID);
@@ -1208,14 +1280,12 @@ class WPShortPixel {
1208
  }
1209
  } else {
1210
  $ID = intval($qID);
1211
- $compressionType = ($type == 'lossless' ? 'lossless' : 'lossy'); //sanity check
1212
-
1213
  $meta = $this->doRestore($ID);
1214
  if($meta) { //restore succeeded
1215
  $meta['ShortPixel'] = array("type" => $compressionType);
1216
  wp_update_attachment_metadata($ID, $meta);
1217
  try {
1218
- $this->sendToProcessing(new ShortPixelMetaFacade($ID), $compressionType == 'lossy' ? 1 : 0);
1219
  $this->prioQ->push($ID);
1220
  $ret = array("Status" => ShortPixelAPI::STATUS_SUCCESS, "Message" => "");
1221
  } catch(Exception $e) { // Exception("Post metadata is corrupt (No attachment URL)") or Exception("Image files are missing.")
@@ -1444,12 +1514,18 @@ class WPShortPixel {
1444
  $this->spMetaDao->resetFailed();
1445
  }
1446
 
1447
- $this->prioQ->startBulk();
1448
  $this->_settings->customBulkPaused = 0;
1449
  self::log("BULK: Start: " . $this->prioQ->getStartBulkId() . ", stop: " . $this->prioQ->getStopBulkId() . " PrioQ: "
1450
  .json_encode($this->prioQ->get()));
1451
  }//end bulk process was clicked
1452
 
 
 
 
 
 
 
1453
  if(isset($_POST["bulkProcessResume"]))
1454
  {
1455
  $this->prioQ->resumeBulk();
@@ -1476,7 +1552,7 @@ class WPShortPixel {
1476
  $msg = $this->bulkProgressMessage($this->prioQ->getDeltaBulkPercent(), $this->prioQ->getTimeRemaining());
1477
 
1478
  $this->view->displayBulkProcessingRunning($this->getPercent($quotaData), $msg, $quotaData['APICallsRemaining'], $this->getAverageCompression(),
1479
- ($pendingMeta !== null ? ($this->prioQ->bulkRunning() ? 3 : 2) : 1));
1480
 
1481
  } else
1482
  {
@@ -2090,6 +2166,7 @@ class WPShortPixel {
2090
  $renderData['bonus'] = ($data['ShortPixelImprovement'] < 5);
2091
  $renderData['backup'] = $this->getBackupFolderAny(get_attached_file($id), $sizesCount? $data['sizes'] : array());
2092
  $renderData['type'] = isset($data['ShortPixel']['type']) ? $data['ShortPixel']['type'] : '';
 
2093
  $renderData['thumbsTotal'] = $sizesCount;
2094
  $renderData['thumbsOpt'] = isset($data['ShortPixel']['thumbsOpt']) ? $data['ShortPixel']['thumbsOpt'] : $sizesCount;
2095
  $renderData['thumbsMissing'] = isset($data['ShortPixel']['thumbsMissing']) ? $data['ShortPixel']['thumbsMissing'] : array();
@@ -2382,8 +2459,19 @@ class WPShortPixel {
2382
  //'crop' => $_wp_additional_image_sizes[ $_size ]['crop']
2383
  }
2384
  }
2385
- return array('width' => $width, 'height' => $height);
2386
  }
 
 
 
 
 
 
 
 
 
 
 
2387
 
2388
  /* public function getEncryptedData() {
2389
  return base64_encode(self::encrypt($this->getApiKey() . "|" . get_site_url(), "sh0r+Pix3l8im1N3r"));
261
  WP_PLUGIN_URL: '<?php echo plugins_url( '', SHORTPIXEL_PLUGIN_FILE ); ?>',
262
  WP_ADMIN_URL: '<?php echo admin_url(); ?>',
263
  API_KEY: "<?php echo $this->_settings->apiKey; ?>",
264
+ DEFAULT_COMPRESSION: <?php echo $this->_settings->compressionType; ?>,
265
  MEDIA_ALERT: '<?php echo $this->_settings->mediaAlert ? "done" : "todo"; ?>',
266
  FRONT_BOOTSTRAP: <?php echo $this->_settings->frontBootstrap && (!isset($this->_settings->lastBackAction) || (time() - $this->_settings->lastBackAction > 600)) ? 1 : 0; ?>,
267
  AJAX_URL: '<?php echo admin_url('admin-ajax.php'); ?>'
496
  $this->prioQ->push('C-' . $id);
497
  }
498
  }
499
+
500
+ public function bulkRestore(){
501
+ global $wpdb, $MAX_EXECUTION_TIME;
502
+
503
+ $startQueryID = $crtStartQueryID = $this->prioQ->getStartBulkId();
504
+ $endQueryID = $this->prioQ->getStopBulkId();
505
+
506
+ if ( $startQueryID <= $endQueryID ) {
507
+ return false;
508
+ }
509
+
510
+ $startTime = time();
511
+ $maxTime = (is_numeric($MAX_EXECUTION_TIME) && $MAX_EXECUTION_TIME > 10 ? $MAX_EXECUTION_TIME - 5 : 25);
512
+ $maxResults = SP_MAX_RESULTS_QUERY * 2;
513
+ $restored = array();
514
+
515
+ //$ind = 0;
516
+ while( $crtStartQueryID >= $endQueryID && time() - $startTime < $maxTime) {
517
+ //if($ind > 1) break;
518
+ //$ind++;
519
+ $resultsPostMeta = WpShortPixelMediaLbraryAdapter::getPostMetaSlice($crtStartQueryID, $endQueryID, $maxResults);
520
+ if ( empty($resultsPostMeta) ) {
521
+ $crtStartQueryID -= $maxResults;
522
+ $startQueryID = $crtStartQueryID;
523
+ $this->prioQ->setStartBulkId($startQueryID);
524
+ continue;
525
+ }
526
+
527
+ foreach ( $resultsPostMeta as $itemMetaData ) {
528
+ $crtStartQueryID = $itemMetaData->post_id;
529
+ $item = new ShortPixelMetaFacade($crtStartQueryID);
530
+ $meta = $item->getMeta();//wp_get_attachment_metadata($crtStartQueryID);
531
+
532
+ if($meta->getStatus() == 2) {
533
+ $res = $this->doRestore($crtStartQueryID);
534
+ $restored[] = array('id' => $crtStartQueryID, 'status' => $res ? 'success' : 'fail');
535
+ }
536
+ }
537
+ }
538
+ $this->advanceBulk($crtStartQueryID);
539
+ return $restored;
540
+ }
541
 
542
  //TODO muta in bulkProvider
543
  public function getBulkItemsFromDb(){
557
 
558
  self::log("GETDB: current StartID: " . $crtStartQueryID);
559
 
560
+ /* $queryPostMeta = "SELECT * FROM " . $wpdb->prefix . "postmeta
561
  WHERE ( post_id <= $crtStartQueryID AND post_id >= $endQueryID )
562
  AND ( meta_key = '_wp_attached_file' OR meta_key = '_wp_attachment_metadata' )
563
  ORDER BY post_id DESC
564
  LIMIT " . SP_MAX_RESULTS_QUERY;
565
  $resultsPostMeta = $wpdb->get_results($queryPostMeta);
566
+ */
567
+ $resultsPostMeta = WpShortPixelMediaLbraryAdapter::getPostMetaSlice($crtStartQueryID, $endQueryID, SP_MAX_RESULTS_QUERY);
568
 
569
  if ( empty($resultsPostMeta) ) {
570
  $crtStartQueryID -= SP_MAX_RESULTS_QUERY;
630
  }
631
  return $items;
632
  }
633
+
634
+ private function checkKey($ID) {
 
 
 
 
 
635
  if( $this->_settings->verifiedKey == false) {
636
  if($ID == null){
637
  $ids = $this->getFromPrioAndCheck();
640
  $response = array("Status" => ShortPixelAPI::STATUS_NO_KEY, "ImageID" => $itemHandler ? $itemHandler->getId() : "-1", "Message" => __('Missing API Key','shortpixel-image-optimiser'));
641
  $this->_settings->bulkLastStatus = $response;
642
  die(json_encode($response));
643
+ }
644
+ }
645
+
646
+ private function sendEmptyQueue() {
647
+ $avg = $this->getAverageCompression();
648
+ $fileCount = $this->_settings->fileCount;
649
+ $response = array("Status" => self::BULK_EMPTY_QUEUE,
650
+ /* translators: console message Empty queue 1234 -> 1234 */
651
+ "Message" => __('Empty queue ','shortpixel-image-optimiser') . $this->prioQ->getStartBulkId() . '->' . $this->prioQ->getStopBulkId(),
652
+ "BulkStatus" => ($this->prioQ->bulkRunning()
653
+ ? "1" : ($this->prioQ->bulkPaused() ? "2" : "0")),
654
+ "AverageCompression" => $avg,
655
+ "FileCount" => $fileCount,
656
+ "BulkPercent" => $this->prioQ->getBulkPercent());
657
+ die(json_encode($response));
658
+ }
659
+
660
+ public function handleImageProcessing($ID = null) {
661
+ //if(rand(1,2) == 2) {
662
+ // header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error', true, 500);
663
+ // die("za stop");
664
+ //}
665
+ //0: check key
666
+ $this->checkKey($ID);
667
 
668
  if($this->_settings->frontBootstrap && is_admin() && !ShortPixelTools::requestIsFrontendAjax()) {
669
  //if in backend, and front-end is activated, mark processing from backend to shut off the front-end for 10 min.
673
  self::log("HIP: 0 Priority Queue: ".json_encode($this->prioQ->get()));
674
  //self::log("HIP: 0 Bulk running? " . $this->prioQ->bulkRunning() . " START " . $this->_settings->startBulkId . " STOP " . $this->_settings->stopBulkId);
675
 
676
+ //handle the bulk restore and cleanup first - these are fast operations taking precedece over optimization
677
+ if($this->prioQ->bulkRunning() && $this->prioQ->getBulkType() == ShortPixelQueue::BULK_TYPE_RESTORE) {
678
+ $res = $this->bulkRestore();
679
+ if($res === false) {
680
+ $this->sendEmptyQueue();
681
+ } else {
682
+ die(json_encode(array("Status" => ShortPixelAPI::STATUS_RETRY,
683
+ "Message" => __('Restoring images... ','shortpixel-image-optimiser') . $this->prioQ->getStartBulkId() . '->' . $this->prioQ->getStopBulkId(),
684
+ "BulkPercent" => $this->prioQ->getBulkPercent(),
685
+ "Restored" => $res )));
686
+ }
687
+
688
+ }
689
+
690
  //1: get 3 ids to process. Take them with priority from the queue
691
  $ids = $this->getFromPrioAndCheck();
692
  if(count($ids) < 3 ) { //take from bulk if bulk processing active
756
  //in this case the queue is really empty
757
  self::log("HIP: 1 STOP BULK");
758
  $bulkEverRan = $this->prioQ->stopBulk();
759
+ $this->sendEmptyQueue();
 
 
 
 
 
 
 
 
 
 
760
  }
761
 
762
  self::log("HIP: 2 Prio Queue: ".json_encode($this->prioQ->get()));
953
  $foundThumbs = WpShortPixelMediaLbraryAdapter::findThumbs($mainFile);
954
  //first identify which thumbs are not in the sizes
955
  $sizes = $meta->getThumbs();
956
+ $mimeType = false;
957
  foreach($foundThumbs as $id => $found) {
958
  //get the mime-type from one of the thumbs metas
959
  foreach($sizes as $size) {
990
  }
991
 
992
  //find any missing thumbs files and mark them as such
993
+ $miss = $meta->getThumbsMissing();
994
+ /* TODO remove */if(is_numeric($miss)) $miss = array();
995
  if( isset($URLsAndPATHs['sizesMissing']) && count($URLsAndPATHs['sizesMissing'])
996
+ && (null === $miss || count(array_diff_key($miss, array_merge($URLsAndPATHs['sizesMissing'], $miss))))) {
997
  //fix missing thumbs in the metadata before sending to processing
998
  $meta->setThumbsMissing($URLsAndPATHs['sizesMissing']);
999
  $itemHandler->updateMeta();
1042
  if(self::isProcessable($imageId)) {
1043
  $this->prioQ->push($imageId);
1044
  $itemHandler = new ShortPixelMetaFacade($imageId);
1045
+ $path = get_attached_file($imageId);//get the full file PATH
1046
  if(!$manual && 'pdf' === pathinfo($path, PATHINFO_EXTENSION) && !$this->_settings->optimizePdfs) {
1047
  $ret = array("Status" => ShortPixelAPI::STATUS_SKIP, "Message" => $imageId);
1048
  } else {
1145
  }
1146
  $pathInfo = pathinfo($file);
1147
 
1148
+ $bkFolder = $this->getBackupFolderAny($file, isset($meta["sizes"]) ? $meta["sizes"] : array());
1149
  $bkFile = trailingslashit($bkFolder) . ShortPixelAPI::MB_basename($file);
1150
 
1151
  //first check if the file is readable by the current user - otherwise it will be unaccessible for the web browser
1264
  }
1265
 
1266
  public function redo($qID, $type = false) {
1267
+ $compressionType = ($type == 'lossless' ? 'lossless' : ($type == 'glossy' ? 'glossy' : 'lossy')); //sanity check
1268
+
1269
  if(ShortPixelMetaFacade::isCustomQueuedId($qID)) {
1270
  $ID = ShortPixelMetaFacade::stripQueuedIdType($qID);
1271
  $meta = $this->doCustomRestore($ID);
1272
  if($meta) {
1273
+ $meta->setCompressionType(ShortPixelAPI::getCompressionTypeCode($compressionType));
1274
  $meta->setStatus(1);
1275
  $this->spMetaDao->update($meta);
1276
  $this->prioQ->push($qID);
1280
  }
1281
  } else {
1282
  $ID = intval($qID);
 
 
1283
  $meta = $this->doRestore($ID);
1284
  if($meta) { //restore succeeded
1285
  $meta['ShortPixel'] = array("type" => $compressionType);
1286
  wp_update_attachment_metadata($ID, $meta);
1287
  try {
1288
+ $this->sendToProcessing(new ShortPixelMetaFacade($ID), ShortPixelAPI::getCompressionTypeCode($compressionType));
1289
  $this->prioQ->push($ID);
1290
  $ret = array("Status" => ShortPixelAPI::STATUS_SUCCESS, "Message" => "");
1291
  } catch(Exception $e) { // Exception("Post metadata is corrupt (No attachment URL)") or Exception("Image files are missing.")
1514
  $this->spMetaDao->resetFailed();
1515
  }
1516
 
1517
+ $this->prioQ->startBulk(ShortPixelQueue::BULK_TYPE_OPTIMIZE);
1518
  $this->_settings->customBulkPaused = 0;
1519
  self::log("BULK: Start: " . $this->prioQ->getStartBulkId() . ", stop: " . $this->prioQ->getStopBulkId() . " PrioQ: "
1520
  .json_encode($this->prioQ->get()));
1521
  }//end bulk process was clicked
1522
 
1523
+ if(isset($_POST["bulkRestore"]))
1524
+ {
1525
+ $this->prioQ->startBulk(ShortPixelQueue::BULK_TYPE_RESTORE);
1526
+ $this->_settings->customBulkPaused = 0;
1527
+ }//end bulk restore was clicked
1528
+
1529
  if(isset($_POST["bulkProcessResume"]))
1530
  {
1531
  $this->prioQ->resumeBulk();
1552
  $msg = $this->bulkProgressMessage($this->prioQ->getDeltaBulkPercent(), $this->prioQ->getTimeRemaining());
1553
 
1554
  $this->view->displayBulkProcessingRunning($this->getPercent($quotaData), $msg, $quotaData['APICallsRemaining'], $this->getAverageCompression(),
1555
+ $this->prioQ->getBulkType() == ShortPixelQueue::BULK_TYPE_RESTORE ? 0 : ($pendingMeta !== null ? ($this->prioQ->bulkRunning() ? 3 : 2) : 1));
1556
 
1557
  } else
1558
  {
2166
  $renderData['bonus'] = ($data['ShortPixelImprovement'] < 5);
2167
  $renderData['backup'] = $this->getBackupFolderAny(get_attached_file($id), $sizesCount? $data['sizes'] : array());
2168
  $renderData['type'] = isset($data['ShortPixel']['type']) ? $data['ShortPixel']['type'] : '';
2169
+ $renderData['invType'] = ShortPixelAPI::getCompressionTypeName($this->getOtherCompressionType(ShortPixelAPI::getCompressionTypeCode($renderData['type'])));
2170
  $renderData['thumbsTotal'] = $sizesCount;
2171
  $renderData['thumbsOpt'] = isset($data['ShortPixel']['thumbsOpt']) ? $data['ShortPixel']['thumbsOpt'] : $sizesCount;
2172
  $renderData['thumbsMissing'] = isset($data['ShortPixel']['thumbsMissing']) ? $data['ShortPixel']['thumbsMissing'] : array();
2459
  //'crop' => $_wp_additional_image_sizes[ $_size ]['crop']
2460
  }
2461
  }
2462
+ return array('width' => max(100, $width), 'height' => max(100, $height));
2463
  }
2464
+
2465
+ public function getOtherCompressionType($compressionType = false) {
2466
+ $defCompType = 0 + $this->getCompressionType();
2467
+ if($compressionType === false) {
2468
+ return $defCompType == 1 ? 2 : $defCompType == 2 ? 0 : 1;
2469
+ }
2470
+ elseif($defCompType == 0 || $defCompType == 2) {
2471
+ return (0 + $compressionType == 0 ? 2 : 0);
2472
+ }
2473
+ return $compressionType == 1 ? 0 : 1;
2474
+ }
2475
 
2476
  /* public function getEncryptedData() {
2477
  return base64_encode(self::encrypt($this->getApiKey() . "|" . get_site_url(), "sh0r+Pix3l8im1N3r"));
class/wp-shortpixel-settings.php CHANGED
@@ -63,6 +63,7 @@ class WPShortPixelSettings {
63
  'redirectedSettings' => 'wp-short-pixel-redirected-settings',
64
 
65
  //bulk state machine
 
66
  'bulkLastStatus' => 'wp-short-pixel-bulk-last-status',
67
  'startBulkId' => 'wp-short-pixel-query-id-start',
68
  'stopBulkId' => 'wp-short-pixel-query-id-stop',
63
  'redirectedSettings' => 'wp-short-pixel-redirected-settings',
64
 
65
  //bulk state machine
66
+ 'bulkType' => 'wp-short-pixel-bulk-type',
67
  'bulkLastStatus' => 'wp-short-pixel-bulk-last-status',
68
  'startBulkId' => 'wp-short-pixel-query-id-start',
69
  'stopBulkId' => 'wp-short-pixel-query-id-stop',
readme.txt CHANGED
@@ -5,7 +5,7 @@ Tags: image optimizer, image optimization, compress pdf, compress jpeg, compress
5
 
6
  Requires at least: 3.2.0
7
  Tested up to: 4.7
8
- Stable tag: 4.2.9
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
@@ -13,7 +13,7 @@ Speed up your website and boost your SEO by compressing old & new images and PDF
13
 
14
  == Description ==
15
 
16
- **A freeemium easy to use, comprehensive, stable and frequently updated image optimization plugin supported by the friendly team that created it. :)**
17
 
18
  Increase your website's SEO ranking, number of visitors and ultimately your sales by optimizing any image or PDF document on your website.
19
  ShortPixel is an easy to use, lightweight, install-and-forget-about-it <a rel="friend" href="https://shortpixel.com" target="_blank">image optimization</a> plugin that can compress all your past images and PDF documents with a single click. New images are automatically resized/rescaled and optimized on the fly, in the background.
@@ -22,13 +22,15 @@ ShortPixel is an easy to use, lightweight, install-and-forget-about-it <a rel="f
22
 
23
  This plugin uses minimal resources and works well with any shared, cloud, VPS or dedicated web hosting. It can optimize any image you have on your website even the images that aren't listed in Media Library like those in galleries like NextGEN or added directly via FTP!
24
 
25
- Both lossy and lossless image compression is available for the most common image types (JPG, PNG, GIF and WebP) plus PDF files. Optimized images mean better user experience, better PageSpeed Insights or GTmetrix results, better Google PageRank and more visitors.
 
 
26
 
27
  Make an instant <a rel="friend" href="http://shortpixel.com/image-compression-test" target="_blank">image compression test</a> on your site or <a rel="friend" href="http://shortpixel.com/online-image-compression" target="_blank">compress some images</a> to make sure they are to your liking.
28
 
29
  **Why is ShortPixel the best choice when it comes to image optimization or PDF compression?**
30
 
31
- * popular plugin with over 30,000 active installations according to WordPress
32
  * compress JPG, PNG, GIF (still or animated) images and also PDF documents
33
  * no file size limit
34
  * option to freely convert any JPEG, PNG or GIF (even animated ones!) to **WebP** for more Google love. <a rel="friend" href="http://blog.shortpixel.com/how-webp-images-can-speed-up-your-site/" target="_blank">How to enable WebP?</a>
@@ -42,7 +44,7 @@ Make an instant <a rel="friend" href="http://shortpixel.com/image-compression-te
42
  * **great for photographers**: <a rel="friend" href="http://blog.shortpixel.com/how-much-smaller-can-be-images-without-exif-icc/" target="_blank">keep or remove EXIF</a> data from your images, compress images with lossless option
43
  * works well with both HTTPS and HTTP websites
44
  * you can run ShortPixel plugin on **multiple websites** or on a **multisite** with a **single API Key**
45
- * it is **safe to test** and use the plugin: all the original images can be restored with a click
46
  * 'Bulk' optimize all the existing images in Media Library or in any gallery with one click
47
  * works great for **eCommerce websites using WooCommerce** or other plugins
48
  * works great with NextGEN gallery, Foo Gallery and any other galleries and sliders
@@ -118,7 +120,7 @@ Let's get ShortPixel plugin running on your WordPress website:
118
 
119
  = Can I restore my images? What happens with the originals? =
120
  If you choose the "Image backup" option in Settings/ShortPixel then the original version of any optimized image or PDF will be saved in the backup folder.
121
- The original image is necessary if you want to restore an image or if you want to convert an image from lossy to lossless or viceversa.
122
 
123
  = What types of formats can be optimized? =
124
  ShortPixel optimizes JPEG, PNG, GIF and PDF type of files.
@@ -217,6 +219,13 @@ The ShortPixel team is here to help. <a href="https://shortpixel.com/contact">Co
217
 
218
  == Changelog ==
219
 
 
 
 
 
 
 
 
220
  = 4.2.9 =
221
 
222
  * fix bug when thumbnails had numeric indexes in the sizes metadata array
5
 
6
  Requires at least: 3.2.0
7
  Tested up to: 4.7
8
+ Stable tag: 4.3.0
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
13
 
14
  == Description ==
15
 
16
+ **A freeemium easy to use, comprehensive, stable and frequently updated image compression plugin supported by the friendly team that created it. :)**
17
 
18
  Increase your website's SEO ranking, number of visitors and ultimately your sales by optimizing any image or PDF document on your website.
19
  ShortPixel is an easy to use, lightweight, install-and-forget-about-it <a rel="friend" href="https://shortpixel.com" target="_blank">image optimization</a> plugin that can compress all your past images and PDF documents with a single click. New images are automatically resized/rescaled and optimized on the fly, in the background.
22
 
23
  This plugin uses minimal resources and works well with any shared, cloud, VPS or dedicated web hosting. It can optimize any image you have on your website even the images that aren't listed in Media Library like those in galleries like NextGEN or added directly via FTP!
24
 
25
+ Both lossy and lossless image compression is available for the most common image types (JPG, PNG, GIF and WebP) plus PDF files.
26
+ We also offer **glossy** JPEG compression which is a very high quality lossy optimization algorithm. Specially designed for photographers!
27
+ Optimized images mean better user experience, better PageSpeed Insights or GTmetrix results, better Google PageRank and more visitors.
28
 
29
  Make an instant <a rel="friend" href="http://shortpixel.com/image-compression-test" target="_blank">image compression test</a> on your site or <a rel="friend" href="http://shortpixel.com/online-image-compression" target="_blank">compress some images</a> to make sure they are to your liking.
30
 
31
  **Why is ShortPixel the best choice when it comes to image optimization or PDF compression?**
32
 
33
+ * popular plugin with over 40,000 active installations according to WordPress
34
  * compress JPG, PNG, GIF (still or animated) images and also PDF documents
35
  * no file size limit
36
  * option to freely convert any JPEG, PNG or GIF (even animated ones!) to **WebP** for more Google love. <a rel="friend" href="http://blog.shortpixel.com/how-webp-images-can-speed-up-your-site/" target="_blank">How to enable WebP?</a>
44
  * **great for photographers**: <a rel="friend" href="http://blog.shortpixel.com/how-much-smaller-can-be-images-without-exif-icc/" target="_blank">keep or remove EXIF</a> data from your images, compress images with lossless option
45
  * works well with both HTTPS and HTTP websites
46
  * you can run ShortPixel plugin on **multiple websites** or on a **multisite** with a **single API Key**
47
+ * it is **safe to test** and use the plugin: all the original images can be restored with a click, either one by one or in bulk
48
  * 'Bulk' optimize all the existing images in Media Library or in any gallery with one click
49
  * works great for **eCommerce websites using WooCommerce** or other plugins
50
  * works great with NextGEN gallery, Foo Gallery and any other galleries and sliders
120
 
121
  = Can I restore my images? What happens with the originals? =
122
  If you choose the "Image backup" option in Settings/ShortPixel then the original version of any optimized image or PDF will be saved in the backup folder.
123
+ The original image is necessary if you want to restore an image or if you want to convert an image from lossy/glossy to lossless or viceversa.
124
 
125
  = What types of formats can be optimized? =
126
  ShortPixel optimizes JPEG, PNG, GIF and PDF type of files.
219
 
220
  == Changelog ==
221
 
222
+ = 4.3.0 =
223
+
224
+ * a new level of optimization intermediate between lossy and lossless: glossy
225
+ * bulk restore for Media Library
226
+ * fix warning when activating plugin in some situations
227
+ * empty backups button always visible (also when the backup option is unchecked)
228
+
229
  = 4.2.9 =
230
 
231
  * fix bug when thumbnails had numeric indexes in the sizes metadata array
res/js/short-pixel.js CHANGED
@@ -191,7 +191,17 @@ var ShortPixel = function() {
191
 
192
  function successActions(id, type, thumbsCount, thumbsTotal, backupEnabled) {
193
  if(backupEnabled == 1) {
194
- var otherType = type.length > 0 ? (type == "lossy" ? "lossless" : "lossy") : "";
 
 
 
 
 
 
 
 
 
 
195
  return '<div class="sp-column-actions">'
196
  + (thumbsTotal > thumbsCount ? "<a class='button button-smaller button-primary' href=\"javascript:optimizeThumbs(" + id + ");\">"
197
  + _spTr.optXThumbs.format(thumbsTotal - thumbsCount) + "</a>" : "")
@@ -583,7 +593,8 @@ function checkBulkProcessingCallApi(){
583
  : ShortPixel.successActions(id, data["Type"], data['ThumbsCount'], data['ThumbsTotal'], data["BackupEnabled"]);
584
 
585
  setCellMessage(id, ShortPixel.successMsg(id, percent, data["Type"], data['ThumbsCount'], data['RetinasCount']), successActions);
586
- ShortPixel.otherMediaUpdateActions(id, ['restore','redo'+(data["Type"] == 'lossy' ? 'lossless': 'lossy'),'view']);
 
587
  var animator = new PercentageAnimator("#sp-msg-" + id + " span.percent", percent);
588
  animator.animate(percent);
589
  if(isBulkPage && typeof data["Thumb"] !== 'undefined') { // && data["PercentImprovement"] > 0) {
191
 
192
  function successActions(id, type, thumbsCount, thumbsTotal, backupEnabled) {
193
  if(backupEnabled == 1) {
194
+
195
+ var otherType;
196
+ if(type.length == 0) {
197
+ otherType = ShortPixel.DEFAULT_COMPRESSION == 1 ? 'glossy' : ShortPixel.DEFAULT_COMPRESSION == 2 ? 'lossless' : 'lossy';
198
+ }
199
+ else if(ShortPixel.DEFAULT_COMPRESSION == 0 || ShortPixel.DEFAULT_COMPRESSION == 2) {
200
+ otherType = (type == 'lossless' ? 'glossy' : 'lossless');
201
+ }
202
+ else otherType = (type == 'lossy' ? 'lossless' : 'lossy');
203
+
204
+
205
  return '<div class="sp-column-actions">'
206
  + (thumbsTotal > thumbsCount ? "<a class='button button-smaller button-primary' href=\"javascript:optimizeThumbs(" + id + ");\">"
207
  + _spTr.optXThumbs.format(thumbsTotal - thumbsCount) + "</a>" : "")
593
  : ShortPixel.successActions(id, data["Type"], data['ThumbsCount'], data['ThumbsTotal'], data["BackupEnabled"]);
594
 
595
  setCellMessage(id, ShortPixel.successMsg(id, percent, data["Type"], data['ThumbsCount'], data['RetinasCount']), successActions);
596
+ var actions = jQuery(['restore', 'view', 'redolossy', 'redoglossy', 'redolossless']).not(['redo'+data["Type"]]).get();
597
+ ShortPixel.otherMediaUpdateActions(id, actions);
598
  var animator = new PercentageAnimator("#sp-msg-" + id + " span.percent", percent);
599
  animator.animate(percent);
600
  if(isBulkPage && typeof data["Thumb"] !== 'undefined') { // && data["PercentImprovement"] > 0) {
shortpixel_api.php CHANGED
@@ -39,7 +39,7 @@ class ShortPixelAPI {
39
  * @param array $URLs - list of urls to send to API
40
  * @param Boolean $Blocking - true means it will wait for an answer
41
  * @param ShortPixelMetaFacade $itemHandler - the Facade that manages different types of image metadatas: MediaLibrary (postmeta table), ShortPixel custom (shortpixel_meta table)
42
- * @param int $compressionType 1 - lossy, 0 - lossless
43
  * @return response from wp_remote_post or error
44
  */
45
  public function doRequests($URLs, $Blocking, $itemHandler, $compressionType = false, $refresh = false) {
@@ -297,7 +297,7 @@ class ShortPixelAPI {
297
  /**
298
  * handles the download of an optimized image from ShortPixel API
299
  * @param type $fileData - info about the file
300
- * @param int $compressionType - 1 - lossy, 0 - lossless
301
  * @return status/message array
302
  */
303
  private function handleDownload($fileData, $compressionType){
@@ -372,7 +372,7 @@ class ShortPixelAPI {
372
  * @param type $APIresponse - the response from the API - contains the optimized images URLs to download
373
  * @param type $PATHs - list of local paths for the files
374
  * @param ShortPixelMetaFacade $itemHandler - the Facade that manages different types of image metadatas: MediaLibrary (postmeta table), ShortPixel custom (shortpixel_meta table)
375
- * @param int $compressionType - 1 - lossy, 0 - lossless
376
  * @return status/message array
377
  */
378
  private function handleSuccess($APIresponse, $PATHs, $itemHandler, $compressionType) {
@@ -520,10 +520,13 @@ class ShortPixelAPI {
520
  if(file_exists($tempWebpFilePATH)) {
521
  $targetWebPFile = dirname($targetFile) . '/' . basename($targetFile, '.' . pathinfo($targetFile, PATHINFO_EXTENSION)) . ".webp";
522
  copy($tempWebpFilePATH, $targetWebPFile);
 
 
523
  $webpSize = $itemHandler->getWebpSizeMeta($targetFile);
524
  if($webpSize) {
525
  $webpSizes[$webpSize['key']] = $webpSize['val'];
526
  }
 
527
  }
528
  @unlink($tempWebpFilePATH);
529
  }
@@ -641,7 +644,11 @@ class ShortPixelAPI {
641
  }
642
 
643
  static public function getCompressionTypeName($compressionType) {
644
- return $compressionType == 1 ? 'lossy' : 'lossless';
 
 
 
 
645
  }
646
 
647
  static private function SaveMessageinMetadata($ID, $Message)
39
  * @param array $URLs - list of urls to send to API
40
  * @param Boolean $Blocking - true means it will wait for an answer
41
  * @param ShortPixelMetaFacade $itemHandler - the Facade that manages different types of image metadatas: MediaLibrary (postmeta table), ShortPixel custom (shortpixel_meta table)
42
+ * @param int $compressionType 1 - lossy, 2 - glossy, 0 - lossless
43
  * @return response from wp_remote_post or error
44
  */
45
  public function doRequests($URLs, $Blocking, $itemHandler, $compressionType = false, $refresh = false) {
297
  /**
298
  * handles the download of an optimized image from ShortPixel API
299
  * @param type $fileData - info about the file
300
+ * @param int $compressionType - 1 - lossy, 2 - glossy, 0 - lossless
301
  * @return status/message array
302
  */
303
  private function handleDownload($fileData, $compressionType){
372
  * @param type $APIresponse - the response from the API - contains the optimized images URLs to download
373
  * @param type $PATHs - list of local paths for the files
374
  * @param ShortPixelMetaFacade $itemHandler - the Facade that manages different types of image metadatas: MediaLibrary (postmeta table), ShortPixel custom (shortpixel_meta table)
375
+ * @param int $compressionType - 1 - lossy, 2 - glossy, 0 - lossless
376
  * @return status/message array
377
  */
378
  private function handleSuccess($APIresponse, $PATHs, $itemHandler, $compressionType) {
520
  if(file_exists($tempWebpFilePATH)) {
521
  $targetWebPFile = dirname($targetFile) . '/' . basename($targetFile, '.' . pathinfo($targetFile, PATHINFO_EXTENSION)) . ".webp";
522
  copy($tempWebpFilePATH, $targetWebPFile);
523
+
524
+ /* the webp thumbnails in metadata sizes is not working so deactivate for now
525
  $webpSize = $itemHandler->getWebpSizeMeta($targetFile);
526
  if($webpSize) {
527
  $webpSizes[$webpSize['key']] = $webpSize['val'];
528
  }
529
+ */
530
  }
531
  @unlink($tempWebpFilePATH);
532
  }
644
  }
645
 
646
  static public function getCompressionTypeName($compressionType) {
647
+ return 0 + $compressionType == 2 ? 'glossy' : (0 + $compressionType == 1 ? 'lossy' : 'lossless');
648
+ }
649
+
650
+ static public function getCompressionTypeCode($compressionName) {
651
+ return $compressionName == 'glossy' ? 2 : ($compressionName == 'lossy' ? 1 : 0);
652
  }
653
 
654
  static private function SaveMessageinMetadata($ID, $Message)
wp-shortpixel.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: ShortPixel Image Optimizer
4
  * Plugin URI: https://shortpixel.com/
5
  * Description: ShortPixel optimizes images automatically, while guarding the quality of your images. Check your <a href="options-general.php?page=wp-shortpixel" target="_blank">Settings &gt; ShortPixel</a> page on how to start optimizing your image library and make your website load faster.
6
- * Version: 4.2.9
7
  * Author: ShortPixel
8
  * Author URI: https://shortpixel.com
9
  * Text Domain: shortpixel-image-optimiser
@@ -11,14 +11,13 @@
11
  */
12
 
13
  define('SP_RESET_ON_ACTIVATE', false); //if true TODO set false
14
-
15
  //define('SHORTPIXEL_DEBUG', true);
16
 
17
  define('SHORTPIXEL_PLUGIN_FILE', __FILE__);
18
 
19
  define('SP_AFFILIATE_CODE', '');
20
 
21
- define('PLUGIN_VERSION', "4.2.9");
22
  define('SP_MAX_TIMEOUT', 10);
23
  define('SP_VALIDATE_MAX_TIMEOUT', 15);
24
  define('SP_BACKUP', 'ShortpixelBackups');
@@ -84,6 +83,16 @@ function shortpixelNggAdd($image) {
84
  $pluginInstance->handleNextGenImageUpload($image);
85
  }
86
 
 
 
 
 
 
 
 
 
 
 
87
  if ( !function_exists( 'vc_action' ) || vc_action() !== 'vc_inline' ) { //handle incompatibility with Visual Composer
88
  add_action( 'init', 'shortpixelInit');
89
  add_action('ngg_added_new_image', 'shortpixelNggAdd');
@@ -93,8 +102,8 @@ if ( !function_exists( 'vc_action' ) || vc_action() !== 'vc_inline' ) { //handle
93
  add_filter( 'wp_generate_attachment_metadata', 'handleImageUploadHook', 10, 2 );
94
  }
95
 
96
- register_activation_hook( __FILE__, array( 'WPShortPixel', 'shortPixelActivatePlugin' ) );
97
- register_deactivation_hook( __FILE__, array( 'WPShortPixel', 'shortPixelDeactivatePlugin' ) );
98
 
99
  }
100
  ?>
3
  * Plugin Name: ShortPixel Image Optimizer
4
  * Plugin URI: https://shortpixel.com/
5
  * Description: ShortPixel optimizes images automatically, while guarding the quality of your images. Check your <a href="options-general.php?page=wp-shortpixel" target="_blank">Settings &gt; ShortPixel</a> page on how to start optimizing your image library and make your website load faster.
6
+ * Version: 4.3.0
7
  * Author: ShortPixel
8
  * Author URI: https://shortpixel.com
9
  * Text Domain: shortpixel-image-optimiser
11
  */
12
 
13
  define('SP_RESET_ON_ACTIVATE', false); //if true TODO set false
 
14
  //define('SHORTPIXEL_DEBUG', true);
15
 
16
  define('SHORTPIXEL_PLUGIN_FILE', __FILE__);
17
 
18
  define('SP_AFFILIATE_CODE', '');
19
 
20
+ define('PLUGIN_VERSION', "4.3.0");
21
  define('SP_MAX_TIMEOUT', 10);
22
  define('SP_VALIDATE_MAX_TIMEOUT', 15);
23
  define('SP_BACKUP', 'ShortpixelBackups');
83
  $pluginInstance->handleNextGenImageUpload($image);
84
  }
85
 
86
+ function shortPixelActivatePlugin () {
87
+ require_once('wp-shortpixel-req.php');
88
+ WPShortPixel::shortPixelActivatePlugin();
89
+ }
90
+
91
+ function shortPixelDeactivatePlugin () {
92
+ require_once('wp-shortpixel-req.php');
93
+ WPShortPixel::shortPixelDeactivatePlugin();
94
+ }
95
+
96
  if ( !function_exists( 'vc_action' ) || vc_action() !== 'vc_inline' ) { //handle incompatibility with Visual Composer
97
  add_action( 'init', 'shortpixelInit');
98
  add_action('ngg_added_new_image', 'shortpixelNggAdd');
102
  add_filter( 'wp_generate_attachment_metadata', 'handleImageUploadHook', 10, 2 );
103
  }
104
 
105
+ register_activation_hook( __FILE__, 'shortPixelActivatePlugin' );
106
+ register_deactivation_hook( __FILE__, 'shortPixelDeactivatePlugin' );
107
 
108
  }
109
  ?>