ShortPixel Image Optimizer - Version 4.19.0

Version Description

Release date June 4th 2020 * Added an animation in settings that better explains the automatic resize done by ShortPixel; * Fix for fatal errors in some cases when updating the plugin, by moving the class loader to PSR-4; * Fix for a situation where the compare function wouldn't work because of a wrong assumption for the backup folder path; * Fix: if directory structure is fully empty, select other media folder displays empty modal; * Fix for check quota button that wasn't working in certain situations; * Fix for missing DB table when doing a bulk restore before having optimized images; * Fix for a DB foreign key issue in situations where multiple WordPress sites run on the same DB; * Fix for backup getting broken on IIS/Windows servers, because of the way Windows handles the paths; * Compability fix for WooCommerce germanized PRO plugin, where the cart page was throwing a fatal error because of the PDF that ShortPixel was trying to optimize; * Various fixes for other media screen, to make it more consistent with the Media Library; * Language 5 new strings added, 1 updated, 1 fuzzied, and 0 obsoleted.

Download this release

Release Info

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

Code changes from version 4.18.1 to 4.19.0

Files changed (59) hide show
  1. build/shortpixel/PackageLoader.php +19 -5
  2. build/shortpixel/notices/composer.json +1 -1
  3. build/shortpixel/notices/src/NoticeController.php +0 -1
  4. build/shortpixel/notices/src/NoticeModel.php +4 -4
  5. changelog.txt +212 -0
  6. class/BuildAutoLoader.php +87 -0
  7. class/{controller/controller.php → Controller.php} +2 -31
  8. class/{controller/admin_controller.php → Controller/AdminController.php} +3 -3
  9. class/{controller/adminnotices_controller.php → Controller/AdminNoticesController.php} +10 -10
  10. class/{controller/apikey_controller.php → Controller/ApiKeyController.php} +5 -4
  11. class/{controller/cache_controller.php → Controller/CacheController.php} +4 -4
  12. class/{controller/edit_media_controller.php → Controller/EditMediaController.php} +4 -3
  13. class/{controller/filesystem_controller.php → Controller/FileSystemController.php} +6 -7
  14. class/{controller/front_controller.php → Controller/FrontController.php} +3 -3
  15. class/{controller/othermedia_controller.php → Controller/OtherMediaController.php} +5 -11
  16. class/{controller/settings.php → Controller/SettingsController.php} +7 -5
  17. class/{controller/views/bulk-restore-all.php → Controller/View/BulkRestoreAll.php} +4 -3
  18. class/{controller/views/bulk_view_controller.php → Controller/View/BulkViewController.php} +16 -27
  19. class/{controller/views/othermedia_view_controller.php → Controller/View/OtherMediaViewController.php} +72 -18
  20. class/{shortpixel-model.php → Model.php} +1 -1
  21. class/{model/apikey_model.php → Model/ApiKeyModel.php} +9 -13
  22. class/{model/cache_model.php → Model/CacheModel.php} +1 -1
  23. class/{model/directory_model.php → Model/DirectoryModel.php} +2 -2
  24. class/{model/directory_othermedia_model.php → Model/DirectoryOtherMediaModel.php} +4 -2
  25. class/{model/environment_model.php → Model/EnvironmentModel.php} +3 -3
  26. class/{model/file_model.php → Model/FileModel.php} +6 -3
  27. class/{model/image_model.php → Model/ImageModel.php} +3 -3
  28. class/{model → Model}/shortpixel-entity.php +0 -0
  29. class/{model → Model}/shortpixel-folder.php +0 -0
  30. class/{model → Model}/shortpixel-meta.php +0 -0
  31. class/{shortpixel_queue.php → Queue.php} +0 -0
  32. class/{shortpixel-tools.php → Tools.php} +0 -4
  33. class/controller/bulk-restore-all.php +0 -2
  34. class/db/shortpixel-custom-meta-dao.php +5 -4
  35. class/db/shortpixel-meta-facade.php +8 -10
  36. class/db/wp-shortpixel-media-library-adapter.php +6 -4
  37. class/external/helpscout.php +2 -0
  38. class/external/nextgen.php +3 -2
  39. class/external/wp-offload-media.php +2 -3
  40. class/plugin.json +1 -0
  41. class/shortpixel-png2jpg.php +20 -20
  42. class/view/settings/part-general.php +101 -0
  43. class/view/shortpixel_view.php +6 -3
  44. class/view/view-other-media.php +6 -7
  45. class/wp-short-pixel.php +129 -64
  46. class/wp-shortpixel-settings.php +1 -1
  47. readme.txt +17 -214
  48. res/css/shortpixel-othermedia.css +20 -5
  49. res/img/heavy-image.png +0 -0
  50. res/img/heavy-image@2x.png +0 -0
  51. res/img/resize-type.png +0 -0
  52. res/img/resize-type@2x.png +0 -0
  53. res/js/shortpixel.js +181 -9
  54. res/js/shortpixel.min.js +1 -1
  55. res/scss/shortpixel-othermedia.scss +32 -4
  56. shortpixel-plugin.php +57 -89
  57. shortpixel_api.php +10 -8
  58. wp-shortpixel-req.php +0 -89
  59. wp-shortpixel.php +22 -21
build/shortpixel/PackageLoader.php CHANGED
@@ -3,12 +3,26 @@ namespace ShortPixel\Build;
3
 
4
  class PackageLoader
