Imagify Image Optimizer - Version 1.6.6

Version Description

  • New: Compatibility with the plugin WP Offload S3 Lite. Your images now will be sent to Amazon S3 after being optimized. Also works when you store your images only on S3, not locally.
  • Improvement: Added a filter to the asynchronous job arguments.
  • Bug fix: Compatibility with Internet Explorer 9 to 11.
  • Regression fix: The comparison tool stopped working in the medias list since the previous version.
Download this release

Release Info

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

Code changes from version 1.6.5 to 1.6.6

Files changed (57) hide show
  1. assets/css/sweetalert2.css +0 -0
  2. assets/css/sweetalert2.min.css +0 -0
  3. assets/images/big-blue-check.png +0 -0
  4. assets/images/icon-arrow-choice.png +0 -0
  5. assets/images/icon-arrow-choice.svg +0 -0
  6. assets/images/icon-lock.png +0 -0
  7. assets/images/icon-lock.svg +0 -0
  8. assets/images/icon-pack.png +0 -0
  9. assets/images/icon-pack.svg +0 -0
  10. assets/images/pic-ericwaltr.jpg +0 -0
  11. assets/images/pic-srhdesign.jpg +0 -0
  12. assets/js/admin.js +16 -16
  13. assets/js/admin.min.js +1 -1
  14. assets/js/bulk.js +5 -3
  15. assets/js/bulk.min.js +1 -1
  16. assets/js/es6-promise.auto.js +1160 -0
  17. assets/js/es6-promise.auto.min.js +1 -0
  18. assets/js/imagify.js +0 -0
  19. assets/js/imagify.min.js +0 -0
  20. assets/js/jquery.twentytwenty.js +4 -4
  21. assets/js/jquery.twentytwenty.min.js +1 -1
  22. assets/js/sweetalert2.js +0 -0
  23. assets/js/sweetalert2.min.js +0 -0
  24. assets/js/upload.js +3 -2
  25. assets/js/upload.min.js +1 -1
  26. imagify.php +2 -2
  27. inc/3rd-party/3rd-party.php +1 -0
  28. inc/3rd-party/amazon-s3-and-cloudfront/amazon-s3-and-cloudfront.php +11 -0
  29. inc/3rd-party/amazon-s3-and-cloudfront/inc/classes/class-imagify-as3cf-attachment.php +831 -0
  30. inc/3rd-party/amazon-s3-and-cloudfront/inc/classes/class-imagify-as3cf.php +295 -0
  31. inc/3rd-party/enable-media-replace.php +2 -4
  32. inc/3rd-party/hosting/wpengine.php +0 -0
  33. inc/3rd-party/nextgen-gallery/inc/admin/heartbeat.php +1 -1
  34. inc/3rd-party/nextgen-gallery/inc/classes/class-imagify-ngg-attachment.php +19 -18
  35. inc/3rd-party/nextgen-gallery/inc/classes/class-imagify-ngg-db.php +0 -0
  36. inc/3rd-party/nextgen-gallery/inc/common/attachments.php +1 -1
  37. inc/3rd-party/nextgen-gallery/inc/functions/admin-stats.php +2 -0
  38. inc/3rd-party/wp-retina-2x.php +2 -2
  39. inc/admin/ajax.php +7 -9
  40. inc/admin/enqueue.php +69 -63
  41. inc/admin/heartbeat.php +1 -1
  42. inc/admin/media.php +2 -2
  43. inc/admin/meta-boxes.php +1 -1
  44. inc/admin/upgrader.php +2 -2
  45. inc/admin/upload.php +1 -1
  46. inc/api/imagify.php +0 -0
  47. inc/classes/abstracts/class-imagify-abstract-attachment.php +16 -3
  48. inc/classes/abstracts/class-imagify-abstract-db.php +0 -0
  49. inc/classes/class-imagify-attachment.php +20 -20
  50. inc/classes/class-imagify.php +0 -0
  51. inc/common/attachments.php +1 -1
  52. inc/functions/admin-stats.php +3 -3
  53. inc/functions/admin-ui.php +0 -0
  54. inc/functions/deprecated.php +0 -0
  55. inc/functions/formatting.php +21 -8
  56. inc/functions/process.php +10 -0
  57. readme.txt +10 -4
