ShortPixel Image Optimizer - Version 4.11.0

Version Description

  • add bulk menu options: restore, reoptimize
  • filter the media list by optimization status
  • sort the media list by optimization status
  • do not display the Media Library (years) folders in the selection list for Other Media folders
  • force PNG 2 JPG conversion option
  • integrate with Gravity Forms
  • integrate with WP Stateless
  • add several actions and a filter (see the Actions and Filters section of the readme)
  • UI improvements to the settings page
  • fix the WPML compatibility when converting from PNG
  • fix SELECT IN image counting bug on rare cases and when >100k records in wp_postmeta
  • add option to delete ShortPixel settings and give feedback form on deactivate plugin
Download this release

Release Info

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

Code changes from version 4.10.5 to 4.11.0

changelog.txt ADDED
@@ -0,0 +1,644 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ = 4.8.10 =
2
+ * restore compatibility with PHP 5.2.x
3
+ * finding unlisted thumbnails - don't bother if dialog dismissed.
4
+ * force JS initialization after 10 sec. if external error on the document.load thread prevented it.
5
+ * onboarding - small text changes
6
+ * images added from the front-end sometimes have get_attached_file() null when hook called, delay the check and processing in this case, instead of marking as Optimization N/A.
7
+ * compatibility with s3-offload pro plugin
8
+ * fix to time estimate at bulk, which sometimes was displaying x hours and 60 minutes left.
9
+ * confirm popup when deleting backups.
10
+
11
+ = 4.8.9 =
12
+ * On some multisites installed in a subdirectory, the get_home_path() doesn't return the subdirectory, fallback to ABSPATH
13
+ * Sometimes images are not PNG even if they have .png extension. Don't try to convert them if imagecreatefrompng returns false.
14
+ * Get an aproximate row count for InnoDB tables to optimize the speed, but fallback to normal count(*) for MyISAM
15
+ * Fix several warnings ($thumbsMissing not an array, $found is not set, etc.)
16
+ * Return error message when folder could not be found, when adding other media folders
17
+ * More info to some API errors
18
+
19
+
20
+ = 4.8.8 =
21
+ * fix for trying to convert .png files that are not png actually
22
+ * fix for installs which don't have PHP GD - deactivate the png 2 jpg conversion
23
+ * fix for unserialize warnings
24
+ * improvements in bulk speed when passing through already optimized images.
25
+ * fix unsupported usage of const by third party punycode.js
26
+ * fix emails with new root domains like user@domain.store
27
+ * fix unsupported flock problem
28
+ * hidden button pending cleanup
29
+ * fix javascript not being able to generate the actions menu upon image being optimized while inside the image edit and displaying false instead
30
+
31
+ = 4.8.7 =
32
+ * fix bug of the resize minimum size alert not dismissing
33
+
34
+ = 4.8.6 =
35
+ * alert user when the plugin doesn't have rights to write to the uploads folder
36
+
37
+ = 4.8.5 =
38
+ * drop usage of the PHP session / wp_option for the priority queue - use a flat file instead.
39
+
40
+ = 4.8.4 =
41
+ * fix compatibility problem with WP 4.9 when editing source files with the new built-in editor
42
+ * fix restore converted PNGs in some situations
43
+ * fix some minor warnings
44
+ * refactor png2jpg functions in another class
45
+ * add compatibility with PHP 5.2
46
+ * generate WebP urls - account for settings with different scheme (http - https)
47
+
48
+ = 4.8.2 =
49
+ * fix minified punycode.js not generated because of ECMA6 not supported by YUI...
50
+
51
+ = 4.8.1 =
52
+ * fix notice that would not dismiss
53
+
54
+ = 4.8.0 =
55
+ * propose best plans options for optimizing all images
56
+ * option to optimize or not the found unlisted thumbs, alert the user about them.
57
+ * convert png to jpeg also when doing bulk if option set. Also search for usages of the image and replace the URLs in the content.
58
+ * fix compatbility problem with S3 Offload which caused sending two different sets of URLs for an image.
59
+ * trim site_url output - found a client case where it ended with a tab...
60
+ * all wp_options with autoload=no
61
+ * subscribe and get the API Key directly from the plugin
62
+ * minify all js and css files
63
+ * performance improvements for the picture tag generation
64
+ * retina versions of the icons
65
+ * fix compatibility with PHP 5.3 for using class:: inside closures
66
+ * fix "Optimize 0 thumbnails" in column menu generated from Javascript.
67
+
68
+ = 4.7.2 =
69
+ * fix wrong use of _ function which displayed warning
70
+
71
+ = 4.7.1 =
72
+ * Deactivate conversion from PNG to JPG for the previous images, until we find a solution for the posts that refer these images.
73
+ * Minor fix to bulk (last item in Media Library sometimes was left unoptimized)
74
+
75
+ = 4.7.0 =
76
+ * convert PNG images to JPG option
77
+ * action called upon optimizing an image: do_action('shortpixel_image_optimised', $post_id);
78
+ * monitor Other Media folders for changes every hour
79
+ * button to delete all ShortPixel metadata making ShortPixel forget it optimized the images in Media Library
80
+ * plugin images at @2x
81
+ * cleanup Other Media tables
82
+ * fix wp-options that would not save in some circumstances
83
+ * fix generate webp <picture> tags when post guids are absolute URLs and image URLs are changed, or when site has HTTP/HTTPS versions
84
+ * fix problem with AMP pages when generating the <picture> tags - when using AMP for WP plugin AMP pages are not changed.
85
+
86
+ = 4.6.0 =
87
+ * add a filter option to the Other Media table
88
+ * fixes in order to comply with WP plugin guidelines
89
+
90
+ = 4.5.5 =
91
+ * max thumbs constant - no more than this number of thumbs will be optimized in one pass
92
+ * fix problem with webp <picture> tag when using Fusion Builder
93
+ * really hide the API key everywhere when configured so
94
+
95
+ = 4.5.3 =
96
+
97
+ * fix Javascript error in bulk in some cases
98
+
99
+ = 4.5.2 =
100
+
101
+ * fix readme again
102
+
103
+ = 4.5.1 =
104
+
105
+ * fix readme
106
+
107
+ = 4.5.0 =
108
+
109
+ * replace img tags in front-end with picture tags, and include the webp images
110
+ * actions menu in Media Library
111
+ * option to compare the optimized (main) image with the original in Media Library
112
+
113
+ = 4.4.2 =
114
+
115
+ * fix wrong custom path in some cases
116
+
117
+ = 4.4.1 =
118
+
119
+ * fix warnings on PHP 7.1 for empty array settings.
120
+
121
+ = 4.4.0 =
122
+
123
+ * exclude images based on patterns or image sizes, exclude paths based on patterns
124
+ * avoid using basename as a fallback for non-UTF8 filenames but instead use own code (basename strips first character if it's not ASCII-128 - for example ISO/IEC 8859-2)
125
+ * processing spinning indicator in the admin top bar with CSS to display OK on all admin themes.
126
+
127
+ = 4.3.1 =
128
+
129
+ * hide API Key on single sites option ( define SHORTPIXEL_HIDE_API_KEY true in wp-config.php)
130
+ * fix for PHP installs on Linux that don't have the posix functions available
131
+ * show an alert when the plugin is no longer able to contact our servers (initially was alerting only before key validation)
132
+
133
+ = 4.3.0 =
134
+
135
+ * a new level of optimization intermediate between lossy and lossless: glossy
136
+ * bulk restore for Media Library
137
+ * fix warning when activating plugin in some situations
138
+ * empty backups button always visible (also when the backup option is unchecked)
139
+
140
+ = 4.2.9 =
141
+
142
+ * fix bug when thumbnails had numeric indexes in the sizes metadata array
143
+ * fix bug when bulk reoptimizing on some specific conditions
144
+
145
+ = 4.2.8 =
146
+
147
+ * fix bug when searching for thumbanils of files with same prefix
148
+ * fix bug when several successive images have all files missing
149
+
150
+ = 4.2.7 =
151
+
152
+ * fix bug when quota expires
153
+
154
+ = 4.2.6 =
155
+
156
+ * add the webp files as thumbs to the sizes array in metadata so they are automatically used by themes that use srcset.
157
+ * add option to optimize PDFs or not.
158
+ * seamless integration with WP/LR Sync plugin.
159
+ * gracefully ignore missing thumbs on disk when doing the optimization - just mark them as missing in the metadata.
160
+ * gracefully add Media Library files that are present on disk but not present in the image metadata (sizes array).
161
+ * option to dismiss the top toolbar ShortPixel alert when quota expired.
162
+ * compute the backup folder size asynchronously in order to speed up the settings page.
163
+ * editors/authors now are able to optimize/restore images from the Media Library list.
164
+ * handle internationalized domain names (punycode encoded).
165
+ * reset failed images from Custom Media when user launches a reprocessing of the images from Bulk.
166
+ * bugfixes
167
+
168
+ = 4.2.5 =
169
+
170
+ * fix for PHP7.1 fatal error when encountering corrupt metadata (wp_get_attachment_metadata returning empty string)
171
+
172
+ = 4.2.4 =
173
+
174
+ * fix not processing the images in the custom image folders if they had uppercase extensions
175
+ * remove the deprecated mcrypt calls.
176
+ * fix jQuery 3.x incompatibility when calling .unload() by using on("beforeunload" .. ) instead
177
+
178
+ = 4.2.3 =
179
+
180
+ * fix compatibility with older PHP by not using closure
181
+ * fix order of optimization of other media - by id not by added timestamp
182
+ * fix js error for manual optimization from js-generated button
183
+ * change call to obsolete get_currentuserinfo method
184
+
185
+ = 4.2.2 =
186
+
187
+ * offer to generate the API key directly from ShortPixel settings.
188
+ * alert and explain why is not allowed to specify a size less than 1024 when resizing.
189
+ * fix metadata for missing thumbs while optimizing.
190
+ * button Cleanup&Retry for images that have missing thumbnails.
191
+ * display what thumbnails are missing.
192
+ * for Windows platforms, do not check the local path to start with a slash
193
+ * fix optimization for images that contain '+' in the path
194
+ * use different styles for bulk boxes instead of the notice class
195
+ * properly display from the start the number of images to be optimized on the bulk button, when thumbnails are not selected.
196
+ * fix for sites that have admin urls with a doubled slash like wp-admin//uploads.php
197
+ * fix JS error on bulk finished page and new images optimizing
198
+ * fix bulk hangup when encountering a block of more than 900 wp_postmeta lines that are not image metadata.
199
+ * fix for cases when the wp-content path returned by wordpress contains backpath items (like wp/../wp-content)
200
+ * fix not saving advanced settings on "Save and go to Bulk" button.
201
+
202
+ = 4.2.1 =
203
+
204
+ * meta box in Media Library image editing form with informations about optimization status and results
205
+ * delete WebP images when image is deleted from Media Library
206
+ * change language domain to match the plugin slug in order to be automatically translatable on translate.wordpress.org.
207
+
208
+ = 4.2.0 =
209
+
210
+ * multilanguage support
211
+ * add retinas count to the ShortPixel Compression column
212
+ * add option not to automatically optimize Media Library images when added
213
+ * fix the size bug happening when optimizing main image then optimizing only thumbnails with resize active
214
+ * restrict log messages to SHORTPIXEL_DEBUG instead of WP_DEBUG
215
+ * fix compatibility with WP < 3.9
216
+ * fix compatibility with watermarking plugins like Image Watermark
217
+ * fix compatibility with WPBakery Visual Composer
218
+
219
+ = 4.1.7 =
220
+
221
+ * fix backup thumbnail js error
222
+
223
+ = 4.1.6 =
224
+
225
+ * fix processing for sites with caps path like http://mysite.com/My-Path/
226
+ * fix WebP generation for images that are already optimized
227
+
228
+ = 4.1.5 =
229
+
230
+ * readme updates - links to informative articles
231
+ * show that WebP format is created free of charge
232
+ * hide the Advanced settings tab completely before API Key validation
233
+ * fix indefinite retries when wrong image size
234
+ * restrict debug mode to ShortPixel own define
235
+
236
+ = 4.1.4 =
237
+
238
+ * fix path problems on multisite on Windows
239
+
240
+ = 4.1.3 =
241
+
242
+ * fix debug mode too intrusive
243
+
244
+ = 4.1.2 =
245
+
246
+ * bulk slider fix
247
+
248
+ = 4.1.1 =
249
+
250
+ * settings fix
251
+
252
+ = 4.1.0 =
253
+
254
+ * retina images support - optimize also retina images
255
+ * WebP support - option to generate also WebP images
256
+ * optimize other media folders also from the root of the site, not only in wp-content
257
+ * restore and re-optimize other media images
258
+ * resize options - defined rectangle to be contained in the resized image or the resized image to contain the defined rectangle
259
+
260
+ = 4.0.2 =
261
+
262
+ * fix compatibility with PHP 5.2
263
+ * fix for URLs like domain.com/CamelCasePath
264
+
265
+ = 4.0.1 =
266
+
267
+ * Optimize from the front-end option
268
+
269
+ = 4.0.0 =
270
+
271
+ * Custom folders optimization
272
+ * NextGen galleries optimization
273
+
274
+ = 3.3.4 =
275
+
276
+ * Fix Settings Resources display
277
+ * Add user and password authentication option for downloading images
278
+ * fix for PHP installs that lack utf8_encode function
279
+ * retry from the optimize Ajax post when server sends a 500 error
280
+
281
+ = 3.3.3 =
282
+
283
+ * Compatibility with WPML Media plugin
284
+ * Fix ListView link on multisites
285
+ * Fix for server configurations that have max_execution_time = 0
286
+
287
+ = 3.3.2 =
288
+
289
+ * fix for PHP installs that are missing the mcrypt functions
290
+
291
+ = 3.3.1 =
292
+
293
+ * small fix to the quota revalidation process
294
+
295
+ = 3.3.0 =
296
+
297
+ * reoptimize lossless/lossy
298
+ * optimize thumbs for images already optimized
299
+ * compatibility with WPML
300
+
301
+ = 3.2.1 =
302
+
303
+ * old PHP compatibility fix
304
+
305
+ = 3.2.0 =
306
+
307
+ * ICC color profile is always preserved.
308
+ * possibility to hide the API key in a multisite install.
309
+ * detection of best protocol to use: https / http.
310
+
311
+ = 3.1.9 =
312
+
313
+ * option to keep the EXIF data and ICC profile.
314
+ * more explanations on settings.
315
+
316
+ = 3.1.8 =
317
+
318
+ * fix reloading bulk page on quota used up
319
+
320
+ = 3.1.7 =
321
+
322
+ * bugfixes
323
+
324
+ = 3.1.6 =
325
+
326
+ * look and feel improvements
327
+
328
+ = 3.1.5 =
329
+
330
+ * longer timeout for the API Key validation postback
331
+
332
+ = 3.1.4 =
333
+
334
+ * fix bug in bulk processing
335
+
336
+ = 3.1.3 =
337
+
338
+ * fix problems with activating the keys on some systems that do not allow post requests
339
+
340
+ = 3.1.2 =
341
+
342
+ * bulk runs now only on media and post pages
343
+ * settings page redesign
344
+ * client site access test from our servers when activating the API key and warn if site not accessible
345
+ * fix last image sometimes unprocessed by bulk
346
+ * fix progress bar to advance when skipping images
347
+
348
+ = 3.1.1 =
349
+
350
+ * fix calculation of displayed counters of images to be processed on bulk start
351
+ * fix restore option that appeared wrongly sometimes - thanks to Bogdan Günther @ http://medianotions.de
352
+
353
+ = 3.1.0 =
354
+
355
+ * rescale big images option - thanks to Bogdan Günther @ http://medianotions.de
356
+ * referral system
357
+ * show how many thumbs are optimized for each image
358
+ * fix the Visual Composer conflict - thanks to Andy Adams - www.certainlysoftware.com
359
+
360
+ = 3.0.8 =
361
+
362
+ * fix issue with files in /tmp dir that weren't deleted in certain cases, issue noted by Daniel - http://germangoogleguy.com
363
+
364
+ = 3.0.7 =
365
+
366
+ * Affiliate codes
367
+ * Solve conflict with wp-ses plugin
368
+ * skip image on _FAIL message
369
+ * mixed content warning fix
370
+
371
+ = 3.0.6 =
372
+
373
+ * Optimized bulk processor behaviour when navigating from one admin page to another.
374
+ * Improved some explanatory texts.
375
+
376
+ = 3.0.5 =
377
+
378
+ * different bug fixes
379
+
380
+ = 3.0.2 =
381
+
382
+ * Progress bar improvements
383
+
384
+ = 3.0.0 =
385
+
386
+ * Major update
387
+ * when validating the API Key on a multisite a message with instructions on how to add the API Key in wp-config.php is displayed
388
+ * check when an optimized image cannot be saved and stop bulk processing (if running)
389
+ * restore backup is not displayed when option is not activated
390
+ * change image status in the Media Library ShortPixel Compression column imediately after the image is reduced, not only after reloading the page. Add spinner to the "Image waiting to be processed" status.
391
+ * images with relative URLs are converted to absolute URL so they can be processed by the plugin
392
+ * proper handling of images with non-standard latin chars inside
393
+ * better average compression computation
394
+ * rewritten handleImageUpload
395
+ * removed MUST_HAVE_KEY
396
+ * changed isProcessable
397
+ * and others :)
398
+
399
+ = 2.1.9 =
400
+
401
+ * Check if the server address is localhost and warn when activating the API key.
402
+ * Quota exceeded now displays a link to billing page
403
+
404
+ = 2.1.8 =
405
+
406
+ * improved texts/explanations for different sections
407
+ * added extra option to convert CMYK to RGB for further size reduction
408
+ * display credits for one time payments as well
409
+ * API Key can also be configured in wp-config.php like this: define('SHORTPIXEL_API_KEY', 'YOUR_API_KEY'); Useful for multisite installations
410
+
411
+
412
+ = 2.1.7 =
413
+ * improved checking and reporting of firewall restriction on client side
414
+ * optimized files are saved in the right location when dealing with WP Multisite
415
+ * updated screenshots
416
+
417
+ = 2.1.6 =
418
+
419
+ * improved login procedure upon quota is exceeded
420
+ * when quota is exceeded user can more easily increase it
421
+ * extra warning regarding the number of thumbs available additionally to main images
422
+ * improved counting of images
423
+ * check if https works if not use http for communications with the API
424
+ * better handling of error messages when API service cannot be contacted
425
+
426
+ = 2.1.5 =
427
+
428
+ * visiting Settings/ShortPixel now resets the Queue flag
429
+ * when plgin's API Key cannot be validated the JS script that calls admin-ajax.php is stopped
430
+ * return meaningful message on Media Library listing when API Key is not valid
431
+ * extra check for API Key validation
432
+
433
+ = 2.1.4 =
434
+
435
+ * fixed global variable issue for some variables
436
+ * fixed API Key validation that occurred for some of the hosting providers out there when HTTPS was used
437
+
438
+ = 2.1.3 =
439
+
440
+ * when backup wasn't activated the processed files weren't put in the right place
441
+ * removed forgotten debug message
442
+ * changed "optimised" to "optimized". Welcome USA :)
443
+ * improved bulk handling and also "cancel" and "resume" options
444
+ * fixed conflict with wpmandrill on wp_mail function
445
+
446
+ = 2.1.2 =
447
+
448
+ * fixed condition that hanged bulk processing sometimes
449
+ * added "Reduced by" text
450
+ * more useful wrong/missing API Key message
451
+ * test if a backup dir can be created upon plugin validation
452
+ * added alert when a file couldn't have been overwritten
453
+ * added alert when a file cannot be saved in backup dir
454
+ * added Quota on API Calls functionality
455
+ * added resume bulk processing feature
456
+
457
+ = 2.1.1 =
458
+
459
+ * fixed condition in function that validates content by extension
460
+ * fixed bug that prevented files uploaded directly in /uploads dir to be properly processed/saved
461
+ * retry link added besides files that failed to be optimized due to different reasons
462
+
463
+ = 2.1.0 =
464
+
465
+ * speedier file download from API resource
466
+ * SQL changed to use less CPU intensive queries
467
+ * improved BULK processing logic, faster results
468
+ * different small fixes & improvements
469
+ * skip processed images when running bulk processing
470
+
471
+
472
+ = 2.0.8 =
473
+
474
+ * improved logic for processed files to be downloaded every time
475
+ * sometimes the processing script stopped before finishing all the files to be optimized, fixed
476
+ * improved processing speed for bulk processing
477
+
478
+ = 2.0.7 =
479
+
480
+ * fixed issue with "missing" images
481
+ * save plugin version for easier debugging
482
+ * list mode is set for media library for first time run
483
+ * fixed bug that prevented backup-ed files to remove when the original was removed
484
+
485
+ = 2.0.6 =
486
+
487
+ * different small fixes
488
+
489
+ = 2.0.5 =
490
+
491
+ * small improvement to make the optimization of newly added images faster.
492
+ * fixed condition when the PDF files weren't processed
493
+ * different improvements
494
+
495
+ = 2.0.4 =
496
+
497
+ * fixed recursive backup directory size counter
498
+ * added backup with subdirectory structure to handle many files
499
+ * empty backup can handle subdirectories & sets the right flag for backup restore
500
+ * latest images are optimized first
501
+ * check for missing images on disk but still linked in DB
502
+
503
+ = 2.0.3 =
504
+
505
+ * added extra check for bad server responses
506
+ * 10 files/post request for file processing
507
+ * updated error codes according to API v2
508
+ * updated description
509
+
510
+ = 2.0.2 =
511
+
512
+ * added more tags so we better describe newest features
513
+
514
+ = 2.0.1 =
515
+
516
+ * some improvements to bulk processing
517
+ * PDF files are also optimized now
518
+ * fixed a thumb processing bug that caused extra API requests
519
+
520
+ = 2.0.0 =
521
+
522
+ * SP plugin uses API v2 and the processing speed is significantly improved
523
+
524
+ = 1.6.10 =
525
+
526
+ * Corrected a bug affecting option saving for some of the users.
527
+
528
+ = 1.6.9 =
529
+
530
+ * Optimize now option only appears when the image wasn't optimized
531
+
532
+ = 1.6.8 =
533
+
534
+ * Bulk Processing optimized to skip images that were already optimized with the same options when Bulk Processing is run multiple times
535
+ * changed the place where original (backup) files are stored
536
+ * extra check for missing(expired) processed images
537
+
538
+ = 1.6.7 =
539
+
540
+ * extra check for exif_imagetype function
541
+
542
+ = 1.6.6 =
543
+
544
+ * changed method from GET to POST for API Key validation
545
+ * bulk optimization text update
546
+
547
+ = 1.6.5 =
548
+
549
+ * plugin tested for WP 4.1
550
+
551
+ = 1.6.4 =
552
+
553
+ * API validation URL changed to v1
554
+
555
+ = 1.6.3 =
556
+
557
+ * fallback to http if plugin activation fails for https
558
+ * added error mesage API Key validation fail
559
+
560
+ = 1.6.2 =
561
+
562
+ * extra check for images that return 3xx/4xx codes to be ignored
563
+ * API Key validation (error) message is returned to user
564
+ * error messages for images are displayed in the "ShortPixel Compression" column
565
+
566
+ = 1.6.1 =
567
+
568
+ * fixed small upload glitch
569
+ * added succes message upon bulk processing completion
570
+ * improved image backup
571
+ * lossy option by default upon plugin installation
572
+
573
+ = 1.6.0 =
574
+
575
+ * images' requests for optimization are sent for all sizes upon image upload in media gallery
576
+ * non-image (e.g. PDF files) are ignored now @ bulk processing
577
+ * bulk optimization improved & some bugs fixed.
578
+ * FAQ/Description small changes
579
+
580
+ = 1.5.1 =
581
+
582
+ * readme changes
583
+
584
+ = 1.5.0 =
585
+
586
+ * pictures are removed from backup as well when deleted
587
+ * restore backup warning/error fixed
588
+ * fixed useless/bad AJAX requests that occured sometimes
589
+ * added user agent to API Key validation for debugging purposes
590
+ * Bulk Processing was freezing for some users, fixed this + added Cancel button
591
+
592
+ = 1.4.1 =
593
+
594
+ * optimize again overwrote the original image, fixed
595
+ * fixed restore errors
596
+ * changes to FAQ/Description texts
597
+
598
+ = 1.4.0 =
599
+
600
+ * Bulk image processing improved so it can optimize all the images in background while admin page is open
601
+ * small changes in readme.txt descrption
602
+
603
+ = 1.3.5 =
604
+
605
+ * fixed broken link in settings page
606
+ * updated FAQ
607
+ * description updated
608
+
609
+ = 1.3.2 =
610
+
611
+ * fixed missing action link @ Bulk Processing
612
+ * added more screenshots
613
+
614
+ = 1.3.1 =
615
+
616
+ * possible fix for API key validation failing
617
+ * added backup and restore for images that are processed with shortpixel
618
+ * optimize now feature on Media Library
619
+
620
+ = 1.0.6 =
621
+
622
+ * bulk processing runs in background now.
623
+
624
+ = 1.0.5 =
625
+
626
+ * extra check for the converted images to be safely copied from ShortPixel
627
+
628
+ = 1.0.4 =
629
+
630
+ * corrections and additions to readme.txt and wp-shortpixel.php
631
+
632
+ = 1.0.3 =
633
+
634
+ * minor bug fixes
635
+
636
+ = 1.0.2 =
637
+
638
+ * Updated Bulk editing to run in background
639
+ * Updated default options
640
+ * Added notifications on activation
641
+
642
+ = 1.0 =
643
+
644
+ * First working version
class/db/shortpixel-meta-facade.php CHANGED
@@ -192,8 +192,12 @@ class ShortPixelMetaFacade {
192
  unset($rawMeta['ShortPixel']['ErrCode']);
193
  }
194
 
195
- wp_update_attachment_metadata($this->ID, $rawMeta);
196
- $this->rawMeta = $rawMeta;
 
 
 
 
197
  }
198
  }
199
  }
@@ -624,12 +628,12 @@ class ShortPixelMetaFacade {
624
  return implode('/', $pathArr) . '/';
625
  }
626
 
627
- public static function isMediaSubfolder($path) {
628
  $uploadDir = wp_upload_dir();
629
  $uploadBase = $uploadDir["basedir"];
630
  $uploadPath = $uploadDir["path"];
631
  //contains the current media upload path
632
- if(ShortPixelFolder::checkFolderIsSubfolder($uploadPath, $path)) {
633
  return true;
634
  }
635
  //contains one of the year subfolders of the media library
@@ -645,10 +649,15 @@ class ShortPixelMetaFacade {
645
  return false;
646
  }
647
 
648
- public function doActions() {
649
  if($this->getType() == self::MEDIA_LIBRARY_TYPE) {
650
  do_action( 'shortpixel_image_optimised', $this->getId() );
651
  }
 
652
 
 
 
 
 
653
  }
654
  }
192
  unset($rawMeta['ShortPixel']['ErrCode']);
193
  }
194
 
195
+ wp_update_attachment_metadata($_ID, $rawMeta);
196
+ update_post_meta($_ID, '_shortpixel_status', $this->meta->getStatus());
197
+
198
+ if($_ID == $this->ID) {
199
+ $this->rawMeta = $rawMeta;
200
+ }
201
  }
202
  }
203
  }
628
  return implode('/', $pathArr) . '/';
629
  }
630
 
631
+ public static function isMediaSubfolder($path, $orParent = true) {
632
  $uploadDir = wp_upload_dir();
633
  $uploadBase = $uploadDir["basedir"];
634
  $uploadPath = $uploadDir["path"];
635
  //contains the current media upload path
636
+ if($orParent && ShortPixelFolder::checkFolderIsSubfolder($uploadPath, $path)) {
637
  return true;
638
  }
639
  //contains one of the year subfolders of the media library
649
  return false;
650
  }
651
 
652
+ public function optimizationSucceeded() {
653
  if($this->getType() == self::MEDIA_LIBRARY_TYPE) {
654
  do_action( 'shortpixel_image_optimised', $this->getId() );
655
  }
656
+ }
657
 
658
+ public function optimizationStarted() {
659
+ if($this->getType() == self::MEDIA_LIBRARY_TYPE) {
660
+ do_action( 'shortpixel_start_image_optimisation', $this->getId() );
661
+ }
662
  }
663
  }
