ShortPixel Image Optimizer - Version 3.1.2

Version Description

  • bulk runs now only on media and post pages
  • settings page redesign
  • client site access test from our servers when activating the API key and warn if site not accessible
  • fix last image sometimes unprocessed by bulk
  • fix progress bar to advance when skipping images
Download this release

Release Info

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

Code changes from version 3.1.1 to 3.1.2

css/short-pixel.css CHANGED
@@ -132,3 +132,88 @@ p.settings-info {
132
  color: #818181;
133
  font-size:13px;
134
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  color: #818181;
133
  font-size:13px;
134
  }
135
+
136
+ /* TABS CONTROLS */
137
+ article.tabs {
138
+ position: relative;
139
+ display: block;
140
+ width: 100%;
141
+ height: 900px;
142
+ margin: 2em auto;
143
+ }
144
+ article.tabs section {
145
+ position: absolute;
146
+ display: block;
147
+ top: 1.8em;
148
+ left: 0;
149
+ height: 900px;
150
+ width:94%;
151
+ padding: 10px 20px;
152
+ background-color: #ddd;
153
+ /* border-radius: 5px; */
154
+ box-shadow: 0 3px 3px rgba(0,0,0,0.1);
155
+ z-index: 0;
156
+ }
157
+ article.tabs section:first-child {
158
+ z-index: 1;
159
+ }
160
+ article.tabs section h2 {
161
+ position: absolute;
162
+ font-size: 1.3em;
163
+ font-weight: normal;
164
+ width: 180px;
165
+ height: 1.8em;
166
+ top: -1.8em;
167
+ left: 10px;
168
+ padding: 0;
169
+ margin: 0;
170
+ color: #999;
171
+ background-color: #ddd;
172
+ /* border-radius: 5px 5px 0 0; */
173
+ }
174
+ article.tabs section:nth-child(2) h2 {
175
+ left: 192px;
176
+ }
177
+ article.tabs section:nth-child(3) h2 {
178
+ left: 374px;
179
+ }
180
+ article.tabs section h2 a {
181
+ display: block;
182
+ width: 100%;
183
+ line-height: 1.8em;
184
+ text-align: center;
185
+ text-decoration: none;
186
+ color: inherit;
187
+ outline: 0 none;
188
+ }
189
+ article.tabs section h2 a:focus,
190
+ article.tabs section#tab-resources a:focus {
191
+ box-shadow: none;
192
+ outline: none;
193
+ }
194
+ article.tabs section.sel-tab,
195
+ article.tabs section.sel-tab h2 {
196
+ color: #333;
197
+ background-color: #fff;
198
+ z-index: 2;
199
+ }
200
+ /*article.tabs section,
201
+ article.tabs section h2 {
202
+ -webkit-transition: all 500ms ease;
203
+ -moz-transition: all 500ms ease;
204
+ -ms-transition: all 500ms ease;
205
+ -o-transition: all 500ms ease;
206
+ transition: all 500ms ease;
207
+ }
208
+ */
209
+ /* Resources */
210
+ section#tab-resources .col-md-6 {
211
+ display: inline-block;
212
+ width: 45%;
213
+ }
214
+ section#tab-resources .text-center {
215
+ text-align: center;
216
+ }
217
+ section#tab-resources p {
218
+ font-size: 16px;
219
+ }
js/short-pixel.js CHANGED
@@ -78,6 +78,25 @@ function checkQuotaExceededAlert() {
78
  * calls itself until receives an Empty queue message
79
  */
80
  function checkBulkProgress() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  //if I'm not the bulk processor, check every 20 sec. if the bulk processor is running, otherwise take the role
82
  if(ShortPixel.bulkProcessor == true || typeof localStorage.bulkTime == 'undefined' || Math.floor(Date.now() / 1000) - localStorage.bulkTime > 90) {
83
  ShortPixel.bulkProcessor = true;
@@ -128,6 +147,7 @@ function checkBulkProcessingCallApi(){
128
  setCellMessage(id, data["Message"]);
129
  if(isBulkPage) {
130
  showToolBarAlert(ShortPixel.STATUS_FAIL, data["Message"]);
 
131
  }
132
  console.log(data["Message"]);
133
  setTimeout(checkBulkProgress, 5000);
@@ -167,6 +187,9 @@ function checkBulkProcessingCallApi(){
167
  case ShortPixel.STATUS_ERROR: //for error and skip also we retry
168
  case ShortPixel.STATUS_SKIP:
169
  console.log('Server response: ' + response);
 
 
 
170
  setTimeout(checkBulkProgress, 5000);
171
  break;
172
  }
@@ -177,6 +200,9 @@ function checkBulkProcessingCallApi(){
177
  function clearBulkProcessor(){
178
  ShortPixel.bulkProcessor = false; //nothing to process, leave the role. Next page load will check again
179
  localStorage.bulkTime = 0;
 
 
 
180
  }
181
 
182
  function setCellMessage(id, message){
78
  * calls itself until receives an Empty queue message
79
  */
80
  function checkBulkProgress() {
81
+ if( window.location.href.search("wp-admin/upload.php") < 0
82
+ && window.location.href.search("wp-admin/edit.php") < 0
83
+ && window.location.href.search("wp-admin/edit-tags.php") < 0
84
+ && window.location.href.search("wp-admin/post-new.php") < 0
85
+ && window.location.href.search("wp-admin/post.php") < 0) return;
86
+
87
+ //if i'm the bulk processor and i'm not the bulk page and a bulk page comes around, leave the bulk processor role
88
+ if(ShortPixel.bulkProcessor == true && window.location.href.search("wp-short-pixel-bulk") < 0
89
+ && typeof localStorage.bulkPage !== 'undefined' && localStorage.bulkPage > 0) {
90
+ ShortPixel.bulkProcessor = false;
91
+ }
92
+
93
+ //if i'm the bulk page, steal the bulk processor
94
+ if( window.location.href.search("wp-short-pixel-bulk") >= 0 ) {
95
+ ShortPixel.bulkProcessor = true;
96
+ localStorage.bulkTime = Math.floor(Date.now() / 1000);
97
+ localStorage.bulkPage = 1;
98
+ }
99
+
100
  //if I'm not the bulk processor, check every 20 sec. if the bulk processor is running, otherwise take the role
101
  if(ShortPixel.bulkProcessor == true || typeof localStorage.bulkTime == 'undefined' || Math.floor(Date.now() / 1000) - localStorage.bulkTime > 90) {
102
  ShortPixel.bulkProcessor = true;
147
  setCellMessage(id, data["Message"]);
148
  if(isBulkPage) {
149
  showToolBarAlert(ShortPixel.STATUS_FAIL, data["Message"]);
150
+ progressUpdate(data["BulkPercent"], data["BulkMsg"]);
151
  }
152
  console.log(data["Message"]);
153
  setTimeout(checkBulkProgress, 5000);
187
  case ShortPixel.STATUS_ERROR: //for error and skip also we retry
188
  case ShortPixel.STATUS_SKIP:
189
  console.log('Server response: ' + response);
190
+ if(isBulkPage && typeof data["BulkPercent"] !== 'undefined') {
191
+ progressUpdate(data["BulkPercent"], data["BulkMsg"]);
192
+ }
193
  setTimeout(checkBulkProgress, 5000);
194
  break;
195
  }
200
  function clearBulkProcessor(){
201
  ShortPixel.bulkProcessor = false; //nothing to process, leave the role. Next page load will check again
202
  localStorage.bulkTime = 0;
203
+ if(window.location.href.search("wp-short-pixel-bulk") >= 0) {
204
+ localStorage.bulkPage = 0;
205
+ }
206
  }
207
 
208
  function setCellMessage(id, message){
readme.txt CHANGED
@@ -5,7 +5,7 @@ Tags: picture, optimization, image editor, pngout, upload speed, shortpixel, co
5
 
6
  Requires at least: 3.0.1
7
  Tested up to: 4.3
8
- Stable tag: 3.1.1
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
@@ -25,6 +25,7 @@ Both new and old images can be optimized with ShortPixel. Once activated, the pl
25
 
26
  * all types of image formats PNG, JPG, GIF (still and animated) and PDF
27
  * thumbnails and featured images are also optimized
 
28
  * free 100 image credits/month. Images that are optimized less that 5% are bonus
29
  * no file size limit
30
  * originals are saved in a backup folder and can be manually restored
@@ -41,6 +42,8 @@ Both monthly subscriptions and one-time plans are available. The same plan can b
41
 
42
  We believe in a better society, so we support educational non-profits. <a href="http://shortpixel.com/contact">Contact us</a> and we’ll see how we can help!
43
 
 
 
44
 
45
  **Why use ShortPixel to optimize you images?**
46
 
@@ -55,18 +58,17 @@ Read more about how <a href="http://googlewebmastercentral.blogspot.ro/2010/04/u
55
 
56
  **New features coming soon:**
57
 
58
- * Affiliate system
59
  * support for NextGen Galley
60
  * mass restore for backed-up images
61
 
62
 
63
  **Get in touch!**
64
 
65
- Website <a href="https://shortpixel.com">https://shortpixel.com</a>
66
- Twitter <a href="https://twitter.com/shortpixel">https://twitter.com/shortpixel</a>
67
- Google+ <a href="https://www.google.com/+Shortpixelpage">https://www.google.com/+Shortpixelpage</a>
68
- Facebook <a href="https://www.facebook.com/ShortPixel">https://www.facebook.com/ShortPixel</a>
69
- LinkedIn <a href="https://www.linkedin.com/company/shortpixel">https://www.linkedin.com/company/shortpixel</a>
70
 
71
 
72
  == Installation ==
@@ -134,7 +136,13 @@ Yes, privacy is guaranteed. The ShortPixel encryption process doesn't allow anyo
134
 
135
  = What happens with my original images after they have been processed with ShortPixel? =
136
 
137
- Your images are automatically stored in a backup folder, on your hosting server. After optimization, if you want to switch back to a certain original image, hit **Restore backup** in the Media Library. If you are happy with the ShortPixel optimized images, you can deactivate saving the backups in the plugin Settings.
 
 
 
 
 
 
138
 
139
  = What types of formats can be optimized? =
140
 
@@ -160,10 +168,18 @@ The ShortPixel team is here to help. <a href="https://shortpixel.com/contact">Co
160
 
161
  == Changelog ==
162
 
 
 
 
 
 
 
 
 
163
  = 3.1.1 =
164
 
165
- * fix calculation of displayed images to be processed counters on bulk start
166
- * restore option appeared wrongly sometimes - thanks to Bogdan Günther @ http://medianotions.de
167
 
168
  = 3.1.0 =
169
 
5
 
6
  Requires at least: 3.0.1
7
  Tested up to: 4.3
8
+ Stable tag: 3.1.2
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
25
 
26
  * all types of image formats PNG, JPG, GIF (still and animated) and PDF
27
  * thumbnails and featured images are also optimized
28
+ * CMYK to RGB conversion
29
  * free 100 image credits/month. Images that are optimized less that 5% are bonus
30
  * no file size limit
31
  * originals are saved in a backup folder and can be manually restored
42
 
43
  We believe in a better society, so we support educational non-profits. <a href="http://shortpixel.com/contact">Contact us</a> and we’ll see how we can help!
44
 
45
+ Help us spread a the word by recommending ShortPixel to your friends and collect 100 additional image credits for each referred sign up.
46
+ Make money by promoting a great plugin with our <a href="https://shortpixel.com/free-sign-up-affiliate">50/50 affiliate program</a>.
47
 
48
  **Why use ShortPixel to optimize you images?**
49
 
58
 
59
  **New features coming soon:**
60
 
 
61
  * support for NextGen Galley
62
  * mass restore for backed-up images
63
 
64
 
65
  **Get in touch!**
66
 
67
+ * Email <a href="https://shortpixel.com/contact">https://shortpixel.com/contact</a>
68
+ * Twitter <a href="https://twitter.com/shortpixel">https://twitter.com/shortpixel</a>
69
+ * Google+ <a href="https://www.google.com/+Shortpixelpage">https://www.google.com/+Shortpixelpage</a>
70
+ * Facebook <a href="https://www.facebook.com/ShortPixel">https://www.facebook.com/ShortPixel</a>
71
+ * LinkedIn <a href="https://www.linkedin.com/company/shortpixel">https://www.linkedin.com/company/shortpixel</a>
72
 
73
 
74
  == Installation ==
136
 
137
  = What happens with my original images after they have been processed with ShortPixel? =
138
 
139
+ If you didn't make any changes in the plugin Settings and you left the 'Image backup' option checked, the originals will be located in a backup folder at:
140
+
141
+ /wp-content/uploads/ShortpixelBackups
142
+
143
+ After optimization, if you want to switch back to a certain original image, hit Restore backup in the Media Library. If you are happy with the optimized images, you can deactivate saving the backups in the plugin Settings.
144
+
145
+
146
 
147
  = What types of formats can be optimized? =
148
 
168
 
169
  == Changelog ==
170
 
171
+ = 3.1.2 =
172
+
173
+ * bulk runs now only on media and post pages
174
+ * settings page redesign
175
+ * client site access test from our servers when activating the API key and warn if site not accessible
176
+ * fix last image sometimes unprocessed by bulk
177
+ * fix progress bar to advance when skipping images
178
+
179
  = 3.1.1 =
180
 
181
+ * fix calculation of displayed counters of images to be processed on bulk start
182
+ * fix restore option that appeared wrongly sometimes - thanks to Bogdan Günther @ http://medianotions.de
183
 
184
  = 3.1.0 =
185
 
shortpixel_queue.php CHANGED
@@ -198,8 +198,16 @@ class ShortPixelQueue {
198
  }
199
 
200
  public function pauseBulk() {
201
- update_option( 'wp-short-pixel-cancel-pointer', $this->startBulkId);//we save this so we can resume bulk processing
 
 
202
  WPShortPixel::log("PAUSE: Pointer = ".get_option( 'wp-short-pixel-cancel-pointer'));
 
 
 
 
 
 
203
  $this->stopBulk();
204
  }
205
 
@@ -241,15 +249,27 @@ class ShortPixelQueue {
241
  public static function resetBulk() {
242
  delete_option('bulkProcessingStatus');
243
  delete_option( 'wp-short-pixel-cancel-pointer');
 
244
  $startBulkId = $stopBulkId = WPShortPixel::getMaxMediaId();
245
  update_option( 'wp-short-pixel-query-id-stop', $startBulkId );
246
  update_option( 'wp-short-pixel-query-id-start', $startBulkId );
247
- update_option('wp-short-pixel-bulk-running-time', 0);
248
- update_option('wp-short-pixel-last-bulk-start-time', 0);
249
- update_option('wp-short-pixel-last-bulk-success-time', 0);
 
 
250
  delete_option( "wp-short-pixel-bulk-processed-items");
 
 
251
  }
252
 
 
 
 
 
 
 
 
253
  public function logBulkProgress() {
254
  $t = time();
255
  $this->incrementBulkCurrentlyProcessed();
198
  }
199
 
200
  public function pauseBulk() {
201
+ $cancelPointer = $this->startBulkId;
202
+ $bulkStartId = $this->getFlagBulkId();
203
+ update_option( 'wp-short-pixel-cancel-pointer', $cancelPointer);//we save this so we can resume bulk processing
204
  WPShortPixel::log("PAUSE: Pointer = ".get_option( 'wp-short-pixel-cancel-pointer'));
205
+ //remove the bulk items from prio queue
206
+ foreach($this->get() as $qItem) {
207
+ if($qItem < $bulkStartId) {
208
+ $this->remove($qItem);
209
+ }
210
+ }
211
  $this->stopBulk();
212
  }
213
 
249
  public static function resetBulk() {
250
  delete_option('bulkProcessingStatus');
251
  delete_option( 'wp-short-pixel-cancel-pointer');
252
+ delete_option( "wp-short-pixel-flag-id");
253
  $startBulkId = $stopBulkId = WPShortPixel::getMaxMediaId();
254
  update_option( 'wp-short-pixel-query-id-stop', $startBulkId );
255
  update_option( 'wp-short-pixel-query-id-start', $startBulkId );
256
+ delete_option( "wp-short-pixel-bulk-previous-percent");
257
+ delete_option( "wp-short-pixel-bulk-processed-items");
258
+ delete_option('wp-short-pixel-bulk-running-time');
259
+ delete_option('wp-short-pixel-last-bulk-start-time');
260
+ delete_option('wp-short-pixel-last-bulk-success-time');
261
  delete_option( "wp-short-pixel-bulk-processed-items");
262
+ delete_option( "wp-short-pixel-bulk-count");
263
+ delete_option( "wp-short-pixel-bulk-done-count");
264
  }
265
 
266
+ public static function resetPrio() {
267
+ delete_option( "wp-short-pixel-priorityQueue");
268
+ if(isset($_SESSION["wp-short-pixel-priorityQueue"])){
269
+ unset($_SESSION["wp-short-pixel-priorityQueue"]);
270
+ }
271
+ }
272
+
273
  public function logBulkProgress() {
274
  $t = time();
275
  $this->incrementBulkCurrentlyProcessed();
shortpixel_view.php CHANGED
@@ -120,8 +120,9 @@ class ShortPixelView {
120
  <div class="wrap short-pixel-bulk-page">
121
  <h1>Bulk Image Optimization by ShortPixel</h1>
122
  <p>Bulk optimization has started.<br>
123
- This process will take some time, depending on the number of images in your library. In the meantime, you can continue using the admin as usual.<br>
124
- However, <strong>if you close the WordPress admin, the bulk processing will pause</strong> until you open the admin again. </p>
 
125
  <?=$this->displayBulkProgressBar(true, $percent, $message)?>
126
  <div class="bulk-progress bulk-slider-container">
127
  <div style="margin-bottom: 10px;"><span class="short-pixel-block-title">Just optimized:</span></div>
@@ -203,6 +204,55 @@ class ShortPixelView {
203
  <?php
204
  }
205
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
206
  public function displaySettingsForm($quotaData) {
207
  $checked = ($this->ctrl->processThumbnails() ? 'checked' : '');
208
  $checkedBackupImages = ($this->ctrl->backupImages() ? 'checked' : '');
@@ -211,7 +261,12 @@ class ShortPixelView {
211
  $resizeDisabled = ($this->ctrl->getResizeImages() ? '' : 'disabled');
212
  $minSizes = $this->ctrl->getMaxIntermediateImageSize();
213
  ?>
214
- <form name='wp_shortpixel_options' action='' method='post' id='wp_shortpixel_options'>
 
 
 
 
 
215
  <table class="form-table">
216
  <tbody>
217
  <tr>
@@ -283,8 +338,8 @@ class ShortPixelView {
283
  </tbody>
284
  </table>
285
  <p class="submit">
286
- <input type="submit" name="save" id="save" class="button button-primary" title="Save Changes" value="Save Changes"> &nbsp;and then&nbsp;
287
- <a class="button button-primary" title="Process all the images in your Media Library" href="upload.php?page=wp-short-pixel-bulk">Bulk Process</a>
288
  </p>
289
  </form>
290
  <script>
@@ -332,8 +387,8 @@ class ShortPixelView {
332
  <?php
333
  }
334
 
335
- function displaySettingsStats($averageCompression, $savedSpace, $savedBandwidth,
336
- $quotaData, $remainingImages, $totalCallsMade, $fileCount, $backupFolderSize) { ?>
337
  <a id="facts"></a>
338
  <h3>Your ShortPixel Stats</h3>
339
  <table class="form-table">
@@ -361,7 +416,7 @@ class ShortPixelView {
361
  <tr>
362
  <th scope="row" bgcolor="#ffffff"><label for="apiQuota">Your ShortPixel plan</label></th>
363
  <td bgcolor="#ffffff">
364
- <?=number_format($quotaData['APICallsQuota'])?>/month, renews in <?=floor(30 + (strtotime($quotaData['APILastRenewalDate']) - time()) / 86400)?> days, on <?=date('M d, Y', strtotime($quotaData['APILastRenewalDate']. ' + 30 days'))?> ( <a href="https://shortpixel.com/login/<?=$this->ctrl->getApiKey();?>" target="_blank">Need More? See the options available</a> )<br/>
365
  <a href="https://shortpixel.com/login/<?=$this->ctrl->getApiKey()?>/tell-a-friend" target="_blank">Join our friend referral system</a> to win more credits. For each user that joins, you receive +100 images credits/month.
366
  </td>
367
  </tr>
@@ -380,7 +435,7 @@ class ShortPixelView {
380
  </tbody>
381
  </table>
382
 
383
- <p style="padding-top: 0px; color: #818181;" >** Increase your image quota by <a href="https://shortpixel.com/login/<?=$this->ctrl->getApiKey()?>" target="_blank">upgrading</a> your ShortPixel plan.</p>
384
 
385
  <table class="form-table">
386
  <tbody>
@@ -400,6 +455,10 @@ class ShortPixelView {
400
  </tr>
401
  <?php } ?>
402
  </tbody>
403
- </table> <?php
 
 
 
 
404
  }
405
  }
120
  <div class="wrap short-pixel-bulk-page">
121
  <h1>Bulk Image Optimization by ShortPixel</h1>
122
  <p>Bulk optimization has started.<br>
123
+ This process will take some time, depending on the number of images in your library. In the meantime, you can continue using
124
+ the admin as usual, <a href='<?=get_admin_url()?>' target='_blank'>in a different browser window or tab</a>.<br>
125
+ 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. </p>
126
  <?=$this->displayBulkProgressBar(true, $percent, $message)?>
127
  <div class="bulk-progress bulk-slider-container">
128
  <div style="margin-bottom: 10px;"><span class="short-pixel-block-title">Just optimized:</span></div>
204
  <?php
205
  }
206
 
207
+ function displaySettings($quotaData, $notice, $resources = null, $averageCompression = null, $savedSpace = null, $savedBandwidth = null,
208
+ $remainingImages = null, $totalCallsMade = null, $fileCount = null, $backupFolderSize = null) {
209
+ //wp_enqueue_script('jquery.idTabs.js', plugins_url('/js/jquery.idTabs.js',__FILE__) );
210
+ ?>
211
+ <h1>ShortPixel Plugin Settings</h1>
212
+ <p>
213
+ <a href="https://shortpixel.com" target="_blank">ShortPixel.com</a> |
214
+ <a href="https://wordpress.org/plugins/shortpixel-image-optimiser/installation/" target="_blank">Installation </a> |
215
+ <a href="https://shortpixel.com/contact" target="_blank">Support </a>
216
+ </p>
217
+ <?php if($notice !== null) { ?>
218
+ <br/>
219
+ <div style="background-color: #fff; border-left: 4px solid <?=$notice['status'] == 'error' ? '#ff0000' : ($notice['status'] == 'warn' ? '#FFC800' : '#7ad03a')?>; box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1); padding: 1px 12px;;width: 95%">
220
+ <p><?=$notice['msg']?></p>
221
+ </div>
222
+ <?php } ?>
223
+
224
+ <article class="tabs">
225
+ <section class='sel-tab' id="tab-settings">
226
+ <h2><a class='tab-link' href='javascript:void(0);' data-id="tab-settings">Settings</a></h2>
227
+ <?php $this->displaySettingsForm($quotaData);?>
228
+ </section> <?php
229
+ if($averageCompression !== null) {?>
230
+ <section id="tab-stats">
231
+ <h2><a class='tab-link' href='javascript:void(0);' data-id="tab-stats">Statistics</a></h2>
232
+ <?php
233
+ $this->displaySettingsStats($quotaData, $averageCompression, $savedSpace, $savedBandwidth,
234
+ $remainingImages, $totalCallsMade, $fileCount, $backupFolderSize);?>
235
+ </section>
236
+ <?php }
237
+ if($resources !== null) {?>
238
+ <section id="tab-resources">
239
+ <h2><a class='tab-link' href='javascript:void(0);' data-id="tab-resources">WP Resources</a></h2>
240
+ <?=(isset($resources['body']) ? $resources['body'] : "Please reload")?>
241
+ </section>
242
+ <?php } ?>
243
+ </article>
244
+ <script>
245
+ jQuery(document).ready(function () {
246
+ jQuery("a.tab-link").click(function(){
247
+ var target = jQuery(this).data("id");
248
+ jQuery("section").removeClass("sel-tab");
249
+ jQuery("section#" +target).addClass("sel-tab");
250
+ });
251
+ });
252
+ </script>
253
+ <?php
254
+ }
255
+
256
  public function displaySettingsForm($quotaData) {
257
  $checked = ($this->ctrl->processThumbnails() ? 'checked' : '');
258
  $checkedBackupImages = ($this->ctrl->backupImages() ? 'checked' : '');
261
  $resizeDisabled = ($this->ctrl->getResizeImages() ? '' : 'disabled');
262
  $minSizes = $this->ctrl->getMaxIntermediateImageSize();
263
  ?>
264
+ <?php if($this->ctrl->getVerifiedKey()) { ?>
265
+ <p>New images uploaded to the Media Library will be optimized automatically.<br/>If you have existing images you would like to optimize, you can use the <a href="' . get_admin_url() . 'upload.php?page=wp-short-pixel-bulk">Bulk Optimization Tool</a>.</p>
266
+ <?php } else { ?>
267
+ <p>Please enter here the API Key provided by ShortPixel:</p>
268
+ <?php } ?>
269
+ <form name='wp_shortpixel_options' action='options-general.php?page=wp-shortpixel&noheader=true' method='post' id='wp_shortpixel_options'>
270
  <table class="form-table">
271
  <tbody>
272
  <tr>
338
  </tbody>
339
  </table>
340
  <p class="submit">
341
+ <input type="submit" name="save" id="save" class="button button-primary" title="Save Changes" value="Save Changes"> &nbsp;
342
+ <input type="submit" name="save" id="bulk" class="button button-primary" title="Save and go to the Bulk Processing page" value="Bulk Process"> &nbsp;
343
  </p>
344
  </form>
345
  <script>
387
  <?php
388
  }
389
 
390
+ function displaySettingsStats($quotaData, $averageCompression, $savedSpace, $savedBandwidth,
391
+ $remainingImages, $totalCallsMade, $fileCount, $backupFolderSize) { ?>
392
  <a id="facts"></a>
393
  <h3>Your ShortPixel Stats</h3>
394
  <table class="form-table">
416
  <tr>
417
  <th scope="row" bgcolor="#ffffff"><label for="apiQuota">Your ShortPixel plan</label></th>
418
  <td bgcolor="#ffffff">
419
+ <?=$quotaData['APICallsQuota']?>/month, renews in <?=floor(30 + (strtotime($quotaData['APILastRenewalDate']) - time()) / 86400)?> days, on <?=date('M d, Y', strtotime($quotaData['APILastRenewalDate']. ' + 30 days'))?> ( <a href="https://shortpixel.com/login/<?=$this->ctrl->getApiKey();?>" target="_blank">Need More? See the options available</a> )<br/>
420
  <a href="https://shortpixel.com/login/<?=$this->ctrl->getApiKey()?>/tell-a-friend" target="_blank">Join our friend referral system</a> to win more credits. For each user that joins, you receive +100 images credits/month.
421
  </td>
422
  </tr>
435
  </tbody>
436
  </table>
437
 
438
+ <p style="padding-top: 0px; color: #818181;" >** Increase your image quota by <a href="https://shortpixel.com/login/<?=$this->ctrl->getApiKey()?>" target="_blank">upgrading your ShortPixel plan.</a></p>
439
 
440
  <table class="form-table">
441
  <tbody>
455
  </tr>
456
  <?php } ?>
457
  </tbody>
458
+ </table>
459
+ <div style="display:none">
460
+
461
+ </div>
462
+ <?php
463
  }
464
  }
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: 3.1.1
7
  * Author: ShortPixel
8
  * Author URI: https://shortpixel.com
9
  */
@@ -21,7 +21,7 @@ define('SP_RESET_ON_ACTIVATE', false);
21
 
22
  define('SP_AFFILIATE_CODE', '');
23
 
24
- define('PLUGIN_VERSION', "3.1.1");
25
  define('SP_MAX_TIMEOUT', 10);
26
  define('SP_BACKUP', 'ShortpixelBackups');
27
  define('SP_BACKUP_FOLDER', WP_CONTENT_DIR . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR . SP_BACKUP);
@@ -140,16 +140,30 @@ class WPShortPixel {
140
  {
141
  self::shortPixelDeactivatePlugin();
142
  if(SP_RESET_ON_ACTIVATE === true && WP_DEBUG === true) { //force reset plugin counters, only on specific occasions and on test environments
143
- update_option( 'wp-short-pixel-fileCount', 0);
 
 
 
 
 
 
144
  update_option( 'wp-short-pixel-thumbnail-count', 0);
145
  update_option( 'wp-short-pixel-files-under-5-percent', 0);
146
  update_option( 'wp-short-pixel-savedSpace', 0);
 
 
 
 
147
  update_option( 'wp-short-pixel-api-retries', 0);//sometimes we need to retry processing/downloading a file multiple times
148
  update_option( 'wp-short-pixel-quota-exceeded', 0);
149
- update_option( 'wp-short-pixel-total-original', 0);//amount of original data
150
- update_option( 'wp-short-pixel-total-optimized', 0);//amount of optimized
151
  update_option( 'wp-short-pixel-bulk-ever-ran', 0);
 
152
  delete_option('wp-short-pixel-priorityQueue');
 
 
 
 
153
  if(isset($_SESSION["wp-short-pixel-priorityQueue"])) {
154
  unset($_SESSION["wp-short-pixel-priorityQueue"]);
155
  }
@@ -165,6 +179,7 @@ class WPShortPixel {
165
  {
166
  include_once dirname( __FILE__ ) . '/shortpixel_queue.php';
167
  ShortPixelQueue::resetBulk();
 
168
  delete_option('wp-short-pixel-activation-notice');
169
  }
170
 
@@ -258,6 +273,11 @@ class WPShortPixel {
258
  $blank = '_blank';
259
  //$icon = "shortpixel-alert.png";
260
  }
 
 
 
 
 
261
  self::log("TB: Start: " . $this->prioQ->getStartBulkId() . ", stop: " . $this->prioQ->getStopBulkId() . " PrioQ: "
262
  .json_encode($this->prioQ->get()));
263
 
@@ -284,7 +304,7 @@ class WPShortPixel {
284
  $action = $wp_list_table->current_action();
285
 
286
  switch($action) {
287
- // 2. Perform the action
288
  case 'short-pixel-bulk':
289
  // security check
290
  check_admin_referer('bulk-media');
@@ -294,7 +314,7 @@ class WPShortPixel {
294
  $mediaIds = array_reverse($_GET['media']);
295
  foreach( $mediaIds as $ID ) {
296
  $meta = wp_get_attachment_metadata($ID);
297
- if( (!isset($meta['ShortPixel']) || !isset($meta['ShortPixel']['WaitingProcessing']) || $meta['ShortPixel']['WaitingProcessing'] != true)
298
  && (!isset($meta['ShortPixelImprovement']) || $meta['ShortPixelImprovement'] != 'Optimization N/A')) {
299
  $this->prioQ->push($ID);
300
  $meta['ShortPixel']['WaitingProcessing'] = true;
@@ -359,12 +379,12 @@ class WPShortPixel {
359
  }
360
  $idList = array();
361
  for ($sanityCheck = 0, $crtStartQueryID = $startQueryID;
362
- $crtStartQueryID > $endQueryID && count($idList) < 3; $sanityCheck++) {
363
 
364
  self::log("GETDB: current StartID: " . $crtStartQueryID);
365
 
366
  $queryPostMeta = "SELECT * FROM " . $wpdb->prefix . "postmeta
367
- WHERE ( post_id <= $crtStartQueryID AND post_id > $endQueryID )
368
  AND ( meta_key = '_wp_attached_file' OR meta_key = '_wp_attachment_metadata' )
369
  ORDER BY post_id DESC
370
  LIMIT " . SP_MAX_RESULTS_QUERY;
@@ -425,14 +445,16 @@ class WPShortPixel {
425
  }
426
 
427
  public function handleImageProcessing($ID = null) {
428
- //die("bau");
429
  //0: check key
430
  if( $this->_verifiedKey == false) {
431
  if($ID == null){
432
  $ids = $this->getFromPrioAndCheck();
433
  $ID = (count($ids) > 0 ? $ids[0] : null);
434
  }
435
- die(json_encode(array("Status" => ShortPixelAPI::STATUS_NO_KEY, "ImageID" => $ID, "Message" => "Missing API Key")));
 
 
436
  }
437
 
438
  self::log("HIP: 0 Priority Queue: ".json_encode($this->prioQ->get()));
@@ -453,13 +475,14 @@ class WPShortPixel {
453
  $bulkEverRan = $this->prioQ->stopBulk();
454
  $avg = self::getAverageCompression();
455
  $fileCount = get_option('wp-short-pixel-fileCount');
456
- die(json_encode(array("Status" => self::BULK_EMPTY_QUEUE,
457
  "Message" => 'Empty queue ' . $this->prioQ->getStartBulkId() . '->' . $this->prioQ->getStopBulkId(),
458
  "BulkStatus" => ($this->prioQ->bulkRunning()
459
  ? "1" : ($this->prioQ->bulkPaused() ? "2" : "0")),
460
  "AverageCompression" => $avg,
461
  "FileCount" => $fileCount,
462
- "BulkPercent" => $this->prioQ->getBulkPercent())));
 
463
  }
464
 
465
  self::log("HIP: 1 Prio Queue: ".json_encode($this->prioQ->get()));
@@ -528,11 +551,17 @@ class WPShortPixel {
528
  //put this one in the failed images list - to show the user at the end
529
  $prio = $this->prioQ->addToFailed($ID);
530
  }
531
- if(!$prio && $ID <= $this->prioQ->getStartBulkId()) {
532
  $this->prioQ->setStartBulkId($ID - 1);
 
 
 
 
 
533
  }
534
  }
535
- die(json_encode($result));
 
536
  }
537
 
538
  private function sendToProcessing($ID) {
@@ -824,21 +853,9 @@ class WPShortPixel {
824
  wp_die('You do not have sufficient permissions to access this page.');
825
  }
826
 
827
- echo '<h1>ShortPixel Plugin Settings</h1>';
828
- echo '<p>
829
- <a href="https://shortpixel.com" target="_blank">ShortPixel.com</a> |
830
- <a href="https://wordpress.org/plugins/shortpixel-image-optimiser/installation/" target="_blank">Installation </a> |
831
- <a href="https://shortpixel.com/contact" target="_blank">Support </a>
832
- </p>';
833
- if($this->_verifiedKey) {
834
- echo '<p>New images uploaded to the Media Library will be optimized automatically.<br/>If you have existing images you would like to optimize, you can use the <a href="' . get_admin_url() . 'upload.php?page=wp-short-pixel-bulk">Bulk Optimization Tool</a>.</p>';
835
- } else {
836
- echo '<p>Please enter here the API Key provided by ShortPixel:</p>';
837
- }
838
-
839
- $noticeHTML = "<br/><div style=\"background-color: #fff; border-left: 4px solid %s; box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1); padding: 1px 12px;\"><p>%s</p></div>";
840
-
841
  //die(var_dump($_POST));
 
 
842
 
843
  //by default we try to fetch the API Key from wp-config.php (if defined)
844
  if ( !isset($_POST['save']) && !get_option('wp-short-pixel-verifiedKey') && defined("SHORTPIXEL_API_KEY") && strlen(SHORTPIXEL_API_KEY) == 20 )
@@ -855,44 +872,45 @@ class WPShortPixel {
855
  {
856
  $KeyLength = strlen($_POST['key']);
857
 
858
- printf($noticeHTML, '#ff0000', "The key you provided has " . $KeyLength . " characters. The API key should have 20 characters, letters and numbers only.<BR> <b>Please check that the API key is the same as the one you received in your confirmation email.</b><BR>
859
  If this problem persists, please contact us at <a href='mailto:help@shortpixel.com?Subject=API Key issues' target='_top'>help@shortpixel.com</a> or <a href='https://shortpixel.com/contact' target='_blank'>here</a>.");
860
  }
861
  else
862
  {
863
- $validityData = $this->getQuotaInformation($_POST['key'], true);
864
 
865
  $this->_apiKey = $_POST['key'];
866
  $this->_apiInterface->setApiKey($this->_apiKey);
867
  update_option('wp-short-pixel-apiKey', $_POST['key']);
868
  if($validityData['APIKeyValid']) {
869
  if(isset($_POST['validate']) && $_POST['validate'] == "validate") {
 
 
 
 
 
870
  //display notification
871
  $urlParts = explode("/", get_site_url());
872
- if( false
873
- && (((count($urlParts) >= 3) && ($urlParts[2] == 'wpshortpixel.com'))
874
- || in_array($_SERVER["SERVER_ADDR"], array("127.0.0.1","::1")))){
875
- printf($noticeHTML, '#FFC800', "API Key is valid but your server seems to have a local address (" . $_SERVER['SERVER_ADDR'] . ").
876
  Please make sure that your server is accessible from the Internet before using the API or otherwise we won't be able to optimize them.");
877
  } else {
878
-
879
  if ( function_exists("is_multisite") && is_multisite() )
880
- printf($noticeHTML, '#7ad03a', "API Key valid! <br>You seem to be running a multisite, please note that API Key can also be configured in wp-config.php like this:<BR> <b>define('SHORTPIXEL_API_KEY', '".$this->_apiKey."');</b>");
881
  else
882
- printf($noticeHTML, '#7ad03a', 'API Key valid!');
883
  }
884
  }
885
  update_option('wp-short-pixel-verifiedKey', true);
886
  $this->_verifiedKey = true;
887
  //test that the "uploads" have the right rights and also we can create the backup dir for ShortPixel
888
  if ( !file_exists(SP_BACKUP_FOLDER) && !@mkdir(SP_BACKUP_FOLDER, 0777, true) )
889
- printf($noticeHTML, '#ff0000', "There is something preventing us to create a new folder for backing up your original files.<BR>
890
- Please make sure that folder <b>" .
891
- WP_CONTENT_DIR . DIRECTORY_SEPARATOR . "uploads</b> has the necessary write and read rights." );
892
  } else {
893
  if(isset($_POST['validate'])) {
894
  //display notification
895
- printf($noticeHTML, '#ff0000', $validityData["Message"]);
896
  }
897
  update_option('wp-short-pixel-verifiedKey', false);
898
  $this->_verifiedKey = false;
@@ -918,17 +936,23 @@ class WPShortPixel {
918
  update_option( 'wp-short-pixel-resize-width', 0 + $this->_resizeWidth);
919
  update_option( 'wp-short-pixel-resize-height', 0 + $this->_resizeHeight);
920
 
 
 
 
 
921
  }
922
  }
923
-
924
-
 
 
 
925
  //empty backup
926
  if(isset($_POST['emptyBackup'])) {
927
  $this->emptyBackup();
928
  }
929
 
930
  $quotaData = $this->checkQuotaAndAlert();
931
- $this->view->displaySettingsForm($quotaData);
932
 
933
  if($this->_verifiedKey) {
934
  $fileCount = number_format(get_option('wp-short-pixel-fileCount'));
@@ -943,8 +967,11 @@ class WPShortPixel {
943
  $remainingImages = ( $remainingImages < 0 ) ? 0 : number_format($remainingImages);
944
  $totalCallsMade = number_format($quotaData['APICallsMadeNumeric'] + $quotaData['APICallsMadeOneTimeNumeric']);
945
 
946
- $this->view->displaySettingsStats($averageCompression, $savedSpace, $savedBandwidth,
947
- $quotaData, $remainingImages, $totalCallsMade, $fileCount, $backupFolderSize);
 
 
 
948
  }
949
 
950
  }
@@ -955,7 +982,14 @@ class WPShortPixel {
955
  : 0;
956
  }
957
 
958
- public function getQuotaInformation($apiKey = null, $appendUserAgent = false) {
 
 
 
 
 
 
 
959
 
960
  if(is_null($apiKey)) { $apiKey = $this->_apiKey; }
961
 
@@ -968,6 +1002,13 @@ class WPShortPixel {
968
  if($appendUserAgent) {
969
  $args['body']['useragent'] = "Agent" . urlencode($_SERVER['HTTP_USER_AGENT']);
970
  }
 
 
 
 
 
 
 
971
  $response = wp_remote_post($requestURL, $args);
972
 
973
  if(is_wp_error( $response )) //some hosting providers won't allow https:// POST connections so we try http:// as well
@@ -980,7 +1021,8 @@ class WPShortPixel {
980
  "APIKeyValid" => false,
981
  "Message" => 'API Key could not be validated due to a connectivity error.<BR>Your firewall may be blocking us. Please contact your hosting provider and ask them to allow connections from your site to IP 176.9.106.46.<BR> If you still cannot validate your API Key after this, please <a href="https://shortpixel.com/contact" target="_blank">contact us</a> and we will try to help. ',
982
  "APICallsMade" => 'Information unavailable. Please check your API key.',
983
- "APICallsQuota" => 'Information unavailable. Please check your API key.');
 
984
 
985
  if(is_object($response) && get_class($response) == 'WP_Error') {
986
 
@@ -1010,7 +1052,6 @@ class WPShortPixel {
1010
  update_option('wp-short-pixel-quota-exceeded',0);
1011
  else
1012
  update_option('wp-short-pixel-quota-exceeded',1);//activate quota limiting
1013
-
1014
  return array(
1015
  "APIKeyValid" => true,
1016
  "APICallsMade" => number_format($data->APICallsMade) . ' images',
@@ -1021,10 +1062,9 @@ class WPShortPixel {
1021
  "APICallsQuotaNumeric" => $data->APICallsQuota,
1022
  "APICallsMadeOneTimeNumeric" => $data->APICallsMadeOneTime,
1023
  "APICallsQuotaOneTimeNumeric" => $data->APICallsQuotaOneTime,
1024
- "APILastRenewalDate" => $data->DateSubscription
 
1025
  );
1026
-
1027
-
1028
  }
1029
 
1030
  public function generateCustomColumn( $column_name, $id ) {
@@ -1087,7 +1127,7 @@ class WPShortPixel {
1087
  }
1088
  if ( get_option('wp-short-backup_images') && !isset($data['ShortPixel']['NoBackup'])) //display restore backup option only when backup is active
1089
  print " | <a href=\"admin.php?action=shortpixel_restore_backup&amp;attachment_ID={$id}\">Restore backup</a>";
1090
- if (count($data['sizes'])) {
1091
  print "<br>+" . count($data['sizes']) . " thumbnails optimized";
1092
  }
1093
  }
@@ -1123,7 +1163,7 @@ class WPShortPixel {
1123
  {
1124
  print "<img src=\"" . plugins_url( 'img/loading.gif', __FILE__ ) . "\">&nbsp;Image waiting to be processed
1125
  | <a href=\"javascript:manualOptimization({$id})\">Retry</a></div>";
1126
- $this->prioQ->push($id); //should be there but just to make sure
1127
  }
1128
 
1129
  } elseif(isset($data['ShortPixel']['NoFileOnDisk'])) {
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: 3.1.2
7
  * Author: ShortPixel
8
  * Author URI: https://shortpixel.com
9
  */
21
 
22
  define('SP_AFFILIATE_CODE', '');
23
 
24
+ define('PLUGIN_VERSION', "3.1.2");
25
  define('SP_MAX_TIMEOUT', 10);
26
  define('SP_BACKUP', 'ShortpixelBackups');
27
  define('SP_BACKUP_FOLDER', WP_CONTENT_DIR . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR . SP_BACKUP);
140
  {
141
  self::shortPixelDeactivatePlugin();
142
  if(SP_RESET_ON_ACTIVATE === true && WP_DEBUG === true) { //force reset plugin counters, only on specific occasions and on test environments
143
+ delete_option('wp-short-pixel-apiKey');
144
+ delete_option('wp-short-pixel-verifiedKey');
145
+ delete_option('wp-short-pixel-compression');
146
+ delete_option('wp-short-process_thumbnails');
147
+ delete_option('wp-short-pixel_cmyk2rgb');
148
+ delete_option('wp-short-backup_images');
149
+ delete_option('wp-short-pixel-view-mode');
150
  update_option( 'wp-short-pixel-thumbnail-count', 0);
151
  update_option( 'wp-short-pixel-files-under-5-percent', 0);
152
  update_option( 'wp-short-pixel-savedSpace', 0);
153
+ delete_option( 'wp-short-pixel-averageCompression');
154
+ delete_option( 'wp-short-pixel-fileCount');
155
+ delete_option( 'wp-short-pixel-total-original');
156
+ delete_option( 'wp-short-pixel-total-optimized');
157
  update_option( 'wp-short-pixel-api-retries', 0);//sometimes we need to retry processing/downloading a file multiple times
158
  update_option( 'wp-short-pixel-quota-exceeded', 0);
159
+ delete_option( 'wp-short-pixel-protocol');
 
160
  update_option( 'wp-short-pixel-bulk-ever-ran', 0);
161
+ delete_option( 'wp-short-pixel-bulk-last-status');
162
  delete_option('wp-short-pixel-priorityQueue');
163
+ delete_option( 'wp-short-pixel-resize-images');
164
+ delete_option( 'wp-short-pixel-resize-width');
165
+ delete_option( 'wp-short-pixel-resize-height');
166
+ delete_option( 'wp-short-pixel-dismissed-notices');
167
  if(isset($_SESSION["wp-short-pixel-priorityQueue"])) {
168
  unset($_SESSION["wp-short-pixel-priorityQueue"]);
169
  }
179
  {
180
  include_once dirname( __FILE__ ) . '/shortpixel_queue.php';
181
  ShortPixelQueue::resetBulk();
182
+ ShortPixelQueue::resetPrio();
183
  delete_option('wp-short-pixel-activation-notice');
184
  }
185
 
273
  $blank = '_blank';
274
  //$icon = "shortpixel-alert.png";
275
  }
276
+ $lastStatus = self::getOpt( 'wp-short-pixel-bulk-last-status', array('Status' => ShortPixelAPI::STATUS_SUCCESS));
277
+ if($lastStatus['Status'] != ShortPixelAPI::STATUS_SUCCESS) {
278
+ $extraClasses = " shortpixel-alert shortpixel-processing";
279
+ $tooltip = $lastStatus['Message'];
280
+ }
281
  self::log("TB: Start: " . $this->prioQ->getStartBulkId() . ", stop: " . $this->prioQ->getStopBulkId() . " PrioQ: "
282
  .json_encode($this->prioQ->get()));
283
 
304
  $action = $wp_list_table->current_action();
305
 
306
  switch($action) {
307
+ // 2. Perform the action
308
  case 'short-pixel-bulk':
309
  // security check
310
  check_admin_referer('bulk-media');
314
  $mediaIds = array_reverse($_GET['media']);
315
  foreach( $mediaIds as $ID ) {
316
  $meta = wp_get_attachment_metadata($ID);
317
+ if( (!isset($meta['ShortPixel']) || (isset($meta['ShortPixel']['WaitingProcessing']) && $meta['ShortPixel']['WaitingProcessing'] == true))
318
  && (!isset($meta['ShortPixelImprovement']) || $meta['ShortPixelImprovement'] != 'Optimization N/A')) {
319
  $this->prioQ->push($ID);
320
  $meta['ShortPixel']['WaitingProcessing'] = true;
379
  }
380
  $idList = array();
381
  for ($sanityCheck = 0, $crtStartQueryID = $startQueryID;
382
+ $crtStartQueryID >= $endQueryID && count($idList) < 3; $sanityCheck++) {
383
 
384
  self::log("GETDB: current StartID: " . $crtStartQueryID);
385
 
386
  $queryPostMeta = "SELECT * FROM " . $wpdb->prefix . "postmeta
387
+ WHERE ( post_id <= $crtStartQueryID AND post_id >= $endQueryID )
388
  AND ( meta_key = '_wp_attached_file' OR meta_key = '_wp_attachment_metadata' )
389
  ORDER BY post_id DESC
390
  LIMIT " . SP_MAX_RESULTS_QUERY;
445
  }
446
 
447
  public function handleImageProcessing($ID = null) {
448
+ //die("stop");
449
  //0: check key
450
  if( $this->_verifiedKey == false) {
451
  if($ID == null){
452
  $ids = $this->getFromPrioAndCheck();
453
  $ID = (count($ids) > 0 ? $ids[0] : null);
454
  }
455
+ $response = array("Status" => ShortPixelAPI::STATUS_NO_KEY, "ImageID" => $ID, "Message" => "Missing API Key");
456
+ update_option( 'wp-short-pixel-bulk-last-status', $response);
457
+ die(json_encode($response));
458
  }
459
 
460
  self::log("HIP: 0 Priority Queue: ".json_encode($this->prioQ->get()));
475
  $bulkEverRan = $this->prioQ->stopBulk();
476
  $avg = self::getAverageCompression();
477
  $fileCount = get_option('wp-short-pixel-fileCount');
478
+ $response = array("Status" => self::BULK_EMPTY_QUEUE,
479
  "Message" => 'Empty queue ' . $this->prioQ->getStartBulkId() . '->' . $this->prioQ->getStopBulkId(),
480
  "BulkStatus" => ($this->prioQ->bulkRunning()
481
  ? "1" : ($this->prioQ->bulkPaused() ? "2" : "0")),
482
  "AverageCompression" => $avg,
483
  "FileCount" => $fileCount,
484
+ "BulkPercent" => $this->prioQ->getBulkPercent());
485
+ die(json_encode($response));
486
  }
487
 
488
  self::log("HIP: 1 Prio Queue: ".json_encode($this->prioQ->get()));
551
  //put this one in the failed images list - to show the user at the end
552
  $prio = $this->prioQ->addToFailed($ID);
553
  }
554
+ if($ID <= $this->prioQ->getStartBulkId()) {
555
  $this->prioQ->setStartBulkId($ID - 1);
556
+ $this->prioQ->logBulkProgress();
557
+ $deltaBulkPercent = $this->prioQ->getDeltaBulkPercent();
558
+ $msg = $this->bulkProgressMessage($deltaBulkPercent, $this->prioQ->getTimeRemaining());
559
+ $result["BulkPercent"] = $this->prioQ->getBulkPercent();
560
+ $result["BulkMsg"] = $msg;
561
  }
562
  }
563
+ update_option( 'wp-short-pixel-bulk-last-status', $result);
564
+ die(json_encode($result));
565
  }
566
 
567
  private function sendToProcessing($ID) {
853
  wp_die('You do not have sufficient permissions to access this page.');
854
  }
855
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
856
  //die(var_dump($_POST));
857
+ $noticeHTML = "";
858
+ $notice = null;
859
 
860
  //by default we try to fetch the API Key from wp-config.php (if defined)
861
  if ( !isset($_POST['save']) && !get_option('wp-short-pixel-verifiedKey') && defined("SHORTPIXEL_API_KEY") && strlen(SHORTPIXEL_API_KEY) == 20 )
872
  {
873
  $KeyLength = strlen($_POST['key']);
874
 
875
+ $notice = array("status" => "error", "msg" => "The key you provided has " . $KeyLength . " characters. The API key should have 20 characters, letters and numbers only.<BR> <b>Please check that the API key is the same as the one you received in your confirmation email.</b><BR>
876
  If this problem persists, please contact us at <a href='mailto:help@shortpixel.com?Subject=API Key issues' target='_top'>help@shortpixel.com</a> or <a href='https://shortpixel.com/contact' target='_blank'>here</a>.");
877
  }
878
  else
879
  {
880
+ $validityData = $this->getQuotaInformation($_POST['key'], true, isset($_POST['validate']) && $_POST['validate'] == "validate");
881
 
882
  $this->_apiKey = $_POST['key'];
883
  $this->_apiInterface->setApiKey($this->_apiKey);
884
  update_option('wp-short-pixel-apiKey', $_POST['key']);
885
  if($validityData['APIKeyValid']) {
886
  if(isset($_POST['validate']) && $_POST['validate'] == "validate") {
887
+ // delete last status if it was no valid key
888
+ $lastStatus = get_option( 'wp-short-pixel-bulk-last-status');
889
+ if(isset($lastStatus) && $lastStatus['Status'] == ShortPixelAPI::STATUS_NO_KEY) {
890
+ delete_option( 'wp-short-pixel-bulk-last-status');
891
+ }
892
  //display notification
893
  $urlParts = explode("/", get_site_url());
894
+ if( $validityData['DomainCheck'] == 'NOT Accessible'){
895
+ $notice = array("status" => "warn", "msg" => "API Key is valid but your site is not accessible from our servers.
 
 
896
  Please make sure that your server is accessible from the Internet before using the API or otherwise we won't be able to optimize them.");
897
  } else {
 
898
  if ( function_exists("is_multisite") && is_multisite() )
899
+ $notice = array("status" => "success", "msg" => "API Key valid! <br>You seem to be running a multisite, please note that API Key can also be configured in wp-config.php like this:<BR> <b>define('SHORTPIXEL_API_KEY', '".$this->_apiKey."');</b>");
900
  else
901
+ $notice = array("status" => "success", "msg" => 'API Key valid!');
902
  }
903
  }
904
  update_option('wp-short-pixel-verifiedKey', true);
905
  $this->_verifiedKey = true;
906
  //test that the "uploads" have the right rights and also we can create the backup dir for ShortPixel
907
  if ( !file_exists(SP_BACKUP_FOLDER) && !@mkdir(SP_BACKUP_FOLDER, 0777, true) )
908
+ $notice = array("status" => "error", "msg" => "There is something preventing us to create a new folder for backing up your original files.<BR>
909
+ Please make sure that folder <b>" . WP_CONTENT_DIR . DIRECTORY_SEPARATOR . "uploads</b> has the necessary write and read rights.");
 
910
  } else {
911
  if(isset($_POST['validate'])) {
912
  //display notification
913
+ $notice = array("status" => "error", "msg" => $validityData["Message"]);
914
  }
915
  update_option('wp-short-pixel-verifiedKey', false);
916
  $this->_verifiedKey = false;
936
  update_option( 'wp-short-pixel-resize-width', 0 + $this->_resizeWidth);
937
  update_option( 'wp-short-pixel-resize-height', 0 + $this->_resizeHeight);
938
 
939
+ if($_POST['save'] == "Bulk Process") {
940
+ wp_redirect("upload.php?page=wp-short-pixel-bulk");
941
+ exit();
942
+ }
943
  }
944
  }
945
+ //now output headers. They were prevented with noheaders=true in the form url in order to be able to redirect if bulk was pressed
946
+ if(isset($_REQUEST['noheader'])) {
947
+ require_once(ABSPATH . 'wp-admin/admin-header.php');
948
+ }
949
+
950
  //empty backup
951
  if(isset($_POST['emptyBackup'])) {
952
  $this->emptyBackup();
953
  }
954
 
955
  $quotaData = $this->checkQuotaAndAlert();
 
956
 
957
  if($this->_verifiedKey) {
958
  $fileCount = number_format(get_option('wp-short-pixel-fileCount'));
967
  $remainingImages = ( $remainingImages < 0 ) ? 0 : number_format($remainingImages);
968
  $totalCallsMade = number_format($quotaData['APICallsMadeNumeric'] + $quotaData['APICallsMadeOneTimeNumeric']);
969
 
970
+ $resources = wp_remote_get("https://shortpixel.com/resources-frag");
971
+ $this->view->displaySettings($quotaData, $notice, $resources, $averageCompression, $savedSpace, $savedBandwidth,
972
+ $remainingImages, $totalCallsMade, $fileCount, $backupFolderSize);
973
+ } else {
974
+ $this->view->displaySettings($quotaData, $notice);
975
  }
976
 
977
  }
982
  : 0;
983
  }
984
 
985
+ /**
986
+ *
987
+ * @param type $apiKey
988
+ * @param type $appendUserAgent
989
+ * @param type $validate - true if we are validating the api key, send also the domain name and number of pics
990
+ * @return type
991
+ */
992
+ public function getQuotaInformation($apiKey = null, $appendUserAgent = false, $validate = false) {
993
 
994
  if(is_null($apiKey)) { $apiKey = $this->_apiKey; }
995
 
1002
  if($appendUserAgent) {
1003
  $args['body']['useragent'] = "Agent" . urlencode($_SERVER['HTTP_USER_AGENT']);
1004
  }
1005
+ if($validate) {
1006
+ $args['body']['DomainCheck'] = get_site_url();
1007
+ $imageCount = $this->countAllProcessableFiles();
1008
+ $args['body']['ImagesCount'] = $imageCount['mainFiles'];
1009
+ $args['body']['ThumbsCount'] = $imageCount['totalFiles'] - $imageCount['mainFiles'];
1010
+ }
1011
+
1012
  $response = wp_remote_post($requestURL, $args);
1013
 
1014
  if(is_wp_error( $response )) //some hosting providers won't allow https:// POST connections so we try http:// as well
1021
  "APIKeyValid" => false,
1022
  "Message" => 'API Key could not be validated due to a connectivity error.<BR>Your firewall may be blocking us. Please contact your hosting provider and ask them to allow connections from your site to IP 176.9.106.46.<BR> If you still cannot validate your API Key after this, please <a href="https://shortpixel.com/contact" target="_blank">contact us</a> and we will try to help. ',
1023
  "APICallsMade" => 'Information unavailable. Please check your API key.',
1024
+ "APICallsQuota" => 'Information unavailable. Please check your API key.',
1025
+ "DomainCheck" => 'NOT Accessible');
1026
 
1027
  if(is_object($response) && get_class($response) == 'WP_Error') {
1028
 
1052
  update_option('wp-short-pixel-quota-exceeded',0);
1053
  else
1054
  update_option('wp-short-pixel-quota-exceeded',1);//activate quota limiting
 
1055
  return array(
1056
  "APIKeyValid" => true,
1057
  "APICallsMade" => number_format($data->APICallsMade) . ' images',
1062
  "APICallsQuotaNumeric" => $data->APICallsQuota,
1063
  "APICallsMadeOneTimeNumeric" => $data->APICallsMadeOneTime,
1064
  "APICallsQuotaOneTimeNumeric" => $data->APICallsQuotaOneTime,
1065
+ "APILastRenewalDate" => $data->DateSubscription,
1066
+ "DomainCheck" => (isset($data->DomainCheck) ? $data->DomainCheck : null)
1067
  );
 
 
1068
  }
1069
 
1070
  public function generateCustomColumn( $column_name, $id ) {
1127
  }
1128
  if ( get_option('wp-short-backup_images') && !isset($data['ShortPixel']['NoBackup'])) //display restore backup option only when backup is active
1129
  print " | <a href=\"admin.php?action=shortpixel_restore_backup&amp;attachment_ID={$id}\">Restore backup</a>";
1130
+ if (isset($data['sizes']) && count($data['sizes'])) {
1131
  print "<br>+" . count($data['sizes']) . " thumbnails optimized";
1132
  }
1133
  }
1163
  {
1164
  print "<img src=\"" . plugins_url( 'img/loading.gif', __FILE__ ) . "\">&nbsp;Image waiting to be processed
1165
  | <a href=\"javascript:manualOptimization({$id})\">Retry</a></div>";
1166
+ if($id > $this->prioQ->getFlagBulkId()) $this->prioQ->push($id); //should be there but just to make sure
1167
  }
1168
 
1169
  } elseif(isset($data['ShortPixel']['NoFileOnDisk'])) {