Imagify Image Optimizer - Version 1.9.3

Version Description

  • 2019/06/17 =
  • Improvement: better compatibility with CDNs when displaying webp images with <picture> tags. There is now a new setting field to fill in the CDN URL in use.
  • Improvement: dont use Heartbeat anymore. This speeds up the optimization process and prevents other plugins to break everything when they remove Heartbeat.
  • Fix: a fatal error upon plugin deactivation.
  • Fix: an occasional fatal error preventing the optimization process to work.
  • Fix: conflict with plugins using an ancient version of Composer.
  • Fix: php notices displayed on the bulk optimization page on rare cases.
  • Fix: a php notice about "Non-string needles" with php 7.3.
  • Fix: a php notice displayed when restoring a custom file.
Download this release

Release Info

Developer wp_media
Plugin Icon 128x128 Imagify Image Optimizer
Version 1.9.3
Comparing to
See all releases

Code changes from version 1.9.2 to 1.9.3

Files changed (46) hide show
  1. assets/css/options.css +42 -12
  2. assets/css/options.min.css +1 -1
  3. assets/js/beat.js +872 -0
  4. assets/js/beat.min.js +1 -0
  5. assets/js/bulk.js +54 -42
  6. assets/js/bulk.min.js +1 -1
  7. assets/js/files-list.js +28 -33
  8. assets/js/files-list.min.js +1 -1
  9. assets/js/media-modal.js +26 -33
  10. assets/js/media-modal.min.js +1 -1
  11. assets/js/options.js +62 -37
  12. assets/js/options.min.js +1 -1
  13. classes/Imagifybeat/Actions.php +438 -0
  14. classes/Imagifybeat/Core.php +172 -0
  15. classes/Optimization/Process/AbstractProcess.php +5 -5
  16. classes/Webp/Picture/Display.php +194 -44
  17. classes/Webp/RewriteRules/Display.php +4 -3
  18. composer.json +4 -1
  19. composer.lock +30 -1
  20. imagify.php +2 -2
  21. inc/3rd-party/3rd-party.php +1 -1
  22. inc/3rd-party/nextgen-gallery/inc/admin/heartbeat.php +0 -13
  23. inc/3rd-party/nextgen-gallery/nextgen-gallery.php +0 -1
  24. inc/3rd-party/wp-rocket.php +0 -28
  25. inc/3rd-party/wp-rocket/classes/Main.php +99 -0
  26. inc/3rd-party/wp-rocket/wp-rocket.php +8 -0
  27. inc/admin/heartbeat.php +0 -358
  28. inc/classes/class-imagify-admin-ajax-post.php +1 -0
  29. inc/classes/class-imagify-assets.php +6 -63
  30. inc/classes/class-imagify-files-scan.php +1 -1
  31. inc/classes/class-imagify-options.php +14 -0
  32. inc/classes/class-imagify-plugin.php +2 -1
  33. inc/classes/class-imagify-settings.php +124 -16
  34. inc/deprecated/3rd-party.php +29 -0
  35. inc/deprecated/classes/class-imagify-assets-deprecated.php +61 -0
  36. inc/deprecated/deprecated.php +379 -0
  37. inc/functions/admin-stats.php +6 -5
  38. inc/functions/i18n.php +18 -13
  39. package.json +1 -1
  40. readme.txt +31 -6
  41. vendor/autoload.php +1 -1
  42. vendor/composer/autoload_classmap.php +3 -0
  43. vendor/composer/autoload_psr4.php +1 -0
  44. vendor/composer/autoload_real.php +4 -4
  45. vendor/composer/autoload_static.php +12 -4
  46. views/part-settings-webp.php +74 -32
assets/css/options.css CHANGED
@@ -181,12 +181,6 @@ p.imagify-api-key-invite-title {
181
  padding-top: 35px;
182
  }
183
 
184
- .imagify-settings input[type="text"] {
185
- color: #4A4A4A;
186
- font-weight: 600;
187
- box-shadow: none;
188
- }
189
-
190
  .imagify-settings div.submit.submit {
191
  border-top: 1px solid #D9D9D9;
192
  margin-top: 2em;
@@ -242,12 +236,14 @@ label + .imagify-info,
242
  margin-left: 38px;
243
  padding-right: 25px;
244
  }
 
 
 
 
245
  label ~ .imagify-options-line {
246
  display: block;
247
  margin: 8px 0 20px 40px;
248
  font-size: 14px;
249
- -webkit-transition: opacity .3s;
250
- transition: opacity .3s;
251
  }
252
  .imagify-options-line + .imagify-info {
253
  margin-left: 38px;
@@ -266,21 +262,30 @@ label[for="imagify_sizes_full"] + .imagify-info {
266
  }
267
 
268
  .imagify-settings.imagify-settings [type="checkbox"]:not(:checked) + label ~ .imagify-options-line,
269
- .imagify-settings.imagify-settings [type="checkbox"]:not(:checked) + label .imagify-visual-label {
 
270
  opacity: .5;
271
  }
272
  .imagify-settings.imagify-settings [type="checkbox"]:checked + label ~ .imagify-options-line,
273
- .imagify-settings.imagify-settings [type="checkbox"]:checked + label .imagify-visual-label {
 
274
  opacity: 1;
275
  }
276
 
 
 
 
 
 
 
277
  .imagify-checkbox-marged {
278
  max-width: 500px;
279
  margin-left: 45px;
280
  }
281
 
282
- #imagify_resize_larger_w {
283
- width: 5em;
 
284
  height: auto;
285
  padding: 6px;
286
  margin: 0 6px;
@@ -290,6 +295,31 @@ label[for="imagify_sizes_full"] + .imagify-info {
290
  color: #338EA6;
291
  font-weight: bold;
292
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
293
 
294
  .imagify-menu-bar-img {
295
  box-sizing: border-box;
181
  padding-top: 35px;
182
  }
183
 
 
 
 
 
 
 
184
  .imagify-settings div.submit.submit {
185
  border-top: 1px solid #D9D9D9;
186
  margin-top: 2em;
236
  margin-left: 38px;
237
  padding-right: 25px;
238
  }
239
+ .imagify-options-line {
240
+ -webkit-transition: opacity .3s;
241
+ transition: opacity .3s;
242
+ }
243
  label ~ .imagify-options-line {
244
  display: block;
245
  margin: 8px 0 20px 40px;
246
  font-size: 14px;
 
 
247
  }
248
  .imagify-options-line + .imagify-info {
249
  margin-left: 38px;
262
  }
263
 
264
  .imagify-settings.imagify-settings [type="checkbox"]:not(:checked) + label ~ .imagify-options-line,
265
+ .imagify-settings.imagify-settings [type="checkbox"]:not(:checked) + label .imagify-visual-label,
266
+ :checked + label ~ .imagify-options-line :checked + label ~ .imagify-options-line .imagify-faded {
267
  opacity: .5;
268
  }
269
  .imagify-settings.imagify-settings [type="checkbox"]:checked + label ~ .imagify-options-line,
270
+ .imagify-settings.imagify-settings [type="checkbox"]:checked + label .imagify-visual-label,
271
+ .imagify-settings.imagify-settings :not(:checked) + label ~ .imagify-options-line :not(:checked) + label ~ .imagify-options-line {
272
  opacity: 1;
273
  }
274
 
275
+ .imagify-radio-group + .imagify-options-line {
276
+ display: block;
277
+ margin: 0 0 0 1.7em;
278
+ font-size: 14px;
279
+ }
280
+
281
  .imagify-checkbox-marged {
282
  max-width: 500px;
283
  margin-left: 45px;
284
  }
285
 
286
+ .imagify-settings [type="text"],
287
+ .imagify-settings [type="number"] {
288
+ width: 20em;
289
  height: auto;
290
  padding: 6px;
291
  margin: 0 6px;
295
  color: #338EA6;
296
  font-weight: bold;
297
  }
298
+ .imagify-settings [type="number"] {
299
+ width: 5em;
300
+ }
301
+ .imagify-settings ::-webkit-input-placeholder {
302
+ color: #B1B1B1;
303
+ font-weight: 400;
304
+ }
305
+ .imagify-settings ::-moz-placeholder {
306
+ color: #B1B1B1;
307
+ font-weight: 400;
308
+ opacity: 1;
309
+ }
310
+ .imagify-settings :-ms-input-placeholder {
311
+ color: #B1B1B1;
312
+ font-weight: 400;
313
+ }
314
+ .imagify-settings :-moz-placeholder {
315
+ color: #B1B1B1;
316
+ font-weight: 400;
317
+ opacity: 1;
318
+ }
319
+ .imagify-settings ::placeholder {
320
+ color: #B1B1B1;
321
+ font-weight: 400;
322
+ }
323
 
324
  .imagify-menu-bar-img {
325
  box-sizing: border-box;
assets/css/options.min.css CHANGED
@@ -1 +1 @@
1
- .wrap.imagify-settings{margin-right:0}.imagify-settings.imagify-have-rocket{margin-right:20px}#imagify-check-api-container{display:block;margin-top:6px;font-weight:700}#imagify-check-api-container .dashicons{font-size:25px}#imagify-check-api-container .dashicons-no:before{color:#f06e57;vertical-align:-1px}#imagify-check-api-container .imagify-icon{font-size:1.8em;margin-right:3px;margin-left:1px;color:#8BC34A;vertical-align:-2px}.imagify-account-info-col .imagify-api-line{padding:22px 26px;background:#343A49}.imagify-api-line label,p.imagify-api-key-invite-title{display:block;margin-bottom:6px;font-size:14px;text-transform:uppercase;letter-spacing:.02em;font-weight:700;color:#343A49}.imagify-account-info-col .imagify-api-line label{color:#E5EBEF;display:inline-block}.imagify-api-line.imagify-api-line input[type=text]{width:100%;padding:6px 10px;border:1px solid #40B1D0;font-family:"PT Mono",Consolas,monospace;font-size:14px;letter-spacing:.01em;font-weight:700;color:#40B1D0;background:0 0;-webkit-box-shadow:none;box-shadow:none}.imagify-no-api-key .imagify-api-line{margin:3em 0 0;padding:2em 0 0;border-top:1px solid #D5D6D9}.imagify-no-api-key .imagify-api-line input[type=text]{margin-top:5px;width:400px;max-width:100%}.imagify-settings .imagify-no-api-key div.submit.submit{border:0;padding:0 16px;margin-top:0;background:#FFF}.imagify-settings .imagify-no-api-key div.submit.submit p{padding-bottom:0}.imagify-options-title{margin:.75em 0 0;font-size:24px;letter-spacing:.02em;font-weight:700;color:#343A49}.imagify-options-subtitle{padding-bottom:.3em;margin-bottom:20px;border-bottom:1px solid #D2D3D6;font-size:14px;letter-spacing:.01em;font-weight:700;text-transform:uppercase;color:#626E7B}.imagify-options-subtitle a{font-size:12px;color:#338EA6;text-transform:none;letter-spacing:0}.imagify-options-subtitle .imagify-info{margin-left:15px}.imagify-setting-line{border-top:1px solid #D2D3D6;padding:25px 0 13px;margin:1em 0}.imagify-options-subtitle+.imagify-setting-line{border-top:0;padding-top:8px}.imagify-setting-optim-level{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:8px 0 18px}.imagify-setting-optim-level>p{margin:0}.imagify-setting-optim-level .imagify-inline-options{-ms-flex-preferred-size:60%;flex-basis:60%;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;width:auto;display:-webkit-box;display:-ms-flexbox;display:flex;background:#2E3243;border-radius:3px}.imagify-setting-optim-level .imagify-inline-options label{display:block!important;width:100%;font-size:14px!important;border-radius:3px!important}.imagify-setting-optim-level .imagify-visual-comparison-text{-ms-flex-preferred-size:40%;flex-basis:40%;-ms-flex-negative:1;flex-shrink:1;padding-left:20px;color:#626E7B;-webkit-box-sizing:border-box;box-sizing:border-box}.imagify-setting-optim-level.imagify-setting-optim-level .imagify-visual-comparison-btn{padding-top:5px;margin-top:2px;border-radius:2px;text-transform:none;letter-spacing:0;text-shadow:none!important}@media (max-width:782px){.imagify-settings .form-table th{padding-top:2em;padding-bottom:.5em}}.imagify-settings .form-table td{vertical-align:top}.imagify-settings .form-table th span{cursor:pointer}.imagify-middle th{padding-top:35px}.imagify-settings input[type=text]{color:#4A4A4A;font-weight:600;-webkit-box-shadow:none;box-shadow:none}.imagify-settings div.submit.submit{border-top:1px solid #D9D9D9;margin-top:2em;padding:18px 0 7px 30px}.imagify-settings .hidden+div.submit.submit{margin-top:-1px}.imagify-settings p.submit{float:left;margin-top:0}.imagify-settings p.submit .button{margin:0 5px}.imagify-sub-header th{text-align:right}.imagify-sub-header .form-table{margin:0}.imagify-sub-header td,.imagify-sub-header th{padding-top:0;padding-bottom:0}.imagify-sub-header [for=api_key]{padding-top:5px}@media (max-width:1120px){.imagify-settings .imagify-logo-block{margin-right:0}.imagify-settings .imagify-rate-us.imagify-rate-us{margin:1em 0 -1em}}.imagify-settings .imagify-rate-us{margin-right:25px;margin-left:auto}.imagify-visual-label,label+.imagify-info{display:inline-block;width:550px;max-width:calc(100% - 38px);margin-left:38px;padding-right:25px}label~.imagify-options-line{display:block;margin:8px 0 20px 40px;font-size:14px;-webkit-transition:opacity .3s;-o-transition:opacity .3s;transition:opacity .3s}.imagify-options-line+.imagify-info{margin-left:38px}label+.imagify-info{margin-top:10px}.imagify-options-line+.imagify-info+.imagify-options-line{margin-top:20px}.imagify-visual-label{vertical-align:-5px}label[for=imagify_sizes_full]+.imagify-info{vertical-align:middle}.imagify-settings.imagify-settings [type=checkbox]:not(:checked)+label .imagify-visual-label,.imagify-settings.imagify-settings [type=checkbox]:not(:checked)+label~.imagify-options-line{opacity:.5}.imagify-settings.imagify-settings [type=checkbox]:checked+label .imagify-visual-label,.imagify-settings.imagify-settings [type=checkbox]:checked+label~.imagify-options-line{opacity:1}.imagify-checkbox-marged{max-width:500px;margin-left:45px}#imagify_resize_larger_w{width:5em;height:auto;padding:6px;margin:0 6px;border:1px solid #8BA6B4;-webkit-box-shadow:none;box-shadow:none;border-radius:2px;color:#338EA6;font-weight:700}.imagify-menu-bar-img{-webkit-box-sizing:border-box;box-sizing:border-box;max-width:100%;height:auto;margin-top:0;border:1px solid #8BA6B4}.imagify-col.imagify-main{float:left;width:calc(100% - 320px);padding-left:0;padding-right:0}.imagify-have-rocket .imagify-main{float:none;width:1265px;max-width:100%}.imagify-sidebar{float:left;width:300px;max-width:100%}.imagify-sidebar-section{border:1px solid #BBB;background:#1F2332;position:relative;padding:10px 20px;text-align:center;color:#F2F2F2}.imagify-sidebar-section+.imagify-sidebar-section{margin-top:2em}@media (max-width:820px){.imagify-main,.imagify-sidebar{float:none;width:auto}.imagify-settings{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.imagify-sidebar{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2;max-width:none;margin-left:0;margin-top:25px}.wp-media-products{text-align:center}.wp-media-products li{display:inline-block;width:100%;max-width:276px}}@media (min-width:1400px){.imagify-main{width:74%}}.imagify-sidebar-close{position:absolute;top:8px;right:12px;text-decoration:none}.imagify-sidebar-close i{font-size:2em;color:rgba(255,255,255,.5)}p.imagify-sidebar-title{margin:1.2em 0 1.5em;text-align:left;color:#F56640;text-transform:uppercase;letter-spacing:.015em;word-spacing:.015em;font-weight:700}p.imagify-sidebar-description{margin:1.5em 0;text-align:left;font-weight:500;color:#F2F2F2}.imagify-sidebar-description strong{color:#39CE9A}.imagify-rocket-cta-promo{display:block;padding:8px 10px;margin:1.3em 0 .5em;border:2px dashed #F56640;border-radius:3px;font-size:18px;font-weight:700;color:#F56640}.imagify-rocket-cta-promo strong,a.btn-rocket{color:#F2F2F2}a.btn-rocket{display:block;font-size:15px;padding:10px 12px;margin:0 0 1.5em;background:#F56640;border-radius:3px;text-transform:uppercase;font-weight:700;text-decoration:none}a.btn-rocket:focus,a.btn-rocket:hover{background:#AC2B15}.imagify-sidebar-section ul{margin-top:20px}.imagify-sidebar-section li{position:relative;margin:1.2em 0;padding-left:25px;text-align:left}.imagify-sidebar-section li:before{content:"✓";position:absolute;left:0;top:0;color:#39CE9A;font-size:18px}label[for=imagify_admin_bar_menu],label[for=imagify_partner_links]{font-weight:400!important;color:#626E7B!important}.imagify-select-all-buttons{margin-top:8px}.imagify-link-like.imagify-select-all{font-weight:700;font-size:12px;color:#3694AE}.imagify-select-all.imagify-is-inactive{color:inherit;text-decoration:none;cursor:default}.imagify-fts-header{padding:10px 16px;background:#343A49;color:#FFF}.imagify-fts-header i{font-size:1.8em;margin-right:12px}.imagify-fts-header p{margin:0;color:#FFF}#imagify-add-themes-to-custom-folder strong,.imagify-fts-header strong{color:#40B1D0;font-weight:700}.imagify-fts-content{padding:16px;background:#F4F7F9;border:1px solid #CDD0D4;border-top:0}.imagify-fts-content p{margin-top:0}.imagify-kindof-title{margin-top:2em;padding:0 0 10px;border-bottom:1px solid #D2D3D6;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;font-weight:700}.imagify-settings .imagify-button-mini{padding:4px 13px 4px 10px}.imagify-settings .imagify-button-mini .dashicons-plus{vertical-align:-7.5px}.imagify-settings .imagify-button-mini.imagify-button-primary:focus,.imagify-settings .imagify-button-mini.imagify-button-primary:hover{color:#FFF}p.imagify-custom-folder-line{position:relative;margin:0;padding:12px 15px;color:#4A5362;font-weight:500;-webkit-transition:all .75s;-o-transition:all .75s;transition:all .75s}.imagify-custom-folder-line.imagify-will-remove{background:#C51162;color:#FFF;-webkit-transform:translateX(-120px);-ms-transform:translateX(-120px);transform:translateX(-120px);opacity:0}.imagify-custom-folder-line:first-child{margin-top:-.5em}.imagify-custom-folder-line+.imagify-custom-folder-line{border-top:1px solid #E9EFF2}.imagify-custom-folders-remove{position:absolute;right:0;top:6px;border:0;padding:5px 10px 4px;-webkit-box-shadow:none;box-shadow:none;color:#7A8996;border-radius:16px;font-size:13px;line-height:18px;background:#FFF;-webkit-transition:all .275s;-o-transition:all .275s;transition:all .275s;cursor:pointer}.imagify-custom-folders-remove-text{max-width:0;overflow:hidden;white-space:nowrap;display:inline-block;-webkit-transform:scale(0);-ms-transform:scale(0);transform:scale(0);opacity:0;-webkit-transition:all .275s;-o-transition:all .275s;transition:all .275s}.imagify-custom-folders-remove:focus,.imagify-custom-folders-remove:hover{background:#D9EFF6;color:#225E6E}.imagify-custom-folders-remove:focus .imagify-custom-folders-remove-text,.imagify-custom-folders-remove:hover .imagify-custom-folders-remove-text{max-width:6em;-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1);opacity:1}.imagify-settings .progress{height:8px;margin-top:1em;background:#343A49}.imagify-settings .bar{position:relative;width:1px;height:8px;background:#46B1CE;-webkit-transition:width .5s;-o-transition:width .5s;transition:width .5s}.imagify-settings .percent{position:absolute;top:6px;right:0;padding:0 5px;line-height:1.85;font-size:14px;font-weight:700;color:#40B1D0}.dashicons.rotate{-webkit-animation:icon-rotate 2.6s infinite linear;animation:icon-rotate 2.6s infinite linear}@-webkit-keyframes icon-rotate{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes icon-rotate{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.imagify-add-custom-folder+.imagify-loader{display:none;vertical-align:middle}.imagify-add-custom-folder[disabled]+.imagify-loader{display:inline-block}.imagify-folders-information{position:relative;margin:-5px 0 20px;padding:10px 10px 10px 40px;text-align:left;background:#F2F2F2}.imagify-folders-information i{position:absolute;left:10px;top:50%;margin-top:-10px}.imagify-folders-tree{margin:0;text-align:left}.imagify-folders-tree li{clear:left}.imagify-folders-tree .imagify-folder{-webkit-box-sizing:border-box;box-sizing:border-box;position:relative;width:48px;z-index:2;float:left;margin-top:-3px;padding:0 8px 0 0;border:0;background:0 0!important;-webkit-box-shadow:none;box-shadow:none;cursor:pointer;-webkit-transition:all .275s;-o-transition:all .275s;transition:all .275s}.imagify-folders-tree span.imagify-folder{padding-left:1.5px}.imagify-folders-tree .imagify-folder:before{content:"+";display:inline-block;width:13px;height:21px;font-size:1.5em;vertical-align:.15em}.imagify-folders-tree span.imagify-folder:before{content:''}.imagify-folders-tree .imagify-folder-icon path{-webkit-transition:all .275s;-o-transition:all .275s;transition:all .275s}.imagify-folders-tree .imagify-is-open .imagify-folder-icon path{stroke:#7A8996}.imagify-folders-tree .imagify-is-open.imagify-folder:before{content:"-";color:#7A8996}.imagify-folders-tree .imagify-is-open~label{color:#7A8996}.imagify-folders-tree .imagify-folder .imagify-loader,.imagify-folders-tree .imagify-folder.imagify-loading:before{display:none}.imagify-folders-tree .imagify-folder.imagify-loading .imagify-loader{display:inline-block;width:13px;height:21px;font-size:1.5em;vertical-align:.15em}.imagify-folders-tree .imagify-folder.imagify-loading .imagify-loader img{display:inline-block;width:100%;height:auto;vertical-align:middle}.imagify-folders-tree button.imagify-folder:focus,.imagify-folders-tree button.imagify-folder:focus path,.imagify-folders-tree button.imagify-folder:hover,.imagify-folders-tree button.imagify-folder:hover path{color:#3694AE;stroke:#3694AE}.imagify-folders-tree .imagify-folder.disabled,.imagify-folders-tree .imagify-folder:disabled{color:#7f7f7f}.imagify-swal-content .imagify-folders-tree label{position:relative;display:block;width:100%;padding:3px 0;font-size:15px;font-weight:500;vertical-align:top;-webkit-transition:all .475s;-o-transition:all .475s;transition:all .475s}.imagify-folders-tree input:focus+label,.imagify-swal-content .imagify-folders-tree label:hover{background:#F4F7F9}.imagify-folders-tree .imagify-folder-already-selected input:focus+label,.imagify-folders-tree .imagify-folder-already-selected label,.imagify-folders-tree .imagify-folder-already-selected label:hover{background:#40B1D0;color:#FFF;border-radius:3px;cursor:default}.imagify-folders-tree .imagify-folder-already-selected button,.imagify-folders-tree .imagify-folder-already-selected button path{color:#FFF;stroke:#FFF;cursor:default}.imagify-folders-tree .imagify-folder-already-selected button:focus path,.imagify-folders-tree .imagify-folder-already-selected button:hover path{stroke:#FFF}.imagify-folders-tree .imagify-folder-already-selected button:before{content:''}.imagify-add-ed-folder{position:absolute;top:0;bottom:0;right:0;font-size:11px;text-transform:uppercase;letter-spacing:.02em;word-spacing:.02em;color:#3694AE;background:#F4F7F9;opacity:0;-webkit-transform:translateX(15px);-ms-transform:translateX(15px);transform:translateX(15px);-webkit-transition:all .275s;-o-transition:all .275s;transition:all .275s}.imagify-folder-already-selected .imagify-add-ed-folder,input:checked+label .imagify-add-ed-folder,input:focus+label .imagify-add-ed-folder,label:hover .imagify-add-ed-folder{opacity:1;-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}input:checked+label .imagify-add-ed-folder{background:#FFF}input:checked+label:hover .imagify-add-ed-folder,input:checked:focus+label .imagify-add-ed-folder{background:#F4F7F9}.imagify-folder-already-selected .imagify-add-ed-folder{background:#40B1D0;color:#FFF}.imagify-fake-checkbox{position:relative;display:inline-block;width:14px;height:14px;margin:3.5px 15px 0 5px;border:1.5px solid #3694AE;border-radius:3px;vertical-align:-4px}.imagify-fake-checkbox:after{position:absolute;left:1px;top:0;content:"✓";color:#3694AE;font-size:14px;line-height:.9;font-style:normal;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;opacity:0;-webkit-transform:scale(0);-ms-transform:scale(0);transform:scale(0);-webkit-transition:all .475s;-o-transition:all .475s;transition:all .475s}.imagify-folder-already-selected .imagify-fake-checkbox:after,input:checked+label .imagify-fake-checkbox:after{opacity:1;-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}.imagify-folder-already-selected .imagify-fake-checkbox{border-color:#40B1D0}.imagify-folder-already-selected .imagify-fake-checkbox:after{color:#FFF}.imagify-folders-sub-tree{position:relative;margin-left:.75em;padding-top:.6em;padding-left:1em;border-left:1px dotted rgba(98,110,123,.3)}.imagify-folders-sub-tree li{position:relative;margin-bottom:4px}.imagify-folders-sub-tree li:before{content:"";position:absolute;top:12px;left:-1em;height:1px;width:.9em;border-top:1px dotted rgba(98,110,123,.3)}.imagify-folders-sub-tree li:last-child:after{content:"";position:absolute;left:-1.1em;bottom:0;height:11px;width:3px;background:#FFF}.imagify-empty-folder{margin-top:-.5em}.imagify-empty-folder em{font-size:12px;font-weight:500;color:#A2AFBC}
1
+ .wrap.imagify-settings{margin-right:0}.imagify-settings.imagify-have-rocket{margin-right:20px}#imagify-check-api-container{display:block;margin-top:6px;font-weight:700}#imagify-check-api-container .dashicons{font-size:25px}#imagify-check-api-container .dashicons-no:before{color:#f06e57;vertical-align:-1px}#imagify-check-api-container .imagify-icon{font-size:1.8em;margin-right:3px;margin-left:1px;color:#8BC34A;vertical-align:-2px}.imagify-account-info-col .imagify-api-line{padding:22px 26px;background:#343A49}.imagify-api-line label,p.imagify-api-key-invite-title{display:block;margin-bottom:6px;font-size:14px;text-transform:uppercase;letter-spacing:.02em;font-weight:700;color:#343A49}.imagify-account-info-col .imagify-api-line label{color:#E5EBEF;display:inline-block}.imagify-api-line.imagify-api-line input[type=text]{width:100%;padding:6px 10px;border:1px solid #40B1D0;font-family:"PT Mono",Consolas,monospace;font-size:14px;letter-spacing:.01em;font-weight:700;color:#40B1D0;background:0 0;-webkit-box-shadow:none;box-shadow:none}.imagify-no-api-key .imagify-api-line{margin:3em 0 0;padding:2em 0 0;border-top:1px solid #D5D6D9}.imagify-no-api-key .imagify-api-line input[type=text]{margin-top:5px;width:400px;max-width:100%}.imagify-settings .imagify-no-api-key div.submit.submit{border:0;padding:0 16px;margin-top:0;background:#FFF}.imagify-settings .imagify-no-api-key div.submit.submit p{padding-bottom:0}.imagify-options-title{margin:.75em 0 0;font-size:24px;letter-spacing:.02em;font-weight:700;color:#343A49}.imagify-options-subtitle{padding-bottom:.3em;margin-bottom:20px;border-bottom:1px solid #D2D3D6;font-size:14px;letter-spacing:.01em;font-weight:700;text-transform:uppercase;color:#626E7B}.imagify-options-subtitle a{font-size:12px;color:#338EA6;text-transform:none;letter-spacing:0}.imagify-options-subtitle .imagify-info{margin-left:15px}.imagify-setting-line{border-top:1px solid #D2D3D6;padding:25px 0 13px;margin:1em 0}.imagify-options-subtitle+.imagify-setting-line{border-top:0;padding-top:8px}.imagify-setting-optim-level{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:8px 0 18px}.imagify-setting-optim-level>p{margin:0}.imagify-setting-optim-level .imagify-inline-options{-ms-flex-preferred-size:60%;flex-basis:60%;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;width:auto;display:-webkit-box;display:-ms-flexbox;display:flex;background:#2E3243;border-radius:3px}.imagify-setting-optim-level .imagify-inline-options label{display:block!important;width:100%;font-size:14px!important;border-radius:3px!important}.imagify-setting-optim-level .imagify-visual-comparison-text{-ms-flex-preferred-size:40%;flex-basis:40%;-ms-flex-negative:1;flex-shrink:1;padding-left:20px;color:#626E7B;-webkit-box-sizing:border-box;box-sizing:border-box}.imagify-setting-optim-level.imagify-setting-optim-level .imagify-visual-comparison-btn{padding-top:5px;margin-top:2px;border-radius:2px;text-transform:none;letter-spacing:0;text-shadow:none!important}@media (max-width:782px){.imagify-settings .form-table th{padding-top:2em;padding-bottom:.5em}}.imagify-settings .form-table td{vertical-align:top}.imagify-settings .form-table th span{cursor:pointer}.imagify-middle th{padding-top:35px}.imagify-settings div.submit.submit{border-top:1px solid #D9D9D9;margin-top:2em;padding:18px 0 7px 30px}.imagify-settings .hidden+div.submit.submit{margin-top:-1px}.imagify-settings p.submit{float:left;margin-top:0}.imagify-settings p.submit .button{margin:0 5px}.imagify-sub-header th{text-align:right}.imagify-sub-header .form-table{margin:0}.imagify-sub-header td,.imagify-sub-header th{padding-top:0;padding-bottom:0}.imagify-sub-header [for=api_key]{padding-top:5px}@media (max-width:1120px){.imagify-settings .imagify-logo-block{margin-right:0}.imagify-settings .imagify-rate-us.imagify-rate-us{margin:1em 0 -1em}}.imagify-settings .imagify-rate-us{margin-right:25px;margin-left:auto}.imagify-visual-label,label+.imagify-info{display:inline-block;width:550px;max-width:calc(100% - 38px);margin-left:38px;padding-right:25px}.imagify-options-line{-webkit-transition:opacity .3s;-o-transition:opacity .3s;transition:opacity .3s}label~.imagify-options-line{display:block;margin:8px 0 20px 40px;font-size:14px}.imagify-options-line+.imagify-info{margin-left:38px}label+.imagify-info{margin-top:10px}.imagify-options-line+.imagify-info+.imagify-options-line{margin-top:20px}.imagify-visual-label{vertical-align:-5px}label[for=imagify_sizes_full]+.imagify-info{vertical-align:middle}.imagify-settings.imagify-settings [type=checkbox]:not(:checked)+label .imagify-visual-label,.imagify-settings.imagify-settings [type=checkbox]:not(:checked)+label~.imagify-options-line,:checked+label~.imagify-options-line :checked+label~.imagify-options-line .imagify-faded{opacity:.5}.imagify-settings.imagify-settings :not(:checked)+label~.imagify-options-line :not(:checked)+label~.imagify-options-line,.imagify-settings.imagify-settings [type=checkbox]:checked+label .imagify-visual-label,.imagify-settings.imagify-settings [type=checkbox]:checked+label~.imagify-options-line{opacity:1}.imagify-radio-group+.imagify-options-line{display:block;margin:0 0 0 1.7em;font-size:14px}.imagify-checkbox-marged{max-width:500px;margin-left:45px}.imagify-settings [type=text],.imagify-settings [type=number]{width:20em;height:auto;padding:6px;margin:0 6px;border:1px solid #8BA6B4;-webkit-box-shadow:none;box-shadow:none;border-radius:2px;color:#338EA6;font-weight:700}.imagify-settings [type=number]{width:5em}.imagify-settings ::-webkit-input-placeholder{color:#B1B1B1;font-weight:400}.imagify-settings :-ms-input-placeholder{color:#B1B1B1;font-weight:400}.imagify-settings ::placeholder{color:#B1B1B1;font-weight:400}.imagify-menu-bar-img{-webkit-box-sizing:border-box;box-sizing:border-box;max-width:100%;height:auto;margin-top:0;border:1px solid #8BA6B4}.imagify-col.imagify-main{float:left;width:calc(100% - 320px);padding-left:0;padding-right:0}.imagify-have-rocket .imagify-main{float:none;width:1265px;max-width:100%}.imagify-sidebar{float:left;width:300px;max-width:100%}.imagify-sidebar-section{border:1px solid #BBB;background:#1F2332;position:relative;padding:10px 20px;text-align:center;color:#F2F2F2}.imagify-sidebar-section+.imagify-sidebar-section{margin-top:2em}@media (max-width:820px){.imagify-main,.imagify-sidebar{float:none;width:auto}.imagify-settings{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.imagify-sidebar{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2;max-width:none;margin-left:0;margin-top:25px}.wp-media-products{text-align:center}.wp-media-products li{display:inline-block;width:100%;max-width:276px}}@media (min-width:1400px){.imagify-main{width:74%}}.imagify-sidebar-close{position:absolute;top:8px;right:12px;text-decoration:none}.imagify-sidebar-close i{font-size:2em;color:rgba(255,255,255,.5)}p.imagify-sidebar-title{margin:1.2em 0 1.5em;text-align:left;color:#F56640;text-transform:uppercase;letter-spacing:.015em;word-spacing:.015em;font-weight:700}p.imagify-sidebar-description{margin:1.5em 0;text-align:left;font-weight:500;color:#F2F2F2}.imagify-sidebar-description strong{color:#39CE9A}.imagify-rocket-cta-promo{display:block;padding:8px 10px;margin:1.3em 0 .5em;border:2px dashed #F56640;border-radius:3px;font-size:18px;font-weight:700;color:#F56640}.imagify-rocket-cta-promo strong,a.btn-rocket{color:#F2F2F2}a.btn-rocket{display:block;font-size:15px;padding:10px 12px;margin:0 0 1.5em;background:#F56640;border-radius:3px;text-transform:uppercase;font-weight:700;text-decoration:none}a.btn-rocket:focus,a.btn-rocket:hover{background:#AC2B15}.imagify-sidebar-section ul{margin-top:20px}.imagify-sidebar-section li{position:relative;margin:1.2em 0;padding-left:25px;text-align:left}.imagify-sidebar-section li:before{content:"✓";position:absolute;left:0;top:0;color:#39CE9A;font-size:18px}label[for=imagify_admin_bar_menu],label[for=imagify_partner_links]{font-weight:400!important;color:#626E7B!important}.imagify-select-all-buttons{margin-top:8px}.imagify-link-like.imagify-select-all{font-weight:700;font-size:12px;color:#3694AE}.imagify-select-all.imagify-is-inactive{color:inherit;text-decoration:none;cursor:default}.imagify-fts-header{padding:10px 16px;background:#343A49;color:#FFF}.imagify-fts-header i{font-size:1.8em;margin-right:12px}.imagify-fts-header p{margin:0;color:#FFF}#imagify-add-themes-to-custom-folder strong,.imagify-fts-header strong{color:#40B1D0;font-weight:700}.imagify-fts-content{padding:16px;background:#F4F7F9;border:1px solid #CDD0D4;border-top:0}.imagify-fts-content p{margin-top:0}.imagify-kindof-title{margin-top:2em;padding:0 0 10px;border-bottom:1px solid #D2D3D6;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;font-weight:700}.imagify-settings .imagify-button-mini{padding:4px 13px 4px 10px}.imagify-settings .imagify-button-mini .dashicons-plus{vertical-align:-7.5px}.imagify-settings .imagify-button-mini.imagify-button-primary:focus,.imagify-settings .imagify-button-mini.imagify-button-primary:hover{color:#FFF}p.imagify-custom-folder-line{position:relative;margin:0;padding:12px 15px;color:#4A5362;font-weight:500;-webkit-transition:all .75s;-o-transition:all .75s;transition:all .75s}.imagify-custom-folder-line.imagify-will-remove{background:#C51162;color:#FFF;-webkit-transform:translateX(-120px);-ms-transform:translateX(-120px);transform:translateX(-120px);opacity:0}.imagify-custom-folder-line:first-child{margin-top:-.5em}.imagify-custom-folder-line+.imagify-custom-folder-line{border-top:1px solid #E9EFF2}.imagify-custom-folders-remove{position:absolute;right:0;top:6px;border:0;padding:5px 10px 4px;-webkit-box-shadow:none;box-shadow:none;color:#7A8996;border-radius:16px;font-size:13px;line-height:18px;background:#FFF;-webkit-transition:all .275s;-o-transition:all .275s;transition:all .275s;cursor:pointer}.imagify-custom-folders-remove-text{max-width:0;overflow:hidden;white-space:nowrap;display:inline-block;-webkit-transform:scale(0);-ms-transform:scale(0);transform:scale(0);opacity:0;-webkit-transition:all .275s;-o-transition:all .275s;transition:all .275s}.imagify-custom-folders-remove:focus,.imagify-custom-folders-remove:hover{background:#D9EFF6;color:#225E6E}.imagify-custom-folders-remove:focus .imagify-custom-folders-remove-text,.imagify-custom-folders-remove:hover .imagify-custom-folders-remove-text{max-width:6em;-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1);opacity:1}.imagify-settings .progress{height:8px;margin-top:1em;background:#343A49}.imagify-settings .bar{position:relative;width:1px;height:8px;background:#46B1CE;-webkit-transition:width .5s;-o-transition:width .5s;transition:width .5s}.imagify-settings .percent{position:absolute;top:6px;right:0;padding:0 5px;line-height:1.85;font-size:14px;font-weight:700;color:#40B1D0}.dashicons.rotate{-webkit-animation:icon-rotate 2.6s infinite linear;animation:icon-rotate 2.6s infinite linear}@-webkit-keyframes icon-rotate{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes icon-rotate{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.imagify-add-custom-folder+.imagify-loader{display:none;vertical-align:middle}.imagify-add-custom-folder[disabled]+.imagify-loader{display:inline-block}.imagify-folders-information{position:relative;margin:-5px 0 20px;padding:10px 10px 10px 40px;text-align:left;background:#F2F2F2}.imagify-folders-information i{position:absolute;left:10px;top:50%;margin-top:-10px}.imagify-folders-tree{margin:0;text-align:left}.imagify-folders-tree li{clear:left}.imagify-folders-tree .imagify-folder{-webkit-box-sizing:border-box;box-sizing:border-box;position:relative;width:48px;z-index:2;float:left;margin-top:-3px;padding:0 8px 0 0;border:0;background:0 0!important;-webkit-box-shadow:none;box-shadow:none;cursor:pointer;-webkit-transition:all .275s;-o-transition:all .275s;transition:all .275s}.imagify-folders-tree span.imagify-folder{padding-left:1.5px}.imagify-folders-tree .imagify-folder:before{content:"+";display:inline-block;width:13px;height:21px;font-size:1.5em;vertical-align:.15em}.imagify-folders-tree span.imagify-folder:before{content:''}.imagify-folders-tree .imagify-folder-icon path{-webkit-transition:all .275s;-o-transition:all .275s;transition:all .275s}.imagify-folders-tree .imagify-is-open .imagify-folder-icon path{stroke:#7A8996}.imagify-folders-tree .imagify-is-open.imagify-folder:before{content:"-";color:#7A8996}.imagify-folders-tree .imagify-is-open~label{color:#7A8996}.imagify-folders-tree .imagify-folder .imagify-loader,.imagify-folders-tree .imagify-folder.imagify-loading:before{display:none}.imagify-folders-tree .imagify-folder.imagify-loading .imagify-loader{display:inline-block;width:13px;height:21px;font-size:1.5em;vertical-align:.15em}.imagify-folders-tree .imagify-folder.imagify-loading .imagify-loader img{display:inline-block;width:100%;height:auto;vertical-align:middle}.imagify-folders-tree button.imagify-folder:focus,.imagify-folders-tree button.imagify-folder:focus path,.imagify-folders-tree button.imagify-folder:hover,.imagify-folders-tree button.imagify-folder:hover path{color:#3694AE;stroke:#3694AE}.imagify-folders-tree .imagify-folder.disabled,.imagify-folders-tree .imagify-folder:disabled{color:#7f7f7f}.imagify-swal-content .imagify-folders-tree label{position:relative;display:block;width:100%;padding:3px 0;font-size:15px;font-weight:500;vertical-align:top;-webkit-transition:all .475s;-o-transition:all .475s;transition:all .475s}.imagify-folders-tree input:focus+label,.imagify-swal-content .imagify-folders-tree label:hover{background:#F4F7F9}.imagify-folders-tree .imagify-folder-already-selected input:focus+label,.imagify-folders-tree .imagify-folder-already-selected label,.imagify-folders-tree .imagify-folder-already-selected label:hover{background:#40B1D0;color:#FFF;border-radius:3px;cursor:default}.imagify-folders-tree .imagify-folder-already-selected button,.imagify-folders-tree .imagify-folder-already-selected button path{color:#FFF;stroke:#FFF;cursor:default}.imagify-folders-tree .imagify-folder-already-selected button:focus path,.imagify-folders-tree .imagify-folder-already-selected button:hover path{stroke:#FFF}.imagify-folders-tree .imagify-folder-already-selected button:before{content:''}.imagify-add-ed-folder{position:absolute;top:0;bottom:0;right:0;font-size:11px;text-transform:uppercase;letter-spacing:.02em;word-spacing:.02em;color:#3694AE;background:#F4F7F9;opacity:0;-webkit-transform:translateX(15px);-ms-transform:translateX(15px);transform:translateX(15px);-webkit-transition:all .275s;-o-transition:all .275s;transition:all .275s}.imagify-folder-already-selected .imagify-add-ed-folder,input:checked+label .imagify-add-ed-folder,input:focus+label .imagify-add-ed-folder,label:hover .imagify-add-ed-folder{opacity:1;-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}input:checked+label .imagify-add-ed-folder{background:#FFF}input:checked+label:hover .imagify-add-ed-folder,input:checked:focus+label .imagify-add-ed-folder{background:#F4F7F9}.imagify-folder-already-selected .imagify-add-ed-folder{background:#40B1D0;color:#FFF}.imagify-fake-checkbox{position:relative;display:inline-block;width:14px;height:14px;margin:3.5px 15px 0 5px;border:1.5px solid #3694AE;border-radius:3px;vertical-align:-4px}.imagify-fake-checkbox:after{position:absolute;left:1px;top:0;content:"✓";color:#3694AE;font-size:14px;line-height:.9;font-style:normal;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;opacity:0;-webkit-transform:scale(0);-ms-transform:scale(0);transform:scale(0);-webkit-transition:all .475s;-o-transition:all .475s;transition:all .475s}.imagify-folder-already-selected .imagify-fake-checkbox:after,input:checked+label .imagify-fake-checkbox:after{opacity:1;-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}.imagify-folder-already-selected .imagify-fake-checkbox{border-color:#40B1D0}.imagify-folder-already-selected .imagify-fake-checkbox:after{color:#FFF}.imagify-folders-sub-tree{position:relative;margin-left:.75em;padding-top:.6em;padding-left:1em;border-left:1px dotted rgba(98,110,123,.3)}.imagify-folders-sub-tree li{position:relative;margin-bottom:4px}.imagify-folders-sub-tree li:before{content:"";position:absolute;top:12px;left:-1em;height:1px;width:.9em;border-top:1px dotted rgba(98,110,123,.3)}.imagify-folders-sub-tree li:last-child:after{content:"";position:absolute;left:-1.1em;bottom:0;height:11px;width:3px;background:#FFF}.imagify-empty-folder{margin-top:-.5em}.imagify-empty-folder em{font-size:12px;font-weight:500;color:#A2AFBC}
assets/js/beat.js ADDED
@@ -0,0 +1,872 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Imagify beat API
3
+ *
4
+ * This is a modified version of WordPress’ Heartbeat (WP 5.2.1).
5
+ * The main difference is that it allows to prevent suspension entirely.
6
+ * It uses the var imagifybeatSettings on init.
7
+ *
8
+ * Custom jQuery events:
9
+ * - imagifybeat-send
10
+ * - imagifybeat-tick
11
+ * - imagifybeat-error
12
+ * - imagifybeat-connection-lost
13
+ * - imagifybeat-connection-restored
14
+ * - imagifybeat-nonces-expired
15
+ *
16
+ * @since 1.9.3
17
+ */
18
+
19
+ window.imagify = window.imagify || {};
20
+
21
+ /* eslint-disable no-use-before-define */
22
+ (function($, d, w, undefined) { // eslint-disable-line no-unused-vars, no-shadow, no-shadow-restricted-names
23
+
24
+ /**
25
+ * Constructs the Imagifybeat API.
26
+ *
27
+ * @since 1.9.3
28
+ * @constructor
29
+ *
30
+ * @return {Imagifybeat} An instance of the Imagifybeat class.
31
+ */
32
+ var Imagifybeat = function() {
33
+ var $document = $( d ),
34
+ settings = {
35
+ // Suspend/resume.
36
+ suspend: false,
37
+
38
+ // Whether suspending is enabled.
39
+ suspendEnabled: true,
40
+
41
+ // Current screen id, defaults to the JS global 'pagenow' when present
42
+ // (in the admin) or 'front'.
43
+ screenId: '',
44
+
45
+ // XHR request URL, defaults to the JS global 'ajaxurl' when present.
46
+ url: '',
47
+
48
+ // Timestamp, start of the last connection request.
49
+ lastTick: 0,
50
+
51
+ // Container for the enqueued items.
52
+ queue: {},
53
+
54
+ // Connect interval (in seconds).
55
+ mainInterval: 60,
56
+
57
+ // Used when the interval is set to 5 sec. temporarily.
58
+ tempInterval: 0,
59
+
60
+ // Used when the interval is reset.
61
+ originalInterval: 0,
62
+
63
+ // Used to limit the number of AJAX requests.
64
+ minimalInterval: 0,
65
+
66
+ // Used together with tempInterval.
67
+ countdown: 0,
68
+
69
+ // Whether a connection is currently in progress.
70
+ connecting: false,
71
+
72
+ // Whether a connection error occurred.
73
+ connectionError: false,
74
+
75
+ // Used to track non-critical errors.
76
+ errorcount: 0,
77
+
78
+ // Whether at least one connection has been completed successfully.
79
+ hasConnected: false,
80
+
81
+ // Whether the current browser w is in focus and the user is active.
82
+ hasFocus: true,
83
+
84
+ // Timestamp, last time the user was active. Checked every 30 sec.
85
+ userActivity: 0,
86
+
87
+ // Flag whether events tracking user activity were set.
88
+ userActivityEvents: false,
89
+
90
+ // Timer that keeps track of how long a user has focus.
91
+ checkFocusTimer: 0,
92
+
93
+ // Timer that keeps track of how long needs to be waited before connecting to
94
+ // the server again.
95
+ beatTimer: 0
96
+ };
97
+
98
+ /**
99
+ * Sets local variables and events, then starts the beat.
100
+ *
101
+ * @since 1.9.3
102
+ * @access private
103
+ *
104
+ * @return {void}
105
+ */
106
+ function initialize() {
107
+ var options, hidden, visibilityState, visibilitychange;
108
+
109
+ if ( typeof w.pagenow === 'string' ) {
110
+ settings.screenId = w.pagenow;
111
+ }
112
+
113
+ if ( typeof w.ajaxurl === 'string' ) {
114
+ settings.url = w.ajaxurl;
115
+ }
116
+
117
+ // Pull in options passed from PHP.
118
+ if ( typeof w.imagifybeatSettings === 'object' ) {
119
+ options = w.imagifybeatSettings;
120
+
121
+ // The XHR URL can be passed as option when w.ajaxurl is not set.
122
+ if ( ! settings.url && options.ajaxurl ) {
123
+ settings.url = options.ajaxurl;
124
+ }
125
+
126
+ /*
127
+ * The interval can be from 15 to 120 sec. and can be set temporarily to 5 sec.
128
+ * It can be set in the initial options or changed later through JS and/or
129
+ * through PHP.
130
+ */
131
+ if ( options.interval ) {
132
+ settings.mainInterval = options.interval;
133
+
134
+ if ( settings.mainInterval < 15 ) {
135
+ settings.mainInterval = 15;
136
+ } else if ( settings.mainInterval > 120 ) {
137
+ settings.mainInterval = 120;
138
+ }
139
+ }
140
+
141
+ /*
142
+ * Used to limit the number of AJAX requests. Overrides all other intervals if
143
+ * they are shorter. Needed for some hosts that cannot handle frequent requests
144
+ * and the user may exceed the allocated server CPU time, etc. The minimal
145
+ * interval can be up to 600 sec. however setting it to longer than 120 sec.
146
+ * will limit or disable some of the functionality (like post locks). Once set
147
+ * at initialization, minimalInterval cannot be changed/overridden.
148
+ */
149
+ if ( options.minimalInterval ) {
150
+ options.minimalInterval = parseInt( options.minimalInterval, 10 );
151
+ settings.minimalInterval = options.minimalInterval > 0 && options.minimalInterval <= 600 ? options.minimalInterval * 1000 : 0;
152
+ }
153
+
154
+ if ( settings.minimalInterval && settings.mainInterval < settings.minimalInterval ) {
155
+ settings.mainInterval = settings.minimalInterval;
156
+ }
157
+
158
+ // 'screenId' can be added from settings on the front end where the JS global
159
+ // 'pagenow' is not set.
160
+ if ( ! settings.screenId ) {
161
+ settings.screenId = options.screenId || 'front';
162
+ }
163
+
164
+ if ( 'disable' === options.suspension ) {
165
+ disableSuspend();
166
+ }
167
+ }
168
+
169
+ // Convert to milliseconds.
170
+ settings.mainInterval = settings.mainInterval * 1000;
171
+ settings.originalInterval = settings.mainInterval;
172
+
173
+ /*
174
+ * Switch the interval to 120 seconds by using the Page Visibility API.
175
+ * If the browser doesn't support it (Safari < 7, Android < 4.4, IE < 10), the
176
+ * interval will be increased to 120 seconds after 5 minutes of mouse and keyboard
177
+ * inactivity.
178
+ */
179
+ if ( typeof document.hidden !== 'undefined' ) {
180
+ hidden = 'hidden';
181
+ visibilitychange = 'visibilitychange';
182
+ visibilityState = 'visibilityState';
183
+ } else if ( typeof document.msHidden !== 'undefined' ) { // IE10
184
+ hidden = 'msHidden';
185
+ visibilitychange = 'msvisibilitychange';
186
+ visibilityState = 'msVisibilityState';
187
+ } else if ( typeof document.webkitHidden !== 'undefined' ) { // Android
188
+ hidden = 'webkitHidden';
189
+ visibilitychange = 'webkitvisibilitychange';
190
+ visibilityState = 'webkitVisibilityState';
191
+ }
192
+
193
+ if ( hidden ) {
194
+ if ( document[ hidden ] ) {
195
+ settings.hasFocus = false;
196
+ }
197
+
198
+ $document.on( visibilitychange + '.imagifybeat', function() {
199
+ if ( 'hidden' === document[ visibilityState ] ) {
200
+ blurred();
201
+ w.clearInterval( settings.checkFocusTimer );
202
+ } else {
203
+ focused();
204
+ if ( document.hasFocus ) {
205
+ settings.checkFocusTimer = w.setInterval( checkFocus, 10000 );
206
+ }
207
+ }
208
+ });
209
+ }
210
+
211
+ // Use document.hasFocus() if available.
212
+ if ( document.hasFocus ) {
213
+ settings.checkFocusTimer = w.setInterval( checkFocus, 10000 );
214
+ }
215
+
216
+ $( w ).on( 'unload.imagifybeat', function() {
217
+ // Don't connect anymore.
218
+ settings.suspend = true;
219
+
220
+ // Abort the last request if not completed.
221
+ if ( settings.xhr && 4 !== settings.xhr.readyState ) {
222
+ settings.xhr.abort();
223
+ }
224
+ } );
225
+
226
+ // Check for user activity every 30 seconds.
227
+ w.setInterval( checkUserActivity, 30000 );
228
+
229
+ // Start one tick after DOM ready.
230
+ $document.ready( function() {
231
+ settings.lastTick = time();
232
+ scheduleNextTick();
233
+ } );
234
+ }
235
+
236
+ /**
237
+ * Returns the current time according to the browser.
238
+ *
239
+ * @since 1.9.3
240
+ * @access private
241
+ *
242
+ * @return {int} Returns the current time.
243
+ */
244
+ function time() {
245
+ return (new Date()).getTime();
246
+ }
247
+
248
+ /**
249
+ * Checks if the iframe is from the same origin.
250
+ *
251
+ * @since 1.9.3
252
+ * @access private
253
+ *
254
+ * @return {bool} Returns whether or not the iframe is from the same origin.
255
+ */
256
+ function isLocalFrame( frame ) {
257
+ var origin, src = frame.src;
258
+
259
+ /*
260
+ * Need to compare strings as WebKit doesn't throw JS errors when iframes have different origin. It throws uncatchable exceptions.
261
+ */
262
+ if ( src && /^https?:\/\//.test( src ) ) {
263
+ origin = w.location.origin ? w.location.origin : w.location.protocol + '//' + w.location.host;
264
+
265
+ if ( src.indexOf( origin ) !== 0 ) {
266
+ return false;
267
+ }
268
+ }
269
+
270
+ try {
271
+ if ( frame.contentWindow.document ) {
272
+ return true;
273
+ }
274
+ } catch ( e ) {} // eslint-disable-line no-empty
275
+
276
+ return false;
277
+ }
278
+
279
+ /**
280
+ * Checks if the document's focus has changed.
281
+ *
282
+ * @since 1.9.3
283
+ * @access private
284
+ *
285
+ * @return {void}
286
+ */
287
+ function checkFocus() {
288
+ if ( settings.hasFocus && ! document.hasFocus() ) {
289
+ blurred();
290
+ } else if ( ! settings.hasFocus && document.hasFocus() ) {
291
+ focused();
292
+ }
293
+ }
294
+
295
+ /**
296
+ * Sets error state and fires an event on XHR errors or timeout.
297
+ *
298
+ * @since 1.9.3
299
+ * @access private
300
+ *
301
+ * @param {string} error The error type passed from the XHR.
302
+ * @param {int} httpStatus The HTTP status code passed from jqXHR (200, 404, 500, etc.).
303
+ * @return {void}
304
+ */
305
+ function setErrorState( error, httpStatus ) {
306
+ var trigger;
307
+
308
+ if ( error ) {
309
+ switch ( error ) {
310
+ case 'abort':
311
+ // Do nothing.
312
+ break;
313
+ case 'timeout':
314
+ // No response for 30 sec.
315
+ trigger = true;
316
+ break;
317
+ case 'error':
318
+ if ( 503 === httpStatus && settings.hasConnected ) {
319
+ trigger = true;
320
+ break;
321
+ }
322
+ /* falls through */
323
+ case 'parsererror':
324
+ case 'empty':
325
+ case 'unknown':
326
+ settings.errorcount++;
327
+
328
+ if ( settings.errorcount > 2 && settings.hasConnected ) {
329
+ trigger = true;
330
+ }
331
+
332
+ break;
333
+ }
334
+
335
+ if ( trigger && ! hasConnectionError() ) {
336
+ settings.connectionError = true;
337
+ $document.trigger( 'imagifybeat-connection-lost', [ error, httpStatus ] );
338
+
339
+ if ( w.wp.hooks ) {
340
+ w.wp.hooks.doAction( 'imagifybeat.connection-lost', error, httpStatus );
341
+ }
342
+ }
343
+ }
344
+ }
345
+
346
+ /**
347
+ * Clears the error state and fires an event if there is a connection error.
348
+ *
349
+ * @since 1.9.3
350
+ * @access private
351
+ *
352
+ * @return {void}
353
+ */
354
+ function clearErrorState() {
355
+ // Has connected successfully.
356
+ settings.hasConnected = true;
357
+
358
+ if ( hasConnectionError() ) {
359
+ settings.errorcount = 0;
360
+ settings.connectionError = false;
361
+ $document.trigger( 'imagifybeat-connection-restored' );
362
+
363
+ if ( w.wp.hooks ) {
364
+ w.wp.hooks.doAction( 'imagifybeat.connection-restored' );
365
+ }
366
+ }
367
+ }
368
+
369
+ /**
370
+ * Gathers the data and connects to the server.
371
+ *
372
+ * @since 1.9.3
373
+ * @access private
374
+ *
375
+ * @return {void}
376
+ */
377
+ function connect() {
378
+ var ajaxData, imagifybeatData;
379
+
380
+ // If the connection to the server is slower than the interval,
381
+ // imagifybeat connects as soon as the previous connection's response is received.
382
+ if ( settings.connecting || settings.suspend ) {
383
+ return;
384
+ }
385
+
386
+ settings.lastTick = time();
387
+
388
+ imagifybeatData = $.extend( {}, settings.queue );
389
+ // Clear the data queue. Anything added after this point will be sent on the next tick.
390
+ settings.queue = {};
391
+
392
+ $document.trigger( 'imagifybeat-send', [ imagifybeatData ] );
393
+
394
+ if ( w.wp.hooks ) {
395
+ w.wp.hooks.doAction( 'imagifybeat.send', imagifybeatData );
396
+ }
397
+
398
+ ajaxData = {
399
+ data: imagifybeatData,
400
+ interval: settings.tempInterval ? settings.tempInterval / 1000 : settings.mainInterval / 1000,
401
+ _nonce: typeof w.imagifybeatSettings === 'object' ? w.imagifybeatSettings.nonce : '',
402
+ action: 'imagifybeat',
403
+ screen_id: settings.screenId,
404
+ has_focus: settings.hasFocus
405
+ };
406
+
407
+ if ( 'customize' === settings.screenId ) {
408
+ ajaxData.wp_customize = 'on';
409
+ }
410
+
411
+ settings.connecting = true;
412
+ settings.xhr = $.ajax( {
413
+ url: settings.url,
414
+ type: 'post',
415
+ timeout: 60000, // Throw an error if not completed after 60 sec.
416
+ data: ajaxData,
417
+ dataType: 'json'
418
+ } ).always( function() {
419
+ settings.connecting = false;
420
+ scheduleNextTick();
421
+ } ).done( function( response, textStatus, jqXHR ) {
422
+ var newInterval;
423
+
424
+ if ( ! response ) {
425
+ setErrorState( 'empty' );
426
+ return;
427
+ }
428
+
429
+ clearErrorState();
430
+
431
+ if ( response.nonces_expired ) {
432
+ $document.trigger( 'imagifybeat-nonces-expired' );
433
+
434
+ if ( w.wp.hooks ) {
435
+ w.wp.hooks.doAction( 'imagifybeat.nonces-expired' );
436
+ }
437
+ }
438
+
439
+ // Change the interval from PHP
440
+ if ( response.imagifybeat_interval ) {
441
+ newInterval = response.imagifybeat_interval;
442
+ delete response.imagifybeat_interval;
443
+ }
444
+
445
+ // Update the imagifybeat nonce if set.
446
+ if ( response.imagifybeat_nonce && typeof w.imagifybeatSettings === 'object' ) {
447
+ w.imagifybeatSettings.nonce = response.imagifybeat_nonce;
448
+ delete response.imagifybeat_nonce;
449
+ }
450
+
451
+ $document.trigger( 'imagifybeat-tick', [ response, textStatus, jqXHR ] );
452
+
453
+ if ( w.wp.hooks ) {
454
+ w.wp.hooks.doAction( 'imagifybeat.tick', response, textStatus, jqXHR );
455
+ }
456
+
457
+ // Do this last. Can trigger the next XHR if connection time > 5 sec. and newInterval == 'fast'.
458
+ if ( newInterval ) {
459
+ interval( newInterval );
460
+ }
461
+ } ).fail( function( jqXHR, textStatus, error ) {
462
+ setErrorState( textStatus || 'unknown', jqXHR.status );
463
+ $document.trigger( 'imagifybeat-error', [ jqXHR, textStatus, error ] );
464
+
465
+ if ( w.wp.hooks ) {
466
+ w.wp.hooks.doAction( 'imagifybeat.error', jqXHR, textStatus, error );
467
+ }
468
+ } );
469
+ }
470
+
471
+ /**
472
+ * Schedules the next connection.
473
+ *
474
+ * Fires immediately if the connection time is longer than the interval.
475
+ *
476
+ * @since 1.9.3
477
+ * @access private
478
+ *
479
+ * @return {void}
480
+ */
481
+ function scheduleNextTick() {
482
+ var delta = time() - settings.lastTick,
483
+ interv = settings.mainInterval;
484
+
485
+ if ( settings.suspend ) {
486
+ return;
487
+ }
488
+
489
+ if ( ! settings.hasFocus && settings.suspendEnabled ) {
490
+ // When no user activity or the window lost focus, increase polling interval to 120 seconds, but only if suspend is enabled.
491
+ interv = 120000; // 120 sec.
492
+ } else if ( settings.countdown > 0 && settings.tempInterval ) {
493
+ interv = settings.tempInterval;
494
+ settings.countdown--;
495
+
496
+ if ( settings.countdown < 1 ) {
497
+ settings.tempInterval = 0;
498
+ }
499
+ }
500
+
501
+ if ( settings.minimalInterval && interv < settings.minimalInterval ) {
502
+ interv = settings.minimalInterval;
503
+ }
504
+
505
+ w.clearTimeout( settings.beatTimer );
506
+
507
+ if ( delta < interv ) {
508
+ settings.beatTimer = w.setTimeout(
509
+ function() {
510
+ connect();
511
+ },
512
+ interv - delta
513
+ );
514
+ } else {
515
+ connect();
516
+ }
517
+ }
518
+
519
+ /**
520
+ * Sets the internal state when the browser w becomes hidden or loses focus.
521
+ *
522
+ * @since 1.9.3
523
+ * @access private
524
+ *
525
+ * @return {void}
526
+ */
527
+ function blurred() {
528
+ settings.hasFocus = false;
529
+ }
530
+
531
+ /**
532
+ * Sets the internal state when the browser w becomes visible or is in focus.
533
+ *
534
+ * @since 1.9.3
535
+ * @access private
536
+ *
537
+ * @return {void}
538
+ */
539
+ function focused() {
540
+ settings.userActivity = time();
541
+
542
+ // Resume if suspended
543
+ settings.suspend = false;
544
+
545
+ if ( ! settings.hasFocus ) {
546
+ settings.hasFocus = true;
547
+ scheduleNextTick();
548
+ }
549
+ }
550
+
551
+ /**
552
+ * Runs when the user becomes active after a period of inactivity.
553
+ *
554
+ * @since 1.9.3
555
+ * @access private
556
+ *
557
+ * @return {void}
558
+ */
559
+ function userIsActive() {
560
+ settings.userActivityEvents = false;
561
+ $document.off( '.imagifybeat-active' );
562
+
563
+ $( 'iframe' ).each( function( i, frame ) {
564
+ if ( isLocalFrame( frame ) ) {
565
+ $( frame.contentWindow ).off( '.imagifybeat-active' );
566
+ }
567
+ } );
568
+
569
+ focused();
570
+ }
571
+
572
+ /**
573
+ * Checks for user activity.
574
+ *
575
+ * Runs every 30 sec. Sets 'hasFocus = true' if user is active and the w is
576
+ * in the background. Sets 'hasFocus = false' if the user has been inactive
577
+ * (no mouse or keyboard activity) for 5 min. even when the w has focus.
578
+ *
579
+ * @since 1.9.3
580
+ * @access private
581
+ *
582
+ * @return {void}
583
+ */
584
+ function checkUserActivity() {
585
+ var lastActive = settings.userActivity ? time() - settings.userActivity : 0;
586
+
587
+ // Set hasFocus to false when no mouse or keyboard activity for 5 min.
588
+ if ( lastActive > 300000 && settings.hasFocus ) {
589
+ blurred();
590
+ }
591
+
592
+ // Suspend after 10 min. of inactivity.
593
+ if ( settings.suspendEnabled && lastActive > 600000 ) {
594
+ settings.suspend = true;
595
+ }
596
+
597
+ if ( ! settings.userActivityEvents ) {
598
+ $document.on( 'mouseover.imagifybeat-active keyup.imagifybeat-active touchend.imagifybeat-active', function() {
599
+ userIsActive();
600
+ } );
601
+
602
+ $( 'iframe' ).each( function( i, frame ) {
603
+ if ( isLocalFrame( frame ) ) {
604
+ $( frame.contentWindow ).on( 'mouseover.imagifybeat-active keyup.imagifybeat-active touchend.imagifybeat-active', function() {
605
+ userIsActive();
606
+ } );
607
+ }
608
+ } );
609
+
610
+ settings.userActivityEvents = true;
611
+ }
612
+ }
613
+
614
+ // Public methods.
615
+
616
+ /**
617
+ * Checks whether the w (or any local iframe in it) has focus, or the user
618
+ * is active.
619
+ *
620
+ * @since 1.9.3
621
+ * @memberOf imagify.beat.prototype
622
+ *
623
+ * @return {bool} True if the w or the user is active.
624
+ */
625
+ function hasFocus() {
626
+ return settings.hasFocus;
627
+ }
628
+
629
+ /**
630
+ * Checks whether there is a connection error.
631
+ *
632
+ * @since 1.9.3
633
+ * @memberOf imagify.beat.prototype
634
+ *
635
+ * @return {bool} True if a connection error was found.
636
+ */
637
+ function hasConnectionError() {
638
+ return settings.connectionError;
639
+ }
640
+
641
+ /**
642
+ * Connects as soon as possible regardless of 'hasFocus' state.
643
+ *
644
+ * Will not open two concurrent connections. If a connection is in progress,
645
+ * will connect again immediately after the current connection completes.
646
+ *
647
+ * @since 1.9.3
648
+ * @memberOf imagify.beat.prototype
649
+ *
650
+ * @return {void}
651
+ */
652
+ function connectNow() {
653
+ settings.lastTick = 0;
654
+ scheduleNextTick();
655
+ }
656
+
657
+ /**
658
+ * Disables suspending.
659
+ *
660
+ * Should be used only when Imagifybeat is performing critical tasks like
661
+ * autosave, post-locking, etc. Using this on many screens may overload the
662
+ * user's hosting account if several browser ws/tabs are left open for a
663
+ * long time.
664
+ *
665
+ * @since 1.9.3
666
+ * @memberOf imagify.beat.prototype
667
+ *
668
+ * @return {void}
669
+ */
670
+ function disableSuspend() {
671
+ settings.suspendEnabled = false;
672
+ }
673
+
674
+ /**
675
+ * Enables suspending.
676
+ *
677
+ * @since 1.9.3
678
+ * @memberOf imagify.beat.prototype
679
+ *
680
+ * @return {void}
681
+ */
682
+ function enableSuspend() {
683
+ settings.suspendEnabled = true;
684
+ }
685
+
686
+ /**
687
+ * Gets/Sets the interval.
688
+ *
689
+ * When setting to 'fast' or 5, the interval is 5 seconds for the next 30 ticks
690
+ * (for 2 minutes and 30 seconds) by default. In this case the number of 'ticks'
691
+ * can be passed as second argument. If the window doesn't have focus, the
692
+ * interval slows down to 2 min.
693
+ *
694
+ * @since 1.9.3
695
+ * @memberOf imagify.beat.prototype
696
+ *
697
+ * @param {string|int} speed Interval: 'fast' or 5, 15, 30, 60, 120. Fast equals 5.
698
+ * @param {string} ticks Tells how many ticks before the interval reverts back. Used with speed = 'fast' or 5.
699
+ * @return {int} Current interval in seconds.
700
+ */
701
+ function interval( speed, ticks ) {
702
+ var newInterval,
703
+ oldInterval = settings.tempInterval ? settings.tempInterval : settings.mainInterval;
704
+
705
+ if ( speed ) {
706
+ switch ( speed ) {
707
+ case 'fast':
708
+ case 5:
709
+ newInterval = 5000;
710
+ break;
711
+ case 15:
712
+ newInterval = 15000;
713
+ break;
714
+ case 30:
715
+ newInterval = 30000;
716
+ break;
717
+ case 60:
718
+ newInterval = 60000;
719
+ break;
720
+ case 120:
721
+ newInterval = 120000;
722
+ break;
723
+ case 'long-polling':
724
+ // Allow long polling, (experimental)
725
+ settings.mainInterval = 0;
726
+ return 0;
727
+ default:
728
+ newInterval = settings.originalInterval;
729
+ }
730
+
731
+ if ( settings.minimalInterval && newInterval < settings.minimalInterval ) {
732
+ newInterval = settings.minimalInterval;
733
+ }
734
+
735
+ if ( 5000 === newInterval ) {
736
+ ticks = parseInt( ticks, 10 ) || 30;
737
+ ticks = ticks < 1 || ticks > 30 ? 30 : ticks;
738
+
739
+ settings.countdown = ticks;
740
+ settings.tempInterval = newInterval;
741
+ } else {
742
+ settings.countdown = 0;
743
+ settings.tempInterval = 0;
744
+ settings.mainInterval = newInterval;
745
+ }
746
+
747
+ // Change the next connection time if new interval has been set.
748
+ // Will connect immediately if the time since the last connection
749
+ // is greater than the new interval.
750
+ if ( newInterval !== oldInterval ) {
751
+ scheduleNextTick();
752
+ }
753
+ }
754
+
755
+ return settings.tempInterval ? settings.tempInterval / 1000 : settings.mainInterval / 1000;
756
+ }
757
+
758
+ /**
759
+ * Resets the interval.
760
+ *
761
+ * @since 1.9.3
762
+ * @memberOf imagify.beat.prototype
763
+ *
764
+ * @return {int} Current interval in seconds.
765
+ */
766
+ function resetInterval() {
767
+ return interval( settings.originalInterval );
768
+ }
769
+
770
+ /**
771
+ * Enqueues data to send with the next XHR.
772
+ *
773
+ * As the data is send asynchronously, this function doesn't return the XHR
774
+ * response. To see the response, use the custom jQuery event 'imagifybeat-tick'
775
+ * on the document, example:
776
+ * $(document).on( 'imagifybeat-tick.myname', function( event, data, textStatus, jqXHR ) {
777
+ * // code
778
+ * });
779
+ * If the same 'handle' is used more than once, the data is not overwritten when
780
+ * the third argument is 'true'. Use `imagify.beat.isQueued('handle')` to see if
781
+ * any data is already queued for that handle.
782
+ *
783
+ * @since 1.9.3
784
+ * @memberOf imagify.beat.prototype
785
+ *
786
+ * @param {string} handle Unique handle for the data, used in PHP to receive the data.
787
+ * @param {mixed} data The data to send.
788
+ * @param {bool} noOverwrite Whether to overwrite existing data in the queue.
789
+ * @return {bool} True if the data was queued.
790
+ */
791
+ function enqueue( handle, data, noOverwrite ) {
792
+ if ( handle ) {
793
+ if ( noOverwrite && this.isQueued( handle ) ) {
794
+ return false;
795
+ }
796
+
797
+ settings.queue[handle] = data;
798
+ return true;
799
+ }
800
+ return false;
801
+ }
802
+
803
+ /**
804
+ * Checks if data with a particular handle is queued.
805
+ *
806
+ * @since 1.9.3
807
+ *
808
+ * @param {string} handle The handle for the data.
809
+ * @return {bool} True if the data is queued with this handle.
810
+ */
811
+ function isQueued( handle ) {
812
+ if ( handle ) {
813
+ return settings.queue.hasOwnProperty( handle );
814
+ }
815
+ }
816
+
817
+ /**
818
+ * Removes data with a particular handle from the queue.
819
+ *
820
+ * @since 1.9.3
821
+ * @memberOf imagify.beat.prototype
822
+ *
823
+ * @param {string} handle The handle for the data.
824
+ */
825
+ function dequeue( handle ) {
826
+ if ( handle ) {
827
+ delete settings.queue[handle];
828
+ }
829
+ }
830
+
831
+ /**
832
+ * Gets data that was enqueued with a particular handle.
833
+ *
834
+ * @since 1.9.3
835
+ * @memberOf imagify.beat.prototype
836
+ *
837
+ * @param {string} handle The handle for the data.
838
+ * @return {mixed} The data or undefined.
839
+ */
840
+ function getQueuedItem( handle ) {
841
+ if ( handle ) {
842
+ return this.isQueued( handle ) ? settings.queue[ handle ] : undefined;
843
+ }
844
+ }
845
+
846
+ initialize();
847
+
848
+ // Expose public methods.
849
+ return {
850
+ hasFocus: hasFocus,
851
+ connectNow: connectNow,
852
+ disableSuspend: disableSuspend,
853
+ enableSuspend: enableSuspend,
854
+ interval: interval,
855
+ resetInterval: resetInterval,
856
+ hasConnectionError: hasConnectionError,
857
+ enqueue: enqueue,
858
+ dequeue: dequeue,
859
+ isQueued: isQueued,
860
+ getQueuedItem: getQueuedItem
861
+ };
862
+ };
863
+
864
+ /**
865
+ * Contains the Imagifybeat API.
866
+ *
867
+ * @namespace imagify.beat
868
+ * @type {Imagifybeat}
869
+ */
870
+ w.imagify.beat = new Imagifybeat();
871
+
872
+ } )( jQuery, document, window );
assets/js/beat.min.js ADDED
@@ -0,0 +1 @@
 
1
+ window.imagify=window.imagify||{},function(a,b,c,d){var e=function(){function e(){return(new Date).getTime()}function f(a){var b,d=a.src;if(d&&/^https?:\/\//.test(d)&&(b=c.location.origin?c.location.origin:c.location.protocol+"//"+c.location.host,0!==d.indexOf(b)))return!1;try{if(a.contentWindow.document)return!0}catch(a){}return!1}function g(){B.hasFocus&&!document.hasFocus()?l():!B.hasFocus&&document.hasFocus()&&m()}function h(a,b){var d;if(a){switch(a){case"abort":break;case"timeout":d=!0;break;case"error":if(503===b&&B.hasConnected){d=!0;break}case"parsererror":case"empty":case"unknown":B.errorcount++,B.errorcount>2&&B.hasConnected&&(d=!0)}d&&!q()&&(B.connectionError=!0,A.trigger("imagifybeat-connection-lost",[a,b]),c.wp.hooks&&c.wp.hooks.doAction("imagifybeat.connection-lost",a,b))}}function i(){B.hasConnected=!0,q()&&(B.errorcount=0,B.connectionError=!1,A.trigger("imagifybeat-connection-restored"),c.wp.hooks&&c.wp.hooks.doAction("imagifybeat.connection-restored"))}function j(){var b,d;B.connecting||B.suspend||(B.lastTick=e(),d=a.extend({},B.queue),B.queue={},A.trigger("imagifybeat-send",[d]),c.wp.hooks&&c.wp.hooks.doAction("imagifybeat.send",d),b={data:d,interval:B.tempInterval?B.tempInterval/1e3:B.mainInterval/1e3,_nonce:"object"==typeof c.imagifybeatSettings?c.imagifybeatSettings.nonce:"",action:"imagifybeat",screen_id:B.screenId,has_focus:B.hasFocus},"customize"===B.screenId&&(b.wp_customize="on"),B.connecting=!0,B.xhr=a.ajax({url:B.url,type:"post",timeout:6e4,data:b,dataType:"json"}).always(function(){B.connecting=!1,k()}).done(function(a,b,d){var e;if(!a)return void h("empty");i(),a.nonces_expired&&(A.trigger("imagifybeat-nonces-expired"),c.wp.hooks&&c.wp.hooks.doAction("imagifybeat.nonces-expired")),a.imagifybeat_interval&&(e=a.imagifybeat_interval,delete a.imagifybeat_interval),a.imagifybeat_nonce&&"object"==typeof c.imagifybeatSettings&&(c.imagifybeatSettings.nonce=a.imagifybeat_nonce,delete a.imagifybeat_nonce),A.trigger("imagifybeat-tick",[a,b,d]),c.wp.hooks&&c.wp.hooks.doAction("imagifybeat.tick",a,b,d),e&&u(e)}).fail(function(a,b,d){h(b||"unknown",a.status),A.trigger("imagifybeat-error",[a,b,d]),c.wp.hooks&&c.wp.hooks.doAction("imagifybeat.error",a,b,d)}))}function k(){var a=e()-B.lastTick,b=B.mainInterval;B.suspend||(!B.hasFocus&&B.suspendEnabled?b=12e4:B.countdown>0&&B.tempInterval&&(b=B.tempInterval,--B.countdown<1&&(B.tempInterval=0)),B.minimalInterval&&b<B.minimalInterval&&(b=B.minimalInterval),c.clearTimeout(B.beatTimer),a<b?B.beatTimer=c.setTimeout(function(){j()},b-a):j())}function l(){B.hasFocus=!1}function m(){B.userActivity=e(),B.suspend=!1,B.hasFocus||(B.hasFocus=!0,k())}function n(){B.userActivityEvents=!1,A.off(".imagifybeat-active"),a("iframe").each(function(b,c){f(c)&&a(c.contentWindow).off(".imagifybeat-active")}),m()}function o(){var b=B.userActivity?e()-B.userActivity:0;b>3e5&&B.hasFocus&&l(),B.suspendEnabled&&b>6e5&&(B.suspend=!0),B.userActivityEvents||(A.on("mouseover.imagifybeat-active keyup.imagifybeat-active touchend.imagifybeat-active",function(){n()}),a("iframe").each(function(b,c){f(c)&&a(c.contentWindow).on("mouseover.imagifybeat-active keyup.imagifybeat-active touchend.imagifybeat-active",function(){n()})}),B.userActivityEvents=!0)}function p(){return B.hasFocus}function q(){return B.connectionError}function r(){B.lastTick=0,k()}function s(){B.suspendEnabled=!1}function t(){B.suspendEnabled=!0}function u(a,b){var c,d=B.tempInterval?B.tempInterval:B.mainInterval;if(a){switch(a){case"fast":case 5:c=5e3;break;case 15:c=15e3;break;case 30:c=3e4;break;case 60:c=6e4;break;case 120:c=12e4;break;case"long-polling":return B.mainInterval=0,0;default:c=B.originalInterval}B.minimalInterval&&c<B.minimalInterval&&(c=B.minimalInterval),5e3===c?(b=parseInt(b,10)||30,b=b<1||b>30?30:b,B.countdown=b,B.tempInterval=c):(B.countdown=0,B.tempInterval=0,B.mainInterval=c),c!==d&&k()}return B.tempInterval?B.tempInterval/1e3:B.mainInterval/1e3}function v(){return u(B.originalInterval)}function w(a,b,c){return!!a&&((!c||!this.isQueued(a))&&(B.queue[a]=b,!0))}function x(a){if(a)return B.queue.hasOwnProperty(a)}function y(a){a&&delete B.queue[a]}function z(a){if(a)return this.isQueued(a)?B.queue[a]:d}var A=a(b),B={suspend:!1,suspendEnabled:!0,screenId:"",url:"",lastTick:0,queue:{},mainInterval:60,tempInterval:0,originalInterval:0,minimalInterval:0,countdown:0,connecting:!1,connectionError:!1,errorcount:0,hasConnected:!1,hasFocus:!0,userActivity:0,userActivityEvents:!1,checkFocusTimer:0,beatTimer:0};return function(){var b,d,f,h;"string"==typeof c.pagenow&&(B.screenId=c.pagenow),"string"==typeof c.ajaxurl&&(B.url=c.ajaxurl),"object"==typeof c.imagifybeatSettings&&(b=c.imagifybeatSettings,!B.url&&b.ajaxurl&&(B.url=b.ajaxurl),b.interval&&(B.mainInterval=b.interval,B.mainInterval<15?B.mainInterval=15:B.mainInterval>120&&(B.mainInterval=120)),b.minimalInterval&&(b.minimalInterval=parseInt(b.minimalInterval,10),B.minimalInterval=b.minimalInterval>0&&b.minimalInterval<=600?1e3*b.minimalInterval:0),B.minimalInterval&&B.mainInterval<B.minimalInterval&&(B.mainInterval=B.minimalInterval),B.screenId||(B.screenId=b.screenId||"front"),"disable"===b.suspension&&s()),B.mainInterval=1e3*B.mainInterval,B.originalInterval=B.mainInterval,void 0!==document.hidden?(d="hidden",h="visibilitychange",f="visibilityState"):void 0!==document.msHidden?(d="msHidden",h="msvisibilitychange",f="msVisibilityState"):void 0!==document.webkitHidden&&(d="webkitHidden",h="webkitvisibilitychange",f="webkitVisibilityState"),d&&(document[d]&&(B.hasFocus=!1),A.on(h+".imagifybeat",function(){"hidden"===document[f]?(l(),c.clearInterval(B.checkFocusTimer)):(m(),document.hasFocus&&(B.checkFocusTimer=c.setInterval(g,1e4)))})),document.hasFocus&&(B.checkFocusTimer=c.setInterval(g,1e4)),a(c).on("unload.imagifybeat",function(){B.suspend=!0,B.xhr&&4!==B.xhr.readyState&&B.xhr.abort()}),c.setInterval(o,3e4),A.ready(function(){B.lastTick=e(),k()})}(),{hasFocus:p,connectNow:r,disableSuspend:s,enableSuspend:t,interval:u,resetInterval:v,hasConnectionError:q,enqueue:w,dequeue:y,isQueued:x,getQueuedItem:z}};c.imagify.beat=new e}(jQuery,document,window);
assets/js/bulk.js CHANGED
@@ -202,25 +202,25 @@ window.imagify = window.imagify || {};
202
 
203
  if ( imagifyBulk.ajaxActions.getStats && $( '.imagify-bulk-table [data-group-id="library"][data-context="wp"]' ).length ) {
204
  // On large WP library, don't request stats periodically, only when everything is done.
205
- imagifyBulk.heartbeatIDs.stats = false;
206
  }
207
 
208
- if ( imagifyBulk.heartbeatIDs.stats ) {
209
- // Heartbeat for stats.
210
  $document
211
- .on( 'heartbeat-send', this.addStatsHeartbeat )
212
- .on( 'heartbeat-tick', this.processStatsHeartbeat );
213
  }
214
 
215
- // Heartbeat for optimization queue.
216
  $document
217
- .on( 'heartbeat-send', this.addQueueHeartbeat )
218
- .on( 'heartbeat-tick', this.processQueueHeartbeat );
219
 
220
- // Heartbeat for requirements.
221
  $document
222
- .on( 'heartbeat-send', this.addRequirementsHeartbeat )
223
- .on( 'heartbeat-tick', this.processRequirementsHeartbeat );
224
  },
225
 
226
  /*
@@ -544,7 +544,7 @@ window.imagify = window.imagify || {};
544
  /**
545
  * Print optimization stats.
546
  *
547
- * @param {object} data Object containing all Heartbeat IDs.
548
  */
549
  updateStats: function ( data ) {
550
  var donutData;
@@ -797,6 +797,10 @@ window.imagify = window.imagify || {};
797
  w.imagify.bulk.displayFolderRow( 'waiting', $row );
798
  } );
799
 
 
 
 
 
800
  // Process the queue.
801
  $w.trigger( 'processQueue.imagify' );
802
  },
@@ -1080,6 +1084,10 @@ window.imagify = window.imagify || {};
1080
  return;
1081
  }
1082
 
 
 
 
 
1083
  // Update folder type status.
1084
  if ( ! $.isEmptyObject( w.imagify.bulk.status ) && ! w.imagify.bulk.status[ item.groupID ].isError ) {
1085
  w.imagify.bulk.status[ item.groupID ].id = 'done';
@@ -1131,14 +1139,18 @@ window.imagify = window.imagify || {};
1131
  noImages = true,
1132
  errorMsg = '';
1133
 
 
 
 
 
1134
  // Display the share box.
1135
  w.imagify.bulk.displayShareBox();
1136
 
1137
  // Reset the queue.
1138
  w.imagify.bulk.folderTypesQueue = [];
1139
 
1140
- // Fetch and display generic stats if stats via heartbeat are disabled.
1141
- if ( ! imagifyBulk.heartbeatIDs.stats ) {
1142
  $.get( w.imagify.bulk.getAjaxUrl( 'getStats' ), {
1143
  types: w.imagify.bulk.getFolderTypes()
1144
  } )
@@ -1247,81 +1259,81 @@ window.imagify = window.imagify || {};
1247
  w.open( this.href, '', 'status=no, scrollbars=no, menubar=no, top=' + clientTop + ', left=' + clientLeft + ', width=' + width + ', height=' + height );
1248
  },
1249
 
1250
- // Heartbeat ===============================================================================
1251
 
1252
  /**
1253
- * Add a Heartbeat ID for global stats on "heartbeat-send" event.
1254
  *
1255
  * @param {object} e Event object.
1256
- * @param {object} data Object containing all Heartbeat IDs.
1257
  */
1258
- addStatsHeartbeat: function ( e, data ) {
1259
- data[ imagifyBulk.heartbeatIDs.stats ] = Object.keys( w.imagify.bulk.getFolderTypes() );
1260
  },
1261
 
1262
  /**
1263
- * Listen for the custom event "heartbeat-tick" on $(document).
1264
  * It allows to update various data periodically.
1265
  *
1266
  * @param {object} e Event object.
1267
- * @param {object} data Object containing all Heartbeat IDs.
1268
  */
1269
- processStatsHeartbeat: function ( e, data ) {
1270
- if ( typeof data[ imagifyBulk.heartbeatIDs.stats ] !== 'undefined' ) {
1271
- w.imagify.bulk.updateStats( data[ imagifyBulk.heartbeatIDs.stats ] );
1272
  }
1273
  },
1274
 
1275
  /**
1276
- * Add a Heartbeat ID on "heartbeat-send" event to sync the optimization queue.
1277
  *
1278
  * @param {object} e Event object.
1279
- * @param {object} data Object containing all Heartbeat IDs.
1280
  */
1281
- addQueueHeartbeat: function ( e, data ) {
1282
  if ( w.imagify.bulk.processingMedia.length ) {
1283
- data[ imagifyBulk.heartbeatIDs.queue ] = w.imagify.bulk.processingMedia;
1284
  }
1285
  },
1286
 
1287
  /**
1288
- * Listen for the custom event "heartbeat-tick" on $(document).
1289
  * It allows to update various data periodically.
1290
  *
1291
  * @param {object} e Event object.
1292
- * @param {object} data Object containing all Heartbeat IDs.
1293
  */
1294
- processQueueHeartbeat: function ( e, data ) {
1295
- if ( typeof data[ imagifyBulk.heartbeatIDs.queue ] !== 'undefined' ) {
1296
- $.each( data[ imagifyBulk.heartbeatIDs.queue ], function ( i, mediaData ) {
1297
  $( w ).trigger( 'mediaProcessed.imagify', [ mediaData ] );
1298
  } );
1299
  }
1300
  },
1301
 
1302
  /**
1303
- * Add a Heartbeat ID for requirements on "heartbeat-send" event.
1304
  *
1305
  * @param {object} e Event object.
1306
- * @param {object} data Object containing all Heartbeat IDs.
1307
  */
1308
- addRequirementsHeartbeat: function ( e, data ) {
1309
- data[ imagifyBulk.heartbeatIDs.requirements ] = 1;
1310
  },
1311
 
1312
  /**
1313
- * Listen for the custom event "heartbeat-tick" on $(document).
1314
  * It allows to update requirements status periodically.
1315
  *
1316
  * @param {object} e Event object.
1317
- * @param {object} data Object containing all Heartbeat IDs.
1318
  */
1319
- processRequirementsHeartbeat: function ( e, data ) {
1320
- if ( typeof data[ imagifyBulk.heartbeatIDs.requirements ] === 'undefined' ) {
1321
  return;
1322
  }
1323
 
1324
- data = data[ imagifyBulk.heartbeatIDs.requirements ];
1325
 
1326
  imagifyBulk.curlMissing = data.curl_missing;
1327
  imagifyBulk.editorMissing = data.editor_missing;
202
 
203
  if ( imagifyBulk.ajaxActions.getStats && $( '.imagify-bulk-table [data-group-id="library"][data-context="wp"]' ).length ) {
204
  // On large WP library, don't request stats periodically, only when everything is done.
205
+ imagifyBulk.imagifybeatIDs.stats = false;
206
  }
207
 
208
+ if ( imagifyBulk.imagifybeatIDs.stats ) {
209
+ // Imagifybeat for stats.
210
  $document
211
+ .on( 'imagifybeat-send', this.addStatsImagifybeat )
212
+ .on( 'imagifybeat-tick', this.processStatsImagifybeat );
213
  }
214
 
215
+ // Imagifybeat for optimization queue.
216
  $document
217
+ .on( 'imagifybeat-send', this.addQueueImagifybeat )
218
+ .on( 'imagifybeat-tick', this.processQueueImagifybeat );
219
 
220
+ // Imagifybeat for requirements.
221
  $document
222
+ .on( 'imagifybeat-send', this.addRequirementsImagifybeat )
223
+ .on( 'imagifybeat-tick', this.processRequirementsImagifybeat );
224
  },
225
 
226
  /*
544
  /**
545
  * Print optimization stats.
546
  *
547
+ * @param {object} data Object containing all Imagifybeat IDs.
548
  */
549
  updateStats: function ( data ) {
550
  var donutData;
797
  w.imagify.bulk.displayFolderRow( 'waiting', $row );
798
  } );
799
 
800
+ // Fasten Imagifybeat: 1 tick every 15 seconds, and disable suspend.
801
+ w.imagify.beat.interval( 15 );
802
+ w.imagify.beat.disableSuspend();
803
+
804
  // Process the queue.
805
  $w.trigger( 'processQueue.imagify' );
806
  },
1084
  return;
1085
  }
1086
 
1087
+ // Reset Imagifybeat interval and enable suspend.
1088
+ w.imagify.beat.resetInterval();
1089
+ w.imagify.beat.enableSuspend();
1090
+
1091
  // Update folder type status.
1092
  if ( ! $.isEmptyObject( w.imagify.bulk.status ) && ! w.imagify.bulk.status[ item.groupID ].isError ) {
1093
  w.imagify.bulk.status[ item.groupID ].id = 'done';
1139
  noImages = true,
1140
  errorMsg = '';
1141
 
1142
+ // Reset Imagifybeat interval and enable suspend.
1143
+ w.imagify.beat.resetInterval();
1144
+ w.imagify.beat.enableSuspend();
1145
+
1146
  // Display the share box.
1147
  w.imagify.bulk.displayShareBox();
1148
 
1149
  // Reset the queue.
1150
  w.imagify.bulk.folderTypesQueue = [];
1151
 
1152
+ // Fetch and display generic stats if stats via Imagifybeat are disabled.
1153
+ if ( ! imagifyBulk.imagifybeatIDs.stats ) {
1154
  $.get( w.imagify.bulk.getAjaxUrl( 'getStats' ), {
1155
  types: w.imagify.bulk.getFolderTypes()
1156
  } )
1259
  w.open( this.href, '', 'status=no, scrollbars=no, menubar=no, top=' + clientTop + ', left=' + clientLeft + ', width=' + width + ', height=' + height );
1260
  },
1261
 
1262
+ // Imagifybeat =============================================================================
1263
 
1264
  /**
1265
+ * Add a Imagifybeat ID for global stats on "imagifybeat-send" event.
1266
  *
1267
  * @param {object} e Event object.
1268
+ * @param {object} data Object containing all Imagifybeat IDs.
1269
  */
1270
+ addStatsImagifybeat: function ( e, data ) {
1271
+ data[ imagifyBulk.imagifybeatIDs.stats ] = Object.keys( w.imagify.bulk.getFolderTypes() );
1272
  },
1273
 
1274
  /**
1275
+ * Listen for the custom event "imagifybeat-tick" on $(document).
1276
  * It allows to update various data periodically.
1277
  *
1278
  * @param {object} e Event object.
1279
+ * @param {object} data Object containing all Imagifybeat IDs.
1280
  */
1281
+ processStatsImagifybeat: function ( e, data ) {
1282
+ if ( typeof data[ imagifyBulk.imagifybeatIDs.stats ] !== 'undefined' ) {
1283
+ w.imagify.bulk.updateStats( data[ imagifyBulk.imagifybeatIDs.stats ] );
1284
  }
1285
  },
1286
 
1287
  /**
1288
+ * Add a Imagifybeat ID on "imagifybeat-send" event to sync the optimization queue.
1289
  *
1290
  * @param {object} e Event object.
1291
+ * @param {object} data Object containing all Imagifybeat IDs.
1292
  */
1293
+ addQueueImagifybeat: function ( e, data ) {
1294
  if ( w.imagify.bulk.processingMedia.length ) {
1295
+ data[ imagifyBulk.imagifybeatIDs.queue ] = w.imagify.bulk.processingMedia;
1296
  }
1297
  },
1298
 
1299
  /**
1300
+ * Listen for the custom event "imagifybeat-tick" on $(document).
1301
  * It allows to update various data periodically.
1302
  *
1303
  * @param {object} e Event object.
1304
+ * @param {object} data Object containing all Imagifybeat IDs.
1305
  */
1306
+ processQueueImagifybeat: function ( e, data ) {
1307
+ if ( typeof data[ imagifyBulk.imagifybeatIDs.queue ] !== 'undefined' ) {
1308
+ $.each( data[ imagifyBulk.imagifybeatIDs.queue ], function ( i, mediaData ) {
1309
  $( w ).trigger( 'mediaProcessed.imagify', [ mediaData ] );
1310
  } );
1311
  }
1312
  },
1313
 
1314
  /**
1315
+ * Add a Imagifybeat ID for requirements on "imagifybeat-send" event.
1316
  *
1317
  * @param {object} e Event object.
1318
+ * @param {object} data Object containing all Imagifybeat IDs.
1319
  */
1320
+ addRequirementsImagifybeat: function ( e, data ) {
1321
+ data[ imagifyBulk.imagifybeatIDs.requirements ] = 1;
1322
  },
1323
 
1324
  /**
1325
+ * Listen for the custom event "imagifybeat-tick" on $(document).
1326
  * It allows to update requirements status periodically.
1327
  *
1328
  * @param {object} e Event object.
1329
+ * @param {object} data Object containing all Imagifybeat IDs.
1330
  */
1331
+ processRequirementsImagifybeat: function ( e, data ) {
1332
+ if ( typeof data[ imagifyBulk.imagifybeatIDs.requirements ] === 'undefined' ) {
1333
  return;
1334
  }
1335
 
1336
+ data = data[ imagifyBulk.imagifybeatIDs.requirements ];
1337
 
1338
  imagifyBulk.curlMissing = data.curl_missing;
1339
  imagifyBulk.editorMissing = data.editor_missing;
assets/js/bulk.min.js CHANGED
@@ -1 +1 @@
1
- window.imagify=window.imagify||{},function(a,b){var c=a.propHooks.checked;a.propHooks.checked={set:function(b,d,e){var f;return f=void 0===c?b[e]=d:c(b,d,e),a(b).trigger("change.imagify"),f}},a.fn.imagifyHide=function(b,c){return b&&b>0?this.hide(b,function(){a(this).addClass("hidden").css("display",""),void 0!==c&&c()}):(this.addClass("hidden"),void 0!==c&&c()),this.attr("aria-hidden","true")},a.fn.imagifyShow=function(b,c){return void 0!==c&&c(),b&&b>0?this.show(b,function(){a(this).removeClass("hidden").css("display","")}):this.removeClass("hidden"),this.attr("aria-hidden","false")}}(jQuery),function(a,b,c,d){c.imagify.bulk={charts:{overview:{canvas:!1,donut:!1,data:{labels:[imagifyBulk.labels.overviewChartLabels.unoptimized,imagifyBulk.labels.overviewChartLabels.optimized,imagifyBulk.labels.overviewChartLabels.error],datasets:[{data:[],backgroundColor:["#10121A","#46B1CE","#C51162"],borderWidth:0}]}},files:{donuts:{}},share:{canvas:!1,donut:!1}},folderTypesQueue:[],status:{},displayedWaitMessage:!1,hasMultipleRows:!0,imagifyAction:"",processIsStopped:!1,processingMedia:[],globalGain:0,globalOriginalSize:0,globalOptimizedSize:0,folderTypesData:{},defaultThumb:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAhBAMAAAClyt9cAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABtQTFRFR3BMjo6Oh4eHqqqq4uLigoKC+fn5fn5+fHx8SBBv5wAAAAF0Uk5TAEDm2GYAAABWSURBVCjPY2BgEBIEAyERBhgQUoKAIAc0EXXjEDQRRTNzBzRdBokhaGoM2CQc0NQwJJegqWFgM3VAUSNsbGwugCKiqBQUpIAiAgICoyIDKyIIB0JAEQA54jRBweNV0AAAAABJRU5ErkJggg==",init:function(){var d=a(b);this.drawOverviewChart(),this.hasMultipleRows=a('.imagify-bulk-table [name="group[]"]').length>1,a(".imagify-selector-button").on("click.imagify",this.openSelectorFromButton),a(".imagify-selector-list input").on("change.imagify init.imagify",this.syncSelectorFromRadio).filter(":checked").trigger("init.imagify"),d.on("keypress.imagify click.imagify",this.closeSelectors),a('.imagify-bulk-table [name="group[]"]').on("change.imagify init.imagify",this.toggleOptimizationButton).trigger("init.imagify"),a(".imagify-show-table-details").on("click.imagify open.imagify close.imagify",this.toggleOptimizationDetails),a("#imagify-bulk-action").on("click.imagify",this.maybeLaunchAllProcesses),a(".imagify-share-networks a").on("click.imagify",this.share),a(c).on("processQueue.imagify",this.processQueue).on("optimizeFiles.imagify",this.optimizeFiles).on("queueEmpty.imagify",this.queueEmpty),imagifyBulk.ajaxActions.getStats&&a('.imagify-bulk-table [data-group-id="library"][data-context="wp"]').length&&(imagifyBulk.heartbeatIDs.stats=!1),imagifyBulk.heartbeatIDs.stats&&d.on("heartbeat-send",this.addStatsHeartbeat).on("heartbeat-tick",this.processStatsHeartbeat),d.on("heartbeat-send",this.addQueueHeartbeat).on("heartbeat-tick",this.processQueueHeartbeat),d.on("heartbeat-send",this.addRequirementsHeartbeat).on("heartbeat-tick",this.processRequirementsHeartbeat)},getAjaxUrl:function(a,b){var d=ajaxurl+c.imagify.concat+"_wpnonce="+imagifyBulk.ajaxNonce+"&action="+imagifyBulk.ajaxActions[a];return b&&b.context&&(d+="&context="+b.context),"getMediaIds"!==a&&"bulkProcess"!==a||(d+="&imagify_action="+c.imagify.bulk.imagifyAction),d},getFolderTypes:function(){return a.isEmptyObject(c.imagify.bulk.folderTypesData)?(a(".imagify-row-folder-type").each(function(){var b=a(this),d={groupID:b.data("group-id"),context:b.data("context")},e=d.groupID+"|"+d.context;c.imagify.bulk.folderTypesData[e]=d}),c.imagify.bulk.folderTypesData):c.imagify.bulk.folderTypesData},getConfirmMessage:function(){return imagifyBulk.labels.processing},closeLevelSelector:function(a,b){if(a&&a.length)return void 0!==b&&b>0?void c.setTimeout(function(){c.imagify.bulk.closeLevelSelector(a)},b):void a.attr("aria-hidden","true")},stopProcess:function(b,d){this.processIsStopped=!0,c.imagify.bulk.status[d.groupID]={isError:!0,id:b},a(c).trigger("queueEmpty.imagify")},hasBlockingError:function(b){return b=void 0!==b&&b,imagifyBulk.curlMissing?(b&&c.imagify.bulk.displayError({html:imagifyBulk.labels.curlMissing}),!0):imagifyBulk.editorMissing?(b&&c.imagify.bulk.displayError({html:imagifyBulk.labels.editorMissing}),!0):imagifyBulk.extHttpBlocked?(b&&c.imagify.bulk.displayError({html:imagifyBulk.labels.extHttpBlocked}),!0):imagifyBulk.apiDown?(b&&c.imagify.bulk.displayError({html:imagifyBulk.labels.apiDown}),!0):imagifyBulk.keyIsValid?!!imagifyBulk.isOverQuota&&(b&&c.imagify.bulk.displayError({title:imagifyBulk.labels.overQuotaTitle,html:a("#tmpl-imagify-overquota-alert").html(),type:"info",customClass:"imagify-swal-has-subtitle imagify-swal-error-header",showConfirmButton:!1}),!0):(b&&c.imagify.bulk.displayError({title:imagifyBulk.labels.invalidAPIKeyTitle,type:"info"}),!0)},displayError:function(b,c,d){var e={title:"",html:"",type:"error",customClass:"",width:620,padding:0,showCloseButton:!0,showConfirmButton:!0};a.isPlainObject(b)?d=a.extend({},e,b):(d=d||{},d=a.extend({},e,{title:b||"",html:c||""},d)),d.title=d.title||imagifyBulk.labels.error,d.customClass+=" imagify-sweet-alert",swal(d).catch(swal.noop)},displayErrorInRow:function(b,c){var d,e;return b=a(b()),d=b.find(".imagify-cell-status ~ td"),e=d.length,c=c||"",d.remove(),b.find(".imagify-cell-status").after('<td colspan="'+e+'">'+c+"</td>"),b},displayFolderRow:function(a,b){var d,e,f,g;return"resting"===a?(b.next(".imagify-row-waiting, .imagify-row-working").remove(),void b.imagifyShow()):(d=b.next(".imagify-row-waiting, .imagify-row-working"),"waiting"===a?(f="#d2d3d6",g=imagifyBulk.labels.waitingOtimizationsText):(f="#40b1d0",g=imagifyBulk.labels.imagesOptimizedText.replace("%s","<span>0</span>")),d.length?(d.hasClass("imagify-row-"+a)||(d.attr("class","imagify-row-"+a),d.find(".imagify-cell-checkbox svg").attr("fill",f),d.children(".imagify-cell-count-optimized").html(g)),b.imagifyHide(),void d.imagifyShow()):(d=b.clone().attr({class:"imagify-row-"+a,"aria-hidden":"false"}),e=c.imagify.template("imagify-spinner"),d.children(".imagify-cell-checkbox").html(e()).find("svg").attr("fill",f),d.children(".imagify-cell-title").html('<span class="imagify-cell-label">'+d.children(".imagify-cell-title").text()+"</span>"),d.children(".imagify-cell-count-optimized").html(g),d.children(".imagify-cell-count-errors, .imagify-cell-optimized-size, .imagify-cell-original-size, .imagify-cell-level").text(""),void b.imagifyHide().after(d)))},displayShareBox:function(){var b,d,e,f,g=imagifyBulk.labels.textToShare;if(!this.globalGain||this.folderTypesQueue.length)return this.globalGain=0,this.globalOriginalSize=0,void(this.globalOptimizedSize=0);b=(100-this.globalOptimizedSize/this.globalOriginalSize*100).toFixed(2),d=c.imagify.humanSize(this.globalGain,1),e=c.imagify.humanSize(this.globalOriginalSize,1),g=g.replace("%1$s",d),g=g.replace("%2$s",e),g=encodeURIComponent(g),f=a(".imagify-row-complete"),f.find(".imagify-ac-rt-total-gain").html(d),f.find(".imagify-ac-rt-total-original").html(e),f.find(".imagify-ac-chart").attr("data-percent",b),f.find(".imagify-sn-twitter").attr("href",imagifyBulk.labels.twitterShareURL+"&amp;text="+g),this.drawShareChart(),f.addClass("done").imagifyShow(),a("html, body").animate({scrollTop:f.offset().top},200),this.globalGain=0,this.globalOriginalSize=0,this.globalOptimizedSize=0},updateStats:function(b){var d;b&&a.isPlainObject(b)&&(c.imagify.bulk.charts.overview.donut.data&&(d=c.imagify.bulk.charts.overview.donut.data.datasets[0].data,b.unoptimized_attachments===d[0]&&b.optimized_attachments===d[1]&&b.errors_attachments===d[2])||(b.unconsumed_quota=b.unconsumed_quota.toFixed(1),a(".imagify-meteo-icon").html(b.quota_icon),a(".imagify-unconsumed-percent").html(b.unconsumed_quota+"%"),a(".imagify-unconsumed-bar").css("width",b.unconsumed_quota+"%").parent().attr("class",b.quota_class),a("#imagify-overview-chart-percent").html(b.optimized_attachments_percent+"<span>%</span>"),a(".imagify-total-percent").html(b.optimized_attachments_percent+"%"),c.imagify.bulk.drawOverviewChart([b.unoptimized_attachments,b.optimized_attachments,b.errors_attachments]),a("#imagify-total-optimized-attachments").html(b.already_optimized_attachments),a("#imagify-original-bar").find(".imagify-barnb").html(b.original_human),a("#imagify-optimized-bar").css("width",100-b.optimized_percent+"%").find(".imagify-barnb").html(b.optimized_human),a("#imagify-total-optimized-attachments-pct").html(b.optimized_percent+"%")))},openSelectorFromButton:function(b){var c=a("#"+a(this).attr("aria-controls"));b.stopPropagation(),a(".imagify-selector-list").not(c).attr("aria-hidden","true"),c.attr("aria-hidden","false").find(":checked").trigger("focus.imagify")},syncSelectorFromRadio:function(){var b=a(this).closest(".imagify-selector-choice");b.addClass("imagify-selector-current-value").attr("aria-current","true").siblings(".imagify-selector-choice").removeClass("imagify-selector-current-value").attr("aria-current","false"),b.closest(".imagify-selector-list").siblings(".imagify-selector-button").find(".imagify-selector-current-value-info").html(b.find("label").html())},closeSelectors:function(b){"keypress"===b.type&&27!==b.keyCode&&13!==b.keyCode||c.imagify.bulk.closeLevelSelector(a('.imagify-selector-list[aria-hidden="false"]'))},toggleOptimizationButton:function(){if(!c.imagify.bulk.hasMultipleRows&&!this.checked)return void a(this).prop("checked",!0);a('.imagify-bulk-table [name="group[]"]:checked').length?a("#imagify-bulk-action").removeAttr("disabled"):a("#imagify-bulk-action").attr("disabled","disabled")},toggleOptimizationDetails:function(b){var c,d=a(this),e=d.closest(".imagify-bulk-table").find(".imagify-bulk-table-details");c="open"===b.type||"close"!==b.type&&e.hasClass("hidden"),c?(d.html(d.data("label-hide")+'<span class="dashicons dashicons-no-alt"></span>'),e.imagifyShow()):(d.html(d.data("label-show")+'<span class="dashicons dashicons-menu"></span>'),e.imagifyHide())},maybeLaunchAllProcesses:function(){var b;if(!a(this).attr("disabled")&&a('.imagify-bulk-table [name="group[]"]:checked').length&&!c.imagify.bulk.hasBlockingError(!0)){if(b=a("#tmpl-imagify-bulk-infos"),!b.length)return void c.imagify.bulk.launchAllProcesses();swal({title:imagifyBulk.labels.bulkInfoTitle,html:b.html(),type:"",customClass:"imagify-sweet-alert imagify-swal-has-subtitle imagify-before-bulk-infos",showCancelButton:!0,padding:0,width:554,confirmButtonText:imagifyBulk.labels.confirmBulk,cancelButtonText:imagifySwal.labels.cancelButtonText,reverseButtons:!0}).then(function(){var d=a('.imagify-bulk-table [name="group[]"]:checked').first().closest(".imagify-row-folder-type");a.get(c.imagify.bulk.getAjaxUrl("bulkInfoSeen",{context:d.data("context")})),b.remove(),c.imagify.bulk.launchAllProcesses()}).catch(swal.noop)}},launchAllProcesses:function(){var b=a(c),d=a("#imagify-bulk-action"),e=!0;d.attr("disabled","disabled").find(".dashicons").addClass("rotate"),b.on("beforeunload",this.getConfirmMessage),a(".imagify-row-complete").imagifyHide(200,function(){a(this).removeClass("done")}),a(".imagify-show-table-details").trigger("close.imagify"),this.folderTypesQueue=[],this.status={},this.displayedWaitMessage=!1,this.processIsStopped=!1,this.imagifyAction="optimize",this.globalGain=0,this.globalOriginalSize=0,this.globalOptimizedSize=0,a('.imagify-bulk-table [name="group[]"]:checked').each(function(){var b=a(this),d=b.closest(".imagify-row-folder-type"),f=d.data("group-id"),g=d.data("context"),h=d.find('.imagify-cell-level [name="level['+f+']"]:checked').val();if(c.imagify.bulk.folderTypesQueue.push({groupID:f,context:g,level:void 0===h?-1:parseInt(h,10)}),c.imagify.bulk.status[f]={isError:!1,id:"waiting"},e)return e=!1,!0;c.imagify.bulk.displayFolderRow("waiting",d)}),b.trigger("processQueue.imagify")},processQueue:function(){var b,d;if(!c.imagify.bulk.processIsStopped){if(!c.imagify.bulk.folderTypesQueue.length)return void a(c).trigger("queueEmpty.imagify");c.imagify.bulk.displayedWaitMessage||(swal({title:imagifyBulk.labels.waitTitle,html:imagifyBulk.labels.waitText,showConfirmButton:!1,padding:0,imageUrl:imagifyBulk.waitImageUrl,customClass:"imagify-sweet-alert"}).catch(swal.noop),c.imagify.bulk.displayedWaitMessage=!0),d=c.imagify.bulk.folderTypesQueue.shift(),b=a("#cb-select-"+d.groupID).closest(".imagify-row-folder-type"),c.imagify.bulk.status[d.groupID].id="fetching",c.imagify.bulk.displayFolderRow("working",b),a.get(c.imagify.bulk.getAjaxUrl("getMediaIds",d)).done(function(e){var f;if(swal.close(),!c.imagify.bulk.processIsStopped){if(f=e.data&&e.data.message?e.data.message:imagifyBulk.ajaxErrorText,!e.success)return void c.imagify.bulk.stopProcess(f,d);if(!e.data||!a.isPlainObject(e.data)&&!a.isArray(e.data))return void c.imagify.bulk.stopProcess(f,d);if(!a.isEmptyObject(e.data))return void a(c).trigger("optimizeFiles.imagify",[d,e.data]);if(c.imagify.bulk.status[d.groupID].id="no-images",c.imagify.bulk.hasMultipleRows&&a("#cb-select-"+d.groupID).prop("checked",!1),!c.imagify.bulk.folderTypesQueue.length)return void a(c).trigger("queueEmpty.imagify");c.imagify.bulk.displayFolderRow("resting",b),a(c).trigger("processQueue.imagify")}}).fail(function(){c.imagify.bulk.stopProcess("get-unoptimized-images",d)})}},optimizeFiles:function(b,d,e){var f,g,h,i,j,k,l,m,n,o,p,q={groupID:d.groupID,mediaID:0,thumbnail:"",filename:"",status:"",icon:"",label:"",thumbnailsCount:"",originalSizeHuman:"",newSizeHuman:"",percentHuman:"",overallSavingHuman:""};c.imagify.bulk.processIsStopped||(f=a("#cb-select-"+d.groupID).closest(".imagify-row-folder-type"),g=f.next(".imagify-row-working"),i=g.find(".imagify-cell-count-errors span"),o=parseInt(i.text(),10),j=f.closest(".imagify-bulk-table"),k=j.find(".imagify-row-progress"),l=k.find(".bar"),"optimize"===c.imagify.bulk.imagifyAction&&(h=g.find(".imagify-cell-count-optimized span"),n=parseInt(h.text(),10)),c.imagify.bulk.status[d.groupID].id="optimizing",j.find(".imagify-bulk-table-details thead").html(a("#tmpl-imagify-file-header-"+d.groupID).html()),m=j.find(".imagify-bulk-table-details tbody").text(""),l.css("width","0%").find(".percent").text("0%"),k.slideDown().attr("aria-hidden","false"),p=new c.imagify.Optimizer({groupID:d.groupID,context:d.context,level:d.level,bufferSize:imagifyBulk.bufferSizes[d.context],ajaxUrl:c.imagify.bulk.getAjaxUrl("bulkProcess",d),files:e,defaultThumb:c.imagify.bulk.defaultThumb,doneEvent:"mediaProcessed.imagify"}),p.before(function(b){var e;c.imagify.bulk.processIsStopped||(e=c.imagify.template("imagify-file-row-"+d.groupID),c.imagify.bulk.processingMedia.push({context:d.context,mediaID:b.mediaID}),m.prepend(e(a.extend({},q,b,{status:"compressing",icon:"admin-generic rotate",label:imagifyBulk.labels.optimizing}))))}),p.each(function(b){var e,f;if(!c.imagify.bulk.processIsStopped){if(e=c.imagify.template("imagify-file-row-"+d.groupID),f=a("#"+d.groupID+"-"+b.mediaID),a.each(c.imagify.bulk.processingMedia,function(a,e){return e.context!==d.context||e.mediaID!==b.mediaID||(c.imagify.bulk.processingMedia.splice(a,1),!1)}),l.css("width",b.progress+"%").find(".percent").html(b.progress+"%"),b.success)return"already-optimized"!==b.status?(f.replaceWith(e(a.extend({},q,b,{status:"complete",icon:"yes",label:imagifyBulk.labels.complete}))),c.imagify.bulk.drawFileChart(a("#"+d.groupID+"-"+b.mediaID).find(".imagify-cell-percentage canvas"))):f.replaceWith(c.imagify.bulk.displayErrorInRow(e(a.extend({},q,b,{status:"complete",icon:"yes",label:imagifyBulk.labels.alreadyOptimized})),b.error)),void("optimize"===c.imagify.bulk.imagifyAction&&(n+=1,h.text(n)));f.replaceWith(c.imagify.bulk.displayErrorInRow(e(a.extend({},q,b,{status:"error",icon:"dismiss",label:imagifyBulk.labels.error})),b.error||b)),i.length?(o+=1,i.text(o)):(o=1,i=g.find(".imagify-cell-count-errors").html(imagifyBulk.labels.imagesErrorText.replace("%s","<span>1</span>")).find("span")),"over-quota"===b.status&&(p.stopProcess(),c.imagify.bulk.stopProcess(b.status,d))}}),p.done(function(b){c.imagify.bulk.hasMultipleRows&&a("#cb-select-"+d.groupID).prop("checked",!1),b.globalOriginalSize&&(c.imagify.bulk.globalGain+=parseInt(b.globalGain,10),c.imagify.bulk.globalOriginalSize+=parseInt(b.globalOriginalSize,10),c.imagify.bulk.globalOptimizedSize+=parseInt(b.globalOptimizedSize,10)),c.imagify.bulk.processIsStopped||(a.isEmptyObject(c.imagify.bulk.status)||c.imagify.bulk.status[d.groupID].isError||(c.imagify.bulk.status[d.groupID].id="done"),f.addClass("updating"),a.get(c.imagify.bulk.getAjaxUrl("getFolderData",d)).done(function(b){c.imagify.bulk.processIsStopped||(b.success&&a.each(b.data,function(a,b){f.children(".imagify-cell-"+a).html(b)}),c.imagify.bulk.displayFolderRow("resting",f))}).always(function(){c.imagify.bulk.processIsStopped||(f.removeClass("updating"),c.imagify.bulk.folderTypesQueue.length?a(c).trigger("processQueue.imagify"):a(c).trigger("queueEmpty.imagify"))}))}),p.run())},queueEmpty:function(){var b=a(".imagify-bulk-table"),d={},e=!1,f=!0,g="";c.imagify.bulk.displayShareBox(),c.imagify.bulk.folderTypesQueue=[],imagifyBulk.heartbeatIDs.stats||a.get(c.imagify.bulk.getAjaxUrl("getStats"),{types:c.imagify.bulk.getFolderTypes()}).done(function(a){a.success&&c.imagify.bulk.updateStats(a.data)}),a.isEmptyObject(c.imagify.bulk.status)||(a.each(c.imagify.bulk.status,function(a,b){return b.isError?(e=b.id,f=!1,!1):"no-images"!==b.id?(f=!1,!1):void 0}),e?("invalid-api-key"===e?d={title:imagifyBulk.labels.invalidAPIKeyTitle,type:"info"}:"over-quota"===e?d={title:imagifyBulk.labels.overQuotaTitle,html:a("#tmpl-imagify-overquota-alert").html(),type:"info",customClass:"imagify-swal-has-subtitle imagify-swal-error-header",showConfirmButton:!1}:"get-unoptimized-images"!==e&&"consumed-all-data"!==e||(d={title:imagifyBulk.labels.getUnoptimizedImagesErrorTitle,html:imagifyBulk.labels.getUnoptimizedImagesErrorText,type:"info"}),c.imagify.bulk.displayError(d)):f&&(g=imagifyBulk.labels.nothingToDoText.hasOwnProperty(c.imagify.bulk.imagifyAction)?imagifyBulk.labels.nothingToDoText[c.imagify.bulk.imagifyAction]:imagifyBulk.labels.nothingToDoText.optimize,c.imagify.bulk.displayError({title:imagifyBulk.labels.nothingToDoTitle,html:g,type:"info"}))),c.imagify.bulk.status={},a(c).off("beforeunload",c.imagify.bulk.getConfirmMessage),c.imagify.bulk.displayFolderRow("resting",b.find(".imagify-row-folder-type").not(".updating")),b.find(".imagify-row-progress").slideUp().attr("aria-hidden","true").find(".bar").removeAttr("style").find(".percent").text("0%"),a('.imagify-bulk-table [name="group[]"]:checked').length?a("#imagify-bulk-action").removeAttr("disabled").find(".dashicons").removeClass("rotate"):a("#imagify-bulk-action").find(".dashicons").removeClass("rotate")},share:function(a){var d,e;a.preventDefault(),c.innerWidth?(d=(c.innerWidth-700)/2,e=(c.innerHeight-290)/2):(d=(b.body.clientWidth-700)/2,e=(b.body.clientHeight-290)/2),c.open(this.href,"","status=no, scrollbars=no, menubar=no, top="+e+", left="+d+", width=700, height=290")},addStatsHeartbeat:function(a,b){b[imagifyBulk.heartbeatIDs.stats]=Object.keys(c.imagify.bulk.getFolderTypes())},processStatsHeartbeat:function(a,b){void 0!==b[imagifyBulk.heartbeatIDs.stats]&&c.imagify.bulk.updateStats(b[imagifyBulk.heartbeatIDs.stats])},addQueueHeartbeat:function(a,b){c.imagify.bulk.processingMedia.length&&(b[imagifyBulk.heartbeatIDs.queue]=c.imagify.bulk.processingMedia)},processQueueHeartbeat:function(b,d){void 0!==d[imagifyBulk.heartbeatIDs.queue]&&a.each(d[imagifyBulk.heartbeatIDs.queue],function(b,d){a(c).trigger("mediaProcessed.imagify",[d])})},addRequirementsHeartbeat:function(a,b){b[imagifyBulk.heartbeatIDs.requirements]=1},processRequirementsHeartbeat:function(a,b){void 0!==b[imagifyBulk.heartbeatIDs.requirements]&&(b=b[imagifyBulk.heartbeatIDs.requirements],imagifyBulk.curlMissing=b.curl_missing,imagifyBulk.editorMissing=b.editor_missing,imagifyBulk.extHttpBlocked=b.external_http_blocked,imagifyBulk.apiDown=b.api_down,imagifyBulk.keyIsValid=b.key_is_valid,imagifyBulk.isOverQuota=b.is_over_quota)},drawOverviewChart:function(d){var e,f;if(this.charts.overview.canvas||(this.charts.overview.canvas=b.getElementById("imagify-overview-chart"),this.charts.overview.canvas)){if(d=d&&a.isArray(d)?d:[],this.charts.overview.donut)return void(d.length&&(0===d.reduce(function(a,b){return a+b},0)&&(d[0]=1),this.charts.overview.donut.data.datasets[0].data=d,this.charts.overview.donut.update()));this.charts.overview.data.datasets[0].data=[parseInt(this.charts.overview.canvas.getAttribute("data-unoptimized"),10),parseInt(this.charts.overview.canvas.getAttribute("data-optimized"),10),parseInt(this.charts.overview.canvas.getAttribute("data-errors"),10)],e=a.extend({},this.charts.overview.data),d.length&&(e.datasets[0].data=d),0===e.datasets[0].data.reduce(function(a,b){return a+b},0)&&(e.datasets[0].data[0]=1),this.charts.overview.donut=new c.imagify.Chart(this.charts.overview.canvas,{type:"doughnut",data:e,options:{legend:{display:!1},events:[],animation:{easing:"easeOutBounce"},tooltips:{displayColors:!1,callbacks:{label:function(a,b){return b.datasets[a.datasetIndex].data[a.index]}}},responsive:!1,cutoutPercentage:85}}),f='<ul class="imagify-doughnut-legend">',a.each(e.labels,function(a,b){f+='<li><span style="background-color:'+e.datasets[0].backgroundColor[a]+'"></span>'+b+"</li>"}),f+="</ul>",b.getElementById("imagify-overview-chart-legend").innerHTML=f}},drawFileChart:function(b){var d=this.charts.files.donuts;b.each(function(){var b=parseInt(a(this).closest(".imagify-chart").next(".imagipercent").text().replace("%",""),10);if(void 0!==d[this.id])return d[this.id].data.datasets[0].data[0]=b,d[this.id].data.datasets[0].data[1]=100-b,void d[this.id].update();d[this.id]=new c.imagify.Chart(this,{type:"doughnut",data:{datasets:[{data:[b,100-b],backgroundColor:["#00B3D3","#D8D8D8"],borderColor:"#fff",borderWidth:1}]},options:{legend:{display:!1},events:[],animation:{easing:"easeOutBounce"},tooltips:{enabled:!1},responsive:!1}})}),this.charts.files.donuts=d},drawShareChart:function(){var d;if(this.charts.share.canvas||(this.charts.share.canvas=b.getElementById("imagify-ac-chart"),this.charts.share.canvas)){if(d=parseInt(a(this.charts.share.canvas).closest(".imagify-ac-chart").attr("data-percent"),10),this.charts.share.donut)return this.charts.share.donut.data.datasets[0].data[0]=d,this.charts.share.donut.data.datasets[0].data[1]=100-d,void this.charts.share.donut.update();this.charts.share.donut=new c.imagify.Chart(this.charts.share.canvas,{type:"doughnut",data:{datasets:[{data:[d,100-d],backgroundColor:["#40B1D0","#FFFFFF"],borderWidth:0}]},options:{legend:{display:!1},events:[],animation:{easing:"easeOutBounce"},tooltips:{enabled:!1},responsive:!1,cutoutPercentage:70}})}}},c.imagify.bulk.init()}(jQuery,document,window);
1
+ window.imagify=window.imagify||{},function(a,b){var c=a.propHooks.checked;a.propHooks.checked={set:function(b,d,e){var f;return f=void 0===c?b[e]=d:c(b,d,e),a(b).trigger("change.imagify"),f}},a.fn.imagifyHide=function(b,c){return b&&b>0?this.hide(b,function(){a(this).addClass("hidden").css("display",""),void 0!==c&&c()}):(this.addClass("hidden"),void 0!==c&&c()),this.attr("aria-hidden","true")},a.fn.imagifyShow=function(b,c){return void 0!==c&&c(),b&&b>0?this.show(b,function(){a(this).removeClass("hidden").css("display","")}):this.removeClass("hidden"),this.attr("aria-hidden","false")}}(jQuery),function(a,b,c,d){c.imagify.bulk={charts:{overview:{canvas:!1,donut:!1,data:{labels:[imagifyBulk.labels.overviewChartLabels.unoptimized,imagifyBulk.labels.overviewChartLabels.optimized,imagifyBulk.labels.overviewChartLabels.error],datasets:[{data:[],backgroundColor:["#10121A","#46B1CE","#C51162"],borderWidth:0}]}},files:{donuts:{}},share:{canvas:!1,donut:!1}},folderTypesQueue:[],status:{},displayedWaitMessage:!1,hasMultipleRows:!0,imagifyAction:"",processIsStopped:!1,processingMedia:[],globalGain:0,globalOriginalSize:0,globalOptimizedSize:0,folderTypesData:{},defaultThumb:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAhBAMAAAClyt9cAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABtQTFRFR3BMjo6Oh4eHqqqq4uLigoKC+fn5fn5+fHx8SBBv5wAAAAF0Uk5TAEDm2GYAAABWSURBVCjPY2BgEBIEAyERBhgQUoKAIAc0EXXjEDQRRTNzBzRdBokhaGoM2CQc0NQwJJegqWFgM3VAUSNsbGwugCKiqBQUpIAiAgICoyIDKyIIB0JAEQA54jRBweNV0AAAAABJRU5ErkJggg==",init:function(){var d=a(b);this.drawOverviewChart(),this.hasMultipleRows=a('.imagify-bulk-table [name="group[]"]').length>1,a(".imagify-selector-button").on("click.imagify",this.openSelectorFromButton),a(".imagify-selector-list input").on("change.imagify init.imagify",this.syncSelectorFromRadio).filter(":checked").trigger("init.imagify"),d.on("keypress.imagify click.imagify",this.closeSelectors),a('.imagify-bulk-table [name="group[]"]').on("change.imagify init.imagify",this.toggleOptimizationButton).trigger("init.imagify"),a(".imagify-show-table-details").on("click.imagify open.imagify close.imagify",this.toggleOptimizationDetails),a("#imagify-bulk-action").on("click.imagify",this.maybeLaunchAllProcesses),a(".imagify-share-networks a").on("click.imagify",this.share),a(c).on("processQueue.imagify",this.processQueue).on("optimizeFiles.imagify",this.optimizeFiles).on("queueEmpty.imagify",this.queueEmpty),imagifyBulk.ajaxActions.getStats&&a('.imagify-bulk-table [data-group-id="library"][data-context="wp"]').length&&(imagifyBulk.imagifybeatIDs.stats=!1),imagifyBulk.imagifybeatIDs.stats&&d.on("imagifybeat-send",this.addStatsImagifybeat).on("imagifybeat-tick",this.processStatsImagifybeat),d.on("imagifybeat-send",this.addQueueImagifybeat).on("imagifybeat-tick",this.processQueueImagifybeat),d.on("imagifybeat-send",this.addRequirementsImagifybeat).on("imagifybeat-tick",this.processRequirementsImagifybeat)},getAjaxUrl:function(a,b){var d=ajaxurl+c.imagify.concat+"_wpnonce="+imagifyBulk.ajaxNonce+"&action="+imagifyBulk.ajaxActions[a];return b&&b.context&&(d+="&context="+b.context),"getMediaIds"!==a&&"bulkProcess"!==a||(d+="&imagify_action="+c.imagify.bulk.imagifyAction),d},getFolderTypes:function(){return a.isEmptyObject(c.imagify.bulk.folderTypesData)?(a(".imagify-row-folder-type").each(function(){var b=a(this),d={groupID:b.data("group-id"),context:b.data("context")},e=d.groupID+"|"+d.context;c.imagify.bulk.folderTypesData[e]=d}),c.imagify.bulk.folderTypesData):c.imagify.bulk.folderTypesData},getConfirmMessage:function(){return imagifyBulk.labels.processing},closeLevelSelector:function(a,b){if(a&&a.length)return void 0!==b&&b>0?void c.setTimeout(function(){c.imagify.bulk.closeLevelSelector(a)},b):void a.attr("aria-hidden","true")},stopProcess:function(b,d){this.processIsStopped=!0,c.imagify.bulk.status[d.groupID]={isError:!0,id:b},a(c).trigger("queueEmpty.imagify")},hasBlockingError:function(b){return b=void 0!==b&&b,imagifyBulk.curlMissing?(b&&c.imagify.bulk.displayError({html:imagifyBulk.labels.curlMissing}),!0):imagifyBulk.editorMissing?(b&&c.imagify.bulk.displayError({html:imagifyBulk.labels.editorMissing}),!0):imagifyBulk.extHttpBlocked?(b&&c.imagify.bulk.displayError({html:imagifyBulk.labels.extHttpBlocked}),!0):imagifyBulk.apiDown?(b&&c.imagify.bulk.displayError({html:imagifyBulk.labels.apiDown}),!0):imagifyBulk.keyIsValid?!!imagifyBulk.isOverQuota&&(b&&c.imagify.bulk.displayError({title:imagifyBulk.labels.overQuotaTitle,html:a("#tmpl-imagify-overquota-alert").html(),type:"info",customClass:"imagify-swal-has-subtitle imagify-swal-error-header",showConfirmButton:!1}),!0):(b&&c.imagify.bulk.displayError({title:imagifyBulk.labels.invalidAPIKeyTitle,type:"info"}),!0)},displayError:function(b,c,d){var e={title:"",html:"",type:"error",customClass:"",width:620,padding:0,showCloseButton:!0,showConfirmButton:!0};a.isPlainObject(b)?d=a.extend({},e,b):(d=d||{},d=a.extend({},e,{title:b||"",html:c||""},d)),d.title=d.title||imagifyBulk.labels.error,d.customClass+=" imagify-sweet-alert",swal(d).catch(swal.noop)},displayErrorInRow:function(b,c){var d,e;return b=a(b()),d=b.find(".imagify-cell-status ~ td"),e=d.length,c=c||"",d.remove(),b.find(".imagify-cell-status").after('<td colspan="'+e+'">'+c+"</td>"),b},displayFolderRow:function(a,b){var d,e,f,g;return"resting"===a?(b.next(".imagify-row-waiting, .imagify-row-working").remove(),void b.imagifyShow()):(d=b.next(".imagify-row-waiting, .imagify-row-working"),"waiting"===a?(f="#d2d3d6",g=imagifyBulk.labels.waitingOtimizationsText):(f="#40b1d0",g=imagifyBulk.labels.imagesOptimizedText.replace("%s","<span>0</span>")),d.length?(d.hasClass("imagify-row-"+a)||(d.attr("class","imagify-row-"+a),d.find(".imagify-cell-checkbox svg").attr("fill",f),d.children(".imagify-cell-count-optimized").html(g)),b.imagifyHide(),void d.imagifyShow()):(d=b.clone().attr({class:"imagify-row-"+a,"aria-hidden":"false"}),e=c.imagify.template("imagify-spinner"),d.children(".imagify-cell-checkbox").html(e()).find("svg").attr("fill",f),d.children(".imagify-cell-title").html('<span class="imagify-cell-label">'+d.children(".imagify-cell-title").text()+"</span>"),d.children(".imagify-cell-count-optimized").html(g),d.children(".imagify-cell-count-errors, .imagify-cell-optimized-size, .imagify-cell-original-size, .imagify-cell-level").text(""),void b.imagifyHide().after(d)))},displayShareBox:function(){var b,d,e,f,g=imagifyBulk.labels.textToShare;if(!this.globalGain||this.folderTypesQueue.length)return this.globalGain=0,this.globalOriginalSize=0,void(this.globalOptimizedSize=0);b=(100-this.globalOptimizedSize/this.globalOriginalSize*100).toFixed(2),d=c.imagify.humanSize(this.globalGain,1),e=c.imagify.humanSize(this.globalOriginalSize,1),g=g.replace("%1$s",d),g=g.replace("%2$s",e),g=encodeURIComponent(g),f=a(".imagify-row-complete"),f.find(".imagify-ac-rt-total-gain").html(d),f.find(".imagify-ac-rt-total-original").html(e),f.find(".imagify-ac-chart").attr("data-percent",b),f.find(".imagify-sn-twitter").attr("href",imagifyBulk.labels.twitterShareURL+"&amp;text="+g),this.drawShareChart(),f.addClass("done").imagifyShow(),a("html, body").animate({scrollTop:f.offset().top},200),this.globalGain=0,this.globalOriginalSize=0,this.globalOptimizedSize=0},updateStats:function(b){var d;b&&a.isPlainObject(b)&&(c.imagify.bulk.charts.overview.donut.data&&(d=c.imagify.bulk.charts.overview.donut.data.datasets[0].data,b.unoptimized_attachments===d[0]&&b.optimized_attachments===d[1]&&b.errors_attachments===d[2])||(b.unconsumed_quota=b.unconsumed_quota.toFixed(1),a(".imagify-meteo-icon").html(b.quota_icon),a(".imagify-unconsumed-percent").html(b.unconsumed_quota+"%"),a(".imagify-unconsumed-bar").css("width",b.unconsumed_quota+"%").parent().attr("class",b.quota_class),a("#imagify-overview-chart-percent").html(b.optimized_attachments_percent+"<span>%</span>"),a(".imagify-total-percent").html(b.optimized_attachments_percent+"%"),c.imagify.bulk.drawOverviewChart([b.unoptimized_attachments,b.optimized_attachments,b.errors_attachments]),a("#imagify-total-optimized-attachments").html(b.already_optimized_attachments),a("#imagify-original-bar").find(".imagify-barnb").html(b.original_human),a("#imagify-optimized-bar").css("width",100-b.optimized_percent+"%").find(".imagify-barnb").html(b.optimized_human),a("#imagify-total-optimized-attachments-pct").html(b.optimized_percent+"%")))},openSelectorFromButton:function(b){var c=a("#"+a(this).attr("aria-controls"));b.stopPropagation(),a(".imagify-selector-list").not(c).attr("aria-hidden","true"),c.attr("aria-hidden","false").find(":checked").trigger("focus.imagify")},syncSelectorFromRadio:function(){var b=a(this).closest(".imagify-selector-choice");b.addClass("imagify-selector-current-value").attr("aria-current","true").siblings(".imagify-selector-choice").removeClass("imagify-selector-current-value").attr("aria-current","false"),b.closest(".imagify-selector-list").siblings(".imagify-selector-button").find(".imagify-selector-current-value-info").html(b.find("label").html())},closeSelectors:function(b){"keypress"===b.type&&27!==b.keyCode&&13!==b.keyCode||c.imagify.bulk.closeLevelSelector(a('.imagify-selector-list[aria-hidden="false"]'))},toggleOptimizationButton:function(){if(!c.imagify.bulk.hasMultipleRows&&!this.checked)return void a(this).prop("checked",!0);a('.imagify-bulk-table [name="group[]"]:checked').length?a("#imagify-bulk-action").removeAttr("disabled"):a("#imagify-bulk-action").attr("disabled","disabled")},toggleOptimizationDetails:function(b){var c,d=a(this),e=d.closest(".imagify-bulk-table").find(".imagify-bulk-table-details");c="open"===b.type||"close"!==b.type&&e.hasClass("hidden"),c?(d.html(d.data("label-hide")+'<span class="dashicons dashicons-no-alt"></span>'),e.imagifyShow()):(d.html(d.data("label-show")+'<span class="dashicons dashicons-menu"></span>'),e.imagifyHide())},maybeLaunchAllProcesses:function(){var b;if(!a(this).attr("disabled")&&a('.imagify-bulk-table [name="group[]"]:checked').length&&!c.imagify.bulk.hasBlockingError(!0)){if(b=a("#tmpl-imagify-bulk-infos"),!b.length)return void c.imagify.bulk.launchAllProcesses();swal({title:imagifyBulk.labels.bulkInfoTitle,html:b.html(),type:"",customClass:"imagify-sweet-alert imagify-swal-has-subtitle imagify-before-bulk-infos",showCancelButton:!0,padding:0,width:554,confirmButtonText:imagifyBulk.labels.confirmBulk,cancelButtonText:imagifySwal.labels.cancelButtonText,reverseButtons:!0}).then(function(){var d=a('.imagify-bulk-table [name="group[]"]:checked').first().closest(".imagify-row-folder-type");a.get(c.imagify.bulk.getAjaxUrl("bulkInfoSeen",{context:d.data("context")})),b.remove(),c.imagify.bulk.launchAllProcesses()}).catch(swal.noop)}},launchAllProcesses:function(){var b=a(c),d=a("#imagify-bulk-action"),e=!0;d.attr("disabled","disabled").find(".dashicons").addClass("rotate"),b.on("beforeunload",this.getConfirmMessage),a(".imagify-row-complete").imagifyHide(200,function(){a(this).removeClass("done")}),a(".imagify-show-table-details").trigger("close.imagify"),this.folderTypesQueue=[],this.status={},this.displayedWaitMessage=!1,this.processIsStopped=!1,this.imagifyAction="optimize",this.globalGain=0,this.globalOriginalSize=0,this.globalOptimizedSize=0,a('.imagify-bulk-table [name="group[]"]:checked').each(function(){var b=a(this),d=b.closest(".imagify-row-folder-type"),f=d.data("group-id"),g=d.data("context"),h=d.find('.imagify-cell-level [name="level['+f+']"]:checked').val();if(c.imagify.bulk.folderTypesQueue.push({groupID:f,context:g,level:void 0===h?-1:parseInt(h,10)}),c.imagify.bulk.status[f]={isError:!1,id:"waiting"},e)return e=!1,!0;c.imagify.bulk.displayFolderRow("waiting",d)}),c.imagify.beat.interval(15),c.imagify.beat.disableSuspend(),b.trigger("processQueue.imagify")},processQueue:function(){var b,d;if(!c.imagify.bulk.processIsStopped){if(!c.imagify.bulk.folderTypesQueue.length)return void a(c).trigger("queueEmpty.imagify");c.imagify.bulk.displayedWaitMessage||(swal({title:imagifyBulk.labels.waitTitle,html:imagifyBulk.labels.waitText,showConfirmButton:!1,padding:0,imageUrl:imagifyBulk.waitImageUrl,customClass:"imagify-sweet-alert"}).catch(swal.noop),c.imagify.bulk.displayedWaitMessage=!0),d=c.imagify.bulk.folderTypesQueue.shift(),b=a("#cb-select-"+d.groupID).closest(".imagify-row-folder-type"),c.imagify.bulk.status[d.groupID].id="fetching",c.imagify.bulk.displayFolderRow("working",b),a.get(c.imagify.bulk.getAjaxUrl("getMediaIds",d)).done(function(e){var f;if(swal.close(),!c.imagify.bulk.processIsStopped){if(f=e.data&&e.data.message?e.data.message:imagifyBulk.ajaxErrorText,!e.success)return void c.imagify.bulk.stopProcess(f,d);if(!e.data||!a.isPlainObject(e.data)&&!a.isArray(e.data))return void c.imagify.bulk.stopProcess(f,d);if(!a.isEmptyObject(e.data))return void a(c).trigger("optimizeFiles.imagify",[d,e.data]);if(c.imagify.bulk.status[d.groupID].id="no-images",c.imagify.bulk.hasMultipleRows&&a("#cb-select-"+d.groupID).prop("checked",!1),!c.imagify.bulk.folderTypesQueue.length)return void a(c).trigger("queueEmpty.imagify");c.imagify.bulk.displayFolderRow("resting",b),a(c).trigger("processQueue.imagify")}}).fail(function(){c.imagify.bulk.stopProcess("get-unoptimized-images",d)})}},optimizeFiles:function(b,d,e){var f,g,h,i,j,k,l,m,n,o,p,q={groupID:d.groupID,mediaID:0,thumbnail:"",filename:"",status:"",icon:"",label:"",thumbnailsCount:"",originalSizeHuman:"",newSizeHuman:"",percentHuman:"",overallSavingHuman:""};c.imagify.bulk.processIsStopped||(f=a("#cb-select-"+d.groupID).closest(".imagify-row-folder-type"),g=f.next(".imagify-row-working"),i=g.find(".imagify-cell-count-errors span"),o=parseInt(i.text(),10),j=f.closest(".imagify-bulk-table"),k=j.find(".imagify-row-progress"),l=k.find(".bar"),"optimize"===c.imagify.bulk.imagifyAction&&(h=g.find(".imagify-cell-count-optimized span"),n=parseInt(h.text(),10)),c.imagify.bulk.status[d.groupID].id="optimizing",j.find(".imagify-bulk-table-details thead").html(a("#tmpl-imagify-file-header-"+d.groupID).html()),m=j.find(".imagify-bulk-table-details tbody").text(""),l.css("width","0%").find(".percent").text("0%"),k.slideDown().attr("aria-hidden","false"),p=new c.imagify.Optimizer({groupID:d.groupID,context:d.context,level:d.level,bufferSize:imagifyBulk.bufferSizes[d.context],ajaxUrl:c.imagify.bulk.getAjaxUrl("bulkProcess",d),files:e,defaultThumb:c.imagify.bulk.defaultThumb,doneEvent:"mediaProcessed.imagify"}),p.before(function(b){var e;c.imagify.bulk.processIsStopped||(e=c.imagify.template("imagify-file-row-"+d.groupID),c.imagify.bulk.processingMedia.push({context:d.context,mediaID:b.mediaID}),m.prepend(e(a.extend({},q,b,{status:"compressing",icon:"admin-generic rotate",label:imagifyBulk.labels.optimizing}))))}),p.each(function(b){var e,f;if(!c.imagify.bulk.processIsStopped){if(e=c.imagify.template("imagify-file-row-"+d.groupID),f=a("#"+d.groupID+"-"+b.mediaID),a.each(c.imagify.bulk.processingMedia,function(a,e){return e.context!==d.context||e.mediaID!==b.mediaID||(c.imagify.bulk.processingMedia.splice(a,1),!1)}),l.css("width",b.progress+"%").find(".percent").html(b.progress+"%"),b.success)return"already-optimized"!==b.status?(f.replaceWith(e(a.extend({},q,b,{status:"complete",icon:"yes",label:imagifyBulk.labels.complete}))),c.imagify.bulk.drawFileChart(a("#"+d.groupID+"-"+b.mediaID).find(".imagify-cell-percentage canvas"))):f.replaceWith(c.imagify.bulk.displayErrorInRow(e(a.extend({},q,b,{status:"complete",icon:"yes",label:imagifyBulk.labels.alreadyOptimized})),b.error)),void("optimize"===c.imagify.bulk.imagifyAction&&(n+=1,h.text(n)));f.replaceWith(c.imagify.bulk.displayErrorInRow(e(a.extend({},q,b,{status:"error",icon:"dismiss",label:imagifyBulk.labels.error})),b.error||b)),i.length?(o+=1,i.text(o)):(o=1,i=g.find(".imagify-cell-count-errors").html(imagifyBulk.labels.imagesErrorText.replace("%s","<span>1</span>")).find("span")),"over-quota"===b.status&&(p.stopProcess(),c.imagify.bulk.stopProcess(b.status,d))}}),p.done(function(b){c.imagify.bulk.hasMultipleRows&&a("#cb-select-"+d.groupID).prop("checked",!1),b.globalOriginalSize&&(c.imagify.bulk.globalGain+=parseInt(b.globalGain,10),c.imagify.bulk.globalOriginalSize+=parseInt(b.globalOriginalSize,10),c.imagify.bulk.globalOptimizedSize+=parseInt(b.globalOptimizedSize,10)),c.imagify.bulk.processIsStopped||(c.imagify.beat.resetInterval(),c.imagify.beat.enableSuspend(),a.isEmptyObject(c.imagify.bulk.status)||c.imagify.bulk.status[d.groupID].isError||(c.imagify.bulk.status[d.groupID].id="done"),f.addClass("updating"),a.get(c.imagify.bulk.getAjaxUrl("getFolderData",d)).done(function(b){c.imagify.bulk.processIsStopped||(b.success&&a.each(b.data,function(a,b){f.children(".imagify-cell-"+a).html(b)}),c.imagify.bulk.displayFolderRow("resting",f))}).always(function(){c.imagify.bulk.processIsStopped||(f.removeClass("updating"),c.imagify.bulk.folderTypesQueue.length?a(c).trigger("processQueue.imagify"):a(c).trigger("queueEmpty.imagify"))}))}),p.run())},queueEmpty:function(){var b=a(".imagify-bulk-table"),d={},e=!1,f=!0,g="";c.imagify.beat.resetInterval(),c.imagify.beat.enableSuspend(),c.imagify.bulk.displayShareBox(),c.imagify.bulk.folderTypesQueue=[],imagifyBulk.imagifybeatIDs.stats||a.get(c.imagify.bulk.getAjaxUrl("getStats"),{types:c.imagify.bulk.getFolderTypes()}).done(function(a){a.success&&c.imagify.bulk.updateStats(a.data)}),a.isEmptyObject(c.imagify.bulk.status)||(a.each(c.imagify.bulk.status,function(a,b){return b.isError?(e=b.id,f=!1,!1):"no-images"!==b.id?(f=!1,!1):void 0}),e?("invalid-api-key"===e?d={title:imagifyBulk.labels.invalidAPIKeyTitle,type:"info"}:"over-quota"===e?d={title:imagifyBulk.labels.overQuotaTitle,html:a("#tmpl-imagify-overquota-alert").html(),type:"info",customClass:"imagify-swal-has-subtitle imagify-swal-error-header",showConfirmButton:!1}:"get-unoptimized-images"!==e&&"consumed-all-data"!==e||(d={title:imagifyBulk.labels.getUnoptimizedImagesErrorTitle,html:imagifyBulk.labels.getUnoptimizedImagesErrorText,type:"info"}),c.imagify.bulk.displayError(d)):f&&(g=imagifyBulk.labels.nothingToDoText.hasOwnProperty(c.imagify.bulk.imagifyAction)?imagifyBulk.labels.nothingToDoText[c.imagify.bulk.imagifyAction]:imagifyBulk.labels.nothingToDoText.optimize,c.imagify.bulk.displayError({title:imagifyBulk.labels.nothingToDoTitle,html:g,type:"info"}))),c.imagify.bulk.status={},a(c).off("beforeunload",c.imagify.bulk.getConfirmMessage),c.imagify.bulk.displayFolderRow("resting",b.find(".imagify-row-folder-type").not(".updating")),b.find(".imagify-row-progress").slideUp().attr("aria-hidden","true").find(".bar").removeAttr("style").find(".percent").text("0%"),a('.imagify-bulk-table [name="group[]"]:checked').length?a("#imagify-bulk-action").removeAttr("disabled").find(".dashicons").removeClass("rotate"):a("#imagify-bulk-action").find(".dashicons").removeClass("rotate")},share:function(a){var d,e;a.preventDefault(),c.innerWidth?(d=(c.innerWidth-700)/2,e=(c.innerHeight-290)/2):(d=(b.body.clientWidth-700)/2,e=(b.body.clientHeight-290)/2),c.open(this.href,"","status=no, scrollbars=no, menubar=no, top="+e+", left="+d+", width=700, height=290")},addStatsImagifybeat:function(a,b){b[imagifyBulk.imagifybeatIDs.stats]=Object.keys(c.imagify.bulk.getFolderTypes())},processStatsImagifybeat:function(a,b){void 0!==b[imagifyBulk.imagifybeatIDs.stats]&&c.imagify.bulk.updateStats(b[imagifyBulk.imagifybeatIDs.stats])},addQueueImagifybeat:function(a,b){c.imagify.bulk.processingMedia.length&&(b[imagifyBulk.imagifybeatIDs.queue]=c.imagify.bulk.processingMedia)},processQueueImagifybeat:function(b,d){void 0!==d[imagifyBulk.imagifybeatIDs.queue]&&a.each(d[imagifyBulk.imagifybeatIDs.queue],function(b,d){a(c).trigger("mediaProcessed.imagify",[d])})},addRequirementsImagifybeat:function(a,b){b[imagifyBulk.imagifybeatIDs.requirements]=1},processRequirementsImagifybeat:function(a,b){void 0!==b[imagifyBulk.imagifybeatIDs.requirements]&&(b=b[imagifyBulk.imagifybeatIDs.requirements],imagifyBulk.curlMissing=b.curl_missing,imagifyBulk.editorMissing=b.editor_missing,imagifyBulk.extHttpBlocked=b.external_http_blocked,imagifyBulk.apiDown=b.api_down,imagifyBulk.keyIsValid=b.key_is_valid,imagifyBulk.isOverQuota=b.is_over_quota)},drawOverviewChart:function(d){var e,f;if(this.charts.overview.canvas||(this.charts.overview.canvas=b.getElementById("imagify-overview-chart"),this.charts.overview.canvas)){if(d=d&&a.isArray(d)?d:[],this.charts.overview.donut)return void(d.length&&(0===d.reduce(function(a,b){return a+b},0)&&(d[0]=1),this.charts.overview.donut.data.datasets[0].data=d,this.charts.overview.donut.update()));this.charts.overview.data.datasets[0].data=[parseInt(this.charts.overview.canvas.getAttribute("data-unoptimized"),10),parseInt(this.charts.overview.canvas.getAttribute("data-optimized"),10),parseInt(this.charts.overview.canvas.getAttribute("data-errors"),10)],e=a.extend({},this.charts.overview.data),d.length&&(e.datasets[0].data=d),0===e.datasets[0].data.reduce(function(a,b){return a+b},0)&&(e.datasets[0].data[0]=1),this.charts.overview.donut=new c.imagify.Chart(this.charts.overview.canvas,{type:"doughnut",data:e,options:{legend:{display:!1},events:[],animation:{easing:"easeOutBounce"},tooltips:{displayColors:!1,callbacks:{label:function(a,b){return b.datasets[a.datasetIndex].data[a.index]}}},responsive:!1,cutoutPercentage:85}}),f='<ul class="imagify-doughnut-legend">',a.each(e.labels,function(a,b){f+='<li><span style="background-color:'+e.datasets[0].backgroundColor[a]+'"></span>'+b+"</li>"}),f+="</ul>",b.getElementById("imagify-overview-chart-legend").innerHTML=f}},drawFileChart:function(b){var d=this.charts.files.donuts;b.each(function(){var b=parseInt(a(this).closest(".imagify-chart").next(".imagipercent").text().replace("%",""),10);if(void 0!==d[this.id])return d[this.id].data.datasets[0].data[0]=b,d[this.id].data.datasets[0].data[1]=100-b,void d[this.id].update();d[this.id]=new c.imagify.Chart(this,{type:"doughnut",data:{datasets:[{data:[b,100-b],backgroundColor:["#00B3D3","#D8D8D8"],borderColor:"#fff",borderWidth:1}]},options:{legend:{display:!1},events:[],animation:{easing:"easeOutBounce"},tooltips:{enabled:!1},responsive:!1}})}),this.charts.files.donuts=d},drawShareChart:function(){var d;if(this.charts.share.canvas||(this.charts.share.canvas=b.getElementById("imagify-ac-chart"),this.charts.share.canvas)){if(d=parseInt(a(this.charts.share.canvas).closest(".imagify-ac-chart").attr("data-percent"),10),this.charts.share.donut)return this.charts.share.donut.data.datasets[0].data[0]=d,this.charts.share.donut.data.datasets[0].data[1]=100-d,void this.charts.share.donut.update();this.charts.share.donut=new c.imagify.Chart(this.charts.share.canvas,{type:"doughnut",data:{datasets:[{data:[d,100-d],backgroundColor:["#40B1D0","#FFFFFF"],borderWidth:0}]},options:{legend:{display:!1},events:[],animation:{easing:"easeOutBounce"},tooltips:{enabled:!1},responsive:!1,cutoutPercentage:70}})}}},c.imagify.bulk.init()}(jQuery,document,window);
assets/js/files-list.js CHANGED
@@ -51,10 +51,6 @@ window.imagify.drawMeAChart = function( canvas ) {
51
  // Update the chart in the media modal when a media is selected, and the ones already printed.
52
  $( w ).on( 'canvasprinted.imagify', this.updateChart ).trigger( 'canvasprinted.imagify' );
53
 
54
- if ( ! this.hasHeartbeat() ) {
55
- return;
56
- }
57
-
58
  // Handle bulk actions.
59
  this.insertBulkActionTags();
60
 
@@ -63,21 +59,23 @@ window.imagify.drawMeAChart = function( canvas ) {
63
  // Optimize, restore, etc.
64
  $document.on( 'click.imagify', '.button-imagify-optimize, .button-imagify-manual-reoptimize, .button-imagify-generate-webp, .button-imagify-restore, .button-imagify-refresh-status', this.processOptimization );
65
 
66
- $document.on( 'heartbeat-send', this.addToHeartbeat );
67
- $document.on( 'heartbeat-tick', this.processHeartbeat );
68
 
69
  // Some items may be processed in background on page load.
70
  $processing = $( '.wp-list-table.imagify-files .button-imagify-processing' );
71
 
72
  if ( $processing.length ) {
73
- // Fasten Heartbeat for a minute.
74
- w.wp.heartbeat.interval( 5, 12 );
75
-
76
  $processing.closest( 'tr' ).find( '.check-column [name="bulk_select[]"]' ).each( function() {
77
  var id = w.imagify.filesList.sanitizeId( this.value );
78
 
79
  w.imagify.filesList.lockItem( w.imagifyFiles.context, id );
80
  } );
 
 
 
81
  }
82
  },
83
 
@@ -190,61 +188,52 @@ window.imagify.drawMeAChart = function( canvas ) {
190
  // The work is done.
191
  w.imagify.filesList.displayProcessResult( context, id, r.data.columns );
192
  } else {
193
- // Still processing in background: we're waiting for the result by poking Heartbeat.
194
- // Set the heartbeat interval to 5 sec for 60 seconds (12 ticks).
195
- w.wp.heartbeat.interval( 5, 12 );
196
  }
197
  } );
198
  },
199
 
200
- // Heartbeat ===============================================================================
201
 
202
  /**
203
- * Tell if we can use Heartbeat.
204
- *
205
- * @return {bool}
206
- */
207
- hasHeartbeat: function() {
208
- return w.imagifyFiles && w.imagifyFiles.heartbeatId && w.wp && w.wp.heartbeat ? true : false;
209
- },
210
-
211
- /**
212
- * Send the media IDs and their status to heartbeat.
213
  *
214
  * @param {object} e Event object.
215
- * @param {object} data Object containing all Heartbeat IDs.
216
  */
217
- addToHeartbeat: function ( e, data ) {
218
  var $boxes = $( '.wp-list-table.imagify-files .check-column [name="bulk_select[]"]' );
219
 
220
  if ( ! $boxes.length ) {
221
  return;
222
  }
223
 
224
- data[ w.imagifyFiles.heartbeatId ] = {};
225
 
226
  $boxes.each( function() {
227
  var id = w.imagify.filesList.sanitizeId( this.value ),
228
  context = w.imagifyFiles.context,
229
  locked = w.imagify.filesList.isItemLocked( context, id ) ? 1 : 0;
230
 
231
- data[ w.imagifyFiles.heartbeatId ][ context ] = data[ w.imagifyFiles.heartbeatId ][ context ] || {};
232
- data[ w.imagifyFiles.heartbeatId ][ context ][ '_' + id ] = locked;
233
  } );
234
  },
235
 
236
  /**
237
- * Listen for the custom event "heartbeat-tick" on $(document).
238
  *
239
  * @param {object} e Event object.
240
- * @param {object} data Object containing all Heartbeat IDs.
241
  */
242
- processHeartbeat: function ( e, data ) {
243
- if ( typeof data[ w.imagifyFiles.heartbeatId ] === 'undefined' ) {
244
  return;
245
  }
246
 
247
- $.each( data[ w.imagifyFiles.heartbeatId ], function( contextId, columns ) {
248
  var context, id;
249
 
250
  context = $.trim( contextId ).match( /^(.+)_(\d+)$/ );
@@ -283,6 +272,12 @@ window.imagify.drawMeAChart = function( canvas ) {
283
  $row.find( '.check-column [type="checkbox"]' ).prop( 'checked', false );
284
 
285
  w.imagify.filesList.unlockItem( context, id );
 
 
 
 
 
 
286
  },
287
 
288
  /**
51
  // Update the chart in the media modal when a media is selected, and the ones already printed.
52
  $( w ).on( 'canvasprinted.imagify', this.updateChart ).trigger( 'canvasprinted.imagify' );
53
 
 
 
 
 
54
  // Handle bulk actions.
55
  this.insertBulkActionTags();
56
 
59
  // Optimize, restore, etc.
60
  $document.on( 'click.imagify', '.button-imagify-optimize, .button-imagify-manual-reoptimize, .button-imagify-generate-webp, .button-imagify-restore, .button-imagify-refresh-status', this.processOptimization );
61
 
62
+ $document.on( 'imagifybeat-send', this.addToImagifybeat );
63
+ $document.on( 'imagifybeat-tick', this.processImagifybeat );
64
 
65
  // Some items may be processed in background on page load.
66
  $processing = $( '.wp-list-table.imagify-files .button-imagify-processing' );
67
 
68
  if ( $processing.length ) {
69
+ // Some media are already being processed.
70
+ // Lock the items, so we can check their status with Imagifybeat.
 
71
  $processing.closest( 'tr' ).find( '.check-column [name="bulk_select[]"]' ).each( function() {
72
  var id = w.imagify.filesList.sanitizeId( this.value );
73
 
74
  w.imagify.filesList.lockItem( w.imagifyFiles.context, id );
75
  } );
76
+
77
+ // Fasten Imagifybeat.
78
+ w.imagify.beat.interval( 15 );
79
  }
80
  },
81
 
188
  // The work is done.
189
  w.imagify.filesList.displayProcessResult( context, id, r.data.columns );
190
  } else {
191
+ // Still processing in background: we're waiting for the result by poking Imagifybeat.
192
+ // Set the Imagifybeat interval to 15 seconds.
193
+ w.imagify.beat.interval( 15 );
194
  }
195
  } );
196
  },
197
 
198
+ // Imagifybeat =============================================================================
199
 
200
  /**
201
+ * Send the media IDs and their status to Imagifybeat.
 
 
 
 
 
 
 
 
 
202
  *
203
  * @param {object} e Event object.
204
+ * @param {object} data Object containing all Imagifybeat IDs.
205
  */
206
+ addToImagifybeat: function ( e, data ) {
207
  var $boxes = $( '.wp-list-table.imagify-files .check-column [name="bulk_select[]"]' );
208
 
209
  if ( ! $boxes.length ) {
210
  return;
211
  }
212
 
213
+ data[ w.imagifyFiles.imagifybeatID ] = {};
214
 
215
  $boxes.each( function() {
216
  var id = w.imagify.filesList.sanitizeId( this.value ),
217
  context = w.imagifyFiles.context,
218
  locked = w.imagify.filesList.isItemLocked( context, id ) ? 1 : 0;
219
 
220
+ data[ w.imagifyFiles.imagifybeatID ][ context ] = data[ w.imagifyFiles.imagifybeatID ][ context ] || {};
221
+ data[ w.imagifyFiles.imagifybeatID ][ context ][ '_' + id ] = locked;
222
  } );
223
  },
224
 
225
  /**
226
+ * Listen for the custom event "imagifybeat-tick" on $(document).
227
  *
228
  * @param {object} e Event object.
229
+ * @param {object} data Object containing all Imagifybeat IDs.
230
  */
231
+ processImagifybeat: function ( e, data ) {
232
+ if ( typeof data[ w.imagifyFiles.imagifybeatID ] === 'undefined' ) {
233
  return;
234
  }
235
 
236
+ $.each( data[ w.imagifyFiles.imagifybeatID ], function( contextId, columns ) {
237
  var context, id;
238
 
239
  context = $.trim( contextId ).match( /^(.+)_(\d+)$/ );
272
  $row.find( '.check-column [type="checkbox"]' ).prop( 'checked', false );
273
 
274
  w.imagify.filesList.unlockItem( context, id );
275
+
276
+ if ( ! w.imagify.filesList.working.length ) {
277
+ // Work is done.
278
+ // Reset Imagifybeat interval.
279
+ w.imagify.beat.resetInterval();
280
+ }
281
  },
282
 
283
  /**
assets/js/files-list.min.js CHANGED
@@ -1 +1 @@
1
- window.imagify.drawMeAChart=function(a){a.each(function(){var a=parseInt(jQuery(this).closest(".imagify-chart").next(".imagify-chart-value").text(),10);new window.imagify.Chart(this,{type:"doughnut",data:{datasets:[{data:[a,100-a],backgroundColor:["#00B3D3","#D8D8D8"],borderColor:"#fff",borderWidth:1}]},options:{legend:{display:!1},events:[],animation:{easing:"easeOutBounce"},tooltips:{enabled:!1},responsive:!1}})})},function(a,b,c,d){c.imagify.filesList={working:[],init:function(){var d,e=a(b);a(c).on("canvasprinted.imagify",this.updateChart).trigger("canvasprinted.imagify"),this.hasHeartbeat()&&(this.insertBulkActionTags(),a("#doaction, #doaction2").on("click.imagify",this.processBulkAction),e.on("click.imagify",".button-imagify-optimize, .button-imagify-manual-reoptimize, .button-imagify-generate-webp, .button-imagify-restore, .button-imagify-refresh-status",this.processOptimization),e.on("heartbeat-send",this.addToHeartbeat),e.on("heartbeat-tick",this.processHeartbeat),d=a(".wp-list-table.imagify-files .button-imagify-processing"),d.length&&(c.wp.heartbeat.interval(5,12),d.closest("tr").find('.check-column [name="bulk_select[]"]').each(function(){var a=c.imagify.filesList.sanitizeId(this.value);c.imagify.filesList.lockItem(c.imagifyFiles.context,a)})))},updateChart:function(b,d){var e;d=d||".imagify-consumption-chart",e=a(d),c.imagify.drawMeAChart(e),e.closest(".imagify-datas-list").siblings(".imagify-datas-details").hide()},insertBulkActionTags:function(){var b='<option value="imagify-bulk-optimize">'+c.imagifyFiles.labels.bulkActionsOptimize+"</option>";(c.imagifyFiles.backupOption||a(".file-has-backup").length)&&(b+='<option value="imagify-bulk-restore">'+c.imagifyFiles.labels.bulkActionsRestore+"</option>"),a('.bulkactions select[name="action"] option:first-child, .bulkactions select[name="action2"] option:first-child').after(b)},processBulkAction:function(b){var c,d=a(this).prev("select").val();"imagify-bulk-optimize"!==d&&"imagify-bulk-restore"!==d&&"imagify-bulk-refresh-status"!==d||(b.preventDefault(),c=d.replace("imagify-bulk-",""),a('input[name="bulk_select[]"]:checked').closest("tr").find(".button-imagify-"+c).each(function(b,c){setTimeout(function(){a(c).trigger("click.imagify")},500*b)}))},processOptimization:function(b){var d,e,f,g=a(this),h=g.closest("tr"),i=h.find('.check-column [type="checkbox"]'),j=imagify.filesList.sanitizeId(i.val()),k=c.imagifyFiles.context;b.preventDefault(),imagify.filesList.isItemLocked(k,j)||(imagify.filesList.lockItem(k,j),e=g.attr("href"),f=c.imagify.template("imagify-button-processing"),d=g.closest(".column-actions, .column-status"),d.html(f({label:g.data("processing-label")})),a.get(e.replace("admin-post.php","admin-ajax.php")).done(function(a){if(!a.success)return a.data&&a.data.row?h.html('<td class="colspanchange" colspan="'+h.children().length+'">'+a.data.row+"</td>"):d.html(a.data),h.find('.check-column [type="checkbox"]').prop("checked",!1),void imagify.filesList.unlockItem(k,j);a.data&&a.data.columns?c.imagify.filesList.displayProcessResult(k,j,a.data.columns):c.wp.heartbeat.interval(5,12)}))},hasHeartbeat:function(){return!!(c.imagifyFiles&&c.imagifyFiles.heartbeatId&&c.wp&&c.wp.heartbeat)},addToHeartbeat:function(b,d){var e=a('.wp-list-table.imagify-files .check-column [name="bulk_select[]"]');e.length&&(d[c.imagifyFiles.heartbeatId]={},e.each(function(){var a=c.imagify.filesList.sanitizeId(this.value),b=c.imagifyFiles.context,e=c.imagify.filesList.isItemLocked(b,a)?1:0;d[c.imagifyFiles.heartbeatId][b]=d[c.imagifyFiles.heartbeatId][b]||{},d[c.imagifyFiles.heartbeatId][b]["_"+a]=e}))},processHeartbeat:function(b,d){void 0!==d[c.imagifyFiles.heartbeatId]&&a.each(d[c.imagifyFiles.heartbeatId],function(b,d){var e,f;(e=a.trim(b).match(/^(.+)_(\d+)$/))&&(f=c.imagify.filesList.sanitizeId(e[2]),(e=c.imagify.filesList.sanitizeContext(e[1]))===c.imagifyFiles.context&&c.imagify.filesList.displayProcessResult(e,f,d))})},displayProcessResult:function(b,d,e){var f=c.imagify.filesList.getContainers(d);a.each(e,function(a,b){f.children(".column-"+a).html(b)}),f.find('.check-column [type="checkbox"]').prop("checked",!1),c.imagify.filesList.unlockItem(b,d)},getContainers:function(b){return a('.wp-list-table.imagify-files .check-column [name="bulk_select[]"][value="'+b+'"]').closest("tr")},sanitizeId:function(a){return parseInt(a,10)},sanitizeContext:function(a){return(a=a.replace("/[^a-z0-9_-]/gi","").toLowerCase())||"wp"},lockItem:function(a,b){this.isItemLocked(a,b)||this.working.push(a+"_"+b)},unlockItem:function(a,b){var c=a+"_"+b,d=_.indexOf(this.working,c);d>-1&&this.working.splice(d,1)},isItemLocked:function(a,b){return _.indexOf(this.working,a+"_"+b)>-1}},c.imagify.filesList.init()}(jQuery,document,window),function(a){for(var b=0,c=["ms","moz","webkit","o"],d=0;d<c.length&&!a.requestAnimationFrame;++d)a.requestAnimationFrame=a[c[d]+"RequestAnimationFrame"],a.cancelAnimationFrame=a[c[d]+"CancelAnimationFrame"]||a[c[d]+"CancelRequestAnimationFrame"];a.requestAnimationFrame||(a.requestAnimationFrame=function(a){var c=(new Date).getTime(),d=Math.max(0,16-(c-b)),e=setTimeout(function(){a(c+d)},d);return b=c+d,e}),a.cancelAnimationFrame||(a.cancelAnimationFrame=function(a){clearTimeout(a)})}(window),function(a,b,c,d){function e(){c.cancelAnimationFrame(g),g=c.requestAnimationFrame(f)}function f(){var b=a(c),f=b.scrollTop(),g=b.outerHeight();a.each(h,function(){var c,i=a(this),j=i.offset().top,k=j+i.outerHeight(),l=f-150,m=f+g+150;h=h.not(i),h.length||b.off("scroll resize orientationchange",e),k>=l&&j<=m&&(c=i.attr("data-lazy-src"),d!==c&&c&&i.attr("src",c).removeAttr("data-lazy-src"),i.next("noscript").remove())})}var g,h=a("#imagify-files-list-form").find("[data-lazy-src]");h.length&&(a(c).on("scroll resize orientationchange",e),f())}(jQuery,document,window);
1
+ window.imagify.drawMeAChart=function(a){a.each(function(){var a=parseInt(jQuery(this).closest(".imagify-chart").next(".imagify-chart-value").text(),10);new window.imagify.Chart(this,{type:"doughnut",data:{datasets:[{data:[a,100-a],backgroundColor:["#00B3D3","#D8D8D8"],borderColor:"#fff",borderWidth:1}]},options:{legend:{display:!1},events:[],animation:{easing:"easeOutBounce"},tooltips:{enabled:!1},responsive:!1}})})},function(a,b,c,d){c.imagify.filesList={working:[],init:function(){var d,e=a(b);a(c).on("canvasprinted.imagify",this.updateChart).trigger("canvasprinted.imagify"),this.insertBulkActionTags(),a("#doaction, #doaction2").on("click.imagify",this.processBulkAction),e.on("click.imagify",".button-imagify-optimize, .button-imagify-manual-reoptimize, .button-imagify-generate-webp, .button-imagify-restore, .button-imagify-refresh-status",this.processOptimization),e.on("imagifybeat-send",this.addToImagifybeat),e.on("imagifybeat-tick",this.processImagifybeat),d=a(".wp-list-table.imagify-files .button-imagify-processing"),d.length&&(d.closest("tr").find('.check-column [name="bulk_select[]"]').each(function(){var a=c.imagify.filesList.sanitizeId(this.value);c.imagify.filesList.lockItem(c.imagifyFiles.context,a)}),c.imagify.beat.interval(15))},updateChart:function(b,d){var e;d=d||".imagify-consumption-chart",e=a(d),c.imagify.drawMeAChart(e),e.closest(".imagify-datas-list").siblings(".imagify-datas-details").hide()},insertBulkActionTags:function(){var b='<option value="imagify-bulk-optimize">'+c.imagifyFiles.labels.bulkActionsOptimize+"</option>";(c.imagifyFiles.backupOption||a(".file-has-backup").length)&&(b+='<option value="imagify-bulk-restore">'+c.imagifyFiles.labels.bulkActionsRestore+"</option>"),a('.bulkactions select[name="action"] option:first-child, .bulkactions select[name="action2"] option:first-child').after(b)},processBulkAction:function(b){var c,d=a(this).prev("select").val();"imagify-bulk-optimize"!==d&&"imagify-bulk-restore"!==d&&"imagify-bulk-refresh-status"!==d||(b.preventDefault(),c=d.replace("imagify-bulk-",""),a('input[name="bulk_select[]"]:checked').closest("tr").find(".button-imagify-"+c).each(function(b,c){setTimeout(function(){a(c).trigger("click.imagify")},500*b)}))},processOptimization:function(b){var d,e,f,g=a(this),h=g.closest("tr"),i=h.find('.check-column [type="checkbox"]'),j=imagify.filesList.sanitizeId(i.val()),k=c.imagifyFiles.context;b.preventDefault(),imagify.filesList.isItemLocked(k,j)||(imagify.filesList.lockItem(k,j),e=g.attr("href"),f=c.imagify.template("imagify-button-processing"),d=g.closest(".column-actions, .column-status"),d.html(f({label:g.data("processing-label")})),a.get(e.replace("admin-post.php","admin-ajax.php")).done(function(a){if(!a.success)return a.data&&a.data.row?h.html('<td class="colspanchange" colspan="'+h.children().length+'">'+a.data.row+"</td>"):d.html(a.data),h.find('.check-column [type="checkbox"]').prop("checked",!1),void imagify.filesList.unlockItem(k,j);a.data&&a.data.columns?c.imagify.filesList.displayProcessResult(k,j,a.data.columns):c.imagify.beat.interval(15)}))},addToImagifybeat:function(b,d){var e=a('.wp-list-table.imagify-files .check-column [name="bulk_select[]"]');e.length&&(d[c.imagifyFiles.imagifybeatID]={},e.each(function(){var a=c.imagify.filesList.sanitizeId(this.value),b=c.imagifyFiles.context,e=c.imagify.filesList.isItemLocked(b,a)?1:0;d[c.imagifyFiles.imagifybeatID][b]=d[c.imagifyFiles.imagifybeatID][b]||{},d[c.imagifyFiles.imagifybeatID][b]["_"+a]=e}))},processImagifybeat:function(b,d){void 0!==d[c.imagifyFiles.imagifybeatID]&&a.each(d[c.imagifyFiles.imagifybeatID],function(b,d){var e,f;(e=a.trim(b).match(/^(.+)_(\d+)$/))&&(f=c.imagify.filesList.sanitizeId(e[2]),(e=c.imagify.filesList.sanitizeContext(e[1]))===c.imagifyFiles.context&&c.imagify.filesList.displayProcessResult(e,f,d))})},displayProcessResult:function(b,d,e){var f=c.imagify.filesList.getContainers(d);a.each(e,function(a,b){f.children(".column-"+a).html(b)}),f.find('.check-column [type="checkbox"]').prop("checked",!1),c.imagify.filesList.unlockItem(b,d),c.imagify.filesList.working.length||c.imagify.beat.resetInterval()},getContainers:function(b){return a('.wp-list-table.imagify-files .check-column [name="bulk_select[]"][value="'+b+'"]').closest("tr")},sanitizeId:function(a){return parseInt(a,10)},sanitizeContext:function(a){return(a=a.replace("/[^a-z0-9_-]/gi","").toLowerCase())||"wp"},lockItem:function(a,b){this.isItemLocked(a,b)||this.working.push(a+"_"+b)},unlockItem:function(a,b){var c=a+"_"+b,d=_.indexOf(this.working,c);d>-1&&this.working.splice(d,1)},isItemLocked:function(a,b){return _.indexOf(this.working,a+"_"+b)>-1}},c.imagify.filesList.init()}(jQuery,document,window),function(a){for(var b=0,c=["ms","moz","webkit","o"],d=0;d<c.length&&!a.requestAnimationFrame;++d)a.requestAnimationFrame=a[c[d]+"RequestAnimationFrame"],a.cancelAnimationFrame=a[c[d]+"CancelAnimationFrame"]||a[c[d]+"CancelRequestAnimationFrame"];a.requestAnimationFrame||(a.requestAnimationFrame=function(a){var c=(new Date).getTime(),d=Math.max(0,16-(c-b)),e=setTimeout(function(){a(c+d)},d);return b=c+d,e}),a.cancelAnimationFrame||(a.cancelAnimationFrame=function(a){clearTimeout(a)})}(window),function(a,b,c,d){function e(){c.cancelAnimationFrame(g),g=c.requestAnimationFrame(f)}function f(){var b=a(c),f=b.scrollTop(),g=b.outerHeight();a.each(h,function(){var c,i=a(this),j=i.offset().top,k=j+i.outerHeight(),l=f-150,m=f+g+150;h=h.not(i),h.length||b.off("scroll resize orientationchange",e),k>=l&&j<=m&&(c=i.attr("data-lazy-src"),d!==c&&c&&i.attr("src",c).removeAttr("data-lazy-src"),i.next("noscript").remove())})}var g,h=a("#imagify-files-list-form").find("[data-lazy-src]");h.length&&(a(c).on("scroll resize orientationchange",e),f())}(jQuery,document,window);
assets/js/media-modal.js CHANGED
@@ -55,23 +55,18 @@ window.imagify.drawMeAChart = function( canvas ) {
55
 
56
  $document.on( 'click', '.imagify-datas-more-action a', this.toggleSlide );
57
 
58
- if ( ! this.hasHeartbeat() ) {
59
- return;
60
- }
61
-
62
  // Optimize, restore, etc.
63
  $document.on( 'click', '.button-imagify-restore, .button-imagify-optimize, .button-imagify-manual-reoptimize, .button-imagify-optimize-missing-sizes, .button-imagify-generate-webp', this.processOptimization );
64
 
65
- $document.on( 'heartbeat-send', this.addToHeartbeat );
66
- $document.on( 'heartbeat-tick', this.processHeartbeat );
67
 
68
  // Some items may be processed in background on page load.
69
  $processing = $( '.imagify-data-actions-container .button-imagify-processing' );
70
 
71
  if ( $processing.length ) {
72
- // Fasten Heartbeat for a minute.
73
- w.wp.heartbeat.interval( 5, 12 );
74
-
75
  $processing.closest( '.imagify-data-actions-container' ).each( function() {
76
  var $this = $( this ),
77
  id = w.imagify.modal.sanitizeId( $this.data( 'id' ) ),
@@ -79,6 +74,9 @@ window.imagify.drawMeAChart = function( canvas ) {
79
 
80
  w.imagify.modal.lockItem( context, id );
81
  } );
 
 
 
82
  }
83
  },
84
 
@@ -136,38 +134,29 @@ window.imagify.drawMeAChart = function( canvas ) {
136
  // The work is done.
137
  w.imagify.modal.displayProcessResult( context, id, response.data.html );
138
  } else {
139
- // Still processing in background: we're waiting for the result by poking Heartbeat.
140
- // Set the heartbeat interval to 5 sec for 60 seconds (12 ticks).
141
- w.wp.heartbeat.interval( 5, 12 );
142
  }
143
  } );
144
  },
145
 
146
- // Heartbeat ===============================================================================
147
-
148
- /**
149
- * Tell if we can use Heartbeat.
150
- *
151
- * @return {bool}
152
- */
153
- hasHeartbeat: function() {
154
- return w.imagifyModal && w.imagifyModal.heartbeatId && w.wp && w.wp.heartbeat ? true : false;
155
- },
156
 
157
  /**
158
- * Send the media IDs and their status to heartbeat.
159
  *
160
  * @param {object} e Event object.
161
- * @param {object} data Object containing all Heartbeat IDs.
162
  */
163
- addToHeartbeat: function ( e, data ) {
164
  var $containers = $( '.imagify-data-actions-container' );
165
 
166
  if ( ! $containers.length ) {
167
  return;
168
  }
169
 
170
- data[ w.imagifyModal.heartbeatId ] = {};
171
 
172
  $containers.each( function() {
173
  var $this = $( this ),
@@ -175,23 +164,23 @@ window.imagify.drawMeAChart = function( canvas ) {
175
  context = w.imagify.modal.sanitizeContext( $this.data( 'context' ) ),
176
  locked = w.imagify.modal.isItemLocked( context, id ) ? 1 : 0;
177
 
178
- data[ w.imagifyModal.heartbeatId ][ context ] = data[ w.imagifyModal.heartbeatId ][ context ] || {};
179
- data[ w.imagifyModal.heartbeatId ][ context ][ '_' + id ] = locked;
180
  } );
181
  },
182
 
183
  /**
184
- * Listen for the custom event "heartbeat-tick" on $(document).
185
  *
186
  * @param {object} e Event object.
187
- * @param {object} data Object containing all Heartbeat IDs.
188
  */
189
- processHeartbeat: function ( e, data ) {
190
- if ( typeof data[ w.imagifyModal.heartbeatId ] === 'undefined' ) {
191
  return;
192
  }
193
 
194
- $.each( data[ w.imagifyModal.heartbeatId ], function( contextId, htmlContent ) {
195
  var context, id;
196
 
197
  context = $.trim( contextId ).match( /^(.+)_(\d+)$/ );
@@ -223,7 +212,11 @@ window.imagify.drawMeAChart = function( canvas ) {
223
  w.imagify.modal.unlockItem( context, id );
224
 
225
  if ( ! w.imagify.modal.working.length ) {
 
 
226
  w.imagify.modal.openSlide( $containers );
 
 
227
  }
228
  },
229
 
55
 
56
  $document.on( 'click', '.imagify-datas-more-action a', this.toggleSlide );
57
 
 
 
 
 
58
  // Optimize, restore, etc.
59
  $document.on( 'click', '.button-imagify-restore, .button-imagify-optimize, .button-imagify-manual-reoptimize, .button-imagify-optimize-missing-sizes, .button-imagify-generate-webp', this.processOptimization );
60
 
61
+ $document.on( 'imagifybeat-send', this.addToImagifybeat );
62
+ $document.on( 'imagifybeat-tick', this.processImagifybeat );
63
 
64
  // Some items may be processed in background on page load.
65
  $processing = $( '.imagify-data-actions-container .button-imagify-processing' );
66
 
67
  if ( $processing.length ) {
68
+ // Some media are already being processed.
69
+ // Lock the items, so we can check their status with Imagifybeat.
 
70
  $processing.closest( '.imagify-data-actions-container' ).each( function() {
71
  var $this = $( this ),
72
  id = w.imagify.modal.sanitizeId( $this.data( 'id' ) ),
74
 
75
  w.imagify.modal.lockItem( context, id );
76
  } );
77
+
78
+ // Fasten Imagifybeat.
79
+ w.imagify.beat.interval( 15 );
80
  }
81
  },
82
 
134
  // The work is done.
135
  w.imagify.modal.displayProcessResult( context, id, response.data.html );
136
  } else {
137
+ // Still processing in background: we're waiting for the result by poking Imagifybeat.
138
+ // Set the Imagifybeat interval to 15 seconds.
139
+ w.imagify.beat.interval( 15 );
140
  }
141
  } );
142
  },
143
 
144
+ // Imagifybeat =============================================================================
 
 
 
 
 
 
 
 
 
145
 
146
  /**
147
+ * Send the media IDs and their status to Imagifybeat.
148
  *
149
  * @param {object} e Event object.
150
+ * @param {object} data Object containing all Imagifybeat IDs.
151
  */
152
+ addToImagifybeat: function ( e, data ) {
153
  var $containers = $( '.imagify-data-actions-container' );
154
 
155
  if ( ! $containers.length ) {
156
  return;
157
  }
158
 
159
+ data[ w.imagifyModal.imagifybeatID ] = {};
160
 
161
  $containers.each( function() {
162
  var $this = $( this ),
164
  context = w.imagify.modal.sanitizeContext( $this.data( 'context' ) ),
165
  locked = w.imagify.modal.isItemLocked( context, id ) ? 1 : 0;
166
 
167
+ data[ w.imagifyModal.imagifybeatID ][ context ] = data[ w.imagifyModal.imagifybeatID ][ context ] || {};
168
+ data[ w.imagifyModal.imagifybeatID ][ context ][ '_' + id ] = locked;
169
  } );
170
  },
171
 
172
  /**
173
+ * Listen for the custom event "imagifybeat-tick" on $(document).
174
  *
175
  * @param {object} e Event object.
176
+ * @param {object} data Object containing all Imagifybeat IDs.
177
  */
178
+ processImagifybeat: function ( e, data ) {
179
+ if ( typeof data[ w.imagifyModal.imagifybeatID ] === 'undefined' ) {
180
  return;
181
  }
182
 
183
+ $.each( data[ w.imagifyModal.imagifybeatID ], function( contextId, htmlContent ) {
184
  var context, id;
185
 
186
  context = $.trim( contextId ).match( /^(.+)_(\d+)$/ );
212
  w.imagify.modal.unlockItem( context, id );
213
 
214
  if ( ! w.imagify.modal.working.length ) {
215
+ // Work is done.
216
+ // Open the last container being processed.
217
  w.imagify.modal.openSlide( $containers );
218
+ // Reset Imagifybeat interval.
219
+ w.imagify.beat.resetInterval();
220
  }
221
  },
222
 
assets/js/media-modal.min.js CHANGED
@@ -1 +1 @@
1
- window.imagify.drawMeAChart=function(a){a.each(function(){var a=parseInt(jQuery(this).closest(".imagify-chart").next(".imagify-chart-value").text(),10);new window.imagify.Chart(this,{type:"doughnut",data:{datasets:[{data:[a,100-a],backgroundColor:["#00B3D3","#D8D8D8"],borderColor:"#fff",borderWidth:1}]},options:{legend:{display:!1},events:[],animation:{easing:"easeOutBounce"},tooltips:{enabled:!1},responsive:!1}})})},function(a,b,c,d){c.imagify.modal={working:[],init:function(){var d,e=a(b);a(c).on("canvasprinted.imagify",this.updateChart).trigger("canvasprinted.imagify"),a(".imagify-datas-details").hide(),e.on("click",".imagify-datas-more-action a",this.toggleSlide),this.hasHeartbeat()&&(e.on("click",".button-imagify-restore, .button-imagify-optimize, .button-imagify-manual-reoptimize, .button-imagify-optimize-missing-sizes, .button-imagify-generate-webp",this.processOptimization),e.on("heartbeat-send",this.addToHeartbeat),e.on("heartbeat-tick",this.processHeartbeat),d=a(".imagify-data-actions-container .button-imagify-processing"),d.length&&(c.wp.heartbeat.interval(5,12),d.closest(".imagify-data-actions-container").each(function(){var b=a(this),d=c.imagify.modal.sanitizeId(b.data("id")),e=c.imagify.modal.sanitizeContext(b.data("context"));c.imagify.modal.lockItem(e,d)})))},updateChart:function(b,d){var e;d=d||".imagify-consumption-chart",e=a(d),c.imagify.drawMeAChart(e),e.closest(".imagify-datas-list").siblings(".imagify-datas-details").hide()},processOptimization:function(b){var d,e,f=a(this),g=f.parents(".imagify-data-actions-container"),h=c.imagify.modal.sanitizeId(g.data("id")),i=c.imagify.modal.sanitizeContext(g.data("context"));b.preventDefault(),c.imagify.modal.isItemLocked(i,h)||(c.imagify.modal.lockItem(i,h),d=f.attr("href"),e=c.imagify.template("imagify-button-processing"),g.html(e({label:f.data("processing-label")})),a.get(d.replace("admin-post.php","admin-ajax.php")).done(function(a){a.data&&a.data.html?c.imagify.modal.displayProcessResult(i,h,a.data.html):c.wp.heartbeat.interval(5,12)}))},hasHeartbeat:function(){return!!(c.imagifyModal&&c.imagifyModal.heartbeatId&&c.wp&&c.wp.heartbeat)},addToHeartbeat:function(b,d){var e=a(".imagify-data-actions-container");e.length&&(d[c.imagifyModal.heartbeatId]={},e.each(function(){var b=a(this),e=c.imagify.modal.sanitizeId(b.data("id")),f=c.imagify.modal.sanitizeContext(b.data("context")),g=c.imagify.modal.isItemLocked(f,e)?1:0;d[c.imagifyModal.heartbeatId][f]=d[c.imagifyModal.heartbeatId][f]||{},d[c.imagifyModal.heartbeatId][f]["_"+e]=g}))},processHeartbeat:function(b,d){void 0!==d[c.imagifyModal.heartbeatId]&&a.each(d[c.imagifyModal.heartbeatId],function(b,d){var e,f;(e=a.trim(b).match(/^(.+)_(\d+)$/))&&(f=c.imagify.modal.sanitizeId(e[2]),e=c.imagify.modal.sanitizeContext(e[1]),c.imagify.modal.displayProcessResult(e,f,d))})},displayProcessResult:function(a,b,d){var e=c.imagify.modal.getContainers(a,b);e.html(d),c.imagify.modal.unlockItem(a,b),c.imagify.modal.working.length||c.imagify.modal.openSlide(e)},openSlide:function(b){b.each(function(){var b=a(this),c=b.find(".imagify-datas-more-action a").data("close");b.find(".imagify-datas-more-action a").addClass("is-open").find(".the-text").text(c),b.find(".imagify-datas-details").show().addClass("is-open")})},toggleSlide:function(b){var c=a(this);b.preventDefault(),c.hasClass("is-open")?(a(c.attr("href")).slideUp(300).removeClass("is-open"),c.removeClass("is-open").find(".the-text").text(c.data("open"))):(a(c.attr("href")).slideDown(300).addClass("is-open"),c.addClass("is-open").find(".the-text").text(c.data("close")))},getContainers:function(b,c){return a('.imagify-data-actions-container[data-id="'+c+'"][data-context="'+b+'"]')},sanitizeId:function(a){return parseInt(a,10)},sanitizeContext:function(a){return(a=a.replace("/[^a-z0-9_-]/gi","").toLowerCase())||"wp"},lockItem:function(a,b){this.isItemLocked(a,b)||this.working.push(a+"_"+b)},unlockItem:function(a,b){var c=a+"_"+b,d=_.indexOf(this.working,c);d>-1&&this.working.splice(d,1)},isItemLocked:function(a,b){return _.indexOf(this.working,a+"_"+b)>-1}},c.imagify.modal.init()}(jQuery,document,window);
1
+ window.imagify.drawMeAChart=function(a){a.each(function(){var a=parseInt(jQuery(this).closest(".imagify-chart").next(".imagify-chart-value").text(),10);new window.imagify.Chart(this,{type:"doughnut",data:{datasets:[{data:[a,100-a],backgroundColor:["#00B3D3","#D8D8D8"],borderColor:"#fff",borderWidth:1}]},options:{legend:{display:!1},events:[],animation:{easing:"easeOutBounce"},tooltips:{enabled:!1},responsive:!1}})})},function(a,b,c,d){c.imagify.modal={working:[],init:function(){var d,e=a(b);a(c).on("canvasprinted.imagify",this.updateChart).trigger("canvasprinted.imagify"),a(".imagify-datas-details").hide(),e.on("click",".imagify-datas-more-action a",this.toggleSlide),e.on("click",".button-imagify-restore, .button-imagify-optimize, .button-imagify-manual-reoptimize, .button-imagify-optimize-missing-sizes, .button-imagify-generate-webp",this.processOptimization),e.on("imagifybeat-send",this.addToImagifybeat),e.on("imagifybeat-tick",this.processImagifybeat),d=a(".imagify-data-actions-container .button-imagify-processing"),d.length&&(d.closest(".imagify-data-actions-container").each(function(){var b=a(this),d=c.imagify.modal.sanitizeId(b.data("id")),e=c.imagify.modal.sanitizeContext(b.data("context"));c.imagify.modal.lockItem(e,d)}),c.imagify.beat.interval(15))},updateChart:function(b,d){var e;d=d||".imagify-consumption-chart",e=a(d),c.imagify.drawMeAChart(e),e.closest(".imagify-datas-list").siblings(".imagify-datas-details").hide()},processOptimization:function(b){var d,e,f=a(this),g=f.parents(".imagify-data-actions-container"),h=c.imagify.modal.sanitizeId(g.data("id")),i=c.imagify.modal.sanitizeContext(g.data("context"));b.preventDefault(),c.imagify.modal.isItemLocked(i,h)||(c.imagify.modal.lockItem(i,h),d=f.attr("href"),e=c.imagify.template("imagify-button-processing"),g.html(e({label:f.data("processing-label")})),a.get(d.replace("admin-post.php","admin-ajax.php")).done(function(a){a.data&&a.data.html?c.imagify.modal.displayProcessResult(i,h,a.data.html):c.imagify.beat.interval(15)}))},addToImagifybeat:function(b,d){var e=a(".imagify-data-actions-container");e.length&&(d[c.imagifyModal.imagifybeatID]={},e.each(function(){var b=a(this),e=c.imagify.modal.sanitizeId(b.data("id")),f=c.imagify.modal.sanitizeContext(b.data("context")),g=c.imagify.modal.isItemLocked(f,e)?1:0;d[c.imagifyModal.imagifybeatID][f]=d[c.imagifyModal.imagifybeatID][f]||{},d[c.imagifyModal.imagifybeatID][f]["_"+e]=g}))},processImagifybeat:function(b,d){void 0!==d[c.imagifyModal.imagifybeatID]&&a.each(d[c.imagifyModal.imagifybeatID],function(b,d){var e,f;(e=a.trim(b).match(/^(.+)_(\d+)$/))&&(f=c.imagify.modal.sanitizeId(e[2]),e=c.imagify.modal.sanitizeContext(e[1]),c.imagify.modal.displayProcessResult(e,f,d))})},displayProcessResult:function(a,b,d){var e=c.imagify.modal.getContainers(a,b);e.html(d),c.imagify.modal.unlockItem(a,b),c.imagify.modal.working.length||(c.imagify.modal.openSlide(e),c.imagify.beat.resetInterval())},openSlide:function(b){b.each(function(){var b=a(this),c=b.find(".imagify-datas-more-action a").data("close");b.find(".imagify-datas-more-action a").addClass("is-open").find(".the-text").text(c),b.find(".imagify-datas-details").show().addClass("is-open")})},toggleSlide:function(b){var c=a(this);b.preventDefault(),c.hasClass("is-open")?(a(c.attr("href")).slideUp(300).removeClass("is-open"),c.removeClass("is-open").find(".the-text").text(c.data("open"))):(a(c.attr("href")).slideDown(300).addClass("is-open"),c.addClass("is-open").find(".the-text").text(c.data("close")))},getContainers:function(b,c){return a('.imagify-data-actions-container[data-id="'+c+'"][data-context="'+b+'"]')},sanitizeId:function(a){return parseInt(a,10)},sanitizeContext:function(a){return(a=a.replace("/[^a-z0-9_-]/gi","").toLowerCase())||"wp"},lockItem:function(a,b){this.isItemLocked(a,b)||this.working.push(a+"_"+b)},unlockItem:function(a,b){var c=a+"_"+b,d=_.indexOf(this.working,c);d>-1&&this.working.splice(d,1)},isItemLocked:function(a,b){return _.indexOf(this.working,a+"_"+b)>-1}},c.imagify.modal.init()}(jQuery,document,window);
assets/js/options.js CHANGED
@@ -7,7 +7,7 @@ window.imagify = window.imagify || {};
7
  var busy = false,
8
  xhr = false;
9
 
10
- $( '#imagify-settings #api_key' ).on( 'blur', function() {
11
  var obj = $( this ),
12
  value = obj.val();
13
 
@@ -54,28 +54,34 @@ window.imagify = window.imagify || {};
54
  /**
55
  * Check the boxes by clicking "labels" (aria-describedby items).
56
  */
57
- $( '.imagify-options-line' ).css( 'cursor', 'pointer' ).on( 'click', function( e ) {
58
  if ( 'INPUT' === e.target.nodeName ) {
59
  return;
60
  }
61
- $( 'input[aria-describedby="' + $( this ).attr( 'id' ) + '"]' ).trigger( 'click' );
62
  } );
63
 
64
- $( '.imagify-settings th span' ).on( 'click', function() {
65
- var $input = $( this ).parent().next( 'td' ).find( 'input:checkbox' );
66
 
67
  if ( 1 === $input.length ) {
68
- $input.trigger( 'click' );
69
  }
70
  } );
71
 
72
  /**
73
  * Auto check on options-line input value change.
74
  */
75
- $( '.imagify-options-line' ).find( 'input' ).on( 'change focus', function() {
76
- var $checkbox = $( this ).closest( '.imagify-options-line' ).prev( 'label' ).prev( 'input' );
77
 
78
- if ( ! $checkbox[0].checked ) {
 
 
 
 
 
 
79
  $checkbox.prop( 'checked', true );
80
  }
81
  } );
@@ -83,7 +89,7 @@ window.imagify = window.imagify || {};
83
  /**
84
  * Imagify Backup alert.
85
  */
86
- $( '.imagify-settings-section' ).find( '#imagify_backup' ).on( 'change', function() {
87
  var $_this = $( this ),
88
  $backupMessage = $_this.siblings( '#backup-dir-is-writable' ),
89
  params = {
@@ -129,6 +135,17 @@ window.imagify = window.imagify || {};
129
  );
130
  } );
131
 
 
 
 
 
 
 
 
 
 
 
 
132
  } )(jQuery, document, window);
133
 
134
 
@@ -510,13 +527,13 @@ window.imagify = window.imagify || {};
510
  // Launch optimization.
511
  this.$button.on( 'click.imagify', { imagifyOptionsBulk: this }, this.maybeLaunchAllProcesses );
512
 
513
- // Heartbeat for optimization queue.
514
  $( d )
515
- .on( 'heartbeat-send', { imagifyOptionsBulk: this }, this.addQueueHeartbeat )
516
- .on( 'heartbeat-tick', { imagifyOptionsBulk: this }, this.processQueueHeartbeat )
517
- // Heartbeat for requirements.
518
- .on( 'heartbeat-send', this.addRequirementsHeartbeat )
519
- .on( 'heartbeat-tick', { imagifyOptionsBulk: this }, this.processRequirementsHeartbeat );
520
  },
521
 
522
  // Event callbacks =========================================================================
@@ -563,7 +580,11 @@ window.imagify = window.imagify || {};
563
  e.data.imagifyOptionsBulk.$button.attr( 'disabled', 'disabled' ).find( '.dashicons' ).addClass( 'rotate' );
564
 
565
  // Add a message to be displayed when the user wants to quit the page.
566
- $( w ).on( 'beforeunload', e.data.imagifyOptionsBulk.getConfirmMessage );
 
 
 
 
567
 
568
  // Fetch IDs of media to optimize.
569
  e.data.imagifyOptionsBulk.fetchIDs();
@@ -578,58 +599,58 @@ window.imagify = window.imagify || {};
578
  return imagifyOptions.bulk.labels.processing;
579
  },
580
 
581
- // Heartbeat ===============================================================================
582
 
583
  /**
584
- * Add a Heartbeat ID on "heartbeat-send" event to sync the optimization queue.
585
  *
586
  * @param {object} e Event object.
587
- * @param {object} data Object containing all Heartbeat IDs.
588
  */
589
- addQueueHeartbeat: function ( e, data ) {
590
  if ( e.data.imagifyOptionsBulk && e.data.imagifyOptionsBulk.processingQueue.length ) {
591
- data[ imagifyOptions.bulk.heartbeatIDs.queue ] = e.data.imagifyOptionsBulk.processingQueue;
592
  }
593
  },
594
 
595
  /**
596
- * Listen for the custom event "heartbeat-tick" on $(document).
597
  * It allows to update various data periodically.
598
  *
599
  * @param {object} e Event object.
600
- * @param {object} data Object containing all Heartbeat IDs.
601
  */
602
- processQueueHeartbeat: function ( e, data ) {
603
- if ( e.data.imagifyOptionsBulk && typeof data[ imagifyOptions.bulk.heartbeatIDs.queue ] !== 'undefined' ) {
604
- $.each( data[ imagifyOptions.bulk.heartbeatIDs.queue ], function ( i, mediaData ) {
605
  e.data.imagifyOptionsBulk.mediaProcessed( mediaData );
606
  } );
607
  }
608
  },
609
 
610
  /**
611
- * Add a Heartbeat ID for requirements on "heartbeat-send" event.
612
  *
613
  * @param {object} e Event object.
614
- * @param {object} data Object containing all Heartbeat IDs.
615
  */
616
- addRequirementsHeartbeat: function ( e, data ) {
617
- data[ imagifyOptions.bulk.heartbeatIDs.requirements ] = 1;
618
  },
619
 
620
  /**
621
- * Listen for the custom event "heartbeat-tick" on $(document).
622
  * It allows to update requirements status periodically.
623
  *
624
  * @param {object} e Event object.
625
- * @param {object} data Object containing all Heartbeat IDs.
626
  */
627
- processRequirementsHeartbeat: function ( e, data ) {
628
- if ( e.data.imagifyOptionsBulk && typeof data[ imagifyOptions.bulk.heartbeatIDs.requirements ] === 'undefined' ) {
629
  return;
630
  }
631
 
632
- data = data[ imagifyOptions.bulk.heartbeatIDs.requirements ];
633
 
634
  imagifyOptions.bulk.curlMissing = data.curl_missing;
635
  imagifyOptions.bulk.editorMissing = data.editor_missing;
@@ -915,8 +936,12 @@ window.imagify = window.imagify || {};
915
  this.processedMedia = 0;
916
  this.totalMedia = 0;
917
 
 
 
 
 
918
  // Unlink the message displayed when the user wants to quit the page.
919
- $( w ).off( 'beforeunload', this.getConfirmMessage );
920
 
921
  // Reset the progress bar.
922
  this.$progressWrap.slideUp().attr( 'aria-hidden', 'true' );
7
  var busy = false,
8
  xhr = false;
9
 
10
+ $( '#imagify-settings #api_key' ).on( 'blur.imagify', function() {
11
  var obj = $( this ),
12
  value = obj.val();
13
 
54
  /**
55
  * Check the boxes by clicking "labels" (aria-describedby items).
56
  */
57
+ $( '.imagify-options-line' ).css( 'cursor', 'pointer' ).on( 'click.imagify', function( e ) {
58
  if ( 'INPUT' === e.target.nodeName ) {
59
  return;
60
  }
61
+ $( 'input[aria-describedby="' + $( this ).attr( 'id' ) + '"]' ).trigger( 'click.imagify' );
62
  } );
63
 
64
+ $( '.imagify-settings th span' ).on( 'click.imagify', function() {
65
+ var $input = $( this ).parent().next( 'td' ).find( ':checkbox' );
66
 
67
  if ( 1 === $input.length ) {
68
+ $input.trigger( 'click.imagify' );
69
  }
70
  } );
71
 
72
  /**
73
  * Auto check on options-line input value change.
74
  */
75
+ $( '.imagify-options-line' ).find( 'input' ).on( 'change.imagify focus.imagify', function() {
76
+ var $checkbox;
77
 
78
+ if ( 'checkbox' === this.type && ! this.checked ) {
79
+ return;
80
+ }
81
+
82
+ $checkbox = $( this ).closest( '.imagify-options-line' ).prev( 'label' ).prev( ':checkbox' );
83
+
84
+ if ( $checkbox.length && ! $checkbox[0].checked ) {
85
  $checkbox.prop( 'checked', true );
86
  }
87
  } );
89
  /**
90
  * Imagify Backup alert.
91
  */
92
+ $( '[name="imagify_settings[backup]"]' ).on( 'change.imagify', function() {
93
  var $_this = $( this ),
94
  $backupMessage = $_this.siblings( '#backup-dir-is-writable' ),
95
  params = {
135
  );
136
  } );
137
 
138
+ /**
139
+ * Fade CDN URL field.
140
+ */
141
+ $( '[name="imagify_settings[display_webp_method]"]' ).on( 'change.imagify init.imagify', function( e ) {
142
+ if ( 'picture' === e.target.value ) {
143
+ $( e.target ).closest( '.imagify-radio-group' ).next( '.imagify-options-line' ).removeClass( 'imagify-faded' );
144
+ } else {
145
+ $( e.target ).closest( '.imagify-radio-group' ).next( '.imagify-options-line' ).addClass( 'imagify-faded' );
146
+ }
147
+ } ).filter( ':checked' ).trigger( 'init.imagify' );
148
+
149
  } )(jQuery, document, window);
150
 
151
 
527
  // Launch optimization.
528
  this.$button.on( 'click.imagify', { imagifyOptionsBulk: this }, this.maybeLaunchAllProcesses );
529
 
530
+ // Imagifybeat for optimization queue.
531
  $( d )
532
+ .on( 'imagifybeat-send', { imagifyOptionsBulk: this }, this.addQueueImagifybeat )
533
+ .on( 'imagifybeat-tick', { imagifyOptionsBulk: this }, this.processQueueImagifybeat )
534
+ // Imagifybeat for requirements.
535
+ .on( 'imagifybeat-send', this.addRequirementsImagifybeat )
536
+ .on( 'imagifybeat-tick', { imagifyOptionsBulk: this }, this.processRequirementsImagifybeat );
537
  },
538
 
539
  // Event callbacks =========================================================================
580
  e.data.imagifyOptionsBulk.$button.attr( 'disabled', 'disabled' ).find( '.dashicons' ).addClass( 'rotate' );
581
 
582
  // Add a message to be displayed when the user wants to quit the page.
583
+ $( w ).on( 'beforeunload.imagify', e.data.imagifyOptionsBulk.getConfirmMessage );
584
+
585
+ // Fasten Imagifybeat: 1 tick every 15 seconds, and disable suspend.
586
+ w.imagify.beat.interval( 15 );
587
+ w.imagify.beat.disableSuspend();
588
 
589
  // Fetch IDs of media to optimize.
590
  e.data.imagifyOptionsBulk.fetchIDs();
599
  return imagifyOptions.bulk.labels.processing;
600
  },
601
 
602
+ // Imagifybeat =============================================================================
603
 
604
  /**
605
+ * Add a Imagifybeat ID on "imagifybeat-send" event to sync the optimization queue.
606
  *
607
  * @param {object} e Event object.
608
+ * @param {object} data Object containing all Imagifybeat IDs.
609
  */
610
+ addQueueImagifybeat: function ( e, data ) {
611
  if ( e.data.imagifyOptionsBulk && e.data.imagifyOptionsBulk.processingQueue.length ) {
612
+ data[ imagifyOptions.bulk.imagifybeatIDs.queue ] = e.data.imagifyOptionsBulk.processingQueue;
613
  }
614
  },
615
 
616
  /**
617
+ * Listen for the custom event "imagifybeat-tick" on $(document).
618
  * It allows to update various data periodically.
619
  *
620
  * @param {object} e Event object.
621
+ * @param {object} data Object containing all Imagifybeat IDs.
622
  */
623
+ processQueueImagifybeat: function ( e, data ) {
624
+ if ( e.data.imagifyOptionsBulk && typeof data[ imagifyOptions.bulk.imagifybeatIDs.queue ] !== 'undefined' ) {
625
+ $.each( data[ imagifyOptions.bulk.imagifybeatIDs.queue ], function ( i, mediaData ) {
626
  e.data.imagifyOptionsBulk.mediaProcessed( mediaData );
627
  } );
628
  }
629
  },
630
 
631
  /**
632
+ * Add a Imagifybeat ID for requirements on "imagifybeat-send" event.
633
  *
634
  * @param {object} e Event object.
635
+ * @param {object} data Object containing all Imagifybeat IDs.
636
  */
637
+ addRequirementsImagifybeat: function ( e, data ) {
638
+ data[ imagifyOptions.bulk.imagifybeatIDs.requirements ] = 1;
639
  },
640
 
641
  /**
642
+ * Listen for the custom event "imagifybeat-tick" on $(document).
643
  * It allows to update requirements status periodically.
644
  *
645
  * @param {object} e Event object.
646
+ * @param {object} data Object containing all Imagifybeat IDs.
647
  */
648
+ processRequirementsImagifybeat: function ( e, data ) {
649
+ if ( e.data.imagifyOptionsBulk && typeof data[ imagifyOptions.bulk.imagifybeatIDs.requirements ] === 'undefined' ) {
650
  return;
651
  }
652
 
653
+ data = data[ imagifyOptions.bulk.imagifybeatIDs.requirements ];
654
 
655
  imagifyOptions.bulk.curlMissing = data.curl_missing;
656
  imagifyOptions.bulk.editorMissing = data.editor_missing;
936
  this.processedMedia = 0;
937
  this.totalMedia = 0;
938
 
939
+ // Reset Imagifybeat interval and enable suspend.
940
+ w.imagify.beat.resetInterval();
941
+ w.imagify.beat.enableSuspend();
942
+
943
  // Unlink the message displayed when the user wants to quit the page.
944
+ $( w ).off( 'beforeunload.imagify', this.getConfirmMessage );
945
 
946
  // Reset the progress bar.
947
  this.$progressWrap.slideUp().attr( 'aria-hidden', 'true' );
assets/js/options.min.js CHANGED
@@ -1 +1 @@
1
- window.imagify=window.imagify||{},function(a,b,c,d){var e=!1,f=!1;a("#imagify-settings #api_key").on("blur",function(){var b=a(this),d=b.val();return""!==a.trim(d)&&(a("#check_api_key").val()===d?(a("#imagify-check-api-container").html('<span class="dashicons dashicons-yes"></span> '+imagifyOptions.labels.ValidApiKeyText),!1):(!0===e?f.abort():(a("#imagify-check-api-container").remove(),b.after('<span id="imagify-check-api-container"><span class="imagify-spinner"></span>'+imagifyOptions.labels.waitApiKeyCheckText+"</span>")),e=!0,void(f=a.get(ajaxurl+c.imagify.concat+"action=imagify_check_api_key_validity&api_key="+b.val()+"&imagifycheckapikeynonce="+a("#imagifycheckapikeynonce").val()).done(function(b){b.success?(a("#imagify-check-api-container").remove(),swal({title:imagifyOptions.labels.ApiKeyCheckSuccessTitle,html:imagifyOptions.labels.ApiKeyCheckSuccessText,type:"success",padding:0,customClass:"imagify-sweet-alert"}).then(function(){location.reload()})):a("#imagify-check-api-container").html('<span class="dashicons dashicons-no"></span> '+b.data),e=!1}))))}),a(".imagify-options-line").css("cursor","pointer").on("click",function(b){"INPUT"!==b.target.nodeName&&a('input[aria-describedby="'+a(this).attr("id")+'"]').trigger("click")}),a(".imagify-settings th span").on("click",function(){var b=a(this).parent().next("td").find("input:checkbox");1===b.length&&b.trigger("click")}),a(".imagify-options-line").find("input").on("change focus",function(){var b=a(this).closest(".imagify-options-line").prev("label").prev("input");b[0].checked||b.prop("checked",!0)}),a(".imagify-settings-section").find("#imagify_backup").on("change",function(){var b=a(this),c=b.siblings("#backup-dir-is-writable"),d={action:"imagify_check_backup_dir_is_writable",_wpnonce:c.data("nonce")};if(b.is(":checked"))return void a.getJSON(ajaxurl,d).done(function(b){a.isPlainObject(b)&&b.success&&(b.data.is_writable?c.addClass("hidden"):c.removeClass("hidden"))});swal({title:imagifyOptions.labels.noBackupTitle,html:imagifyOptions.labels.noBackupText,type:"warning",customClass:"imagify-sweet-alert",padding:0,showCancelButton:!0,cancelButtonText:imagifySwal.labels.cancelButtonText,reverseButtons:!0}).then(function(){c.addClass("hidden")},function(){b.prop("checked",!0)})})}(jQuery,document,window),function(a,b,c,d){a.imagifyUser&&c.getJSON(ajaxurl,a.imagifyUser).done(function(a){c.isPlainObject(a)&&a.success&&(a.data.id=null,a.data.plan_id=null,a.data.is=[],c.each(a.data,function(b,d){var e=".imagify-user-"+b.replace(/_/g,"-");0===b.indexOf("is_")?d&&a.data.is.push(e):"is"!==b&&c(e).text(d)}),a.data.is.push("best-plan"),c(a.data.is.join(",")).removeClass("hidden"))})}(window,document,jQuery),function(a,b,c,d){function e(b){var d,e,f,g,h,i=!1,j=null;b&&(f=c("#imagify-custom-folders-selected"),g=f.find(".imagify-custom-folder-line"),h=g.find('[value="'+b+'"]'),h.length||(b=b.split("#///#"),d=b[1].replace(/\/+$/,"").toLowerCase(),e=a.imagify.template("imagify-custom-folder"),g.each(function(){var a=c(this),h=a.data("path").replace(/\/+$/,"").toLowerCase();return""!==h&&0===d.indexOf(h)?(i=!0,!1):d<h?(a.before(e({value:b[0],label:b[1]})),g=f.find(".imagify-custom-folder-line"),i=!0,!1):void 0}),i||(f.append(e({value:b[0],label:b[1]})),g=f.find(".imagify-custom-folder-line")),""!==d&&g.each(function(){var a=c(this),b=a.data("path").toLowerCase();null!==j&&0===b.indexOf(j)?a.find(".imagify-custom-folders-remove").trigger("click.imagify"):j=b}),f.next(".hidden").removeClass("hidden")))}imagifyOptions.getFilesTree&&(c("#imagify-add-custom-folder").on("click.imagify",function(){var a,b=c(this),d=[];b.attr("disabled")||(b.attr("disabled","disabled").next("img").attr("aria-hidden","false"),a=c("#imagify-custom-folders-selected"),a.find("input").each(function(){d.push(this.value)}),c.post(imagifyOptions.getFilesTree,{folder:"/",selected:d},null,"json").done(function(a){if(!a.success)return void swal({title:imagifyOptions.labels.error,html:a.data||"",type:"error",padding:0,customClass:"imagify-sweet-alert"});swal({title:imagifyOptions.labels.filesTreeTitle,html:'<div class="imagify-swal-subtitle">'+imagifyOptions.labels.filesTreeSubTitle+'</div><div class="imagify-swal-content"><p class="imagify-folders-information"><i class="dashicons dashicons-info" aria-hidden="true"></i>'+imagifyOptions.labels.cleaningInfo+'</p><ul id="imagify-folders-tree" class="imagify-folders-tree">'+a.data+"</ul></div>",type:"",customClass:"imagify-sweet-alert imagify-swal-has-subtitle imagify-folders-selection",showCancelButton:!0,padding:0,confirmButtonText:imagifyOptions.labels.confirmFilesTreeBtn,cancelButtonText:imagifySwal.labels.cancelButtonText,reverseButtons:!0}).then(function(){var a=c("#imagify-folders-tree input").serializeArray();a.length&&c.each(a,function(a,b){e(b.value)})}).catch(swal.noop)}).fail(function(){swal({title:imagifyOptions.labels.error,type:"error",customClass:"imagify-sweet-alert",padding:0})}).always(function(){b.removeAttr("disabled").next("img").attr("aria-hidden","true")}))}),c(b).on("click.imagify","#imagify-folders-tree [data-folder]",function(){var a=c(this),b=a.nextAll(".imagify-folders-sub-tree"),d=[];if(!a.attr("disabled")&&!a.siblings(":checkbox").is(":checked")){if(a.attr("disabled","disabled").addClass("imagify-loading"),b.length)return a.hasClass("imagify-is-open")?(b.addClass("hidden"),a.removeClass(" imagify-is-open")):(b.removeClass("hidden"),a.addClass("imagify-is-open")),void a.removeAttr("disabled").removeClass("imagify-loading");c("#imagify-custom-folders-selected").find("input").each(function(){d.push(this.value)}),c.post(imagifyOptions.getFilesTree,{folder:a.data("folder"),selected:d},null,"json").done(function(b){if(!b.success)return void swal({title:imagifyOptions.labels.error,html:b.data||"",type:"error",padding:0,customClass:"imagify-sweet-alert"});a.addClass("imagify-is-open").parent().append('<ul class="imagify-folders-sub-tree">'+b.data+"</ul>")}).fail(function(){swal({title:imagifyOptions.labels.error,type:"error",padding:0,customClass:"imagify-sweet-alert"})}).always(function(){a.removeAttr("disabled").removeClass("imagify-loading")})}}),c("#imagify-custom-folders").on("click.imagify",".imagify-custom-folders-remove",function(){var b=c(this).closest(".imagify-custom-folder-line").addClass("imagify-will-remove");a.setTimeout(function(){b.remove(),c("#imagify-custom-folders-selected").siblings(".imagify-success.hidden").removeClass("hidden")},750)}),c("#imagify-add-themes-to-custom-folder").on("click.imagify",function(){var a=c(this);e(a.data("theme")),e(a.data("theme-parent")),a.replaceWith("<p>"+imagifyOptions.labels.themesAdded+"</p>")}))}(window,document,jQuery),function(a,b,c,d){imagifyOptions.bulk&&(a.imagify.optionsBulk={fetchQueue:[],queue:[],processingQueue:[],fetchError:!1,error:!1,working:!1,processIsStopped:!0,processedMedia:0,totalMedia:0,$button:null,$progressWrap:null,$progressBar:null,$progressText:null,init:function(){this.$button=c("#imagify-generate-webp-versions"),this.$progressWrap=this.$button.siblings(".imagify-progress"),this.$progressBar=this.$progressWrap.find(".bar"),this.$progressText=this.$progressBar.find(".percent"),c("#imagify_convert_to_webp").on("change.imagify init.imagify",{imagifyOptionsBulk:this},this.toggleButton).trigger("init.imagify"),this.$button.on("click.imagify",{imagifyOptionsBulk:this},this.maybeLaunchAllProcesses),c(b).on("heartbeat-send",{imagifyOptionsBulk:this},this.addQueueHeartbeat).on("heartbeat-tick",{imagifyOptionsBulk:this},this.processQueueHeartbeat).on("heartbeat-send",this.addRequirementsHeartbeat).on("heartbeat-tick",{imagifyOptionsBulk:this},this.processRequirementsHeartbeat)},toggleButton:function(a){this.checked?a.data.imagifyOptionsBulk.$button.removeAttr("disabled"):a.data.imagifyOptionsBulk.$button.attr("disabled","disabled")},maybeLaunchAllProcesses:function(b){b.data.imagifyOptionsBulk&&!b.data.imagifyOptionsBulk.working&&(b.data.imagifyOptionsBulk.hasBlockingError(!0)||(b.data.imagifyOptionsBulk.fetchQueue=imagifyOptions.bulk.contexts,b.data.imagifyOptionsBulk.queue=[],b.data.imagifyOptionsBulk.processingQueue=[],b.data.imagifyOptionsBulk.fetchError=!1,b.data.imagifyOptionsBulk.error=!1,b.data.imagifyOptionsBulk.working=!0,b.data.imagifyOptionsBulk.processIsStopped=!1,b.data.imagifyOptionsBulk.processedMedia=0,b.data.imagifyOptionsBulk.totalMedia=0,b.data.imagifyOptionsBulk.$button.attr("disabled","disabled").find(".dashicons").addClass("rotate"),c(a).on("beforeunload",b.data.imagifyOptionsBulk.getConfirmMessage),b.data.imagifyOptionsBulk.fetchIDs()))},getConfirmMessage:function(){return imagifyOptions.bulk.labels.processing},addQueueHeartbeat:function(a,b){a.data.imagifyOptionsBulk&&a.data.imagifyOptionsBulk.processingQueue.length&&(b[imagifyOptions.bulk.heartbeatIDs.queue]=a.data.imagifyOptionsBulk.processingQueue)},processQueueHeartbeat:function(a,b){a.data.imagifyOptionsBulk&&void 0!==b[imagifyOptions.bulk.heartbeatIDs.queue]&&c.each(b[imagifyOptions.bulk.heartbeatIDs.queue],function(b,c){a.data.imagifyOptionsBulk.mediaProcessed(c)})},addRequirementsHeartbeat:function(a,b){b[imagifyOptions.bulk.heartbeatIDs.requirements]=1},processRequirementsHeartbeat:function(a,b){a.data.imagifyOptionsBulk&&void 0===b[imagifyOptions.bulk.heartbeatIDs.requirements]||(b=b[imagifyOptions.bulk.heartbeatIDs.requirements],imagifyOptions.bulk.curlMissing=b.curl_missing,imagifyOptions.bulk.editorMissing=b.editor_missing,imagifyOptions.bulk.extHttpBlocked=b.external_http_blocked,imagifyOptions.bulk.apiDown=b.api_down,imagifyOptions.bulk.keyIsValid=b.key_is_valid,imagifyOptions.bulk.isOverQuota=b.is_over_quota)},fetchIDs:function(){var a,b;if(!this.processIsStopped){if(!this.fetchQueue.length)return this.queue.length?(this.$progressBar.removeAttr("style"),this.$progressText.text("0"+(this.totalMedia?"/"+this.totalMedia:"")),this.$progressWrap.slideDown().attr("aria-hidden","false"),void this.processQueue()):(this.fetchError||(this.fetchError="no-images"),this.stopProcess(this.fetchError),void(this.fetchError=!1));a=this,b=this.fetchQueue.shift(),c.get(this.getAjaxUrl("getMediaIds",b)).done(function(d){var e;if(!a.processIsStopped)return e=d.data&&d.data.message?d.data.message:imagifyOptions.bulk.ajaxErrorText,d.success&&c.isArray(d.data)?void(d.data.length&&(a.totalMedia+=d.data.length,a.queue.push({context:b,optimizeURL:a.getAjaxUrl("bulkProcess",b),mediaIDs:d.data}))):void(a.fetchError||(a.fetchError=e))}).fail(function(){a.fetchError||(a.fetchError="get-unoptimized-images")}).always(function(){a.fetchIDs()})}},processQueue:function(){var a=this;this.processIsStopped||(this.queue.length||this.processingQueue.length)&&c.each(this.queue,function(b,d){if(a.processingQueue.length>=imagifyOptions.bulk.bufferSize)return!1;c.each(d.mediaIDs,function(){if(a.processMedia({context:d.context,mediaID:d.mediaIDs.shift(),optimizeURL:d.optimizeURL}),d.mediaIDs.length||a.queue.shift(),a.processingQueue.length>=imagifyOptions.bulk.bufferSize)return!1})})},processMedia:function(a){var b=this,d={context:a.context,mediaID:a.mediaID};this.processingQueue.push({context:a.context,mediaID:a.mediaID}),c.post({url:a.optimizeURL,data:{media_id:a.mediaID,context:a.context},dataType:"json"}).done(function(a){a.success||b.mediaProcessed(d)}).fail(function(){b.mediaProcessed(d)})},mediaProcessed:function(a){var b=this;this.processIsStopped||(c.each(this.processingQueue,function(c,d){if(a.context===d.context&&a.mediaID===d.mediaID)return b.processingQueue.splice(c,1),!1}),++this.processedMedia,a.progress=Math.floor(this.processedMedia/this.totalMedia*100),this.$progressBar.css("width",a.progress+"%"),this.$progressText.text(this.processedMedia+"/"+this.totalMedia),this.queue.length||this.processingQueue.length?this.processQueue():this.totalMedia===this.processedMedia&&this.queueEmpty())},queueEmpty:function(){var b={};!1!==this.error&&(b="invalid-api-key"===this.error?{title:imagifyOptions.bulk.labels.invalidAPIKeyTitle,type:"info"}:"over-quota"===this.error?{title:imagifyOptions.bulk.labels.overQuotaTitle,html:c("#tmpl-imagify-overquota-alert").html(),type:"info",customClass:"imagify-swal-has-subtitle imagify-swal-error-header",showConfirmButton:!1}:"get-unoptimized-images"===this.error||"consumed-all-data"===this.error?{title:imagifyOptions.bulk.labels.getUnoptimizedImagesErrorTitle,html:imagifyOptions.bulk.labels.getUnoptimizedImagesErrorText,type:"info"}:"no-images"===this.error?{title:imagifyOptions.bulk.labels.nothingToDoTitle,html:imagifyOptions.bulk.labels.nothingToDoText,type:"info"}:{title:imagifyOptions.bulk.labels.error,html:this.error,type:"info"},this.displayError(b),this.error=!1),this.fetchQueue=[],this.queue=[],this.processingQueue=[],this.fetchError=!1,this.working=!1,this.processIsStopped=!1,this.processedMedia=0,this.totalMedia=0,c(a).off("beforeunload",this.getConfirmMessage),this.$progressWrap.slideUp().attr("aria-hidden","true"),this.$progressBar.removeAttr("style"),this.$progressText.text("0"),this.$button.removeAttr("disabled").find(".dashicons").removeClass("rotate")},hasBlockingError:function(a){return a=void 0!==a&&a,imagifyOptions.bulk.curlMissing?(a&&this.displayError({html:imagifyOptions.bulk.labels.curlMissing}),!0):imagifyOptions.bulk.editorMissing?(a&&this.displayError({html:imagifyOptions.bulk.labels.editorMissing}),!0):imagifyOptions.bulk.extHttpBlocked?(a&&this.displayError({html:imagifyOptions.bulk.labels.extHttpBlocked}),!0):imagifyOptions.bulk.apiDown?(a&&this.displayError({html:imagifyOptions.bulk.labels.apiDown}),!0):imagifyOptions.bulk.keyIsValid?!!imagifyOptions.bulk.isOverQuota&&(a&&this.displayError({title:imagifyOptions.bulk.labels.overQuotaTitle,html:c("#tmpl-imagify-overquota-alert").html(),type:"info",customClass:"imagify-swal-has-subtitle imagify-swal-error-header",showConfirmButton:!1}),!0):(a&&this.displayError({title:imagifyOptions.bulk.labels.invalidAPIKeyTitle,type:"info"}),!0)},displayError:function(a,b,d){var e={title:"",html:"",type:"error",customClass:"",width:620,padding:0,showCloseButton:!0,showConfirmButton:!0};c.isPlainObject(a)?d=c.extend({},e,a):(d=d||{},d=c.extend({},e,{title:a||"",html:b||""},d)),d.title=d.title||imagifyOptions.bulk.labels.error,d.customClass+=" imagify-sweet-alert",swal(d).catch(swal.noop)},getAjaxUrl:function(b,c){var d;return d=ajaxurl+a.imagify.concat+"_wpnonce="+imagifyOptions.bulk.ajaxNonce,d+="&action="+imagifyOptions.bulk.ajaxActions[b],d+="&context="+c,d+="&imagify_action=generate_webp"},stopProcess:function(a){this.processIsStopped=!0,this.error=a,this.queueEmpty()}},a.imagify.optionsBulk.init())}(window,document,jQuery),function(a,b,c,d){var e=c.propHooks.checked;c.propHooks.checked={set:function(a,b,d){var f;return f=void 0===e?a[d]=b:e(a,b,d),c(a).trigger("change.imagify"),f}},c(".imagify-select-all").on("click.imagify",function(){var a=c(this),b=a.data("action"),d=a.closest(".imagify-select-all-buttons"),e=d.prev(".imagify-check-group"),f="imagify-is-inactive";if(a.hasClass(f))return!1;d.find(".imagify-select-all").removeClass(f).attr("aria-disabled","false"),a.addClass(f).attr("aria-disabled","true"),e.find(".imagify-row-check").prop("checked",function(){return!c(this).is(":hidden,:disabled")&&"select"===b})}),c(".imagify-check-group .imagify-row-check").on("change.imagify",function(){var a=c(this).closest(".imagify-check-group"),b=a.find(".imagify-row-check"),d=b.filter(":visible:enabled").length,e=b.filter(":visible:enabled:checked").length,f=a.next(".imagify-select-all-buttons"),g="imagify-is-inactive";0===e&&f.find('[data-action="unselect"]').addClass(g).attr("aria-disabled","true"),e===d&&f.find('[data-action="select"]').addClass(g).attr("aria-disabled","true"),e!==d&&e>0&&f.find(".imagify-select-all").removeClass(g).attr("aria-disabled","false")})}(window,document,jQuery);
1
+ window.imagify=window.imagify||{},function(a,b,c,d){var e=!1,f=!1;a("#imagify-settings #api_key").on("blur.imagify",function(){var b=a(this),d=b.val();return""!==a.trim(d)&&(a("#check_api_key").val()===d?(a("#imagify-check-api-container").html('<span class="dashicons dashicons-yes"></span> '+imagifyOptions.labels.ValidApiKeyText),!1):(!0===e?f.abort():(a("#imagify-check-api-container").remove(),b.after('<span id="imagify-check-api-container"><span class="imagify-spinner"></span>'+imagifyOptions.labels.waitApiKeyCheckText+"</span>")),e=!0,void(f=a.get(ajaxurl+c.imagify.concat+"action=imagify_check_api_key_validity&api_key="+b.val()+"&imagifycheckapikeynonce="+a("#imagifycheckapikeynonce").val()).done(function(b){b.success?(a("#imagify-check-api-container").remove(),swal({title:imagifyOptions.labels.ApiKeyCheckSuccessTitle,html:imagifyOptions.labels.ApiKeyCheckSuccessText,type:"success",padding:0,customClass:"imagify-sweet-alert"}).then(function(){location.reload()})):a("#imagify-check-api-container").html('<span class="dashicons dashicons-no"></span> '+b.data),e=!1}))))}),a(".imagify-options-line").css("cursor","pointer").on("click.imagify",function(b){"INPUT"!==b.target.nodeName&&a('input[aria-describedby="'+a(this).attr("id")+'"]').trigger("click.imagify")}),a(".imagify-settings th span").on("click.imagify",function(){var b=a(this).parent().next("td").find(":checkbox");1===b.length&&b.trigger("click.imagify")}),a(".imagify-options-line").find("input").on("change.imagify focus.imagify",function(){var b;("checkbox"!==this.type||this.checked)&&(b=a(this).closest(".imagify-options-line").prev("label").prev(":checkbox"),b.length&&!b[0].checked&&b.prop("checked",!0))}),a('[name="imagify_settings[backup]"]').on("change.imagify",function(){var b=a(this),c=b.siblings("#backup-dir-is-writable"),d={action:"imagify_check_backup_dir_is_writable",_wpnonce:c.data("nonce")};if(b.is(":checked"))return void a.getJSON(ajaxurl,d).done(function(b){a.isPlainObject(b)&&b.success&&(b.data.is_writable?c.addClass("hidden"):c.removeClass("hidden"))});swal({title:imagifyOptions.labels.noBackupTitle,html:imagifyOptions.labels.noBackupText,type:"warning",customClass:"imagify-sweet-alert",padding:0,showCancelButton:!0,cancelButtonText:imagifySwal.labels.cancelButtonText,reverseButtons:!0}).then(function(){c.addClass("hidden")},function(){b.prop("checked",!0)})}),a('[name="imagify_settings[display_webp_method]"]').on("change.imagify init.imagify",function(b){"picture"===b.target.value?a(b.target).closest(".imagify-radio-group").next(".imagify-options-line").removeClass("imagify-faded"):a(b.target).closest(".imagify-radio-group").next(".imagify-options-line").addClass("imagify-faded")}).filter(":checked").trigger("init.imagify")}(jQuery,document,window),function(a,b,c,d){a.imagifyUser&&c.getJSON(ajaxurl,a.imagifyUser).done(function(a){c.isPlainObject(a)&&a.success&&(a.data.id=null,a.data.plan_id=null,a.data.is=[],c.each(a.data,function(b,d){var e=".imagify-user-"+b.replace(/_/g,"-");0===b.indexOf("is_")?d&&a.data.is.push(e):"is"!==b&&c(e).text(d)}),a.data.is.push("best-plan"),c(a.data.is.join(",")).removeClass("hidden"))})}(window,document,jQuery),function(a,b,c,d){function e(b){var d,e,f,g,h,i=!1,j=null;b&&(f=c("#imagify-custom-folders-selected"),g=f.find(".imagify-custom-folder-line"),h=g.find('[value="'+b+'"]'),h.length||(b=b.split("#///#"),d=b[1].replace(/\/+$/,"").toLowerCase(),e=a.imagify.template("imagify-custom-folder"),g.each(function(){var a=c(this),h=a.data("path").replace(/\/+$/,"").toLowerCase();return""!==h&&0===d.indexOf(h)?(i=!0,!1):d<h?(a.before(e({value:b[0],label:b[1]})),g=f.find(".imagify-custom-folder-line"),i=!0,!1):void 0}),i||(f.append(e({value:b[0],label:b[1]})),g=f.find(".imagify-custom-folder-line")),""!==d&&g.each(function(){var a=c(this),b=a.data("path").toLowerCase();null!==j&&0===b.indexOf(j)?a.find(".imagify-custom-folders-remove").trigger("click.imagify"):j=b}),f.next(".hidden").removeClass("hidden")))}imagifyOptions.getFilesTree&&(c("#imagify-add-custom-folder").on("click.imagify",function(){var a,b=c(this),d=[];b.attr("disabled")||(b.attr("disabled","disabled").next("img").attr("aria-hidden","false"),a=c("#imagify-custom-folders-selected"),a.find("input").each(function(){d.push(this.value)}),c.post(imagifyOptions.getFilesTree,{folder:"/",selected:d},null,"json").done(function(a){if(!a.success)return void swal({title:imagifyOptions.labels.error,html:a.data||"",type:"error",padding:0,customClass:"imagify-sweet-alert"});swal({title:imagifyOptions.labels.filesTreeTitle,html:'<div class="imagify-swal-subtitle">'+imagifyOptions.labels.filesTreeSubTitle+'</div><div class="imagify-swal-content"><p class="imagify-folders-information"><i class="dashicons dashicons-info" aria-hidden="true"></i>'+imagifyOptions.labels.cleaningInfo+'</p><ul id="imagify-folders-tree" class="imagify-folders-tree">'+a.data+"</ul></div>",type:"",customClass:"imagify-sweet-alert imagify-swal-has-subtitle imagify-folders-selection",showCancelButton:!0,padding:0,confirmButtonText:imagifyOptions.labels.confirmFilesTreeBtn,cancelButtonText:imagifySwal.labels.cancelButtonText,reverseButtons:!0}).then(function(){var a=c("#imagify-folders-tree input").serializeArray();a.length&&c.each(a,function(a,b){e(b.value)})}).catch(swal.noop)}).fail(function(){swal({title:imagifyOptions.labels.error,type:"error",customClass:"imagify-sweet-alert",padding:0})}).always(function(){b.removeAttr("disabled").next("img").attr("aria-hidden","true")}))}),c(b).on("click.imagify","#imagify-folders-tree [data-folder]",function(){var a=c(this),b=a.nextAll(".imagify-folders-sub-tree"),d=[];if(!a.attr("disabled")&&!a.siblings(":checkbox").is(":checked")){if(a.attr("disabled","disabled").addClass("imagify-loading"),b.length)return a.hasClass("imagify-is-open")?(b.addClass("hidden"),a.removeClass(" imagify-is-open")):(b.removeClass("hidden"),a.addClass("imagify-is-open")),void a.removeAttr("disabled").removeClass("imagify-loading");c("#imagify-custom-folders-selected").find("input").each(function(){d.push(this.value)}),c.post(imagifyOptions.getFilesTree,{folder:a.data("folder"),selected:d},null,"json").done(function(b){if(!b.success)return void swal({title:imagifyOptions.labels.error,html:b.data||"",type:"error",padding:0,customClass:"imagify-sweet-alert"});a.addClass("imagify-is-open").parent().append('<ul class="imagify-folders-sub-tree">'+b.data+"</ul>")}).fail(function(){swal({title:imagifyOptions.labels.error,type:"error",padding:0,customClass:"imagify-sweet-alert"})}).always(function(){a.removeAttr("disabled").removeClass("imagify-loading")})}}),c("#imagify-custom-folders").on("click.imagify",".imagify-custom-folders-remove",function(){var b=c(this).closest(".imagify-custom-folder-line").addClass("imagify-will-remove");a.setTimeout(function(){b.remove(),c("#imagify-custom-folders-selected").siblings(".imagify-success.hidden").removeClass("hidden")},750)}),c("#imagify-add-themes-to-custom-folder").on("click.imagify",function(){var a=c(this);e(a.data("theme")),e(a.data("theme-parent")),a.replaceWith("<p>"+imagifyOptions.labels.themesAdded+"</p>")}))}(window,document,jQuery),function(a,b,c,d){imagifyOptions.bulk&&(a.imagify.optionsBulk={fetchQueue:[],queue:[],processingQueue:[],fetchError:!1,error:!1,working:!1,processIsStopped:!0,processedMedia:0,totalMedia:0,$button:null,$progressWrap:null,$progressBar:null,$progressText:null,init:function(){this.$button=c("#imagify-generate-webp-versions"),this.$progressWrap=this.$button.siblings(".imagify-progress"),this.$progressBar=this.$progressWrap.find(".bar"),this.$progressText=this.$progressBar.find(".percent"),c("#imagify_convert_to_webp").on("change.imagify init.imagify",{imagifyOptionsBulk:this},this.toggleButton).trigger("init.imagify"),this.$button.on("click.imagify",{imagifyOptionsBulk:this},this.maybeLaunchAllProcesses),c(b).on("imagifybeat-send",{imagifyOptionsBulk:this},this.addQueueImagifybeat).on("imagifybeat-tick",{imagifyOptionsBulk:this},this.processQueueImagifybeat).on("imagifybeat-send",this.addRequirementsImagifybeat).on("imagifybeat-tick",{imagifyOptionsBulk:this},this.processRequirementsImagifybeat)},toggleButton:function(a){this.checked?a.data.imagifyOptionsBulk.$button.removeAttr("disabled"):a.data.imagifyOptionsBulk.$button.attr("disabled","disabled")},maybeLaunchAllProcesses:function(b){b.data.imagifyOptionsBulk&&!b.data.imagifyOptionsBulk.working&&(b.data.imagifyOptionsBulk.hasBlockingError(!0)||(b.data.imagifyOptionsBulk.fetchQueue=imagifyOptions.bulk.contexts,b.data.imagifyOptionsBulk.queue=[],b.data.imagifyOptionsBulk.processingQueue=[],b.data.imagifyOptionsBulk.fetchError=!1,b.data.imagifyOptionsBulk.error=!1,b.data.imagifyOptionsBulk.working=!0,b.data.imagifyOptionsBulk.processIsStopped=!1,b.data.imagifyOptionsBulk.processedMedia=0,b.data.imagifyOptionsBulk.totalMedia=0,b.data.imagifyOptionsBulk.$button.attr("disabled","disabled").find(".dashicons").addClass("rotate"),c(a).on("beforeunload.imagify",b.data.imagifyOptionsBulk.getConfirmMessage),a.imagify.beat.interval(15),a.imagify.beat.disableSuspend(),b.data.imagifyOptionsBulk.fetchIDs()))},getConfirmMessage:function(){return imagifyOptions.bulk.labels.processing},addQueueImagifybeat:function(a,b){a.data.imagifyOptionsBulk&&a.data.imagifyOptionsBulk.processingQueue.length&&(b[imagifyOptions.bulk.imagifybeatIDs.queue]=a.data.imagifyOptionsBulk.processingQueue)},processQueueImagifybeat:function(a,b){a.data.imagifyOptionsBulk&&void 0!==b[imagifyOptions.bulk.imagifybeatIDs.queue]&&c.each(b[imagifyOptions.bulk.imagifybeatIDs.queue],function(b,c){a.data.imagifyOptionsBulk.mediaProcessed(c)})},addRequirementsImagifybeat:function(a,b){b[imagifyOptions.bulk.imagifybeatIDs.requirements]=1},processRequirementsImagifybeat:function(a,b){a.data.imagifyOptionsBulk&&void 0===b[imagifyOptions.bulk.imagifybeatIDs.requirements]||(b=b[imagifyOptions.bulk.imagifybeatIDs.requirements],imagifyOptions.bulk.curlMissing=b.curl_missing,imagifyOptions.bulk.editorMissing=b.editor_missing,imagifyOptions.bulk.extHttpBlocked=b.external_http_blocked,imagifyOptions.bulk.apiDown=b.api_down,imagifyOptions.bulk.keyIsValid=b.key_is_valid,imagifyOptions.bulk.isOverQuota=b.is_over_quota)},fetchIDs:function(){var a,b;if(!this.processIsStopped){if(!this.fetchQueue.length)return this.queue.length?(this.$progressBar.removeAttr("style"),this.$progressText.text("0"+(this.totalMedia?"/"+this.totalMedia:"")),this.$progressWrap.slideDown().attr("aria-hidden","false"),void this.processQueue()):(this.fetchError||(this.fetchError="no-images"),this.stopProcess(this.fetchError),void(this.fetchError=!1));a=this,b=this.fetchQueue.shift(),c.get(this.getAjaxUrl("getMediaIds",b)).done(function(d){var e;if(!a.processIsStopped)return e=d.data&&d.data.message?d.data.message:imagifyOptions.bulk.ajaxErrorText,d.success&&c.isArray(d.data)?void(d.data.length&&(a.totalMedia+=d.data.length,a.queue.push({context:b,optimizeURL:a.getAjaxUrl("bulkProcess",b),mediaIDs:d.data}))):void(a.fetchError||(a.fetchError=e))}).fail(function(){a.fetchError||(a.fetchError="get-unoptimized-images")}).always(function(){a.fetchIDs()})}},processQueue:function(){var a=this;this.processIsStopped||(this.queue.length||this.processingQueue.length)&&c.each(this.queue,function(b,d){if(a.processingQueue.length>=imagifyOptions.bulk.bufferSize)return!1;c.each(d.mediaIDs,function(){if(a.processMedia({context:d.context,mediaID:d.mediaIDs.shift(),optimizeURL:d.optimizeURL}),d.mediaIDs.length||a.queue.shift(),a.processingQueue.length>=imagifyOptions.bulk.bufferSize)return!1})})},processMedia:function(a){var b=this,d={context:a.context,mediaID:a.mediaID};this.processingQueue.push({context:a.context,mediaID:a.mediaID}),c.post({url:a.optimizeURL,data:{media_id:a.mediaID,context:a.context},dataType:"json"}).done(function(a){a.success||b.mediaProcessed(d)}).fail(function(){b.mediaProcessed(d)})},mediaProcessed:function(a){var b=this;this.processIsStopped||(c.each(this.processingQueue,function(c,d){if(a.context===d.context&&a.mediaID===d.mediaID)return b.processingQueue.splice(c,1),!1}),++this.processedMedia,a.progress=Math.floor(this.processedMedia/this.totalMedia*100),this.$progressBar.css("width",a.progress+"%"),this.$progressText.text(this.processedMedia+"/"+this.totalMedia),this.queue.length||this.processingQueue.length?this.processQueue():this.totalMedia===this.processedMedia&&this.queueEmpty())},queueEmpty:function(){var b={};!1!==this.error&&(b="invalid-api-key"===this.error?{title:imagifyOptions.bulk.labels.invalidAPIKeyTitle,type:"info"}:"over-quota"===this.error?{title:imagifyOptions.bulk.labels.overQuotaTitle,html:c("#tmpl-imagify-overquota-alert").html(),type:"info",customClass:"imagify-swal-has-subtitle imagify-swal-error-header",showConfirmButton:!1}:"get-unoptimized-images"===this.error||"consumed-all-data"===this.error?{title:imagifyOptions.bulk.labels.getUnoptimizedImagesErrorTitle,html:imagifyOptions.bulk.labels.getUnoptimizedImagesErrorText,type:"info"}:"no-images"===this.error?{title:imagifyOptions.bulk.labels.nothingToDoTitle,html:imagifyOptions.bulk.labels.nothingToDoText,type:"info"}:{title:imagifyOptions.bulk.labels.error,html:this.error,type:"info"},this.displayError(b),this.error=!1),this.fetchQueue=[],this.queue=[],this.processingQueue=[],this.fetchError=!1,this.working=!1,this.processIsStopped=!1,this.processedMedia=0,this.totalMedia=0,a.imagify.beat.resetInterval(),a.imagify.beat.enableSuspend(),c(a).off("beforeunload.imagify",this.getConfirmMessage),this.$progressWrap.slideUp().attr("aria-hidden","true"),this.$progressBar.removeAttr("style"),this.$progressText.text("0"),this.$button.removeAttr("disabled").find(".dashicons").removeClass("rotate")},hasBlockingError:function(a){return a=void 0!==a&&a,imagifyOptions.bulk.curlMissing?(a&&this.displayError({html:imagifyOptions.bulk.labels.curlMissing}),!0):imagifyOptions.bulk.editorMissing?(a&&this.displayError({html:imagifyOptions.bulk.labels.editorMissing}),!0):imagifyOptions.bulk.extHttpBlocked?(a&&this.displayError({html:imagifyOptions.bulk.labels.extHttpBlocked}),!0):imagifyOptions.bulk.apiDown?(a&&this.displayError({html:imagifyOptions.bulk.labels.apiDown}),!0):imagifyOptions.bulk.keyIsValid?!!imagifyOptions.bulk.isOverQuota&&(a&&this.displayError({title:imagifyOptions.bulk.labels.overQuotaTitle,html:c("#tmpl-imagify-overquota-alert").html(),type:"info",customClass:"imagify-swal-has-subtitle imagify-swal-error-header",showConfirmButton:!1}),!0):(a&&this.displayError({title:imagifyOptions.bulk.labels.invalidAPIKeyTitle,type:"info"}),!0)},displayError:function(a,b,d){var e={title:"",html:"",type:"error",customClass:"",width:620,padding:0,showCloseButton:!0,showConfirmButton:!0};c.isPlainObject(a)?d=c.extend({},e,a):(d=d||{},d=c.extend({},e,{title:a||"",html:b||""},d)),d.title=d.title||imagifyOptions.bulk.labels.error,d.customClass+=" imagify-sweet-alert",swal(d).catch(swal.noop)},getAjaxUrl:function(b,c){var d;return d=ajaxurl+a.imagify.concat+"_wpnonce="+imagifyOptions.bulk.ajaxNonce,d+="&action="+imagifyOptions.bulk.ajaxActions[b],d+="&context="+c,d+="&imagify_action=generate_webp"},stopProcess:function(a){this.processIsStopped=!0,this.error=a,this.queueEmpty()}},a.imagify.optionsBulk.init())}(window,document,jQuery),function(a,b,c,d){var e=c.propHooks.checked;c.propHooks.checked={set:function(a,b,d){var f;return f=void 0===e?a[d]=b:e(a,b,d),c(a).trigger("change.imagify"),f}},c(".imagify-select-all").on("click.imagify",function(){var a=c(this),b=a.data("action"),d=a.closest(".imagify-select-all-buttons"),e=d.prev(".imagify-check-group"),f="imagify-is-inactive";if(a.hasClass(f))return!1;d.find(".imagify-select-all").removeClass(f).attr("aria-disabled","false"),a.addClass(f).attr("aria-disabled","true"),e.find(".imagify-row-check").prop("checked",function(){return!c(this).is(":hidden,:disabled")&&"select"===b})}),c(".imagify-check-group .imagify-row-check").on("change.imagify",function(){var a=c(this).closest(".imagify-check-group"),b=a.find(".imagify-row-check"),d=b.filter(":visible:enabled").length,e=b.filter(":visible:enabled:checked").length,f=a.next(".imagify-select-all-buttons"),g="imagify-is-inactive";0===e&&f.find('[data-action="unselect"]').addClass(g).attr("aria-disabled","true"),e===d&&f.find('[data-action="select"]').addClass(g).attr("aria-disabled","true"),e!==d&&e>0&&f.find(".imagify-select-all").removeClass(g).attr("aria-disabled","false")})}(window,document,jQuery);
classes/Imagifybeat/Actions.php ADDED
@@ -0,0 +1,438 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Imagify\Imagifybeat;
3
+
4
+ defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
5
+
6
+ /**
7
+ * Imagifybeat actions.
8
+ *
9
+ * @since 1.9.3
10
+ * @author Grégory Viguier
11
+ */
12
+ class Actions {
13
+ use \Imagify\Traits\FakeSingletonTrait;
14
+
15
+ /**
16
+ * The list of action IDs.
17
+ * Keys are related to method names, values are Imagifybeat IDs.
18
+ *
19
+ * @var array
20
+ * @since 1.9.3
21
+ * @access private
22
+ * @author Grégory Viguier
23
+ */
24
+ private $imagifybeat_ids = [
25
+ 'requirements' => 'imagify_requirements',
26
+ 'bulk_optimization_stats' => 'imagify_bulk_optimization_stats',
27
+ 'bulk_optimization_status' => 'imagify_bulk_optimization_status',
28
+ 'options_optimization_status' => 'imagify_options_optimization_status',
29
+ 'library_optimization_status' => 'imagify_library_optimization_status',
30
+ 'custom_folders_optimization_status' => 'imagify_custom_folders_optimization_status',
31
+ ];
32
+
33
+ /**
34
+ * Class init: launch hooks.
35
+ *
36
+ * @since 1.9.3
37
+ * @access public
38
+ * @author Grégory Viguier
39
+ */
40
+ public function init() {
41
+ foreach ( $this->imagifybeat_ids as $action => $imagifybeat_id ) {
42
+ add_filter( 'imagifybeat_received', [ $this, 'add_' . $action . '_to_response' ], 10, 2 );
43
+ }
44
+ }
45
+
46
+
47
+ /** ----------------------------------------------------------------------------------------- */
48
+ /** IMAGIFYBEAT CALLBACKS =================================================================== */
49
+ /** ----------------------------------------------------------------------------------------- */
50
+
51
+ /**
52
+ * Add requirements to Imagifybeat data.
53
+ *
54
+ * @since 1.9.3
55
+ * @access public
56
+ * @author Grégory Viguier
57
+ *
58
+ * @param array $response The Imagifybeat response.
59
+ * @param array $data The $_POST data sent.
60
+ * @return array
61
+ */
62
+ public function add_requirements_to_response( $response, $data ) {
63
+ $imagifybeat_id = $this->get_imagifybeat_id_for_callback( __FUNCTION__ );
64
+
65
+ if ( ! $imagifybeat_id || empty( $data[ $imagifybeat_id ] ) ) {
66
+ return $response;
67
+ }
68
+
69
+ $is_blocked = \Imagify_Requirements::is_imagify_blocked();
70
+ $is_api_up = \Imagify_Requirements::is_api_up();
71
+ $is_key_valid = \Imagify_Requirements::is_api_key_valid();
72
+ $is_over_quota = \Imagify_Requirements::is_over_quota();
73
+
74
+ $response[ $imagifybeat_id ] = [
75
+ 'curl_missing' => ! \Imagify_Requirements::supports_curl(),
76
+ 'editor_missing' => ! \Imagify_Requirements::supports_image_editor(),
77
+ 'external_http_blocked' => $is_blocked,
78
+ 'api_down' => $is_blocked || ! $is_api_up,
79
+ 'key_is_valid' => ! $is_blocked && $is_api_up && $is_key_valid,
80
+ 'is_over_quota' => ! $is_blocked && $is_api_up && $is_key_valid && $is_over_quota,
81
+ ];
82
+
83
+ return $response;
84
+ }
85
+
86
+ /**
87
+ * Add bulk stats to Imagifybeat data.
88
+ *
89
+ * @since 1.9.3
90
+ * @access public
91
+ * @author Grégory Viguier
92
+ *
93
+ * @param array $response The Imagifybeat response.
94
+ * @param array $data The $_POST data sent.
95
+ * @return array
96
+ */
97
+ public function add_bulk_optimization_stats_to_response( $response, $data ) {
98
+ $imagifybeat_id = $this->get_imagifybeat_id_for_callback( __FUNCTION__ );
99
+
100
+ if ( ! $imagifybeat_id || empty( $data[ $imagifybeat_id ] ) ) {
101
+ return $response;
102
+ }
103
+
104
+ $folder_types = array_flip( array_filter( $data[ $imagifybeat_id ] ) );
105
+
106
+ $response[ $imagifybeat_id ] = imagify_get_bulk_stats(
107
+ $folder_types,
108
+ [
109
+ 'fullset' => true,
110
+ ]
111
+ );
112
+
113
+ return $response;
114
+ }
115
+
116
+ /**
117
+ * Look for media where status has changed, compared to what Imagifybeat sends.
118
+ * This is used in the bulk optimization page.
119
+ *
120
+ * @since 1.9.3
121
+ * @access public
122
+ * @author Grégory Viguier
123
+ *
124
+ * @param array $response The Imagifybeat response.
125
+ * @param array $data The $_POST data sent.
126
+ * @return array
127
+ */
128
+ public function add_bulk_optimization_status_to_response( $response, $data ) {
129
+ $imagifybeat_id = $this->get_imagifybeat_id_for_callback( __FUNCTION__ );
130
+
131
+ if ( ! $imagifybeat_id || empty( $data[ $imagifybeat_id ] ) || ! is_array( $data[ $imagifybeat_id ] ) ) {
132
+ return $response;
133
+ }
134
+
135
+ $statuses = [];
136
+
137
+ foreach ( $data[ $imagifybeat_id ] as $item ) {
138
+ if ( empty( $statuses[ $item['context'] ] ) ) {
139
+ $statuses[ $item['context'] ] = [];
140
+ }
141
+
142
+ $statuses[ $item['context'] ][ '_' . $item['mediaID'] ] = 1;
143
+ }
144
+
145
+ $results = $this->get_modified_optimization_statuses( $statuses );
146
+
147
+ if ( ! $results ) {
148
+ return $response;
149
+ }
150
+
151
+ $response[ $imagifybeat_id ] = [];
152
+
153
+ // Sanitize received data and grab some other info.
154
+ foreach ( $results as $context_id => $media_atts ) {
155
+ $process = imagify_get_optimization_process( $media_atts['media_id'], $media_atts['context'] );
156
+ $optim_data = $process->get_data();
157
+
158
+ if ( $optim_data->is_optimized() ) {
159
+ // Successfully optimized.
160
+ $full_size_data = $optim_data->get_size_data();
161
+ $response[ $imagifybeat_id ][] = [
162
+ 'mediaID' => $media_atts['media_id'],
163
+ 'context' => $media_atts['context'],
164
+ 'success' => true,
165
+ 'status' => 'optimized',
166
+ // Raw data.
167
+ 'originalOverallSize' => $full_size_data['original_size'],
168
+ 'newOverallSize' => $full_size_data['optimized_size'],
169
+ 'overallSaving' => $full_size_data['original_size'] - $full_size_data['optimized_size'],
170
+ 'thumbnailsCount' => $optim_data->get_optimized_sizes_count(),
171
+ // Human readable data.
172
+ 'originalSizeHuman' => imagify_size_format( $full_size_data['original_size'], 2 ),
173
+ 'newSizeHuman' => imagify_size_format( $full_size_data['optimized_size'], 2 ),
174
+ 'overallSavingHuman' => imagify_size_format( $full_size_data['original_size'] - $full_size_data['optimized_size'], 2 ),
175
+ 'originalOverallSizeHuman' => imagify_size_format( $full_size_data['original_size'], 2 ),
176
+ 'percentHuman' => $full_size_data['percent'] . '%',
177
+ ];
178
+ } elseif ( $optim_data->is_already_optimized() ) {
179
+ // Already optimized.
180
+ $response[ $imagifybeat_id ][] = [
181
+ 'mediaID' => $media_atts['media_id'],
182
+ 'context' => $media_atts['context'],
183
+ 'success' => true,
184
+ 'status' => 'already-optimized',
185
+ ];
186
+ } else {
187
+ // Error.
188
+ $full_size_data = $optim_data->get_size_data();
189
+ $message = ! empty( $full_size_data['error'] ) ? $full_size_data['error'] : '';
190
+ $status = 'error';
191
+
192
+ if ( 'You\'ve consumed all your data. You have to upgrade your account to continue' === $message ) {
193
+ $status = 'over-quota';
194
+ }
195
+
196
+ $response[ $imagifybeat_id ][] = [
197
+ 'mediaID' => $media_atts['media_id'],
198
+ 'context' => $media_atts['context'],
199
+ 'success' => false,
200
+ 'status' => $status,
201
+ 'error' => imagify_translate_api_message( $message ),
202
+ ];
203
+ }
204
+ }
205
+
206
+ return $response;
207
+ }
208
+
209
+ /**
210
+ * Look for media where status has changed, compared to what Imagifybeat sends.
211
+ * This is used in the settings page.
212
+ *
213
+ * @since 1.9
214
+ * @author Grégory Viguier
215
+ *
216
+ * @param array $response The Imagifybeat response.
217
+ * @param array $data The $_POST data sent.
218
+ * @return array
219
+ */
220
+ public function add_options_optimization_status_to_response( $response, $data ) {
221
+ $imagifybeat_id = $this->get_imagifybeat_id_for_callback( __FUNCTION__ );
222
+
223
+ if ( ! $imagifybeat_id || empty( $data[ $imagifybeat_id ] ) || ! is_array( $data[ $imagifybeat_id ] ) ) {
224
+ return $response;
225
+ }
226
+
227
+ $statuses = [];
228
+
229
+ foreach ( $data[ $imagifybeat_id ] as $item ) {
230
+ if ( empty( $statuses[ $item['context'] ] ) ) {
231
+ $statuses[ $item['context'] ] = [];
232
+ }
233
+
234
+ $statuses[ $item['context'] ][ '_' . $item['mediaID'] ] = 1;
235
+ }
236
+
237
+ $results = $this->get_modified_optimization_statuses( $statuses );
238
+
239
+ if ( ! $results ) {
240
+ return $response;
241
+ }
242
+
243
+ $response[ $imagifybeat_id ] = [];
244
+
245
+ foreach ( $results as $result ) {
246
+ $response[ $imagifybeat_id ][] = [
247
+ 'mediaID' => $result['media_id'],
248
+ 'context' => $result['context'],
249
+ ];
250
+ }
251
+
252
+ return $response;
253
+ }
254
+
255
+ /**
256
+ * Look for media where status has changed, compared to what Imagifybeat sends.
257
+ * This is used in the WP Media Library.
258
+ *
259
+ * @since 1.9.3
260
+ * @access public
261
+ * @author Grégory Viguier
262
+ *
263
+ * @param array $response The Imagifybeat response.
264
+ * @param array $data The $_POST data sent.
265
+ * @return array
266
+ */
267
+ public function add_library_optimization_status_to_response( $response, $data ) {
268
+ $imagifybeat_id = $this->get_imagifybeat_id_for_callback( __FUNCTION__ );
269
+
270
+ if ( ! $imagifybeat_id || empty( $data[ $imagifybeat_id ] ) || ! is_array( $data[ $imagifybeat_id ] ) ) {
271
+ return $response;
272
+ }
273
+
274
+ $response[ $imagifybeat_id ] = $this->get_modified_optimization_statuses( $data[ $imagifybeat_id ] );
275
+
276
+ if ( ! $response[ $imagifybeat_id ] ) {
277
+ return $response;
278
+ }
279
+
280
+ // Sanitize received data and grab some other info.
281
+ foreach ( $response[ $imagifybeat_id ] as $context_id => $media_atts ) {
282
+ $process = imagify_get_optimization_process( $media_atts['media_id'], $media_atts['context'] );
283
+
284
+ $response[ $imagifybeat_id ][ $context_id ] = get_imagify_media_column_content( $process, false );
285
+ }
286
+
287
+ return $response;
288
+ }
289
+
290
+ /**
291
+ * Look for media where status has changed, compared to what Imagifybeat sends.
292
+ * This is used in the custom folders list (the "Other Media" page).
293
+ *
294
+ * @since 1.9.3
295
+ * @access public
296
+ * @author Grégory Viguier
297
+ *
298
+ * @param array $response The Imagifybeat response.
299
+ * @param array $data The $_POST data sent.
300
+ * @return array
301
+ */
302
+ public function add_custom_folders_optimization_status_to_response( $response, $data ) {
303
+ $imagifybeat_id = $this->get_imagifybeat_id_for_callback( __FUNCTION__ );
304
+
305
+ if ( ! $imagifybeat_id || empty( $data[ $imagifybeat_id ] ) || ! is_array( $data[ $imagifybeat_id ] ) ) {
306
+ return $response;
307
+ }
308
+
309
+ $response[ $imagifybeat_id ] = $this->get_modified_optimization_statuses( $data[ $imagifybeat_id ] );
310
+
311
+ if ( ! $response[ $imagifybeat_id ] ) {
312
+ return $response;
313
+ }
314
+
315
+ $admin_ajax_post = \Imagify_Admin_Ajax_Post::get_instance();
316
+ $list_table = new \Imagify_Files_List_Table( [
317
+ 'screen' => 'imagify-files',
318
+ ] );
319
+
320
+ // Sanitize received data and grab some other info.
321
+ foreach ( $response[ $imagifybeat_id ] as $context_id => $media_atts ) {
322
+ $process = imagify_get_optimization_process( $media_atts['media_id'], $media_atts['context'] );
323
+
324
+ $response[ $imagifybeat_id ][ $context_id ] = $admin_ajax_post->get_media_columns( $process, $list_table );
325
+ }
326
+
327
+ return $response;
328
+ }
329
+
330
+
331
+ /** ----------------------------------------------------------------------------------------- */
332
+ /** TOOLS =================================================================================== */
333
+ /** ----------------------------------------------------------------------------------------- */
334
+
335
+ /**
336
+ * Look for media where status has changed, compared to what Imagifybeat sends.
337
+ *
338
+ * @since 1.9.3
339
+ * @access public
340
+ * @author Grégory Viguier
341
+ *
342
+ * @param array $data The data received.
343
+ * @return array
344
+ */
345
+ public function get_modified_optimization_statuses( $data ) {
346
+ if ( ! $data ) {
347
+ return [];
348
+ }
349
+
350
+ $output = [];
351
+
352
+ // Sanitize received data and grab some other info.
353
+ foreach ( $data as $context => $media_statuses ) {
354
+ if ( ! $context || ! $media_statuses || ! is_array( $media_statuses ) ) {
355
+ continue;
356
+ }
357
+
358
+ // Sanitize the IDs: IDs come as strings, prefixed with an undescore character (to prevent JavaScript from screwing everything).
359
+ $media_ids = array_keys( $media_statuses );
360
+ $media_ids = array_map( function( $media_id ) {
361
+ return (int) substr( $media_id, 1 );
362
+ }, $media_ids );
363
+ $media_ids = array_filter( $media_ids );
364
+
365
+ if ( ! $media_ids ) {
366
+ continue;
367
+ }
368
+
369
+ // Sanitize the context.
370
+ $context_instance = imagify_get_context( $context );
371
+ $context = $context_instance->get_name();
372
+ $process_class_name = imagify_get_optimization_process_class_name( $context );
373
+ $transient_name = sprintf( $process_class_name::LOCK_NAME, $context, '%' );
374
+ $is_network_wide = $context_instance->is_network_wide();
375
+
376
+ \Imagify_DB::cache_process_locks( $context, $media_ids );
377
+
378
+ // Now that everything is cached for this context, we can get the transients without hitting the DB.
379
+ foreach ( $media_ids as $id ) {
380
+ $is_locked = (bool) $media_statuses[ '_' . $id ];
381
+ $option_name = str_replace( '%', $id, $transient_name );
382
+
383
+ if ( $is_network_wide ) {
384
+ $in_db = (bool) get_site_transient( $option_name );
385
+ } else {
386
+ $in_db = (bool) get_transient( $option_name );
387
+ }
388
+
389
+ if ( $is_locked === $in_db ) {
390
+ continue;
391
+ }
392
+
393
+ $output[ $context . '_' . $id ] = [
394
+ 'media_id' => $id,
395
+ 'context' => $context,
396
+ ];
397
+ }
398
+ }
399
+
400
+ return $output;
401
+ }
402
+
403
+ /**
404
+ * Get an Imagifybeat ID, given an action.
405
+ *
406
+ * @since 1.9.3
407
+ * @access public
408
+ * @author Grégory Viguier
409
+ *
410
+ * @param string $action An action corresponding to the ID we want.
411
+ * @return string|bool The ID. False on failure.
412
+ */
413
+ public function get_imagifybeat_id( $action ) {
414
+ if ( ! empty( $this->imagifybeat_ids[ $action ] ) ) {
415
+ return $this->imagifybeat_ids[ $action ];
416
+ }
417
+
418
+ return false;
419
+ }
420
+
421
+ /**
422
+ * Get an Imagifybeat ID, given a callback name.
423
+ *
424
+ * @since 1.9.3
425
+ * @access private
426
+ * @author Grégory Viguier
427
+ *
428
+ * @param string $callback A method’s name.
429
+ * @return string|bool The ID. False on failure.
430
+ */
431
+ private function get_imagifybeat_id_for_callback( $callback ) {
432
+ if ( preg_match( '@^add_(?<id>.+)_to_response$@', $callback, $matches ) ) {
433
+ return $this->get_imagifybeat_id( $matches['id'] );
434
+ }
435
+
436
+ return false;
437
+ }
438
+ }
classes/Imagifybeat/Core.php ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Imagify\Imagifybeat;
3
+
4
+ defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
5
+
6
+ /**
7
+ * Imagifybeat core.
8
+ *
9
+ * @since 1.9.3
10
+ * @author Grégory Viguier
11
+ */
12
+ class Core {
13
+ use \Imagify\Traits\FakeSingletonTrait;
14
+
15
+ /**
16
+ * Class init: launch hooks.
17
+ *
18
+ * @since 1.9.3
19
+ * @access public
20
+ * @author Grégory Viguier
21
+ */
22
+ public function init() {
23
+ add_action( 'wp_ajax_imagifybeat', [ $this, 'core_handler' ], 1 );
24
+ add_filter( 'imagifybeat_refresh_nonces', [ $this, 'refresh_imagifybeat_nonces' ] );
25
+ }
26
+
27
+ /**
28
+ * Ajax handler for the Imagifybeat API.
29
+ *
30
+ * Runs when the user is logged in.
31
+ *
32
+ * @since 1.9.3
33
+ * @access public
34
+ * @author Grégory Viguier
35
+ */
36
+ public function core_handler() {
37
+ if ( empty( $_POST['_nonce'] ) ) {
38
+ wp_send_json_error();
39
+ }
40
+
41
+ $data = [];
42
+ $response = [];
43
+ $nonce_state = wp_verify_nonce( wp_unslash( $_POST['_nonce'] ), 'imagifybeat-nonce' );
44
+
45
+ // Screen_id is the same as $current_screen->id and the JS global 'pagenow'.
46
+ if ( ! empty( $_POST['screen_id'] ) ) {
47
+ $screen_id = sanitize_key( $_POST['screen_id'] );
48
+ } else {
49
+ $screen_id = 'front';
50
+ }
51
+
52
+ if ( ! empty( $_POST['data'] ) ) {
53
+ $data = wp_unslash( (array) $_POST['data'] );
54
+ }
55
+
56
+ if ( 1 !== $nonce_state ) {
57
+ /**
58
+ * Filters the nonces to send.
59
+ *
60
+ * @since 1.9.3
61
+ * @author Grégory Viguier
62
+ *
63
+ * @param array $response The Imagifybeat response.
64
+ * @param array $data The $_POST data sent.
65
+ * @param string $screen_id The screen id.
66
+ */
67
+ $response = apply_filters( 'imagifybeat_refresh_nonces', $response, $data, $screen_id );
68
+
69
+ if ( false === $nonce_state ) {
70
+ // User is logged in but nonces have expired.
71
+ $response['nonces_expired'] = true;
72
+ wp_send_json( $response );
73
+ }
74
+ }
75
+
76
+ if ( ! empty( $data ) ) {
77
+ /**
78
+ * Filters the Imagifybeat response received.
79
+ *
80
+ * @since 1.9.3
81
+ * @author Grégory Viguier
82
+ *
83
+ * @param array $response The Imagifybeat response.
84
+ * @param array $data The $_POST data sent.
85
+ * @param string $screen_id The screen id.
86
+ */
87
+ $response = apply_filters( 'imagifybeat_received', $response, $data, $screen_id );
88
+ }
89
+
90
+ /**
91
+ * Filters the Imagifybeat response sent.
92
+ *
93
+ * @since 1.9.3
94
+ * @author Grégory Viguier
95
+ *
96
+ * @param array $response The Imagifybeat response.
97
+ * @param string $screen_id The screen id.
98
+ */
99
+ $response = apply_filters( 'imagifybeat_send', $response, $screen_id );
100
+
101
+ /**
102
+ * Fires when Imagifybeat ticks in logged-in environments.
103
+ *
104
+ * Allows the transport to be easily replaced with long-polling.
105
+ *
106
+ * @since 1.9.3
107
+ * @author Grégory Viguier
108
+ *
109
+ * @param array $response The Imagifybeat response.
110
+ * @param string $screen_id The screen id.
111
+ */
112
+ do_action( 'imagifybeat_tick', $response, $screen_id );
113
+
114
+ // Send the current time according to the server.
115
+ $response['server_time'] = time();
116
+
117
+ wp_send_json( $response );
118
+ }
119
+
120
+ /**
121
+ * Add the latest Imagifybeat nonce to the Imagifybeat response.
122
+ *
123
+ * @since 1.9.3
124
+ * @access public
125
+ * @author Grégory Viguier
126
+ *
127
+ * @param array $response The Imagifybeat response.
128
+ * @return array The Imagifybeat response.
129
+ */
130
+ public function refresh_imagifybeat_nonces( $response ) {
131
+ // Refresh the Imagifybeat nonce.
132
+ $response['imagifybeat_nonce'] = wp_create_nonce( 'imagifybeat-nonce' );
133
+ return $response;
134
+ }
135
+
136
+ /**
137
+ * Get Imagifybeat settings.
138
+ *
139
+ * @since 1.9.3
140
+ * @access public
141
+ * @author Grégory Viguier
142
+ *
143
+ * @return array
144
+ */
145
+ public function get_settings() {
146
+ global $pagenow;
147
+
148
+ $settings = [];
149
+
150
+ if ( ! is_admin() ) {
151
+ $settings['ajaxurl'] = admin_url( 'admin-ajax.php', 'relative' );
152
+ }
153
+
154
+ if ( is_user_logged_in() ) {
155
+ $settings['nonce'] = wp_create_nonce( 'imagifybeat-nonce' );
156
+ }
157
+
158
+ if ( 'customize.php' === $pagenow ) {
159
+ $settings['screenId'] = 'customize';
160
+ }
161
+
162
+ /**
163
+ * Filters the Imagifybeat settings.
164
+ *
165
+ * @since 1.9.3
166
+ * @author Grégory Viguier
167
+ *
168
+ * @param array $settings Imagifybeat settings array.
169
+ */
170
+ return (array) apply_filters( 'imagifybeat_settings', $settings );
171
+ }
172
+ }
classes/Optimization/Process/AbstractProcess.php CHANGED
@@ -643,7 +643,7 @@ abstract class AbstractProcess implements ProcessInterface {
643
  $response = $this->maybe_resize( $thumb_size, $file );
644
 
645
  if ( ! is_wp_error( $response ) ) {
646
- // Resizement succeeded: optimize the file.
647
  $response = $file->optimize( [
648
  'backup' => ! $response['backuped'] && $this->can_backup( $size ),
649
  'backup_path' => $media->get_raw_backup_path(),
@@ -1082,7 +1082,7 @@ abstract class AbstractProcess implements ProcessInterface {
1082
  'no_dimensions',
1083
  sprintf(
1084
  /* translators: %s is an error message. */
1085
- __( 'Resizement failed: %s', 'imagify' ),
1086
  __( 'Imagify could not get the image dimensions.', 'imagify' )
1087
  )
1088
  );
@@ -1107,8 +1107,8 @@ abstract class AbstractProcess implements ProcessInterface {
1107
  'resize_failure',
1108
  sprintf(
1109
  /* translators: %s is an error message. */
1110
- __( 'Resizement failed: %s', 'imagify' ),
1111
- $resized_path->get_message()
1112
  )
1113
  );
1114
  }
@@ -1123,7 +1123,7 @@ abstract class AbstractProcess implements ProcessInterface {
1123
  sprintf(
1124
  /* translators: %s is an error message. */
1125
  __( 'Backup failed: %s', 'imagify' ),
1126
- $backuped->get_message()
1127
  )
1128
  );
1129
  }
643
  $response = $this->maybe_resize( $thumb_size, $file );
644
 
645
  if ( ! is_wp_error( $response ) ) {
646
+ // Resizing succeeded: optimize the file.
647
  $response = $file->optimize( [
648
  'backup' => ! $response['backuped'] && $this->can_backup( $size ),
649
  'backup_path' => $media->get_raw_backup_path(),
1082
  'no_dimensions',
1083
  sprintf(
1084
  /* translators: %s is an error message. */
1085
+ __( 'Resizing failed: %s', 'imagify' ),
1086
  __( 'Imagify could not get the image dimensions.', 'imagify' )
1087
  )
1088
  );
1107
  'resize_failure',
1108
  sprintf(
1109
  /* translators: %s is an error message. */
1110
+ __( 'Resizing failed: %s', 'imagify' ),
1111
+ $resized_path->get_error_message()
1112
  )
1113
  );
1114
  }
1123
  sprintf(
1124
  /* translators: %s is an error message. */
1125
  __( 'Backup failed: %s', 'imagify' ),
1126
+ $backuped->get_error_message()
1127
  )
1128
  );
1129
  }
classes/Webp/Picture/Display.php CHANGED
@@ -50,7 +50,7 @@ class Display {
50
  * @author Grégory Viguier
51
  */
52
  public function init() {
53
- add_action( 'template_redirect', [ $this, 'start_content_process' ], 6 );
54
  }
55
 
56
  /** ----------------------------------------------------------------------------------------- */
@@ -167,10 +167,16 @@ class Display {
167
  */
168
  protected function build_picture_tag( $image ) {
169
  $to_remove = [
170
- 'alt' => '',
171
- 'data-lazy-src' => '',
172
- 'data-src' => '',
173
- 'sizes' => '',
 
 
 
 
 
 
174
  ];
175
 
176
  $attributes = array_diff_key( $image['attributes'], $to_remove );
@@ -216,9 +222,10 @@ class Display {
216
  * @return string A <source> tag.
217
  */
218
  protected function build_source_tag( $image ) {
219
- $attributes = [
220
- 'type' => 'image/webp',
221
- 'srcset' => [
 
222
  $image['src']['webp_url'],
223
  ],
224
  ];
@@ -232,14 +239,27 @@ class Display {
232
  continue;
233
  }
234
 
235
- $attributes['srcset'][] = $srcset['webp_url'] . ' ' . $srcset['descriptor'];
236
  }
237
  }
238
 
239
- $attributes['srcset'] = implode( ', ', $attributes['srcset'] );
240
 
241
- if ( ! empty( $image['attributes']['sizes'] ) ) {
242
- $attributes['sizes'] = $image['attributes']['sizes'];
 
 
 
 
 
 
 
 
 
 
 
 
 
243
  }
244
 
245
  /**
@@ -268,19 +288,6 @@ class Display {
268
  * @return string A <img> tag.
269
  */
270
  protected function build_img_tag( $image ) {
271
- $attributes = $image['attributes'];
272
- $attributes['src'] = $image['src']['url'];
273
-
274
- if ( ! empty( $image['srcset'] ) ) {
275
- $attributes['srcset'] = [];
276
-
277
- foreach ( $image['srcset'] as $srcset ) {
278
- $attributes['srcset'][] = $srcset['url'] . ' ' . $srcset['descriptor'];
279
- }
280
-
281
- $attributes['srcset'] = implode( ', ', $attributes['srcset'] );
282
- }
283
-
284
  $to_remove = [
285
  'class' => '',
286
  'height' => '',
@@ -290,7 +297,7 @@ class Display {
290
  'width' => '',
291
  ];
292
 
293
- $attributes = array_diff_key( $attributes, $to_remove );
294
 
295
  /**
296
  * Filter the attributes to be added to the <img> tag.
@@ -385,6 +392,10 @@ class Display {
385
  }
386
 
387
  foreach ( $image['srcset'] as $j => $srcset ) {
 
 
 
 
388
  if ( empty( $srcset['webp_exists'] ) || empty( $srcset['webp_url'] ) ) {
389
  unset( $images[ $i ]['srcset'][ $j ]['webp_url'] );
390
  }
@@ -444,7 +455,16 @@ class Display {
444
  }
445
 
446
  // Deal with the src attribute.
447
- if ( empty( $attributes['src'] ) ) {
 
 
 
 
 
 
 
 
 
448
  // No src attribute.
449
  return false;
450
  }
@@ -455,7 +475,7 @@ class Display {
455
  $extensions = implode( '|', $extensions );
456
  }
457
 
458
- if ( ! preg_match( '@^(?<src>(?:https?:)?//.+\.(?<extension>' . $extensions . '))(?<query>\?.*)?$@i', $attributes['src'], $src ) ) {
459
  // Not a supported image format.
460
  return false;
461
  }
@@ -465,22 +485,33 @@ class Display {
465
  $webp_url .= ! empty( $src['query'] ) ? $src['query'] : '';
466
 
467
  $data = [
468
- 'tag' => $image,
469
- 'attributes' => $attributes,
470
- 'src' => [
471
- 'url' => $attributes['src'],
 
472
  'webp_url' => $webp_url,
473
  'webp_path' => $webp_path,
474
  'webp_exists' => $webp_path && $this->filesystem->exists( $webp_path ),
475
  ],
476
- 'srcset' => [],
 
477
  ];
478
 
479
- unset( $data['attributes']['src'], $data['attributes']['srcset'] );
480
-
481
  // Deal with the srcset attribute.
482
- if ( ! empty( $attributes['srcset'] ) ) {
483
- $srcset = explode( ',', $attributes['srcset'] );
 
 
 
 
 
 
 
 
 
 
 
484
 
485
  foreach ( $srcset as $srcs ) {
486
  $srcs = preg_split( '/\s+/', trim( $srcs ) );
@@ -533,7 +564,7 @@ class Display {
533
  return false;
534
  }
535
 
536
- if ( ! isset( $data['tag'], $data['attributes'], $data['src'], $data['srcset'] ) ) {
537
  return false;
538
  }
539
 
@@ -565,21 +596,36 @@ class Display {
565
  * @return string|bool The file path. False on failure.
566
  */
567
  protected function url_to_path( $url ) {
568
- static $scheme;
569
  static $uploads_url;
570
  static $uploads_dir;
571
  static $root_url;
572
  static $root_dir;
 
 
573
 
574
- if ( ! isset( $scheme ) ) {
575
- $scheme = is_ssl() ? 'https' : 'http';
576
- $uploads_url = set_url_scheme( $this->filesystem->get_upload_baseurl(), $scheme );
577
  $uploads_dir = $this->filesystem->get_upload_basedir( true );
578
- $root_url = set_url_scheme( $this->filesystem->get_site_root_url(), $scheme );
579
  $root_dir = $this->filesystem->get_site_root();
 
 
 
 
 
 
 
 
 
 
 
580
  }
581
 
582
- $url = set_url_scheme( $url, $scheme );
 
 
 
 
583
 
584
  if ( stripos( $url, $uploads_url ) === 0 ) {
585
  return str_ireplace( $uploads_url, $uploads_dir, $url );
@@ -591,4 +637,108 @@ class Display {
591
 
592
  return false;
593
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
594
  }
50
  * @author Grégory Viguier
51
  */
52
  public function init() {
53
+ add_action( 'template_redirect', [ $this, 'start_content_process' ], -1000 );
54
  }
55
 
56
  /** ----------------------------------------------------------------------------------------- */
167
  */
168
  protected function build_picture_tag( $image ) {
169
  $to_remove = [
170
+ 'alt' => '',
171
+ 'data-lazy-src' => '',
172
+ 'data-src' => '',
173
+ 'src' => '',
174
+ 'data-lazy-srcset' => '',
175
+ 'data-srcset' => '',
176
+ 'srcset' => '',
177
+ 'data-lazy-sizes' => '',
178
+ 'data-sizes' => '',
179
+ 'sizes' => '',
180
  ];
181
 
182
  $attributes = array_diff_key( $image['attributes'], $to_remove );
222
  * @return string A <source> tag.
223
  */
224
  protected function build_source_tag( $image ) {
225
+ $srcset_source = ! empty( $image['srcset_attribute'] ) ? $image['srcset_attribute'] : $image['src_attribute'] . 'set';
226
+ $attributes = [
227
+ 'type' => 'image/webp',
228
+ $srcset_source => [
229
  $image['src']['webp_url'],
230
  ],
231
  ];
239
  continue;
240
  }
241
 
242
+ $attributes[ $srcset_source ][] = $srcset['webp_url'] . ' ' . $srcset['descriptor'];
243
  }
244
  }
245
 
246
+ $attributes[ $srcset_source ] = implode( ', ', $attributes[ $srcset_source ] );
247
 
248
+ foreach ( [ 'data-lazy-srcset', 'data-srcset', 'srcset' ] as $srcset_attr ) {
249
+ if ( ! empty( $image['attributes'][ $srcset_attr ] ) && $srcset_attr !== $srcset_source ) {
250
+ $attributes[ $srcset_attr ] = $image['attributes'][ $srcset_attr ];
251
+ }
252
+ }
253
+
254
+ if ( 'srcset' !== $srcset_source && empty( $attributes['srcset'] ) && ! empty( $image['attributes']['src'] ) ) {
255
+ // Lazyload: the "src" attr should contain a placeholder (a data image or a blank.gif ).
256
+ $attributes['srcset'] = $image['attributes']['src'];
257
+ }
258
+
259
+ foreach ( [ 'data-lazy-sizes', 'data-sizes', 'sizes' ] as $sizes_attr ) {
260
+ if ( ! empty( $image['attributes'][ $sizes_attr ] ) ) {
261
+ $attributes[ $sizes_attr ] = $image['attributes'][ $sizes_attr ];
262
+ }
263
  }
264
 
265
  /**
288
  * @return string A <img> tag.
289
  */
290
  protected function build_img_tag( $image ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
291
  $to_remove = [
292
  'class' => '',
293
  'height' => '',
297
  'width' => '',
298
  ];
299
 
300
+ $attributes = array_diff_key( $image['attributes'], $to_remove );
301
 
302
  /**
303
  * Filter the attributes to be added to the <img> tag.
392
  }
393
 
394
  foreach ( $image['srcset'] as $j => $srcset ) {
395
+ if ( ! is_array( $srcset ) ) {
396
+ continue;
397
+ }
398
+
399
  if ( empty( $srcset['webp_exists'] ) || empty( $srcset['webp_url'] ) ) {
400
  unset( $images[ $i ]['srcset'][ $j ]['webp_url'] );
401
  }
455
  }
456
 
457
  // Deal with the src attribute.
458
+ $src_source = false;
459
+
460
+ foreach ( [ 'data-lazy-src', 'data-src', 'src' ] as $src_attr ) {
461
+ if ( ! empty( $attributes[ $src_attr ] ) ) {
462
+ $src_source = $src_attr;
463
+ break;
464
+ }
465
+ }
466
+
467
+ if ( ! $src_source ) {
468
  // No src attribute.
469
  return false;
470
  }
475
  $extensions = implode( '|', $extensions );
476
  }
477
 
478
+ if ( ! preg_match( '@^(?<src>(?:https?:)?//.+\.(?<extension>' . $extensions . '))(?<query>\?.*)?$@i', $attributes[ $src_source ], $src ) ) {
479
  // Not a supported image format.
480
  return false;
481
  }
485
  $webp_url .= ! empty( $src['query'] ) ? $src['query'] : '';
486
 
487
  $data = [
488
+ 'tag' => $image,
489
+ 'attributes' => $attributes,
490
+ 'src_attribute' => $src_source,
491
+ 'src' => [
492
+ 'url' => $attributes[ $src_source ],
493
  'webp_url' => $webp_url,
494
  'webp_path' => $webp_path,
495
  'webp_exists' => $webp_path && $this->filesystem->exists( $webp_path ),
496
  ],
497
+ 'srcset_attribute' => false,
498
+ 'srcset' => [],
499
  ];
500
 
 
 
501
  // Deal with the srcset attribute.
502
+ $srcset_source = false;
503
+
504
+ foreach ( [ 'data-lazy-srcset', 'data-srcset', 'srcset' ] as $srcset_attr ) {
505
+ if ( ! empty( $attributes[ $srcset_attr ] ) ) {
506
+ $srcset_source = $srcset_attr;
507
+ break;
508
+ }
509
+ }
510
+
511
+ if ( $srcset_source ) {
512
+ $data['srcset_attribute'] = $srcset_source;
513
+
514
+ $srcset = explode( ',', $attributes[ $srcset_source ] );
515
 
516
  foreach ( $srcset as $srcs ) {
517
  $srcs = preg_split( '/\s+/', trim( $srcs ) );
564
  return false;
565
  }
566
 
567
+ if ( ! isset( $data['tag'], $data['attributes'], $data['src_attribute'], $data['src'], $data['srcset_attribute'], $data['srcset'] ) ) {
568
  return false;
569
  }
570
 
596
  * @return string|bool The file path. False on failure.
597
  */
598
  protected function url_to_path( $url ) {
 
599
  static $uploads_url;
600
  static $uploads_dir;
601
  static $root_url;
602
  static $root_dir;
603
+ static $cdn_url;
604
+ static $domain_url;
605
 
606
+ if ( ! isset( $uploads_url ) ) {
607
+ $uploads_url = set_url_scheme( $this->filesystem->get_upload_baseurl() );
 
608
  $uploads_dir = $this->filesystem->get_upload_basedir( true );
609
+ $root_url = set_url_scheme( $this->filesystem->get_site_root_url() );
610
  $root_dir = $this->filesystem->get_site_root();
611
+ $cdn_url = $this->get_cdn_source();
612
+ $cdn_url = $cdn_url['url'] ? set_url_scheme( $cdn_url['url'] ) : false;
613
+ $domain_url = false;
614
+
615
+ if ( $cdn_url ) {
616
+ $domain_url = wp_parse_url( $root_url );
617
+
618
+ if ( ! empty( $domain_url['scheme'] ) && ! empty( $domain_url['host'] ) ) {
619
+ $domain_url = $domain_url['scheme'] . '://' . $domain_url['host'] . '/';
620
+ }
621
+ }
622
  }
623
 
624
+ $url = set_url_scheme( $url );
625
+
626
+ if ( $domain_url && stripos( $url, $cdn_url ) === 0 ) {
627
+ $url = str_ireplace( $cdn_url, $domain_url, $url );
628
+ }
629
 
630
  if ( stripos( $url, $uploads_url ) === 0 ) {
631
  return str_ireplace( $uploads_url, $uploads_dir, $url );
637
 
638
  return false;
639
  }
640
+
641
+ /**
642
+ * Get the CDN "source".
643
+ *
644
+ * @since 1.9.3
645
+ * @access public
646
+ * @author Grégory Viguier
647
+ *
648
+ * @param string $option_url An URL to use instead of the one stored in the option. It is used only if no constant/filter.
649
+ * @return array {
650
+ * @type string $source Where does it come from? Possible values are 'constant', 'filter', or 'option'.
651
+ * @type string $name Who? Can be a constant name, a plugin name, or an empty string.
652
+ * @type string $url The CDN URL, with a trailing slash. An empty string if no URL is set.
653
+ * }
654
+ */
655
+ public function get_cdn_source( $option_url = '' ) {
656
+ if ( defined( 'IMAGIFY_CDN_URL' ) && IMAGIFY_CDN_URL && is_string( IMAGIFY_CDN_URL ) ) {
657
+ // Use a constant.
658
+ $source = [
659
+ 'source' => 'constant',
660
+ 'name' => 'IMAGIFY_CDN_URL',
661
+ 'url' => IMAGIFY_CDN_URL,
662
+ ];
663
+ } else {
664
+ // Maybe use a filter.
665
+ $filter_source = [
666
+ 'name' => null,
667
+ 'url' => null,
668
+ ];
669
+
670
+ /**
671
+ * Provide a custom CDN source.
672
+ *
673
+ * @since 1.9.3
674
+ * @author Grégory Viguier
675
+ *
676
+ * @param array $filter_source {
677
+ * @type $name string The name of which provides the URL (plugin name, etc).
678
+ * @type $url string The CDN URL.
679
+ * }
680
+ */
681
+ $filter_source = apply_filters( 'imagify_cdn_source', $filter_source );
682
+
683
+ if ( ! empty( $filter_source['url'] ) ) {
684
+ $source = [
685
+ 'source' => 'filter',
686
+ 'name' => ! empty( $filter_source['name'] ) ? $filter_source['name'] : '',
687
+ 'url' => $filter_source['url'],
688
+ ];
689
+ }
690
+ }
691
+
692
+ if ( empty( $source['url'] ) ) {
693
+ // No constant, no filter: use the option.
694
+ $source = [
695
+ 'source' => 'option',
696
+ 'name' => '',
697
+ 'url' => $option_url && is_string( $option_url ) ? $option_url : get_imagify_option( 'cdn_url' ),
698
+ ];
699
+ }
700
+
701
+ if ( empty( $source['url'] ) ) {
702
+ // Nothing set.
703
+ return [
704
+ 'source' => 'option',
705
+ 'name' => '',
706
+ 'url' => '',
707
+ ];
708
+ }
709
+
710
+ $source['url'] = $this->sanitize_cdn_url( $source['url'] );
711
+
712
+ if ( empty( $source['url'] ) ) {
713
+ // Not an URL.
714
+ return [
715
+ 'source' => 'option',
716
+ 'name' => '',
717
+ 'url' => '',
718
+ ];
719
+ }
720
+
721
+ return $source;
722
+ }
723
+
724
+ /**
725
+ * Sanitize the CDN URL value.
726
+ *
727
+ * @since 1.9.3
728
+ * @access public
729
+ * @author Grégory Viguier
730
+ *
731
+ * @param string $url The URL to sanitize.
732
+ * @return string
733
+ */
734
+ public function sanitize_cdn_url( $url ) {
735
+ $url = sanitize_text_field( $url );
736
+
737
+ if ( ! $url || ! preg_match( '@^https?://.+\.[^.]+@i', $url ) ) {
738
+ // Not an URL.
739
+ return '';
740
+ }
741
+
742
+ return trailingslashit( $url );
743
+ }
744
  }
classes/Webp/RewriteRules/Display.php CHANGED
@@ -196,12 +196,13 @@ class Display {
196
  return;
197
  }
198
 
199
- $file_path = $conf->get_file_path();
 
200
 
201
- if ( ! $this->filesystem->exists( $file_path ) ) {
202
  return;
203
  }
204
- if ( ! $this->filesystem->is_writable( $file_path ) ) {
205
  return;
206
  }
207
 
196
  return;
197
  }
198
 
199
+ $file_path = $conf->get_file_path();
200
+ $filesystem = \Imagify_Filesystem::get_instance();
201
 
202
+ if ( ! $filesystem->exists( $file_path ) ) {
203
  return;
204
  }
205
+ if ( ! $filesystem->is_writable( $file_path ) ) {
206
  return;
207
  }
208
 
composer.json CHANGED
@@ -21,6 +21,7 @@
21
  ],
22
  "type": "wordpress-plugin",
23
  "config": {
 
24
  "classmap-authoritative": true,
25
  "sort-packages": true
26
  },
@@ -34,6 +35,7 @@
34
  "composer/installers": "~1.0"
35
  },
36
  "require-dev": {
 
37
  "dealerdirect/phpcodesniffer-composer-installer": "^0.4.4",
38
  "phpcompatibility/phpcompatibility-wp": "*",
39
  "squizlabs/php_codesniffer": "^3.2",
@@ -46,7 +48,8 @@
46
  "Imagify\\ThirdParty\\EnableMediaReplace\\": "inc/3rd-party/enable-media-replace/classes/",
47
  "Imagify\\ThirdParty\\FormidablePro\\": "inc/3rd-party/formidable-pro/classes/",
48
  "Imagify\\ThirdParty\\NGG\\": "inc/3rd-party/nextgen-gallery/classes/",
49
- "Imagify\\ThirdParty\\RegenerateThumbnails\\": "inc/3rd-party/regenerate-thumbnails/classes/"
 
50
  },
51
  "classmap": [
52
  "inc/classes",
21
  ],
22
  "type": "wordpress-plugin",
23
  "config": {
24
+ "classloader-suffix": "WPMediaImagifyWordPressPlugin",
25
  "classmap-authoritative": true,
26
  "sort-packages": true
27
  },
35
  "composer/installers": "~1.0"
36
  },
37
  "require-dev": {
38
+ "dangoodman/composer-for-wordpress": "^2.0",
39
  "dealerdirect/phpcodesniffer-composer-installer": "^0.4.4",
40
  "phpcompatibility/phpcompatibility-wp": "*",
41
  "squizlabs/php_codesniffer": "^3.2",
48
  "Imagify\\ThirdParty\\EnableMediaReplace\\": "inc/3rd-party/enable-media-replace/classes/",
49
  "Imagify\\ThirdParty\\FormidablePro\\": "inc/3rd-party/formidable-pro/classes/",
50
  "Imagify\\ThirdParty\\NGG\\": "inc/3rd-party/nextgen-gallery/classes/",
51
+ "Imagify\\ThirdParty\\RegenerateThumbnails\\": "inc/3rd-party/regenerate-thumbnails/classes/",
52
+ "Imagify\\ThirdParty\\WPRocket\\": "inc/3rd-party/wp-rocket/classes/"
53
  },
54
  "classmap": [
55
  "inc/classes",
composer.lock CHANGED
@@ -4,7 +4,7 @@
4
  "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
5
  "This file is @generated automatically"
6
  ],
7
- "content-hash": "e96f76a611c307bee5cfe6085097ddd0",
8
  "packages": [
9
  {
10
  "name": "a5hleyrich/wp-background-processing",
@@ -164,6 +164,35 @@
164
  }
165
  ],
166
  "packages-dev": [
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
  {
168
  "name": "dealerdirect/phpcodesniffer-composer-installer",
169
  "version": "v0.4.4",
4
  "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
5
  "This file is @generated automatically"
6
  ],
7
+ "content-hash": "32d48d612bdea48360a6edc576c6e046",
8
  "packages": [
9
  {
10
  "name": "a5hleyrich/wp-background-processing",
164
  }
165
  ],
166
  "packages-dev": [
167
+ {
168
+ "name": "dangoodman/composer-for-wordpress",
169
+ "version": "2.0.0",
170
+ "source": {
171
+ "type": "git",
172
+ "url": "https://github.com/dangoodman/composer-for-wordpress.git",
173
+ "reference": "be478117ee9b2fbcdb5a6580a5ec69b66e711e20"
174
+ },
175
+ "dist": {
176
+ "type": "zip",
177
+ "url": "https://api.github.com/repos/dangoodman/composer-for-wordpress/zipball/be478117ee9b2fbcdb5a6580a5ec69b66e711e20",
178
+ "reference": "be478117ee9b2fbcdb5a6580a5ec69b66e711e20",
179
+ "shasum": ""
180
+ },
181
+ "require": {
182
+ "composer-plugin-api": "^1.0"
183
+ },
184
+ "type": "composer-plugin",
185
+ "extra": {
186
+ "class": "Dangoodman\\ComposerForWordpress\\ComposerForWordpress"
187
+ },
188
+ "autoload": {
189
+ "psr-4": {
190
+ "Dangoodman\\ComposerForWordpress\\": "."
191
+ }
192
+ },
193
+ "notification-url": "https://packagist.org/downloads/",
194
+ "time": "2018-06-20T15:01:37+00:00"
195
+ },
196
  {
197
  "name": "dealerdirect/phpcodesniffer-composer-installer",
198
  "version": "v0.4.4",
imagify.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: Imagify
4
  * Plugin URI: https://wordpress.org/plugins/imagify/
5
  * Description: Dramaticaly reduce image file sizes without losing quality, make your website load faster, boost your SEO and save money on your bandwidth using Imagify, the new most advanced image optimization tool.
6
- * Version: 1.9.2
7
  * Requires PHP: 5.4
8
  * Author: WP Media
9
  * Author URI: https://wp-media.me/
@@ -20,7 +20,7 @@
20
  defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
21
 
22
  // Imagify defines.
23
- define( 'IMAGIFY_VERSION', '1.9.2' );
24
  define( 'IMAGIFY_SLUG', 'imagify' );
25
  define( 'IMAGIFY_FILE', __FILE__ );
26
  define( 'IMAGIFY_PATH', realpath( plugin_dir_path( IMAGIFY_FILE ) ) . '/' );
3
  * Plugin Name: Imagify
4
  * Plugin URI: https://wordpress.org/plugins/imagify/
5
  * Description: Dramaticaly reduce image file sizes without losing quality, make your website load faster, boost your SEO and save money on your bandwidth using Imagify, the new most advanced image optimization tool.
6
+ * Version: 1.9.3
7
  * Requires PHP: 5.4
8
  * Author: WP Media
9
  * Author URI: https://wp-media.me/
20
  defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
21
 
22
  // Imagify defines.
23
+ define( 'IMAGIFY_VERSION', '1.9.3' );
24
  define( 'IMAGIFY_SLUG', 'imagify' );
25
  define( 'IMAGIFY_FILE', __FILE__ );
26
  define( 'IMAGIFY_PATH', realpath( plugin_dir_path( IMAGIFY_FILE ) ) . '/' );
inc/3rd-party/3rd-party.php CHANGED
@@ -12,7 +12,7 @@ require IMAGIFY_PATH . 'inc/3rd-party/nextgen-gallery/nextgen-gallery.php';
12
  require IMAGIFY_PATH . 'inc/3rd-party/regenerate-thumbnails/regenerate-thumbnails.php';
13
  require IMAGIFY_PATH . 'inc/3rd-party/screets-lc.php';
14
  require IMAGIFY_PATH . 'inc/3rd-party/wp-real-media-library.php';
15
- require IMAGIFY_PATH . 'inc/3rd-party/wp-rocket.php';
16
  require IMAGIFY_PATH . 'inc/3rd-party/yoast-seo.php';
17
 
18
  /**
12
  require IMAGIFY_PATH . 'inc/3rd-party/regenerate-thumbnails/regenerate-thumbnails.php';
13
  require IMAGIFY_PATH . 'inc/3rd-party/screets-lc.php';
14
  require IMAGIFY_PATH . 'inc/3rd-party/wp-real-media-library.php';
15
+ require IMAGIFY_PATH . 'inc/3rd-party/wp-rocket/wp-rocket.php';
16
  require IMAGIFY_PATH . 'inc/3rd-party/yoast-seo.php';
17
 
18
  /**
inc/3rd-party/nextgen-gallery/inc/admin/heartbeat.php DELETED
@@ -1,13 +0,0 @@
1
- <?php
2
- defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
3
-
4
- global $pagenow;
5
-
6
- /**
7
- * Update the Heartbeat API settings.
8
- *
9
- * @since 1.5
10
- */
11
- if ( 'admin.php' === $pagenow && isset( $_GET['page'] ) && imagify_get_ngg_bulk_screen_slug() === $_GET['page'] ) { // WPCS: CSRF ok.
12
- add_filter( 'heartbeat_settings', '_imagify_heartbeat_settings', IMAGIFY_INT_MAX );
13
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/3rd-party/nextgen-gallery/nextgen-gallery.php CHANGED
@@ -24,5 +24,4 @@ if ( is_admin() ) {
24
  require IMAGIFY_PATH . 'inc/3rd-party/nextgen-gallery/inc/admin/menu.php';
25
  require IMAGIFY_PATH . 'inc/3rd-party/nextgen-gallery/inc/admin/gallery.php';
26
  require IMAGIFY_PATH . 'inc/3rd-party/nextgen-gallery/inc/admin/bulk.php';
27
- require IMAGIFY_PATH . 'inc/3rd-party/nextgen-gallery/inc/admin/heartbeat.php';
28
  }
24
  require IMAGIFY_PATH . 'inc/3rd-party/nextgen-gallery/inc/admin/menu.php';
25
  require IMAGIFY_PATH . 'inc/3rd-party/nextgen-gallery/inc/admin/gallery.php';
26
  require IMAGIFY_PATH . 'inc/3rd-party/nextgen-gallery/inc/admin/bulk.php';
 
27
  }
inc/3rd-party/wp-rocket.php DELETED
@@ -1,28 +0,0 @@
1
- <?php
2
- defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
3
-
4
- if ( defined( 'WP_ROCKET_VERSION' ) ) :
5
-
6
- add_action( 'imagify_assets_enqueued', 'imagify_dequeue_sweetalert_wprocket' );
7
- /**
8
- * Don't load Imagify CSS & JS files on WP Rocket options screen to avoid conflict with older version of SweetAlert.
9
- * Since 1.6.10 they should be enqueued only if one of our notices displays here.
10
- *
11
- * @since 1.6.9.1
12
- * @since 1.6.10 Use the new class Imagify_Assets.
13
- * @author Jonathan Buttigieg
14
- * @author Grégory Viguier
15
- */
16
- function imagify_dequeue_sweetalert_wprocket() {
17
- if ( ! defined( 'WP_ROCKET_PLUGIN_SLUG' ) ) {
18
- return;
19
- }
20
-
21
- if ( ! imagify_is_screen( 'settings_page_' . WP_ROCKET_PLUGIN_SLUG ) && ! imagify_is_screen( 'settings_page_' . WP_ROCKET_PLUGIN_SLUG . '-network' ) ) {
22
- return;
23
- }
24
-
25
- Imagify_Assets::get_instance()->dequeue_script( array( 'sweetalert-core', 'sweetalert', 'notices' ) );
26
- }
27
-
28
- endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/3rd-party/wp-rocket/classes/Main.php ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Imagify\ThirdParty\WPRocket;
3
+
4
+ defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
5
+
6
+ /**
7
+ * Compat class for WP Rocket plugin.
8
+ *
9
+ * @since 1.9.3
10
+ * @author Grégory Viguier
11
+ */
12
+ class Main {
13
+ use \Imagify\Traits\FakeSingletonTrait;
14
+
15
+ /**
16
+ * Launch the hooks.
17
+ *
18
+ * @since 1.9.3
19
+ * @access public
20
+ * @author Grégory Viguier
21
+ */
22
+ public function init() {
23
+ add_action( 'imagify_assets_enqueued', [ $this, 'dequeue_sweetalert' ] );
24
+ add_filter( 'imagify_cdn_source', [ $this, 'set_cdn_source' ] );
25
+ }
26
+
27
+
28
+ /** ----------------------------------------------------------------------------------------- */
29
+ /** HOOKS =================================================================================== */
30
+ /** ----------------------------------------------------------------------------------------- */
31
+
32
+ /**
33
+ * Don't load Imagify CSS & JS files on WP Rocket options screen to avoid conflict with older version of SweetAlert.
34
+ *
35
+ * @since 1.9.3
36
+ * @access public
37
+ * @author Grégory Viguier
38
+ */
39
+ public function dequeue_sweetalert() {
40
+ if ( ! defined( 'WP_ROCKET_PLUGIN_SLUG' ) ) {
41
+ return;
42
+ }
43
+
44
+ if ( ! imagify_is_screen( 'settings_page_' . WP_ROCKET_PLUGIN_SLUG ) && ! imagify_is_screen( 'settings_page_' . WP_ROCKET_PLUGIN_SLUG . '-network' ) ) {
45
+ return;
46
+ }
47
+
48
+ \Imagify_Assets::get_instance()->dequeue_script( array( 'sweetalert-core', 'sweetalert', 'notices' ) );
49
+ }
50
+
51
+ /**
52
+ * Provide a custom CDN source.
53
+ *
54
+ * @since 1.9.3
55
+ * @author Grégory Viguier
56
+ *
57
+ * @param array $source {
58
+ * An array of arguments.
59
+ *
60
+ * @type $name string The name of which provides the URL (plugin name, etc).
61
+ * @type $url string The CDN URL.
62
+ * }
63
+ * @return array
64
+ */
65
+ public function set_cdn_source( $source ) {
66
+ if ( ! function_exists( 'get_rocket_cdn_cnames' ) || ! function_exists( 'get_rocket_option' ) ) {
67
+ return $source;
68
+ }
69
+
70
+ if ( ! get_rocket_option( 'cdn' ) ) {
71
+ return $source;
72
+ }
73
+
74
+ $url = get_rocket_cdn_cnames( [ 'all', 'images' ] );
75
+
76
+ if ( ! $url ) {
77
+ return $source;
78
+ }
79
+
80
+ $url = reset( $url );
81
+
82
+ if ( ! $url ) {
83
+ return $source;
84
+ }
85
+
86
+ if ( ! preg_match( '@^(https?:)?//@i', $url ) ) {
87
+ $url = '//' . $url;
88
+ }
89
+
90
+ $scheme = wp_parse_url( \Imagify_Filesystem::get_instance()->get_site_root_url() );
91
+ $scheme = ! empty( $scheme['scheme'] ) ? $scheme['scheme'] : null;
92
+ $url = set_url_scheme( $url, $scheme );
93
+
94
+ $source['name'] = 'WP Rocket';
95
+ $source['url'] = $url;
96
+
97
+ return $source;
98
+ }
99
+ }
inc/3rd-party/wp-rocket/wp-rocket.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
3
+
4
+ if ( defined( 'WP_ROCKET_VERSION' ) ) :
5
+
6
+ \Imagify\ThirdParty\WPRocket\Main::get_instance()->init();
7
+
8
+ endif;
inc/admin/heartbeat.php DELETED
@@ -1,358 +0,0 @@
1
- <?php
2
- defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
3
-
4
- add_filter( 'heartbeat_received', '_imagify_heartbeat_received', 10, 2 );
5
- /**
6
- * Prepare the data that goes back with the Heartbeat API.
7
- *
8
- * @since 1.4.5
9
- *
10
- * @param array $response The Heartbeat response.
11
- * @param array $data The $_POST data sent.
12
- * @return array
13
- */
14
- function _imagify_heartbeat_received( $response, $data ) {
15
- $heartbeat_id = 'imagify_bulk_data';
16
-
17
- if ( empty( $data[ $heartbeat_id ] ) ) {
18
- return $response;
19
- }
20
-
21
- $folder_types = array_flip( array_filter( $data[ $heartbeat_id ] ) );
22
-
23
- $response[ $heartbeat_id ] = imagify_get_bulk_stats( $folder_types, array(
24
- 'fullset' => true,
25
- ) );
26
-
27
- return $response;
28
- }
29
-
30
- add_filter( 'heartbeat_received', 'imagify_heartbeat_requirements_received', 10, 2 );
31
- /**
32
- * Prepare the data that goes back with the Heartbeat API.
33
- *
34
- * @since 1.7.1
35
- * @author Grégory Viguier
36
- *
37
- * @param array $response The Heartbeat response.
38
- * @param array $data The $_POST data sent.
39
- * @return array
40
- */
41
- function imagify_heartbeat_requirements_received( $response, $data ) {
42
- $heartbeat_id = 'imagify_bulk_requirements';
43
-
44
- if ( empty( $data[ $heartbeat_id ] ) ) {
45
- return $response;
46
- }
47
-
48
- $response[ $heartbeat_id ] = array(
49
- 'curl_missing' => ! Imagify_Requirements::supports_curl(),
50
- 'editor_missing' => ! Imagify_Requirements::supports_image_editor(),
51
- 'external_http_blocked' => Imagify_Requirements::is_imagify_blocked(),
52
- 'api_down' => Imagify_Requirements::is_imagify_blocked() || ! Imagify_Requirements::is_api_up(),
53
- 'key_is_valid' => ! Imagify_Requirements::is_imagify_blocked() && Imagify_Requirements::is_api_up() && Imagify_Requirements::is_api_key_valid(),
54
- 'is_over_quota' => ! Imagify_Requirements::is_imagify_blocked() && Imagify_Requirements::is_api_up() && Imagify_Requirements::is_api_key_valid() && Imagify_Requirements::is_over_quota(),
55
- );
56
-
57
- return $response;
58
- }
59
-
60
- add_filter( 'heartbeat_received', 'imagify_heartbeat_bulk_optimization_status_received', 10, 2 );
61
- /**
62
- * Look for media where status has changed, compared to what Heartbeat sends.
63
- * This is used in the bulk optimization page.
64
- *
65
- * @since 1.9
66
- * @author Grégory Viguier
67
- *
68
- * @param array $response The Heartbeat response.
69
- * @param array $data The $_POST data sent.
70
- * @return array
71
- */
72
- function imagify_heartbeat_bulk_optimization_status_received( $response, $data ) {
73
- $heartbeat_id = 'imagify_bulk_queue';
74
-
75
- if ( empty( $data[ $heartbeat_id ] ) || ! is_array( $data[ $heartbeat_id ] ) ) {
76
- return $response;
77
- }
78
-
79
- $statuses = [];
80
-
81
- foreach ( $data[ $heartbeat_id ] as $item ) {
82
- if ( empty( $statuses[ $item['context'] ] ) ) {
83
- $statuses[ $item['context'] ] = [];
84
- }
85
-
86
- $statuses[ $item['context'] ][ '_' . $item['mediaID'] ] = 1;
87
- }
88
-
89
- $results = imagify_get_modified_optimization_statusses( $statuses );
90
-
91
- if ( ! $results ) {
92
- return $response;
93
- }
94
-
95
- $response[ $heartbeat_id ] = [];
96
-
97
- // Sanitize received data and grab some other info.
98
- foreach ( $results as $context_id => $media_atts ) {
99
- $process = imagify_get_optimization_process( $media_atts['media_id'], $media_atts['context'] );
100
- $optim_data = $process->get_data();
101
-
102
- if ( $optim_data->is_optimized() ) {
103
- // Successfully optimized.
104
- $full_size_data = $optim_data->get_size_data();
105
- $response[ $heartbeat_id ][] = [
106
- 'mediaID' => $media_atts['media_id'],
107
- 'context' => $media_atts['context'],
108
- 'success' => true,
109
- 'status' => 'optimized',
110
- // Raw data.
111
- 'originalOverallSize' => $full_size_data['original_size'],
112
- 'newOverallSize' => $full_size_data['optimized_size'],
113
- 'overallSaving' => $full_size_data['original_size'] - $full_size_data['optimized_size'],
114
- 'thumbnailsCount' => $optim_data->get_optimized_sizes_count(),
115
- // Human readable data.
116
- 'originalSizeHuman' => imagify_size_format( $full_size_data['original_size'], 2 ),
117
- 'newSizeHuman' => imagify_size_format( $full_size_data['optimized_size'], 2 ),
118
- 'overallSavingHuman' => imagify_size_format( $full_size_data['original_size'] - $full_size_data['optimized_size'], 2 ),
119
- 'originalOverallSizeHuman' => imagify_size_format( $full_size_data['original_size'], 2 ),
120
- 'percentHuman' => $full_size_data['percent'] . '%',
121
- ];
122
- } elseif ( $optim_data->is_already_optimized() ) {
123
- // Already optimized.
124
- $response[ $heartbeat_id ][] = [
125
- 'mediaID' => $media_atts['media_id'],
126
- 'context' => $media_atts['context'],
127
- 'success' => true,
128
- 'status' => 'already-optimized',
129
- ];
130
- } else {
131
- // Error.
132
- $full_size_data = $optim_data->get_size_data();
133
- $message = ! empty( $full_size_data['error'] ) ? $full_size_data['error'] : '';
134
- $status = 'error';
135
-
136
- if ( 'You\'ve consumed all your data. You have to upgrade your account to continue' === $message ) {
137
- $status = 'over-quota';
138
- }
139
-
140
- $response[ $heartbeat_id ][] = [
141
- 'mediaID' => $media_atts['media_id'],
142
- 'context' => $media_atts['context'],
143
- 'success' => false,
144
- 'status' => $status,
145
- 'error' => imagify_translate_api_message( $message ),
146
- ];
147
- }
148
- }
149
-
150
- return $response;
151
- }
152
-
153
- add_filter( 'heartbeat_received', 'imagify_heartbeat_options_bulk_optimization_status_received', 10, 2 );
154
- /**
155
- * Look for media where status has changed, compared to what Heartbeat sends.
156
- * This is used in the settings page.
157
- *
158
- * @since 1.9
159
- * @author Grégory Viguier
160
- *
161
- * @param array $response The Heartbeat response.
162
- * @param array $data The $_POST data sent.
163
- * @return array
164
- */
165
- function imagify_heartbeat_options_bulk_optimization_status_received( $response, $data ) {
166
- $heartbeat_id = 'imagify_options_bulk_queue';
167
-
168
- if ( empty( $data[ $heartbeat_id ] ) || ! is_array( $data[ $heartbeat_id ] ) ) {
169
- return $response;
170
- }
171
-
172
- $statuses = [];
173
-
174
- foreach ( $data[ $heartbeat_id ] as $item ) {
175
- if ( empty( $statuses[ $item['context'] ] ) ) {
176
- $statuses[ $item['context'] ] = [];
177
- }
178
-
179
- $statuses[ $item['context'] ][ '_' . $item['mediaID'] ] = 1;
180
- }
181
-
182
- $results = imagify_get_modified_optimization_statusses( $statuses );
183
-
184
- if ( ! $results ) {
185
- return $response;
186
- }
187
-
188
- $response[ $heartbeat_id ] = [];
189
-
190
- foreach ( $results as $result ) {
191
- $response[ $heartbeat_id ][] = [
192
- 'mediaID' => $result['media_id'],
193
- 'context' => $result['context'],
194
- ];
195
- }
196
-
197
- return $response;
198
- }
199
-
200
- add_filter( 'heartbeat_received', 'imagify_heartbeat_optimization_status_received', 10, 2 );
201
- /**
202
- * Look for media where status has changed, compared to what Heartbeat sends.
203
- * This is used in the WP Media Library.
204
- *
205
- * @since 1.9
206
- * @author Grégory Viguier
207
- *
208
- * @param array $response The Heartbeat response.
209
- * @param array $data The $_POST data sent.
210
- * @return array
211
- */
212
- function imagify_heartbeat_optimization_status_received( $response, $data ) {
213
- $heartbeat_id = get_imagify_localize_script_translations( 'media-modal' );
214
- $heartbeat_id = $heartbeat_id['heartbeatId'];
215
-
216
- if ( empty( $data[ $heartbeat_id ] ) || ! is_array( $data[ $heartbeat_id ] ) ) {
217
- return $response;
218
- }
219
-
220
- $response[ $heartbeat_id ] = imagify_get_modified_optimization_statusses( $data[ $heartbeat_id ] );
221
-
222
- if ( ! $response[ $heartbeat_id ] ) {
223
- return $response;
224
- }
225
-
226
- // Sanitize received data and grab some other info.
227
- foreach ( $response[ $heartbeat_id ] as $context_id => $media_atts ) {
228
- $process = imagify_get_optimization_process( $media_atts['media_id'], $media_atts['context'] );
229
-
230
- $response[ $heartbeat_id ][ $context_id ] = get_imagify_media_column_content( $process, false );
231
- }
232
-
233
- return $response;
234
- }
235
-
236
- add_filter( 'heartbeat_received', 'imagify_heartbeat_custom_folders_optimization_status_received', 10, 2 );
237
- /**
238
- * Look for media where status has changed, compared to what Heartbeat sends.
239
- * This is used in the custom folders list (the "Other Media" page).
240
- *
241
- * @since 1.9
242
- * @author Grégory Viguier
243
- *
244
- * @param array $response The Heartbeat response.
245
- * @param array $data The $_POST data sent.
246
- * @return array
247
- */
248
- function imagify_heartbeat_custom_folders_optimization_status_received( $response, $data ) {
249
- $heartbeat_id = get_imagify_localize_script_translations( 'files-list' );
250
- $heartbeat_id = $heartbeat_id['heartbeatId'];
251
-
252
- if ( empty( $data[ $heartbeat_id ] ) || ! is_array( $data[ $heartbeat_id ] ) ) {
253
- return $response;
254
- }
255
-
256
- $response[ $heartbeat_id ] = imagify_get_modified_optimization_statusses( $data[ $heartbeat_id ] );
257
-
258
- if ( ! $response[ $heartbeat_id ] ) {
259
- return $response;
260
- }
261
-
262
- $admin_ajax_post = Imagify_Admin_Ajax_Post::get_instance();
263
- $list_table = new Imagify_Files_List_Table( [
264
- 'screen' => 'imagify-files',
265
- ] );
266
-
267
- // Sanitize received data and grab some other info.
268
- foreach ( $response[ $heartbeat_id ] as $context_id => $media_atts ) {
269
- $process = imagify_get_optimization_process( $media_atts['media_id'], $media_atts['context'] );
270
-
271
- $response[ $heartbeat_id ][ $context_id ] = $admin_ajax_post->get_media_columns( $process, $list_table );
272
- }
273
-
274
- return $response;
275
- }
276
- /**
277
- * Look for media where status has changed, compared to what Heartbeat sends.
278
- *
279
- * @since 1.9
280
- * @author Grégory Viguier
281
- *
282
- * @param array $data The data received.
283
- * @return array
284
- */
285
- function imagify_get_modified_optimization_statusses( $data ) {
286
- if ( ! $data ) {
287
- return [];
288
- }
289
-
290
- $output = [];
291
-
292
- // Sanitize received data and grab some other info.
293
- foreach ( $data as $context => $media_statuses ) {
294
- if ( ! $context || ! $media_statuses || ! is_array( $media_statuses ) ) {
295
- continue;
296
- }
297
-
298
- // Sanitize the IDs: IDs come as strings, prefixed with an undescore character (to prevent JavaScript from screwing everything).
299
- $media_ids = array_keys( $media_statuses );
300
- $media_ids = array_map( function( $media_id ) {
301
- return (int) substr( $media_id, 1 );
302
- }, $media_ids );
303
- $media_ids = array_filter( $media_ids );
304
-
305
- if ( ! $media_ids ) {
306
- continue;
307
- }
308
-
309
- // Sanitize the context.
310
- $context_instance = imagify_get_context( $context );
311
- $context = $context_instance->get_name();
312
- $process_class_name = imagify_get_optimization_process_class_name( $context );
313
- $transient_name = sprintf( $process_class_name::LOCK_NAME, $context, '%' );
314
- $is_network_wide = $context_instance->is_network_wide();
315
-
316
- Imagify_DB::cache_process_locks( $context, $media_ids );
317
-
318
- // Now that everything is cached for this context, we can get the transients without hitting the DB.
319
- foreach ( $media_ids as $id ) {
320
- $is_locked = (bool) $media_statuses[ '_' . $id ];
321
- $option_name = str_replace( '%', $id, $transient_name );
322
-
323
- if ( $is_network_wide ) {
324
- $in_db = (bool) get_site_transient( $option_name );
325
- } else {
326
- $in_db = (bool) get_transient( $option_name );
327
- }
328
-
329
- if ( $is_locked === $in_db ) {
330
- continue;
331
- }
332
-
333
- $output[ $context . '_' . $id ] = [
334
- 'media_id' => $id,
335
- 'context' => $context,
336
- ];
337
- }
338
- }
339
-
340
- return $output;
341
- }
342
-
343
-
344
- if ( Imagify_Views::get_instance()->is_bulk_page() || Imagify_Views::get_instance()->is_settings_page() ) {
345
- add_filter( 'heartbeat_settings', '_imagify_heartbeat_settings', IMAGIFY_INT_MAX );
346
- }
347
- /**
348
- * Update the Heartbeat API settings.
349
- *
350
- * @since 1.4.5
351
- *
352
- * @param array $settings Heartbeat API settings.
353
- * @return array
354
- */
355
- function _imagify_heartbeat_settings( $settings ) {
356
- $settings['interval'] = 30;
357
- return $settings;
358
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/classes/class-imagify-admin-ajax-post.php CHANGED
@@ -704,6 +704,7 @@ class Imagify_Admin_Ajax_Post extends Imagify_Admin_Ajax_Post_Deprecated {
704
  wp_send_json_error( $result->get_error_message() );
705
  }
706
 
 
707
  $this->file_optimization_output( $process );
708
  }
709
 
704
  wp_send_json_error( $result->get_error_message() );
705
  }
706
 
707
+ $process = imagify_get_optimization_process( $media_id, 'custom-folders' );
708
  $this->file_optimization_output( $process );
709
  }
710
 
inc/classes/class-imagify-assets.php CHANGED
@@ -206,7 +206,9 @@ class Imagify_Assets extends Imagify_Assets_Deprecated {
206
 
207
  $this->register_script( 'twentytwenty', 'jquery.twentytwenty', array( 'jquery', 'event-move', 'chart', 'admin' ) )->defer_localization( 'imagifyTTT' );
208
 
209
- $this->register_script( 'media-modal', 'media-modal', array( 'jquery', 'heartbeat', 'underscore', 'chart', 'admin' ) )->localize( 'imagifyModal' );
 
 
210
 
211
  $this->register_script( 'pricing-modal', 'pricing-modal', array( 'jquery', 'admin' ) )->defer_localization( 'imagifyPricingModal' );
212
 
@@ -214,11 +216,11 @@ class Imagify_Assets extends Imagify_Assets_Deprecated {
214
 
215
  $this->register_script( 'async', 'imagify-gulp' );
216
 
217
- $this->register_script( 'bulk', 'bulk', array( 'jquery', 'heartbeat', 'underscore', 'chart', 'sweetalert', 'async', 'admin' ) )->defer_localization( 'imagifyBulk' );
218
 
219
- $this->register_script( 'options', 'options', array( 'jquery', 'heartbeat', 'sweetalert', 'underscore', 'admin' ) )->defer_localization( 'imagifyOptions' );
220
 
221
- $this->register_script( 'files-list', 'files-list', array( 'jquery', 'heartbeat', 'underscore', 'chart', 'admin' ) )->defer_localization( 'imagifyFiles' );
222
  }
223
 
224
  /**
@@ -491,8 +493,6 @@ class Imagify_Assets extends Imagify_Assets_Deprecated {
491
  $this->current_handle = $handle;
492
  $this->current_handle_type = 'js';
493
 
494
- $this->maybe_register_heartbeat( $handle );
495
-
496
  if ( ! empty( $this->scripts[ $handle ] ) ) {
497
  // If we registered it, it's one of our scripts.
498
  $handle = self::JS_PREFIX . $handle;
@@ -756,63 +756,6 @@ class Imagify_Assets extends Imagify_Assets_Deprecated {
756
  return $depts;
757
  }
758
 
759
- /**
760
- * Make sure Heartbeat is registered if the given script requires it.
761
- * Lots of people love deregister Heartbeat.
762
- *
763
- * @since 1.6.11
764
- * @author Grégory Viguier
765
- *
766
- * @param string $handle Name of the script. Should be unique.
767
- */
768
- protected function maybe_register_heartbeat( $handle ) {
769
- global $wp_version;
770
-
771
- if ( wp_script_is( 'heartbeat', 'registered' ) ) {
772
- return;
773
- }
774
-
775
- if ( ! empty( $this->scripts[ $handle ] ) ) {
776
- // If we registered it, it's one of our scripts.
777
- $handle = self::JS_PREFIX . $handle;
778
- }
779
-
780
- $wp_scripts = wp_scripts();
781
- $dependencies = $wp_scripts->query( $handle );
782
-
783
- if ( ! $dependencies || ! $dependencies->deps ) {
784
- return;
785
- }
786
-
787
- $dependencies = array_flip( $dependencies->deps );
788
-
789
- if ( ! isset( $dependencies['heartbeat'] ) ) {
790
- return;
791
- }
792
-
793
- $suffix = SCRIPT_DEBUG ? '' : '.min';
794
- $depts = [ 'jquery' ];
795
-
796
- if ( version_compare( $wp_version, '5.0.0' ) >= 0 ) {
797
- $depts[] = 'wp-hooks';
798
- }
799
-
800
- wp_register_script( 'heartbeat', "/wp-includes/js/heartbeat$suffix.js", $depts, false, true ); // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.NoExplicitVersion
801
-
802
- if ( $wp_scripts->get_data( 'heartbeat', 'data' ) ) {
803
- return;
804
- }
805
-
806
- /** This filter is documented in /wp-includes/script-loader.php */
807
- $data = apply_filters( 'heartbeat_settings', [] );
808
-
809
- if ( empty( $data['nonce'] ) ) {
810
- $data = wp_heartbeat_settings( $data );
811
- }
812
-
813
- wp_localize_script( 'heartbeat', 'heartbeatSettings', $data );
814
- }
815
-
816
  /**
817
  * Tell if debug is on.
818
  *
206
 
207
  $this->register_script( 'twentytwenty', 'jquery.twentytwenty', array( 'jquery', 'event-move', 'chart', 'admin' ) )->defer_localization( 'imagifyTTT' );
208
 
209
+ $this->register_script( 'beat', 'beat', array( 'jquery' ) )->localize( 'imagifybeatSettings' );
210
+
211
+ $this->register_script( 'media-modal', 'media-modal', array( 'jquery', 'beat', 'underscore', 'chart', 'admin' ) )->localize( 'imagifyModal' );
212
 
213
  $this->register_script( 'pricing-modal', 'pricing-modal', array( 'jquery', 'admin' ) )->defer_localization( 'imagifyPricingModal' );
214
 
216
 
217
  $this->register_script( 'async', 'imagify-gulp' );
218
 
219
+ $this->register_script( 'bulk', 'bulk', array( 'jquery', 'beat', 'underscore', 'chart', 'sweetalert', 'async', 'admin' ) )->defer_localization( 'imagifyBulk' );
220
 
221
+ $this->register_script( 'options', 'options', array( 'jquery', 'beat', 'sweetalert', 'underscore', 'admin' ) )->defer_localization( 'imagifyOptions' );
222
 
223
+ $this->register_script( 'files-list', 'files-list', array( 'jquery', 'beat', 'underscore', 'chart', 'admin' ) )->defer_localization( 'imagifyFiles' );
224
  }
225
 
226
  /**
493
  $this->current_handle = $handle;
494
  $this->current_handle_type = 'js';
495
 
 
 
496
  if ( ! empty( $this->scripts[ $handle ] ) ) {
497
  // If we registered it, it's one of our scripts.
498
  $handle = self::JS_PREFIX . $handle;
756
  return $depts;
757
  }
758
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
759
  /**
760
  * Tell if debug is on.
761
  *
inc/classes/class-imagify-files-scan.php CHANGED
@@ -143,7 +143,7 @@ class Imagify_Files_Scan {
143
  }
144
  }
145
 
146
- foreach ( $folders as $folder ) {
147
  if ( strpos( $file_path, $folder ) === 0 ) {
148
  return true;
149
  }
143
  }
144
  }
145
 
146
+ foreach ( $folders as $folder => $i ) {
147
  if ( strpos( $file_path, $folder ) === 0 ) {
148
  return true;
149
  }
inc/classes/class-imagify-options.php CHANGED
@@ -44,6 +44,7 @@ class Imagify_Options extends Imagify_Abstract_Options {
44
  'convert_to_webp' => 0,
45
  'display_webp' => 0,
46
  'display_webp_method' => 'picture',
 
47
  'exif' => 0,
48
  'disallowed-sizes' => array(),
49
  'admin_bar_menu' => 0,
@@ -190,6 +191,19 @@ class Imagify_Options extends Imagify_Abstract_Options {
190
  // For an invalid value, return the "reset" value.
191
  $reset_values = $this->get_reset_values();
192
  return $reset_values[ $key ];
 
 
 
 
 
 
 
 
 
 
 
 
 
193
  }
194
 
195
  return false;
44
  'convert_to_webp' => 0,
45
  'display_webp' => 0,
46
  'display_webp_method' => 'picture',
47
+ 'cdn_url' => '',
48
  'exif' => 0,
49
  'disallowed-sizes' => array(),
50
  'admin_bar_menu' => 0,
191
  // For an invalid value, return the "reset" value.
192
  $reset_values = $this->get_reset_values();
193
  return $reset_values[ $key ];
194
+
195
+ case 'cdn_url':
196
+ $cdn_source = \Imagify\Webp\Picture\Display::get_instance()->get_cdn_source( $value );
197
+
198
+ if ( 'option' !== $cdn_source['source'] ) {
199
+ /**
200
+ * If the URL is defined via constant or filter, unset the option.
201
+ * This is useful when the CDN is disabled: there is no need to do anything then.
202
+ */
203
+ return '';
204
+ }
205
+
206
+ return $cdn_source['url'];
207
  }
208
 
209
  return false;
inc/classes/class-imagify-plugin.php CHANGED
@@ -58,6 +58,8 @@ class Imagify_Plugin {
58
  Imagify_Admin_Ajax_Post::get_instance()->init();
59
  Imagify_Settings::get_instance()->init();
60
  Imagify_Views::get_instance()->init();
 
 
61
  }
62
 
63
  if ( ! wp_doing_ajax() ) {
@@ -121,7 +123,6 @@ class Imagify_Plugin {
121
  }
122
 
123
  require_once $inc_path . 'admin/upgrader.php';
124
- require_once $inc_path . 'admin/heartbeat.php';
125
  require_once $inc_path . 'admin/upload.php';
126
  require_once $inc_path . 'admin/media.php';
127
  require_once $inc_path . 'admin/meta-boxes.php';
58
  Imagify_Admin_Ajax_Post::get_instance()->init();
59
  Imagify_Settings::get_instance()->init();
60
  Imagify_Views::get_instance()->init();
61
+ \Imagify\Imagifybeat\Core::get_instance()->init();
62
+ \Imagify\Imagifybeat\Actions::get_instance()->init();
63
  }
64
 
65
  if ( ! wp_doing_ajax() ) {
123
  }
124
 
125
  require_once $inc_path . 'admin/upgrader.php';
 
126
  require_once $inc_path . 'admin/upload.php';
127
  require_once $inc_path . 'admin/media.php';
128
  require_once $inc_path . 'admin/meta-boxes.php';
inc/classes/class-imagify-settings.php CHANGED
@@ -458,14 +458,14 @@ class Imagify_Settings {
458
  * {current_value} int|bool USE ONLY WHEN DEALING WITH DATA THAT IS NOT SAVED IN THE PLUGIN OPTIONS. If not provided, the field will automatically get the value from the options.
459
  */
460
  public function field_checkbox( $args ) {
461
- $args = array_merge( array(
462
  'option_name' => '',
463
  'label' => '',
464
  'info' => '',
465
- 'attributes' => array(),
466
  // To not use the plugin settings: use an integer.
467
  'current_value' => null,
468
- ), $args );
469
 
470
  if ( ! $args['option_name'] || ! $args['label'] ) {
471
  return;
@@ -473,17 +473,17 @@ class Imagify_Settings {
473
 
474
  if ( is_numeric( $args['current_value'] ) || is_bool( $args['current_value'] ) ) {
475
  // We don't use the plugin settings.
476
- $current_value = (int) (bool) $args['current_values'];
477
  } else {
478
  // This is a normal plugin setting.
479
  $current_value = $this->options->get( $args['option_name'] );
480
  }
481
 
482
  $option_name_class = sanitize_html_class( $args['option_name'] );
483
- $attributes = array(
484
  'name' => $this->option_name . '[' . $args['option_name'] . ']',
485
  'id' => 'imagify_' . $option_name_class,
486
- );
487
 
488
  if ( $args['info'] && empty( $attributes['aria-describedby'] ) ) {
489
  $attributes['aria-describedby'] = 'describe-' . $option_name_class;
@@ -524,17 +524,16 @@ class Imagify_Settings {
524
  * {current_values} array USE ONLY WHEN DEALING WITH DATA THAT IS NOT SAVED IN THE PLUGIN OPTIONS. If not provided, the field will automatically get the value from the options.
525
  */
526
  public function field_checkbox_list( $args ) {
527
-
528
- $args = array_merge( array(
529
  'option_name' => '',
530
  'legend' => '',
531
- 'values' => array(),
532
- 'disabled_values' => array(),
533
  'reverse_check' => false,
534
- 'attributes' => array(),
535
  // To not use the plugin settings: use an array.
536
  'current_values' => false,
537
- ), $args );
538
 
539
  if ( ! $args['option_name'] || ! $args['values'] ) {
540
  return;
@@ -549,11 +548,11 @@ class Imagify_Settings {
549
  }
550
 
551
  $option_name_class = sanitize_html_class( $args['option_name'] );
552
- $attributes = array_merge( array(
553
  'name' => $this->option_name . '[' . $args['option_name'] . ( $args['reverse_check'] ? '-checked' : '' ) . '][]',
554
  'id' => 'imagify_' . $option_name_class . '_%s',
555
  'class' => 'imagify-row-check',
556
- ), $args['attributes'] );
557
 
558
  $id_attribute = $attributes['id'];
559
  unset( $attributes['id'] );
@@ -657,11 +656,11 @@ class Imagify_Settings {
657
  }
658
 
659
  $option_name_class = sanitize_html_class( $args['option_name'] );
660
- $attributes = array_merge( array(
661
  'name' => $this->option_name . '[' . $args['option_name'] . ']',
662
  'id' => 'imagify_' . $option_name_class . '_%s',
663
  'class' => 'imagify-row-radio',
664
- ), $args['attributes'] );
665
 
666
  $id_attribute = $attributes['id'];
667
  unset( $attributes['id'] );
@@ -697,6 +696,115 @@ class Imagify_Settings {
697
  <?php
698
  }
699
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
700
 
701
  /** ----------------------------------------------------------------------------------------- */
702
  /** FIELD VALUES ============================================================================ */
458
  * {current_value} int|bool USE ONLY WHEN DEALING WITH DATA THAT IS NOT SAVED IN THE PLUGIN OPTIONS. If not provided, the field will automatically get the value from the options.
459
  */
460
  public function field_checkbox( $args ) {
461
+ $args = array_merge( [
462
  'option_name' => '',
463
  'label' => '',
464
  'info' => '',
465
+ 'attributes' => [],
466
  // To not use the plugin settings: use an integer.
467
  'current_value' => null,
468
+ ], $args );
469
 
470
  if ( ! $args['option_name'] || ! $args['label'] ) {
471
  return;
473
 
474
  if ( is_numeric( $args['current_value'] ) || is_bool( $args['current_value'] ) ) {
475
  // We don't use the plugin settings.
476
+ $current_value = (int) (bool) $args['current_value'];
477
  } else {
478
  // This is a normal plugin setting.
479
  $current_value = $this->options->get( $args['option_name'] );
480
  }
481
 
482
  $option_name_class = sanitize_html_class( $args['option_name'] );
483
+ $attributes = [
484
  'name' => $this->option_name . '[' . $args['option_name'] . ']',
485
  'id' => 'imagify_' . $option_name_class,
486
+ ];
487
 
488
  if ( $args['info'] && empty( $attributes['aria-describedby'] ) ) {
489
  $attributes['aria-describedby'] = 'describe-' . $option_name_class;
524
  * {current_values} array USE ONLY WHEN DEALING WITH DATA THAT IS NOT SAVED IN THE PLUGIN OPTIONS. If not provided, the field will automatically get the value from the options.
525
  */
526
  public function field_checkbox_list( $args ) {
527
+ $args = array_merge( [
 
528
  'option_name' => '',
529
  'legend' => '',
530
+ 'values' => [],
531
+ 'disabled_values' => [],
532
  'reverse_check' => false,
533
+ 'attributes' => [],
534
  // To not use the plugin settings: use an array.
535
  'current_values' => false,
536
+ ], $args );
537
 
538
  if ( ! $args['option_name'] || ! $args['values'] ) {
539
  return;
548
  }
549
 
550
  $option_name_class = sanitize_html_class( $args['option_name'] );
551
+ $attributes = array_merge( [
552
  'name' => $this->option_name . '[' . $args['option_name'] . ( $args['reverse_check'] ? '-checked' : '' ) . '][]',
553
  'id' => 'imagify_' . $option_name_class . '_%s',
554
  'class' => 'imagify-row-check',
555
+ ], $args['attributes'] );
556
 
557
  $id_attribute = $attributes['id'];
558
  unset( $attributes['id'] );
656
  }
657
 
658
  $option_name_class = sanitize_html_class( $args['option_name'] );
659
+ $attributes = array_merge( [
660
  'name' => $this->option_name . '[' . $args['option_name'] . ']',
661
  'id' => 'imagify_' . $option_name_class . '_%s',
662
  'class' => 'imagify-row-radio',
663
+ ], $args['attributes'] );
664
 
665
  $id_attribute = $attributes['id'];
666
  unset( $attributes['id'] );
696
  <?php
697
  }
698
 
699
+ /**
700
+ * Display a text box.
701
+ *
702
+ * @since 1.9.3
703
+ * @access public
704
+ * @author Grégory Viguier
705
+ *
706
+ * @param array $args Arguments:
707
+ * {option_name} string The option name. E.g. 'disallowed-sizes'. Mandatory.
708
+ * {label} string The label to use.
709
+ * {info} string Text to display in an "Info box" after the field. A 'aria-describedby' attribute will automatically be created.
710
+ * {attributes} array A list of HTML attributes, as 'attribute' => 'value'.
711
+ * {current_value} int|bool USE ONLY WHEN DEALING WITH DATA THAT IS NOT SAVED IN THE PLUGIN OPTIONS. If not provided, the field will automatically get the value from the options.
712
+ */
713
+ public function field_text_box( $args ) {
714
+ $args = array_merge( [
715
+ 'option_name' => '',
716
+ 'label' => '',
717
+ 'info' => '',
718
+ 'attributes' => [],
719
+ // To not use the plugin settings.
720
+ 'current_value' => null,
721
+ ], $args );
722
+
723
+ if ( ! $args['option_name'] || ! $args['label'] ) {
724
+ return;
725
+ }
726
+
727
+ if ( is_numeric( $args['current_value'] ) || is_string( $args['current_value'] ) ) {
728
+ // We don't use the plugin settings.
729
+ $current_value = $args['current_value'];
730
+ } else {
731
+ // This is a normal plugin setting.
732
+ $current_value = $this->options->get( $args['option_name'] );
733
+ }
734
+
735
+ $option_name_class = sanitize_html_class( $args['option_name'] );
736
+ $attributes = [
737
+ 'name' => $this->option_name . '[' . $args['option_name'] . ']',
738
+ 'id' => 'imagify_' . $option_name_class,
739
+ ];
740
+
741
+ if ( $args['info'] && empty( $attributes['aria-describedby'] ) ) {
742
+ $attributes['aria-describedby'] = 'describe-' . $option_name_class;
743
+ }
744
+
745
+ $attributes = array_merge( $attributes, $args['attributes'] );
746
+ $args['attributes'] = self::build_attributes( $attributes );
747
+ ?>
748
+ <!-- Empty onclick attribute to make clickable labels on iTruc & Mac -->
749
+ <label for="<?php echo $attributes['id']; ?>" onclick=""><?php echo $args['label']; ?></label>
750
+ <input type="text" value="<?php echo esc_attr( $current_value ); ?>"<?php echo $args['attributes']; ?> />
751
+ <?php
752
+ if ( ! $args['info'] ) {
753
+ return;
754
+ }
755
+ ?>
756
+ <span id="<?php echo $attributes['aria-describedby']; ?>" class="imagify-info">
757
+ <span class="dashicons dashicons-info"></span>
758
+ <?php echo $args['info']; ?>
759
+ </span>
760
+ <?php
761
+ }
762
+
763
+ /**
764
+ * Display a simple hidden input.
765
+ *
766
+ * @since 1.9.3
767
+ * @access public
768
+ * @author Grégory Viguier
769
+ *
770
+ * @param array $args Arguments:
771
+ * {option_name} string The option name. E.g. 'disallowed-sizes'. Mandatory.
772
+ * {attributes} array A list of HTML attributes, as 'attribute' => 'value'.
773
+ * {current_value} int|bool USE ONLY WHEN DEALING WITH DATA THAT IS NOT SAVED IN THE PLUGIN OPTIONS. If not provided, the field will automatically get the value from the options.
774
+ */
775
+ public function field_hidden( $args ) {
776
+ $args = array_merge( [
777
+ 'option_name' => '',
778
+ 'attributes' => [],
779
+ // To not use the plugin settings.
780
+ 'current_value' => null,
781
+ ], $args );
782
+
783
+ if ( ! $args['option_name'] ) {
784
+ return;
785
+ }
786
+
787
+ if ( is_numeric( $args['current_value'] ) || is_string( $args['current_value'] ) ) {
788
+ // We don't use the plugin settings.
789
+ $current_value = $args['current_value'];
790
+ } else {
791
+ // This is a normal plugin setting.
792
+ $current_value = $this->options->get( $args['option_name'] );
793
+ }
794
+
795
+ $option_name_class = sanitize_html_class( $args['option_name'] );
796
+ $attributes = [
797
+ 'name' => $this->option_name . '[' . $args['option_name'] . ']',
798
+ 'id' => 'imagify_' . $option_name_class,
799
+ ];
800
+
801
+ $attributes = array_merge( $attributes, $args['attributes'] );
802
+ $args['attributes'] = self::build_attributes( $attributes );
803
+ ?>
804
+ <input type="hidden" value="<?php echo esc_attr( $current_value ); ?>"<?php echo $args['attributes']; ?> />
805
+ <?php
806
+ }
807
+
808
 
809
  /** ----------------------------------------------------------------------------------------- */
810
  /** FIELD VALUES ============================================================================ */
inc/deprecated/3rd-party.php CHANGED
@@ -300,3 +300,32 @@ if ( function_exists( 'wr2x_delete_attachment' ) ) :
300
  }
301
 
302
  endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
300
  }
301
 
302
  endif;
303
+
304
+ if ( defined( 'WP_ROCKET_VERSION' ) ) :
305
+
306
+ /**
307
+ * Don't load Imagify CSS & JS files on WP Rocket options screen to avoid conflict with older version of SweetAlert.
308
+ * Since 1.6.10 they should be enqueued only if one of our notices displays here.
309
+ *
310
+ * @since 1.6.9.1
311
+ * @since 1.6.10 Use the new class Imagify_Assets.
312
+ * @since 1.9.3 Deprecated.
313
+ * @author Jonathan Buttigieg
314
+ * @author Grégory Viguier
315
+ * @deprecated
316
+ */
317
+ function imagify_dequeue_sweetalert_wprocket() {
318
+ _deprecated_function( __FUNCTION__ . '()', '1.9.3', '\\Imagify\\ThirdParty\\WPRocket\\Main::dequeue_sweetalert()' );
319
+
320
+ if ( ! defined( 'WP_ROCKET_PLUGIN_SLUG' ) ) {
321
+ return;
322
+ }
323
+
324
+ if ( ! imagify_is_screen( 'settings_page_' . WP_ROCKET_PLUGIN_SLUG ) && ! imagify_is_screen( 'settings_page_' . WP_ROCKET_PLUGIN_SLUG . '-network' ) ) {
325
+ return;
326
+ }
327
+
328
+ Imagify_Assets::get_instance()->dequeue_script( array( 'sweetalert-core', 'sweetalert', 'notices' ) );
329
+ }
330
+
331
+ endif;
inc/deprecated/classes/class-imagify-assets-deprecated.php CHANGED
@@ -40,4 +40,65 @@ class Imagify_Assets_Deprecated {
40
  </script>
41
  <?php
42
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  }
40
  </script>
41
  <?php
42
  }
43
+
44
+ /**
45
+ * Make sure Heartbeat is registered if the given script requires it.
46
+ * Lots of people love deregister Heartbeat.
47
+ *
48
+ * @since 1.6.11
49
+ * @since 1.9.3 Deprecated.
50
+ * @author Grégory Viguier
51
+ * @deprecated
52
+ *
53
+ * @param string $handle Name of the script. Should be unique.
54
+ */
55
+ protected function maybe_register_heartbeat( $handle ) {
56
+ global $wp_version;
57
+
58
+ _deprecated_function( get_class( $this ) . '::' . __FUNCTION__ . '()', '1.9.3' );
59
+
60
+ if ( wp_script_is( 'heartbeat', 'registered' ) ) {
61
+ return;
62
+ }
63
+
64
+ if ( ! empty( $this->scripts[ $handle ] ) ) {
65
+ // If we registered it, it's one of our scripts.
66
+ $handle = self::JS_PREFIX . $handle;
67
+ }
68
+
69
+ $wp_scripts = wp_scripts();
70
+ $dependencies = $wp_scripts->query( $handle );
71
+
72
+ if ( ! $dependencies || ! $dependencies->deps ) {
73
+ return;
74
+ }
75
+
76
+ $dependencies = array_flip( $dependencies->deps );
77
+
78
+ if ( ! isset( $dependencies['heartbeat'] ) ) {
79
+ return;
80
+ }
81
+
82
+ $suffix = SCRIPT_DEBUG ? '' : '.min';
83
+ $depts = [ 'jquery' ];
84
+
85
+ if ( version_compare( $wp_version, '5.0.0' ) >= 0 ) {
86
+ $depts[] = 'wp-hooks';
87
+ }
88
+
89
+ wp_register_script( 'heartbeat', "/wp-includes/js/heartbeat$suffix.js", $depts, false, true ); // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.NoExplicitVersion
90
+
91
+ if ( $wp_scripts->get_data( 'heartbeat', 'data' ) ) {
92
+ return;
93
+ }
94
+
95
+ /** This filter is documented in /wp-includes/script-loader.php */
96
+ $data = apply_filters( 'heartbeat_settings', [] );
97
+
98
+ if ( empty( $data['nonce'] ) ) {
99
+ $data = wp_heartbeat_settings( $data );
100
+ }
101
+
102
+ wp_localize_script( 'heartbeat', 'heartbeatSettings', $data );
103
+ }
104
  }
inc/deprecated/deprecated.php CHANGED
@@ -1283,4 +1283,383 @@ if ( is_admin() ) :
1283
  }
1284
  }
1285
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1286
  endif;
1283
  }
1284
  }
1285
 
1286
+ /**
1287
+ * Update the Heartbeat API settings.
1288
+ *
1289
+ * @since 1.4.5
1290
+ * @since 1.9.3 Deprecated.
1291
+ * @deprecated
1292
+ *
1293
+ * @param array $settings Heartbeat API settings.
1294
+ * @return array
1295
+ */
1296
+ function _imagify_heartbeat_settings( $settings ) {
1297
+ _deprecated_function( __FUNCTION__ . '()', '1.9.3' );
1298
+
1299
+ $settings['interval'] = 30;
1300
+ return $settings;
1301
+ }
1302
+
1303
+ /**
1304
+ * Prepare the data that goes back with the Imagifybeat API.
1305
+ *
1306
+ * @since 1.4.5
1307
+ * @since 1.9.3 Deprecated.
1308
+ * @deprecated
1309
+ *
1310
+ * @param array $response The Imagifybeat response.
1311
+ * @param array $data The $_POST data sent.
1312
+ * @return array
1313
+ */
1314
+ function _imagify_heartbeat_received( $response, $data ) {
1315
+ _deprecated_function( __FUNCTION__ . '()', '1.9.3', '\\Imagify\\Imagifybeat\\Actions::get_instance()->add_bulk_optimization_stats_to_response()' );
1316
+
1317
+ $heartbeat_id = 'imagify_bulk_data';
1318
+
1319
+ if ( empty( $data[ $heartbeat_id ] ) ) {
1320
+ return $response;
1321
+ }
1322
+
1323
+ $folder_types = array_flip( array_filter( $data[ $heartbeat_id ] ) );
1324
+
1325
+ $response[ $heartbeat_id ] = imagify_get_bulk_stats( $folder_types, array(
1326
+ 'fullset' => true,
1327
+ ) );
1328
+
1329
+ return $response;
1330
+ }
1331
+
1332
+ /**
1333
+ * Prepare the data that goes back with the Imagifybeat API.
1334
+ *
1335
+ * @since 1.7.1
1336
+ * @since 1.9.3 Deprecated.
1337
+ * @author Grégory Viguier
1338
+ * @deprecated
1339
+ *
1340
+ * @param array $response The Imagifybeat response.
1341
+ * @param array $data The $_POST data sent.
1342
+ * @return array
1343
+ */
1344
+ function imagify_heartbeat_requirements_received( $response, $data ) {
1345
+ _deprecated_function( __FUNCTION__ . '()', '1.9.3', '\\Imagify\\Imagifybeat\\Actions::get_instance()->add_requirements_to_response()' );
1346
+
1347
+ $heartbeat_id = 'imagify_bulk_requirements';
1348
+
1349
+ if ( empty( $data[ $heartbeat_id ] ) ) {
1350
+ return $response;
1351
+ }
1352
+
1353
+ $response[ $heartbeat_id ] = array(
1354
+ 'curl_missing' => ! Imagify_Requirements::supports_curl(),
1355
+ 'editor_missing' => ! Imagify_Requirements::supports_image_editor(),
1356
+ 'external_http_blocked' => Imagify_Requirements::is_imagify_blocked(),
1357
+ 'api_down' => Imagify_Requirements::is_imagify_blocked() || ! Imagify_Requirements::is_api_up(),
1358
+ 'key_is_valid' => ! Imagify_Requirements::is_imagify_blocked() && Imagify_Requirements::is_api_up() && Imagify_Requirements::is_api_key_valid(),
1359
+ 'is_over_quota' => ! Imagify_Requirements::is_imagify_blocked() && Imagify_Requirements::is_api_up() && Imagify_Requirements::is_api_key_valid() && Imagify_Requirements::is_over_quota(),
1360
+ );
1361
+
1362
+ return $response;
1363
+ }
1364
+
1365
+ /**
1366
+ * Look for media where status has changed, compared to what Imagifybeat sends.
1367
+ * This is used in the bulk optimization page.
1368
+ *
1369
+ * @since 1.9
1370
+ * @since 1.9.3 Deprecated.
1371
+ * @author Grégory Viguier
1372
+ * @deprecated
1373
+ *
1374
+ * @param array $response The Imagifybeat response.
1375
+ * @param array $data The $_POST data sent.
1376
+ * @return array
1377
+ */
1378
+ function imagify_heartbeat_bulk_optimization_status_received( $response, $data ) {
1379
+ _deprecated_function( __FUNCTION__ . '()', '1.9.3', '\\Imagify\\Imagifybeat\\Actions::get_instance()->add_bulk_optimization_status_to_response()' );
1380
+
1381
+ $heartbeat_id = 'imagify_bulk_queue';
1382
+
1383
+ if ( empty( $data[ $heartbeat_id ] ) || ! is_array( $data[ $heartbeat_id ] ) ) {
1384
+ return $response;
1385
+ }
1386
+
1387
+ $statuses = [];
1388
+
1389
+ foreach ( $data[ $heartbeat_id ] as $item ) {
1390
+ if ( empty( $statuses[ $item['context'] ] ) ) {
1391
+ $statuses[ $item['context'] ] = [];
1392
+ }
1393
+
1394
+ $statuses[ $item['context'] ][ '_' . $item['mediaID'] ] = 1;
1395
+ }
1396
+
1397
+ $results = imagify_get_modified_optimization_statusses( $statuses );
1398
+
1399
+ if ( ! $results ) {
1400
+ return $response;
1401
+ }
1402
+
1403
+ $response[ $heartbeat_id ] = [];
1404
+
1405
+ // Sanitize received data and grab some other info.
1406
+ foreach ( $results as $context_id => $media_atts ) {
1407
+ $process = imagify_get_optimization_process( $media_atts['media_id'], $media_atts['context'] );
1408
+ $optim_data = $process->get_data();
1409
+
1410
+ if ( $optim_data->is_optimized() ) {
1411
+ // Successfully optimized.
1412
+ $full_size_data = $optim_data->get_size_data();
1413
+ $response[ $heartbeat_id ][] = [
1414
+ 'mediaID' => $media_atts['media_id'],
1415
+ 'context' => $media_atts['context'],
1416
+ 'success' => true,
1417
+ 'status' => 'optimized',
1418
+ // Raw data.
1419
+ 'originalOverallSize' => $full_size_data['original_size'],
1420
+ 'newOverallSize' => $full_size_data['optimized_size'],
1421
+ 'overallSaving' => $full_size_data['original_size'] - $full_size_data['optimized_size'],
1422
+ 'thumbnailsCount' => $optim_data->get_optimized_sizes_count(),
1423
+ // Human readable data.
1424
+ 'originalSizeHuman' => imagify_size_format( $full_size_data['original_size'], 2 ),
1425
+ 'newSizeHuman' => imagify_size_format( $full_size_data['optimized_size'], 2 ),
1426
+ 'overallSavingHuman' => imagify_size_format( $full_size_data['original_size'] - $full_size_data['optimized_size'], 2 ),
1427
+ 'originalOverallSizeHuman' => imagify_size_format( $full_size_data['original_size'], 2 ),
1428
+ 'percentHuman' => $full_size_data['percent'] . '%',
1429
+ ];
1430
+ } elseif ( $optim_data->is_already_optimized() ) {
1431
+ // Already optimized.
1432
+ $response[ $heartbeat_id ][] = [
1433
+ 'mediaID' => $media_atts['media_id'],
1434
+ 'context' => $media_atts['context'],
1435
+ 'success' => true,
1436
+ 'status' => 'already-optimized',
1437
+ ];
1438
+ } else {
1439
+ // Error.
1440
+ $full_size_data = $optim_data->get_size_data();
1441
+ $message = ! empty( $full_size_data['error'] ) ? $full_size_data['error'] : '';
1442
+ $status = 'error';
1443
+
1444
+ if ( 'You\'ve consumed all your data. You have to upgrade your account to continue' === $message ) {
1445
+ $status = 'over-quota';
1446
+ }
1447
+
1448
+ $response[ $heartbeat_id ][] = [
1449
+ 'mediaID' => $media_atts['media_id'],
1450
+ 'context' => $media_atts['context'],
1451
+ 'success' => false,
1452
+ 'status' => $status,
1453
+ 'error' => imagify_translate_api_message( $message ),
1454
+ ];
1455
+ }
1456
+ }
1457
+
1458
+ return $response;
1459
+ }
1460
+
1461
+ /**
1462
+ * Look for media where status has changed, compared to what Imagifybeat sends.
1463
+ * This is used in the settings page.
1464
+ *
1465
+ * @since 1.9
1466
+ * @since 1.9.3 Deprecated.
1467
+ * @author Grégory Viguier
1468
+ * @deprecated
1469
+ *
1470
+ * @param array $response The Imagifybeat response.
1471
+ * @param array $data The $_POST data sent.
1472
+ * @return array
1473
+ */
1474
+ function imagify_heartbeat_options_bulk_optimization_status_received( $response, $data ) {
1475
+ _deprecated_function( __FUNCTION__ . '()', '1.9.3', '\\Imagify\\Imagifybeat\\Actions::get_instance()->add_options_optimization_status_to_response()' );
1476
+
1477
+ $heartbeat_id = 'imagify_options_bulk_queue';
1478
+
1479
+ if ( empty( $data[ $heartbeat_id ] ) || ! is_array( $data[ $heartbeat_id ] ) ) {
1480
+ return $response;
1481
+ }
1482
+
1483
+ $statuses = [];
1484
+
1485
+ foreach ( $data[ $heartbeat_id ] as $item ) {
1486
+ if ( empty( $statuses[ $item['context'] ] ) ) {
1487
+ $statuses[ $item['context'] ] = [];
1488
+ }
1489
+
1490
+ $statuses[ $item['context'] ][ '_' . $item['mediaID'] ] = 1;
1491
+ }
1492
+
1493
+ $results = imagify_get_modified_optimization_statusses( $statuses );
1494
+
1495
+ if ( ! $results ) {
1496
+ return $response;
1497
+ }
1498
+
1499
+ $response[ $heartbeat_id ] = [];
1500
+
1501
+ foreach ( $results as $result ) {
1502
+ $response[ $heartbeat_id ][] = [
1503
+ 'mediaID' => $result['media_id'],
1504
+ 'context' => $result['context'],
1505
+ ];
1506
+ }
1507
+
1508
+ return $response;
1509
+ }
1510
+
1511
+ /**
1512
+ * Look for media where status has changed, compared to what Imagifybeat sends.
1513
+ * This is used in the WP Media Library.
1514
+ *
1515
+ * @since 1.9
1516
+ * @since 1.9.3 Deprecated.
1517
+ * @author Grégory Viguier
1518
+ * @deprecated
1519
+ *
1520
+ * @param array $response The Imagifybeat response.
1521
+ * @param array $data The $_POST data sent.
1522
+ * @return array
1523
+ */
1524
+ function imagify_heartbeat_optimization_status_received( $response, $data ) {
1525
+ _deprecated_function( __FUNCTION__ . '()', '1.9.3', '\\Imagify\\Imagifybeat\\Actions::get_instance()->add_library_optimization_status_to_response()' );
1526
+
1527
+ $heartbeat_id = get_imagify_localize_script_translations( 'media-modal' );
1528
+ $heartbeat_id = $heartbeat_id['heartbeatId'];
1529
+
1530
+ if ( empty( $data[ $heartbeat_id ] ) || ! is_array( $data[ $heartbeat_id ] ) ) {
1531
+ return $response;
1532
+ }
1533
+
1534
+ $response[ $heartbeat_id ] = imagify_get_modified_optimization_statusses( $data[ $heartbeat_id ] );
1535
+
1536
+ if ( ! $response[ $heartbeat_id ] ) {
1537
+ return $response;
1538
+ }
1539
+
1540
+ // Sanitize received data and grab some other info.
1541
+ foreach ( $response[ $heartbeat_id ] as $context_id => $media_atts ) {
1542
+ $process = imagify_get_optimization_process( $media_atts['media_id'], $media_atts['context'] );
1543
+
1544
+ $response[ $heartbeat_id ][ $context_id ] = get_imagify_media_column_content( $process, false );
1545
+ }
1546
+
1547
+ return $response;
1548
+ }
1549
+
1550
+ /**
1551
+ * Look for media where status has changed, compared to what Imagifybeat sends.
1552
+ * This is used in the custom folders list (the "Other Media" page).
1553
+ *
1554
+ * @since 1.9
1555
+ * @since 1.9.3 Deprecated.
1556
+ * @author Grégory Viguier
1557
+ * @deprecated
1558
+ *
1559
+ * @param array $response The Imagifybeat response.
1560
+ * @param array $data The $_POST data sent.
1561
+ * @return array
1562
+ */
1563
+ function imagify_heartbeat_custom_folders_optimization_status_received( $response, $data ) {
1564
+ _deprecated_function( __FUNCTION__ . '()', '1.9.3', '\\Imagify\\Imagifybeat\\Actions::get_instance()->add_custom_folders_optimization_status_to_response()' );
1565
+
1566
+ $heartbeat_id = get_imagify_localize_script_translations( 'files-list' );
1567
+ $heartbeat_id = $heartbeat_id['heartbeatId'];
1568
+
1569
+ if ( empty( $data[ $heartbeat_id ] ) || ! is_array( $data[ $heartbeat_id ] ) ) {
1570
+ return $response;
1571
+ }
1572
+
1573
+ $response[ $heartbeat_id ] = imagify_get_modified_optimization_statusses( $data[ $heartbeat_id ] );
1574
+
1575
+ if ( ! $response[ $heartbeat_id ] ) {
1576
+ return $response;
1577
+ }
1578
+
1579
+ $admin_ajax_post = Imagify_Admin_Ajax_Post::get_instance();
1580
+ $list_table = new Imagify_Files_List_Table( [
1581
+ 'screen' => 'imagify-files',
1582
+ ] );
1583
+
1584
+ // Sanitize received data and grab some other info.
1585
+ foreach ( $response[ $heartbeat_id ] as $context_id => $media_atts ) {
1586
+ $process = imagify_get_optimization_process( $media_atts['media_id'], $media_atts['context'] );
1587
+
1588
+ $response[ $heartbeat_id ][ $context_id ] = $admin_ajax_post->get_media_columns( $process, $list_table );
1589
+ }
1590
+
1591
+ return $response;
1592
+ }
1593
+
1594
+ /**
1595
+ * Look for media where status has changed, compared to what Imagifybeat sends.
1596
+ *
1597
+ * @since 1.9
1598
+ * @since 1.9.3 Deprecated.
1599
+ * @author Grégory Viguier
1600
+ * @deprecated
1601
+ *
1602
+ * @param array $data The data received.
1603
+ * @return array
1604
+ */
1605
+ function imagify_get_modified_optimization_statusses( $data ) {
1606
+ _deprecated_function( __FUNCTION__ . '()', '1.9.3', '\\Imagify\\Imagifybeat\\Actions::get_instance()->get_modified_optimization_statuses()' );
1607
+
1608
+ if ( ! $data ) {
1609
+ return [];
1610
+ }
1611
+
1612
+ $output = [];
1613
+
1614
+ // Sanitize received data and grab some other info.
1615
+ foreach ( $data as $context => $media_statuses ) {
1616
+ if ( ! $context || ! $media_statuses || ! is_array( $media_statuses ) ) {
1617
+ continue;
1618
+ }
1619
+
1620
+ // Sanitize the IDs: IDs come as strings, prefixed with an undescore character (to prevent JavaScript from screwing everything).
1621
+ $media_ids = array_keys( $media_statuses );
1622
+ $media_ids = array_map( function( $media_id ) {
1623
+ return (int) substr( $media_id, 1 );
1624
+ }, $media_ids );
1625
+ $media_ids = array_filter( $media_ids );
1626
+
1627
+ if ( ! $media_ids ) {
1628
+ continue;
1629
+ }
1630
+
1631
+ // Sanitize the context.
1632
+ $context_instance = imagify_get_context( $context );
1633
+ $context = $context_instance->get_name();
1634
+ $process_class_name = imagify_get_optimization_process_class_name( $context );
1635
+ $transient_name = sprintf( $process_class_name::LOCK_NAME, $context, '%' );
1636
+ $is_network_wide = $context_instance->is_network_wide();
1637
+
1638
+ Imagify_DB::cache_process_locks( $context, $media_ids );
1639
+
1640
+ // Now that everything is cached for this context, we can get the transients without hitting the DB.
1641
+ foreach ( $media_ids as $id ) {
1642
+ $is_locked = (bool) $media_statuses[ '_' . $id ];
1643
+ $option_name = str_replace( '%', $id, $transient_name );
1644
+
1645
+ if ( $is_network_wide ) {
1646
+ $in_db = (bool) get_site_transient( $option_name );
1647
+ } else {
1648
+ $in_db = (bool) get_transient( $option_name );
1649
+ }
1650
+
1651
+ if ( $is_locked === $in_db ) {
1652
+ continue;
1653
+ }
1654
+
1655
+ $output[ $context . '_' . $id ] = [
1656
+ 'media_id' => $id,
1657
+ 'context' => $context,
1658
+ ];
1659
+ }
1660
+ }
1661
+
1662
+ return $output;
1663
+ }
1664
+
1665
  endif;
inc/functions/admin-stats.php CHANGED
@@ -350,16 +350,17 @@ function imagify_count_saving_data( $key = '' ) {
350
  continue;
351
  }
352
 
353
- $original_data = $attachment_data['sizes']['full'];
354
-
355
- if ( empty( $original_data['success'] ) ) {
356
  /**
357
- * Case where this attachment has multiple '_imagify_status' metas, and is fetched (in the above query) as a "success" while the '_imagify_data' says otherwise.
358
- * Don't ask how it's possible, I don't know.
 
359
  */
360
  continue;
361
  }
362
 
 
 
363
  ++$count;
364
 
365
  // Increment the original sizes.
350
  continue;
351
  }
352
 
353
+ if ( empty( $attachment_data['sizes']['full']['success'] ) ) {
 
 
354
  /**
355
+ * - Case where this attachment has multiple '_imagify_status' metas, and is fetched (in the above query) as a "success" while the '_imagify_data' says otherwise.
356
+ * - Case where this meta has no "full" entry.
357
+ * Don't ask how it's possible, I don't know ¯\(°_o)/¯
358
  */
359
  continue;
360
  }
361
 
362
+ $original_data = $attachment_data['sizes']['full'];
363
+
364
  ++$count;
365
 
366
  // Increment the original sizes.
inc/functions/i18n.php CHANGED
@@ -13,6 +13,8 @@ defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
13
  function get_imagify_localize_script_translations( $context ) {
14
  global $post_id;
15
 
 
 
16
  switch ( $context ) {
17
  case 'admin-bar':
18
  if ( is_admin() ) {
@@ -81,9 +83,9 @@ function get_imagify_localize_script_translations( $context ) {
81
  'apiDown' => Imagify_Requirements::is_imagify_blocked() || ! Imagify_Requirements::is_api_up(),
82
  'keyIsValid' => ! Imagify_Requirements::is_imagify_blocked() && Imagify_Requirements::is_api_up() && Imagify_Requirements::is_api_key_valid(),
83
  'isOverQuota' => ! Imagify_Requirements::is_imagify_blocked() && Imagify_Requirements::is_api_up() && Imagify_Requirements::is_api_key_valid() && Imagify_Requirements::is_over_quota(),
84
- 'heartbeatIDs' => [
85
- 'queue' => 'imagify_options_bulk_queue',
86
- 'requirements' => 'imagify_bulk_requirements',
87
  ],
88
  'ajaxActions' => [
89
  'getMediaIds' => 'imagify_get_media_ids',
@@ -176,9 +178,12 @@ function get_imagify_localize_script_translations( $context ) {
176
  ],
177
  ];
178
 
 
 
 
179
  case 'media-modal':
180
  return [
181
- 'heartbeatId' => 'imagify_optimization_status',
182
  ];
183
 
184
  case 'library':
@@ -199,10 +204,10 @@ function get_imagify_localize_script_translations( $context ) {
199
  'apiDown' => Imagify_Requirements::is_imagify_blocked() || ! Imagify_Requirements::is_api_up(),
200
  'keyIsValid' => ! Imagify_Requirements::is_imagify_blocked() && Imagify_Requirements::is_api_up() && Imagify_Requirements::is_api_key_valid(),
201
  'isOverQuota' => ! Imagify_Requirements::is_imagify_blocked() && Imagify_Requirements::is_api_up() && Imagify_Requirements::is_api_key_valid() && Imagify_Requirements::is_over_quota(),
202
- 'heartbeatIDs' => [
203
- 'stats' => 'imagify_bulk_data',
204
- 'queue' => 'imagify_bulk_queue',
205
- 'requirements' => 'imagify_bulk_requirements',
206
  ],
207
  'waitImageUrl' => IMAGIFY_ASSETS_IMG_URL . 'popin-loader.svg',
208
  'ajaxActions' => [
@@ -266,7 +271,7 @@ function get_imagify_localize_script_translations( $context ) {
266
  ];
267
 
268
  if ( get_transient( 'imagify_large_library' ) ) {
269
- // On huge media libraries, don't use heartbeat, and fetch stats only when the process ends.
270
  $translations['ajaxActions']['getStats'] = 'imagify_bulk_get_stats';
271
  }
272
 
@@ -297,10 +302,10 @@ function get_imagify_localize_script_translations( $context ) {
297
 
298
  case 'files-list':
299
  return [
300
- 'backupOption' => get_imagify_option( 'backup' ),
301
- 'context' => 'custom-folders',
302
- 'heartbeatId' => 'imagify_custom_folders_optimization_status',
303
- 'labels' => [
304
  'bulkActionsOptimize' => __( 'Optimize', 'imagify' ),
305
  'bulkActionsRestore' => __( 'Restore Original', 'imagify' ),
306
  ],
13
  function get_imagify_localize_script_translations( $context ) {
14
  global $post_id;
15
 
16
+ $imagifybeat_actions = \Imagify\Imagifybeat\Actions::get_instance();
17
+
18
  switch ( $context ) {
19
  case 'admin-bar':
20
  if ( is_admin() ) {
83
  'apiDown' => Imagify_Requirements::is_imagify_blocked() || ! Imagify_Requirements::is_api_up(),
84
  'keyIsValid' => ! Imagify_Requirements::is_imagify_blocked() && Imagify_Requirements::is_api_up() && Imagify_Requirements::is_api_key_valid(),
85
  'isOverQuota' => ! Imagify_Requirements::is_imagify_blocked() && Imagify_Requirements::is_api_up() && Imagify_Requirements::is_api_key_valid() && Imagify_Requirements::is_over_quota(),
86
+ 'imagifybeatIDs' => [
87
+ 'queue' => $imagifybeat_actions->get_imagifybeat_id( 'bulk_optimization_status' ),
88
+ 'requirements' => $imagifybeat_actions->get_imagifybeat_id( 'requirements' ),
89
  ],
90
  'ajaxActions' => [
91
  'getMediaIds' => 'imagify_get_media_ids',
178
  ],
179
  ];
180
 
181
+ case 'beat':
182
+ return \Imagify\Imagifybeat\Core::get_instance()->get_settings();
183
+
184
  case 'media-modal':
185
  return [
186
+ 'imagifybeatID' => $imagifybeat_actions->get_imagifybeat_id( 'library_optimization_status' ),
187
  ];
188
 
189
  case 'library':
204
  'apiDown' => Imagify_Requirements::is_imagify_blocked() || ! Imagify_Requirements::is_api_up(),
205
  'keyIsValid' => ! Imagify_Requirements::is_imagify_blocked() && Imagify_Requirements::is_api_up() && Imagify_Requirements::is_api_key_valid(),
206
  'isOverQuota' => ! Imagify_Requirements::is_imagify_blocked() && Imagify_Requirements::is_api_up() && Imagify_Requirements::is_api_key_valid() && Imagify_Requirements::is_over_quota(),
207
+ 'imagifybeatIDs' => [
208
+ 'stats' => $imagifybeat_actions->get_imagifybeat_id( 'bulk_optimization_stats' ),
209
+ 'queue' => $imagifybeat_actions->get_imagifybeat_id( 'bulk_optimization_status' ),
210
+ 'requirements' => $imagifybeat_actions->get_imagifybeat_id( 'requirements' ),
211
  ],
212
  'waitImageUrl' => IMAGIFY_ASSETS_IMG_URL . 'popin-loader.svg',
213
  'ajaxActions' => [
271
  ];
272
 
273
  if ( get_transient( 'imagify_large_library' ) ) {
274
+ // On huge media libraries, don't use Imagifybeat, and fetch stats only when the process ends.
275
  $translations['ajaxActions']['getStats'] = 'imagify_bulk_get_stats';
276
  }
277
 
302
 
303
  case 'files-list':
304
  return [
305
+ 'backupOption' => get_imagify_option( 'backup' ),
306
+ 'context' => 'custom-folders',
307
+ 'imagifybeatID' => $imagifybeat_actions->get_imagifybeat_id( 'custom_folders_optimization_status' ),
308
+ 'labels' => [
309
  'bulkActionsOptimize' => __( 'Optimize', 'imagify' ),
310
  'bulkActionsRestore' => __( 'Restore Original', 'imagify' ),
311
  ],
package.json CHANGED
@@ -1,7 +1,7 @@
1
  {
2
  "name": "imagify",
3
  "description": "Imagify Image Optimizer. Dramatically reduce image file sizes without losing quality, make your website load faster, boost your SEO and save money on your bandwidth.",
4
- "version": "1.9.2",
5
  "homepage": "https://wordpress.org/plugins/imagify/",
6
  "license": "GPL-2.0",
7
  "private": true,
1
  {
2
  "name": "imagify",
3
  "description": "Imagify Image Optimizer. Dramatically reduce image file sizes without losing quality, make your website load faster, boost your SEO and save money on your bandwidth.",
4
+ "version": "1.9.3",
5
  "homepage": "https://wordpress.org/plugins/imagify/",
6
  "license": "GPL-2.0",
7
  "private": true,
readme.txt CHANGED
@@ -1,9 +1,9 @@
1
- === Imagify Image Optimizer ===
2
  Contributors: wp_media, GregLone
3
- Tags: compress image, images, performance, optimization, photos, upload, resize, gif, png, jpg, reduce image size, retina
4
  Requires at least: 4.0.0
5
- Tested up to: 5.2
6
- Stable tag: 1.9.2
7
 
8
  Dramatically reduce image file sizes without losing quality, make your website load faster, boost your SEO and save money on your bandwidth.
9
 
@@ -11,8 +11,8 @@ Dramatically reduce image file sizes without losing quality, make your website l
11
 
12
  Speed up your website with lighter images without losing quality.
13
 
14
- Imagify is the most advanced image compression tool, you can now use this power directly in WordPress.
15
- After enabling it, all your images including thumbnails will be automatically optimized when uploaded into WordPress. You can also use Imagify to convert and serve WebP images for free.
16
 
17
  WooCommerce and NextGen Gallery compatible.
18
 
@@ -34,6 +34,21 @@ Three level of compression are available:
34
 
35
  With the backup option, you can change your mind whenever you want by restoring your images to their original version or optimize them to another compression level.
36
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  = What our users think of Imagify? =
38
 
39
  > "Imagify is an awesome tool that is powerful & easy to use. It's fast, rivals and surpasses other established plugins/software. Awesome!" — [Simon Harper](https://twitter.com/SRHDesign/status/663758140505235456)
@@ -138,6 +153,16 @@ When the plugin is disabled, your existing images remain optimized. Backups of t
138
  4. Other Media Page
139
 
140
  == Changelog ==
 
 
 
 
 
 
 
 
 
 
141
  = 1.9.2 - 2019/05/16 =
142
  * Fix: don’t display support bubble anymore.
143
 
1
+ === Imagify - WebP & Image Compression ===
2
  Contributors: wp_media, GregLone
3
+ Tags: compress image, images, performance, optimization, webp
4
  Requires at least: 4.0.0
5
+ Tested up to: 5.2.2
6
+ Stable tag: 1.9.3
7
 
8
  Dramatically reduce image file sizes without losing quality, make your website load faster, boost your SEO and save money on your bandwidth.
9
 
11
 
12
  Speed up your website with lighter images without losing quality.
13
 
14
+ Imagify is the most advanced tool to optimize images. You can now use this power directly in WordPress.
15
+ After enabling it, all your images including thumbnails will be automatically optimized when uploaded into WordPress. You can also use Imagify to convert WebP images for free.
16
 
17
  WooCommerce and NextGen Gallery compatible.
18
 
34
 
35
  With the backup option, you can change your mind whenever you want by restoring your images to their original version or optimize them to another compression level.
36
 
37
+ = HOW ABOUT WEBP IMAGES? =
38
+ Now, for each image you optimize with the Imagify plugin, you’ll also get its **WebP version** (if you tick the option in the settings); in your Media library, this will result in the following image versions:
39
+ - full-sized optimized image,
40
+ - full-sized WebP image,
41
+ - optimized thumbnails,
42
+ - WebP thumbnails.
43
+
44
+ The optimization will also work for images included in your themes and plugins.
45
+
46
+ If you want, Imagify can also display WebP images on your front-end in two ways:
47
+ - `<picture>` tag,
48
+ - rewrite rules in the .htaccess file.
49
+
50
+ If you kept a backup copy of the original images, you have the possibility to **create their WebP version separately** (one by one or via the bulk optimization).
51
+
52
  = What our users think of Imagify? =
53
 
54
  > "Imagify is an awesome tool that is powerful & easy to use. It's fast, rivals and surpasses other established plugins/software. Awesome!" — [Simon Harper](https://twitter.com/SRHDesign/status/663758140505235456)
153
  4. Other Media Page
154
 
155
  == Changelog ==
156
+ = 1.9.3 - 2019/06/17 =
157
+ * Improvement: better compatibility with CDNs when displaying webp images with `&lt;picture&gt;` tags. There is now a new setting field to fill in the CDN URL in use.
158
+ * Improvement: don’t use Heartbeat anymore. This speeds up the optimization process and prevents other plugins to break everything when they remove Heartbeat.
159
+ * Fix: a fatal error upon plugin deactivation.
160
+ * Fix: an occasional fatal error preventing the optimization process to work.
161
+ * Fix: conflict with plugins using an ancient version of Composer.
162
+ * Fix: php notices displayed on the bulk optimization page on rare cases.
163
+ * Fix: a php notice about "Non-string needles" with php 7.3.
164
+ * Fix: a php notice displayed when restoring a custom file.
165
+
166
  = 1.9.2 - 2019/05/16 =
167
  * Fix: don’t display support bubble anymore.
168
 
vendor/autoload.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
- return ComposerAutoloaderInitb780e2ce7c81834ff923ca9ba6283b0f::getLoader();
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInit2efd1f353f7434673320a5d6ba6d8b75::getLoader();
vendor/composer/autoload_classmap.php CHANGED
@@ -109,6 +109,8 @@ return array(
109
  'Imagify\\Context\\Noop' => $baseDir . '/classes/Context/Noop.php',
110
  'Imagify\\Context\\WP' => $baseDir . '/classes/Context/WP.php',
111
  'Imagify\\DB\\DBInterface' => $baseDir . '/classes/DB/DBInterface.php',
 
 
112
  'Imagify\\Job\\MediaOptimization' => $baseDir . '/classes/Job/MediaOptimization.php',
113
  'Imagify\\Media\\AbstractMedia' => $baseDir . '/classes/Media/AbstractMedia.php',
114
  'Imagify\\Media\\CustomFolders' => $baseDir . '/classes/Media/CustomFolders.php',
@@ -142,6 +144,7 @@ return array(
142
  'Imagify\\ThirdParty\\NGG\\Optimization\\Data\\NGG' => $baseDir . '/inc/3rd-party/nextgen-gallery/classes/Optimization/Data/NGG.php',
143
  'Imagify\\ThirdParty\\NGG\\Optimization\\Process\\NGG' => $baseDir . '/inc/3rd-party/nextgen-gallery/classes/Optimization/Process/NGG.php',
144
  'Imagify\\ThirdParty\\RegenerateThumbnails\\Main' => $baseDir . '/inc/3rd-party/regenerate-thumbnails/classes/Main.php',
 
145
  'Imagify\\Traits\\FakeSingletonTrait' => $baseDir . '/classes/Traits/FakeSingletonTrait.php',
146
  'Imagify\\Traits\\MediaRowTrait' => $baseDir . '/classes/Traits/MediaRowTrait.php',
147
  'Imagify\\Webp\\Apache' => $baseDir . '/classes/Webp/Apache.php',
109
  'Imagify\\Context\\Noop' => $baseDir . '/classes/Context/Noop.php',
110
  'Imagify\\Context\\WP' => $baseDir . '/classes/Context/WP.php',
111
  'Imagify\\DB\\DBInterface' => $baseDir . '/classes/DB/DBInterface.php',
112
+ 'Imagify\\Imagifybeat\\Actions' => $baseDir . '/classes/Imagifybeat/Actions.php',
113
+ 'Imagify\\Imagifybeat\\Core' => $baseDir . '/classes/Imagifybeat/Core.php',
114
  'Imagify\\Job\\MediaOptimization' => $baseDir . '/classes/Job/MediaOptimization.php',
115
  'Imagify\\Media\\AbstractMedia' => $baseDir . '/classes/Media/AbstractMedia.php',
116
  'Imagify\\Media\\CustomFolders' => $baseDir . '/classes/Media/CustomFolders.php',
144
  'Imagify\\ThirdParty\\NGG\\Optimization\\Data\\NGG' => $baseDir . '/inc/3rd-party/nextgen-gallery/classes/Optimization/Data/NGG.php',
145
  'Imagify\\ThirdParty\\NGG\\Optimization\\Process\\NGG' => $baseDir . '/inc/3rd-party/nextgen-gallery/classes/Optimization/Process/NGG.php',
146
  'Imagify\\ThirdParty\\RegenerateThumbnails\\Main' => $baseDir . '/inc/3rd-party/regenerate-thumbnails/classes/Main.php',
147
+ 'Imagify\\ThirdParty\\WPRocket\\Main' => $baseDir . '/inc/3rd-party/wp-rocket/classes/Main.php',
148
  'Imagify\\Traits\\FakeSingletonTrait' => $baseDir . '/classes/Traits/FakeSingletonTrait.php',
149
  'Imagify\\Traits\\MediaRowTrait' => $baseDir . '/classes/Traits/MediaRowTrait.php',
150
  'Imagify\\Webp\\Apache' => $baseDir . '/classes/Webp/Apache.php',
vendor/composer/autoload_psr4.php CHANGED
@@ -6,6 +6,7 @@ $vendorDir = dirname(dirname(__FILE__));
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
 
9
  'Imagify\\ThirdParty\\RegenerateThumbnails\\' => array($baseDir . '/inc/3rd-party/regenerate-thumbnails/classes'),
10
  'Imagify\\ThirdParty\\NGG\\' => array($baseDir . '/inc/3rd-party/nextgen-gallery/classes'),
11
  'Imagify\\ThirdParty\\FormidablePro\\' => array($baseDir . '/inc/3rd-party/formidable-pro/classes'),
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
9
+ 'Imagify\\ThirdParty\\WPRocket\\' => array($baseDir . '/inc/3rd-party/wp-rocket/classes'),
10
  'Imagify\\ThirdParty\\RegenerateThumbnails\\' => array($baseDir . '/inc/3rd-party/regenerate-thumbnails/classes'),
11
  'Imagify\\ThirdParty\\NGG\\' => array($baseDir . '/inc/3rd-party/nextgen-gallery/classes'),
12
  'Imagify\\ThirdParty\\FormidablePro\\' => array($baseDir . '/inc/3rd-party/formidable-pro/classes'),
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInitb780e2ce7c81834ff923ca9ba6283b0f
6
  {
7
  private static $loader;
8
 
@@ -19,15 +19,15 @@ class ComposerAutoloaderInitb780e2ce7c81834ff923ca9ba6283b0f
19
  return self::$loader;
20
  }
21
 
22
- spl_autoload_register(array('ComposerAutoloaderInitb780e2ce7c81834ff923ca9ba6283b0f', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInitb780e2ce7c81834ff923ca9ba6283b0f', 'loadClassLoader'));
25
 
26
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27
  if ($useStaticLoader) {
28
  require_once __DIR__ . '/autoload_static.php';
29
 
30
- call_user_func(\Composer\Autoload\ComposerStaticInitb780e2ce7c81834ff923ca9ba6283b0f::getInitializer($loader));
31
  } else {
32
  $classMap = require __DIR__ . '/autoload_classmap.php';
33
  if ($classMap) {
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInit2efd1f353f7434673320a5d6ba6d8b75
6
  {
7
  private static $loader;
8
 
19
  return self::$loader;
20
  }
21
 
22
+ spl_autoload_register(array('ComposerAutoloaderInit2efd1f353f7434673320a5d6ba6d8b75', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInit2efd1f353f7434673320a5d6ba6d8b75', 'loadClassLoader'));
25
 
26
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27
  if ($useStaticLoader) {
28
  require_once __DIR__ . '/autoload_static.php';
29
 
30
+ call_user_func(\Composer\Autoload\ComposerStaticInit2efd1f353f7434673320a5d6ba6d8b75::getInitializer($loader));
31
  } else {
32
  $classMap = require __DIR__ . '/autoload_classmap.php';
33
  if ($classMap) {
vendor/composer/autoload_static.php CHANGED
@@ -4,11 +4,12 @@
4
 
5
  namespace Composer\Autoload;
6
 
7
- class ComposerStaticInitb780e2ce7c81834ff923ca9ba6283b0f
8
  {
9
  public static $prefixLengthsPsr4 = array (
10
  'I' =>
11
  array (
 
12
  'Imagify\\ThirdParty\\RegenerateThumbnails\\' => 40,
13
  'Imagify\\ThirdParty\\NGG\\' => 23,
14
  'Imagify\\ThirdParty\\FormidablePro\\' => 33,
@@ -23,6 +24,10 @@ class ComposerStaticInitb780e2ce7c81834ff923ca9ba6283b0f
23
  );
24
 
25
  public static $prefixDirsPsr4 = array (
 
 
 
 
26
  'Imagify\\ThirdParty\\RegenerateThumbnails\\' =>
27
  array (
28
  0 => __DIR__ . '/../..' . '/inc/3rd-party/regenerate-thumbnails/classes',
@@ -157,6 +162,8 @@ class ComposerStaticInitb780e2ce7c81834ff923ca9ba6283b0f
157
  'Imagify\\Context\\Noop' => __DIR__ . '/../..' . '/classes/Context/Noop.php',
158
  'Imagify\\Context\\WP' => __DIR__ . '/../..' . '/classes/Context/WP.php',
159
  'Imagify\\DB\\DBInterface' => __DIR__ . '/../..' . '/classes/DB/DBInterface.php',
 
 
160
  'Imagify\\Job\\MediaOptimization' => __DIR__ . '/../..' . '/classes/Job/MediaOptimization.php',
161
  'Imagify\\Media\\AbstractMedia' => __DIR__ . '/../..' . '/classes/Media/AbstractMedia.php',
162
  'Imagify\\Media\\CustomFolders' => __DIR__ . '/../..' . '/classes/Media/CustomFolders.php',
@@ -190,6 +197,7 @@ class ComposerStaticInitb780e2ce7c81834ff923ca9ba6283b0f
190
  'Imagify\\ThirdParty\\NGG\\Optimization\\Data\\NGG' => __DIR__ . '/../..' . '/inc/3rd-party/nextgen-gallery/classes/Optimization/Data/NGG.php',
191
  'Imagify\\ThirdParty\\NGG\\Optimization\\Process\\NGG' => __DIR__ . '/../..' . '/inc/3rd-party/nextgen-gallery/classes/Optimization/Process/NGG.php',
192
  'Imagify\\ThirdParty\\RegenerateThumbnails\\Main' => __DIR__ . '/../..' . '/inc/3rd-party/regenerate-thumbnails/classes/Main.php',
 
193
  'Imagify\\Traits\\FakeSingletonTrait' => __DIR__ . '/../..' . '/classes/Traits/FakeSingletonTrait.php',
194
  'Imagify\\Traits\\MediaRowTrait' => __DIR__ . '/../..' . '/classes/Traits/MediaRowTrait.php',
195
  'Imagify\\Webp\\Apache' => __DIR__ . '/../..' . '/classes/Webp/Apache.php',
@@ -252,9 +260,9 @@ class ComposerStaticInitb780e2ce7c81834ff923ca9ba6283b0f
252
  public static function getInitializer(ClassLoader $loader)
253
  {
254
  return \Closure::bind(function () use ($loader) {
255
- $loader->prefixLengthsPsr4 = ComposerStaticInitb780e2ce7c81834ff923ca9ba6283b0f::$prefixLengthsPsr4;
256
- $loader->prefixDirsPsr4 = ComposerStaticInitb780e2ce7c81834ff923ca9ba6283b0f::$prefixDirsPsr4;
257
- $loader->classMap = ComposerStaticInitb780e2ce7c81834ff923ca9ba6283b0f::$classMap;
258
 
259
  }, null, ClassLoader::class);
260
  }
4
 
5
  namespace Composer\Autoload;
6
 
7
+ class ComposerStaticInit2efd1f353f7434673320a5d6ba6d8b75
8
  {
9
  public static $prefixLengthsPsr4 = array (
10
  'I' =>
11
  array (
12
+ 'Imagify\\ThirdParty\\WPRocket\\' => 28,
13
  'Imagify\\ThirdParty\\RegenerateThumbnails\\' => 40,
14
  'Imagify\\ThirdParty\\NGG\\' => 23,
15
  'Imagify\\ThirdParty\\FormidablePro\\' => 33,
24
  );
25
 
26
  public static $prefixDirsPsr4 = array (
27
+ 'Imagify\\ThirdParty\\WPRocket\\' =>
28
+ array (
29
+ 0 => __DIR__ . '/../..' . '/inc/3rd-party/wp-rocket/classes',
30
+ ),
31
  'Imagify\\ThirdParty\\RegenerateThumbnails\\' =>
32
  array (
33
  0 => __DIR__ . '/../..' . '/inc/3rd-party/regenerate-thumbnails/classes',
162
  'Imagify\\Context\\Noop' => __DIR__ . '/../..' . '/classes/Context/Noop.php',
163
  'Imagify\\Context\\WP' => __DIR__ . '/../..' . '/classes/Context/WP.php',
164
  'Imagify\\DB\\DBInterface' => __DIR__ . '/../..' . '/classes/DB/DBInterface.php',
165
+ 'Imagify\\Imagifybeat\\Actions' => __DIR__ . '/../..' . '/classes/Imagifybeat/Actions.php',
166
+ 'Imagify\\Imagifybeat\\Core' => __DIR__ . '/../..' . '/classes/Imagifybeat/Core.php',
167
  'Imagify\\Job\\MediaOptimization' => __DIR__ . '/../..' . '/classes/Job/MediaOptimization.php',
168
  'Imagify\\Media\\AbstractMedia' => __DIR__ . '/../..' . '/classes/Media/AbstractMedia.php',
169
  'Imagify\\Media\\CustomFolders' => __DIR__ . '/../..' . '/classes/Media/CustomFolders.php',
197
  'Imagify\\ThirdParty\\NGG\\Optimization\\Data\\NGG' => __DIR__ . '/../..' . '/inc/3rd-party/nextgen-gallery/classes/Optimization/Data/NGG.php',
198
  'Imagify\\ThirdParty\\NGG\\Optimization\\Process\\NGG' => __DIR__ . '/../..' . '/inc/3rd-party/nextgen-gallery/classes/Optimization/Process/NGG.php',
199
  'Imagify\\ThirdParty\\RegenerateThumbnails\\Main' => __DIR__ . '/../..' . '/inc/3rd-party/regenerate-thumbnails/classes/Main.php',
200
+ 'Imagify\\ThirdParty\\WPRocket\\Main' => __DIR__ . '/../..' . '/inc/3rd-party/wp-rocket/classes/Main.php',
201
  'Imagify\\Traits\\FakeSingletonTrait' => __DIR__ . '/../..' . '/classes/Traits/FakeSingletonTrait.php',
202
  'Imagify\\Traits\\MediaRowTrait' => __DIR__ . '/../..' . '/classes/Traits/MediaRowTrait.php',
203
  'Imagify\\Webp\\Apache' => __DIR__ . '/../..' . '/classes/Webp/Apache.php',
260
  public static function getInitializer(ClassLoader $loader)
261
  {
262
  return \Closure::bind(function () use ($loader) {
263
+ $loader->prefixLengthsPsr4 = ComposerStaticInit2efd1f353f7434673320a5d6ba6d8b75::$prefixLengthsPsr4;
264
+ $loader->prefixDirsPsr4 = ComposerStaticInit2efd1f353f7434673320a5d6ba6d8b75::$prefixDirsPsr4;
265
+ $loader->classMap = ComposerStaticInit2efd1f353f7434673320a5d6ba6d8b75::$classMap;
266
 
267
  }, null, ClassLoader::class);
268
  }
views/part-settings-webp.php CHANGED
@@ -22,9 +22,6 @@ $settings = Imagify_Settings::get_instance();
22
  $settings->field_checkbox( [
23
  'option_name' => 'display_webp',
24
  'label' => __( 'Display images in webp format on the site', 'imagify' ),
25
- 'attributes' => [
26
- 'aria-describedby' => 'describe-convert_to_webp',
27
- ],
28
  ] );
29
  ?>
30
 
@@ -33,53 +30,98 @@ $settings = Imagify_Settings::get_instance();
33
  $settings->field_radio_list( [
34
  'option_name' => 'display_webp_method',
35
  'values' => [
36
- 'picture' => __( 'Use &lt;picture&gt; tags', 'imagify' ),
37
  'rewrite' => __( 'Use rewrite rules', 'imagify' ),
 
 
38
  ],
39
  'attributes' => [
40
  'aria-describedby' => 'describe-convert_to_webp',
41
  ],
42
  ] );
43
  ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  </div>
45
- </div>
46
 
47
- <div id="describe-convert_to_webp" class="imagify-info">
48
- <span class="dashicons dashicons-info"></span>
49
- <?php
50
- printf(
51
- /* translators: 1 and 2 are HTML tag names, 3 is a <strong> tag opening, 4 is the <strong> tag closing. */
52
- esc_html__( 'The first option replaces the %1$s tags with %2$s tags. %3$sThis is the preferred solution but some themes may break%4$s, so make sure to verify that everything seems fine.', 'imagify' ),
53
- '<code>&lt;img&gt;</code>',
54
- '<code>&lt;picture&gt;</code>',
55
- '<strong>',
56
- '</strong>'
57
- );
58
 
59
- echo '<br/>';
 
 
 
 
 
 
 
60
 
61
- $conf_file_path = \Imagify\Webp\Display::get_instance()->get_file_path( true );
 
62
 
63
- if ( $conf_file_path ) {
64
  printf(
65
- /* translators: 1 is a file name, 2 is a <strong> tag opening, 3 is the <strong> tag closing. */
66
- esc_html__( 'The second option adds rewrite rules to your site’s configuration file (%1$s) and does not alter your pages code. %2$sThis does not work with CDN though.%3$s', 'imagify' ),
67
- '<code>' . esc_html( $conf_file_path ) . '</code>',
 
68
  '<strong>',
69
  '</strong>'
70
  );
71
 
72
  echo '<br/>';
73
- }
74
 
75
- /**
76
- * Add more information about webp.
77
- *
78
- * @since 1.9
79
- * @author Grégory Viguier
80
- */
81
- do_action( 'imagify_settings_webp_info' );
82
- ?>
 
83
  </div>
84
 
85
  <?php
@@ -93,7 +135,7 @@ $settings = Imagify_Settings::get_instance();
93
  echo esc_html(
94
  sprintf(
95
  /* translators: %s is a formatted number (don’t use %d). */
96
- _n( 'It seems that you have %s media without webp versions. You can generate them here if a backup copy is available.', 'It seems that you have %s media without webp versions. You can generate them here if backup copies are available.', $count, 'imagify' ),
97
  number_format_i18n( $count )
98
  )
99
  );
22
  $settings->field_checkbox( [
23
  'option_name' => 'display_webp',
24
  'label' => __( 'Display images in webp format on the site', 'imagify' ),
 
 
 
25
  ] );
26
  ?>
27
 
30
  $settings->field_radio_list( [
31
  'option_name' => 'display_webp_method',
32
  'values' => [
 
33
  'rewrite' => __( 'Use rewrite rules', 'imagify' ),
34
+ /* translators: 1 and 2 are <em> tag opening and closing. */
35
+ 'picture' => sprintf( __( 'Use &lt;picture&gt; tags %1$s(preferred)%2$s', 'imagify' ), '<em>', '</em>' ),
36
  ],
37
  'attributes' => [
38
  'aria-describedby' => 'describe-convert_to_webp',
39
  ],
40
  ] );
41
  ?>
42
+
43
+ <div class="imagify-options-line">
44
+ <?php
45
+ $cdn_source = \Imagify\Webp\Picture\Display::get_instance()->get_cdn_source();
46
+
47
+ if ( 'option' !== $cdn_source['source'] ) {
48
+ if ( 'constant' === $cdn_source['source'] ) {
49
+ printf(
50
+ /* translators: 1 is an URL, 2 is a php constant name. */
51
+ esc_html__( 'Your CDN URL is set to %1$s by the constant %2$s.', 'imagify' ),
52
+ '<code>' . esc_url( $cdn_source['url'] ) . '</code>',
53
+ '<code>' . esc_html( $cdn_source['name'] ) . '</code>'
54
+ );
55
+ } elseif ( ! empty( $cdn_source['name'] ) ) {
56
+ printf(
57
+ /* translators: 1 is an URL, 2 is a plugin name. */
58
+ esc_html__( 'Your CDN URL is set to %1$s by %2$s.', 'imagify' ),
59
+ '<code>' . esc_url( $cdn_source['url'] ) . '</code>',
60
+ '<code>' . esc_html( $cdn_source['name'] ) . '</code>'
61
+ );
62
+ } else {
63
+ printf(
64
+ /* translators: %s is an URL. */
65
+ esc_html__( 'Your CDN URL is set to %1$s by filter.', 'imagify' ),
66
+ '<code>' . esc_url( $cdn_source['url'] ) . '</code>'
67
+ );
68
+ }
69
+
70
+ $settings->field_hidden( [
71
+ 'option_name' => 'cdn_url',
72
+ 'current_value' => $cdn_source['url'],
73
+ ] );
74
+ } else {
75
+ $settings->field_text_box( [
76
+ 'option_name' => 'cdn_url',
77
+ 'label' => __( 'If you use a CDN, specify the URL:', 'imagify' ),
78
+ 'attributes' => [
79
+ 'size' => 30,
80
+ 'placeholder' => __( 'https://cdn.example.com', 'imagify' ),
81
+ ],
82
+ ] );
83
+ }
84
+ ?>
85
+ </div>
86
  </div>
 
87
 
88
+ <div id="describe-display_webp_method" class="imagify-info">
89
+ <span class="dashicons dashicons-info"></span>
90
+ <?php
91
+ $conf_file_path = \Imagify\Webp\Display::get_instance()->get_file_path( true );
 
 
 
 
 
 
 
92
 
93
+ if ( $conf_file_path ) {
94
+ printf(
95
+ /* translators: 1 is a file name, 2 is a <strong> tag opening, 3 is the <strong> tag closing. */
96
+ esc_html__( 'The first option adds rewrite rules to your site’s configuration file (%1$s) and does not alter your pages code. %2$sThis does not work with CDN though.%3$s', 'imagify' ),
97
+ '<code>' . esc_html( $conf_file_path ) . '</code>',
98
+ '<strong>',
99
+ '</strong>'
100
+ );
101
 
102
+ echo '<br/>';
103
+ }
104
 
 
105
  printf(
106
+ /* translators: 1 and 2 are HTML tag names, 3 is a <strong> tag opening, 4 is the <strong> tag closing. */
107
+ esc_html__( 'The second option replaces the %1$s tags with %2$s tags. %3$sThis is the preferred solution but some themes may break%4$s, so make sure to verify that everything seems fine.', 'imagify' ),
108
+ '<code>&lt;img&gt;</code>',
109
+ '<code>&lt;picture&gt;</code>',
110
  '<strong>',
111
  '</strong>'
112
  );
113
 
114
  echo '<br/>';
 
115
 
116
+ /**
117
+ * Add more information about webp.
118
+ *
119
+ * @since 1.9
120
+ * @author Grégory Viguier
121
+ */
122
+ do_action( 'imagify_settings_webp_info' );
123
+ ?>
124
+ </div>
125
  </div>
126
 
127
  <?php
135
  echo esc_html(
136
  sprintf(
137
  /* translators: %s is a formatted number (don’t use %d). */
138
+ _n( 'It seems that you have %s optimized image without webp versions. You can generate them here if a backup copy is available.', 'It seems that you have %s optimized images without webp versions. You can generate them here if backup copies are available.', $count, 'imagify' ),
139
  number_format_i18n( $count )
140
  )
141
  );