class/db/wp-shortpixel-media-library-adapter.php CHANGED
@@ -45,6 +45,12 @@ class WpShortPixelMediaLbraryAdapter {
45
  $filesList= $wpdb->get_results("SELECT * FROM " . $wpdb->prefix . "postmeta
46
  WHERE post_id IN (" . implode(',', $idInfo->ids) . ")
47
  AND ( meta_key = '_wp_attached_file' OR meta_key = '_wp_attachment_metadata' )");
 
 
 
 
 
 
48
 
49
  foreach ( $filesList as $file )
50
  {
@@ -291,15 +297,16 @@ class WpShortPixelMediaLbraryAdapter {
291
  return $thumbs;
292
  }
293
 
294
- protected static function getOptimalChunkSize() {
295
  global $wpdb;
296
  //get an aproximate but fast row count.
297
- $row = $wpdb->get_results("EXPLAIN SELECT count(*) from " . $wpdb->prefix . "posts");
298
  if(isset($row['rows'])) {
299
  $cnt = $row['rows'];
300
  } else {
301
- $cnt = $wpdb->get_results("SELECT count(*) posts FROM " . $wpdb->prefix . "posts");
302
  }
 
303
  $posts = isset($cnt) && count($cnt) > 0 ? $cnt[0]->posts : 0;
304
  if($posts > 100000) {
305
  return 10000;
45
  $filesList= $wpdb->get_results("SELECT * FROM " . $wpdb->prefix . "postmeta
46
  WHERE post_id IN (" . implode(',', $idInfo->ids) . ")
47
  AND ( meta_key = '_wp_attached_file' OR meta_key = '_wp_attachment_metadata' )");
48
+
49
+ //in one case this query returned zero items but if fewer items in the IDs list, it worked so apply this workaround:
50
+ if($limit > 1000 && count($filesList) == 0) {
51
+ $limit = 1000;
52
+ continue;
53
+ }
54
 
55
  foreach ( $filesList as $file )
56
  {
297
  return $thumbs;
298
  }
299
 
300
+ public static function getOptimalChunkSize($table = 'posts') {
301
  global $wpdb;
302
  //get an aproximate but fast row count.
303
+ $row = $wpdb->get_results("EXPLAIN SELECT count(*) from " . $wpdb->prefix . $table);
304
  if(isset($row['rows'])) {
305
  $cnt = $row['rows'];
306
  } else {
307
+ $cnt = $wpdb->get_results("SELECT count(*) posts FROM " . $wpdb->prefix . $table);
308
  }
309
+ //json_encode($wpdb->get_results("SHOW VARIABLES LIKE 'max_allowed_packet'"));
310
  $posts = isset($cnt) && count($cnt) > 0 ? $cnt[0]->posts : 0;
311
  if($posts > 100000) {
312
  return 10000;
class/shortpixel-png2jpg.php CHANGED
@@ -20,6 +20,8 @@ class ShortPixelPng2Jpg {
20
  $transparent = 0;
21
  $transparent_pixel = $img = $bg = false;
22
 
 
 
23
  if (!file_exists($image) || ord(file_get_contents($image, false, null, 25, 1)) & 4) {
24
  $transparent = 1;
25
  } else {
@@ -156,9 +158,14 @@ class ShortPixelPng2Jpg {
156
  $image = $params['file'];
157
  WPShortPixel::log("Convert Media PNG to JPG on upload: {$image}");
158
 
159
- $ret = $this->canConvertPng2Jpg($image);
160
- if ($ret['notTransparent']) {
161
- $ret = $this->doConvertPng2Jpg($params, $this->_settings->backupImages, false, $ret['img']);
 
 
 
 
 
162
  if($ret->unlink) @unlink($ret->unlink);
163
  $paramsC = $ret->params;
164
  if($paramsC['type'] == 'image/jpeg') {
@@ -185,10 +192,12 @@ class ShortPixelPng2Jpg {
185
  * @param type $ID
186
  * @return string
187
  */
188
- public function checkConvertMediaPng2Jpg($meta, $ID) {
189
 
 
 
190
  if(!$this->_settings->png2jpg || !isset($meta['file']) || strtolower(substr($meta['file'], -4)) !== '.png') {
191
- return $meta;
192
  }
193
 
194
  WPShortPixel::log("Send to processing: Convert Media PNG to JPG #{$ID} META: " . json_encode($meta));
@@ -213,15 +222,19 @@ class ShortPixelPng2Jpg {
213
  $meta['ShortPixel']['ErrCode'] = ShortPixelAPI::ERR_PNG2JPG_MEMORY;
214
  wp_update_attachment_metadata($ID, $meta);
215
 
216
- $retC = $this->canConvertPng2Jpg($imagePath);
217
- if (!$retC['notTransparent']) {
 
 
 
 
 
218
  WPShortPixel::log("PNG2JPG not a PNG");
219
  return $meta; //cannot convert it
220
  }
221
 
222
  WPShortPixel::log(" CONVERTING MAIN: $imagePath");
223
- $retMain = $this->doConvertPng2Jpg(array('file' => $imagePath, 'url' => false, 'type' => 'image/png'), $this->_settings->backupImages, false, $retC['img']);
224
- WPShortPixel::log(" CONVERTED MAIN: " . json_encode($retMain));
225
  WPShortPixel::log("PNG2JPG doConvert Main RETURNED " . json_encode($retMain));
226
  $ret = $retMain->params;
227
  $toUnlink = array();
@@ -245,10 +258,8 @@ class ShortPixelPng2Jpg {
245
  WPShortPixel::log(" SET IMAGE PATH: $imagePath");
246
 
247
  //conversion succeeded for the main image, update meta and proceed to thumbs. (It could also not succeed if the converted file is not smaller)
248
- $meta['file'] = str_replace($basePath, '', $ret['file']);
249
- $meta['type'] = 'image/jpeg';
250
- update_attached_file($ID, $meta['file']);
251
- wp_update_attachment_metadata($ID, $meta);
252
 
253
  $originalSizes = isset($meta['sizes']) ? $meta['sizes'] : array();
254
  foreach($meta['sizes'] as $size => $info) {
@@ -260,18 +271,16 @@ class ShortPixelPng2Jpg {
260
  if ($rett['type'] == 'image/jpeg') {
261
  $toUnlink[] = $retThumb->unlink;
262
  WPShortPixel::log("PNG2JPG thumb is jpg");
263
- $meta['sizes'][$size]['file'] = wp_basename($rett['file']);
264
- $meta['sizes'][$size]['mime-type'] = 'image/jpeg';
265
  $pngSize += $rett['png_size'];
266
  $jpgSize += $rett['jpg_size'];
267
  WPShortPixel::log("PNG2JPG total PNG size: $pngSize total JPG size: $jpgSize");
268
  $originalSizes[$size]['file'] = wp_basename($rett['file'], '.jpg') . '.png';
269
  WPShortPixel::log("PNG2JPG thumb original: " . $originalSizes[$size]['file']);
270
  $toReplace[$baseUrl . $baseRelPath . $info['file']] = $baseUrl . $baseRelPath . wp_basename($rett['file']);
271
- wp_update_attachment_metadata($ID, $meta);
 
272
  }
273
  }
274
- WPShortPixel::log("ORIGINAL SIZESSSS: " . json_encode($originalSizes));
275
  $meta['ShortPixelPng2Jpg'] = array('originalFile' => $imagePath, 'originalSizes' => $originalSizes, 'originalSizes2' => $originalSizes,
276
  'backup' => $this->_settings->backupImages,
277
  'optimizationPercent' => round(100.0 * (1.00 - $jpgSize / $pngSize)));
@@ -290,6 +299,42 @@ class ShortPixelPng2Jpg {
290
  return $meta;
291
  }
292
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
293
  /**
294
  * taken from Velvet Blues Update URLs plugin
295
  * @param $options
@@ -316,18 +361,14 @@ class ShortPixelPng2Jpg {
316
  WPShortPixel::log("PNG2JPG update URLS on $option ");
317
  if( $option == 'custom' ){
318
  $n = 0;
319
- $row_count = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->postmeta" );
320
- $page_size = 10000;
321
- $pages = ceil( $row_count / $page_size );
322
-
323
- for( $page = 0; $page < $pages; $page++ ) {
324
- $start = $page * $page_size;
325
- $pmquery = "SELECT * FROM $wpdb->postmeta WHERE meta_value <> '' AND meta_key <> '_wp_attachment_metadata' AND meta_key <> '_wp_attached_file' LIMIT $start, $page_size";
326
- $items = $wpdb->get_results( $pmquery );
327
  foreach( $items as $item ) {
328
  $value = $item->meta_value;
329
- if( trim($value) == '' )
330
  continue;
 
331
 
332
  $edited = (object)array('data' => $value, 'replaced' => false);
333
  foreach($map as $oldurl => $newurl) {
20
  $transparent = 0;
21
  $transparent_pixel = $img = $bg = false;
22
 
23
+ //WPShortPixel::log("PNG2JPG SHELL EXEC: " . shell_exec('convert ' . $image . ' -format "%[opaque]" info:'));
24
+
25
  if (!file_exists($image) || ord(file_get_contents($image, false, null, 25, 1)) & 4) {
26
  $transparent = 1;
27
  } else {
158
  $image = $params['file'];
159
  WPShortPixel::log("Convert Media PNG to JPG on upload: {$image}");
160
 
161
+ if($this->_settings->png2jpg == 2) {
162
+ $doConvert = true;
163
+ } else {
164
+ $ret = $this->canConvertPng2Jpg($image);
165
+ $doConvert = $ret['notTransparent'];
166
+ }
167
+ if ($doConvert) {
168
+ $ret = $this->doConvertPng2Jpg($params, $this->_settings->backupImages, false, isset($ret['img']) ? $ret['img'] : false);
169
  if($ret->unlink) @unlink($ret->unlink);
170
  $paramsC = $ret->params;
171
  if($paramsC['type'] == 'image/jpeg') {
192
  * @param type $ID
193
  * @return string
194
  */
195
+ public function checkConvertMediaPng2Jpg($itemHandler) {
196
 
197
+ $meta = $itemHandler->getRawMeta();
198
+ $ID = $itemHandler->getId();
199
  if(!$this->_settings->png2jpg || !isset($meta['file']) || strtolower(substr($meta['file'], -4)) !== '.png') {
200
+ return ;
201
  }
202
 
203
  WPShortPixel::log("Send to processing: Convert Media PNG to JPG #{$ID} META: " . json_encode($meta));
222
  $meta['ShortPixel']['ErrCode'] = ShortPixelAPI::ERR_PNG2JPG_MEMORY;
223
  wp_update_attachment_metadata($ID, $meta);
224
 
225
+ if($this->_settings->png2jpg == 2) {
226
+ $doConvert = true;
227
+ } else {
228
+ $retC = $this->canConvertPng2Jpg($image);
229
+ $doConvert = $retC['notTransparent'];
230
+ }
231
+ if (!$doConvert) {
232
  WPShortPixel::log("PNG2JPG not a PNG");
233
  return $meta; //cannot convert it
234
  }
235
 
236
  WPShortPixel::log(" CONVERTING MAIN: $imagePath");
237
+ $retMain = $this->doConvertPng2Jpg(array('file' => $imagePath, 'url' => false, 'type' => 'image/png'), $this->_settings->backupImages, false, isset($retC['img']) ? $retC['img'] : false);
 
238
  WPShortPixel::log("PNG2JPG doConvert Main RETURNED " . json_encode($retMain));
239
  $ret = $retMain->params;
240
  $toUnlink = array();
258
  WPShortPixel::log(" SET IMAGE PATH: $imagePath");
259
 
260
  //conversion succeeded for the main image, update meta and proceed to thumbs. (It could also not succeed if the converted file is not smaller)
261
+ $duplicates = $this->updateFileAlsoInWPMLDuplicates($ID, $meta, str_replace($basePath, '', $ret['file']));
262
+ WPShortPixel::log(" WPML duplicates: " . json_encode($duplicates));
 
 
263
 
264
  $originalSizes = isset($meta['sizes']) ? $meta['sizes'] : array();
265
  foreach($meta['sizes'] as $size => $info) {
271
  if ($rett['type'] == 'image/jpeg') {
272
  $toUnlink[] = $retThumb->unlink;
273
  WPShortPixel::log("PNG2JPG thumb is jpg");
 
 
274
  $pngSize += $rett['png_size'];
275
  $jpgSize += $rett['jpg_size'];
276
  WPShortPixel::log("PNG2JPG total PNG size: $pngSize total JPG size: $jpgSize");
277
  $originalSizes[$size]['file'] = wp_basename($rett['file'], '.jpg') . '.png';
278
  WPShortPixel::log("PNG2JPG thumb original: " . $originalSizes[$size]['file']);
279
  $toReplace[$baseUrl . $baseRelPath . $info['file']] = $baseUrl . $baseRelPath . wp_basename($rett['file']);
280
+
281
+ $this->updateThumbAlsoInWPMLDuplicates($ID, $meta, $duplicates, $size, wp_basename($rett['file']));
282
  }
283
  }
 
284
  $meta['ShortPixelPng2Jpg'] = array('originalFile' => $imagePath, 'originalSizes' => $originalSizes, 'originalSizes2' => $originalSizes,
285
  'backup' => $this->_settings->backupImages,
286
  'optimizationPercent' => round(100.0 * (1.00 - $jpgSize / $pngSize)));
299
  return $meta;
300
  }
301
 
302
+ /**
303
+ * @param $parentID
304
+ * @param $parentMeta by ref. is changed
305
+ * @param $file
306
+ * @return array WPML duplicates
307
+ */
308
+ protected function updateFileAlsoInWPMLDuplicates($parentID, &$parentMeta, $file){
309
+ $duplicates = ShortPixelMetaFacade::getWPMLDuplicates($parentID);
310
+ foreach($duplicates as $ID) {
311
+ $meta = $parentID == $ID ? $parentMeta : wp_get_attachment_metadata($ID);
312
+ $meta['file'] = $file;
313
+ $meta['type'] = 'image/jpeg';
314
+ if($parentID == $ID) $parentMeta = $meta;
315
+ update_attached_file($ID, $meta['file']);
316
+ wp_update_attachment_metadata($ID, $meta);
317
+ }
318
+ return $duplicates;
319
+ }
320
+
321
+ /**
322
+ * @param $parentID
323
+ * @param $parentMeta by ref. is changed
324
+ * @param $duplicates
325
+ * @param $size
326
+ * @param $thumbnail
327
+ */
328
+ protected function updateThumbAlsoInWPMLDuplicates($parentID, &$parentMeta, $duplicates, $size, $thumbnail) {
329
+ foreach($duplicates as $ID) {
330
+ $meta = $parentID == $ID ? $parentMeta : wp_get_attachment_metadata($ID);
331
+ $meta['sizes'][$size]['file'] = wp_basename($thumbnail);
332
+ $meta['sizes'][$size]['mime-type'] = 'image/jpeg';
333
+ if($parentID == $ID) $parentMeta = $meta;
334
+ wp_update_attachment_metadata($ID, $meta);
335
+ }
336
+ }
337
+
338
  /**
339
  * taken from Velvet Blues Update URLs plugin
340
  * @param $options
361
  WPShortPixel::log("PNG2JPG update URLS on $option ");
362
  if( $option == 'custom' ){
363
  $n = 0;
364
+ $page_size = WpShortPixelMediaLbraryAdapter::getOptimalChunkSize('postmeta');
365
+
366
+ for( $page = 0; $items = $wpdb->get_results("SELECT * FROM $wpdb->postmeta LIMIT " . ($page * $page_size) . ", $page_size"); $page++ ) {
 
 
 
 
 
367
  foreach( $items as $item ) {
368
  $value = $item->meta_value;
369
+ if( trim($value) == '' || $item->meta_key == '_wp_attached_file' || $item->meta_key == '_wp_attachment_metadata') {
370
  continue;
371
+ }
372
 
373
  $edited = (object)array('data' => $value, 'replaced' => false);
374
  foreach($map as $oldurl => $newurl) {
class/view/shortpixel-feedback.php ADDED
@@ -0,0 +1,280 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * User: simon
4
+ * Date: 11.04.2018
5
+ */
6
+
7
+ class ShortPixelFeedback {
8
+
9
+ private $key;
10
+ private $ctrl;
11
+ private $plugin_file = '';
12
+ private $plugin_name = '';
13
+
14
+ function __construct( $_plugin_file, $slug, $key, $ctrl) {
15
+
16
+ $this->plugin_file = $_plugin_file;
17
+ $this->plugin_name = $slug; //for translations
18
+ $this->key = $key;
19
+ $this->ctrl = $ctrl;
20
+
21
+ // Deactivation
22
+ add_filter( 'plugin_action_links_' . plugin_basename( $this->plugin_file ), array( $this, 'filterActionLinks') );
23
+ add_action( 'admin_footer-plugins.php', array( $this, 'goodbyeAjax') );
24
+ add_action( 'wp_ajax_shortpixel_deactivate_plugin', array( $this, 'deactivatePluginCallback') );
25
+
26
+ }
27
+
28
+ /**
29
+ * Filter the deactivation link to allow us to present a form when the user deactivates the plugin
30
+ * @since 1.0.0
31
+ */
32
+ public function filterActionLinks( $links ) {
33
+
34
+ if( isset( $links['deactivate'] ) ) {
35
+ $deactivation_link = $links['deactivate'];
36
+ // Insert an onClick action to allow form before deactivating
37
+ $deactivation_link = str_replace( '<a ',
38
+ '<div class="shortpixel-deactivate-form-wrapper">
39
+ <span class="shortpixel-deactivate-form" id="shortpixel-deactivate-form-' . esc_attr( $this->plugin_name ) . '"></span>
40
+ </div><a onclick="javascript:event.preventDefault();" id="shortpixel-deactivate-link-' . esc_attr( $this->plugin_name ) . '" ', $deactivation_link );
41
+ $links['deactivate'] = $deactivation_link;
42
+ }
43
+ return $links;
44
+ }
45
+
46
+ /**
47
+ * Form text strings
48
+ * These can be filtered
49
+ * @since 1.0.0
50
+ */
51
+ public function goodbyeAjax() {
52
+ // Get our strings for the form
53
+ $form = $this->getFormInfo();
54
+
55
+ // Build the HTML to go in the form
56
+ $html = '<div class="shortpixel-deactivate-form-head"><strong>' . esc_html( $form['heading'] ) . '</strong></div>';
57
+ $html .= '<div class="shortpixel-deactivate-form-body">';
58
+ if( is_array( $form['options'] ) ) {
59
+ $html .= '<div class="shortpixel-deactivate-options">';
60
+ $html .= '<span title="' . __( 'Check this if you don\\\'t plan to use ShortPixel in the future on this website. You might also want to run a Bulk Delete SP Metadata before removing the plugin (Media Library -> Bulk ShortPixel).', $this->plugin_name )
61
+ . '"><input type="checkbox" name="shortpixel-remove-settings" id="shortpixel-remove-settings" value="yes"> <label for="shortpixel-remove-settings">'
62
+ . esc_html__( 'Remove the ShortPixel settings on plugin delete.', $this->plugin_name ) . '</label></span><br>';
63
+ $html .= '<p><strong>' . esc_html( $form['body'] ) . '</strong></p><p>';
64
+ foreach( $form['options'] as $key => $option ) {
65
+ $html .= '<input type="radio" name="shortpixel-deactivate-reason"'.('features' == $key ? ' checked="checked"' : '').' id="' . esc_attr( $key ) . '" value="' . esc_attr( $key ) . '"> <label for="' . esc_attr( $key ) . '">' . esc_attr( $option ) . '</label><br>';
66
+ }
67
+ $html .= '</p><label id="shortpixel-deactivate-details-label" for="shortpixel-deactivate-reasons"><strong>' . esc_html( $form['details'] ) .'</strong></label><textarea name="shortpixel-deactivate-details" id="shortpixel-deactivate-details" rows="2" style="width:100%"></textarea>';
68
+ $html .= '<label for="anonymous" title="'
69
+ . __("If you UNCHECK this then your email address will be sent along with your feedback. This can be used by ShortPixel to get back to you for more info or a solution.",'shortpixel-image-optimiser')
70
+ . '"><input type="checkbox" name="shortpixel-deactivate-tracking" checked="checked" id="anonymous"> ' . esc_html__( 'Send anonymous', $this->plugin_name ) . '</label><br>';
71
+ $html .= '</div><!-- .shortpixel-deactivate-options -->';
72
+ }
73
+ $html .= '</div><!-- .shortpixel-deactivate-form-body -->';
74
+ $html .= '<p class="deactivating-spinner"><span class="spinner"></span> ' . __( 'Submitting form', $this->plugin_name ) . '</p>';
75
+ $html .= '<div class="shortpixel-deactivate-form-footer"><p><a id="shortpixel-deactivate-plugin" href="#">' . __( 'Just Deactivate', $this->plugin_name ) . '</a><a id="shortpixel-deactivate-submit-form" class="button button-primary" href="#">' . __( 'Submit and Deactivate', $this->plugin_name ) . '</a></p></div>'
76
+ ?>
77
+ <div class="shortpixel-deactivate-form-bg"></div>
78
+ <style type="text/css">
79
+ .shortpixel-deactivate-form-active .shortpixel-deactivate-form-bg {
80
+ background: rgba( 0, 0, 0, .5 );
81
+ position: fixed;
82
+ top: 0;
83
+ left: 0;
84
+ width: 100%;
85
+ height: 100%;
86
+ }
87
+ .shortpixel-deactivate-form-wrapper {
88
+ position: relative;
89
+ z-index: 999;
90
+ display: none;
91
+ }
92
+ .shortpixel-deactivate-form-active .shortpixel-deactivate-form-wrapper {
93
+ display: block;
94
+ }
95
+ .shortpixel-deactivate-form {
96
+ display: none;
97
+ }
98
+ .shortpixel-deactivate-form-active .shortpixel-deactivate-form {
99
+ position: absolute;
100
+ bottom: 30px;
101
+ left: 0;
102
+ max-width: 500px;
103
+ min-width: 330px;
104
+ background: #fff;
105
+ white-space: normal;
106
+ }
107
+ .shortpixel-deactivate-form-head {
108
+ background: #4bbfcc;
109
+ color: #fff;
110
+ padding: 8px 18px;
111
+ }
112
+ .shortpixel-deactivate-form-body {
113
+ padding: 8px 18px;
114
+ color: #444;
115
+ }
116
+ .deactivating-spinner {
117
+ display: none;
118
+ }
119
+ .deactivating-spinner .spinner {
120
+ float: none;
121
+ margin: 4px 4px 0 18px;
122
+ vertical-align: bottom;
123
+ visibility: visible;
124
+ }
125
+ .shortpixel-deactivate-form-footer {
126
+ padding: 8px 18px;
127
+ }
128
+ .shortpixel-deactivate-form-footer p {
129
+ display: flex;
130
+ align-items: center;
131
+ justify-content: space-between;
132
+ }
133
+ .shortpixel-deactivate-form.process-response .shortpixel-deactivate-form-body,
134
+ .shortpixel-deactivate-form.process-response .shortpixel-deactivate-form-footer {
135
+ position: relative;
136
+ }
137
+ .shortpixel-deactivate-form.process-response .shortpixel-deactivate-form-body:after,
138
+ .shortpixel-deactivate-form.process-response .shortpixel-deactivate-form-footer:after {
139
+ content: "";
140
+ display: block;
141
+ position: absolute;
142
+ top: 0;
143
+ left: 0;
144
+ width: 100%;
145
+ height: 100%;
146
+ background-color: rgba( 255, 255, 255, .5 );
147
+ }
148
+ </style>
149
+ <script>
150
+ jQuery(document).ready(function($){
151
+ var deactivateURL = $("#shortpixel-deactivate-link-<?php echo esc_attr( $this->plugin_name ); ?>"),
152
+ formContainer = $('#shortpixel-deactivate-form-<?php echo esc_attr( $this->plugin_name ); ?>'),
153
+ detailsStrings = {
154
+ 'setup' : '<?php echo __( 'What was the dificult part ?', $this->plugin_name ) ?>',
155
+ 'documentation' : '<?php echo __( 'What can we describe more ?', $this->plugin_name ) ?>',
156
+ 'features' : '<?php echo __( 'How could we improve ?', $this->plugin_name ) ?>',
157
+ 'better-plugin' : '<?php echo __( 'Can you mention it ?', $this->plugin_name ) ?>',
158
+ 'incompatibility' : '<?php echo __( 'With what plugin or theme is incompatible ?', $this->plugin_name ) ?>',
159
+ 'maintenance' : '<?php echo __( 'Please specify', $this->plugin_name ) ?>',
160
+ };
161
+
162
+ $( deactivateURL ).on("click",function(){
163
+ // We'll send the user to this deactivation link when they've completed or dismissed the form
164
+ var url = deactivateURL.attr( 'href' );
165
+ $('body').toggleClass('shortpixel-deactivate-form-active');
166
+ formContainer.fadeIn({complete: function(){
167
+ var offset = formContainer.offset();
168
+ if( offset.top < 50) {
169
+ $(this).parent().css('top', (50 - offset.top) + 'px')
170
+ }
171
+ $('html,body').animate({ scrollTop: Math.max(0, offset.top - 50) });
172
+ }});
173
+ formContainer.html( '<?php echo $html; ?>');
174
+
175
+ formContainer.on( 'change', 'input[name="shortpixel-deactivate-reason"]', function(){
176
+ var detailsLabel = formContainer.find( '#shortpixel-deactivate-details-label strong' );
177
+ var value = formContainer.find( 'input[name="shortpixel-deactivate-reason"]:checked' ).val();
178
+ detailsLabel.text( detailsStrings[ value ] );
179
+ });
180
+
181
+ formContainer.on('click', '#shortpixel-deactivate-submit-form', function(e){
182
+ debugger;
183
+ var data = {
184
+ 'action': 'shortpixel_deactivate_plugin',
185
+ 'security': "<?php echo wp_create_nonce ( 'shortpixel_deactivate_plugin' ); ?>",
186
+ 'dataType': "json"
187
+ };
188
+ e.preventDefault();
189
+ // As soon as we click, the body of the form should disappear
190
+ formContainer.addClass( 'process-response' );
191
+ // Fade in spinner
192
+ formContainer.find(".deactivating-spinner").fadeIn();
193
+
194
+ data['reason'] = formContainer.find( 'input[name="shortpixel-deactivate-reason"]:checked' ).val();
195
+ data['details'] = formContainer.find('#shortpixel-deactivate-details').val();
196
+ data['anonymous'] = formContainer.find( '#anonymous:checked' ).length;
197
+ data['remove-settings'] = formContainer.find( '#shortpixel-remove-settings:checked').length;
198
+
199
+ $.post(
200
+ ajaxurl,
201
+ data,
202
+ function(response){
203
+ // Redirect to original deactivation URL
204
+ debugger;
205
+ window.location.href = url;
206
+ }
207
+ );
208
+ });
209
+
210
+ formContainer.on('click', '#shortpixel-deactivate-plugin', function(e){
211
+ e.preventDefault();
212
+ window.location.href = url;
213
+ });
214
+
215
+ // If we click outside the form, the form will close
216
+ $('.shortpixel-deactivate-form-bg').on('click',function(){
217
+ formContainer.fadeOut();
218
+ $('body').removeClass('shortpixel-deactivate-form-active');
219
+ });
220
+ });
221
+ });
222
+ </script>
223
+ <?php }
224
+
225
+ /*
226
+ * Form text strings
227
+ * These are non-filterable and used as fallback in case filtered strings aren't set correctly
228
+ * @since 1.0.0
229
+ */
230
+ public function getFormInfo() {
231
+ $form = array();
232
+ $form['heading'] = __( 'Sorry to see you go', $this->plugin_name );
233
+ $form['body'] = __( 'Before you deactivate the plugin, would you quickly give us your reason for doing so?', $this->plugin_name );
234
+ $form['options'] = array(
235
+ 'setup' => __( 'Set up is too difficult', $this->plugin_name ),
236
+ 'documentation' => __( 'Lack of documentation', $this->plugin_name ),
237
+ 'features' => __( 'Not the features I wanted', $this->plugin_name ),
238
+ 'better-plugin' => __( 'Found a better plugin', $this->plugin_name ),
239
+ 'incompatibility' => __( 'Incompatible with theme or plugin', $this->plugin_name ),
240
+ 'maintenance' => __( 'Other', $this->plugin_name ),
241
+ );
242
+ $form['details'] = __( 'How could we improve ?', $this->plugin_name );
243
+ return $form;
244
+ }
245
+
246
+ public function deactivatePluginCallback() {
247
+
248
+ check_ajax_referer( 'shortpixel_deactivate_plugin', 'security' );
249
+
250
+ if ( isset($_POST['reason']) && isset($_POST['details']) && isset($_POST['anonymous']) ) {
251
+ $_POST = $this->ctrl->validateFeedback($_POST);
252
+ require_once 'shortpixel-plugin-request.php';
253
+ $anonymous = isset($_POST['anonymous']) && $_POST['anonymous'];
254
+ $args = array(
255
+ 'key' => $anonymous ? false : $this->key,
256
+ 'reason' => $_POST['reason'],
257
+ 'details' => $_POST['details'],
258
+ 'anonymous' => $anonymous
259
+ );
260
+ $request = new ShortPixelPluginRequest( $this->plugin_file, 'http://' . SHORTPIXEL_API . '/v2/feedback.php', $args );
261
+ if ( $request->request_successful ) {
262
+ echo json_encode( array(
263
+ 'status' => 'ok',
264
+ ) );
265
+ }else{
266
+ echo json_encode( array(
267
+ 'status' => 'nok',
268
+ ) );
269
+ }
270
+ }else{
271
+ echo json_encode( array(
272
+ 'status' => 'OK',
273
+ ) );
274
+ }
275
+
276
+ die();
277
+
278
+ }
279
+
280
+ }
class/view/shortpixel-plugin-request.php ADDED
@@ -0,0 +1,217 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * User: simon
4
+ * Date: 11.04.2018
5
+ */
6
+
7
+ class ShortPixelPluginRequest {
8
+
9
+ /**
10
+ * Url for the request
11
+ *
12
+ * @var string
13
+ */
14
+ private $url;
15
+ /**
16
+ * Api endpoint
17
+ *
18
+ * @var string
19
+ */
20
+ private $data = array(
21
+ 'server' => array(),
22
+ 'user' => array(),
23
+ 'wordpress' => array(
24
+ 'deactivated_plugin' => array(),
25
+ ),
26
+ );
27
+ /**
28
+ * Plugin file
29
+ *
30
+ * @var string
31
+ */
32
+ private $plugin_file = '';
33
+
34
+ private $allow_tracking = 0;
35
+
36
+ public $request_successful = false;
37
+
38
+ function __construct( $_plugin_file, $url, $args ) {
39
+
40
+ $this->url = $url;
41
+ // Set variables
42
+ $this->allow_tracking = !$args['anonymous'];
43
+ $this->plugin_file = $_plugin_file;
44
+ $this->data['unique'] = md5( home_url() . get_bloginfo( 'admin_email' ) );
45
+ $this->data['key'] = $args['key'];
46
+ $this->data['wordpress']['deactivated_plugin']['uninstall_reason'] = $args['reason'];
47
+ $this->data['wordpress']['deactivated_plugin']['uninstall_details'] = $args['details'];
48
+
49
+ // Start collecting data
50
+ $this->_collect_data();
51
+ $this->request_successful = $this->_send_request();
52
+ }
53
+
54
+ /**
55
+ * Collect all data for the request.
56
+ *
57
+ */
58
+ private function _collect_data() {
59
+
60
+ $current_plugin = get_plugin_data( $this->plugin_file );
61
+
62
+ // Plugin data
63
+ $this->data['wordpress']['deactivated_plugin']['slug'] = $current_plugin['TextDomain'];
64
+ $this->data['wordpress']['deactivated_plugin']['name'] = $current_plugin['Name'];
65
+ $this->data['wordpress']['deactivated_plugin']['version'] = $current_plugin['Version'];
66
+ $this->data['wordpress']['deactivated_plugin']['author'] = $current_plugin['AuthorName'];
67
+
68
+ if ( $this->allow_tracking ) {
69
+ //$this->_collect_wordpress_data();
70
+ //$this->_collect_server_data();
71
+ $this->_collect_user_data();
72
+ }
73
+
74
+ }
75
+
76
+ /**
77
+ * Collect WordPress data.
78
+ *
79
+ */
80
+ private function _collect_wordpress_data() {
81
+ $this->data['wordpress']['locale'] = ( get_bloginfo( 'version' ) >= 4.7 ) ? get_user_locale() : get_locale();
82
+ $this->data['wordpress']['wp_version'] = get_bloginfo( 'version' );
83
+ $this->data['wordpress']['multisite'] = is_multisite();
84
+
85
+ $this->data['wordpress']['themes'] = $this->get_themes();
86
+ $this->data['wordpress']['plugins'] = $this->get_plugins();
87
+ }
88
+
89
+ /**
90
+ * Collect server data.
91
+ *
92
+ */
93
+ private function _collect_server_data() {
94
+ $this->data['server']['server'] = isset( $_SERVER['SERVER_SOFTWARE'] ) ? $_SERVER['SERVER_SOFTWARE'] : '';
95
+ $this->data['server']['php_version'] = phpversion();
96
+ $this->data['server']['url'] = home_url();
97
+ }
98
+
99
+ /**
100
+ * Collect user data.
101
+ *
102
+ */
103
+ private function _collect_user_data() {
104
+ $admin = get_user_by( 'email', get_bloginfo( 'admin_email' ) );
105
+ if ( ! $admin ) {
106
+ $this->data['user']['email'] = '';
107
+ $this->data['user']['first_name'] = '';
108
+ $this->data['user']['last_name'] = '';
109
+ }else{
110
+ $this->data['user']['email'] = get_bloginfo( 'admin_email' );
111
+ $this->data['user']['first_name'] = $admin->first_name;
112
+ $this->data['user']['last_name'] = $admin->last_name;
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Get current themes
118
+ *
119
+ * @return array
120
+ */
121
+ private function get_themes() {
122
+ $theme = wp_get_theme();
123
+
124
+ return array(
125
+ 'installed' => $this->_get_installed_themes(),
126
+ 'active' => array(
127
+ 'slug' => get_stylesheet(),
128
+ 'name' => $theme->get( 'Name' ),
129
+ 'version' => $theme->get( 'Version' ),
130
+ 'author' => $theme->get( 'Author' ),
131
+ ),
132
+ );
133
+ }
134
+
135
+ /**
136
+ * Get an array of installed themes
137
+ */
138
+ private function _get_installed_themes() {
139
+ $installed = wp_get_themes();
140
+ $theme = get_stylesheet();
141
+ $arr = array();
142
+
143
+ foreach ( $installed as $slug => $info ) {
144
+ if ( $slug === $theme ) {
145
+ continue;
146
+ }
147
+ $arr[ $slug ] = array(
148
+ 'slug' => $slug,
149
+ 'name' => $info->get( 'Name' ),
150
+ 'version' => $info->get( 'Version' ),
151
+ 'author' => $info->get( 'Author' )
152
+ );
153
+ };
154
+
155
+ return $arr;
156
+ }
157
+
158
+ /**
159
+ * Get a list of installed plugins
160
+ */
161
+ private function get_plugins() {
162
+ if ( ! function_exists( 'get_plugins' ) ) {
163
+ include ABSPATH . '/wp-admin/includes/plugin.php';
164
+ }
165
+
166
+ $plugins = get_plugins();
167
+ $option = get_option( 'active_plugins', array() );
168
+ $active = array();
169
+ $installed = array();
170
+ foreach ( $plugins as $id => $info ) {
171
+ if ( in_array( $id, $active ) ) {
172
+ continue;
173
+ }
174
+
175
+ $id = explode( '/', $id );
176
+ $id = ucwords( str_replace( '-', ' ', $id[0] ) );
177
+
178
+ $installed[] = $id;
179
+ }
180
+
181
+ foreach ( $option as $id ) {
182
+ $id = explode( '/', $id );
183
+ $id = ucwords( str_replace( '-', ' ', $id[0] ) );
184
+
185
+ $active[] = $id;
186
+ }
187
+
188
+ return array(
189
+ 'installed' => $installed,
190
+ 'active' => $active,
191
+ );
192
+ }
193
+
194
+ /**
195
+ * Send dat to server.
196
+ *
197
+ */
198
+ private function _send_request() {
199
+
200
+ $request = wp_remote_post( $this->url, array(
201
+ 'method' => 'POST',
202
+ 'timeout' => 20,
203
+ 'redirection' => 5,
204
+ 'httpversion' => '1.1',
205
+ 'blocking' => true,
206
+ 'body' => $this->data,
207
+ 'user-agent' => 'MT/EPSILON-CUSTOMER-TRACKING/' . esc_url( home_url() )
208
+ ) );
209
+
210
+ if ( is_wp_error( $request ) ) {
211
+ return false;
212
+ }
213
+
214
+ return true;
215
+
216
+ }
217
+ }
class/view/shortpixel_view.php CHANGED
@@ -298,7 +298,7 @@ class ShortPixelView {
298
  <p><?php _e('Please see below the optimization status so far:','shortpixel-image-optimiser');?></p>
299
  <?php $this->displayBulkStats($quotaData['totalProcessedFiles'], $quotaData['mainProcessedFiles'], $under5PercentCount, $averageCompression, $savedSpace);?>
300
  <?php if($quotaData['totalProcessedFiles'] < $quotaData['totalFiles']) { ?>
301
- <p><?php printf(__('%d images and %d thumbnails are not yet optimized by ShortPixel.','shortpixel-image-optimiser'),
302
  number_format($quotaData['mainFiles'] - $quotaData['mainProcessedFiles']),
303
  number_format(($quotaData['totalFiles'] - $quotaData['mainFiles']) - ($quotaData['totalProcessedFiles'] - $quotaData['mainProcessedFiles'])));?>
304
  </p>
@@ -389,8 +389,7 @@ class ShortPixelView {
389
  <p><?php printf(__('Go to the ShortPixel <a href="%soptions-general.php?page=wp-shortpixel#stats">Stats</a>
390
  and see all your websites\' optimized stats. Download your detailed <a href="https://%s/v2/report.php?key=%s">Optimization Report</a>
391
  to check your image optimization statistics for the last 40 days.','shortpixel-image-optimiser'),
392
- SHORTPIXEL_API,
393
- get_admin_url(), (defined("SHORTPIXEL_HIDE_API_KEY") ? '' : $this->ctrl->getApiKey()) );?></p>
394
  <?php
395
  $failed = $this->ctrl->getPrioQ()->getFailed();
396
  if(count($failed)) { ?>
@@ -850,7 +849,7 @@ class ShortPixelView {
850
  if($showApiKey) {
851
  $canValidate = true;?>
852
  <input name="key" type="text" id="key" value="<?php echo( $this->ctrl->getApiKey() );?>"
853
- class="regular-text" <?php echo($editApiKey ? "" : 'disabled') ?>>
854
  <?php } elseif(defined("SHORTPIXEL_API_KEY")) {
855
  $canValidate = true;?>
856
  <input name="key" type="text" id="key" disabled="true" placeholder="<?php
@@ -864,7 +863,12 @@ class ShortPixelView {
864
  <input type="hidden" name="validate" id="valid" value=""/>
865
  <span class="spinner" id="pluginemail_spinner" style="float:none;"></span>
866
  <button type="button" id="validate" class="button button-primary" title="<?php _e('Validate the provided API key','shortpixel-image-optimiser');?>"
867
- onclick="ShortPixel.validateKey()" <?php echo $canValidate ? "" : "disabled"?>><?php _e('Validate','shortpixel-image-optimiser');?></button>
 
 
 
 
 
868
  <?php if($showApiKey && !$editApiKey) { ?>
869
  <p class="settings-info"><?php _e('Key defined in wp-config.php.','shortpixel-image-optimiser');?></p>
870
  <?php } ?>
@@ -880,29 +884,44 @@ class ShortPixelView {
880
  <label for="compressionType"><?php _e('Compression type:','shortpixel-image-optimiser');?></label>
881
  </th>
882
  <td>
883
- <input type="radio" name="compressionType" value="1" <?php echo( $this->ctrl->getCompressionType() == 1 ? "checked" : "" );?>><?php
884
- _e('Lossy (recommended)','shortpixel-image-optimiser');?></br>
885
- <p class="settings-info"><?php _e('<b>Lossy compression: </b>offers the best compression rate.</br> This is the recommended option for most users, producing results that look the same as the original to the human eye. You can run a test for free ','shortpixel-image-optimiser');?>
886
- <a href="https://shortpixel.com/online-image-compression" target="_blank"><?php _e('here','shortpixel-image-optimiser');?></a>.</p></br>
887
- <input type="radio" name="compressionType" value="2" <?php echo( $this->ctrl->getCompressionType() == 2 ? "checked" : "" );?>><?php
888
- _e('Glossy','shortpixel-image-optimiser');?></br>
889
- <p class="settings-info"><?php _e('<b>Glossy compression: </b>creates images that are almost pixel-perfect identical to the originals.</br> Best option for photographers and other professionals that use very high quality images on their sites and want best compression while keeping the quality untouched.','shortpixel-image-optimiser');?>
890
- <a href="http://blog.shortpixel.com/glossy-image-optimization-for-photographers/" target="_blank" class="shortpixel-help-link">
891
- <span class="dashicons dashicons-editor-help"></span><?php _e('More info about glossy','shortpixel-image-optimiser');?>
892
- </a></p>
893
- </br>
894
- <input type="radio" name="compressionType" value="0" <?php echo( $this->ctrl->getCompressionType() == 0 ? "checked" : "" );?>><?php
895
- _e('Lossless','shortpixel-image-optimiser');?>
896
- <p class="settings-info">
897
- <?php _e('<b>Lossless compression: </b> the resulting image is pixel-identical with the original image.</br>Make sure not a single pixel looks different in the optimized image compared with the original.
898
- In some rare cases you will need to use this type of compression. Some technical drawings or images from vector graphics are possible situations.','shortpixel-image-optimiser');?>
899
- </p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
900
  </td>
901
  </tr>
902
- </tbody>
903
- </table>
904
- <table class="form-table">
905
- <tbody>
906
  <tr>
907
  <th scope="row"><label for="thumbnails"><?php _e('Also include thumbnails:','shortpixel-image-optimiser');?></label></th>
908
  <td><input name="thumbnails" type="checkbox" id="thumbnails" <?php echo( $checked );?>> <?php
@@ -1003,6 +1022,7 @@ class ShortPixelView {
1003
  $settings->png2jpg = 0;
1004
  }
1005
  $convertPng2Jpg = ($settings->png2jpg ? 'checked' : '');
 
1006
  $allSizes = $this->ctrl->getAllThumbnailSizes();
1007
  $excludeSizes = $settings->excludeSizes;
1008
  ?>
@@ -1013,7 +1033,7 @@ class ShortPixelView {
1013
  <table class="form-table">
1014
  <tbody>
1015
  <tr>
1016
- <th scope="row"><label for="resize"><?php _e('Additional media folders','shortpixel-image-optimiser');?></label></th>
1017
  <td>
1018
  <span style="display:none;">Current PHP version: <?php echo(phpversion()) ?></span>
1019
  <?php if($customFolders) { ?>
@@ -1115,8 +1135,10 @@ class ShortPixelView {
1115
  <tr>
1116
  <th scope="row"><label for="png2jpg"><?php _e('Convert PNG images to JPEG','shortpixel-image-optimiser');?></label></th>
1117
  <td>
1118
- <input name="png2jpg" type="checkbox" id="resize" <?php echo( $convertPng2Jpg );?> <?php echo($gdInstalled ? '' : 'disabled') ?>> <?php
1119
- _e('Automatically convert the PNG images to JPEG if possible.','shortpixel-image-optimiser');
 
 
1120
  if(!$gdInstalled) {echo("&nbsp;<span style='color:red;'>" . __('You need PHP GD for this. Please ask your hosting to install it.','shortpixel-image-optimiser') . "</span>");}
1121
  ?>
1122
  <p class="settings-info">
@@ -1213,9 +1235,9 @@ class ShortPixelView {
1213
  </td>
1214
  </tr>
1215
  <tr>
1216
- <th scope="row"><label for="resize"><?php _e('Process in front-end','shortpixel-image-optimiser');?></label></th>
1217
  <td>
1218
- <input name="frontBootstrap" type="checkbox" id="resize" <?php echo( $frontBootstrap );?>> <?php _e('Automatically optimize images added by users in front end.','shortpixel-image-optimiser');?>
1219
  <p class="settings-info">
1220
  <?php _e('Check this if you have users that add images or PDF documents from custom forms in the front-end. This could increase the load on your server if you have a lot of users simultaneously connected.','shortpixel-image-optimiser');?>
1221
  </p>
298
  <p><?php _e('Please see below the optimization status so far:','shortpixel-image-optimiser');?></p>
299
  <?php $this->displayBulkStats($quotaData['totalProcessedFiles'], $quotaData['mainProcessedFiles'], $under5PercentCount, $averageCompression, $savedSpace);?>
300
  <?php if($quotaData['totalProcessedFiles'] < $quotaData['totalFiles']) { ?>
301
+ <p><?php printf(__('%s images and %s thumbnails are not yet optimized by ShortPixel.','shortpixel-image-optimiser'),
302
  number_format($quotaData['mainFiles'] - $quotaData['mainProcessedFiles']),
303
  number_format(($quotaData['totalFiles'] - $quotaData['mainFiles']) - ($quotaData['totalProcessedFiles'] - $quotaData['mainProcessedFiles'])));?>
304
  </p>
389
  <p><?php printf(__('Go to the ShortPixel <a href="%soptions-general.php?page=wp-shortpixel#stats">Stats</a>
390
  and see all your websites\' optimized stats. Download your detailed <a href="https://%s/v2/report.php?key=%s">Optimization Report</a>
391
  to check your image optimization statistics for the last 40 days.','shortpixel-image-optimiser'),
392
+ get_admin_url(), SHORTPIXEL_API, (defined("SHORTPIXEL_HIDE_API_KEY") ? '' : $this->ctrl->getApiKey()) );?></p>
 
393
  <?php
394
  $failed = $this->ctrl->getPrioQ()->getFailed();
395
  if(count($failed)) { ?>
849
  if($showApiKey) {
850
  $canValidate = true;?>
851
  <input name="key" type="text" id="key" value="<?php echo( $this->ctrl->getApiKey() );?>"
852
+ class="regular-text" <?php echo($editApiKey ? "" : 'disabled') ?> <?php echo $this->ctrl->getVerifiedKey() ? 'onkeyup="ShortPixel.apiKeyChanged()"' : '' ?>>
853
  <?php } elseif(defined("SHORTPIXEL_API_KEY")) {
854
  $canValidate = true;?>
855
  <input name="key" type="text" id="key" disabled="true" placeholder="<?php
863
  <input type="hidden" name="validate" id="valid" value=""/>
864
  <span class="spinner" id="pluginemail_spinner" style="float:none;"></span>
865
  <button type="button" id="validate" class="button button-primary" title="<?php _e('Validate the provided API key','shortpixel-image-optimiser');?>"
866
+ onclick="ShortPixel.validateKey()" <?php echo $canValidate ? "" : "disabled"?> <?php echo $this->ctrl->getVerifiedKey() ? 'style="display:none;"' : '' ?>>
867
+ <?php _e('Validate','shortpixel-image-optimiser');?>
868
+ </button>
869
+ <span class="shortpixel-key-valid" <?php echo $this->ctrl->getVerifiedKey() ? '' : 'style="display:none;"' ?>>
870
+ <span class="dashicons dashicons-yes"></span>Your API key is valid.
871
+ </span>
872
  <?php if($showApiKey && !$editApiKey) { ?>
873
  <p class="settings-info"><?php _e('Key defined in wp-config.php.','shortpixel-image-optimiser');?></p>
874
  <?php } ?>
884
  <label for="compressionType"><?php _e('Compression type:','shortpixel-image-optimiser');?></label>
885
  </th>
886
  <td>
887
+
888
+
889
+ <div class="shortpixel-compression">
890
+ <div class="shortpixel-compression-options">
891
+ <label class="lossy" title="This is the recommended option in most cases, producing results that look the same as the original to the human eye.">
892
+ <input type="radio" class="shortpixel-radio-lossy" name="compressionType" value="1" <?php echo( $this->ctrl->getCompressionType() == 1 ? "checked" : "" );?>><span>Lossy</span>
893
+ </label>
894
+ <label class="glossy" title="Best option for photographers and other professionals that use very high quality images on their sites and want best compression while keeping the quality untouched.">
895
+ <input type="radio" class="shortpixel-radio-glossy" name="compressionType" value="2" <?php echo( $this->ctrl->getCompressionType() == 2 ? "checked" : "" );?>><span>Glossy</span>
896
+ </label>
897
+ <label class="lossless" title="Make sure not a single pixel looks different in the optimized image compared with the original. In some rare cases you will need to use this type of compression. Some technical drawings or images from vector graphics are possible situations.">
898
+ <input type="radio" class="shortpixel-radio-lossless" name="compressionType" value="0" <?php echo( $this->ctrl->getCompressionType() == 0 ? "checked" : "" );?>><span>Lossless</span>
899
+ </label>
900
+ <a href="https://shortpixel.com/online-image-compression" style="margin-left:20px;" target="_blank">Make a few tests</a> to help you decide.
901
+ </div>
902
+ <p class="settings-info shortpixel-radio-info shortpixel-radio-lossy" <?php echo( $this->ctrl->getCompressionType() == 1 ? "" : 'style="display:none"' );?>>
903
+ <?php _e('<b>Lossy compression (recommended): </b>offers the best compression rate.</br> This is the recommended option for most users, producing results that look the same as the original to the human eye.','shortpixel-image-optimiser');?>
904
+ </p>
905
+ <p class="settings-info shortpixel-radio-info shortpixel-radio-glossy" <?php echo( $this->ctrl->getCompressionType() == 2 ? "" : 'style="display:none"' );?>>
906
+ <?php _e('<b>Glossy compression: </b>creates images that are almost pixel-perfect identical to the originals.</br> Best option for photographers and other professionals that use very high quality images on their sites and want best compression while keeping the quality untouched.','shortpixel-image-optimiser');?>
907
+ <a href="http://blog.shortpixel.com/glossy-image-optimization-for-photographers/" target="_blank" class="shortpixel-help-link">
908
+ <span class="dashicons dashicons-editor-help"></span><?php _e('More info about glossy','shortpixel-image-optimiser');?>
909
+ </a></p>
910
+ <p class="settings-info shortpixel-radio-info shortpixel-radio-lossless" <?php echo( $this->ctrl->getCompressionType() == 0 ? "" : 'style="display:none"' );?>>
911
+ <?php _e('<b>Lossless compression: </b> the resulting image is pixel-identical with the original image.</br>Make sure not a single pixel looks different in the optimized image compared with the original.
912
+ In some rare cases you will need to use this type of compression. Some technical drawings or images from vector graphics are possible situations.','shortpixel-image-optimiser');?>
913
+ </p>
914
+ </div>
915
+ <script>
916
+ function shortpixelCompressionLevelInfo() {
917
+ jQuery(".shortpixel-compression p").css("display", "none");
918
+ jQuery(".shortpixel-compression p." + jQuery(".shortpixel-compression-options input:radio:checked").attr('class')).css("display", "block");
919
+ }
920
+ //shortpixelCompressionLevelInfo();
921
+ jQuery(".shortpixel-compression-options input:radio").change(shortpixelCompressionLevelInfo);
922
+ </script>
923
  </td>
924
  </tr>
 
 
 
 
925
  <tr>
926
  <th scope="row"><label for="thumbnails"><?php _e('Also include thumbnails:','shortpixel-image-optimiser');?></label></th>
927
  <td><input name="thumbnails" type="checkbox" id="thumbnails" <?php echo( $checked );?>> <?php
1022
  $settings->png2jpg = 0;
1023
  }
1024
  $convertPng2Jpg = ($settings->png2jpg ? 'checked' : '');
1025
+ $convertPng2JpgForce = ($settings->png2jpg > 1 ? 'checked' : '');
1026
  $allSizes = $this->ctrl->getAllThumbnailSizes();
1027
  $excludeSizes = $settings->excludeSizes;
1028
  ?>
1033
  <table class="form-table">
1034
  <tbody>
1035
  <tr>
1036
+ <th scope="row"><label for="additional-media"><?php _e('Additional media folders','shortpixel-image-optimiser');?></label></th>
1037
  <td>
1038
  <span style="display:none;">Current PHP version: <?php echo(phpversion()) ?></span>
1039
  <?php if($customFolders) { ?>
1135
  <tr>
1136
  <th scope="row"><label for="png2jpg"><?php _e('Convert PNG images to JPEG','shortpixel-image-optimiser');?></label></th>
1137
  <td>
1138
+ <input name="png2jpg" type="checkbox" id="png2jpg" <?php echo( $convertPng2Jpg );?> <?php echo($gdInstalled ? '' : 'disabled') ?>> <?php
1139
+ _e('Automatically convert the PNG images to JPEG if possible.','shortpixel-image-optimiser');?>
1140
+ <input name="png2jpgForce" type="checkbox" id="png2jpgForce" <?php echo( $convertPng2JpgForce );?> <?php echo($gdInstalled ? '' : 'disabled') ?>> <?php
1141
+ _e('Force conversion of images with transparency.','shortpixel-image-optimiser');
1142
  if(!$gdInstalled) {echo("&nbsp;<span style='color:red;'>" . __('You need PHP GD for this. Please ask your hosting to install it.','shortpixel-image-optimiser') . "</span>");}
1143
  ?>
1144
  <p class="settings-info">
1235
  </td>
1236
  </tr>
1237
  <tr>
1238
+ <th scope="row"><label for="frontBootstrap"><?php _e('Process in front-end','shortpixel-image-optimiser');?></label></th>
1239
  <td>
1240
+ <input name="frontBootstrap" type="checkbox" id="frontBootstrap" <?php echo( $frontBootstrap );?>> <?php _e('Automatically optimize images added by users in front end.','shortpixel-image-optimiser');?>
1241
  <p class="settings-info">
1242
  <?php _e('Check this if you have users that add images or PDF documents from custom forms in the front-end. This could increase the load on your server if you have a lot of users simultaneously connected.','shortpixel-image-optimiser');?>
1243
  </p>
class/wp-short-pixel.php CHANGED
@@ -54,6 +54,10 @@ class WPShortPixel {
54
  //Media custom column
55
  add_filter( 'manage_media_columns', array( &$this, 'columns' ) );//add media library column header
56
  add_action( 'manage_media_custom_column', array( &$this, 'generateCustomColumn' ), 10, 2 );//generate the media library column
 
 
 
 
57
  //Edit media meta box
58
  add_action( 'add_meta_boxes', array( &$this, 'shortpixelInfoBox') );
59
  //for cleaning up the WebP images when an attachment is deleted
@@ -101,6 +105,13 @@ class WPShortPixel {
101
  add_action( 'admin_bar_menu', array( &$this, 'toolbar_shortpixel_processing'), 999 );
102
  //deactivate plugin
103
  add_action( 'admin_post_shortpixel_deactivate_plugin', array(&$this, 'deactivatePlugin'));
 
 
 
 
 
 
 
104
  }
105
 
106
  //automatic optimization
@@ -170,12 +181,19 @@ class WPShortPixel {
170
 
171
  public static function shortPixelDeactivatePlugin()//reset some params to avoid trouble for plugins that were activated/deactivated/activated
172
  {
173
- include_once dirname( SHORTPIXEL_PLUGIN_FILE ) . '/wp-shortpixel-req.php';
174
  ShortPixelQueue::resetBulk();
175
  ShortPixelQueue::resetPrio();
176
  WPShortPixelSettings::onDeactivate();
177
  }
178
-
 
 
 
 
 
 
 
 
179
  public function getConflictingPlugins() {
180
  $conflictPlugins = array(
181
  'WP Smush - Image Optimization' => 'wp-smushit/wp-smush.php',
@@ -263,7 +281,6 @@ class WPShortPixel {
263
  //looks like the user hasn't got enough credits to process the monthly images, display a notice telling this
264
  ShortPixelView::displayActivationNotice('upgmonth', array('monthAvg' => $this->getMonthAvg($stats), 'monthlyQuota' => $quotaData['APICallsQuotaNumeric']));
265
  }
266
-
267
  }
268
  }
269
 
@@ -382,6 +399,10 @@ class WPShortPixel {
382
  wp_register_script('short-pixel' . $this->jsSuffix, plugins_url('/res/js/short-pixel' . $this->jsSuffix,SHORTPIXEL_PLUGIN_FILE), array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION);
383
  $jsTranslation = array(
384
  'optimizeWithSP' => __( 'Optimize with ShortPixel', 'shortpixel-image-optimiser' ),
 
 
 
 
385
  'changeMLToListMode' => __( 'In order to access the ShortPixel Optimization actions and info, please change to {0}List View{1}List View{2}Dismiss{3}', 'shortpixel-image-optimiser' ),
386
  'alertOnlyAppliesToNewImages' => __( 'This type of optimization will apply to new uploaded images. Images that were already processed will not be re-optimized unless you restart the bulk process.', 'shortpixel-image-optimiser' ),
387
  'areYouSureStopOptimizing' => __( 'Are you sure you want to stop optimizing the folder {0}?', 'shortpixel-image-optimiser' ),
@@ -473,15 +494,18 @@ class WPShortPixel {
473
  $wp_list_table = _get_list_table('WP_Media_List_Table');
474
  $action = $wp_list_table->current_action();
475
 
 
 
 
 
 
 
 
 
 
476
  switch($action) {
477
  // 2. Perform the action
478
  case 'short-pixel-bulk':
479
- // security check
480
- check_admin_referer('bulk-media');
481
- if(!is_array($_GET['media'])) {
482
- break;
483
- }
484
- $mediaIds = array_reverse($_GET['media']);
485
  foreach( $mediaIds as $ID ) {
486
  $meta = wp_get_attachment_metadata($ID);
487
  if( ( !isset($meta['ShortPixel']) //never touched by ShortPixel
@@ -493,6 +517,34 @@ class WPShortPixel {
493
  }
494
  }
495
  break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
496
  }
497
  }
498
 
@@ -607,72 +659,98 @@ class WPShortPixel {
607
  * @param type $ID
608
  * @return string
609
  */
610
- public function checkConvertMediaPng2Jpg($meta, $ID) {
611
  $converter = new ShortPixelPng2Jpg($this->_settings);
612
- return $converter->checkConvertMediaPng2Jpg($meta, $ID);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
613
  }
614
 
615
  /**
616
  * this is hooked onto the NextGen upload
617
  * @param type $image
618
  */
619
- public function handleNextGenImageUpload($image) {
620
- if($this->_settings->includeNextGen == 1) {
 
621
  $imageFsPath = ShortPixelNextGenAdapter::getImageAbspath($image);
622
 
623
  $customFolders = $this->spMetaDao->getFolders();
624
 
625
  $folderId = -1;
626
- foreach($customFolders as $folder) {
627
- if(strpos($imageFsPath, $folder->getPath()) === 0) {
628
  $folderId = $folder->getId();
629
  break;
630
  }
631
  }
632
- if($folderId == -1) { //if not found, create
633
  $galleryPath = dirname($imageFsPath);
634
  $folder = new ShortPixelFolder(array("path" => $galleryPath), $this->_settings->excludePatterns);
635
  $folderMsg = $this->spMetaDao->saveFolder($folder);
636
  $folderId = $folder->getId();
637
  //self::log("NG Image Upload: created folder from path $galleryPath : Folder info: " . json_encode($folder));
638
  }
639
- $pathParts = explode('/', trim($imageFsPath));
640
- //Add the main image
641
- $meta = new ShortPixelMeta();
642
- $meta->setPath($imageFsPath);
643
- $meta->setName($pathParts[count($pathParts) - 1]);
644
- $meta->setFolderId($folderId);
645
- $meta->setExtMetaId($image->pid); // do this only for main image, not for thumbnais.
646
- $meta->setCompressionType($this->_settings->compressionType);
647
- $meta->setKeepExif($this->_settings->keepExif);
648
- $meta->setCmyk2rgb($this->_settings->CMYKtoRGBconversion);
649
- $meta->setResize($this->_settings->resizeImages);
650
- $meta->setResizeWidth($this->_settings->resizeWidth);
651
- $meta->setResizeHeight($this->_settings->resizeHeight);
652
- $ID = $this->spMetaDao->addImage($meta);
653
- $meta->setId($ID);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
654
  $this->prioQ->push('C-' . $ID);
655
- //add the thumb image if exists
656
- $pathParts[] = "thumbs_" . $pathParts[count($pathParts) - 1];
657
- $pathParts[count($pathParts) - 2] = "thumbs";
658
- $thumbPath = implode('/', $pathParts);
659
- if(file_exists($thumbPath)) {
660
- $metaThumb = new ShortPixelMeta();
661
- $metaThumb->setPath($thumbPath);
662
- $metaThumb->setName($pathParts[count($pathParts) - 1]);
663
- $metaThumb->setFolderId($folderId);
664
- $metaThumb->setCompressionType($this->_settings->compressionType);
665
- $metaThumb->setKeepExif($this->_settings->keepExif);
666
- $metaThumb->setCmyk2rgb($this->_settings->CMYKtoRGBconversion);
667
- $metaThumb->setResize($this->_settings->resizeImages);
668
- $metaThumb->setResizeWidth($this->_settings->resizeWidth);
669
- $metaThumb->setResizeHeight($this->_settings->resizeHeight);
670
- $ID = $this->spMetaDao->addImage($metaThumb);
671
- $metaThumb->setId($ID);
672
- $this->prioQ->push('C-' . $ID);
673
- }
674
- return $meta;
675
  }
 
676
  }
677
 
678
  public function optimizeCustomImage($id) {
@@ -1183,7 +1261,7 @@ class WPShortPixel {
1183
 
1184
  //for the moment deactivate the conversion for existing images
1185
  if($itemHandler->getType() == ShortPixelMetaFacade::MEDIA_LIBRARY_TYPE) { //currently only for ML
1186
- $rawMeta = $this->checkConvertMediaPng2Jpg($itemHandler->getRawMeta(), $itemHandler->getId());
1187
 
1188
  if(isset($rawMeta['type']) && $rawMeta['type'] == 'image/jpeg') {
1189
  $itemHandler->getMeta(true);
@@ -1383,7 +1461,7 @@ class WPShortPixel {
1383
  if($backup) return $backup;
1384
  }
1385
  }
1386
- return $ret;
1387
  }
1388
 
1389
  protected function setFilePerms($file) {
@@ -1410,6 +1488,8 @@ class WPShortPixel {
1410
 
1411
  //TODO specific to Media Lib., move accordingly
1412
  protected function doRestore($attachmentID, $rawMeta = null) {
 
 
1413
  $file = $origFile = get_attached_file($attachmentID);
1414
 
1415
  $itemHandler = new ShortPixelMetaFacade($attachmentID);
@@ -1514,6 +1594,7 @@ class WPShortPixel {
1514
  unset($crtMeta["ShortPixelImprovement"]);
1515
  unset($crtMeta['ShortPixel']);
1516
  unset($crtMeta['ShortPixelPng2Jpg']);
 
1517
  if($width && $height) {
1518
  $crtMeta['width'] = $width;
1519
  $crtMeta['height'] = $height;
@@ -1554,6 +1635,8 @@ class WPShortPixel {
1554
  $this->throwNotice('generic-err', $e->getMessage());
1555
  return false;
1556
  }
 
 
1557
  return $rawMeta;
1558
  }
1559
 
@@ -1891,6 +1974,7 @@ class WPShortPixel {
1891
  if($this->_settings->hasCustomFolders && $this->spMetaDao->getPendingMetaCount()) {
1892
  $this->_settings->customBulkPaused = 1;
1893
  }
 
1894
  }
1895
 
1896
  if(isset($_POST["bulkProcess"]))
@@ -2062,8 +2146,8 @@ class WPShortPixel {
2062
  if( count($files) > 2 ) { // The 2 accounts for . and ..
2063
  echo "<ul class='jqueryFileTree'>";
2064
  foreach( $files as $file ) {
2065
-
2066
- if($file == 'ShortpixelBackups') continue;
2067
 
2068
  $htmlRel = str_replace("'", "&apos;", $returnDir . $file);
2069
  $htmlName = htmlentities($file);
@@ -2243,7 +2327,7 @@ class WPShortPixel {
2243
  }
2244
 
2245
  public function renderSettingsMenu() {
2246
- if ( !current_user_can( 'manage_options' ) ) {
2247
  wp_die(__('You do not have sufficient permissions to access this page.','shortpixel-image-optimiser'));
2248
  }
2249
 
@@ -2255,7 +2339,7 @@ class WPShortPixel {
2255
  $notice = null;
2256
  $folderMsg = false;
2257
  $addedFolder = false;
2258
-
2259
  $this->_settings->redirectedSettings = 2;
2260
 
2261
  //by default we try to fetch the API Key from wp-config.php (if defined)
@@ -2296,7 +2380,7 @@ class WPShortPixel {
2296
  if( isset($_POST['save']) || isset($_POST['saveAdv'])
2297
  || (isset($_POST['validate']) && $_POST['validate'] == "validate")
2298
  || isset($_POST['removeFolder']) || isset($_POST['recheckFolder'])) {
2299
-
2300
  //handle API Key - common for save and validate.
2301
  $_POST['key'] = trim(str_replace("*", "", isset($_POST['key']) ? $_POST['key'] : $this->_settings->apiKey)); //the API key might not be set if the editing is disabled.
2302
 
@@ -2322,7 +2406,7 @@ class WPShortPixel {
2322
  $this->_settings->siteAuthPass = (isset($_POST['siteAuthPass']) ? $_POST['siteAuthPass'] : $this->_settings->siteAuthPass);
2323
  }
2324
 
2325
- $validityData = $this->getQuotaInformation($_POST['key'], true, isset($_POST['validate']) && $_POST['validate'] == "validate");
2326
 
2327
  $this->_settings->apiKey = $_POST['key'];
2328
  if($validityData['APIKeyValid']) {
@@ -2398,7 +2482,7 @@ class WPShortPixel {
2398
  $this->_settings->optimizeRetina = (isset($_POST['optimizeRetina']) ? 1: 0);
2399
  $this->_settings->optimizeUnlisted = (isset($_POST['optimizeUnlisted']) ? 1: 0);
2400
  $this->_settings->optimizePdfs = (isset($_POST['optimizePdfs']) ? 1: 0);
2401
- $this->_settings->png2jpg = (isset($_POST['png2jpg']) ? 1: 0);
2402
 
2403
  //die(var_dump($_POST['excludePatterns']));
2404
 
@@ -2524,7 +2608,7 @@ class WPShortPixel {
2524
  * @param type $validate - true if we are validating the api key, send also the domain name and number of pics
2525
  * @return type
2526
  */
2527
- public function getQuotaInformation($apiKey = null, $appendUserAgent = false, $validate = false) {
2528
 
2529
  if(is_null($apiKey)) { $apiKey = $this->_settings->apiKey; }
2530
 
@@ -2552,12 +2636,15 @@ class WPShortPixel {
2552
  $argsStr .= "&DomainCheck={$args['body']['DomainCheck']}&Info={$args['body']['Info']}&ImagesCount={$imageCount['mainFiles']}&ThumbsCount={$args['body']['ThumbsCount']}";
2553
  }
2554
  $args['body']['host'] = parse_url(get_site_url(),PHP_URL_HOST);
2555
- $argsStr .= "&url={$args['body']['host']}";
2556
  if(strlen($this->_settings->siteAuthUser)) {
2557
  $args['body']['user'] = $this->_settings->siteAuthUser;
2558
  $args['body']['pass'] = urlencode($this->_settings->siteAuthPass);
2559
  $argsStr .= "&user={$args['body']['user']}&pass={$args['body']['pass']}";
2560
  }
 
 
 
2561
 
2562
  $comm = array();
2563
 
@@ -2598,6 +2685,7 @@ class WPShortPixel {
2598
  $response = wp_remote_get($requestURL, $args);
2599
  $comm[] = array("sent" => "POST: " . $requestURL, "args" => $args, "received" => $response);
2600
  }
 
2601
 
2602
  $defaultData = array(
2603
  "APIKeyValid" => false,
@@ -2694,7 +2782,7 @@ class WPShortPixel {
2694
 
2695
  $file = get_attached_file($id);
2696
  $data = wp_get_attachment_metadata($id);
2697
- //if($extended) var_dump($data);
2698
  $fileExtension = strtolower(pathinfo($file, PATHINFO_EXTENSION));
2699
  $invalidKey = !$this->_settings->verifiedKey;
2700
  $quotaExceeded = $this->_settings->quotaExceeded;
@@ -2741,7 +2829,7 @@ class WPShortPixel {
2741
  $renderData['thumbsMissing'] = isset($data['ShortPixel']['thumbsMissing']) ? $data['ShortPixel']['thumbsMissing'] : array();
2742
  $renderData['retinasOpt'] = isset($data['ShortPixel']['retinasOpt']) ? $data['ShortPixel']['retinasOpt'] : null;
2743
  $renderData['exifKept'] = isset($data['ShortPixel']['exifKept']) ? $data['ShortPixel']['exifKept'] : null;
2744
- $renderData['png2jpg'] = isset($data['ShortPixelPng2Jpg']);
2745
  $renderData['date'] = isset($data['ShortPixel']['date']) ? $data['ShortPixel']['date'] : null;
2746
  $renderData['quotaExceeded'] = $quotaExceeded;
2747
  $webP = 0;
@@ -2805,6 +2893,59 @@ class WPShortPixel {
2805
  }
2806
  }
2807
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2808
  function optimizationPercentIfPng2Jpg($meta) {
2809
  $png2jpgPercent = isset($meta['ShortPixelPng2Jpg']['optimizationPercent']) ? $meta['ShortPixelPng2Jpg']['optimizationPercent'] : 0;
2810
  return number_format(100.0 - (100.0 - $png2jpgPercent) * (100.0 - $meta['ShortPixelImprovement']) / 100.0, 2);
@@ -3181,6 +3322,13 @@ class WPShortPixel {
3181
  </script><?php
3182
  }
3183
 
 
 
 
 
 
 
 
3184
 
3185
  /* public function getEncryptedData() {
3186
  return base64_encode(self::encrypt($this->getApiKey() . "|" . get_site_url(), "sh0r+Pix3l8im1N3r"));
54
  //Media custom column
55
  add_filter( 'manage_media_columns', array( &$this, 'columns' ) );//add media library column header
56
  add_action( 'manage_media_custom_column', array( &$this, 'generateCustomColumn' ), 10, 2 );//generate the media library column
57
+ //Sort and filter on ShortPixel Compression column
58
+ add_filter( 'manage_upload_sortable_columns', array( &$this, 'columnRegisterSortable') );
59
+ add_filter( 'request', array( &$this, 'columnOrderFilterBy') );
60
+ add_action('restrict_manage_posts', array( &$this, 'mediaAddFilterDropdown'));
61
  //Edit media meta box
62
  add_action( 'add_meta_boxes', array( &$this, 'shortpixelInfoBox') );
63
  //for cleaning up the WebP images when an attachment is deleted
105
  add_action( 'admin_bar_menu', array( &$this, 'toolbar_shortpixel_processing'), 999 );
106
  //deactivate plugin
107
  add_action( 'admin_post_shortpixel_deactivate_plugin', array(&$this, 'deactivatePlugin'));
108
+ //only if the key is not yet valid or the user hasn't bought any credits.
109
+ $stats = $this->_settings->currentStats;
110
+ $totalCredits = isset($stats["APICallsQuotaNumeric"]) ? $stats['APICallsQuotaNumeric'] + $stats['APICallsQuotaOneTimeNumeric'] : 0;
111
+ if(!$this->_settings->verifiedKey || $totalCredits < 4000) {
112
+ require_once 'view/shortpixel-feedback.php';
113
+ new ShortPixelFeedback( SHORTPIXEL_PLUGIN_FILE, 'shortpixel-image-optimiser', $this->_settings->apiKey, $this);
114
+ }
115
  }
116
 
117
  //automatic optimization
181
 
182
  public static function shortPixelDeactivatePlugin()//reset some params to avoid trouble for plugins that were activated/deactivated/activated
183
  {
 
184
  ShortPixelQueue::resetBulk();
185
  ShortPixelQueue::resetPrio();
186
  WPShortPixelSettings::onDeactivate();
187
  }
188
+
189
+ public static function shortPixelUninstallPlugin()//reset some params to avoid trouble for plugins that were activated/deactivated/activated
190
+ {
191
+ $settings = new WPShortPixelSettings();
192
+ if($settings->removeSettingsOnDeletePlugin == 1) {
193
+ WPShortPixelSettings::debugResetOptions();
194
+ }
195
+ }
196
+
197
  public function getConflictingPlugins() {
198
  $conflictPlugins = array(
199
  'WP Smush - Image Optimization' => 'wp-smushit/wp-smush.php',
281
  //looks like the user hasn't got enough credits to process the monthly images, display a notice telling this
282
  ShortPixelView::displayActivationNotice('upgmonth', array('monthAvg' => $this->getMonthAvg($stats), 'monthlyQuota' => $quotaData['APICallsQuotaNumeric']));
283
  }
 
284
  }
285
  }
286
 
399
  wp_register_script('short-pixel' . $this->jsSuffix, plugins_url('/res/js/short-pixel' . $this->jsSuffix,SHORTPIXEL_PLUGIN_FILE), array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION);
400
  $jsTranslation = array(
401
  'optimizeWithSP' => __( 'Optimize with ShortPixel', 'shortpixel-image-optimiser' ),
402
+ 'redoLossy' => __( 'Re-optimize Lossy', 'shortpixel-image-optimiser' ),
403
+ 'redoGlossy' => __( 'Re-optimize Glossy', 'shortpixel-image-optimiser' ),
404
+ 'redoLossless' => __( 'Re-optimize Lossless', 'shortpixel-image-optimiser' ),
405
+ 'restoreOriginal' => __( 'Restore Originals', 'shortpixel-image-optimiser' ),
406
  'changeMLToListMode' => __( 'In order to access the ShortPixel Optimization actions and info, please change to {0}List View{1}List View{2}Dismiss{3}', 'shortpixel-image-optimiser' ),
407
  'alertOnlyAppliesToNewImages' => __( 'This type of optimization will apply to new uploaded images. Images that were already processed will not be re-optimized unless you restart the bulk process.', 'shortpixel-image-optimiser' ),
408
  'areYouSureStopOptimizing' => __( 'Are you sure you want to stop optimizing the folder {0}?', 'shortpixel-image-optimiser' ),
494
  $wp_list_table = _get_list_table('WP_Media_List_Table');
495
  $action = $wp_list_table->current_action();
496
 
497
+ if(strpos($action, 'short-pixel-bulk') === 0 ) {
498
+ // security check
499
+ check_admin_referer('bulk-media');
500
+ if(!is_array($_GET['media'])) {
501
+ return;
502
+ }
503
+ $mediaIds = array_reverse($_GET['media']);
504
+ }
505
+
506
  switch($action) {
507
  // 2. Perform the action
508
  case 'short-pixel-bulk':
 
 
 
 
 
 
509
  foreach( $mediaIds as $ID ) {
510
  $meta = wp_get_attachment_metadata($ID);
511
  if( ( !isset($meta['ShortPixel']) //never touched by ShortPixel
517
  }
518
  }
519
  break;
520
+ case 'short-pixel-bulk-lossy':
521
+ $this->restoreAndQueueList($mediaIds, 'lossy');
522
+ break;
523
+ case 'short-pixel-bulk-glossy':
524
+ $this->restoreAndQueueList($mediaIds, 'glossy');
525
+ break;
526
+ case 'short-pixel-bulk-lossless':
527
+ $this->restoreAndQueueList($mediaIds, 'lossless');
528
+ break;
529
+ case 'short-pixel-bulk-restore':
530
+ foreach( $mediaIds as $ID ) {
531
+ $this->doRestore($ID);
532
+ }
533
+ break;
534
+ }
535
+ }
536
+
537
+ protected function restoreAndQueueList($mediaIds, $type) {
538
+ foreach( $mediaIds as $ID ) {
539
+ $meta = wp_get_attachment_metadata($ID);
540
+ if(isset($meta['ShortPixel']['type']) && $meta['ShortPixel']['type'] !== $type) {
541
+ $meta = $this->doRestore($ID);
542
+ if($meta) { //restore succeeded
543
+ $meta['ShortPixel'] = array("type" => $type, 'WaitingProcessing' => true);
544
+ wp_update_attachment_metadata($ID, $meta);
545
+ $this->prioQ->push($ID);
546
+ }
547
+ }
548
  }
549
  }
550
 
659
  * @param type $ID
660
  * @return string
661
  */
662
+ public function checkConvertMediaPng2Jpg($itemHandler) {
663
  $converter = new ShortPixelPng2Jpg($this->_settings);
664
+ return $converter->checkConvertMediaPng2Jpg($itemHandler);
665
+ }
666
+
667
+ public function handleGravityFormsImageField($value) {
668
+ $uploadDir = wp_upload_dir();
669
+ if(!($folder = $this->spMetaDao->getFolder($uploadDir['basedir'] . '/gravity_forms'))) {
670
+ return;
671
+ }
672
+ if(strpos($value , '|:|')) {
673
+ $cleanup = explode('|:|', $value);
674
+ $value = $cleanup[0];
675
+ }
676
+ //ShortPixel is monitoring the gravity forms folder, add the image to queue
677
+ $localPath = str_replace($uploadDir['baseurl'], $uploadDir['basedir'], $value);
678
+
679
+ return $this->addPathToCustomFolder($localPath, $folder->getId(), 0);
680
  }
681
 
682
  /**
683
  * this is hooked onto the NextGen upload
684
  * @param type $image
685
  */
686
+ public function handleNextGenImageUpload($image)
687
+ {
688
+ if ($this->_settings->includeNextGen == 1) {
689
  $imageFsPath = ShortPixelNextGenAdapter::getImageAbspath($image);
690
 
691
  $customFolders = $this->spMetaDao->getFolders();
692
 
693
  $folderId = -1;
694
+ foreach ($customFolders as $folder) {
695
+ if (strpos($imageFsPath, $folder->getPath()) === 0) {
696
  $folderId = $folder->getId();
697
  break;
698
  }
699
  }
700
+ if ($folderId == -1) { //if not found, create
701
  $galleryPath = dirname($imageFsPath);
702
  $folder = new ShortPixelFolder(array("path" => $galleryPath), $this->_settings->excludePatterns);
703
  $folderMsg = $this->spMetaDao->saveFolder($folder);
704
  $folderId = $folder->getId();
705
  //self::log("NG Image Upload: created folder from path $galleryPath : Folder info: " . json_encode($folder));
706
  }
707
+
708
+ return $this->addPathToCustomFolder($imageFsPath, $folderId, $image->pid);
709
+ }
710
+ }
711
+
712
+ protected function addPathToCustomFolder($imageFsPath, $folderId, $pid) {
713
+ //prevent adding it multiple times if the action is called repeatedly (Gravity Forms does that)
714
+ $existing = $this->spMetaDao->getMetaForPath($imageFsPath);
715
+ if($existing) {
716
+ return $existing;
717
+ }
718
+ $pathParts = explode('/', trim($imageFsPath));
719
+ //Add the main image
720
+ $meta = new ShortPixelMeta();
721
+ $meta->setPath($imageFsPath);
722
+ $meta->setName($pathParts[count($pathParts) - 1]);
723
+ $meta->setFolderId($folderId);
724
+ $meta->setExtMetaId($pid); // do this only for main image, not for thumbnais.
725
+ $meta->setCompressionType($this->_settings->compressionType);
726
+ $meta->setKeepExif($this->_settings->keepExif);
727
+ $meta->setCmyk2rgb($this->_settings->CMYKtoRGBconversion);
728
+ $meta->setResize($this->_settings->resizeImages);
729
+ $meta->setResizeWidth($this->_settings->resizeWidth);
730
+ $meta->setResizeHeight($this->_settings->resizeHeight);
731
+ $ID = $this->spMetaDao->addImage($meta);
732
+ $meta->setId($ID);
733
+ $this->prioQ->push('C-' . $ID);
734
+ //add the thumb image if exists
735
+ $pathParts[] = "thumbs_" . $pathParts[count($pathParts) - 1];
736
+ $pathParts[count($pathParts) - 2] = "thumbs";
737
+ $thumbPath = implode('/', $pathParts);
738
+ if(file_exists($thumbPath)) {
739
+ $metaThumb = new ShortPixelMeta();
740
+ $metaThumb->setPath($thumbPath);
741
+ $metaThumb->setName($pathParts[count($pathParts) - 1]);
742
+ $metaThumb->setFolderId($folderId);
743
+ $metaThumb->setCompressionType($this->_settings->compressionType);
744
+ $metaThumb->setKeepExif($this->_settings->keepExif);
745
+ $metaThumb->setCmyk2rgb($this->_settings->CMYKtoRGBconversion);
746
+ $metaThumb->setResize($this->_settings->resizeImages);
747
+ $metaThumb->setResizeWidth($this->_settings->resizeWidth);
748
+ $metaThumb->setResizeHeight($this->_settings->resizeHeight);
749
+ $ID = $this->spMetaDao->addImage($metaThumb);
750
+ $metaThumb->setId($ID);
751
  $this->prioQ->push('C-' . $ID);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
752
  }
753
+ return $meta;
754
  }
755
 
756
  public function optimizeCustomImage($id) {
1261
 
1262
  //for the moment deactivate the conversion for existing images
1263
  if($itemHandler->getType() == ShortPixelMetaFacade::MEDIA_LIBRARY_TYPE) { //currently only for ML
1264
+ $rawMeta = $this->checkConvertMediaPng2Jpg($itemHandler);
1265
 
1266
  if(isset($rawMeta['type']) && $rawMeta['type'] == 'image/jpeg') {
1267
  $itemHandler->getMeta(true);
1461
  if($backup) return $backup;
1462
  }
1463
  }
1464
+ return apply_filters("shortpixel_backup_folder", $ret);
1465
  }
1466
 
1467
  protected function setFilePerms($file) {
1488
 
1489
  //TODO specific to Media Lib., move accordingly
1490
  protected function doRestore($attachmentID, $rawMeta = null) {
1491
+ do_action("shortpixel_before_restore_image", $attachmentID);
1492
+
1493
  $file = $origFile = get_attached_file($attachmentID);
1494
 
1495
  $itemHandler = new ShortPixelMetaFacade($attachmentID);
1594
  unset($crtMeta["ShortPixelImprovement"]);
1595
  unset($crtMeta['ShortPixel']);
1596
  unset($crtMeta['ShortPixelPng2Jpg']);
1597
+ delete_post_meta($ID, '_shortpixel_status');
1598
  if($width && $height) {
1599
  $crtMeta['width'] = $width;
1600
  $crtMeta['height'] = $height;
1635
  $this->throwNotice('generic-err', $e->getMessage());
1636
  return false;
1637
  }
1638
+
1639
+ do_action("shortpixel_after_restore_image", $attachmentID);
1640
  return $rawMeta;
1641
  }
1642
 
1974
  if($this->_settings->hasCustomFolders && $this->spMetaDao->getPendingMetaCount()) {
1975
  $this->_settings->customBulkPaused = 1;
1976
  }
1977
+ $this->_settings->cancelPointer = NULL;
1978
  }
1979
 
1980
  if(isset($_POST["bulkProcess"]))
2146
  if( count($files) > 2 ) { // The 2 accounts for . and ..
2147
  echo "<ul class='jqueryFileTree'>";
2148
  foreach( $files as $file ) {
2149
+
2150
+ if($file == 'ShortpixelBackups' || ShortPixelMetaFacade::isMediaSubfolder($postDir . $file, false)) continue;
2151
 
2152
  $htmlRel = str_replace("'", "&apos;", $returnDir . $file);
2153
  $htmlName = htmlentities($file);
2327
  }
2328
 
2329
  public function renderSettingsMenu() {
2330
+ if ( !current_user_can( 'manage_options' ) ) {
2331
  wp_die(__('You do not have sufficient permissions to access this page.','shortpixel-image-optimiser'));
2332
  }
2333
 
2339
  $notice = null;
2340
  $folderMsg = false;
2341
  $addedFolder = false;
2342
+
2343
  $this->_settings->redirectedSettings = 2;
2344
 
2345
  //by default we try to fetch the API Key from wp-config.php (if defined)
2380
  if( isset($_POST['save']) || isset($_POST['saveAdv'])
2381
  || (isset($_POST['validate']) && $_POST['validate'] == "validate")
2382
  || isset($_POST['removeFolder']) || isset($_POST['recheckFolder'])) {
2383
+
2384
  //handle API Key - common for save and validate.
2385
  $_POST['key'] = trim(str_replace("*", "", isset($_POST['key']) ? $_POST['key'] : $this->_settings->apiKey)); //the API key might not be set if the editing is disabled.
2386
 
2406
  $this->_settings->siteAuthPass = (isset($_POST['siteAuthPass']) ? $_POST['siteAuthPass'] : $this->_settings->siteAuthPass);
2407
  }
2408
 
2409
+ $validityData = $this->getQuotaInformation($_POST['key'], true, isset($_POST['validate']) && $_POST['validate'] == "validate", $_POST);
2410
 
2411
  $this->_settings->apiKey = $_POST['key'];
2412
  if($validityData['APIKeyValid']) {
2482
  $this->_settings->optimizeRetina = (isset($_POST['optimizeRetina']) ? 1: 0);
2483
  $this->_settings->optimizeUnlisted = (isset($_POST['optimizeUnlisted']) ? 1: 0);
2484
  $this->_settings->optimizePdfs = (isset($_POST['optimizePdfs']) ? 1: 0);
2485
+ $this->_settings->png2jpg = (isset($_POST['png2jpg']) ? (isset($_POST['png2jpgForce']) ? 2 : 1): 0);
2486
 
2487
  //die(var_dump($_POST['excludePatterns']));
2488
 
2608
  * @param type $validate - true if we are validating the api key, send also the domain name and number of pics
2609
  * @return type
2610
  */
2611
+ public function getQuotaInformation($apiKey = null, $appendUserAgent = false, $validate = false, $settings = false) {
2612
 
2613
  if(is_null($apiKey)) { $apiKey = $this->_settings->apiKey; }
2614
 
2636
  $argsStr .= "&DomainCheck={$args['body']['DomainCheck']}&Info={$args['body']['Info']}&ImagesCount={$imageCount['mainFiles']}&ThumbsCount={$args['body']['ThumbsCount']}";
2637
  }
2638
  $args['body']['host'] = parse_url(get_site_url(),PHP_URL_HOST);
2639
+ $argsStr .= "&host={$args['body']['host']}";
2640
  if(strlen($this->_settings->siteAuthUser)) {
2641
  $args['body']['user'] = $this->_settings->siteAuthUser;
2642
  $args['body']['pass'] = urlencode($this->_settings->siteAuthPass);
2643
  $argsStr .= "&user={$args['body']['user']}&pass={$args['body']['pass']}";
2644
  }
2645
+ if($settings !== false) {
2646
+ $args['body']['Settings'] = $settings;
2647
+ }
2648
 
2649
  $comm = array();
2650
 
2685
  $response = wp_remote_get($requestURL, $args);
2686
  $comm[] = array("sent" => "POST: " . $requestURL, "args" => $args, "received" => $response);
2687
  }
2688
+ self::log("API STATUS COMM: " . json_encode($comm));
2689
 
2690
  $defaultData = array(
2691
  "APIKeyValid" => false,
2782
 
2783
  $file = get_attached_file($id);
2784
  $data = wp_get_attachment_metadata($id);
2785
+ //if($extended) {var_dump(wp_get_attachment_url($id)); var_dump($data);}
2786
  $fileExtension = strtolower(pathinfo($file, PATHINFO_EXTENSION));
2787
  $invalidKey = !$this->_settings->verifiedKey;
2788
  $quotaExceeded = $this->_settings->quotaExceeded;
2829
  $renderData['thumbsMissing'] = isset($data['ShortPixel']['thumbsMissing']) ? $data['ShortPixel']['thumbsMissing'] : array();
2830
  $renderData['retinasOpt'] = isset($data['ShortPixel']['retinasOpt']) ? $data['ShortPixel']['retinasOpt'] : null;
2831
  $renderData['exifKept'] = isset($data['ShortPixel']['exifKept']) ? $data['ShortPixel']['exifKept'] : null;
2832
+ $renderData['png2jpg'] = isset($data['ShortPixelPng2Jpg']) ? $data['ShortPixelPng2Jpg'] : 0;
2833
  $renderData['date'] = isset($data['ShortPixel']['date']) ? $data['ShortPixel']['date'] : null;
2834
  $renderData['quotaExceeded'] = $quotaExceeded;
2835
  $webP = 0;
2893
  }
2894
  }
2895
 
2896
+ function columnRegisterSortable($columns) {
2897
+ $columns['wp-shortPixel'] = 'ShortPixel Compression';
2898
+ return $columns;
2899
+ }
2900
+
2901
+ function columnOrderFilterBy($vars) {
2902
+ if ( isset( $vars['orderby'] ) && 'ShortPixel Compression' == $vars['orderby'] ) {
2903
+ $vars = array_merge( $vars, array(
2904
+ 'meta_key' => '_shortpixel_status',
2905
+ 'orderby' => 'meta_value_num',
2906
+ ) );
2907
+ }
2908
+ if ( 'upload.php' == $GLOBALS['pagenow'] && !empty( $_GET['shortpixel_status'] ) ) {
2909
+
2910
+ $status = $_GET['shortpixel_status'];
2911
+ $metaKey = '_shortpixel_status';
2912
+ $metaCompare = $status == 0 ? 'NOT EXISTS' : ($status < 0 ? '<' : '=');
2913
+
2914
+ $vars = array_merge( $vars, array(
2915
+ 'meta_query' => array(
2916
+ array(
2917
+ 'key' => $metaKey,
2918
+ 'value' => $status,
2919
+ 'compare' => $metaCompare,
2920
+ ),
2921
+ )
2922
+ ));
2923
+ }
2924
+ return $vars;
2925
+ }
2926
+
2927
+ function mediaAddFilterDropdown() {
2928
+ $scr = get_current_screen();
2929
+ if ( $scr->base !== 'upload' ) return;
2930
+
2931
+ $status = filter_input(INPUT_GET, 'shortpixel_status', FILTER_SANITIZE_STRING );
2932
+ $selected = (int)$status > 0 ? $status : 0;
2933
+ $args = array(
2934
+ 'show_option_none' => 'ShortPixel',
2935
+ 'name' => 'shortpixel_status',
2936
+ 'selected' => $selected
2937
+ );
2938
+ // wp_dropdown_users( $args );
2939
+
2940
+ echo("<select name='shortpixel_status' id='shortpixel_status'>\n"
2941
+ . "\t<option value='0'" . ($status == 0 ? " selected='selected'" : "") . ">All images</option>\n"
2942
+ . "\t<option value='2'" . ($status == 2 ? " selected='selected'" : "") . ">Optimized</option>\n"
2943
+ . "\t<option value='none'" . ($status == 'none' ? " selected='selected'" : "") . ">Unoptimized</option>\n"
2944
+ . "\t<option value='1'" . ($status == 1 ? " selected='selected'" : "") . ">Pending</option>\n"
2945
+ . "\t<option value='-1'" . ($status < 0 ? " selected='selected'" : "") . ">Errors</option>\n"
2946
+ . "</select>");
2947
+ }
2948
+
2949
  function optimizationPercentIfPng2Jpg($meta) {
2950
  $png2jpgPercent = isset($meta['ShortPixelPng2Jpg']['optimizationPercent']) ? $meta['ShortPixelPng2Jpg']['optimizationPercent'] : 0;
2951
  return number_format(100.0 - (100.0 - $png2jpgPercent) * (100.0 - $meta['ShortPixelImprovement']) / 100.0, 2);
3322
  </script><?php
3323
  }
3324
 
3325
+ public function validateFeedback($params) {
3326
+ if(isset($params['remove-settings'])) {
3327
+ $this->_settings->removeSettingsOnDeletePlugin = $params['remove-settings'];
3328
+ }
3329
+ return $params;
3330
+ }
3331
+
3332
 
3333
  /* public function getEncryptedData() {
3334
  return base64_encode(self::encrypt($this->getApiKey() . "|" . get_site_url(), "sh0r+Pix3l8im1N3r"));
class/wp-shortpixel-settings.php CHANGED
@@ -51,7 +51,10 @@ class WPShortPixelSettings {
51
  'includeNextGen' => array('key' => 'wp-short-pixel-include-next-gen', 'default' => null, 'group' => 'options'),
52
  'hasCustomFolders' => array('key' => 'wp-short-pixel-has-custom-folders', 'default' => false, 'group' => 'options'),
53
  'customBulkPaused' => array('key' => 'wp-short-pixel-custom-bulk-paused', 'default' => false, 'group' => 'options'),
54
-
 
 
 
55
  //stats, notices, etc.
56
  'currentStats' => array('key' => 'wp-short-pixel-current-total-files', 'default' => null, 'group' => 'state'),
57
  'fileCount' => array('key' => 'wp-short-pixel-fileCount', 'default' => 0, 'group' => 'state'),
@@ -134,6 +137,7 @@ class WPShortPixelSettings {
134
  update_option( 'wp-short-pixel-activation-date', time(), 'no');
135
  delete_option( 'wp-short-pixel-bulk-last-status');
136
  delete_option( 'wp-short-pixel-current-total-files');
 
137
  $dismissed = get_option('wp-short-pixel-dismissed-notices', array());
138
  if(isset($dismissed['compat'])) {
139
  unset($dismissed['compat']);
51
  'includeNextGen' => array('key' => 'wp-short-pixel-include-next-gen', 'default' => null, 'group' => 'options'),
52
  'hasCustomFolders' => array('key' => 'wp-short-pixel-has-custom-folders', 'default' => false, 'group' => 'options'),
53
  'customBulkPaused' => array('key' => 'wp-short-pixel-custom-bulk-paused', 'default' => false, 'group' => 'options'),
54
+
55
+ //uninstall
56
+ 'removeSettingsOnDeletePlugin' => array('key' => 'wp-short-pixel-remove-settings-on-delete-plugin', 'default' => false, 'group' => 'options'),
57
+
58
  //stats, notices, etc.
59
  'currentStats' => array('key' => 'wp-short-pixel-current-total-files', 'default' => null, 'group' => 'state'),
60
  'fileCount' => array('key' => 'wp-short-pixel-fileCount', 'default' => 0, 'group' => 'state'),
137
  update_option( 'wp-short-pixel-activation-date', time(), 'no');
138
  delete_option( 'wp-short-pixel-bulk-last-status');
139
  delete_option( 'wp-short-pixel-current-total-files');
140
+ delete_option(self::$_optionsMap['removeSettingsOnDeletePlugin']['key']);
141
  $dismissed = get_option('wp-short-pixel-dismissed-notices', array());
142
  if(isset($dismissed['compat'])) {
143
  unset($dismissed['compat']);
readme.txt CHANGED
@@ -4,7 +4,7 @@ Tags: compress, image, compression, optimize, image optimizer, image optimiser,
4
  Requires at least: 3.2.0
5
  Tested up to: 4.9
6
  Requires PHP: 5.2
7
- Stable tag: 4.10.5
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -14,8 +14,6 @@ Speed up your website and boost your SEO by compressing old & new images and PDF
14
 
15
  **A freemium easy to use, comprehensive, stable and frequently updated image compression plugin supported by the friendly team that created it. :)**
16
 
17
- We are GDPR ready! <a href="https://shortpixel.com/privacy#gdpr" target="_blank">Read more.</a>
18
-
19
  Increase your website's SEO ranking, number of visitors and ultimately your sales by optimizing any image or PDF document on your website.
20
  ShortPixel is an easy to use, lightweight, install-and-forget-about-it <a href="https://shortpixel.com" target="_blank">image optimization</a> plugin that can compress all your past images and PDF documents with a single click. New images are automatically resized/rescaled and optimized on the fly, in the background.
21
 
@@ -31,7 +29,7 @@ Make an instant <a href="http://shortpixel.com/image-compression-test" target="_
31
 
32
  **Why is ShortPixel the best choice when it comes to image optimization or PDF compression?**
33
 
34
- * popular plugin with over 50,000 active installations according to WordPress
35
  * compress JPG, PNG, GIF (still or animated) images and also PDF documents
36
  * option to automatically convert PNG to JPG if that will result in smaller images. Ideal for large images in PNG format.
37
  * no file size limit
@@ -39,13 +37,15 @@ Make an instant <a href="http://shortpixel.com/image-compression-test" target="_
39
  * option to include the generated WebP images into the front-end pages by using the &lt;picture&gt; tag instead of &lt;img&gt;
40
  * compatible with WP Retina 2x - all **retina images** are automatically compressed. <a href="http://blog.shortpixel.com/how-to-use-optimized-retina-images-on-your-wordpress-site-for-best-user-experience-on-apple-devices/" target="_blank">How to benefit from Retina displays?</a>
41
  * optimize thumbnails as well as featured images. You can also **select individual thumbnails to exclude** from optimization.
42
- * ability to optimize any image on your site including images in **NextGEN Gallery** and any other image gallery or slider
 
43
  * featured images can be automatically resized before being optimized with 2 different options. No need for additional plugins like Imsanity
44
  * CMYK to RGB conversion
45
  * **24h <a href="https://wordpress.org/support/plugin/shortpixel-image-optimiser/reviews/?filter=5" target="_blank">stellar support</a>** (24/7) directly from developers.
46
  * easily **test lossy/lossless** versions of the images with a single click in your Media Library
47
  * **great for photographers**: <a href="http://blog.shortpixel.com/how-much-smaller-can-be-images-without-exif-icc/" target="_blank">keep or remove EXIF</a> data from your images, compress images with lossless option
48
  * works well with both HTTPS and HTTP websites
 
49
  * you can run ShortPixel plugin on **multiple websites** or on a **multisite** with a **single API Key**
50
  * it is **safe to test** and use the plugin: all the original images can be restored with a click, either one by one or in bulk
51
  * 'Bulk' optimize all the existing images in Media Library or in any gallery with one click
@@ -57,11 +57,12 @@ Make an instant <a href="http://shortpixel.com/image-compression-test" target="_
57
  * compatible with watermarking plugins
58
  * option to deactivate auto-optimizing images on upload
59
  * images that are optimized less that 5% are bonus
60
- * WooCommerce, WP offload S3 compatible
61
  * 40 days optimization report with all image details and overall statistics
 
62
  * **free optimization credits for non-profits**, <a href="https://shortpixel.com/contact" target="_blank">contact us</a> for details
63
 
64
- **How much it costs?**
65
  ShortPixel comes with 100 free credits/month and additional credits can be bought with as little as $4.99 for 5,000 image credits.
66
  Check out <a href="https://shortpixel.com/pricing" target="_blank">our prices</a>.
67
 
@@ -208,6 +209,16 @@ Let's get ShortPixel plugin running on your WordPress website:
208
 
209
  The ShortPixel team is here to help. <a href="https://shortpixel.com/contact">Contact us</a>!
210
 
 
 
 
 
 
 
 
 
 
 
211
  == Screenshots ==
212
 
213
  1. Bulk optimization running. (Media>Bulk ShortPixel)
@@ -230,6 +241,20 @@ The ShortPixel team is here to help. <a href="https://shortpixel.com/contact">Co
230
 
231
  == Changelog ==
232
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
233
  = 4.10.5 =
234
  * GDPR compliance
235
 
@@ -273,525 +298,5 @@ The ShortPixel team is here to help. <a href="https://shortpixel.com/contact">Co
273
  * fix slider optimized percent over the bulk warning box.
274
  * display the x close link for the bulk warning box.
275
 
276
- = 4.8.10 =
277
- * restore compatibility with PHP 5.2.x
278
- * finding unlisted thumbnails - don't bother if dialog dismissed.
279
- * force JS initialization after 10 sec. if external error on the document.load thread prevented it.
280
- * onboarding - small text changes
281
- * images added from the front-end sometimes have get_attached_file() null when hook called, delay the check and processing in this case, instead of marking as Optimization N/A.
282
- * compatibility with s3-offload pro plugin
283
- * fix to time estimate at bulk, which sometimes was displaying x hours and 60 minutes left.
284
- * confirm popup when deleting backups.
285
-
286
- = 4.8.9 =
287
- * On some multisites installed in a subdirectory, the get_home_path() doesn't return the subdirectory, fallback to ABSPATH
288
- * Sometimes images are not PNG even if they have .png extension. Don't try to convert them if imagecreatefrompng returns false.
289
- * Get an aproximate row count for InnoDB tables to optimize the speed, but fallback to normal count(*) for MyISAM
290
- * Fix several warnings ($thumbsMissing not an array, $found is not set, etc.)
291
- * Return error message when folder could not be found, when adding other media folders
292
- * More info to some API errors
293
-
294
-
295
- = 4.8.8 =
296
- * fix for trying to convert .png files that are not png actually
297
- * fix for installs which don't have PHP GD - deactivate the png 2 jpg conversion
298
- * fix for unserialize warnings
299
- * improvements in bulk speed when passing through already optimized images.
300
- * fix unsupported usage of const by third party punycode.js
301
- * fix emails with new root domains like user@domain.store
302
- * fix unsupported flock problem
303
- * hidden button pending cleanup
304
- * fix javascript not being able to generate the actions menu upon image being optimized while inside the image edit and displaying false instead
305
-
306
- = 4.8.7 =
307
- * fix bug of the resize minimum size alert not dismissing
308
-
309
- = 4.8.6 =
310
- * alert user when the plugin doesn't have rights to write to the uploads folder
311
-
312
- = 4.8.5 =
313
- * drop usage of the PHP session / wp_option for the priority queue - use a flat file instead.
314
-
315
- = 4.8.4 =
316
- * fix compatibility problem with WP 4.9 when editing source files with the new built-in editor
317
- * fix restore converted PNGs in some situations
318
- * fix some minor warnings
319
- * refactor png2jpg functions in another class
320
- * add compatibility with PHP 5.2
321
- * generate WebP urls - account for settings with different scheme (http - https)
322
-
323
- = 4.8.2 =
324
- * fix minified punycode.js not generated because of ECMA6 not supported by YUI...
325
-
326
- = 4.8.1 =
327
- * fix notice that would not dismiss
328
-
329
- = 4.8.0 =
330
- * propose best plans options for optimizing all images
331
- * option to optimize or not the found unlisted thumbs, alert the user about them.
332
- * convert png to jpeg also when doing bulk if option set. Also search for usages of the image and replace the URLs in the content.
333
- * fix compatbility problem with S3 Offload which caused sending two different sets of URLs for an image.
334
- * trim site_url output - found a client case where it ended with a tab...
335
- * all wp_options with autoload=no
336
- * subscribe and get the API Key directly from the plugin
337
- * minify all js and css files
338
- * performance improvements for the picture tag generation
339
- * retina versions of the icons
340
- * fix compatibility with PHP 5.3 for using class:: inside closures
341
- * fix "Optimize 0 thumbnails" in column menu generated from Javascript.
342
-
343
- = 4.7.2 =
344
- * fix wrong use of _ function which displayed warning
345
-
346
- = 4.7.1 =
347
- * Deactivate conversion from PNG to JPG for the previous images, until we find a solution for the posts that refer these images.
348
- * Minor fix to bulk (last item in Media Library sometimes was left unoptimized)
349
-
350
- = 4.7.0 =
351
- * convert PNG images to JPG option
352
- * action called upon optimizing an image: do_action('shortpixel_image_optimized', $post_id);
353
- * monitor Other Media folders for changes every hour
354
- * button to delete all ShortPixel metadata making ShortPixel forget it optimized the images in Media Library
355
- * plugin images at @2x
356
- * cleanup Other Media tables
357
- * fix wp-options that would not save in some circumstances
358
- * fix generate webp <picture> tags when post guids are absolute URLs and image URLs are changed, or when site has HTTP/HTTPS versions
359
- * fix problem with AMP pages when generating the <picture> tags - when using AMP for WP plugin AMP pages are not changed.
360
-
361
- = 4.6.0 =
362
- * add a filter option to the Other Media table
363
- * fixes in order to comply with WP plugin guidelines
364
-
365
- = 4.5.5 =
366
- * max thumbs constant - no more than this number of thumbs will be optimized in one pass
367
- * fix problem with webp <picture> tag when using Fusion Builder
368
- * really hide the API key everywhere when configured so
369
-
370
- = 4.5.3 =
371
-
372
- * fix Javascript error in bulk in some cases
373
-
374
- = 4.5.2 =
375
-
376
- * fix readme again
377
-
378
- = 4.5.1 =
379
-
380
- * fix readme
381
-
382
- = 4.5.0 =
383
-
384
- * replace img tags in front-end with picture tags, and include the webp images
385
- * actions menu in Media Library
386
- * option to compare the optimized (main) image with the original in Media Library
387
-
388
- = 4.4.2 =
389
-
390
- * fix wrong custom path in some cases
391
-
392
- = 4.4.1 =
393
-
394
- * fix warnings on PHP 7.1 for empty array settings.
395
-
396
- = 4.4.0 =
397
-
398
- * exclude images based on patterns or image sizes, exclude paths based on patterns
399
- * avoid using basename as a fallback for non-UTF8 filenames but instead use own code (basename strips first character if it's not ASCII-128 - for example ISO/IEC 8859-2)
400
- * processing spinning indicator in the admin top bar with CSS to display OK on all admin themes.
401
-
402
- = 4.3.1 =
403
-
404
- * hide API Key on single sites option ( define SHORTPIXEL_HIDE_API_KEY true in wp-config.php)
405
- * fix for PHP installs on Linux that don't have the posix functions available
406
- * show an alert when the plugin is no longer able to contact our servers (initially was alerting only before key validation)
407
-
408
- = 4.3.0 =
409
-
410
- * a new level of optimization intermediate between lossy and lossless: glossy
411
- * bulk restore for Media Library
412
- * fix warning when activating plugin in some situations
413
- * empty backups button always visible (also when the backup option is unchecked)
414
-
415
- = 4.2.9 =
416
-
417
- * fix bug when thumbnails had numeric indexes in the sizes metadata array
418
- * fix bug when bulk reoptimizing on some specific conditions
419
-
420
- = 4.2.8 =
421
-
422
- * fix bug when searching for thumbanils of files with same prefix
423
- * fix bug when several successive images have all files missing
424
-
425
- = 4.2.7 =
426
-
427
- * fix bug when quota expires
428
-
429
- = 4.2.6 =
430
-
431
- * add the webp files as thumbs to the sizes array in metadata so they are automatically used by themes that use srcset.
432
- * add option to optimize PDFs or not.
433
- * seamless integration with WP/LR Sync plugin.
434
- * gracefully ignore missing thumbs on disk when doing the optimization - just mark them as missing in the metadata.
435
- * gracefully add Media Library files that are present on disk but not present in the image metadata (sizes array).
436
- * option to dismiss the top toolbar ShortPixel alert when quota expired.
437
- * compute the backup folder size asynchronously in order to speed up the settings page.
438
- * editors/authors now are able to optimize/restore images from the Media Library list.
439
- * handle internationalized domain names (punycode encoded).
440
- * reset failed images from Custom Media when user launches a reprocessing of the images from Bulk.
441
- * bugfixes
442
-
443
- = 4.2.5 =
444
-
445
- * fix for PHP7.1 fatal error when encountering corrupt metadata (wp_get_attachment_metadata returning empty string)
446
-
447
- = 4.2.4 =
448
-
449
- * fix not processing the images in the custom image folders if they had uppercase extensions
450
- * remove the deprecated mcrypt calls.
451
- * fix jQuery 3.x incompatibility when calling .unload() by using on("beforeunload" .. ) instead
452
-
453
- = 4.2.3 =
454
-
455
- * fix compatibility with older PHP by not using closure
456
- * fix order of optimization of other media - by id not by added timestamp
457
- * fix js error for manual optimization from js-generated button
458
- * change call to obsolete get_currentuserinfo method
459
-
460
- = 4.2.2 =
461
-
462
- * offer to generate the API key directly from ShortPixel settings.
463
- * alert and explain why is not allowed to specify a size less than 1024 when resizing.
464
- * fix metadata for missing thumbs while optimizing.
465
- * button Cleanup&Retry for images that have missing thumbnails.
466
- * display what thumbnails are missing.
467
- * for Windows platforms, do not check the local path to start with a slash
468
- * fix optimization for images that contain '+' in the path
469
- * use different styles for bulk boxes instead of the notice class
470
- * properly display from the start the number of images to be optimized on the bulk button, when thumbnails are not selected.
471
- * fix for sites that have admin urls with a doubled slash like wp-admin//uploads.php
472
- * fix JS error on bulk finished page and new images optimizing
473
- * fix bulk hangup when encountering a block of more than 900 wp_postmeta lines that are not image metadata.
474
- * fix for cases when the wp-content path returned by wordpress contains backpath items (like wp/../wp-content)
475
- * fix not saving advanced settings on "Save and go to Bulk" button.
476
-
477
- = 4.2.1 =
478
-
479
- * meta box in Media Library image editing form with informations about optimization status and results
480
- * delete WebP images when image is deleted from Media Library
481
- * change language domain to match the plugin slug in order to be automatically translatable on translate.wordpress.org.
482
-
483
- = 4.2.0 =
484
-
485
- * multilanguage support
486
- * add retinas count to the ShortPixel Compression column
487
- * add option not to automatically optimize Media Library images when added
488
- * fix the size bug happening when optimizing main image then optimizing only thumbnails with resize active
489
- * restrict log messages to SHORTPIXEL_DEBUG instead of WP_DEBUG
490
- * fix compatibility with WP < 3.9
491
- * fix compatibility with watermarking plugins like Image Watermark
492
- * fix compatibility with WPBakery Visual Composer
493
-
494
- = 4.1.7 =
495
-
496
- * fix backup thumbnail js error
497
-
498
- = 4.1.6 =
499
-
500
- * fix processing for sites with caps path like http://mysite.com/My-Path/
501
- * fix WebP generation for images that are already optimized
502
-
503
- = 4.1.5 =
504
-
505
- * readme updates - links to informative articles
506
- * show that WebP format is created free of charge
507
- * hide the Advanced settings tab completely before API Key validation
508
- * fix indefinite retries when wrong image size
509
- * restrict debug mode to ShortPixel own define
510
-
511
- = 4.1.4 =
512
-
513
- * fix path problems on multisite on Windows
514
-
515
- = 4.1.3 =
516
-
517
- * fix debug mode too intrusive
518
-
519
- = 4.1.2 =
520
-
521
- * bulk slider fix
522
-
523
- = 4.1.1 =
524
-
525
- * settings fix
526
-
527
- = 4.1.0 =
528
-
529
- * retina images support - optimize also retina images
530
- * WebP support - option to generate also WebP images
531
- * optimize other media folders also from the root of the site, not only in wp-content
532
- * restore and re-optimize other media images
533
- * resize options - defined rectangle to be contained in the resized image or the resized image to contain the defined rectangle
534
-
535
- = 4.0.2 =
536
-
537
- * fix compatibility with PHP 5.2
538
- * fix for URLs like domain.com/CamelCasePath
539
-
540
- = 4.0.1 =
541
-
542
- * Optimize from the front-end option
543
-
544
- = 4.0.0 =
545
-
546
- * Custom folders optimization
547
- * NextGen galleries optimization
548
-
549
- = 3.3.4 =
550
-
551
- * Fix Settings Resources display
552
- * Add user and password authentication option for downloading images
553
- * fix for PHP installs that lack utf8_encode function
554
- * retry from the optimize Ajax post when server sends a 500 error
555
-
556
- = 3.3.3 =
557
-
558
- * Compatibility with WPML Media plugin
559
- * Fix ListView link on multisites
560
- * Fix for server configurations that have max_execution_time = 0
561
-
562
- = 3.3.2 =
563
-
564
- * fix for PHP installs that are missing the mcrypt functions
565
-
566
- = 3.3.1 =
567
-
568
- * small fix to the quota revalidation process
569
-
570
- = 3.3.0 =
571
-
572
- * reoptimize lossless/lossy
573
- * optimize thumbs for images already optimized
574
- * compatibility with WPML
575
-
576
- = 3.2.1 =
577
-
578
- * old PHP compatibility fix
579
-
580
- = 3.2.0 =
581
-
582
- * ICC color profile is always preserved.
583
- * possibility to hide the API key in a multisite install.
584
- * detection of best protocol to use: https / http.
585
-
586
- = 3.1.9 =
587
-
588
- * option to keep the EXIF data and ICC profile.
589
- * more explanations on settings.
590
-
591
- = 3.1.8 =
592
-
593
- * fix reloading bulk page on quota used up
594
-
595
- = 3.1.7 =
596
-
597
- * bugfixes
598
-
599
- = 3.1.6 =
600
-
601
- * look and feel improvements
602
-
603
- = 3.1.5 =
604
-
605
- * longer timeout for the API Key validation postback
606
-
607
- = 3.1.4 =
608
-
609
- * fix bug in bulk processing
610
-
611
- = 3.1.3 =
612
-
613
- * fix problems with activating the keys on some systems that do not allow post requests
614
-
615
- = 3.1.2 =
616
-
617
- * bulk runs now only on media and post pages
618
- * settings page redesign
619
- * client site access test from our servers when activating the API key and warn if site not accessible
620
- * fix last image sometimes unprocessed by bulk
621
- * fix progress bar to advance when skipping images
622
-
623
- = 3.1.1 =
624
-
625
- * fix calculation of displayed counters of images to be processed on bulk start
626
- * fix restore option that appeared wrongly sometimes - thanks to Bogdan Günther @ http://medianotions.de
627
-
628
- = 3.1.0 =
629
-
630
- * rescale big images option - thanks to Bogdan Günther @ http://medianotions.de
631
- * referral system
632
- * show how many thumbs are optimized for each image
633
- * fix the Visual Composer conflict - thanks to Andy Adams - www.certainlysoftware.com
634
-
635
- = 3.0.8 =
636
-
637
- * fix issue with files in /tmp dir that weren't deleted in certain cases, issue noted by Daniel - http://germangoogleguy.com
638
-
639
- = 3.0.7 =
640
-
641
- * Affiliate codes
642
- * Solve conflict with wp-ses plugin
643
- * skip image on _FAIL message
644
- * mixed content warning fix
645
-
646
- = 3.0.6 =
647
-
648
- * Optimized bulk processor behaviour when navigating from one admin page to another.
649
- * Improved some explanatory texts.
650
-
651
- = 3.0.5 =
652
-
653
- * different bug fixes
654
-
655
- = 3.0.2 =
656
-
657
- * Progress bar improvements
658
-
659
- = 3.0.0 =
660
-
661
- * Major update
662
- * when validating the API Key on a multisite a message with instructions on how to add the API Key in wp-config.php is displayed
663
- * check when an optimized image cannot be saved and stop bulk processing (if running)
664
- * restore backup is not displayed when option is not activated
665
- * change image status in the Media Library ShortPixel Compression column imediately after the image is reduced, not only after reloading the page. Add spinner to the "Image waiting to be processed" status.
666
- * images with relative URLs are converted to absolute URL so they can be processed by the plugin
667
- * proper handling of images with non-standard latin chars inside
668
- * better average compression computation
669
- * rewritten handleImageUpload
670
- * removed MUST_HAVE_KEY
671
- * changed isProcessable
672
- * and others :)
673
-
674
- = 2.1.9 =
675
-
676
- * Check if the server address is localhost and warn when activating the API key.
677
- * Quota exceeded now displays a link to billing page
678
-
679
- = 2.1.8 =
680
-
681
- * improved texts/explanations for different sections
682
- * added extra option to convert CMYK to RGB for further size reduction
683
- * display credits for one time payments as well
684
- * API Key can also be configured in wp-config.php like this: define('SHORTPIXEL_API_KEY', 'YOUR_API_KEY'); Useful for multisite installations
685
-
686
-
687
- = 2.1.7 =
688
- * improved checking and reporting of firewall restriction on client side
689
- * optimized files are saved in the right location when dealing with WP Multisite
690
- * updated screenshots
691
-
692
- = 2.1.6 =
693
-
694
- * improved login procedure upon quota is exceeded
695
- * when quota is exceeded user can more easily increase it
696
- * extra warning regarding the number of thumbs available additionally to main images
697
- * improved counting of images
698
- * check if https works if not use http for communications with the API
699
- * better handling of error messages when API service cannot be contacted
700
-
701
- = 2.1.5 =
702
-
703
- * visiting Settings/ShortPixel now resets the Queue flag
704
- * when plgin's API Key cannot be validated the JS script that calls admin-ajax.php is stopped
705
- * return meaningful message on Media Library listing when API Key is not valid
706
- * extra check for API Key validation
707
-
708
- = 2.1.4 =
709
-
710
- * fixed global variable issue for some variables
711
- * fixed API Key validation that occurred for some of the hosting providers out there when HTTPS was used
712
-
713
- = 2.1.3 =
714
-
715
- * when backup wasn't activated the processed files weren't put in the right place
716
- * removed forgotten debug message
717
- * changed "optimised" to "optimized". Welcome USA :)
718
- * improved bulk handling and also "cancel" and "resume" options
719
- * fixed conflict with wpmandrill on wp_mail function
720
-
721
- = 2.1.2 =
722
-
723
- * fixed condition that hanged bulk processing sometimes
724
- * added "Reduced by" text
725
- * more useful wrong/missing API Key message
726
- * test if a backup dir can be created upon plugin validation
727
- * added alert when a file couldn't have been overwritten
728
- * added alert when a file cannot be saved in backup dir
729
- * added Quota on API Calls functionality
730
- * added resume bulk processing feature
731
-
732
- = 2.1.1 =
733
-
734
- * fixed condition in function that validates content by extension
735
- * fixed bug that prevented files uploaded directly in /uploads dir to be properly processed/saved
736
- * retry link added besides files that failed to be optimized due to different reasons
737
-
738
- = 2.1.0 =
739
-
740
- * speedier file download from API resource
741
- * SQL changed to use less CPU intensive queries
742
- * improved BULK processing logic, faster results
743
- * different small fixes & improvements
744
- * skip processed images when running bulk processing
745
-
746
-
747
- = 2.0.8 =
748
-
749
- * improved logic for processed files to be downloaded every time
750
- * sometimes the processing script stopped before finishing all the files to be optimized, fixed
751
- * improved processing speed for bulk processing
752
-
753
- = 2.0.7 =
754
-
755
- * fixed issue with "missing" images
756
- * save plugin version for easier debugging
757
- * list mode is set for media library for first time run
758
- * fixed bug that prevented backup-ed files to remove when the original was removed
759
-
760
- = 2.0.6 =
761
-
762
- * different small fixes
763
-
764
- = 2.0.5 =
765
-
766
- * small improvement to make the optimization of newly added images faster.
767
- * fixed condition when the PDF files weren't processed
768
- * different improvements
769
-
770
- = 2.0.4 =
771
-
772
- * fixed recursive backup directory size counter
773
- * added backup with subdirectory structure to handle many files
774
- * empty backup can handle subdirectories & sets the right flag for backup restore
775
- * latest images are optimized first
776
- * check for missing images on disk but still linked in DB
777
-
778
- = 2.0.3 =
779
-
780
- * added extra check for bad server responses
781
- * 10 files/post request for file processing
782
- * updated error codes according to API v2
783
- * updated description
784
-
785
- = 2.0.2 =
786
-
787
- * added more tags so we better describe newest features
788
-
789
- = 2.0.1 =
790
-
791
- * some improvements to bulk processing
792
- * PDF files are also optimized now
793
- * fixed a thumb processing bug that caused extra API requests
794
-
795
- = 2.0.0 =
796
-
797
- * SP plugin uses API v2 and the processing speed is significantly improved
4
  Requires at least: 3.2.0
5
  Tested up to: 4.9
6
  Requires PHP: 5.2
7
+ Stable tag: 4.11.0
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
14
 
15
  **A freemium easy to use, comprehensive, stable and frequently updated image compression plugin supported by the friendly team that created it. :)**
16
 
 
 
17
  Increase your website's SEO ranking, number of visitors and ultimately your sales by optimizing any image or PDF document on your website.
18
  ShortPixel is an easy to use, lightweight, install-and-forget-about-it <a href="https://shortpixel.com" target="_blank">image optimization</a> plugin that can compress all your past images and PDF documents with a single click. New images are automatically resized/rescaled and optimized on the fly, in the background.
19
 
29
 
30
  **Why is ShortPixel the best choice when it comes to image optimization or PDF compression?**
31
 
32
+ * popular plugin with over 80,000 active installations according to WordPress
33
  * compress JPG, PNG, GIF (still or animated) images and also PDF documents
34
  * option to automatically convert PNG to JPG if that will result in smaller images. Ideal for large images in PNG format.
35
  * no file size limit
37
  * option to include the generated WebP images into the front-end pages by using the &lt;picture&gt; tag instead of &lt;img&gt;
38
  * compatible with WP Retina 2x - all **retina images** are automatically compressed. <a href="http://blog.shortpixel.com/how-to-use-optimized-retina-images-on-your-wordpress-site-for-best-user-experience-on-apple-devices/" target="_blank">How to benefit from Retina displays?</a>
39
  * optimize thumbnails as well as featured images. You can also **select individual thumbnails to exclude** from optimization.
40
+ * ability to optimize any image on your site including images in **NextGEN Gallery** and any other image galleries or sliders
41
+ * integrates with Gravity Forms post_image field type optimizing the images upon upload
42
  * featured images can be automatically resized before being optimized with 2 different options. No need for additional plugins like Imsanity
43
  * CMYK to RGB conversion
44
  * **24h <a href="https://wordpress.org/support/plugin/shortpixel-image-optimiser/reviews/?filter=5" target="_blank">stellar support</a>** (24/7) directly from developers.
45
  * easily **test lossy/lossless** versions of the images with a single click in your Media Library
46
  * **great for photographers**: <a href="http://blog.shortpixel.com/how-much-smaller-can-be-images-without-exif-icc/" target="_blank">keep or remove EXIF</a> data from your images, compress images with lossless option
47
  * works well with both HTTPS and HTTP websites
48
+ * uses progressive JPEG for larger images in order to speed up the image display
49
  * you can run ShortPixel plugin on **multiple websites** or on a **multisite** with a **single API Key**
50
  * it is **safe to test** and use the plugin: all the original images can be restored with a click, either one by one or in bulk
51
  * 'Bulk' optimize all the existing images in Media Library or in any gallery with one click
57
  * compatible with watermarking plugins
58
  * option to deactivate auto-optimizing images on upload
59
  * images that are optimized less that 5% are bonus
60
+ * WooCommerce, WP offload S3 and WP Stateless compatible
61
  * 40 days optimization report with all image details and overall statistics
62
+ * We are GDPR compliant! <a href="https://shortpixel.com/privacy#gdpr" target="_blank">Read more.</a>
63
  * **free optimization credits for non-profits**, <a href="https://shortpixel.com/contact" target="_blank">contact us</a> for details
64
 
65
+ **How much does it cost?**
66
  ShortPixel comes with 100 free credits/month and additional credits can be bought with as little as $4.99 for 5,000 image credits.
67
  Check out <a href="https://shortpixel.com/pricing" target="_blank">our prices</a>.
68
 
209
 
210
  The ShortPixel team is here to help. <a href="https://shortpixel.com/contact">Contact us</a>!
211
 
212
+
213
+ == Actions and Filters for Developers ==
214
+
215
+ The ShortPixel Image Optimiser plugin calls the following actions and filters:
216
+ > do_action( 'shortpixel_image_optimised', $post_id ); //upon successful optimization
217
+ > do_action("shortpixel_before_restore_image", $post_id); //before restoring an image from backup
218
+ > do_action("shortpixel_after_restore_image", $post_id); //after succesful restore
219
+ > apply_filters("shortpixel_backup_folder", $backup_folder); //just before returning the ShortPixel backup folder, usually ...wp-content/uploads/ShortpixelBackups
220
+
221
+
222
  == Screenshots ==
223
 
224
  1. Bulk optimization running. (Media>Bulk ShortPixel)
241
 
242
  == Changelog ==
243
 
244
+ = 4.11.0 =
245
+ * add bulk menu options: restore, reoptimize
246
+ * filter the media list by optimization status
247
+ * sort the media list by optimization status
248
+ * do not display the Media Library (years) folders in the selection list for Other Media folders
249
+ * force PNG 2 JPG conversion option
250
+ * integrate with Gravity Forms
251
+ * integrate with WP Stateless
252
+ * add several actions and a filter (see the Actions and Filters section of the readme)
253
+ * UI improvements to the settings page
254
+ * fix the WPML compatibility when converting from PNG
255
+ * fix SELECT IN image counting bug on rare cases and when >100k records in wp_postmeta
256
+ * add option to delete ShortPixel settings and give feedback form on deactivate plugin
257
+
258
  = 4.10.5 =
259
  * GDPR compliance
260
 
298
  * fix slider optimized percent over the bulk warning box.
299
  * display the x close link for the bulk warning box.
300
 
301
+ = EARLIER VERSIONS =
302
+ * please refer to the changelog.txt file
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
res/css/short-pixel.css CHANGED
@@ -397,6 +397,14 @@ div.shortpixel-modal .sptw-modal-spinner {
397
  line-height:16px;
398
  float:right;
399
  }
 
 
 
 
 
 
 
 
400
  .wp-core-ui .bulk-play a.button .bulk-btn-img {
401
  float:left;
402
  display:inline-block;
@@ -552,6 +560,48 @@ p.settings-info.shortpixel-settings-error {
552
  color: #c32525;
553
  }
554
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
555
  /* TABS CONTROLS */
556
  article.sp-tabs {
557
  position: relative;
397
  line-height:16px;
398
  float:right;
399
  }
400
+
401
+ th.sortable.column-wp-shortPixel a,
402
+ th.sorted.column-wp-shortPixel a {
403
+ display: inline-block;
404
+ }
405
+ .column-wp-shortPixel .sorting-indicator {
406
+ display: inline-block;
407
+ }
408
  .wp-core-ui .bulk-play a.button .bulk-btn-img {
409
  float:left;
410
  display:inline-block;
560
  color: #c32525;
561
  }
562
 
563
+ .shortpixel-key-valid{
564
+ font-weight:bold;
565
+ }
566
+ .shortpixel-key-valid .dashicons-yes:before{
567
+ font-size: 2em;
568
+ line-height: 25px;
569
+ color: #3485ba;
570
+ margin-left: -20px;
571
+ }
572
+ .shortpixel-compression .shortpixel-compression-options {
573
+ color: #999;
574
+ }
575
+ .shortpixel-compression strong {
576
+ line-height: 22px;
577
+ }
578
+ .shortpixel-compression .shortpixel-compression-options {
579
+ display: inline-block;
580
+ }
581
+ .shortpixel-compression label {
582
+ width:158px;
583
+ margin: 0 -2px;
584
+ background-color:#e2faff;
585
+ font-weight: bold;
586
+ display: inline-block;
587
+ }
588
+ .shortpixel-compression label span {
589
+ text-align:center;
590
+ font-size: 18px;
591
+ padding:8px 0px;
592
+ display:block;
593
+ }
594
+ .shortpixel-compression label input {
595
+ display: none;
596
+ }
597
+ .shortpixel-compression input:checked + span {
598
+ background-color:#0085ba;
599
+ color:#F7F7F7;
600
+ }
601
+ .shortpixel-compression .shortpixel-radio-info {
602
+ min-height: 60px;
603
+ }
604
+
605
  /* TABS CONTROLS */
606
  article.sp-tabs {
607
  position: relative;
res/css/short-pixel.min.css CHANGED
@@ -1 +1 @@
1
- .sp-dropbtn.button{padding:1px 24px 20px 5px;font-size:20px;cursor:pointer}.sp-dropdown{position:relative;display:inline-block}.sp-dropdown-content{display:none;right:0;position:absolute;background-color:#f9f9f9;min-width:190px;box-shadow:0 8px 16px 0 rgba(0,0,0,0.2);z-index:1}.sp-dropdown-content a{color:black;padding:12px 16px;text-decoration:none;display:block}.sp-dropdown-content a:hover{background-color:#f1f1f1}.sp-dropdown.sp-show .sp-dropdown-content{display:block}div.fb-like{transform:scale(1.3);-ms-transform:scale(1.3);-webkit-transform:scale(1.3);-o-transform:scale(1.3);-moz-transform:scale(1.3);transform-origin:bottom left;-ms-transform-origin:bottom left;-webkit-transform-origin:bottom left;-moz-transform-origin:bottom left;-webkit-transform-origin:bottom left}.wp-core-ui .button.button-alert,.wp-core-ui .button.button-alert:hover{background:#f79797}.wp-core-ui .button.remove-folder-button{min-width:120px}.sp-notice{background:#fff;border-left:4px solid #fff;-webkit-box-shadow:0 1px 1px 0 rgba(0,0,0,.1);box-shadow:0 1px 1px 0 rgba(0,0,0,.1);padding:1px 12px}@media(max-width:1249px){.sp-notice{margin:5px 15px 2px}}.sp-notice-info{border-left-color:#00a0d2}.sp-notice-success{border-left-color:#46b450}li.sp-conflict-plugins-list{line-height:28px;list-style:disc;margin-left:80px}li.sp-conflict-plugins-list a.button{margin-left:10px}div.short-pixel-bulk-page input.dial{font-size:16px!important}div.short-pixel-bulk-page h1{margin-bottom:20px}div.bulk-progress div.sp-h2{margin-top:0;margin-bottom:10px;font-size:23px;font-weight:400;padding:9px 15px 4px 0;line-height:29px}div.bulk-progress-partners{margin-top:20px}div.bulk-progress.bulk-progress-partners a div{display:inline-block;vertical-align:top;line-height:50px;margin-left:30px;font-size:1.2em}div.bulk-progress .bulk-progress-indicator,div.sp-quota-exceeded-alert .bulk-progress-indicator{display:inline-block;text-align:center;padding:0 10px;margin-left:10px;float:left;height:90px;overflow:hidden;border:1px solid #1caecb}div.wrap.short-pixel-bulk-page .bulk-notice-container{margin-top:15px;position:absolute;width:500px}div.wrap.short-pixel-bulk-page .bulk-notice-container .bulk-notice-msg{text-align:center;margin:10px 0 0 32px;overflow:hidden;border:1px solid #1caecb;background-color:#9ddbe0;border-radius:5px;padding:7px 10px 10px;display:none;max-width:600px;margin-right:20px}div.wrap.short-pixel-bulk-page .bulk-notice-container .bulk-notice-msg.bulk-error{border:1px solid #b5914d;background-color:#ffe996;margin-right:20px;position: relative;z-index:10}div.wrap.short-pixel-bulk-page .bulk-notice-container .bulk-notice-msg.bulk-error.bulk-error-fatal{border:1px solid #c32525;background-color:#ff969d}div.wrap.short-pixel-bulk-page .bulk-notice-msg img{float:left;margin-top:3px;margin-right:5px}div.sp-bulk-summary{float:right;margin:8px 5px 3px 20px}input.dial{box-shadow:none}.shortpixel-table .column-filename{max-width:32em;width:40%}.shortpixel-table .column-folder{max-width:20em;width:20%}.shortpixel-table .column-media_type{max-width:8em;width:10%}.shortpixel-table .column-status{max-width:16em;width:15%}.shortpixel-table .column-options{max-width:16em;width:15%}.form-table table.shortpixel-folders-list tr{background-color:#eee}.form-table table.shortpixel-folders-list td{padding:5px 10px}div.shortpixel-rate-us{display:inline-block;margin-left:10px;vertical-align:top;font-weight:bold}div.shortpixel-rate-us>a{vertical-align:middle;padding:1px 5px 0;text-align:center;display:inline-block}div.shortpixel-rate-us>a>span{display:inline-block;vertical-align:top;margin-top:5px}div.shortpixel-rate-us>a>img{padding-top:7px}div.shortpixel-rate-us>a:active,div.shortpixel-rate-us>a:hover,div.shortpixel-rate-us>a:focus{outline:0;border-style:none}.sp-loading-small{margin-top:2px;float:left;margin-right:5px}li.shortpixel-toolbar-processing>a.ab-item>div,#wpadminbar li.shortpixel-toolbar-processing>a.ab-item>div{height:33px;margin-top:-1px;padding:0 3px}li.shortpixel-toolbar-processing>a.ab-item>div>img,#wpadminbar li.shortpixel-toolbar-processing>a.ab-item>div>img{margin-right:2px;margin-top:6px}li.shortpixel-toolbar-processing>a.ab-item>div>span.shp-alert,#wpadminbar li.shortpixel-toolbar-processing>a.ab-item>div>span.shp-alert{display:none}li.shortpixel-toolbar-processing.shortpixel-alert>a.ab-item>div>span.shp-alert,#wpadminbar li.shortpixel-toolbar-processing.shortpixel-alert>a.ab-item>div>span.shp-alert{display:inline;font-size:26px;color:red;font-weight:bold;vertical-align:top}li.shortpixel-toolbar-processing.shortpixel-alert>a.ab-item>div,#wpadminbar li.shortpixel-toolbar-processing.shortpixel-alert>a.ab-item>div{background-image:none}.sp-quota-exceeded-alert{background-color:#fff;border-left:4px solid #f00;box-shadow:0 1px 1px 0 rgba(0,0,0,0.1);padding:1px 12px}.shortpixel-hide{display:none}.shortpixel-clearfix{width:100%;float:left}div.sp-modal-shade{display:none;position:fixed;z-index:10;left:0;top:0;width:100%;height:100%;overflow:auto;background-color:#000;background-color:rgba(0,0,0,0.4)}div.shortpixel-modal{background-color:#fefefe;margin:8% auto;padding:20px;border:1px solid #888;width:30%;min-width:300px}div.shortpixel-modal .sp-close-button,div.shortpixel-modal .sp-close-upgrade-button{float:right;margin-top:0;background:transparent;border:0;font-size:22px;line-height:10px;cursor:pointer}.twentytwenty-horizontal .twentytwenty-before-label:before,.twentytwenty-horizontal .twentytwenty-after-label:before{font-family:inherit;font-size:16px}div.sp-modal-title{font-size:22px}div.sp-modal-body{margin-top:20px}.short-pixel-bulk-page p{margin:.6em 0}div.shortpixel-modal .sptw-modal-spinner{background-image:url("../img/spinner2.gif");background-repeat:no-repeat;background-position:center}.short-pixel-bulk-page form.start{display:table;content:" ";width:98%;background-color:white;padding:10px 10px 0;position:relative}.bulk-stats-container{display:inline-block;min-width:450px;width:45%;float:left;padding-right:50px;font-size:1.1em;line-height:1.5em}.bulk-text-container{display:inline-block;min-width:440px;width:45%;float:left;padding-right:50px}.bulk-text-container h3{border-bottom:1px solid #a8a8a8;margin-bottom:.5em;padding-bottom:.5em}.bulk-wide{display:inline-block;width:90%;float:left;margin-top:25px}.bulk-stats-container .bulk-label{width:220px;display:inline-block}.bulk-stats-container .bulk-val{width:50px;display:inline-block;text-align:right}.bulk-stats-container .bulk-total{font-weight:bold;margin-top:10px;margin-bottom:10px}.wp-core-ui .bulk-play{display:inline;width:310px;float:left;margin-bottom:20px}.wp-core-ui .bulk-play.bulk-nothing-optimize{font-weight:bold;color:#0080b2;border:1px solid;border-radius:5px;margin-top:60px;padding:5px 12px}.wp-core-ui .bulk-play a.button{height:60px;margin-top:27px;width:290px;overflow:hidden}.wp-core-ui .column-wp-shortPixel .sp-column-actions{max-width:140px;float:right;text-align:right}.wp-core-ui .column-wp-shortPixel .sp-column-actions .button.button-smaller{margin-right:0}.wp-core-ui .column-wp-shortPixel .button.button-smaller{font-size:13px;padding:0 5px;margin-bottom:4px;height:20px;line-height:16px;float:right}.wp-core-ui .bulk-play a.button .bulk-btn-img{float:left;display:inline-block;padding-top:6px}.wp-core-ui .bulk-play a.button .bulk-btn-txt{float:left;display:inline-block;text-align:right;line-height:1.3em;margin:11px 10px}.wp-core-ui .bulk-play a.button .bulk-btn-txt span.label{font-size:1.6em}.wp-core-ui .bulk-play a.button .bulk-btn-txt span.total{font-size:1.4em}.short-pixel-notice-icon{float:left;margin:10px 10px 10px 0}.bulk-progress{padding:20px 32px 17px;background-color:#fff}.bulk-progress.bulk-stats>div{display:inline-block}.bulk-progress.bulk-stats>div.label{width:320px}.bulk-progress.bulk-stats>div.stat-value{width:80px;text-align:right}.progress{background-color:#ecedee;height:30px;position:relative;width:60%;display:inline-block;margin-right:28px}.progress .progress-img{position:absolute;top:-10px;z-index:2;margin-left:-35px;line-height:48px;font-size:22px;font-weight:bold}.progress .progress-img span{vertical-align:top;margin-left:-7px}.progress .progress-left{background-color:#1cbecb;bottom:0;left:0;position:absolute;top:0;z-index:1;font-size:22px;font-weight:bold;line-height:28px;text-align:center;color:#fff}.bulk-estimate{font-size:20px;line-height:30px;vertical-align:top;display:inline-block}.wp-core-ui .button-primary.bulk-cancel{float:right;height:30px}.short-pixel-block-title{font-size:22px;font-weight:bold;margin-bottom:15px;text-align:center;margin-bottom:30px}.sp-floating-block.bulk-slider-container{display:none}.sp-floating-block.sp-notice.bulk-notices-parent{padding:0;margin:0;float:right;margin-right:500px!important}.bulk-slider-container{margin-top:20px;min-height:300px;overflow:hidden}.bulk-slider-container h2{margin-bottom:15px}.bulk-slider-container span.filename{font-weight:normal}.bulk-slider{display:table;margin:0 auto}.bulk-slider .bulk-slide{margin:0 auto;padding-left:120px;display:inline-block;font-weight:bold}.bulk-slider .img-original,.bulk-slider .img-optimized{display:inline-block;margin-right:20px;text-align:center}.bulk-slider .img-original div,.bulk-slider .img-optimized div{max-height:450px;overflow:hidden}.bulk-slider .img-original img,.bulk-slider .img-optimized img{max-width:300px}.bulk-slider .img-info{display:inline-block;vertical-align:top;font-size:48px;max-width:150px;padding:10px 0 0 20px}.bulk-slide-images{display:inline-block;border:1px solid #1caecb;padding:15px 0 0 20px}p.settings-info{padding-top:0;color:#818181;font-size:13px!important}p.settings-info.shortpixel-settings-error{color:#c32525}article.sp-tabs{position:relative;display:block;width:100%;height:1100px;margin:2em auto}article.sp-tabs section{position:absolute;display:block;top:1.8em;left:0;height:1100px;width:94%;padding:10px 20px;background-color:#ddd;box-shadow:0 3px 3px rgba(0,0,0,0.1);z-index:0}article.sp-tabs section:first-child{z-index:1}article.sp-tabs section h2{position:absolute;font-size:1.3em;font-weight:normal;width:180px;height:1.8em;top:-1.8em;left:10px;padding:0;margin:0;color:#999;background-color:#ddd}article.sp-tabs section:nth-child(2) h2{left:192px}article.sp-tabs section:nth-child(3) h2{left:374px}article.sp-tabs section:nth-child(4) h2{left:556px}article.sp-tabs section:nth-child(5) h2{left: 738px}article.sp-tabs section h2 a{display:block;width:100%;line-height:1.8em;text-align:center;text-decoration:none;color:#23282d;outline:0 none}article.sp-tabs section h2 a:focus,article.sp-tabs section#tab-resources a:focus{box-shadow:none;outline:0}article.sp-tabs section.sel-tab,article.sp-tabs section.sel-tab h2{color:#333;background-color:#fff;z-index:2}.shortpixel-help-link span.dashicons{text-decoration:none;margin-top:-1px}@media(min-width:1000px){section#tab-resources .col-md-6{display:inline-block;width:45%}}@media(max-width:999px){section#tab-resources .col-sm-12{display:inline-block;width:100%}}section#tab-resources .text-center{text-align:center}section#tab-resources p{font-size:16px}.wrap.short-pixel-bulk-page{margin-right:0}.sp-container{overflow:hidden;display:block;width:100%}.sp-floating-block{overflow:hidden;display:inline-block;float:left;margin-right:1.1%!important}.sp-full-width{width:98.8%;box-sizing:border-box}.sp-double-width{width:65.52%;box-sizing:border-box}.sp-single-width{width:32.23%;box-sizing:border-box}@media(max-width:1759px){.sp-floating-block{margin-right:1.3%!important}.sp-double-width,.sp-full-width{width:98.65%}.sp-single-width{width:48.7%}}@media(max-width:1249px){.sp-floating-block{margin-right:2%!important}.sp-double-width,.sp-full-width,.sp-single-width{width:97%}}.sp-tabs h2:before{content:none}#wpadminbar .shortpixel-toolbar-processing .cssload-container{width:100%;height:24px;text-align:center;position:absolute;top:0;left:-1px}#wpadminbar .shortpixel-toolbar-processing.shortpixel-quota-exceeded .cssload-container,#wpadminbar .shortpixel-toolbar-processing.shortpixel-alert .cssload-container{display:none}#wpadminbar .shortpixel-toolbar-processing .cssload-speeding-wheel{width:24px;height:24px;opacity:.7;margin:0 auto;border:4px solid #1cbfcb;border-radius:50%;border-left-color:transparent;animation:cssload-spin 2000ms infinite linear;-o-animation:cssload-spin 2000ms infinite linear;-ms-animation:cssload-spin 2000ms infinite linear;-webkit-animation:cssload-spin 2000ms infinite linear;-moz-animation:cssload-spin 2000ms infinite linear}@keyframes cssload-spin{100%{transform:rotate(360deg);transform:rotate(360deg)}}@-o-keyframes cssload-spin{100%{-o-transform:rotate(360deg);transform:rotate(360deg)}}@-ms-keyframes cssload-spin{100%{-ms-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes cssload-spin{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-moz-keyframes cssload-spin{100%{-moz-transform:rotate(360deg);transform:rotate(360deg)}}
1
+ .sp-dropbtn.button{padding:1px 24px 20px 5px;font-size:20px;cursor:pointer}.sp-dropdown{position:relative;display:inline-block}.sp-dropdown-content{display:none;right:0;position:absolute;background-color:#f9f9f9;min-width:190px;box-shadow:0 8px 16px 0 rgba(0,0,0,0.2);z-index:1}.sp-dropdown-content a{color:black;padding:12px 16px;text-decoration:none;display:block}.sp-dropdown-content a:hover{background-color:#f1f1f1}.sp-dropdown.sp-show .sp-dropdown-content{display:block}div.fb-like{transform:scale(1.3);-ms-transform:scale(1.3);-webkit-transform:scale(1.3);-o-transform:scale(1.3);-moz-transform:scale(1.3);transform-origin:bottom left;-ms-transform-origin:bottom left;-webkit-transform-origin:bottom left;-moz-transform-origin:bottom left;-webkit-transform-origin:bottom left}.wp-core-ui .button.button-alert,.wp-core-ui .button.button-alert:hover{background:#f79797}.wp-core-ui .button.remove-folder-button{min-width:120px}.sp-notice{background:#fff;border-left:4px solid #fff;-webkit-box-shadow:0 1px 1px 0 rgba(0,0,0,.1);box-shadow:0 1px 1px 0 rgba(0,0,0,.1);padding:1px 12px}@media(max-width:1249px){.sp-notice{margin:5px 15px 2px}}.sp-notice-info{border-left-color:#00a0d2}.sp-notice-success{border-left-color:#46b450}li.sp-conflict-plugins-list{line-height:28px;list-style:disc;margin-left:80px}li.sp-conflict-plugins-list a.button{margin-left:10px}div.short-pixel-bulk-page input.dial{font-size:16px !important}div.short-pixel-bulk-page h1{margin-bottom:20px}div.bulk-progress div.sp-h2{margin-top:0;margin-bottom:10px;font-size:23px;font-weight:400;padding:9px 15px 4px 0;line-height:29px}div.bulk-progress-partners{margin-top:20px}div.bulk-progress.bulk-progress-partners a div{display:inline-block;vertical-align:top;line-height:50px;margin-left:30px;font-size:1.2em}div.bulk-progress .bulk-progress-indicator,div.sp-quota-exceeded-alert .bulk-progress-indicator{display:inline-block;text-align:center;padding:0 10px;margin-left:10px;float:left;height:90px;overflow:hidden;border:1px solid #1caecb}div.wrap.short-pixel-bulk-page .bulk-notice-container{margin-top:15px;position:absolute;width:500px}div.wrap.short-pixel-bulk-page .bulk-notice-container .bulk-notice-msg{text-align:center;margin:10px 0 0 32px;overflow:hidden;border:1px solid #1caecb;background-color:#9ddbe0;border-radius:5px;padding:7px 10px 10px;display:none;max-width:600px;margin-right:20px}div.wrap.short-pixel-bulk-page .bulk-notice-container .bulk-notice-msg.bulk-error{border:1px solid #b5914d;background-color:#ffe996;margin-right:20px;position:relative;z-index:10}div.wrap.short-pixel-bulk-page .bulk-notice-container .bulk-notice-msg.bulk-error.bulk-error-fatal{border:1px solid #c32525;background-color:#ff969d}div.wrap.short-pixel-bulk-page .bulk-notice-msg img{float:left;margin-top:3px;margin-right:5px}div.sp-bulk-summary{float:right;margin:8px 5px 3px 20px}input.dial{box-shadow:none}.shortpixel-table .column-filename{max-width:32em;width:40%}.shortpixel-table .column-folder{max-width:20em;width:20%}.shortpixel-table .column-media_type{max-width:8em;width:10%}.shortpixel-table .column-status{max-width:16em;width:15%}.shortpixel-table .column-options{max-width:16em;width:15%}.form-table table.shortpixel-folders-list tr{background-color:#eee}.form-table table.shortpixel-folders-list td{padding:5px 10px}div.shortpixel-rate-us{display:inline-block;margin-left:10px;vertical-align:top;font-weight:bold}div.shortpixel-rate-us>a{vertical-align:middle;padding:1px 5px 0;text-align:center;display:inline-block}div.shortpixel-rate-us>a>span{display:inline-block;vertical-align:top;margin-top:5px}div.shortpixel-rate-us>a>img{padding-top:7px}div.shortpixel-rate-us>a:active,div.shortpixel-rate-us>a:hover,div.shortpixel-rate-us>a:focus{outline:0;border-style:none}.sp-loading-small{margin-top:2px;float:left;margin-right:5px}li.shortpixel-toolbar-processing>a.ab-item>div,#wpadminbar li.shortpixel-toolbar-processing>a.ab-item>div{height:33px;margin-top:-1px;padding:0 3px}li.shortpixel-toolbar-processing>a.ab-item>div>img,#wpadminbar li.shortpixel-toolbar-processing>a.ab-item>div>img{margin-right:2px;margin-top:6px}li.shortpixel-toolbar-processing>a.ab-item>div>span.shp-alert,#wpadminbar li.shortpixel-toolbar-processing>a.ab-item>div>span.shp-alert{display:none}li.shortpixel-toolbar-processing.shortpixel-alert>a.ab-item>div>span.shp-alert,#wpadminbar li.shortpixel-toolbar-processing.shortpixel-alert>a.ab-item>div>span.shp-alert{display:inline;font-size:26px;color:red;font-weight:bold;vertical-align:top}li.shortpixel-toolbar-processing.shortpixel-alert>a.ab-item>div,#wpadminbar li.shortpixel-toolbar-processing.shortpixel-alert>a.ab-item>div{background-image:none}.sp-quota-exceeded-alert{background-color:#fff;border-left:4px solid red;box-shadow:0 1px 1px 0 rgba(0,0,0,0.1);padding:1px 12px}.shortpixel-clearfix{width:100%;float:left}div.sp-modal-shade{display:none;position:fixed;z-index:10;left:0;top:0;width:100%;height:100%;overflow:auto;background-color:#000;background-color:rgba(0,0,0,0.4)}div.shortpixel-modal{background-color:#fefefe;margin:8% auto;padding:20px;border:1px solid #888;width:30%;min-width:300px}div.shortpixel-modal .sp-close-button,div.shortpixel-modal .sp-close-upgrade-button{float:right;margin-top:0;background:transparent;border:0;font-size:22px;line-height:10px;cursor:pointer}.twentytwenty-horizontal .twentytwenty-before-label:before,.twentytwenty-horizontal .twentytwenty-after-label:before{font-family:inherit;font-size:16px}div.sp-modal-title{font-size:22px}div.sp-modal-body{margin-top:20px}.short-pixel-bulk-page p{margin:.6em 0}div.shortpixel-modal .sptw-modal-spinner{background-image:url("../img/spinner2.gif");background-repeat:no-repeat;background-position:center}.short-pixel-bulk-page form.start{display:table;content:" ";width:98%;background-color:white;padding:10px 10px 0;position:relative}.bulk-stats-container{display:inline-block;min-width:450px;width:45%;float:left;padding-right:50px;font-size:1.1em;line-height:1.5em}.bulk-text-container{display:inline-block;min-width:440px;width:45%;float:left;padding-right:50px}.bulk-text-container h3{border-bottom:1px solid #a8a8a8;margin-bottom:.5em;padding-bottom:.5em}.bulk-wide{display:inline-block;width:90%;float:left;margin-top:25px}.bulk-stats-container .bulk-label{width:220px;display:inline-block}.bulk-stats-container .bulk-val{width:50px;display:inline-block;text-align:right}.bulk-stats-container .bulk-total{font-weight:bold;margin-top:10px;margin-bottom:10px}.wp-core-ui .bulk-play{display:inline;width:310px;float:left;margin-bottom:20px}.wp-core-ui .bulk-play.bulk-nothing-optimize{font-weight:bold;color:#0080b2;border:1px solid;border-radius:5px;margin-top:60px;padding:5px 12px}.wp-core-ui .bulk-play a.button{height:60px;margin-top:27px;width:290px;overflow:hidden}.wp-core-ui .column-wp-shortPixel .sp-column-actions{max-width:140px;float:right;text-align:right}.wp-core-ui .column-wp-shortPixel .sp-column-actions .button.button-smaller{margin-right:0}.wp-core-ui .column-wp-shortPixel .button.button-smaller{font-size:13px;padding:0 5px;margin-bottom:4px;height:20px;line-height:16px;float:right}th.sortable.column-wp-shortPixel a,th.sorted.column-wp-shortPixel a{display:inline-block}.column-wp-shortPixel .sorting-indicator{display:inline-block}.wp-core-ui .bulk-play a.button .bulk-btn-img{float:left;display:inline-block;padding-top:6px}.wp-core-ui .bulk-play a.button .bulk-btn-txt{float:left;display:inline-block;text-align:right;line-height:1.3em;margin:11px 10px}.wp-core-ui .bulk-play a.button .bulk-btn-txt span.label{font-size:1.6em}.wp-core-ui .bulk-play a.button .bulk-btn-txt span.total{font-size:1.4em}.short-pixel-notice-icon{float:left;margin:10px 10px 10px 0}.bulk-progress{padding:20px 32px 17px;background-color:#fff}.bulk-progress.bulk-stats>div{display:inline-block}.bulk-progress.bulk-stats>div.label{width:320px}.bulk-progress.bulk-stats>div.stat-value{width:80px;text-align:right}.progress{background-color:#ecedee;height:30px;position:relative;width:60%;display:inline-block;margin-right:28px}.progress .progress-img{position:absolute;top:-10px;z-index:2;margin-left:-35px;line-height:48px;font-size:22px;font-weight:bold}.progress .progress-img span{vertical-align:top;margin-left:-7px}.progress .progress-left{background-color:#1cbecb;bottom:0;left:0;position:absolute;top:0;z-index:1;font-size:22px;font-weight:bold;line-height:28px;text-align:center;color:#fff}.bulk-estimate{font-size:20px;line-height:30px;vertical-align:top;display:inline-block}.wp-core-ui .button-primary.bulk-cancel{float:right;height:30px}.short-pixel-block-title{font-size:22px;font-weight:bold;margin-bottom:15px;text-align:center;margin-bottom:30px}.sp-floating-block.bulk-slider-container{display:none}.sp-floating-block.sp-notice.bulk-notices-parent{padding:0;margin:0;float:right;margin-right:500px !important}.bulk-slider-container{margin-top:20px;min-height:300px;overflow:hidden}.bulk-slider-container h2{margin-bottom:15px}.bulk-slider-container span.filename{font-weight:normal}.bulk-slider{display:table;margin:0 auto}.bulk-slider .bulk-slide{margin:0 auto;padding-left:120px;display:inline-block;font-weight:bold}.bulk-slider .img-original,.bulk-slider .img-optimized{display:inline-block;margin-right:20px;text-align:center}.bulk-slider .img-original div,.bulk-slider .img-optimized div{max-height:450px;overflow:hidden}.bulk-slider .img-original img,.bulk-slider .img-optimized img{max-width:300px}.bulk-slider .img-info{display:inline-block;vertical-align:top;font-size:48px;max-width:150px;padding:10px 0 0 20px}.bulk-slide-images{display:inline-block;border:1px solid #1caecb;padding:15px 0 0 20px}p.settings-info{padding-top:0;color:#818181;font-size:13px !important}p.settings-info.shortpixel-settings-error{color:#c32525}.shortpixel-key-valid{font-weight:bold}.shortpixel-key-valid .dashicons-yes:before{font-size:2em;line-height:25px;color:#3485ba;margin-left:-20px}.shortpixel-compression .shortpixel-compression-options{color:#999}.shortpixel-compression strong{line-height:22px}.shortpixel-compression .shortpixel-compression-options{display:inline-block}.shortpixel-compression label{width:158px;margin:0 -2px;background-color:#e2faff;font-weight:bold;display:inline-block}.shortpixel-compression label span{text-align:center;font-size:18px;padding:8px 0;display:block}.shortpixel-compression label input{display:none}.shortpixel-compression input:checked+span{background-color:#0085ba;color:#f7f7f7}.shortpixel-compression .shortpixel-radio-info{min-height:60px}article.sp-tabs{position:relative;display:block;width:100%;height:1100px;margin:2em auto}article.sp-tabs section{position:absolute;display:block;top:1.8em;left:0;height:1100px;width:94%;padding:10px 20px;background-color:#ddd;box-shadow:0 3px 3px rgba(0,0,0,0.1);z-index:0}article.sp-tabs section:first-child{z-index:1}article.sp-tabs section h2{position:absolute;font-size:1.3em;font-weight:normal;width:180px;height:1.8em;top:-1.8em;left:10px;padding:0;margin:0;color:#999;background-color:#ddd}article.sp-tabs section:nth-child(2) h2{left:192px}article.sp-tabs section:nth-child(3) h2{left:374px}article.sp-tabs section:nth-child(4) h2{left:556px}article.sp-tabs section:nth-child(5) h2{left:738px}article.sp-tabs section h2 a{display:block;width:100%;line-height:1.8em;text-align:center;text-decoration:none;color:#23282d;outline:0 none}article.sp-tabs section h2 a:focus,article.sp-tabs section#tab-resources a:focus{box-shadow:none;outline:0}article.sp-tabs section.sel-tab,article.sp-tabs section.sel-tab h2{color:#333;background-color:#fff;z-index:2}.shortpixel-help-link span.dashicons{text-decoration:none;margin-top:-1px}@media(min-width:1000px){section#tab-resources .col-md-6{display:inline-block;width:45%}}@media(max-width:999px){section#tab-resources .col-sm-12{display:inline-block;width:100%}}section#tab-resources .text-center{text-align:center}section#tab-resources p{font-size:16px}.wrap.short-pixel-bulk-page{margin-right:0}.sp-container{overflow:hidden;display:block;width:100%}.sp-floating-block{overflow:hidden;display:inline-block;float:left;margin-right:1.1% !important}.sp-full-width{width:98.8%;box-sizing:border-box}.sp-double-width{width:65.52%;box-sizing:border-box}.sp-single-width{width:32.23%;box-sizing:border-box}@media(max-width:1759px){.sp-floating-block{margin-right:1.3% !important}.sp-double-width,.sp-full-width{width:98.65%}.sp-single-width{width:48.7%}}@media(max-width:1249px){.sp-floating-block{margin-right:2% !important}.sp-double-width,.sp-full-width,.sp-single-width{width:97%}}.sp-tabs h2:before{content:none}#wpadminbar .shortpixel-toolbar-processing .cssload-container{width:100%;height:24px;text-align:center;position:absolute;top:0;left:-1px}#wpadminbar .shortpixel-toolbar-processing.shortpixel-quota-exceeded .cssload-container,#wpadminbar .shortpixel-toolbar-processing.shortpixel-alert .cssload-container{display:none}#wpadminbar .shortpixel-toolbar-processing .cssload-speeding-wheel{width:24px;height:24px;opacity:.7;margin:0 auto;border:4px solid #1cbfcb;border-radius:50%;border-left-color:transparent;animation:cssload-spin 2000ms infinite linear;-o-animation:cssload-spin 2000ms infinite linear;-ms-animation:cssload-spin 2000ms infinite linear;-webkit-animation:cssload-spin 2000ms infinite linear;-moz-animation:cssload-spin 2000ms infinite linear}@keyframes cssload-spin{100%{transform:rotate(360deg);transform:rotate(360deg)}}@-o-keyframes cssload-spin{100%{-o-transform:rotate(360deg);transform:rotate(360deg)}}@-ms-keyframes cssload-spin{100%{-ms-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes cssload-spin{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-moz-keyframes cssload-spin{100%{-moz-transform:rotate(360deg);transform:rotate(360deg)}}
res/js/short-pixel.js CHANGED
@@ -12,7 +12,12 @@ var ShortPixel = function() {
12
  //are we on media list?
13
  if( jQuery('table.wp-list-table.media').length > 0) {
14
  //register a bulk action
15
- jQuery('select[name^="action"] option:last-child').before('<option value="short-pixel-bulk">' + _spTr.optimizeWithSP + '</option>');
 
 
 
 
 
16
  }
17
 
18
  ShortPixel.setOptions(ShortPixelConstants);
@@ -83,7 +88,9 @@ var ShortPixel = function() {
83
  if(this !== prev) {
84
  prev = this;
85
  }
 
86
  alert(_spTr.alertOnlyAppliesToNewImages);
 
87
  };
88
  }
89
  ShortPixel.enableResize("#resize");
@@ -124,6 +131,11 @@ var ShortPixel = function() {
124
  return true;
125
  });
126
  }
 
 
 
 
 
127
 
128
  function setupAdvancedTab() {
129
  jQuery("input.remove-folder-button").click(function(){
@@ -597,6 +609,7 @@ var ShortPixel = function() {
597
  validateKey : validateKey,
598
  enableResize : enableResize,
599
  setupGeneralTab : setupGeneralTab,
 
600
  setupAdvancedTab : setupAdvancedTab,
601
  checkThumbsUpdTotal : checkThumbsUpdTotal,
602
  switchSettingsTab : switchSettingsTab,
12
  //are we on media list?
13
  if( jQuery('table.wp-list-table.media').length > 0) {
14
  //register a bulk action
15
+ jQuery('select[name^="action"] option:last-child').before('<option value="short-pixel-bulk">' + _spTr.optimizeWithSP
16
+ + '</option><option value="short-pixel-bulk-lossy"> → ' + _spTr.redoLossy
17
+ + '</option><option value="short-pixel-bulk-glossy"> → ' + _spTr.redoGlossy
18
+ + '</option><option value="short-pixel-bulk-lossless"> → ' + _spTr.redoLossless
19
+ + '</option><option value="short-pixel-bulk-restore"> → ' + _spTr.restoreOriginal
20
+ + '</option>');
21
  }
22
 
23
  ShortPixel.setOptions(ShortPixelConstants);
88
  if(this !== prev) {
89
  prev = this;
90
  }
91
+ if(typeof ShortPixel.setupGeneralTabAlert !== 'undefined') return;
92
  alert(_spTr.alertOnlyAppliesToNewImages);
93
+ ShortPixel.setupGeneralTabAlert = 1;
94
  };
95
  }
96
  ShortPixel.enableResize("#resize");
131
  return true;
132
  });
133
  }
134
+
135
+ function apiKeyChanged() {
136
+ jQuery(".wp-shortpixel-options .shortpixel-key-valid").css("display", "none");
137
+ jQuery(".wp-shortpixel-options button#validate").css("display", "inline-block");
138
+ }
139
 
140
  function setupAdvancedTab() {
141
  jQuery("input.remove-folder-button").click(function(){
609
  validateKey : validateKey,
610
  enableResize : enableResize,
611
  setupGeneralTab : setupGeneralTab,
612
+ apiKeyChanged : apiKeyChanged,
613
  setupAdvancedTab : setupAdvancedTab,
614
  checkThumbsUpdTotal : checkThumbsUpdTotal,
615
  switchSettingsTab : switchSettingsTab,
res/js/short-pixel.min.js CHANGED
@@ -1 +1 @@
1
- jQuery(document).ready(function(a){ShortPixel.init()});var ShortPixel=function(){function F(){if(typeof ShortPixel.API_KEY!=="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>")}ShortPixel.setOptions(ShortPixelConstants);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>'+_spTr.changeMLToListMode.format('<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 l(N){for(var O in N){ShortPixel[O]=N[O]}}function s(N){return/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{1,63})+$/.test(N)}function m(){var N=jQuery("#pluginemail").val();if(ShortPixel.isEmailValid(N)){jQuery("#request_key").removeClass("disabled")}jQuery("#request_key").attr("href",jQuery("#request_key").attr("href").split("?")[0]+"?pluginemail="+N)}function a(){jQuery("#valid").val("validate");jQuery("#wp_shortpixel_options").submit()}jQuery("#key").keypress(function(N){if(N.which==13){jQuery("#valid").val("validate")}});function I(N){if(jQuery(N).is(":checked")){jQuery("#width,#height").removeAttr("disabled")}else{jQuery("#width,#height").attr("disabled","disabled")}}function e(N,P,R){for(var O=0,Q=null;O<N.length;O++){N[O].onclick=function(){if(this!==Q){Q=this}alert(_spTr.alertOnlyAppliesToNewImages)}}ShortPixel.enableResize("#resize");jQuery("#resize").change(function(){I(this)});jQuery(".resize-sizes").blur(function(T){var U=jQuery(this);if(ShortPixel.resizeSizesAlert==U.val()){return}ShortPixel.resizeSizesAlert=U.val();var S=jQuery("#min-"+U.attr("name")).val();if(U.val()<Math.min(S,1024)){if(S>1024){alert(_spTr.pleaseDoNotSetLesser1024.format(U.attr("name")))}else{alert(_spTr.pleaseDoNotSetLesserSize.format(U.attr("name"),U.attr("name"),S))}T.preventDefault();U.focus()}else{this.defaultValue=U.val()}});jQuery(".shortpixel-confirm").click(function(T){var S=confirm(T.target.getAttribute("data-confirm"));if(!S){T.preventDefault();return false}return true})}function t(){jQuery("input.remove-folder-button").click(function(){var O=jQuery(this).data("value");var N=confirm(_spTr.areYouSureStopOptimizing.format(O));if(N==true){jQuery("#removeFolder").val(O);jQuery("#wp_shortpixel_options").submit()}});jQuery("input.recheck-folder-button").click(function(){var O=jQuery(this).data("value");var N=confirm(_spTr.areYouSureStopOptimizing.format(O));if(N==true){jQuery("#recheckFolder").val(O);jQuery("#wp_shortpixel_options").submit()}})}function H(N){var O=jQuery("#"+(N.checked?"total":"main")+"ToProcess").val();jQuery("div.bulk-play span.total").text(O);jQuery("#displayTotal").text(O)}function w(O){var N=jQuery("section#"+O);if(N.length>0){jQuery("section").removeClass("sel-tab");jQuery("section#"+O).addClass("sel-tab")}}function x(){var N=jQuery("section#tab-settings .wp-shortpixel-options").height()+90;N=Math.max(N,jQuery("section#tab-adv-settings .wp-shortpixel-options").height()+20);N=Math.max(N,jQuery("section#tab-resources .area1").height()+60);jQuery("#shortpixel-settings-tabs").css("height",N);jQuery("#shortpixel-settings-tabs section").css("height",N)}function J(){var N={action:"shortpixel_dismiss_media_alert"};jQuery.get(ShortPixel.AJAX_URL,N,function(O){N=JSON.parse(O);if(N.Status=="success"){jQuery("#short-pixel-media-alert").hide();console.log("dismissed")}})}function j(){var N={action:"shortpixel_check_quota"};jQuery.get(ShortPixel.AJAX_URL,N,function(){console.log("quota refreshed")})}function z(N){if(N.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 b(R,P,O,Q,N){return(P>0?"<div class='sp-column-info'>"+_spTr.reducedBy+" <strong><span class='percent'>"+P+"%</span></strong> ":"")+(P>0&&P<5?"<br>":"")+(P<5?_spTr.bonusProcessing:"")+(O.length>0?" ("+O+")":"")+(0+Q>0?"<br>"+_spTr.plusXthumbsOpt.format(Q):"")+(0+N>0?"<br>"+_spTr.plusXretinasOpt.format(N):"")+"</div>"}function o(O,N){jQuery(O).knob({readOnly:true,width:N,height:N,fgColor:"#1CAECB",format:function(P){return P+"%"}})}function c(U,P,S,R,O,T){if(O==1){var Q=jQuery(".sp-column-actions-template").clone();if(!Q.length){return false}var N;if(P.length==0){N=["lossy","lossless"]}else{N=["lossy","glossy","lossless"].filter(function(V){return !(V==P)})}Q.html(Q.html().replace(/__SP_ID__/g,U));if(T.substr(T.lastIndexOf(".")+1).toLowerCase()=="pdf"){jQuery(".sp-action-compare",Q).remove()}if(S==0&&R>0){Q.html(Q.html().replace("__SP_THUMBS_TOTAL__",R))}else{jQuery(".sp-action-optimize-thumbs",Q).remove();jQuery(".sp-dropbtn",Q).removeClass("button-primary")}Q.html(Q.html().replace(/__SP_FIRST_TYPE__/g,N[0]));Q.html(Q.html().replace(/__SP_SECOND_TYPE__/g,N[1]));return Q.html()}return""}function h(R,Q){R=R.substring(2);if(jQuery(".shortpixel-other-media").length){var P=["optimize","retry","restore","redo","quota","view"];for(var O=0,N=P.length;O<N;O++){jQuery("#"+P[O]+"_"+R).css("display","none")}for(var O=0,N=Q.length;O<N;O++){jQuery("#"+Q[O]+"_"+R).css("display","")}}}function i(N){ShortPixel.retries++;if(isNaN(ShortPixel.retries)){ShortPixel.retries=1}if(ShortPixel.retries<6){console.log("Invalid response from server (Error: "+N+"). Retrying pass "+(ShortPixel.retries+1)+"...");setTimeout(checkBulkProgress,5000)}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: "+N+")","");console.log("Invalid response from server 6 times. Giving up.")}}function k(N){N.action="shortpixel_browse_content";var O="";jQuery.ajax({type:"POST",url:ShortPixel.AJAX_URL,data:N,success:function(P){O=P},async:false});return O}function d(){var N={action:"shortpixel_get_backup_size"};var O="";jQuery.ajax({type:"POST",url:ShortPixel.AJAX_URL,data:N,success:function(P){O=P},async:false});return O}function f(O){if(!jQuery("#tos").is(":checked")){O.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 N={action:"shortpixel_new_api_key",email:jQuery("#pluginemail").val()};jQuery.ajax({type:"POST",async:false,url:ShortPixel.AJAX_URL,data:N,success:function(P){data=JSON.parse(P);if(data.Status=="success"){O.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");O.preventDefault()}else{}}}});jQuery("#request_key").removeAttr("onclick")}else{jQuery("#pluginemail-error").css("display","");jQuery("#pluginemail-info").css("display","none");O.preventDefault()}jQuery("#request_key").removeClass("disabled");jQuery("#pluginemail_spinner").removeClass("is-active")}function K(){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 N={action:"shortpixel_propose_upgrade"};jQuery.ajax({type:"POST",url:ShortPixel.AJAX_URL,data:N,success:function(O){jQuery("#shortPixelProposeUpgrade .sp-modal-body").removeClass("sptw-modal-spinner");jQuery("#shortPixelProposeUpgrade .sp-modal-body").html(O)}})}function D(){jQuery("#shortPixelProposeUpgradeShade").css("display","none");jQuery("#shortPixelProposeUpgrade").addClass("shortpixel-hide");if(ShortPixel.toRefresh){ShortPixel.recheckQuota()}}function u(){jQuery("#short-pixel-notice-unlisted").hide();jQuery("#optimizeUnlisted").prop("checked",true);var N={action:"shortpixel_dismiss_notice",notice_id:"unlisted",notice_data:"true"};jQuery.get(ShortPixel.AJAX_URL,N,function(O){N=JSON.parse(O);if(N.Status==ShortPixel.STATUS_SUCCESS){console.log("dismissed")}})}function n(){jQuery(".select-folder-button").click(function(){jQuery(".sp-folder-picker-shade").css("display","block");jQuery(".sp-folder-picker").fileTree({script:ShortPixel.browseContent,multiFolder:false})});jQuery(".shortpixel-modal input.select-folder-cancel").click(function(){jQuery(".sp-folder-picker-shade").css("display","none")});jQuery(".shortpixel-modal input.select-folder").click(function(){var N=jQuery("UL.jqueryFileTree LI.directory.selected A").attr("rel").trim();if(N){var O=jQuery("#customFolderBase").val()+N;if(O.slice(-1)=="/"){O=O.slice(0,-1)}jQuery("#addCustomFolder").val(O);jQuery("#addCustomFolderView").val(O);jQuery(".sp-folder-picker-shade").css("display","none")}else{alert("Please select a folder from the list.")}})}function C(R,Q,P){var O=jQuery(".bulk-notice-msg.bulk-lengthy");if(O.length==0){return}var N=jQuery("a",O);N.text(Q);if(P){N.attr("href",P)}else{N.attr("href",N.data("href").replace("__ID__",R))}O.css("display","block")}function y(){jQuery(".bulk-notice-msg.bulk-lengthy").css("display","none")}function v(N){var O=jQuery(".bulk-notice-msg.bulk-"+N);if(O.length==0){return}O.css("display","block")}function L(N){jQuery(".bulk-notice-msg.bulk-"+N).css("display","none")}function r(T,R,S,Q){var N=jQuery("#bulk-error-template");if(N.length==0){return}var P=N.clone();P.attr("id","bulk-error-"+T);if(T==-1){jQuery("span.sp-err-title",P).remove();P.addClass("bulk-error-fatal")}else{jQuery("img",P).remove();jQuery("#bulk-error-".id).remove()}jQuery("span.sp-err-content",P).html(R);var O=jQuery("a.sp-post-link",P);if(Q){O.attr("href",Q)}else{O.attr("href",O.attr("href").replace("__ID__",T))}O.text(S);N.after(P);P.css("display","block")}function A(N,O){if(!confirm(_spTr["confirmBulk"+N])){O.stopPropagation();O.preventDefault();return false}return true}function q(N){jQuery(N).parent().parent().remove()}function E(N){return N.substring(0,2)=="C-"}function G(){window.location.href=window.location.href+(window.location.href.indexOf("?")>0?"&":"?")+"checkquota=1"}function g(O){O.preventDefault();if(!this.menuCloseEvent){jQuery(window).click(function(P){if(!P.target.matches(".sp-dropbtn")){jQuery(".sp-dropdown.sp-show").removeClass("sp-show")}});this.menuCloseEvent=true}var N=O.target.parentElement.classList.contains("sp-show");jQuery(".sp-dropdown.sp-show").removeClass("sp-show");if(!N){O.target.parentElement.classList.add("sp-show")}}function M(N){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;jQuery(".sp-close-button").click(ShortPixel.closeComparerPopup)}if(this.comparerData.origUrl===false){jQuery.ajax({type:"POST",url:ShortPixel.AJAX_URL,data:{action:"shortpixel_get_comparer_data",id:N},success:function(O){data=JSON.parse(O);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 B(R,P,O,Q){var U=R;var T=(P<150||R<350);var S=jQuery(T?"#spUploadCompareSideBySide":"#spUploadCompare");if(!T){jQuery("#spCompareSlider").html('<img class="spUploadCompareOriginal"/><img class="spUploadCompareOptimized"/>')}R=Math.max(350,Math.min(800,(R<350?(R+25)*2:(P<150?R+25:R))));P=Math.max(150,(T?(U>350?2*(P+45):P+45):P*R/U));jQuery(".sp-modal-body",S).css("width",R);jQuery(".shortpixel-slider",S).css("width",R);S.css("width",R);jQuery(".sp-modal-body",S).css("height",P);S.css("display","block");S.parent().css("display","block");if(!T){jQuery("#spCompareSlider").twentytwenty({slider_move:"mousemove"})}jQuery(document).on("keyup.sp_modal_active",ShortPixel.closeComparerPopup);var N=jQuery(".spUploadCompareOptimized",S);jQuery(".spUploadCompareOriginal",S).attr("src",O);setTimeout(function(){jQuery(window).trigger("resize")},1000);N.load(function(){jQuery(window).trigger("resize")});N.attr("src",Q)}function p(N){jQuery("#spUploadCompareSideBySide").parent().css("display","none");jQuery("#spUploadCompareSideBySide").css("display","none");jQuery("#spUploadCompare").css("display","none");jQuery(document).unbind("keyup.sp_modal_active")}return{init:F,setOptions:l,isEmailValid:s,updateSignupEmail:m,validateKey:a,enableResize:I,setupGeneralTab:e,setupAdvancedTab:t,checkThumbsUpdTotal:H,switchSettingsTab:w,adjustSettingsTabs:x,onBulkThumbsCheck:z,dismissMediaAlert:J,checkQuota:j,percentDial:o,successMsg:b,successActions:c,otherMediaUpdateActions:h,retry:i,initFolderSelector:n,browseContent:k,getBackupSize:d,newApiKey:f,proposeUpgrade:K,closeProposeUpgrade:D,includeUnlisted:u,bulkShowLengthyMsg:C,bulkHideLengthyMsg:y,bulkShowMaintenanceMsg:v,bulkHideMaintenanceMsg:L,bulkShowError:r,confirmBulkAction:A,removeBulkMsg:q,isCustomImageId:E,recheckQuota:G,openImageMenu:g,menuCloseEvent:false,loadComparer:M,displayComparerPopup:B,closeComparerPopup:p,comparerData:{cssLoaded:false,jsLoaded:false,origUrl:false,optUrl:false,width:0,height:0},toRefresh:false,resizeSizesAlert:false}}();function showToolBarAlert(c,b,d){var a=jQuery("li.shortpixel-toolbar-processing");switch(c){case ShortPixel.STATUS_QUOTA_EXCEEDED:if(window.location.href.search("wp-short-pixel-bulk")>0&&jQuery(".sp-quota-exceeded-alert").length==0){location.reload();return}a.addClass("shortpixel-alert");a.addClass("shortpixel-quota-exceeded");jQuery("a",a).attr("href","options-general.php?page=wp-shortpixel");jQuery("a div",a).attr("title","ShortPixel quota exceeded. Click for details.");break;case ShortPixel.STATUS_SKIP:case ShortPixel.STATUS_FAIL:a.addClass("shortpixel-alert shortpixel-processing");jQuery("a div",a).attr("title",b);if(typeof d!=="undefined"){jQuery("a",a).attr("href","post.php?post="+d+"&action=edit")}break;case ShortPixel.STATUS_NO_KEY:a.addClass("shortpixel-alert");a.addClass("shortpixel-quota-exceeded");jQuery("a",a).attr("href","options-general.php?page=wp-shortpixel");jQuery("a div",a).attr("title","Get API Key");break;case ShortPixel.STATUS_SUCCESS:case ShortPixel.STATUS_RETRY:a.addClass("shortpixel-processing");a.removeClass("shortpixel-alert");jQuery("a",a).removeAttr("target");jQuery("a",a).attr("href",jQuery("a img",a).attr("success-url"))}a.removeClass("shortpixel-hide")}function hideToolBarAlert(){jQuery("li.shortpixel-toolbar-processing.shortpixel-processing").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 b=function(f){if(!d){d=true;return f}return"/"};var d=false;var a=window.location.href.toLowerCase().replace(/\/\//g,b);d=false;var c=ShortPixel.WP_ADMIN_URL.toLowerCase().replace(/\/\//g,b);if(a.search(c)<0){var e=document.createElement("a");e.href=a;a=a.replace(e.protocol+"//"+e.hostname,e.protocol+"//"+e.hostname.split(".").map(function(f){return sp_punycode.toASCII(f)}).join("."))}if(a.search(c+"upload.php")<0&&a.search(c+"edit.php")<0&&a.search(c+"edit-tags.php")<0&&a.search(c+"post-new.php")<0&&a.search(c+"post.php")<0&&a.search("page=nggallery-manage-gallery")<0&&(ShortPixel.FRONT_BOOTSTRAP==0||a.search(c)==0)){hideToolBarAlert();return}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=Math.floor(Date.now()/1000);localStorage.bulkPage=1}if(ShortPixel.bulkProcessor==true||typeof localStorage.bulkTime=="undefined"||Math.floor(Date.now()/1000)-localStorage.bulkTime>90){ShortPixel.bulkProcessor=true;localStorage.bulkPage=(window.location.href.search("wp-short-pixel-bulk")>=0?1:0);localStorage.bulkTime=Math.floor(Date.now()/1000);console.log(localStorage.bulkTime);checkBulkProcessingCallApi()}else{setTimeout(checkBulkProgress,5000)}}function checkBulkProcessingCallApi(){var a={action:"shortpixel_image_processing"};jQuery.ajax({type:"POST",url:ShortPixel.AJAX_URL,data:a,success:function(g){if(g.length>0){var i=null;try{var i=JSON.parse(g)}catch(k){ShortPixel.retry(k.message);return}ShortPixel.retries=0;var d=i.ImageID;var j=(jQuery("div.short-pixel-bulk-page").length>0);switch(i.Status){case ShortPixel.STATUS_NO_KEY:setCellMessage(d,i.Message,"<a class='button button-smaller button-primary' href=\"https://shortpixel.com/wp-apikey"+ShortPixel.AFFILIATE+'" target="_blank">'+_spTr.getApiKey+"</a>");showToolBarAlert(ShortPixel.STATUS_NO_KEY);break;case ShortPixel.STATUS_QUOTA_EXCEEDED:setCellMessage(d,i.Message,"<a class='button button-smaller button-primary' href=\"https://shortpixel.com/login/"+ShortPixel.API_KEY+'" 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);if(i.Stop==false){setTimeout(checkBulkProgress,5000)}ShortPixel.otherMediaUpdateActions(d,["quota","view"]);break;case ShortPixel.STATUS_FAIL:setCellMessage(d,i.Message,"<a class='button button-smaller button-primary' href=\"javascript:manualOptimization('"+d+"', false)\">"+_spTr.retry+"</a>");showToolBarAlert(ShortPixel.STATUS_FAIL,i.Message,d);if(j){ShortPixel.bulkShowError(d,i.Message,i.Filename,i.CustomImageLink);if(i.BulkPercent){progressUpdate(i.BulkPercent,i.BulkMsg)}ShortPixel.otherMediaUpdateActions(d,["retry","view"])}console.log(i.Message);setTimeout(checkBulkProgress,5000);break;case ShortPixel.STATUS_EMPTY_QUEUE:console.log(i.Message);clearBulkProcessor();hideToolBarAlert();var c=jQuery("#bulk-progress");if(j&&c.length&&i.BulkStatus!="2"){progressUpdate(100,"Bulk finished!");jQuery("a.bulk-cancel").attr("disabled","disabled");hideSlider();setTimeout(function(){window.location.reload()},3000)}break;case ShortPixel.STATUS_SUCCESS:if(j){ShortPixel.bulkHideLengthyMsg();ShortPixel.bulkHideMaintenanceMsg()}var l=i.PercentImprovement;showToolBarAlert(ShortPixel.STATUS_SUCCESS,"");var b=ShortPixel.isCustomImageId(d)?"":ShortPixel.successActions(d,i.Type,i.ThumbsCount,i.ThumbsTotal,i.BackupEnabled,i.Filename);setCellMessage(d,ShortPixel.successMsg(d,l,i.Type,i.ThumbsCount,i.RetinasCount),b);var h=jQuery(["restore","view","redolossy","redoglossy","redolossless"]).not(["redo"+i.Type]).get();ShortPixel.otherMediaUpdateActions(d,h);var f=new PercentageAnimator("#sp-msg-"+d+" span.percent",l);f.animate(l);if(j&&typeof i.Thumb!=="undefined"){if(i.BulkPercent){progressUpdate(i.BulkPercent,i.BulkMsg)}if(i.Thumb.length>0){sliderUpdate(d,i.Thumb,i.BkThumb,i.PercentImprovement,i.Filename);if(typeof i.AverageCompression!=="undefined"&&0+i.AverageCompression>0){jQuery("#sp-avg-optimization").html('<input type="text" class="dial" value="'+Math.round(i.AverageCompression)+'"/>');ShortPixel.percentDial("#sp-avg-optimization .dial",60)}}}console.log("Server response: "+g);if(j&&typeof i.BulkPercent!=="undefined"){progressUpdate(i.BulkPercent,i.BulkMsg)}setTimeout(checkBulkProgress,5000);break;case ShortPixel.STATUS_SKIP:if(i.Silent!==1){ShortPixel.bulkShowError(d,i.Message,i.Filename,i.CustomImageLink)}case ShortPixel.STATUS_ERROR:if(typeof i.Message!=="undefined"){showToolBarAlert(ShortPixel.STATUS_SKIP,i.Message+" Image ID: "+d);setCellMessage(d,i.Message,"")}ShortPixel.otherMediaUpdateActions(d,["retry","view"]);case ShortPixel.STATUS_RETRY:console.log("Server response: "+g);showToolBarAlert(ShortPixel.STATUS_RETRY,"");if(j&&typeof i.BulkPercent!=="undefined"){progressUpdate(i.BulkPercent,i.BulkMsg)}if(j&&i.Count>3){ShortPixel.bulkShowLengthyMsg(d,i.Filename,i.CustomImageLink)}setTimeout(checkBulkProgress,5000);break;case ShortPixel.STATUS_MAINTENANCE:ShortPixel.bulkShowMaintenanceMsg("maintenance");setTimeout(checkBulkProgress,60000);break;case ShortPixel.STATUS_QUEUE_FULL:ShortPixel.bulkShowMaintenanceMsg("queue-full");setTimeout(checkBulkProgress,60000);break;default:ShortPixel.retry("Unknown status "+i.Status+". Retrying...");break}}},error:function(b){ShortPixel.retry(b.statusText)}})}function clearBulkProcessor(){ShortPixel.bulkProcessor=false;localStorage.bulkTime=0;if(window.location.href.search("wp-short-pixel-bulk")>=0){localStorage.bulkPage=0}}function setCellMessage(d,a,c){var b=jQuery("#sp-msg-"+d);if(b.length>0){b.html("<div class='sp-column-actions'>"+c+"</div><div class='sp-column-info'>"+a+"</div>");b.css("color","")}b=jQuery("#sp-cust-msg-"+d);if(b.length>0){b.html("<div class='sp-column-info'>"+a+"</div>")}}function manualOptimization(c,a){setCellMessage(c,"<img src='"+ShortPixel.WP_PLUGIN_URL+"/res/img/loading.gif' 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 b={action:"shortpixel_manual_optimization",image_id:c,cleanup:a};jQuery.ajax({type:"GET",url:ShortPixel.AJAX_URL,data:b,success:function(d){var e=JSON.parse(d);if(e.Status==ShortPixel.STATUS_SUCCESS){setTimeout(checkBulkProgress,2000)}else{setCellMessage(c,typeof e.Message!=="undefined"?e.Message:_spTr.thisContentNotProcessable,"")}},error:function(d){b.action="shortpixel_check_status";jQuery.ajax({type:"GET",url:ShortPixel.AJAX_URL,data:b,success:function(e){var f=JSON.parse(e);if(f.Status!==ShortPixel.STATUS_SUCCESS){setCellMessage(c,typeof f.Message!=="undefined"?f.Message:_spTr.thisContentNotProcessable,"")}}})}})}function reoptimize(c,a){setCellMessage(c,"<img src='"+ShortPixel.WP_PLUGIN_URL+"/res/img/loading.gif' 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 b={action:"shortpixel_redo",attachment_ID:c,type:a};jQuery.get(ShortPixel.AJAX_URL,b,function(d){b=JSON.parse(d);if(b.Status==ShortPixel.STATUS_SUCCESS){setTimeout(checkBulkProgress,2000)}else{$msg=typeof b.Message!=="undefined"?b.Message:_spTr.thisContentNotProcessable;setCellMessage(c,$msg,"");showToolBarAlert(ShortPixel.STATUS_FAIL,$msg)}})}function optimizeThumbs(b){setCellMessage(b,"<img src='"+ShortPixel.WP_PLUGIN_URL+"/res/img/loading.gif' class='sp-loading-small'>"+_spTr.imageWaitOptThumbs,"");jQuery("li.shortpixel-toolbar-processing").removeClass("shortpixel-hide");jQuery("li.shortpixel-toolbar-processing").addClass("shortpixel-processing");var a={action:"shortpixel_optimize_thumbs",attachment_ID:b};jQuery.get(ShortPixel.AJAX_URL,a,function(c){a=JSON.parse(c);if(a.Status==ShortPixel.STATUS_SUCCESS){setTimeout(checkBulkProgress,2000)}else{setCellMessage(b,typeof a.Message!=="undefined"?a.Message:_spTr.thisContentNotProcessable,"")}})}function dismissShortPixelNoticeExceed(b){jQuery("#wp-admin-bar-shortpixel_processing").hide();var a={action:"shortpixel_dismiss_notice",notice_id:"exceed"};jQuery.get(ShortPixel.AJAX_URL,a,function(c){a=JSON.parse(c);if(a.Status==ShortPixel.STATUS_SUCCESS){console.log("dismissed")}});b.preventDefault()}function dismissShortPixelNotice(b){jQuery("#short-pixel-notice-"+b).hide();var a={action:"shortpixel_dismiss_notice",notice_id:b};jQuery.get(ShortPixel.AJAX_URL,a,function(c){a=JSON.parse(c);if(a.Status==ShortPixel.STATUS_SUCCESS){console.log("dismissed")}})}function PercentageAnimator(b,a){this.animationSpeed=10;this.increment=2;this.curPercentage=0;this.targetPercentage=a;this.outputSelector=b;this.animate=function(c){this.targetPercentage=c;setTimeout(PercentageTimer.bind(null,this),this.animationSpeed)}}function PercentageTimer(a){if(a.curPercentage-a.targetPercentage<-a.increment){a.curPercentage+=a.increment}else{if(a.curPercentage-a.targetPercentage>a.increment){a.curPercentage-=a.increment}else{a.curPercentage=a.targetPercentage}}jQuery(a.outputSelector).text(a.curPercentage+"%");if(a.curPercentage!=a.targetPercentage){setTimeout(PercentageTimer.bind(null,a),a.animationSpeed)}}function progressUpdate(c,b){var a=jQuery("#bulk-progress");if(a.length){jQuery(".progress-left",a).css("width",c+"%");jQuery(".progress-img",a).css("left",c+"%");if(c>24){jQuery(".progress-img span",a).html("");jQuery(".progress-left",a).html(c+"%")}else{jQuery(".progress-img span",a).html(c+"%");jQuery(".progress-left",a).html("")}jQuery(".bulk-estimate").html(b)}}function sliderUpdate(g,c,d,e,b){var f=jQuery(".bulk-slider div.bulk-slide:first-child");if(f.length===0){return}if(f.attr("id")!="empty-slide"){f.hide()}f.css("z-index",1000);jQuery(".bulk-img-opt",f).attr("src","");if(typeof d==="undefined"){d=""}if(d.length>0){jQuery(".bulk-img-orig",f).attr("src","")}var a=f.clone();a.attr("id","slide-"+g);jQuery(".bulk-img-opt",a).attr("src",c);if(d.length>0){jQuery(".img-original",a).css("display","inline-block");jQuery(".bulk-img-orig",a).attr("src",d)}else{jQuery(".img-original",a).css("display","none")}jQuery(".bulk-opt-percent",a).html('<input type="text" class="dial" value="'+e+'"/>');jQuery(".bulk-slider").append(a);ShortPixel.percentDial("#"+a.attr("id")+" .dial",100);jQuery(".bulk-slider-container span.filename").html("&nbsp;&nbsp;"+b);if(f.attr("id")=="empty-slide"){f.remove();jQuery(".bulk-slider-container").css("display","block")}else{f.animate({left:f.width()+f.position().left},"slow","swing",function(){f.remove();a.fadeIn("slow")})}}function hideSlider(){jQuery(".bulk-slider-container").css("display","none")}function showStats(){var a=jQuery(".bulk-stats");if(a.length>0){}}if(!(typeof String.prototype.format=="function")){String.prototype.format=function(){var b=this,a=arguments.length;while(a--){b=b.replace(new RegExp("\\{"+a+"\\}","gm"),arguments[a])}return b}};
1
+ jQuery(document).ready(function(a){ShortPixel.init()});var ShortPixel=function(){function G(){if(typeof ShortPixel.API_KEY!=="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);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>'+_spTr.changeMLToListMode.format('<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 l(O){for(var P in O){ShortPixel[P]=O[P]}}function s(O){return/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{1,63})+$/.test(O)}function m(){var O=jQuery("#pluginemail").val();if(ShortPixel.isEmailValid(O)){jQuery("#request_key").removeClass("disabled")}jQuery("#request_key").attr("href",jQuery("#request_key").attr("href").split("?")[0]+"?pluginemail="+O)}function a(){jQuery("#valid").val("validate");jQuery("#wp_shortpixel_options").submit()}jQuery("#key").keypress(function(O){if(O.which==13){jQuery("#valid").val("validate")}});function J(O){if(jQuery(O).is(":checked")){jQuery("#width,#height").removeAttr("disabled")}else{jQuery("#width,#height").attr("disabled","disabled")}}function e(O,Q,S){for(var P=0,R=null;P<O.length;P++){O[P].onclick=function(){if(this!==R){R=this}if(typeof ShortPixel.setupGeneralTabAlert!=="undefined"){return}alert(_spTr.alertOnlyAppliesToNewImages);ShortPixel.setupGeneralTabAlert=1}}ShortPixel.enableResize("#resize");jQuery("#resize").change(function(){J(this)});jQuery(".resize-sizes").blur(function(U){var V=jQuery(this);if(ShortPixel.resizeSizesAlert==V.val()){return}ShortPixel.resizeSizesAlert=V.val();var T=jQuery("#min-"+V.attr("name")).val();if(V.val()<Math.min(T,1024)){if(T>1024){alert(_spTr.pleaseDoNotSetLesser1024.format(V.attr("name")))}else{alert(_spTr.pleaseDoNotSetLesserSize.format(V.attr("name"),V.attr("name"),T))}U.preventDefault();V.focus()}else{this.defaultValue=V.val()}});jQuery(".shortpixel-confirm").click(function(U){var T=confirm(U.target.getAttribute("data-confirm"));if(!T){U.preventDefault();return false}return true})}function A(){jQuery(".wp-shortpixel-options .shortpixel-key-valid").css("display","none");jQuery(".wp-shortpixel-options button#validate").css("display","inline-block")}function t(){jQuery("input.remove-folder-button").click(function(){var P=jQuery(this).data("value");var O=confirm(_spTr.areYouSureStopOptimizing.format(P));if(O==true){jQuery("#removeFolder").val(P);jQuery("#wp_shortpixel_options").submit()}});jQuery("input.recheck-folder-button").click(function(){var P=jQuery(this).data("value");var O=confirm(_spTr.areYouSureStopOptimizing.format(P));if(O==true){jQuery("#recheckFolder").val(P);jQuery("#wp_shortpixel_options").submit()}})}function I(O){var P=jQuery("#"+(O.checked?"total":"main")+"ToProcess").val();jQuery("div.bulk-play span.total").text(P);jQuery("#displayTotal").text(P)}function w(P){var O=jQuery("section#"+P);if(O.length>0){jQuery("section").removeClass("sel-tab");jQuery("section#"+P).addClass("sel-tab")}}function x(){var O=jQuery("section#tab-settings .wp-shortpixel-options").height()+90;O=Math.max(O,jQuery("section#tab-adv-settings .wp-shortpixel-options").height()+20);O=Math.max(O,jQuery("section#tab-resources .area1").height()+60);jQuery("#shortpixel-settings-tabs").css("height",O);jQuery("#shortpixel-settings-tabs section").css("height",O)}function K(){var O={action:"shortpixel_dismiss_media_alert"};jQuery.get(ShortPixel.AJAX_URL,O,function(P){O=JSON.parse(P);if(O.Status=="success"){jQuery("#short-pixel-media-alert").hide();console.log("dismissed")}})}function j(){var O={action:"shortpixel_check_quota"};jQuery.get(ShortPixel.AJAX_URL,O,function(){console.log("quota refreshed")})}function z(O){if(O.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 b(S,Q,P,R,O){return(Q>0?"<div class='sp-column-info'>"+_spTr.reducedBy+" <strong><span class='percent'>"+Q+"%</span></strong> ":"")+(Q>0&&Q<5?"<br>":"")+(Q<5?_spTr.bonusProcessing:"")+(P.length>0?" ("+P+")":"")+(0+R>0?"<br>"+_spTr.plusXthumbsOpt.format(R):"")+(0+O>0?"<br>"+_spTr.plusXretinasOpt.format(O):"")+"</div>"}function o(P,O){jQuery(P).knob({readOnly:true,width:O,height:O,fgColor:"#1CAECB",format:function(Q){return Q+"%"}})}function c(V,Q,T,S,P,U){if(P==1){var R=jQuery(".sp-column-actions-template").clone();if(!R.length){return false}var O;if(Q.length==0){O=["lossy","lossless"]}else{O=["lossy","glossy","lossless"].filter(function(W){return !(W==Q)})}R.html(R.html().replace(/__SP_ID__/g,V));if(U.substr(U.lastIndexOf(".")+1).toLowerCase()=="pdf"){jQuery(".sp-action-compare",R).remove()}if(T==0&&S>0){R.html(R.html().replace("__SP_THUMBS_TOTAL__",S))}else{jQuery(".sp-action-optimize-thumbs",R).remove();jQuery(".sp-dropbtn",R).removeClass("button-primary")}R.html(R.html().replace(/__SP_FIRST_TYPE__/g,O[0]));R.html(R.html().replace(/__SP_SECOND_TYPE__/g,O[1]));return R.html()}return""}function h(S,R){S=S.substring(2);if(jQuery(".shortpixel-other-media").length){var Q=["optimize","retry","restore","redo","quota","view"];for(var P=0,O=Q.length;P<O;P++){jQuery("#"+Q[P]+"_"+S).css("display","none")}for(var P=0,O=R.length;P<O;P++){jQuery("#"+R[P]+"_"+S).css("display","")}}}function i(O){ShortPixel.retries++;if(isNaN(ShortPixel.retries)){ShortPixel.retries=1}if(ShortPixel.retries<6){console.log("Invalid response from server (Error: "+O+"). Retrying pass "+(ShortPixel.retries+1)+"...");setTimeout(checkBulkProgress,5000)}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: "+O+")","");console.log("Invalid response from server 6 times. Giving up.")}}function k(O){O.action="shortpixel_browse_content";var P="";jQuery.ajax({type:"POST",url:ShortPixel.AJAX_URL,data:O,success:function(Q){P=Q},async:false});return P}function d(){var O={action:"shortpixel_get_backup_size"};var P="";jQuery.ajax({type:"POST",url:ShortPixel.AJAX_URL,data:O,success:function(Q){P=Q},async:false});return P}function f(P){if(!jQuery("#tos").is(":checked")){P.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 O={action:"shortpixel_new_api_key",email:jQuery("#pluginemail").val()};jQuery.ajax({type:"POST",async:false,url:ShortPixel.AJAX_URL,data:O,success:function(Q){data=JSON.parse(Q);if(data.Status=="success"){P.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");P.preventDefault()}else{}}}});jQuery("#request_key").removeAttr("onclick")}else{jQuery("#pluginemail-error").css("display","");jQuery("#pluginemail-info").css("display","none");P.preventDefault()}jQuery("#request_key").removeClass("disabled");jQuery("#pluginemail_spinner").removeClass("is-active")}function L(){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 O={action:"shortpixel_propose_upgrade"};jQuery.ajax({type:"POST",url:ShortPixel.AJAX_URL,data:O,success:function(P){jQuery("#shortPixelProposeUpgrade .sp-modal-body").removeClass("sptw-modal-spinner");jQuery("#shortPixelProposeUpgrade .sp-modal-body").html(P)}})}function E(){jQuery("#shortPixelProposeUpgradeShade").css("display","none");jQuery("#shortPixelProposeUpgrade").addClass("shortpixel-hide");if(ShortPixel.toRefresh){ShortPixel.recheckQuota()}}function u(){jQuery("#short-pixel-notice-unlisted").hide();jQuery("#optimizeUnlisted").prop("checked",true);var O={action:"shortpixel_dismiss_notice",notice_id:"unlisted",notice_data:"true"};jQuery.get(ShortPixel.AJAX_URL,O,function(P){O=JSON.parse(P);if(O.Status==ShortPixel.STATUS_SUCCESS){console.log("dismissed")}})}function n(){jQuery(".select-folder-button").click(function(){jQuery(".sp-folder-picker-shade").css("display","block");jQuery(".sp-folder-picker").fileTree({script:ShortPixel.browseContent,multiFolder:false})});jQuery(".shortpixel-modal input.select-folder-cancel").click(function(){jQuery(".sp-folder-picker-shade").css("display","none")});jQuery(".shortpixel-modal input.select-folder").click(function(){var O=jQuery("UL.jqueryFileTree LI.directory.selected A").attr("rel").trim();if(O){var P=jQuery("#customFolderBase").val()+O;if(P.slice(-1)=="/"){P=P.slice(0,-1)}jQuery("#addCustomFolder").val(P);jQuery("#addCustomFolderView").val(P);jQuery(".sp-folder-picker-shade").css("display","none")}else{alert("Please select a folder from the list.")}})}function D(S,R,Q){var P=jQuery(".bulk-notice-msg.bulk-lengthy");if(P.length==0){return}var O=jQuery("a",P);O.text(R);if(Q){O.attr("href",Q)}else{O.attr("href",O.data("href").replace("__ID__",S))}P.css("display","block")}function y(){jQuery(".bulk-notice-msg.bulk-lengthy").css("display","none")}function v(O){var P=jQuery(".bulk-notice-msg.bulk-"+O);if(P.length==0){return}P.css("display","block")}function M(O){jQuery(".bulk-notice-msg.bulk-"+O).css("display","none")}function r(U,S,T,R){var O=jQuery("#bulk-error-template");if(O.length==0){return}var Q=O.clone();Q.attr("id","bulk-error-"+U);if(U==-1){jQuery("span.sp-err-title",Q).remove();Q.addClass("bulk-error-fatal")}else{jQuery("img",Q).remove();jQuery("#bulk-error-".id).remove()}jQuery("span.sp-err-content",Q).html(S);var P=jQuery("a.sp-post-link",Q);if(R){P.attr("href",R)}else{P.attr("href",P.attr("href").replace("__ID__",U))}P.text(T);O.after(Q);Q.css("display","block")}function B(O,P){if(!confirm(_spTr["confirmBulk"+O])){P.stopPropagation();P.preventDefault();return false}return true}function q(O){jQuery(O).parent().parent().remove()}function F(O){return O.substring(0,2)=="C-"}function H(){window.location.href=window.location.href+(window.location.href.indexOf("?")>0?"&":"?")+"checkquota=1"}function g(P){P.preventDefault();if(!this.menuCloseEvent){jQuery(window).click(function(Q){if(!Q.target.matches(".sp-dropbtn")){jQuery(".sp-dropdown.sp-show").removeClass("sp-show")}});this.menuCloseEvent=true}var O=P.target.parentElement.classList.contains("sp-show");jQuery(".sp-dropdown.sp-show").removeClass("sp-show");if(!O){P.target.parentElement.classList.add("sp-show")}}function N(O){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;jQuery(".sp-close-button").click(ShortPixel.closeComparerPopup)}if(this.comparerData.origUrl===false){jQuery.ajax({type:"POST",url:ShortPixel.AJAX_URL,data:{action:"shortpixel_get_comparer_data",id:O},success:function(P){data=JSON.parse(P);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 C(S,Q,P,R){var V=S;var U=(Q<150||S<350);var T=jQuery(U?"#spUploadCompareSideBySide":"#spUploadCompare");if(!U){jQuery("#spCompareSlider").html('<img class="spUploadCompareOriginal"/><img class="spUploadCompareOptimized"/>')}S=Math.max(350,Math.min(800,(S<350?(S+25)*2:(Q<150?S+25:S))));Q=Math.max(150,(U?(V>350?2*(Q+45):Q+45):Q*S/V));jQuery(".sp-modal-body",T).css("width",S);jQuery(".shortpixel-slider",T).css("width",S);T.css("width",S);jQuery(".sp-modal-body",T).css("height",Q);T.css("display","block");T.parent().css("display","block");if(!U){jQuery("#spCompareSlider").twentytwenty({slider_move:"mousemove"})}jQuery(document).on("keyup.sp_modal_active",ShortPixel.closeComparerPopup);var O=jQuery(".spUploadCompareOptimized",T);jQuery(".spUploadCompareOriginal",T).attr("src",P);setTimeout(function(){jQuery(window).trigger("resize")},1000);O.load(function(){jQuery(window).trigger("resize")});O.attr("src",R)}function p(O){jQuery("#spUploadCompareSideBySide").parent().css("display","none");jQuery("#spUploadCompareSideBySide").css("display","none");jQuery("#spUploadCompare").css("display","none");jQuery(document).unbind("keyup.sp_modal_active")}return{init:G,setOptions:l,isEmailValid:s,updateSignupEmail:m,validateKey:a,enableResize:J,setupGeneralTab:e,apiKeyChanged:A,setupAdvancedTab:t,checkThumbsUpdTotal:I,switchSettingsTab:w,adjustSettingsTabs:x,onBulkThumbsCheck:z,dismissMediaAlert:K,checkQuota:j,percentDial:o,successMsg:b,successActions:c,otherMediaUpdateActions:h,retry:i,initFolderSelector:n,browseContent:k,getBackupSize:d,newApiKey:f,proposeUpgrade:L,closeProposeUpgrade:E,includeUnlisted:u,bulkShowLengthyMsg:D,bulkHideLengthyMsg:y,bulkShowMaintenanceMsg:v,bulkHideMaintenanceMsg:M,bulkShowError:r,confirmBulkAction:B,removeBulkMsg:q,isCustomImageId:F,recheckQuota:H,openImageMenu:g,menuCloseEvent:false,loadComparer:N,displayComparerPopup:C,closeComparerPopup:p,comparerData:{cssLoaded:false,jsLoaded:false,origUrl:false,optUrl:false,width:0,height:0},toRefresh:false,resizeSizesAlert:false}}();function showToolBarAlert(c,b,d){var a=jQuery("li.shortpixel-toolbar-processing");switch(c){case ShortPixel.STATUS_QUOTA_EXCEEDED:if(window.location.href.search("wp-short-pixel-bulk")>0&&jQuery(".sp-quota-exceeded-alert").length==0){location.reload();return}a.addClass("shortpixel-alert");a.addClass("shortpixel-quota-exceeded");jQuery("a",a).attr("href","options-general.php?page=wp-shortpixel");jQuery("a div",a).attr("title","ShortPixel quota exceeded. Click for details.");break;case ShortPixel.STATUS_SKIP:case ShortPixel.STATUS_FAIL:a.addClass("shortpixel-alert shortpixel-processing");jQuery("a div",a).attr("title",b);if(typeof d!=="undefined"){jQuery("a",a).attr("href","post.php?post="+d+"&action=edit")}break;case ShortPixel.STATUS_NO_KEY:a.addClass("shortpixel-alert");a.addClass("shortpixel-quota-exceeded");jQuery("a",a).attr("href","options-general.php?page=wp-shortpixel");jQuery("a div",a).attr("title","Get API Key");break;case ShortPixel.STATUS_SUCCESS:case ShortPixel.STATUS_RETRY:a.addClass("shortpixel-processing");a.removeClass("shortpixel-alert");jQuery("a",a).removeAttr("target");jQuery("a",a).attr("href",jQuery("a img",a).attr("success-url"))}a.removeClass("shortpixel-hide")}function hideToolBarAlert(){jQuery("li.shortpixel-toolbar-processing.shortpixel-processing").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 b=function(f){if(!d){d=true;return f}return"/"};var d=false;var a=window.location.href.toLowerCase().replace(/\/\//g,b);d=false;var c=ShortPixel.WP_ADMIN_URL.toLowerCase().replace(/\/\//g,b);if(a.search(c)<0){var e=document.createElement("a");e.href=a;a=a.replace(e.protocol+"//"+e.hostname,e.protocol+"//"+e.hostname.split(".").map(function(f){return sp_punycode.toASCII(f)}).join("."))}if(a.search(c+"upload.php")<0&&a.search(c+"edit.php")<0&&a.search(c+"edit-tags.php")<0&&a.search(c+"post-new.php")<0&&a.search(c+"post.php")<0&&a.search("page=nggallery-manage-gallery")<0&&(ShortPixel.FRONT_BOOTSTRAP==0||a.search(c)==0)){hideToolBarAlert();return}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=Math.floor(Date.now()/1000);localStorage.bulkPage=1}if(ShortPixel.bulkProcessor==true||typeof localStorage.bulkTime=="undefined"||Math.floor(Date.now()/1000)-localStorage.bulkTime>90){ShortPixel.bulkProcessor=true;localStorage.bulkPage=(window.location.href.search("wp-short-pixel-bulk")>=0?1:0);localStorage.bulkTime=Math.floor(Date.now()/1000);console.log(localStorage.bulkTime);checkBulkProcessingCallApi()}else{setTimeout(checkBulkProgress,5000)}}function checkBulkProcessingCallApi(){var a={action:"shortpixel_image_processing"};jQuery.ajax({type:"POST",url:ShortPixel.AJAX_URL,data:a,success:function(g){if(g.length>0){var i=null;try{var i=JSON.parse(g)}catch(k){ShortPixel.retry(k.message);return}ShortPixel.retries=0;var d=i.ImageID;var j=(jQuery("div.short-pixel-bulk-page").length>0);switch(i.Status){case ShortPixel.STATUS_NO_KEY:setCellMessage(d,i.Message,"<a class='button button-smaller button-primary' href=\"https://shortpixel.com/wp-apikey"+ShortPixel.AFFILIATE+'" target="_blank">'+_spTr.getApiKey+"</a>");showToolBarAlert(ShortPixel.STATUS_NO_KEY);break;case ShortPixel.STATUS_QUOTA_EXCEEDED:setCellMessage(d,i.Message,"<a class='button button-smaller button-primary' href=\"https://shortpixel.com/login/"+ShortPixel.API_KEY+'" 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);if(i.Stop==false){setTimeout(checkBulkProgress,5000)}ShortPixel.otherMediaUpdateActions(d,["quota","view"]);break;case ShortPixel.STATUS_FAIL:setCellMessage(d,i.Message,"<a class='button button-smaller button-primary' href=\"javascript:manualOptimization('"+d+"', false)\">"+_spTr.retry+"</a>");showToolBarAlert(ShortPixel.STATUS_FAIL,i.Message,d);if(j){ShortPixel.bulkShowError(d,i.Message,i.Filename,i.CustomImageLink);if(i.BulkPercent){progressUpdate(i.BulkPercent,i.BulkMsg)}ShortPixel.otherMediaUpdateActions(d,["retry","view"])}console.log(i.Message);setTimeout(checkBulkProgress,5000);break;case ShortPixel.STATUS_EMPTY_QUEUE:console.log(i.Message);clearBulkProcessor();hideToolBarAlert();var c=jQuery("#bulk-progress");if(j&&c.length&&i.BulkStatus!="2"){progressUpdate(100,"Bulk finished!");jQuery("a.bulk-cancel").attr("disabled","disabled");hideSlider();setTimeout(function(){window.location.reload()},3000)}break;case ShortPixel.STATUS_SUCCESS:if(j){ShortPixel.bulkHideLengthyMsg();ShortPixel.bulkHideMaintenanceMsg()}var l=i.PercentImprovement;showToolBarAlert(ShortPixel.STATUS_SUCCESS,"");var b=ShortPixel.isCustomImageId(d)?"":ShortPixel.successActions(d,i.Type,i.ThumbsCount,i.ThumbsTotal,i.BackupEnabled,i.Filename);setCellMessage(d,ShortPixel.successMsg(d,l,i.Type,i.ThumbsCount,i.RetinasCount),b);var h=jQuery(["restore","view","redolossy","redoglossy","redolossless"]).not(["redo"+i.Type]).get();ShortPixel.otherMediaUpdateActions(d,h);var f=new PercentageAnimator("#sp-msg-"+d+" span.percent",l);f.animate(l);if(j&&typeof i.Thumb!=="undefined"){if(i.BulkPercent){progressUpdate(i.BulkPercent,i.BulkMsg)}if(i.Thumb.length>0){sliderUpdate(d,i.Thumb,i.BkThumb,i.PercentImprovement,i.Filename);if(typeof i.AverageCompression!=="undefined"&&0+i.AverageCompression>0){jQuery("#sp-avg-optimization").html('<input type="text" class="dial" value="'+Math.round(i.AverageCompression)+'"/>');ShortPixel.percentDial("#sp-avg-optimization .dial",60)}}}console.log("Server response: "+g);if(j&&typeof i.BulkPercent!=="undefined"){progressUpdate(i.BulkPercent,i.BulkMsg)}setTimeout(checkBulkProgress,5000);break;case ShortPixel.STATUS_SKIP:if(i.Silent!==1){ShortPixel.bulkShowError(d,i.Message,i.Filename,i.CustomImageLink)}case ShortPixel.STATUS_ERROR:if(typeof i.Message!=="undefined"){showToolBarAlert(ShortPixel.STATUS_SKIP,i.Message+" Image ID: "+d);setCellMessage(d,i.Message,"")}ShortPixel.otherMediaUpdateActions(d,["retry","view"]);case ShortPixel.STATUS_RETRY:console.log("Server response: "+g);showToolBarAlert(ShortPixel.STATUS_RETRY,"");if(j&&typeof i.BulkPercent!=="undefined"){progressUpdate(i.BulkPercent,i.BulkMsg)}if(j&&i.Count>3){ShortPixel.bulkShowLengthyMsg(d,i.Filename,i.CustomImageLink)}setTimeout(checkBulkProgress,5000);break;case ShortPixel.STATUS_MAINTENANCE:ShortPixel.bulkShowMaintenanceMsg("maintenance");setTimeout(checkBulkProgress,60000);break;case ShortPixel.STATUS_QUEUE_FULL:ShortPixel.bulkShowMaintenanceMsg("queue-full");setTimeout(checkBulkProgress,60000);break;default:ShortPixel.retry("Unknown status "+i.Status+". Retrying...");break}}},error:function(b){ShortPixel.retry(b.statusText)}})}function clearBulkProcessor(){ShortPixel.bulkProcessor=false;localStorage.bulkTime=0;if(window.location.href.search("wp-short-pixel-bulk")>=0){localStorage.bulkPage=0}}function setCellMessage(d,a,c){var b=jQuery("#sp-msg-"+d);if(b.length>0){b.html("<div class='sp-column-actions'>"+c+"</div><div class='sp-column-info'>"+a+"</div>");b.css("color","")}b=jQuery("#sp-cust-msg-"+d);if(b.length>0){b.html("<div class='sp-column-info'>"+a+"</div>")}}function manualOptimization(c,a){setCellMessage(c,"<img src='"+ShortPixel.WP_PLUGIN_URL+"/res/img/loading.gif' 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 b={action:"shortpixel_manual_optimization",image_id:c,cleanup:a};jQuery.ajax({type:"GET",url:ShortPixel.AJAX_URL,data:b,success:function(d){var e=JSON.parse(d);if(e.Status==ShortPixel.STATUS_SUCCESS){setTimeout(checkBulkProgress,2000)}else{setCellMessage(c,typeof e.Message!=="undefined"?e.Message:_spTr.thisContentNotProcessable,"")}},error:function(d){b.action="shortpixel_check_status";jQuery.ajax({type:"GET",url:ShortPixel.AJAX_URL,data:b,success:function(e){var f=JSON.parse(e);if(f.Status!==ShortPixel.STATUS_SUCCESS){setCellMessage(c,typeof f.Message!=="undefined"?f.Message:_spTr.thisContentNotProcessable,"")}}})}})}function reoptimize(c,a){setCellMessage(c,"<img src='"+ShortPixel.WP_PLUGIN_URL+"/res/img/loading.gif' 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 b={action:"shortpixel_redo",attachment_ID:c,type:a};jQuery.get(ShortPixel.AJAX_URL,b,function(d){b=JSON.parse(d);if(b.Status==ShortPixel.STATUS_SUCCESS){setTimeout(checkBulkProgress,2000)}else{$msg=typeof b.Message!=="undefined"?b.Message:_spTr.thisContentNotProcessable;setCellMessage(c,$msg,"");showToolBarAlert(ShortPixel.STATUS_FAIL,$msg)}})}function optimizeThumbs(b){setCellMessage(b,"<img src='"+ShortPixel.WP_PLUGIN_URL+"/res/img/loading.gif' class='sp-loading-small'>"+_spTr.imageWaitOptThumbs,"");jQuery("li.shortpixel-toolbar-processing").removeClass("shortpixel-hide");jQuery("li.shortpixel-toolbar-processing").addClass("shortpixel-processing");var a={action:"shortpixel_optimize_thumbs",attachment_ID:b};jQuery.get(ShortPixel.AJAX_URL,a,function(c){a=JSON.parse(c);if(a.Status==ShortPixel.STATUS_SUCCESS){setTimeout(checkBulkProgress,2000)}else{setCellMessage(b,typeof a.Message!=="undefined"?a.Message:_spTr.thisContentNotProcessable,"")}})}function dismissShortPixelNoticeExceed(b){jQuery("#wp-admin-bar-shortpixel_processing").hide();var a={action:"shortpixel_dismiss_notice",notice_id:"exceed"};jQuery.get(ShortPixel.AJAX_URL,a,function(c){a=JSON.parse(c);if(a.Status==ShortPixel.STATUS_SUCCESS){console.log("dismissed")}});b.preventDefault()}function dismissShortPixelNotice(b){jQuery("#short-pixel-notice-"+b).hide();var a={action:"shortpixel_dismiss_notice",notice_id:b};jQuery.get(ShortPixel.AJAX_URL,a,function(c){a=JSON.parse(c);if(a.Status==ShortPixel.STATUS_SUCCESS){console.log("dismissed")}})}function PercentageAnimator(b,a){this.animationSpeed=10;this.increment=2;this.curPercentage=0;this.targetPercentage=a;this.outputSelector=b;this.animate=function(c){this.targetPercentage=c;setTimeout(PercentageTimer.bind(null,this),this.animationSpeed)}}function PercentageTimer(a){if(a.curPercentage-a.targetPercentage<-a.increment){a.curPercentage+=a.increment}else{if(a.curPercentage-a.targetPercentage>a.increment){a.curPercentage-=a.increment}else{a.curPercentage=a.targetPercentage}}jQuery(a.outputSelector).text(a.curPercentage+"%");if(a.curPercentage!=a.targetPercentage){setTimeout(PercentageTimer.bind(null,a),a.animationSpeed)}}function progressUpdate(c,b){var a=jQuery("#bulk-progress");if(a.length){jQuery(".progress-left",a).css("width",c+"%");jQuery(".progress-img",a).css("left",c+"%");if(c>24){jQuery(".progress-img span",a).html("");jQuery(".progress-left",a).html(c+"%")}else{jQuery(".progress-img span",a).html(c+"%");jQuery(".progress-left",a).html("")}jQuery(".bulk-estimate").html(b)}}function sliderUpdate(g,c,d,e,b){var f=jQuery(".bulk-slider div.bulk-slide:first-child");if(f.length===0){return}if(f.attr("id")!="empty-slide"){f.hide()}f.css("z-index",1000);jQuery(".bulk-img-opt",f).attr("src","");if(typeof d==="undefined"){d=""}if(d.length>0){jQuery(".bulk-img-orig",f).attr("src","")}var a=f.clone();a.attr("id","slide-"+g);jQuery(".bulk-img-opt",a).attr("src",c);if(d.length>0){jQuery(".img-original",a).css("display","inline-block");jQuery(".bulk-img-orig",a).attr("src",d)}else{jQuery(".img-original",a).css("display","none")}jQuery(".bulk-opt-percent",a).html('<input type="text" class="dial" value="'+e+'"/>');jQuery(".bulk-slider").append(a);ShortPixel.percentDial("#"+a.attr("id")+" .dial",100);jQuery(".bulk-slider-container span.filename").html("&nbsp;&nbsp;"+b);if(f.attr("id")=="empty-slide"){f.remove();jQuery(".bulk-slider-container").css("display","block")}else{f.animate({left:f.width()+f.position().left},"slow","swing",function(){f.remove();a.fadeIn("slow")})}}function hideSlider(){jQuery(".bulk-slider-container").css("display","none")}function showStats(){var a=jQuery(".bulk-stats");if(a.length>0){}}if(!(typeof String.prototype.format=="function")){String.prototype.format=function(){var b=this,a=arguments.length;while(a--){b=b.replace(new RegExp("\\{"+a+"\\}","gm"),arguments[a])}return b}};
shortpixel_api.php CHANGED
@@ -84,7 +84,9 @@ class ShortPixelAPI {
84
  if(!count($URLs)) {
85
  throw new Exception(__('Image files are missing.','shortpixel-image-optimiser'));
86
  }
87
-
 
 
88
  $requestParameters = array(
89
  'plugin_version' => SHORTPIXEL_IMAGE_OPTIMISER_VERSION,
90
  'key' => $this->_settings->apiKey,
@@ -606,7 +608,7 @@ class ShortPixelAPI {
606
  $meta->setStatus(2);
607
 
608
  $itemHandler->updateMeta($meta);
609
- $itemHandler->doActions();
610
 
611
  if(!$originalSpace) { //das kann nicht sein, alles klar?!
612
  throw new Exception("OriginalSpace = 0. APIResponse" . json_encode($APIresponse));
84
  if(!count($URLs)) {
85
  throw new Exception(__('Image files are missing.','shortpixel-image-optimiser'));
86
  }
87
+
88
+ //WpShortPixel::log("DO REQUESTS for META: " . json_encode($itemHandler->getRawMeta()) . " STACK: " . json_encode(debug_backtrace()));
89
+
90
  $requestParameters = array(
91
  'plugin_version' => SHORTPIXEL_IMAGE_OPTIMISER_VERSION,
92
  'key' => $this->_settings->apiKey,
608
  $meta->setStatus(2);
609
 
610
  $itemHandler->updateMeta($meta);
611
+ $itemHandler->optimizationSucceeded();
612
 
613
  if(!$originalSpace) { //das kann nicht sein, alles klar?!
614
  throw new Exception("OriginalSpace = 0. APIResponse" . json_encode($APIresponse));
wp-shortpixel.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: ShortPixel Image Optimizer
4
  * Plugin URI: https://shortpixel.com/
5
  * Description: ShortPixel optimizes images automatically, while guarding the quality of your images. Check your <a href="options-general.php?page=wp-shortpixel" target="_blank">Settings &gt; ShortPixel</a> page on how to start optimizing your image library and make your website load faster.
6
- * Version: 4.10.5
7
  * Author: ShortPixel
8
  * Author URI: https://shortpixel.com
9
  * Text Domain: shortpixel-image-optimiser
@@ -18,7 +18,7 @@ define('SHORTPIXEL_PLUGIN_FILE', __FILE__);
18
 
19
  //define('SHORTPIXEL_AFFILIATE_CODE', '');
20
 
21
- define('SHORTPIXEL_IMAGE_OPTIMISER_VERSION', "4.10.5");
22
  define('SHORTPIXEL_MAX_TIMEOUT', 10);
23
  define('SHORTPIXEL_VALIDATE_MAX_TIMEOUT', 15);
24
  define('SHORTPIXEL_BACKUP', 'ShortpixelBackups');
@@ -26,7 +26,7 @@ define('SHORTPIXEL_MAX_API_RETRIES', 50);
26
  define('SHORTPIXEL_MAX_ERR_RETRIES', 5);
27
  define('SHORTPIXEL_MAX_FAIL_RETRIES', 3);
28
  if(!defined('SHORTPIXEL_MAX_THUMBS')) { //can be defined in wp-config.php
29
- define('SHORTPIXEL_MAX_THUMBS', 100);
30
  }
31
 
32
  define('SHORTPIXEL_PRESEND_ITEMS', 3);
@@ -131,6 +131,11 @@ function shortPixelDeactivatePlugin () {
131
  WPShortPixel::shortPixelDeactivatePlugin();
132
  }
133
 
 
 
 
 
 
134
  //Picture generation, hooked on the_content filter
135
  function shortPixelConvertImgToPictureAddWebp($content) {
136
  if(function_exists('is_amp_endpoint') && is_amp_endpoint()) {
@@ -156,6 +161,18 @@ function shortPixelAddPictureJs() {
156
  . '</script>';
157
  }
158
 
 
 
 
 
 
 
 
 
 
 
 
 
159
  if ( get_option('wp-short-pixel-create-webp-markup')) {
160
  add_filter( 'the_content', 'shortPixelConvertImgToPictureAddWebp', 10000 ); // priority big, so it will be executed last
161
  add_filter( 'post_thumbnail_html', 'shortPixelConvertImgToPictureAddWebp');
@@ -163,7 +180,6 @@ if ( get_option('wp-short-pixel-create-webp-markup')) {
163
  // add_action( 'wp_enqueue_scripts', 'spAddPicturefillJs' );
164
  }
165
 
166
-
167
  if ( !function_exists( 'vc_action' ) || vc_action() !== 'vc_inline' ) { //handle incompatibility with Visual Composer
168
  add_action( 'init', 'shortpixelInit');
169
  add_action('ngg_added_new_image', 'shortPixelNggAdd');
@@ -180,5 +196,5 @@ if ( !function_exists( 'vc_action' ) || vc_action() !== 'vc_inline' ) { //handle
180
 
181
  register_activation_hook( __FILE__, 'shortPixelActivatePlugin' );
182
  register_deactivation_hook( __FILE__, 'shortPixelDeactivatePlugin' );
183
- }
184
  ?>
3
  * Plugin Name: ShortPixel Image Optimizer
4
  * Plugin URI: https://shortpixel.com/
5
  * Description: ShortPixel optimizes images automatically, while guarding the quality of your images. Check your <a href="options-general.php?page=wp-shortpixel" target="_blank">Settings &gt; ShortPixel</a> page on how to start optimizing your image library and make your website load faster.
6
+ * Version: 4.11.0
7
  * Author: ShortPixel
8
  * Author URI: https://shortpixel.com
9
  * Text Domain: shortpixel-image-optimiser
18
 
19
  //define('SHORTPIXEL_AFFILIATE_CODE', '');
20
 
21
+ define('SHORTPIXEL_IMAGE_OPTIMISER_VERSION', "4.11.0");
22
  define('SHORTPIXEL_MAX_TIMEOUT', 10);
23
  define('SHORTPIXEL_VALIDATE_MAX_TIMEOUT', 15);
24
  define('SHORTPIXEL_BACKUP', 'ShortpixelBackups');
26
  define('SHORTPIXEL_MAX_ERR_RETRIES', 5);
27
  define('SHORTPIXEL_MAX_FAIL_RETRIES', 3);
28
  if(!defined('SHORTPIXEL_MAX_THUMBS')) { //can be defined in wp-config.php
29
+ define('SHORTPIXEL_MAX_THUMBS', 149);
30
  }
31
 
32
  define('SHORTPIXEL_PRESEND_ITEMS', 3);
131
  WPShortPixel::shortPixelDeactivatePlugin();
132
  }
133
 
134
+ function shortPixelUninstallPlugin () {
135
+ require_once('wp-shortpixel-req.php');
136
+ WPShortPixel::shortPixelUninstallPlugin();
137
+ }
138
+
139
  //Picture generation, hooked on the_content filter
140
  function shortPixelConvertImgToPictureAddWebp($content) {
141
  if(function_exists('is_amp_endpoint') && is_amp_endpoint()) {
161
  . '</script>';
162
  }
163
 
164
+ add_filter( 'gform_save_field_value', 'shortPixelGravityForms', 10, 5 );
165
+
166
+ function shortPixelGravityForms( $value, $lead, $field, $form ) {
167
+ global $shortPixelPluginInstance;
168
+ if($field->type == 'post_image') {
169
+ require_once('wp-shortpixel-req.php');
170
+ $shortPixelPluginInstance = new WPShortPixel;
171
+ $shortPixelPluginInstance->handleGravityFormsImageField($value);
172
+ }
173
+ return $value;
174
+ }
175
+
176
  if ( get_option('wp-short-pixel-create-webp-markup')) {
177
  add_filter( 'the_content', 'shortPixelConvertImgToPictureAddWebp', 10000 ); // priority big, so it will be executed last
178
  add_filter( 'post_thumbnail_html', 'shortPixelConvertImgToPictureAddWebp');
180
  // add_action( 'wp_enqueue_scripts', 'spAddPicturefillJs' );
181
  }
182
 
 
183
  if ( !function_exists( 'vc_action' ) || vc_action() !== 'vc_inline' ) { //handle incompatibility with Visual Composer
184
  add_action( 'init', 'shortpixelInit');
185
  add_action('ngg_added_new_image', 'shortPixelNggAdd');
196
 
197
  register_activation_hook( __FILE__, 'shortPixelActivatePlugin' );
198
  register_deactivation_hook( __FILE__, 'shortPixelDeactivatePlugin' );
199
+ register_uninstall_hook(__FILE__, 'shortPixelUninstallPlugin');}
200
  ?>