ShortPixel Image Optimizer - Version 4.1.5

Version Description

  • readme updates - links to informative articles
  • show that WebP format is created free of charge
  • hide the Advanced settings tab completely before API Key validation
  • fix indefinite retries when wrong image size
  • restrict debug mode to ShortPixel own define
Download this release

Release Info

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

Code changes from version 4.1.4 to 4.1.5

class/db/shortpixel-meta-facade.php CHANGED
@@ -60,7 +60,7 @@ class ShortPixelMetaFacade {
60
  : (isset($rawMeta["ShortPixelImprovement"]) && is_numeric($rawMeta["ShortPixelImprovement"]) ? 2
61
  : (isset($rawMeta["ShortPixel"]["WaitingProcessing"]) ? 1
62
  : -500))),
63
- "retries" =>(isset($rawMeta["ShortPixel"]["retries"]) ? $rawMeta["ShortPixel"]["retries"] : 0),
64
  ));
65
  }
66
 
@@ -84,34 +84,33 @@ class ShortPixelMetaFacade {
84
  }
85
  }
86
  elseif($this->type == ShortPixelMetaFacade::MEDIA_LIBRARY_TYPE) {
87
- //TODO vezi daca nu mai bine mutam asta in Facade - acolo unde actualizam meta, in updateMeta
88
  $duplicates = ShortPixelMetaFacade::getWPMLDuplicates($this->ID);
89
  foreach($duplicates as $_ID) {
90
  $rawMeta = wp_get_attachment_metadata($_ID);
91
  if(!is_array($rawMeta)) {
92
  $rawMeta = array("previous_meta" => $rawMeta, 'ShortPixel' => array());
93
  }
94
- $rawMeta['ShortPixel']['type'] = ($newMeta->getCompressionType() == 1 ? "lossy" : "lossless");
95
- $rawMeta['ShortPixel']['exifKept'] = $newMeta->getKeepExif();
96
- $rawMeta['ShortPixel']['date'] = date("Y-m-d", strtotime($newMeta->getTsOptimized()));
97
  //thumbs were processed if settings or if they were explicitely requested
98
- $rawMeta['ShortPixel']['thumbsOpt'] = $newMeta->getThumbsOpt();
99
  //if thumbsTodo - this means there was an explicit request to process thumbs for an image that was previously processed without
100
  // don't update the ShortPixelImprovement ratio as this is only calculated based on main image
101
- if($newMeta->getThumbsTodo()) {
102
  $rawMeta['ShortPixel']['thumbsTodo'] = true;
103
  } else {
104
- $rawMeta['ShortPixelImprovement'] = "".round($newMeta->getImprovementPercent(),2);
105
  unset($rawMeta['ShortPixel']['thumbsTodo']);
106
  }
107
- if($newMeta->getActualWidth() && $newMeta->getActualHeight()) {
108
- $rawMeta['width'] = $newMeta->getActualWidth();
109
- $rawMeta['height'] = $newMeta->getActualHeight();
110
  }
111
- if(!$newMeta->getBackup()) {
112
  $rawMeta['ShortPixel']['NoBackup'] = true;
113
  }
114
- if($newMeta->getStatus() !== 1) {
115
  unset($rawMeta['ShortPixel']['WaitingProcessing']);
116
  }
117
  wp_update_attachment_metadata($this->ID, $rawMeta);
60
  : (isset($rawMeta["ShortPixelImprovement"]) && is_numeric($rawMeta["ShortPixelImprovement"]) ? 2
61
  : (isset($rawMeta["ShortPixel"]["WaitingProcessing"]) ? 1
62
  : -500))),
63
+ "retries" =>(isset($rawMeta["ShortPixel"]["Retries"]) ? $rawMeta["ShortPixel"]["Retries"] : 0),
64
  ));
65
  }
66
 
84
  }
85
  }
