Version Description
- exclude images based on patterns or image sizes, exclude paths based on patterns
- avoid using basename as a fallback for non-UTF8 filenames but instead use own code (basename strips first character if it's not ASCII-128 - for example ISO/IEC 8859-2)
- processing spinning indicator in the admin top bar with CSS to display OK on all admin themes.
Download this release
Release Info
| Developer | ShortPixel |
| Plugin | |
| Version | 4.4.0 |
| Comparing to | |
| See all releases | |
Code changes from version 4.3.1 to 4.4.0
- class/db/shortpixel-custom-meta-dao.php +6 -5
- class/db/shortpixel-meta-facade.php +8 -7
- class/db/wp-shortpixel-media-library-adapter.php +3 -1
- class/model/shortpixel-folder.php +7 -4
- class/view/shortpixel_view.php +26 -0
- class/wp-short-pixel.php +96 -36
- class/wp-shortpixel-settings.php +73 -78
- readme.txt +7 -1
- res/css/short-pixel.css +49 -2
- res/js/short-pixel.js +5 -5
- shortpixel_api.php +25 -18
- wp-shortpixel.php +2 -3
class/db/shortpixel-custom-meta-dao.php
CHANGED
|
@@ -2,7 +2,7 @@
|
|
| 2 |
|
| 3 |
class ShortPixelCustomMetaDao {
|
| 4 |
const META_VERSION = 1;
|
| 5 |
-
private $db;
|
| 6 |
|
| 7 |
private static $fields = array(
|
| 8 |
ShortPixelMeta::TABLE_SUFFIX => array(
|
|
@@ -31,8 +31,9 @@ class ShortPixelCustomMetaDao {
|
|
| 31 |
)
|
| 32 |
);
|
| 33 |
|
| 34 |
-
public function __construct($db) {
|
| 35 |
$this->db = $db;
|
|
|
|
| 36 |
}
|
| 37 |
|
| 38 |
public static function getCreateFolderTableSQL($tablePrefix, $charsetCollate) {
|
|
@@ -127,7 +128,7 @@ class ShortPixelCustomMetaDao {
|
|
| 127 |
$rows = $this->db->query($sql);
|
| 128 |
$folders = array();
|
| 129 |
foreach($rows as $row) {
|
| 130 |
-
$folders[] = new ShortPixelFolder($row);
|
| 131 |
}
|
| 132 |
return $folders;
|
| 133 |
}
|
|
@@ -137,7 +138,7 @@ class ShortPixelCustomMetaDao {
|
|
| 137 |
$rows = $this->db->query($sql, array($path));
|
| 138 |
$folders = array();
|
| 139 |
foreach($rows as $row) {
|
| 140 |
-
return new ShortPixelFolder($row);
|
| 141 |
}
|
| 142 |
return false;
|
| 143 |
}
|
|
@@ -201,7 +202,7 @@ class ShortPixelCustomMetaDao {
|
|
| 201 |
if($this->getFolder($addedFolder)) {
|
| 202 |
return __('Folder already added.','shortpixel-image-optimiser');
|
| 203 |
}
|
| 204 |
-
$folder = new ShortPixelFolder(array("path" => $addedFolder));
|
| 205 |
try {
|
| 206 |
$folder->setFileCount($folder->countFiles());
|
| 207 |
} catch(SpFileRightsException $ex) {
|
| 2 |
|
| 3 |
class ShortPixelCustomMetaDao {
|
| 4 |
const META_VERSION = 1;
|
| 5 |
+
private $db, $excludePatterns;
|
| 6 |
|
| 7 |
private static $fields = array(
|
| 8 |
ShortPixelMeta::TABLE_SUFFIX => array(
|
| 31 |
)
|
| 32 |
);
|
| 33 |
|
| 34 |
+
public function __construct($db, $excludePatterns = false) {
|
| 35 |
$this->db = $db;
|
| 36 |
+
$this->excludePatterns = $excludePatterns;
|
| 37 |
}
|
| 38 |
|
| 39 |
public static function getCreateFolderTableSQL($tablePrefix, $charsetCollate) {
|
| 128 |
$rows = $this->db->query($sql);
|
| 129 |
$folders = array();
|
| 130 |
foreach($rows as $row) {
|
| 131 |
+
$folders[] = new ShortPixelFolder($row, $this->excludePatterns);
|
| 132 |
}
|
| 133 |
return $folders;
|
| 134 |
}
|
| 138 |
$rows = $this->db->query($sql, array($path));
|
| 139 |
$folders = array();
|
| 140 |
foreach($rows as $row) {
|
| 141 |
+
return new ShortPixelFolder($row, $this->excludePatterns);
|
| 142 |
}
|
| 143 |
return false;
|
| 144 |
}
|
| 202 |
if($this->getFolder($addedFolder)) {
|
| 203 |
return __('Folder already added.','shortpixel-image-optimiser');
|
| 204 |
}
|
| 205 |
+
$folder = new ShortPixelFolder(array("path" => $addedFolder), $this->excludePatterns);
|
| 206 |
try {
|
| 207 |
$folder->setFileCount($folder->countFiles());
|
| 208 |
} catch(SpFileRightsException $ex) {
|
class/db/shortpixel-meta-facade.php
CHANGED
|
@@ -64,7 +64,9 @@ class ShortPixelMetaFacade {
|
|
| 64 |
"backup" => !isset($rawMeta['ShortPixel']['NoBackup']),
|
| 65 |
"status" => (!isset($rawMeta["ShortPixel"]) ? 0
|
| 66 |
: (isset($rawMeta["ShortPixelImprovement"]) && is_numeric($rawMeta["ShortPixelImprovement"])
|
| 67 |
-
&& !($rawMeta['ShortPixelImprovement'] == 0
|
|
|
|
|
|
|
| 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),
|
|
@@ -192,16 +194,15 @@ class ShortPixelMetaFacade {
|
|
| 192 |
}
|
| 193 |
}
|
| 194 |
|
| 195 |
-
function incrementRetries($count = 1) {
|
| 196 |
if($this->type == self::CUSTOM_TYPE) {
|
| 197 |
$this->meta->setRetries($this->meta->getRetries() + $count);
|
| 198 |
-
$this->updateMeta();
|
| 199 |
} else {
|
| 200 |
if(!isset($this->rawMeta['ShortPixel'])) {$this->rawMeta['ShortPixel'] = array();}
|
| 201 |
$this->rawMeta['ShortPixel']['Retries'] = isset($this->rawMeta['ShortPixel']['Retries']) ? $this->rawMeta['ShortPixel']['Retries'] + $count : $count;
|
| 202 |
$this->meta->setRetries($this->rawMeta['ShortPixel']['Retries']);
|
| 203 |
-
wp_update_attachment_metadata($this->ID, $this->rawMeta);
|
| 204 |
}
|
|
|
|
| 205 |
}
|
| 206 |
|
| 207 |
function setWaitingProcessing($status = true) {
|
|
@@ -228,7 +229,7 @@ class ShortPixelMetaFacade {
|
|
| 228 |
if($errorCode == ShortPixelAPI::ERR_FILE_NOT_FOUND) {
|
| 229 |
$this->spMetaDao->delete($this->meta);
|
| 230 |
} else {
|
| 231 |
-
$this->
|
| 232 |
}
|
| 233 |
} else {
|
| 234 |
$this->rawMeta['ShortPixelImprovement'] = $this->meta->getMessage();
|
|
@@ -301,8 +302,8 @@ class ShortPixelMetaFacade {
|
|
| 301 |
$sizes = $meta->getThumbs();
|
| 302 |
|
| 303 |
//it is NOT a PDF file and thumbs are processable
|
| 304 |
-
if (
|
| 305 |
-
|
| 306 |
&& count($sizes))
|
| 307 |
{
|
| 308 |
$uploadDir = wp_upload_dir();
|
| 64 |
"backup" => !isset($rawMeta['ShortPixel']['NoBackup']),
|
| 65 |
"status" => (!isset($rawMeta["ShortPixel"]) ? 0
|
| 66 |
: (isset($rawMeta["ShortPixelImprovement"]) && is_numeric($rawMeta["ShortPixelImprovement"])
|
| 67 |
+
&& !( $rawMeta['ShortPixelImprovement'] == 0
|
| 68 |
+
&& ( isset($rawMeta['ShortPixel']['WaitingProcessing'])
|
| 69 |
+
|| isset($rawMeta['ShortPixel']['date']) && $rawMeta['ShortPixel']['date'] == '1970-01-01')) ? 2
|
| 70 |
: (isset($rawMeta["ShortPixel"]["WaitingProcessing"]) ? 1
|
| 71 |
: (isset($rawMeta["ShortPixel"]['ErrCode']) ? $rawMeta["ShortPixel"]['ErrCode'] : -500)))),
|
| 72 |
"retries" =>(isset($rawMeta["ShortPixel"]["Retries"]) ? $rawMeta["ShortPixel"]["Retries"] : 0),
|
| 194 |
}
|
| 195 |
}
|
| 196 |
|
| 197 |
+
function incrementRetries($count = 1, $errorCode = -999, $errorMessage = '') {
|
| 198 |
if($this->type == self::CUSTOM_TYPE) {
|
| 199 |
$this->meta->setRetries($this->meta->getRetries() + $count);
|
|
|
|
| 200 |
} else {
|
| 201 |
if(!isset($this->rawMeta['ShortPixel'])) {$this->rawMeta['ShortPixel'] = array();}
|
| 202 |
$this->rawMeta['ShortPixel']['Retries'] = isset($this->rawMeta['ShortPixel']['Retries']) ? $this->rawMeta['ShortPixel']['Retries'] + $count : $count;
|
| 203 |
$this->meta->setRetries($this->rawMeta['ShortPixel']['Retries']);
|
|
|
|
| 204 |
}
|
| 205 |
+
$this->setError($errorCode, $errorMessage);
|
| 206 |
}
|
| 207 |
|
| 208 |
function setWaitingProcessing($status = true) {
|
| 229 |
if($errorCode == ShortPixelAPI::ERR_FILE_NOT_FOUND) {
|
| 230 |
$this->spMetaDao->delete($this->meta);
|
| 231 |
} else {
|
| 232 |
+
$this->updateMeta();
|
| 233 |
}
|
| 234 |
} else {
|
| 235 |
$this->rawMeta['ShortPixelImprovement'] = $this->meta->getMessage();
|
| 302 |
$sizes = $meta->getThumbs();
|
| 303 |
|
| 304 |
//it is NOT a PDF file and thumbs are processable
|
| 305 |
+
if ( /* strtolower(substr($path,strrpos($path, ".")+1)) != "pdf"
|
| 306 |
+
&&*/ ($processThumbnails || $onlyThumbs)
|
| 307 |
&& count($sizes))
|
| 308 |
{
|
| 309 |
$uploadDir = wp_upload_dir();
|
class/db/wp-shortpixel-media-library-adapter.php
CHANGED
|
@@ -12,6 +12,7 @@ class WpShortPixelMediaLbraryAdapter {
|
|
| 12 |
$limit = self::getOptimalChunkSize();
|
| 13 |
$pointer = 0;
|
| 14 |
$filesWithErrors = array();
|
|
|
|
| 15 |
|
| 16 |
//count all the files, main and thumbs
|
| 17 |
while ( 1 ) {
|
|
@@ -46,7 +47,8 @@ class WpShortPixelMediaLbraryAdapter {
|
|
| 46 |
$sizesCount = isset($attachment['sizes']) ? WpShortPixelMediaLbraryAdapter::countNonWebpSizes($attachment['sizes']) : 0;
|
| 47 |
//processable
|
| 48 |
$isProcessable = false;
|
| 49 |
-
if(isset($attachment['file']) && !isset($filesMap[$attachment['file']])
|
|
|
|
| 50 |
$isProcessable = true;
|
| 51 |
if ( isset($attachment['sizes']) ) {
|
| 52 |
$totalFiles += $sizesCount;
|
| 12 |
$limit = self::getOptimalChunkSize();
|
| 13 |
$pointer = 0;
|
| 14 |
$filesWithErrors = array();
|
| 15 |
+
$excludePatterns = WPShortPixelSettings::getOpt("excludePatterns");
|
| 16 |
|
| 17 |
//count all the files, main and thumbs
|
| 18 |
while ( 1 ) {
|
| 47 |
$sizesCount = isset($attachment['sizes']) ? WpShortPixelMediaLbraryAdapter::countNonWebpSizes($attachment['sizes']) : 0;
|
| 48 |
//processable
|
| 49 |
$isProcessable = false;
|
| 50 |
+
if( isset($attachment['file']) && !isset($filesMap[$attachment['file']])
|
| 51 |
+
&& WPShortPixel::_isProcessablePath($attachment['file'], array(), $excludePatterns)){
|
| 52 |
$isProcessable = true;
|
| 53 |
if ( isset($attachment['sizes']) ) {
|
| 54 |
$totalFiles += $sizesCount;
|
class/model/shortpixel-folder.php
CHANGED
|
@@ -11,10 +11,13 @@ class ShortPixelFolder extends ShortPixelEntity{
|
|
| 11 |
protected $tsCreated;
|
| 12 |
protected $tsUpdated;
|
| 13 |
|
|
|
|
|
|
|
| 14 |
const TABLE_SUFFIX = 'folders';
|
| 15 |
|
| 16 |
-
public function __construct($data) {
|
| 17 |
parent::__construct($data);
|
|
|
|
| 18 |
}
|
| 19 |
|
| 20 |
public static function checkFolder($folder, $base) {
|
|
@@ -81,7 +84,7 @@ class ShortPixelFolder extends ShortPixelEntity{
|
|
| 81 |
if(in_array($t, $ignore)) continue;
|
| 82 |
if (is_dir($tpath)) {
|
| 83 |
$size += $this->countFiles($tpath);
|
| 84 |
-
} elseif(WPShortPixel::
|
| 85 |
$size++;
|
| 86 |
}
|
| 87 |
}
|
|
@@ -111,7 +114,7 @@ class ShortPixelFolder extends ShortPixelEntity{
|
|
| 111 |
$tpath = trailingslashit($path) . $t;
|
| 112 |
if (is_dir($tpath)) {
|
| 113 |
self::getFileListRecursive($tpath, $fileHandle, $onlyNewerThan);
|
| 114 |
-
} elseif($add && WPShortPixel::
|
| 115 |
fwrite($fileHandle, $tpath . "\n");
|
| 116 |
}
|
| 117 |
}
|
|
@@ -132,7 +135,7 @@ class ShortPixelFolder extends ShortPixelEntity{
|
|
| 132 |
$tpath = trailingslashit($path) . $t;
|
| 133 |
if (is_dir($tpath)) {
|
| 134 |
self::checkFolderContentsRecursive($tpath, $callback);
|
| 135 |
-
} elseif( WPShortPixel::
|
| 136 |
&& !(in_array($tpath, $reference) && $reference[$tpath]->compressedSize == filesize($tpath))) {
|
| 137 |
$changed[] = $tpath;
|
| 138 |
}
|
| 11 |
protected $tsCreated;
|
| 12 |
protected $tsUpdated;
|
| 13 |
|
| 14 |
+
protected $excludePatterns;
|
| 15 |
+
|
| 16 |
const TABLE_SUFFIX = 'folders';
|
| 17 |
|
| 18 |
+
public function __construct($data, $excludePatterns = false) {
|
| 19 |
parent::__construct($data);
|
| 20 |
+
$this->excludePatterns = $excludePatterns;
|
| 21 |
}
|
| 22 |
|
| 23 |
public static function checkFolder($folder, $base) {
|
| 84 |
if(in_array($t, $ignore)) continue;
|
| 85 |
if (is_dir($tpath)) {
|
| 86 |
$size += $this->countFiles($tpath);
|
| 87 |
+
} elseif(WPShortPixel::_isProcessablePath($tpath, array(), $this->excludePatterns)) {
|
| 88 |
$size++;
|
| 89 |
}
|
| 90 |
}
|
| 114 |
$tpath = trailingslashit($path) . $t;
|
| 115 |
if (is_dir($tpath)) {
|
| 116 |
self::getFileListRecursive($tpath, $fileHandle, $onlyNewerThan);
|
| 117 |
+
} elseif($add && WPShortPixel::_isProcessablePath($tpath, array(), WPShortPixelSettings::getOpt('excludePatterns'))) {
|
| 118 |
fwrite($fileHandle, $tpath . "\n");
|
| 119 |
}
|
| 120 |
}
|
| 135 |
$tpath = trailingslashit($path) . $t;
|
| 136 |
if (is_dir($tpath)) {
|
| 137 |
self::checkFolderContentsRecursive($tpath, $callback);
|
| 138 |
+
} elseif( WPShortPixel::_isProcessablePath($tpath, array(), WPShortPixelSettings::getOpt('excludePatterns'))
|
| 139 |
&& !(in_array($tpath, $reference) && $reference[$tpath]->compressedSize == filesize($tpath))) {
|
| 140 |
$changed[] = $tpath;
|
| 141 |
}
|
class/view/shortpixel_view.php
CHANGED
|
@@ -826,6 +826,13 @@ class ShortPixelView {
|
|
| 826 |
$autoMediaLibrary = ($settings->autoMediaLibrary ? 'checked' : '');
|
| 827 |
$optimizeRetina = ($settings->optimizeRetina ? 'checked' : '');
|
| 828 |
$optimizePdfs = ($settings->optimizePdfs ? 'checked' : '');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 829 |
?>
|
| 830 |
<div class="wp-shortpixel-options">
|
| 831 |
<?php if(!$this->ctrl->getVerifiedKey()) { ?>
|
|
@@ -953,6 +960,25 @@ class ShortPixelView {
|
|
| 953 |
<input name="optimizePdfs" type="checkbox" id="optimizePdfs" <?php echo( $optimizePdfs );?>> <?php _e('Automatically optimize PDF documents.','shortpixel-image-optimiser');?>
|
| 954 |
</td>
|
| 955 |
</tr>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 956 |
<tr>
|
| 957 |
<th scope="row"><label for="authentication"><?php _e('HTTP AUTH credentials','shortpixel-image-optimiser');?></label></th>
|
| 958 |
<td>
|
| 826 |
$autoMediaLibrary = ($settings->autoMediaLibrary ? 'checked' : '');
|
| 827 |
$optimizeRetina = ($settings->optimizeRetina ? 'checked' : '');
|
| 828 |
$optimizePdfs = ($settings->optimizePdfs ? 'checked' : '');
|
| 829 |
+
$excludePatterns = "";
|
| 830 |
+
if($settings->excludePatterns) {
|
| 831 |
+
foreach($settings->excludePatterns as $item) {
|
| 832 |
+
$excludePatterns .= $item['type'] . ":" . $item['value'] . ", ";
|
| 833 |
+
}
|
| 834 |
+
$excludePatterns = substr($excludePatterns, 0, -2);
|
| 835 |
+
}
|
| 836 |
?>
|
| 837 |
<div class="wp-shortpixel-options">
|
| 838 |
<?php if(!$this->ctrl->getVerifiedKey()) { ?>
|
| 960 |
<input name="optimizePdfs" type="checkbox" id="optimizePdfs" <?php echo( $optimizePdfs );?>> <?php _e('Automatically optimize PDF documents.','shortpixel-image-optimiser');?>
|
| 961 |
</td>
|
| 962 |
</tr>
|
| 963 |
+
<tr>
|
| 964 |
+
<th scope="row"><label for="excludePatterns"><?php _e('Exclude patterns','shortpixel-image-optimiser');?></label></th>
|
| 965 |
+
<td>
|
| 966 |
+
<input name="excludePatterns" type="text" id="excludePatterns" value="<?php echo( $excludePatterns );?>" class="regular-text" placeholder="<?php
|
| 967 |
+
_e('file:keepbig, path:/ignore_regex/i, size:1000x2000','shortpixel-image-optimiser');?>">
|
| 968 |
+
<?php _e('Exclude certain images from being optimized, based on patterns.','shortpixel-image-optimiser');?>
|
| 969 |
+
<p class="settings-info">
|
| 970 |
+
<?php _e('Add patterns separated by comma. A pattern consist of a <strong>type:value</strong> pair; the accepted types are '
|
| 971 |
+
. '<strong>"file"</strong>, <strong>"path"</strong> and <strong>"size"</strong>. '
|
| 972 |
+
. 'A file will be excluded if it matches any of the patterns. '
|
| 973 |
+
. '<br>For a <strong>"file"</strong> pattern only the filename will be matched but for a <strong>"path"</strong>, '
|
| 974 |
+
. 'all the path will be matched (useful for excluding certain subdirectories altoghether).'
|
| 975 |
+
. 'For these you can also use regular expressions accepted by preg_match, but without "," or ":". '
|
| 976 |
+
. '<br>For the <strong>"size"</strong> type, '
|
| 977 |
+
. 'which applies only to Media Library images, <strong>the main images (not thumbnails)</strong> that have the size in the specified range will be excluded. '
|
| 978 |
+
. 'The format for the "size" exclude is: <strong>minWidth</strong>-<strong>maxWidth</strong>x<strong>minHeight</strong>-<strong>maxHeight</strong>, for example <strong>size:1000-1100x2000-2200</strong>. You can also specify a precise size, as <strong>1000x2000</strong>.','shortpixel-image-optimiser');?>
|
| 979 |
+
</p>
|
| 980 |
+
</td>
|
| 981 |
+
</tr>
|
| 982 |
<tr>
|
| 983 |
<th scope="row"><label for="authentication"><?php _e('HTTP AUTH credentials','shortpixel-image-optimiser');?></label></th>
|
| 984 |
<td>
|
class/wp-short-pixel.php
CHANGED
|
@@ -29,7 +29,7 @@ class WPShortPixel {
|
|
| 29 |
$this->_settings = new WPShortPixelSettings();
|
| 30 |
$this->_apiInterface = new ShortPixelAPI($this->_settings);
|
| 31 |
$this->hasNextGen = ShortPixelNextGenAdapter::hasNextGen();
|
| 32 |
-
$this->spMetaDao = new ShortPixelCustomMetaDao(new WpShortPixelDb(), $this->_settings->
|
| 33 |
$this->prioQ = new ShortPixelQueue($this, $this->_settings);
|
| 34 |
$this->view = new ShortPixelView($this);
|
| 35 |
|
|
@@ -146,7 +146,7 @@ class WPShortPixel {
|
|
| 146 |
WPShortPixelSettings::debugResetOptions();
|
| 147 |
|
| 148 |
$settings = new WPShortPixelSettings();
|
| 149 |
-
$spMetaDao = new ShortPixelCustomMetaDao(new WpShortPixelDb(), $settings->
|
| 150 |
$spMetaDao->dropTables();
|
| 151 |
}
|
| 152 |
WPShortPixelSettings::onActivate();
|
|
@@ -331,7 +331,8 @@ class WPShortPixel {
|
|
| 331 |
$args = array(
|
| 332 |
'id' => 'shortpixel_processing',
|
| 333 |
'title' => '<div id="' . $id . '" title="' . $tooltip . '" ><img src="'
|
| 334 |
-
. plugins_url( 'res/img/'.$icon, SHORTPIXEL_PLUGIN_FILE ) . '" success-url="' . $successLink . '"><span class="shp-alert">!</span
|
|
|
|
| 335 |
'href' => $link,
|
| 336 |
'meta' => array('target'=> $blank, 'class' => 'shortpixel-toolbar-processing' . $extraClasses)
|
| 337 |
);
|
|
@@ -395,13 +396,18 @@ class WPShortPixel {
|
|
| 395 |
//else
|
| 396 |
//self::log("IMG: Auto-analyzing file ID #{$ID}");
|
| 397 |
|
| 398 |
-
if(
|
|
|
|
|
|
|
|
|
|
|
|
|
| 399 |
{//not a file that we can process
|
| 400 |
$meta['ShortPixelImprovement'] = __('Optimization N/A','shortpixel-image-optimiser');
|
| 401 |
return $meta;
|
| 402 |
}
|
| 403 |
else
|
| 404 |
{//the kind of file we can process. goody.
|
|
|
|
| 405 |
$this->prioQ->push($ID);
|
| 406 |
//that's a hack for watermarking plugins, don't send the image right away to processing, only add it in the queue
|
| 407 |
include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
|
|
@@ -443,7 +449,7 @@ class WPShortPixel {
|
|
| 443 |
}
|
| 444 |
if($folderId == -1) { //if not found, create
|
| 445 |
$galleryPath = dirname($imageFsPath);
|
| 446 |
-
$folder = new ShortPixelFolder(array("path" => $galleryPath));
|
| 447 |
$folderMsg = $this->spMetaDao->saveFolder($folder);
|
| 448 |
$folderId = $folder->getId();
|
| 449 |
//self::log("NG Image Upload: created folder from path $galleryPath : Folder info: " . json_encode($folder));
|
|
@@ -575,7 +581,7 @@ class WPShortPixel {
|
|
| 575 |
|
| 576 |
foreach ( $resultsPostMeta as $itemMetaData ) {
|
| 577 |
$crtStartQueryID = $itemMetaData->post_id;
|
| 578 |
-
if(!in_array($crtStartQueryID, $idList) &&
|
| 579 |
$item = new ShortPixelMetaFacade($crtStartQueryID);
|
| 580 |
$meta = $item->getMeta();//wp_get_attachment_metadata($crtStartQueryID);
|
| 581 |
|
|
@@ -738,8 +744,7 @@ class WPShortPixel {
|
|
| 738 |
$firstUrlAndPaths = $URLsAndPATHs;
|
| 739 |
}
|
| 740 |
} catch(Exception $e) { // Exception("Post metadata is corrupt (No attachment URL)") or Exception("Image files are missing.")
|
| 741 |
-
$
|
| 742 |
-
$crtItemHandler->incrementRetries();
|
| 743 |
if(! $this->prioQ->remove($crtItemHandler->getQueuedId()) ){
|
| 744 |
$this->advanceBulk($crtItemHandler->getId());
|
| 745 |
$res['searching'] = true;
|
|
@@ -869,9 +874,10 @@ class WPShortPixel {
|
|
| 869 |
}
|
| 870 |
else {
|
| 871 |
if(isset($result['Code'])) {
|
| 872 |
-
$itemHandler->
|
|
|
|
|
|
|
| 873 |
}
|
| 874 |
-
$itemHandler->incrementRetries();
|
| 875 |
}
|
| 876 |
}
|
| 877 |
elseif ($result["Status"] == ShortPixelAPI::STATUS_SKIP
|
|
@@ -1039,7 +1045,7 @@ class WPShortPixel {
|
|
| 1039 |
|
| 1040 |
//custom hook
|
| 1041 |
public function optimizeNowHook($imageId, $manual = false) {
|
| 1042 |
-
if(
|
| 1043 |
$this->prioQ->push($imageId);
|
| 1044 |
$itemHandler = new ShortPixelMetaFacade($imageId);
|
| 1045 |
$path = get_attached_file($imageId);//get the full file PATH
|
|
@@ -1047,7 +1053,7 @@ class WPShortPixel {
|
|
| 1047 |
$ret = array("Status" => ShortPixelAPI::STATUS_SKIP, "Message" => $imageId);
|
| 1048 |
} else {
|
| 1049 |
try {
|
| 1050 |
-
$this->sendToProcessing($itemHandler);
|
| 1051 |
$ret = array("Status" => ShortPixelAPI::STATUS_SUCCESS, "Message" => "");
|
| 1052 |
} catch(Exception $e) { // Exception("Post metadata is corrupt (No attachment URL)")
|
| 1053 |
$itemHandler->getMeta();
|
|
@@ -1343,7 +1349,7 @@ class WPShortPixel {
|
|
| 1343 |
$file = get_attached_file($ID);
|
| 1344 |
$meta = wp_get_attachment_metadata($ID);
|
| 1345 |
|
| 1346 |
-
if(self::
|
| 1347 |
{
|
| 1348 |
try {
|
| 1349 |
$SubDir = ShortPixelMetaFacade::returnSubDir($file, ShortPixelMetaFacade::MEDIA_LIBRARY_TYPE);
|
|
@@ -1616,18 +1622,6 @@ class WPShortPixel {
|
|
| 1616 |
));
|
| 1617 |
|
| 1618 |
|
| 1619 |
-
//parse all images and set the right flag that the image has no backup
|
| 1620 |
-
/* this is obsolete as the backup exists decision is taken on verfication of the actual backup files
|
| 1621 |
-
foreach($attachments as $attachment)
|
| 1622 |
-
{
|
| 1623 |
-
if(self::isProcessable($attachment->ID) == false) continue;
|
| 1624 |
-
|
| 1625 |
-
$meta = wp_get_attachment_metadata($attachment->ID);
|
| 1626 |
-
$meta['ShortPixel']['NoBackup'] = true;
|
| 1627 |
-
wp_update_attachment_metadata($attachment->ID, $meta);
|
| 1628 |
-
}
|
| 1629 |
-
*/
|
| 1630 |
-
|
| 1631 |
//delete the actual files on disk
|
| 1632 |
$this->deleteDir(SP_BACKUP_FOLDER);//call a recursive function to empty files and sub-dirs in backup dir
|
| 1633 |
}
|
|
@@ -1879,6 +1873,21 @@ class WPShortPixel {
|
|
| 1879 |
$this->_settings->createWebp = (isset($_POST['createWebp']) ? 1: 0);
|
| 1880 |
$this->_settings->optimizeRetina = (isset($_POST['optimizeRetina']) ? 1: 0);
|
| 1881 |
$this->_settings->optimizePdfs = (isset($_POST['optimizePdfs']) ? 1: 0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1882 |
$this->_settings->frontBootstrap = (isset($_POST['frontBootstrap']) ? 1: 0);
|
| 1883 |
$this->_settings->autoMediaLibrary = (isset($_POST['autoMediaLibrary']) ? 1: 0);
|
| 1884 |
|
|
@@ -2123,13 +2132,13 @@ class WPShortPixel {
|
|
| 2123 |
public function generateCustomColumn( $column_name, $id, $extended = false ) {
|
| 2124 |
if( 'wp-shortPixel' == $column_name ) {
|
| 2125 |
|
| 2126 |
-
|
| 2127 |
-
if(!self::isProcessablePath($file)) {
|
| 2128 |
$renderData['status'] = 'n/a';
|
| 2129 |
$this->view->renderCustomColumn($id, $renderData, $extended);
|
| 2130 |
return;
|
| 2131 |
}
|
| 2132 |
-
|
|
|
|
| 2133 |
$data = wp_get_attachment_metadata($id);
|
| 2134 |
$fileExtension = strtolower(pathinfo($file, PATHINFO_EXTENSION));
|
| 2135 |
$invalidKey = !$this->_settings->verifiedKey;
|
|
@@ -2167,7 +2176,7 @@ class WPShortPixel {
|
|
| 2167 |
$renderData['status'] = $fileExtension == "pdf" ? 'pdfOptimized' : 'imgOptimized';
|
| 2168 |
$renderData['percent'] = $data['ShortPixelImprovement'];
|
| 2169 |
$renderData['bonus'] = ($data['ShortPixelImprovement'] < 5);
|
| 2170 |
-
$renderData['backup'] = $this->getBackupFolderAny(
|
| 2171 |
$renderData['type'] = isset($data['ShortPixel']['type']) ? $data['ShortPixel']['type'] : '';
|
| 2172 |
$renderData['invType'] = ShortPixelAPI::getCompressionTypeName($this->getOtherCompressionType(ShortPixelAPI::getCompressionTypeCode($renderData['type'])));
|
| 2173 |
$renderData['thumbsTotal'] = $sizesCount;
|
|
@@ -2194,9 +2203,9 @@ class WPShortPixel {
|
|
| 2194 |
}
|
| 2195 |
$renderData['webpCount'] = $webP;
|
| 2196 |
}
|
| 2197 |
-
elseif($data['ShortPixelImprovement'] == __('Optimization N/A','shortpixel-image-optimiser')) { //We don't optimize this
|
| 2198 |
$renderData['status'] = 'n/a';
|
| 2199 |
-
}
|
| 2200 |
elseif(isset($meta['ShortPixel']['BulkProcessing'])) { //Scheduled to bulk.
|
| 2201 |
$renderData['status'] = $quotaExceeded ? 'quotaExceeded' : 'optimizeNow';
|
| 2202 |
$renderData['message'] = 'Waiting for bulk processing.';
|
|
@@ -2220,7 +2229,9 @@ class WPShortPixel {
|
|
| 2220 |
elseif(isset($data['ShortPixel']['WaitingProcessing'])) {
|
| 2221 |
$renderData['status'] = $quotaExceeded ? 'quotaExceeded' : 'retry';
|
| 2222 |
$renderData['message'] = "<img src=\"" . plugins_url( 'res/img/loading.gif', SHORTPIXEL_PLUGIN_FILE ) . "\" class='sp-loading-small'> " . __("Image waiting to be processed.",'shortpixel-image-optimiser');
|
| 2223 |
-
if($id > $this->prioQ->getFlagBulkId() || !$this->prioQ->bulkRunning())
|
|
|
|
|
|
|
| 2224 |
}
|
| 2225 |
else { //finally
|
| 2226 |
$renderData['status'] = $quotaExceeded ? 'quotaExceeded' : 'optimizeNow';
|
|
@@ -2340,20 +2351,69 @@ class WPShortPixel {
|
|
| 2340 |
return round($bytes, $precision) . ' ' . $units[$pow];
|
| 2341 |
}
|
| 2342 |
|
| 2343 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2344 |
$path = get_attached_file($ID);//get the full file PATH
|
| 2345 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2346 |
}
|
| 2347 |
|
| 2348 |
-
static public function
|
| 2349 |
$pathParts = pathinfo($path);
|
| 2350 |
$ext = $pathParts['extension'];
|
| 2351 |
-
if( isset($ext) && in_array(strtolower($ext), array_diff(self::$PROCESSABLE_EXTENSIONS, $
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2352 |
return true;
|
| 2353 |
} else {
|
| 2354 |
return false;
|
| 2355 |
}
|
| 2356 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2357 |
|
| 2358 |
|
| 2359 |
//return an array with URL(s) and PATH(s) for this file
|
| 29 |
$this->_settings = new WPShortPixelSettings();
|
| 30 |
$this->_apiInterface = new ShortPixelAPI($this->_settings);
|
| 31 |
$this->hasNextGen = ShortPixelNextGenAdapter::hasNextGen();
|
| 32 |
+
$this->spMetaDao = new ShortPixelCustomMetaDao(new WpShortPixelDb(), $this->_settings->excludePatterns);
|
| 33 |
$this->prioQ = new ShortPixelQueue($this, $this->_settings);
|
| 34 |
$this->view = new ShortPixelView($this);
|
| 35 |
|
| 146 |
WPShortPixelSettings::debugResetOptions();
|
| 147 |
|
| 148 |
$settings = new WPShortPixelSettings();
|
| 149 |
+
$spMetaDao = new ShortPixelCustomMetaDao(new WpShortPixelDb(), $settings->excludePatterns);
|
| 150 |
$spMetaDao->dropTables();
|
| 151 |
}
|
| 152 |
WPShortPixelSettings::onActivate();
|
| 331 |
$args = array(
|
| 332 |
'id' => 'shortpixel_processing',
|
| 333 |
'title' => '<div id="' . $id . '" title="' . $tooltip . '" ><img src="'
|
| 334 |
+
. plugins_url( 'res/img/'.$icon, SHORTPIXEL_PLUGIN_FILE ) . '" success-url="' . $successLink . '"><span class="shp-alert">!</span>'
|
| 335 |
+
.'<div class="cssload-container"><div class="cssload-speeding-wheel"></div></div></div>',
|
| 336 |
'href' => $link,
|
| 337 |
'meta' => array('target'=> $blank, 'class' => 'shortpixel-toolbar-processing' . $extraClasses)
|
| 338 |
);
|
| 396 |
//else
|
| 397 |
//self::log("IMG: Auto-analyzing file ID #{$ID}");
|
| 398 |
|
| 399 |
+
if(!$this->_settings->optimizePdfs && 'pdf' === pathinfo(get_attached_file($ID), PATHINFO_EXTENSION)) {
|
| 400 |
+
//pdf is not optimized automatically as per the option, but can be optimized by button. Nothing to do.
|
| 401 |
+
return $meta;
|
| 402 |
+
}
|
| 403 |
+
elseif( self::_isProcessable($ID, array(), $this->_settings->excludePatterns, $meta) == false )
|
| 404 |
{//not a file that we can process
|
| 405 |
$meta['ShortPixelImprovement'] = __('Optimization N/A','shortpixel-image-optimiser');
|
| 406 |
return $meta;
|
| 407 |
}
|
| 408 |
else
|
| 409 |
{//the kind of file we can process. goody.
|
| 410 |
+
|
| 411 |
$this->prioQ->push($ID);
|
| 412 |
//that's a hack for watermarking plugins, don't send the image right away to processing, only add it in the queue
|
| 413 |
include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
|
| 449 |
}
|
| 450 |
if($folderId == -1) { //if not found, create
|
| 451 |
$galleryPath = dirname($imageFsPath);
|
| 452 |
+
$folder = new ShortPixelFolder(array("path" => $galleryPath), $this->_settings->excludePatterns);
|
| 453 |
$folderMsg = $this->spMetaDao->saveFolder($folder);
|
| 454 |
$folderId = $folder->getId();
|
| 455 |
//self::log("NG Image Upload: created folder from path $galleryPath : Folder info: " . json_encode($folder));
|
| 581 |
|
| 582 |
foreach ( $resultsPostMeta as $itemMetaData ) {
|
| 583 |
$crtStartQueryID = $itemMetaData->post_id;
|
| 584 |
+
if(!in_array($crtStartQueryID, $idList) && $this->isProcessable($crtStartQueryID, ($this->_settings->optimizePdfs ? array() : array('pdf')))) {
|
| 585 |
$item = new ShortPixelMetaFacade($crtStartQueryID);
|
| 586 |
$meta = $item->getMeta();//wp_get_attachment_metadata($crtStartQueryID);
|
| 587 |
|
| 744 |
$firstUrlAndPaths = $URLsAndPATHs;
|
| 745 |
}
|
| 746 |
} catch(Exception $e) { // Exception("Post metadata is corrupt (No attachment URL)") or Exception("Image files are missing.")
|
| 747 |
+
$crtItemHandler->incrementRetries(1, ShortPixelAPI::ERR_FILE_NOT_FOUND, $e->getMessage());
|
|
|
|
| 748 |
if(! $this->prioQ->remove($crtItemHandler->getQueuedId()) ){
|
| 749 |
$this->advanceBulk($crtItemHandler->getId());
|
| 750 |
$res['searching'] = true;
|
| 874 |
}
|
| 875 |
else {
|
| 876 |
if(isset($result['Code'])) {
|
| 877 |
+
$itemHandler->incrementRetries(1, $result['Code'], $result["Message"]);
|
| 878 |
+
} else {
|
| 879 |
+
$itemHandler->incrementRetries(1, -999, "Connection error (" . $result["Message"] . ")" );
|
| 880 |
}
|
|
|
|
| 881 |
}
|
| 882 |
}
|
| 883 |
elseif ($result["Status"] == ShortPixelAPI::STATUS_SKIP
|
| 1045 |
|
| 1046 |
//custom hook
|
| 1047 |
public function optimizeNowHook($imageId, $manual = false) {
|
| 1048 |
+
if($this->isProcessable($imageId)) {
|
| 1049 |
$this->prioQ->push($imageId);
|
| 1050 |
$itemHandler = new ShortPixelMetaFacade($imageId);
|
| 1051 |
$path = get_attached_file($imageId);//get the full file PATH
|
| 1053 |
$ret = array("Status" => ShortPixelAPI::STATUS_SKIP, "Message" => $imageId);
|
| 1054 |
} else {
|
| 1055 |
try {
|
| 1056 |
+
$this->sendToProcessing($itemHandler, false, $itemHandler->getMeta()->getThumbsTodo());
|
| 1057 |
$ret = array("Status" => ShortPixelAPI::STATUS_SUCCESS, "Message" => "");
|
| 1058 |
} catch(Exception $e) { // Exception("Post metadata is corrupt (No attachment URL)")
|
| 1059 |
$itemHandler->getMeta();
|
| 1349 |
$file = get_attached_file($ID);
|
| 1350 |
$meta = wp_get_attachment_metadata($ID);
|
| 1351 |
|
| 1352 |
+
if(self::_isProcessable($ID) != false) //we use the static isProcessable to bypass the exclude patterns
|
| 1353 |
{
|
| 1354 |
try {
|
| 1355 |
$SubDir = ShortPixelMetaFacade::returnSubDir($file, ShortPixelMetaFacade::MEDIA_LIBRARY_TYPE);
|
| 1622 |
));
|
| 1623 |
|
| 1624 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1625 |
//delete the actual files on disk
|
| 1626 |
$this->deleteDir(SP_BACKUP_FOLDER);//call a recursive function to empty files and sub-dirs in backup dir
|
| 1627 |
}
|
| 1873 |
$this->_settings->createWebp = (isset($_POST['createWebp']) ? 1: 0);
|
| 1874 |
$this->_settings->optimizeRetina = (isset($_POST['optimizeRetina']) ? 1: 0);
|
| 1875 |
$this->_settings->optimizePdfs = (isset($_POST['optimizePdfs']) ? 1: 0);
|
| 1876 |
+
if(isset($_POST['excludePatterns']) && strlen($_POST['excludePatterns'])) {
|
| 1877 |
+
$patterns = array();
|
| 1878 |
+
$items = explode(',', $_POST['excludePatterns']);
|
| 1879 |
+
foreach($items as $pat) {
|
| 1880 |
+
$parts = explode(':', $pat);
|
| 1881 |
+
if(count($parts) == 1) {
|
| 1882 |
+
$patterns[] = array("type" =>"name", "value" => trim($pat));
|
| 1883 |
+
} else {
|
| 1884 |
+
$patterns[] = array("type" =>trim($parts[0]), "value" => trim($parts[1]));
|
| 1885 |
+
}
|
| 1886 |
+
}
|
| 1887 |
+
$this->_settings->excludePatterns = $patterns;
|
| 1888 |
+
} else {
|
| 1889 |
+
$this->_settings->excludePatterns = array();
|
| 1890 |
+
}
|
| 1891 |
$this->_settings->frontBootstrap = (isset($_POST['frontBootstrap']) ? 1: 0);
|
| 1892 |
$this->_settings->autoMediaLibrary = (isset($_POST['autoMediaLibrary']) ? 1: 0);
|
| 1893 |
|
| 2132 |
public function generateCustomColumn( $column_name, $id, $extended = false ) {
|
| 2133 |
if( 'wp-shortPixel' == $column_name ) {
|
| 2134 |
|
| 2135 |
+
if(!$this->isProcessable($id)) {
|
|
|
|
| 2136 |
$renderData['status'] = 'n/a';
|
| 2137 |
$this->view->renderCustomColumn($id, $renderData, $extended);
|
| 2138 |
return;
|
| 2139 |
}
|
| 2140 |
+
|
| 2141 |
+
$file = get_attached_file($id);
|
| 2142 |
$data = wp_get_attachment_metadata($id);
|
| 2143 |
$fileExtension = strtolower(pathinfo($file, PATHINFO_EXTENSION));
|
| 2144 |
$invalidKey = !$this->_settings->verifiedKey;
|
| 2176 |
$renderData['status'] = $fileExtension == "pdf" ? 'pdfOptimized' : 'imgOptimized';
|
| 2177 |
$renderData['percent'] = $data['ShortPixelImprovement'];
|
| 2178 |
$renderData['bonus'] = ($data['ShortPixelImprovement'] < 5);
|
| 2179 |
+
$renderData['backup'] = $this->getBackupFolderAny($file, $sizesCount? $data['sizes'] : array());
|
| 2180 |
$renderData['type'] = isset($data['ShortPixel']['type']) ? $data['ShortPixel']['type'] : '';
|
| 2181 |
$renderData['invType'] = ShortPixelAPI::getCompressionTypeName($this->getOtherCompressionType(ShortPixelAPI::getCompressionTypeCode($renderData['type'])));
|
| 2182 |
$renderData['thumbsTotal'] = $sizesCount;
|
| 2203 |
}
|
| 2204 |
$renderData['webpCount'] = $webP;
|
| 2205 |
}
|
| 2206 |
+
/* elseif($data['ShortPixelImprovement'] == __('Optimization N/A','shortpixel-image-optimiser')) { //We don't optimize this
|
| 2207 |
$renderData['status'] = 'n/a';
|
| 2208 |
+
}*/
|
| 2209 |
elseif(isset($meta['ShortPixel']['BulkProcessing'])) { //Scheduled to bulk.
|
| 2210 |
$renderData['status'] = $quotaExceeded ? 'quotaExceeded' : 'optimizeNow';
|
| 2211 |
$renderData['message'] = 'Waiting for bulk processing.';
|
| 2229 |
elseif(isset($data['ShortPixel']['WaitingProcessing'])) {
|
| 2230 |
$renderData['status'] = $quotaExceeded ? 'quotaExceeded' : 'retry';
|
| 2231 |
$renderData['message'] = "<img src=\"" . plugins_url( 'res/img/loading.gif', SHORTPIXEL_PLUGIN_FILE ) . "\" class='sp-loading-small'> " . __("Image waiting to be processed.",'shortpixel-image-optimiser');
|
| 2232 |
+
if(!$quotaExceeded && ($id > $this->prioQ->getFlagBulkId() || !$this->prioQ->bulkRunning())) {
|
| 2233 |
+
$this->prioQ->push($id); //should be there but just to make sure
|
| 2234 |
+
}
|
| 2235 |
}
|
| 2236 |
else { //finally
|
| 2237 |
$renderData['status'] = $quotaExceeded ? 'quotaExceeded' : 'optimizeNow';
|
| 2351 |
return round($bytes, $precision) . ' ' . $units[$pow];
|
| 2352 |
}
|
| 2353 |
|
| 2354 |
+
public function isProcessable($ID, $excludeExtensions = array()) {
|
| 2355 |
+
$excludePatterns = $this->_settings->excludePatterns;
|
| 2356 |
+
return self::_isProcessable($ID, $excludeExtensions, $excludePatterns);
|
| 2357 |
+
}
|
| 2358 |
+
|
| 2359 |
+
public function isProcessablePath($path, $excludeExtensions = array()) {
|
| 2360 |
+
$excludePatterns = $this->_settings->excludePatterns;
|
| 2361 |
+
return self::_isProcessablePath($path, $excludeExtensions, $excludePatterns);
|
| 2362 |
+
}
|
| 2363 |
+
|
| 2364 |
+
static public function _isProcessable($ID, $excludeExtensions = array(), $excludePatterns = array(), $meta = false) {
|
| 2365 |
$path = get_attached_file($ID);//get the full file PATH
|
| 2366 |
+
if(isset($excludePatterns) && is_array($excludePatterns)) {
|
| 2367 |
+
foreach($excludePatterns as $excludePattern) {
|
| 2368 |
+
$type = $excludePattern["type"];
|
| 2369 |
+
if($type == "size") {
|
| 2370 |
+
$meta = $meta? $meta : wp_get_attachment_metadata($ID);
|
| 2371 |
+
if( isset($meta["width"]) && isset($meta["height"])
|
| 2372 |
+
&& self::isProcessableSize($meta["width"], $meta["height"], $excludePattern["value"]) === false){
|
| 2373 |
+
return false;
|
| 2374 |
+
}
|
| 2375 |
+
}
|
| 2376 |
+
}
|
| 2377 |
+
}
|
| 2378 |
+
return $path ? self::_isProcessablePath($path, $excludeExtensions, $excludePatterns) : false;
|
| 2379 |
}
|
| 2380 |
|
| 2381 |
+
static public function _isProcessablePath($path, $excludeExtensions = array(), $excludePatterns = array()) {
|
| 2382 |
$pathParts = pathinfo($path);
|
| 2383 |
$ext = $pathParts['extension'];
|
| 2384 |
+
if( isset($ext) && in_array(strtolower($ext), array_diff(self::$PROCESSABLE_EXTENSIONS, $excludeExtensions))) {
|
| 2385 |
+
//apply patterns defined by user to exclude some file names or paths
|
| 2386 |
+
if(!$excludePatterns || !is_array($excludePatterns)) { return true; }
|
| 2387 |
+
foreach($excludePatterns as $item) {
|
| 2388 |
+
$type = trim($item["type"]);
|
| 2389 |
+
if(in_array($type, array("name", "path"))) {
|
| 2390 |
+
$pattern = trim($item["value"]);
|
| 2391 |
+
$target = $type == "name" ? ShortPixelAPI::MB_basename($path) : $path;
|
| 2392 |
+
if( $pattern[0] == '/' && preg_match($pattern, $target) //search as regex pattern if starts with a /
|
| 2393 |
+
|| $pattern[0] != '/' && strpos($target, $pattern) !== false) { //search as a substring if not
|
| 2394 |
+
return false;
|
| 2395 |
+
}
|
| 2396 |
+
}
|
| 2397 |
+
}
|
| 2398 |
return true;
|
| 2399 |
} else {
|
| 2400 |
return false;
|
| 2401 |
}
|
| 2402 |
}
|
| 2403 |
+
|
| 2404 |
+
static public function isProcessableSize($width, $height, $excludePattern) {
|
| 2405 |
+
$ranges = preg_split("/(x|×)/",$excludePattern);
|
| 2406 |
+
$widthBounds = explode("-", $ranges[0]);
|
| 2407 |
+
$heightBounds = isset($ranges[1]) ? explode("-", $ranges[1]) : false;
|
| 2408 |
+
if( $width >= 0 + $widthBounds[0]
|
| 2409 |
+
&& (!isset($widthBounds[1]) || isset($widthBounds[1]) && $width <= 0 + $widthBounds[1])
|
| 2410 |
+
&& ( $heightBounds === false
|
| 2411 |
+
|| ($height >= 0 + $heightBounds[0]
|
| 2412 |
+
&& (!isset($heightBounds[1]) || isset($heightBounds[1]) && $height <= 0 + $heightBounds[1])))) {
|
| 2413 |
+
return false;
|
| 2414 |
+
}
|
| 2415 |
+
return true;
|
| 2416 |
+
}
|
| 2417 |
|
| 2418 |
|
| 2419 |
//return an array with URL(s) and PATH(s) for this file
|
class/wp-shortpixel-settings.php
CHANGED
|
@@ -15,76 +15,77 @@ class WPShortPixelSettings {
|
|
| 15 |
|
| 16 |
private static $_optionsMap = array(
|
| 17 |
//This one is accessed also directly via get_option
|
| 18 |
-
'frontBootstrap' => 'wp-short-pixel-front-bootstrap', //set to 1 when need the plugin active for logged in user in the front-end
|
| 19 |
-
'lastBackAction' => 'wp-short-pixel-last-back-action', //when less than 10 min. passed from this timestamp, the front-bootstrap is ineffective.
|
| 20 |
|
| 21 |
//optimization options
|
| 22 |
-
'apiKey' => 'wp-short-pixel-apiKey',
|
| 23 |
-
'verifiedKey' => 'wp-short-pixel-verifiedKey',
|
| 24 |
-
'compressionType' => 'wp-short-pixel-compression',
|
| 25 |
-
'processThumbnails' => 'wp-short-process_thumbnails',
|
| 26 |
-
'keepExif' => 'wp-short-pixel-keep-exif',
|
| 27 |
-
'CMYKtoRGBconversion' => 'wp-short-pixel_cmyk2rgb',
|
| 28 |
-
'createWebp' => 'wp-short-create-webp',
|
| 29 |
-
'optimizeRetina' => 'wp-short-pixel-optimize-retina',
|
| 30 |
-
'backupImages' => 'wp-short-backup_images',
|
| 31 |
-
'resizeImages' => 'wp-short-pixel-resize-images',
|
| 32 |
-
'resizeType' => 'wp-short-pixel-resize-type',
|
| 33 |
-
'resizeWidth' => 'wp-short-pixel-resize-width',
|
| 34 |
-
'resizeHeight' => 'wp-short-pixel-resize-height',
|
| 35 |
-
'siteAuthUser' => 'wp-short-pixel-site-auth-user',
|
| 36 |
-
'siteAuthPass' => 'wp-short-pixel-site-auth-pass',
|
| 37 |
-
'autoMediaLibrary' => 'wp-short-pixel-auto-media-library',
|
| 38 |
-
'optimizePdfs' => 'wp-short-pixel-optimize-pdfs',
|
|
|
|
| 39 |
|
| 40 |
//optimize other images than the ones in Media Library
|
| 41 |
-
'includeNextGen' => 'wp-short-pixel-include-next-gen',
|
| 42 |
-
'hasCustomFolders' => 'wp-short-pixel-has-custom-folders',
|
| 43 |
-
'customBulkPaused' => 'wp-short-pixel-custom-bulk-paused',
|
| 44 |
|
| 45 |
//stats, notices, etc.
|
| 46 |
-
'currentTotalFiles' => 'wp-short-pixel-current-total-files',
|
| 47 |
-
'fileCount' => 'wp-short-pixel-fileCount',
|
| 48 |
-
'thumbsCount' => 'wp-short-pixel-thumbnail-count',
|
| 49 |
-
'under5Percent' => 'wp-short-pixel-files-under-5-percent',
|
| 50 |
-
'savedSpace' => 'wp-short-pixel-savedSpace',
|
| 51 |
-
'averageCompression' => 'wp-short-pixel-averageCompression',
|
| 52 |
-
'apiRetries' => 'wp-short-pixel-api-retries',
|
| 53 |
-
'totalOptimized' => 'wp-short-pixel-total-optimized',
|
| 54 |
-
'totalOriginal' => 'wp-short-pixel-total-original',
|
| 55 |
-
'quotaExceeded' => 'wp-short-pixel-quota-exceeded',
|
| 56 |
-
'httpProto' => 'wp-short-pixel-protocol',
|
| 57 |
-
'downloadProto' => 'wp-short-pixel-download-protocol',
|
| 58 |
-
'mediaAlert' => 'wp-short-pixel-media-alert',
|
| 59 |
-
'dismissedNotices' => 'wp-short-pixel-dismissed-notices',
|
| 60 |
-
'activationDate' => 'wp-short-pixel-activation-date',
|
| 61 |
-
'activationNotice' => 'wp-short-pixel-activation-notice',
|
| 62 |
-
'mediaLibraryViewMode' => 'wp-short-pixel-view-mode',
|
| 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',
|
| 70 |
-
'bulkCount' => 'wp-short-pixel-bulk-count',
|
| 71 |
-
'bulkPreviousPercent' => 'wp-short-pixel-bulk-previous-percent',
|
| 72 |
-
'bulkCurrentlyProcessed' => 'wp-short-pixel-bulk-processed-items',
|
| 73 |
-
'bulkAlreadyDoneCount' => 'wp-short-pixel-bulk-done-count',
|
| 74 |
-
'lastBulkStartTime' => 'wp-short-pixel-last-bulk-start-time',
|
| 75 |
-
'lastBulkSuccessTime' => 'wp-short-pixel-last-bulk-success-time',
|
| 76 |
-
'bulkRunningTime' => 'wp-short-pixel-bulk-running-time',
|
| 77 |
-
'cancelPointer' => 'wp-short-pixel-cancel-pointer',
|
| 78 |
-
'skipToCustom' => 'wp-short-pixel-skip-to-custom',
|
| 79 |
-
'bulkEverRan' => 'wp-short-pixel-bulk-ever-ran',
|
| 80 |
-
'flagId' => 'wp-short-pixel-flag-id',
|
| 81 |
-
'failedImages' => 'wp-short-pixel-failed-imgs',
|
| 82 |
-
'bulkProcessingStatus' => 'bulkProcessingStatus',
|
| 83 |
|
| 84 |
-
'priorityQueue' => 'wp-short-pixel-priorityQueue',
|
| 85 |
-
'prioritySkip' => 'wp-short-pixel-prioritySkip',
|
| 86 |
|
| 87 |
-
'' => '',
|
| 88 |
);
|
| 89 |
|
| 90 |
public function __construct() {
|
|
@@ -99,28 +100,19 @@ class WPShortPixelSettings {
|
|
| 99 |
$this->_processThumbnails = self::getOpt('wp-short-process_thumbnails', $this->_processThumbnails);
|
| 100 |
$this->_CMYKtoRGBconversion = self::getOpt('wp-short-pixel_cmyk2rgb', $this->_CMYKtoRGBconversion);
|
| 101 |
$this->_backupImages = self::getOpt('wp-short-backup_images', $this->_backupImages);
|
| 102 |
-
// the following lines practically set defaults for options if they're not set
|
| 103 |
-
self::getOpt('wp-short-pixel-auto-media-library', 1);
|
| 104 |
-
self::getOpt('wp-short-pixel-optimize-retina', 1);
|
| 105 |
-
self::getOpt('wp-short-pixel-optimize-pdfs', 1);
|
| 106 |
-
self::getOpt( 'wp-short-pixel-fileCount', 0);
|
| 107 |
-
self::getOpt( 'wp-short-pixel-thumbnail-count', 0);//amount of optimized thumbnails
|
| 108 |
-
self::getOpt( 'wp-short-pixel-files-under-5-percent', 0);//amount of optimized thumbnails
|
| 109 |
-
self::getOpt( 'wp-short-pixel-savedSpace', 0);
|
| 110 |
-
self::getOpt( 'wp-short-pixel-api-retries', 0);//sometimes we need to retry processing/downloading a file multiple times
|
| 111 |
-
self::getOpt( 'wp-short-pixel-quota-exceeded', 0);
|
| 112 |
-
self::getOpt( 'wp-short-pixel-total-original', 0);//amount of original data
|
| 113 |
-
self::getOpt( 'wp-short-pixel-total-optimized', 0);//amount of optimized
|
| 114 |
-
self::getOpt( 'wp-short-pixel-protocol', 'https');
|
| 115 |
-
|
| 116 |
$this->_resizeImages = self::getOpt( 'wp-short-pixel-resize-images', 0);
|
| 117 |
$this->_resizeWidth = self::getOpt( 'wp-short-pixel-resize-width', 0);
|
| 118 |
$this->_resizeHeight = self::getOpt( 'wp-short-pixel-resize-height', 0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 119 |
}
|
| 120 |
|
| 121 |
public static function debugResetOptions() {
|
| 122 |
foreach(self::$_optionsMap as $key => $val) {
|
| 123 |
-
delete_option($val);
|
| 124 |
}
|
| 125 |
if(isset($_SESSION["wp-short-pixel-priorityQueue"])) {
|
| 126 |
unset($_SESSION["wp-short-pixel-priorityQueue"]);
|
|
@@ -150,7 +142,7 @@ class WPShortPixelSettings {
|
|
| 150 |
public function __get($name)
|
| 151 |
{
|
| 152 |
if (array_key_exists($name, self::$_optionsMap)) {
|
| 153 |
-
return $this->getOpt(self::$_optionsMap[$name]);
|
| 154 |
}
|
| 155 |
$trace = debug_backtrace();
|
| 156 |
trigger_error(
|
|
@@ -164,14 +156,17 @@ class WPShortPixelSettings {
|
|
| 164 |
public function __set($name, $value) {
|
| 165 |
if (array_key_exists($name, self::$_optionsMap)) {
|
| 166 |
if($value !== null) {
|
| 167 |
-
$this->setOpt(self::$_optionsMap[$name], $value);
|
| 168 |
} else {
|
| 169 |
-
delete_option(self::$_optionsMap[$name]);
|
| 170 |
}
|
| 171 |
}
|
| 172 |
}
|
| 173 |
|
| 174 |
public static function getOpt($key, $default = null) {
|
|
|
|
|
|
|
|
|
|
| 175 |
if(get_option($key) === false) {
|
| 176 |
add_option( $key, $default, '', 'yes' );
|
| 177 |
}
|
| 15 |
|
| 16 |
private static $_optionsMap = array(
|
| 17 |
//This one is accessed also directly via get_option
|
| 18 |
+
'frontBootstrap' => array('key' => 'wp-short-pixel-front-bootstrap', 'default' => null), //set to 1 when need the plugin active for logged in user in the front-end
|
| 19 |
+
'lastBackAction' => array('key' => 'wp-short-pixel-last-back-action', 'default' => null), //when less than 10 min. passed from this timestamp, the front-bootstrap is ineffective.
|
| 20 |
|
| 21 |
//optimization options
|
| 22 |
+
'apiKey' => array('key' => 'wp-short-pixel-apiKey', 'default' => ''),
|
| 23 |
+
'verifiedKey' => array('key' => 'wp-short-pixel-verifiedKey', 'default' => false),
|
| 24 |
+
'compressionType' => array('key' => 'wp-short-pixel-compression', 'default' => 1),
|
| 25 |
+
'processThumbnails' => array('key' => 'wp-short-process_thumbnails', 'default' => null),
|
| 26 |
+
'keepExif' => array('key' => 'wp-short-pixel-keep-exif', 'default' => 0),
|
| 27 |
+
'CMYKtoRGBconversion' => array('key' => 'wp-short-pixel_cmyk2rgb', 'default' => 1),
|
| 28 |
+
'createWebp' => array('key' => 'wp-short-create-webp', 'default' => null),
|
| 29 |
+
'optimizeRetina' => array('key' => 'wp-short-pixel-optimize-retina', 'default' => 1),
|
| 30 |
+
'backupImages' => array('key' => 'wp-short-backup_images', 'default' => 1),
|
| 31 |
+
'resizeImages' => array('key' => 'wp-short-pixel-resize-images', 'default' => false),
|
| 32 |
+
'resizeType' => array('key' => 'wp-short-pixel-resize-type', 'default' => null),
|
| 33 |
+
'resizeWidth' => array('key' => 'wp-short-pixel-resize-width', 'default' => 0),
|
| 34 |
+
'resizeHeight' => array('key' => 'wp-short-pixel-resize-height', 'default' => 0),
|
| 35 |
+
'siteAuthUser' => array('key' => 'wp-short-pixel-site-auth-user', 'default' => null),
|
| 36 |
+
'siteAuthPass' => array('key' => 'wp-short-pixel-site-auth-pass', 'default' => null),
|
| 37 |
+
'autoMediaLibrary' => array('key' => 'wp-short-pixel-auto-media-library', 'default' => 1),
|
| 38 |
+
'optimizePdfs' => array('key' => 'wp-short-pixel-optimize-pdfs', 'default' => 1),
|
| 39 |
+
'excludePatterns' => array('key' => 'wp-short-pixel-exclude-patterns', 'default' => array()),
|
| 40 |
|
| 41 |
//optimize other images than the ones in Media Library
|
| 42 |
+
'includeNextGen' => array('key' => 'wp-short-pixel-include-next-gen', 'default' => null),
|
| 43 |
+
'hasCustomFolders' => array('key' => 'wp-short-pixel-has-custom-folders', 'default' => false),
|
| 44 |
+
'customBulkPaused' => array('key' => 'wp-short-pixel-custom-bulk-paused', 'default' => false),
|
| 45 |
|
| 46 |
//stats, notices, etc.
|
| 47 |
+
'currentTotalFiles' => array('key' => 'wp-short-pixel-current-total-files', 'default' => null),
|
| 48 |
+
'fileCount' => array('key' => 'wp-short-pixel-fileCount', 'default' => 0),
|
| 49 |
+
'thumbsCount' => array('key' => 'wp-short-pixel-thumbnail-count', 'default' => 0),
|
| 50 |
+
'under5Percent' => array('key' => 'wp-short-pixel-files-under-5-percent', 'default' => 0),
|
| 51 |
+
'savedSpace' => array('key' => 'wp-short-pixel-savedSpace', 'default' => 0),
|
| 52 |
+
'averageCompression' => array('key' => 'wp-short-pixel-averageCompression', 'default' => null),
|
| 53 |
+
'apiRetries' => array('key' => 'wp-short-pixel-api-retries', 'default' => 0),
|
| 54 |
+
'totalOptimized' => array('key' => 'wp-short-pixel-total-optimized', 'default' => 0),
|
| 55 |
+
'totalOriginal' => array('key' => 'wp-short-pixel-total-original', 'default' => 0),
|
| 56 |
+
'quotaExceeded' => array('key' => 'wp-short-pixel-quota-exceeded', 'default' => 0),
|
| 57 |
+
'httpProto' => array('key' => 'wp-short-pixel-protocol', 'default' => 'https'),
|
| 58 |
+
'downloadProto' => array('key' => 'wp-short-pixel-download-protocol', 'default' => null),
|
| 59 |
+
'mediaAlert' => array('key' => 'wp-short-pixel-media-alert', 'default' => null),
|
| 60 |
+
'dismissedNotices' => array('key' => 'wp-short-pixel-dismissed-notices', 'default' => null),
|
| 61 |
+
'activationDate' => array('key' => 'wp-short-pixel-activation-date', 'default' => null),
|
| 62 |
+
'activationNotice' => array('key' => 'wp-short-pixel-activation-notice', 'default' => null),
|
| 63 |
+
'mediaLibraryViewMode' => array('key' => 'wp-short-pixel-view-mode', 'default' => null),
|
| 64 |
+
'redirectedSettings' => array('key' => 'wp-short-pixel-redirected-settings', 'default' => null),
|
| 65 |
|
| 66 |
//bulk state machine
|
| 67 |
+
'bulkType' => array('key' => 'wp-short-pixel-bulk-type', 'default' => null),
|
| 68 |
+
'bulkLastStatus' => array('key' => 'wp-short-pixel-bulk-last-status', 'default' => null),
|
| 69 |
+
'startBulkId' => array('key' => 'wp-short-pixel-query-id-start', 'default' => 0),
|
| 70 |
+
'stopBulkId' => array('key' => 'wp-short-pixel-query-id-stop', 'default' => 0),
|
| 71 |
+
'bulkCount' => array('key' => 'wp-short-pixel-bulk-count', 'default' => 0),
|
| 72 |
+
'bulkPreviousPercent' => array('key' => 'wp-short-pixel-bulk-previous-percent', 'default' => 0),
|
| 73 |
+
'bulkCurrentlyProcessed' => array('key' => 'wp-short-pixel-bulk-processed-items', 'default' => 0),
|
| 74 |
+
'bulkAlreadyDoneCount' => array('key' => 'wp-short-pixel-bulk-done-count', 'default' => 0),
|
| 75 |
+
'lastBulkStartTime' => array('key' => 'wp-short-pixel-last-bulk-start-time', 'default' => 0),
|
| 76 |
+
'lastBulkSuccessTime' => array('key' => 'wp-short-pixel-last-bulk-success-time', 'default' => 0),
|
| 77 |
+
'bulkRunningTime' => array('key' => 'wp-short-pixel-bulk-running-time', 'default' => 0),
|
| 78 |
+
'cancelPointer' => array('key' => 'wp-short-pixel-cancel-pointer', 'default' => 0),
|
| 79 |
+
'skipToCustom' => array('key' => 'wp-short-pixel-skip-to-custom', 'default' => null),
|
| 80 |
+
'bulkEverRan' => array('key' => 'wp-short-pixel-bulk-ever-ran', 'default' => false),
|
| 81 |
+
'flagId' => array('key' => 'wp-short-pixel-flag-id', 'default' => 0),
|
| 82 |
+
'failedImages' => array('key' => 'wp-short-pixel-failed-imgs', 'default' => 0),
|
| 83 |
+
'bulkProcessingStatus' => array('key' => 'bulkProcessingStatus', 'default' => null),
|
| 84 |
|
| 85 |
+
'priorityQueue' => array('key' => 'wp-short-pixel-priorityQueue', 'default' => null),
|
| 86 |
+
'prioritySkip' => array('key' => 'wp-short-pixel-prioritySkip', 'default' => null),
|
| 87 |
|
| 88 |
+
//'' => array('key' => 'wp-short-pixel-', 'default' => null),
|
| 89 |
);
|
| 90 |
|
| 91 |
public function __construct() {
|
| 100 |
$this->_processThumbnails = self::getOpt('wp-short-process_thumbnails', $this->_processThumbnails);
|
| 101 |
$this->_CMYKtoRGBconversion = self::getOpt('wp-short-pixel_cmyk2rgb', $this->_CMYKtoRGBconversion);
|
| 102 |
$this->_backupImages = self::getOpt('wp-short-backup_images', $this->_backupImages);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 103 |
$this->_resizeImages = self::getOpt( 'wp-short-pixel-resize-images', 0);
|
| 104 |
$this->_resizeWidth = self::getOpt( 'wp-short-pixel-resize-width', 0);
|
| 105 |
$this->_resizeHeight = self::getOpt( 'wp-short-pixel-resize-height', 0);
|
| 106 |
+
|
| 107 |
+
// the following lines practically set defaults for options if they're not set
|
| 108 |
+
foreach(self::$_optionsMap as $opt) {
|
| 109 |
+
self::getOpt($opt['key'], $opt['default']);
|
| 110 |
+
}
|
| 111 |
}
|
| 112 |
|
| 113 |
public static function debugResetOptions() {
|
| 114 |
foreach(self::$_optionsMap as $key => $val) {
|
| 115 |
+
delete_option($val['key']);
|
| 116 |
}
|
| 117 |
if(isset($_SESSION["wp-short-pixel-priorityQueue"])) {
|
| 118 |
unset($_SESSION["wp-short-pixel-priorityQueue"]);
|
| 142 |
public function __get($name)
|
| 143 |
{
|
| 144 |
if (array_key_exists($name, self::$_optionsMap)) {
|
| 145 |
+
return $this->getOpt(self::$_optionsMap[$name]['key']);
|
| 146 |
}
|
| 147 |
$trace = debug_backtrace();
|
| 148 |
trigger_error(
|
| 156 |
public function __set($name, $value) {
|
| 157 |
if (array_key_exists($name, self::$_optionsMap)) {
|
| 158 |
if($value !== null) {
|
| 159 |
+
$this->setOpt(self::$_optionsMap[$name]['key'], $value);
|
| 160 |
} else {
|
| 161 |
+
delete_option(self::$_optionsMap[$name]['key']);
|
| 162 |
}
|
| 163 |
}
|
| 164 |
}
|
| 165 |
|
| 166 |
public static function getOpt($key, $default = null) {
|
| 167 |
+
if(isset(self::$_optionsMap[$key]['key'])) { //first try our name
|
| 168 |
+
$key = self::$_optionsMap[$key]['key'];
|
| 169 |
+
}
|
| 170 |
if(get_option($key) === false) {
|
| 171 |
add_option( $key, $default, '', 'yes' );
|
| 172 |
}
|
readme.txt
CHANGED
|
@@ -6,7 +6,7 @@ Tags: compress, image, compression, optimize, image optimizer, image compression
|
|
| 6 |
|
| 7 |
Requires at least: 3.2.0
|
| 8 |
Tested up to: 4.7
|
| 9 |
-
Stable tag: 4.
|
| 10 |
License: GPLv2 or later
|
| 11 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
| 12 |
|
|
@@ -221,6 +221,12 @@ The ShortPixel team is here to help. <a href="https://shortpixel.com/contact">Co
|
|
| 221 |
|
| 222 |
== Changelog ==
|
| 223 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 224 |
= 4.3.1 =
|
| 225 |
|
| 226 |
* hide API Key on single sites option ( define SHORTPIXEL_HIDE_API_KEY true in wp-config.php)
|
| 6 |
|
| 7 |
Requires at least: 3.2.0
|
| 8 |
Tested up to: 4.7
|
| 9 |
+
Stable tag: 4.4.0
|
| 10 |
License: GPLv2 or later
|
| 11 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
| 12 |
|
| 221 |
|
| 222 |
== Changelog ==
|
| 223 |
|
| 224 |
+
= 4.4.0 =
|
| 225 |
+
|
| 226 |
+
* exclude images based on patterns or image sizes, exclude paths based on patterns
|
| 227 |
+
* avoid using basename as a fallback for non-UTF8 filenames but instead use own code (basename strips first character if it's not ASCII-128 - for example ISO/IEC 8859-2)
|
| 228 |
+
* processing spinning indicator in the admin top bar with CSS to display OK on all admin themes.
|
| 229 |
+
|
| 230 |
= 4.3.1 =
|
| 231 |
|
| 232 |
* hide API Key on single sites option ( define SHORTPIXEL_HIDE_API_KEY true in wp-config.php)
|
res/css/short-pixel.css
CHANGED
|
@@ -176,10 +176,10 @@ div.shortpixel-rate-us > a:focus {
|
|
| 176 |
|
| 177 |
li.shortpixel-toolbar-processing > a.ab-item > div,
|
| 178 |
#wpadminbar li.shortpixel-toolbar-processing > a.ab-item > div{
|
| 179 |
-
background-image: url("../img/loading-dark-big.gif");
|
| 180 |
background-position: center center;
|
| 181 |
background-repeat: no-repeat;
|
| 182 |
-
height: 33px;
|
| 183 |
margin-top: -1px;
|
| 184 |
padding: 0 3px;
|
| 185 |
}
|
|
@@ -602,3 +602,50 @@ section#tab-resources p {
|
|
| 602 |
.sp-tabs h2:before{
|
| 603 |
content:none;
|
| 604 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 176 |
|
| 177 |
li.shortpixel-toolbar-processing > a.ab-item > div,
|
| 178 |
#wpadminbar li.shortpixel-toolbar-processing > a.ab-item > div{
|
| 179 |
+
/* background-image: url("../img/loading-dark-big.gif");
|
| 180 |
background-position: center center;
|
| 181 |
background-repeat: no-repeat;
|
| 182 |
+
*/ height: 33px;
|
| 183 |
margin-top: -1px;
|
| 184 |
padding: 0 3px;
|
| 185 |
}
|
| 602 |
.sp-tabs h2:before{
|
| 603 |
content:none;
|
| 604 |
}
|
| 605 |
+
|
| 606 |
+
#wpadminbar .shortpixel-toolbar-processing .cssload-container {
|
| 607 |
+
width: 100%;
|
| 608 |
+
height: 24px;
|
| 609 |
+
text-align: center;
|
| 610 |
+
position: absolute;
|
| 611 |
+
top: 0px;
|
| 612 |
+
left: -1px;
|
| 613 |
+
}
|
| 614 |
+
#wpadminbar .shortpixel-toolbar-processing.shortpixel-quota-exceeded .cssload-container{
|
| 615 |
+
display: none;
|
| 616 |
+
}
|
| 617 |
+
|
| 618 |
+
#wpadminbar .shortpixel-toolbar-processing .cssload-speeding-wheel {
|
| 619 |
+
width: 24px;
|
| 620 |
+
height: 24px;
|
| 621 |
+
opacity: 0.7;
|
| 622 |
+
margin: 0 auto;
|
| 623 |
+
border: 4px solid rgb(28,191,203);
|
| 624 |
+
border-radius: 50%;
|
| 625 |
+
border-left-color: transparent;
|
| 626 |
+
animation: cssload-spin 2000ms infinite linear;
|
| 627 |
+
-o-animation: cssload-spin 2000ms infinite linear;
|
| 628 |
+
-ms-animation: cssload-spin 2000ms infinite linear;
|
| 629 |
+
-webkit-animation: cssload-spin 2000ms infinite linear;
|
| 630 |
+
-moz-animation: cssload-spin 2000ms infinite linear;
|
| 631 |
+
}
|
| 632 |
+
|
| 633 |
+
@keyframes cssload-spin {
|
| 634 |
+
100%{ transform: rotate(360deg); transform: rotate(360deg); }
|
| 635 |
+
}
|
| 636 |
+
|
| 637 |
+
@-o-keyframes cssload-spin {
|
| 638 |
+
100%{ -o-transform: rotate(360deg); transform: rotate(360deg); }
|
| 639 |
+
}
|
| 640 |
+
|
| 641 |
+
@-ms-keyframes cssload-spin {
|
| 642 |
+
100%{ -ms-transform: rotate(360deg); transform: rotate(360deg); }
|
| 643 |
+
}
|
| 644 |
+
|
| 645 |
+
@-webkit-keyframes cssload-spin {
|
| 646 |
+
100%{ -webkit-transform: rotate(360deg); transform: rotate(360deg); }
|
| 647 |
+
}
|
| 648 |
+
|
| 649 |
+
@-moz-keyframes cssload-spin {
|
| 650 |
+
100%{ -moz-transform: rotate(360deg); transform: rotate(360deg); }
|
| 651 |
+
}
|
res/js/short-pixel.js
CHANGED
|
@@ -529,21 +529,21 @@ function checkBulkProcessingCallApi(){
|
|
| 529 |
ShortPixel.retry(e.message);
|
| 530 |
return;
|
| 531 |
}
|
|
|
|
|
|
|
| 532 |
var id = data["ImageID"];
|
| 533 |
|
| 534 |
var isBulkPage = (jQuery("div.short-pixel-bulk-page").length > 0);
|
| 535 |
|
| 536 |
switch (data["Status"]) {
|
| 537 |
case ShortPixel.STATUS_NO_KEY:
|
| 538 |
-
setCellMessage(id, "<a class='button button-smaller button-primary' href=\"https://shortpixel.com/wp-apikey\" target=\"_blank\">" + _spTr.getApiKey + "</a>"
|
| 539 |
-
data["Message"]);
|
| 540 |
showToolBarAlert(ShortPixel.STATUS_NO_KEY);
|
| 541 |
break;
|
| 542 |
case ShortPixel.STATUS_QUOTA_EXCEEDED:
|
| 543 |
-
setCellMessage(id, "<a class='button button-smaller button-primary' href=\"https://shortpixel.com/login/"
|
| 544 |
+ ShortPixel.API_KEY + "\" target=\"_blank\">" + _spTr.extendQuota + "</a>"
|
| 545 |
-
+ "<a class='button button-smaller' href='admin.php?action=shortpixel_check_quota'>" + _spTr.check__Quota + "</a>"
|
| 546 |
-
data["Message"]);
|
| 547 |
showToolBarAlert(ShortPixel.STATUS_QUOTA_EXCEEDED);
|
| 548 |
if(data['Stop'] == false) { //there are other items in the priority list, maybe processed, try those
|
| 549 |
setTimeout(checkBulkProgress, 5000);
|
| 529 |
ShortPixel.retry(e.message);
|
| 530 |
return;
|
| 531 |
}
|
| 532 |
+
ShortPixel.retries = 0;
|
| 533 |
+
|
| 534 |
var id = data["ImageID"];
|
| 535 |
|
| 536 |
var isBulkPage = (jQuery("div.short-pixel-bulk-page").length > 0);
|
| 537 |
|
| 538 |
switch (data["Status"]) {
|
| 539 |
case ShortPixel.STATUS_NO_KEY:
|
| 540 |
+
setCellMessage(id, data["Message"], "<a class='button button-smaller button-primary' href=\"https://shortpixel.com/wp-apikey\" target=\"_blank\">" + _spTr.getApiKey + "</a>");
|
|
|
|
| 541 |
showToolBarAlert(ShortPixel.STATUS_NO_KEY);
|
| 542 |
break;
|
| 543 |
case ShortPixel.STATUS_QUOTA_EXCEEDED:
|
| 544 |
+
setCellMessage(id, data["Message"], "<a class='button button-smaller button-primary' href=\"https://shortpixel.com/login/"
|
| 545 |
+ ShortPixel.API_KEY + "\" target=\"_blank\">" + _spTr.extendQuota + "</a>"
|
| 546 |
+
+ "<a class='button button-smaller' href='admin.php?action=shortpixel_check_quota'>" + _spTr.check__Quota + "</a>");
|
|
|
|
| 547 |
showToolBarAlert(ShortPixel.STATUS_QUOTA_EXCEEDED);
|
| 548 |
if(data['Stop'] == false) { //there are other items in the priority list, maybe processed, try those
|
| 549 |
setTimeout(checkBulkProgress, 5000);
|
shortpixel_api.php
CHANGED
|
@@ -23,6 +23,7 @@ class ShortPixelAPI {
|
|
| 23 |
const ERR_SAVE_BKP = -5;
|
| 24 |
const ERR_INCORRECT_FILE_SIZE = -6;
|
| 25 |
const ERR_DOWNLOAD = -7;
|
|
|
|
| 26 |
|
| 27 |
private $_settings;
|
| 28 |
private $_maxAttempts = 10;
|
|
@@ -103,8 +104,7 @@ class ShortPixelAPI {
|
|
| 103 |
|
| 104 |
if ( isset($errorMessage) )
|
| 105 |
{//set details inside file so user can know what happened
|
| 106 |
-
$itemHandler->
|
| 107 |
-
$itemHandler->incrementRetries();
|
| 108 |
return array("response" => array("code" => $errorCode, "message" => $errorMessage ));
|
| 109 |
}
|
| 110 |
|
|
@@ -171,8 +171,7 @@ class ShortPixelAPI {
|
|
| 171 |
{//keeps track of time
|
| 172 |
if ( $apiRetries > MAX_API_RETRIES )//we tried to process this time too many times, giving up...
|
| 173 |
{
|
| 174 |
-
$itemHandler->
|
| 175 |
-
$itemHandler->incrementRetries();
|
| 176 |
$this->_settings->apiRetries = 0; //fai added to solve a bug?
|
| 177 |
return array("Status" => self::STATUS_SKIP,
|
| 178 |
"Message" => ($itemHandler->getType() == ShortPixelMetaFacade::CUSTOM_TYPE ? __('Image ID','shortpixel-image-optimiser') : __('Media ID','shortpixel-image-optimiser'))
|
|
@@ -219,22 +218,24 @@ class ShortPixelAPI {
|
|
| 219 |
return $this->handleSuccess($APIresponse, $PATHs, $itemHandler, $compressionType);
|
| 220 |
default:
|
| 221 |
//handle error
|
|
|
|
| 222 |
if ( !file_exists($PATHs[0]) ) {
|
| 223 |
-
$itemHandler->incrementRetries(2);
|
| 224 |
$err = array("Status" => self::STATUS_NOT_FOUND, "Message" => "File not found on disk. "
|
| 225 |
. ($itemHandler->getType() == ShortPixelMetaFacade::CUSTOM_TYPE ? "Image" : "Media")
|
| 226 |
-
. " ID: " . $itemHandler->getId());
|
|
|
|
| 227 |
}
|
| 228 |
elseif ( isset($APIresponse[0]->Status->Message) ) {
|
| 229 |
//return array("Status" => self::STATUS_FAIL, "Message" => "There was an error and your request was not processed (" . $APIresponse[0]->Status->Message . "). REQ: " . json_encode($URLs));
|
| 230 |
-
$err = array("Status" => self::STATUS_FAIL, "Code" => (isset($APIresponse[0]->Status->Code) ? $APIresponse[0]->Status->Code :
|
| 231 |
"Message" => __('There was an error and your request was not processed.','shortpixel-image-optimiser')
|
| 232 |
. " (" . $APIresponse[0]->Status->Message . ")");
|
| 233 |
} else {
|
| 234 |
-
$err = array("Status" => self::STATUS_FAIL, "Message" => __('There was an error and your request was not processed.','shortpixel-image-optimiser')
|
|
|
|
| 235 |
}
|
| 236 |
|
| 237 |
-
$itemHandler->incrementRetries();
|
| 238 |
$meta = $itemHandler->getMeta();
|
| 239 |
if($meta->getRetries() >= MAX_FAIL_RETRIES) {
|
| 240 |
$meta->setStatus($APIresponse[0]->Status->Code);
|
|
@@ -447,8 +448,7 @@ class ShortPixelAPI {
|
|
| 447 |
if ( !@copy($source[$fileID], $filePATH) )
|
| 448 |
{//file couldn't be saved in backup folder
|
| 449 |
$msg = sprintf(__('Cannot save file <i>%s</i> in backup directory','shortpixel-image-optimiser'),self::MB_basename($source[$fileID]));
|
| 450 |
-
$itemHandler->
|
| 451 |
-
$itemHandler->incrementRetries();
|
| 452 |
return array("Status" => self::STATUS_FAIL, "Message" => $msg);
|
| 453 |
}
|
| 454 |
}
|
|
@@ -456,8 +456,7 @@ class ShortPixelAPI {
|
|
| 456 |
$NoBackup = true;
|
| 457 |
} else {//cannot write to the backup dir, return with an error
|
| 458 |
$msg = __('Cannot save file in backup directory','shortpixel-image-optimiser');
|
| 459 |
-
$itemHandler->
|
| 460 |
-
$itemHandler->incrementRetries();
|
| 461 |
return array("Status" => self::STATUS_FAIL, "Message" => $msg);
|
| 462 |
}
|
| 463 |
|
|
@@ -535,8 +534,7 @@ class ShortPixelAPI {
|
|
| 535 |
{
|
| 536 |
$msg = sprintf(__('Optimized version of %s file(s) couldn\'t be updated.','shortpixel-image-optimiser'),$writeFailed);
|
| 537 |
//#ShortPixelAPI::SaveMessageinMetadata($ID, 'Error: optimized version of ' . $writeFailed . ' file(s) couldn\'t be updated.');
|
| 538 |
-
$itemHandler->
|
| 539 |
-
$itemHandler->incrementRetries();
|
| 540 |
update_option('bulkProcessingStatus', "error");
|
| 541 |
return array("Status" => self::STATUS_FAIL, "Code" =>"write-fail", "Message" => $msg);
|
| 542 |
}
|
|
@@ -596,10 +594,19 @@ class ShortPixelAPI {
|
|
| 596 |
*/
|
| 597 |
static public function MB_basename($Path, $suffix = false){
|
| 598 |
$Separator = " qq ";
|
| 599 |
-
$
|
| 600 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 601 |
$Base = str_replace($Separator, "", $Base);
|
| 602 |
-
return $Base;
|
| 603 |
}
|
| 604 |
|
| 605 |
/**
|
| 23 |
const ERR_SAVE_BKP = -5;
|
| 24 |
const ERR_INCORRECT_FILE_SIZE = -6;
|
| 25 |
const ERR_DOWNLOAD = -7;
|
| 26 |
+
const ERR_UNKNOWN = -999;
|
| 27 |
|
| 28 |
private $_settings;
|
| 29 |
private $_maxAttempts = 10;
|
| 104 |
|
| 105 |
if ( isset($errorMessage) )
|
| 106 |
{//set details inside file so user can know what happened
|
| 107 |
+
$itemHandler->incrementRetries(1, $errorCode, $errorMessage);
|
|
|
|
| 108 |
return array("response" => array("code" => $errorCode, "message" => $errorMessage ));
|
| 109 |
}
|
| 110 |
|
| 171 |
{//keeps track of time
|
| 172 |
if ( $apiRetries > MAX_API_RETRIES )//we tried to process this time too many times, giving up...
|
| 173 |
{
|
| 174 |
+
$itemHandler->incrementRetries(1, self::ERR_TIMEOUT, __('Timed out while processing.','shortpixel-image-optimiser'));
|
|
|
|
| 175 |
$this->_settings->apiRetries = 0; //fai added to solve a bug?
|
| 176 |
return array("Status" => self::STATUS_SKIP,
|
| 177 |
"Message" => ($itemHandler->getType() == ShortPixelMetaFacade::CUSTOM_TYPE ? __('Image ID','shortpixel-image-optimiser') : __('Media ID','shortpixel-image-optimiser'))
|
| 218 |
return $this->handleSuccess($APIresponse, $PATHs, $itemHandler, $compressionType);
|
| 219 |
default:
|
| 220 |
//handle error
|
| 221 |
+
$incR = 1;
|
| 222 |
if ( !file_exists($PATHs[0]) ) {
|
|
|
|
| 223 |
$err = array("Status" => self::STATUS_NOT_FOUND, "Message" => "File not found on disk. "
|
| 224 |
. ($itemHandler->getType() == ShortPixelMetaFacade::CUSTOM_TYPE ? "Image" : "Media")
|
| 225 |
+
. " ID: " . $itemHandler->getId(), "Code" => self::ERR_FILE_NOT_FOUND);
|
| 226 |
+
$incR = 3;
|
| 227 |
}
|
| 228 |
elseif ( isset($APIresponse[0]->Status->Message) ) {
|
| 229 |
//return array("Status" => self::STATUS_FAIL, "Message" => "There was an error and your request was not processed (" . $APIresponse[0]->Status->Message . "). REQ: " . json_encode($URLs));
|
| 230 |
+
$err = array("Status" => self::STATUS_FAIL, "Code" => (isset($APIresponse[0]->Status->Code) ? $APIresponse[0]->Status->Code : self::ERR_UNKNOWN),
|
| 231 |
"Message" => __('There was an error and your request was not processed.','shortpixel-image-optimiser')
|
| 232 |
. " (" . $APIresponse[0]->Status->Message . ")");
|
| 233 |
} else {
|
| 234 |
+
$err = array("Status" => self::STATUS_FAIL, "Message" => __('There was an error and your request was not processed.','shortpixel-image-optimiser'),
|
| 235 |
+
"Code" => (isset($APIresponse[0]->Status->Code) ? $APIresponse[0]->Status->Code : self::ERR_UNKNOWN));
|
| 236 |
}
|
| 237 |
|
| 238 |
+
$itemHandler->incrementRetries($incR, $err["Code"], $err["Message"]);
|
| 239 |
$meta = $itemHandler->getMeta();
|
| 240 |
if($meta->getRetries() >= MAX_FAIL_RETRIES) {
|
| 241 |
$meta->setStatus($APIresponse[0]->Status->Code);
|
| 448 |
if ( !@copy($source[$fileID], $filePATH) )
|
| 449 |
{//file couldn't be saved in backup folder
|
| 450 |
$msg = sprintf(__('Cannot save file <i>%s</i> in backup directory','shortpixel-image-optimiser'),self::MB_basename($source[$fileID]));
|
| 451 |
+
$itemHandler->incrementRetries(1, self::ERR_SAVE_BKP, $msg);
|
|
|
|
| 452 |
return array("Status" => self::STATUS_FAIL, "Message" => $msg);
|
| 453 |
}
|
| 454 |
}
|
| 456 |
$NoBackup = true;
|
| 457 |
} else {//cannot write to the backup dir, return with an error
|
| 458 |
$msg = __('Cannot save file in backup directory','shortpixel-image-optimiser');
|
| 459 |
+
$itemHandler->incrementRetries(1, self::ERR_SAVE_BKP, $msg);
|
|
|
|
| 460 |
return array("Status" => self::STATUS_FAIL, "Message" => $msg);
|
| 461 |
}
|
| 462 |
|
| 534 |
{
|
| 535 |
$msg = sprintf(__('Optimized version of %s file(s) couldn\'t be updated.','shortpixel-image-optimiser'),$writeFailed);
|
| 536 |
//#ShortPixelAPI::SaveMessageinMetadata($ID, 'Error: optimized version of ' . $writeFailed . ' file(s) couldn\'t be updated.');
|
| 537 |
+
$itemHandler->incrementRetries(1, self::ERR_SAVE, $msg);
|
|
|
|
| 538 |
update_option('bulkProcessingStatus', "error");
|
| 539 |
return array("Status" => self::STATUS_FAIL, "Code" =>"write-fail", "Message" => $msg);
|
| 540 |
}
|
| 594 |
*/
|
| 595 |
static public function MB_basename($Path, $suffix = false){
|
| 596 |
$Separator = " qq ";
|
| 597 |
+
$qqPath = preg_replace("/[^ ]/u", $Separator."\$0".$Separator, $Path);
|
| 598 |
+
if(!$qqPath) { //this is not an UTF8 string!! Don't rely on basename either, since if filename starts with a non-ASCII character it strips it off
|
| 599 |
+
$fileName = end(explode(DIRECTORY_SEPARATOR, $Path));
|
| 600 |
+
$pos = strpos($fileName, $suffix);
|
| 601 |
+
if($pos !== false) {
|
| 602 |
+
return substr($fileName, 0, $pos);
|
| 603 |
+
}
|
| 604 |
+
return $fileName;
|
| 605 |
+
}
|
| 606 |
+
$suffix = preg_replace("/[^ ]/u", $Separator."\$0".$Separator, $suffix);
|
| 607 |
+
$Base = basename($qqPath, $suffix);
|
| 608 |
$Base = str_replace($Separator, "", $Base);
|
| 609 |
+
return $Base;
|
| 610 |
}
|
| 611 |
|
| 612 |
/**
|
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 > ShortPixel</a> page on how to start optimizing your image library and make your website load faster.
|
| 6 |
-
* Version: 4.
|
| 7 |
* Author: ShortPixel
|
| 8 |
* Author URI: https://shortpixel.com
|
| 9 |
* Text Domain: shortpixel-image-optimiser
|
|
@@ -17,7 +17,7 @@ define('SHORTPIXEL_PLUGIN_FILE', __FILE__);
|
|
| 17 |
|
| 18 |
define('SP_AFFILIATE_CODE', '');
|
| 19 |
|
| 20 |
-
define('PLUGIN_VERSION', "4.
|
| 21 |
define('SP_MAX_TIMEOUT', 10);
|
| 22 |
define('SP_VALIDATE_MAX_TIMEOUT', 15);
|
| 23 |
define('SP_BACKUP', 'ShortpixelBackups');
|
|
@@ -104,6 +104,5 @@ if ( !function_exists( 'vc_action' ) || vc_action() !== 'vc_inline' ) { //handle
|
|
| 104 |
|
| 105 |
register_activation_hook( __FILE__, 'shortPixelActivatePlugin' );
|
| 106 |
register_deactivation_hook( __FILE__, 'shortPixelDeactivatePlugin' );
|
| 107 |
-
|
| 108 |
}
|
| 109 |
?>
|
| 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 > ShortPixel</a> page on how to start optimizing your image library and make your website load faster.
|
| 6 |
+
* Version: 4.4.0
|
| 7 |
* Author: ShortPixel
|
| 8 |
* Author URI: https://shortpixel.com
|
| 9 |
* Text Domain: shortpixel-image-optimiser
|
| 17 |
|
| 18 |
define('SP_AFFILIATE_CODE', '');
|
| 19 |
|
| 20 |
+
define('PLUGIN_VERSION', "4.4.0");
|
| 21 |
define('SP_MAX_TIMEOUT', 10);
|
| 22 |
define('SP_VALIDATE_MAX_TIMEOUT', 15);
|
| 23 |
define('SP_BACKUP', 'ShortpixelBackups');
|
| 104 |
|
| 105 |
register_activation_hook( __FILE__, 'shortPixelActivatePlugin' );
|
| 106 |
register_deactivation_hook( __FILE__, 'shortPixelDeactivatePlugin' );
|
|
|
|
| 107 |
}
|
| 108 |
?>
|