5
  {
6
- public $dir;
 
7
 
8
- public function getComposerFile()
9
- {
10
- return json_decode(file_get_contents($this->dir."/composer.json"), 1);
11
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
  public function load($dir)
14
  {
3
 
4
  class PackageLoader
5
  {
6
+ public $dir;
7
+ public $composerFile = false;
8
 
9
+ public function __construct()
10
+ {
11
+
12
+ }
13
+
14
+ public function setComposerFile($filePath)
15
+ {
16
+ $this->composerFile = json_decode(file_get_contents($filePath),1);
17
+ }
18
+
19
+ public function getComposerFile($filePath = false )
20
+ {
21
+ if (! $this->composerFile)
22
+ $this->composerFile = json_decode(file_get_contents($this->dir."/composer.json"), 1);
23
+
24
+ return $this->composerFile;
25
+ }
26
 
27
  public function load($dir)
28
  {
build/shortpixel/notices/composer.json CHANGED
@@ -1,7 +1,7 @@
1
  {
2
  "name": "shortpixel/notices",
3
  "description": "ShortPixel WordPress Notice System",
4
- "version": "1.4",
5
  "type": "library",
6
  "license": "MIT",
7
  "authors": [
1
  {
2
  "name": "shortpixel/notices",
3
  "description": "ShortPixel WordPress Notice System",
4
+ "version": "1.5",
5
  "type": "library",
6
  "license": "MIT",
7
  "authors": [
build/shortpixel/notices/src/NoticeController.php CHANGED
@@ -19,7 +19,6 @@ class NoticeController //extends ShortPixelController
19
  /** For backward compat. Never call constructor directly. */
20
  public function __construct()
21
  {
22
- // $this->loadModel('notice');
23
  $ns = __NAMESPACE__;
24
  $ns = substr($ns, 0, strpos($ns, '\\')); // try to get first part of namespace
25
  $this->notice_option = $ns . '-notices';
19
  /** For backward compat. Never call constructor directly. */
20
  public function __construct()
21
  {
 
22
  $ns = __NAMESPACE__;
23
  $ns = substr($ns, 0, strpos($ns, '\\')); // try to get first part of namespace
24
  $this->notice_option = $ns . '-notices';
build/shortpixel/notices/src/NoticeModel.php CHANGED
@@ -89,11 +89,11 @@ class NoticeModel //extends ShortPixelModel
89
  */
90
  public function addDetail($detail, $clean = false)
91
  {
92
- if ($clean)
93
- $this->details = array();
94
 
95
- if (! in_array($detail, $this->details) )
96
- $this->details[] = $detail;
97
  }
98
 
99
 
89
  */
90
  public function addDetail($detail, $clean = false)
91
  {
92
+ if ($clean)
93
+ $this->details = array();
94
 
95
+ if (! in_array($detail, $this->details) )
96
+ $this->details[] = $detail;
97
  }
98
 
99
 
changelog.txt CHANGED
@@ -1,3 +1,215 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  = 4.12.8 =
2
 
3
  Release date: 25th February 2019
1
+ = 4.16.4 =
2
+
3
+ Release date: 26th March 2020
4
+ * Fix for some notices that could not be dismissed
5
+ * Fix for "Confirm new credits" notification
6
+ * Language – 0 new strings added, 0 updated, 0 fuzzied, and 0 obsoleted
7
+
8
+ = 4.16.3 =
9
+
10
+ Release date: 9th March 2020
11
+ * Fix missing button to choose a plan when running out of credits.
12
+ * Language – 0 new strings added, 0 updated, 0 fuzzied, and 0 obsoleted
13
+
14
+ = 4.16.2 =
15
+
16
+ Release date: 27th February 2020
17
+ * Fix notices javascript.
18
+ * Language – 0 new strings added, 0 updated, 0 fuzzied, and 0 obsoleted
19
+
20
+ = 4.16.1 =
21
+
22
+ Release date: 14th February 2020
23
+ * Fix non-dismissable alerts.
24
+ * Reference to the Website Speed Optimization service.
25
+ * Fixed: deleteItemCache in wrong place ( before save ) thus resetting data
26
+ * Fixed: NextGen integration
27
+ * Language – 3 new strings added, 0 updated, 0 fuzzied, and 0 obsoleted
28
+
29
+ = 4.16.0 =
30
+
31
+ Release date: 4th February 2020
32
+ * New - Token support for Cloudflare via config constant or settings.
33
+ * Backup setting - add orange warning when backups are off.
34
+ * Button to dismiss the top bar notification of missing files.
35
+ * Shortpixel now loads scripts with 'defer' on front site, if it's configured to be loaded there.
36
+ * Hiding Cloudflare details via wp-config.php.
37
+ * Hide the option "Process in front-end" when "Optimize media on upload" is not checked.
38
+ * Fixes for multibyte filenames with mixed locales.
39
+ * Fixes for combination of S3-offload, webp pictures and cnames.
40
+ * Reworked Notifications.
41
+ * Fixed - PNG2JPG Retry button didn't work, now properly resets retry counter.
42
+ * Fixed - Realpath in directory model throws off installations with symlinks.
43
+ * Fixed - Thrown Exception in API with corrupted images now caught.
44
+ * Fixed - Debug window link was visible when it should not.
45
+ * Fixed - ExcludePattern without value would result in notices.
46
+ * Language – 7 new strings added, 0 updated, 0 fuzzied, and 0 obsoleted
47
+
48
+ = 4.15.4 =
49
+
50
+ Release date: 29th January 2020
51
+ * Change the Help beacon to V2.
52
+ * Language – 0 new strings added, 0 updated, 0 fuzzied, and 0 obsoleted
53
+
54
+ = 4.15.3 =
55
+
56
+ Release date: 20th December 2019
57
+ * Hide the "Process in front-end" option if "Optimize media on upload" unchecked
58
+ * Add ALT text for plugin images in Admin
59
+ * Moved CSS for the admin bar to the actual admin bar stylesheet, other css no longer loading on those pages
60
+ * Fixes for windows specific paths
61
+ * Fixed: warning flood when using old version of S3-offload
62
+ * Fix for frontend and error shortpixel in top toolbar
63
+ * Fixed: Pancake menu now showing proper actions ( none ) if backup is not there.
64
+ * Fixed: Windows paths in wp-short-pixel getBackupFolderInternal
65
+ * Language – 4 new strings added, 0 updated, 0 fuzzied, and 0 obsoleted
66
+
67
+ = 4.15.2 =
68
+
69
+ Release date: 28th November 2019
70
+ * Fix for is_null error and "Call to undefined method ShortPixel\ShortPixelPlugin::alterHtaccess" in some cases.
71
+ * Language – 0 new strings added, 0 updated, 0 fuzzied, and 0 obsoleted
72
+
73
+ = 4.15.1 =
74
+
75
+ Release date: 27th November 2019
76
+ * Fix the infamous T_PAAMAYIM_NEKUDOTAYIM error on PHP 5.3 with WP Offload Media compat. module.
77
+ * Language – 0 new strings added, 0 updated, 0 fuzzied, and 0 obsoleted
78
+
79
+ = 4.15.0 =
80
+
81
+ Release date: 27th November 2019
82
+ * Ask if WebP files should be created before bulk optimization : checkbox added in Bulk page.
83
+ * Added filters for optimal chunk size when selecting records from wp_postmeta while bulk processing: 'shortpixel/db/chunk_size'.
84
+ * Optimize images also on edit-media screen.
85
+ * Experimental support for static cache firewalls, and sending images w/ timestamp: SHORTPIXEL_EXPERIMENTAL_SECURICACHE.
86
+ * Limit loading of JS / CSS to pages we do work on.
87
+ * Refactoring & speed optimizations: - new external class for gravity forms, nextgen and visual composer, new controller for global admin hooks, new front controller, updated plugin init, clean(ish) root file, database optimization(reduced number of queries), unlistedThumbs checker only fires when the optimize unlisted check is active, optimizations for filesystem and findFileByPattern.
88
+ * WPML Duplicates - Don't mark empty GUID's as duplicate.
89
+ * Fix broken styles on WP 5.3.
90
+ * Fix in case meta_value in processCountable has a WP_Error object instead of normal metadata.
91
+ * Fix on WP Engine when large wp_postmeta table: limit to 16K the size of the query with ID list.
92
+ * Fixed: error when log path is not writeable
93
+ * Fixed: double sends within the same images, can happen with something like WPML and it's duplicated media.
94
+ * Fixed: bug when searching unlisted images, in some circumstances.
95
+ * Fixed: max_execution_time when time is set lower than 0.
96
+ * Fixed: directories with no permission would give PHP error
97
+ * Fixed: pathToUrl now also works for paths outside wp uploads
98
+ * Fixed: check for DOING_AJAX on redirect to settings.
99
+ * Fixed: Shortpixel icon + exclamation mark in toolbar showing on every page load.
100
+ * Fixed: Add Custom media browser doesn't display files anymore
101
+ * Fixed: WebP option adds an extra border if image already has a border -> borders will not be replicated to <picture> tags.
102
+ * Fixed: Validating empty key doesn't show any message.
103
+ * Fixed: on Nginx writes .htaccess files.
104
+ * Fixed: Bug with safeGetAttachmentUrl for URLs that start with //.
105
+ * Fixed: New S3-Offload version breaks Shortpixel and offloading.
106
+ * Fixed: get_attached_file when S3-Offload is active, breaks other plugins.
107
+ * Fixed: crash when doing .htaccess files ( WP 5.3 specific ).
108
+ * Fixed: double file occurences on png2jpg in conjunction with s3offload.
109
+ * Language – 1 new strings added, 0 updated, 0 fuzzied, and 0 obsoleted
110
+
111
+ = 4.14.6 =
112
+
113
+ Release date: 9th October 2019
114
+ * Don't convert to `<picture>` the `<img>`s with backgrounds.
115
+ * Remove unused eval() call.
116
+ * Restore the validate button next to API Key but change label to "Save and validate"
117
+ * Fixed: PNGtoJPG issue with already uploaded images
118
+ * Fixed: finding wrong unlisted thumbnails due to regex.
119
+ * Fixed: fatal error when trying to delete crashed attachement ( without proper URL )
120
+ * Fix for S3 offload - PNG2JPG , doesn't remove old JPG files
121
+ * Fixed: S3Offload will not offload anymore when 'Copy files to bucket' is off ( and object was not previously offloaded )
122
+ * S3Offload doesn't offload via optimiser anymore if this setting is off
123
+ * Fixed: cutting out initial offload if optimization needs to be done, when autolibrary is on
124
+ * Fix for PNG2JPG - JPG files remained in backupdir.
125
+ * Small fix for remote download thumbnails
126
+ * Fixed: notice in filemodel due meta-facade feeding array
127
+ * Fixed: bug in File2Url in filesystemcontroller
128
+ * Fixed: download issue in attempt to remote download
129
+ * Language – 0 new strings added, 1 updated, 0 fuzzied, and 0 obsoleted
130
+
131
+ = 4.14.5 =
132
+
133
+ Release date: 29th August 2019
134
+ * If constant SHORTPIXEL_USE_DOUBLE_WEBP_EXTENSION is defined as true, use double extension for WebP (.jpg.webp)
135
+ * Fixed: Javascript - String.prototype causes errors on React apps
136
+ * Fixed: Undefined page load when using ShortPixel and Divi preloaded images
137
+ * Fixed: Offload Media - When removing PNG2JPG converted file, the files / folder are not removed.
138
+ * Fixed: When the constant that enables using double extensions for WebP (.jpg.webp) is active, the webp's are found as unlisted thumbnails and sent to optimization.
139
+ * Fixed: missing call to apply_filters('shortpixel_image_exists'...) on a particular case.
140
+ * Language – 0 new strings added, 1 updated, 0 fuzzied, and 0 obsoleted
141
+
142
+ = 4.14.4 =
143
+
144
+ Release date: 19th August 2019
145
+ * Check if unlisted thumbnails present for already optimized images (in case the thumbnails were added later) in Media Library list and when doing bulk. This also integrates with the Unicode plugin.
146
+ * If JSON PHP module not present, add a proper error
147
+ * Fixed: bulk error "WordPress database error You have an error in your SQL syntax" on some installs
148
+ * Fixed: Warning: count() Parameter must be an array.
149
+ * Language – 0 new strings added, 0 updated, 0 fuzzied, and 0 obsoleted
150
+
151
+ = 4.14.3 =
152
+
153
+ Release date: 22nd July 2019
154
+ * Compatibility with Flywheel hosting by not using flock if Flywheel detected
155
+ * When using the PICTURE tag to deliver WebP, keep the width and height at `<IMG>` level
156
+ * Refactoring of the API Key settings page, refactoring of Other media
157
+ * Performance improvements for selecting from large wp_posts and wp_postmeta tables when doing bulk optimization
158
+ * Display a message when bulk is skipping many processed images, if bulk processing is ran again.
159
+ * Fixed: Other media - Recompress adds "Preserve CMYK"
160
+ * Fixed: duplicate error message when validating wrong API key
161
+ * Conflict message: align the text vertically and provide space between text and button when displayed on any admin page
162
+ * Fixed: Other media Restore fails when original file is readable, not writable
163
+
164
+ = 4.14.2 =
165
+
166
+ Release date: 1st July 2019
167
+ * add the possibility to define custom infixes for thumbnails (like image-uai-150x150.jpg for image.jpg) - comma separated define SHORTPIXEL_CUSTOM_THUMB_INFIXES
168
+
169
+ = 4.14.1 =
170
+
171
+ Release date: 17th June 2019
172
+ * Fix errors when DOMDocument not present
173
+
174
+ = 4.14.0 =
175
+
176
+ Release date: 17th June 2019
177
+ * Add new filters proposed by WP Stateless: shortpixel_backup_folder, shortpixel_image_exists, shortpixel_image_urls
178
+ * Better placement of the elements on the Other Media page
179
+ * Fix custom bulk for PDFs when the pdf thumbnails are not activated
180
+ * Fix selecting items from DB twice for bulk in some circumstances
181
+ * Warn user that converting PNG to JPG while keeping EXIF in options doesn't keep it (no EXIF for PNGs).
182
+ * When SHORTPIXEL_DEBUG=x get parameter is provided, display a floating link to the shortpixel_log file
183
+ * Adaptive Max execution time and capped to 90 sec. for the bulk background AJAX calls. (Kinsta has a max_execution_time of 300 sec. in PHP but the HTTP connection is cut after 180 sec.)
184
+ * Fix custom 404 page for missing images not working when using .htaccess for WebP
185
+ * Fix WebP picture tag with relative URLs not working in some circumstances
186
+ * Fix replacing the `<img>` inside an existing `<picture>` tag with another `<picture>` tag.
187
+ * Clear SP optimization cache in order to be able to optimize an image which initially had permissions error, after changing the permissions.
188
+ * Fix being able to list the contents of ShortpixelBackups on some badly configured servers.
189
+ * Fix error when inputting D'Artagnan in the AUTH pass field of settings.
190
+ * Add the Quriobot for support.
191
+
192
+ = 4.13.1 =
193
+
194
+ Release date: 16th April 2019
195
+ * fix thumbnail optimization when a thumbnail was replaced with another one
196
+ * better integration with Regenerate Thumbnails Advanced
197
+
198
+ = 4.13.0 =
199
+
200
+ Release date: 10th April 2019
201
+ * Bulk restore for the Other Media
202
+ * make the filename extension be updated when manually optimizing a PNG from Media Library, if the convert to JPG is active, without refreshing the page
203
+ * Integration with Regenerate Thumbnails Advanced new 2.0 beta version
204
+ * Add the rules for WebP in the WP-CONTENT .htaccess
205
+ * ShortPixel Other Media - display the time of optimization in the grid and offer option to sort by it
206
+ * Keep sort order when optimizing / refreshing page on Other Media
207
+ * offer the visual comparer for Other Media too
208
+ * resolve the Settings inconsistency in Other Media (settings displayed were from when adding the folder not from when actually optimizing)
209
+ * Make pressing Escape or clicking outside of any popup close it.
210
+ * Fixed: Restoring an Other Media item and then Optimizing it again optimizes it Lossless
211
+ * fix generating the WebP `<picture>` tags when the images are either on a subdomain or on a CDN domain having the same root domain as the main site.
212
+
213
  = 4.12.8 =
214
 
215
  Release date: 25th February 2019
class/BuildAutoLoader.php ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace ShortPixel;
3
+
4
+ class BuildAutoLoader
5
+ {
6
+
7
+ public static function buildJSON()
8
+ {
9
+ $plugin = array(
10
+ 'name' => 'ShortPixel/Plugin',
11
+ 'description' => 'ShortPixel AutoLoader',
12
+ 'type' => 'function',
13
+ 'autoload' => array('psr-4' => array('ShortPixel' => 'class'),
14
+ 'files' => self::getFiles(),
15
+ ),
16
+ );
17
+
18
+ $f = fopen('class/plugin.json', 'w');
19
+ fwrite($f, json_encode($plugin));
20
+ fclose($f);
21
+ }
22
+
23
+ public static function getFiles()
24
+ {
25
+ $main = array(
26
+ 'shortpixel_api.php',
27
+ 'class/wp-short-pixel.php',
28
+ 'class/wp-shortpixel-settings.php',
29
+ 'class/view/shortpixel_view.php',
30
+ 'class/shortpixel-png2jpg.php',
31
+ );
32
+
33
+ $models = array(
34
+ 'class/Model/shortpixel-entity.php',
35
+ 'class/Model/shortpixel-meta.php',
36
+ 'class/Model/shortpixel-folder.php',
37
+ );
38
+
39
+ $db = array(
40
+ 'class/db/shortpixel-db.php',
41
+ 'class/db/wp-shortpixel-db.php',
42
+ 'class/db/shortpixel-custom-meta-dao.php',
43
+ 'class/db/wp-shortpixel-media-library-adapter.php',
44
+ 'class/db/shortpixel-meta-facade.php'
45
+ );
46
+
47
+
48
+ $externals = array(
49
+ 'class/external/cloudflare.php',
50
+ 'class/external/flywheel.php',
51
+ 'class/external/gravityforms.php',
52
+ 'class/external/helpscout.php',
53
+ 'class/external/nextgen.php',
54
+ 'class/external/securi.php',
55
+ 'class/external/shortpixel_queue_db.php',
56
+ 'class/external/visualcomposer.php',
57
+ 'class/external/wp-offload-media.php',
58
+ 'class/external/wpengine.php',
59
+ );
60
+
61
+
62
+ return array_merge($main,$models,$db,$externals);
63
+ }
64
+
65
+ }
66
+
67
+ /*require_once('shortpixel_api.php');
68
+
69
+ //entities
70
+ require_once('class/model/shortpixel-entity.php');
71
+ require_once('class/model/shortpixel-meta.php');
72
+ require_once('class/model/shortpixel-folder.php');
73
+ //exceptions
74
+ //database access
75
+ require_once('class/db/shortpixel-db.php');
76
+ require_once('class/db/wp-shortpixel-db.php');
77
+ require_once('class/db/shortpixel-custom-meta-dao.php');
78
+
79
+ require_once('class/db/wp-shortpixel-media-library-adapter.php');
80
+ require_once('class/db/shortpixel-meta-facade.php');
81
+ //view
82
+ require_once('class/view/shortpixel_view.php');
83
+ */
84
+
85
+
86
+ //require_once( ABSPATH . 'wp-admin/includes/image.php' );
87
+ //include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
class/{controller/controller.php → Controller.php} RENAMED
@@ -2,7 +2,7 @@
2
  namespace ShortPixel;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
 
5
- class ShortPixelController
6
  {
7
  protected static $controllers = array();
8
 
@@ -26,31 +26,11 @@ class ShortPixelController
26
  public static function init()
27
  {
28
  foreach (get_declared_classes() as $class) {
29
- if (is_subclass_of($class, \ShortPixelTools::namespaceit('shortPixelController') ))
30
  self::$controllers[] = $class;
31
  }
32
  }
33
 
34
- /* Static function to use for finding a associated controller within the WP page ecosystem
35
- *
36
- * e.g. My page path in Wp-admin is bulk-restore-all, it can autofind needed controller ( and view )
37
- */
38
- public static function findControllerbySlug($name)
39
- {
40
- foreach(self::$controllers as $className)
41
- {
42
- if (! isset($className::$slug)) // controllers not connected by slugs
43
- continue;
44
-
45
- if ($className::$slug == $name)
46
- {
47
- return $className; // found!
48
- }
49
- }
50
-
51
- return false;
52
- }
53
-
54
  public function __construct()
55
  {
56
  $this->view = new \stdClass;
@@ -127,15 +107,6 @@ class ShortPixelController
127
 
128
  }
129
 
130
- /** Loads the Model Data Structure upon request
131
- *
132
- * @param string $name Name of the model
133
- */
134
- protected function loadModel($name){
135
- return \wpSPIO()->loadModel($name);
136
- }
137
-
138
-
139
  /** Accepts POST data, maps, checks missing fields, and applies sanitization to it.
140
  * @param array $post POST data
141
  */
2
  namespace ShortPixel;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
 
5
+ class Controller
6
  {
7
  protected static $controllers = array();
8
 
26
  public static function init()
27
  {
28
  foreach (get_declared_classes() as $class) {
29
+ if (is_subclass_of($class, 'ShortPixel\Controller') )
30
  self::$controllers[] = $class;
31
  }
32
  }
33
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  public function __construct()
35
  {
36
  $this->view = new \stdClass;
107
 
108
  }
109
 
 
 
 
 
 
 
 
 
 
110
  /** Accepts POST data, maps, checks missing fields, and applies sanitization to it.
111
  * @param array $post POST data
112
  */
class/{controller/admin_controller.php → Controller/AdminController.php} RENAMED
@@ -1,5 +1,5 @@
1
  <?php
2
- namespace ShortPixel;
3
  use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
4
  use ShortPixel\Notices\NoticeController as Notices;
5
 
@@ -7,7 +7,7 @@ use ShortPixel\Notices\NoticeController as Notices;
7
  *
8
  * This should be a delegation class connection global hooks and such to the best shortpixel handler.
9
  */
10
- class adminController extends ShortPixelController
11
  {
12
  protected static $instance;
13
 
@@ -19,7 +19,7 @@ class adminController extends ShortPixelController
19
  public static function getInstance()
20
  {
21
  if (is_null(self::$instance))
22
- self::$instance = new adminController();
23
 
24
  return self::$instance;
25
  }
1
  <?php
2
+ namespace ShortPixel\Controller;
3
  use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
4
  use ShortPixel\Notices\NoticeController as Notices;
5
 
7
  *
8
  * This should be a delegation class connection global hooks and such to the best shortpixel handler.
9
  */
10
+ class AdminController extends \ShortPixel\Controller
11
  {
12
  protected static $instance;
13
 
19
  public static function getInstance()
20
  {
21
  if (is_null(self::$instance))
22
+ self::$instance = new AdminController();
23
 
24
  return self::$instance;
25
  }
class/{controller/adminnotices_controller.php → Controller/AdminNoticesController.php} RENAMED
@@ -1,15 +1,16 @@
1
  <?php
2
- namespace ShortPixel;
3
  use ShortPixel\Notices\NoticeController as Notices;
4
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
5
 
 
6
 
7
  /* Controller for automatic Notices about status of the plugin.
8
  * This controller is bound for automatic fire. Regular procedural notices should just be queued using the Notices modules.
9
  * Called in admin_notices.
10
  */
11
 
12
- class adminNoticesController extends ShortPixelController
13
  {
14
  protected static $instance;
15
 
@@ -44,7 +45,7 @@ class adminNoticesController extends ShortPixelController
44
  public static function getInstance()
45
  {
46
  if (is_null(self::$instance))
47
- self::$instance = new adminNoticesController();
48
 
49
  return self::$instance;
50
  }
@@ -109,8 +110,8 @@ class adminNoticesController extends ShortPixelController
109
  {
110
  echo $notice->getForDisplay();
111
 
112
- if ($notice->getID() == adminNoticesController::MSG_QUOTA_REACHED || $notice->getID() == adminNoticesController::MSG_UPGRADE_MONTH
113
- || $notice->getID() == adminNoticesController::MSG_UPGRADE_BULK)
114
  {
115
  wp_enqueue_script('jquery.knob.min.js');
116
  wp_enqueue_script('jquery.tooltip.min.js');
@@ -408,7 +409,6 @@ class adminNoticesController extends ShortPixelController
408
  protected function getQuotaExceededMessage($quotaData)
409
  {
410
  $averageCompression = \wpSPIO()->getShortPixel()->getAverageCompression();
411
- \wpSPIO()->loadModel('apikey');
412
 
413
  $keyModel = new apiKeyModel();
414
  $keyModel->loadKey();
@@ -446,11 +446,11 @@ class adminNoticesController extends ShortPixelController
446
 
447
  $message .= '<h3>' . __('Quota Exceeded','shortpixel-image-optimiser') . '</h3>';
448
 
449
- $recheck = isset($_GET['checkquota']) ? true : false;
450
 
451
- if($recheck) {
452
  $message .= '<p style="color: red">' . __('You have no available image credits. If you just bought a package, please note that sometimes it takes a few minutes for the payment confirmation to be sent to us by the payment processor.','shortpixel-image-optimiser') . '</p>';
453
- }
454
 
455
  $message .= '<p>' . sprintf(__('The plugin has optimized <strong>%s images</strong> and stopped because it reached the available quota limit.','shortpixel-image-optimiser'),
456
  number_format(max(0, $quotaData['APICallsMadeNumeric'] + $quotaData['APICallsMadeOneTimeNumeric'])));
@@ -470,7 +470,7 @@ class adminNoticesController extends ShortPixelController
470
  <strong>' . __('Upgrade','shortpixel-image-optimiser') . '</strong>
471
  </a>
472
  <input type="button" name="checkQuota" class="button" value="'. __('Confirm New Credits','shortpixel-image-optimiser') . '"
473
- onclick="ShortPixel.recheckQuota()">
474
  </div>';
475
 
476
  $message .= '<p>' . __('Get more image credits by referring ShortPixel to your friends!','shortpixel-image-optimiser') . '
1
  <?php
2
+ namespace ShortPixel\Controller;
3
  use ShortPixel\Notices\NoticeController as Notices;
4
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
5
 
6
+ use ShortPixel\Model\ApiKeyModel as ApiKeyModel;
7
 
8
  /* Controller for automatic Notices about status of the plugin.
9
  * This controller is bound for automatic fire. Regular procedural notices should just be queued using the Notices modules.
10
  * Called in admin_notices.
11
  */
12
 
13
+ class AdminNoticesController extends \ShortPixel\Controller
14
  {
15
  protected static $instance;
16
 
45
  public static function getInstance()
46
  {
47
  if (is_null(self::$instance))
48
+ self::$instance = new AdminNoticesController();
49
 
50
  return self::$instance;
51
  }
110
  {
111
  echo $notice->getForDisplay();
112
 
113
+ if ($notice->getID() == AdminNoticesController::MSG_QUOTA_REACHED || $notice->getID() == AdminNoticesController::MSG_UPGRADE_MONTH
114
+ || $notice->getID() == AdminNoticesController::MSG_UPGRADE_BULK)
115
  {
116
  wp_enqueue_script('jquery.knob.min.js');
117
  wp_enqueue_script('jquery.tooltip.min.js');
409
  protected function getQuotaExceededMessage($quotaData)
410
  {
411
  $averageCompression = \wpSPIO()->getShortPixel()->getAverageCompression();
 
412
 
413
  $keyModel = new apiKeyModel();
414
  $keyModel->loadKey();
446
 
447
  $message .= '<h3>' . __('Quota Exceeded','shortpixel-image-optimiser') . '</h3>';
448
 
449
+ // $recheck = isset($_GET['checkquota']) ? true : false;
450
 
451
+ /* if($recheck) {
452
  $message .= '<p style="color: red">' . __('You have no available image credits. If you just bought a package, please note that sometimes it takes a few minutes for the payment confirmation to be sent to us by the payment processor.','shortpixel-image-optimiser') . '</p>';
453
+ } */
454
 
455
  $message .= '<p>' . sprintf(__('The plugin has optimized <strong>%s images</strong> and stopped because it reached the available quota limit.','shortpixel-image-optimiser'),
456
  number_format(max(0, $quotaData['APICallsMadeNumeric'] + $quotaData['APICallsMadeOneTimeNumeric'])));
470
  <strong>' . __('Upgrade','shortpixel-image-optimiser') . '</strong>
471
  </a>
472
  <input type="button" name="checkQuota" class="button" value="'. __('Confirm New Credits','shortpixel-image-optimiser') . '"
473
+ onclick="ShortPixel.checkQuota()">
474
  </div>';
475
 
476
  $message .= '<p>' . __('Get more image credits by referring ShortPixel to your friends!','shortpixel-image-optimiser') . '
class/{controller/apikey_controller.php → Controller/ApiKeyController.php} RENAMED
@@ -1,18 +1,19 @@
1
  <?php
2
- namespace ShortPixel;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
 
 
 
5
  /* Main function of this controller is to load key on runtime
6
  This should probably in future incorporate some apikey checking functions that shouldn't be in model.
7
  */
8
- class ApiKeyController extends shortPixelController
9
  {
10
  private static $instance;
11
 
12
  public function __construct()
13
  {
14
- $this->loadModel('apikey');
15
- $this->model = new apiKeyModel();
16
  $this->load();
17
  }
18
 
1
  <?php
2
+ namespace ShortPixel\Controller;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
 
5
+ use ShortPixel\Model\ApiKeyModel as ApiKeyModel;
6
+
7
  /* Main function of this controller is to load key on runtime
8
  This should probably in future incorporate some apikey checking functions that shouldn't be in model.
9
  */
10
+ class ApiKeyController extends \ShortPixel\Controller
11
  {
12
  private static $instance;
13
 
14
  public function __construct()
15
  {
16
+ $this->model = new ApiKeyModel();
 
17
  $this->load();
18
  }
19
 
class/{controller/cache_controller.php → Controller/CacheController.php} RENAMED
@@ -1,19 +1,19 @@
1
  <?php
2
- namespace ShortPixel;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
 
 
5
  // Future replacement for everything that needs temporary storage
6
  // Storage agnostic -> called function should not need to know what is stored where, this is job of controller.
7
  // Works with cache-model, which handles the data representation and storage.
8
  //
9
 
10
- class CacheController extends ShortPixelController
11
  {
12
  protected static $cached_items = array();
13
 
14
  public function __construct()
15
  {
16
- $this->loadModel('cache');
17
  }
18
 
19
  public function storeItem($name, $value, $expires = HOUR_IN_SECONDS)
@@ -44,7 +44,7 @@ class CacheController extends ShortPixelController
44
  if (isset(self::$cached_items[$name]))
45
  return self::$cached_items[$name];
46
 
47
- $cache = new cacheModel($name);
48
  $cache = apply_filters('shortpixel/cache/get', $cache, $name);
49
  self::$cached_items[$name] = $cache;
50
 
1
  <?php
2
+ namespace ShortPixel\Controller;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
 
5
+ use ShortPixel\Model\CacheModel as CacheModel;
6
  // Future replacement for everything that needs temporary storage
7
  // Storage agnostic -> called function should not need to know what is stored where, this is job of controller.
8
  // Works with cache-model, which handles the data representation and storage.
9
  //
10
 
11
+ class CacheController extends \ShortPixel\Controller
12
  {
13
  protected static $cached_items = array();
14
 
15
  public function __construct()
16
  {
 
17
  }
18
 
19
  public function storeItem($name, $value, $expires = HOUR_IN_SECONDS)
44
  if (isset(self::$cached_items[$name]))
45
  return self::$cached_items[$name];
46
 
47
+ $cache = new CacheModel($name);
48
  $cache = apply_filters('shortpixel/cache/get', $cache, $name);
49
  self::$cached_items[$name] = $cache;
50
 
class/{controller/edit_media_controller.php → Controller/EditMediaController.php} RENAMED
@@ -1,9 +1,11 @@
1
  <?php
2
- namespace ShortPixel;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
 
 
 
5
  // Future contoller for the edit media metabox view.
6
- class editMediaController extends ShortPixelController
7
  {
8
  protected $template = 'view-edit-media';
9
  protected $model = 'image';
@@ -14,7 +16,6 @@ class editMediaController extends ShortPixelController
14
  public function __construct()
15
  {
16
  parent::__construct();
17
- $this->loadModel($this->model);
18
  }
19
 
20
  // This data should be rendered by Image Model in the future.
1
  <?php
2
+ namespace ShortPixel\Controller;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
 
5
+ use ShortPixel\Model\ImageModel as ImageModel;
6
+
7
  // Future contoller for the edit media metabox view.
8
+ class EditMediaController extends \ShortPixel\Controller
9
  {
10
  protected $template = 'view-edit-media';
11
  protected $model = 'image';
16
  public function __construct()
17
  {
18
  parent::__construct();
 
19
  }
20
 
21
  // This data should be rendered by Image Model in the future.
class/{controller/filesystem_controller.php → Controller/FileSystemController.php} RENAMED
@@ -1,22 +1,21 @@
1
  <?php
2
- namespace ShortPixel;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
 
 
 
 
5
 
6
  /** Controller for FileSystem operations
7
  *
8
  * This controller is used for -compound- ( complex ) FS operations, using the provided models File en Directory.
9
  */
10
- Class FileSystemController extends ShortPixelController
11
  {
12
  protected $env;
13
 
14
  public function __construct()
15
  {
16
- $this->loadModel('file');
17
- $this->loadModel('directory');
18
- // $this->loadModel('environment');
19
-
20
  $this->env = wpSPIO()->env();
21
 
22
  }
@@ -166,7 +165,7 @@ Class FileSystemController extends ShortPixelController
166
  if (is_null($url))
167
  return false;
168
 
169
- $parsed = parse_url($url); // returns array, null, or false.
170
 
171
  if (! is_null($parsed) && $parsed !== false)
172
  return $url;
1
  <?php
2
+ namespace ShortPixel\Controller;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
 
5
+ use ShortPixel\Model\DirectoryModel as DirectoryModel;
6
+ use ShortPixel\Model\FileModel as FileModel;
7
+
8
 
9
  /** Controller for FileSystem operations
10
  *
11
  * This controller is used for -compound- ( complex ) FS operations, using the provided models File en Directory.
12
  */
13
+ Class FileSystemController extends \ShortPixel\Controller
14
  {
15
  protected $env;
16
 
17
  public function __construct()
18
  {
 
 
 
 
19
  $this->env = wpSPIO()->env();
20
 
21
  }
165
  if (is_null($url))
166
  return false;
167
 
168
+ $parsed = parse_url($url); // returns array, null, or false.
169
 
170
  if (! is_null($parsed) && $parsed !== false)
171
  return $url;
class/{controller/front_controller.php → Controller/FrontController.php} RENAMED
@@ -1,11 +1,11 @@
1
  <?php
2
- namespace ShortPixel;
3
  use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
4
  use ShortPixel\Notices\NoticeController as Notices;
5
 
6
 
7
  /** Handle everything that SP is doing front-wise */
8
- class frontController extends ShortPixelController
9
  {
10
  // DeliverWebp option settings for front-end delivery of webp
11
  const WEBP_GLOBAL = 1;
@@ -16,7 +16,7 @@ class frontController extends ShortPixelController
16
  {
17
  $do_front = \wpSPIO()->settings()->frontBootstrap;
18
 
19
- if (wpSPIO()->env()->is_front) // if is front.
20
  {
21
  $this->initWebpHooks();
22
  if ($do_front)
1
  <?php
2
+ namespace ShortPixel\Controller;
3
  use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
4
  use ShortPixel\Notices\NoticeController as Notices;
5
 
6
 
7
  /** Handle everything that SP is doing front-wise */
8
+ class FrontController extends \ShortPixel\Controller
9
  {
10
  // DeliverWebp option settings for front-end delivery of webp
11
  const WEBP_GLOBAL = 1;
16
  {
17
  $do_front = \wpSPIO()->settings()->frontBootstrap;
18
 
19
+ if (\wpSPIO()->env()->is_front) // if is front.
20
  {
21
  $this->initWebpHooks();
22
  if ($do_front)
class/{controller/othermedia_controller.php → Controller/OtherMediaController.php} RENAMED
@@ -1,23 +1,17 @@
1
  <?php
2
-
3
- namespace ShortPixel;
4
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
5
  use ShortPixel\Notices\NoticeController as Notices;
6
 
 
 
 
7
  // Future contoller for the edit media metabox view.
8
- class OtherMediaController extends ShortPixelController
9
  {
10
-
11
- // protected $dataProvider; // spmetadao
12
-
13
  public function __construct()
14
  {
15
  parent::__construct();
16
- // $this->dataProvider = \wpSPIO()->getShortPixel()->getSpMetaDao();
17
-
18
- $this->loadModel('directory');
19
- $this->loadModel('directory_othermedia');
20
-
21
  }
22
 
23
  // Get CustomFolder for usage.
1
  <?php
2
+ namespace ShortPixel\Controller;
 
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
  use ShortPixel\Notices\NoticeController as Notices;
5
 
6
+ use ShortPixel\Model\DirectoryOtherMediaModel as DirectoryOtherMediaModel;
7
+ use ShortPixel\Model\DirectoryModel as DirectoryModel;
8
+
9
  // Future contoller for the edit media metabox view.
10
+ class OtherMediaController extends \ShortPixel\Controller
11
  {
 
 
 
12
  public function __construct()
13
  {
14
  parent::__construct();
 
 
 
 
 
15
  }
16
 
17
  // Get CustomFolder for usage.
class/{controller/settings.php → Controller/SettingsController.php} RENAMED
@@ -1,9 +1,13 @@
1
  <?php
2
- namespace ShortPixel;
3
  use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
4
  use ShortPixel\Notices\NoticeController as Notice;
5
 
6
- class SettingsController extends shortPixelController
 
 
 
 
7
  {
8
 
9
  //env
@@ -35,7 +39,6 @@ class SettingsController extends shortPixelController
35
  // @todo Remove Debug Call
36
  $this->model = new \WPShortPixelSettings();
37
 
38
- $this->loadModel('apikey');
39
  $this->keyModel = new ApiKeyModel();
40
 
41
  parent::__construct();
@@ -118,7 +121,6 @@ class SettingsController extends shortPixelController
118
  public function action_debug_medialibrary()
119
  {
120
  $this->loadEnv();
121
- $this->loadModel('image');
122
 
123
  \WpShortPixelMediaLbraryAdapter::reCountMediaLibraryItems();
124
 
@@ -135,7 +137,7 @@ class SettingsController extends shortPixelController
135
  $nextgen->nextGenEnabled($previous);
136
 
137
  // Reset any integration notices when updating settings.
138
- adminNoticesController::resetIntegrationNotices();
139
  }
140
 
141
  $check_key = false;
1
  <?php
2
+ namespace ShortPixel\Controller;
3
  use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
4
  use ShortPixel\Notices\NoticeController as Notice;
5
 
6
+ use ShortPixel\Model\ApiKeyModel as ApiKeyModel;
7
+
8
+ use ShortPixel\NextGen as NextGen;
9
+
10
+ class SettingsController extends \ShortPixel\Controller
11
  {
12
 
13
  //env
39
  // @todo Remove Debug Call
40
  $this->model = new \WPShortPixelSettings();
41
 
 
42
  $this->keyModel = new ApiKeyModel();
43
 
44
  parent::__construct();
121
  public function action_debug_medialibrary()
122
  {
123
  $this->loadEnv();
 
124
 
125
  \WpShortPixelMediaLbraryAdapter::reCountMediaLibraryItems();
126
 
137
  $nextgen->nextGenEnabled($previous);
138
 
139
  // Reset any integration notices when updating settings.
140
+ AdminNoticesController::resetIntegrationNotices();
141
  }
142
 
143
  $check_key = false;
class/{controller/views/bulk-restore-all.php → Controller/View/BulkRestoreAll.php} RENAMED
@@ -1,9 +1,10 @@
1
  <?php
2
- namespace ShortPixel;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
 
 
5
 
6
- class BulkRestoreAll extends ShortPixelController
7
  {
8
  protected static $slug = 'bulk-restore-all';
9
  protected $template = 'view-restore-all';
@@ -74,7 +75,7 @@ class BulkRestoreAll extends ShortPixelController
74
  // Not doing this, since it's deliverd from bulk_view_controller. Yes, this is hacky. Prob. controller should merge.
75
  // $this->checkPost(); // check if any POST vars are there ( which should be if custom restore is on )
76
  $selected_folders = isset($_POST['selected_folders']) ? $_POST['selected_folders'] : array();
77
-
78
  // handle the custom folders if there are any.
79
  if (count($selected_folders) > 0)
80
  {
1
  <?php
2
+ namespace ShortPixel\Controller\View;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
 
5
+ use \ShortPixel\Controller\OtherMediaController as OtherMediaController;
6
 
7
+ class BulkRestoreAll extends \ShortPixel\Controller
8
  {
9
  protected static $slug = 'bulk-restore-all';
10
  protected $template = 'view-restore-all';
75
  // Not doing this, since it's deliverd from bulk_view_controller. Yes, this is hacky. Prob. controller should merge.
76
  // $this->checkPost(); // check if any POST vars are there ( which should be if custom restore is on )
77
  $selected_folders = isset($_POST['selected_folders']) ? $_POST['selected_folders'] : array();
78
+
79
  // handle the custom folders if there are any.
80
  if (count($selected_folders) > 0)
81
  {
class/{controller/views/bulk_view_controller.php → Controller/View/BulkViewController.php} RENAMED
@@ -1,9 +1,12 @@
1
  <?php
2
- namespace ShortPixel;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
  use ShortPixel\Notices\NoticeController as Notices;
5
 
6
- class BulkViewController extends ShortPixelController
 
 
 
7
  {
8
 
9
  protected $form_action = 'sp-bulk';
@@ -109,7 +112,7 @@ protected $selected_folders = array();
109
  if(isset($_POST["bulkRestore"]))
110
  {
111
  Log::addInfo('Bulk Process - Bulk Restore');
112
- $bulkRestore = new \ShortPixel\BulkRestoreAll(); // controller
113
  $bulkRestore->setupBulk();
114
 
115
  $prioQ->startBulk(\ShortPixelQueue::BULK_TYPE_RESTORE);
@@ -151,31 +154,17 @@ protected $selected_folders = array();
151
  {
152
  $settings = \wpSPIO()->settings();
153
  $prioQ = \wpSPIO()->getShortPixel()->getPrioQ();
154
- /*
155
- $template_part = isset($_GET['part']) ? sanitize_text_field($_GET['part']) : false;
156
- $controller = \ShortPixelTools::namespaceit('ShortPixelController');
157
- $partControl = $controller::findControllerbySlug($template_part);
158
 
159
- if ($partControl)
160
- {
161
- $viewObj = new $partControl();
162
- $viewObj->setShortPixel($this);
163
- $viewObj->loadView(); // TODO [BS] This should call load, which should init and call view inside controller.
164
- }
165
 
166
- if (! $template_part)
167
- { */
168
- $averageCompression = \wpSPIO()->getShortPixel()->getAverageCompression();
169
- $thumbsProcessedCount = $settings->thumbsCount;//amount of optimized thumbnails
170
- $under5PercentCount = $settings->under5Percent;//amount of under 5% optimized imgs.
171
- $quotaData = $this->quotaData;
172
- $percent = $prioQ->bulkPaused() ? \wpSPIO()->getShortPixel()->getPercent($quotaData) : false;
173
-
174
- $view = new \ShortPixelView(\wpSPIO()->getShortPixel());
175
- $view->displayBulkProcessingForm($quotaData, $thumbsProcessedCount, $under5PercentCount,
176
- $prioQ->bulkRan(), $averageCompression, $settings->fileCount,
177
- \ShortPixelTools::formatBytes($settings->savedSpace), $percent, $this->pendingMeta);
178
- // }
179
  }
180
 
181
  public function loadViewProgress()
@@ -184,7 +173,7 @@ protected $selected_folders = array();
184
  $prioQ = \wpSPIO()->getShortPixel()->getPrioQ();
185
 
186
  if($settings->quotaExceeded == 1) {
187
- \ShortPixel\adminNoticesController::reInstateQuotaExceeded();
188
  return false;
189
  }
190
 
1
  <?php
2
+ namespace ShortPixel\Controller\View;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
  use ShortPixel\Notices\NoticeController as Notices;
5
 
6
+ use \ShortPixel\Controller\AdminNoticesController as AdminNoticesController;
7
+
8
+
9
+ class BulkViewController extends \ShortPixel\Controller
10
  {
11
 
12
  protected $form_action = 'sp-bulk';
112
  if(isset($_POST["bulkRestore"]))
113
  {
114
  Log::addInfo('Bulk Process - Bulk Restore');
115
+ $bulkRestore = new BulkRestoreAll(); // controller
116
  $bulkRestore->setupBulk();
117
 
118
  $prioQ->startBulk(\ShortPixelQueue::BULK_TYPE_RESTORE);
154
  {
155
  $settings = \wpSPIO()->settings();
156
  $prioQ = \wpSPIO()->getShortPixel()->getPrioQ();
 
 
 
 
157
 
158
+ $averageCompression = \wpSPIO()->getShortPixel()->getAverageCompression();
159
+ $thumbsProcessedCount = $settings->thumbsCount;//amount of optimized thumbnails
160
+ $under5PercentCount = $settings->under5Percent;//amount of under 5% optimized imgs.
161
+ $quotaData = $this->quotaData;
162
+ $percent = $prioQ->bulkPaused() ? \wpSPIO()->getShortPixel()->getPercent($quotaData) : false;
 
163
 
164
+ $view = new \ShortPixelView(\wpSPIO()->getShortPixel());
165
+ $view->displayBulkProcessingForm($quotaData, $thumbsProcessedCount, $under5PercentCount,
166
+ $prioQ->bulkRan(), $averageCompression, $settings->fileCount,
167
+ \ShortPixelTools::formatBytes($settings->savedSpace), $percent, $this->pendingMeta);
 
 
 
 
 
 
 
 
 
168
  }
169
 
170
  public function loadViewProgress()
173
  $prioQ = \wpSPIO()->getShortPixel()->getPrioQ();
174
 
175
  if($settings->quotaExceeded == 1) {
176
+ AdminNoticesController::reInstateQuotaExceeded();
177
  return false;
178
  }
179
 
class/{controller/views/othermedia_view_controller.php → Controller/View/OtherMediaViewController.php} RENAMED
@@ -1,15 +1,16 @@
1
  <?php
2
- namespace ShortPixel;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
  use ShortPixel\Notices\NoticeController as Notices;
5
 
 
 
6
 
7
  // Future contoller for the edit media metabox view.
8
- class OtherMediaViewController extends ShortPixelController
9
  {
10
  //$this->model = new
11
  protected $template = 'view-other-media';
12
- protected $model = 'image';
13
 
14
  // Pagination .
15
  protected $items_per_page = 20;
@@ -23,8 +24,6 @@ class OtherMediaViewController extends ShortPixelController
23
 
24
  public function __construct()
25
  {
26
- $this->loadModel($this->model);
27
- // $this->loadModel('image');
28
  parent::__construct();
29
  $this->setActions(); // possible actions.
30
 
@@ -88,8 +87,10 @@ class OtherMediaViewController extends ShortPixelController
88
  protected function setActions()
89
  {
90
  $nonce = wp_create_nonce( 'sp_custom_action' );
 
 
91
  $actions = array(
92
- 'optimize' => array('action' => 'optimize', '_wpnonce' => $nonce , 'text' => __('Optimize now','shortpixel-image-optimiser')),
93
 
94
  'retry' => array('action' => 'optimize', '_wpnonce' => $nonce, 'text' => __('Retry','shortpixel-image-optimiser')),
95
 
@@ -99,14 +100,21 @@ class OtherMediaViewController extends ShortPixelController
99
 
100
  'redoglossy' => array('action' => 'redo', '_wpnonce' => $nonce, 'type' => 'glossy', 'text' => __('Re-optimize glossy','shortpixel-image-optimiser')),
101
 
102
- 'quota' => array('action' => 'quota', '_wpnonce' => $nonce, 'text' =>__('Check quota','shortpixel-image-optimiser')),
 
 
 
 
 
103
 
104
  'restore' => array('action' => 'restore', '_wpnonce' => $nonce, 'text' => __('Restore Backup','shortpixel-image-optimiser')),
105
 
106
  'compare' => array('link' => '<a href="javascript:ShortPixel.loadComparer(\'C-%%item_id%%\');">%%text%%</a>',
107
  'text' => __('Compare', 'shortpixel-image-optimiser')),
108
  'view' => array('link' => '<a href="%%item_url%%" target="_blank">%%text%%</a>', 'text' => __('View','shortpixel-image-optimiser')),
109
- 'no-key' => array('link' => '<a href="options-general.php?page=wp-shortpixel-settings">%%text%%</a>', 'text' => __('Invalid API Key. Check your Settings','shortpixel-image-optimiser') ),
 
 
110
  );
111
  $this->actions = $actions;
112
  }
@@ -142,6 +150,12 @@ class OtherMediaViewController extends ShortPixelController
142
  ),
143
  );
144
 
 
 
 
 
 
 
145
  return $headings;
146
  }
147
 
@@ -235,6 +249,7 @@ class OtherMediaViewController extends ShortPixelController
235
  $this->view->rewriteHREF = '';
236
 
237
  $otherMediaController = new OtherMediaController();
 
238
 
239
  if (! $action)
240
  return; // no action this view.
@@ -252,19 +267,19 @@ class OtherMediaViewController extends ShortPixelController
252
  switch ($action)
253
  {
254
  case 'optimize':
255
- $this->shortPixel->optimizeCustomImage($item_id);
256
  $this->rewriteHREF();
257
 
258
  break;
259
  case 'restore':
260
- if($this->shortPixel->doCustomRestore($item_id))
261
  {
262
  Notices::addSuccess(__('File Successfully restored', 'shortpixel-image-optimiser'));
263
  }
264
  $this->rewriteHREF();
265
  break;
266
  case 'redo':
267
- $this->shortPixel->redo('C-' . $item_id, sanitize_text_field($_GET['type']));
268
  $this->rewriteHREF();
269
 
270
  break;
@@ -279,10 +294,18 @@ class OtherMediaViewController extends ShortPixelController
279
  case 'bulk-optimize': // bulk action checkboxes
280
  $optimize_ids = esc_sql($_POST['bulk-optimize']);
281
  foreach ($optimize_ids as $id) {
282
- $this->shortPixel->optimizeCustomImage($id);
283
  }
284
  $this->rewriteHREF();
285
  break;
 
 
 
 
 
 
 
 
286
  }
287
  }
288
 
@@ -468,14 +491,18 @@ class OtherMediaViewController extends ShortPixelController
468
  $thisActions = array();
469
  $settings = \wpSPIO()->settings();
470
  $keyControl = ApiKeyController::getInstance();
 
471
 
472
  if (! $keyControl->keyIsVerified())
473
  {
474
- $thisActions[] = $this->actions['no-key'];
 
475
  }
476
  elseif ($settings->quotaExceeded)
477
  {
 
478
  $thisActions[] = $this->actions['quota'];
 
479
  }
480
  elseif ($item->status < \ShortPixelMeta::FILE_STATUS_UNPROCESSED)
481
  {
@@ -511,10 +538,10 @@ class OtherMediaViewController extends ShortPixelController
511
  }
512
  }
513
 
514
- return $this->renderActions($thisActions, $item, $file);
515
  }
516
 
517
- protected function renderActions($actions, $item, $file)
518
  {
519
 
520
  foreach($actions as $index => $action)
@@ -538,13 +565,19 @@ class OtherMediaViewController extends ShortPixelController
538
  $url = $this->getPageURL(array('action' => $action_arg, '_wpnonce' => $nonce, 'item_id' => $item->id));
539
  if (isset($action['type']))
540
  $url = add_query_arg('type', $action['type'], $url);
 
541
 
542
- $link = '<a href="' . $url . '" class="action-' . $action_arg . '">' . $text . '</a>';
 
543
  }
544
 
545
  $actions[$index] = $link;
546
  }
547
 
 
 
 
 
548
  return $actions;
549
  }
550
 
@@ -562,6 +595,15 @@ class OtherMediaViewController extends ShortPixelController
562
 
563
  protected function getDisplayStatus($item)
564
  {
 
 
 
 
 
 
 
 
 
565
  switch($item->status) {
566
  case \ShortPixelMeta::FILE_STATUS_RESTORED:
567
  $msg = __('Restored','shortpixel-image-optimiser');
@@ -573,7 +615,7 @@ class OtherMediaViewController extends ShortPixelController
573
  $msg = $this->getSuccessMessage($item);
574
  break;
575
  case 1: $msg = "<img src=\"" . wpSPIO()->plugin_url('res/img/loading.gif') . "\" class='sp-loading-small'>&nbsp;"
576
- . __('Pending','shortpixel-image-optimiser');
577
  break;
578
  case 0: $msg = __('Image not processed.','shortpixel-image-optimiser');
579
  break;
@@ -678,14 +720,26 @@ class OtherMediaViewController extends ShortPixelController
678
 
679
  protected function getDisplayActions($actions)
680
  {
 
681
  if (count($actions) == 0)
682
  {
683
  return '';
684
  }
685
  elseif (count($actions) == 1)
686
  {
687
- return "<div class='single-action button-primary'>" . $actions[0] . "</div>";
688
  }
 
 
 
 
 
 
 
 
 
 
 
689
  else{
690
 
691
  $output = "<div class='sp-dropdown'>
1
  <?php
2
+ namespace ShortPixel\Controller\View;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
  use ShortPixel\Notices\NoticeController as Notices;
5
 
6
+ use ShortPixel\Controller\ApiKeyController as ApiKeyController;
7
+ use ShortPixel\Controller\OtherMediaController as OtherMediaController;
8
 
9
  // Future contoller for the edit media metabox view.
10
+ class OtherMediaViewController extends \ShortPixel\Controller
11
  {
12
  //$this->model = new
13
  protected $template = 'view-other-media';
 
14
 
15
  // Pagination .
16
  protected $items_per_page = 20;
24
 
25
  public function __construct()
26
  {
 
 
27
  parent::__construct();
28
  $this->setActions(); // possible actions.
29
 
87
  protected function setActions()
88
  {
89
  $nonce = wp_create_nonce( 'sp_custom_action' );
90
+ $keyControl = ApiKeyController::getInstance();
91
+
92
  $actions = array(
93
+ 'optimize' => array('action' => 'optimize', '_wpnonce' => $nonce , 'text' => __('Optimize now','shortpixel-image-optimiser'), 'class' => ''),
94
 
95
  'retry' => array('action' => 'optimize', '_wpnonce' => $nonce, 'text' => __('Retry','shortpixel-image-optimiser')),
96
 
100
 
101
  'redoglossy' => array('action' => 'redo', '_wpnonce' => $nonce, 'type' => 'glossy', 'text' => __('Re-optimize glossy','shortpixel-image-optimiser')),
102
 
103
+ 'quota' => array('action' => 'check-quota', '_wpnonce' => $nonce, 'text' =>__('Check quota','shortpixel-image-optimiser'), 'class' => 'button button-smaller'),
104
+ 'extend-quota' => array('link' => '<a href="https://shortpixel.com/login/' . $keyControl->getKeyForDisplay() . '" target="_blank" class="button-primary button-smaller">' . __('Extend Quota','shortpixel-image-optimiser') . '</a>'),
105
+
106
+ /* <a class='button button-smaller button-primary' href='". (defined("SHORTPIXEL_HIDE_API_KEY") ? '' : $this->ctrl->getApiKey()) . "' target='_blank'>"
107
+ . __('Extend Quota','shortpixel-image-optimiser') .
108
+ "</a> */
109
 
110
  'restore' => array('action' => 'restore', '_wpnonce' => $nonce, 'text' => __('Restore Backup','shortpixel-image-optimiser')),
111
 
112
  'compare' => array('link' => '<a href="javascript:ShortPixel.loadComparer(\'C-%%item_id%%\');">%%text%%</a>',
113
  'text' => __('Compare', 'shortpixel-image-optimiser')),
114
  'view' => array('link' => '<a href="%%item_url%%" target="_blank">%%text%%</a>', 'text' => __('View','shortpixel-image-optimiser')),
115
+ /*'no-key' => array('link' => __('Invalid API Key', 'shortpixel-image-optimiser') . ' <a href="options-general.php?page=wp-shortpixel-settings" class="text-link">%%text%%</a>', 'text' => __('Check your Settings','shortpixel-image-optimiser') ), */
116
+
117
+
118
  );
119
  $this->actions = $actions;
120
  }
150
  ),
151
  );
152
 
153
+ $keyControl = ApiKeyController::getInstance();
154
+ if (! $keyControl->keyIsVerified())
155
+ {
156
+ $headings['actions']['title'] = '';
157
+ }
158
+
159
  return $headings;
160
  }
161
 
249
  $this->view->rewriteHREF = '';
250
 
251
  $otherMediaController = new OtherMediaController();
252
+ $shortpixel = \wpSPIO()->getShortPixel();
253
 
254
  if (! $action)
255
  return; // no action this view.
267
  switch ($action)
268
  {
269
  case 'optimize':
270
+ $shortpixel->optimizeCustomImage($item_id);
271
  $this->rewriteHREF();
272
 
273
  break;
274
  case 'restore':
275
+ if($shortpixel->doCustomRestore($item_id))
276
  {
277
  Notices::addSuccess(__('File Successfully restored', 'shortpixel-image-optimiser'));
278
  }
279
  $this->rewriteHREF();
280
  break;
281
  case 'redo':
282
+ $shortpixel->redo('C-' . $item_id, sanitize_text_field($_GET['type']));
283
  $this->rewriteHREF();
284
 
285
  break;
294
  case 'bulk-optimize': // bulk action checkboxes
295
  $optimize_ids = esc_sql($_POST['bulk-optimize']);
296
  foreach ($optimize_ids as $id) {
297
+ $shortpixel->optimizeCustomImage($id);
298
  }
299
  $this->rewriteHREF();
300
  break;
301
+ case 'check-quota':
302
+ $shortpixel->getQuotaInformation();
303
+
304
+ $this->rewriteHREF();
305
+ break;
306
+ default:
307
+ Log::addWarn('Action hit OtherMediaViewController but was not caught' . $action . ' on '. $item_id);
308
+ break;
309
  }
310
  }
311
 
491
  $thisActions = array();
492
  $settings = \wpSPIO()->settings();
493
  $keyControl = ApiKeyController::getInstance();
494
+ $forceSingular = false; // force view to show all actions separate, not in clickdown
495
 
496
  if (! $keyControl->keyIsVerified())
497
  {
498
+ //$thisActions[] = $this->actions['no-key'];
499
+
500
  }
501
  elseif ($settings->quotaExceeded)
502
  {
503
+ $thisActions[] = $this->actions['extend-quota'];
504
  $thisActions[] = $this->actions['quota'];
505
+ $forceSingular = true;
506
  }
507
  elseif ($item->status < \ShortPixelMeta::FILE_STATUS_UNPROCESSED)
508
  {
538
  }
539
  }
540
 
541
+ return $this->renderActions($thisActions, $item, $file, $forceSingular);
542
  }
543
 
544
+ protected function renderActions($actions, $item, $file, $forceSingular = false)
545
  {
546
 
547
  foreach($actions as $index => $action)
565
  $url = $this->getPageURL(array('action' => $action_arg, '_wpnonce' => $nonce, 'item_id' => $item->id));
566
  if (isset($action['type']))
567
  $url = add_query_arg('type', $action['type'], $url);
568
+ $class = (isset($action['class'])) ? $action['class'] : '';
569
 
570
+
571
+ $link = '<a href="' . $url . '" class="action-' . $action_arg . ' ' . $class . '">' . $text . '</a>';
572
  }
573
 
574
  $actions[$index] = $link;
575
  }
576
 
577
+ if ($forceSingular)
578
+ {
579
+ array_unshift($actions, 'render-loose');
580
+ }
581
  return $actions;
582
  }
583
 
595
 
596
  protected function getDisplayStatus($item)
597
  {
598
+ $keyControl = ApiKeyController::getInstance();
599
+
600
+
601
+ if (! $keyControl->keyIsVerified())
602
+ {
603
+ $msg = __('Invalid API Key', 'shortpixel-image-optimiser') . ' <a href="options-general.php?page=wp-shortpixel-settings" class="text-link">' . __('Check your Settings','shortpixel-image-optimiser') . '</a>';
604
+ return $msg;
605
+ }
606
+
607
  switch($item->status) {
608
  case \ShortPixelMeta::FILE_STATUS_RESTORED:
609
  $msg = __('Restored','shortpixel-image-optimiser');
615
  $msg = $this->getSuccessMessage($item);
616
  break;
617
  case 1: $msg = "<img src=\"" . wpSPIO()->plugin_url('res/img/loading.gif') . "\" class='sp-loading-small'>&nbsp;"
618
+ . __('Image waiting to be processed','shortpixel-image-optimiser');
619
  break;
620
  case 0: $msg = __('Image not processed.','shortpixel-image-optimiser');
621
  break;
720
 
721
  protected function getDisplayActions($actions)
722
  {
723
+
724
  if (count($actions) == 0)
725
  {
726
  return '';
727
  }
728
  elseif (count($actions) == 1)
729
  {
730
+ return "<div class='single-action'>" . $actions[0] . "</div>";
731
  }
732
+ elseif($actions[0] == 'render-loose')
733
+ {
734
+ array_shift($actions);
735
+ $output = '<div class="multi-action-wrapper">';
736
+ foreach($actions as $action )
737
+ {
738
+ $output .= "<div class='single-action'>" . $action. "</div>";
739
+ }
740
+ $output .= "</div>";
741
+ return $output;
742
+ }
743
  else{
744
 
745
  $output = "<div class='sp-dropdown'>
class/{shortpixel-model.php → Model.php} RENAMED
@@ -2,7 +2,7 @@
2
  namespace ShortPixel;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
 
5
- abstract class ShortPixelModel
6
  {
7
  protected $model = array();
8
 
2
  namespace ShortPixel;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
 
5
+ abstract class Model
6
  {
7
  protected $model = array();
8
 
class/{model/apikey_model.php → Model/ApiKeyModel.php} RENAMED
@@ -1,9 +1,11 @@
1
  <?php
2
- namespace ShortPixel;
3
  use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
4
  use ShortPixel\Notices\NoticeController as Notice;
5
 
6
- class ApiKeyModel extends ShortPixelModel
 
 
7
  {
8
 
9
  // variables
@@ -186,9 +188,9 @@ class ApiKeyModel extends ShortPixelModel
186
  $this->key_is_verified = false;
187
  Log::addDebug('Clearing API Key');
188
 
189
- adminNoticesController::resetAPINotices();
190
- adminNoticesController::resetQuotaNotices();
191
- adminNoticesController::resetIntegrationNotices();
192
 
193
  $this->update();
194
 
@@ -252,7 +254,7 @@ class ApiKeyModel extends ShortPixelModel
252
  Notice::addError($notice);
253
  }
254
 
255
- adminNoticesController::resetAPINotices();
256
  }
257
 
258
 
@@ -290,13 +292,7 @@ class ApiKeyModel extends ShortPixelModel
290
  wp_redirect(admin_url("options-general.php?page=wp-shortpixel-settings"));
291
  exit();
292
  }
293
- /*elseif (function_exists('is_multisite') && is_multisite() && !$this->_settings->verifiedKey)
294
- { // @todo not optimal, License key needs it's own model to do checks upon.
295
- $scontrolname = \shortPixelTools::namespaceit("SettingsController");
296
- $scontrol = new $scontrolname();
297
- $scontrol->setShortPixel($this);
298
- $scontrol->checkKey();
299
- } */
300
  }
301
 
302
 
1
  <?php
2
+ namespace ShortPixel\Model;
3
  use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
4
  use ShortPixel\Notices\NoticeController as Notice;
5
 
6
+ use ShortPixel\Controller\AdminNoticesController as AdminNoticesController;
7
+
8
+ class ApiKeyModel extends \ShortPixel\Model
9
  {
10
 
11
  // variables
188
  $this->key_is_verified = false;
189
  Log::addDebug('Clearing API Key');
190
 
191
+ AdminNoticesController::resetAPINotices();
192
+ AdminNoticesController::resetQuotaNotices();
193
+ AdminNoticesController::resetIntegrationNotices();
194
 
195
  $this->update();
196
 
254
  Notice::addError($notice);
255
  }
256
 
257
+ AdminNoticesController::resetAPINotices();
258
  }
259
 
260
 
292
  wp_redirect(admin_url("options-general.php?page=wp-shortpixel-settings"));
293
  exit();
294
  }
295
+
 
 
 
 
 
 
296
  }
297
 
298
 
class/{model/cache_model.php → Model/CacheModel.php} RENAMED
@@ -1,5 +1,5 @@
1
  <?php
2
- namespace ShortPixel;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
 
5
 
1
  <?php
2
+ namespace ShortPixel\Model;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
 
5
 
class/{model/directory_model.php → Model/DirectoryModel.php} RENAMED
@@ -1,5 +1,5 @@
1
  <?php
2
- namespace ShortPixel;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
 
5
  /* Model for Directories
@@ -9,7 +9,7 @@ use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
9
  *
10
  */
11
 
12
- class DirectoryModel extends ShortPixelModel
13
  {
14
  // Directory info
15
  protected $path;
1
  <?php
2
+ namespace ShortPixel\Model;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
 
5
  /* Model for Directories
9
  *
10
  */
11
 
12
+ class DirectoryModel extends \ShortPixel\Model
13
  {
14
  // Directory info
15
  protected $path;
class/{model/directory_othermedia_model.php → Model/DirectoryOtherMediaModel.php} RENAMED
@@ -1,8 +1,10 @@
1
  <?php
2
- namespace ShortPixel;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
  use ShortPixel\Notices\NoticeController as Notice;
5
 
 
 
6
  // extends DirectoryModel. Handles Shortpixel_meta database table
7
  // Replacing main parts of shortpixel-folder
8
  class DirectoryOtherMediaModel extends DirectoryModel
@@ -310,7 +312,7 @@ class DirectoryOtherMediaModel extends DirectoryModel
310
  $args = wp_parse_args($args, $defaults);
311
 
312
  $fs = \wpSPIO()->fileSystem();
313
- $cache = new \ShortPixel\CacheController();
314
 
315
  $spMetaDao = \wpSPIO()->getShortPixel()->getSpMetaDao();
316
 
1
  <?php
2
+ namespace ShortPixel\Model;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
  use ShortPixel\Notices\NoticeController as Notice;
5
 
6
+ use \ShortPixel\Model\DirectoryModel as DirectoryModel;
7
+
8
  // extends DirectoryModel. Handles Shortpixel_meta database table
9
  // Replacing main parts of shortpixel-folder
10
  class DirectoryOtherMediaModel extends DirectoryModel
312
  $args = wp_parse_args($args, $defaults);
313
 
314
  $fs = \wpSPIO()->fileSystem();
315
+ $cache = new \ShortPixel\Controller\CacheController();
316
 
317
  $spMetaDao = \wpSPIO()->getShortPixel()->getSpMetaDao();
318
 
class/{model/environment_model.php → Model/EnvironmentModel.php} RENAMED
@@ -1,12 +1,12 @@
1
  <?php
2
- namespace ShortPixel;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
 
5
  /** Loads a few environment variables handy to have nearby
6
  *
7
  * Notice - This is meant to be loaded via the plugin class. Easy access with wpSPIO()->getEnv().
8
  */
9
- class EnvironmentModel extends ShortPixelModel
10
  {
11
  // Server and PHP
12
  public $is_nginx;
@@ -174,7 +174,7 @@ class EnvironmentModel extends ShortPixelModel
174
 
175
  public function setIntegrations()
176
  {
177
- $ng = NextGen::getInstance();
178
  $this->has_nextgen = $ng->has_nextgen();
179
 
180
  }
1
  <?php
2
+ namespace ShortPixel\Model;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
 
5
  /** Loads a few environment variables handy to have nearby
6
  *
7
  * Notice - This is meant to be loaded via the plugin class. Easy access with wpSPIO()->getEnv().
8
  */
9
+ class EnvironmentModel extends \ShortPixel\Model
10
  {
11
  // Server and PHP
12
  public $is_nginx;
174
 
175
  public function setIntegrations()
176
  {
177
+ $ng = \ShortPixel\NextGen::getInstance();
178
  $this->has_nextgen = $ng->has_nextgen();
179
 
180
  }
class/{model/file_model.php → Model/FileModel.php} RENAMED
@@ -1,5 +1,5 @@
1
  <?php
2
- namespace ShortPixel;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
 
5
  /* FileModel class.
@@ -12,7 +12,7 @@ use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
12
  * - Every file can have a backup counterpart.
13
  *
14
  */
15
- class FileModel extends ShortPixelModel
16
  {
17
 
18
  // File info
@@ -178,6 +178,7 @@ class FileModel extends ShortPixelModel
178
  return 0;
179
  }
180
 
 
181
  /** Copy a file to somewhere
182
  *
183
  * @param $destination String Full Path to new file.
@@ -329,9 +330,11 @@ class FileModel extends ShortPixelModel
329
 
330
  $path = wp_normalize_path($path);
331
 
 
332
  // if path does not contain basepath.
333
  $uploadPath = wp_normalize_path($this->getUploadPath()); // mixed slashes and dashes can also be a config-error in WP.
334
- if (strpos($path, ABSPATH) === false && strpos($path, $uploadPath) === false)
 
335
  $path = $this->relativeToFullPath($path);
336
 
337
  $path = apply_filters('shortpixel/filesystem/processFilePath', $path, $original_path);
1
  <?php
2
+ namespace ShortPixel\Model;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
 
5
  /* FileModel class.
12
  * - Every file can have a backup counterpart.
13
  *
14
  */
15
+ class FileModel extends \ShortPixel\Model
16
  {
17
 
18
  // File info
178
  return 0;
179
  }
180
 
181
+
182
  /** Copy a file to somewhere
183
  *
184
  * @param $destination String Full Path to new file.
330
 
331
  $path = wp_normalize_path($path);
332
 
333
+
334
  // if path does not contain basepath.
335
  $uploadPath = wp_normalize_path($this->getUploadPath()); // mixed slashes and dashes can also be a config-error in WP.
336
+ $abspath = wp_normalize_path(ABSPATH); // yup, can also be wrong.
337
+ if (strpos($path, $abspath) === false && strpos($path, $uploadPath) === false)
338
  $path = $this->relativeToFullPath($path);
339
 
340
  $path = apply_filters('shortpixel/filesystem/processFilePath', $path, $original_path);
class/{model/image_model.php → Model/ImageModel.php} RENAMED
@@ -1,5 +1,5 @@
1
  <?php
2
- namespace ShortPixel;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
 
5
  /* ImageModel class.
@@ -11,7 +11,7 @@ use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
11
  * - Goal: Structural ONE method calls of image related information, and combining information. Same task is now done on many places.
12
  * -- Shortpixel Class should be able to blindly call model for information, correct metadata and such.
13
  */
14
- class ImageModel extends ShortPixelModel
15
  {
16
 
17
  private $file; // the file representation
@@ -41,7 +41,7 @@ class ImageModel extends ShortPixelModel
41
  $this->meta = $this->facade->getMeta();
42
 
43
  $this->setImageStatus();
44
- $this->file = $fs->getAttachedFile($post_id);
45
 
46
  // WP 5.3 and higher. Check for original file.
47
  if (function_exists('wp_get_original_image_path'))
1
  <?php
2
+ namespace ShortPixel\Model;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
 
5
  /* ImageModel class.
11
  * - Goal: Structural ONE method calls of image related information, and combining information. Same task is now done on many places.
12
  * -- Shortpixel Class should be able to blindly call model for information, correct metadata and such.
13
  */
14
+ class ImageModel extends \ShortPixel\Model
15
  {
16
 
17
  private $file; // the file representation
41
  $this->meta = $this->facade->getMeta();
42
 
43
  $this->setImageStatus();
44
+ $this->file = $fs->getFile($this->meta->getPath() ); //$fs->getAttachedFile($post_id);
45
 
46
  // WP 5.3 and higher. Check for original file.
47
  if (function_exists('wp_get_original_image_path'))
class/{model → Model}/shortpixel-entity.php RENAMED
File without changes
class/{model → Model}/shortpixel-folder.php RENAMED
File without changes
class/{model → Model}/shortpixel-meta.php RENAMED
File without changes
class/{shortpixel_queue.php → Queue.php} RENAMED
File without changes
class/{shortpixel-tools.php → Tools.php} RENAMED
@@ -33,10 +33,6 @@ class ShortPixelTools {
33
  return plugin_dir_path(SHORTPIXEL_PLUGIN_FILE);
34
  }
35
 
36
- public static function namespaceit($name)
37
- {
38
- return '\ShortPixel\\' . $name;
39
- }
40
 
41
  public static function requestIsFrontendAjax()
42
  {
33
  return plugin_dir_path(SHORTPIXEL_PLUGIN_FILE);
34
  }
35
 
 
 
 
 
36
 
37
  public static function requestIsFrontendAjax()
38
  {
class/controller/bulk-restore-all.php DELETED
@@ -1,2 +0,0 @@
1
- <?php
2
- // Silence is golden.
 
 
class/db/shortpixel-custom-meta-dao.php CHANGED
@@ -85,13 +85,14 @@ class ShortPixelCustomMetaDao {
85
  private function addIfMissing($type, $table, $key, $field, $fkTable = null, $fkField = null) {
86
  $hasIndexSql = "select count(*) hasIndex from information_schema.statistics where table_name = '%s' and index_name = '%s' and table_schema = database()";
87
  $createIndexSql = "ALTER TABLE %s ADD UNIQUE INDEX %s (%s)";
88
- $createFkSql = "ALTER TABLE %s ADD FOREIGN KEY %s(%s) REFERENCES %s(%s)";
89
  $hasIndex = $this->db->query(sprintf($hasIndexSql, $table, $key));
90
  if($hasIndex[0]->hasIndex == 0){
91
  if($type == "UNIQUE INDEX"){
92
  $this->db->query(sprintf($createIndexSql, $table, $key, $field));
93
- } else {
94
  $this->db->query(sprintf($createFkSql, $table, $key, $field, $fkTable, $fkField));
 
95
  }
96
  return true;
97
  }
@@ -127,8 +128,8 @@ class ShortPixelCustomMetaDao {
127
 
128
  $this->addIfMissing("UNIQUE INDEX", $this->db->getPrefix()."shortpixel_meta", "sp_path_md5", "path_md5");
129
  // $this->addIfMissing("UNIQUE INDEX", $this->db->getPrefix()."shortpixel_meta", "sp_path", "path");
130
- $this->addIfMissing("FOREIGN KEY", $this->db->getPrefix()."shortpixel_meta", "fk_shortpixel_meta_folder", "folder_id",
131
- $this->db->getPrefix()."shortpixel_folders", "id");
132
  }
133
 
134
  public function getFolders() {
85
  private function addIfMissing($type, $table, $key, $field, $fkTable = null, $fkField = null) {
86
  $hasIndexSql = "select count(*) hasIndex from information_schema.statistics where table_name = '%s' and index_name = '%s' and table_schema = database()";
87
  $createIndexSql = "ALTER TABLE %s ADD UNIQUE INDEX %s (%s)";
88
+ //$createFkSql = "ALTER TABLE %s ADD FOREIGN KEY %s(%s) REFERENCES %s(%s)";
89
  $hasIndex = $this->db->query(sprintf($hasIndexSql, $table, $key));
90
  if($hasIndex[0]->hasIndex == 0){
91
  if($type == "UNIQUE INDEX"){
92
  $this->db->query(sprintf($createIndexSql, $table, $key, $field));
93
+ /* } else {
94
  $this->db->query(sprintf($createFkSql, $table, $key, $field, $fkTable, $fkField));
95
+ */
96
  }
97
  return true;
98
  }
128
 
129
  $this->addIfMissing("UNIQUE INDEX", $this->db->getPrefix()."shortpixel_meta", "sp_path_md5", "path_md5");
130
  // $this->addIfMissing("UNIQUE INDEX", $this->db->getPrefix()."shortpixel_meta", "sp_path", "path");
131
+ /* $this->addIfMissing("FOREIGN KEY", $this->db->getPrefix()."shortpixel_meta", "fk_shortpixel_meta_folder", "folder_id",
132
+ $this->db->getPrefix()."shortpixel_folders", "id"); */
133
  }
134
 
135
  public function getFolders() {
class/db/shortpixel-meta-facade.php CHANGED
@@ -1,8 +1,7 @@
1
  <?php
2
  use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
3
- use ShortPixel\ImageModel as ImageModel;
4
- use ShortPixel\FileSystemController as FileSystem;
5
- use ShortPixel\CacheController as Cache;
6
 
7
  class ShortPixelMetaFacade {
8
  const MEDIA_LIBRARY_TYPE = 1;
@@ -50,7 +49,7 @@ class ShortPixelMetaFacade {
50
  }
51
 
52
  private static function rawMetaToMeta($ID, $rawMeta) {
53
- $file = \wpSPIO()->filesystem()->getAttachedFile($ID);
54
  $path = $file->getFullPath();
55
 
56
  return new ShortPixelMeta(array(
@@ -281,7 +280,7 @@ class ShortPixelMetaFacade {
281
  Log::addDebug('Finding Thumbs on path' . $meta->getPath());
282
  $thumbs = WpShortPixelMediaLbraryAdapter::findThumbs($meta->getPath());
283
 
284
- $fs = new \ShortPixel\FileSystemController();
285
  $mainFile = $fs->getFile($meta->getPath());
286
 
287
  // Find Thumbs returns *full file path*
@@ -551,8 +550,7 @@ class ShortPixelMetaFacade {
551
  return $cacheItem->getValue();
552
  }
553
 
554
- $fs = new FileSystem();
555
- \wpSPIO()->loadModel('image');
556
 
557
  if($this->type == self::CUSTOM_TYPE) {
558
  $meta = $this->getMeta();
@@ -568,10 +566,10 @@ class ShortPixelMetaFacade {
568
  $filePaths[] = $meta->getPath();
569
  } else {
570
 
571
- $imageObj = new \ShortPixel\ImageModel();
572
  $imageObj->setbyPostID($this->ID);
573
 
574
- $fsFile = $imageObj->getFile(); //\wpSPIO()->filesystem()->getAttachedFile($this->ID);//get the full file PATH
575
 
576
  //$fsFile = $fs->getFile($path);
577
  $mainExists = apply_filters('shortpixel_image_exists', $fsFile->exists(), $fsFile->getFullPath(), $this->ID);
@@ -772,7 +770,7 @@ class ShortPixelMetaFacade {
772
  public function attemptRemoteDownload($url, $path, $attach_id)
773
  {
774
  $downloadTimeout = max(SHORTPIXEL_MAX_EXECUTION_TIME - 10, 15);
775
- $fs = new \ShortPixel\FileSystemController();
776
  $pathFile = $fs->getFile($path);
777
 
778
  $args_for_get = array(
1
  <?php
2
  use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
3
+ use ShortPixel\Model\ImageModel as ImageModel;
4
+ use ShortPixel\Controller\CacheController as Cache;
 
5
 
6
  class ShortPixelMetaFacade {
7
  const MEDIA_LIBRARY_TYPE = 1;
49
  }
50
 
51
  private static function rawMetaToMeta($ID, $rawMeta) {
52
+ $file = \wpSPIO()->fileSystem()->getAttachedFile($ID);
53
  $path = $file->getFullPath();
54
 
55
  return new ShortPixelMeta(array(
280
  Log::addDebug('Finding Thumbs on path' . $meta->getPath());
281
  $thumbs = WpShortPixelMediaLbraryAdapter::findThumbs($meta->getPath());
282
 
283
+ $fs = \wpSPIO()->fileSystem();
284
  $mainFile = $fs->getFile($meta->getPath());
285
 
286
  // Find Thumbs returns *full file path*
550
  return $cacheItem->getValue();
551
  }
552
 
553
+ $fs = \wpSPIO()->fileSystem();
 
554
 
555
  if($this->type == self::CUSTOM_TYPE) {
556
  $meta = $this->getMeta();
566
  $filePaths[] = $meta->getPath();
567
  } else {
568
 
569
+ $imageObj = new ImageModel();
570
  $imageObj->setbyPostID($this->ID);
571
 
572
+ $fsFile = $imageObj->getFile();
573
 
574
  //$fsFile = $fs->getFile($path);
575
  $mainExists = apply_filters('shortpixel_image_exists', $fsFile->exists(), $fsFile->getFullPath(), $this->ID);
770
  public function attemptRemoteDownload($url, $path, $attach_id)
771
  {
772
  $downloadTimeout = max(SHORTPIXEL_MAX_EXECUTION_TIME - 10, 15);
773
+ $fs = \wpSPIO()->fileSystem();
774
  $pathFile = $fs->getFile($path);
775
 
776
  $args_for_get = array(
class/db/wp-shortpixel-media-library-adapter.php CHANGED
@@ -1,6 +1,8 @@
1
  <?php
2
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
3
 
 
 
4
  class WpShortPixelMediaLbraryAdapter {
5
 
6
  private static $urls_this_run = array();
@@ -22,7 +24,7 @@ class WpShortPixelMediaLbraryAdapter {
22
 
23
  $foundUnlistedThumbs = false;
24
  $counter = 0;
25
- $fs = new \ShortPixel\FileSystemController();
26
 
27
  $filesWithErrors = array(); $moreFilesWithErrors = 0;
28
  $excludePatterns = WPShortPixelSettings::getOpt("excludePatterns");
@@ -533,7 +535,7 @@ class WpShortPixelMediaLbraryAdapter {
533
  // @todo weak call. See how in future settings might come via central provider.
534
  $settings = new \WPShortPixelSettings();
535
 
536
- $fs = new \ShortPixel\FileSystemController();
537
  $mainfile = $fs->getFile($filepath);
538
 
539
  $sizesCount = isset($data['sizes']) ? WpShortPixelMediaLbraryAdapter::countSizesNotExcluded($data['sizes']) : 0;
@@ -667,7 +669,7 @@ class WpShortPixelMediaLbraryAdapter {
667
  $thumbs = array();
668
 
669
  // New
670
- $fs = new \ShortPixel\FileSystemController();
671
  $file = $fs->getFile($mainFile);
672
 
673
  $directory = $file->getFileDir();
@@ -883,7 +885,7 @@ class WpShortPixelMediaLbraryAdapter {
883
  }
884
  foreach($idInfo->ids as $post_id)
885
  {
886
- $imageModel = new \ShortPixel\ImageModel();
887
  $imageModel->setByPostID($post_id);
888
  $imageModel->reAcquire();
889
  Log::addDebug('Reacquired: ' . $post_id );
1
  <?php
2
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
3
 
4
+ use ShortPixel\Model\ImageModel as ImageModel;
5
+
6
  class WpShortPixelMediaLbraryAdapter {
7
 
8
  private static $urls_this_run = array();
24
 
25
  $foundUnlistedThumbs = false;
26
  $counter = 0;
27
+ $fs = \wpSPIO()->fileSystem();
28
 
29
  $filesWithErrors = array(); $moreFilesWithErrors = 0;
30
  $excludePatterns = WPShortPixelSettings::getOpt("excludePatterns");
535
  // @todo weak call. See how in future settings might come via central provider.
536
  $settings = new \WPShortPixelSettings();
537
 
538
+ $fs = \wpSPIO()->fileSystem();
539
  $mainfile = $fs->getFile($filepath);
540
 
541
  $sizesCount = isset($data['sizes']) ? WpShortPixelMediaLbraryAdapter::countSizesNotExcluded($data['sizes']) : 0;
669
  $thumbs = array();
670
 
671
  // New
672
+ $fs = \wpSPIO()->fileSystem();
673
  $file = $fs->getFile($mainFile);
674
 
675
  $directory = $file->getFileDir();
885
  }
886
  foreach($idInfo->ids as $post_id)
887
  {
888
+ $imageModel = new ImageModel();
889
  $imageModel->setByPostID($post_id);
890
  $imageModel->reAcquire();
891
  Log::addDebug('Reacquired: ' . $post_id );
class/external/helpscout.php CHANGED
@@ -1,6 +1,8 @@
1
  <?php
2
  namespace ShortPixel;
3
 
 
 
4
  // Integration class for HelpScout
5
  class HelpScout
6
  {
1
  <?php
2
  namespace ShortPixel;
3
 
4
+ use ShortPixel\Controller\ApiKeyController as ApiKeyController;
5
+
6
  // Integration class for HelpScout
7
  class HelpScout
8
  {
class/external/nextgen.php CHANGED
@@ -3,6 +3,8 @@ namespace ShortPixel;
3
  use ShortPixel\Notices\NoticeController as Notice;
4
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
5
 
 
 
6
 
7
  class NextGen
8
  {
@@ -78,7 +80,6 @@ class NextGen
78
  public function nextGenEnabled($silent)
79
  {
80
 
81
- \WpShortPixelDb::checkCustomTables(); // check if custom tables are created, if not, create them
82
  $this->addNextGenGalleriesToCustom($silent);
83
  }
84
 
@@ -200,7 +201,7 @@ class NextGen
200
 
201
  public function resetNotification()
202
  {
203
- Notice::removeNoticeByID(adminNoticesController::MSG_INTEGRATION_NGGALLERY);
204
  }
205
 
206
  public function onDeleteImage($nggId, $size)
3
  use ShortPixel\Notices\NoticeController as Notice;
4
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
5
 
6
+ use ShortPixel\Controller\AdminNoticesController as AdminNoticesController;
7
+ use ShortPixel\Controller\OtherMediaController as OtherMediaController;
8
 
9
  class NextGen
10
  {
80
  public function nextGenEnabled($silent)
81
  {
82
 
 
83
  $this->addNextGenGalleriesToCustom($silent);
84
  }
85
 
201
 
202
  public function resetNotification()
203
  {
204
+ Notice::removeNoticeByID(AdminNoticesController::MSG_INTEGRATION_NGGALLERY);
205
  }
206
 
207
  public function onDeleteImage($nggId, $size)
class/external/wp-offload-media.php CHANGED
@@ -1,7 +1,6 @@
1
  <?php
2
  namespace ShortPixel;
3
  use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
4
- use ShortPixel\FileSystemController as FileSystem;
5
  use ShortPixel\Notices\NoticeController as Notice;
6
 
7
  class wpOffload
@@ -151,7 +150,7 @@ class wpOffload
151
 
152
  public function image_converted($id)
153
  {
154
- $fs = new \ShortPixel\FileSystemController();
155
 
156
  // Don't offload when setting is off.
157
  // delete the old file.
@@ -240,7 +239,7 @@ class wpOffload
240
  private function getWebpPaths($paths, $check_exists = true)
241
  {
242
  $newPaths = array();
243
- $fs = new FileSystem();
244
 
245
  foreach($paths as $size => $path)
246
  {
1
  <?php
2
  namespace ShortPixel;
3
  use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
 
4
  use ShortPixel\Notices\NoticeController as Notice;
5
 
6
  class wpOffload
150
 
151
  public function image_converted($id)
152
  {
153
+ $fs = \wpSPIO()->fileSystem();
154
 
155
  // Don't offload when setting is off.
156
  // delete the old file.
239
  private function getWebpPaths($paths, $check_exists = true)
240
  {
241
  $newPaths = array();
242
+ $fs = \wpSPIO()->fileSystem();
243
 
244
  foreach($paths as $size => $path)
245
  {
class/plugin.json ADDED
@@ -0,0 +1 @@
 
1
+ {"name":"ShortPixel\/Plugin","description":"ShortPixel AutoLoader","type":"function","autoload":{"psr-4":{"ShortPixel":"class"},"files":["shortpixel_api.php","class\/wp-short-pixel.php","class\/wp-shortpixel-settings.php","class\/view\/shortpixel_view.php","class\/shortpixel-png2jpg.php","class\/Model\/shortpixel-entity.php","class\/Model\/shortpixel-meta.php","class\/Model\/shortpixel-folder.php","class\/db\/shortpixel-db.php","class\/db\/wp-shortpixel-db.php","class\/db\/shortpixel-custom-meta-dao.php","class\/db\/wp-shortpixel-media-library-adapter.php","class\/db\/shortpixel-meta-facade.php","class\/external\/cloudflare.php","class\/external\/flywheel.php","class\/external\/gravityforms.php","class\/external\/helpscout.php","class\/external\/nextgen.php","class\/external\/securi.php","class\/external\/shortpixel_queue_db.php","class\/external\/visualcomposer.php","class\/external\/wp-offload-media.php","class\/external\/wpengine.php"]}}
class/shortpixel-png2jpg.php CHANGED
@@ -6,8 +6,8 @@
6
  */
7
 
8
  use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
9
- use ShortPixel\FileModel as FileModel;
10
- use ShortPixel\Directorymodel as DirectoryModel;
11
 
12
  //TODO decouple from directly using WP metadata, in order to be able to use it for custom images
13
  class ShortPixelPng2Jpg {
@@ -27,10 +27,10 @@ class ShortPixelPng2Jpg {
27
  //WPShortPixel::log("PNG2JPG SHELL EXEC: " . shell_exec('convert ' . $image . ' -format "%[opaque]" info:'));
28
 
29
  if (!file_exists($image)) {
30
- WPShortPixel::log("PNG2JPG FILE MISSING: " . $image);
31
  $transparent = 1;
32
  } elseif(ord(file_get_contents($image, false, null, 25, 1)) & 4) {
33
- WPShortPixel::log("PNG2JPG: 25th byte has thrid bit 1 - transparency");
34
  $transparent = 1;
35
  } else {
36
  $contents = file_get_contents($image);
@@ -39,18 +39,18 @@ class ShortPixelPng2Jpg {
39
  }
40
  if (!$transparent) {
41
  $is = getimagesize($image);
42
- WPShortPixel::log("PNG2JPG Image width: " . $is[0] . " height: " . $is[1] . " aprox. size: " . round($is[0]*$is[1]*5/1024/1024) . "M memory limit: " . ini_get('memory_limit') . " USED: " . memory_get_usage());
43
- WPShortPixel::log("PNG2JPG create from png $image");
44
  $img = @imagecreatefrompng($image);
45
- WPShortPixel::log("PNG2JPG created from png");
46
  if(!$img) {
47
- WPShortPixel::log("PNG2JPG not a PNG, imagecreatefrompng failed ");
48
  $transparent = true; //it's not a PNG, can't convert it
49
  } else {
50
- WPShortPixel::log("PNG2JPG is PNG");
51
  $w = imagesx($img); // Get the width of the image
52
  $h = imagesy($img); // Get the height of the image
53
- WPShortPixel::log("PNG2JPG width $w height $h. Now checking pixels.");
54
  //run through pixels until transparent pixel is found:
55
  for ($i = 0; $i < $w; $i++) {
56
  for ($j = 0; $j < $h; $j++) {
@@ -65,7 +65,7 @@ class ShortPixelPng2Jpg {
65
  }
66
  } // non-transparant.
67
 
68
- WPShortPixel::log("PNG2JPG is " . (!$transparent && !$transparent_pixel ? " not" : "") . " transparent");
69
  //pass on the img too, if it was already loaded from PNG, matter of performance
70
  return array('notTransparent' => !$transparent && !$transparent_pixel, 'img' => $img);
71
  }
@@ -83,12 +83,12 @@ class ShortPixelPng2Jpg {
83
  $image = $params['file'];
84
  $fs = \wpSPIO()->filesystem();
85
 
86
- WPShortPixel::log("PNG2JPG doConvert $image");
87
  if(!$img) {
88
- WPShortPixel::log("PNG2JPG doConvert create from PNG");
89
  $img = (file_exists($image) ? imagecreatefrompng($image) : false);
90
  if(!$img) {
91
- WPShortPixel::log("PNG2JPG doConvert image cannot be created.");
92
  return (object)array("params" => $params, "unlink" => false); //actually not a PNG.
93
  }
94
  }
@@ -96,7 +96,7 @@ class ShortPixelPng2Jpg {
96
  // WPShortPixel::log("PNG2JPG doConvert img ready");
97
  $x = imagesx($img);
98
  $y = imagesy($img);
99
- WPShortPixel::log("PNG2JPG doConvert width $x height $y");
100
  $bg = imagecreatetruecolor($x, $y);
101
  // WPShortPixel::log("PNG2JPG doConvert img created truecolor");
102
  if(!$bg) return (object)array("params" => $params, "unlink" => false);
@@ -119,22 +119,22 @@ class ShortPixelPng2Jpg {
119
  $newUrl = str_replace($filename, $uniquefile->getFileName(), $params['url']); //preg_replace("/\.png$/i", ".jpg", $params['url']);
120
 
121
  if (imagejpeg($bg, $newPath, 90)) {
122
- WPShortPixel::log("PNG2JPG doConvert created JPEG at $newPath");
123
  $newSize = filesize($newPath);
124
  $origSize = filesize($image);
125
  if($newSize > $origSize * 0.95 || $newSize == 0) {
126
  //if the image is not 5% smaller, don't bother.
127
  //if the size is 0, a conversion (or disk write) problem happened, go on with the PNG
128
- WPShortPixel::log("PNG2JPG converted image is larger ($newSize vs. $origSize), keeping the PNG");
129
  unlink($newPath);
130
  return (object)array("params" => $params, "unlink" => false);
131
  }
132
  //backup?
133
  if($backup) {
134
  $imageForBk = trailingslashit(dirname($image)) . ShortPixelAPI::MB_basename($newPath, '.jpg') . '.png';
135
- WPShortPixel::log("imageForBk should be PNG: $imageForBk");
136
  if($image != $imageForBk) {
137
- WPShortPixel::log("PNG2JPG doConvert rename $image to $imageForBk");
138
  @rename($image, $imageForBk);
139
  }
140
  if(!file_exists($imageForBk)) {
@@ -144,7 +144,7 @@ class ShortPixelPng2Jpg {
144
  $image = $imageForBk;
145
  $ret = ShortPixelAPI::backupImage($image, array($image));
146
  if($ret['Status'] !== ShortPixelAPI::STATUS_SUCCESS) {
147
- WPShortPixel::log("PNG2JPG couldn't backup, keeping the PNG");
148
  unlink($newPath);
149
  return (object)array("params" => $params, "unlink" => false);
150
  }
6
  */
7
 
8
  use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
9
+ use ShortPixel\Model\FileModel as FileModel;
10
+ use ShortPixel\Model\Directorymodel as DirectoryModel;
11
 
12
  //TODO decouple from directly using WP metadata, in order to be able to use it for custom images
13
  class ShortPixelPng2Jpg {
27
  //WPShortPixel::log("PNG2JPG SHELL EXEC: " . shell_exec('convert ' . $image . ' -format "%[opaque]" info:'));
28
 
29
  if (!file_exists($image)) {
30
+ Log::addDebug("PNG2JPG FILE MISSING: " . $image);
31
  $transparent = 1;
32
  } elseif(ord(file_get_contents($image, false, null, 25, 1)) & 4) {
33
+ Log::addDebug("PNG2JPG: 25th byte has thrid bit 1 - transparency");
34
  $transparent = 1;
35
  } else {
36
  $contents = file_get_contents($image);
39
  }
40
  if (!$transparent) {
41
  $is = getimagesize($image);
42
+ Log::addDebug("PNG2JPG Image width: " . $is[0] . " height: " . $is[1] . " aprox. size: " . round($is[0]*$is[1]*5/1024/1024) . "M memory limit: " . ini_get('memory_limit') . " USED: " . memory_get_usage());
43
+ Log::addDebug("PNG2JPG create from png $image");
44
  $img = @imagecreatefrompng($image);
45
+ Log::addDebug("PNG2JPG created from png");
46
  if(!$img) {
47
+ Log::addDebug("PNG2JPG not a PNG, imagecreatefrompng failed ");
48
  $transparent = true; //it's not a PNG, can't convert it
49
  } else {
50
+ Log::addDebug("PNG2JPG is PNG");
51
  $w = imagesx($img); // Get the width of the image
52
  $h = imagesy($img); // Get the height of the image
53
+ Log::addDebug("PNG2JPG width $w height $h. Now checking pixels.");
54
  //run through pixels until transparent pixel is found:
55
  for ($i = 0; $i < $w; $i++) {
56
  for ($j = 0; $j < $h; $j++) {
65
  }
66
  } // non-transparant.
67
 
68
+ Log::addDebug("PNG2JPG is " . (!$transparent && !$transparent_pixel ? " not" : "") . " transparent");
69
  //pass on the img too, if it was already loaded from PNG, matter of performance
70
  return array('notTransparent' => !$transparent && !$transparent_pixel, 'img' => $img);
71
  }
83
  $image = $params['file'];
84
  $fs = \wpSPIO()->filesystem();
85
 
86
+ Log::addDebug("PNG2JPG doConvert $image");
87
  if(!$img) {
88
+ Log::addDebug("PNG2JPG doConvert create from PNG");
89
  $img = (file_exists($image) ? imagecreatefrompng($image) : false);
90
  if(!$img) {
91
+ Log::addDebug("PNG2JPG doConvert image cannot be created.");
92
  return (object)array("params" => $params, "unlink" => false); //actually not a PNG.
93
  }
94
  }
96
  // WPShortPixel::log("PNG2JPG doConvert img ready");
97
  $x = imagesx($img);
98
  $y = imagesy($img);
99
+ Log::addDebug("PNG2JPG doConvert width $x height $y");
100
  $bg = imagecreatetruecolor($x, $y);
101
  // WPShortPixel::log("PNG2JPG doConvert img created truecolor");
102
  if(!$bg) return (object)array("params" => $params, "unlink" => false);
119
  $newUrl = str_replace($filename, $uniquefile->getFileName(), $params['url']); //preg_replace("/\.png$/i", ".jpg", $params['url']);
120
 
121
  if (imagejpeg($bg, $newPath, 90)) {
122
+ Log::addDebug("PNG2JPG doConvert created JPEG at $newPath");
123
  $newSize = filesize($newPath);
124
  $origSize = filesize($image);
125
  if($newSize > $origSize * 0.95 || $newSize == 0) {
126
  //if the image is not 5% smaller, don't bother.
127
  //if the size is 0, a conversion (or disk write) problem happened, go on with the PNG
128
+ Log::addDebug("PNG2JPG converted image is larger ($newSize vs. $origSize), keeping the PNG");
129
  unlink($newPath);
130
  return (object)array("params" => $params, "unlink" => false);
131
  }
132
  //backup?
133
  if($backup) {
134
  $imageForBk = trailingslashit(dirname($image)) . ShortPixelAPI::MB_basename($newPath, '.jpg') . '.png';
135
+ Log::addDebug("imageForBk should be PNG: $imageForBk");
136
  if($image != $imageForBk) {
137
+ Log::addDebug("PNG2JPG doConvert rename $image to $imageForBk");
138
  @rename($image, $imageForBk);
139
  }
140
  if(!file_exists($imageForBk)) {
144
  $image = $imageForBk;
145
  $ret = ShortPixelAPI::backupImage($image, array($image));
146
  if($ret['Status'] !== ShortPixelAPI::STATUS_SUCCESS) {
147
+ Log::addDebug("PNG2JPG couldn't backup, keeping the PNG");
148
  unlink($newPath);
149
  return (object)array("params" => $params, "unlink" => false);
150
  }
class/view/settings/part-general.php CHANGED
@@ -170,6 +170,7 @@
170
  <span class="dashicons dashicons-editor-help"></span><?php _e('Read more','shortpixel-image-optimiser');?>
171
  </a><br/>
172
  </p>
 
173
  <div style="margin-top: 10px;">
174
  <input type="radio" name="resizeType" id="resize_type_outer" value="outer" <?php echo($view->data->resizeType == 'inner' ? '' : 'checked') ?> style="margin: -50px 10px 60px 0;">
175
  <img alt="<?php _e('Resize outer','shortpixel-image-optimiser'); ?>" src="<?php echo(wpSPIO()->plugin_url('res/img/resize-outer.png' ));?>"
@@ -183,6 +184,106 @@
183
  <span class="dashicons dashicons-editor-help"></span><?php _e('What is this?','shortpixel-image-optimiser');?></a>
184
  </div>
185
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
  </td>
187
  </tr>
188
  </tbody>
170
  <span class="dashicons dashicons-editor-help"></span><?php _e('Read more','shortpixel-image-optimiser');?>
171
  </a><br/>
172
  </p>
173
+ <?php if(false) { ?>
174
  <div style="margin-top: 10px;">
175
  <input type="radio" name="resizeType" id="resize_type_outer" value="outer" <?php echo($view->data->resizeType == 'inner' ? '' : 'checked') ?> style="margin: -50px 10px 60px 0;">
176
  <img alt="<?php _e('Resize outer','shortpixel-image-optimiser'); ?>" src="<?php echo(wpSPIO()->plugin_url('res/img/resize-outer.png' ));?>"
184
  <span class="dashicons dashicons-editor-help"></span><?php _e('What is this?','shortpixel-image-optimiser');?></a>
185
  </div>
186
  </div>
187
+ <?php } ?>
188
+
189
+ <style>
190
+ .presentation-wrap {
191
+ padding: 10px;
192
+ text-align: center;
193
+ display: flex;
194
+ justify-content: center;
195
+ width: 600px;
196
+ }
197
+ @media(max-width: 1280px) {
198
+ .presentation-wrap {
199
+ width: 460px;
200
+ }
201
+ }
202
+ @media(max-width: 1140px) {
203
+ .presentation-wrap {
204
+ width: 320px;
205
+ }
206
+ }
207
+ .presentation-wrap img {
208
+ margin-auto;
209
+ }
210
+ .spai-resize-frame {
211
+ position: absolute;
212
+ border: 2px dashed #fd1d1d;
213
+ }
214
+ .spai-resize-frame:after {
215
+ font-size: 10px;
216
+ font-weight: bold;
217
+ position: absolute;
218
+ bottom: -15px;
219
+ right: 0;
220
+ color: red;
221
+ }
222
+ .resize-options-wrap {
223
+ margin: 10px 20px 0 20px;
224
+ float: left;
225
+ }
226
+ .resize-type-wrap label {
227
+ display: inline-block;
228
+ padding: 15px 0 0 0;
229
+ }
230
+ </style>
231
+ <div class="resize-type-wrap" <?php echo( $view->data->resizeImages ? '' : 'style="display:none;"' );?>>
232
+ <div class="resize-options-wrap">
233
+ <label title="<?php _e('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','shortpixel-image-optimiser');?>">
234
+ <input type="radio" name="resizeType" id="resize_type_outer" value="outer" <?= $view->data->resizeType == 'inner' ? '' : 'checked'; ?>>
235
+ <?= __( 'Cover', 'shortpixel-image-optimiser' ); ?>
236
+ </label><br>
237
+ <label title="<?php _e('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','shortpixel-image-optimiser');?>">
238
+ <input type="radio" name="resizeType" id="resize_type_inner" value="inner" <?= $view->data->resizeType == 'inner' ? 'checked' : ''; ?>>
239
+ <?= __( 'Contain', 'shortpixel-image-optimiser' ); ?>
240
+ </label><br>
241
+ <div style="display:inline-block;margin-top: 15px;"><a href="https://blog.shortpixel.com/resize-images/" class="shortpixel-help-link" target="_blank">
242
+ <span class="dashicons dashicons-editor-help"></span><?php _e('What is this?','shortpixel-image-optimiser');?></a>
243
+ </div>
244
+
245
+ </div>
246
+ <?php
247
+ $resize_width = (int) ( $view->data->resizeWidth > 0 ? $view->data->resizeWidth : min( 924, $view->minSizes[ 'width' ] ) );
248
+ $resize_height = (int) ( $view->data->resizeHeight > 0 ? $view->data->resizeHeight : min( 924, $view->minSizes[ 'height' ] ) );
249
+ $ratio = $resize_height / $resize_width;
250
+
251
+ $frame_style = 'padding-top:' . round( ( $ratio < 1.5 ? ( $ratio < 0.5 ? 0.5 : $ratio ) : 1.5 ) * 100, 0 ) . '%;';
252
+
253
+ $image_size = getimagesize( wpSPIO()->plugin_path( 'res/img/resize-type.png' ) );
254
+ ?>
255
+ <div class="presentation-wrap">
256
+ <div class="spai-resize-frame"></div>
257
+ <img class="spai-resize-img" src="<?php echo(wpSPIO()->plugin_url('res/img/resize-type.png'));?>" data-width="300" data-height="160"
258
+ srcset="<?php echo(wpSPIO()->plugin_url('res/img/resize-type@2x.png'));?> 2x" alt="">
259
+ </div>
260
+
261
+ <!--
262
+ <div class="presentation-wrap">
263
+ <div class="presentation-wrapper hidden" data-type="<?= $view->data->resizeType ?>">
264
+ <div class="frame-wrap">
265
+ <div class="frame">
266
+ <div class="frame-inner" style="<?= $frame_style; ?>">
267
+ <div class="image-wrap">
268
+ <img src="<?= wpSPIO()->plugin_url( 'res/img/resize-type.png' ); ?>" data-width="<?= $image_size[ 0 ]; ?>" data-height="<?= $image_size[ 1 ]; ?>" srcset="<?= wpSPIO()->plugin_url( 'res/img/resize-type@2x.png' ); ?> 2x" alt="" />
269
+ </div>
270
+ </div>
271
+ </div>
272
+ </div>
273
+ </div>
274
+ </div>
275
+ -->
276
+ </div>
277
+ <script type="text/javascript">
278
+
279
+ </script>
280
+
281
+
282
+
283
+
284
+
285
+
286
+
287
  </td>
288
  </tr>
289
  </tbody>
class/view/shortpixel_view.php CHANGED
@@ -1,6 +1,8 @@
1
  <?php
2
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
3
 
 
 
4
  class ShortPixelView {
5
 
6
  private $ctrl;
@@ -1569,7 +1571,7 @@ class ShortPixelView {
1569
  public function renderCustomColumn($id, $data, $extended = false){ ?>
1570
  <?php if ($extended) // extended ( edit-media ) moved to it's own view.
1571
  {
1572
- $controller = new \ShortPixel\editMediaController();
1573
  $controller->setTempData($data);
1574
  $controller->setLegacyView($this);
1575
  $controller->setShortPixel($this->ctrl);
@@ -1708,11 +1710,12 @@ class ShortPixelView {
1708
  }
1709
 
1710
  public function getQuotaExceededHTML($message = '') {
 
1711
  return "<div class='sp-column-actions' style='width:110px;'>
1712
- <a class='button button-smaller button-primary' href='https://shortpixel.com/login/". (defined("SHORTPIXEL_HIDE_API_KEY") ? '' : $this->ctrl->getApiKey()) . "' target='_blank'>"
1713
  . __('Extend Quota','shortpixel-image-optimiser') .
1714
  "</a>
1715
- <a class='button button-smaller' href='admin.php?action=shortpixel_check_quota'>"
1716
  . __('Check&nbsp;&nbsp;Quota','shortpixel-image-optimiser') .
1717
  "</a></div>
1718
  <div class='sp-column-info'>" . $message . " " . __('Quota Exceeded','shortpixel-image-optimiser') . "</div>";
1
  <?php
2
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
3
 
4
+ use ShortPixel\Controller\ApiKeyController as ApiKeyController;
5
+
6
  class ShortPixelView {
7
 
8
  private $ctrl;
1571
  public function renderCustomColumn($id, $data, $extended = false){ ?>
1572
  <?php if ($extended) // extended ( edit-media ) moved to it's own view.
1573
  {
1574
+ $controller = new \ShortPixel\Controller\EditMediaController();
1575
  $controller->setTempData($data);
1576
  $controller->setLegacyView($this);
1577
  $controller->setShortPixel($this->ctrl);
1710
  }
1711
 
1712
  public function getQuotaExceededHTML($message = '') {
1713
+ $keyControl = ApiKeyController::getInstance();
1714
  return "<div class='sp-column-actions' style='width:110px;'>
1715
+ <a class='button button-smaller button-primary' href='https://shortpixel.com/login/". $keyControl->getKeyForDisplay() . "' target='_blank'>"
1716
  . __('Extend Quota','shortpixel-image-optimiser') .
1717
  "</a>
1718
+ <a class='button button-smaller' href='javascript:ShortPixel.checkQuota();'>"
1719
  . __('Check&nbsp;&nbsp;Quota','shortpixel-image-optimiser') .
1720
  "</a></div>
1721
  <div class='sp-column-info'>" . $message . " " . __('Quota Exceeded','shortpixel-image-optimiser') . "</div>";
class/view/view-other-media.php CHANGED
@@ -96,15 +96,14 @@ echo $this->view->rewriteHREF;
96
 
97
  $folder = isset($folders[$folder_id]) ? $folders[$folder_id] : false;
98
  $media_type = ($folder && $folder->isNextGen()) ? __('Nextgen', 'shortpixel-image-optimiser') : __('Custom', 'shortpixel_image_optimiser');
 
 
99
 
100
  ?>
101
- <span><div class='thumb'>
102
- <?php if ($filesize <= 500000 && $filesize > 0):
103
- $img_url = $fs->pathToUrl($itemFile); ?>
104
- <img src="<?php echo $img_url ?>" />
105
- <?php endif; ?>
106
-
107
- </div></span>
108
  <span class='filename'><?php echo $itemFile->getFileName() ?>
109
  <div class="row-actions"><?php
110
  $numberActions = count($rowActions);
96
 
97
  $folder = isset($folders[$folder_id]) ? $folders[$folder_id] : false;
98
  $media_type = ($folder && $folder->isNextGen()) ? __('Nextgen', 'shortpixel-image-optimiser') : __('Custom', 'shortpixel_image_optimiser');
99
+ $img_url = $fs->pathToUrl($itemFile);
100
+ $heavy = ($filesize <= 500000 && $filesize > 0);
101
 
102
  ?>
103
+ <span><a href="<?php echo($img_url);?>" target="_blank">
104
+ <div class='thumb' <?php if($heavy) echo('title="' . __('This image is heavy and it would slow this page down if displayed here. Click to open it in a new browser tab.', 'shortpixel-image-optimiser') . '"');
105
+ ?> style="background-image:url('<?php echo($heavy ? $img_url : wpSPIO()->plugin_url('res/img/heavy-image@2x.png' )) ?>')"></div>
106
+ </a></span>
 
 
 
107
  <span class='filename'><?php echo $itemFile->getFileName() ?>
108
  <div class="row-actions"><?php
109
  $numberActions = count($rowActions);
class/wp-short-pixel.php CHANGED
@@ -2,9 +2,11 @@
2
  //use ShortPixel\DebugItem as DebugItem;
3
  use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
4
  use ShortPixel\Notices\NoticeController as Notices;
5
- use ShortPixel\FileModel as FileModel;
6
- use ShortPixel\Directorymodel as DirectoryModel;
7
- use ShortPixel\ImageModel as ImageModel;
 
 
8
 
9
  class WPShortPixel {
10
 
@@ -46,21 +48,16 @@ class WPShortPixel {
46
  $this->prioQ = (! defined('SHORTPIXEL_NOFLOCK')) ? new ShortPixelQueue($this, $this->_settings) : new ShortPixelQueueDB($this, $this->_settings);
47
  $this->view = new ShortPixelView($this);
48
 
49
- if (self::$first_run === false)
50
  {
51
  $this->loadHooks();
52
  }
53
-
54
- // only load backed, or when frontend processing is enabled.
55
- /*if (is_admin() || $this->_settings->frontBootstrap )
56
- {
57
- $keyControl = \ShortPixel\ApiKeyController::getInstance();
58
- } */
59
 
60
  }
61
 
62
  /** Fire only once hooks. In time these function mostly should be divided between controllers / hook itself moved to ShortPixel Plugin */
63
- protected function loadHooks()
64
  {
65
  self::$first_run = true;
66
  load_plugin_textdomain('shortpixel-image-optimiser', false, plugin_basename(dirname( SHORTPIXEL_PLUGIN_FILE )).'/lang');
@@ -106,8 +103,7 @@ class WPShortPixel {
106
  //custom hook
107
  add_action( 'shortpixel-optimize-now', array( &$this, 'optimizeNowHook' ), 10, 1);
108
 
109
- add_action( 'shortpixel-thumbnails-before-regenerate', array( &$this, 'thumbnailsBeforeRegenerateHook' ), 10, 1);
110
- add_action( 'shortpixel-thumbnails-regenerated', array( &$this, 'thumbnailsRegeneratedHook' ), 10, 4);
111
  add_filter( 'shortpixel_get_backup', array( &$this, 'shortpixelGetBackupFilter' ), 10, 1 );
112
 
113
  if($isAdminUser) {
@@ -324,14 +320,13 @@ class WPShortPixel {
324
 
325
  wp_register_script('shortpixel', plugins_url('/res/js/shortpixel' . $this->jsSuffix,SHORTPIXEL_PLUGIN_FILE), array('jquery', 'jquery.knob.min.js'), SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true);
326
 
327
- $keyControl = \ShortPixel\ApiKeyController::getInstance();
328
- $apikey = $keyControl->getKeyForDisplay();
329
-
330
  // Get a Secret Key.
331
- $cacheControl = new \ShortPixel\CacheController();
332
  $bulkSecret = $cacheControl->getItem('bulk-secret');
333
  $secretKey = (! is_null($bulkSecret->getValue() )) ? $bulkSecret->getValue() : false;
334
 
 
 
335
 
336
  // Using an Array within another Array to protect the primitive values from being cast to strings
337
  $ShortPixelConstants = array(array(
@@ -348,13 +343,11 @@ class WPShortPixel {
348
  'STATUS_SEARCHING' => ShortPixelAPI::STATUS_SEARCHING,
349
  'WP_PLUGIN_URL'=>plugins_url( '', SHORTPIXEL_PLUGIN_FILE ),
350
  'WP_ADMIN_URL'=>admin_url(),
351
- // 'API_KEY'=> $apikey,
352
  'API_IS_ACTIVE' => $keyControl->keyIsVerified(),
353
  'DEFAULT_COMPRESSION'=>0 + intval($this->_settings->compressionType), // no int can happen when settings are empty still
354
  'MEDIA_ALERT'=>$this->_settings->mediaAlert ? "done" : "todo",
355
  'FRONT_BOOTSTRAP'=>$this->_settings->frontBootstrap && (!isset($this->_settings->lastBackAction) || (time() - $this->_settings->lastBackAction > 600)) ? 1 : 0,
356
  'AJAX_URL'=>admin_url('admin-ajax.php'),
357
- 'AFFILIATE'=>false,
358
  'BULK_SECRET' => $secretKey,
359
  ));
360
 
@@ -399,8 +392,13 @@ class WPShortPixel {
399
  'loading' => __('Loading...', 'shortpixel-image-optimiser' ),
400
  //'' => __('', 'shortpixel-image-optimiser' ),
401
  );
 
 
 
 
402
  wp_localize_script( 'shortpixel', '_spTr', $jsTranslation );
403
  wp_localize_script( 'shortpixel', 'ShortPixelConstants', $ShortPixelConstants );
 
404
 
405
  wp_register_script('jquery.knob.min.js', plugins_url('/res/js/jquery.knob.min.js',SHORTPIXEL_PLUGIN_FILE) );
406
  wp_register_script('jquery.tooltip.min.js', plugins_url('/res/js/jquery.tooltip.min.js',SHORTPIXEL_PLUGIN_FILE) );
@@ -685,7 +683,7 @@ class WPShortPixel {
685
  //send a processing request right after a file was uploaded, do NOT wait for response
686
  $this->_apiInterface->doRequests($URLsAndPATHs['URLs'], false, $itemHandler, false, $refresh);
687
  } catch(Exception $e) {
688
- Log::addWarning('Handle Media Library Image Exceptions', $e);
689
  $meta['ShortPixelImprovement'] = $e->getMessage();
690
  return $meta;
691
  }
@@ -1144,7 +1142,7 @@ class WPShortPixel {
1144
  if (isset($_POST['bulk-secret']))
1145
  {
1146
  $secret = sanitize_text_field($_POST['bulk-secret']);
1147
- $cacheControl = new \ShortPixel\CacheController();
1148
  $cachedObj = $cacheControl->getItem('bulk-secret');
1149
 
1150
  if (! $cachedObj->exists())
@@ -1208,7 +1206,7 @@ class WPShortPixel {
1208
  && !$this->_settings->customBulkPaused)
1209
  { //take from custom images if any left to optimize - only if bulk was ever started
1210
  //but first refresh. Refresh interval is handled by controller.
1211
- $otherMedia = new \ShortPixel\OtherMediaController();
1212
  $otherMedia->refreshFolders();
1213
  /*if(time() - $this->_settings->hasCustomFolders > 3600) {
1214
  $notice = null; $this->refreshCustomFolders();
@@ -1471,7 +1469,7 @@ class WPShortPixel {
1471
  // Generate new actions after doing something for custom type (for now)
1472
  if($itemHandler->getType() == ShortPixelMetaFacade::CUSTOM_TYPE)
1473
  {
1474
- $othermediaView = new \ShortPixel\OtherMediaViewController();
1475
  $othermediaView->setShortPixel($this);
1476
  $result['actions'] = $othermediaView->renderNewActions(substr($itemId, 2));
1477
  }
@@ -1525,7 +1523,7 @@ class WPShortPixel {
1525
  Log::addDebug('Finding Thumbs on path' . $meta->getPath());
1526
  //$thumbs = WpShortPixelMediaLbraryAdapter::findThumbs($meta->getPath());
1527
 
1528
- $fs = new \ShortPixel\FileSystemController();
1529
  $mainFile = $fs->getFile($meta->getPath());
1530
 
1531
  // Find Thumbs returns *full file path*
@@ -1787,6 +1785,7 @@ class WPShortPixel {
1787
  */
1788
  public function thumbnailsRegeneratedHook($postId, $originalMeta, $regeneratedSizes = array(), $bulk = false) {
1789
 
 
1790
  if(isset($originalMeta["ShortPixelImprovement"]) && is_numeric($originalMeta["ShortPixelImprovement"])) {
1791
  $shortPixelMeta = $originalMeta["ShortPixel"];
1792
  unset($shortPixelMeta['thumbsMissing']);
@@ -1812,6 +1811,7 @@ class WPShortPixel {
1812
  if(isset($originalMeta["ShortPixelPng2Jpg"])) {
1813
  $meta["ShortPixelPng2Jpg"] = $originalMeta["ShortPixelPng2Jpg"];
1814
  }
 
1815
  //wp_update_attachment_metadata($postId, $meta);
1816
  update_post_meta($postId, '_wp_attachment_metadata', $meta);
1817
 
@@ -2003,9 +2003,8 @@ class WPShortPixel {
2003
  $fs = \wpSPIO()->filesystem();
2004
 
2005
  // Setup Original File and Data. This is used to determine backup path.
2006
- \wpSPIO()->loadModel('image');
2007
 
2008
- $imageObj = new \ShortPixel\ImageModel();
2009
  $imageObj->setbyPostID($attachmentID);
2010
 
2011
  $fsFile = $imageObj->getFile();
@@ -2031,8 +2030,22 @@ class WPShortPixel {
2031
 
2032
  // Get correct Backup Folder and file. .
2033
  $sizes = isset($rawMeta["sizes"]) ? $rawMeta["sizes"] : array();
2034
- $bkFolder = $fs->getDirectory($this->getBackupFolderAny($fsFile->getFullPath(), $sizes));
2035
- $bkFile = $fs->getFile($bkFolder->getPath() . $fsFile->getFileName());
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2036
 
2037
  Log::addDebug('Restore, Backup File -- ', array($bkFile->getFullPath(), $fsFile->getFullPath() ) );
2038
  // $pathInfo = pathinfo($file);
@@ -2235,7 +2248,7 @@ class WPShortPixel {
2235
  $crtMeta['sizes'] = $png2jpgSizes;
2236
  } else {
2237
  //this was an image converted on upload, regenerate the thumbs using the PNG main image BUT deactivate temporarily the filter!!
2238
- $admin = \ShortPixel\adminController::getInstance();
2239
 
2240
  //@todo Can be removed when test seems working.
2241
  $test = remove_filter( 'wp_generate_attachment_metadata', array($admin,'handleImageUploadHook'),10);
@@ -2354,7 +2367,7 @@ class WPShortPixel {
2354
  $fullSubDir = str_replace(get_home_path(), "", dirname($file)) . '/';
2355
  $bkFile = SHORTPIXEL_BACKUP_FOLDER . '/' . $fullSubDir . ShortPixelAPI::MB_basename($file);
2356
 
2357
- $fs = new \ShortPixel\FileSystemController();
2358
 
2359
  $fileObj = $fs->getFile($file);
2360
  $backupFile = $fileObj->getBackupFile(); // returns FileModel
@@ -2363,7 +2376,6 @@ class WPShortPixel {
2363
  {
2364
  Log::addWarn("Custom File $ID - $file does not have a backup");
2365
  $notice = Notices::addWarning(__('Not able to restore file(s). Could not find backup', 'shortpixel-image-optimiser'), true);
2366
- Log::addTemp('BackupFILe Notice', $notice);
2367
  Notices::addDetail($notice, (string) $file);
2368
  return false;
2369
  }
@@ -2566,20 +2578,46 @@ class WPShortPixel {
2566
  die(json_encode($ret));
2567
  }
2568
 
2569
- public function handleCheckQuota() {
2570
- $this->getQuotaInformation();
 
 
 
 
 
 
 
 
 
 
 
 
2571
  // store the referring webpage location
2572
  $sendback = wp_get_referer();
2573
  // sanitize the referring webpage location
2574
  $sendback = preg_replace('|[^a-z0-9-~+_.?#=&;,/:]|i', '', $sendback);
2575
  // send the user back where they came from
2576
- wp_redirect($sendback);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2577
  // we are done
2578
  }
2579
 
2580
- public function handleCheckQuotaAjax() {
2581
- $this->getQuotaInformation();
2582
- }
2583
 
2584
  // @todo integrate this in a normal way / move @unlinks to proper fs delete.
2585
  public function handleDeleteAttachmentInBackup($ID) {
@@ -2800,9 +2838,17 @@ class WPShortPixel {
2800
  $dir = $fs->getDirectory($postDir);
2801
  $files = $dir->getFiles();
2802
  $subdirs = $fs->sortFiles($dir->getSubDirectories()); // runs through FS sort.
2803
-
2804
  $returnDir = substr($postDir, strlen($root));
2805
 
 
 
 
 
 
 
 
 
 
2806
  if( count($subdirs) > 0 ) {
2807
  echo "<ul class='jqueryFileTree'>";
2808
  foreach($subdirs as $dir ) {
@@ -2810,7 +2856,6 @@ class WPShortPixel {
2810
  $dirpath = $dir->getPath();
2811
  $dirname = $dir->getName();
2812
  // @todo Should in time be moved to othermedia_controller / check if media library
2813
- if($dirname == 'ShortpixelBackups' || ShortPixelMetaFacade::isMediaSubfolder($dirname, false)) continue;
2814
 
2815
  $htmlRel = str_replace("'", "&apos;", $returnDir . $dirname);
2816
  $htmlName = htmlentities($dirname);
@@ -2818,17 +2863,21 @@ class WPShortPixel {
2818
 
2819
  if( $dir->exists() ) {
2820
  //KEEP the spaces in front of the rel values - it's a trick to make WP Hide not replace the wp-content path
2821
- // if( is_dir($postDir . $file) && (!$onlyFiles || $onlyFolders) ) {
2822
  echo "<li class='directory collapsed'>{$checkbox}<a rel=' " .$htmlRel. "/'>" . $htmlName . "</a></li>";
2823
- /* } else if (!$onlyFolders || $onlyFiles) {
2824
- echo "<li class='file ext_{$ext}'>{$checkbox}<a rel=' " . $htmlRel . "'>" . $htmlName . "</a></li>";
2825
- } */
2826
  }
 
2827
  }
2828
 
2829
  echo "</ul>";
2830
  }
 
 
 
 
 
 
2831
  }
 
2832
  die();
2833
  }
2834
 
@@ -2844,18 +2893,37 @@ class WPShortPixel {
2844
 
2845
  $ret = array();
2846
  // This shall not be Intval, since Post_id can be custom (C-xx)
2847
- $handle = new ShortPixelMetaFacade( sanitize_text_field($_POST['id']) );
2848
-
2849
- $meta = $handle->getMeta();
2850
- $rawMeta = $handle->getRawMeta();
2851
- $backupUrl = content_url() . "/" . SHORTPIXEL_UPLOADS_NAME . "/" . SHORTPIXEL_BACKUP . "/";
2852
- $uploadsUrl = ShortPixelMetaFacade::getHomeUrl();
2853
- $urlBkPath = ShortPixelMetaFacade::returnSubDir($meta->getPath());
2854
- $ret['origUrl'] = $backupUrl . $urlBkPath . $meta->getName();
2855
- if ($meta->getType() == ShortPixelMetaFacade::CUSTOM_TYPE)
 
 
 
2856
  {
2857
- $ret['optUrl'] = $uploadsUrl . $meta->getWebPath();
2858
- self::log('Getting image - ' . $urlBkPath . $meta->getPath());
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2859
  // [BS] Another bug? Width / Height not stored in Shortpixel meta.
2860
  $ret['width'] = $meta->getActualWidth();
2861
  $ret['height'] = $meta->getActualHeight();
@@ -2873,14 +2941,14 @@ class WPShortPixel {
2873
  $ret['height']= $imageSizes[1];
2874
  }
2875
  }
2876
- }
2877
  else
2878
  {
2879
  $ret['optUrl'] = wp_get_attachment_url( $_POST['id'] ); //$uploadsUrl . $urlBkPath . $meta->getName();
2880
  $ret['width'] = $rawMeta['width'];
2881
  $ret['height'] = $rawMeta['height'];
2882
  }
2883
-
2884
  die(json_encode((object)$ret));
2885
  }
2886
 
@@ -2923,7 +2991,7 @@ class WPShortPixel {
2923
  if($validityData['APIKeyValid']) {
2924
  $this->_settings->apiKey = $key;
2925
  $this->_settings->verifiedKey = true;
2926
- \ShortPixel\adminNoticesController::resetAPINotices();
2927
  Notices::addSuccess(__('Great, you successfully claimed your API Key! Please take a few moments to review the plugin settings below before starting to optimize your images.','shortpixel-image-optimiser'));
2928
  }
2929
  }
@@ -3168,9 +3236,7 @@ class WPShortPixel {
3168
 
3169
  if(!is_wp_error( $response )){
3170
  $this->_settings->httpProto = ($this->_settings->httpProto == 'https' ? 'http' : 'https');
3171
- //echo("protocol " . $this->_settings->httpProto . " succeeded");
3172
  } else {
3173
- //echo("protocol " . $this->_settings->httpProto . " failed too");
3174
  }
3175
  }
3176
  //Second fallback to HTTP get
@@ -3209,8 +3275,7 @@ class WPShortPixel {
3209
  }
3210
 
3211
  if($response['response']['code'] != 200) {
3212
- //$defaultData['Message'] .= "<BR><i>Debug info: response code {$response['response']['code']} URL $requestURL , Response ".json_encode($response)."</i>";
3213
- return $defaultData;
3214
  }
3215
 
3216
  $data = $response['body'];
@@ -3254,6 +3319,7 @@ class WPShortPixel {
3254
  $crtStats['optimizePdfs'] = $this->_settings->optimizePdfs;
3255
  $this->_settings->currentStats = $crtStats;
3256
 
 
3257
  return $dataArray;
3258
  }
3259
 
@@ -3263,8 +3329,8 @@ class WPShortPixel {
3263
  //unset($dismissed['exceed']);
3264
  $this->_settings->prioritySkip = array();
3265
  $this->_settings->dismissedNotices = $dismissed;
3266
- \ShortPixel\adminNoticesController::resetAPINotices();
3267
- \ShortPixel\adminNoticesController::resetQuotaNotices();
3268
  }
3269
  $this->_settings->quotaExceeded = 0;
3270
  }
@@ -3561,7 +3627,6 @@ class WPShortPixel {
3561
  */
3562
  public function onDeleteImage($post_id) {
3563
  Log::addDebug('onDeleteImage - Image Removal Detected ' . $post_id);
3564
- \wpSPIO()->loadModel('image');
3565
  $result = null;
3566
 
3567
  try
2
  //use ShortPixel\DebugItem as DebugItem;
3
  use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
4
  use ShortPixel\Notices\NoticeController as Notices;
5
+ use ShortPixel\Model\FileModel as FileModel;
6
+ use ShortPixel\Model\Directorymodel as DirectoryModel;
7
+ use ShortPixel\Model\ImageModel as ImageModel;
8
+
9
+ use ShortPixel\Controller\AdminNoticesController as AdminNoticesController;
10
 
11
  class WPShortPixel {
12
 
48
  $this->prioQ = (! defined('SHORTPIXEL_NOFLOCK')) ? new ShortPixelQueue($this, $this->_settings) : new ShortPixelQueueDB($this, $this->_settings);
49
  $this->view = new ShortPixelView($this);
50
 
51
+ /* if (self::$first_run === false)
52
  {
53
  $this->loadHooks();
54
  }
55
+ */
 
 
 
 
 
56
 
57
  }
58
 
59
  /** Fire only once hooks. In time these function mostly should be divided between controllers / hook itself moved to ShortPixel Plugin */
60
+ public function loadHooks()
61
  {
62
  self::$first_run = true;
63
  load_plugin_textdomain('shortpixel-image-optimiser', false, plugin_basename(dirname( SHORTPIXEL_PLUGIN_FILE )).'/lang');
103
  //custom hook
104
  add_action( 'shortpixel-optimize-now', array( &$this, 'optimizeNowHook' ), 10, 1);
105
 
106
+
 
107
  add_filter( 'shortpixel_get_backup', array( &$this, 'shortpixelGetBackupFilter' ), 10, 1 );
108
 
109
  if($isAdminUser) {
320
 
321
  wp_register_script('shortpixel', plugins_url('/res/js/shortpixel' . $this->jsSuffix,SHORTPIXEL_PLUGIN_FILE), array('jquery', 'jquery.knob.min.js'), SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true);
322
 
 
 
 
323
  // Get a Secret Key.
324
+ $cacheControl = new \ShortPixel\Controller\CacheController();
325
  $bulkSecret = $cacheControl->getItem('bulk-secret');
326
  $secretKey = (! is_null($bulkSecret->getValue() )) ? $bulkSecret->getValue() : false;
327
 
328
+ $keyControl = \ShortPixel\Controller\ApiKeyController::getInstance();
329
+ $apikey = $keyControl->getKeyForDisplay();
330
 
331
  // Using an Array within another Array to protect the primitive values from being cast to strings
332
  $ShortPixelConstants = array(array(
343
  'STATUS_SEARCHING' => ShortPixelAPI::STATUS_SEARCHING,
344
  'WP_PLUGIN_URL'=>plugins_url( '', SHORTPIXEL_PLUGIN_FILE ),
345
  'WP_ADMIN_URL'=>admin_url(),
 
346
  'API_IS_ACTIVE' => $keyControl->keyIsVerified(),
347
  'DEFAULT_COMPRESSION'=>0 + intval($this->_settings->compressionType), // no int can happen when settings are empty still
348
  'MEDIA_ALERT'=>$this->_settings->mediaAlert ? "done" : "todo",
349
  'FRONT_BOOTSTRAP'=>$this->_settings->frontBootstrap && (!isset($this->_settings->lastBackAction) || (time() - $this->_settings->lastBackAction > 600)) ? 1 : 0,
350
  'AJAX_URL'=>admin_url('admin-ajax.php'),
 
351
  'BULK_SECRET' => $secretKey,
352
  ));
353
 
392
  'loading' => __('Loading...', 'shortpixel-image-optimiser' ),
393
  //'' => __('', 'shortpixel-image-optimiser' ),
394
  );
395
+
396
+ $actions = array(
397
+ 'nonce_check_quota' => wp_create_nonce('check_quota')
398
+ );
399
  wp_localize_script( 'shortpixel', '_spTr', $jsTranslation );
400
  wp_localize_script( 'shortpixel', 'ShortPixelConstants', $ShortPixelConstants );
401
+ wp_localize_script('shortpixel', 'ShortPixelActions', $actions);
402
 
403
  wp_register_script('jquery.knob.min.js', plugins_url('/res/js/jquery.knob.min.js',SHORTPIXEL_PLUGIN_FILE) );
404
  wp_register_script('jquery.tooltip.min.js', plugins_url('/res/js/jquery.tooltip.min.js',SHORTPIXEL_PLUGIN_FILE) );
683
  //send a processing request right after a file was uploaded, do NOT wait for response
684
  $this->_apiInterface->doRequests($URLsAndPATHs['URLs'], false, $itemHandler, false, $refresh);
685
  } catch(Exception $e) {
686
+ Log::addWarn('Handle Media Library Image Exceptions', $e);
687
  $meta['ShortPixelImprovement'] = $e->getMessage();
688
  return $meta;
689
  }
1142
  if (isset($_POST['bulk-secret']))
1143
  {
1144
  $secret = sanitize_text_field($_POST['bulk-secret']);
1145
+ $cacheControl = new \ShortPixel\Controller\CacheController();
1146
  $cachedObj = $cacheControl->getItem('bulk-secret');
1147
 
1148
  if (! $cachedObj->exists())
1206
  && !$this->_settings->customBulkPaused)
1207
  { //take from custom images if any left to optimize - only if bulk was ever started
1208
  //but first refresh. Refresh interval is handled by controller.
1209
+ $otherMedia = new \ShortPixel\Controller\OtherMediaController();
1210
  $otherMedia->refreshFolders();
1211
  /*if(time() - $this->_settings->hasCustomFolders > 3600) {
1212
  $notice = null; $this->refreshCustomFolders();
1469
  // Generate new actions after doing something for custom type (for now)
1470
  if($itemHandler->getType() == ShortPixelMetaFacade::CUSTOM_TYPE)
1471
  {
1472
+ $othermediaView = new \ShortPixel\Controller\View\OtherMediaViewController();
1473
  $othermediaView->setShortPixel($this);
1474
  $result['actions'] = $othermediaView->renderNewActions(substr($itemId, 2));
1475
  }
1523
  Log::addDebug('Finding Thumbs on path' . $meta->getPath());
1524
  //$thumbs = WpShortPixelMediaLbraryAdapter::findThumbs($meta->getPath());
1525
 
1526
+ $fs = \wpSPIO()->fileSystem();
1527
  $mainFile = $fs->getFile($meta->getPath());
1528
 
1529
  // Find Thumbs returns *full file path*
1785
  */
1786
  public function thumbnailsRegeneratedHook($postId, $originalMeta, $regeneratedSizes = array(), $bulk = false) {
1787
 
1788
+
1789
  if(isset($originalMeta["ShortPixelImprovement"]) && is_numeric($originalMeta["ShortPixelImprovement"])) {
1790
  $shortPixelMeta = $originalMeta["ShortPixel"];
1791
  unset($shortPixelMeta['thumbsMissing']);
1811
  if(isset($originalMeta["ShortPixelPng2Jpg"])) {
1812
  $meta["ShortPixelPng2Jpg"] = $originalMeta["ShortPixelPng2Jpg"];
1813
  }
1814
+
1815
  //wp_update_attachment_metadata($postId, $meta);
1816
  update_post_meta($postId, '_wp_attachment_metadata', $meta);
1817
 
2003
  $fs = \wpSPIO()->filesystem();
2004
 
2005
  // Setup Original File and Data. This is used to determine backup path.
 
2006
 
2007
+ $imageObj = new ImageModel();
2008
  $imageObj->setbyPostID($attachmentID);
2009
 
2010
  $fsFile = $imageObj->getFile();
2030
 
2031
  // Get correct Backup Folder and file. .
2032
  $sizes = isset($rawMeta["sizes"]) ? $rawMeta["sizes"] : array();
2033
+ $oldBackupFolder = $this->getBackupFolderAny($fsFile->getFullPath(), $sizes);
2034
+
2035
+ // This is a bad patch. Just return if the backupFolder is hopeless, don't waste resources.
2036
+ if (!$oldBackupFolder)
2037
+ {
2038
+ $notice = Notices::addWarning(__("Not all backup files found. Restore not performed on these files ",'shortpixel-image-optimiser'), true);
2039
+ Notices::addDetail($notice, (string) $bkFile);
2040
+
2041
+ Log::addError('No Backup Files Found: ' . $bkFile);
2042
+ return false;
2043
+ }
2044
+ else
2045
+ {
2046
+ $bkFolder = $fs->getDirectory($oldBackupFolder);
2047
+ $bkFile = $fs->getFile($bkFolder->getPath() . $fsFile->getFileName());
2048
+ }
2049
 
2050
  Log::addDebug('Restore, Backup File -- ', array($bkFile->getFullPath(), $fsFile->getFullPath() ) );
2051
  // $pathInfo = pathinfo($file);
2248
  $crtMeta['sizes'] = $png2jpgSizes;
2249
  } else {
2250
  //this was an image converted on upload, regenerate the thumbs using the PNG main image BUT deactivate temporarily the filter!!
2251
+ $admin = \ShortPixel\Controller\AdminController::getInstance();
2252
 
2253
  //@todo Can be removed when test seems working.
2254
  $test = remove_filter( 'wp_generate_attachment_metadata', array($admin,'handleImageUploadHook'),10);
2367
  $fullSubDir = str_replace(get_home_path(), "", dirname($file)) . '/';
2368
  $bkFile = SHORTPIXEL_BACKUP_FOLDER . '/' . $fullSubDir . ShortPixelAPI::MB_basename($file);
2369
 
2370
+ $fs = \wpSPIO()->fileSystem();
2371
 
2372
  $fileObj = $fs->getFile($file);
2373
  $backupFile = $fileObj->getBackupFile(); // returns FileModel
2376
  {
2377
  Log::addWarn("Custom File $ID - $file does not have a backup");
2378
  $notice = Notices::addWarning(__('Not able to restore file(s). Could not find backup', 'shortpixel-image-optimiser'), true);
 
2379
  Notices::addDetail($notice, (string) $file);
2380
  return false;
2381
  }
2578
  die(json_encode($ret));
2579
  }
2580
 
2581
+ public function handleCheckQuota()
2582
+ {
2583
+ $return_json = isset($_POST['return_json']) ? true : false;
2584
+ if (! isset($_POST['nonce']) || ! wp_verify_nonce($_POST['nonce'], 'check_quota'))
2585
+ {
2586
+ Log::addError('Handle Check Quota, No nonce');
2587
+ exit('no nonce');
2588
+ }
2589
+
2590
+ $result = $this->getQuotaInformation();
2591
+
2592
+ // If quota still exceeds, and manual check is requests, reset notices to update on situation.
2593
+ if ($this->_settings->quotaExceeded)
2594
+ AdminNoticesController::resetQuotaNotices();
2595
  // store the referring webpage location
2596
  $sendback = wp_get_referer();
2597
  // sanitize the referring webpage location
2598
  $sendback = preg_replace('|[^a-z0-9-~+_.?#=&;,/:]|i', '', $sendback);
2599
  // send the user back where they came from
2600
+ if ($return_json)
2601
+ {
2602
+ $result = array('status' => 'no-quota', 'redirect' => $sendback);
2603
+ //$has_quota = isset($result['APICallsRemaining']) && (intval($result['APICallsRemaining']) > 0) ? true : false;
2604
+ if (! $this->_settings->quotaExceeded)
2605
+ {
2606
+ $result['status'] = 'has-quota';
2607
+ // $result['quota'] = $result['APICallsRemaining'];
2608
+ }
2609
+ else
2610
+ {
2611
+ Notices::addWarning( __('You have no available image credits. If you just bought a package, please note that sometimes it takes a few minutes for the payment confirmation to be sent to us by the payment processor.','shortpixel-image-optimiser') );
2612
+ }
2613
+
2614
+ wp_send_json($result);
2615
+ }
2616
+ else
2617
+ wp_redirect($sendback);
2618
  // we are done
2619
  }
2620
 
 
 
 
2621
 
2622
  // @todo integrate this in a normal way / move @unlinks to proper fs delete.
2623
  public function handleDeleteAttachmentInBackup($ID) {
2838
  $dir = $fs->getDirectory($postDir);
2839
  $files = $dir->getFiles();
2840
  $subdirs = $fs->sortFiles($dir->getSubDirectories()); // runs through FS sort.
 
2841
  $returnDir = substr($postDir, strlen($root));
2842
 
2843
+ foreach($subdirs as $index => $dir) // weed out the media library subdirectories.
2844
+ {
2845
+ $dirname = $dir->getName();
2846
+ if($dirname == 'ShortpixelBackups' || ShortPixelMetaFacade::isMediaSubfolder($dirname, false))
2847
+ {
2848
+ unset($subdirs[$index]);
2849
+ }
2850
+ }
2851
+
2852
  if( count($subdirs) > 0 ) {
2853
  echo "<ul class='jqueryFileTree'>";
2854
  foreach($subdirs as $dir ) {
2856
  $dirpath = $dir->getPath();
2857
  $dirname = $dir->getName();
2858
  // @todo Should in time be moved to othermedia_controller / check if media library
 
2859
 
2860
  $htmlRel = str_replace("'", "&apos;", $returnDir . $dirname);
2861
  $htmlName = htmlentities($dirname);
2863
 
2864
  if( $dir->exists() ) {
2865
  //KEEP the spaces in front of the rel values - it's a trick to make WP Hide not replace the wp-content path
 
2866
  echo "<li class='directory collapsed'>{$checkbox}<a rel=' " .$htmlRel. "/'>" . $htmlName . "</a></li>";
 
 
 
2867
  }
2868
+
2869
  }
2870
 
2871
  echo "</ul>";
2872
  }
2873
+ elseif ($_POST['dir'] == '/')
2874
+ {
2875
+ echo "<ul class='jqueryFileTree'>";
2876
+ _e('No Directories found that can be added to Custom Folders', 'shortpixel-image-optimiser');
2877
+ echo "</ul>";
2878
+ }
2879
  }
2880
+
2881
  die();
2882
  }
2883
 
2893
 
2894
  $ret = array();
2895
  // This shall not be Intval, since Post_id can be custom (C-xx)
2896
+ // $handle = new ShortPixelMetaFacade( sanitize_text_field($_POST['id']) );
2897
+
2898
+ $fs = \wpSPIO()->filesystem();
2899
+
2900
+ $imageObj = new ImageModel();
2901
+ $imageObj->setByPostID(sanitize_text_field($_POST['id']));
2902
+
2903
+ $file = $imageObj->getFile();
2904
+ $backupFile = $file->getBackupFile();
2905
+
2906
+ /* Check if image is scaled, and has no backup, if there is a backup of original (full) file */
2907
+ if (! $backupFile && $imageObj->has_original())
2908
  {
2909
+ $file = $imageObj->has_original();
2910
+ $backupFile = $file->getBackupFile();
2911
+ }
2912
+
2913
+ $backup_url = $fs->pathToUrl($backupFile);
2914
+
2915
+ $meta = $imageObj->getMeta();
2916
+ // $rawMeta = $imageObj->getFacade()->getRawMeta();
2917
+
2918
+ // $backupUrl = content_url() . "/" . SHORTPIXEL_UPLOADS_NAME . "/" . SHORTPIXEL_BACKUP . "/";
2919
+ // $uploadsUrl = ShortPixelMetaFacade::getHomeUrl();
2920
+ // $urlBkPath = ShortPixelMetaFacade::returnSubDir($meta->getPath());
2921
+ $ret['origUrl'] = $backup_url; // $backupUrl . $urlBkPath . $meta->getName();
2922
+
2923
+ // if ($meta->getType() == ShortPixelMetaFacade::CUSTOM_TYPE)
2924
+ // {
2925
+ $ret['optUrl'] = $fs->pathToUrl($file); // $uploadsUrl . $meta->getWebPath();
2926
+ // self::log('Getting image - ' . $urlBkPath . $meta->getPath());
2927
  // [BS] Another bug? Width / Height not stored in Shortpixel meta.
2928
  $ret['width'] = $meta->getActualWidth();
2929
  $ret['height'] = $meta->getActualHeight();
2941
  $ret['height']= $imageSizes[1];
2942
  }
2943
  }
2944
+ /* }
2945
  else
2946
  {
2947
  $ret['optUrl'] = wp_get_attachment_url( $_POST['id'] ); //$uploadsUrl . $urlBkPath . $meta->getName();
2948
  $ret['width'] = $rawMeta['width'];
2949
  $ret['height'] = $rawMeta['height'];
2950
  }
2951
+ */
2952
  die(json_encode((object)$ret));
2953
  }
2954
 
2991
  if($validityData['APIKeyValid']) {
2992
  $this->_settings->apiKey = $key;
2993
  $this->_settings->verifiedKey = true;
2994
+ \ShortPixel\Controller\AdminNoticesController::resetAPINotices();
2995
  Notices::addSuccess(__('Great, you successfully claimed your API Key! Please take a few moments to review the plugin settings below before starting to optimize your images.','shortpixel-image-optimiser'));
2996
  }
2997
  }
3236
 
3237
  if(!is_wp_error( $response )){
3238
  $this->_settings->httpProto = ($this->_settings->httpProto == 'https' ? 'http' : 'https');
 
3239
  } else {
 
3240
  }
3241
  }
3242
  //Second fallback to HTTP get
3275
  }
3276
 
3277
  if($response['response']['code'] != 200) {
3278
+ return $defaultData;
 
3279
  }
3280
 
3281
  $data = $response['body'];
3319
  $crtStats['optimizePdfs'] = $this->_settings->optimizePdfs;
3320
  $this->_settings->currentStats = $crtStats;
3321
 
3322
+ Log::addDebug('GetQuotaInformation Result ', $dataArray);
3323
  return $dataArray;
3324
  }
3325
 
3329
  //unset($dismissed['exceed']);
3330
  $this->_settings->prioritySkip = array();
3331
  $this->_settings->dismissedNotices = $dismissed;
3332
+ \ShortPixel\Controller\adminNoticesController::resetAPINotices();
3333
+ \ShortPixel\Controller\adminNoticesController::resetQuotaNotices();
3334
  }
3335
  $this->_settings->quotaExceeded = 0;
3336
  }
3627
  */
3628
  public function onDeleteImage($post_id) {
3629
  Log::addDebug('onDeleteImage - Image Removal Detected ' . $post_id);
 
3630
  $result = null;
3631
 
3632
  try
class/wp-shortpixel-settings.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
 
3
  /** Settings Model **/
4
- class WPShortPixelSettings extends ShortPixel\ShortPixelModel {
5
  private $_apiKey = '';
6
  private $_compressionType = 1;
7
  private $_keepExif = 0;
1
  <?php
2
 
3
  /** Settings Model **/
4
+ class WPShortPixelSettings extends \ShortPixel\Model {
5
  private $_apiKey = '';
6
  private $_compressionType = 1;
7
  private $_keepExif = 0;
readme.txt CHANGED
@@ -4,7 +4,7 @@ Tags: compressor, image, compression, optimize, image optimizer, image optimiser
4
  Requires at least: 3.2.0
5
  Tested up to: 5.4.1
6
  Requires PHP: 5.3
7
- Stable tag: 4.18.1
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -281,6 +281,21 @@ Hide the Cloudflare settings by defining these constants in wp-config.php:
281
 
282
  == Changelog ==
283
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
284
  = 4.18.1 =
285
 
286
  Release date 20th May 2020
@@ -351,217 +366,5 @@ Release date: 2nd April 2020
351
  * Removed from the plugin the files that are not used anymore;
352
  * Language – 15 new strings added, 0 updated, 0 fuzzied, and 8 obsoleted.
353
 
354
- = 4.16.4 =
355
-
356
- Release date: 26th March 2020
357
- * Fix for some notices that could not be dismissed
358
- * Fix for "Confirm new credits" notification
359
- * Language – 0 new strings added, 0 updated, 0 fuzzied, and 0 obsoleted
360
-
361
- = 4.16.3 =
362
-
363
- Release date: 9th March 2020
364
- * Fix missing button to choose a plan when running out of credits.
365
- * Language – 0 new strings added, 0 updated, 0 fuzzied, and 0 obsoleted
366
-
367
- = 4.16.2 =
368
-
369
- Release date: 27th February 2020
370
- * Fix notices javascript.
371
- * Language – 0 new strings added, 0 updated, 0 fuzzied, and 0 obsoleted
372
-
373
- = 4.16.1 =
374
-
375
- Release date: 14th February 2020
376
- * Fix non-dismissable alerts.
377
- * Reference to the Website Speed Optimization service.
378
- * Fixed: deleteItemCache in wrong place ( before save ) thus resetting data
379
- * Fixed: NextGen integration
380
- * Language – 3 new strings added, 0 updated, 0 fuzzied, and 0 obsoleted
381
-
382
- = 4.16.0 =
383
-
384
- Release date: 4th February 2020
385
- * New - Token support for Cloudflare via config constant or settings.
386
- * Backup setting - add orange warning when backups are off.
387
- * Button to dismiss the top bar notification of missing files.
388
- * Shortpixel now loads scripts with 'defer' on front site, if it's configured to be loaded there.
389
- * Hiding Cloudflare details via wp-config.php.
390
- * Hide the option "Process in front-end" when "Optimize media on upload" is not checked.
391
- * Fixes for multibyte filenames with mixed locales.
392
- * Fixes for combination of S3-offload, webp pictures and cnames.
393
- * Reworked Notifications.
394
- * Fixed - PNG2JPG Retry button didn't work, now properly resets retry counter.
395
- * Fixed - Realpath in directory model throws off installations with symlinks.
396
- * Fixed - Thrown Exception in API with corrupted images now caught.
397
- * Fixed - Debug window link was visible when it should not.
398
- * Fixed - ExcludePattern without value would result in notices.
399
- * Language – 7 new strings added, 0 updated, 0 fuzzied, and 0 obsoleted
400
-
401
- = 4.15.4 =
402
-
403
- Release date: 29th January 2020
404
- * Change the Help beacon to V2.
405
- * Language – 0 new strings added, 0 updated, 0 fuzzied, and 0 obsoleted
406
-
407
- = 4.15.3 =
408
-
409
- Release date: 20th December 2019
410
- * Hide the "Process in front-end" option if "Optimize media on upload" unchecked
411
- * Add ALT text for plugin images in Admin
412
- * Moved CSS for the admin bar to the actual admin bar stylesheet, other css no longer loading on those pages
413
- * Fixes for windows specific paths
414
- * Fixed: warning flood when using old version of S3-offload
415
- * Fix for frontend and error shortpixel in top toolbar
416
- * Fixed: Pancake menu now showing proper actions ( none ) if backup is not there.
417
- * Fixed: Windows paths in wp-short-pixel getBackupFolderInternal
418
- * Language – 4 new strings added, 0 updated, 0 fuzzied, and 0 obsoleted
419
-
420
- = 4.15.2 =
421
-
422
- Release date: 28th November 2019
423
- * Fix for is_null error and "Call to undefined method ShortPixel\ShortPixelPlugin::alterHtaccess" in some cases.
424
- * Language – 0 new strings added, 0 updated, 0 fuzzied, and 0 obsoleted
425
-
426
- = 4.15.1 =
427
-
428
- Release date: 27th November 2019
429
- * Fix the infamous T_PAAMAYIM_NEKUDOTAYIM error on PHP 5.3 with WP Offload Media compat. module.
430
- * Language – 0 new strings added, 0 updated, 0 fuzzied, and 0 obsoleted
431
-
432
- = 4.15.0 =
433
-
434
- Release date: 27th November 2019
435
- * Ask if WebP files should be created before bulk optimization : checkbox added in Bulk page.
436
- * Added filters for optimal chunk size when selecting records from wp_postmeta while bulk processing: 'shortpixel/db/chunk_size'.
437
- * Optimize images also on edit-media screen.
438
- * Experimental support for static cache firewalls, and sending images w/ timestamp: SHORTPIXEL_EXPERIMENTAL_SECURICACHE.
439
- * Limit loading of JS / CSS to pages we do work on.
440
- * Refactoring & speed optimizations: - new external class for gravity forms, nextgen and visual composer, new controller for global admin hooks, new front controller, updated plugin init, clean(ish) root file, database optimization(reduced number of queries), unlistedThumbs checker only fires when the optimize unlisted check is active, optimizations for filesystem and findFileByPattern.
441
- * WPML Duplicates - Don't mark empty GUID's as duplicate.
442
- * Fix broken styles on WP 5.3.
443
- * Fix in case meta_value in processCountable has a WP_Error object instead of normal metadata.
444
- * Fix on WP Engine when large wp_postmeta table: limit to 16K the size of the query with ID list.
445
- * Fixed: error when log path is not writeable
446
- * Fixed: double sends within the same images, can happen with something like WPML and it's duplicated media.
447
- * Fixed: bug when searching unlisted images, in some circumstances.
448
- * Fixed: max_execution_time when time is set lower than 0.
449
- * Fixed: directories with no permission would give PHP error
450
- * Fixed: pathToUrl now also works for paths outside wp uploads
451
- * Fixed: check for DOING_AJAX on redirect to settings.
452
- * Fixed: Shortpixel icon + exclamation mark in toolbar showing on every page load.
453
- * Fixed: Add Custom media browser doesn't display files anymore
454
- * Fixed: WebP option adds an extra border if image already has a border -> borders will not be replicated to <picture> tags.
455
- * Fixed: Validating empty key doesn't show any message.
456
- * Fixed: on Nginx writes .htaccess files.
457
- * Fixed: Bug with safeGetAttachmentUrl for URLs that start with //.
458
- * Fixed: New S3-Offload version breaks Shortpixel and offloading.
459
- * Fixed: get_attached_file when S3-Offload is active, breaks other plugins.
460
- * Fixed: crash when doing .htaccess files ( WP 5.3 specific ).
461
- * Fixed: double file occurences on png2jpg in conjunction with s3offload.
462
- * Language – 1 new strings added, 0 updated, 0 fuzzied, and 0 obsoleted
463
-
464
- = 4.14.6 =
465
-
466
- Release date: 9th October 2019
467
- * Don't convert to `<picture>` the `<img>`s with backgrounds.
468
- * Remove unused eval() call.
469
- * Restore the validate button next to API Key but change label to "Save and validate"
470
- * Fixed: PNGtoJPG issue with already uploaded images
471
- * Fixed: finding wrong unlisted thumbnails due to regex.
472
- * Fixed: fatal error when trying to delete crashed attachement ( without proper URL )
473
- * Fix for S3 offload - PNG2JPG , doesn't remove old JPG files
474
- * Fixed: S3Offload will not offload anymore when 'Copy files to bucket' is off ( and object was not previously offloaded )
475
- * S3Offload doesn't offload via optimiser anymore if this setting is off
476
- * Fixed: cutting out initial offload if optimization needs to be done, when autolibrary is on
477
- * Fix for PNG2JPG - JPG files remained in backupdir.
478
- * Small fix for remote download thumbnails
479
- * Fixed: notice in filemodel due meta-facade feeding array
480
- * Fixed: bug in File2Url in filesystemcontroller
481
- * Fixed: download issue in attempt to remote download
482
- * Language – 0 new strings added, 1 updated, 0 fuzzied, and 0 obsoleted
483
-
484
- = 4.14.5 =
485
-
486
- Release date: 29th August 2019
487
- * If constant SHORTPIXEL_USE_DOUBLE_WEBP_EXTENSION is defined as true, use double extension for WebP (.jpg.webp)
488
- * Fixed: Javascript - String.prototype causes errors on React apps
489
- * Fixed: Undefined page load when using ShortPixel and Divi preloaded images
490
- * Fixed: Offload Media - When removing PNG2JPG converted file, the files / folder are not removed.
491
- * Fixed: When the constant that enables using double extensions for WebP (.jpg.webp) is active, the webp's are found as unlisted thumbnails and sent to optimization.
492
- * Fixed: missing call to apply_filters('shortpixel_image_exists'...) on a particular case.
493
- * Language – 0 new strings added, 1 updated, 0 fuzzied, and 0 obsoleted
494
-
495
- = 4.14.4 =
496
-
497
- Release date: 19th August 2019
498
- * Check if unlisted thumbnails present for already optimized images (in case the thumbnails were added later) in Media Library list and when doing bulk. This also integrates with the Unicode plugin.
499
- * If JSON PHP module not present, add a proper error
500
- * Fixed: bulk error "WordPress database error You have an error in your SQL syntax" on some installs
501
- * Fixed: Warning: count() Parameter must be an array.
502
- * Language – 0 new strings added, 0 updated, 0 fuzzied, and 0 obsoleted
503
-
504
- = 4.14.3 =
505
-
506
- Release date: 22nd July 2019
507
- * Compatibility with Flywheel hosting by not using flock if Flywheel detected
508
- * When using the PICTURE tag to deliver WebP, keep the width and height at `<IMG>` level
509
- * Refactoring of the API Key settings page, refactoring of Other media
510
- * Performance improvements for selecting from large wp_posts and wp_postmeta tables when doing bulk optimization
511
- * Display a message when bulk is skipping many processed images, if bulk processing is ran again.
512
- * Fixed: Other media - Recompress adds "Preserve CMYK"
513
- * Fixed: duplicate error message when validating wrong API key
514
- * Conflict message: align the text vertically and provide space between text and button when displayed on any admin page
515
- * Fixed: Other media Restore fails when original file is readable, not writable
516
-
517
- = 4.14.2 =
518
-
519
- Release date: 1st July 2019
520
- * add the possibility to define custom infixes for thumbnails (like image-uai-150x150.jpg for image.jpg) - comma separated define SHORTPIXEL_CUSTOM_THUMB_INFIXES
521
-
522
- = 4.14.1 =
523
-
524
- Release date: 17th June 2019
525
- * Fix errors when DOMDocument not present
526
-
527
- = 4.14.0 =
528
-
529
- Release date: 17th June 2019
530
- * Add new filters proposed by WP Stateless: shortpixel_backup_folder, shortpixel_image_exists, shortpixel_image_urls
531
- * Better placement of the elements on the Other Media page
532
- * Fix custom bulk for PDFs when the pdf thumbnails are not activated
533
- * Fix selecting items from DB twice for bulk in some circumstances
534
- * Warn user that converting PNG to JPG while keeping EXIF in options doesn't keep it (no EXIF for PNGs).
535
- * When SHORTPIXEL_DEBUG=x get parameter is provided, display a floating link to the shortpixel_log file
536
- * Adaptive Max execution time and capped to 90 sec. for the bulk background AJAX calls. (Kinsta has a max_execution_time of 300 sec. in PHP but the HTTP connection is cut after 180 sec.)
537
- * Fix custom 404 page for missing images not working when using .htaccess for WebP
538
- * Fix WebP picture tag with relative URLs not working in some circumstances
539
- * Fix replacing the `<img>` inside an existing `<picture>` tag with another `<picture>` tag.
540
- * Clear SP optimization cache in order to be able to optimize an image which initially had permissions error, after changing the permissions.
541
- * Fix being able to list the contents of ShortpixelBackups on some badly configured servers.
542
- * Fix error when inputting D'Artagnan in the AUTH pass field of settings.
543
- * Add the Quriobot for support.
544
-
545
- = 4.13.1 =
546
-
547
- Release date: 16th April 2019
548
- * fix thumbnail optimization when a thumbnail was replaced with another one
549
- * better integration with Regenerate Thumbnails Advanced
550
-
551
- = 4.13.0 =
552
-
553
- Release date: 10th April 2019
554
- * Bulk restore for the Other Media
555
- * make the filename extension be updated when manually optimizing a PNG from Media Library, if the convert to JPG is active, without refreshing the page
556
- * Integration with Regenerate Thumbnails Advanced new 2.0 beta version
557
- * Add the rules for WebP in the WP-CONTENT .htaccess
558
- * ShortPixel Other Media - display the time of optimization in the grid and offer option to sort by it
559
- * Keep sort order when optimizing / refreshing page on Other Media
560
- * offer the visual comparer for Other Media too
561
- * resolve the Settings inconsistency in Other Media (settings displayed were from when adding the folder not from when actually optimizing)
562
- * Make pressing Escape or clicking outside of any popup close it.
563
- * Fixed: Restoring an Other Media item and then Optimizing it again optimizes it Lossless
564
- * fix generating the WebP `<picture>` tags when the images are either on a subdomain or on a CDN domain having the same root domain as the main site.
565
-
566
  = EARLIER VERSIONS =
567
- * please refer to the changelog.txt file inside the plugin archive.
4
  Requires at least: 3.2.0
5
  Tested up to: 5.4.1
6
  Requires PHP: 5.3
7
+ Stable tag: 4.19.0
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
281
 
282
  == Changelog ==
283
 
284
+ = 4.19.0 =
285
+
286
+ Release date June 4th 2020
287
+ * Added an animation in settings that better explains the automatic resize done by ShortPixel;
288
+ * Fix for fatal errors in some cases when updating the plugin, by moving the class loader to PSR-4;
289
+ * Fix for a situation where the compare function wouldn't work because of a wrong assumption for the backup folder path;
290
+ * Fix: if directory structure is fully empty, select other media folder displays empty modal;
291
+ * Fix for check quota button that wasn't working in certain situations;
292
+ * Fix for missing DB table when doing a bulk restore before having optimized images;
293
+ * Fix for a DB foreign key issue in situations where multiple WordPress sites run on the same DB;
294
+ * Fix for backup getting broken on IIS/Windows servers, because of the way Windows handles the paths;
295
+ * Compability fix for WooCommerce germanized PRO plugin, where the cart page was throwing a fatal error because of the PDF that ShortPixel was trying to optimize;
296
+ * Various fixes for other media screen, to make it more consistent with the Media Library;
297
+ * Language – 5 new strings added, 1 updated, 1 fuzzied, and 0 obsoleted.
298
+
299
  = 4.18.1 =
300
 
301
  Release date 20th May 2020
366
  * Removed from the plugin the files that are not used anymore;
367
  * Language – 15 new strings added, 0 updated, 0 fuzzied, and 8 obsoleted.
368
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
369
  = EARLIER VERSIONS =
370
+ * please refer to the <a href="https://github.com/short-pixel-optimizer/shortpixel-image-optimiser/blob/master/changelog.txt" target="_blank">changelog.txt</a> file inside the plugin archive.
res/css/shortpixel-othermedia.css CHANGED
@@ -65,7 +65,9 @@
65
  min-width: 60px;
66
  min-height: 60px;
67
  display: inline-block;
68
- border: 1px solid #ccc; }
 
 
69
  .shortpixel-other-media .list-overview .item .thumb img {
70
  max-width: 60px;
71
  max-height: 60px;
@@ -73,11 +75,24 @@
73
  background: #eee; }
74
  .shortpixel-other-media .list-overview .item .actions {
75
  min-width: 105px; }
76
- .shortpixel-other-media .list-overview .item .single-action.button-primary a {
77
- color: #fff;
78
- text-decoration: none; }
 
 
 
 
 
 
 
 
 
 
 
 
79
  .shortpixel-other-media .list-overview .item .sp-column-info {
80
- width: 400px;
 
81
  display: inline-block; }
82
  @media (max-width: 1550px) {
83
  .shortpixel-other-media .list-overview .item .sp-column-info {
65
  min-width: 60px;
66
  min-height: 60px;
67
  display: inline-block;
68
+ border: 1px solid #ccc;
69
+ background-size: cover;
70
+ background-position: center;}
71
  .shortpixel-other-media .list-overview .item .thumb img {
72
  max-width: 60px;
73
  max-height: 60px;
75
  background: #eee; }
76
  .shortpixel-other-media .list-overview .item .actions {
77
  min-width: 105px; }
78
+ .shortpixel-other-media .list-overview .item .single-action {
79
+ text-align: center; }
80
+ .shortpixel-other-media .list-overview .item .single-action .button-primary a {
81
+ color: #fff;
82
+ text-decoration: none; }
83
+ .shortpixel-other-media .list-overview .item .single-action .button-smaller {
84
+ width: 110px; }
85
+ .shortpixel-other-media .list-overview .item .multi-action-wrapper {
86
+ display: flex;
87
+ flex-direction: column; }
88
+ .shortpixel-other-media .list-overview .item .multi-action-wrapper .single-action {
89
+ display: inline-block;
90
+ margin: 8px 0; }
91
+ .shortpixel-other-media .list-overview .item .multi-action-wrapper .single-action a {
92
+ display: block; }
93
  .shortpixel-other-media .list-overview .item .sp-column-info {
94
+ max-width: 400px;
95
+ min-width: 250px;
96
  display: inline-block; }
97
  @media (max-width: 1550px) {
98
  .shortpixel-other-media .list-overview .item .sp-column-info {
res/img/heavy-image.png ADDED
Binary file
res/img/heavy-image@2x.png ADDED
Binary file
res/img/resize-type.png ADDED
Binary file
res/img/resize-type@2x.png ADDED
Binary file
res/js/shortpixel.js CHANGED
@@ -80,8 +80,12 @@ var ShortPixel = function() {
80
  function enableResize(elm) {
81
  if(jQuery(elm).is(':checked')) {
82
  jQuery("#width,#height").removeAttr("disabled");
 
 
83
  } else {
84
  jQuery("#width,#height").attr("disabled", "disabled");
 
 
85
  }
86
  }
87
 
@@ -330,9 +334,15 @@ var ShortPixel = function() {
330
  }
331
 
332
  function checkQuota() {
333
- var data = {action:'shortpixel_check_quota'};
334
- jQuery.get(ShortPixel.AJAX_URL, data, function() {
 
 
 
 
335
  console.log("quota refreshed");
 
 
336
  });
337
  }
338
 
@@ -525,7 +535,7 @@ var ShortPixel = function() {
525
  jQuery("#shortPixelProposeUpgradeShade").css("display", "none");
526
  jQuery("#shortPixelProposeUpgrade").addClass('shortpixel-hide');
527
  if(ShortPixel.toRefresh) {
528
- ShortPixel.recheckQuota();
529
  }
530
  }
531
 
@@ -682,11 +692,7 @@ var ShortPixel = function() {
682
  return id.substring(0,2) == "C-";
683
  }
684
 
685
- function recheckQuota() {
686
- var parts = window.location.href.split('#');
687
 
688
- window.location.href=parts[0]+(parts[0].indexOf('?')>0?'&':'?')+'checkquota=1' + (typeof parts[1] === 'undefined' ? '' : '#' + parts[1]);
689
- }
690
 
691
  function openImageMenu(e) {
692
  e.preventDefault();
@@ -851,7 +857,7 @@ var ShortPixel = function() {
851
  checkRandomAnswer : checkRandomAnswer,
852
  removeBulkMsg : removeBulkMsg,
853
  isCustomImageId : isCustomImageId,
854
- recheckQuota : recheckQuota,
855
  openImageMenu : openImageMenu,
856
  menuCloseEvent : false,
857
  loadComparer : loadComparer,
@@ -1076,7 +1082,7 @@ function checkBulkProcessingCallApi(){
1076
  case ShortPixel.STATUS_QUOTA_EXCEEDED:
1077
  setCellMessage(id, data["Message"], "<a class='button button-smaller button-primary' href=\"https://shortpixel.com/login/"
1078
  + "\" target=\"_blank\">" + _spTr.extendQuota + "</a>"
1079
- + "<a class='button button-smaller' href='admin.php?action=shortpixel_check_quota'>" + _spTr.check__Quota + "</a>");
1080
  showToolBarAlert(ShortPixel.STATUS_QUOTA_EXCEEDED);
1081
  if(data['Stop'] == false) { //there are other items in the priority list, maybe processed, try those
1082
  setBulkTimer(5000);
@@ -1496,3 +1502,169 @@ function SPstringFormat() {
1496
  /*if (!(typeof String.prototype.format == 'function')) {
1497
  String.prototype.format = stringFormat;
1498
  } */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  function enableResize(elm) {
81
  if(jQuery(elm).is(':checked')) {
82
  jQuery("#width,#height").removeAttr("disabled");
83
+ SpioResize.lastW = false; //to trigger the animation
84
+ jQuery(".resize-type-wrap").show(800, window.SpioResize.run);
85
  } else {
86
  jQuery("#width,#height").attr("disabled", "disabled");
87
+ window.SpioResize.hide();
88
+ jQuery(".resize-type-wrap").hide(800);
89
  }
90
  }
91
 
334
  }
335
 
336
  function checkQuota() {
337
+ var data = {
338
+ action:'shortpixel_check_quota',
339
+ nonce: ShortPixelActions.nonce_check_quota,
340
+ return_json: true
341
+ };
342
+ jQuery.post(ShortPixel.AJAX_URL, data, function(result) {
343
  console.log("quota refreshed");
344
+ console.log(result);
345
+ window.location.href = result.redirect;
346
  });
347
  }
348
 
535
  jQuery("#shortPixelProposeUpgradeShade").css("display", "none");
536
  jQuery("#shortPixelProposeUpgrade").addClass('shortpixel-hide');
537
  if(ShortPixel.toRefresh) {
538
+ ShortPixel.checkQuota();
539
  }
540
  }
541
 
692
  return id.substring(0,2) == "C-";
693
  }
694
 
 
 
695
 
 
 
696
 
697
  function openImageMenu(e) {
698
  e.preventDefault();
857
  checkRandomAnswer : checkRandomAnswer,
858
  removeBulkMsg : removeBulkMsg,
859
  isCustomImageId : isCustomImageId,
860
+ // recheckQuota : recheckQuota,
861
  openImageMenu : openImageMenu,
862
  menuCloseEvent : false,
863
  loadComparer : loadComparer,
1082
  case ShortPixel.STATUS_QUOTA_EXCEEDED:
1083
  setCellMessage(id, data["Message"], "<a class='button button-smaller button-primary' href=\"https://shortpixel.com/login/"
1084
  + "\" target=\"_blank\">" + _spTr.extendQuota + "</a>"
1085
+ + "<a class='button button-smaller' href='javascript:ShortPixel.checkQuota()'>" + _spTr.check__Quota + "</a>");
1086
  showToolBarAlert(ShortPixel.STATUS_QUOTA_EXCEEDED);
1087
  if(data['Stop'] == false) { //there are other items in the priority list, maybe processed, try those
1088
  setBulkTimer(5000);
1502
  /*if (!(typeof String.prototype.format == 'function')) {
1503
  String.prototype.format = stringFormat;
1504
  } */
1505
+
1506
+
1507
+ ( function( $, w, d ) {
1508
+ w.SpioResize = {
1509
+ image : {
1510
+ width : 0,
1511
+ height : 0
1512
+ },
1513
+ lag: 2000,
1514
+ step1: false,
1515
+ step2: false,
1516
+ step3: false,
1517
+ sizeRule: null,
1518
+ initialized: false,
1519
+ lastW: false,
1520
+ lastH: false,
1521
+ lastType: false,
1522
+ };
1523
+
1524
+ SpioResize.hide = function() {
1525
+ $('.presentation-wrap').css('opacity', 0);
1526
+ }
1527
+
1528
+ SpioResize.animate = function(img, step1, frame, step2, rule) {
1529
+ img.animate( step1, 1000, 'swing', function(){
1530
+ SpioResize.step3 = setTimeout(function(){
1531
+ document.styleSheets[0].deleteRule(SpioResize.sizeRule);
1532
+ frame.animate(step2, 1000, 'swing', function() {
1533
+ SpioResize.sizeRule = document.styleSheets[0].insertRule(rule);
1534
+ })
1535
+ }, 600);
1536
+ });
1537
+
1538
+ }
1539
+
1540
+ SpioResize.run = function() {
1541
+ if(!SpioResize.initialized) {
1542
+ var $document = $( d );
1543
+ $document.on( 'input change', 'input[name="resizeWidth"], input[name="resizeHeight"]', function(e) {
1544
+ clearTimeout(SpioResize.change);
1545
+ SpioResize.changeDone = true;
1546
+ SpioResize.changeFired = false;
1547
+ SpioResize.change = setTimeout( function() {
1548
+ SpioResize.changeFired = true;
1549
+ SpioResize.run();
1550
+ }, 1500 );
1551
+ } );
1552
+ $document.on( 'blur', 'input[name="resizeWidth"], input[name="resizeHeight"]', function(e) {
1553
+ if(SpioResize.changeFired) {
1554
+ return;
1555
+ }
1556
+ clearTimeout(SpioResize.change);
1557
+ SpioResize.change = setTimeout( function() {
1558
+ SpioResize.run();
1559
+ }, 1500 );
1560
+ } );
1561
+ $document.on( 'change', 'input[name="resizeType"]', function(e) {
1562
+ SpioResize.run();
1563
+ });
1564
+ SpioResize.initialized = true;
1565
+ }
1566
+
1567
+ var w = $('#width').val();
1568
+ var h = $('#height').val();
1569
+ if(!w || !h) return;
1570
+ var type = ($('#resize_type_outer').is(':checked') ? 'outer' : 'inner');
1571
+ if(w === SpioResize.lastW && h === SpioResize.lastH && type === SpioResize.lastType) {
1572
+ return;
1573
+ }
1574
+ SpioResize.hide();
1575
+ SpioResize.lastW = w;
1576
+ SpioResize.lastH = h;
1577
+ SpioResize.lastType = type;
1578
+
1579
+ var frame1W = Math.round(120 * Math.sqrt(w / h));
1580
+ var frame1H = Math.round(120 * Math.sqrt(h / w));
1581
+ var frameAR = frame1W / frame1H;
1582
+ if(frame1W > 280) {
1583
+ frame1W = 280; frame1H = Math.round(280 / frameAR);
1584
+ }
1585
+ if(frame1H > 150) {
1586
+ frame1H = 150; frame1W = Math.round(150 * frameAR);
1587
+ }
1588
+ var imgAR = 15 / 8;
1589
+ var img = $('img.spai-resize-img');
1590
+ img.css('width', '');
1591
+ img.css('height', '');
1592
+ img.css('margin', '0px');
1593
+ var frame = $('div.spai-resize-frame');
1594
+ frame.css('display', 'none');
1595
+ frame.css('width', frame1W + 'px');
1596
+ frame.css('height', frame1H + 'px');
1597
+ frame.css('margin', Math.round((156 - frame1H ) / 2) + 'px auto 0');
1598
+
1599
+ clearTimeout(SpioResize.step1); clearTimeout(SpioResize.step2); clearTimeout(SpioResize.step3);
1600
+ img.stop(); frame.stop();
1601
+
1602
+ if(SpioResize.sizeRule !== null) {
1603
+ document.styleSheets[0].deleteRule(SpioResize.sizeRule);
1604
+ SpioResize.sizeRule = null;
1605
+ }
1606
+ SpioResize.sizeRule = document.styleSheets[0].insertRule('.spai-resize-frame:after { content: "' + w + ' × ' + h + '"; }');
1607
+ frame.addClass('spai-resize-frame');
1608
+
1609
+ $('.presentation-wrap').animate( {opacity: 1}, 500, 'swing', function(){
1610
+ //because damn chrome is not repainting the frame after we change the sizes otherwise... :(
1611
+ frame.css('display', 'block');
1612
+
1613
+ SpioResize.step2 = setTimeout(function(){
1614
+ if(type == 'outer') {
1615
+ if(imgAR > frameAR) {
1616
+ var step1 = {
1617
+ height: frame1H + 'px',
1618
+ margin: Math.round((160 - frame1H) / 2) + 'px 0px'
1619
+ };
1620
+ var frameNewW = frame1H * imgAR;
1621
+ var step2 = { width: Math.round(frameNewW) + 'px' };
1622
+ var rule = '.spai-resize-frame:after { content: "' + Math.round(frameNewW * w / frame1W) + ' × ' + h + '"; }';
1623
+ } else {
1624
+ var step1 = {
1625
+ width: frame1W + 'px',
1626
+ margin: Math.round((160 - frame1W / imgAR) / 2) + 'px 0px'
1627
+ };
1628
+ var frameNewH = frame1W / imgAR;
1629
+ var step2 = {
1630
+ height: Math.round(frameNewH) + 'px',
1631
+ margin: Math.round((156 - frameNewH) / 2) + 'px auto 0'
1632
+ };
1633
+ var rule = '.spai-resize-frame:after { content: "' + w + ' × ' + Math.round(frameNewH * w / frame1W) + '"; }';
1634
+
1635
+ }
1636
+ } else {
1637
+ if(imgAR > frameAR) {
1638
+ var step1 = {
1639
+ width: frame1W,
1640
+ margin: Math.round((160 - frame1W / imgAR) / 2) + 'px 0px'
1641
+ };
1642
+ var frameNewH = frame1W / imgAR;
1643
+ var step2 = {
1644
+ height: Math.round(frameNewH) + 'px',
1645
+ margin: Math.round((156 - frameNewH) / 2) + 'px auto 0'
1646
+ };
1647
+ var rule = '.spai-resize-frame:after { content: "' + w + ' × ' + Math.round(frameNewH * w / frame1W) + '"; }';
1648
+ } else {
1649
+ var step1 = {
1650
+ height: frame1H,
1651
+ margin: Math.round((160 - frame1H) / 2) + 'px 0px'
1652
+ };
1653
+ var frameNewW = frame1H * imgAR;
1654
+ var step2 = {
1655
+ width: Math.round(frameNewW) + 'px'
1656
+ };
1657
+ var rule = '.spai-resize-frame:after { content: "' + Math.round(frameNewW * w / frame1W) + ' × ' + h + '"; }';
1658
+ }
1659
+ }
1660
+ SpioResize.animate(img, step1, frame, step2, rule);
1661
+ }, 1000);
1662
+ });
1663
+ }
1664
+
1665
+ $( function() {
1666
+ if($('#resize').is('checked')) {
1667
+ SpioResize.run();
1668
+ }
1669
+ } );
1670
+ } )( jQuery, window, document );
res/js/shortpixel.min.js CHANGED
@@ -1 +1 @@
1
- function showToolBarAlert(e,r,t){var o=jQuery("li.shortpixel-toolbar-processing");switch(e){case ShortPixel.STATUS_QUOTA_EXCEEDED:if(window.location.href.search("wp-short-pixel-bulk")>0&&0==jQuery(".sp-quota-exceeded-alert").length)return;o.addClass("shortpixel-alert"),o.addClass("shortpixel-quota-exceeded"),jQuery("a",o).attr("href","options-general.php?page=wp-shortpixel-settings"),jQuery("a div",o).attr("title","ShortPixel quota exceeded. Click for details.");break;case ShortPixel.STATUS_SKIP:case ShortPixel.STATUS_FAIL:o.addClass("shortpixel-alert shortpixel-processing"),jQuery("a div",o).attr("title",r),void 0!==t&&jQuery("a",o).attr("href","post.php?post="+t+"&action=edit");break;case ShortPixel.STATUS_NO_KEY:o.addClass("shortpixel-alert"),o.addClass("shortpixel-quota-exceeded"),jQuery("a",o).attr("href","options-general.php?page=wp-shortpixel-settings"),jQuery("a div",o).attr("title","Get API Key");break;case ShortPixel.STATUS_SUCCESS:case ShortPixel.STATUS_RETRY:o.addClass("shortpixel-processing"),o.removeClass("shortpixel-alert"),jQuery("a",o).removeAttr("target"),jQuery("a",o).attr("href",jQuery("a img",o).attr("success-url"))}o.removeClass("shortpixel-hide")}function hideToolBarAlert(e){var r=jQuery("li.shortpixel-toolbar-processing.shortpixel-processing");ShortPixel.STATUS_EMPTY_QUEUE==e&&(r.hasClass("shortpixel-alert")||r.hasClass("shortpixel-quota-exceeded"))||r.addClass("shortpixel-hide")}function hideQuotaExceededToolBarAlert(){jQuery("li.shortpixel-toolbar-processing.shortpixel-quota-exceeded").addClass("shortpixel-hide")}function checkQuotaExceededAlert(){"undefined"!=typeof shortPixelQuotaExceeded&&(1==shortPixelQuotaExceeded?showToolBarAlert(ShortPixel.STATUS_QUOTA_EXCEEDED):hideQuotaExceededToolBarAlert())}function checkBulkProgress(){var e=function(e){return r?"/":(r=!0,e)},r=!1,t=window.location.href.toLowerCase().replace(/\/\//g,e);r=!1;var o=ShortPixel.WP_ADMIN_URL.toLowerCase().replace(/\/\//g,e);if(t.search(o)<0&&(t=ShortPixel.convertPunycode(t),o=ShortPixel.convertPunycode(o)),1==ShortPixel.bulkProcessor&&window.location.href.search("wp-short-pixel-bulk")<0&&void 0!==localStorage.bulkPage&&localStorage.bulkPage>0&&(ShortPixel.bulkProcessor=!1),window.location.href.search("wp-short-pixel-bulk")>=0&&(ShortPixel.bulkProcessor=!0,localStorage.bulkTime=Date.now(),localStorage.bulkPage=1,ShortPixel.BULK_SECRET=!1),!1!==ShortPixel.BULK_SECRET&&ShortPixel.BULK_SECRET!=localStorage.bulkSecret)return clearBulkProcessor(),jQuery("li.shortpixel-toolbar-processing").removeClass("shortpixel-processing"),void jQuery("li.shortpixel-toolbar-processing").addClass("shortpixel-hide");1==ShortPixel.bulkProcessor||void 0===localStorage.bulkTime||Date.now()-localStorage.bulkTime>1e4?(ShortPixel.bulkProcessor=!0,localStorage.bulkPage=window.location.href.search("wp-short-pixel-bulk")>=0?1:0,localStorage.bulkTime=Date.now(),null==localStorage.getItem("bulkSecret")&&(localStorage.bulkSecret=Math.random().toString(36).substring(7)),checkBulkProcessingCallApi()):setBulkTimer(2e4)}function setBulkTimer(e){window.clearTimeout(bulkTimer),e>0&&(bulkTimer=window.setTimeout(checkBulkProgress,e))}function checkBulkProcessingCallApi(){var e={action:"shortpixel_image_processing","bulk-secret":localStorage.bulkSecret};jQuery.ajax({type:"POST",url:ShortPixel.AJAX_URL,data:e,success:function(e){if(e.length>0){r=null;try{var r=JSON.parse(e)}catch(e){return void ShortPixel.retry(e.message)}ShortPixel.retries=0;var t=r.ImageID,o=jQuery("div.short-pixel-bulk-page").length>0;switch(r.Status&&r.Status!=ShortPixel.STATUS_SEARCHING&&(ShortPixel.returnedStatusSearching>=2&&jQuery(".bulk-notice-msg.bulk-searching").hide(),ShortPixel.returnedStatusSearching=0),r.Status){case ShortPixel.STATUS_NO_KEY:setCellMessage(t,r.Message,'<a class=\'button button-smaller button-primary\' href="https://shortpixel.com/wp-apikey" target="_blank">'+_spTr.getApiKey+"</a>"),showToolBarAlert(ShortPixel.STATUS_NO_KEY);break;case ShortPixel.STATUS_QUOTA_EXCEEDED:setCellMessage(t,r.Message,'<a class=\'button button-smaller button-primary\' href="https://shortpixel.com/login/" target="_blank">'+_spTr.extendQuota+"</a><a class='button button-smaller' href='admin.php?action=shortpixel_check_quota'>"+_spTr.check__Quota+"</a>"),showToolBarAlert(ShortPixel.STATUS_QUOTA_EXCEEDED),0==r.Stop&&setBulkTimer(5e3),ShortPixel.otherMediaUpdateActions(t,["quota","view"]);break;case ShortPixel.STATUS_FAIL:setCellMessage(t,r.Message,"<a class='button button-smaller button-primary' href=\"javascript:manualOptimization('"+t+"', true)\">"+_spTr.retry+"</a>"),showToolBarAlert(ShortPixel.STATUS_FAIL,r.Message,t),o&&(ShortPixel.bulkShowError(t,r.Message,r.Filename,r.CustomImageLink),r.BulkPercent&&progressUpdate(r.BulkPercent,r.BulkMsg),ShortPixel.otherMediaUpdateActions(t,["retry","view"])),console.log(r.Message),setBulkTimer(5e3);break;case ShortPixel.STATUS_EMPTY_QUEUE:console.log(r.Message),clearBulkProcessor(),hideToolBarAlert(r.Status);var s=jQuery("#bulk-progress");o&&s.length&&"2"!=r.BulkStatus&&(progressUpdate(100,"Bulk finished!"),jQuery("a.bulk-cancel").attr("disabled","disabled"),hideSlider(),setTimeout(function(){window.location.reload()},3e3));break;case ShortPixel.STATUS_SUCCESS:o&&(ShortPixel.bulkHideLengthyMsg(),ShortPixel.bulkHideMaintenanceMsg());var i=r.PercentImprovement;showToolBarAlert(ShortPixel.STATUS_SUCCESS,"");var a=ShortPixel.isCustomImageId(t)?"":ShortPixel.successActions(t,r.Type,r.ThumbsCount,r.ThumbsTotal,r.BackupEnabled,r.Filename);if(setCellMessage(t,ShortPixel.successMsg(t,i,r.Type,r.ThumbsCount,r.RetinasCount),a),jQuery("#post-"+t).length>0&&jQuery("#post-"+t).find(".filename").text(r.Filename),jQuery(".misc-pub-filename strong").length>0&&jQuery(".misc-pub-filename strong").text(r.Filename),ShortPixel.isCustomImageId(t)&&r.TsOptimized&&r.TsOptimized.length>0){n=jQuery(".list-overview .item-"+t);jQuery(n).children(".date").text(r.TsOptimized),jQuery(n).find(".row-actions .action-optimize").remove()}var l=jQuery(["restore","view","redolossy","redoglossy","redolossless"]).not(["redo"+r.Type]).get();ShortPixel.otherMediaUpdateActions(t,l);new PercentageAnimator("#sp-msg-"+t+" span.percent",i).animate(i),o&&void 0!==r.Thumb&&(r.BulkPercent&&progressUpdate(r.BulkPercent,r.BulkMsg),r.Thumb.length>0&&(sliderUpdate(t,r.Thumb,r.BkThumb,r.PercentImprovement,r.Filename),void 0!==r.AverageCompression&&0+r.AverageCompression>0&&(jQuery("#sp-avg-optimization").html('<input type="text" class="dial" value="'+Math.round(r.AverageCompression)+'"/>'),ShortPixel.percentDial("#sp-avg-optimization .dial",60)))),console.log("Server response: "+e),o&&void 0!==r.BulkPercent&&progressUpdate(r.BulkPercent,r.BulkMsg),setBulkTimer(5e3);break;case ShortPixel.STATUS_SKIP:1!==r.Silent&&ShortPixel.bulkShowError(t,r.Message,r.Filename,r.CustomImageLink);case ShortPixel.STATUS_ERROR:void 0!==r.Message&&(showToolBarAlert(ShortPixel.STATUS_SKIP,r.Message+" Image ID: "+t),setCellMessage(t,r.Message,"")),ShortPixel.otherMediaUpdateActions(t,["retry","view"]);case ShortPixel.STATUS_RETRY:console.log("Server response: "+e),showToolBarAlert(ShortPixel.STATUS_RETRY,""),o&&void 0!==r.BulkPercent&&progressUpdate(r.BulkPercent,r.BulkMsg),o&&r.Count>3&&ShortPixel.bulkShowLengthyMsg(t,r.Filename,r.CustomImageLink),setBulkTimer(5e3);break;case ShortPixel.STATUS_SEARCHING:console.log("Server response: "+e),ShortPixel.returnedStatusSearching++,ShortPixel.returnedStatusSearching>=2&&jQuery(".bulk-notice-msg.bulk-searching").show(),setBulkTimer(2500);break;case ShortPixel.STATUS_MAINTENANCE:ShortPixel.bulkShowMaintenanceMsg("maintenance"),setBulkTimer(6e4);break;case ShortPixel.STATUS_QUEUE_FULL:ShortPixel.bulkShowMaintenanceMsg("queue-full"),setBulkTimer(6e4);break;default:ShortPixel.retry("Unknown status "+r.Status+". Retrying...")}if(void 0!==t&&ShortPixel.isCustomImageId(t)){var n=jQuery(".list-overview .item-"+t);jQuery(n).find(".row-actions .action-optimize").remove(),r.actions&&jQuery(n).children(".actions").html(r.actions)}}},error:function(e){ShortPixel.retry(e.statusText)}})}function clearBulkProcessor(){ShortPixel.bulkProcessor=!1,localStorage.bulkTime=Date.now(),setBulkTimer(0),window.location.href.search("wp-short-pixel-bulk")>=0&&(localStorage.bulkPage=0)}function setCellMessage(e,r,t){var o=jQuery("#sp-msg-"+e);o.length>0&&(o.html("<div class='sp-column-actions'>"+t+"</div><div class='sp-column-info'>"+r+"</div>"),o.css("color","")),(o=jQuery("#sp-cust-msg-"+e)).length>0&&o.html("<div class='sp-column-info'>"+r+"</div>")}function manualOptimization(e,r){setCellMessage(e,"<img src='"+ShortPixel.WP_PLUGIN_URL+"/res/img/loading.gif' alt='"+_spTr.loading+"' class='sp-loading-small'>Image waiting to be processed",""),jQuery("li.shortpixel-toolbar-processing").removeClass("shortpixel-hide"),jQuery("li.shortpixel-toolbar-processing").removeClass("shortpixel-alert"),jQuery("li.shortpixel-toolbar-processing").addClass("shortpixel-processing");var t={action:"shortpixel_manual_optimization",image_id:e,cleanup:r};jQuery.ajax({type:"GET",url:ShortPixel.AJAX_URL,data:t,success:function(r){var t=JSON.parse(r);t.Status==ShortPixel.STATUS_SUCCESS?(setBulkTimer(2e3),ShortPixel.BULK_SECRET=!1):setCellMessage(e,void 0!==t.Message?t.Message:_spTr.thisContentNotProcessable,"")},error:function(r){t.action="shortpixel_check_status",jQuery.ajax({type:"GET",url:ShortPixel.AJAX_URL,data:t,success:function(r){var t=JSON.parse(r);t.Status!==ShortPixel.STATUS_SUCCESS&&setCellMessage(e,void 0!==t.Message?t.Message:_spTr.thisContentNotProcessable,"")}})}})}function reoptimize(e,r){setCellMessage(e,"<img src='"+ShortPixel.WP_PLUGIN_URL+"/res/img/loading.gif' alt='"+_spTr.loading+"' class='sp-loading-small'>Image waiting to be reprocessed",""),jQuery("li.shortpixel-toolbar-processing").removeClass("shortpixel-hide"),jQuery("li.shortpixel-toolbar-processing").addClass("shortpixel-processing");var t={action:"shortpixel_redo",attachment_ID:e,type:r};jQuery.get(ShortPixel.AJAX_URL,t,function(r){(t=JSON.parse(r)).Status==ShortPixel.STATUS_SUCCESS?(setBulkTimer(2e3),ShortPixel.BULK_SECRET=!1):($msg=void 0!==t.Message?t.Message:_spTr.thisContentNotProcessable,setCellMessage(e,$msg,""),showToolBarAlert(ShortPixel.STATUS_FAIL,$msg))})}function optimizeThumbs(e){setCellMessage(e,"<img src='"+ShortPixel.WP_PLUGIN_URL+"/res/img/loading.gif' alt='"+_spTr.loading+"' class='sp-loading-small'>"+_spTr.imageWaitOptThumbs,""),jQuery("li.shortpixel-toolbar-processing").removeClass("shortpixel-hide"),jQuery("li.shortpixel-toolbar-processing").addClass("shortpixel-processing");var r={action:"shortpixel_optimize_thumbs",attachment_ID:e};jQuery.get(ShortPixel.AJAX_URL,r,function(t){(r=JSON.parse(t)).Status==ShortPixel.STATUS_SUCCESS?(setBulkTimer(2e3),ShortPixel.BULK_SECRET=!1):setCellMessage(e,void 0!==r.Message?r.Message:_spTr.thisContentNotProcessable,"")})}function dismissShortPixelNotice(e){jQuery("#short-pixel-notice-"+e).hide();var r={action:"shortpixel_dismiss_notice",notice_id:e};jQuery.get(ShortPixel.AJAX_URL,r,function(e){(r=JSON.parse(e)).Status==ShortPixel.STATUS_SUCCESS&&console.log("dismissed")})}function dismissFileError(){jQuery(".shortpixel-alert").hide();var e={action:"shortpixel_dismissFileError"};jQuery.get(ShortPixel.AJAX_URL,e,function(r){(e=JSON.parse(r)).Status==ShortPixel.STATUS_SUCCESS&&console.log("dismissed")})}function PercentageAnimator(e,r){this.animationSpeed=10,this.increment=2,this.curPercentage=0,this.targetPercentage=r,this.outputSelector=e,this.animate=function(e){this.targetPercentage=e,setTimeout(PercentageTimer.bind(null,this),this.animationSpeed)}}function PercentageTimer(e){e.curPercentage-e.targetPercentage<-e.increment?e.curPercentage+=e.increment:e.curPercentage-e.targetPercentage>e.increment?e.curPercentage-=e.increment:e.curPercentage=e.targetPercentage,jQuery(e.outputSelector).text(e.curPercentage+"%"),e.curPercentage!=e.targetPercentage&&setTimeout(PercentageTimer.bind(null,e),e.animationSpeed)}function progressUpdate(e,r){var t=jQuery("#bulk-progress");t.length&&(jQuery(".progress-left",t).css("width",e+"%"),jQuery(".progress-img",t).css("left",e+"%"),e>24?(jQuery(".progress-img span",t).html(""),jQuery(".progress-left",t).html(e+"%")):(jQuery(".progress-img span",t).html(e+"%"),jQuery(".progress-left",t).html("")),jQuery(".bulk-estimate").html(r))}function sliderUpdate(e,r,t,o,s){var i=jQuery(".bulk-slider div.bulk-slide:first-child");if(0!==i.length){"empty-slide"!=i.attr("id")&&i.hide(),i.css("z-index",1e3),jQuery(".bulk-img-opt",i).attr("src",""),void 0===t&&(t=""),t.length>0&&jQuery(".bulk-img-orig",i).attr("src","");var a=i.clone();a.attr("id","slide-"+e),jQuery(".bulk-img-opt",a).attr("src",r),t.length>0?(jQuery(".img-original",a).css("display","inline-block"),jQuery(".bulk-img-orig",a).attr("src",t)):jQuery(".img-original",a).css("display","none"),jQuery(".bulk-opt-percent",a).html('<input type="text" class="dial" value="'+o+'"/>'),jQuery(".bulk-slider").append(a),ShortPixel.percentDial("#"+a.attr("id")+" .dial",100),jQuery(".bulk-slider-container span.filename").html("&nbsp;&nbsp;"+s),"empty-slide"==i.attr("id")?(i.remove(),jQuery(".bulk-slider-container").css("display","block")):i.animate({left:i.width()+i.position().left},"slow","swing",function(){i.remove(),a.fadeIn("slow")})}}function hideSlider(){jQuery(".bulk-slider-container").css("display","none")}function showStats(){jQuery(".bulk-stats").length}function SPstringFormat(){var e=Array.prototype.slice.call(arguments);if(0!==e.length){var r=e.shift();for(i=0;i<e.length;i++)r=r.replace(new RegExp("\\{"+i+"\\}","gm"),e[i]);return r}}jQuery(document).ready(function(){ShortPixel.init()});var bulkTimer,ShortPixel=function(){function e(e){jQuery(e).is(":checked")?jQuery("#width,#height").removeAttr("disabled"):jQuery("#width,#height").attr("disabled","disabled")}function r(){jQuery("#shortpixel-hs-button-blind").remove(),jQuery("#shortpixel-hs-tools").remove(),jQuery("#hs-beacon").remove(),jQuery("#botbutton").remove(),jQuery("#shortpixel-hs-blind").remove()}return jQuery("#key").keypress(function(e){13==e.which&&jQuery("#valid").val("validate")}),{init:function(){void 0===ShortPixel.API_IS_ACTIVE&&(jQuery("table.wp-list-table.media").length>0&&jQuery('select[name^="action"] option:last-child').before('<option value="short-pixel-bulk">'+_spTr.optimizeWithSP+'</option><option value="short-pixel-bulk-lossy"> → '+_spTr.redoLossy+'</option><option value="short-pixel-bulk-glossy"> → '+_spTr.redoGlossy+'</option><option value="short-pixel-bulk-lossless"> → '+_spTr.redoLossless+'</option><option value="short-pixel-bulk-restore"> → '+_spTr.restoreOriginal+"</option>"),ShortPixel.setOptions(ShortPixelConstants[0]),jQuery("#backup-folder-size").length&&jQuery("#backup-folder-size").html(ShortPixel.getBackupSize()),"todo"==ShortPixel.MEDIA_ALERT&&jQuery("div.media-frame.mode-grid").length>0&&jQuery("div.media-frame.mode-grid").before('<div id="short-pixel-media-alert" class="notice notice-warning"><p>'+SPstringFormat(_spTr.changeMLToListMode,'<a href="upload.php?mode=list" class="view-list"><span class="screen-reader-text">'," </span>",'</a><a class="alignright" href="javascript:ShortPixel.dismissMediaAlert();">',"</a>")+"</p></div>"),jQuery(window).on("beforeunload",function(){1==ShortPixel.bulkProcessor&&clearBulkProcessor()}),checkQuotaExceededAlert(),checkBulkProgress())},setOptions:function(e){for(var r in e)ShortPixel[r]=e[r]},isEmailValid:function(e){return/^\w+([\.+-]?\w+)*@\w+([\.-]?\w+)*(\.\w{1,63})+$/.test(e)},updateSignupEmail:function(){var e=jQuery("#pluginemail").val();ShortPixel.isEmailValid(e)&&jQuery("#request_key").removeClass("disabled"),jQuery("#request_key").attr("href",jQuery("#request_key").attr("href").split("?")[0]+"?pluginemail="+e)},validateKey:function(e){jQuery("#valid").val("validate"),jQuery(e).parents("form").submit()},enableResize:e,setupGeneralTab:function(){var r=0;void 0!==document.wp_shortpixel_options&&(r=document.wp_shortpixel_options.compressionType);for(var t=0,o=null;t<r.length;t++)r[t].onclick=function(){this!==o&&(o=this),void 0===ShortPixel.setupGeneralTabAlert&&(alert(_spTr.alertOnlyAppliesToNewImages),ShortPixel.setupGeneralTabAlert=1)};ShortPixel.enableResize("#resize"),jQuery("#resize").change(function(){e(this)}),jQuery(".resize-sizes").blur(function(e){var r=jQuery(e.target);if(ShortPixel.resizeSizesAlert!=r.val()){ShortPixel.resizeSizesAlert=r.val();var t=jQuery("#min-"+r.attr("name")).val(),o=jQuery("#min-"+r.attr("name")).data("nicename");r.val()<Math.min(t,1024)?(t>1024?alert(SPstringFormat(_spTr.pleaseDoNotSetLesser1024,o)):alert(SPstringFormat(_spTr.pleaseDoNotSetLesserSize,o,o,t)),e.preventDefault(),r.focus()):this.defaultValue=r.val()}}),jQuery(".shortpixel-confirm").click(function(e){return!!confirm(e.target.getAttribute("data-confirm"))||(e.preventDefault(),!1)}),jQuery('input[name="removeExif"], input[name="png2jpg"]').on("change",function(){ShortPixel.checkExifWarning()}),ShortPixel.checkExifWarning(),jQuery('input[name="backupImages"]').on("change",function(){ShortPixel.checkBackUpWarning()}),ShortPixel.checkBackUpWarning()},apiKeyChanged:function(){jQuery(".wp-shortpixel-options .shortpixel-key-valid").css("display","none"),jQuery(".wp-shortpixel-options button#validate").css("display","inline-block")},setupAdvancedTab:function(){jQuery("input.remove-folder-button").click(function(){var e=jQuery(this).data("value"),r=jQuery(this).data("name");1==confirm(SPstringFormat(_spTr.areYouSureStopOptimizing,r))&&(jQuery("#removeFolder").val(e),jQuery("#wp_shortpixel_options").submit())}),jQuery("input.recheck-folder-button").click(function(){var e=jQuery(this).data("value");1==confirm(SPstringFormat(_spTr.areYouSureStopOptimizing,e))&&(jQuery("#recheckFolder").val(e),jQuery("#wp_shortpixel_options").submit())})},checkThumbsUpdTotal:function(e){var r=jQuery("#"+(e.checked?"total":"main")+"ToProcess").val();jQuery("div.bulk-play span.total").text(r),jQuery("#displayTotal").text(r)},initSettings:function(){ShortPixel.adjustSettingsTabs(),ShortPixel.setupGeneralTab(),jQuery(window).resize(function(){ShortPixel.adjustSettingsTabs()}),jQuery("article.sp-tabs a.tab-link").click(function(e){var r=jQuery(e.target).data("id");ShortPixel.switchSettingsTab(r)}),jQuery("input[type=radio][name=deliverWebpType]").change(function(){"deliverWebpAltered"==this.value?window.confirm(_spTr.alertDeliverWebPAltered)?0==jQuery("input[type=radio][name=deliverWebpAlteringType]:checked").length&&jQuery("#deliverWebpAlteredWP").prop("checked",!0):jQuery(this).prop("checked",!1):"deliverWebpUnaltered"==this.value&&window.alert(_spTr.alertDeliverWebPUnaltered)})},switchSettingsTab:function(e){var r=e.replace("tab-",""),t="",o=jQuery("section#"+e);jQuery('input[name="display_part"]').val(r);var s=window.location.href.toString();if(s.indexOf("?")>0){var i=s.substring(0,s.indexOf("?"));i+="?"+jQuery.param({page:"wp-shortpixel-settings",part:r}),window.history.replaceState({},document.title,i)}if(o.length>0&&(jQuery("section").removeClass("sel-tab"),jQuery("section .wp-shortpixel-tab-content").fadeOut(50),jQuery(o).addClass("sel-tab"),ShortPixel.adjustSettingsTabs(),jQuery(o).find(".wp-shortpixel-tab-content").fadeIn(50)),"undefined"!=typeof HS&&void 0!==HS.beacon.suggest){switch(r){case"settings":t=shortpixel_suggestions_settings;break;case"adv-settings":t=shortpixel_suggestions_adv_settings;break;case"cloudflare":case"stats":t=shortpixel_suggestions_cloudflare}HS.beacon.suggest(t)}},adjustSettingsTabs:function(){var e=jQuery("section.sel-tab").height()+90;jQuery(".section-wrapper").css("height",e)},onBulkThumbsCheck:function(e){e.checked?(jQuery("#with-thumbs").css("display","inherit"),jQuery("#without-thumbs").css("display","none")):(jQuery("#without-thumbs").css("display","inherit"),jQuery("#with-thumbs").css("display","none"))},dismissMediaAlert:function(){var e={action:"shortpixel_dismiss_media_alert"};jQuery.get(ShortPixel.AJAX_URL,e,function(r){"success"==(e=JSON.parse(r)).Status&&jQuery("#short-pixel-media-alert").hide()})},closeHelpPane:r,dismissHelpPane:function(){r(),dismissShortPixelNotice("help")},checkQuota:function(){jQuery.get(ShortPixel.AJAX_URL,{action:"shortpixel_check_quota"},function(){console.log("quota refreshed")})},percentDial:function(e,r){jQuery(e).knob({readOnly:!0,width:r,height:r,fgColor:"#1CAECB",format:function(e){return e+"%"}})},successMsg:function(e,r,t,o,s){return(r>0?"<div class='sp-column-info'>"+_spTr.reducedBy+" <strong><span class='percent'>"+r+"%</span></strong> ":"")+(r>0&&r<5?"<br>":"")+(r<5?_spTr.bonusProcessing:"")+(t.length>0?" ("+t+")":"")+(0+o>0?"<br>"+SPstringFormat(_spTr.plusXthumbsOpt,o):"")+(0+s>0?"<br>"+SPstringFormat(_spTr.plusXretinasOpt,s):"")+"</div>"},successActions:function(e,r,t,o,s,i){if(1==s){var a=jQuery(".sp-column-actions-template").clone();if(!a.length)return!1;var l;return l=0==r.length?["lossy","lossless"]:["lossy","glossy","lossless"].filter(function(e){return!(e==r)}),a.html(a.html().replace(/__SP_ID__/g,e)),"pdf"==i.substr(i.lastIndexOf(".")+1).toLowerCase()&&jQuery(".sp-action-compare",a).remove(),0==t&&o>0?a.html(a.html().replace("__SP_THUMBS_TOTAL__",o)):(jQuery(".sp-action-optimize-thumbs",a).remove(),jQuery(".sp-dropbtn",a).removeClass("button-primary")),a.html(a.html().replace(/__SP_FIRST_TYPE__/g,l[0])),a.html(a.html().replace(/__SP_SECOND_TYPE__/g,l[1])),a.html()}return""},otherMediaUpdateActions:function(e,r){if(e=e.substring(2),jQuery(".shortpixel-other-media").length){for(var t=["optimize","retry","restore","redo","quota","view"],o=0,s=t.length;o<s;o++)jQuery("#"+t[o]+"_"+e).css("display","none");for(var o=0,s=r.length;o<s;o++)jQuery("#"+r[o]+"_"+e).css("display","")}},retry:function(e){ShortPixel.retries++,isNaN(ShortPixel.retries)&&(ShortPixel.retries=1),ShortPixel.retries<6?(console.log("Invalid response from server (Error: "+e+"). Retrying pass "+(ShortPixel.retries+1)+"..."),setBulkTimer(5e3)):(ShortPixel.bulkShowError(-1,"Invalid response from server received 6 times. Please retry later by reloading this page, or <a href='https://shortpixel.com/contact' target='_blank'>contact support</a>. (Error: "+e+")",""),console.log("Invalid response from server 6 times. Giving up."))},initFolderSelector:function(){jQuery(".select-folder-button").click(function(){jQuery(".sp-folder-picker-shade").fadeIn(100),jQuery(".shortpixel-modal.modal-folder-picker").show();var e=jQuery(".sp-folder-picker");e.parent().css("margin-left",-e.width()/2),e.fileTree({script:ShortPixel.browseContent,multiFolder:!1})}),jQuery(".shortpixel-modal input.select-folder-cancel, .sp-folder-picker-shade").click(function(){jQuery(".sp-folder-picker-shade").fadeOut(100),jQuery(".shortpixel-modal.modal-folder-picker").hide()}),jQuery(".shortpixel-modal input.select-folder").click(function(e){if(r=jQuery("UL.jqueryFileTree LI.directory.selected"),0==jQuery(r).length)var r=jQuery("UL.jqueryFileTree LI.selected").parents(".directory");var t=jQuery(r).children("a").attr("rel");if(void 0!==t)if(t=t.trim()){var o=jQuery("#customFolderBase").val()+t;o=o.replace(/\/\//,"/"),console.debug("FullPath"+o),jQuery("#addCustomFolder").val(o),jQuery("#addCustomFolderView").val(o),jQuery(".sp-folder-picker-shade").fadeOut(100),jQuery(".shortpixel-modal.modal-folder-picker").css("display","none"),jQuery("#saveAdvAddFolder").removeClass("hidden")}else alert("Please select a folder from the list.")})},browseContent:function(e){e.action="shortpixel_browse_content";var r="";return jQuery.ajax({type:"POST",url:ShortPixel.AJAX_URL,data:e,success:function(e){r=e},async:!1}),r},getBackupSize:function(){var e="";return jQuery.ajax({type:"POST",url:ShortPixel.AJAX_URL,data:{action:"shortpixel_get_backup_size"},success:function(r){e=r},async:!1}),e},newApiKey:function(e){if(!jQuery("#tos").is(":checked"))return e.preventDefault(),jQuery("#tos-robo").fadeIn(400,function(){jQuery("#tos-hand").fadeIn()}),void jQuery("#tos").click(function(){jQuery("#tos-robo").css("display","none"),jQuery("#tos-hand").css("display","none")});if(jQuery("#request_key").addClass("disabled"),jQuery("#pluginemail_spinner").addClass("is-active"),ShortPixel.updateSignupEmail(),ShortPixel.isEmailValid(jQuery("#pluginemail").val())){jQuery("#pluginemail-error").css("display","none");var r={action:"shortpixel_new_api_key",email:jQuery("#pluginemail").val()};jQuery.ajax({type:"POST",async:!1,url:ShortPixel.AJAX_URL,data:r,success:function(r){data=JSON.parse(r),"success"==data.Status?(e.preventDefault(),window.location.reload()):"invalid"==data.Status&&(jQuery("#pluginemail-error").html("<b>"+data.Details+"</b>"),jQuery("#pluginemail-error").css("display",""),jQuery("#pluginemail-info").css("display","none"),e.preventDefault())}}),jQuery("#request_key").removeAttr("onclick")}else jQuery("#pluginemail-error").css("display",""),jQuery("#pluginemail-info").css("display","none"),e.preventDefault();jQuery("#request_key").removeClass("disabled"),jQuery("#pluginemail_spinner").removeClass("is-active")},proposeUpgrade:function(){jQuery("#shortPixelProposeUpgrade .sp-modal-body").addClass("sptw-modal-spinner"),jQuery("#shortPixelProposeUpgrade .sp-modal-body").html(""),jQuery("#shortPixelProposeUpgradeShade").css("display","block"),jQuery("#shortPixelProposeUpgrade").removeClass("shortpixel-hide"),jQuery.ajax({type:"POST",url:ShortPixel.AJAX_URL,data:{action:"shortpixel_propose_upgrade"},success:function(e){jQuery("#shortPixelProposeUpgrade .sp-modal-body").removeClass("sptw-modal-spinner"),jQuery("#shortPixelProposeUpgrade .sp-modal-body").html(e)}})},closeProposeUpgrade:function(){jQuery("#shortPixelProposeUpgradeShade").css("display","none"),jQuery("#shortPixelProposeUpgrade").addClass("shortpixel-hide"),ShortPixel.toRefresh&&ShortPixel.recheckQuota()},bulkShowLengthyMsg:function(e,r,t){var o=jQuery(".bulk-notice-msg.bulk-lengthy");if(0!=o.length){var s=jQuery("a",o);s.text(r),t?s.attr("href",t):s.attr("href",s.data("href").replace("__ID__",e)),o.css("display","block")}},bulkHideLengthyMsg:function(){jQuery(".bulk-notice-msg.bulk-lengthy").css("display","none")},bulkShowMaintenanceMsg:function(e){var r=jQuery(".bulk-notice-msg.bulk-"+e);0!=r.length&&r.css("display","block")},bulkHideMaintenanceMsg:function(e){jQuery(".bulk-notice-msg.bulk-"+e).css("display","none")},bulkShowError:function(e,r,t,o){var s=jQuery("#bulk-error-template");if(0!=s.length){var i=s.clone();i.attr("id","bulk-error-"+e),-1==e?(jQuery("span.sp-err-title",i).remove(),i.addClass("bulk-error-fatal")):(jQuery("img",i).remove(),jQuery("#bulk-error-".id).remove()),jQuery("span.sp-err-content",i).html(r);var a=jQuery("a.sp-post-link",i);o?a.attr("href",o):a.attr("href",a.attr("href").replace("__ID__",e)),a.text(t),s.after(i),i.css("display","block")}},confirmBulkAction:function(e,r){return!!confirm(_spTr["confirmBulk"+e])||(r.stopPropagation(),r.preventDefault(),!1)},checkRandomAnswer:function(e){var r=jQuery(e.target).val(),t=jQuery('input[name="random_answer"]').val(),o=jQuery('input[name="random_answer"]').data("target");r==t?(jQuery(o).removeClass("disabled").prop("disabled",!1),jQuery(o).removeAttr("aria-disabled")):jQuery(o).addClass("disabled").prop("disabled",!0)},removeBulkMsg:function(e){jQuery(e).parent().parent().remove()},isCustomImageId:function(e){return"C-"==e.substring(0,2)},recheckQuota:function(){var e=window.location.href.split("#");window.location.href=e[0]+(e[0].indexOf("?")>0?"&":"?")+"checkquota=1"+(void 0===e[1]?"":"#"+e[1])},openImageMenu:function(e){e.preventDefault(),this.menuCloseEvent||(jQuery(window).click(function(e){e.target.matches(".sp-dropbtn")||jQuery(".sp-dropdown.sp-show").removeClass("sp-show")}),this.menuCloseEvent=!0);var r=e.target.parentElement.classList.contains("sp-show");jQuery(".sp-dropdown.sp-show").removeClass("sp-show"),r||e.target.parentElement.classList.add("sp-show")},menuCloseEvent:!1,loadComparer:function(e){this.comparerData.origUrl=!1,!1===this.comparerData.cssLoaded&&(jQuery("<link>").appendTo("head").attr({type:"text/css",rel:"stylesheet",href:this.WP_PLUGIN_URL+"/res/css/twentytwenty.min.css"}),this.comparerData.cssLoaded=2),!1===this.comparerData.jsLoaded&&(jQuery.getScript(this.WP_PLUGIN_URL+"/res/js/jquery.twentytwenty.min.js",function(){ShortPixel.comparerData.jsLoaded=2,ShortPixel.comparerData.origUrl.length>0&&ShortPixel.displayComparerPopup(ShortPixel.comparerData.width,ShortPixel.comparerData.height,ShortPixel.comparerData.origUrl,ShortPixel.comparerData.optUrl)}),this.comparerData.jsLoaded=1),!1===this.comparerData.origUrl&&(jQuery.ajax({type:"POST",url:ShortPixel.AJAX_URL,data:{action:"shortpixel_get_comparer_data",id:e},success:function(e){data=JSON.parse(e),jQuery.extend(ShortPixel.comparerData,data),2==ShortPixel.comparerData.jsLoaded&&ShortPixel.displayComparerPopup(ShortPixel.comparerData.width,ShortPixel.comparerData.height,ShortPixel.comparerData.origUrl,ShortPixel.comparerData.optUrl)}}),this.comparerData.origUrl="")},displayComparerPopup:function(e,r,t,o){var s=e,i=r<150||e<350,a=jQuery(i?"#spUploadCompareSideBySide":"#spUploadCompare"),l=jQuery(".sp-modal-shade");i||jQuery("#spCompareSlider").html('<img alt="'+_spTr.originalImage+'" class="spUploadCompareOriginal"/><img alt="'+_spTr.optimizedImage+'" class="spUploadCompareOptimized"/>'),e=Math.max(350,Math.min(800,e<350?2*(e+25):r<150?e+25:e)),r=Math.max(150,i?s>350?2*(r+45):r+45:r*e/s);var n="-"+Math.round(e/2);jQuery(".sp-modal-body",a).css("width",e),jQuery(".shortpixel-slider",a).css("width",e),a.css("width",e),a.css("marginLeft",n+"px"),jQuery(".sp-modal-body",a).css("height",r),a.show(),l.show(),i||jQuery("#spCompareSlider").twentytwenty({slider_move:"mousemove"}),jQuery(".sp-close-button").on("click",ShortPixel.closeComparerPopup),jQuery(document).on("keyup.sp_modal_active",ShortPixel.closeComparerPopup),jQuery(".sp-modal-shade").on("click",ShortPixel.closeComparerPopup);var u=jQuery(".spUploadCompareOptimized",a);jQuery(".spUploadCompareOriginal",a).attr("src",t),setTimeout(function(){jQuery(window).trigger("resize")},1e3),u.load(function(){jQuery(window).trigger("resize")}),u.attr("src",o)},closeComparerPopup:function(e){jQuery("#spUploadCompareSideBySide").hide(),jQuery("#spUploadCompare").hide(),jQuery(".sp-modal-shade").hide(),jQuery(document).unbind("keyup.sp_modal_active"),jQuery(".sp-modal-shade").off("click"),jQuery(".sp-close-button").off("click")},convertPunycode:function(e){var r=document.createElement("a");return r.href=e,e.indexOf(r.protocol+"//"+r.hostname)<0?r.href:e.replace(r.protocol+"//"+r.hostname,r.protocol+"//"+r.hostname.split(".").map(function(e){return sp_punycode.toASCII(e)}).join("."))},checkExifWarning:function(){!jQuery('input[name="removeExif"]').is(":checked")&&jQuery('input[name="png2jpg"]').is(":checked")?jQuery(".exif_warning").fadeIn():jQuery(".exif_warning").fadeOut(),!jQuery('input[name="removeExif"]').is(":checked")&&jQuery(".exif_imagick_warning").data("imagick")<=0?jQuery(".exif_imagick_warning").fadeIn():jQuery(".exif_imagick_warning").fadeOut()},checkBackUpWarning:function(){jQuery('input[name="backupImages"]').is(":checked")?jQuery(".backup_warning").fadeOut():jQuery(".backup_warning").fadeIn()},comparerData:{cssLoaded:!1,jsLoaded:!1,origUrl:!1,optUrl:!1,width:0,height:0},toRefresh:!1,resizeSizesAlert:!1,returnedStatusSearching:0}}();
1
+ jQuery(document).ready((function(){ShortPixel.init()}));var ShortPixel=function(){function e(){if(typeof ShortPixel.API_IS_ACTIVE!=="undefined")return;if(jQuery("table.wp-list-table.media").length>0){jQuery('select[name^="action"] option:last-child').before('<option value="short-pixel-bulk">'+_spTr.optimizeWithSP+'</option><option value="short-pixel-bulk-lossy"> → '+_spTr.redoLossy+'</option><option value="short-pixel-bulk-glossy"> → '+_spTr.redoGlossy+'</option><option value="short-pixel-bulk-lossless"> → '+_spTr.redoLossless+'</option><option value="short-pixel-bulk-restore"> → '+_spTr.restoreOriginal+"</option>")}ShortPixel.setOptions(ShortPixelConstants[0]);if(jQuery("#backup-folder-size").length){jQuery("#backup-folder-size").html(ShortPixel.getBackupSize())}if(ShortPixel.MEDIA_ALERT=="todo"&&jQuery("div.media-frame.mode-grid").length>0){jQuery("div.media-frame.mode-grid").before('<div id="short-pixel-media-alert" class="notice notice-warning"><p>'+SPstringFormat(_spTr.changeMLToListMode,'<a href="upload.php?mode=list" class="view-list"><span class="screen-reader-text">'," </span>",'</a><a class="alignright" href="javascript:ShortPixel.dismissMediaAlert();">',"</a>")+"</p></div>")}jQuery(window).on("beforeunload",(function(){if(ShortPixel.bulkProcessor==true){clearBulkProcessor()}}));checkQuotaExceededAlert();checkBulkProgress()}function r(e){for(var r in e){ShortPixel[r]=e[r]}}function t(e){return/^\w+([\.+-]?\w+)*@\w+([\.-]?\w+)*(\.\w{1,63})+$/.test(e)}function i(){var e=jQuery("#pluginemail").val();if(ShortPixel.isEmailValid(e)){jQuery("#request_key").removeClass("disabled")}jQuery("#request_key").attr("href",jQuery("#request_key").attr("href").split("?")[0]+"?pluginemail="+e)}function s(e){jQuery("#valid").val("validate");jQuery(e).parents("form").submit()}jQuery("#key").keypress((function(e){if(e.which==13){jQuery("#valid").val("validate")}}));function o(e){if(jQuery(e).is(":checked")){jQuery("#width,#height").removeAttr("disabled");SpioResize.lastW=false;jQuery(".resize-type-wrap").show(800,window.SpioResize.run)}else{jQuery("#width,#height").attr("disabled","disabled");window.SpioResize.hide();jQuery(".resize-type-wrap").hide(800)}}function a(){if(!jQuery('input[name="removeExif"]').is(":checked")&&jQuery('input[name="png2jpg"]').is(":checked"))jQuery(".exif_warning").fadeIn();else jQuery(".exif_warning").fadeOut();if(!jQuery('input[name="removeExif"]').is(":checked")&&jQuery(".exif_imagick_warning").data("imagick")<=0)jQuery(".exif_imagick_warning").fadeIn();else jQuery(".exif_imagick_warning").fadeOut()}function l(){if(!jQuery('input[name="backupImages"]').is(":checked")){jQuery(".backup_warning").fadeIn()}else{jQuery(".backup_warning").fadeOut()}}function n(){var e=0;if(typeof document.wp_shortpixel_options!=="undefined")e=document.wp_shortpixel_options.compressionType;for(var r=0,t=null;r<e.length;r++){e[r].onclick=function(){if(this!==t){t=this}if(typeof ShortPixel.setupGeneralTabAlert!=="undefined")return;alert(_spTr.alertOnlyAppliesToNewImages);ShortPixel.setupGeneralTabAlert=1}}ShortPixel.enableResize("#resize");jQuery("#resize").change((function(){o(this)}));jQuery(".resize-sizes").blur((function(e){var r=jQuery(e.target);if(ShortPixel.resizeSizesAlert==r.val())return;ShortPixel.resizeSizesAlert=r.val();var t=jQuery("#min-"+r.attr("name")).val();var i=jQuery("#min-"+r.attr("name")).data("nicename");if(r.val()<Math.min(t,1024)){if(t>1024){alert(SPstringFormat(_spTr.pleaseDoNotSetLesser1024,i))}else{alert(SPstringFormat(_spTr.pleaseDoNotSetLesserSize,i,i,t))}e.preventDefault();r.focus()}else{this.defaultValue=r.val()}}));jQuery(".shortpixel-confirm").click((function(e){var r=confirm(e.target.getAttribute("data-confirm"));if(!r){e.preventDefault();return false}return true}));jQuery('input[name="removeExif"], input[name="png2jpg"]').on("change",(function(){ShortPixel.checkExifWarning()}));ShortPixel.checkExifWarning();jQuery('input[name="backupImages"]').on("change",(function(){ShortPixel.checkBackUpWarning()}));ShortPixel.checkBackUpWarning()}function u(){jQuery(".wp-shortpixel-options .shortpixel-key-valid").css("display","none");jQuery(".wp-shortpixel-options button#validate").css("display","inline-block")}function p(){jQuery("input.remove-folder-button").click((function(){var e=jQuery(this).data("value");var r=jQuery(this).data("name");var t=confirm(SPstringFormat(_spTr.areYouSureStopOptimizing,r));if(t==true){jQuery("#removeFolder").val(e);jQuery("#wp_shortpixel_options").submit()}}));jQuery("input.recheck-folder-button").click((function(){var e=jQuery(this).data("value");var r=confirm(SPstringFormat(_spTr.areYouSureStopOptimizing,e));if(r==true){jQuery("#recheckFolder").val(e);jQuery("#wp_shortpixel_options").submit()}}))}function c(e){var r=jQuery("#"+(e.checked?"total":"main")+"ToProcess").val();jQuery("div.bulk-play span.total").text(r);jQuery("#displayTotal").text(r)}function d(){ShortPixel.adjustSettingsTabs();ShortPixel.setupGeneralTab();jQuery(window).resize((function(){ShortPixel.adjustSettingsTabs()}));jQuery("article.sp-tabs a.tab-link").click((function(e){var r=jQuery(e.target).data("id");ShortPixel.switchSettingsTab(r)}));jQuery("input[type=radio][name=deliverWebpType]").change((function(){if(this.value=="deliverWebpAltered"){if(window.confirm(_spTr.alertDeliverWebPAltered)){var e=jQuery("input[type=radio][name=deliverWebpAlteringType]:checked").length;if(e==0){jQuery("#deliverWebpAlteredWP").prop("checked",true)}}else{jQuery(this).prop("checked",false)}}else if(this.value=="deliverWebpUnaltered"){window.alert(_spTr.alertDeliverWebPUnaltered)}}))}function h(e){var r=e.replace("tab-",""),t="",i=jQuery("section#"+e);jQuery('input[name="display_part"]').val(r);var s=window.location.href.toString();if(s.indexOf("?")>0){var o=s.substring(0,s.indexOf("?"));o+="?"+jQuery.param({page:"wp-shortpixel-settings",part:r});window.history.replaceState({},document.title,o)}if(i.length>0){jQuery("section").removeClass("sel-tab");jQuery("section .wp-shortpixel-tab-content").fadeOut(50);jQuery(i).addClass("sel-tab");ShortPixel.adjustSettingsTabs();jQuery(i).find(".wp-shortpixel-tab-content").fadeIn(50)}if(typeof HS!=="undefined"&&typeof HS.beacon.suggest!=="undefined"){switch(r){case"settings":t=shortpixel_suggestions_settings;break;case"adv-settings":t=shortpixel_suggestions_adv_settings;break;case"cloudflare":case"stats":t=shortpixel_suggestions_cloudflare;break;default:break}HS.beacon.suggest(t)}}function f(){var e=jQuery("section.sel-tab").height()+90;jQuery(".section-wrapper").css("height",e)}function m(){var e={action:"shortpixel_dismiss_media_alert"};jQuery.get(ShortPixel.AJAX_URL,e,(function(r){e=JSON.parse(r);if(e["Status"]=="success"){jQuery("#short-pixel-media-alert").hide()}}))}function g(){jQuery("#shortpixel-hs-button-blind").remove();jQuery("#shortpixel-hs-tools").remove();jQuery("#hs-beacon").remove();jQuery("#botbutton").remove();jQuery("#shortpixel-hs-blind").remove()}function S(){g();dismissShortPixelNotice("help")}function y(){var e={action:"shortpixel_check_quota",nonce:ShortPixelActions.nonce_check_quota,return_json:true};jQuery.post(ShortPixel.AJAX_URL,e,(function(e){console.log("quota refreshed");console.log(e);window.location.href=e.redirect}))}function x(e){if(e.checked){jQuery("#with-thumbs").css("display","inherit");jQuery("#without-thumbs").css("display","none")}else{jQuery("#without-thumbs").css("display","inherit");jQuery("#with-thumbs").css("display","none")}}function j(e,r,t,i,s){return(r>0?"<div class='sp-column-info'>"+_spTr.reducedBy+" <strong><span class='percent'>"+r+"%</span></strong> ":"")+(r>0&&r<5?"<br>":"")+(r<5?_spTr.bonusProcessing:"")+(t.length>0?" ("+t+")":"")+(0+i>0?"<br>"+SPstringFormat(_spTr.plusXthumbsOpt,i):"")+(0+s>0?"<br>"+SPstringFormat(_spTr.plusXretinasOpt,s):"")+"</div>"}function P(e,r){jQuery(e).knob({readOnly:true,width:r,height:r,fgColor:"#1CAECB",format:function(e){return e+"%"}})}function v(e,r,t,i,s,o){if(s==1){var a=jQuery(".sp-column-actions-template").clone();if(!a.length)return false;var l;if(r.length==0){l=["lossy","lossless"]}else{l=["lossy","glossy","lossless"].filter((function(e){return!(e==r)}))}a.html(a.html().replace(/__SP_ID__/g,e));if(o.substr(o.lastIndexOf(".")+1).toLowerCase()=="pdf"){jQuery(".sp-action-compare",a).remove()}if(t==0&&i>0){a.html(a.html().replace("__SP_THUMBS_TOTAL__",i))}else{jQuery(".sp-action-optimize-thumbs",a).remove();jQuery(".sp-dropbtn",a).removeClass("button-primary")}a.html(a.html().replace(/__SP_FIRST_TYPE__/g,l[0]));a.html(a.html().replace(/__SP_SECOND_TYPE__/g,l[1]));return a.html()}return""}function Q(e,r){e=e.substring(2);if(jQuery(".shortpixel-other-media").length){var t=["optimize","retry","restore","redo","quota","view"];for(var i=0,s=t.length;i<s;i++){jQuery("#"+t[i]+"_"+e).css("display","none")}for(var i=0,s=r.length;i<s;i++){jQuery("#"+r[i]+"_"+e).css("display","")}}}function b(e){ShortPixel.retries++;if(isNaN(ShortPixel.retries))ShortPixel.retries=1;if(ShortPixel.retries<6){console.log("Invalid response from server (Error: "+e+"). Retrying pass "+(ShortPixel.retries+1)+"...");setBulkTimer(5e3)}else{ShortPixel.bulkShowError(-1,"Invalid response from server received 6 times. Please retry later by reloading this page, or <a href='https://shortpixel.com/contact' target='_blank'>contact support</a>. (Error: "+e+")","");console.log("Invalid response from server 6 times. Giving up.")}}function k(e){e.action="shortpixel_browse_content";var r="";jQuery.ajax({type:"POST",url:ShortPixel.AJAX_URL,data:e,success:function(e){r=e},async:false});return r}function T(){var e={action:"shortpixel_get_backup_size"};var r="";jQuery.ajax({type:"POST",url:ShortPixel.AJAX_URL,data:e,success:function(e){r=e},async:false});return r}function _(e){if(!jQuery("#tos").is(":checked")){e.preventDefault();jQuery("#tos-robo").fadeIn(400,(function(){jQuery("#tos-hand").fadeIn()}));jQuery("#tos").click((function(){jQuery("#tos-robo").css("display","none");jQuery("#tos-hand").css("display","none")}));return}jQuery("#request_key").addClass("disabled");jQuery("#pluginemail_spinner").addClass("is-active");ShortPixel.updateSignupEmail();if(ShortPixel.isEmailValid(jQuery("#pluginemail").val())){jQuery("#pluginemail-error").css("display","none");var r={action:"shortpixel_new_api_key",email:jQuery("#pluginemail").val()};jQuery.ajax({type:"POST",async:false,url:ShortPixel.AJAX_URL,data:r,success:function(r){data=JSON.parse(r);if(data["Status"]=="success"){e.preventDefault();window.location.reload()}else if(data["Status"]=="invalid"){jQuery("#pluginemail-error").html("<b>"+data["Details"]+"</b>");jQuery("#pluginemail-error").css("display","");jQuery("#pluginemail-info").css("display","none");e.preventDefault()}else{}}});jQuery("#request_key").removeAttr("onclick")}else{jQuery("#pluginemail-error").css("display","");jQuery("#pluginemail-info").css("display","none");e.preventDefault()}jQuery("#request_key").removeClass("disabled");jQuery("#pluginemail_spinner").removeClass("is-active")}function w(){jQuery("#shortPixelProposeUpgrade .sp-modal-body").addClass("sptw-modal-spinner");jQuery("#shortPixelProposeUpgrade .sp-modal-body").html("");jQuery("#shortPixelProposeUpgradeShade").css("display","block");jQuery("#shortPixelProposeUpgrade").removeClass("shortpixel-hide");var e={action:"shortpixel_propose_upgrade"};jQuery.ajax({type:"POST",url:ShortPixel.AJAX_URL,data:e,success:function(e){jQuery("#shortPixelProposeUpgrade .sp-modal-body").removeClass("sptw-modal-spinner");jQuery("#shortPixelProposeUpgrade .sp-modal-body").html(e)}})}function C(){jQuery("#shortPixelProposeUpgradeShade").css("display","none");jQuery("#shortPixelProposeUpgrade").addClass("shortpixel-hide");if(ShortPixel.toRefresh){ShortPixel.checkQuota()}}function A(){jQuery(".select-folder-button").click((function(){jQuery(".sp-folder-picker-shade").fadeIn(100);jQuery(".shortpixel-modal.modal-folder-picker").show();var e=jQuery(".sp-folder-picker");e.parent().css("margin-left",-e.width()/2);e.fileTree({script:ShortPixel.browseContent,multiFolder:false})}));jQuery(".shortpixel-modal input.select-folder-cancel, .sp-folder-picker-shade").click((function(){jQuery(".sp-folder-picker-shade").fadeOut(100);jQuery(".shortpixel-modal.modal-folder-picker").hide()}));jQuery(".shortpixel-modal input.select-folder").click((function(e){var r=jQuery("UL.jqueryFileTree LI.directory.selected");if(jQuery(r).length==0)var r=jQuery("UL.jqueryFileTree LI.selected").parents(".directory");var t=jQuery(r).children("a").attr("rel");if(typeof t==="undefined")return;t=t.trim();if(t){var i=jQuery("#customFolderBase").val()+t;i=i.replace(/\/\//,"/");console.debug("FullPath"+i);jQuery("#addCustomFolder").val(i);jQuery("#addCustomFolderView").val(i);jQuery(".sp-folder-picker-shade").fadeOut(100);jQuery(".shortpixel-modal.modal-folder-picker").css("display","none");jQuery("#saveAdvAddFolder").removeClass("hidden")}else{alert("Please select a folder from the list.")}}))}function U(e,r,t){var i=jQuery(".bulk-notice-msg.bulk-lengthy");if(i.length==0)return;var s=jQuery("a",i);s.text(r);if(t){s.attr("href",t)}else{s.attr("href",s.data("href").replace("__ID__",e))}i.css("display","block")}function z(){jQuery(".bulk-notice-msg.bulk-lengthy").css("display","none")}function R(e){var r=jQuery(".bulk-notice-msg.bulk-"+e);if(r.length==0)return;r.css("display","block")}function E(e){jQuery(".bulk-notice-msg.bulk-"+e).css("display","none")}function M(e,r,t,i){var s=jQuery("#bulk-error-template");if(s.length==0)return;var o=s.clone();o.attr("id","bulk-error-"+e);if(e==-1){jQuery("span.sp-err-title",o).remove();o.addClass("bulk-error-fatal")}else{jQuery("img",o).remove();jQuery("#bulk-error-".id).remove()}jQuery("span.sp-err-content",o).html(r);var a=jQuery("a.sp-post-link",o);if(i){a.attr("href",i)}else{a.attr("href",a.attr("href").replace("__ID__",e))}a.text(t);s.after(o);o.css("display","block")}function B(e,r){if(!confirm(_spTr["confirmBulk"+e])){r.stopPropagation();r.preventDefault();return false}return true}function L(e){var r=jQuery(e.target).val();var t=jQuery('input[name="random_answer"]').val();var i=jQuery('input[name="random_answer"]').data("target");if(r==t){jQuery(i).removeClass("disabled").prop("disabled",false);jQuery(i).removeAttr("aria-disabled")}else{jQuery(i).addClass("disabled").prop("disabled",true)}}function I(e){jQuery(e).parent().parent().remove()}function D(e){return e.substring(0,2)=="C-"}function O(e){e.preventDefault();if(!this.menuCloseEvent){jQuery(window).click((function(e){if(!e.target.matches(".sp-dropbtn")){jQuery(".sp-dropdown.sp-show").removeClass("sp-show")}}));this.menuCloseEvent=true}var r=e.target.parentElement.classList.contains("sp-show");jQuery(".sp-dropdown.sp-show").removeClass("sp-show");if(!r)e.target.parentElement.classList.add("sp-show")}function F(e){this.comparerData.origUrl=false;if(this.comparerData.cssLoaded===false){jQuery("<link>").appendTo("head").attr({type:"text/css",rel:"stylesheet",href:this.WP_PLUGIN_URL+"/res/css/twentytwenty.min.css"});this.comparerData.cssLoaded=2}if(this.comparerData.jsLoaded===false){jQuery.getScript(this.WP_PLUGIN_URL+"/res/js/jquery.twentytwenty.min.js",(function(){ShortPixel.comparerData.jsLoaded=2;if(ShortPixel.comparerData.origUrl.length>0){ShortPixel.displayComparerPopup(ShortPixel.comparerData.width,ShortPixel.comparerData.height,ShortPixel.comparerData.origUrl,ShortPixel.comparerData.optUrl)}}));this.comparerData.jsLoaded=1}if(this.comparerData.origUrl===false){jQuery.ajax({type:"POST",url:ShortPixel.AJAX_URL,data:{action:"shortpixel_get_comparer_data",id:e},success:function(e){data=JSON.parse(e);jQuery.extend(ShortPixel.comparerData,data);if(ShortPixel.comparerData.jsLoaded==2){ShortPixel.displayComparerPopup(ShortPixel.comparerData.width,ShortPixel.comparerData.height,ShortPixel.comparerData.origUrl,ShortPixel.comparerData.optUrl)}}});this.comparerData.origUrl=""}}function N(e,r,t,i){var s=e;var o=r<150||e<350;var a=jQuery(o?"#spUploadCompareSideBySide":"#spUploadCompare");var l=jQuery(".sp-modal-shade");if(!o){jQuery("#spCompareSlider").html('<img alt="'+_spTr.originalImage+'" class="spUploadCompareOriginal"/><img alt="'+_spTr.optimizedImage+'" class="spUploadCompareOptimized"/>')}e=Math.max(350,Math.min(800,e<350?(e+25)*2:r<150?e+25:e));r=Math.max(150,o?s>350?2*(r+45):r+45:r*e/s);var n="-"+Math.round(e/2);jQuery(".sp-modal-body",a).css("width",e);jQuery(".shortpixel-slider",a).css("width",e);a.css("width",e);a.css("marginLeft",n+"px");jQuery(".sp-modal-body",a).css("height",r);a.show();l.show();if(!o){jQuery("#spCompareSlider").twentytwenty({slider_move:"mousemove"})}jQuery(".sp-close-button").on("click",ShortPixel.closeComparerPopup);jQuery(document).on("keyup.sp_modal_active",ShortPixel.closeComparerPopup);jQuery(".sp-modal-shade").on("click",ShortPixel.closeComparerPopup);var u=jQuery(".spUploadCompareOptimized",a);jQuery(".spUploadCompareOriginal",a).attr("src",t);setTimeout((function(){jQuery(window).trigger("resize")}),1e3);u.load((function(){jQuery(window).trigger("resize")}));u.attr("src",i)}function W(e){jQuery("#spUploadCompareSideBySide").hide();jQuery("#spUploadCompare").hide();jQuery(".sp-modal-shade").hide();jQuery(document).unbind("keyup.sp_modal_active");jQuery(".sp-modal-shade").off("click");jQuery(".sp-close-button").off("click")}function J(e){var r=document.createElement("a");r.href=e;if(e.indexOf(r.protocol+"//"+r.hostname)<0){return r.href}return e.replace(r.protocol+"//"+r.hostname,r.protocol+"//"+r.hostname.split(".").map((function(e){return sp_punycode.toASCII(e)})).join("."))}return{init:e,setOptions:r,isEmailValid:t,updateSignupEmail:i,validateKey:s,enableResize:o,setupGeneralTab:n,apiKeyChanged:u,setupAdvancedTab:p,checkThumbsUpdTotal:c,initSettings:d,switchSettingsTab:h,adjustSettingsTabs:f,onBulkThumbsCheck:x,dismissMediaAlert:m,closeHelpPane:g,dismissHelpPane:S,checkQuota:y,percentDial:P,successMsg:j,successActions:v,otherMediaUpdateActions:Q,retry:b,initFolderSelector:A,browseContent:k,getBackupSize:T,newApiKey:_,proposeUpgrade:w,closeProposeUpgrade:C,bulkShowLengthyMsg:U,bulkHideLengthyMsg:z,bulkShowMaintenanceMsg:R,bulkHideMaintenanceMsg:E,bulkShowError:M,confirmBulkAction:B,checkRandomAnswer:L,removeBulkMsg:I,isCustomImageId:D,openImageMenu:O,menuCloseEvent:false,loadComparer:F,displayComparerPopup:N,closeComparerPopup:W,convertPunycode:J,checkExifWarning:a,checkBackUpWarning:l,comparerData:{cssLoaded:false,jsLoaded:false,origUrl:false,optUrl:false,width:0,height:0},toRefresh:false,resizeSizesAlert:false,returnedStatusSearching:0}}();function showToolBarAlert(e,r,t){var i=jQuery("li.shortpixel-toolbar-processing");switch(e){case ShortPixel.STATUS_QUOTA_EXCEEDED:if(window.location.href.search("wp-short-pixel-bulk")>0&&jQuery(".sp-quota-exceeded-alert").length==0){return}i.addClass("shortpixel-alert");i.addClass("shortpixel-quota-exceeded");jQuery("a",i).attr("href","options-general.php?page=wp-shortpixel-settings");jQuery("a div",i).attr("title","ShortPixel quota exceeded. Click for details.");break;case ShortPixel.STATUS_SKIP:case ShortPixel.STATUS_FAIL:i.addClass("shortpixel-alert shortpixel-processing");jQuery("a div",i).attr("title",r);if(typeof t!=="undefined"){jQuery("a",i).attr("href","post.php?post="+t+"&action=edit")}break;case ShortPixel.STATUS_NO_KEY:i.addClass("shortpixel-alert");i.addClass("shortpixel-quota-exceeded");jQuery("a",i).attr("href","options-general.php?page=wp-shortpixel-settings");jQuery("a div",i).attr("title","Get API Key");break;case ShortPixel.STATUS_SUCCESS:case ShortPixel.STATUS_RETRY:i.addClass("shortpixel-processing");i.removeClass("shortpixel-alert");jQuery("a",i).removeAttr("target");jQuery("a",i).attr("href",jQuery("a img",i).attr("success-url"))}i.removeClass("shortpixel-hide")}function hideToolBarAlert(e){var r=jQuery("li.shortpixel-toolbar-processing.shortpixel-processing");if(ShortPixel.STATUS_EMPTY_QUEUE==e){if(r.hasClass("shortpixel-alert")||r.hasClass("shortpixel-quota-exceeded")){return}}r.addClass("shortpixel-hide")}function hideQuotaExceededToolBarAlert(){jQuery("li.shortpixel-toolbar-processing.shortpixel-quota-exceeded").addClass("shortpixel-hide")}function checkQuotaExceededAlert(){if(typeof shortPixelQuotaExceeded!="undefined"){if(shortPixelQuotaExceeded==1){showToolBarAlert(ShortPixel.STATUS_QUOTA_EXCEEDED)}else{hideQuotaExceededToolBarAlert()}}}function checkBulkProgress(){var e=function(e){if(!r){r=true;return e}return"/"};var r=false;var t=window.location.href.toLowerCase().replace(/\/\//g,e);r=false;var i=ShortPixel.WP_ADMIN_URL.toLowerCase().replace(/\/\//g,e);if(t.search(i)<0){t=ShortPixel.convertPunycode(t);i=ShortPixel.convertPunycode(i)}if(ShortPixel.bulkProcessor==true&&window.location.href.search("wp-short-pixel-bulk")<0&&typeof localStorage.bulkPage!=="undefined"&&localStorage.bulkPage>0){ShortPixel.bulkProcessor=false}if(window.location.href.search("wp-short-pixel-bulk")>=0){ShortPixel.bulkProcessor=true;localStorage.bulkTime=Date.now();localStorage.bulkPage=1;ShortPixel.BULK_SECRET=false}if(ShortPixel.BULK_SECRET!==false){if(ShortPixel.BULK_SECRET!=localStorage.bulkSecret){clearBulkProcessor();jQuery("li.shortpixel-toolbar-processing").removeClass("shortpixel-processing");jQuery("li.shortpixel-toolbar-processing").addClass("shortpixel-hide");return}}if(ShortPixel.bulkProcessor==true||typeof localStorage.bulkTime=="undefined"||Date.now()-localStorage.bulkTime>1e4){ShortPixel.bulkProcessor=true;localStorage.bulkPage=window.location.href.search("wp-short-pixel-bulk")>=0?1:0;localStorage.bulkTime=Date.now();if(localStorage.getItem("bulkSecret")==null)localStorage.bulkSecret=Math.random().toString(36).substring(7);checkBulkProcessingCallApi()}else{setBulkTimer(2e4)}}var bulkTimer;function setBulkTimer(e){window.clearTimeout(bulkTimer);if(e>0){bulkTimer=window.setTimeout(checkBulkProgress,e)}}function checkBulkProcessingCallApi(){var e={action:"shortpixel_image_processing","bulk-secret":localStorage.bulkSecret};jQuery.ajax({type:"POST",url:ShortPixel.AJAX_URL,data:e,success:function(e){if(e.length>0){var r=null;try{var r=JSON.parse(e)}catch(e){ShortPixel.retry(e.message);return}ShortPixel.retries=0;var t=r["ImageID"];var i=jQuery("div.short-pixel-bulk-page").length>0;if(r["Status"]&&r["Status"]!=ShortPixel.STATUS_SEARCHING){if(ShortPixel.returnedStatusSearching>=2)jQuery(".bulk-notice-msg.bulk-searching").hide();ShortPixel.returnedStatusSearching=0}switch(r["Status"]){case ShortPixel.STATUS_NO_KEY:setCellMessage(t,r["Message"],"<a class='button button-smaller button-primary' href=\"https://shortpixel.com/wp-apikey"+'" target="_blank">'+_spTr.getApiKey+"</a>");showToolBarAlert(ShortPixel.STATUS_NO_KEY);break;case ShortPixel.STATUS_QUOTA_EXCEEDED:setCellMessage(t,r["Message"],"<a class='button button-smaller button-primary' href=\"https://shortpixel.com/login/"+'" target="_blank">'+_spTr.extendQuota+"</a>"+"<a class='button button-smaller' href='javascript:ShortPixel.checkQuota()'>"+_spTr.check__Quota+"</a>");showToolBarAlert(ShortPixel.STATUS_QUOTA_EXCEEDED);if(r["Stop"]==false){setBulkTimer(5e3)}ShortPixel.otherMediaUpdateActions(t,["quota","view"]);break;case ShortPixel.STATUS_FAIL:setCellMessage(t,r["Message"],"<a class='button button-smaller button-primary' href=\"javascript:manualOptimization('"+t+"', true)\">"+_spTr.retry+"</a>");showToolBarAlert(ShortPixel.STATUS_FAIL,r["Message"],t);if(i){ShortPixel.bulkShowError(t,r["Message"],r["Filename"],r["CustomImageLink"]);if(r["BulkPercent"]){progressUpdate(r["BulkPercent"],r["BulkMsg"])}ShortPixel.otherMediaUpdateActions(t,["retry","view"])}console.log(r["Message"]);setBulkTimer(5e3);break;case ShortPixel.STATUS_EMPTY_QUEUE:console.log(r["Message"]);clearBulkProcessor();hideToolBarAlert(r["Status"]);var s=jQuery("#bulk-progress");if(i&&s.length&&r["BulkStatus"]!="2"){progressUpdate(100,"Bulk finished!");jQuery("a.bulk-cancel").attr("disabled","disabled");hideSlider();setTimeout((function(){window.location.reload()}),3e3)}break;case ShortPixel.STATUS_SUCCESS:if(i){ShortPixel.bulkHideLengthyMsg();ShortPixel.bulkHideMaintenanceMsg()}var o=r["PercentImprovement"];showToolBarAlert(ShortPixel.STATUS_SUCCESS,"");var a=ShortPixel.isCustomImageId(t)?"":ShortPixel.successActions(t,r["Type"],r["ThumbsCount"],r["ThumbsTotal"],r["BackupEnabled"],r["Filename"]);setCellMessage(t,ShortPixel.successMsg(t,o,r["Type"],r["ThumbsCount"],r["RetinasCount"]),a);if(jQuery("#post-"+t).length>0)jQuery("#post-"+t).find(".filename").text(r["Filename"]);if(jQuery(".misc-pub-filename strong").length>0)jQuery(".misc-pub-filename strong").text(r["Filename"]);if(ShortPixel.isCustomImageId(t)&&r["TsOptimized"]&&r["TsOptimized"].length>0){var l=jQuery(".list-overview .item-"+t);jQuery(l).children(".date").text(r["TsOptimized"]);jQuery(l).find(".row-actions .action-optimize").remove()}var n=jQuery(["restore","view","redolossy","redoglossy","redolossless"]).not(["redo"+r["Type"]]).get();ShortPixel.otherMediaUpdateActions(t,n);var u=new PercentageAnimator("#sp-msg-"+t+" span.percent",o);u.animate(o);if(i&&typeof r["Thumb"]!=="undefined"){if(r["BulkPercent"]){progressUpdate(r["BulkPercent"],r["BulkMsg"])}if(r["Thumb"].length>0){sliderUpdate(t,r["Thumb"],r["BkThumb"],r["PercentImprovement"],r["Filename"]);if(typeof r["AverageCompression"]!=="undefined"&&0+r["AverageCompression"]>0){jQuery("#sp-avg-optimization").html('<input type="text" class="dial" value="'+Math.round(r["AverageCompression"])+'"/>');ShortPixel.percentDial("#sp-avg-optimization .dial",60)}}}console.log("Server response: "+e);if(i&&typeof r["BulkPercent"]!=="undefined"){progressUpdate(r["BulkPercent"],r["BulkMsg"])}setBulkTimer(5e3);break;case ShortPixel.STATUS_SKIP:if(r["Silent"]!==1){ShortPixel.bulkShowError(t,r["Message"],r["Filename"],r["CustomImageLink"])}case ShortPixel.STATUS_ERROR:if(typeof r["Message"]!=="undefined"){showToolBarAlert(ShortPixel.STATUS_SKIP,r["Message"]+" Image ID: "+t);setCellMessage(t,r["Message"],"")}ShortPixel.otherMediaUpdateActions(t,["retry","view"]);case ShortPixel.STATUS_RETRY:console.log("Server response: "+e);showToolBarAlert(ShortPixel.STATUS_RETRY,"");if(i&&typeof r["BulkPercent"]!=="undefined"){progressUpdate(r["BulkPercent"],r["BulkMsg"])}if(i&&r["Count"]>3){ShortPixel.bulkShowLengthyMsg(t,r["Filename"],r["CustomImageLink"])}setBulkTimer(5e3);break;case ShortPixel.STATUS_SEARCHING:console.log("Server response: "+e);ShortPixel.returnedStatusSearching++;if(ShortPixel.returnedStatusSearching>=2){jQuery(".bulk-notice-msg.bulk-searching").show()}setBulkTimer(2500);break;case ShortPixel.STATUS_MAINTENANCE:ShortPixel.bulkShowMaintenanceMsg("maintenance");setBulkTimer(6e4);break;case ShortPixel.STATUS_QUEUE_FULL:ShortPixel.bulkShowMaintenanceMsg("queue-full");setBulkTimer(6e4);break;default:ShortPixel.retry("Unknown status "+r["Status"]+". Retrying...");break}if(typeof t!="undefined"&&ShortPixel.isCustomImageId(t)){var l=jQuery(".list-overview .item-"+t);jQuery(l).find(".row-actions .action-optimize").remove();if(r["actions"]){jQuery(l).children(".actions").html(r["actions"])}}}},error:function(e){ShortPixel.retry(e.statusText)}})}function clearBulkProcessor(){ShortPixel.bulkProcessor=false;localStorage.bulkTime=Date.now();setBulkTimer(0);if(window.location.href.search("wp-short-pixel-bulk")>=0){localStorage.bulkPage=0}}function setCellMessage(e,r,t){var i=jQuery("#sp-msg-"+e);if(i.length>0){i.html("<div class='sp-column-actions'>"+t+"</div>"+"<div class='sp-column-info'>"+r+"</div>");i.css("color","")}i=jQuery("#sp-cust-msg-"+e);if(i.length>0){i.html("<div class='sp-column-info'>"+r+"</div>")}}function manualOptimization(e,r){setCellMessage(e,"<img src='"+ShortPixel.WP_PLUGIN_URL+"/res/img/loading.gif' alt='"+_spTr.loading+"' class='sp-loading-small'>Image waiting to be processed","");jQuery("li.shortpixel-toolbar-processing").removeClass("shortpixel-hide");jQuery("li.shortpixel-toolbar-processing").removeClass("shortpixel-alert");jQuery("li.shortpixel-toolbar-processing").addClass("shortpixel-processing");var t={action:"shortpixel_manual_optimization",image_id:e,cleanup:r};jQuery.ajax({type:"GET",url:ShortPixel.AJAX_URL,data:t,success:function(r){var t=JSON.parse(r);if(t["Status"]==ShortPixel.STATUS_SUCCESS){setBulkTimer(2e3);ShortPixel.BULK_SECRET=false}else{setCellMessage(e,typeof t["Message"]!=="undefined"?t["Message"]:_spTr.thisContentNotProcessable,"")}},error:function(r){t.action="shortpixel_check_status";jQuery.ajax({type:"GET",url:ShortPixel.AJAX_URL,data:t,success:function(r){var t=JSON.parse(r);if(t["Status"]!==ShortPixel.STATUS_SUCCESS){setCellMessage(e,typeof t["Message"]!=="undefined"?t["Message"]:_spTr.thisContentNotProcessable,"")}}})}})}function reoptimize(e,r){setCellMessage(e,"<img src='"+ShortPixel.WP_PLUGIN_URL+"/res/img/loading.gif' alt='"+_spTr.loading+"' class='sp-loading-small'>Image waiting to be reprocessed","");jQuery("li.shortpixel-toolbar-processing").removeClass("shortpixel-hide");jQuery("li.shortpixel-toolbar-processing").addClass("shortpixel-processing");var t={action:"shortpixel_redo",attachment_ID:e,type:r};jQuery.get(ShortPixel.AJAX_URL,t,(function(r){t=JSON.parse(r);if(t["Status"]==ShortPixel.STATUS_SUCCESS){setBulkTimer(2e3);ShortPixel.BULK_SECRET=false}else{$msg=typeof t["Message"]!=="undefined"?t["Message"]:_spTr.thisContentNotProcessable;setCellMessage(e,$msg,"");showToolBarAlert(ShortPixel.STATUS_FAIL,$msg)}}))}function optimizeThumbs(e){setCellMessage(e,"<img src='"+ShortPixel.WP_PLUGIN_URL+"/res/img/loading.gif' alt='"+_spTr.loading+"' class='sp-loading-small'>"+_spTr.imageWaitOptThumbs,"");jQuery("li.shortpixel-toolbar-processing").removeClass("shortpixel-hide");jQuery("li.shortpixel-toolbar-processing").addClass("shortpixel-processing");var r={action:"shortpixel_optimize_thumbs",attachment_ID:e};jQuery.get(ShortPixel.AJAX_URL,r,(function(t){r=JSON.parse(t);if(r["Status"]==ShortPixel.STATUS_SUCCESS){setBulkTimer(2e3);ShortPixel.BULK_SECRET=false}else{setCellMessage(e,typeof r["Message"]!=="undefined"?r["Message"]:_spTr.thisContentNotProcessable,"")}}))}function dismissShortPixelNotice(e){jQuery("#short-pixel-notice-"+e).hide();var r={action:"shortpixel_dismiss_notice",notice_id:e};jQuery.get(ShortPixel.AJAX_URL,r,(function(e){r=JSON.parse(e);if(r["Status"]==ShortPixel.STATUS_SUCCESS){console.log("dismissed")}}))}function dismissFileError(){jQuery(".shortpixel-alert").hide();var e={action:"shortpixel_dismissFileError"};jQuery.get(ShortPixel.AJAX_URL,e,(function(r){e=JSON.parse(r);if(e["Status"]==ShortPixel.STATUS_SUCCESS){console.log("dismissed")}}))}function PercentageAnimator(e,r){this.animationSpeed=10;this.increment=2;this.curPercentage=0;this.targetPercentage=r;this.outputSelector=e;this.animate=function(e){this.targetPercentage=e;setTimeout(PercentageTimer.bind(null,this),this.animationSpeed)}}function PercentageTimer(e){if(e.curPercentage-e.targetPercentage<-e.increment){e.curPercentage+=e.increment}else if(e.curPercentage-e.targetPercentage>e.increment){e.curPercentage-=e.increment}else{e.curPercentage=e.targetPercentage}jQuery(e.outputSelector).text(e.curPercentage+"%");if(e.curPercentage!=e.targetPercentage){setTimeout(PercentageTimer.bind(null,e),e.animationSpeed)}}function progressUpdate(e,r){var t=jQuery("#bulk-progress");if(t.length){jQuery(".progress-left",t).css("width",e+"%");jQuery(".progress-img",t).css("left",e+"%");if(e>24){jQuery(".progress-img span",t).html("");jQuery(".progress-left",t).html(e+"%")}else{jQuery(".progress-img span",t).html(e+"%");jQuery(".progress-left",t).html("")}jQuery(".bulk-estimate").html(r)}}function sliderUpdate(e,r,t,i,s){var o=jQuery(".bulk-slider div.bulk-slide:first-child");if(o.length===0){return}if(o.attr("id")!="empty-slide"){o.hide()}o.css("z-index",1e3);jQuery(".bulk-img-opt",o).attr("src","");if(typeof t==="undefined"){t=""}if(t.length>0){jQuery(".bulk-img-orig",o).attr("src","")}var a=o.clone();a.attr("id","slide-"+e);jQuery(".bulk-img-opt",a).attr("src",r);if(t.length>0){jQuery(".img-original",a).css("display","inline-block");jQuery(".bulk-img-orig",a).attr("src",t)}else{jQuery(".img-original",a).css("display","none")}jQuery(".bulk-opt-percent",a).html('<input type="text" class="dial" value="'+i+'"/>');jQuery(".bulk-slider").append(a);ShortPixel.percentDial("#"+a.attr("id")+" .dial",100);jQuery(".bulk-slider-container span.filename").html("&nbsp;&nbsp;"+s);if(o.attr("id")=="empty-slide"){o.remove();jQuery(".bulk-slider-container").css("display","block")}else{o.animate({left:o.width()+o.position().left},"slow","swing",(function(){o.remove();a.fadeIn("slow")}))}}function hideSlider(){jQuery(".bulk-slider-container").css("display","none")}function showStats(){var e=jQuery(".bulk-stats");if(e.length>0){}}function SPstringFormat(){var e=Array.prototype.slice.call(arguments);if(e.length===0)return;var r=e.shift();for(i=0;i<e.length;i++){r=r.replace(new RegExp("\\{"+i+"\\}","gm"),e[i])}return r}(function(e,r,t){r.SpioResize={image:{width:0,height:0},lag:2e3,step1:false,step2:false,step3:false,sizeRule:null,initialized:false,lastW:false,lastH:false,lastType:false};SpioResize.hide=function(){e(".presentation-wrap").css("opacity",0)};SpioResize.animate=function(e,r,t,i,s){e.animate(r,1e3,"swing",(function(){SpioResize.step3=setTimeout((function(){document.styleSheets[0].deleteRule(SpioResize.sizeRule);t.animate(i,1e3,"swing",(function(){SpioResize.sizeRule=document.styleSheets[0].insertRule(s)}))}),600)}))};SpioResize.run=function(){if(!SpioResize.initialized){var r=e(t);r.on("input change",'input[name="resizeWidth"], input[name="resizeHeight"]',(function(e){clearTimeout(SpioResize.change);SpioResize.changeDone=true;SpioResize.changeFired=false;SpioResize.change=setTimeout((function(){SpioResize.changeFired=true;SpioResize.run()}),1500)}));r.on("blur",'input[name="resizeWidth"], input[name="resizeHeight"]',(function(e){if(SpioResize.changeFired){return}clearTimeout(SpioResize.change);SpioResize.change=setTimeout((function(){SpioResize.run()}),1500)}));r.on("change",'input[name="resizeType"]',(function(e){SpioResize.run()}));SpioResize.initialized=true}var i=e("#width").val();var s=e("#height").val();if(!i||!s)return;var o=e("#resize_type_outer").is(":checked")?"outer":"inner";if(i===SpioResize.lastW&&s===SpioResize.lastH&&o===SpioResize.lastType){return}SpioResize.hide();SpioResize.lastW=i;SpioResize.lastH=s;SpioResize.lastType=o;var a=Math.round(120*Math.sqrt(i/s));var l=Math.round(120*Math.sqrt(s/i));var n=a/l;if(a>280){a=280;l=Math.round(280/n)}if(l>150){l=150;a=Math.round(150*n)}var u=15/8;var p=e("img.spai-resize-img");p.css("width","");p.css("height","");p.css("margin","0px");var c=e("div.spai-resize-frame");c.css("display","none");c.css("width",a+"px");c.css("height",l+"px");c.css("margin",Math.round((156-l)/2)+"px auto 0");clearTimeout(SpioResize.step1);clearTimeout(SpioResize.step2);clearTimeout(SpioResize.step3);p.stop();c.stop();if(SpioResize.sizeRule!==null){document.styleSheets[0].deleteRule(SpioResize.sizeRule);SpioResize.sizeRule=null}SpioResize.sizeRule=document.styleSheets[0].insertRule('.spai-resize-frame:after { content: "'+i+" × "+s+'"; }');c.addClass("spai-resize-frame");e(".presentation-wrap").animate({opacity:1},500,"swing",(function(){c.css("display","block");SpioResize.step2=setTimeout((function(){if(o=="outer"){if(u>n){var e={height:l+"px",margin:Math.round((160-l)/2)+"px 0px"};var r=l*u;var t={width:Math.round(r)+"px"};var d='.spai-resize-frame:after { content: "'+Math.round(r*i/a)+" × "+s+'"; }'}else{var e={width:a+"px",margin:Math.round((160-a/u)/2)+"px 0px"};var h=a/u;var t={height:Math.round(h)+"px",margin:Math.round((156-h)/2)+"px auto 0"};var d='.spai-resize-frame:after { content: "'+i+" × "+Math.round(h*i/a)+'"; }'}}else{if(u>n){var e={width:a,margin:Math.round((160-a/u)/2)+"px 0px"};var h=a/u;var t={height:Math.round(h)+"px",margin:Math.round((156-h)/2)+"px auto 0"};var d='.spai-resize-frame:after { content: "'+i+" × "+Math.round(h*i/a)+'"; }'}else{var e={height:l,margin:Math.round((160-l)/2)+"px 0px"};var r=l*u;var t={width:Math.round(r)+"px"};var d='.spai-resize-frame:after { content: "'+Math.round(r*i/a)+" × "+s+'"; }'}}SpioResize.animate(p,e,c,t,d)}),1e3)}))};e((function(){if(e("#resize").is("checked")){SpioResize.run()}}))})(jQuery,window,document);
res/scss/shortpixel-othermedia.scss CHANGED
@@ -124,6 +124,8 @@
124
  min-height: 60px;
125
  display: inline-block;
126
  border: 1px solid #ccc;
 
 
127
 
128
  img {
129
  max-width: 60px;
@@ -136,13 +138,39 @@
136
  {
137
  min-width: 105px;
138
  }
139
- .single-action.button-primary a
140
  {
141
- color: #fff;
142
- text-decoration: none;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
  }
144
  .sp-column-info {
145
- width: 400px;
 
146
  display: inline-block;
147
  @media(max-width: 1550px) {
148
  width: auto;
124
  min-height: 60px;
125
  display: inline-block;
126
  border: 1px solid #ccc;
127
+ background-size: cover;
128
+ background-position: center;
129
 
130
  img {
131
  max-width: 60px;
138
  {
139
  min-width: 105px;
140
  }
141
+ .single-action
142
  {
143
+ text-align: center;
144
+ .button-primary a
145
+ {
146
+ color: #fff;
147
+ text-decoration: none;
148
+ }
149
+ .button-smaller
150
+ {
151
+ width: 110px;
152
+ }
153
+ }
154
+
155
+ .multi-action-wrapper
156
+ {
157
+ display: flex;
158
+ flex-direction: column;
159
+ .single-action
160
+ {
161
+ display: inline-block;
162
+ margin: 8px 0;
163
+ a
164
+ {
165
+ display: block;
166
+
167
+ }
168
+ }
169
+
170
  }
171
  .sp-column-info {
172
+ max-width: 400px;
173
+ min-width: 250px;
174
  display: inline-block;
175
  @media(max-width: 1550px) {
176
  width: auto;
shortpixel-plugin.php CHANGED
@@ -3,6 +3,7 @@ namespace ShortPixel;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
  use ShortPixel\Notices\NoticeController as Notices;
5
 
 
6
 
7
  /** Plugin class
8
  * This class is meant for: WP Hooks, init of runtime and Controller Routing.
@@ -30,52 +31,55 @@ class ShortPixelPlugin
30
  $this->plugin_path = plugin_dir_path(SHORTPIXEL_PLUGIN_FILE);
31
  $this->plugin_url = plugin_dir_url(SHORTPIXEL_PLUGIN_FILE);
32
 
33
- $this->initRuntime(); // require controllers, and other needed classes
34
  //$this->initHooks();
35
- add_action('plugins_loaded', array($this, 'init'), 5); // early as possible init.
36
  }
37
 
38
- /*
39
- * Init the plugin after plugins_loaded hook. All of WP is there, all plugins.
40
- * This can't be loaded on construct time, because of model Loaders etc, with would result in loop.
41
- *
42
- */
43
- public function init()
44
  {
45
- if(isset($_REQUEST['noheader'])) {
46
- $this->is_noheaders = true;
47
- }
 
 
 
 
 
 
 
 
 
48
 
 
 
 
 
49
 
50
- /* Filter to prevent SPIO from starting. This can be used by third-parties to prevent init when needed for a particular situation.
51
- * Hook into plugins_loaded with priority lower than 5 */
52
- $init = apply_filters('shortpixel/plugin/init', true);
 
53
 
54
- if (! $init)
55
- {
56
- return;
57
- }
58
 
59
- $this->initHooks();
60
 
61
- // @todo Transitionary init for the time being, since plugin init functionality is still split between.
62
- global $shortPixelPluginInstance;
63
- $shortPixelPluginInstance = new \wpShortPixel();
64
- $this->shortPixel = $shortPixelPluginInstance;
65
 
66
- $front = new frontController();
67
- $admin = adminController::getInstance();
68
- $adminNotices = adminNoticesController::getInstance(); // Hook in the admin notices.
69
- $notices = Notices::getInstance(); // This hooks the ajax listener
 
 
70
 
71
  if ($this->settings()->autoMediaLibrary)
72
  {
73
  // compat filter to shortcircuit this in cases. (see external - visualcomposer)
74
  if (apply_filters('shortpixel/init/automedialibrary', true))
75
  {
76
- // $autoPng2Jpg = get_option('wp-short-pixel-png2jpg');
77
- //$autoMediaLibrary = get_option('wp-short-pixel-auto-media-library');
78
-
79
  if($this->settings()->autoMediaLibrary && $this->settings()->png2jpg) {
80
  add_action( 'wp_handle_upload', array($admin,'handlePng2JpgHook'));
81
  // @todo Document what plugin does mpp
@@ -116,13 +120,12 @@ class ShortPixelPlugin
116
  */
117
  public function env()
118
  {
119
- $this->loadModel('environment');
120
- return EnvironmentModel::getInstance();
121
  }
122
 
123
  public function fileSystem()
124
  {
125
- return new \ShortPixel\FileSystemController();
126
  }
127
 
128
  /** Create instance. This should not be needed to call anywhere else than main plugin file
@@ -138,34 +141,9 @@ class ShortPixelPlugin
138
 
139
  }
140
 
141
- /** Init Runtime. Loads all classes. */
142
- protected function initRuntime()
143
- {
144
- $plugin_path = plugin_dir_path(SHORTPIXEL_PLUGIN_FILE);
145
- foreach($this->paths as $short_path)
146
- {
147
- $directory_path = realpath($plugin_path . $short_path);
148
-
149
- if ($directory_path !== false)
150
- {
151
- $it = new \DirectoryIterator($directory_path);
152
- foreach($it as $file)
153
- {
154
- $file_path = $file->getRealPath();
155
- if ($file->isFile() && pathinfo($file_path, PATHINFO_EXTENSION) == 'php')
156
- {
157
- require_once($file_path);
158
- }
159
- }
160
- }
161
- }
162
-
163
- // Loads all subclassed controllers. This is used for slug-based discovery of which controller to run
164
- $controllerClass = \ShortPixelTools::namespaceit('ShortPixelController');
165
- $controllerClass::init();
166
- }
167
 
168
  /** Hooks for all WordPress related hooks
 
169
  */
170
  public function initHooks()
171
  {
@@ -173,6 +151,9 @@ class ShortPixelPlugin
173
  add_action('admin_enqueue_scripts', array($this, 'admin_scripts')); // admin scripts
174
  add_action('admin_enqueue_scripts', array($this, 'load_admin_scripts'), 90); // loader via route.
175
  // defer notices a little to allow other hooks ( notable adminnotices )
 
 
 
176
  }
177
 
178
  /** Hook in our admin pages */
@@ -304,21 +285,24 @@ class ShortPixelPlugin
304
  switch($plugin_page)
305
  {
306
  case 'wp-shortpixel-settings': // settings
307
- $controller = \shortPixelTools::namespaceit("SettingsController");
308
  break;
309
  case 'wp-short-pixel-custom': // other media
310
  /* $this->load_style('shortpixel-othermedia'); */
311
- $controller = \shortPixelTools::namespaceit('OtherMediaViewController');
312
  break;
313
  case 'wp-short-pixel-bulk':
314
  if ($template_part)
315
  {
316
- $partControl = ShortPixelController::findControllerbySlug($template_part);
317
- if ($partControl)
318
- $controller = $partControl;
 
 
 
319
  }
320
  else
321
- $controller = \shortPixelTools::namespaceit('BulkViewController');
322
  break;
323
  }
324
 
@@ -337,24 +321,6 @@ class ShortPixelPlugin
337
  }
338
  }
339
 
340
- /** Loads the Model Data Structure upon request
341
- *
342
- * @param string $name Name of the model
343
- */
344
- public function loadModel($name){
345
- $path = \ShortPixelTools::getPluginPath() . 'class/model/' . $name . '_model.php';
346
-
347
- if (! in_array($name, self::$modelsLoaded))
348
- {
349
- self::$modelsLoaded[] = $name;
350
- if(file_exists($path)){
351
- require_once($path);
352
- }
353
- else {
354
- Log::addError("Model $name could not be found");
355
- }
356
- }
357
- }
358
 
359
  // Get the plugin URL, based on real URL.
360
  public function plugin_url($urlpath = '')
@@ -407,10 +373,10 @@ class ShortPixelPlugin
407
 
408
  \WpShortPixelDb::checkCustomTables();
409
 
410
- adminNoticesController::resetCompatNotice();
411
- adminNoticesController::resetAPINotices();
412
- adminNoticesController::resetQuotaNotices();
413
- adminNoticesController::resetIntegrationNotices();
414
 
415
  \WPShortPixelSettings::onActivate();
416
 
@@ -422,14 +388,13 @@ class ShortPixelPlugin
422
  (! defined('SHORTPIXEL_NOFLOCK')) ? \ShortPixelQueue::resetPrio() : \ShortPixelQueueDB::resetPrio();
423
  \WPShortPixelSettings::onDeactivate();
424
 
425
- //$settingsControl = new \ShortPixel\SettingsController();
426
  $env = wpSPIO()->env();
427
 
428
  if (! $env->is_nginx)
429
  \WpShortPixel::alterHtaccess(true);
430
 
431
  // save remove.
432
- $fs = new FileSystemController();
433
  $log = $fs->getFile(SHORTPIXEL_BACKUP_FOLDER . "/shortpixel_log");
434
  if ($log->exists())
435
  $log->delete();
@@ -451,4 +416,7 @@ class ShortPixelPlugin
451
  }
452
  }
453
 
 
 
 
454
  } // class plugin
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
  use ShortPixel\Notices\NoticeController as Notices;
5
 
6
+ //use ShortPixel\Controller;
7
 
8
  /** Plugin class
9
  * This class is meant for: WP Hooks, init of runtime and Controller Routing.
31
  $this->plugin_path = plugin_dir_path(SHORTPIXEL_PLUGIN_FILE);
32
  $this->plugin_url = plugin_dir_url(SHORTPIXEL_PLUGIN_FILE);
33
 
 
34
  //$this->initHooks();
35
+ add_action('plugins_loaded', array($this, 'lowInit'), 5); // early as possible init.
36
  }
37
 
38
+
39
+ /** LowInit after all Plugins are loaded. Core WP function can still be missing. This should mostly add hooks */
40
+ public function lowInit()
 
 
 
41
  {
42
+ if(isset($_REQUEST['noheader'])) {
43
+ $this->is_noheaders = true;
44
+ }
45
+
46
+ /* Filter to prevent SPIO from starting. This can be used by third-parties to prevent init when needed for a particular situation.
47
+ * Hook into plugins_loaded with priority lower than 5 */
48
+ $init = apply_filters('shortpixel/plugin/init', true);
49
+
50
+ if (! $init)
51
+ {
52
+ return;
53
+ }
54
 
55
+ // @todo Transitionary init for the time being, since plugin init functionality is still split between.
56
+ global $shortPixelPluginInstance;
57
+ $shortPixelPluginInstance = new \wpShortPixel();
58
+ $this->shortPixel = $shortPixelPluginInstance;
59
 
60
+ $front = new Controller\FrontController();
61
+ $admin = Controller\AdminController::getInstance();
62
+ $adminNotices = Controller\AdminNoticesController::getInstance(); // Hook in the admin notices.
63
+ $notices = Notices::getInstance(); // This hooks the ajax listener
64
 
65
+ $this->initHooks();
 
 
 
66
 
 
67
 
68
+ add_action('admin_init', array($this, 'init'));
69
+ }
 
 
70
 
71
+
72
+ /** Mainline Admin Init. Tasks that can be loaded later should go here */
73
+ public function init()
74
+ {
75
+ $this->shortPixel->loadHooks();
76
+ $admin = Controller\AdminController::getInstance();
77
 
78
  if ($this->settings()->autoMediaLibrary)
79
  {
80
  // compat filter to shortcircuit this in cases. (see external - visualcomposer)
81
  if (apply_filters('shortpixel/init/automedialibrary', true))
82
  {
 
 
 
83
  if($this->settings()->autoMediaLibrary && $this->settings()->png2jpg) {
84
  add_action( 'wp_handle_upload', array($admin,'handlePng2JpgHook'));
85
  // @todo Document what plugin does mpp
120
  */
121
  public function env()
122
  {
123
+ return Model\EnvironmentModel::getInstance();
 
124
  }
125
 
126
  public function fileSystem()
127
  {
128
+ return new Controller\FileSystemController();
129
  }
130
 
131
  /** Create instance. This should not be needed to call anywhere else than main plugin file
141
 
142
  }
143
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
 
145
  /** Hooks for all WordPress related hooks
146
+ * For now hooks in the lowInit, asap.
147
  */
148
  public function initHooks()
149
  {
151
  add_action('admin_enqueue_scripts', array($this, 'admin_scripts')); // admin scripts
152
  add_action('admin_enqueue_scripts', array($this, 'load_admin_scripts'), 90); // loader via route.
153
  // defer notices a little to allow other hooks ( notable adminnotices )
154
+
155
+ add_action( 'shortpixel-thumbnails-before-regenerate', array( $this->shortPixel, 'thumbnailsBeforeRegenerateHook' ), 10, 1);
156
+ add_action( 'shortpixel-thumbnails-regenerated', array( $this->shortPixel, 'thumbnailsRegeneratedHook' ), 10, 4);
157
  }
158
 
159
  /** Hook in our admin pages */
285
  switch($plugin_page)
286
  {
287
  case 'wp-shortpixel-settings': // settings
288
+ $controller = 'ShortPixel\Controller\SettingsController';
289
  break;
290
  case 'wp-short-pixel-custom': // other media
291
  /* $this->load_style('shortpixel-othermedia'); */
292
+ $controller = 'ShortPixel\Controller\View\OtherMediaViewController';
293
  break;
294
  case 'wp-short-pixel-bulk':
295
  if ($template_part)
296
  {
297
+ switch($template_part)
298
+ {
299
+ case 'bulk-restore-all':
300
+ $controller = '\ShortPixel\Controller\View\BulkRestoreAll';
301
+ break;
302
+ }
303
  }
304
  else
305
+ $controller = '\ShortPixel\Controller\View\BulkViewController';
306
  break;
307
  }
308
 
321
  }
322
  }
323
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
324
 
325
  // Get the plugin URL, based on real URL.
326
  public function plugin_url($urlpath = '')
373
 
374
  \WpShortPixelDb::checkCustomTables();
375
 
376
+ Controller\AdminNoticesController::resetCompatNotice();
377
+ Controller\AdminNoticesController::resetAPINotices();
378
+ Controller\AdminNoticesController::resetQuotaNotices();
379
+ Controller\AdminNoticesController::resetIntegrationNotices();
380
 
381
  \WPShortPixelSettings::onActivate();
382
 
388
  (! defined('SHORTPIXEL_NOFLOCK')) ? \ShortPixelQueue::resetPrio() : \ShortPixelQueueDB::resetPrio();
389
  \WPShortPixelSettings::onDeactivate();
390
 
 
391
  $env = wpSPIO()->env();
392
 
393
  if (! $env->is_nginx)
394
  \WpShortPixel::alterHtaccess(true);
395
 
396
  // save remove.
397
+ $fs = new Controller\FileSystemController();
398
  $log = $fs->getFile(SHORTPIXEL_BACKUP_FOLDER . "/shortpixel_log");
399
  if ($log->exists())
400
  $log->delete();
416
  }
417
  }
418
 
419
+
420
+
421
+
422
  } // class plugin
shortpixel_api.php CHANGED
@@ -287,7 +287,6 @@ class ShortPixelAPI {
287
  }
288
  elseif ( isset($APIresponse[0]->Status->Message) ) {
289
  //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));
290
- Log::addTemp("Failed API REquest", $APIresponse);
291
  $err = array("Status" => self::STATUS_FAIL, "Code" => (isset($APIresponse[0]->Status->Code) ? $APIresponse[0]->Status->Code : self::ERR_UNKNOWN),
292
  "Message" => __('There was an error and your request was not processed.','shortpixel-image-optimiser')
293
  . " (" . wp_basename($APIresponse[0]->OriginalURL) . ": " . $APIresponse[0]->Status->Message . ")");
@@ -470,12 +469,11 @@ class ShortPixelAPI {
470
  return array("Status" => self::STATUS_SUCCESS);
471
  }
472
 
473
- //Log::addDebug('Backing The Up', array($mainPath, $PATHs));
474
-
475
  //$fullSubDir = str_replace(wp_normalize_path(get_home_path()), "", wp_normalize_path(dirname($itemHandler->getMeta()->getPath()))) . '/';
476
  //$SubDir = ShortPixelMetaFacade::returnSubDir($itemHandler->getMeta()->getPath(), $itemHandler->getType());
477
  $fullSubDir = ShortPixelMetaFacade::returnSubDir($mainPath);
478
  $source = $PATHs; //array with final paths for these files
 
479
  $fs = \wpSPIO()->filesystem();
480
 
481
  if( !file_exists(SHORTPIXEL_BACKUP_FOLDER) && ! ShortPixelFolder::createBackUpFolder() ) {//creates backup folder if it doesn't exist
@@ -487,15 +485,19 @@ class ShortPixelAPI {
487
 
488
  foreach ( $source as $fileID => $filePATH )//create destination files array
489
  {
490
- $destination[$fileID] = SHORTPIXEL_BACKUP_FOLDER . '/' . $fullSubDir . self::MB_basename($source[$fileID]);
 
 
 
 
491
  }
492
 
493
  //now that we have original files and where we should back them up we attempt to do just that
494
  if(is_writable(SHORTPIXEL_BACKUP_FOLDER))
495
  {
496
- foreach ( $destination as $fileID => $filePATH )
497
  {
498
- $destination_file = $fs->getFile($filePATH);
499
 
500
  if ( ! $destination_file->exists() )
501
  {
@@ -503,7 +505,7 @@ class ShortPixelAPI {
503
  $result = $source_file->copy($destination_file);
504
  if ( ! $result )
505
  {//file couldn't be saved in backup folder
506
- $msg = sprintf(__('Cannot save file <i>%s</i> in backup directory','shortpixel-image-optimiser'),self::MB_basename($source[$fileID]));
507
  return array("Status" => self::STATUS_FAIL, "Message" => $msg);
508
  }
509
 
@@ -688,7 +690,7 @@ class ShortPixelAPI {
688
  // The settings model.
689
  $settings = \wpSPIO()->settings();
690
 
691
- $fs = new \ShortPixel\FileSystemController();
692
 
693
  //Log::addDebug($tempFiles);
694
  // Check and Run all tempfiles. Move it to appropiate places.
287
  }
288
  elseif ( isset($APIresponse[0]->Status->Message) ) {
289
  //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));
 
290
  $err = array("Status" => self::STATUS_FAIL, "Code" => (isset($APIresponse[0]->Status->Code) ? $APIresponse[0]->Status->Code : self::ERR_UNKNOWN),
291
  "Message" => __('There was an error and your request was not processed.','shortpixel-image-optimiser')
292
  . " (" . wp_basename($APIresponse[0]->OriginalURL) . ": " . $APIresponse[0]->Status->Message . ")");
469
  return array("Status" => self::STATUS_SUCCESS);
470
  }
471
 
 
 
472
  //$fullSubDir = str_replace(wp_normalize_path(get_home_path()), "", wp_normalize_path(dirname($itemHandler->getMeta()->getPath()))) . '/';
473
  //$SubDir = ShortPixelMetaFacade::returnSubDir($itemHandler->getMeta()->getPath(), $itemHandler->getType());
474
  $fullSubDir = ShortPixelMetaFacade::returnSubDir($mainPath);
475
  $source = $PATHs; //array with final paths for these files
476
+
477
  $fs = \wpSPIO()->filesystem();
478
 
479
  if( !file_exists(SHORTPIXEL_BACKUP_FOLDER) && ! ShortPixelFolder::createBackUpFolder() ) {//creates backup folder if it doesn't exist
485
 
486
  foreach ( $source as $fileID => $filePATH )//create destination files array
487
  {
488
+ $file = $fs->getFile($filePATH);
489
+ $bkFilePath = $fs->getBackupDirectory($file);
490
+ $bkFile = $fs->getFile($bkFilePath . $file->getFileName() );
491
+
492
+ $destination[$fileID] = $bkFile; //SHORTPIXEL_BACKUP_FOLDER . '/' . $fullSubDir . self::MB_basename($source[$fileID]);
493
  }
494
 
495
  //now that we have original files and where we should back them up we attempt to do just that
496
  if(is_writable(SHORTPIXEL_BACKUP_FOLDER))
497
  {
498
+ foreach ( $destination as $fileID => $destination_file )
499
  {
500
+ //$destination_file = $fs->getFile($filePATH);
501
 
502
  if ( ! $destination_file->exists() )
503
  {
505
  $result = $source_file->copy($destination_file);
506
  if ( ! $result )
507
  {//file couldn't be saved in backup folder
508
+ $msg = sprintf(__('Cannot save file <i>%s</i> in backup directory','shortpixel-image-optimiser'),$destination_file->getFullPath() );
509
  return array("Status" => self::STATUS_FAIL, "Message" => $msg);
510
  }
511
 
690
  // The settings model.
691
  $settings = \wpSPIO()->settings();
692
 
693
+ $fs = \wpSPIO()->fileSystem();
694
 
695
  //Log::addDebug($tempFiles);
696
  // Check and Run all tempfiles. Move it to appropiate places.
wp-shortpixel-req.php DELETED
@@ -1,89 +0,0 @@
1
- <?php
2
- /*
3
- if(defined('SHORTPIXEL_DEBUG') && SHORTPIXEL_DEBUG === true) {
4
- require_once('shortpixel-debug.php');
5
- } else {
6
- define('SHORTPIXEL_DEBUG', false);
7
- } */
8
-
9
- // Debug. Hook as early as possible.
10
- //require_once('class/controller/controller.php');
11
- //require_once('class/controller/debug.php');
12
- //require_once('class/model/shortpixel-debug.php');
13
-
14
- // @todo wp-shortpixel-settings which depends on this model should be called when needed; in the model/ directory. That will be some work, so for now here.
15
- //require_once('class/shortpixel-model.php');
16
-
17
- //use ShortPixel\DebugItem as DebugItem;
18
- //use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
19
-
20
- /*if (! defined('SHORTPIXEL_DEBUG'))
21
- {
22
- define('SHORTPIXEL_DEBUG', false);
23
- } */
24
-
25
- // [BS] New plugin runtime.
26
- //require_once('shortpixel-plugin.php'); // loads runtime and needed classes.
27
- //new Shortpixel\ShortPixelPlugin();
28
-
29
- // @todo Temporary until main plugin file will receive it's unclutter. Require the things loaded by new plugin main
30
- /*if (! class_exists('ShortPixel\ShortPixelPlugin'))
31
- {
32
- require_once('class/shortpixel_queue.php');
33
- require_once('class/shortpixel-png2jpg.php');
34
- require_once('class/wp-short-pixel.php');
35
- require_once('class/wp-shortpixel-settings.php');
36
- require_once('class/wp-shortpixel-cloudflare-api.php');
37
- require_once('class/shortpixel-tools.php');
38
- require_once('class/controller/bulk-restore-all.php');
39
- } */
40
-
41
- //require_once('class/wp-short-pixel.php');
42
- //require_once('class/wp-shortpixel-settings.php');
43
- //require_once('class/wp-shortpixel-cloudflare-api.php');
44
- require_once('shortpixel_api.php');
45
- //require_once('class/shortpixel_queue.php');
46
- //require_once('class/shortpixel-png2jpg.php');
47
- //entities
48
- require_once('class/model/shortpixel-entity.php');
49
- require_once('class/model/shortpixel-meta.php');
50
- require_once('class/model/shortpixel-folder.php');
51
- //exceptions
52
- //require_once('class/model/sp-file-rights-exception.php');
53
- //database access
54
- require_once('class/db/shortpixel-db.php');
55
- require_once('class/db/wp-shortpixel-db.php');
56
- require_once('class/db/shortpixel-custom-meta-dao.php');
57
-
58
- require_once('class/db/wp-shortpixel-media-library-adapter.php');
59
- require_once('class/db/shortpixel-meta-facade.php');
60
- //view
61
- require_once('class/view/shortpixel_view.php');
62
-
63
- //require_once('class/shortpixel-tools.php');
64
-
65
- //require_once('class/controller/bulk-restore-all.php');
66
-
67
- require_once( ABSPATH . 'wp-admin/includes/image.php' );
68
- include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
69
-
70
- // for retro compatibility with WP < 3.5
71
- // @todo Move this to compatibility file.
72
- if( !function_exists('wp_normalize_path') ){
73
- function wp_normalize_path( $path ) {
74
- $path = str_replace( '\\', '/', $path );
75
- $path = preg_replace( '|(?<=.)/+|', '/', $path );
76
- if ( ':' === substr( $path, 1, 1 ) ) {
77
- $path = ucfirst( $path );
78
- }
79
- return $path;
80
- }
81
- }
82
-
83
- /*
84
- if ( !is_plugin_active( 'wpmandrill/wpmandrill.php' ) //avoid conflicts with some plugins
85
- && !is_plugin_active( 'wp-ses/wp-ses.php' )
86
- && !is_plugin_active( 'wordfence/wordfence.php') ) {
87
- require_once( ABSPATH . 'wp-includes/pluggable.php' );
88
- }
89
- */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-settings" target="_blank">Settings &gt; ShortPixel</a> page on how to start optimizing your image library and make your website load faster.
6
- * Version: 4.18.1
7
  * Author: ShortPixel
8
  * Author URI: https://shortpixel.com
9
  * Text Domain: shortpixel-image-optimiser
@@ -32,7 +32,7 @@ define('SHORTPIXEL_PLUGIN_DIR', __DIR__);
32
 
33
  //define('SHORTPIXEL_AFFILIATE_CODE', '');
34
 
35
- define('SHORTPIXEL_IMAGE_OPTIMISER_VERSION', "4.18.1");
36
  define('SHORTPIXEL_MAX_TIMEOUT', 10);
37
  define('SHORTPIXEL_VALIDATE_MAX_TIMEOUT', 15);
38
  define('SHORTPIXEL_BACKUP', 'ShortpixelBackups');
@@ -57,7 +57,7 @@ elseif($max_exec < 0) // some hosts like to set negative figures on this. Ignore
57
  $max_exec = 30;
58
  define('SHORTPIXEL_MAX_EXECUTION_TIME', $max_exec);
59
 
60
- // ** @todo For what is this needed? */
61
  require_once(SHORTPIXEL_PLUGIN_DIR . '/build/shortpixel/autoload.php');
62
 
63
  $sp__uploads = wp_upload_dir();
@@ -74,10 +74,21 @@ define('SHORTPIXEL_BACKUP_URL',
74
 
75
  define('SHORTPIXEL_MAX_EXECUTION_TIME2', 2 );
76
  define("SHORTPIXEL_MAX_RESULTS_QUERY", 30);
 
77
  //define("SHORTPIXEL_NOFLOCK", true); // don't use flock queue, can cause instability.
78
  //define("SHORTPIXEL_EXPERIMENTAL_SECURICACHE", true); // tries to add timestamps to URLS, to prevent hitting the cache.
79
  //define('SHORTPIXEL_SILENT_MODE', true); // no global notifications. Can lead to data damage. After setting, reactivate plugin.
80
 
 
 
 
 
 
 
 
 
 
 
81
  /* Function to reach core function of ShortPixel
82
  * Use to get plugin url, plugin path, or certain core controllers
83
  */
@@ -89,29 +100,19 @@ if (! function_exists("wpSPIO")) {
89
  }
90
  }
91
  // [BS] Start runtime here
92
- require_once(SHORTPIXEL_PLUGIN_DIR . '/wp-shortpixel-req.php'); // @todo should be incorporated here.
93
- require_once(SHORTPIXEL_PLUGIN_DIR . '/class/controller/controller.php');
94
- require_once(SHORTPIXEL_PLUGIN_DIR . '/class/shortpixel-model.php');
95
  require_once(SHORTPIXEL_PLUGIN_DIR . '/shortpixel-plugin.php'); // loads runtime and needed classes.
96
 
97
-
98
- if (! defined('SHORTPIXEL_DEBUG'))
99
- {
100
- define('SHORTPIXEL_DEBUG', false);
101
- }
102
- $log = \ShortPixel\ShortPixelLogger\ShortPixelLogger::getInstance();
103
- if (\ShortPixel\ShortPixelLogger\ShortPixelLogger::debugIsActive())
104
- $log->setLogPath(SHORTPIXEL_BACKUP_FOLDER . "/shortpixel_log");
105
-
106
- // Pre-Runtime Checks
107
- // @todo Better solution for pre-runtime inclusions of externals.
108
- // Should not be required here. wpspio initruntime loads externals
109
 
110
  wpSPIO(); // let's go!
111
 
112
-
113
-
114
-
115
  register_activation_hook( __FILE__, array('\ShortPixel\ShortPixelPlugin','activatePlugin') );
116
  register_deactivation_hook( __FILE__, array('\ShortPixel\ShortPixelPlugin','deactivatePlugin') );
117
  register_uninstall_hook(__FILE__, array('\ShortPixel\ShortPixelPlugin','uninstallPlugin') );
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-settings" target="_blank">Settings &gt; ShortPixel</a> page on how to start optimizing your image library and make your website load faster.
6
+ * Version: 4.19.0
7
  * Author: ShortPixel
8
  * Author URI: https://shortpixel.com
9
  * Text Domain: shortpixel-image-optimiser
32
 
33
  //define('SHORTPIXEL_AFFILIATE_CODE', '');
34
 
35
+ define('SHORTPIXEL_IMAGE_OPTIMISER_VERSION', "4.19.0");
36
  define('SHORTPIXEL_MAX_TIMEOUT', 10);
37
  define('SHORTPIXEL_VALIDATE_MAX_TIMEOUT', 15);
38
  define('SHORTPIXEL_BACKUP', 'ShortpixelBackups');
57
  $max_exec = 30;
58
  define('SHORTPIXEL_MAX_EXECUTION_TIME', $max_exec);
59
 
60
+ // ** Load the modules */
61
  require_once(SHORTPIXEL_PLUGIN_DIR . '/build/shortpixel/autoload.php');
62
 
63
  $sp__uploads = wp_upload_dir();
74
 
75
  define('SHORTPIXEL_MAX_EXECUTION_TIME2', 2 );
76
  define("SHORTPIXEL_MAX_RESULTS_QUERY", 30);
77
+
78
  //define("SHORTPIXEL_NOFLOCK", true); // don't use flock queue, can cause instability.
79
  //define("SHORTPIXEL_EXPERIMENTAL_SECURICACHE", true); // tries to add timestamps to URLS, to prevent hitting the cache.
80
  //define('SHORTPIXEL_SILENT_MODE', true); // no global notifications. Can lead to data damage. After setting, reactivate plugin.
81
 
82
+ // Starting logging services, early as possible.
83
+ if (! defined('SHORTPIXEL_DEBUG'))
84
+ {
85
+ define('SHORTPIXEL_DEBUG', false);
86
+ }
87
+ $log = \ShortPixel\ShortPixelLogger\ShortPixelLogger::getInstance();
88
+ if (\ShortPixel\ShortPixelLogger\ShortPixelLogger::debugIsActive())
89
+ $log->setLogPath(SHORTPIXEL_BACKUP_FOLDER . "/shortpixel_log");
90
+
91
+
92
  /* Function to reach core function of ShortPixel
93
  * Use to get plugin url, plugin path, or certain core controllers
94
  */
100
  }
101
  }
102
  // [BS] Start runtime here
103
+ //require_once(SHORTPIXEL_PLUGIN_DIR . '/wp-shortpixel-req.php'); // @todo should be incorporated here.
104
+ //require_once(SHORTPIXEL_PLUGIN_DIR . '/class/controller/controller.php');
105
+ //require_once(SHORTPIXEL_PLUGIN_DIR . '/class/shortpixel-model.php');
106
  require_once(SHORTPIXEL_PLUGIN_DIR . '/shortpixel-plugin.php'); // loads runtime and needed classes.
107
 
108
+ // PSR-4 package loader.
109
+ $loader = new ShortPixel\Build\PackageLoader();
110
+ $loader->setComposerFile(SHORTPIXEL_PLUGIN_DIR . '/class/plugin.json');
111
+ $loader->load(SHORTPIXEL_PLUGIN_DIR);
 
 
 
 
 
 
 
 
112
 
113
  wpSPIO(); // let's go!
114
 
115
+ // Activation / Deactivation services
 
 
116
  register_activation_hook( __FILE__, array('\ShortPixel\ShortPixelPlugin','activatePlugin') );
117
  register_deactivation_hook( __FILE__, array('\ShortPixel\ShortPixelPlugin','deactivatePlugin') );
118
  register_uninstall_hook(__FILE__, array('\ShortPixel\ShortPixelPlugin','uninstallPlugin') );