86
  elseif($this->type == ShortPixelMetaFacade::MEDIA_LIBRARY_TYPE) {
 
87
  $duplicates = ShortPixelMetaFacade::getWPMLDuplicates($this->ID);
88
  foreach($duplicates as $_ID) {
89
  $rawMeta = wp_get_attachment_metadata($_ID);
90
  if(!is_array($rawMeta)) {
91
  $rawMeta = array("previous_meta" => $rawMeta, 'ShortPixel' => array());
92
  }
93
+ $rawMeta['ShortPixel']['type'] = ($this->meta->getCompressionType() == 1 ? "lossy" : "lossless");
94
+ $rawMeta['ShortPixel']['exifKept'] = $this->meta->getKeepExif();
95
+ $rawMeta['ShortPixel']['date'] = date("Y-m-d", strtotime($this->meta->getTsOptimized()));
96
  //thumbs were processed if settings or if they were explicitely requested
97
+ $rawMeta['ShortPixel']['thumbsOpt'] = $this->meta->getThumbsOpt();
98
  //if thumbsTodo - this means there was an explicit request to process thumbs for an image that was previously processed without
99
  // don't update the ShortPixelImprovement ratio as this is only calculated based on main image
100
+ if($this->meta->getThumbsTodo()) {
101
  $rawMeta['ShortPixel']['thumbsTodo'] = true;
102
  } else {
103
+ $rawMeta['ShortPixelImprovement'] = "".round($this->meta->getImprovementPercent(),2);
104
  unset($rawMeta['ShortPixel']['thumbsTodo']);
105
  }
106
+ if($this->meta->getActualWidth() && $this->meta->getActualHeight()) {
107
+ $rawMeta['width'] = $this->meta->getActualWidth();
108
+ $rawMeta['height'] = $this->meta->getActualHeight();
109
  }
110
+ if(!$this->meta->getBackup()) {
111
  $rawMeta['ShortPixel']['NoBackup'] = true;
112
  }
113
+ if($this->meta->getStatus() !== 1) {
114
  unset($rawMeta['ShortPixel']['WaitingProcessing']);
115
  }
116
  wp_update_attachment_metadata($this->ID, $rawMeta);
class/model/shortpixel-folder.php CHANGED
@@ -108,7 +108,7 @@ class ShortPixelFolder extends ShortPixelEntity{
108
  */
109
  foreach($files as $t) {
110
  if(in_array($t, $ignore)) continue;
111
- $tpath = rtrim($path, '/') . '/' . $t;
112
  if (is_dir($tpath)) {
113
  self::getFileListRecursive($tpath, $fileHandle, $onlyNewerThan);
114
  } elseif($add && in_array(pathinfo($t, PATHINFO_EXTENSION), WPShortPixel::$PROCESSABLE_EXTENSIONS)) {
@@ -117,6 +117,28 @@ class ShortPixelFolder extends ShortPixelEntity{
117
  }
118
  }
119
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  public function getFolderContentsChangeDate() {
121
  return self::getFolderContentsChangeDateRecursive($this->getPath(), 0, time($this->getTsUpdated()));
122
  }
108
  */
109
  foreach($files as $t) {
110
  if(in_array($t, $ignore)) continue;
111
+ $tpath = trailingslashit($path) . $t;
112
  if (is_dir($tpath)) {
113
  self::getFileListRecursive($tpath, $fileHandle, $onlyNewerThan);
114
  } elseif($add && in_array(pathinfo($t, PATHINFO_EXTENSION), WPShortPixel::$PROCESSABLE_EXTENSIONS)) {
117
  }
118
  }
119
 
120
+ public function checkFolderContents($callback) {
121
+ $changed = array();
122
+ self::checkFolderContentsRecursive($this->getPath(), $changed, $callback);
123
+ return $changed;
124
+ }
125
+
126
+ protected static function checkFolderContentsRecursive($path, &$changed, $callback) {
127
+ $ignore = array('.','..');
128
+ $files = scandir($path);
129
+ $reference = call_user_func_array($callback, array($path));
130
+ foreach($files as $t) {
131
+ if(in_array($t, $ignore)) continue;
132
+ $tpath = trailingslashit($path) . $t;
133
+ if (is_dir($tpath)) {
134
+ self::checkFolderContentsRecursive($tpath, $callback);
135
+ } elseif( in_array(pathinfo($t, PATHINFO_EXTENSION), WPShortPixel::$PROCESSABLE_EXTENSIONS)
136
+ && !(in_array($tpath, $reference) && $reference[$tpath]->compressedSize == filesize($tpath))) {
137
+ $changed[] = $tpath;
138
+ }
139
+ }
140
+ }
141
+
142
  public function getFolderContentsChangeDate() {
143
  return self::getFolderContentsChangeDateRecursive($this->getPath(), 0, time($this->getTsUpdated()));
144
  }
class/view/shortpixel-list-table.php CHANGED
@@ -70,7 +70,7 @@ class ShortPixelListTable extends WP_List_Table {
70
  } elseif($item->status == 2) {
71
  $actionsEnabled['restore'] = true;
72
  $actionsEnabled['redo'.($item->compression_type == 1 ? "lossless" : "lossy")] = true;
73
- } elseif($item->status == 3) {
74
  $actionsEnabled['retry'] = true;
75
  }
76
  $actionsEnabled['view'] = true;
70
  } elseif($item->status == 2) {
71
  $actionsEnabled['restore'] = true;
72
  $actionsEnabled['redo'.($item->compression_type == 1 ? "lossless" : "lossy")] = true;
73
+ } elseif($item->status == 3 || $item->status < 0) {
74
  $actionsEnabled['retry'] = true;
75
  }
76
  $actionsEnabled['view'] = true;
class/view/shortpixel_view.php CHANGED
@@ -500,10 +500,12 @@ class ShortPixelView {
500
  <h2><a class='tab-link' href='javascript:void(0);' data-id="tab-settings">General</a></h2>
501
  <?php $this->displaySettingsForm($showApiKey, $editApiKey, $quotaData);?>
502
  </section>
 
503
  <section <?php echo($showAdvanced ? "class='sel-tab'" : "");?> id="tab-adv-settings">
504
  <h2><a class='tab-link' href='javascript:void(0);' data-id="tab-adv-settings">Advanced</a></h2>
505
  <?php $this->displayAdvancedSettingsForm($customFolders, $addedFolder);?>
506
  </section>
 
507
  </form><span style="display:none">&nbsp;</span><?php //the span is a trick to keep the sections ordered as nth-child in styles: 1,2,3,4 (otherwise the third section would be nth-child(2) too, because of the form)
508
  if($averageCompression !== null) {?>
509
  <section id="tab-stats">
@@ -523,7 +525,9 @@ class ShortPixelView {
523
  <script>
524
  jQuery(document).ready(function () {
525
  ShortPixel.adjustSettingsTabs();
526
-
 
 
527
  if(window.location.hash) {
528
  var target = 'tab-' + window.location.hash.substring(window.location.hash.indexOf("#")+1)
529
  ShortPixel.switchSettingsTab(target);
@@ -573,7 +577,7 @@ class ShortPixelView {
573
  <?php } ?>
574
  <input type="hidden" name="validate" id="valid" value=""/>
575
  <button type="button" id="validate" class="button button-primary" title="Validate the provided API key"
576
- onclick="validateKey()" <?php echo $canValidate ? "" : "disabled"?>>Validate</button>
577
  <?php if($showApiKey && !$editApiKey) { ?>
578
  <p class="settings-info">Key defined in wp-config.php.</p>
579
  <?php } ?>
@@ -644,7 +648,7 @@ class ShortPixelView {
644
  <input type="radio" name="resize_type" id="resize_type_outer" value="outer" <?php echo($settings->resizeType == 'inner' ? '' : 'checked') ?> style="margin: -50px 10px 60px 0;">
645
  <img src="<?php echo(plugins_url( 'shortpixel-image-optimiser/res/img/resize-outer.png' ));?>" title="Sizes will be greater or equal to the corresponding value. For example, if you set the resize dimensions at 1000x1200, an image of 2000x3000px will be resized to 1000x1500px while an image of 3000x2000px will be resized to 1800x1200px">
646
  <input type="radio" name="resize_type" id="resize_type_inner" value="inner" <?php echo($settings->resizeType == 'inner' ? 'checked' : '') ?> style="margin: -50px 10px 60px 35px;">
647
- <img src="<?php echo(plugins_url( 'shortpixel-image-optimiser/res/img/resize-inner.png' ));?>" title="Sizes will be smaller or equal to the corresponding value. For the same example values, an image of 2000x3000px will be resized to 800x1200px while an image of 3000x2000px will be resized to 1000x667px">
648
  </div>
649
  </td>
650
  </tr>
@@ -655,6 +659,13 @@ class ShortPixelView {
655
  <input type="submit" name="save" id="bulk" class="button button-primary" title="Save and go to the Bulk Processing page" value="Save and Go to Bulk Process"> &nbsp;
656
  </p>
657
  </div>
 
 
 
 
 
 
 
658
  <?php }
659
  }
660
 
@@ -717,12 +728,14 @@ class ShortPixelView {
717
  </td>
718
  <td>
719
  <input type="button" class="button remove-folder-button" data-value="<?php echo($folder->getPath()); ?>" title="Stop <?php echo($action . " " . $folder->getPath()); ?>" value="Stop <?php echo $action;?>">
 
720
  </td>
721
  </tr>
722
  <?php }?>
723
  </table>
724
  <?php } ?>
725
  <input type="hidden" name="removeFolder" id="removeFolder"/>
 
726
  <input type="text" name="addCustomFolderView" id="addCustomFolderView" class="regular-text" value="<?php echo($addedFolder);?>" disabled style="width: 50em;max-width: 70%;">&nbsp;
727
  <input type="hidden" name="addCustomFolder" id="addCustomFolder" value="<?php echo($addedFolder);?>"/>
728
  <input type="hidden" id="customFolderBase" value="<?php echo $this->ctrl->getCustomFolderBase(); ?>">
@@ -756,8 +769,8 @@ class ShortPixelView {
756
  <tr>
757
  <th scope="row"><label for="createWebp">WebP versions</label></th>
758
  <td>
759
- <input name="createWebp" type="checkbox" id="createWebp" <?php echo( $createWebp );?>> Create also <a href="http://blog.shortpixel.com/how-webp-images-can-speed-up-your-site/" target="_blank">WebP versions</a> of the images.
760
- <p class="settings-info">WebP images can be up to three times smaller than PNGs and 25% smaller than JPGs.</p>
761
  </td>
762
  </tr>
763
  <tr>
@@ -783,56 +796,9 @@ class ShortPixelView {
783
  </p>
784
  </div>
785
  <script>
786
- var rad = document.wp_shortpixel_options.compressionType;
787
- var prev = null;
788
- var minWidth = Math.min(1024, <?php echo($minSizes['width']);?>),
789
- minHeight = Math.min(1024, <?php echo($minSizes['height']);?>);
790
- for(var i = 0; i < rad.length; i++) {
791
- rad[i].onclick = function() {
792
-
793
- if(this !== prev) {
794
- prev = this;
795
- }
796
- alert('This type of optimization will apply to new uploaded images.\nImages that were already processed will not be re-optimized unless you restart the bulk process.');
797
- };
798
- }
799
- function enableResize(elm) {
800
- if(jQuery(elm).is(':checked')) {
801
- jQuery("#width,#height").removeAttr("disabled");
802
- } else {
803
- jQuery("#width,#height").attr("disabled", "disabled");
804
- }
805
- }
806
- enableResize("#resize");
807
- jQuery("#resize").change(function(){ enableResize(this) });
808
- jQuery("#width").blur(function(){
809
- jQuery(this).val(Math.max(minWidth, parseInt(jQuery(this).val())));
810
- });
811
- jQuery("#height").blur(function(){
812
- jQuery(this).val(Math.max(minHeight, parseInt(jQuery(this).val())));
813
- });
814
- jQuery("input.remove-folder-button").click(function(){
815
- var path = jQuery(this).data("value");
816
- var r = confirm("Are you sure you want to stop optimizing the folder " + path + "?");
817
- if (r == true) {
818
- jQuery("#removeFolder").val(path);
819
- jQuery('#wp_shortpixel_options').submit();
820
- }
821
- });
822
- </script>
823
- <?php } ?>
824
- <script>
825
- function validateKey(){
826
- jQuery('#valid').val('validate');
827
- jQuery('#wp_shortpixel_options').submit();
828
- }
829
- jQuery("#key").keypress(function(e) {
830
- if(e.which == 13) {
831
- jQuery('#valid').val('validate');
832
- }
833
- });
834
  </script>
835
- <?php
836
  }
837
 
838
  function displaySettingsStats($quotaData, $averageCompression, $savedSpace, $savedBandwidth,
500
  <h2><a class='tab-link' href='javascript:void(0);' data-id="tab-settings">General</a></h2>
501
  <?php $this->displaySettingsForm($showApiKey, $editApiKey, $quotaData);?>
502
  </section>
503
+ <?php if($this->ctrl->getVerifiedKey()) {?>
504
  <section <?php echo($showAdvanced ? "class='sel-tab'" : "");?> id="tab-adv-settings">
505
  <h2><a class='tab-link' href='javascript:void(0);' data-id="tab-adv-settings">Advanced</a></h2>
506
  <?php $this->displayAdvancedSettingsForm($customFolders, $addedFolder);?>
507
  </section>
508
+ <?php } ?>
509
  </form><span style="display:none">&nbsp;</span><?php //the span is a trick to keep the sections ordered as nth-child in styles: 1,2,3,4 (otherwise the third section would be nth-child(2) too, because of the form)
510
  if($averageCompression !== null) {?>
511
  <section id="tab-stats">
525
  <script>
526
  jQuery(document).ready(function () {
527
  ShortPixel.adjustSettingsTabs();
528
+ jQuery( window ).resize(function() {
529
+ ShortPixel.adjustSettingsTabs();
530
+ });
531
  if(window.location.hash) {
532
  var target = 'tab-' + window.location.hash.substring(window.location.hash.indexOf("#")+1)
533
  ShortPixel.switchSettingsTab(target);
577
  <?php } ?>
578
  <input type="hidden" name="validate" id="valid" value=""/>
579
  <button type="button" id="validate" class="button button-primary" title="Validate the provided API key"
580
+ onclick="ShortPixel.validateKey()" <?php echo $canValidate ? "" : "disabled"?>>Validate</button>
581
  <?php if($showApiKey && !$editApiKey) { ?>
582
  <p class="settings-info">Key defined in wp-config.php.</p>
583
  <?php } ?>
648
  <input type="radio" name="resize_type" id="resize_type_outer" value="outer" <?php echo($settings->resizeType == 'inner' ? '' : 'checked') ?> style="margin: -50px 10px 60px 0;">
649
  <img src="<?php echo(plugins_url( 'shortpixel-image-optimiser/res/img/resize-outer.png' ));?>" title="Sizes will be greater or equal to the corresponding value. For example, if you set the resize dimensions at 1000x1200, an image of 2000x3000px will be resized to 1000x1500px while an image of 3000x2000px will be resized to 1800x1200px">
650
  <input type="radio" name="resize_type" id="resize_type_inner" value="inner" <?php echo($settings->resizeType == 'inner' ? 'checked' : '') ?> style="margin: -50px 10px 60px 35px;">
651
+ <img src="<?php echo(plugins_url( 'shortpixel-image-optimiser/res/img/resize-inner.png' ));?>" title="Sizes will be smaller or equal to the corresponding value. For example, if you set the resize dimensions at 1000x1200, an image of 2000x3000px will be resized to 800x1200px while an image of 3000x2000px will be resized to 1000x667px">
652
  </div>
653
  </td>
654
  </tr>
659
  <input type="submit" name="save" id="bulk" class="button button-primary" title="Save and go to the Bulk Processing page" value="Save and Go to Bulk Process"> &nbsp;
660
  </p>
661
  </div>
662
+ <script>
663
+ jQuery(document).ready(function () {
664
+ ShortPixel.setupGeneralTab(document.wp_shortpixel_options.compressionType,
665
+ Math.min(1024, <?php echo($minSizes['width']);?>),
666
+ Math.min(1024, <?php echo($minSizes['height']);?>));
667
+ });
668
+ </script>
669
  <?php }
670
  }
671
 
728
  </td>
729
  <td>
730
  <input type="button" class="button remove-folder-button" data-value="<?php echo($folder->getPath()); ?>" title="Stop <?php echo($action . " " . $folder->getPath()); ?>" value="Stop <?php echo $action;?>">
731
+ <input type="button" style="display:none;" class="button button-alert recheck-folder-button" data-value="<?php echo($folder->getPath()); ?>" title="Full folder refresh, check each file of the folder if it changed since it was optimized. Might take up to 1 min. for big folders." value="Refresh">
732
  </td>
733
  </tr>
734
  <?php }?>
735
  </table>
736
  <?php } ?>
737
  <input type="hidden" name="removeFolder" id="removeFolder"/>
738
+ <input type="hidden" name="recheckFolder" id="removeFolder"/>
739
  <input type="text" name="addCustomFolderView" id="addCustomFolderView" class="regular-text" value="<?php echo($addedFolder);?>" disabled style="width: 50em;max-width: 70%;">&nbsp;
740
  <input type="hidden" name="addCustomFolder" id="addCustomFolder" value="<?php echo($addedFolder);?>"/>
741
  <input type="hidden" id="customFolderBase" value="<?php echo $this->ctrl->getCustomFolderBase(); ?>">
769
  <tr>
770
  <th scope="row"><label for="createWebp">WebP versions</label></th>
771
  <td>
772
+ <input name="createWebp" type="checkbox" id="createWebp" <?php echo( $createWebp );?>> Create also <a href="http://blog.shortpixel.com/how-webp-images-can-speed-up-your-site/" target="_blank">WebP versions</a> of the images <strong>for free</strong>.
773
+ <p class="settings-info">WebP images can be up to three times smaller than PNGs and 25% smaller than JPGs. Choosing this option <strong>does not use up additional credits</strong>.</p>
774
  </td>
775
  </tr>
776
  <tr>
796
  </p>
797
  </div>
798
  <script>
799
+ jQuery(document).ready(function () { ShortPixel.setupAdvancedTab();});
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
800
  </script>
801
+ <?php }
802
  }
803
 
804
  function displaySettingsStats($quotaData, $averageCompression, $savedSpace, $savedBandwidth,
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.6
8
- Stable tag: 4.1.4
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
@@ -27,8 +27,8 @@ Make an instant <a rel="friend" href="http://shortpixel.com/image-compression-te
27
  * popular plugin with over 20,000 active installations according to WordPress
28
  * compress JPG, PNG, GIF (still or animated) images and also PDF documents
29
  * no file size limit
30
- * 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>
31
- * compatible with WP Retina 2x - all **retina images** are automatically compressed
32
  * optimize thumbnails as well as featured images
33
  * ability to optimize any image on your site including images in **NextGEN Gallery** and any other image gallery or slider
34
  * featured images can be rescaled before being optimized with 2 different options. No need for additional plugins like Imsanity
@@ -178,6 +178,14 @@ The ShortPixel team is here to help. <a href="https://shortpixel.com/contact">Co
178
 
179
  == Changelog ==
180
 
 
 
 
 
 
 
 
 
181
  = 4.1.4 =
182
 
183
  * fix path problems on multisite on Windows
5
 
6
  Requires at least: 3.2.0
7
  Tested up to: 4.6
8
+ Stable tag: 4.1.5
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
27
  * popular plugin with over 20,000 active installations according to WordPress
28
  * compress JPG, PNG, GIF (still or animated) images and also PDF documents
29
  * no file size limit
30
+ * 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>
31
+ * compatible with WP Retina 2x - all **retina images** are automatically compressed. <a rel="friend" href="http://blog.shortpixel.com/how-to-use-optimized-retina-images-on-your-wordpress-site-for-best-user-experience-on-apple-devices/" target="_blank">How to benefit from Retina displays?</a>
32
  * optimize thumbnails as well as featured images
33
  * ability to optimize any image on your site including images in **NextGEN Gallery** and any other image gallery or slider
34
  * featured images can be rescaled before being optimized with 2 different options. No need for additional plugins like Imsanity
178
 
179
  == Changelog ==
180
 
181
+ = 4.1.5 =
182
+
183
+ * readme updates - links to informative articles
184
+ * show that WebP format is created free of charge
185
+ * hide the Advanced settings tab completely before API Key validation
186
+ * fix indefinite retries when wrong image size
187
+ * restrict debug mode to ShortPixel own define
188
+
189
  = 4.1.4 =
190
 
191
  * fix path problems on multisite on Windows
res/css/short-pixel.css CHANGED
@@ -10,6 +10,12 @@ div.fb-like {
10
  -moz-transform-origin: bottom left;
11
  -webkit-transform-origin: bottom left;
12
  }
 
 
 
 
 
 
13
  div.short-pixel-bulk-page input.dial {
14
  font-size: 16px !important;
15
  }
@@ -477,9 +483,17 @@ article.sp-tabs section h2 {
477
  }
478
  */
479
  /* Resources */
480
- section#tab-resources .col-md-6 {
481
- display: inline-block;
482
- width: 45%;
 
 
 
 
 
 
 
 
483
  }
484
  section#tab-resources .text-center {
485
  text-align: center;
@@ -533,4 +547,4 @@ section#tab-resources p {
533
  .sp-double-width, .sp-full-width, .sp-single-width {
534
  width: 97%;
535
  }
536
- }
10
  -moz-transform-origin: bottom left;
11
  -webkit-transform-origin: bottom left;
12
  }
13
+ .wp-core-ui .button.button-alert, .wp-core-ui .button.button-alert:hover {
14
+ background: #f79797;
15
+ }
16
+ .wp-core-ui .button.remove-folder-button {
17
+ min-width: 120px;
18
+ }
19
  div.short-pixel-bulk-page input.dial {
20
  font-size: 16px !important;
21
  }
483
  }
484
  */
485
  /* Resources */
486
+ @media(min-width: 1000px) {
487
+ section#tab-resources .col-md-6 {
488
+ display: inline-block;
489
+ width: 45%;
490
+ }
491
+ }
492
+ @media(max-width: 999px) {
493
+ section#tab-resources .col-sm-12 {
494
+ display: inline-block;
495
+ width: 100%;
496
+ }
497
  }
498
  section#tab-resources .text-center {
499
  text-align: center;
547
  .sp-double-width, .sp-full-width, .sp-single-width {
548
  width: 97%;
549
  }
550
+ }
res/js/short-pixel.js CHANGED
@@ -33,6 +33,64 @@ var ShortPixel = function() {
33
  }