assets/css/sweetalert2.css CHANGED
File without changes
assets/css/sweetalert2.min.css CHANGED
File without changes
assets/images/big-blue-check.png CHANGED
File without changes
assets/images/icon-arrow-choice.png CHANGED
File without changes
assets/images/icon-arrow-choice.svg CHANGED
File without changes
assets/images/icon-lock.png CHANGED
File without changes
assets/images/icon-lock.svg CHANGED
File without changes
assets/images/icon-pack.png CHANGED
File without changes
assets/images/icon-pack.svg CHANGED
File without changes
assets/images/pic-ericwaltr.jpg CHANGED
File without changes
assets/images/pic-srhdesign.jpg CHANGED
File without changes
assets/js/admin.js CHANGED
@@ -169,7 +169,7 @@ window.imagify = window.imagify || {
169
  // Imagify light modal =============================================================================
170
  (function($, d, w, undefined) {
171
 
172
- var imagify_open_modal = function( $the_link ) {
173
  var the_target = $the_link.data( 'target' ) || $the_link.attr( 'href' );
174
 
175
  $( the_target ).css( 'display', 'flex' ).hide().fadeIn( 400 ).attr( 'aria-hidden', 'false' ).attr( 'tabindex', '0' ).focus().removeAttr( 'tabindex' ).addClass( 'modal-is-open' );
@@ -181,9 +181,9 @@ window.imagify = window.imagify || {
181
 
182
  $( d )
183
  // On click on modal trigger.
184
- .on( 'click.imagify', '.imagify-modal-trigger', function() {
185
- imagify_open_modal( $( this ) );
186
- return false;
187
  } )
188
  // On click on close button.
189
  .on( 'click.imagify', '.imagify-modal .close-btn', function() {
@@ -211,8 +211,6 @@ window.imagify = window.imagify || {
211
  e.preventDefault();
212
  // Trigger the event.
213
  $( '.imagify-modal.modal-is-open' ).find( '.close-btn' ).trigger( 'click.imagify' );
214
-
215
- return false;
216
  }
217
  } );
218
 
@@ -1027,13 +1025,13 @@ window.imagify = window.imagify || {
1027
  *
1028
  * @uses imagifyModal.switchToView()
1029
  */
1030
- imagifyModal.$anotherBtn.on( 'click.imagify', function() {
1031
  var type = $( this ).data( 'imagify-choose' ),
1032
  tab = 'imagify-pricing-tab-' + ( 'plan' === type ? 'monthly' : 'onetime' );
1033
 
1034
- imagifyModal.switchToView( imagifyModal.$plansView, { tab: tab } );
1035
 
1036
- return false;
1037
  } );
1038
 
1039
  /**
@@ -1043,7 +1041,7 @@ window.imagify = window.imagify || {
1043
  * @uses imagifyModal.switchToView()
1044
  * @uses imagifyModal.populatePayBtn()
1045
  */
1046
- imagifyModal.$modal.on( 'click.imagify', '.imagify-payment-btn-select-plan', function() {
1047
  var $_this = $( this ),
1048
  $offer_line = $_this.closest( '.imagify-offer-line' ),
1049
  datas = $_this.data( 'offer' ),
@@ -1057,6 +1055,8 @@ window.imagify = window.imagify || {
1057
  imgs = $offer_line.find( '.imagify-approx-nb' ).text(),
1058
  offer_size = $offer_line.find( '.imagify-offer-size' ).text();
1059
 
 
 
1060
  // Change views to go back pre-checkout.
1061
  imagifyModal.switchToView( imagifyModal.$preView );
1062
 
@@ -1089,7 +1089,6 @@ window.imagify = window.imagify || {
1089
 
1090
  // Update price information in button.
1091
  imagifyModal.populatePayBtn();
1092
- return false;
1093
  } );
1094
 
1095
  /**
@@ -1099,9 +1098,11 @@ window.imagify = window.imagify || {
1099
  * @uses imagifyModal.getPeriod()
1100
  * @uses imagifyModal.iframeSetSrc()
1101
  */
1102
- $( '#imagify-modal-checkout-btn' ).on( 'click.imagify', function() {
1103
  var $monthly_offer, $onetime_offer, checkout_datas;
1104
 
 
 
1105
  // Do nothing if button disabled.
1106
  if ( $( this ).hasClass( 'imagify-button-disabled' ) ) {
1107
  return;
@@ -1127,23 +1128,22 @@ window.imagify = window.imagify || {
1127
  checkout_datas.period = imagifyModal.getPeriod();
1128
 
1129
  imagifyModal.iframeSetSrc( checkout_datas );
1130
- return false;
1131
  } );
1132
 
1133
  /**
1134
  * Go back to previous step ("Choose Another Plan" links).
1135
  */
1136
- $( '.imagify-back-to-plans' ).on( 'click.imagify', function() {
1137
  var $_this = $( this ),
1138
  is_onetime = $_this.closest( '.imagify-cart-item' ).hasClass( 'imagify-cart-item-onetime' );
1139
 
 
 
1140
  if ( is_onetime ) {
1141
  $( '.imagify-offer-onetime' ).find( '.imagify-choose-another-plan' ).trigger( 'click.imagify' );
1142
  } else {
1143
  $( '.imagify-offer-monthly' ).find( '.imagify-choose-another-plan' ).trigger( 'click.imagify' );
1144
  }
1145
-
1146
- return false;
1147
  } );
1148
 
1149
  // Message/communication API.
169
  // Imagify light modal =============================================================================
170
  (function($, d, w, undefined) {
171
 
172
+ var imagifyOpenModal = function( $the_link ) {
173
  var the_target = $the_link.data( 'target' ) || $the_link.attr( 'href' );
174
 
175
  $( the_target ).css( 'display', 'flex' ).hide().fadeIn( 400 ).attr( 'aria-hidden', 'false' ).attr( 'tabindex', '0' ).focus().removeAttr( 'tabindex' ).addClass( 'modal-is-open' );
181
 
182
  $( d )
183
  // On click on modal trigger.
184
+ .on( 'click.imagify', '.imagify-modal-trigger', function( e ) {
185
+ e.preventDefault();
186
+ imagifyOpenModal( $( this ) );
187
  } )
188
  // On click on close button.
189
  .on( 'click.imagify', '.imagify-modal .close-btn', function() {
211
  e.preventDefault();
212
  // Trigger the event.
213
  $( '.imagify-modal.modal-is-open' ).find( '.close-btn' ).trigger( 'click.imagify' );
 
 
214
  }
215
  } );
216
 
1025
  *
1026
  * @uses imagifyModal.switchToView()
1027
  */
1028
+ imagifyModal.$anotherBtn.on( 'click.imagify', function( e ) {
1029
  var type = $( this ).data( 'imagify-choose' ),
1030
  tab = 'imagify-pricing-tab-' + ( 'plan' === type ? 'monthly' : 'onetime' );
1031
 
1032
+ e.preventDefault();
1033
 
1034
+ imagifyModal.switchToView( imagifyModal.$plansView, { tab: tab } );
1035
  } );
1036
 
1037
  /**
1041
  * @uses imagifyModal.switchToView()
1042
  * @uses imagifyModal.populatePayBtn()
1043
  */
1044
+ imagifyModal.$modal.on( 'click.imagify', '.imagify-payment-btn-select-plan', function( e ) {
1045
  var $_this = $( this ),
1046
  $offer_line = $_this.closest( '.imagify-offer-line' ),
1047
  datas = $_this.data( 'offer' ),
1055
  imgs = $offer_line.find( '.imagify-approx-nb' ).text(),
1056
  offer_size = $offer_line.find( '.imagify-offer-size' ).text();
1057
 
1058
+ e.preventDefault();
1059
+
1060
  // Change views to go back pre-checkout.
1061
  imagifyModal.switchToView( imagifyModal.$preView );
1062
 
1089
 
1090
  // Update price information in button.
1091
  imagifyModal.populatePayBtn();
 
1092
  } );
1093
 
1094
  /**
1098
  * @uses imagifyModal.getPeriod()
1099
  * @uses imagifyModal.iframeSetSrc()
1100
  */
1101
+ $( '#imagify-modal-checkout-btn' ).on( 'click.imagify', function( e ) {
1102
  var $monthly_offer, $onetime_offer, checkout_datas;
1103
 
1104
+ e.preventDefault();
1105
+
1106
  // Do nothing if button disabled.
1107
  if ( $( this ).hasClass( 'imagify-button-disabled' ) ) {
1108
  return;
1128
  checkout_datas.period = imagifyModal.getPeriod();
1129
 
1130
  imagifyModal.iframeSetSrc( checkout_datas );
 
1131
  } );
1132
 
1133
  /**
1134
  * Go back to previous step ("Choose Another Plan" links).
1135
  */
1136
+ $( '.imagify-back-to-plans' ).on( 'click.imagify', function( e ) {
1137
  var $_this = $( this ),
1138
  is_onetime = $_this.closest( '.imagify-cart-item' ).hasClass( 'imagify-cart-item-onetime' );
1139
 
1140
+ e.preventDefault();
1141
+
1142
  if ( is_onetime ) {
1143
  $( '.imagify-offer-onetime' ).find( '.imagify-choose-another-plan' ).trigger( 'click.imagify' );
1144
  } else {
1145
  $( '.imagify-offer-monthly' ).find( '.imagify-choose-another-plan' ).trigger( 'click.imagify' );
1146
  }
 
 
1147
  } );
1148
 
1149
  // Message/communication API.
assets/js/admin.min.js CHANGED
@@ -1 +1 @@
1
- window.imagify=window.imagify||{concat:ajaxurl.indexOf("?")>0?"&":"?",log:function(a){void 0!==console&&console.log(a)},info:function(a){void 0!==console&&console.info(a)}},function(a,b,c,d){var e=!1;a("#wp-admin-bar-imagify").hover(function(){var b;!0!==e&&(e=!0,b=a("#wp-admin-bar-imagify-profile-content"),b.is(":empty")&&a.get(ajaxurl+imagify.concat+"action=imagify_get_admin_bar_profile&imagifygetadminbarprofilenonce="+a("#imagifygetadminbarprofilenonce").val()).done(function(c){b.html(c.data),a("#wp-admin-bar-imagify-profile-loading").remove(),e=!1}))})}(jQuery,document,window),function(a,b,c,d){a("#imagify-signup").on("click.imagify",function(b){b.preventDefault(),swal({title:imagifyAdmin.labels.signupTitle,html:imagifyAdmin.labels.signupText,confirmButtonText:imagifyAdmin.labels.signupConfirmButtonText,input:"email",allowOutsideClick:!0,showLoaderOnConfirm:!0,customClass:"imagify-sweet-alert imagify-sweet-alert-signup",inputValidator:function(b){return new Promise(function(c,d){""!==a.trim(b)&&b?c():d(imagifyAdmin.labels.signupErrorEmptyEmail)})},preConfirm:function(b){return new Promise(function(c,d){setTimeout(function(){a.get(ajaxurl+imagify.concat+"action=imagify_signup&email="+b+"&imagifysignupnonce="+a("#imagifysignupnonce").val()).done(function(a){a.success?c():d(a.data)})},2e3)})}}).then(function(){swal({title:imagifyAdmin.labels.signupSuccessTitle,html:imagifyAdmin.labels.signupSuccessText,type:"success",customClass:"imagify-sweet-alert"})})}),a("#imagify-save-api-key").on("click.imagify",function(b){b.preventDefault(),swal({title:imagifyAdmin.labels.saveApiKeyTitle,html:imagifyAdmin.labels.saveApiKeyText,confirmButtonText:imagifyAdmin.labels.saveApiKeyConfirmButtonText,input:"text",allowOutsideClick:!0,showLoaderOnConfirm:!0,customClass:"imagify-sweet-alert imagify-sweet-alert-signup",inputValidator:function(b){return new Promise(function(c,d){""!==a.trim(b)&&b?c():d(imagifyAdmin.labels.ApiKeyErrorEmpty)})},preConfirm:function(b){return new Promise(function(c,d){a.get(ajaxurl+imagify.concat+"action=imagify_check_api_key_validity&api_key="+b+"&imagifycheckapikeynonce="+a("#imagifycheckapikeynonce").val()).done(function(a){a.success?c():d(a.data)})})}}).then(function(){swal({title:imagifyAdmin.labels.ApiKeyCheckSuccessTitle,html:imagifyAdmin.labels.ApiKeyCheckSuccessText,type:"success",customClass:"imagify-sweet-alert"})})}),a(".imagify-notice-dismiss").on("click.imagify",function(b){var c=a(this),d=c.parents(".imagify-welcome, .imagify-notice"),e=c.attr("href");b.preventDefault(),d.fadeTo(100,0,function(){a(this).slideUp(100,function(){a(this).remove()})}),a.get(e.replace("admin-post.php","admin-ajax.php"))})}(jQuery,document,window),function(a,b,c,d){var e=function(b){var c=b.data("target")||b.attr("href");a(c).css("display","flex").hide().fadeIn(400).attr("aria-hidden","false").attr("tabindex","0").focus().removeAttr("tabindex").addClass("modal-is-open"),a("body").addClass("imagify-modal-is-open")};a(".imagify-modal").attr("aria-hidden","true"),a(b).on("click.imagify",".imagify-modal-trigger",function(){return e(a(this)),!1}).on("click.imagify",".imagify-modal .close-btn",function(){a(this).closest(".imagify-modal").fadeOut(400).attr("aria-hidden","true").removeClass("modal-is-open").trigger("modalClosed.imagify"),a("body").removeClass("imagify-modal-is-open")}).on("blur.imagify",".imagify-modal .close-btn",function(){var b=a(this).closest(".imagify-modal");"false"===b.attr("aria-hidden")&&b.attr("tabindex","0").focus().removeAttr("tabindex")}).on("click.imagify",".imagify-modal",function(b){a(b.target).filter(".modal-is-open").find(".close-btn").trigger("click.imagify")}).on("keydown.imagify",function(b){if(27===b.keyCode&&a(".imagify-modal.modal-is-open").length>0)return b.preventDefault(),a(".imagify-modal.modal-is-open").find(".close-btn").trigger("click.imagify"),!1})}(jQuery,document,window),function(a,b,c,d){var e={};a("#imagify-pricing-modal").length&&(e={$modal:a("#imagify-pricing-modal"),$checkboxes:a(".imagify-offer-line .imagify-checkbox"),$radios:a(".imagify-payment-modal .imagify-radio-line input"),$preView:a("#imagify-pre-checkout-view"),$plansView:a("#imagify-plans-selection-view").hide(),$paymentView:a("#imagify-payment-process-view").hide(),$successView:a("#imagify-success-view").hide(),$anotherBtn:a(".imagify-choose-another-plan"),speedFadeIn:300,getHtmlPrice:function(a,b){var c,d,e,f,g;return b||(b=null),"object"!=typeof a?(a+="",a=a.split("."),a[1]=1===a[1].length?a[1]+"0":(""+a[1]).substring(0,2),g='<span class="imagify-price-big">'+a[0]+"</span> ",g+='<span class="imagify-price-mini">.'+a[1]+"</span>"):(c=a.monthly+"",d=a.yearly+"",e=c.split("."),f=d.split("."),g='<span class="imagify-switch-my">',g+='<span aria-hidden="'+("monthly"===b?"false":"true")+'" class="imagify-monthly">',g+='<span class="imagify-price-big">'+e[0]+"</span> ",g+='<span class="imagify-price-mini">.'+(1===e[1].length?e[1]+"0":(""+e[1]).substring(0,2))+"</span>",g+="</span> ",g+='<span aria-hidden="'+("yearly"===b?"false":"true")+'" class="imagify-yearly">',g+='<span class="imagify-price-big">'+f[0]+"</span> ",g+='<span class="imagify-price-mini">.'+(1===f[1].length?f[1]+"0":(""+f[1]).substring(0,2))+"</span>",g+="</span>",g+="</span>")},getHtmlDiscountPrice:function(a,b){var c,d,e="";return b||(b=null),"object"==typeof a?(c=a.monthly+"",d=a.yearly+"",e+='<span class="imagify-price-discount">',e+='<span class="imagify-price-discount-dollar">$</span>',e+='<span class="imagify-switch-my">',e+='<span aria-hidden="'+("monthly"===b?"false":"true")+'" class="imagify-monthly">',e+='<span class="imagify-price-discount-number">'+c+"</span>",e+="</span>",e+='<span aria-hidden="'+("yearly"===b?"false":"true")+'" class="imagify-yearly">',e+='<span class="imagify-price-discount-number">'+d+"</span>",e+="</span>",e+="</span>",e+="</span>"):(a+="",e+='<span class="imagify-price-discount">',e+='<span class="imagify-price-discount-dollar">$</span>',e+='<span class="imagify-price-discount-number">'+a+"</span>",e+="</span>"),e},populateOffer:function(a,b,d,f){var g,h,i,j=c.imagify_discount_datas,k=b.additional_gb,l=b.annual_cost,m=b.id,n=b.label,o=b.monthly_cost,p=b.quota,q=b.cost,r=p>=1e3?p/1e3+" GB":p+" MB",s="monthly"===d?{monthly:o,yearly:Math.round(l/12*100)/100}:q,t=s;return j.is_active&&"percentage"===j.coupon_type&&"monthly"===d&&(g=(100-j.coupon_value)/100,s="monthly"===d?{monthly:o*g,yearly:Math.round(l*g/12*100)/100}:q*g),void 0!==f&&a.addClass("imagify-"+d+"-"+n+f),a.find(".imagify-offer-size").text(r),a.find(".imagify-number-block").html(e.getHtmlPrice(s,"monthly")),j.is_active&&"percentage"===j.coupon_type&&"monthly"===d&&(a.find(".imagify-price-block").prev(".imagify-price-discount").remove(),a.find(".imagify-price-block").before(e.getHtmlDiscountPrice(t,"monthly"))),a.find(".imagify-approx-nb").text(5*p),"monthly"===d&&a.find(".imagify-price-add-data").text("$"+k),h=a.find(".imagify-payment-btn-select-plan").length?a.find(".imagify-payment-btn-select-plan"):a,i="monthly"===d?'{"'+n+'":{"id":'+m+',"name":"'+r+'","data":'+p+',"dataf":"'+r+'","imgs":'+5*p+',"prices":{"monthly":'+s.monthly+',"yearly":'+s.yearly+',"add":'+k+"}}}":'{"ot'+n+'":{"id":'+m+',"name":"'+r+'","data":'+p+',"dataf":"'+r+'","imgs":'+5*p+',"price":'+s+"}}",h.attr("data-offer",i),a},populatePayBtn:function(){var b=JSON.parse(a(".imagify-offer-monthly").attr("data-offer")),c=JSON.parse(a(".imagify-offer-onetime").attr("data-offer")),d=0,e=0,f=0;a(".imagify-offer-monthly").hasClass("imagify-offer-selected")&&(e=a("#imagify-subscription-monthly").filter(":checked").length?b[Object.keys(b)[0]].prices.monthly:12*b[Object.keys(b)[0]].prices.yearly),a(".imagify-offer-onetime").hasClass("imagify-offer-selected")&&(f=c[Object.keys(c)[0]].price),d=parseFloat(f+e).toFixed(2),"0.00"===d||0===d?a("#imagify-modal-checkout-btn").attr("disabled","disabled").addClass("imagify-button-disabled"):a("#imagify-modal-checkout-btn").removeAttr("disabled").removeClass("imagify-button-disabled")},checkCoupon:function(){var b,c,d,e,f=a("#imagify-coupon-code").val();""!==f&&(b=a(".imagify-coupon-text"),c=b.find("label"),d=a(".imagify-coupon-section"),e=a("#imagify-get-pricing-modal").data("nonce"),b.addClass("checking"),a.post(ajaxurl,{action:"imagify_check_coupon",coupon:f,imagifynonce:e},function(a){var e;b.removeClass("checking"),a.success?a.data.success?(e="percentage"===a.data.coupon_type?a.data.value+"%":"$"+a.data.value,d.removeClass("invalid").addClass("validated"),c.html(imagifyAdmin.labels.successCouponAPI),c.find(".imagify-coupon-offer").text(e),c.find(".imagify-coupon-word").text(f)):(d.removeClass("validated").addClass("invalid"),c.text(a.data.detail)):(d.removeClass("validated").addClass("invalid"),c.text(imagifyAdmin.labels.errorCouponAPI))}))},getPricing:function(b){var d=b.data("nonce"),f={action:"imagify_get_prices",imagifynonce:d},g={action:"imagify_get_images_counts",imagifynonce:d},h={action:"imagify_get_discount",imagifynonce:d};e.$modal.find(".imagify-modal-loader").hide().show(),a.post(ajaxurl,f,function(b){if(!b.success)return void e.populatePayBtn();a.post(ajaxurl,g,function(d){d.success&&a.post(ajaxurl,h,function(f){var g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C="",D="",E=!1,F=!1;if(f.success){if(g=d.data,h=b.data,i=f.data,j=h.monthlies,k=h.onetimes,l=Math.round(g.average_month_size.raw/1e6),m=Math.round(g.total_library_size.raw/1e6),n=a("#imagify-offer-monthly-template"),o=a("#imagify-offer-onetime-template"),p=o.html(),q=n.html(),r=a(".imagify-estimation-block"),r.removeClass("imagify-analyzing"),r.find(".average-month-size").text(g.average_month_size.human),r.find(".total-library-size").text(g.total_library_size.human),l<25&&m<25?(a(".imagify-pre-checkout-offers .imagify-modal-title").addClass("imagify-enough-free"),a(".imagify-offer-selected").removeClass("imagify-offer-selected").find(".imagify-checkbox").removeAttr("checked")):(a(".imagify-enough-free").removeClass("imagify-enough-free"),a(".imagify-offer-selected").addClass("imagify-offer-selected").find(".imagify-checkbox").attr("checked","checked")),null===j||null===k)return s=a(".imagify-pre-checkout-offers"),s.hide().attr("aria-hidden",!0),s.closest(".imagify-modal-views").find(".imagify-popin-message").remove(),s.after('<div class="imagify-popin-message imagify-error"><p>'+imagifyAdmin.labels.errorPriceAPI+"</p></div>"),void e.$modal.find(".imagify-modal-loader").fadeOut(300);if(c.imagify_discount_datas=i,i.is_active&&(t=a(".imagify-modal-promotion"),u=i.date_end.split("T")[0],v=i.coupon_value,w="percentage"===i.coupon_type?v+"%":"$"+v,a("#imagify-coupon-code").val(i.label).attr("readonly",!0),t.addClass("active").attr("aria-hidden","false"),t.find(".imagify-promotion-number").text(w),t.find(".imagify-promotion-date").text(u),e.checkCoupon()),a.each(j,function(b,c){var d,f,g="";return"free"===c.label||(d=a(q).clone(),!1!==F&&b-F>2||(l<c.quota&&!1===F&&(g=" imagify-offer-selected",F=b,f=a(".imagify-pre-checkout-offers").find(".imagify-offer-monthly"),e.populateOffer(f,c,"monthly")),d=e.populateOffer(d,c,"monthly",g),void(D+=d[0].outerHTML)))}),x=a(D).filter(".imagify-offer-selected").prevAll(),x.length>1){for(y=x.length-1,z=a(D),A=0;A<y;A++)delete z[A];for(D="",B=0;B<z.length;B++)D+=a("<div/>").append(z[B]).html()}a.each(k,function(b,c){var d,f=a(p).clone(),g=a(".imagify-pre-checkout-offers").find(".imagify-offer-onetime"),h="";m<c.quota&&!1===E&&(h=" imagify-offer-selected",E=!0,e.populateOffer(g,c,"onetime")),k.length-1===b&&!1===E&&(d=k[k.length-1],e.populateOffer(g,d,"onetime")),f=e.populateOffer(f,c,"onetime",h),C+=f[0].outerHTML}),n.parent().find(".imagify-offer-line")&&n.parent().find(".imagify-offer-line").remove(),n.before(D),o.parent().find(".imagify-offer-line")&&o.parent().find(".imagify-offer-line").remove(),o.before(C),e.$modal.find(".imagify-modal-loader").fadeOut(300)}})}),e.populatePayBtn()})},checkCheckbox:function(b){b.each(function(){var b=a(this);b.is(":checked")?b.closest(".imagify-offer-line").addClass("imagify-offer-selected"):b.closest(".imagify-offer-line").removeClass("imagify-offer-selected")}),e.populatePayBtn()},checkRadio:function(b){return b.each(function(){var b,c,d=a(this);b=d.parent(".imagify-cart-list-switcher").length?d.closest(".imagify-cart"):d.parent(".imagify-small-options").length?d.parent(".imagify-small-options").next(".imagify-pricing-table"):d.closest(".imagify-offer-line"),c=b.find(".imagify-switch-my"),"yearly"===d.val()?(b.addClass("imagify-year-selected").removeClass("imagify-month-selected"),c.find(".imagify-monthly").attr("aria-hidden","true"),c.find(".imagify-yearly").attr("aria-hidden","false")):(b.addClass("imagify-month-selected").removeClass("imagify-year-selected"),c.find(".imagify-monthly").attr("aria-hidden","false"),c.find(".imagify-yearly").attr("aria-hidden","true"))}),e.populatePayBtn(),b},populateBtnPrice:setInterval(function(){e.populatePayBtn()},1e3),getPeriod:function(){return a(".imagify-offer-monthly").hasClass("imagify-month-selected")?"monthly":"yearly"},getApiKey:function(){return a("#imagify-payment-iframe").data("imagify-api")},switchToView:function(a,b){var c=a.attr("id"),d=e.$modal.children(".imagify-modal-content");a.siblings(".imagify-modal-views").hide().attr("aria-hidden","true"),b&&b.tab&&a.find('a[href="#'+b.tab+'"]').trigger("click.imagify"),"imagify-payment-process-view"===c?d.addClass("imagify-iframe-viewing"):d.removeClass("imagify-iframe-viewing"),"imagify-success-view"===c?(d.addClass("imagify-success-viewing"),e.$modal.attr("aria-labelledby","imagify-success-view")):(d.removeClass("imagify-success-viewing"),e.$modal.removeAttr("aria-labelledby")),a.fadeIn(e.speedFadeIn).attr("aria-hidden","false")},iframeSetSrc:function(b){var c,d,f,g,h,i,j,k=a("#imagify-payment-iframe"),l=k.attr("src"),m=k.data("src"),n=0,o=0;if("string"==typeof b&&""!==l)return j="monthly"===b?"yearly":"monthly",l=l.replace(j,b),void k.attr("src",l);if("object"==typeof b){if(b.monthly&&(n=b.monthly[Object.keys(b.monthly)[0]].id),b.onetime&&(o=b.onetime[Object.keys(b.onetime)[0]].id,o=o+""=="999"?b.onetime[Object.keys(b.onetime)[0]].data:o),!b.period)return void imagify.info("No period defined");e.getApiKey(),c=o,d="yearly"===b.period?n:0,f="monthly"===b.period?n:0,g=a("#imagify-coupon-code").val(),h=""===g?"none":g,parseFloat(a(".imagify-global-amount").text()).toFixed(2),m=m+c+"/"+f+"/"+d+"/"+h+"/",i=k.remove().attr("src",m),e.$paymentView.html(i)}},paymentClose:function(){a(".imagify-iframe-viewing .close-btn").trigger("click.imagify"),a(".imagify-iframe-viewing").removeClass("imagify-iframe-viewing")},paymentBack:function(){e.switchToView(e.$preView)},paymentSuccess:function(){e.switchToView(e.$successView)},checkPluginMessage:function(a){var b=a.origin||a.originalEvent.origin;if("https://app.imagify.io"===b||"http://dapp.imagify.io"===b)switch(a.data){case"cancel":e.paymentClose();break;case"back":e.paymentBack();break;case"success":e.paymentSuccess()}}},e.checkCheckbox(e.$checkboxes),e.checkRadio(e.$radios.filter(":checked")),e.checkCoupon(),e.$checkboxes.on("change.imagify",function(){e.checkCheckbox(a(this))}),e.$radios.on("change.imagify",function(){e.checkRadio(a(this))}),a("#imagify-get-pricing-modal").on("click.imagify-ajax",function(){e.getPricing(a(this))}),a(b).on("modalClosed.imagify",".imagify-payment-modal",function(){a(this).find(".imagify-modal-content").removeClass("imagify-success-viewing imagify-iframe-viewing"),setTimeout(function(){a(".imagify-modal-views").hide(),a("#imagify-pre-checkout-view").show()},300)}),a("#imagify-coupon-code").on("blur.imagify",function(){a(this).attr("readonly")||e.checkCoupon()}).on("keydown.imagify",function(b){var c=a(this);if(!c.attr("readonly"))return 13===b.keyCode||32===b.keyCode?(e.checkCoupon(),!1):void(c.val().length>=3?c.closest(".imagify-coupon-input").addClass("imagify-canbe-validate"):c.closest(".imagify-coupon-input").removeClass("imagify-canbe-validate"))}),a("#imagify-coupon-validate").on("click.imagify",function(){e.checkCoupon(),a(this).closest(".imagify-canbe-validate").removeClass("imagify-canbe-validate")}),e.$anotherBtn.on("click.imagify",function(){var b=a(this).data("imagify-choose"),c="imagify-pricing-tab-"+("plan"===b?"monthly":"onetime");return e.switchToView(e.$plansView,{tab:c}),!1}),e.$modal.on("click.imagify",".imagify-payment-btn-select-plan",function(){var b=a(this),c=b.closest(".imagify-offer-line"),d=b.data("offer"),f=b.attr("data-offer"),g="imagify-pricing-tab-monthly"!==b.closest(".imagify-tab-content").attr("id"),h=g?e.$preView.find(".imagify-offer-onetime"):e.$preView.find(".imagify-offer-monthly"),i=g?null:b.closest(".imagify-pricing-table").hasClass("imagify-month-selected")?"monthly":"yearly",j=g?e.getHtmlPrice(d[Object.keys(d)[0]].price):e.getHtmlPrice(d[Object.keys(d)[0]].prices,i),k=g?"":'<span class="imagify-price-by">'+c.find(".imagify-price-by").text()+"</span>",l=c.find(".imagify-price-discount").html(),m=c.find(".imagify-approx-nb").text(),n=c.find(".imagify-offer-size").text();return e.switchToView(e.$preView),h.find(".imagify-number-block").html(j+k),h.find(".imagify-price-discount").html(l),h.find(".imagify-approx-nb").text(m),h.find(".imagify-offer-size").text(n),h.attr("data-offer",f),g||(h.find(".imagify-price-add-data").text(c.find(".imagify-price-add-data").text()),"monthly"===i?h.find("#imagify-subscription-monthly").trigger("click.imagify"):h.find("#imagify-subscription-yearly").trigger("click.imagify"),h.find(".imagify-inline-options").find("input:radio:checked").trigger("change.imagify")),e.populatePayBtn(),!1}),a("#imagify-modal-checkout-btn").on("click.imagify",function(){var b,c,d;if(!a(this).hasClass("imagify-button-disabled"))return b=a(".imagify-offer-monthly"),c=a(".imagify-offer-onetime"),d={},b.hasClass("imagify-offer-selected")&&(d.monthly=JSON.parse(b.attr("data-offer"))),c.hasClass("imagify-offer-selected")&&(d.onetime=JSON.parse(c.attr("data-offer"))),e.switchToView(e.$paymentView),d.period=e.getPeriod(),e.iframeSetSrc(d),!1}),a(".imagify-back-to-plans").on("click.imagify",function(){return a(this).closest(".imagify-cart-item").hasClass("imagify-cart-item-onetime")?a(".imagify-offer-onetime").find(".imagify-choose-another-plan").trigger("click.imagify"):a(".imagify-offer-monthly").find(".imagify-choose-another-plan").trigger("click.imagify"),!1}),c.addEventListener("message",e.checkPluginMessage,!0))}(jQuery,document,window),function(a,b,c,d){a(".imagify-tab").on("click.imagify",function(b){var c,d=a(this);b.preventDefault(),d.hasClass("imagify-current")||(c=d.find("a").attr("href")||"#"+d.find("a").attr("aria-controls"),d.closest(".imagify-tabs").next(".imagify-tabs-contents").find(".imagify-tab-content").hide().attr("aria-hidden","true"),a(c).fadeIn(275).attr("aria-hidden","false"),d.closest(".imagify-tabs").find(".imagify-tab").removeClass("imagify-current").attr("aria-selected","false"),d.addClass("imagify-current").attr("aria-selected","true"))})}(jQuery,document,window);
1
+ window.imagify=window.imagify||{concat:ajaxurl.indexOf("?")>0?"&":"?",log:function(a){void 0!==console&&console.log(a)},info:function(a){void 0!==console&&console.info(a)}},function(a,b,c,d){var e=!1;a("#wp-admin-bar-imagify").hover(function(){var b;!0!==e&&(e=!0,b=a("#wp-admin-bar-imagify-profile-content"),b.is(":empty")&&a.get(ajaxurl+imagify.concat+"action=imagify_get_admin_bar_profile&imagifygetadminbarprofilenonce="+a("#imagifygetadminbarprofilenonce").val()).done(function(c){b.html(c.data),a("#wp-admin-bar-imagify-profile-loading").remove(),e=!1}))})}(jQuery,document,window),function(a,b,c,d){a("#imagify-signup").on("click.imagify",function(b){b.preventDefault(),swal({title:imagifyAdmin.labels.signupTitle,html:imagifyAdmin.labels.signupText,confirmButtonText:imagifyAdmin.labels.signupConfirmButtonText,input:"email",allowOutsideClick:!0,showLoaderOnConfirm:!0,customClass:"imagify-sweet-alert imagify-sweet-alert-signup",inputValidator:function(b){return new Promise(function(c,d){""!==a.trim(b)&&b?c():d(imagifyAdmin.labels.signupErrorEmptyEmail)})},preConfirm:function(b){return new Promise(function(c,d){setTimeout(function(){a.get(ajaxurl+imagify.concat+"action=imagify_signup&email="+b+"&imagifysignupnonce="+a("#imagifysignupnonce").val()).done(function(a){a.success?c():d(a.data)})},2e3)})}}).then(function(){swal({title:imagifyAdmin.labels.signupSuccessTitle,html:imagifyAdmin.labels.signupSuccessText,type:"success",customClass:"imagify-sweet-alert"})})}),a("#imagify-save-api-key").on("click.imagify",function(b){b.preventDefault(),swal({title:imagifyAdmin.labels.saveApiKeyTitle,html:imagifyAdmin.labels.saveApiKeyText,confirmButtonText:imagifyAdmin.labels.saveApiKeyConfirmButtonText,input:"text",allowOutsideClick:!0,showLoaderOnConfirm:!0,customClass:"imagify-sweet-alert imagify-sweet-alert-signup",inputValidator:function(b){return new Promise(function(c,d){""!==a.trim(b)&&b?c():d(imagifyAdmin.labels.ApiKeyErrorEmpty)})},preConfirm:function(b){return new Promise(function(c,d){a.get(ajaxurl+imagify.concat+"action=imagify_check_api_key_validity&api_key="+b+"&imagifycheckapikeynonce="+a("#imagifycheckapikeynonce").val()).done(function(a){a.success?c():d(a.data)})})}}).then(function(){swal({title:imagifyAdmin.labels.ApiKeyCheckSuccessTitle,html:imagifyAdmin.labels.ApiKeyCheckSuccessText,type:"success",customClass:"imagify-sweet-alert"})})}),a(".imagify-notice-dismiss").on("click.imagify",function(b){var c=a(this),d=c.parents(".imagify-welcome, .imagify-notice"),e=c.attr("href");b.preventDefault(),d.fadeTo(100,0,function(){a(this).slideUp(100,function(){a(this).remove()})}),a.get(e.replace("admin-post.php","admin-ajax.php"))})}(jQuery,document,window),function(a,b,c,d){var e=function(b){var c=b.data("target")||b.attr("href");a(c).css("display","flex").hide().fadeIn(400).attr("aria-hidden","false").attr("tabindex","0").focus().removeAttr("tabindex").addClass("modal-is-open"),a("body").addClass("imagify-modal-is-open")};a(".imagify-modal").attr("aria-hidden","true"),a(b).on("click.imagify",".imagify-modal-trigger",function(b){b.preventDefault(),e(a(this))}).on("click.imagify",".imagify-modal .close-btn",function(){a(this).closest(".imagify-modal").fadeOut(400).attr("aria-hidden","true").removeClass("modal-is-open").trigger("modalClosed.imagify"),a("body").removeClass("imagify-modal-is-open")}).on("blur.imagify",".imagify-modal .close-btn",function(){var b=a(this).closest(".imagify-modal");"false"===b.attr("aria-hidden")&&b.attr("tabindex","0").focus().removeAttr("tabindex")}).on("click.imagify",".imagify-modal",function(b){a(b.target).filter(".modal-is-open").find(".close-btn").trigger("click.imagify")}).on("keydown.imagify",function(b){27===b.keyCode&&a(".imagify-modal.modal-is-open").length>0&&(b.preventDefault(),a(".imagify-modal.modal-is-open").find(".close-btn").trigger("click.imagify"))})}(jQuery,document,window),function(a,b,c,d){var e={};a("#imagify-pricing-modal").length&&(e={$modal:a("#imagify-pricing-modal"),$checkboxes:a(".imagify-offer-line .imagify-checkbox"),$radios:a(".imagify-payment-modal .imagify-radio-line input"),$preView:a("#imagify-pre-checkout-view"),$plansView:a("#imagify-plans-selection-view").hide(),$paymentView:a("#imagify-payment-process-view").hide(),$successView:a("#imagify-success-view").hide(),$anotherBtn:a(".imagify-choose-another-plan"),speedFadeIn:300,getHtmlPrice:function(a,b){var c,d,e,f,g;return b||(b=null),"object"!=typeof a?(a+="",a=a.split("."),a[1]=1===a[1].length?a[1]+"0":(""+a[1]).substring(0,2),g='<span class="imagify-price-big">'+a[0]+"</span> ",g+='<span class="imagify-price-mini">.'+a[1]+"</span>"):(c=a.monthly+"",d=a.yearly+"",e=c.split("."),f=d.split("."),g='<span class="imagify-switch-my">',g+='<span aria-hidden="'+("monthly"===b?"false":"true")+'" class="imagify-monthly">',g+='<span class="imagify-price-big">'+e[0]+"</span> ",g+='<span class="imagify-price-mini">.'+(1===e[1].length?e[1]+"0":(""+e[1]).substring(0,2))+"</span>",g+="</span> ",g+='<span aria-hidden="'+("yearly"===b?"false":"true")+'" class="imagify-yearly">',g+='<span class="imagify-price-big">'+f[0]+"</span> ",g+='<span class="imagify-price-mini">.'+(1===f[1].length?f[1]+"0":(""+f[1]).substring(0,2))+"</span>",g+="</span>",g+="</span>")},getHtmlDiscountPrice:function(a,b){var c,d,e="";return b||(b=null),"object"==typeof a?(c=a.monthly+"",d=a.yearly+"",e+='<span class="imagify-price-discount">',e+='<span class="imagify-price-discount-dollar">$</span>',e+='<span class="imagify-switch-my">',e+='<span aria-hidden="'+("monthly"===b?"false":"true")+'" class="imagify-monthly">',e+='<span class="imagify-price-discount-number">'+c+"</span>",e+="</span>",e+='<span aria-hidden="'+("yearly"===b?"false":"true")+'" class="imagify-yearly">',e+='<span class="imagify-price-discount-number">'+d+"</span>",e+="</span>",e+="</span>",e+="</span>"):(a+="",e+='<span class="imagify-price-discount">',e+='<span class="imagify-price-discount-dollar">$</span>',e+='<span class="imagify-price-discount-number">'+a+"</span>",e+="</span>"),e},populateOffer:function(a,b,d,f){var g,h,i,j=c.imagify_discount_datas,k=b.additional_gb,l=b.annual_cost,m=b.id,n=b.label,o=b.monthly_cost,p=b.quota,q=b.cost,r=p>=1e3?p/1e3+" GB":p+" MB",s="monthly"===d?{monthly:o,yearly:Math.round(l/12*100)/100}:q,t=s;return j.is_active&&"percentage"===j.coupon_type&&"monthly"===d&&(g=(100-j.coupon_value)/100,s="monthly"===d?{monthly:o*g,yearly:Math.round(l*g/12*100)/100}:q*g),void 0!==f&&a.addClass("imagify-"+d+"-"+n+f),a.find(".imagify-offer-size").text(r),a.find(".imagify-number-block").html(e.getHtmlPrice(s,"monthly")),j.is_active&&"percentage"===j.coupon_type&&"monthly"===d&&(a.find(".imagify-price-block").prev(".imagify-price-discount").remove(),a.find(".imagify-price-block").before(e.getHtmlDiscountPrice(t,"monthly"))),a.find(".imagify-approx-nb").text(5*p),"monthly"===d&&a.find(".imagify-price-add-data").text("$"+k),h=a.find(".imagify-payment-btn-select-plan").length?a.find(".imagify-payment-btn-select-plan"):a,i="monthly"===d?'{"'+n+'":{"id":'+m+',"name":"'+r+'","data":'+p+',"dataf":"'+r+'","imgs":'+5*p+',"prices":{"monthly":'+s.monthly+',"yearly":'+s.yearly+',"add":'+k+"}}}":'{"ot'+n+'":{"id":'+m+',"name":"'+r+'","data":'+p+',"dataf":"'+r+'","imgs":'+5*p+',"price":'+s+"}}",h.attr("data-offer",i),a},populatePayBtn:function(){var b=JSON.parse(a(".imagify-offer-monthly").attr("data-offer")),c=JSON.parse(a(".imagify-offer-onetime").attr("data-offer")),d=0,e=0,f=0;a(".imagify-offer-monthly").hasClass("imagify-offer-selected")&&(e=a("#imagify-subscription-monthly").filter(":checked").length?b[Object.keys(b)[0]].prices.monthly:12*b[Object.keys(b)[0]].prices.yearly),a(".imagify-offer-onetime").hasClass("imagify-offer-selected")&&(f=c[Object.keys(c)[0]].price),d=parseFloat(f+e).toFixed(2),"0.00"===d||0===d?a("#imagify-modal-checkout-btn").attr("disabled","disabled").addClass("imagify-button-disabled"):a("#imagify-modal-checkout-btn").removeAttr("disabled").removeClass("imagify-button-disabled")},checkCoupon:function(){var b,c,d,e,f=a("#imagify-coupon-code").val();""!==f&&(b=a(".imagify-coupon-text"),c=b.find("label"),d=a(".imagify-coupon-section"),e=a("#imagify-get-pricing-modal").data("nonce"),b.addClass("checking"),a.post(ajaxurl,{action:"imagify_check_coupon",coupon:f,imagifynonce:e},function(a){var e;b.removeClass("checking"),a.success?a.data.success?(e="percentage"===a.data.coupon_type?a.data.value+"%":"$"+a.data.value,d.removeClass("invalid").addClass("validated"),c.html(imagifyAdmin.labels.successCouponAPI),c.find(".imagify-coupon-offer").text(e),c.find(".imagify-coupon-word").text(f)):(d.removeClass("validated").addClass("invalid"),c.text(a.data.detail)):(d.removeClass("validated").addClass("invalid"),c.text(imagifyAdmin.labels.errorCouponAPI))}))},getPricing:function(b){var d=b.data("nonce"),f={action:"imagify_get_prices",imagifynonce:d},g={action:"imagify_get_images_counts",imagifynonce:d},h={action:"imagify_get_discount",imagifynonce:d};e.$modal.find(".imagify-modal-loader").hide().show(),a.post(ajaxurl,f,function(b){if(!b.success)return void e.populatePayBtn();a.post(ajaxurl,g,function(d){d.success&&a.post(ajaxurl,h,function(f){var g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C="",D="",E=!1,F=!1;if(f.success){if(g=d.data,h=b.data,i=f.data,j=h.monthlies,k=h.onetimes,l=Math.round(g.average_month_size.raw/1e6),m=Math.round(g.total_library_size.raw/1e6),n=a("#imagify-offer-monthly-template"),o=a("#imagify-offer-onetime-template"),p=o.html(),q=n.html(),r=a(".imagify-estimation-block"),r.removeClass("imagify-analyzing"),r.find(".average-month-size").text(g.average_month_size.human),r.find(".total-library-size").text(g.total_library_size.human),l<25&&m<25?(a(".imagify-pre-checkout-offers .imagify-modal-title").addClass("imagify-enough-free"),a(".imagify-offer-selected").removeClass("imagify-offer-selected").find(".imagify-checkbox").removeAttr("checked")):(a(".imagify-enough-free").removeClass("imagify-enough-free"),a(".imagify-offer-selected").addClass("imagify-offer-selected").find(".imagify-checkbox").attr("checked","checked")),null===j||null===k)return s=a(".imagify-pre-checkout-offers"),s.hide().attr("aria-hidden",!0),s.closest(".imagify-modal-views").find(".imagify-popin-message").remove(),s.after('<div class="imagify-popin-message imagify-error"><p>'+imagifyAdmin.labels.errorPriceAPI+"</p></div>"),void e.$modal.find(".imagify-modal-loader").fadeOut(300);if(c.imagify_discount_datas=i,i.is_active&&(t=a(".imagify-modal-promotion"),u=i.date_end.split("T")[0],v=i.coupon_value,w="percentage"===i.coupon_type?v+"%":"$"+v,a("#imagify-coupon-code").val(i.label).attr("readonly",!0),t.addClass("active").attr("aria-hidden","false"),t.find(".imagify-promotion-number").text(w),t.find(".imagify-promotion-date").text(u),e.checkCoupon()),a.each(j,function(b,c){var d,f,g="";return"free"===c.label||(d=a(q).clone(),!1!==F&&b-F>2||(l<c.quota&&!1===F&&(g=" imagify-offer-selected",F=b,f=a(".imagify-pre-checkout-offers").find(".imagify-offer-monthly"),e.populateOffer(f,c,"monthly")),d=e.populateOffer(d,c,"monthly",g),void(D+=d[0].outerHTML)))}),x=a(D).filter(".imagify-offer-selected").prevAll(),x.length>1){for(y=x.length-1,z=a(D),A=0;A<y;A++)delete z[A];for(D="",B=0;B<z.length;B++)D+=a("<div/>").append(z[B]).html()}a.each(k,function(b,c){var d,f=a(p).clone(),g=a(".imagify-pre-checkout-offers").find(".imagify-offer-onetime"),h="";m<c.quota&&!1===E&&(h=" imagify-offer-selected",E=!0,e.populateOffer(g,c,"onetime")),k.length-1===b&&!1===E&&(d=k[k.length-1],e.populateOffer(g,d,"onetime")),f=e.populateOffer(f,c,"onetime",h),C+=f[0].outerHTML}),n.parent().find(".imagify-offer-line")&&n.parent().find(".imagify-offer-line").remove(),n.before(D),o.parent().find(".imagify-offer-line")&&o.parent().find(".imagify-offer-line").remove(),o.before(C),e.$modal.find(".imagify-modal-loader").fadeOut(300)}})}),e.populatePayBtn()})},checkCheckbox:function(b){b.each(function(){var b=a(this);b.is(":checked")?b.closest(".imagify-offer-line").addClass("imagify-offer-selected"):b.closest(".imagify-offer-line").removeClass("imagify-offer-selected")}),e.populatePayBtn()},checkRadio:function(b){return b.each(function(){var b,c,d=a(this);b=d.parent(".imagify-cart-list-switcher").length?d.closest(".imagify-cart"):d.parent(".imagify-small-options").length?d.parent(".imagify-small-options").next(".imagify-pricing-table"):d.closest(".imagify-offer-line"),c=b.find(".imagify-switch-my"),"yearly"===d.val()?(b.addClass("imagify-year-selected").removeClass("imagify-month-selected"),c.find(".imagify-monthly").attr("aria-hidden","true"),c.find(".imagify-yearly").attr("aria-hidden","false")):(b.addClass("imagify-month-selected").removeClass("imagify-year-selected"),c.find(".imagify-monthly").attr("aria-hidden","false"),c.find(".imagify-yearly").attr("aria-hidden","true"))}),e.populatePayBtn(),b},populateBtnPrice:setInterval(function(){e.populatePayBtn()},1e3),getPeriod:function(){return a(".imagify-offer-monthly").hasClass("imagify-month-selected")?"monthly":"yearly"},getApiKey:function(){return a("#imagify-payment-iframe").data("imagify-api")},switchToView:function(a,b){var c=a.attr("id"),d=e.$modal.children(".imagify-modal-content");a.siblings(".imagify-modal-views").hide().attr("aria-hidden","true"),b&&b.tab&&a.find('a[href="#'+b.tab+'"]').trigger("click.imagify"),"imagify-payment-process-view"===c?d.addClass("imagify-iframe-viewing"):d.removeClass("imagify-iframe-viewing"),"imagify-success-view"===c?(d.addClass("imagify-success-viewing"),e.$modal.attr("aria-labelledby","imagify-success-view")):(d.removeClass("imagify-success-viewing"),e.$modal.removeAttr("aria-labelledby")),a.fadeIn(e.speedFadeIn).attr("aria-hidden","false")},iframeSetSrc:function(b){var c,d,f,g,h,i,j,k=a("#imagify-payment-iframe"),l=k.attr("src"),m=k.data("src"),n=0,o=0;if("string"==typeof b&&""!==l)return j="monthly"===b?"yearly":"monthly",l=l.replace(j,b),void k.attr("src",l);if("object"==typeof b){if(b.monthly&&(n=b.monthly[Object.keys(b.monthly)[0]].id),b.onetime&&(o=b.onetime[Object.keys(b.onetime)[0]].id,o=o+""=="999"?b.onetime[Object.keys(b.onetime)[0]].data:o),!b.period)return void imagify.info("No period defined");e.getApiKey(),c=o,d="yearly"===b.period?n:0,f="monthly"===b.period?n:0,g=a("#imagify-coupon-code").val(),h=""===g?"none":g,parseFloat(a(".imagify-global-amount").text()).toFixed(2),m=m+c+"/"+f+"/"+d+"/"+h+"/",i=k.remove().attr("src",m),e.$paymentView.html(i)}},paymentClose:function(){a(".imagify-iframe-viewing .close-btn").trigger("click.imagify"),a(".imagify-iframe-viewing").removeClass("imagify-iframe-viewing")},paymentBack:function(){e.switchToView(e.$preView)},paymentSuccess:function(){e.switchToView(e.$successView)},checkPluginMessage:function(a){var b=a.origin||a.originalEvent.origin;if("https://app.imagify.io"===b||"http://dapp.imagify.io"===b)switch(a.data){case"cancel":e.paymentClose();break;case"back":e.paymentBack();break;case"success":e.paymentSuccess()}}},e.checkCheckbox(e.$checkboxes),e.checkRadio(e.$radios.filter(":checked")),e.checkCoupon(),e.$checkboxes.on("change.imagify",function(){e.checkCheckbox(a(this))}),e.$radios.on("change.imagify",function(){e.checkRadio(a(this))}),a("#imagify-get-pricing-modal").on("click.imagify-ajax",function(){e.getPricing(a(this))}),a(b).on("modalClosed.imagify",".imagify-payment-modal",function(){a(this).find(".imagify-modal-content").removeClass("imagify-success-viewing imagify-iframe-viewing"),setTimeout(function(){a(".imagify-modal-views").hide(),a("#imagify-pre-checkout-view").show()},300)}),a("#imagify-coupon-code").on("blur.imagify",function(){a(this).attr("readonly")||e.checkCoupon()}).on("keydown.imagify",function(b){var c=a(this);if(!c.attr("readonly"))return 13===b.keyCode||32===b.keyCode?(e.checkCoupon(),!1):void(c.val().length>=3?c.closest(".imagify-coupon-input").addClass("imagify-canbe-validate"):c.closest(".imagify-coupon-input").removeClass("imagify-canbe-validate"))}),a("#imagify-coupon-validate").on("click.imagify",function(){e.checkCoupon(),a(this).closest(".imagify-canbe-validate").removeClass("imagify-canbe-validate")}),e.$anotherBtn.on("click.imagify",function(b){var c=a(this).data("imagify-choose"),d="imagify-pricing-tab-"+("plan"===c?"monthly":"onetime");b.preventDefault(),e.switchToView(e.$plansView,{tab:d})}),e.$modal.on("click.imagify",".imagify-payment-btn-select-plan",function(b){var c=a(this),d=c.closest(".imagify-offer-line"),f=c.data("offer"),g=c.attr("data-offer"),h="imagify-pricing-tab-monthly"!==c.closest(".imagify-tab-content").attr("id"),i=h?e.$preView.find(".imagify-offer-onetime"):e.$preView.find(".imagify-offer-monthly"),j=h?null:c.closest(".imagify-pricing-table").hasClass("imagify-month-selected")?"monthly":"yearly",k=h?e.getHtmlPrice(f[Object.keys(f)[0]].price):e.getHtmlPrice(f[Object.keys(f)[0]].prices,j),l=h?"":'<span class="imagify-price-by">'+d.find(".imagify-price-by").text()+"</span>",m=d.find(".imagify-price-discount").html(),n=d.find(".imagify-approx-nb").text(),o=d.find(".imagify-offer-size").text();b.preventDefault(),e.switchToView(e.$preView),i.find(".imagify-number-block").html(k+l),i.find(".imagify-price-discount").html(m),i.find(".imagify-approx-nb").text(n),i.find(".imagify-offer-size").text(o),i.attr("data-offer",g),h||(i.find(".imagify-price-add-data").text(d.find(".imagify-price-add-data").text()),"monthly"===j?i.find("#imagify-subscription-monthly").trigger("click.imagify"):i.find("#imagify-subscription-yearly").trigger("click.imagify"),i.find(".imagify-inline-options").find("input:radio:checked").trigger("change.imagify")),e.populatePayBtn()}),a("#imagify-modal-checkout-btn").on("click.imagify",function(b){var c,d,f;b.preventDefault(),a(this).hasClass("imagify-button-disabled")||(c=a(".imagify-offer-monthly"),d=a(".imagify-offer-onetime"),f={},c.hasClass("imagify-offer-selected")&&(f.monthly=JSON.parse(c.attr("data-offer"))),d.hasClass("imagify-offer-selected")&&(f.onetime=JSON.parse(d.attr("data-offer"))),e.switchToView(e.$paymentView),f.period=e.getPeriod(),e.iframeSetSrc(f))}),a(".imagify-back-to-plans").on("click.imagify",function(b){var c=a(this),d=c.closest(".imagify-cart-item").hasClass("imagify-cart-item-onetime");b.preventDefault(),d?a(".imagify-offer-onetime").find(".imagify-choose-another-plan").trigger("click.imagify"):a(".imagify-offer-monthly").find(".imagify-choose-another-plan").trigger("click.imagify")}),c.addEventListener("message",e.checkPluginMessage,!0))}(jQuery,document,window),function(a,b,c,d){a(".imagify-tab").on("click.imagify",function(b){var c,d=a(this);b.preventDefault(),d.hasClass("imagify-current")||(c=d.find("a").attr("href")||"#"+d.find("a").attr("aria-controls"),d.closest(".imagify-tabs").next(".imagify-tabs-contents").find(".imagify-tab-content").hide().attr("aria-hidden","true"),a(c).fadeIn(275).attr("aria-hidden","false"),d.closest(".imagify-tabs").find(".imagify-tab").removeClass("imagify-current").attr("aria-selected","false"),d.addClass("imagify-current").attr("aria-selected","true"))})}(jQuery,document,window);
assets/js/bulk.js CHANGED
@@ -1,4 +1,4 @@
1
- /* globals ajaxurl: false, console: false, imagify: true, ImagifyGulp: false, swal: false */
2
 
3
  window.imagify = window.imagify || {
4
  concat: ajaxurl.indexOf( '?' ) > 0 ? '&' : '?',
@@ -174,17 +174,19 @@ window.imagify = window.imagify || {
174
  $( '#imagify-bulk-action' ).trigger( 'click' );
175
  } );
176
 
177
- $( '#imagify-bulk-action' ).on( 'click', function() {
178
  var $obj = $( this ),
179
  optimizationLevel = $( '[name="optimization_level"]:checked' ).val(),
180
  confirmMessage;
181
 
 
 
182
  if ( optimizationLevel === undefined ) {
183
  optimizationLevel = -1;
184
  }
185
 
186
  if ( $obj.attr( 'disabled' ) ) {
187
- return false;
188
  }
189
 
190
  $obj.attr( 'disabled', 'disabled' );
1
+ /* globals ajaxurl: false, console: false, imagify: true, Chart: false, ImagifyGulp: false, swal: false */
2
 
3
  window.imagify = window.imagify || {
4
  concat: ajaxurl.indexOf( '?' ) > 0 ? '&' : '?',
174
  $( '#imagify-bulk-action' ).trigger( 'click' );
175
  } );
176
 
177
+ $( '#imagify-bulk-action' ).on( 'click', function( e ) {
178
  var $obj = $( this ),
179
  optimizationLevel = $( '[name="optimization_level"]:checked' ).val(),
180
  confirmMessage;
181
 
182
+ e.preventDefault();
183
+
184
  if ( optimizationLevel === undefined ) {
185
  optimizationLevel = -1;
186
  }
187
 
188
  if ( $obj.attr( 'disabled' ) ) {
189
+ return;
190
  }
191
 
192
  $obj.attr( 'disabled', 'disabled' );
assets/js/bulk.min.js CHANGED
@@ -1 +1 @@
1
- window.imagify=window.imagify||{concat:ajaxurl.indexOf("?")>0?"&":"?",log:function(a){void 0!==console&&console.log(a)},info:function(a){void 0!==console&&console.info(a)}},function(a,b,c,d){function e(b){b.each(function(){var b=a(this),c=parseInt(b.closest(".imagify-chart").next(".imagipercent").text(),10),d=[{value:c,color:"#00B3D3"},{value:100-c,color:"#D8D8D8"}];new Chart(b[0].getContext("2d")).Doughnut(d,{segmentStrokeColor:"#FFF",segmentStrokeWidth:1,animateRotate:!0,tooltipEvents:[]})})}function f(b){b.each(function(){var b=a(this),c=parseInt(b.closest(".imagify-ac-chart").attr("data-percent"),10),d=[{value:c,color:"#40B1D0"},{value:100-c,color:"#FFFFFF"}];new Chart(b[0].getContext("2d")).Doughnut(d,{segmentStrokeColor:"transparent",segmentStrokeWidth:0,animateRotate:!0,animation:!0,percentageInnerCutout:70,tooltipEvents:[]})})}var g,h,i=b.getElementById("imagify-overview-chart"),j=[{value:imagifyBulk.labels.totalUnoptimizedAttachments,color:"#D9E4EB",highlight:"#D9E4EB",label:imagifyBulk.labels.overviewChartLabels.unoptimized},{value:imagifyBulk.labels.totalOptimizedAttachments,color:"#46B1CE",highlight:"#46B1CE",label:imagifyBulk.labels.overviewChartLabels.optimized},{value:imagifyBulk.labels.totalErrorsAttachments,color:"#2E3242",highlight:"#2E3242",label:imagifyBulk.labels.overviewChartLabels.error}];i&&(g=new Chart(i.getContext("2d")).Doughnut(j,{segmentStrokeColor:"transparent",segmentStrokeWidth:0,animateRotate:!0,animation:!0,percentageInnerCutout:85,legendTemplate:'<ul class="imagify-<%=name.toLowerCase()%>-legend"><% for (var i=0; i<segments.length; i++){%><li><span style="background-color:<%=segments[i].fillColor%>"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>',tooltipTemplate:"<%= value %>"}),h='<ul class="imagify-doughnut-legend">',a(j).each(function(a){h+='<li><span style="background-color:'+j[a].color+'"></span>'+j[a].label+"</li>"}),h+="</ul>",b.getElementById("imagify-overview-chart-legend").innerHTML=h),a(b).on("heartbeat-send",function(a,b){b.imagify_heartbeat=imagifyBulk.heartbeat_id}),a(b).on("heartbeat-tick",function(b,c){c.imagify_bulk_data&&(c=c.imagify_bulk_data,a("#imagify-overview-chart-percent").html(c.optimized_attachments_percent+"<span>%</span>"),a(".imagify-total-percent").html(c.optimized_attachments_percent+"%"),a(".imagify-unconsumed-percent").html(c.unconsumed_quota+"%"),a(".imagify-unconsumed-bar").css("width",c.unconsumed_quota+"%"),a("#imagify-total-optimized-attachments").html(c.already_optimized_attachments),a("#imagify-original-bar").find(".imagify-barnb").html(c.original_human),a("#imagify-optimized-bar").css("width",c.optimized_percent+"%").find(".imagify-barnb").html(c.optimized_human),a("#imagify-total-optimized-attachments-pct").html(c.optimized_percent+"%"),g.segments[0].value=c.unoptimized_attachments,g.segments[1].value=c.optimized_attachments,g.segments[2].value=c.errors_attachments,g.update())}),a("#imagify-simulate-bulk-action").on("click",function(b){b.preventDefault(),a("#imagify-bulk-action").trigger("click")}),a("#imagify-bulk-action").on("click",function(){var b,d=a(this),g=a('[name="optimization_level"]:checked').val();if(void 0===g&&(g=-1),d.attr("disabled"))return!1;d.attr("disabled","disabled"),d.find(".dashicons").addClass("rotate"),b=function(){return imagifyBulk.labels.processing},a(c).on("beforeunload",b),swal({title:imagifyBulk.labels.waitTitle,html:imagifyBulk.labels.waitText,showConfirmButton:!1,imageUrl:imagifyBulk.labels.waitImageUrl}),a.get(ajaxurl+imagify.concat+"action="+imagifyBulk.ajax_action+"&optimization_level="+g+"&imagifybulkuploadnonce="+a("#imagifybulkuploadnonce").val()).done(function(g){var h,i,j="",k="",l=0,m=0,n=0,o=0;if(!g.success)return d.removeAttr("disabled"),d.find(".dashicons").removeClass("rotate"),a(c).off("beforeunload",b),"invalid-api-key"===g.data.message&&(j=imagifyBulk.labels.invalidAPIKeyTitle),"over-quota"===g.data.message&&(j=imagifyBulk.labels.overQuotaTitle,imagifyBulk.labels.overQuotaText),"no-images"===g.data.message&&(j=imagifyBulk.labels.noAttachmentToOptimizeTitle,k=imagifyBulk.labels.noAttachmentToOptimizeText),void swal({title:j,html:k,type:"info",customClass:"imagify-sweet-alert"});swal.close(),a(".imagify-row-progress").slideDown(),a(".imagify-no-uploaded-yet, .imagify-row-complete").hide(200),i=a(".imagify-bulk-table table tbody"),h=new ImagifyGulp({lib:ajaxurl+imagify.concat+"action=imagify_bulk_upload&imagifybulkuploadnonce="+a("#imagifybulkuploadnonce").val(),images:g.data,context:imagifyBulk.ajax_context}),h.before(function(a){i.find(".imagify-row-progress").after('<tr id="attachment-'+a.id+'"><td class="imagify-cell-filename"><span class="imagiuploaded"><img src="'+a.thumbnail+'"/>"</span><span class="imagifilename">'+a.filename+'</span></td><td class="imagify-cell-status"><span class="imagistatus status-compressing"><span class="dashicons dashicons-admin-generic rotate"></span>Compressing<span></span></span></td><td class="imagify-cell-original"></td><td class="imagify-cell-optimized"></td><td class="imagify-cell-percentage"></td><td class="imagify-cell-thumbnails"></td><td class="imagify-cell-savings"></td></tr>')}).each(function(b){var c=a("#imagify-progress-bar"),d="error",f="dismiss",g="Error";if(c.css({width:b.progress+"%"}),c.find(".percent").html(b.progress+"%"),b.success)return a("#attachment-"+b.image+" .imagify-cell-status").html('<span class="imagistatus status-complete"><span class="dashicons dashicons-yes"></span>Complete</span>'),a("#attachment-"+b.image+" .imagify-cell-original").html(b.original_size_human),a("#attachment-"+b.image+" .imagify-cell-optimized").html(b.new_size_human),a("#attachment-"+b.image+" .imagify-cell-percentage").html('<span class="imagify-chart"><span class="imagify-chart-container"><canvas height="18" width="18" id="imagify-consumption-chart" style="width: 18px; height: 18px;"></canvas></span></span><span class="imagipercent">'+b.percent+"</span>%"),e(a("#attachment-"+b.image+" .imagify-cell-percentage").find("canvas")),a("#attachment-"+b.image+" .imagify-cell-thumbnails").html(b.thumbnails),a("#attachment-"+b.image+" .imagify-cell-savings").html(h.humanSize(b.overall_saving,1)),l=l+b.thumbnails+1,a(".imagify-cell-nb-files").html(l+" file(s)"),n+=b.original_overall_size,a(".imagify-total-original").html(h.humanSize(n,1)),o+=b.overall_saving,void a(".imagify-total-gain").html(h.humanSize(o,1));b.error.indexOf("You've consumed all your data")>=0&&swal({title:imagifyBulk.labels.overQuotaTitle,html:imagifyBulk.labels.overQuotaText,type:"error",customClass:"imagify-sweet-alert"}).then(function(){location.reload()}),b.error.indexOf("This image is already compressed")>=0?(d="warning",f="warning",g="Notice"):(m++,a(".imagify-cell-errors").html(m+" error(s)")),a("#attachment-"+b.image).after('<tr><td colspan="7"><span class="status-'+d+'">'+b.error+"</span></td></tr>"),a("#attachment-"+b.image+" .imagify-cell-status").html('<span class="imagistatus status-'+d+'"><span class="dashicons dashicons-'+f+'"></span>'+g+"</span>")}).done(function(e){var g;d.removeAttr("disabled").find(".dashicons").removeClass("rotate"),a(c).off("beforeunload",b),a(".imagify-row-progress").slideUp(),"NaN"!==e.global_percent&&(a(".imagify-row-complete").removeClass("hidden").addClass("done").attr("aria-hidden","false"),a("html, body").animate({scrollTop:a(".imagify-row-complete").offset().top},200),a(".imagify-ac-rt-total-gain").html(e.global_gain_human),a(".imagify-ac-rt-total-original").html(e.global_original_size_human),g=imagifyBulk.labels.textToShare,g=g.replace("%1$s",e.global_gain_human),g=g.replace("%2$s",e.global_original_size_human),g=encodeURIComponent(g),a(".imagify-sn-twitter").attr("href","https://twitter.com/intent/tweet?source=webclient&amp;original_referer="+imagifyBulk.labels.pluginURL+"&amp;text="+g+"&amp;url="+imagifyBulk.labels.pluginURL+"&amp;related=imagify&amp;hastags=performance,web,wordpress"),a(".imagify-ac-chart").attr("data-percent",e.global_percent),f(a(".imagify-ac-chart").find("canvas")))}).error(function(a){imagify.log("Can't optimize image with id "+a)}).run()}).fail(function(){swal({title:imagifyBulk.labels.getUnoptimizedImagesErrorTitle,html:imagifyBulk.labels.getUnoptimizedImagesErrorText,type:"error",customClass:"imagify-sweet-alert"}).then(function(){location.reload()})})})}(jQuery,document,window),function(a,b,c,d){var e,f;c.innerWidth?(e=(c.innerWidth-700)/2,f=(c.innerHeight-290)/2):(e=(b.body.clientWidth-700)/2,f=(b.body.clientHeight-290)/2),[].forEach.call(b.querySelectorAll(".imagify-share-networks a"),function(a){a.addEventListener("click",function(a){c.open(this.href,"","status=no, scrollbars=no, menubar=no, top="+f+", left="+e+", width=700, height=290"),a.preventDefault()},!1)})}(jQuery,document,window);
1
+ window.imagify=window.imagify||{concat:ajaxurl.indexOf("?")>0?"&":"?",log:function(a){void 0!==console&&console.log(a)},info:function(a){void 0!==console&&console.info(a)}},function(a,b,c,d){function e(b){b.each(function(){var b=a(this),c=parseInt(b.closest(".imagify-chart").next(".imagipercent").text(),10),d=[{value:c,color:"#00B3D3"},{value:100-c,color:"#D8D8D8"}];new Chart(b[0].getContext("2d")).Doughnut(d,{segmentStrokeColor:"#FFF",segmentStrokeWidth:1,animateRotate:!0,tooltipEvents:[]})})}function f(b){b.each(function(){var b=a(this),c=parseInt(b.closest(".imagify-ac-chart").attr("data-percent"),10),d=[{value:c,color:"#40B1D0"},{value:100-c,color:"#FFFFFF"}];new Chart(b[0].getContext("2d")).Doughnut(d,{segmentStrokeColor:"transparent",segmentStrokeWidth:0,animateRotate:!0,animation:!0,percentageInnerCutout:70,tooltipEvents:[]})})}var g,h,i=b.getElementById("imagify-overview-chart"),j=[{value:imagifyBulk.labels.totalUnoptimizedAttachments,color:"#D9E4EB",highlight:"#D9E4EB",label:imagifyBulk.labels.overviewChartLabels.unoptimized},{value:imagifyBulk.labels.totalOptimizedAttachments,color:"#46B1CE",highlight:"#46B1CE",label:imagifyBulk.labels.overviewChartLabels.optimized},{value:imagifyBulk.labels.totalErrorsAttachments,color:"#2E3242",highlight:"#2E3242",label:imagifyBulk.labels.overviewChartLabels.error}];i&&(g=new Chart(i.getContext("2d")).Doughnut(j,{segmentStrokeColor:"transparent",segmentStrokeWidth:0,animateRotate:!0,animation:!0,percentageInnerCutout:85,legendTemplate:'<ul class="imagify-<%=name.toLowerCase()%>-legend"><% for (var i=0; i<segments.length; i++){%><li><span style="background-color:<%=segments[i].fillColor%>"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>',tooltipTemplate:"<%= value %>"}),h='<ul class="imagify-doughnut-legend">',a(j).each(function(a){h+='<li><span style="background-color:'+j[a].color+'"></span>'+j[a].label+"</li>"}),h+="</ul>",b.getElementById("imagify-overview-chart-legend").innerHTML=h),a(b).on("heartbeat-send",function(a,b){b.imagify_heartbeat=imagifyBulk.heartbeat_id}),a(b).on("heartbeat-tick",function(b,c){c.imagify_bulk_data&&(c=c.imagify_bulk_data,a("#imagify-overview-chart-percent").html(c.optimized_attachments_percent+"<span>%</span>"),a(".imagify-total-percent").html(c.optimized_attachments_percent+"%"),a(".imagify-unconsumed-percent").html(c.unconsumed_quota+"%"),a(".imagify-unconsumed-bar").css("width",c.unconsumed_quota+"%"),a("#imagify-total-optimized-attachments").html(c.already_optimized_attachments),a("#imagify-original-bar").find(".imagify-barnb").html(c.original_human),a("#imagify-optimized-bar").css("width",c.optimized_percent+"%").find(".imagify-barnb").html(c.optimized_human),a("#imagify-total-optimized-attachments-pct").html(c.optimized_percent+"%"),g.segments[0].value=c.unoptimized_attachments,g.segments[1].value=c.optimized_attachments,g.segments[2].value=c.errors_attachments,g.update())}),a("#imagify-simulate-bulk-action").on("click",function(b){b.preventDefault(),a("#imagify-bulk-action").trigger("click")}),a("#imagify-bulk-action").on("click",function(b){var d,g=a(this),h=a('[name="optimization_level"]:checked').val();b.preventDefault(),void 0===h&&(h=-1),g.attr("disabled")||(g.attr("disabled","disabled"),g.find(".dashicons").addClass("rotate"),d=function(){return imagifyBulk.labels.processing},a(c).on("beforeunload",d),swal({title:imagifyBulk.labels.waitTitle,html:imagifyBulk.labels.waitText,showConfirmButton:!1,imageUrl:imagifyBulk.labels.waitImageUrl}),a.get(ajaxurl+imagify.concat+"action="+imagifyBulk.ajax_action+"&optimization_level="+h+"&imagifybulkuploadnonce="+a("#imagifybulkuploadnonce").val()).done(function(b){var h,i,j="",k="",l=0,m=0,n=0,o=0;if(!b.success)return g.removeAttr("disabled"),g.find(".dashicons").removeClass("rotate"),a(c).off("beforeunload",d),"invalid-api-key"===b.data.message&&(j=imagifyBulk.labels.invalidAPIKeyTitle),"over-quota"===b.data.message&&(j=imagifyBulk.labels.overQuotaTitle,imagifyBulk.labels.overQuotaText),"no-images"===b.data.message&&(j=imagifyBulk.labels.noAttachmentToOptimizeTitle,k=imagifyBulk.labels.noAttachmentToOptimizeText),void swal({title:j,html:k,type:"info",customClass:"imagify-sweet-alert"});swal.close(),a(".imagify-row-progress").slideDown(),a(".imagify-no-uploaded-yet, .imagify-row-complete").hide(200),i=a(".imagify-bulk-table table tbody"),h=new ImagifyGulp({lib:ajaxurl+imagify.concat+"action=imagify_bulk_upload&imagifybulkuploadnonce="+a("#imagifybulkuploadnonce").val(),images:b.data,context:imagifyBulk.ajax_context}),h.before(function(a){i.find(".imagify-row-progress").after('<tr id="attachment-'+a.id+'"><td class="imagify-cell-filename"><span class="imagiuploaded"><img src="'+a.thumbnail+'"/>"</span><span class="imagifilename">'+a.filename+'</span></td><td class="imagify-cell-status"><span class="imagistatus status-compressing"><span class="dashicons dashicons-admin-generic rotate"></span>Compressing<span></span></span></td><td class="imagify-cell-original"></td><td class="imagify-cell-optimized"></td><td class="imagify-cell-percentage"></td><td class="imagify-cell-thumbnails"></td><td class="imagify-cell-savings"></td></tr>')}).each(function(b){var c=a("#imagify-progress-bar"),d="error",f="dismiss",g="Error";if(c.css({width:b.progress+"%"}),c.find(".percent").html(b.progress+"%"),b.success)return a("#attachment-"+b.image+" .imagify-cell-status").html('<span class="imagistatus status-complete"><span class="dashicons dashicons-yes"></span>Complete</span>'),a("#attachment-"+b.image+" .imagify-cell-original").html(b.original_size_human),a("#attachment-"+b.image+" .imagify-cell-optimized").html(b.new_size_human),a("#attachment-"+b.image+" .imagify-cell-percentage").html('<span class="imagify-chart"><span class="imagify-chart-container"><canvas height="18" width="18" id="imagify-consumption-chart" style="width: 18px; height: 18px;"></canvas></span></span><span class="imagipercent">'+b.percent+"</span>%"),e(a("#attachment-"+b.image+" .imagify-cell-percentage").find("canvas")),a("#attachment-"+b.image+" .imagify-cell-thumbnails").html(b.thumbnails),a("#attachment-"+b.image+" .imagify-cell-savings").html(h.humanSize(b.overall_saving,1)),l=l+b.thumbnails+1,a(".imagify-cell-nb-files").html(l+" file(s)"),n+=b.original_overall_size,a(".imagify-total-original").html(h.humanSize(n,1)),o+=b.overall_saving,void a(".imagify-total-gain").html(h.humanSize(o,1));b.error.indexOf("You've consumed all your data")>=0&&swal({title:imagifyBulk.labels.overQuotaTitle,html:imagifyBulk.labels.overQuotaText,type:"error",customClass:"imagify-sweet-alert"}).then(function(){location.reload()}),b.error.indexOf("This image is already compressed")>=0?(d="warning",f="warning",g="Notice"):(m++,a(".imagify-cell-errors").html(m+" error(s)")),a("#attachment-"+b.image).after('<tr><td colspan="7"><span class="status-'+d+'">'+b.error+"</span></td></tr>"),a("#attachment-"+b.image+" .imagify-cell-status").html('<span class="imagistatus status-'+d+'"><span class="dashicons dashicons-'+f+'"></span>'+g+"</span>")}).done(function(b){var e;g.removeAttr("disabled").find(".dashicons").removeClass("rotate"),a(c).off("beforeunload",d),a(".imagify-row-progress").slideUp(),"NaN"!==b.global_percent&&(a(".imagify-row-complete").removeClass("hidden").addClass("done").attr("aria-hidden","false"),a("html, body").animate({scrollTop:a(".imagify-row-complete").offset().top},200),a(".imagify-ac-rt-total-gain").html(b.global_gain_human),a(".imagify-ac-rt-total-original").html(b.global_original_size_human),e=imagifyBulk.labels.textToShare,e=e.replace("%1$s",b.global_gain_human),e=e.replace("%2$s",b.global_original_size_human),e=encodeURIComponent(e),a(".imagify-sn-twitter").attr("href","https://twitter.com/intent/tweet?source=webclient&amp;original_referer="+imagifyBulk.labels.pluginURL+"&amp;text="+e+"&amp;url="+imagifyBulk.labels.pluginURL+"&amp;related=imagify&amp;hastags=performance,web,wordpress"),a(".imagify-ac-chart").attr("data-percent",b.global_percent),f(a(".imagify-ac-chart").find("canvas")))}).error(function(a){imagify.log("Can't optimize image with id "+a)}).run()}).fail(function(){swal({title:imagifyBulk.labels.getUnoptimizedImagesErrorTitle,html:imagifyBulk.labels.getUnoptimizedImagesErrorText,type:"error",customClass:"imagify-sweet-alert"}).then(function(){location.reload()})}))})}(jQuery,document,window),function(a,b,c,d){var e,f;c.innerWidth?(e=(c.innerWidth-700)/2,f=(c.innerHeight-290)/2):(e=(b.body.clientWidth-700)/2,f=(b.body.clientHeight-290)/2),[].forEach.call(b.querySelectorAll(".imagify-share-networks a"),function(a){a.addEventListener("click",function(a){c.open(this.href,"","status=no, scrollbars=no, menubar=no, top="+f+", left="+e+", width=700, height=290"),a.preventDefault()},!1)})}(jQuery,document,window);
assets/js/es6-promise.auto.js ADDED
@@ -0,0 +1,1160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * @overview es6-promise - a tiny implementation of Promises/A+.
3
+ * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald)
4
+ * @license Licensed under MIT license
5
+ * See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE
6
+ * @version 4.1.0+f9a5575b
7
+ */
8
+
9
+ (function (global, factory) {
10
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
11
+ typeof define === 'function' && define.amd ? define(factory) :
12
+ (global.ES6Promise = factory());
13
+ }(this, (function () { 'use strict';
14
+
15
+ function objectOrFunction(x) {
16
+ return typeof x === 'function' || typeof x === 'object' && x !== null;
17
+ }
18
+
19
+ function isFunction(x) {
20
+ return typeof x === 'function';
21
+ }
22
+
23
+ var _isArray = undefined;
24
+ if (!Array.isArray) {
25
+ _isArray = function (x) {
26
+ return Object.prototype.toString.call(x) === '[object Array]';
27
+ };
28
+ } else {
29
+ _isArray = Array.isArray;
30
+ }
31
+
32
+ var isArray = _isArray;
33
+
34
+ var len = 0;
35
+ var vertxNext = undefined;
36
+ var customSchedulerFn = undefined;
37
+
38
+ var asap = function asap(callback, arg) {
39
+ queue[len] = callback;
40
+ queue[len + 1] = arg;
41
+ len += 2;
42
+ if (len === 2) {
43
+ // If len is 2, that means that we need to schedule an async flush.
44
+ // If additional callbacks are queued before the queue is flushed, they
45
+ // will be processed by this flush that we are scheduling.
46
+ if (customSchedulerFn) {
47
+ customSchedulerFn(flush);
48
+ } else {
49
+ scheduleFlush();
50
+ }
51
+ }
52
+ };
53
+
54
+ function setScheduler(scheduleFn) {
55
+ customSchedulerFn = scheduleFn;
56
+ }
57
+
58
+ function setAsap(asapFn) {
59
+ asap = asapFn;
60
+ }
61
+
62
+ var browserWindow = typeof window !== 'undefined' ? window : undefined;
63
+ var browserGlobal = browserWindow || {};
64
+ var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
65
+ var isNode = typeof self === 'undefined' && typeof process !== 'undefined' && ({}).toString.call(process) === '[object process]';
66
+
67
+ // test for web worker but not in IE10
68
+ var isWorker = typeof Uint8ClampedArray !== 'undefined' && typeof importScripts !== 'undefined' && typeof MessageChannel !== 'undefined';
69
+
70
+ // node
71
+ function useNextTick() {
72
+ // node version 0.10.x displays a deprecation warning when nextTick is used recursively
73
+ // see https://github.com/cujojs/when/issues/410 for details
74
+ return function () {
75
+ return process.nextTick(flush);
76
+ };
77
+ }
78
+
79
+ // vertx
80
+ function useVertxTimer() {
81
+ if (typeof vertxNext !== 'undefined') {
82
+ return function () {
83
+ vertxNext(flush);
84
+ };
85
+ }
86
+
87
+ return useSetTimeout();
88
+ }
89
+
90
+ function useMutationObserver() {
91
+ var iterations = 0;
92
+ var observer = new BrowserMutationObserver(flush);
93
+ var node = document.createTextNode('');
94
+ observer.observe(node, { characterData: true });
95
+
96
+ return function () {
97
+ node.data = iterations = ++iterations % 2;
98
+ };
99
+ }
100
+
101
+ // web worker
102
+ function useMessageChannel() {
103
+ var channel = new MessageChannel();
104
+ channel.port1.onmessage = flush;
105
+ return function () {
106
+ return channel.port2.postMessage(0);
107
+ };
108
+ }
109
+
110
+ function useSetTimeout() {
111
+ // Store setTimeout reference so es6-promise will be unaffected by
112
+ // other code modifying setTimeout (like sinon.useFakeTimers())
113
+ var globalSetTimeout = setTimeout;
114
+ return function () {
115
+ return globalSetTimeout(flush, 1);
116
+ };
117
+ }
118
+
119
+ var queue = new Array(1000);
120
+ function flush() {
121
+ for (var i = 0; i < len; i += 2) {
122
+ var callback = queue[i];
123
+ var arg = queue[i + 1];
124
+
125
+ callback(arg);
126
+
127
+ queue[i] = undefined;
128
+ queue[i + 1] = undefined;
129
+ }
130
+
131
+ len = 0;
132
+ }
133
+
134
+ function attemptVertx() {
135
+ try {
136
+ var r = require;
137
+ var vertx = r('vertx');
138
+ vertxNext = vertx.runOnLoop || vertx.runOnContext;
139
+ return useVertxTimer();
140
+ } catch (e) {
141
+ return useSetTimeout();
142
+ }
143
+ }
144
+
145
+ var scheduleFlush = undefined;
146
+ // Decide what async method to use to triggering processing of queued callbacks:
147
+ if (isNode) {
148
+ scheduleFlush = useNextTick();
149
+ } else if (BrowserMutationObserver) {
150
+ scheduleFlush = useMutationObserver();
151
+ } else if (isWorker) {
152
+ scheduleFlush = useMessageChannel();
153
+ } else if (browserWindow === undefined && typeof require === 'function') {
154
+ scheduleFlush = attemptVertx();
155
+ } else {
156
+ scheduleFlush = useSetTimeout();
157
+ }
158
+
159
+ function then(onFulfillment, onRejection) {
160
+ var _arguments = arguments;
161
+
162
+ var parent = this;
163
+
164
+ var child = new this.constructor(noop);
165
+
166
+ if (child[PROMISE_ID] === undefined) {
167
+ makePromise(child);
168
+ }
169
+
170
+ var _state = parent._state;
171
+
172
+ if (_state) {
173
+ (function () {
174
+ var callback = _arguments[_state - 1];
175
+ asap(function () {
176
+ return invokeCallback(_state, child, callback, parent._result);
177
+ });
178
+ })();
179
+ } else {
180
+ subscribe(parent, child, onFulfillment, onRejection);
181
+ }
182
+
183
+ return child;
184
+ }
185
+
186
+ /**
187
+ `Promise.resolve` returns a promise that will become resolved with the
188
+ passed `value`. It is shorthand for the following:
189
+
190
+ ```javascript
191
+ let promise = new Promise(function(resolve, reject){
192
+ resolve(1);
193
+ });
194
+
195
+ promise.then(function(value){
196
+ // value === 1
197
+ });
198
+ ```
199
+
200
+ Instead of writing the above, your code now simply becomes the following:
201
+
202
+ ```javascript
203
+ let promise = Promise.resolve(1);
204
+
205
+ promise.then(function(value){
206
+ // value === 1
207
+ });
208
+ ```
209
+
210
+ @method resolve
211
+ @static
212
+ @param {Any} value value that the returned promise will be resolved with
213
+ Useful for tooling.
214
+ @return {Promise} a promise that will become fulfilled with the given
215
+ `value`
216
+ */
217
+ function resolve(object) {
218
+ /*jshint validthis:true */
219
+ var Constructor = this;
220
+
221
+ if (object && typeof object === 'object' && object.constructor === Constructor) {
222
+ return object;
223
+ }
224
+
225
+ var promise = new Constructor(noop);
226
+ _resolve(promise, object);
227
+ return promise;
228
+ }
229
+
230
+ var PROMISE_ID = Math.random().toString(36).substring(16);
231
+
232
+ function noop() {}
233
+
234
+ var PENDING = void 0;
235
+ var FULFILLED = 1;
236
+ var REJECTED = 2;
237
+
238
+ var GET_THEN_ERROR = new ErrorObject();
239
+
240
+ function selfFulfillment() {
241
+ return new TypeError("You cannot resolve a promise with itself");
242
+ }
243
+
244
+ function cannotReturnOwn() {
245
+ return new TypeError('A promises callback cannot return that same promise.');
246
+ }
247
+
248
+ function getThen(promise) {
249
+ try {
250
+ return promise.then;
251
+ } catch (error) {
252
+ GET_THEN_ERROR.error = error;
253
+ return GET_THEN_ERROR;
254
+ }
255
+ }
256
+
257
+ function tryThen(then, value, fulfillmentHandler, rejectionHandler) {
258
+ try {
259
+ then.call(value, fulfillmentHandler, rejectionHandler);
260
+ } catch (e) {
261
+ return e;
262
+ }
263
+ }
264
+
265
+ function handleForeignThenable(promise, thenable, then) {
266
+ asap(function (promise) {
267
+ var sealed = false;
268
+ var error = tryThen(then, thenable, function (value) {
269
+ if (sealed) {
270
+ return;
271
+ }
272
+ sealed = true;
273
+ if (thenable !== value) {
274
+ _resolve(promise, value);
275
+ } else {
276
+ fulfill(promise, value);
277
+ }
278
+ }, function (reason) {
279
+ if (sealed) {
280
+ return;
281
+ }
282
+ sealed = true;
283
+
284
+ _reject(promise, reason);
285
+ }, 'Settle: ' + (promise._label || ' unknown promise'));
286
+
287
+ if (!sealed && error) {
288
+ sealed = true;
289
+ _reject(promise, error);
290
+ }
291
+ }, promise);
292
+ }
293
+
294
+ function handleOwnThenable(promise, thenable) {
295
+ if (thenable._state === FULFILLED) {
296
+ fulfill(promise, thenable._result);
297
+ } else if (thenable._state === REJECTED) {
298
+ _reject(promise, thenable._result);
299
+ } else {
300
+ subscribe(thenable, undefined, function (value) {
301
+ return _resolve(promise, value);
302
+ }, function (reason) {
303
+ return _reject(promise, reason);
304
+ });
305
+ }
306
+ }
307
+
308
+ function handleMaybeThenable(promise, maybeThenable, then$$) {
309
+ if (maybeThenable.constructor === promise.constructor && then$$ === then && maybeThenable.constructor.resolve === resolve) {
310
+ handleOwnThenable(promise, maybeThenable);
311
+ } else {
312
+ if (then$$ === GET_THEN_ERROR) {
313
+ _reject(promise, GET_THEN_ERROR.error);
314
+ GET_THEN_ERROR.error = null;
315
+ } else if (then$$ === undefined) {
316
+ fulfill(promise, maybeThenable);
317
+ } else if (isFunction(then$$)) {
318
+ handleForeignThenable(promise, maybeThenable, then$$);
319
+ } else {
320
+ fulfill(promise, maybeThenable);
321
+ }
322
+ }
323
+ }
324
+
325
+ function _resolve(promise, value) {
326
+ if (promise === value) {
327
+ _reject(promise, selfFulfillment());
328
+ } else if (objectOrFunction(value)) {
329
+ handleMaybeThenable(promise, value, getThen(value));
330
+ } else {
331
+ fulfill(promise, value);
332
+ }
333
+ }
334
+
335
+ function publishRejection(promise) {
336
+ if (promise._onerror) {
337
+ promise._onerror(promise._result);
338
+ }
339
+
340
+ publish(promise);
341
+ }
342
+
343
+ function fulfill(promise, value) {
344
+ if (promise._state !== PENDING) {
345
+ return;
346
+ }
347
+
348
+ promise._result = value;
349
+ promise._state = FULFILLED;
350
+
351
+ if (promise._subscribers.length !== 0) {
352
+ asap(publish, promise);
353
+ }
354
+ }
355
+
356
+ function _reject(promise, reason) {
357
+ if (promise._state !== PENDING) {
358
+ return;
359
+ }
360
+ promise._state = REJECTED;
361
+ promise._result = reason;
362
+
363
+ asap(publishRejection, promise);
364
+ }
365
+
366
+ function subscribe(parent, child, onFulfillment, onRejection) {
367
+ var _subscribers = parent._subscribers;
368
+ var length = _subscribers.length;
369
+
370
+ parent._onerror = null;
371
+
372
+ _subscribers[length] = child;
373
+ _subscribers[length + FULFILLED] = onFulfillment;
374
+ _subscribers[length + REJECTED] = onRejection;
375
+
376
+ if (length === 0 && parent._state) {
377
+ asap(publish, parent);
378
+ }
379
+ }
380
+
381
+ function publish(promise) {
382
+ var subscribers = promise._subscribers;
383
+ var settled = promise._state;
384
+
385
+ if (subscribers.length === 0) {
386
+ return;
387
+ }
388
+
389
+ var child = undefined,
390
+ callback = undefined,
391
+ detail = promise._result;
392
+
393
+ for (var i = 0; i < subscribers.length; i += 3) {
394
+ child = subscribers[i];
395
+ callback = subscribers[i + settled];
396
+
397
+ if (child) {
398
+ invokeCallback(settled, child, callback, detail);
399
+ } else {
400
+ callback(detail);
401
+ }
402
+ }
403
+
404
+ promise._subscribers.length = 0;
405
+ }
406
+
407
+ function ErrorObject() {
408
+ this.error = null;
409
+ }
410
+
411
+ var TRY_CATCH_ERROR = new ErrorObject();
412
+
413
+ function tryCatch(callback, detail) {
414
+ try {
415
+ return callback(detail);
416
+ } catch (e) {
417
+ TRY_CATCH_ERROR.error = e;
418
+ return TRY_CATCH_ERROR;
419
+ }
420
+ }
421
+
422
+ function invokeCallback(settled, promise, callback, detail) {
423
+ var hasCallback = isFunction(callback),
424
+ value = undefined,
425
+ error = undefined,
426
+ succeeded = undefined,
427
+ failed = undefined;
428
+
429
+ if (hasCallback) {
430
+ value = tryCatch(callback, detail);
431
+
432
+ if (value === TRY_CATCH_ERROR) {
433
+ failed = true;
434
+ error = value.error;
435
+ value.error = null;
436
+ } else {
437
+ succeeded = true;
438
+ }
439
+
440
+ if (promise === value) {
441
+ _reject(promise, cannotReturnOwn());
442
+ return;
443
+ }
444
+ } else {
445
+ value = detail;
446
+ succeeded = true;
447
+ }
448
+
449
+ if (promise._state !== PENDING) {
450
+ // noop
451
+ } else if (hasCallback && succeeded) {
452
+ _resolve(promise, value);
453
+ } else if (failed) {
454
+ _reject(promise, error);
455
+ } else if (settled === FULFILLED) {
456
+ fulfill(promise, value);
457
+ } else if (settled === REJECTED) {
458
+ _reject(promise, value);
459
+ }
460
+ }
461
+
462
+ function initializePromise(promise, resolver) {
463
+ try {
464
+ resolver(function resolvePromise(value) {
465
+ _resolve(promise, value);
466
+ }, function rejectPromise(reason) {
467
+ _reject(promise, reason);
468
+ });
469
+ } catch (e) {
470
+ _reject(promise, e);
471
+ }
472
+ }
473
+
474
+ var id = 0;
475
+ function nextId() {
476
+ return id++;
477
+ }
478
+
479
+ function makePromise(promise) {
480
+ promise[PROMISE_ID] = id++;
481
+ promise._state = undefined;
482
+ promise._result = undefined;
483
+ promise._subscribers = [];
484
+ }
485
+
486
+ function Enumerator(Constructor, input) {
487
+ this._instanceConstructor = Constructor;
488
+ this.promise = new Constructor(noop);
489
+
490
+ if (!this.promise[PROMISE_ID]) {
491
+ makePromise(this.promise);
492
+ }
493
+
494
+ if (isArray(input)) {
495
+ this._input = input;
496
+ this.length = input.length;
497
+ this._remaining = input.length;
498
+
499
+ this._result = new Array(this.length);
500
+
501
+ if (this.length === 0) {
502
+ fulfill(this.promise, this._result);
503
+ } else {
504
+ this.length = this.length || 0;
505
+ this._enumerate();
506
+ if (this._remaining === 0) {
507
+ fulfill(this.promise, this._result);
508
+ }
509
+ }
510
+ } else {
511
+ _reject(this.promise, validationError());
512
+ }
513
+ }
514
+
515
+ function validationError() {
516
+ return new Error('Array Methods must be provided an Array');
517
+ };
518
+
519
+ Enumerator.prototype._enumerate = function () {
520
+ var length = this.length;
521
+ var _input = this._input;
522
+
523
+ for (var i = 0; this._state === PENDING && i < length; i++) {
524
+ this._eachEntry(_input[i], i);
525
+ }
526
+ };
527
+
528
+ Enumerator.prototype._eachEntry = function (entry, i) {
529
+ var c = this._instanceConstructor;
530
+ var resolve$$ = c.resolve;
531
+
532
+ if (resolve$$ === resolve) {
533
+ var _then = getThen(entry);
534
+
535
+ if (_then === then && entry._state !== PENDING) {
536
+ this._settledAt(entry._state, i, entry._result);
537
+ } else if (typeof _then !== 'function') {
538
+ this._remaining--;
539
+ this._result[i] = entry;
540
+ } else if (c === Promise) {
541
+ var promise = new c(noop);
542
+ handleMaybeThenable(promise, entry, _then);
543
+ this._willSettleAt(promise, i);
544
+ } else {
545
+ this._willSettleAt(new c(function (resolve$$) {
546
+ return resolve$$(entry);
547
+ }), i);
548
+ }
549
+ } else {
550
+ this._willSettleAt(resolve$$(entry), i);
551
+ }
552
+ };
553
+
554
+ Enumerator.prototype._settledAt = function (state, i, value) {
555
+ var promise = this.promise;
556
+
557
+ if (promise._state === PENDING) {
558
+ this._remaining--;
559
+
560
+ if (state === REJECTED) {
561
+ _reject(promise, value);
562
+ } else {
563
+ this._result[i] = value;
564
+ }
565
+ }
566
+
567
+ if (this._remaining === 0) {
568
+ fulfill(promise, this._result);
569
+ }
570
+ };
571
+
572
+ Enumerator.prototype._willSettleAt = function (promise, i) {
573
+ var enumerator = this;
574
+
575
+ subscribe(promise, undefined, function (value) {
576
+ return enumerator._settledAt(FULFILLED, i, value);
577
+ }, function (reason) {
578
+ return enumerator._settledAt(REJECTED, i, reason);
579
+ });
580
+ };
581
+
582
+ /**
583
+ `Promise.all` accepts an array of promises, and returns a new promise which
584
+ is fulfilled with an array of fulfillment values for the passed promises, or
585
+ rejected with the reason of the first passed promise to be rejected. It casts all
586
+ elements of the passed iterable to promises as it runs this algorithm.
587
+
588
+ Example:
589
+
590
+ ```javascript
591
+ let promise1 = resolve(1);
592
+ let promise2 = resolve(2);
593
+ let promise3 = resolve(3);
594
+ let promises = [ promise1, promise2, promise3 ];
595
+
596
+ Promise.all(promises).then(function(array){
597
+ // The array here would be [ 1, 2, 3 ];
598
+ });
599
+ ```
600
+
601
+ If any of the `promises` given to `all` are rejected, the first promise
602
+ that is rejected will be given as an argument to the returned promises's
603
+ rejection handler. For example:
604
+
605
+ Example:
606
+
607
+ ```javascript
608
+ let promise1 = resolve(1);
609
+ let promise2 = reject(new Error("2"));
610
+ let promise3 = reject(new Error("3"));
611
+ let promises = [ promise1, promise2, promise3 ];
612
+
613
+ Promise.all(promises).then(function(array){
614
+ // Code here never runs because there are rejected promises!
615
+ }, function(error) {
616
+ // error.message === "2"
617
+ });
618
+ ```
619
+
620
+ @method all
621
+ @static
622
+ @param {Array} entries array of promises
623
+ @param {String} label optional string for labeling the promise.
624
+ Useful for tooling.
625
+ @return {Promise} promise that is fulfilled when all `promises` have been
626
+ fulfilled, or rejected if any of them become rejected.
627
+ @static
628
+ */
629
+ function all(entries) {
630
+ return new Enumerator(this, entries).promise;
631
+ }
632
+
633
+ /**
634
+ `Promise.race` returns a new promise which is settled in the same way as the
635
+ first passed promise to settle.
636
+
637
+ Example:
638
+
639
+ ```javascript
640
+ let promise1 = new Promise(function(resolve, reject){
641
+ setTimeout(function(){
642
+ resolve('promise 1');
643
+ }, 200);
644
+ });
645
+
646
+ let promise2 = new Promise(function(resolve, reject){
647
+ setTimeout(function(){
648
+ resolve('promise 2');
649
+ }, 100);
650
+ });
651
+
652
+ Promise.race([promise1, promise2]).then(function(result){
653
+ // result === 'promise 2' because it was resolved before promise1
654
+ // was resolved.
655
+ });
656
+ ```
657
+
658
+ `Promise.race` is deterministic in that only the state of the first
659
+ settled promise matters. For example, even if other promises given to the
660
+ `promises` array argument are resolved, but the first settled promise has
661
+ become rejected before the other promises became fulfilled, the returned
662
+ promise will become rejected:
663
+
664
+ ```javascript
665
+ let promise1 = new Promise(function(resolve, reject){
666
+ setTimeout(function(){
667
+ resolve('promise 1');
668
+ }, 200);
669
+ });
670
+
671
+ let promise2 = new Promise(function(resolve, reject){
672
+ setTimeout(function(){
673
+ reject(new Error('promise 2'));
674
+ }, 100);
675
+ });
676
+
677
+ Promise.race([promise1, promise2]).then(function(result){
678
+ // Code here never runs
679
+ }, function(reason){
680
+ // reason.message === 'promise 2' because promise 2 became rejected before
681
+ // promise 1 became fulfilled
682
+ });
683
+ ```
684
+
685
+ An example real-world use case is implementing timeouts:
686
+
687
+ ```javascript
688
+ Promise.race([ajax('foo.json'), timeout(5000)])
689
+ ```
690
+
691
+ @method race
692
+ @static
693
+ @param {Array} promises array of promises to observe
694
+ Useful for tooling.
695
+ @return {Promise} a promise which settles in the same way as the first passed
696
+ promise to settle.
697
+ */
698
+ function race(entries) {
699
+ /*jshint validthis:true */
700
+ var Constructor = this;
701
+
702
+ if (!isArray(entries)) {
703
+ return new Constructor(function (_, reject) {
704
+ return reject(new TypeError('You must pass an array to race.'));
705
+ });
706
+ } else {
707
+ return new Constructor(function (resolve, reject) {
708
+ var length = entries.length;
709
+ for (var i = 0; i < length; i++) {
710
+ Constructor.resolve(entries[i]).then(resolve, reject);
711
+ }
712
+ });
713
+ }
714
+ }
715
+
716
+ /**
717
+ `Promise.reject` returns a promise rejected with the passed `reason`.
718
+ It is shorthand for the following:
719
+
720
+ ```javascript
721
+ let promise = new Promise(function(resolve, reject){
722
+ reject(new Error('WHOOPS'));
723
+ });
724
+
725
+ promise.then(function(value){
726
+ // Code here doesn't run because the promise is rejected!
727
+ }, function(reason){
728
+ // reason.message === 'WHOOPS'
729
+ });
730
+ ```
731
+
732
+ Instead of writing the above, your code now simply becomes the following:
733
+
734
+ ```javascript
735
+ let promise = Promise.reject(new Error('WHOOPS'));
736
+
737
+ promise.then(function(value){
738
+ // Code here doesn't run because the promise is rejected!
739
+ }, function(reason){
740
+ // reason.message === 'WHOOPS'
741
+ });
742
+ ```
743
+
744
+ @method reject
745
+ @static
746
+ @param {Any} reason value that the returned promise will be rejected with.
747
+ Useful for tooling.
748
+ @return {Promise} a promise rejected with the given `reason`.
749
+ */
750
+ function reject(reason) {
751
+ /*jshint validthis:true */
752
+ var Constructor = this;
753
+ var promise = new Constructor(noop);
754
+ _reject(promise, reason);
755
+ return promise;
756
+ }
757
+
758
+ function needsResolver() {
759
+ throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');
760
+ }
761
+
762
+ function needsNew() {
763
+ throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");
764
+ }
765
+
766
+ /**
767
+ Promise objects represent the eventual result of an asynchronous operation. The
768
+ primary way of interacting with a promise is through its `then` method, which
769
+ registers callbacks to receive either a promise's eventual value or the reason
770
+ why the promise cannot be fulfilled.
771
+
772
+ Terminology
773
+ -----------
774
+
775
+ - `promise` is an object or function with a `then` method whose behavior conforms to this specification.
776
+ - `thenable` is an object or function that defines a `then` method.
777
+ - `value` is any legal JavaScript value (including undefined, a thenable, or a promise).
778
+ - `exception` is a value that is thrown using the throw statement.
779
+ - `reason` is a value that indicates why a promise was rejected.
780
+ - `settled` the final resting state of a promise, fulfilled or rejected.
781
+
782
+ A promise can be in one of three states: pending, fulfilled, or rejected.
783
+
784
+ Promises that are fulfilled have a fulfillment value and are in the fulfilled
785
+ state. Promises that are rejected have a rejection reason and are in the
786
+ rejected state. A fulfillment value is never a thenable.
787
+
788
+ Promises can also be said to *resolve* a value. If this value is also a
789
+ promise, then the original promise's settled state will match the value's
790
+ settled state. So a promise that *resolves* a promise that rejects will
791
+ itself reject, and a promise that *resolves* a promise that fulfills will
792
+ itself fulfill.
793
+
794
+
795
+ Basic Usage:
796
+ ------------
797
+
798
+ ```js
799
+ let promise = new Promise(function(resolve, reject) {
800
+ // on success
801
+ resolve(value);
802
+
803
+ // on failure
804
+ reject(reason);
805
+ });
806
+
807
+ promise.then(function(value) {
808
+ // on fulfillment
809
+ }, function(reason) {
810
+ // on rejection
811
+ });
812
+ ```
813
+
814
+ Advanced Usage:
815
+ ---------------
816
+
817
+ Promises shine when abstracting away asynchronous interactions such as
818
+ `XMLHttpRequest`s.
819
+
820
+ ```js
821
+ function getJSON(url) {
822
+ return new Promise(function(resolve, reject){
823
+ let xhr = new XMLHttpRequest();
824
+
825
+ xhr.open('GET', url);
826
+ xhr.onreadystatechange = handler;
827
+ xhr.responseType = 'json';
828
+ xhr.setRequestHeader('Accept', 'application/json');
829
+ xhr.send();
830
+
831
+ function handler() {
832
+ if (this.readyState === this.DONE) {
833
+ if (this.status === 200) {
834
+ resolve(this.response);
835
+ } else {
836
+ reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']'));
837
+ }
838
+ }
839
+ };
840
+ });
841
+ }
842
+
843
+ getJSON('/posts.json').then(function(json) {
844
+ // on fulfillment
845
+ }, function(reason) {
846
+ // on rejection
847
+ });
848
+ ```
849
+
850
+ Unlike callbacks, promises are great composable primitives.
851
+
852
+ ```js
853
+ Promise.all([
854
+ getJSON('/posts'),
855
+ getJSON('/comments')
856
+ ]).then(function(values){
857
+ values[0] // => postsJSON
858
+ values[1] // => commentsJSON
859
+
860
+ return values;
861
+ });
862
+ ```
863
+
864
+ @class Promise
865
+ @param {function} resolver
866
+ Useful for tooling.
867
+ @constructor
868
+ */
869
+ function Promise(resolver) {
870
+ this[PROMISE_ID] = nextId();
871
+ this._result = this._state = undefined;
872
+ this._subscribers = [];
873
+
874
+ if (noop !== resolver) {
875
+ typeof resolver !== 'function' && needsResolver();
876
+ this instanceof Promise ? initializePromise(this, resolver) : needsNew();
877
+ }
878
+ }
879
+
880
+ Promise.all = all;
881
+ Promise.race = race;
882
+ Promise.resolve = resolve;
883
+ Promise.reject = reject;
884
+ Promise._setScheduler = setScheduler;
885
+ Promise._setAsap = setAsap;
886
+ Promise._asap = asap;
887
+
888
+ Promise.prototype = {
889
+ constructor: Promise,
890
+
891
+ /**
892
+ The primary way of interacting with a promise is through its `then` method,
893
+ which registers callbacks to receive either a promise's eventual value or the
894
+ reason why the promise cannot be fulfilled.
895
+
896
+ ```js
897
+ findUser().then(function(user){
898
+ // user is available
899
+ }, function(reason){
900
+ // user is unavailable, and you are given the reason why
901
+ });
902
+ ```
903
+
904
+ Chaining
905
+ --------
906
+
907
+ The return value of `then` is itself a promise. This second, 'downstream'
908
+ promise is resolved with the return value of the first promise's fulfillment
909
+ or rejection handler, or rejected if the handler throws an exception.
910
+
911
+ ```js
912
+ findUser().then(function (user) {
913
+ return user.name;
914
+ }, function (reason) {
915
+ return 'default name';
916
+ }).then(function (userName) {
917
+ // If `findUser` fulfilled, `userName` will be the user's name, otherwise it
918
+ // will be `'default name'`
919
+ });
920
+
921
+ findUser().then(function (user) {
922
+ throw new Error('Found user, but still unhappy');
923
+ }, function (reason) {
924
+ throw new Error('`findUser` rejected and we're unhappy');
925
+ }).then(function (value) {
926
+ // never reached
927
+ }, function (reason) {
928
+ // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.
929
+ // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'.
930
+ });
931
+ ```
932
+ If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream.
933
+
934
+ ```js
935
+ findUser().then(function (user) {
936
+ throw new PedagogicalException('Upstream error');
937
+ }).then(function (value) {
938
+ // never reached
939
+ }).then(function (value) {
940
+ // never reached
941
+ }, function (reason) {
942
+ // The `PedgagocialException` is propagated all the way down to here
943
+ });
944
+ ```
945
+
946
+ Assimilation
947
+ ------------
948
+
949
+ Sometimes the value you want to propagate to a downstream promise can only be
950
+ retrieved asynchronously. This can be achieved by returning a promise in the
951
+ fulfillment or rejection handler. The downstream promise will then be pending
952
+ until the returned promise is settled. This is called *assimilation*.
953
+
954
+ ```js
955
+ findUser().then(function (user) {
956
+ return findCommentsByAuthor(user);
957
+ }).then(function (comments) {
958
+ // The user's comments are now available
959
+ });
960
+ ```
961
+
962
+ If the assimliated promise rejects, then the downstream promise will also reject.
963
+
964
+ ```js
965
+ findUser().then(function (user) {
966
+ return findCommentsByAuthor(user);
967
+ }).then(function (comments) {
968
+ // If `findCommentsByAuthor` fulfills, we'll have the value here
969
+ }, function (reason) {
970
+ // If `findCommentsByAuthor` rejects, we'll have the reason here
971
+ });
972
+ ```
973
+
974
+ Simple Example
975
+ --------------
976
+
977
+ Synchronous Example
978
+
979
+ ```javascript
980
+ let result;
981
+
982
+ try {
983
+ result = findResult();
984
+ // success
985
+ } catch(reason) {
986
+ // failure
987
+ }
988
+ ```
989
+
990
+ Errback Example
991
+
992
+ ```js
993
+ findResult(function(result, err){
994
+ if (err) {
995
+ // failure
996
+ } else {
997
+ // success
998
+ }
999
+ });
1000
+ ```
1001
+
1002
+ Promise Example;
1003
+
1004
+ ```javascript
1005
+ findResult().then(function(result){
1006
+ // success
1007
+ }, function(reason){
1008
+ // failure
1009
+ });
1010
+ ```
1011
+
1012
+ Advanced Example
1013
+ --------------
1014
+
1015
+ Synchronous Example
1016
+
1017
+ ```javascript
1018
+ let author, books;
1019
+
1020
+ try {
1021
+ author = findAuthor();
1022
+ books = findBooksByAuthor(author);
1023
+ // success
1024
+ } catch(reason) {
1025
+ // failure
1026
+ }
1027
+ ```
1028
+
1029
+ Errback Example
1030
+
1031
+ ```js
1032
+
1033
+ function foundBooks(books) {
1034
+
1035
+ }
1036
+
1037
+ function failure(reason) {
1038
+
1039
+ }
1040
+
1041
+ findAuthor(function(author, err){
1042
+ if (err) {
1043
+ failure(err);
1044
+ // failure
1045
+ } else {
1046
+ try {
1047
+ findBoooksByAuthor(author, function(books, err) {
1048
+ if (err) {
1049
+ failure(err);
1050
+ } else {
1051
+ try {
1052
+ foundBooks(books);
1053
+ } catch(reason) {
1054
+ failure(reason);
1055
+ }
1056
+ }
1057
+ });
1058
+ } catch(error) {
1059
+ failure(err);
1060
+ }
1061
+ // success
1062
+ }
1063
+ });
1064
+ ```
1065
+
1066
+ Promise Example;
1067
+
1068
+ ```javascript
1069
+ findAuthor().
1070
+ then(findBooksByAuthor).
1071
+ then(function(books){
1072
+ // found books
1073
+ }).catch(function(reason){
1074
+ // something went wrong
1075
+ });
1076
+ ```
1077
+
1078
+ @method then
1079
+ @param {Function} onFulfilled
1080
+ @param {Function} onRejected
1081
+ Useful for tooling.
1082
+ @return {Promise}
1083
+ */
1084
+ then: then,
1085
+
1086
+ /**
1087
+ `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same
1088
+ as the catch block of a try/catch statement.
1089
+
1090
+ ```js
1091
+ function findAuthor(){
1092
+ throw new Error('couldn't find that author');
1093
+ }
1094
+
1095
+ // synchronous
1096
+ try {
1097
+ findAuthor();
1098
+ } catch(reason) {
1099
+ // something went wrong
1100
+ }
1101
+
1102
+ // async with promises
1103
+ findAuthor().catch(function(reason){
1104
+ // something went wrong
1105
+ });
1106
+ ```
1107
+
1108
+ @method catch
1109
+ @param {Function} onRejection
1110
+ Useful for tooling.
1111
+ @return {Promise}
1112
+ */
1113
+ 'catch': function _catch(onRejection) {
1114
+ return this.then(null, onRejection);
1115
+ }
1116
+ };
1117
+
1118
+ function polyfill() {
1119
+ var local = undefined;
1120
+
1121
+ if (typeof global !== 'undefined') {
1122
+ local = global;
1123
+ } else if (typeof self !== 'undefined') {
1124
+ local = self;
1125
+ } else {
1126
+ try {
1127
+ local = Function('return this')();
1128
+ } catch (e) {
1129
+ throw new Error('polyfill failed because global object is unavailable in this environment');
1130
+ }
1131
+ }
1132
+
1133
+ var P = local.Promise;
1134
+
1135
+ if (P) {
1136
+ var promiseToString = null;
1137
+ try {
1138
+ promiseToString = Object.prototype.toString.call(P.resolve());
1139
+ } catch (e) {
1140
+ // silently ignored
1141
+ }
1142
+
1143
+ if (promiseToString === '[object Promise]' && !P.cast) {
1144
+ return;
1145
+ }
1146
+ }
1147
+
1148
+ local.Promise = Promise;
1149
+ }
1150
+
1151
+ // Strange compat..
1152
+ Promise.polyfill = polyfill;
1153
+ Promise.Promise = Promise;
1154
+
1155
+ Promise.polyfill();
1156
+
1157
+ return Promise;
1158
+
1159
+ })));
1160
+ //# sourceMappingURL=es6-promise.auto.map
assets/js/es6-promise.auto.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.ES6Promise=e()}(this,function(){"use strict";function t(t){return"function"==typeof t||"object"==typeof t&&null!==t}function e(t){return"function"==typeof t}function n(t){I=t}function r(t){J=t}function o(){return function(){return process.nextTick(a)}}function i(){return"undefined"!=typeof H?function(){H(a)}:c()}function s(){var t=0,e=new V(a),n=document.createTextNode("");return e.observe(n,{characterData:!0}),function(){n.data=t=++t%2}}function u(){var t=new MessageChannel;return t.port1.onmessage=a,function(){return t.port2.postMessage(0)}}function c(){var t=setTimeout;return function(){return t(a,1)}}function a(){for(var t=0;t<G;t+=2){var e=$[t],n=$[t+1];e(n),$[t]=void 0,$[t+1]=void 0}G=0}function f(){try{var t=require,e=t("vertx");return H=e.runOnLoop||e.runOnContext,i()}catch(n){return c()}}function l(t,e){var n=arguments,r=this,o=new this.constructor(p);void 0===o[et]&&k(o);var i=r._state;return i?!function(){var t=n[i-1];J(function(){return x(i,o,t,r._result)})}():E(r,o,t,e),o}function h(t){var e=this;if(t&&"object"==typeof t&&t.constructor===e)return t;var n=new e(p);return g(n,t),n}function p(){}function v(){return new TypeError("You cannot resolve a promise with itself")}function d(){return new TypeError("A promises callback cannot return that same promise.")}function _(t){try{return t.then}catch(e){return it.error=e,it}}function y(t,e,n,r){try{t.call(e,n,r)}catch(o){return o}}function m(t,e,n){J(function(t){var r=!1,o=y(n,e,function(n){r||(r=!0,e!==n?g(t,n):S(t,n))},function(e){r||(r=!0,j(t,e))},"Settle: "+(t._label||" unknown promise"));!r&&o&&(r=!0,j(t,o))},t)}function b(t,e){e._state===rt?S(t,e._result):e._state===ot?j(t,e._result):E(e,void 0,function(e){return g(t,e)},function(e){return j(t,e)})}function w(t,n,r){n.constructor===t.constructor&&r===l&&n.constructor.resolve===h?b(t,n):r===it?(j(t,it.error),it.error=null):void 0===r?S(t,n):e(r)?m(t,n,r):S(t,n)}function g(e,n){e===n?j(e,v()):t(n)?w(e,n,_(n)):S(e,n)}function A(t){t._onerror&&t._onerror(t._result),T(t)}function S(t,e){t._state===nt&&(t._result=e,t._state=rt,0!==t._subscribers.length&&J(T,t))}function j(t,e){t._state===nt&&(t._state=ot,t._result=e,J(A,t))}function E(t,e,n,r){var o=t._subscribers,i=o.length;t._onerror=null,o[i]=e,o[i+rt]=n,o[i+ot]=r,0===i&&t._state&&J(T,t)}function T(t){var e=t._subscribers,n=t._state;if(0!==e.length){for(var r=void 0,o=void 0,i=t._result,s=0;s<e.length;s+=3)r=e[s],o=e[s+n],r?x(n,r,o,i):o(i);t._subscribers.length=0}}function M(){this.error=null}function P(t,e){try{return t(e)}catch(n){return st.error=n,st}}function x(t,n,r,o){var i=e(r),s=void 0,u=void 0,c=void 0,a=void 0;if(i){if(s=P(r,o),s===st?(a=!0,u=s.error,s.error=null):c=!0,n===s)return void j(n,d())}else s=o,c=!0;n._state!==nt||(i&&c?g(n,s):a?j(n,u):t===rt?S(n,s):t===ot&&j(n,s))}function C(t,e){try{e(function(e){g(t,e)},function(e){j(t,e)})}catch(n){j(t,n)}}function O(){return ut++}function k(t){t[et]=ut++,t._state=void 0,t._result=void 0,t._subscribers=[]}function Y(t,e){this._instanceConstructor=t,this.promise=new t(p),this.promise[et]||k(this.promise),B(e)?(this._input=e,this.length=e.length,this._remaining=e.length,this._result=new Array(this.length),0===this.length?S(this.promise,this._result):(this.length=this.length||0,this._enumerate(),0===this._remaining&&S(this.promise,this._result))):j(this.promise,q())}function q(){return new Error("Array Methods must be provided an Array")}function F(t){return new Y(this,t).promise}function D(t){var e=this;return new e(B(t)?function(n,r){for(var o=t.length,i=0;i<o;i++)e.resolve(t[i]).then(n,r)}:function(t,e){return e(new TypeError("You must pass an array to race."))})}function K(t){var e=this,n=new e(p);return j(n,t),n}function L(){throw new TypeError("You must pass a resolver function as the first argument to the promise constructor")}function N(){throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.")}function U(t){this[et]=O(),this._result=this._state=void 0,this._subscribers=[],p!==t&&("function"!=typeof t&&L(),this instanceof U?C(this,t):N())}function W(){var t=void 0;if("undefined"!=typeof global)t=global;else if("undefined"!=typeof self)t=self;else try{t=Function("return this")()}catch(e){throw new Error("polyfill failed because global object is unavailable in this environment")}var n=t.Promise;if(n){var r=null;try{r=Object.prototype.toString.call(n.resolve())}catch(e){}if("[object Promise]"===r&&!n.cast)return}t.Promise=U}var z=void 0;z=Array.isArray?Array.isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)};var B=z,G=0,H=void 0,I=void 0,J=function(t,e){$[G]=t,$[G+1]=e,G+=2,2===G&&(I?I(a):tt())},Q="undefined"!=typeof window?window:void 0,R=Q||{},V=R.MutationObserver||R.WebKitMutationObserver,X="undefined"==typeof self&&"undefined"!=typeof process&&"[object process]"==={}.toString.call(process),Z="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel,$=new Array(1e3),tt=void 0;tt=X?o():V?s():Z?u():void 0===Q&&"function"==typeof require?f():c();var et=Math.random().toString(36).substring(16),nt=void 0,rt=1,ot=2,it=new M,st=new M,ut=0;return Y.prototype._enumerate=function(){for(var t=this.length,e=this._input,n=0;this._state===nt&&n<t;n++)this._eachEntry(e[n],n)},Y.prototype._eachEntry=function(t,e){var n=this._instanceConstructor,r=n.resolve;if(r===h){var o=_(t);if(o===l&&t._state!==nt)this._settledAt(t._state,e,t._result);else if("function"!=typeof o)this._remaining--,this._result[e]=t;else if(n===U){var i=new n(p);w(i,t,o),this._willSettleAt(i,e)}else this._willSettleAt(new n(function(e){return e(t)}),e)}else this._willSettleAt(r(t),e)},Y.prototype._settledAt=function(t,e,n){var r=this.promise;r._state===nt&&(this._remaining--,t===ot?j(r,n):this._result[e]=n),0===this._remaining&&S(r,this._result)},Y.prototype._willSettleAt=function(t,e){var n=this;E(t,void 0,function(t){return n._settledAt(rt,e,t)},function(t){return n._settledAt(ot,e,t)})},U.all=F,U.race=D,U.resolve=h,U.reject=K,U._setScheduler=n,U._setAsap=r,U._asap=J,U.prototype={constructor:U,then:l,"catch":function(t){return this.then(null,t)}},U.polyfill=W,U.Promise=U,U.polyfill(),U});
assets/js/imagify.js CHANGED
File without changes
assets/js/imagify.min.js CHANGED
File without changes
assets/js/jquery.twentytwenty.js CHANGED
@@ -236,11 +236,13 @@ window.imagify = window.imagify || {
236
 
237
  settings.modalAppendTo.append( modalHtml );
238
 
239
- settings.trigger.on( 'click.imagify', function() {
240
  var $modal = $( $( this ).data( 'target' ) ),
241
  imgsLoaded = 0,
242
  $tt, checkLoad;
243
 
 
 
244
  if ( typeof imagifyOpenModal === 'function' && settings.openModal ) {
245
  imagifyOpenModal( $( this ) );
246
  }
@@ -323,8 +325,6 @@ window.imagify = window.imagify || {
323
  checkLoad = null;
324
  return 'done';
325
  }, 75 );
326
-
327
- return false;
328
  } );
329
  }; // imagifyTwentyModal( options );
330
 
@@ -461,6 +461,7 @@ window.imagify = window.imagify || {
461
  clipStyles;
462
 
463
  e.stopPropagation();
 
464
 
465
  // Button coloration.
466
  $duo.removeClass( 'selected' );
@@ -492,7 +493,6 @@ window.imagify = window.imagify || {
492
  }
493
 
494
  drawMeAChart( $( '.imagify-level-' + image ).find( '.imagify-chart' ).find( 'canvas' ) );
495
- return false;
496
  } );
497
  } );
498
 
236
 
237
  settings.modalAppendTo.append( modalHtml );
238
 
239
+ settings.trigger.on( 'click.imagify', function( e ) {
240
  var $modal = $( $( this ).data( 'target' ) ),
241
  imgsLoaded = 0,
242
  $tt, checkLoad;
243
 
244
+ e.preventDefault();
245
+
246
  if ( typeof imagifyOpenModal === 'function' && settings.openModal ) {
247
  imagifyOpenModal( $( this ) );
248
  }
325
  checkLoad = null;
326
  return 'done';
327
  }, 75 );
 
 
328
  } );
329
  }; // imagifyTwentyModal( options );
330
 
461
  clipStyles;
462
 
463
  e.stopPropagation();
464
+ e.preventDefault();
465
 
466
  // Button coloration.
467
  $duo.removeClass( 'selected' );
493
  }
494
 
495
  drawMeAChart( $( '.imagify-level-' + image ).find( '.imagify-chart' ).find( 'canvas' ) );
 
496
  } );
497
  } );
498
 
assets/js/jquery.twentytwenty.min.js CHANGED
@@ -1 +1 @@
1
- window.imagify=window.imagify||{concat:ajaxurl.indexOf("?")>0?"&":"?",log:function(a){void 0!==console&&console.log(a)},info:function(a){void 0!==console&&console.info(a)}},function(a,b,c,d){a.fn.twentytwenty=function(b,c){return b=a.extend({handlePosition:.5,orientation:"horizontal",labelBefore:"Before",labelAfter:"After"},b),this.each(function(){var d=b.handlePosition,e=a(this),f=b.orientation,g="vertical"===f?"down":"left",h="vertical"===f?"up":"right",i=e.find("img:first"),j=e.find("img:last");e.wrap('<div class="twentytwenty-wrapper twentytwenty-'+f+'"></div>'),e.append('<div class="twentytwenty-overlay"></div>'),e.append('<div class="twentytwenty-handle"></div>');var k=e.find(".twentytwenty-handle");k.append('<span class="twentytwenty-'+g+'-arrow"></span>'),k.append('<span class="twentytwenty-'+h+'-arrow"></span>'),e.addClass("twentytwenty-container"),i.addClass("twentytwenty-before"),j.addClass("twentytwenty-after");var l=e.find(".twentytwenty-overlay");l.append('<div class="twentytwenty-labels twentytwenty-before-label"><span class="twentytwenty-label-content">'+b.labelBefore+"</span></div>"),l.append('<div class="twentytwenty-labels twentytwenty-after-label"><span class="twentytwenty-label-content">'+b.labelAfter+"</span></div>");var m=function(a){var b=i.width(),c=i.height();return{w:b+"px",h:c+"px",cw:a*b+"px",ch:a*c+"px"}},n=function(a){var b=e.find(".twentytwenty-before");"vertical"===f?b.css("clip","rect(0,"+a.w+","+a.ch+",0)"):b.css("clip","rect(0,"+a.cw+","+a.h+",0)"),e.css("height",a.h),"function"==typeof c&&c()},o=function(a){var b=m(a);k.css("vertical"===f?"top":"left","vertical"===f?b.ch:b.cw),n(b)},p=0,q=0,r=0,s=0;a(window).on("resize.twentytwenty",function(){o(d)}),k.on("movestart",function(a){(a.distX>a.distY&&a.distX<-a.distY||a.distX<a.distY&&a.distX>-a.distY)&&"vertical"!==f?a.preventDefault():(a.distX<a.distY&&a.distX<-a.distY||a.distX>a.distY&&a.distX>-a.distY)&&"vertical"===f&&a.preventDefault(),e.addClass("active"),p=e.offset().left,q=e.offset().top,r=i.width(),s=i.height()}),k.on("moveend",function(){e.removeClass("active")}),k.on("move",function(a){e.hasClass("active")&&(d="vertical"===f?(a.pageY-q)/s:(a.pageX-p)/r,d<0&&(d=0),d>1&&(d=1),o(d))}),e.find("img").on("mousedown",function(a){a.preventDefault()}),a(window).trigger("resize.twentytwenty")})}}(jQuery,document,window),function(a,b,c,d){var e=function(b){b.each(function(){var b=a(this),c=parseInt(b.closest(".imagify-chart").next(".imagify-chart-value").text()),d=[{value:c,color:"#00B3D3"},{value:100-c,color:"#D8D8D8"}];new Chart(b[0].getContext("2d")).Doughnut(d,{segmentStrokeColor:"#2A2E3C",segmentStrokeWidth:1,animateRotate:!0,percentageInnerCutout:60,tooltipEvents:[]})})},f=function(b){var c=b.data("target")||b.attr("href");a(c).css("display","flex").hide().fadeIn(400).attr("aria-hidden","false").attr("tabindex","0").focus().removeAttr("tabindex").addClass("modal-is-open"),a("body").addClass("imagify-modal-is-open")},g=function(b){var d,g={width:0,height:0,originalUrl:"",optimizedUrl:"",originalSize:0,optimizedSize:0,saving:0,modalAppendTo:a("body"),trigger:a('[data-target="imagify-visual-comparison"]'),modalId:"imagify-visual-comparison",openModal:!1},h=a.extend({},g,b);if(0===h.width||0===h.height||""===h.originalUrl||""===h.optimizedUrl||0===h.originalSize||0===h.optimizedSize||0===h.saving)return"error";d='<div id="'+h.modalId+'" class="imagify-modal imagify-visual-comparison" aria-hidden="true">',d+='<div class="imagify-modal-content loading">',d+='<div class="twentytwenty-container">',d+='<img class="imagify-img-before" alt="" width="'+h.width+'" height="'+h.height+'">',d+='<img class="imagify-img-after" alt="" width="'+h.width+'" height="'+h.height+'">',d+="</div>",d+='<div class="imagify-comparison-levels">',d+='<div class="imagify-c-level imagify-level-original go-left">',d+='<p class="imagify-c-level-row">',d+='<span class="label">'+imagifyTTT.labels.filesize+"</span>",d+='<span class="value level">'+h.originalSize+"</span>",d+="</p>",d+="</div>",d+='<div class="imagify-c-level imagify-level-optimized go-right">',d+='<p class="imagify-c-level-row">',d+='<span class="label">'+imagifyTTT.labels.filesize+"</span>",d+='<span class="value level">'+h.optimizedSize+"</span>",d+="</p>",d+='<p class="imagify-c-level-row">',d+='<span class="label">'+imagifyTTT.labels.saving+"</span>",d+='<span class="value"><span class="imagify-chart"><span class="imagify-chart-container"><canvas id="imagify-consumption-chart-normal" width="15" height="15"></canvas></span></span><span class="imagify-chart-value">'+h.saving+"</span>%</span>",d+="</p>",d+="</div>",d+="</div>",d+='<button class="close-btn absolute" type="button"><i aria-hidden="true" class="dashicons dashicons-no-alt"></i><span class="screen-reader-text">'+imagifyTTT.labels.close+"</span></button>",d+="</div>",d+="</div>",h.modalAppendTo.append(d),h.trigger.on("click.imagify",function(){var b,d,g=a(a(this).data("target")),i=0;return"function"==typeof f&&h.openModal&&f(a(this)),g.find(".imagify-modal-content").css({width:.85*a(c).outerWidth()+"px","max-width":h.width}),g.find(".imagify-img-before").on("load",function(){i++}).attr("src",h.originalUrl),g.find(".imagify-img-after").on("load",function(){i++}).attr("src",h.optimizedUrl),b=g.find(".twentytwenty-container"),d=setInterval(function(){if(2===i)return b.twentytwenty({handlePosition:.3,orientation:"horizontal",labelBefore:imagifyTTT.labels.original_l,labelAfter:imagifyTTT.labels.optimized_l},function(){var d,f,h,i,j,k,l=a(c).height(),m=g.find(".twentytwenty-container").height(),n=g.find(".twentytwenty-wrapper").position().top;b.closest(".imagify-modal-content").hasClass("loaded")||(b.closest(".imagify-modal-content").removeClass("loading").addClass("loaded"),e(g.find(".imagify-level-optimized").find(".imagify-chart").find("canvas"))),l<m&&!g.hasClass("modal-is-too-high")&&(g.addClass("modal-is-too-high"),d=g.find(".twentytwenty-handle"),f=g.find(".twentytwenty-label-content"),h=g.find(".imagify-comparison-levels"),i=h.outerHeight(),j=(l-n-d.height())/2,k=l-3*n-i,d.css({top:j}),f.css({top:k,bottom:"auto"}),g.find(".twentytwenty-wrapper").css({paddingBottom:i}),g.find(".imagify-modal-content").on("scroll.imagify",function(){var b=a(this).scrollTop();d.css({top:j+b}),f.css({top:k+b}),h.css({bottom:-b})}))}),clearInterval(d),d=null,"done"},75),!1})};if(a(".imagify-visual-comparison-btn").on("click",function(){var b,d,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B;1!==a(".twentytwenty-wrapper").length&&(a(a(this).data("target")).find(".imagify-modal-content").css("width",.95*a(c).outerWidth()+"px"),a(".twentytwenty-container").length>0&&a(c).outerWidth()<=800||(b=a(".twentytwenty-container"),d=0,f=b.data("loader"),g=b.data("label-original"),h=b.data("label-normal"),i=b.data("label-aggressive"),j=b.data("label-ultra"),k=b.data("original-label").replace(/\*\*/,"<strong>").replace(/\*\*/,"</strong>"),l=b.data("original-alt"),m=b.data("original-img"),n=b.data("original-dim").split("x"),o=b.data("normal-alt"),p=b.data("normal-img"),q=b.data("normal-dim").split("x"),r=b.data("aggressive-alt"),s=b.data("aggressive-img"),t=b.data("aggressive-dim").split("x"),u=b.data("ultra-label").replace(/\*\*/,"<strong>").replace(/\*\*/,"</strong>"),v=b.data("ultra-alt"),w=b.data("ultra-img"),x=b.data("ultra-dim").split("x"),y='<span class="twentytwenty-duo-buttons twentytwenty-duo-left">',y+='<button type="button" class="imagify-comparison-original selected" data-img="original">'+g+"</button>",y+='<button type="button" class="imagify-comparison-normal" data-img="normal">'+h+"</button>",y+='<button type="button" class="imagify-comparison-aggressive" data-img="aggressive">'+i+"</button>",y+="</span>",z='<span class="twentytwenty-duo-buttons twentytwenty-duo-right">',z+='<button type="button" class="imagify-comparison-normal" data-img="normal">'+h+"</button>",z+='<button type="button" class="imagify-comparison-aggressive" data-img="aggressive">'+i+"</button>",z+='<button type="button" class="imagify-comparison-ultra selected" data-img="ultra">'+j+"</button>",z+="</span>",b.before('<img class="loader" src="'+f+'" alt="Loading…" width="64" height="64">'),a(".twentytwenty-left-buttons").append(y),a(".twentytwenty-right-buttons").append(z),A='<img class="img-original" alt="'+l+'" width="'+n[0]+'" height="'+n[1]+'">',A+='<img class="img-normal" alt="'+o+'" width="'+q[0]+'" height="'+q[1]+'">',A+='<img class="img-aggressive" alt="'+r+'" width="'+t[0]+'" height="'+t[1]+'">',A+='<img class="img-ultra" alt="'+v+'" width="'+x[0]+'" height="'+x[1]+'">',A+=a(".twentytwenty-left-buttons").lenght?y+z:"",b.closest(".imagify-modal-content").addClass("loading").find(".twentytwenty-container").append(A),a(".img-original").on("load",function(){d++}).attr("src",m),a(".img-normal").on("load",function(){d++}).attr("src",p),a(".img-aggressive").on("load",function(){d++}).attr("src",s),a(".img-ultra").on("load",function(){d++}).attr("src",w),B=setInterval(function(){4===d&&(b.twentytwenty({handlePosition:.6,orientation:"horizontal",labelBefore:k,labelAfter:u},function(){b.closest(".imagify-modal-content").hasClass("loaded")||(b.closest(".imagify-modal-content").removeClass("loading").addClass("loaded"),e(a(".imagify-level-ultra").find(".imagify-chart").find("canvas")))}),clearInterval(B),B=null)},75),a(".imagify-comparison-title").on("click",".twentytwenty-duo-buttons button:not(.selected)",function(b){var c,d=a(this),f=d.closest(".imagify-comparison-title").nextAll(".twentytwenty-wrapper").find(".twentytwenty-container"),g=d.closest(".twentytwenty-duo-buttons").hasClass("twentytwenty-duo-left")?"left":"right",h="left"===g?d.closest(".imagify-comparison-title").find(".twentytwenty-duo-right"):d.closest(".imagify-comparison-title").find(".twentytwenty-duo-left"),i=d.closest(".twentytwenty-duo-buttons").find("button"),j=f.find(".twentytwenty-before"),k=f.find(".twentytwenty-after"),l=d.data("img");return b.stopPropagation(),i.removeClass("selected"),d.addClass("selected"),h.find(".selected").data("img")===l&&h.find("button:not(.selected)").eq(0).trigger("click"),"left"===g&&(c=j.css("clip"),j.attr("style",""),j.removeClass("twentytwenty-before"),f.find(".img-"+l).addClass("twentytwenty-before").css("clip",c),a(".twentytwenty-before-label").find(".twentytwenty-label-content").text(f.data(l+"-label")),a(".imagify-c-level.go-left").attr("aria-hidden","true").removeClass("go-left go-right"),a(".imagify-level-"+l).attr("aria-hidden","false").addClass("go-left")),"right"===g&&(k.removeClass("twentytwenty-after"),f.find(".img-"+l).addClass("twentytwenty-after"),a(".twentytwenty-after-label").find(".twentytwenty-label-content").text(f.data(l+"-label")),a(".imagify-c-level.go-right").attr("aria-hidden","true").removeClass("go-left go-right"),a(".imagify-level-"+l).attr("aria-hidden","false").addClass("go-right")),e(a(".imagify-level-"+l).find(".imagify-chart").find("canvas")),!1})))}),a(".post-php").find(".wp_attachment_image").find(".thumbnail").length>0){var h,i,j=a(".post-php").find(".wp_attachment_image"),k=j.find(".thumbnail"),l={src:k.prop("src"),width:k.width(),height:k.height()},m={src:a("#imagify-full-original").val(),size:a("#imagify-full-original-size").val()},n=a("#misc-publishing-actions").find(".misc-pub-imagify").find(".button-primary");l.width>360&&a("#imagify-full-original").length>0&&""!==a("#imagify-full-original").val()?(h=a(".misc-pub-filesize").find("strong").text(),i=a(".imagify-data-item").find(".imagify-chart-value").text(),a('[id^="imgedit-open-btn-"]').before('<button type="button" class="imagify-button-primary button-primary imagify-modal-trigger" data-target="#imagify-visual-comparison" id="imagify-start-comparison">'+imagifyTTT.labels.compare+"</button>"),g({width:l.width,height:l.height,originalUrl:m.src,optimizedUrl:l.src,originalSize:m.size,optimizedSize:h,saving:i,modalAppendTo:j,trigger:a("#imagify-start-comparison"),modalId:"imagify-visual-comparison"})):l.width<360&&a("#imagify-full-original").length>0&&""!==a("#imagify-full-original").val()||a("#imagify-full-original").length>0&&""===a("#imagify-full-original").val()||1===a("#misc-publishing-actions").find(".misc-pub-imagify").find(".button-primary").length&&(a('[id^="imgedit-open-btn-"]').before('<span class="spinner imagify-hidden"></span><a class="imagify-button-primary button-primary imagify-optimize-trigger" id="imagify-optimize-trigger" href="'+n.attr("href")+'">'+imagifyTTT.labels.optimize+"</a>"),a("#imagify-optimize-trigger").on("click",function(){a(this).prev(".spinner").removeClass("imagify-hidden").addClass("is-active")}))}if(a(".upload-php").find(".imagify-compare-images").length>0&&a(".imagify-compare-images").each(function(){var b=a(this),c=b.data("id"),d=b.closest("#post-"+c).find(".column-imagify_optimized_file");g({width:b.data("full-width"),height:b.data("full-height"),originalUrl:b.data("backup-src"),optimizedUrl:b.data("full-src"),originalSize:d.find(".original").text(),optimizedSize:d.find(".imagify-data-item").find(".big").text(),saving:d.find(".imagify-chart-value").text(),modalAppendTo:b.closest(".column-primary"),trigger:b,modalId:"imagify-comparison-"+c})}),a(".upload-php").length>0)var o=function(a){var b={};return c.location.href.replace(/[?&]+([^=&]+)=?([^&]*)?/gi,function(a,c,d){b[c]=void 0!==d?d:""}),a?b[a]?b[a]:null:b},p=function(){var b=setInterval(function(){var c;a(".media-modal").find(".imagify-datas-details").length&&(a("#imagify-original-src").length>0&&""!==a("#imagify-original-src")&&(a(".media-frame-content").find(".attachment-actions").prepend('<button type="button" class="imagify-button-primary button-primary imagify-modal-trigger" data-target="#imagify-comparison-modal" id="imagify-media-frame-comparison-btn">'+imagifyTTT.labels.compare+"</button>"),c=a(".media-frame-content").find(".compat-field-imagify"),g({width:a("#imagify-full-width").val(),height:a("#imagify-full-height").val(),originalUrl:a("#imagify-original-src").val(),optimizedUrl:a("#imagify-full-src").val(),originalSize:a("#imagify-original-size").val(),optimizedSize:c.find(".imagify-data-item").find(".big").text(),saving:c.find(".imagify-chart-value").text(),modalAppendTo:a(".media-frame-content").find(".thumbnail-image"),trigger:a("#imagify-media-frame-comparison-btn"),modalId:"imagify-comparison-modal",openModal:!0})),clearInterval(b),b=null)},20)},q=setInterval(function(){a(".upload-php").find(".media-frame.mode-grid").find(".attachments").length&&(a(".upload-php").find(".media-frame.mode-grid").on("click",".attachment",function(){p()}),o("item")&&p(),clearInterval(q),q=null)},100)}(jQuery,document,window);
1
+ window.imagify=window.imagify||{concat:ajaxurl.indexOf("?")>0?"&":"?",log:function(a){void 0!==console&&console.log(a)},info:function(a){void 0!==console&&console.info(a)}},function(a,b,c,d){a.fn.twentytwenty=function(b,c){return b=a.extend({handlePosition:.5,orientation:"horizontal",labelBefore:"Before",labelAfter:"After"},b),this.each(function(){var d=b.handlePosition,e=a(this),f=b.orientation,g="vertical"===f?"down":"left",h="vertical"===f?"up":"right",i=e.find("img:first"),j=e.find("img:last");e.wrap('<div class="twentytwenty-wrapper twentytwenty-'+f+'"></div>'),e.append('<div class="twentytwenty-overlay"></div>'),e.append('<div class="twentytwenty-handle"></div>');var k=e.find(".twentytwenty-handle");k.append('<span class="twentytwenty-'+g+'-arrow"></span>'),k.append('<span class="twentytwenty-'+h+'-arrow"></span>'),e.addClass("twentytwenty-container"),i.addClass("twentytwenty-before"),j.addClass("twentytwenty-after");var l=e.find(".twentytwenty-overlay");l.append('<div class="twentytwenty-labels twentytwenty-before-label"><span class="twentytwenty-label-content">'+b.labelBefore+"</span></div>"),l.append('<div class="twentytwenty-labels twentytwenty-after-label"><span class="twentytwenty-label-content">'+b.labelAfter+"</span></div>");var m=function(a){var b=i.width(),c=i.height();return{w:b+"px",h:c+"px",cw:a*b+"px",ch:a*c+"px"}},n=function(a){var b=e.find(".twentytwenty-before");"vertical"===f?b.css("clip","rect(0,"+a.w+","+a.ch+",0)"):b.css("clip","rect(0,"+a.cw+","+a.h+",0)"),e.css("height",a.h),"function"==typeof c&&c()},o=function(a){var b=m(a);k.css("vertical"===f?"top":"left","vertical"===f?b.ch:b.cw),n(b)},p=0,q=0,r=0,s=0;a(window).on("resize.twentytwenty",function(){o(d)}),k.on("movestart",function(a){(a.distX>a.distY&&a.distX<-a.distY||a.distX<a.distY&&a.distX>-a.distY)&&"vertical"!==f?a.preventDefault():(a.distX<a.distY&&a.distX<-a.distY||a.distX>a.distY&&a.distX>-a.distY)&&"vertical"===f&&a.preventDefault(),e.addClass("active"),p=e.offset().left,q=e.offset().top,r=i.width(),s=i.height()}),k.on("moveend",function(){e.removeClass("active")}),k.on("move",function(a){e.hasClass("active")&&(d="vertical"===f?(a.pageY-q)/s:(a.pageX-p)/r,d<0&&(d=0),d>1&&(d=1),o(d))}),e.find("img").on("mousedown",function(a){a.preventDefault()}),a(window).trigger("resize.twentytwenty")})}}(jQuery,document,window),function(a,b,c,d){var e=function(b){b.each(function(){var b=a(this),c=parseInt(b.closest(".imagify-chart").next(".imagify-chart-value").text()),d=[{value:c,color:"#00B3D3"},{value:100-c,color:"#D8D8D8"}];new Chart(b[0].getContext("2d")).Doughnut(d,{segmentStrokeColor:"#2A2E3C",segmentStrokeWidth:1,animateRotate:!0,percentageInnerCutout:60,tooltipEvents:[]})})},f=function(b){var c=b.data("target")||b.attr("href");a(c).css("display","flex").hide().fadeIn(400).attr("aria-hidden","false").attr("tabindex","0").focus().removeAttr("tabindex").addClass("modal-is-open"),a("body").addClass("imagify-modal-is-open")},g=function(b){var d,g={width:0,height:0,originalUrl:"",optimizedUrl:"",originalSize:0,optimizedSize:0,saving:0,modalAppendTo:a("body"),trigger:a('[data-target="imagify-visual-comparison"]'),modalId:"imagify-visual-comparison",openModal:!1},h=a.extend({},g,b);if(0===h.width||0===h.height||""===h.originalUrl||""===h.optimizedUrl||0===h.originalSize||0===h.optimizedSize||0===h.saving)return"error";d='<div id="'+h.modalId+'" class="imagify-modal imagify-visual-comparison" aria-hidden="true">',d+='<div class="imagify-modal-content loading">',d+='<div class="twentytwenty-container">',d+='<img class="imagify-img-before" alt="" width="'+h.width+'" height="'+h.height+'">',d+='<img class="imagify-img-after" alt="" width="'+h.width+'" height="'+h.height+'">',d+="</div>",d+='<div class="imagify-comparison-levels">',d+='<div class="imagify-c-level imagify-level-original go-left">',d+='<p class="imagify-c-level-row">',d+='<span class="label">'+imagifyTTT.labels.filesize+"</span>",d+='<span class="value level">'+h.originalSize+"</span>",d+="</p>",d+="</div>",d+='<div class="imagify-c-level imagify-level-optimized go-right">',d+='<p class="imagify-c-level-row">',d+='<span class="label">'+imagifyTTT.labels.filesize+"</span>",d+='<span class="value level">'+h.optimizedSize+"</span>",d+="</p>",d+='<p class="imagify-c-level-row">',d+='<span class="label">'+imagifyTTT.labels.saving+"</span>",d+='<span class="value"><span class="imagify-chart"><span class="imagify-chart-container"><canvas id="imagify-consumption-chart-normal" width="15" height="15"></canvas></span></span><span class="imagify-chart-value">'+h.saving+"</span>%</span>",d+="</p>",d+="</div>",d+="</div>",d+='<button class="close-btn absolute" type="button"><i aria-hidden="true" class="dashicons dashicons-no-alt"></i><span class="screen-reader-text">'+imagifyTTT.labels.close+"</span></button>",d+="</div>",d+="</div>",h.modalAppendTo.append(d),h.trigger.on("click.imagify",function(b){var d,g,i=a(a(this).data("target")),j=0;b.preventDefault(),"function"==typeof f&&h.openModal&&f(a(this)),i.find(".imagify-modal-content").css({width:.85*a(c).outerWidth()+"px","max-width":h.width}),i.find(".imagify-img-before").on("load",function(){j++}).attr("src",h.originalUrl),i.find(".imagify-img-after").on("load",function(){j++}).attr("src",h.optimizedUrl),d=i.find(".twentytwenty-container"),g=setInterval(function(){if(2===j)return d.twentytwenty({handlePosition:.3,orientation:"horizontal",labelBefore:imagifyTTT.labels.original_l,labelAfter:imagifyTTT.labels.optimized_l},function(){var b,f,g,h,j,k,l=a(c).height(),m=i.find(".twentytwenty-container").height(),n=i.find(".twentytwenty-wrapper").position().top;d.closest(".imagify-modal-content").hasClass("loaded")||(d.closest(".imagify-modal-content").removeClass("loading").addClass("loaded"),e(i.find(".imagify-level-optimized").find(".imagify-chart").find("canvas"))),l<m&&!i.hasClass("modal-is-too-high")&&(i.addClass("modal-is-too-high"),b=i.find(".twentytwenty-handle"),f=i.find(".twentytwenty-label-content"),g=i.find(".imagify-comparison-levels"),h=g.outerHeight(),j=(l-n-b.height())/2,k=l-3*n-h,b.css({top:j}),f.css({top:k,bottom:"auto"}),i.find(".twentytwenty-wrapper").css({paddingBottom:h}),i.find(".imagify-modal-content").on("scroll.imagify",function(){var c=a(this).scrollTop();b.css({top:j+c}),f.css({top:k+c}),g.css({bottom:-c})}))}),clearInterval(g),g=null,"done"},75)})};if(a(".imagify-visual-comparison-btn").on("click",function(){var b,d,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B;1!==a(".twentytwenty-wrapper").length&&(a(a(this).data("target")).find(".imagify-modal-content").css("width",.95*a(c).outerWidth()+"px"),a(".twentytwenty-container").length>0&&a(c).outerWidth()<=800||(b=a(".twentytwenty-container"),d=0,f=b.data("loader"),g=b.data("label-original"),h=b.data("label-normal"),i=b.data("label-aggressive"),j=b.data("label-ultra"),k=b.data("original-label").replace(/\*\*/,"<strong>").replace(/\*\*/,"</strong>"),l=b.data("original-alt"),m=b.data("original-img"),n=b.data("original-dim").split("x"),o=b.data("normal-alt"),p=b.data("normal-img"),q=b.data("normal-dim").split("x"),r=b.data("aggressive-alt"),s=b.data("aggressive-img"),t=b.data("aggressive-dim").split("x"),u=b.data("ultra-label").replace(/\*\*/,"<strong>").replace(/\*\*/,"</strong>"),v=b.data("ultra-alt"),w=b.data("ultra-img"),x=b.data("ultra-dim").split("x"),y='<span class="twentytwenty-duo-buttons twentytwenty-duo-left">',y+='<button type="button" class="imagify-comparison-original selected" data-img="original">'+g+"</button>",y+='<button type="button" class="imagify-comparison-normal" data-img="normal">'+h+"</button>",y+='<button type="button" class="imagify-comparison-aggressive" data-img="aggressive">'+i+"</button>",y+="</span>",z='<span class="twentytwenty-duo-buttons twentytwenty-duo-right">',z+='<button type="button" class="imagify-comparison-normal" data-img="normal">'+h+"</button>",z+='<button type="button" class="imagify-comparison-aggressive" data-img="aggressive">'+i+"</button>",z+='<button type="button" class="imagify-comparison-ultra selected" data-img="ultra">'+j+"</button>",z+="</span>",b.before('<img class="loader" src="'+f+'" alt="Loading…" width="64" height="64">'),a(".twentytwenty-left-buttons").append(y),a(".twentytwenty-right-buttons").append(z),A='<img class="img-original" alt="'+l+'" width="'+n[0]+'" height="'+n[1]+'">',A+='<img class="img-normal" alt="'+o+'" width="'+q[0]+'" height="'+q[1]+'">',A+='<img class="img-aggressive" alt="'+r+'" width="'+t[0]+'" height="'+t[1]+'">',A+='<img class="img-ultra" alt="'+v+'" width="'+x[0]+'" height="'+x[1]+'">',A+=a(".twentytwenty-left-buttons").lenght?y+z:"",b.closest(".imagify-modal-content").addClass("loading").find(".twentytwenty-container").append(A),a(".img-original").on("load",function(){d++}).attr("src",m),a(".img-normal").on("load",function(){d++}).attr("src",p),a(".img-aggressive").on("load",function(){d++}).attr("src",s),a(".img-ultra").on("load",function(){d++}).attr("src",w),B=setInterval(function(){4===d&&(b.twentytwenty({handlePosition:.6,orientation:"horizontal",labelBefore:k,labelAfter:u},function(){b.closest(".imagify-modal-content").hasClass("loaded")||(b.closest(".imagify-modal-content").removeClass("loading").addClass("loaded"),e(a(".imagify-level-ultra").find(".imagify-chart").find("canvas")))}),clearInterval(B),B=null)},75),a(".imagify-comparison-title").on("click",".twentytwenty-duo-buttons button:not(.selected)",function(b){var c,d=a(this),f=d.closest(".imagify-comparison-title").nextAll(".twentytwenty-wrapper").find(".twentytwenty-container"),g=d.closest(".twentytwenty-duo-buttons").hasClass("twentytwenty-duo-left")?"left":"right",h="left"===g?d.closest(".imagify-comparison-title").find(".twentytwenty-duo-right"):d.closest(".imagify-comparison-title").find(".twentytwenty-duo-left"),i=d.closest(".twentytwenty-duo-buttons").find("button"),j=f.find(".twentytwenty-before"),k=f.find(".twentytwenty-after"),l=d.data("img");b.stopPropagation(),b.preventDefault(),i.removeClass("selected"),d.addClass("selected"),h.find(".selected").data("img")===l&&h.find("button:not(.selected)").eq(0).trigger("click"),"left"===g&&(c=j.css("clip"),j.attr("style",""),j.removeClass("twentytwenty-before"),f.find(".img-"+l).addClass("twentytwenty-before").css("clip",c),a(".twentytwenty-before-label").find(".twentytwenty-label-content").text(f.data(l+"-label")),a(".imagify-c-level.go-left").attr("aria-hidden","true").removeClass("go-left go-right"),a(".imagify-level-"+l).attr("aria-hidden","false").addClass("go-left")),"right"===g&&(k.removeClass("twentytwenty-after"),f.find(".img-"+l).addClass("twentytwenty-after"),a(".twentytwenty-after-label").find(".twentytwenty-label-content").text(f.data(l+"-label")),a(".imagify-c-level.go-right").attr("aria-hidden","true").removeClass("go-left go-right"),a(".imagify-level-"+l).attr("aria-hidden","false").addClass("go-right")),e(a(".imagify-level-"+l).find(".imagify-chart").find("canvas"))})))}),a(".post-php").find(".wp_attachment_image").find(".thumbnail").length>0){var h,i,j=a(".post-php").find(".wp_attachment_image"),k=j.find(".thumbnail"),l={src:k.prop("src"),width:k.width(),height:k.height()},m={src:a("#imagify-full-original").val(),size:a("#imagify-full-original-size").val()},n=a("#misc-publishing-actions").find(".misc-pub-imagify").find(".button-primary");l.width>360&&a("#imagify-full-original").length>0&&""!==a("#imagify-full-original").val()?(h=a(".misc-pub-filesize").find("strong").text(),i=a(".imagify-data-item").find(".imagify-chart-value").text(),a('[id^="imgedit-open-btn-"]').before('<button type="button" class="imagify-button-primary button-primary imagify-modal-trigger" data-target="#imagify-visual-comparison" id="imagify-start-comparison">'+imagifyTTT.labels.compare+"</button>"),g({width:l.width,height:l.height,originalUrl:m.src,optimizedUrl:l.src,originalSize:m.size,optimizedSize:h,saving:i,modalAppendTo:j,trigger:a("#imagify-start-comparison"),modalId:"imagify-visual-comparison"})):l.width<360&&a("#imagify-full-original").length>0&&""!==a("#imagify-full-original").val()||a("#imagify-full-original").length>0&&""===a("#imagify-full-original").val()||1===a("#misc-publishing-actions").find(".misc-pub-imagify").find(".button-primary").length&&(a('[id^="imgedit-open-btn-"]').before('<span class="spinner imagify-hidden"></span><a class="imagify-button-primary button-primary imagify-optimize-trigger" id="imagify-optimize-trigger" href="'+n.attr("href")+'">'+imagifyTTT.labels.optimize+"</a>"),a("#imagify-optimize-trigger").on("click",function(){a(this).prev(".spinner").removeClass("imagify-hidden").addClass("is-active")}))}if(a(".upload-php").find(".imagify-compare-images").length>0&&a(".imagify-compare-images").each(function(){var b=a(this),c=b.data("id"),d=b.closest("#post-"+c).find(".column-imagify_optimized_file");g({width:b.data("full-width"),height:b.data("full-height"),originalUrl:b.data("backup-src"),optimizedUrl:b.data("full-src"),originalSize:d.find(".original").text(),optimizedSize:d.find(".imagify-data-item").find(".big").text(),saving:d.find(".imagify-chart-value").text(),modalAppendTo:b.closest(".column-primary"),trigger:b,modalId:"imagify-comparison-"+c})}),a(".upload-php").length>0)var o=function(a){var b={};return c.location.href.replace(/[?&]+([^=&]+)=?([^&]*)?/gi,function(a,c,d){b[c]=void 0!==d?d:""}),a?b[a]?b[a]:null:b},p=function(){var b=setInterval(function(){var c;a(".media-modal").find(".imagify-datas-details").length&&(a("#imagify-original-src").length>0&&""!==a("#imagify-original-src")&&(a(".media-frame-content").find(".attachment-actions").prepend('<button type="button" class="imagify-button-primary button-primary imagify-modal-trigger" data-target="#imagify-comparison-modal" id="imagify-media-frame-comparison-btn">'+imagifyTTT.labels.compare+"</button>"),c=a(".media-frame-content").find(".compat-field-imagify"),g({width:a("#imagify-full-width").val(),height:a("#imagify-full-height").val(),originalUrl:a("#imagify-original-src").val(),optimizedUrl:a("#imagify-full-src").val(),originalSize:a("#imagify-original-size").val(),optimizedSize:c.find(".imagify-data-item").find(".big").text(),saving:c.find(".imagify-chart-value").text(),modalAppendTo:a(".media-frame-content").find(".thumbnail-image"),trigger:a("#imagify-media-frame-comparison-btn"),modalId:"imagify-comparison-modal",openModal:!0})),clearInterval(b),b=null)},20)},q=setInterval(function(){a(".upload-php").find(".media-frame.mode-grid").find(".attachments").length&&(a(".upload-php").find(".media-frame.mode-grid").on("click",".attachment",function(){p()}),o("item")&&p(),clearInterval(q),q=null)},100)}(jQuery,document,window);
assets/js/sweetalert2.js CHANGED
File without changes
assets/js/sweetalert2.min.js CHANGED
File without changes
assets/js/upload.js CHANGED
@@ -112,9 +112,11 @@ window.imagify = window.imagify || {
112
  */
113
  $( '.imagify-datas-details' ).hide();
114
 
115
- $( d ).on( 'click', '.imagify-datas-more-action a', function() {
116
  var $this = $( this );
117
 
 
 
118
  if ( $this.hasClass( 'is-open' ) ) {
119
  $( $this.attr( 'href' ) ).slideUp( 300 ).removeClass( 'is-open' );
120
  $this.removeClass( 'is-open' ).find( '.the-text' ).text( $this.data( 'open' ) );
@@ -122,7 +124,6 @@ window.imagify = window.imagify || {
122
  $( $this.attr( 'href' ) ).slideDown( 300 ).addClass( 'is-open' );
123
  $this.addClass( 'is-open' ).find( '.the-text' ).text( $this.data( 'close' ) );
124
  }
125
- return false;
126
  } );
127
 
128
  /**
112
  */
113
  $( '.imagify-datas-details' ).hide();
114
 
115
+ $( d ).on( 'click', '.imagify-datas-more-action a', function( e ) {
116
  var $this = $( this );
117
 
118
+ e.preventDefault();
119
+
120
  if ( $this.hasClass( 'is-open' ) ) {
121
  $( $this.attr( 'href' ) ).slideUp( 300 ).removeClass( 'is-open' );
122
  $this.removeClass( 'is-open' ).find( '.the-text' ).text( $this.data( 'open' ) );
124
  $( $this.attr( 'href' ) ).slideDown( 300 ).addClass( 'is-open' );
125
  $this.addClass( 'is-open' ).find( '.the-text' ).text( $this.data( 'close' ) );
126
  }
 
127
  } );
128
 
129
  /**
assets/js/upload.min.js CHANGED
@@ -1 +1 @@
1
- window.imagify=window.imagify||{concat:ajaxurl.indexOf("?")>0?"&":"?",log:function(a){void 0!==console&&console.log(a)},info:function(a){void 0!==console&&console.info(a)}},function(a,b,c,d){function e(b){b.each(function(){var b=parseInt(a(this).closest(".imagify-chart").next(".imagify-chart-value").text()),c=[{value:b,color:"#00B3D3"},{value:100-b,color:"#D8D8D8"}];new Chart(a(this)[0].getContext("2d")).Doughnut(c,{segmentStrokeColor:"#FFF",segmentStrokeWidth:1,animateRotate:!0,tooltipEvents:[]})})}var f,g,h;f='<option value="imagify-bulk-upload">'+imagifyUpload.bulkActionsLabels.optimize+"</option>",f+='<option value="imagify-bulk-restore">'+imagifyUpload.bulkActionsLabels.restore+"</option>",a('.bulkactions select[name="action"]').find("option:last-child").before(f),a('.bulkactions select[name="action2"]').find("option:last-child").before(f),a("#doaction").add("#doaction2").on("click",function(b){var c,d,e=a(this).prev("select").val().split("-");"imagify"===e[0]&&(b.preventDefault(),c=e[2],d=a('input[name^="media"]:checked').map(function(){return this.value}).get(),d.forEach(function(b,d){setTimeout(function(){a("#imagify-"+c+"-"+b).trigger("click")},300*d)}))}),a(b).on("click",".button-imagify-restore, .button-imagify-manual-upload, .button-imagify-manual-override-upload",function(b){var c=a(this),d=c.parents(".column-imagify_optimized_file, .compat-field-imagify .field"),f=c.attr("href");b.preventDefault(),d.length||(d=c.closest(".column")),d.html('<div class="button"><span class="imagify-spinner"></span>'+c.data("waiting-label")+"</div>"),a.get(f.replace("admin-post.php","admin-ajax.php")).done(function(a){d.html(a.data),d.find(".imagify-datas-more-action a").addClass("is-open").find(".the-text").text(d.find(".imagify-datas-more-action a").data("close")),d.find(".imagify-datas-details").addClass("is-open"),e(d.find(".imagify-chart-container").find("canvas"))})}),a(".imagify-datas-details").hide(),a(b).on("click",".imagify-datas-more-action a",function(){var b=a(this);return b.hasClass("is-open")?(a(b.attr("href")).slideUp(300).removeClass("is-open"),b.removeClass("is-open").find(".the-text").text(b.data("open"))):(a(b.attr("href")).slideDown(300).addClass("is-open"),b.addClass("is-open").find(".the-text").text(b.data("close"))),!1}),g=function(a){var b={};return c.location.href.replace(/[?&]+([^=&]+)=?([^&]*)?/gi,function(a,c,d){b[c]=void 0!==d?d:""}),a?b[a]?b[a]:null:b},h=function(){var b=setInterval(function(){var c=a(".media-modal .imagify-datas-details");c.length&&(c.hide(),e(a("#imagify-consumption-chart")),clearInterval(b),b=null)},20)},a(".upload-php").find(".media-frame.mode-grid").on("click",".attachment",function(){h()}),a(".upload-php").length&&g("item")&&h(),a("#insert-media-button").on("click.imagify",function(){var b=setInterval(function(){var c=a(".media-frame-content .attachments");c.length&&(c.on("click.imagify",".attachment",function(){h()}),clearInterval(b),b=null)},100)}),e(a(".imagify-chart-container").find("canvas"))}(jQuery,document,window);
1
+ window.imagify=window.imagify||{concat:ajaxurl.indexOf("?")>0?"&":"?",log:function(a){void 0!==console&&console.log(a)},info:function(a){void 0!==console&&console.info(a)}},function(a,b,c,d){function e(b){b.each(function(){var b=parseInt(a(this).closest(".imagify-chart").next(".imagify-chart-value").text()),c=[{value:b,color:"#00B3D3"},{value:100-b,color:"#D8D8D8"}];new Chart(a(this)[0].getContext("2d")).Doughnut(c,{segmentStrokeColor:"#FFF",segmentStrokeWidth:1,animateRotate:!0,tooltipEvents:[]})})}var f,g,h;f='<option value="imagify-bulk-upload">'+imagifyUpload.bulkActionsLabels.optimize+"</option>",f+='<option value="imagify-bulk-restore">'+imagifyUpload.bulkActionsLabels.restore+"</option>",a('.bulkactions select[name="action"]').find("option:last-child").before(f),a('.bulkactions select[name="action2"]').find("option:last-child").before(f),a("#doaction").add("#doaction2").on("click",function(b){var c,d,e=a(this).prev("select").val().split("-");"imagify"===e[0]&&(b.preventDefault(),c=e[2],d=a('input[name^="media"]:checked').map(function(){return this.value}).get(),d.forEach(function(b,d){setTimeout(function(){a("#imagify-"+c+"-"+b).trigger("click")},300*d)}))}),a(b).on("click",".button-imagify-restore, .button-imagify-manual-upload, .button-imagify-manual-override-upload",function(b){var c=a(this),d=c.parents(".column-imagify_optimized_file, .compat-field-imagify .field"),f=c.attr("href");b.preventDefault(),d.length||(d=c.closest(".column")),d.html('<div class="button"><span class="imagify-spinner"></span>'+c.data("waiting-label")+"</div>"),a.get(f.replace("admin-post.php","admin-ajax.php")).done(function(a){d.html(a.data),d.find(".imagify-datas-more-action a").addClass("is-open").find(".the-text").text(d.find(".imagify-datas-more-action a").data("close")),d.find(".imagify-datas-details").addClass("is-open"),e(d.find(".imagify-chart-container").find("canvas"))})}),a(".imagify-datas-details").hide(),a(b).on("click",".imagify-datas-more-action a",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")))}),g=function(a){var b={};return c.location.href.replace(/[?&]+([^=&]+)=?([^&]*)?/gi,function(a,c,d){b[c]=void 0!==d?d:""}),a?b[a]?b[a]:null:b},h=function(){var b=setInterval(function(){var c=a(".media-modal .imagify-datas-details");c.length&&(c.hide(),e(a("#imagify-consumption-chart")),clearInterval(b),b=null)},20)},a(".upload-php").find(".media-frame.mode-grid").on("click",".attachment",function(){h()}),a(".upload-php").length&&g("item")&&h(),a("#insert-media-button").on("click.imagify",function(){var b=setInterval(function(){var c=a(".media-frame-content .attachments");c.length&&(c.on("click.imagify",".attachment",function(){h()}),clearInterval(b),b=null)},100)}),e(a(".imagify-chart-container").find("canvas"))}(jQuery,document,window);
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.6.5
7
  * Author: WP Media
8
  * Author URI: http://wp-media.me
9
  * Licence: GPLv2
@@ -17,7 +17,7 @@
17
  defined( 'ABSPATH' ) || die( 'Cheatin\' uh?' );
18
 
19
  // Imagify defines.
20
- define( 'IMAGIFY_VERSION' , '1.6.5' );
21
  define( 'IMAGIFY_SLUG' , 'imagify' );
22
  define( 'IMAGIFY_SETTINGS_SLUG' , IMAGIFY_SLUG . '_settings' );
23
  define( 'IMAGIFY_WEB_MAIN' , 'https://imagify.io' );
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.6.6
7
  * Author: WP Media
8
  * Author URI: http://wp-media.me
9
  * Licence: GPLv2
17
  defined( 'ABSPATH' ) || die( 'Cheatin\' uh?' );
18
 
19
  // Imagify defines.
20
+ define( 'IMAGIFY_VERSION' , '1.6.6' );
21
  define( 'IMAGIFY_SLUG' , 'imagify' );
22
  define( 'IMAGIFY_SETTINGS_SLUG' , IMAGIFY_SLUG . '_settings' );
23
  define( 'IMAGIFY_WEB_MAIN' , 'https://imagify.io' );
inc/3rd-party/3rd-party.php CHANGED
@@ -1,6 +1,7 @@
1
  <?php
2
  defined( 'ABSPATH' ) || die( 'Cheatin\' uh?' );
3
 
 
4
  require( IMAGIFY_3RD_PARTY_PATH . 'enable-media-replace.php' );
5
  require( IMAGIFY_3RD_PARTY_PATH . 'nextgen-gallery/nextgen-gallery.php' );
6
  require( IMAGIFY_3RD_PARTY_PATH . 'wp-retina-2x.php' );
1
  <?php
2
  defined( 'ABSPATH' ) || die( 'Cheatin\' uh?' );
3
 
4
+ require( IMAGIFY_3RD_PARTY_PATH . 'amazon-s3-and-cloudfront/amazon-s3-and-cloudfront.php' );
5
  require( IMAGIFY_3RD_PARTY_PATH . 'enable-media-replace.php' );
6
  require( IMAGIFY_3RD_PARTY_PATH . 'nextgen-gallery/nextgen-gallery.php' );
7
  require( IMAGIFY_3RD_PARTY_PATH . 'wp-retina-2x.php' );
inc/3rd-party/amazon-s3-and-cloudfront/amazon-s3-and-cloudfront.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined( 'ABSPATH' ) || die( 'Cheatin\' uh?' );
3
+
4
+ if ( function_exists( 'as3cf_init' ) && is_admin() ) :
5
+
6
+ require( dirname( __FILE__ ) . '/inc/classes/class-imagify-as3cf.php' );
7
+ require( dirname( __FILE__ ) . '/inc/classes/class-imagify-as3cf-attachment.php' );
8
+
9
+ add_action( 'imagify_loaded', array( imagify_as3cf(), 'init' ), 1 );
10
+
11
+ endif;
inc/3rd-party/amazon-s3-and-cloudfront/inc/classes/class-imagify-as3cf-attachment.php ADDED
@@ -0,0 +1,831 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined( 'ABSPATH' ) || die( 'Cheatin\' uh?' );
3
+
4
+ /**
5
+ * Imagify WP Offload S3 attachment class.
6
+ *
7
+ * @since 1.6.6
8
+ * @author Grégory Viguier
9
+ */
10
+ class Imagify_AS3CF_Attachment extends Imagify_Attachment {
11
+
12
+ /**
13
+ * Class version.
14
+ *
15
+ * @var string
16
+ */
17
+ const VERSION = '1.0';
18
+
19
+ /**
20
+ * Tell if AS3CF settings will be used for this attachment.
21
+ *
22
+ * @var bool
23
+ */
24
+ protected $use_s3_settings;
25
+
26
+ /**
27
+ * Tell if the files should be deleted once sent to S3.
28
+ *
29
+ * @var bool
30
+ */
31
+ protected $delete_files;
32
+
33
+ /**
34
+ * The name of the transient that tells if optimization is processing.
35
+ *
36
+ * @var string.
37
+ */
38
+ protected $optimization_state_transient;
39
+
40
+ /**
41
+ * The constructor.
42
+ *
43
+ * @since 1.6.6
44
+ * @author Grégory Viguier
45
+ *
46
+ * @param int $id The attachment ID.
47
+ */
48
+ public function __construct( $id = 0 ) {
49
+ global $post;
50
+
51
+ if ( $id && is_a( $id, 'WP_Post' ) ) {
52
+ $id = $id->ID;
53
+ } elseif ( ! $id && is_object( $post ) ) {
54
+ $this->id = $post->ID;
55
+ } else {
56
+ $this->id = absint( $id );
57
+ }
58
+
59
+ $this->optimization_state_transient = 'imagify-async-in-progress-' . $this->id;
60
+ }
61
+
62
+
63
+ /** ----------------------------------------------------------------------------------------- */
64
+ /** ATTACHMENT PATHS AND URLS =============================================================== */
65
+ /** ----------------------------------------------------------------------------------------- */
66
+
67
+ /**
68
+ * Get the original attachment path.
69
+ *
70
+ * @since 1.6.6
71
+ * @author Grégory Viguier
72
+ *
73
+ * @return string|bool Path to the file if it exists or has been successfully retrieved from S3. False on failure.
74
+ */
75
+ public function get_original_path() {
76
+ return $this->get_thumbnail_path();
77
+ }
78
+
79
+ /**
80
+ * Get a thumbnail path.
81
+ *
82
+ * @since 1.6.6
83
+ * @author Grégory Viguier
84
+ *
85
+ * @param string $size_file The basename of the file. If not provided, the path to the main file is returned.
86
+ * @return string|bool Path to the file if it exists or has been successfully retrieved from S3. False on failure.
87
+ */
88
+ public function get_thumbnail_path( $size_file = false ) {
89
+ if ( ! $this->is_mime_type_supported() ) {
90
+ return false;
91
+ }
92
+
93
+ $file_path = get_attached_file( $this->id, true );
94
+
95
+ if ( $size_file ) {
96
+ // It's not the full size.
97
+ $file_path = dirname( $file_path ) . '/' . $size_file;
98
+ }
99
+
100
+ return $file_path;
101
+ }
102
+
103
+ /**
104
+ * Get the original attachment URL.
105
+ *
106
+ * @since 1.6.6
107
+ * @author Grégory Viguier
108
+ *
109
+ * @return string|bool The main file URL. False on failure.
110
+ */
111
+ public function get_original_url() {
112
+ return $this->get_thumbnail_url();
113
+ }
114
+
115
+ /**
116
+ * Get a thumbnail URL.
117
+ *
118
+ * @since 1.6.6
119
+ * @author Grégory Viguier
120
+ *
121
+ * @param string $size_file The basename of the file. If not provided, the main file's URL is returned.
122
+ * @return string|bool The file URL. False on failure.
123
+ */
124
+ public function get_thumbnail_url( $size_file = false ) {
125
+ if ( ! $this->is_mime_type_supported() ) {
126
+ return false;
127
+ }
128
+
129
+ $file_url = wp_get_attachment_url( $this->id );
130
+
131
+ if ( $size_file ) {
132
+ // It's not the full size.
133
+ $file_url = trailingslashit( dirname( $file_url ) ) . $size_file;
134
+ }
135
+
136
+ return $file_url;
137
+ }
138
+
139
+
140
+ /** ----------------------------------------------------------------------------------------- */
141
+ /** THE PUBLIC STUFF ======================================================================== */
142
+ /** ----------------------------------------------------------------------------------------- */
143
+
144
+ /**
145
+ * Optimize all sizes with Imagify.
146
+ *
147
+ * @since 1.6.6
148
+ * @author Grégory Viguier
149
+ *
150
+ * @param int $optimization_level The optimization level (2 = ultra, 1 = aggressive, 0 = normal).
151
+ * @param array $metadata The attachment meta data, containing the sizes. Provide only for a new attachment.
152
+ * @return array|bool The optimization data. False on failure.
153
+ */
154
+ public function optimize( $optimization_level = null, $metadata = array() ) {
155
+ $metadata_changed = false;
156
+
157
+ /**
158
+ * Make some sanity tests first.
159
+ */
160
+
161
+ // Check if the attachment extension is allowed.
162
+ if ( ! $this->is_mime_type_supported() ) {
163
+ return false;
164
+ }
165
+
166
+ // To avoid issue with "original_size" at 0 in "_imagify_data".
167
+ if ( 0 === (int) $this->get_stats_data( 'original_size' ) ) {
168
+ $this->delete_imagify_data();
169
+ }
170
+
171
+ $optimization_level = isset( $optimization_level ) ? (int) $optimization_level : (int) get_imagify_option( 'optimization_level', 1 );
172
+
173
+ // Check if the full size is already optimized with this level.
174
+ if ( $this->is_optimized() && $this->get_optimization_level() === $optimization_level ) {
175
+ return false;
176
+ }
177
+
178
+ // Get file path of the full size.
179
+ $attachment_path = $this->get_original_path();
180
+
181
+ if ( ! $attachment_path ) {
182
+ // We're in deep sh**.
183
+ return false;
184
+ }
185
+
186
+ $filesystem = imagify_get_filesystem();
187
+
188
+ if ( ! $filesystem->exists( $attachment_path ) && ! $this->get_file_from_s3( $attachment_path ) ) {
189
+ // The file doesn't exist and couldn't be retrieved from S3.
190
+ return false;
191
+ }
192
+
193
+ /**
194
+ * Start the process.
195
+ */
196
+
197
+ // Set a "optimization status" transient.
198
+ set_transient( $this->optimization_state_transient, true, 10 * MINUTE_IN_SECONDS );
199
+
200
+ /** This hook is documented in /inc/classes/class-imagify-attachment.php. */
201
+ do_action( 'before_imagify_optimize_attachment', $this->id );
202
+
203
+ $metadata = $this->set_deletion_status( $metadata );
204
+
205
+ // Store the paths of the files that may be deleted once optimized and sent to S3.
206
+ $to_delete = array();
207
+ $filesize_total = 0;
208
+
209
+ // Maybe resize (and backup) the image.
210
+ $resized = $this->maybe_resize( $attachment_path );
211
+
212
+ if ( $resized ) {
213
+ $size = @getimagesize( $attachment_path );
214
+
215
+ if ( isset( $size[0], $size[1] ) ) {
216
+ $metadata['width'] = $size[0];
217
+ $metadata['height'] = $size[1];
218
+ $metadata_changed = true;
219
+ }
220
+ }
221
+
222
+ // Optimize the full size.
223
+ $response = do_imagify( $attachment_path, array(
224
+ 'optimization_level' => $optimization_level,
225
+ 'context' => 'wp',
226
+ 'resized' => $resized,
227
+ 'original_size' => $this->get_original_size( false ),
228
+ ) );
229
+
230
+ $data = $this->fill_data( null, $response, $this->get_original_url() );
231
+
232
+ if ( $this->delete_files ) {
233
+ $to_delete[] = $attachment_path;
234
+ // This is used by AS3CF.
235
+ $bytes = $filesystem->size( $attachment_path );
236
+
237
+ if ( false !== $bytes ) {
238
+ $metadata_changed = true;
239
+ $filesize_total += $bytes;
240
+ $metadata['filesize'] = $bytes;
241
+ } else {
242
+ $metadata['filesize'] = 0;
243
+ }
244
+ }
245
+
246
+ if ( ! $data ) {
247
+ // The optimization failed.
248
+ $metadata = $metadata_changed ? $metadata : false;
249
+ $this->cleanup( $metadata, $to_delete );
250
+ return false;
251
+ }
252
+
253
+ // Optimize all thumbnails.
254
+ if ( ! empty( $metadata['sizes'] ) ) {
255
+ $disallowed_sizes = (array) get_imagify_option( 'disallowed-sizes', array() );
256
+ $is_active_for_network = imagify_is_active_for_network();
257
+
258
+ foreach ( $metadata['sizes'] as $size_key => $size_data ) {
259
+ $thumbnail_path = $this->get_thumbnail_path( $size_data['file'] );
260
+
261
+ if ( $this->delete_files ) {
262
+ $to_delete[] = $thumbnail_path;
263
+
264
+ // Even if this size must not be optimized ($disallowed_sizes), we must fetch the file from S3 to get its size.
265
+ if ( ! $filesystem->exists( $thumbnail_path ) && ! $this->get_file_from_s3( $thumbnail_path ) ) {
266
+ // Doesn't exist and couldn't be retrieved from S3.
267
+ $data['sizes'][ $size_key ] = array(
268
+ 'success' => false,
269
+ 'error' => __( 'This size could not be retrieved from Amazon S3.', 'imagify' ),
270
+ );
271
+ continue;
272
+ }
273
+
274
+ // This is used by AS3CF.
275
+ $bytes = $filesystem->size( $thumbnail_path );
276
+
277
+ if ( false !== $bytes ) {
278
+ $filesize_total += $bytes;
279
+ }
280
+ }
281
+
282
+ // Check if this size has to be optimized.
283
+ if ( isset( $disallowed_sizes[ $size_key ] ) && ! $is_active_for_network ) {
284
+ $data['sizes'][ $size_key ] = array(
285
+ 'success' => false,
286
+ 'error' => __( 'This size isn\'t authorized to be optimized. Update your Imagify settings if you want to optimize it.', 'imagify' ),
287
+ );
288
+ continue;
289
+ }
290
+
291
+ if ( ! $this->delete_files && ! $filesystem->exists( $thumbnail_path ) && ! $this->get_file_from_s3( $thumbnail_path ) ) {
292
+ // Doesn't exist and couldn't be retrieved from S3.
293
+ $data['sizes'][ $size_key ] = array(
294
+ 'success' => false,
295
+ 'error' => __( 'This size could not be retrieved from Amazon S3.', 'imagify' ),
296
+ );
297
+ continue;
298
+ }
299
+
300
+ $thumbnail_url = $this->get_thumbnail_url( $size_data['file'] );
301
+
302
+ // Optimize the thumbnail size.
303
+ $response = do_imagify( $thumbnail_path, array(
304
+ 'backup' => false,
305
+ 'optimization_level' => $optimization_level,
306
+ 'context' => 'wp',
307
+ ) );
308
+
309
+ $data = $this->fill_data( $data, $response, $thumbnail_url, $size_key );
310
+
311
+ /** This filter is documented in /inc/classes/class-imagify-attachment.php. */
312
+ $data = apply_filters( 'imagify_fill_thumbnail_data', $data, $response, $this->id, $thumbnail_path, $thumbnail_url, $size_key, $optimization_level );
313
+ } // End foreach().
314
+ } // End if().
315
+
316
+ $data['stats']['percent'] = round( ( ( $data['stats']['original_size'] - $data['stats']['optimized_size'] ) / $data['stats']['original_size'] ) * 100, 2 );
317
+
318
+ update_post_meta( $this->id, '_imagify_data', $data );
319
+ update_post_meta( $this->id, '_imagify_status', 'success' );
320
+ update_post_meta( $this->id, '_imagify_optimization_level', $optimization_level );
321
+
322
+ if ( $this->delete_files && $filesize_total ) {
323
+ // Add the total file size for all image sizes. This is a meta used by AS3CF.
324
+ update_post_meta( $this->id, 'wpos3_filesize_total', $filesize_total );
325
+ }
326
+
327
+ $optimized_data = $this->get_data();
328
+
329
+ /** This hook is documented in /inc/classes/class-imagify-attachment.php. */
330
+ do_action( 'after_imagify_optimize_attachment', $this->id, $optimized_data );
331
+
332
+ $sent = $this->maybe_send_attachment_to_s3( $metadata, $attachment_path );
333
+ // Update metadata only if they changed.
334
+ $metadata = $metadata_changed ? $metadata : false;
335
+ // Delete files only if they have been uploaded to S3.
336
+ $to_delete = $sent ? $to_delete : array();
337
+
338
+ $this->cleanup( $metadata, $to_delete );
339
+
340
+ return $optimized_data;
341
+ }
342
+
343
+ /**
344
+ * Process an attachment restoration from the backup file.
345
+ *
346
+ * @since 1.6.6
347
+ * @author Grégory Viguier
348
+ *
349
+ * @return array A list of files sent to S3.
350
+ */
351
+ public function restore() {
352
+ // Check if the attachment extension is allowed.
353
+ if ( ! $this->is_mime_type_supported() ) {
354
+ return false;
355
+ }
356
+
357
+ // Stop the process if there is no backup file to restore.
358
+ if ( ! $this->has_backup() ) {
359
+ return false;
360
+ }
361
+
362
+ /** This hook is documented in /inc/classes/class-imagify-attachment.php. */
363
+ do_action( 'before_imagify_restore_attachment', $this->id );
364
+
365
+ $backup_path = $this->get_backup_path();
366
+ $attachment_path = $this->get_original_path();
367
+ $filesystem = imagify_get_filesystem();
368
+
369
+ if ( ! $attachment_path ) {
370
+ return false;
371
+ }
372
+
373
+ // Create the original image from the backup.
374
+ $filesystem->copy( $backup_path, $attachment_path, true );
375
+ imagify_chmod_file( $attachment_path );
376
+
377
+ if ( ! $filesystem->exists( $attachment_path ) ) {
378
+ return false;
379
+ }
380
+
381
+ if ( ! function_exists( 'wp_generate_attachment_metadata' ) ) {
382
+ require_once( ABSPATH . 'wp-admin/includes/image.php' );
383
+ }
384
+
385
+ // Remove old optimization data.
386
+ $this->delete_imagify_data();
387
+
388
+ /** This hook is documented in /inc/classes/class-imagify-attachment.php. */
389
+ do_action( 'after_imagify_restore_attachment', $this->id );
390
+
391
+ $this->set_deletion_status();
392
+
393
+ // If the files must be deleted, we need to store the file sizes.
394
+ $filesize_total = 0;
395
+ // Generate new thumbnails and new metadata.
396
+ $metadata = wp_generate_attachment_metadata( $this->id, $attachment_path );
397
+ // Send to S3.
398
+ $sent = $this->maybe_send_attachment_to_s3( $metadata, $attachment_path );
399
+ // Files restored (and maybe to delete).
400
+ $files = array();
401
+
402
+ if ( $sent ) {
403
+ $files[] = $attachment_path;
404
+ }
405
+
406
+ if ( $this->delete_files ) {
407
+ // This is used by AS3CF.
408
+ $bytes = $filesystem->size( $attachment_path );
409
+
410
+ if ( false !== $bytes ) {
411
+ $filesize_total += $bytes;
412
+ $metadata['filesize'] = $bytes;
413
+ } else {
414
+ $metadata['filesize'] = 0;
415
+ }
416
+ }
417
+
418
+ if ( ! empty( $metadata['sizes'] ) && ( $sent || $this->delete_files ) ) {
419
+ foreach ( $metadata['sizes'] as $size_key => $size_data ) {
420
+ $thumbnail_path = $this->get_thumbnail_path( $size_data['file'] );
421
+
422
+ if ( $sent ) {
423
+ $files[] = $thumbnail_path;
424
+ }
425
+
426
+ if ( $this->delete_files ) {
427
+ // This is used by AS3CF.
428
+ $bytes = $filesystem->size( $thumbnail_path );
429
+
430
+ if ( false !== $bytes ) {
431
+ $filesize_total += $bytes;
432
+ }
433
+ }
434
+ }
435
+ }
436
+
437
+ if ( $this->delete_files && $filesize_total ) {
438
+ // Add the total file size for all image sizes. This is a meta used by AS3CF.
439
+ update_post_meta( $this->id, 'wpos3_filesize_total', $filesize_total );
440
+ }
441
+
442
+ $to_delete = $this->delete_files ? $files : array();
443
+
444
+ $this->cleanup( $metadata, $to_delete );
445
+
446
+ return $files;
447
+ }
448
+
449
+
450
+ /** ----------------------------------------------------------------------------------------- */
451
+ /** INTERNAL UTILITIES ====================================================================== */
452
+ /** ----------------------------------------------------------------------------------------- */
453
+
454
+ /**
455
+ * Cleanup after optimization or a restore:
456
+ * - Maybe update metadata.
457
+ * - Maybe delete local files.
458
+ * - Delete the "optimization status" transient.
459
+ *
460
+ * @since 1.6.6
461
+ * @author Grégory Viguier
462
+ *
463
+ * @param array $new_metadata New attachment metadata to be stored.
464
+ * @param array $files_to_remove Files to delete.
465
+ */
466
+ protected function cleanup( $new_metadata, $files_to_remove ) {
467
+ if ( $new_metadata ) {
468
+ /**
469
+ * Filter the metadata stored after optimization or a restore.
470
+ *
471
+ * @since 1.6.6
472
+ * @author Grégory Viguier
473
+ *
474
+ * @param array $new_metadata New attachment metadata to be stored.
475
+ * @param int $id The attachment ID.
476
+ */
477
+ $new_metadata = apply_filters( 'imagify_as3cf_attachment_cleanup_metadata', $new_metadata, $this->id );
478
+ /**
479
+ * Update the attachment meta that contains the file sizes.
480
+ * Here we don't use wp_update_attachment_metadata() to prevent triggering unwanted hooks.
481
+ */
482
+ update_post_meta( $this->id, '_wp_attachment_metadata', $new_metadata );
483
+ }
484
+
485
+ if ( $files_to_remove ) {
486
+ $attachment_path = $this->get_original_path();
487
+ /** This filter is documented in /amazon-s3-and-cloudfront/classes/amazon-s3-and-cloudfront.php. */
488
+ $files_to_remove = (array) apply_filters( 'as3cf_upload_attachment_local_files_to_remove', $files_to_remove, $this->id, $attachment_path );
489
+ $files_to_remove = array_filter( $files_to_remove );
490
+
491
+ if ( $files_to_remove ) {
492
+ $files_to_remove = array_unique( $files_to_remove );
493
+ /**
494
+ * Delete the local files.
495
+ */
496
+ array_map( array( $this, 'maybe_delete_file' ), $files_to_remove );
497
+ }
498
+ }
499
+
500
+ /**
501
+ * Delete the "optimization status" transient.
502
+ */
503
+ delete_transient( $this->optimization_state_transient );
504
+ }
505
+
506
+ /**
507
+ * Maybe resize (and backup) an image.
508
+ *
509
+ * @since 1.6.6
510
+ * @author Grégory Viguier
511
+ *
512
+ * @param string $attachment_path The file path.
513
+ * @return bool True on success. False on failure.
514
+ */
515
+ protected function maybe_resize( $attachment_path ) {
516
+ $do_resize = get_imagify_option( 'resize_larger' );
517
+ $resize_width = get_imagify_option( 'resize_larger_w' );
518
+ $attachment_size = @getimagesize( $attachment_path );
519
+
520
+ if ( ! $do_resize || ! isset( $attachment_size[0] ) || $resize_width >= $attachment_size[0] ) {
521
+ return false;
522
+ }
523
+
524
+ $resized_attachment_path = $this->resize( $attachment_path, $attachment_size, $resize_width );
525
+
526
+ if ( is_wp_error( $resized_attachment_path ) ) {
527
+ return false;
528
+ }
529
+
530
+ $backed_up = $this->maybe_backup( $attachment_path );
531
+
532
+ if ( false === $backed_up ) {
533
+ return false;
534
+ }
535
+
536
+ $filesystem = imagify_get_filesystem();
537
+
538
+ $filesystem->move( $resized_attachment_path, $attachment_path, true );
539
+ imagify_chmod_file( $attachment_path );
540
+
541
+ // If resized temp file still exists, delete it.
542
+ if ( $filesystem->exists( $resized_attachment_path ) ) {
543
+ $filesystem->delete( $resized_attachment_path );
544
+ }
545
+
546
+ return $filesystem->exists( $attachment_path );
547
+ }
548
+
549
+ /**
550
+ * Maybe backup a file.
551
+ *
552
+ * @since 1.6.6
553
+ * @author Grégory Viguier
554
+ *
555
+ * @param string $attachment_path The file path.
556
+ * @return bool|null True on success. False on failure. Null if backup is not needed.
557
+ */
558
+ protected function maybe_backup( $attachment_path ) {
559
+ if ( ! get_imagify_option( 'backup' ) ) {
560
+ return null;
561
+ }
562
+
563
+ $filesystem = imagify_get_filesystem();
564
+ $backup_path = get_imagify_attachment_backup_path( $attachment_path );
565
+ $backup_path_info = pathinfo( $backup_path );
566
+
567
+ wp_mkdir_p( $backup_path_info['dirname'] );
568
+
569
+ // TO DO - check and send a error message if the backup can't be created.
570
+ $filesystem->copy( $attachment_path, $backup_path, true );
571
+ imagify_chmod_file( $backup_path );
572
+
573
+ return $filesystem->exists( $backup_path );
574
+ }
575
+
576
+ /**
577
+ * Tell if the files must be deleted after being optimized or restored.
578
+ * It sets the 2 properties $this->use_s3_settings and $this->delete_files.
579
+ *
580
+ * @since 1.6.6
581
+ * @author Grégory Viguier
582
+ *
583
+ * @param array $metadata Attachment metadata. Provide, only if it comes from a 'wp_generate_attachment_metadata' or 'wp_update_attachment_metadata' hook.
584
+ * @return array Attachment metadata. If not provided as argument, new values are fetched.
585
+ */
586
+ protected function set_deletion_status( $metadata = false ) {
587
+ global $as3cf;
588
+
589
+ if ( $metadata ) {
590
+ /**
591
+ * Metadata is provided: we were in a 'wp_generate_attachment_metadata' or 'wp_update_attachment_metadata' hook.
592
+ * This means we'll follow AS3CF settings to know if the local files must be sent to S3 and/or deleted.
593
+ */
594
+ $this->use_s3_settings = true;
595
+ $this->delete_files = $as3cf->get_setting( 'copy-to-s3' ) && $as3cf->get_setting( 'remove-local-file' );
596
+
597
+ return $metadata;
598
+ }
599
+
600
+ /**
601
+ * Metadata is not provided: we were not in a 'wp_generate_attachment_metadata' or 'wp_update_attachment_metadata' hook.
602
+ * So, we fetch the current meta value.
603
+ * This also means we won't follow AS3CF settings to know if the local files must be sent to S3 and/or deleted.
604
+ * In that case we'll send the files to S3 if they already are there, and delete them if they is a 'filesize' entry in the metadata.
605
+ */
606
+ $metadata = wp_get_attachment_metadata( $this->id, true );
607
+ $this->use_s3_settings = false;
608
+ $this->delete_files = isset( $metadata['filesize'] );
609
+
610
+ return $metadata;
611
+ }
612
+
613
+
614
+ /** ----------------------------------------------------------------------------------------- */
615
+ /** S3 UTILITIES ============================================================================ */
616
+ /** ----------------------------------------------------------------------------------------- */
617
+
618
+ /**
619
+ * Tell if AS3CF is set up.
620
+ *
621
+ * @since 1.6.6
622
+ * @author Grégory Viguier
623
+ *
624
+ * @return bool
625
+ */
626
+ public function is_s3_setup() {
627
+ global $as3cf;
628
+ static $is;
629
+
630
+ if ( ! isset( $is ) ) {
631
+ $is = $as3cf->is_plugin_setup();
632
+ }
633
+
634
+ return $is;
635
+ }
636
+
637
+ /**
638
+ * Tell if an attachment is stored on S3.
639
+ *
640
+ * @since 1.6.6
641
+ * @author Grégory Viguier
642
+ *
643
+ * @return array|bool The S3 info on success. False if the attachment is not on S3.
644
+ */
645
+ public function get_s3_info() {
646
+ global $as3cf;
647
+ return $as3cf->get_attachment_s3_info( $this->id );
648
+ }
649
+
650
+ /**
651
+ * Get a file from S3.
652
+ *
653
+ * @since 1.6.6
654
+ * @author Grégory Viguier
655
+ *
656
+ * @param string $file_path The file path.
657
+ * @return string|bool The file path on success, false on failure.
658
+ */
659
+ protected function get_file_from_s3( $file_path ) {
660
+ global $as3cf;
661
+
662
+ if ( ! $this->is_mime_type_supported() ) {
663
+ return false;
664
+ }
665
+
666
+ if ( ! $this->is_s3_setup() ) {
667
+ return false;
668
+ }
669
+
670
+ $s3_object = $this->get_s3_info();
671
+
672
+ if ( ! $s3_object ) {
673
+ // The attachment is not on S3.
674
+ return false;
675
+ }
676
+
677
+ $filesystem = imagify_get_filesystem();
678
+ $s3_object['key'] = dirname( $s3_object['key'] ) . '/' . basename( $file_path );
679
+
680
+ // Retrieve file from S3.
681
+ $as3cf->plugin_compat->copy_s3_file_to_server( $s3_object, $file_path );
682
+
683
+ return $filesystem->exists( $file_path ) ? $file_path : false;
684
+ }
685
+
686
+ /**
687
+ * Maybe send the attachment to S3.
688
+ *
689
+ * @since 1.6.6
690
+ * @author Grégory Viguier
691
+ *
692
+ * @param array $metadata The attachment metadata.
693
+ * @param string $attachment_path The attachment path.
694
+ * @param bool $remove_local_files True to let AS3CF delete the local files (if set in the settings). We usually don't want that, we do it by ourselves.
695
+ * @return bool True on success. False otherwize.
696
+ */
697
+ protected function maybe_send_attachment_to_s3( $metadata = null, $attachment_path = null, $remove_local_files = false ) {
698
+ global $as3cf;
699
+
700
+ if ( ! $this->can_send_to_s3() ) {
701
+ return false;
702
+ }
703
+
704
+ $s3_object = $this->get_s3_info();
705
+
706
+ if ( ! $s3_object ) {
707
+ return false;
708
+ }
709
+
710
+ $full_file_path = $this->get_original_path();
711
+
712
+ if ( ! $full_file_path ) {
713
+ // This is bad.
714
+ return false;
715
+ }
716
+
717
+ $s3_data = $as3cf->upload_attachment_to_s3( $this->id, $metadata, $attachment_path, false, $remove_local_files );
718
+
719
+ return ! is_wp_error( $s3_data );
720
+ }
721
+
722
+ /**
723
+ * Tell if an attachment can be sent to S3.
724
+ *
725
+ * @since 1.6.6
726
+ * @author Grégory Viguier
727
+ *
728
+ * @return bool
729
+ */
730
+ protected function can_send_to_s3() {
731
+ global $as3cf;
732
+ static $can = array();
733
+ static $copy_to_s3;
734
+
735
+ if ( isset( $can[ $this->id ] ) ) {
736
+ return $can[ $this->id ];
737
+ }
738
+
739
+ if ( ! isset( $copy_to_s3 ) ) {
740
+ $copy_to_s3 = (bool) $as3cf->get_setting( 'copy-to-s3' );
741
+ }
742
+
743
+ $is_s3_setup = $this->is_s3_setup();
744
+ $s3_object = $this->get_s3_info();
745
+ // S3 is set up and the attachment is on S3.
746
+ $can[ $this->id ] = $is_s3_setup && $s3_object;
747
+
748
+ if ( $can[ $this->id ] && ! empty( $this->use_s3_settings ) ) {
749
+ // Use AS3CF setting to tell if we're allowed to send the files.
750
+ $can[ $this->id ] = $copy_to_s3;
751
+ }
752
+
753
+ /**
754
+ * Filter the result of Imagify_AS3CF_Attachment::can_send_to_s3().
755
+ *
756
+ * @since 1.6.6
757
+ * @author Grégory Viguier
758
+ *
759
+ * @param bool $can True if the attachment can be sent. False otherwize.
760
+ * @param int $id The attachment ID.
761
+ * @param array $s3_object The S3 infos.
762
+ * @param bool $is_s3_setup AS3CF is set up or not.
763
+ * @param bool $copy_to_s3 AS3CF setting that tells if a "new" attachment can be sent.
764
+ * @param bool $use_s3_settings Tell if we must use AS3CF setting in this case.
765
+ */
766
+ $can[ $this->id ] = (bool) apply_filters( 'imagify_can_send_to_s3', $can[ $this->id ], $this->id, $s3_object, $is_s3_setup, $copy_to_s3, $this->use_s3_settings );
767
+
768
+ return $can[ $this->id ];
769
+ }
770
+
771
+ /**
772
+ * Maybe delete the local file.
773
+ *
774
+ * @since 1.6.6
775
+ * @author Grégory Viguier
776
+ *
777
+ * @param string $file_path The file path.
778
+ * @return bool True if deleted or doesn't exist. False on failure or if the file is not supposed to be deleted.
779
+ */
780
+ protected function maybe_delete_file( $file_path ) {
781
+ if ( ! $this->file_should_be_deleted( $file_path ) ) {
782
+ return false;
783
+ }
784
+
785
+ $filesystem = imagify_get_filesystem();
786
+
787
+ if ( ! $filesystem->exists( $file_path ) ) {
788
+ return true;
789
+ }
790
+
791
+ return $filesystem->delete( $file_path, false, 'f' );
792
+ }
793
+
794
+ /**
795
+ * Tell if a file should be deleted.
796
+ *
797
+ * @since 1.6.6
798
+ * @author Grégory Viguier
799
+ *
800
+ * @param string $file_path The file path.
801
+ * @return bool True to delete, false to keep.
802
+ */
803
+ protected function file_should_be_deleted( $file_path ) {
804
+ if ( ! $file_path || ! $this->delete_files ) {
805
+ // We keep the file.
806
+ return false;
807
+ }
808
+
809
+ /** This hook is documented in /amazon-s3-and-cloudfront/classes/amazon-s3-and-cloudfront.php. */
810
+ $preserve = apply_filters( 'as3cf_preserve_file_from_local_removal', false, $file_path );
811
+
812
+ return false === $preserve;
813
+ }
814
+
815
+
816
+ /** ----------------------------------------------------------------------------------------- */
817
+ /** VARIOUS TOOLS =========================================================================== */
818
+ /** ----------------------------------------------------------------------------------------- */
819
+
820
+ /**
821
+ * Tell if the attachment has a supported mime type.
822
+ *
823
+ * @since 1.6.6
824
+ * @author Grégory Viguier
825
+ *
826
+ * @return bool
827
+ */
828
+ public function is_mime_type_supported() {
829
+ return $this->id && imagify_as3cf()->is_mime_type_supported( $this->id );
830
+ }
831
+ }
inc/3rd-party/amazon-s3-and-cloudfront/inc/classes/class-imagify-as3cf.php ADDED
@@ -0,0 +1,295 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined( 'ABSPATH' ) || die( 'Cheatin\' uh?' );
3
+
4
+ /**
5
+ * Imagify WP Offload S3 class.
6
+ *
7
+ * @since 1.6.6
8
+ * @author Grégory Viguier
9
+ */
10
+ class Imagify_AS3CF {
11
+
12
+ /**
13
+ * Class version.
14
+ *
15
+ * @var string
16
+ */
17
+ const VERSION = '1.0';
18
+
19
+ /**
20
+ * Context used with get_imagify_attachment_class_name().
21
+ * It matches the class name Imagify_AS3CF_Attachment.
22
+ *
23
+ * @var string
24
+ */
25
+ const CONTEXT = 'AS3CF';
26
+
27
+ /**
28
+ * An array containing the IDs (as keys) of attachments just being uploaded.
29
+ *
30
+ * @var array
31
+ */
32
+ protected $uploads = array();
33
+
34
+ /**
35
+ * The single instance of the class.
36
+ *
37
+ * @var object
38
+ */
39
+ protected static $_instance;
40
+
41
+ /**
42
+ * Get the main Instance.
43
+ *
44
+ * Ensures only one instance of class is loaded or can be loaded.
45
+ *
46
+ * @since 1.6.6
47
+ * @author Grégory Viguier
48
+ *
49
+ * @return object Main instance.
50
+ */
51
+ public static function get_instance() {
52
+ if ( ! isset( self::$_instance ) ) {
53
+ self::$_instance = new self();
54
+ }
55
+
56
+ return self::$_instance;
57
+ }
58
+
59
+ /**
60
+ * The class constructor.
61
+ *
62
+ * @since 1.6.6
63
+ * @author Grégory Viguier
64
+ */
65
+ protected function __construct() {}
66
+
67
+ /**
68
+ * Launch the hooks.
69
+ *
70
+ * @since 1.6.6
71
+ * @author Grégory Viguier
72
+ */
73
+ public function init() {
74
+ static $done = false;
75
+
76
+ if ( $done ) {
77
+ return;
78
+ }
79
+ $done = true;
80
+
81
+ /**
82
+ * One context to rule 'em all.
83
+ */
84
+ add_filter( 'imagify_optimize_attachment_context', array( $this, 'optimize_attachment_context' ), 10, 2 );
85
+
86
+ /**
87
+ * Automatic optimisation.
88
+ */
89
+ // Remove some of our hooks: let S3 work first in these cases.
90
+ remove_filter( 'wp_generate_attachment_metadata', '_imagify_optimize_attachment', PHP_INT_MAX );
91
+ remove_action( 'wp_ajax_imagify_async_optimize_as3cf', '_do_admin_post_async_optimize_upload_new_media' );
92
+ remove_action( 'shutdown', '_imagify_optimize_save_image_editor_file' );
93
+ remove_action( 'wp_ajax_imagify_async_optimize_save_image_editor_file', '_do_admin_post_async_optimize_save_image_editor_file' );
94
+
95
+ // Store the IDs of the attachments being uploaded.
96
+ add_filter( 'wp_generate_attachment_metadata', array( $this, 'store_upload_ids' ), 10, 2 );
97
+ // Once uploaded to S3, launch the async optimization.
98
+ add_filter( 'wp_update_attachment_metadata', array( $this, 'do_async_job' ), 210, 2 );
99
+ // Do the optimization in a new thread.
100
+ add_action( 'wp_ajax_imagify_async_optimize_as3cf', array( $this, 'optimize' ) );
101
+ }
102
+
103
+
104
+ /** ----------------------------------------------------------------------------------------- */
105
+ /** VARIOUS HOOKS =========================================================================== */
106
+ /** ----------------------------------------------------------------------------------------- */
107
+
108
+ /**
109
+ * Filter the context used for the optimization (and other stuff).
110
+ * That way, we'll use the class Imagify_AS3CF_Attachment everywhere (instead of Imagify_Attachment), and make all the manual optimizations fine.
111
+ *
112
+ * @since 1.6.6
113
+ * @author Grégory Viguier
114
+ *
115
+ * @param string $context The context to determine the class name.
116
+ * @param int $attachment_id The attachment ID.
117
+ * @return string The new context.
118
+ */
119
+ public function optimize_attachment_context( $context, $attachment_id ) {
120
+ if ( self::CONTEXT === $context || $this->is_mime_type_supported( $attachment_id ) ) {
121
+ return self::CONTEXT;
122
+ }
123
+ return $context;
124
+ }
125
+
126
+
127
+ /** ----------------------------------------------------------------------------------------- */
128
+ /** AUTOMATIC OPTIMIZATION: OPTIMIZE AFTER S3 HAS DONE ITS WORK ============================= */
129
+ /** ----------------------------------------------------------------------------------------- */
130
+
131
+ /**
132
+ * Filter the generated attachment meta data.
133
+ * This is used when a new attachment has just been uploaded (or not, when wp_generate_attachment_metadata() is used).
134
+ * We use it to tell the difference later in wp_update_attachment_metadata().
135
+ *
136
+ * @since 1.6.6
137
+ * @author Grégory Viguier
138
+ * @see $this->do_async_job()
139
+ *
140
+ * @param array $metadata An array of attachment meta data.
141
+ * @param int $attachment_id Current attachment ID.
142
+ * @return array
143
+ */
144
+ public function store_upload_ids( $metadata, $attachment_id ) {
145
+
146
+ if ( $this->is_mime_type_supported( $attachment_id ) ) {
147
+ $this->uploads[ $attachment_id ] = 1;
148
+ }
149
+
150
+ return $metadata;
151
+ }
152
+
153
+ /**
154
+ * After an image (maybe) being sent to S3, launch an async optimization.
155
+ *
156
+ * @since 1.6.6
157
+ * @author Grégory Viguier
158
+ * @see $this->store_upload_ids()
159
+ *
160
+ * @param array $metadata An array of attachment meta data.
161
+ * @param int $attachment_id Current attachment ID.
162
+ * @return array
163
+ */
164
+ public function do_async_job( $metadata, $attachment_id ) {
165
+ static $auto_optimize;
166
+
167
+ $is_new_upload = ! empty( $this->uploads[ $attachment_id ] );
168
+ unset( $this->uploads[ $attachment_id ] );
169
+
170
+ if ( ! $metadata || ! $this->is_mime_type_supported( $attachment_id ) ) {
171
+ return $metadata;
172
+ }
173
+
174
+ if ( ! isset( $auto_optimize ) ) {
175
+ $auto_optimize = get_imagify_option( 'api_key' ) && get_imagify_option( 'auto_optimize' );
176
+ }
177
+
178
+ if ( $is_new_upload && ! $auto_optimize ) {
179
+ // It's a new upload and auto-optimization is disabled.
180
+ return $metadata;
181
+ }
182
+
183
+ if ( ! $is_new_upload && ! get_post_meta( $attachment_id, '_imagify_data', true ) ) {
184
+ // It's not a new upload and the attachment is not optimized yet.
185
+ return $metadata;
186
+ }
187
+
188
+ $data = array();
189
+
190
+ // Some specifics for the image editor.
191
+ if ( isset( $_POST['action'], $_POST['do'], $_POST['postid'] ) && 'image-editor' === $_POST['action'] && (int) $_POST['postid'] === $attachment_id ) { // WPCS: CSRF ok.
192
+ check_ajax_referer( 'image_editor-' . $_POST['postid'] );
193
+ $data = $_POST;
194
+ }
195
+
196
+ imagify_do_async_job( array(
197
+ 'action' => 'imagify_async_optimize_as3cf',
198
+ '_ajax_nonce' => wp_create_nonce( 'imagify_async_optimize_as3cf' ),
199
+ 'post_id' => $attachment_id,
200
+ 'metadata' => $metadata,
201
+ 'data' => $data,
202
+ ) );
203
+
204
+ return $metadata;
205
+ }
206
+
207
+ /**
208
+ * Once an image has been sent to S3, optimize it and send it again.
209
+ *
210
+ * @since 1.6.6
211
+ * @author Grégory Viguier
212
+ */
213
+ public function optimize() {
214
+ global $as3cf;
215
+
216
+ check_ajax_referer( 'imagify_async_optimize_as3cf' );
217
+
218
+ if ( empty( $_POST['post_id'] ) || ! current_user_can( 'upload_files' ) ) {
219
+ die();
220
+ }
221
+
222
+ $attachment_id = absint( $_POST['post_id'] );
223
+
224
+ if ( ! $attachment_id || empty( $_POST['metadata'] ) || ! is_array( $_POST['metadata'] ) || empty( $_POST['metadata']['sizes'] ) ) {
225
+ die();
226
+ }
227
+
228
+ if ( ! $this->is_mime_type_supported( $attachment_id ) ) {
229
+ die();
230
+ }
231
+
232
+ $optimization_level = null;
233
+ $class_name = get_imagify_attachment_class_name( self::CONTEXT, $attachment_id, 'as3cf_optimize' );
234
+ $attachment = new $class_name( $attachment_id );
235
+
236
+ // Some specifics for the image editor.
237
+ if ( ! empty( $_POST['data']['do'] ) ) {
238
+ $optimization_level = (int) get_post_meta( $attachment_id, '_imagify_optimization_level', true );
239
+
240
+ // Remove old optimization data.
241
+ $attachment->delete_imagify_data();
242
+
243
+ if ( 'restore' === $_POST['data']['do'] ) {
244
+ // Restore the backup file.
245
+ $attachment->restore();
246
+ }
247
+ }
248
+
249
+ // Optimize it.
250
+ $attachment->optimize( $optimization_level, $_POST['metadata'] );
251
+ }
252
+
253
+
254
+ /** ----------------------------------------------------------------------------------------- */
255
+ /** TOOLS =================================================================================== */
256
+ /** ----------------------------------------------------------------------------------------- */
257
+
258
+ /**
259
+ * Tell if the attachment has a supported mime type.
260
+ *
261
+ * @since 1.6.6
262
+ * @author Grégory Viguier
263
+ *
264
+ * @param int $post_id The attachment ID.
265
+ * @return bool
266
+ */
267
+ public function is_mime_type_supported( $post_id ) {
268
+ static $is = array( false );
269
+
270
+ $post_id = absint( $post_id );
271
+
272
+ if ( isset( $is[ $post_id ] ) ) {
273
+ return $is[ $post_id ];
274
+ }
275
+
276
+ $mime_types = get_imagify_mime_type();
277
+ $mime_types = array_flip( $mime_types );
278
+ $mime_type = get_post_mime_type( $post_id );
279
+ $is[ $post_id ] = isset( $mime_types[ $mime_type ] );
280
+
281
+ return $is[ $post_id ];
282
+ }
283
+ }
284
+
285
+ /**
286
+ * Returns the main instance of the Imagify_AS3CF class.
287
+ *
288
+ * @since 1.6.6
289
+ * @author Grégory Viguier
290
+ *
291
+ * @return object The Imagify_AS3CF instance.
292
+ */
293
+ function imagify_as3cf() {
294
+ return Imagify_AS3CF::get_instance();
295
+ }
inc/3rd-party/enable-media-replace.php CHANGED
@@ -21,13 +21,11 @@ if ( function_exists( 'emr_delete_current_files' ) ) :
21
  }
22
 
23
  $optimization_level = get_post_meta( $attachment_id, '_imagify_optimization_level', true );
24
- $class_name = get_imagify_attachment_class_name( 'wp' );
25
  $attachment = new $class_name( $attachment_id );
26
 
27
  // Remove old optimization data.
28
- delete_post_meta( $attachment_id, '_imagify_data' );
29
- delete_post_meta( $attachment_id, '_imagify_status' );
30
- delete_post_meta( $attachment_id, '_imagify_optimization_level' );
31
 
32
  // Optimize it!!!!!
33
  $attachment->optimize( $optimization_level );
21
  }
22
 
23
  $optimization_level = get_post_meta( $attachment_id, '_imagify_optimization_level', true );
24
+ $class_name = get_imagify_attachment_class_name( 'wp', $attachment_id, 'enable-media-replace-upload-done' );
25
  $attachment = new $class_name( $attachment_id );
26
 
27
  // Remove old optimization data.
28
+ $attachment->delete_imagify_data();
 
 
29
 
30
  // Optimize it!!!!!
31
  $attachment->optimize( $optimization_level );
inc/3rd-party/hosting/wpengine.php CHANGED
File without changes
inc/3rd-party/nextgen-gallery/inc/admin/heartbeat.php CHANGED
@@ -23,7 +23,7 @@ function _imagify_ngg_heartbeat_received( $response, $data ) {
23
  $user = new Imagify_User();
24
 
25
  $response['imagify_bulk_data'] = array(
26
- 'already_optimized_attachments' => $saving_data['count'],
27
  'optimized_attachments' => imagify_ngg_count_optimized_attachments(),
28
  'unoptimized_attachments' => imagify_ngg_count_unoptimized_attachments(),
29
  'errors_attachments' => imagify_ngg_count_error_attachments(),
23
  $user = new Imagify_User();
24
 
25
  $response['imagify_bulk_data'] = array(
26
+ 'already_optimized_attachments' => number_format_i18n( $saving_data['count'] ),
27
  'optimized_attachments' => imagify_ngg_count_optimized_attachments(),
28
  'unoptimized_attachments' => imagify_ngg_count_unoptimized_attachments(),
29
  'errors_attachments' => imagify_ngg_count_error_attachments(),
inc/3rd-party/nextgen-gallery/inc/classes/class-imagify-ngg-attachment.php CHANGED
@@ -14,7 +14,7 @@ class Imagify_NGG_Attachment extends Imagify_Attachment {
14
  *
15
  * @var string
16
  */
17
- const VERSION = '1.0.1';
18
 
19
  /**
20
  * The image object.
@@ -191,19 +191,28 @@ class Imagify_NGG_Attachment extends Imagify_Attachment {
191
  *
192
  * @since 1.5
193
  * @since 1.6.5 Not static anymore.
 
194
  * @author Jonathan Buttigieg
195
  * @access public
196
  *
197
  * @param array $data The statistics data.
198
  * @param object $response The API response.
199
- * @param int $id The attachment ID.
200
  * @param int $url The attachment URL.
201
  * @param string $size The attachment size key.
202
  * @return bool|array False if the original size has an error or an array contains the data for other result.
203
  */
204
- public function fill_data( $data, $response, $id, $url, $size = 'full' ) {
 
205
  $data['sizes'] = ! empty( $data['sizes'] ) && is_array( $data['sizes'] ) ? $data['sizes'] : array();
206
 
 
 
 
 
 
 
 
 
207
  if ( is_wp_error( $response ) ) {
208
  $error = $response->get_error_message();
209
  $error_status = 'error';
@@ -219,8 +228,8 @@ class Imagify_NGG_Attachment extends Imagify_Attachment {
219
  $error_status = 'already_optimized';
220
  }
221
 
222
- imagify_ngg_db()->update( $id, array(
223
- 'pid' => $id,
224
  'status' => $error_status,
225
  'data' => serialize( $data ),
226
  ) );
@@ -264,19 +273,9 @@ class Imagify_NGG_Attachment extends Imagify_Attachment {
264
  public function optimize( $optimization_level = null, $metadata = array() ) {
265
  $optimization_level = is_null( $optimization_level ) ? (int) get_imagify_option( 'optimization_level', 1 ) : (int) $optimization_level;
266
 
267
- $data = array(
268
- 'stats' => array(
269
- 'original_size' => 0,
270
- 'optimized_size' => 0,
271
- 'percent' => 0,
272
- ),
273
- );
274
-
275
  // To avoid issue with "original_size" at 0 in "_imagify_data".
276
  if ( 0 === (int) $this->get_stats_data( 'original_size' ) ) {
277
- delete_post_meta( $this->id, '_imagify_data' );
278
- delete_post_meta( $this->id, '_imagify_status' );
279
- delete_post_meta( $this->id, '_imagify_optimization_level' );
280
  }
281
 
282
  // Get file path & URL for original image.
@@ -342,7 +341,8 @@ class Imagify_NGG_Attachment extends Imagify_Attachment {
342
  'resized' => $resized,
343
  'original_size' => $attachment_original_size,
344
  ) );
345
- $data = $this->fill_data( $data, $response, $this->id, $attachment_url );
 
346
 
347
  if ( ! $data ) {
348
  delete_transient( 'imagify-ngg-async-in-progress-' . $this->id );
@@ -432,7 +432,8 @@ class Imagify_NGG_Attachment extends Imagify_Attachment {
432
  'optimization_level' => $optimization_level,
433
  'context' => 'wp',
434
  ) );
435
- $data = $this->fill_data( $data, $response, $this->id, $thumbnail_url, $size_key );
 
436
 
437
  /**
438
  * Filter the optimization data of a specific thumbnail.
14
  *
15
  * @var string
16
  */
17
+ const VERSION = '1.0.2';
18
 
19
  /**
20
  * The image object.
191
  *
192
  * @since 1.5
193
  * @since 1.6.5 Not static anymore.
194
+ * @since 1.6.6 Removed the attachment ID parameter.
195
  * @author Jonathan Buttigieg
196
  * @access public
197
  *
198
  * @param array $data The statistics data.
199
  * @param object $response The API response.
 
200
  * @param int $url The attachment URL.
201
  * @param string $size The attachment size key.
202
  * @return bool|array False if the original size has an error or an array contains the data for other result.
203
  */
204
+ public function fill_data( $data, $response, $url, $size = 'full' ) {
205
+ $data = is_array( $data ) ? $data : array();
206
  $data['sizes'] = ! empty( $data['sizes'] ) && is_array( $data['sizes'] ) ? $data['sizes'] : array();
207
 
208
+ if ( empty( $data['stats'] ) ) {
209
+ $data['stats'] = array(
210
+ 'original_size' => 0,
211
+ 'optimized_size' => 0,
212
+ 'percent' => 0,
213
+ );
214
+ }
215
+
216
  if ( is_wp_error( $response ) ) {
217
  $error = $response->get_error_message();
218
  $error_status = 'error';
228
  $error_status = 'already_optimized';
229
  }
230
 
231
+ imagify_ngg_db()->update( $this->id, array(
232
+ 'pid' => $this->id,
233
  'status' => $error_status,
234
  'data' => serialize( $data ),
235
  ) );
273
  public function optimize( $optimization_level = null, $metadata = array() ) {
274
  $optimization_level = is_null( $optimization_level ) ? (int) get_imagify_option( 'optimization_level', 1 ) : (int) $optimization_level;
275
 
 
 
 
 
 
 
 
 
276
  // To avoid issue with "original_size" at 0 in "_imagify_data".
277
  if ( 0 === (int) $this->get_stats_data( 'original_size' ) ) {
278
+ $this->delete_imagify_data();
 
 
279
  }
280
 
281
  // Get file path & URL for original image.
341
  'resized' => $resized,
342
  'original_size' => $attachment_original_size,
343
  ) );
344
+
345
+ $data = $this->fill_data( null, $response, $attachment_url );
346
 
347
  if ( ! $data ) {
348
  delete_transient( 'imagify-ngg-async-in-progress-' . $this->id );
432
  'optimization_level' => $optimization_level,
433
  'context' => 'wp',
434
  ) );
435
+
436
+ $data = $this->fill_data( $data, $response, $thumbnail_url, $size_key );
437
 
438
  /**
439
  * Filter the optimization data of a specific thumbnail.
inc/3rd-party/nextgen-gallery/inc/classes/class-imagify-ngg-db.php CHANGED
File without changes
inc/3rd-party/nextgen-gallery/inc/common/attachments.php CHANGED
@@ -55,7 +55,7 @@ add_filter( 'ngg_medialibrary_imported_image', '_imagify_ngg_media_library_impor
55
  * @return object
56
  */
57
  function _imagify_ngg_media_library_imported_image_data( $image, $attachment ) {
58
- $class_name = get_imagify_attachment_class_name( 'wp' );
59
  $attachment = new $class_name( $attachment->ID );
60
 
61
  if ( ! $attachment->is_optimized() ) {
55
  * @return object
56
  */
57
  function _imagify_ngg_media_library_imported_image_data( $image, $attachment ) {
58
+ $class_name = get_imagify_attachment_class_name( 'wp', $attachment->ID, 'ngg_medialibrary_imported_image' );
59
  $attachment = new $class_name( $attachment->ID );
60
 
61
  if ( ! $attachment->is_optimized() ) {
inc/3rd-party/nextgen-gallery/inc/functions/admin-stats.php CHANGED
@@ -101,5 +101,7 @@ function imagify_ngg_percent_optimized_attachments() {
101
  function imagify_ngg_count_saving_data() {
102
  global $wpdb;
103
 
 
 
104
  return $wpdb->get_col( "SELECT $table_name.data FROM {$wpdb->ngg_imagify_data} WHERE status = 'success'" ); // WPCS: unprepared SQL ok.
105
  }
101
  function imagify_ngg_count_saving_data() {
102
  global $wpdb;
103
 
104
+ $table_name = $wpdb->ngg_imagify_data;
105
+
106
  return $wpdb->get_col( "SELECT $table_name.data FROM {$wpdb->ngg_imagify_data} WHERE status = 'success'" ); // WPCS: unprepared SQL ok.
107
  }
inc/3rd-party/wp-retina-2x.php CHANGED
@@ -79,10 +79,10 @@ if ( function_exists( 'wr2x_get_retina' ) ) :
79
  'optimization_level' => $optimization_level,
80
  'context' => 'wp-retina',
81
  ) );
82
- $class_name = get_imagify_attachment_class_name( 'wp' );
83
  $attachment = new $class_name( $id );
84
 
85
- return $attachment->fill_data( $data, $response, $id, $url, $size_key . '@2x' );
86
  }
87
 
88
  endif;
79
  'optimization_level' => $optimization_level,
80
  'context' => 'wp-retina',
81
  ) );
82
+ $class_name = get_imagify_attachment_class_name( 'wp', $id, 'imagify_fill_thumbnail_data' );
83
  $attachment = new $class_name( $id );
84
 
85
+ return $attachment->fill_data( $data, $response, $url, $size_key . '@2x' );
86
  }
87
 
88
  endif;
inc/admin/ajax.php CHANGED
@@ -30,7 +30,7 @@ function _do_admin_post_imagify_manual_upload() {
30
 
31
  $context = esc_html( $_GET['context'] );
32
  $attachment_id = absint( $_GET['attachment_id'] );
33
- $class_name = get_imagify_attachment_class_name( $context );
34
  $attachment = new $class_name( $attachment_id );
35
 
36
  // Optimize it!!!!!
@@ -71,7 +71,7 @@ function _do_admin_post_imagify_manual_override_upload() {
71
 
72
  $context = esc_html( $_GET['context'] );
73
  $attachment_id = absint( $_GET['attachment_id'] );
74
- $class_name = get_imagify_attachment_class_name( $context );
75
  $attachment = new $class_name( $attachment_id );
76
 
77
  // Restore the backup file.
@@ -115,7 +115,7 @@ function _do_admin_post_imagify_restore_upload() {
115
 
116
  $context = esc_html( $_GET['context'] );
117
  $attachment_id = absint( $_GET['attachment_id'] );
118
- $class_name = get_imagify_attachment_class_name( $context );
119
  $attachment = new $class_name( $attachment_id );
120
 
121
  // Restore the backup file.
@@ -147,7 +147,7 @@ function _do_wp_ajax_imagify_bulk_upload() {
147
 
148
  $context = esc_html( $_POST['context'] );
149
  $attachment_id = absint( $_POST['image'] );
150
- $class_name = get_imagify_attachment_class_name( $context );
151
  $attachment = new $class_name( $attachment_id );
152
  $optimization_level = get_transient( 'imagify_bulk_optimization_level' );
153
 
@@ -205,7 +205,7 @@ function _do_admin_post_async_optimize_upload_new_media() {
205
 
206
  $context = esc_html( $_POST['context'] );
207
  $attachment_id = absint( $_POST['attachment_id'] );
208
- $class_name = get_imagify_attachment_class_name( $context );
209
  $attachment = new $class_name( $attachment_id );
210
 
211
  // Optimize it!!!!!
@@ -234,14 +234,12 @@ function _do_admin_post_async_optimize_save_image_editor_file() {
234
  }
235
 
236
  $optimization_level = (int) get_post_meta( $attachment_id, '_imagify_optimization_level', true );
237
- $class_name = get_imagify_attachment_class_name( 'wp' );
238
  $attachment = new $class_name( $attachment_id );
239
  $metadata = wp_get_attachment_metadata( $attachment_id );
240
 
241
  // Remove old optimization data.
242
- delete_post_meta( $attachment_id, '_imagify_data' );
243
- delete_post_meta( $attachment_id, '_imagify_status' );
244
- delete_post_meta( $attachment_id, '_imagify_optimization_level' );
245
 
246
  if ( 'restore' === $_POST['do'] ) {
247
  // Restore the backup file.
30
 
31
  $context = esc_html( $_GET['context'] );
32
  $attachment_id = absint( $_GET['attachment_id'] );
33
+ $class_name = get_imagify_attachment_class_name( $context, $attachment_id, 'imagify_manual_upload' );
34
  $attachment = new $class_name( $attachment_id );
35
 
36
  // Optimize it!!!!!
71
 
72
  $context = esc_html( $_GET['context'] );
73
  $attachment_id = absint( $_GET['attachment_id'] );
74
+ $class_name = get_imagify_attachment_class_name( $context, $attachment_id, 'imagify_manual_override_upload' );
75
  $attachment = new $class_name( $attachment_id );
76
 
77
  // Restore the backup file.
115
 
116
  $context = esc_html( $_GET['context'] );
117
  $attachment_id = absint( $_GET['attachment_id'] );
118
+ $class_name = get_imagify_attachment_class_name( $context, $attachment_id, 'imagify_restore_upload' );
119
  $attachment = new $class_name( $attachment_id );
120
 
121
  // Restore the backup file.
147
 
148
  $context = esc_html( $_POST['context'] );
149
  $attachment_id = absint( $_POST['image'] );
150
+ $class_name = get_imagify_attachment_class_name( $context, $attachment_id, 'imagify_bulk_upload' );
151
  $attachment = new $class_name( $attachment_id );
152
  $optimization_level = get_transient( 'imagify_bulk_optimization_level' );
153
 
205
 
206
  $context = esc_html( $_POST['context'] );
207
  $attachment_id = absint( $_POST['attachment_id'] );
208
+ $class_name = get_imagify_attachment_class_name( $context, $attachment_id, 'imagify_async_optimize_upload_new_media' );
209
  $attachment = new $class_name( $attachment_id );
210
 
211
  // Optimize it!!!!!
234
  }
235
 
236
  $optimization_level = (int) get_post_meta( $attachment_id, '_imagify_optimization_level', true );
237
+ $class_name = get_imagify_attachment_class_name( 'wp', $attachment_id, 'wp_ajax_imagify_async_optimize_save_image_editor_file' );
238
  $attachment = new $class_name( $attachment_id );
239
  $metadata = wp_get_attachment_metadata( $attachment_id );
240
 
241
  // Remove old optimization data.
242
+ $attachment->delete_imagify_data();
 
 
243
 
244
  if ( 'restore' === $_POST['do'] ) {
245
  // Restore the backup file.
inc/admin/enqueue.php CHANGED
@@ -13,78 +13,106 @@ function _imagify_admin_print_styles() {
13
  $css_ext = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '.css' : '.min.css';
14
  $js_ext = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '.js' : '.min.js';
15
 
 
 
 
16
  wp_register_style(
17
- 'imagify-css-admin',
18
- IMAGIFY_ASSETS_CSS_URL . 'admin' . $css_ext,
19
  array(),
20
- IMAGIFY_VERSION
21
  );
22
 
 
 
 
23
  wp_register_style(
24
- 'imagify-css-sweetalert',
25
- IMAGIFY_ASSETS_CSS_URL . 'sweetalert2' . $css_ext,
26
  array(),
27
  IMAGIFY_VERSION
28
  );
29
 
30
  wp_register_style(
31
- 'imagify-css-twentytwenty',
32
- IMAGIFY_ASSETS_CSS_URL . 'twentytwenty' . $css_ext,
33
  array(),
34
  IMAGIFY_VERSION
35
  );
36
 
 
 
 
37
  wp_register_script(
38
- 'imagify-js-async',
39
- IMAGIFY_ASSETS_JS_URL . 'imagify' . $js_ext,
40
- array( 'imagify-js-bulk' ),
41
- IMAGIFY_VERSION,
42
  true
43
  );
44
 
45
  wp_register_script(
46
- 'imagify-js-admin',
47
- IMAGIFY_ASSETS_JS_URL . 'admin' . $js_ext,
 
 
 
 
 
 
 
 
48
  array(),
49
- IMAGIFY_VERSION,
50
  true
51
  );
52
 
53
  wp_register_script(
54
- 'imagify-js-options',
55
- IMAGIFY_ASSETS_JS_URL . 'options' . $js_ext,
 
 
 
 
 
 
 
 
 
 
 
56
  array(),
57
  IMAGIFY_VERSION,
58
  true
59
  );
60
 
61
  wp_register_script(
62
- 'imagify-js-upload',
63
- IMAGIFY_ASSETS_JS_URL . 'upload' . $js_ext,
64
- array( 'jquery' ),
65
  IMAGIFY_VERSION,
66
  true
67
  );
68
 
69
  wp_register_script(
70
- 'imagify-js-sweetalert',
71
- IMAGIFY_ASSETS_JS_URL . 'sweetalert2' . $js_ext,
72
- array( 'jquery' ),
73
  IMAGIFY_VERSION,
74
  true
75
  );
76
 
77
  wp_register_script(
78
- 'imagify-js-chart',
79
- IMAGIFY_ASSETS_JS_URL . 'chart' . $js_ext,
80
- array(),
81
  IMAGIFY_VERSION,
82
  true
83
  );
84
 
85
  wp_register_script(
86
- 'imagify-js-bulk',
87
- IMAGIFY_ASSETS_JS_URL . 'bulk' . $js_ext,
88
  array( 'jquery', 'imagify-js-chart' ),
89
  IMAGIFY_VERSION,
90
  true
@@ -97,72 +125,53 @@ function _imagify_admin_print_styles() {
97
  IMAGIFY_VERSION,
98
  true
99
  );
100
- wp_register_script(
101
- 'imagify-js-event-move',
102
- IMAGIFY_ASSETS_JS_URL . 'jquery.event.move' . $js_ext,
103
- array( 'jquery' ),
104
- IMAGIFY_VERSION,
105
- true
106
- );
107
 
108
  /*
109
- * Styles loaded in the whole admnistration.
110
  */
111
  wp_enqueue_style( 'imagify-css-admin' );
112
  wp_enqueue_style( 'imagify-css-sweetalert' );
113
 
114
- /*
115
- * Scripts loaded in the whole admnistration.
116
- */
117
- wp_enqueue_script( 'imagify-js-sweetalert' );
118
- wp_enqueue_script( 'imagify-js-admin' );
119
-
120
- $admin_data = get_imagify_localize_script_translations( 'admin' );
121
- wp_localize_script( 'imagify-js-admin', 'imagifyAdmin', $admin_data );
122
  wp_enqueue_script( 'imagify-js-admin' );
 
123
 
124
  /*
125
- * Scripts loaded in /wp-admin/options-general.php?page=imagify.
126
  */
127
  if ( isset( $current_screen ) && ( 'settings_page_imagify' === $current_screen->base || 'settings_page_imagify-network' === $current_screen->base ) ) {
128
- wp_enqueue_script( 'imagify-js-chart' );
129
- wp_enqueue_script( 'imagify-js-event-move' );
130
- wp_enqueue_script( 'imagify-js-twentytwenty' );
131
- wp_enqueue_script( 'imagify-js-options' );
132
  wp_enqueue_style( 'imagify-css-twentytwenty' );
133
 
134
- $options_data = get_imagify_localize_script_translations( 'options' );
135
- wp_localize_script( 'imagify-js-options', 'imagifyOptions', $options_data );
 
136
  }
137
 
138
  /**
139
- * Scripts loaded in /wp-admin/upload.php and post.php.
140
  */
141
  if ( isset( $current_screen ) && ( 'upload' === $current_screen->base || 'post' === $current_screen->base ) ) {
142
- $upload_data = get_imagify_localize_script_translations( 'upload' );
143
- wp_localize_script( 'imagify-js-upload', 'imagifyUpload', $upload_data );
144
- wp_enqueue_script( 'imagify-js-chart' );
145
  wp_enqueue_script( 'imagify-js-upload' );
 
146
  }
147
 
148
  /**
149
- * Scripts loaded in:
150
  * /wp-admin/post.php (for attachment post type),
151
  * /wp-admin/upload.php (for attachments list).
152
  */
153
  if ( isset( $current_screen ) && ( ('post' === $current_screen->base && 'attachment' === $current_screen->post_type ) || 'upload' === $current_screen->base ) ) {
154
- wp_localize_script( 'imagify-js-twentytwenty', 'imagifyTTT', get_imagify_localize_script_translations( 'twentytwenty' ) );
155
- wp_enqueue_script( 'imagify-js-chart' );
156
- wp_enqueue_script( 'imagify-js-event-move' );
157
- wp_enqueue_script( 'imagify-js-twentytwenty' );
158
  wp_enqueue_style( 'imagify-css-twentytwenty' );
 
 
 
159
  }
160
 
161
  /**
162
- * Scripts loaded in /wp-admin/upload.php?page=imagify-bulk-optimization.
163
  */
164
  if ( isset( $current_screen ) && 'media_page_imagify-bulk-optimization' === $current_screen->base ) {
165
  wp_enqueue_script( 'heartbeat' );
 
166
 
167
  $bulk_data = get_imagify_localize_script_translations( 'bulk' );
168
  $bulk_data['heartbeat_id'] = 'update_bulk_data';
@@ -180,9 +189,6 @@ function _imagify_admin_print_styles() {
180
  $bulk_data['buffer_size'] = apply_filters( 'imagify_bulk_buffer_size', $bulk_data['buffer_size'] );
181
 
182
  wp_localize_script( 'imagify-js-bulk', 'imagifyBulk', $bulk_data );
183
- wp_enqueue_script( 'imagify-js-chart' );
184
- wp_enqueue_script( 'imagify-js-async' );
185
- wp_enqueue_script( 'imagify-js-bulk' );
186
  }
187
  }
188
 
13
  $css_ext = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '.css' : '.min.css';
14
  $js_ext = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '.js' : '.min.js';
15
 
16
+ /**
17
+ * 3rd Party Styles.
18
+ */
19
  wp_register_style(
20
+ 'imagify-css-sweetalert',
21
+ IMAGIFY_ASSETS_CSS_URL . 'sweetalert2' . $css_ext,
22
  array(),
23
+ '4.0.15'
24
  );
25
 
26
+ /**
27
+ * Imagify Styles.
28
+ */
29
  wp_register_style(
30
+ 'imagify-css-twentytwenty',
31
+ IMAGIFY_ASSETS_CSS_URL . 'twentytwenty' . $css_ext,
32
  array(),
33
  IMAGIFY_VERSION
34
  );
35
 
36
  wp_register_style(
37
+ 'imagify-css-admin',
38
+ IMAGIFY_ASSETS_CSS_URL . 'admin' . $css_ext,
39
  array(),
40
  IMAGIFY_VERSION
41
  );
42
 
43
+ /**
44
+ * 3rd Party Scripts.
45
+ */
46
  wp_register_script(
47
+ 'imagify-js-promise-polyfill',
48
+ IMAGIFY_ASSETS_JS_URL . 'es6-promise.auto' . $js_ext,
49
+ array(),
50
+ '4.1.0',
51
  true
52
  );
53
 
54
  wp_register_script(
55
+ 'imagify-js-sweetalert',
56
+ IMAGIFY_ASSETS_JS_URL . 'sweetalert2' . $js_ext,
57
+ array( 'jquery', 'imagify-js-promise-polyfill' ),
58
+ '4.0.15',
59
+ true
60
+ );
61
+
62
+ wp_register_script(
63
+ 'imagify-js-chart',
64
+ IMAGIFY_ASSETS_JS_URL . 'chart' . $js_ext,
65
  array(),
66
+ '1.0.2',
67
  true
68
  );
69
 
70
  wp_register_script(
71
+ 'imagify-js-event-move',
72
+ IMAGIFY_ASSETS_JS_URL . 'jquery.event.move' . $js_ext,
73
+ array( 'jquery' ),
74
+ '1.3.6',
75
+ true
76
+ );
77
+
78
+ /**
79
+ * Imagify Scripts.
80
+ */
81
+ wp_register_script(
82
+ 'imagify-js-async',
83
+ IMAGIFY_ASSETS_JS_URL . 'imagify' . $js_ext,
84
  array(),
85
  IMAGIFY_VERSION,
86
  true
87
  );
88
 
89
  wp_register_script(
90
+ 'imagify-js-bulk',
91
+ IMAGIFY_ASSETS_JS_URL . 'bulk' . $js_ext,
92
+ array( 'jquery', 'imagify-js-chart', 'imagify-js-sweetalert', 'imagify-js-async' ),
93
  IMAGIFY_VERSION,
94
  true
95
  );
96
 
97
  wp_register_script(
98
+ 'imagify-js-admin',
99
+ IMAGIFY_ASSETS_JS_URL . 'admin' . $js_ext,
100
+ array( 'jquery', 'imagify-js-sweetalert' ),
101
  IMAGIFY_VERSION,
102
  true
103
  );
104
 
105
  wp_register_script(
106
+ 'imagify-js-options',
107
+ IMAGIFY_ASSETS_JS_URL . 'options' . $js_ext,
108
+ array( 'jquery', 'imagify-js-sweetalert' ),
109
  IMAGIFY_VERSION,
110
  true
111
  );
112
 
113
  wp_register_script(
114
+ 'imagify-js-upload',
115
+ IMAGIFY_ASSETS_JS_URL . 'upload' . $js_ext,
116
  array( 'jquery', 'imagify-js-chart' ),
117
  IMAGIFY_VERSION,
118
  true
125
  IMAGIFY_VERSION,
126
  true
127
  );
 
 
 
 
 
 
 
128
 
129
  /*
130
+ * Loaded in the whole admnistration.
131
  */
132
  wp_enqueue_style( 'imagify-css-admin' );
133
  wp_enqueue_style( 'imagify-css-sweetalert' );
134
 
 
 
 
 
 
 
 
 
135
  wp_enqueue_script( 'imagify-js-admin' );
136
+ wp_localize_script( 'imagify-js-admin', 'imagifyAdmin', get_imagify_localize_script_translations( 'admin' ) );
137
 
138
  /*
139
+ * Loaded in /wp-admin/options-general.php?page=imagify.
140
  */
141
  if ( isset( $current_screen ) && ( 'settings_page_imagify' === $current_screen->base || 'settings_page_imagify-network' === $current_screen->base ) ) {
 
 
 
 
142
  wp_enqueue_style( 'imagify-css-twentytwenty' );
143
 
144
+ wp_enqueue_script( 'imagify-js-twentytwenty' );
145
+ wp_enqueue_script( 'imagify-js-options' );
146
+ wp_localize_script( 'imagify-js-options', 'imagifyOptions', get_imagify_localize_script_translations( 'options' ) );
147
  }
148
 
149
  /**
150
+ * Loaded in /wp-admin/upload.php and post.php.
151
  */
152
  if ( isset( $current_screen ) && ( 'upload' === $current_screen->base || 'post' === $current_screen->base ) ) {
 
 
 
153
  wp_enqueue_script( 'imagify-js-upload' );
154
+ wp_localize_script( 'imagify-js-upload', 'imagifyUpload', get_imagify_localize_script_translations( 'upload' ) );
155
  }
156
 
157
  /**
158
+ * Loaded in:
159
  * /wp-admin/post.php (for attachment post type),
160
  * /wp-admin/upload.php (for attachments list).
161
  */
162
  if ( isset( $current_screen ) && ( ('post' === $current_screen->base && 'attachment' === $current_screen->post_type ) || 'upload' === $current_screen->base ) ) {
 
 
 
 
163
  wp_enqueue_style( 'imagify-css-twentytwenty' );
164
+
165
+ wp_enqueue_script( 'imagify-js-twentytwenty' );
166
+ wp_localize_script( 'imagify-js-twentytwenty', 'imagifyTTT', get_imagify_localize_script_translations( 'twentytwenty' ) );
167
  }
168
 
169
  /**
170
+ * Loaded in /wp-admin/upload.php?page=imagify-bulk-optimization.
171
  */
172
  if ( isset( $current_screen ) && 'media_page_imagify-bulk-optimization' === $current_screen->base ) {
173
  wp_enqueue_script( 'heartbeat' );
174
+ wp_enqueue_script( 'imagify-js-bulk' );
175
 
176
  $bulk_data = get_imagify_localize_script_translations( 'bulk' );
177
  $bulk_data['heartbeat_id'] = 'update_bulk_data';
189
  $bulk_data['buffer_size'] = apply_filters( 'imagify_bulk_buffer_size', $bulk_data['buffer_size'] );
190
 
191
  wp_localize_script( 'imagify-js-bulk', 'imagifyBulk', $bulk_data );
 
 
 
192
  }
193
  }
194
 
inc/admin/heartbeat.php CHANGED
@@ -22,7 +22,7 @@ function _imagify_heartbeat_received( $response, $data ) {
22
  $user = new Imagify_User();
23
 
24
  $response['imagify_bulk_data'] = array(
25
- 'already_optimized_attachments' => $saving_data['count'],
26
  'optimized_attachments' => imagify_count_optimized_attachments(),
27
  'unoptimized_attachments' => imagify_count_unoptimized_attachments(),
28
  'errors_attachments' => imagify_count_error_attachments(),
22
  $user = new Imagify_User();
23
 
24
  $response['imagify_bulk_data'] = array(
25
+ 'already_optimized_attachments' => number_format_i18n( $saving_data['count'] ),
26
  'optimized_attachments' => imagify_count_optimized_attachments(),
27
  'unoptimized_attachments' => imagify_count_unoptimized_attachments(),
28
  'errors_attachments' => imagify_count_error_attachments(),
inc/admin/media.php CHANGED
@@ -19,7 +19,7 @@ function _imagify_attachment_fields_to_edit( $form_fields, $post ) {
19
  return $form_fields;
20
  }
21
 
22
- $class_name = get_imagify_attachment_class_name( 'wp' );
23
  $attachment = new $class_name( $post->ID );
24
 
25
  $form_fields['imagify'] = array(
@@ -50,7 +50,7 @@ function _imagify_add_actions_to_media_list_row( $actions, $post ) {
50
  return $actions;
51
  }
52
 
53
- $class_name = get_imagify_attachment_class_name( 'wp' );
54
  $attachment = new $class_name( $post->ID );
55
 
56
  // If Imagify license not valid, or image is not optimized, do nothing.
19
  return $form_fields;
20
  }
21
 
22
+ $class_name = get_imagify_attachment_class_name( 'wp', $post->ID, 'attachment_fields_to_edit' );
23
  $attachment = new $class_name( $post->ID );
24
 
25
  $form_fields['imagify'] = array(
50
  return $actions;
51
  }
52
 
53
+ $class_name = get_imagify_attachment_class_name( 'wp', $post->ID, 'media_row_actions' );
54
  $attachment = new $class_name( $post->ID );
55
 
56
  // If Imagify license not valid, or image is not optimized, do nothing.
inc/admin/meta-boxes.php CHANGED
@@ -14,7 +14,7 @@ function _imagify_attachment_submitbox_misc_actions() {
14
  return;
15
  }
16
 
17
- $class_name = get_imagify_attachment_class_name( 'wp' );
18
  $attachment = new $class_name( $post->ID );
19
 
20
  if ( ! imagify_valid_key() && ! $attachment->is_optimized() ) {
14
  return;
15
  }
16
 
17
+ $class_name = get_imagify_attachment_class_name( 'wp', $post->ID, 'attachment_submitbox_misc_actions' );
18
  $attachment = new $class_name( $post->ID );
19
 
20
  if ( ! imagify_valid_key() && ! $attachment->is_optimized() ) {
inc/admin/upgrader.php CHANGED
@@ -82,7 +82,7 @@ function _imagify_new_upgrade( $imagify_version, $current_version ) {
82
 
83
  if ( $query->posts ) {
84
  foreach ( (array) $query->posts as $id ) {
85
- $class_name = get_imagify_attachment_class_name( 'wp' );
86
  $attachment = new $class_name( $id );
87
  $attachment_error = $attachment->get_optimized_error();
88
  $attachment_error = trim( $attachment_error );
@@ -126,7 +126,7 @@ function _imagify_new_upgrade( $imagify_version, $current_version ) {
126
 
127
  if ( $query->posts ) {
128
  foreach ( (array) $query->posts as $id ) {
129
- $class_name = get_imagify_attachment_class_name( 'wp' );
130
  $attachment = new $class_name( $id );
131
  $attachment_stats = $attachment->get_stats_data();
132
 
82
 
83
  if ( $query->posts ) {
84
  foreach ( (array) $query->posts as $id ) {
85
+ $class_name = get_imagify_attachment_class_name( 'wp', $id, 'imagify_upgrade' );
86
  $attachment = new $class_name( $id );
87
  $attachment_error = $attachment->get_optimized_error();
88
  $attachment_error = trim( $attachment_error );
126
 
127
  if ( $query->posts ) {
128
  foreach ( (array) $query->posts as $id ) {
129
+ $class_name = get_imagify_attachment_class_name( 'wp', $id, 'imagify_upgrade' );
130
  $attachment = new $class_name( $id );
131
  $attachment_stats = $attachment->get_stats_data();
132
 
inc/admin/upload.php CHANGED
@@ -31,7 +31,7 @@ function _imagify_manage_media_custom_column( $column_name, $attachment_id ) {
31
  return;
32
  }
33
 
34
- $class_name = get_imagify_attachment_class_name( 'wp' );
35
  $attachment = new $class_name( $attachment_id );
36
 
37
  echo get_imagify_media_column_content( $attachment );
31
  return;
32
  }
33
 
34
+ $class_name = get_imagify_attachment_class_name( 'wp', $attachment_id, 'manage_media_custom_column' );
35
  $attachment = new $class_name( $attachment_id );
36
 
37
  echo get_imagify_media_column_content( $attachment );
inc/api/imagify.php CHANGED
File without changes
inc/classes/abstracts/class-imagify-abstract-attachment.php CHANGED
@@ -13,7 +13,7 @@ class Imagify_Abstract_Attachment {
13
  *
14
  * @var string
15
  */
16
- const VERSION = '1.0.1';
17
 
18
  /**
19
  * The attachment ID.
@@ -117,6 +117,19 @@ class Imagify_Abstract_Attachment {
117
  return -1;
118
  }
119
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  /**
121
  * Get the attachment optimization level label.
122
  *
@@ -372,16 +385,16 @@ class Imagify_Abstract_Attachment {
372
  *
373
  * @since 1.0
374
  * @since 1.6.5 Not static anymore.
 
375
  * @access public
376
  *
377
  * @param array $data The statistics data.
378
  * @param object $response The API response.
379
- * @param int $id The attachment ID.
380
  * @param int $url The attachment URL.
381
  * @param string $size The attachment size key.
382
  * @return bool|array False if the original size has an error or an array contains the data for other result.
383
  */
384
- public function fill_data( $data, $response, $id, $url, $size = 'full' ) {
385
  return array();
386
  }
387
 
13
  *
14
  * @var string
15
  */
16
+ const VERSION = '1.0.2';
17
 
18
  /**
19
  * The attachment ID.
117
  return -1;
118
  }
119
 
120
+ /**
121
+ * Delete the 3 metas used by Imagify.
122
+ *
123
+ * @since 1.6.6
124
+ * @access public
125
+ * @author Grégory Viguier
126
+ */
127
+ public function delete_imagify_data() {
128
+ delete_post_meta( $this->id, '_imagify_data' );
129
+ delete_post_meta( $this->id, '_imagify_status' );
130
+ delete_post_meta( $this->id, '_imagify_optimization_level' );
131
+ }
132
+
133
  /**
134
  * Get the attachment optimization level label.
135
  *
385
  *
386
  * @since 1.0
387
  * @since 1.6.5 Not static anymore.
388
+ * @since 1.6.6 Removed the attachment ID parameter.
389
  * @access public
390
  *
391
  * @param array $data The statistics data.
392
  * @param object $response The API response.
 
393
  * @param int $url The attachment URL.
394
  * @param string $size The attachment size key.
395
  * @return bool|array False if the original size has an error or an array contains the data for other result.
396
  */
397
+ public function fill_data( $data, $response, $url, $size = 'full' ) {
398
  return array();
399
  }
400
 
inc/classes/abstracts/class-imagify-abstract-db.php CHANGED
File without changes
inc/classes/class-imagify-attachment.php CHANGED
@@ -13,7 +13,7 @@ class Imagify_Attachment extends Imagify_Abstract_Attachment {
13
  *
14
  * @var string
15
  */
16
- const VERSION = '1.0.1';
17
 
18
  /**
19
  * The constructor
@@ -146,18 +146,27 @@ class Imagify_Attachment extends Imagify_Abstract_Attachment {
146
  *
147
  * @since 1.0
148
  * @since 1.6.5 Not static anymore.
 
149
  * @access public
150
  *
151
  * @param array $data The statistics data.
152
  * @param object $response The API response.
153
- * @param int $id The attachment ID.
154
  * @param int $url The attachment URL.
155
  * @param string $size The attachment size key.
156
  * @return bool|array False if the original size has an error or an array contains the data for other result.
157
  */
158
- public function fill_data( $data, $response, $id, $url, $size = 'full' ) {
 
159
  $data['sizes'] = ! empty( $data['sizes'] ) && is_array( $data['sizes'] ) ? $data['sizes'] : array();
160
 
 
 
 
 
 
 
 
 
161
  if ( is_wp_error( $response ) ) {
162
  $error = $response->get_error_message();
163
  $error_status = 'error';
@@ -169,13 +178,13 @@ class Imagify_Attachment extends Imagify_Abstract_Attachment {
169
 
170
  // Update the error status for the original size.
171
  if ( 'full' === $size ) {
172
- update_post_meta( $id, '_imagify_data', $data );
173
 
174
  if ( false !== strpos( $error, 'This image is already compressed' ) ) {
175
  $error_status = 'already_optimized';
176
  }
177
 
178
- update_post_meta( $id, '_imagify_status', $error_status );
179
 
180
  return false;
181
  }
@@ -216,19 +225,10 @@ class Imagify_Attachment extends Imagify_Abstract_Attachment {
216
 
217
  $metadata = $metadata ? $metadata : wp_get_attachment_metadata( $this->id );
218
  $sizes = isset( $metadata['sizes'] ) ? (array) $metadata['sizes'] : array();
219
- $data = array(
220
- 'stats' => array(
221
- 'original_size' => 0,
222
- 'optimized_size' => 0,
223
- 'percent' => 0,
224
- ),
225
- );
226
 
227
  // To avoid issue with "original_size" at 0 in "_imagify_data".
228
  if ( 0 === (int) $this->get_stats_data( 'original_size' ) ) {
229
- delete_post_meta( $this->id, '_imagify_data' );
230
- delete_post_meta( $this->id, '_imagify_status' );
231
- delete_post_meta( $this->id, '_imagify_optimization_level' );
232
  }
233
 
234
  // Get file path & URL for original image.
@@ -299,7 +299,8 @@ class Imagify_Attachment extends Imagify_Abstract_Attachment {
299
  'resized' => $resized,
300
  'original_size' => $attachment_original_size,
301
  ) );
302
- $data = $this->fill_data( $data, $response, $this->id, $attachment_url );
 
303
 
304
  if ( ! $data ) {
305
  delete_transient( 'imagify-async-in-progress-' . $this->id );
@@ -336,7 +337,8 @@ class Imagify_Attachment extends Imagify_Abstract_Attachment {
336
  'optimization_level' => $optimization_level,
337
  'context' => 'wp',
338
  ) );
339
- $data = $this->fill_data( $data, $response, $this->id, $thumbnail_url, $size_key );
 
340
 
341
  /**
342
  * Filter the optimization data of a specific thumbnail.
@@ -417,9 +419,7 @@ class Imagify_Attachment extends Imagify_Abstract_Attachment {
417
  wp_generate_attachment_metadata( $this->id, $attachment_path );
418
 
419
  // Remove old optimization data.
420
- delete_post_meta( $this->id, '_imagify_data' );
421
- delete_post_meta( $this->id, '_imagify_status' );
422
- delete_post_meta( $this->id, '_imagify_optimization_level' );
423
 
424
  // Restore the original size in the metadata.
425
  $this->update_metadata_size();
13
  *
14
  * @var string
15
  */
16
+ const VERSION = '1.0.2';
17
 
18
  /**
19
  * The constructor
146
  *
147
  * @since 1.0
148
  * @since 1.6.5 Not static anymore.
149
+ * @since 1.6.6 Removed the attachment ID parameter.
150
  * @access public
151
  *
152
  * @param array $data The statistics data.
153
  * @param object $response The API response.
 
154
  * @param int $url The attachment URL.
155
  * @param string $size The attachment size key.
156
  * @return bool|array False if the original size has an error or an array contains the data for other result.
157
  */
158
+ public function fill_data( $data, $response, $url, $size = 'full' ) {
159
+ $data = is_array( $data ) ? $data : array();
160
  $data['sizes'] = ! empty( $data['sizes'] ) && is_array( $data['sizes'] ) ? $data['sizes'] : array();
161
 
162
+ if ( empty( $data['stats'] ) ) {
163
+ $data['stats'] = array(
164
+ 'original_size' => 0,
165
+ 'optimized_size' => 0,
166
+ 'percent' => 0,
167
+ );
168
+ }
169
+
170
  if ( is_wp_error( $response ) ) {
171
  $error = $response->get_error_message();
172
  $error_status = 'error';
178
 
179
  // Update the error status for the original size.
180
  if ( 'full' === $size ) {
181
+ update_post_meta( $this->id, '_imagify_data', $data );
182
 
183
  if ( false !== strpos( $error, 'This image is already compressed' ) ) {
184
  $error_status = 'already_optimized';
185
  }
186
 
187
+ update_post_meta( $this->id, '_imagify_status', $error_status );
188
 
189
  return false;
190
  }
225
 
226
  $metadata = $metadata ? $metadata : wp_get_attachment_metadata( $this->id );
227
  $sizes = isset( $metadata['sizes'] ) ? (array) $metadata['sizes'] : array();
 
 
 
 
 
 
 
228
 
229
  // To avoid issue with "original_size" at 0 in "_imagify_data".
230
  if ( 0 === (int) $this->get_stats_data( 'original_size' ) ) {
231
+ $this->delete_imagify_data();
 
 
232
  }
233
 
234
  // Get file path & URL for original image.
299
  'resized' => $resized,
300
  'original_size' => $attachment_original_size,
301
  ) );
302
+
303
+ $data = $this->fill_data( null, $response, $attachment_url );
304
 
305
  if ( ! $data ) {
306
  delete_transient( 'imagify-async-in-progress-' . $this->id );
337
  'optimization_level' => $optimization_level,
338
  'context' => 'wp',
339
  ) );
340
+
341
+ $data = $this->fill_data( $data, $response, $thumbnail_url, $size_key );
342
 
343
  /**
344
  * Filter the optimization data of a specific thumbnail.
419
  wp_generate_attachment_metadata( $this->id, $attachment_path );
420
 
421
  // Remove old optimization data.
422
+ $this->delete_imagify_data();
 
 
423
 
424
  // Restore the original size in the metadata.
425
  $this->update_metadata_size();
inc/classes/class-imagify.php CHANGED
File without changes
inc/common/attachments.php CHANGED
@@ -37,7 +37,7 @@ add_action( 'delete_attachment', '_imagify_delete_backup_file' );
37
  * @param int $post_id Attachment ID.
38
  */
39
  function _imagify_delete_backup_file( $post_id ) {
40
- $class_name = get_imagify_attachment_class_name( 'wp' );
41
  $attachment = new $class_name( $post_id );
42
  $attachment->delete_backup();
43
  }
37
  * @param int $post_id Attachment ID.
38
  */
39
  function _imagify_delete_backup_file( $post_id ) {
40
+ $class_name = get_imagify_attachment_class_name( 'wp', $post_id, 'delete_attachment' );
41
  $attachment = new $class_name( $post_id );
42
  $attachment->delete_backup();
43
  }
inc/functions/admin-stats.php CHANGED
@@ -231,7 +231,7 @@ function imagify_count_saving_data( $key = '' ) {
231
  continue;
232
  }
233
 
234
- $stats_data = $attachment_data['stats'];
235
  $original_data = $attachment_data['sizes']['full'];
236
 
237
  // Increment the original sizes.
@@ -241,7 +241,7 @@ function imagify_count_saving_data( $key = '' ) {
241
  unset( $attachment_data['sizes']['full'] );
242
 
243
  // Increment the thumbnails sizes.
244
- foreach ( $attachment_data['sizes'] as $size_key => $size_data ) {
245
  if ( ! empty( $size_data['success'] ) ) {
246
  $original_size += $size_data['original_size'];
247
  $optimized_size += $size_data['optimized_size'];
@@ -250,7 +250,7 @@ function imagify_count_saving_data( $key = '' ) {
250
  }
251
 
252
  $data = array(
253
- 'count' => count( $attachments ),
254
  'original_size' => $original_size,
255
  'optimized_size' => $optimized_size,
256
  'percent' => $optimized_size ? ceil( ( ( $original_size - $optimized_size ) / $original_size ) * 100 ) : 0,
231
  continue;
232
  }
233
 
234
+ ++$count;
235
  $original_data = $attachment_data['sizes']['full'];
236
 
237
  // Increment the original sizes.
241
  unset( $attachment_data['sizes']['full'] );
242
 
243
  // Increment the thumbnails sizes.
244
+ foreach ( $attachment_data['sizes'] as $size_data ) {
245
  if ( ! empty( $size_data['success'] ) ) {
246
  $original_size += $size_data['original_size'];
247
  $optimized_size += $size_data['optimized_size'];
250
  }
251
 
252
  $data = array(
253
+ 'count' => $count,
254
  'original_size' => $original_size,
255
  'optimized_size' => $optimized_size,
256
  'percent' => $optimized_size ? ceil( ( ( $original_size - $optimized_size ) / $original_size ) * 100 ) : 0,
inc/functions/admin-ui.php CHANGED
File without changes
inc/functions/deprecated.php CHANGED
File without changes
inc/functions/formatting.php CHANGED
@@ -36,15 +36,28 @@ function imagify_round_half_five( $number ) {
36
  /**
37
  * Get the Imagify attachment class name depending to a context.
38
  *
39
- * @since 1.5
40
- * @source Jonathan Buttigieg
 
41
  *
42
- * @param string $context The context to determine the class name.
43
- * @return string $class_name The Imagify attachment class name.
 
 
44
  */
45
- function get_imagify_attachment_class_name( $context = 'wp' ) {
46
- $class_name = 'Imagify_';
47
- $class_name .= 'wp' !== $context ? $context . '_Attachment' : 'Attachment';
 
 
 
 
 
 
 
 
 
 
48
 
49
- return $class_name;
50
  }
36
  /**
37
  * Get the Imagify attachment class name depending to a context.
38
  *
39
+ * @since 1.5
40
+ * @since 1.6.6 $attachment_id and $identifier have been added.
41
+ * @author Jonathan Buttigieg
42
  *
43
+ * @param string $context The context to determine the class name.
44
+ * @param int $attachment_id The attachment ID.
45
+ * @param string $identifier An identifier.
46
+ * @return string The Imagify attachment class name.
47
  */
48
+ function get_imagify_attachment_class_name( $context, $attachment_id, $identifier ) {
49
+ $context = $context ? $context : 'wp';
50
+ /**
51
+ * Filter the context used for the optimization.
52
+ *
53
+ * @since 1.6.6
54
+ * @author Grégory Viguier
55
+ *
56
+ * @param string $context The context.
57
+ * @param int $attachment_id The attachment ID.
58
+ * @param string $identifier An identifier.
59
+ */
60
+ $context = apply_filters( 'imagify_optimize_attachment_context', $context, $attachment_id, $identifier );
61
 
62
+ return 'Imagify_' . ( 'wp' !== $context ? $context . '_' : '' ) . 'Attachment';
63
  }
inc/functions/process.php CHANGED
@@ -165,5 +165,15 @@ function imagify_do_async_job( $body ) {
165
  'sslverify' => apply_filters( 'https_local_ssl_verify', false ),
166
  );
167
 
 
 
 
 
 
 
 
 
 
 
168
  wp_remote_post( admin_url( 'admin-ajax.php' ), $args );
169
  }
165
  'sslverify' => apply_filters( 'https_local_ssl_verify', false ),
166
  );
167
 
168
+ /**
169
+ * Filter the arguments used to launch an async job.
170
+ *
171
+ * @since 1.6.6
172
+ * @author Grégory Viguier
173
+ *
174
+ * @param array $args An array of arguments passed to wp_remote_post().
175
+ */
176
+ $args = apply_filters( 'imagify_do_async_job_args', $args );
177
+
178
  wp_remote_post( admin_url( 'admin-ajax.php' ), $args );
179
  }
readme.txt CHANGED
@@ -3,7 +3,7 @@ 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: 3.7.0
5
  Tested up to: 4.8.0
6
- Stable tag: 1.6.5
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
 
@@ -136,11 +136,17 @@ When the plugin is disabled, your existing images remain optimized. Backups of t
136
  3. Media Page
137
 
138
  == Changelog ==
 
 
 
 
 
 
139
  = 1.6.5 =
140
  * Improvement: Code quality of the whole plugin has been improved to fit more WordPress coding standards.
141
- * Improvement: Lots of internationalisation improvements. Now the plugin's internationalisation fully rely on the repository system.
142
  * Bug Fix: Fixed an error with php 7.1: `Uncaught Error: [] operator not supported for strings in /wp-content/plugins/imagify/inc/functions/admin.php:134`.
143
-
144
  = 1.6.4 =
145
  * Improvement: Provide a link to optimize in higher level when an image is already optimized.
146
  * Improvement: Add a dedicated message for 413 HTTP error when the image is too big to be uploaded on our servers.
@@ -304,7 +310,7 @@ When the plugin is disabled, your existing images remain optimized. Backups of t
304
  * Improvement: When your bulk optimization is over, success message isn't inside the table anymore
305
  * Improvement: To quit the bulk optimization processing you have to confirm your action
306
  * Bug Fix: JS: `console` undefined on some IE browsers
307
- * Bug Fix: PHP Warning: Illegal string offset 'sizes' in ../inc/functions/admin-stats.php on line 180
308
  * Bug Fix: Don't count GIF & SVG in the Imagify statistics
309
 
310
  = 1.1.5 =
3
  Tags: compress image, images, performance, optimization, photos, upload, resize, gif, png, jpg, reduce image size, retina
4
  Requires at least: 3.7.0
5
  Tested up to: 4.8.0
6
+ Stable tag: 1.6.6
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
 
136
  3. Media Page
137
 
138
  == Changelog ==
139
+ = 1.6.6 =
140
+ * New: Compatibility with the plugin WP Offload S3 Lite. Your images now will be sent to Amazon S3 after being optimized. Also works when you store your images only on S3, not locally.
141
+ * Improvement: Added a filter to the asynchronous job arguments.
142
+ * Bug fix: Compatibility with Internet Explorer 9 to 11.
143
+ * Regression fix: The comparison tool stopped working in the medias list since the previous version.
144
+
145
  = 1.6.5 =
146
  * Improvement: Code quality of the whole plugin has been improved to fit more WordPress coding standards.
147
+ * Improvement: Lots of internationalization improvements. Now the plugin's internationalization fully rely on the repository system.
148
  * Bug Fix: Fixed an error with php 7.1: `Uncaught Error: [] operator not supported for strings in /wp-content/plugins/imagify/inc/functions/admin.php:134`.
149
+
150
  = 1.6.4 =
151
  * Improvement: Provide a link to optimize in higher level when an image is already optimized.
152
  * Improvement: Add a dedicated message for 413 HTTP error when the image is too big to be uploaded on our servers.
310
  * Improvement: When your bulk optimization is over, success message isn't inside the table anymore
311
  * Improvement: To quit the bulk optimization processing you have to confirm your action
312
  * Bug Fix: JS: `console` undefined on some IE browsers
313
+ * Bug Fix: PHP Warning: `Illegal string offset 'sizes' in ../inc/functions/admin-stats.php on line 180`
314
  * Bug Fix: Don't count GIF & SVG in the Imagify statistics
315
 
316
  = 1.1.5 =