34
  }
35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  function checkThumbsUpdTotal(el) {
37
  var total = jQuery("#" +(el.checked ? "total" : "main")+ "ToProcess").val();
38
  jQuery("div.bulk-play span.total").text(total);
@@ -48,8 +106,9 @@ var ShortPixel = function() {
48
  }
49
 
50
  function adjustSettingsTabsHeight(){
51
- var sectionHeight = jQuery('.wp-shortpixel-options').height() + 60;
52
- sectionHeight = Math.max(sectionHeight, jQuery('section#tab-resources .area1').height() + 20);
 
53
  jQuery('#shortpixel-settings-tabs').css('height', sectionHeight);
54
  jQuery('#shortpixel-settings-tabs section').css('height', sectionHeight);
55
  }
@@ -224,6 +283,10 @@ var ShortPixel = function() {
224
 
225
  return {
226
  setOptions : setOptions,
 
 
 
 
227
  checkThumbsUpdTotal : checkThumbsUpdTotal,
228
  switchSettingsTab : switchSettingsTab,
229
  adjustSettingsTabs : adjustSettingsTabsHeight,
33
  }
34
  }
35
 
36
+ function validateKey(){
37
+ jQuery('#valid').val('validate');
38
+ jQuery('#wp_shortpixel_options').submit();
39
+ }
40
+
41
+ jQuery("#key").keypress(function(e) {
42
+ if(e.which == 13) {
43
+ jQuery('#valid').val('validate');
44
+ }
45
+ });
46
+
47
+ function enableResize(elm) {
48
+ if(jQuery(elm).is(':checked')) {
49
+ jQuery("#width,#height").removeAttr("disabled");
50
+ } else {
51
+ jQuery("#width,#height").attr("disabled", "disabled");
52
+ }
53
+ }
54
+
55
+ function setupGeneralTab(rad, minWidth, minHeight) {
56
+ for(var i = 0, prev = null; i < rad.length; i++) {
57
+ rad[i].onclick = function() {
58
+
59
+ if(this !== prev) {
60
+ prev = this;
61
+ }
62
+ alert('This type of optimization will apply to new uploaded images.\nImages that were already processed will not be re-optimized unless you restart the bulk process.');
63
+ };
64
+ }
65
+ ShortPixel.enableResize("#resize");
66
+ jQuery("#resize").change(function(){ enableResize(this); });
67
+ jQuery("#width").blur(function(){
68
+ jQuery(this).val(Math.max(minWidth, parseInt(jQuery(this).val())));
69
+ });
70
+ jQuery("#height").blur(function(){
71
+ jQuery(this).val(Math.max(minHeight, parseInt(jQuery(this).val())));
72
+ });
73
+ }
74
+
75
+ function setupAdvancedTab() {
76
+ jQuery("input.remove-folder-button").click(function(){
77
+ var path = jQuery(this).data("value");
78
+ var r = confirm("Are you sure you want to stop optimizing the folder " + path + "?");
79
+ if (r == true) {
80
+ jQuery("#removeFolder").val(path);
81
+ jQuery('#wp_shortpixel_options').submit();
82
+ }
83
+ });
84
+ jQuery("input.recheck-folder-button").click(function(){
85
+ var path = jQuery(this).data("value");
86
+ var r = confirm("Are you sure you want to stop optimizing the folder " + path + "?");
87
+ if (r == true) {
88
+ jQuery("#recheckFolder").val(path);
89
+ jQuery('#wp_shortpixel_options').submit();
90
+ }
91
+ });
92
+ }
93
+
94
  function checkThumbsUpdTotal(el) {
95
  var total = jQuery("#" +(el.checked ? "total" : "main")+ "ToProcess").val();
96
  jQuery("div.bulk-play span.total").text(total);
106
  }
107
 
108
  function adjustSettingsTabsHeight(){
109
+ var sectionHeight = jQuery('section#tab-settings .wp-shortpixel-options').height() + 60;
110
+ sectionHeight = Math.max(sectionHeight, jQuery('section#tab-adv-settings .wp-shortpixel-options').height() + 20);
111
+ sectionHeight = Math.max(sectionHeight, jQuery('section#tab-resources .area1').height() + 60);
112
  jQuery('#shortpixel-settings-tabs').css('height', sectionHeight);
113
  jQuery('#shortpixel-settings-tabs section').css('height', sectionHeight);
114
  }
283
 
284
  return {
285
  setOptions : setOptions,
286
+ validateKey : validateKey,
287
+ enableResize : enableResize,
288
+ setupGeneralTab : setupGeneralTab,
289
+ setupAdvancedTab : setupAdvancedTab,
290
  checkThumbsUpdTotal : checkThumbsUpdTotal,
291
  switchSettingsTab : switchSettingsTab,
292
  adjustSettingsTabs : adjustSettingsTabsHeight,
shortpixel_api.php CHANGED
@@ -19,6 +19,7 @@ class ShortPixelAPI {
19
  const ERR_TIMEOUT = -3;
20
  const ERR_SAVE = -4;
21
  const ERR_SAVE_BKP = -5;
 
22
 
23
  private $_settings;
24
  private $_maxAttempts = 10;
19
  const ERR_TIMEOUT = -3;
20
  const ERR_SAVE = -4;
21
  const ERR_SAVE_BKP = -5;
22
+ const ERR_INCORRECT_FILE_SIZE = -6;
23
 
24
  private $_settings;
25
  private $_maxAttempts = 10;
wp-shortpixel-req.php CHANGED
@@ -1,5 +1,5 @@
1
  <?php
2
- if(WP_DEBUG === true) {
3
  require_once('shortpixel-debug.php');
4
  }
5
 
1
  <?php
2
+ if(defined('SHORTPIXEL_DEBUG') && SHORTPIXEL_DEBUG === true) {
3
  require_once('shortpixel-debug.php');
4
  }
5
 
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.1.4
7
  * Author: ShortPixel
8
  * Author URI: https://shortpixel.com
9
  */
@@ -12,7 +12,7 @@ define('SP_RESET_ON_ACTIVATE', false); //if true TODO set false
12
 
13
  define('SP_AFFILIATE_CODE', '');
14
 
15
- define('PLUGIN_VERSION', "4.1.4");
16
  define('SP_MAX_TIMEOUT', 10);
17
  define('SP_VALIDATE_MAX_TIMEOUT', 15);
18
  define('SP_BACKUP', 'ShortpixelBackups');
@@ -160,7 +160,7 @@ class WPShortPixel {
160
  }
161
 
162
  function registerAdminPage( ) {
163
- if(count($this->spMetaDao->hasFoldersTable() && $this->spMetaDao->getFolders())) {
164
  add_media_page( 'Other Media Optimized by ShortPixel', 'Other Media', 'edit_others_posts', 'wp-short-pixel-custom', array( &$this, 'listCustomMedia' ) );
165
  }
166
  add_media_page( 'ShortPixel Bulk Process', 'Bulk ShortPixel', 'edit_others_posts', 'wp-short-pixel-bulk', array( &$this, 'bulkProcess' ) );
@@ -710,26 +710,18 @@ class WPShortPixel {
710
  }
711
  }
712
  elseif ($result["Status"] == ShortPixelAPI::STATUS_ERROR) {
713
- //$meta = wp_get_attachment_metadata($ID);
714
- //if(isset($meta['ShortPixel']['Retries']) && $meta['ShortPixel']['Retries'] > MAX_ERR_RETRIES) {
715
  if($meta->getRetries() > MAX_ERR_RETRIES) {
716
- //if(! $this->prioQ->remove($ID) ){
717
  if(! $this->prioQ->remove($itemId) ){
718
- //$this->advanceBulk($ID, $result);
719
  $this->advanceBulk($meta->getId(), $result);
720
  }
721
- //unset($meta['ShortPixel']);
722
- //wp_update_attachment_metadata($ID, $meta);
723
  $itemHandler->deleteMeta(); //this deletes only the ShortPixel fields from meta, in case of WP Media library
724
  $result["Status"] = ShortPixelAPI::STATUS_SKIP;
725
  $result["Message"] .= " Retry limit reached. Skipping file ID " . $itemId . ".";
 
726
  }
727
  else {
728
- //if(!isset($meta['ShortPixel'])) { $meta['ShortPixel'] = array(); }
729
- //$meta['ShortPixel']['Retries'] = isset($meta['ShortPixel']['Retries']) ? $meta['ShortPixel']['Retries'] + 1 : 1;
730
- //wp_update_attachment_metadata($ID, $meta);
731
  $itemHandler->incrementRetries();
732
- }
733
  }
734
  elseif ($result["Status"] == ShortPixelAPI::STATUS_SKIP
735
  || $result["Status"] == ShortPixelAPI::STATUS_FAIL) {
@@ -1360,6 +1352,11 @@ class WPShortPixel {
1360
  }
1361
  }
1362
 
 
 
 
 
 
1363
  protected function refreshCustomFolders(&$notice, $ignore = false) {
1364
  $customFolders = array();
1365
  if($this->_settings->hasCustomFolders) {
@@ -1410,7 +1407,7 @@ class WPShortPixel {
1410
  //by default we try to fetch the API Key from wp-config.php (if defined)
1411
  if ( defined("SHORTPIXEL_API_KEY") && strlen(SHORTPIXEL_API_KEY) == 20)
1412
  {
1413
- if(!isset($_POST['save']) && strlen($this->getApiKey()) == 0) {
1414
  $_POST['validate'] = "validate";
1415
  }
1416
  $_POST['key'] = SHORTPIXEL_API_KEY;
@@ -1421,7 +1418,7 @@ class WPShortPixel {
1421
 
1422
  if( isset($_POST['save']) || isset($_POST['saveAdv'])
1423
  || (isset($_POST['validate']) && $_POST['validate'] == "validate")
1424
- || isset($_POST['removeFolder'])) {
1425
 
1426
  //handle API Key - common for save and validate.
1427
  $_POST['key'] = trim(str_replace("*", "", isset($_POST['key']) ? $_POST['key'] : $this->_settings->apiKey)); //the API key might not be set if the editing is disabled.
@@ -1521,6 +1518,9 @@ class WPShortPixel {
1521
  $customFolders = $this->spMetaDao->getFolders();
1522
  $_POST["saveAdv"] = true;
1523
  }
 
 
 
1524
  }
1525
 
1526
  //now output headers. They were prevented with noheaders=true in the form url in order to be able to redirect if bulk was pressed
@@ -1627,10 +1627,11 @@ class WPShortPixel {
1627
  }
1628
  if($validate) {
1629
  $args['body']['DomainCheck'] = get_site_url();
 
1630
  $imageCount = WpShortPixelMediaLbraryAdapter::countAllProcessableFiles();
1631
  $args['body']['ImagesCount'] = $imageCount['mainFiles'];
1632
  $args['body']['ThumbsCount'] = $imageCount['totalFiles'] - $imageCount['mainFiles'];
1633
- $argsStr .= "&DomainCheck={$args['body']['DomainCheck']}&ImagesCount={$imageCount['mainFiles']}&ThumbsCount={$args['body']['ThumbsCount']}";
1634
  }
1635
  if(strlen($this->_settings->siteAuthUser)) {
1636
  $args['body']['url'] = parse_url(get_site_url(),PHP_URL_HOST);
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.1.5
7
  * Author: ShortPixel
8
  * Author URI: https://shortpixel.com
9
  */
12
 
13
  define('SP_AFFILIATE_CODE', '');
14
 
15
+ define('PLUGIN_VERSION', "4.1.5");
16
  define('SP_MAX_TIMEOUT', 10);
17
  define('SP_VALIDATE_MAX_TIMEOUT', 15);
18
  define('SP_BACKUP', 'ShortpixelBackups');
160
  }
161
 
162
  function registerAdminPage( ) {
163
+ if($this->spMetaDao->hasFoldersTable() && count($this->spMetaDao->getFolders())) {
164
  add_media_page( 'Other Media Optimized by ShortPixel', 'Other Media', 'edit_others_posts', 'wp-short-pixel-custom', array( &$this, 'listCustomMedia' ) );
165
  }
166
  add_media_page( 'ShortPixel Bulk Process', 'Bulk ShortPixel', 'edit_others_posts', 'wp-short-pixel-bulk', array( &$this, 'bulkProcess' ) );
710
  }
711
  }
712
  elseif ($result["Status"] == ShortPixelAPI::STATUS_ERROR) {
 
 
713
  if($meta->getRetries() > MAX_ERR_RETRIES) {
 
714
  if(! $this->prioQ->remove($itemId) ){
 
715
  $this->advanceBulk($meta->getId(), $result);
716
  }
 
 
717
  $itemHandler->deleteMeta(); //this deletes only the ShortPixel fields from meta, in case of WP Media library
718
  $result["Status"] = ShortPixelAPI::STATUS_SKIP;
719
  $result["Message"] .= " Retry limit reached. Skipping file ID " . $itemId . ".";
720
+ $itemHandler->setError(ShortPixelAPI::ERR_INCORRECT_FILE_SIZE, $result["Message"] );
721
  }
722
  else {
 
 
 
723
  $itemHandler->incrementRetries();
724
+ }
725
  }
726
  elseif ($result["Status"] == ShortPixelAPI::STATUS_SKIP
727
  || $result["Status"] == ShortPixelAPI::STATUS_FAIL) {
1352
  }
1353
  }
1354
 
1355
+ protected function fullRefreshCustomFolder($path, &$notice) {
1356
+ $folder = $this->spMetaDao->getFolder($path);
1357
+ $diff = $folder->checkFolderContents(array('ShortPixelCustomMetaDao', 'getPathFiles'));
1358
+ }
1359
+
1360
  protected function refreshCustomFolders(&$notice, $ignore = false) {
1361
  $customFolders = array();
1362
  if($this->_settings->hasCustomFolders) {
1407
  //by default we try to fetch the API Key from wp-config.php (if defined)
1408
  if ( defined("SHORTPIXEL_API_KEY") && strlen(SHORTPIXEL_API_KEY) == 20)
1409
  {
1410
+ if(!isset($_POST['save']) && (strlen($this->getApiKey()) == 0 || SHORTPIXEL_API_KEY != $this->getApiKey())) {
1411
  $_POST['validate'] = "validate";
1412
  }
1413
  $_POST['key'] = SHORTPIXEL_API_KEY;
1418
 
1419
  if( isset($_POST['save']) || isset($_POST['saveAdv'])
1420
  || (isset($_POST['validate']) && $_POST['validate'] == "validate")
1421
+ || isset($_POST['removeFolder']) || isset($_POST['recheckFolder'])) {
1422
 
1423
  //handle API Key - common for save and validate.
1424
  $_POST['key'] = trim(str_replace("*", "", isset($_POST['key']) ? $_POST['key'] : $this->_settings->apiKey)); //the API key might not be set if the editing is disabled.
1518
  $customFolders = $this->spMetaDao->getFolders();
1519
  $_POST["saveAdv"] = true;
1520
  }
1521
+ if(isset($_POST['recheckFolder']) && strlen(($_POST['recheckFolder']))) {
1522
+ //$folder->fullRefreshCustomFolder($_POST['recheckFolder']); //aici singura solutie pare callback care spune daca exita url-ul complet
1523
+ }
1524
  }
1525
 
1526
  //now output headers. They were prevented with noheaders=true in the form url in order to be able to redirect if bulk was pressed
1627
  }
1628
  if($validate) {
1629
  $args['body']['DomainCheck'] = get_site_url();
1630
+ $args['body']['Info'] = get_bloginfo('version') . '|' . phpversion();
1631
  $imageCount = WpShortPixelMediaLbraryAdapter::countAllProcessableFiles();
1632
  $args['body']['ImagesCount'] = $imageCount['mainFiles'];
1633
  $args['body']['ThumbsCount'] = $imageCount['totalFiles'] - $imageCount['mainFiles'];
1634
+ $argsStr .= "&DomainCheck={$args['body']['DomainCheck']}&Info={$args['body']['Info']}&ImagesCount={$imageCount['mainFiles']}&ThumbsCount={$args['body']['ThumbsCount']}";
1635
  }
1636
  if(strlen($this->_settings->siteAuthUser)) {
1637
  $args['body']['url'] = parse_url(get_site_url(),PHP_URL_HOST);