From 44fa95e5896c70af6b19cdcc41ab6845258daea8 Mon Sep 17 00:00:00 2001 From: Chris Klosowski Date: Mon, 11 Sep 2023 18:11:30 -0700 Subject: [PATCH] Adding release/3.2.1 code --- .buildkite/pipeline.yml | 81 ----- Gruntfile.js | 61 ++-- assets/js/admin/downloads/index.js | 2 + assets/js/edd-admin-downloads.js | 2 +- bin/.exclude | 22 -- bin/update-stripe.sh | 38 --- easy-digital-downloads.php | 2 +- includes/.blocks-hash | 1 - includes/admin/admin-bar.php | 4 +- includes/admin/class-edd-notices.php | 68 +++- includes/admin/plugins.php | 5 +- includes/api/class-edd-api.php | 125 +++---- includes/class-easy-digital-downloads.php | 2 +- includes/class-edd-license-handler.php | 4 +- includes/gateways/.stripe-hash | 1 - .../gateways/paypal/webhooks/functions.php | 98 ++++-- .../includes/admin/upgrade-functions.php | 23 -- .../stripe/includes/class-edd-stripe.php | 1 + includes/payments/class-edd-payment.php | 2 +- includes/upgrades/functions.php | 18 +- languages/easy-digital-downloads.pot | 311 ++++++++++-------- package.json | 8 +- readme.txt | 7 +- src/Admin/Extensions/ExtensionPage.php | 36 +- src/Admin/PassHandler/Settings.php | 8 + src/Core.php | 1 - src/Gateways/Stripe/Admin/LicenseManager.php | 81 +++-- src/Gateways/Stripe/ApplicationFee.php | 2 +- src/Gateways/Stripe/License.php | 99 +++++- src/Licensing/Traits/Controls.php | 2 +- tests/orders/tests-edd-payment.php | 4 + tests/stripe/admin/tests-license-manager.php | 4 - tests/stripe/tests-application-fee.php | 2 +- tests/tests-api.php | 87 ++++- 34 files changed, 701 insertions(+), 511 deletions(-) delete mode 100644 .buildkite/pipeline.yml delete mode 100644 bin/.exclude delete mode 100755 bin/update-stripe.sh delete mode 100644 includes/.blocks-hash delete mode 100644 includes/gateways/.stripe-hash diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml deleted file mode 100644 index a7de93a420..0000000000 --- a/.buildkite/pipeline.yml +++ /dev/null @@ -1,81 +0,0 @@ -steps: - - - label: "Pull PHP 7.4" - command: "docker pull -q public.ecr.aws/q7y6e9n2/unit-test-images/php:7.4" - retry: - automatic: true - - - label: "Pull PHP 8.0" - command: "docker pull -q public.ecr.aws/q7y6e9n2/unit-test-images/php:8.0" - retry: - automatic: true - - - wait - - - label: "Pull PHP 8.1" - command: "docker pull -q public.ecr.aws/q7y6e9n2/unit-test-images/php:8.1" - retry: - automatic: true - - - label: "Pull MariaDB" - command: "docker pull -q mariadb:10.4" - retry: - automatic: true - - - wait - - - env: - TEST_INPLACE: "0" - TEST_PHP_VERSION: "7.4" - TEST_WP_VERSION: "5.8.6" - WP_MULTISITE: "0" - COMPOSE_HTTP_TIMEOUT: 180 - DOCKER_CLIENT_TIMEOUT: 180 - label: 'PHP: 7.4 | WP: 5.8.6 | Multisite: 0' - plugins: - - docker-compose#v4.14.0: - config: docker-compose-phpunit.yml - propagate-environment: true - propagate-uid-gid: true - skip-pull: true - run: wordpress - - - env: - TEST_INPLACE: "0" - TEST_PHP_VERSION: "{{matrix.php}}" - TEST_WP_VERSION: "{{matrix.wp}}" - WP_MULTISITE: "{{matrix.multisite}}" - COMPOSE_HTTP_TIMEOUT: 180 - DOCKER_CLIENT_TIMEOUT: 180 - label: 'PHP: "{{matrix.php}}" | WP: "{{matrix.wp}}" | Multisite: {{matrix.multisite}}' - plugins: - - docker-compose#v4.14.0: - config: docker-compose-phpunit.yml - propagate-environment: true - propagate-uid-gid: true - skip-pull: true - run: wordpress - matrix: - setup: # Max of 6 Dimensions. - php: # Max of 20 elements. - - "8.0" - - "8.1" - wp: - - "6.1.2" - - "6.2.2" - - "latest" - multisite: - - "0" - adjustments: # Max of 12 adjustments. - - with: - php: "8.1" - wp: "latest" - multisite: "1" - - with: - php: "8.0" - wp: "5.9.5" - multisite: "0" - - with: - php: "8.1" - wp: "6.0.3" - multisite: "0" diff --git a/Gruntfile.js b/Gruntfile.js index 0fa987553b..863d3744b4 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -45,6 +45,7 @@ module.exports = function ( grunt ) { // Clean up build directory clean: { main: [ 'build/**' ], + repo: [ 'build/<%= pkg.name %>-public/**' ], }, // Copy the plugin into the build directory @@ -115,6 +116,33 @@ module.exports = function ( grunt ) { ], dest: 'build/<%= pkg.name %>/', }, + repo: { + src: [ + '**', + 'assets/**', + '!assets/pro/**', + '!build/**', + 'i18n/**', + 'includes/**', + '!includes/blocks/pro/**', + '!includes/blocks/assets/pro/**', + '!includes/blocks/build/pro/**', + '!includes/blocks/node_modules/**', + '!includes/blocks/src/pro/**', + 'languages/**', + 'libraries/**', + '!node_modules/**', + 'templates/**', + 'vendor/**', + 'src/**', + '!assets/pro/**', + '!vendor/**', + 'vendor/autoload.php', + 'vendor/composer/**', + 'vendor/symfony/deprecation-contracts/**' + ], + dest: 'build/<%= pkg.name %>-public/', + } }, // Compress build directory into .zip and -.zip @@ -142,41 +170,26 @@ module.exports = function ( grunt ) { }, replace: { - blocks: { + pro: { options: { patterns: [ { - match: /init_blocks/g, - replacement: 'init_core_blocks', - expression: true, - }, - { - match: /update_required_pages/g, - replacement: 'update_core_required_pages', - expression: true, - }, - { - match: /remove_action(.*);/g, - replacement: '', - expression: true, - }, - { - match: /remove_filter(.*);/g, - replacement: '', + match: /Plugin Name: Easy Digital Downloads \(Pro\)/g, + replacement: 'Plugin Name: Easy Digital Downloads', expression: true, - }, + } ] }, files: [ { expand: true, flatten: true, - src: [ 'includes/blocks/edd-blocks.php' ], - dest: 'includes/blocks' + src: [ 'build/easy-digital-downloads/easy-digital-downloads.php' ], + dest: 'build/easy-digital-downloads' } ] }, - pro: { + repo: { options: { patterns: [ { @@ -190,8 +203,8 @@ module.exports = function ( grunt ) { { expand: true, flatten: true, - src: [ 'build/easy-digital-downloads/easy-digital-downloads.php' ], - dest: 'build/easy-digital-downloads' + src: [ 'build/easy-digital-downloads-public/easy-digital-downloads.php' ], + dest: 'build/easy-digital-downloads-public' } ] } diff --git a/assets/js/admin/downloads/index.js b/assets/js/admin/downloads/index.js index b16a776baf..998684f215 100644 --- a/assets/js/admin/downloads/index.js +++ b/assets/js/admin/downloads/index.js @@ -231,6 +231,7 @@ var EDD_Download_Configuration = { } ); if ( 'bundle' === product_type ) { + product_files.show(); edd_download_limit_wrap.hide(); } else if ( 'service' === $( this ).val() ) { const has_files = product_files.find( '.edd_upload_field' ).toArray().some( el => !!el.value ); @@ -245,6 +246,7 @@ var EDD_Download_Configuration = { edd_download_limit_wrap.show(); } } else { + product_files.show(); edd_download_limit_wrap.show(); } } ); diff --git a/assets/js/edd-admin-downloads.js b/assets/js/edd-admin-downloads.js index c245d4509a..b369f639b2 100644 --- a/assets/js/edd-admin-downloads.js +++ b/assets/js/edd-admin-downloads.js @@ -1 +1 @@ -!function(e){var t={};function i(n){if(t[n])return t[n].exports;var a=t[n]={i:n,l:!1,exports:{}};return e[n].call(a.exports,a,a.exports,i),a.l=!0,a.exports}i.m=e,i.c=t,i.d=function(e,t,n){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(i.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var a in e)i.d(n,a,function(t){return e[t]}.bind(null,a));return n},i.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="",i(i.s=301)}({1:function(e,t){e.exports=jQuery},12:function(e,t,i){var n=i(5).default,a=i(14);e.exports=function(e){var t=a(e,"string");return"symbol"===n(t)?t:String(t)},e.exports.__esModule=!0,e.exports.default=e.exports},14:function(e,t,i){var n=i(5).default;e.exports=function(e,t){if("object"!==n(e)||null===e)return e;var i=e[Symbol.toPrimitive];if(void 0!==i){var a=i.call(e,t||"default");if("object"!==n(a))return a;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)},e.exports.__esModule=!0,e.exports.default=e.exports},20:function(e,t,i){"use strict";(function(e){i.d(t,"a",(function(){return l}));var n=i(3),a=i.n(n);function r(e,t){var i=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),i.push.apply(i,n)}return i}function d(e){for(var t=1;tn&&(n=t)})),i=n+=1;var r=t.clone();return r.removeClass("edd_add_blank"),r.attr("data-key",i),r.find("input, select, textarea").val("").each((function(){var t=e(this),n=t.attr("name"),a=t.attr("id");n&&(n=n.replace(/\[(\d+)\]/,"["+parseInt(i)+"]"),t.attr("name",n)),t.attr("data-key",i),void 0!==a&&(a=a.replace(/(\d+)/,parseInt(i)),t.attr("id",a))})),r.find("select").each((function(){e(this).val(t.find('select[name="'+e(this).attr("name")+'"]').val())})),r.find('input[type="checkbox"]').each((function(){e(this).is(":checked")&&e(this).prop("checked",!1),e(this).val(1)})),r.find("span.edd_price_id").each((function(){e(this).text(parseInt(i))})),r.find("input.edd_repeatable_index").each((function(){e(this).val(parseInt(e(this).data("key")))})),r.find("span.edd_file_id").each((function(){e(this).text(parseInt(i))})),r.find(".edd_repeatable_default_input").each((function(){e(this).val(parseInt(i)).removeAttr("checked")})),r.find(".edd_repeatable_condition_field").each((function(){e(this).find("option:eq(0)").prop("selected","selected")})),r.find("label").each((function(){var t=e(this).attr("for");t&&e(this).attr("for",t.replace(/(\d+)/,parseInt(i)))})),r.find(".search-choice").remove(),r.find(".chosen-container").remove(),Object(a.a)(r.find(".edd-help-tip")),r},add:function(){e(document.body).on("click",".edd_add_repeatable",(function(t){t.preventDefault();var i=e(this).closest(".edd_repeatable_table").find(".edd_repeatable_row").last(),n=r.clone_repeatable(i);n.insertAfter(i).find("input, textarea, select").filter(":visible").eq(0).focus(),r.initChosen(n)}))},move:function(){e(".edd_repeatable_table .edd-repeatables-wrap").sortable({axis:"y",handle:".edd-draghandle-anchor",items:".edd_repeatable_row",cursor:"move",tolerance:"pointer",containment:"parent",distance:2,opacity:.7,scroll:!0,update:function(){var t=0;e(this).find(".edd_repeatable_row").each((function(){e(this).find("input.edd_repeatable_index").each((function(){e(this).val(t)})),t++}))},start:function(e,t){t.placeholder.height(t.item.height()-2)}})},remove:function(){e(document.body).on("click",".edd-remove-row, .edd_remove_repeatable",(function(t){t.preventDefault();var i,n=e(this).parents(".edd_repeatable_row"),a=n.parent().find(".edd_repeatable_row").length,r=e(this).data("type"),d="div.edd_repeatable_"+r+"s";if(i=(e(this).is(".ui-sortable .edd_repeatable_row:first-child .edd-remove-row, .ui-sortable .edd_repeatable_row:first-child .edd_remove_repeatable")?n.next(".edd_repeatable_row"):n.prev(".edd_repeatable_row")).find("select, input, textarea, button").filter(":visible").eq(0),"price"===r){var o=n.data("key");e('.edd_repeatable_condition_field option[value="'+o+'"]').remove()}if(a>1)e("input, select",n).val(""),n.fadeOut("fast").remove(),i.focus();else switch(r){case"price":alert(edd_vars.one_price_min);break;case"file":e("input, select",n).val("");break;default:alert(edd_vars.one_field_min)}e(d).each((function(t){e(this).find("input, select").each((function(){var i=e(this).attr("name");i=i.replace(/\[(\d+)\]/,"["+t+"]"),e(this).attr("name",i).attr("id",i)}))}))}))},type:function(){var t=e("#edd_product_files");setTimeout((function(){edd_vars.download_has_files||"service"!==e("#_edd_product_type").val()||t.hide()}),100),e(document.body).on("change","#_edd_product_type",(function(i){var n=e(this).val(),a=e("#edd_download_limit_wrap");t.addClass("ajax--loading");var d={action:"edd_swap_download_type",product_type:n,post_id:edd_vars.post_id};e.post(ajaxurl,d,(function(e){e.success&&(t.find(".inside").empty().append(e.data.html),r.initChosen(t)),t.removeClass("ajax--loading")})),"bundle"===n?a.hide():"service"===e(this).val()?t.find(".edd_upload_field").toArray().some((function(e){return!!e.value}))?(t.show(),a.show()):(setTimeout((function(){t.hide()}),100),a.hide()):a.show()}))},prices:function(){e(document.body).on("change","#edd_variable_pricing",(function(t){var i=e(this).is(":checked"),n=e("#edd_regular_price_field"),a=e("#edd_variable_price_fields, .edd_repeatable_table .pricing"),r=e(".edd-bundled-product-row, .edd-repeatable-row-standard-fields");i?(n.hide(),a.show(),r.addClass("has-variable-pricing")):(n.show(),a.hide(),r.removeClass("has-variable-pricing"))}))},files:function(){var t;window.formfield="",e(document.body).on("click",".edd_upload_file_button",(function(i){i.preventDefault();var n=e(this);window.formfield=n.closest(".edd_repeatable_upload_wrapper"),t||((t=wp.media.frames.file_frame=wp.media({title:n.data("uploader-title"),frame:"post",state:"insert",button:{text:n.data("uploader-button-text")},multiple:"0"!==e(this).data("multiple")})).on("menu:render:default",(function(e){e.unset("library-separator"),e.unset("gallery"),e.unset("featured-image"),e.unset("embed"),e.unset("playlist"),e.unset("video-playlist"),e.set({})})),t.on("insert",(function(){t.state().get("selection").each((function(t,i){var n="image"===(t=t.toJSON()).type&&e(".attachment-display-settings .size option:selected").val(),a=t.url,d=t.title.length>0?t.title:t.filename;if(n&&void 0!==t.sizes[n]&&(a=t.sizes[n].url),"image"===t.type&&(d=n&&void 0!==t.sizes[n]?d+"-"+t.sizes[n].width+"x"+t.sizes[n].height:d+"-"+t.width+"x"+t.height),0===i)window.formfield.find(".edd_repeatable_attachment_id_field").val(t.id),window.formfield.find(".edd_repeatable_thumbnail_size_field").val(n),window.formfield.find(".edd_repeatable_upload_field").val(a),window.formfield.find(".edd_repeatable_name_field").val(d);else{var o=window.formfield,l=r.clone_repeatable(o);l.find(".edd_repeatable_attachment_id_field").val(t.id),l.find(".edd_repeatable_thumbnail_size_field").val(n),l.find(".edd_repeatable_upload_field").val(a),l.find(".edd_repeatable_name_field").val(d),l.insertAfter(o)}}))}))),t.open()})),e(".edd_repeatable_upload_field").on("focus",(function(){var t=e(this);t.data("originalFile",t.val())})).on("change",(function(){var t=e(this);t.data("originalFile")!==t.val()&&t.closest(".edd-repeatable-row-standard-fields").find(".edd_repeatable_attachment_id_field").val(0)})),window.formfield=""},updatePrices:function(){e("#edd_price_fields").on("keyup",".edd_variable_prices_name",(function(){var t=e(this).parents(".edd_repeatable_row").data("key"),i=e(this).val(),n=e(".edd_repeatable_condition_field option[value="+t+"]");n.length>0?n.text(i):e(".edd_repeatable_condition_field").append(e("").attr("value",t).text(i))}))},showAdvanced:function(){e(document.body).on("click",".toggle-custom-price-option-section",(function(t){t.preventDefault();var i=e(this),n=i.html()===edd_vars.show_advanced_settings;n?i.html(edd_vars.hide_advanced_settings):i.html(edd_vars.show_advanced_settings);var a=i.parents(".edd-repeatable-row-header");a.siblings(".edd-custom-price-option-sections-wrap").slideToggle(),e(":input:not(input[type=button],input[type=submit],button):visible:first",n?a.siblings(".edd-custom-price-option-sections-wrap"):a.siblings(".edd-repeatable-row-standard-fields")).focus()}))},initChosen:function(t){t.find(".edd-select-chosen").each((function(){var t=e(this);t.chosen(Object(n.a)(t))})),t.find(".edd-select-chosen").css("width","100%"),t.find(".edd-select-chosen .chosen-search input").attr("placeholder",edd_vars.search_placeholder)}});t(document).ready((function(e){r.init()}))}.call(this,i(1),i(1))},302:function(e,t,i){(function(e){e(document).ready((function(e){e("body").on("click","#the-list .editinline",(function(){var t=e(this).closest("tr").attr("id");t=t.replace("post-","");var i=e("#post-"+t).find(".column-price .downloadprice-"+t).val();i!==e("#post-"+t+".column-price .downloadprice-"+t).val()?e(".regprice","#edd-download-data").val(i).attr("disabled",!1):e(".regprice","#edd-download-data").val(edd_vars.quick_edit_warning).attr("disabled","disabled")}))}))}).call(this,i(1))},33:function(e,t,i){"use strict";(function(e,n){i.d(t,"a",(function(){return a}));var a=function(t){t.tooltip({content:function(){return e(this).prop("title")},tooltipClass:"edd-ui-tooltip",position:{my:"center top",at:"center bottom+10",collision:"flipfit"},hide:{duration:200},show:{duration:200}})};n(document).ready((function(e){a(e(".edd-help-tip"))}))}).call(this,i(1),i(1))},5:function(e,t){function i(t){return e.exports=i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},e.exports.__esModule=!0,e.exports.default=e.exports,i(t)}e.exports=i,e.exports.__esModule=!0,e.exports.default=e.exports}}); \ No newline at end of file +!function(e){var t={};function i(n){if(t[n])return t[n].exports;var a=t[n]={i:n,l:!1,exports:{}};return e[n].call(a.exports,a,a.exports,i),a.l=!0,a.exports}i.m=e,i.c=t,i.d=function(e,t,n){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(i.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var a in e)i.d(n,a,function(t){return e[t]}.bind(null,a));return n},i.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="",i(i.s=301)}({1:function(e,t){e.exports=jQuery},12:function(e,t,i){var n=i(5).default,a=i(14);e.exports=function(e){var t=a(e,"string");return"symbol"===n(t)?t:String(t)},e.exports.__esModule=!0,e.exports.default=e.exports},14:function(e,t,i){var n=i(5).default;e.exports=function(e,t){if("object"!==n(e)||null===e)return e;var i=e[Symbol.toPrimitive];if(void 0!==i){var a=i.call(e,t||"default");if("object"!==n(a))return a;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)},e.exports.__esModule=!0,e.exports.default=e.exports},20:function(e,t,i){"use strict";(function(e){i.d(t,"a",(function(){return l}));var n=i(3),a=i.n(n);function r(e,t){var i=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),i.push.apply(i,n)}return i}function d(e){for(var t=1;tn&&(n=t)})),i=n+=1;var r=t.clone();return r.removeClass("edd_add_blank"),r.attr("data-key",i),r.find("input, select, textarea").val("").each((function(){var t=e(this),n=t.attr("name"),a=t.attr("id");n&&(n=n.replace(/\[(\d+)\]/,"["+parseInt(i)+"]"),t.attr("name",n)),t.attr("data-key",i),void 0!==a&&(a=a.replace(/(\d+)/,parseInt(i)),t.attr("id",a))})),r.find("select").each((function(){e(this).val(t.find('select[name="'+e(this).attr("name")+'"]').val())})),r.find('input[type="checkbox"]').each((function(){e(this).is(":checked")&&e(this).prop("checked",!1),e(this).val(1)})),r.find("span.edd_price_id").each((function(){e(this).text(parseInt(i))})),r.find("input.edd_repeatable_index").each((function(){e(this).val(parseInt(e(this).data("key")))})),r.find("span.edd_file_id").each((function(){e(this).text(parseInt(i))})),r.find(".edd_repeatable_default_input").each((function(){e(this).val(parseInt(i)).removeAttr("checked")})),r.find(".edd_repeatable_condition_field").each((function(){e(this).find("option:eq(0)").prop("selected","selected")})),r.find("label").each((function(){var t=e(this).attr("for");t&&e(this).attr("for",t.replace(/(\d+)/,parseInt(i)))})),r.find(".search-choice").remove(),r.find(".chosen-container").remove(),Object(a.a)(r.find(".edd-help-tip")),r},add:function(){e(document.body).on("click",".edd_add_repeatable",(function(t){t.preventDefault();var i=e(this).closest(".edd_repeatable_table").find(".edd_repeatable_row").last(),n=r.clone_repeatable(i);n.insertAfter(i).find("input, textarea, select").filter(":visible").eq(0).focus(),r.initChosen(n)}))},move:function(){e(".edd_repeatable_table .edd-repeatables-wrap").sortable({axis:"y",handle:".edd-draghandle-anchor",items:".edd_repeatable_row",cursor:"move",tolerance:"pointer",containment:"parent",distance:2,opacity:.7,scroll:!0,update:function(){var t=0;e(this).find(".edd_repeatable_row").each((function(){e(this).find("input.edd_repeatable_index").each((function(){e(this).val(t)})),t++}))},start:function(e,t){t.placeholder.height(t.item.height()-2)}})},remove:function(){e(document.body).on("click",".edd-remove-row, .edd_remove_repeatable",(function(t){t.preventDefault();var i,n=e(this).parents(".edd_repeatable_row"),a=n.parent().find(".edd_repeatable_row").length,r=e(this).data("type"),d="div.edd_repeatable_"+r+"s";if(i=(e(this).is(".ui-sortable .edd_repeatable_row:first-child .edd-remove-row, .ui-sortable .edd_repeatable_row:first-child .edd_remove_repeatable")?n.next(".edd_repeatable_row"):n.prev(".edd_repeatable_row")).find("select, input, textarea, button").filter(":visible").eq(0),"price"===r){var o=n.data("key");e('.edd_repeatable_condition_field option[value="'+o+'"]').remove()}if(a>1)e("input, select",n).val(""),n.fadeOut("fast").remove(),i.focus();else switch(r){case"price":alert(edd_vars.one_price_min);break;case"file":e("input, select",n).val("");break;default:alert(edd_vars.one_field_min)}e(d).each((function(t){e(this).find("input, select").each((function(){var i=e(this).attr("name");i=i.replace(/\[(\d+)\]/,"["+t+"]"),e(this).attr("name",i).attr("id",i)}))}))}))},type:function(){var t=e("#edd_product_files");setTimeout((function(){edd_vars.download_has_files||"service"!==e("#_edd_product_type").val()||t.hide()}),100),e(document.body).on("change","#_edd_product_type",(function(i){var n=e(this).val(),a=e("#edd_download_limit_wrap");t.addClass("ajax--loading");var d={action:"edd_swap_download_type",product_type:n,post_id:edd_vars.post_id};e.post(ajaxurl,d,(function(e){e.success&&(t.find(".inside").empty().append(e.data.html),r.initChosen(t)),t.removeClass("ajax--loading")})),"bundle"===n?(t.show(),a.hide()):"service"===e(this).val()?t.find(".edd_upload_field").toArray().some((function(e){return!!e.value}))?(t.show(),a.show()):(setTimeout((function(){t.hide()}),100),a.hide()):(t.show(),a.show())}))},prices:function(){e(document.body).on("change","#edd_variable_pricing",(function(t){var i=e(this).is(":checked"),n=e("#edd_regular_price_field"),a=e("#edd_variable_price_fields, .edd_repeatable_table .pricing"),r=e(".edd-bundled-product-row, .edd-repeatable-row-standard-fields");i?(n.hide(),a.show(),r.addClass("has-variable-pricing")):(n.show(),a.hide(),r.removeClass("has-variable-pricing"))}))},files:function(){var t;window.formfield="",e(document.body).on("click",".edd_upload_file_button",(function(i){i.preventDefault();var n=e(this);window.formfield=n.closest(".edd_repeatable_upload_wrapper"),t||((t=wp.media.frames.file_frame=wp.media({title:n.data("uploader-title"),frame:"post",state:"insert",button:{text:n.data("uploader-button-text")},multiple:"0"!==e(this).data("multiple")})).on("menu:render:default",(function(e){e.unset("library-separator"),e.unset("gallery"),e.unset("featured-image"),e.unset("embed"),e.unset("playlist"),e.unset("video-playlist"),e.set({})})),t.on("insert",(function(){t.state().get("selection").each((function(t,i){var n="image"===(t=t.toJSON()).type&&e(".attachment-display-settings .size option:selected").val(),a=t.url,d=t.title.length>0?t.title:t.filename;if(n&&void 0!==t.sizes[n]&&(a=t.sizes[n].url),"image"===t.type&&(d=n&&void 0!==t.sizes[n]?d+"-"+t.sizes[n].width+"x"+t.sizes[n].height:d+"-"+t.width+"x"+t.height),0===i)window.formfield.find(".edd_repeatable_attachment_id_field").val(t.id),window.formfield.find(".edd_repeatable_thumbnail_size_field").val(n),window.formfield.find(".edd_repeatable_upload_field").val(a),window.formfield.find(".edd_repeatable_name_field").val(d);else{var o=window.formfield,l=r.clone_repeatable(o);l.find(".edd_repeatable_attachment_id_field").val(t.id),l.find(".edd_repeatable_thumbnail_size_field").val(n),l.find(".edd_repeatable_upload_field").val(a),l.find(".edd_repeatable_name_field").val(d),l.insertAfter(o)}}))}))),t.open()})),e(".edd_repeatable_upload_field").on("focus",(function(){var t=e(this);t.data("originalFile",t.val())})).on("change",(function(){var t=e(this);t.data("originalFile")!==t.val()&&t.closest(".edd-repeatable-row-standard-fields").find(".edd_repeatable_attachment_id_field").val(0)})),window.formfield=""},updatePrices:function(){e("#edd_price_fields").on("keyup",".edd_variable_prices_name",(function(){var t=e(this).parents(".edd_repeatable_row").data("key"),i=e(this).val(),n=e(".edd_repeatable_condition_field option[value="+t+"]");n.length>0?n.text(i):e(".edd_repeatable_condition_field").append(e("").attr("value",t).text(i))}))},showAdvanced:function(){e(document.body).on("click",".toggle-custom-price-option-section",(function(t){t.preventDefault();var i=e(this),n=i.html()===edd_vars.show_advanced_settings;n?i.html(edd_vars.hide_advanced_settings):i.html(edd_vars.show_advanced_settings);var a=i.parents(".edd-repeatable-row-header");a.siblings(".edd-custom-price-option-sections-wrap").slideToggle(),e(":input:not(input[type=button],input[type=submit],button):visible:first",n?a.siblings(".edd-custom-price-option-sections-wrap"):a.siblings(".edd-repeatable-row-standard-fields")).focus()}))},initChosen:function(t){t.find(".edd-select-chosen").each((function(){var t=e(this);t.chosen(Object(n.a)(t))})),t.find(".edd-select-chosen").css("width","100%"),t.find(".edd-select-chosen .chosen-search input").attr("placeholder",edd_vars.search_placeholder)}});t(document).ready((function(e){r.init()}))}.call(this,i(1),i(1))},302:function(e,t,i){(function(e){e(document).ready((function(e){e("body").on("click","#the-list .editinline",(function(){var t=e(this).closest("tr").attr("id");t=t.replace("post-","");var i=e("#post-"+t).find(".column-price .downloadprice-"+t).val();i!==e("#post-"+t+".column-price .downloadprice-"+t).val()?e(".regprice","#edd-download-data").val(i).attr("disabled",!1):e(".regprice","#edd-download-data").val(edd_vars.quick_edit_warning).attr("disabled","disabled")}))}))}).call(this,i(1))},33:function(e,t,i){"use strict";(function(e,n){i.d(t,"a",(function(){return a}));var a=function(t){t.tooltip({content:function(){return e(this).prop("title")},tooltipClass:"edd-ui-tooltip",position:{my:"center top",at:"center bottom+10",collision:"flipfit"},hide:{duration:200},show:{duration:200}})};n(document).ready((function(e){a(e(".edd-help-tip"))}))}).call(this,i(1),i(1))},5:function(e,t){function i(t){return e.exports=i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},e.exports.__esModule=!0,e.exports.default=e.exports,i(t)}e.exports=i,e.exports.__esModule=!0,e.exports.default=e.exports}}); \ No newline at end of file diff --git a/bin/.exclude b/bin/.exclude deleted file mode 100644 index 67647a2366..0000000000 --- a/bin/.exclude +++ /dev/null @@ -1,22 +0,0 @@ -./.buildkite -./.git -./.github -./.editorconfig -./.browserlistrc -./.gitattributes -./.gitignore -./node_modules -./build -./assets/css/admin -./assets/css/frontend -./assets/css/variables -./assets/js/admin -./assets/js/frontend -./assets/js/packages -./webpack.config.js -./SUPPORT.md -./readme.md -./package.json -./package-lock.json -./vendor -./includes/blocks/node_modules diff --git a/bin/update-stripe.sh b/bin/update-stripe.sh deleted file mode 100755 index d39fde2b52..0000000000 --- a/bin/update-stripe.sh +++ /dev/null @@ -1,38 +0,0 @@ -# Remove anything that already exists. -rm -rf includes/gateways/stripe - -# Initial clone -git clone git@github.com:awesomemotive/edd-stripe includes/gateways/stripe - -# Install dependencies -cd includes/gateways/stripe -npm install && npm run build - -git rev-parse HEAD > ../.stripe-hash - -# Clean up files for distribution. -# @todo Maybe use git archive? However composer.json would -# need to be removed from .gitattributes export-ignore -rm -rf node_modules -rm -rf tests -rm -rf bin -rm -rf languages -rm -rf includes/pro -rm -rf .git -rm -rf .github -rm .gitattributes -rm .gitignore -rm .npmrc -rm package-lock.json -rm package.json -rm composer.json -rm composer.lock -rm webpack.config.js -rm phpcs.ruleset.xml -rm phpunit.xml.dist -rm Gruntfile.js -rm -rf assets/css/src -rm -rf assets/js/src - -# Reset cwd -cd ../../../ diff --git a/easy-digital-downloads.php b/easy-digital-downloads.php index 69620c76bf..c4574ccd77 100755 --- a/easy-digital-downloads.php +++ b/easy-digital-downloads.php @@ -5,7 +5,7 @@ * Description: The easiest way to sell digital products with WordPress. * Author: Easy Digital Downloads * Author URI: https://easydigitaldownloads.com - * Version: 3.2.0 + * Version: 3.2.1 * Text Domain: easy-digital-downloads * Domain Path: /languages * Requires at least: 5.8 diff --git a/includes/.blocks-hash b/includes/.blocks-hash deleted file mode 100644 index cd9ee9766d..0000000000 --- a/includes/.blocks-hash +++ /dev/null @@ -1 +0,0 @@ -db0d390615a3b67334225d7af26df6b6f3dbce37 diff --git a/includes/admin/admin-bar.php b/includes/admin/admin-bar.php index e414ad82ae..ea7edff5e4 100644 --- a/includes/admin/admin-bar.php +++ b/includes/admin/admin-bar.php @@ -117,7 +117,9 @@ function edd_maybe_add_store_mode_admin_bar_menu( $wp_admin_bar ) { ), ) ); - if ( ! edd_is_pro() ) { + + $pass_manager = new \EDD\Admin\Pass_Manager(); + if ( ! $pass_manager->has_pass() ) { $url = edd_link_helper( 'https://easydigitaldownloads.com/lite-upgrade/', array( diff --git a/includes/admin/class-edd-notices.php b/includes/admin/class-edd-notices.php index 3717870477..1b9d4039f7 100644 --- a/includes/admin/class-edd-notices.php +++ b/includes/admin/class-edd-notices.php @@ -128,19 +128,21 @@ public function add_notice( $args = array() ) { */ public function add_notices() { - // User can view shop reports + // User can view shop reports. if ( current_user_can( 'view_shop_reports' ) ) { $this->add_reports_notices(); } - // User can manage the entire shop + // User can manage the entire shop. if ( current_user_can( 'manage_shop_settings' ) ) { $this->add_data_notices(); $this->add_settings_notices(); $this->add_order_upgrade_notice(); + $this->add_stripe_notice(); + $this->add_paypal_sync_notice(); } - // Generic notices + // Generic notices. if ( ! empty( $_REQUEST['edd-message'] ) ) { $this->add_user_action_notices( $_REQUEST['edd-message'] ); } @@ -484,6 +486,66 @@ private function add_order_upgrade_notice() { ); } + /** + * Adds a notice if the Stripe Pro gateway is outdated. + * This is due to a name change in the gateway. + * + * @since 3.2.1 + * @return void + */ + private function add_stripe_notice() { + if ( ! defined( 'EDD_STRIPE_VERSION' ) || ( defined( 'EDD_STRIPE_VERSION' ) && version_compare( EDD_STRIPE_VERSION, '2.8.4', '>=' ) ) ) { + return; + } + $this->add_notice( + array( + 'id' => 'edd-stripe-outdated', + 'class' => 'notice-warning', + 'message' => sprintf( + // translators: 1. opening link tag; 2. opening link tag; 3. closing link tag. + __( 'You are running an outdated version of the Easy Digital Downloads — Stripe Pro Payment Gateway. You may need to log into %1$syour account%3$s to download the latest version and %2$smanually upgrade%3$s it.', 'easy-digital-downloads' ), + '', + '', + '' + ), + 'is_dismissible' => false, + ) + ); + } + + /** + * Adds a notice if PayPal webhooks need to synced. + * + * @since 3.2.1 + * @return void + */ + private function add_paypal_sync_notice() { + if ( ! get_option( 'edd_paypal_webhook_sync_failed' ) ) { + return; + } + $url = edd_get_admin_url( + array( + 'page' => 'edd-settings', + 'tab' => 'gateways', + 'section' => 'paypal_commerce', + ) + ); + + $this->add_notice( + array( + 'id' => 'edd-paypal-webhook-sync', + 'class' => 'updated', + 'message' => sprintf( + /* translators: %1$s: Opening anchor tag; %2$s: Closing anchor tag. */ + __( 'New webhooks have been registered for PayPal Commerce, but we were unable to update them automatically. Please %1$ssync your webhooks manually%2$s.', 'easy-digital-downloads' ), + '', + '' + ), + 'is_dismissible' => false, + ) + ); + } + /** * Notices about actions that the user has taken * diff --git a/includes/admin/plugins.php b/includes/admin/plugins.php index 1648149107..5742e41e67 100755 --- a/includes/admin/plugins.php +++ b/includes/admin/plugins.php @@ -23,9 +23,10 @@ * @return array $links */ function edd_plugin_action_links( $links = array() ) { - $edd_links = array(); + $edd_links = array(); + $pass_manager = new \EDD\Admin\Pass_Manager(); - if ( ! edd_is_pro() ) { + if ( ! $pass_manager->has_pass() ) { $url = edd_link_helper( 'https://easydigitaldownloads.com/lite-upgrade/', diff --git a/includes/api/class-edd-api.php b/includes/api/class-edd-api.php index 590541811c..c01eeab808 100755 --- a/includes/api/class-edd-api.php +++ b/includes/api/class-edd-api.php @@ -614,12 +614,9 @@ public function process_query() { break; - case 'file-download-logs' : - + case 'file-download-logs': $customer = isset( $wp_query->query_vars['customer'] ) ? $wp_query->query_vars['customer'] : null; - - $data = $this->get_download_logs( $customer ); - + $data = $this->get_download_logs( $customer ); break; case 'info' : @@ -1669,62 +1666,37 @@ public function get_discounts( $discount = null ) { * Process Get Downloads API Request to retrieve download logs * * @since 2.5 - * @author Daniel J Griffiths - * - * @param int $customer_id The customer ID you wish to retrieve download logs for + * @since 3.2.1 Updated to use edd_get_file_download_logs(). * + * @param int $customer_id The customer ID or email you wish to retrieve download logs for. * @return array Multidimensional array of the download logs */ public function get_download_logs( $customer_id = 0 ) { - $edd_logs = EDD()->debug_log; - $downloads = array(); - $invalid_customer = false; + $downloads = array(); + $paged = $this->get_paged(); + $per_page = $this->per_page(); + $offset = $per_page * ( $paged - 1 ); + $valid_customer = true; - $paged = $this->get_paged(); - $per_page = $this->per_page(); - $offset = $per_page * ( $paged - 1 ); - - $meta_query = array(); + $query = array( + 'number' => $per_page, + 'offset' => $offset, + ); if ( ! empty( $customer_id ) ) { - - $customer = new EDD_Customer( $customer_id ); - - if ( $customer->id > 0 ) { - $meta_query['relation'] = 'OR'; - - if ( $customer->id > 0 ) { - // Based on customer->user_id - $meta_query[] = array( - 'key' => '_edd_log_user_id', - 'value' => $customer->user_id, - ); - } - - // Based on customer->email - $meta_query[] = array( - 'key' => '_edd_log_user_info', - 'value' => $customer->email, - 'compare' => 'LIKE', - ); + if ( is_email( $customer_id ) ) { + $customer = edd_get_customer_by( 'email', $customer_id ); } else { - $invalid_customer = true; + $customer = edd_get_customer( $customer_id ); + } + if ( $customer ) { + $query['customer_id'] = $customer->id; + } else { + $valid_customer = false; } } - $query = array( - 'log_type' => 'file_download', - 'paged' => $paged, - 'meta_query' => $meta_query, - 'posts_per_page' => $per_page, - 'update_post_meta_cache' => false, - 'update_post_term_cache' => false, - ); - - $logs = array(); - if ( ! $invalid_customer ) { - $logs = $edd_logs->get_connected_logs( $query ); - } + $logs = $valid_customer ? edd_get_file_download_logs( $query ) : false; if ( empty( $logs ) ) { $error['error'] = __( 'No download logs found!', 'easy-digital-downloads' ); @@ -1734,33 +1706,36 @@ public function get_download_logs( $customer_id = 0 ) { foreach ( $logs as $log ) { - $log_meta = get_post_custom( $log->ID ); - $payment_id = isset( $log_meta['_edd_log_payment_id'] ) ? $log_meta['_edd_log_payment_id'][0] : false; - - $payment_customer_id = edd_get_payment_customer_id( $payment_id ); - $payment_customer = new EDD_Customer( $payment_customer_id ); - $user_id = ( $payment_customer->user_id > 0 ) ? $payment_customer->user_id : false; - $ip = $log_meta['_edd_log_ip'][0]; - $files = edd_get_payment_meta_downloads( $payment_id ); - $files = edd_get_download_files( $files[0]['id'] ); - $file_id = (int) $log_meta['_edd_log_file_id'][0]; - $file_id = $file_id !== false ? $file_id : 0; - $file_name = isset( $files[ $file_id ]['name'] ) ? $files[ $file_id ]['name'] : null; - - $item = (array) apply_filters( 'edd_api_download_log_item', array( - 'ID' => $log->ID, - 'user_id' => $user_id, - 'product_id' => $log->post_parent, - 'product_name' => get_the_title( $log->post_parent ), - 'customer_id' => $payment_customer_id, - 'payment_id' => $payment_id, - 'file' => $file_name, - 'ip' => $ip, - 'date' => $log->post_date, - ), $log, $log_meta ); + $customer = edd_get_customer( $log->customer_id ); + $file_id = $log->file_id; + $file_name = edd_get_file_download_log_meta( $log->id, 'file_name', true ); + if ( empty( $file_name ) ) { + $files = get_post_meta( $log->product_id, 'edd_download_files', true ); + if ( is_array( $files ) && isset( $files[ $file_id ] ) ) { + $file_name = ! empty( $files[ $file_id ]['name'] ) + ? $files[ $file_id ]['name'] + : edd_get_file_name( $files[ $file_id ] ); + } + } - $downloads['download_logs'][] = $item; + $item = (array) apply_filters( + 'edd_api_download_log_item', + array( + 'ID' => (int) $log->id, + 'user_id' => (int) $customer->user_id, + 'product_id' => (int) $log->product_id, + 'product_name' => edd_get_download_name( $log->product_id, $log->product_id ), + 'customer_id' => (int) $log->customer_id, + 'payment_id' => (int) $log->order_id, + 'file' => $file_name, + 'ip' => $log->ip, + 'date' => $log->date_created, + ), + $log, + edd_get_file_download_log_meta( $log->id ) + ); + $downloads['download_logs'][] = $item; } return apply_filters( 'edd_api_download_logs', $downloads, $this ); diff --git a/includes/class-easy-digital-downloads.php b/includes/class-easy-digital-downloads.php index 61b5671785..7f4ff99ee1 100644 --- a/includes/class-easy-digital-downloads.php +++ b/includes/class-easy-digital-downloads.php @@ -362,7 +362,7 @@ private function setup_constants() { // Plugin version. if ( ! defined( 'EDD_VERSION' ) ) { - define( 'EDD_VERSION', '3.2.0' ); + define( 'EDD_VERSION', '3.2.1' ); } // Make sure CAL_GREGORIAN is defined. diff --git a/includes/class-edd-license-handler.php b/includes/class-edd-license-handler.php index 973bbe6ee8..c746f2f0f2 100644 --- a/includes/class-edd-license-handler.php +++ b/includes/class-edd-license-handler.php @@ -147,9 +147,6 @@ private function hooks() { // Add the EDD version to the API parameters. add_filter( 'edd_sl_plugin_updater_api_params', array( $this, 'filter_sl_api_params' ), 10, 3 ); - - // Fix missing Stripe keys due to option name change. - add_action( 'admin_init', array( $this, 'fix_stripe_key' ) ); } /** @@ -365,6 +362,7 @@ public function filter_sl_api_params( $api_params, $api_data, $plugin_file ) { * update the license key to fix automatic updates. * * @since 3.0.4 + * @deprecated 3.2.1 * @return void */ public function fix_stripe_key() { diff --git a/includes/gateways/.stripe-hash b/includes/gateways/.stripe-hash deleted file mode 100644 index 4d98cc91cc..0000000000 --- a/includes/gateways/.stripe-hash +++ /dev/null @@ -1 +0,0 @@ -feb67d63562231e67ed6184c353b2be4dbf3bc1d diff --git a/includes/gateways/paypal/webhooks/functions.php b/includes/gateways/paypal/webhooks/functions.php index 204b05e3c1..0ef1faf3c1 100644 --- a/includes/gateways/paypal/webhooks/functions.php +++ b/includes/gateways/paypal/webhooks/functions.php @@ -117,18 +117,23 @@ function create_webhook( $mode = '' ) { $event_types[] = array( 'name' => $event ); } - $response = $api->make_request( 'v1/notifications/webhooks', array( - 'url' => $webhook_url, - 'event_types' => $event_types - ) ); + $response = $api->make_request( + 'v1/notifications/webhooks', + array( + 'url' => $webhook_url, + 'event_types' => $event_types, + ) + ); if ( 201 !== $api->last_response_code ) { - throw new API_Exception( sprintf( - /* Translators: %d - HTTP response code; %s - Full response from the API. */ - __( 'Invalid response code %d while creating webhook. Response: %s', 'easy-digital-downloads' ), - $api->last_response_code, - json_encode( $response ) - ) ); + throw new API_Exception( + sprintf( + /* Translators: %d - HTTP response code; %s - Full response from the API. */ + __( 'Invalid response code %1$d while creating webhook. Response: %2$s', 'easy-digital-downloads' ), + $api->last_response_code, + json_encode( $response ) + ) + ); } if ( empty( $response->id ) ) { @@ -157,6 +162,9 @@ function sync_webhook( $mode = '' ) { $mode = edd_is_test_mode() ? API::MODE_SANDBOX : API::MODE_LIVE; } + // If the webhook sync failed during a cron event and we are syncing again, delete the option to clear the admin notice. + delete_option( 'edd_paypal_webhook_sync_failed' ); + $webhook_id = get_webhook_id( $mode ); if ( empty( $webhook_id ) ) { throw new \Exception( esc_html__( 'Webhook not configured.', 'easy-digital-downloads' ) ); @@ -171,13 +179,13 @@ function sync_webhook( $mode = '' ) { array( 'op' => 'replace', 'path' => '/url', - 'value' => get_webhook_url() + 'value' => get_webhook_url(), ), array( 'op' => 'replace', 'path' => '/event_types', - 'value' => $event_types - ) + 'value' => $event_types, + ), ); $api = new API( $mode ); @@ -187,17 +195,34 @@ function sync_webhook( $mode = '' ) { } if ( 200 !== $api->last_response_code ) { - throw new API_Exception( sprintf( - /* Translators: %d - HTTP response code; %s - Full response from the API. */ - __( 'Invalid response code %d while syncing webhook. Response: %s', 'easy-digital-downloads' ), - $api->last_response_code, - json_encode( $response ) - ) ); + throw new API_Exception( + sprintf( + /* Translators: %d - HTTP response code; %s - Full response from the API. */ + __( 'Invalid response code %1$d while syncing webhook. Response: %2$s', 'easy-digital-downloads' ), + $api->last_response_code, + json_encode( $response ) + ) + ); } return true; } +/** + * Syncs the webhook on a cron event. + * + * @since 3.2.1 + * @return void + */ +function sync_webhook_on_cron() { + try { + sync_webhook(); + } catch ( \Exception $e ) { + add_option( 'edd_paypal_webhook_sync_failed', time(), '', false ); + } +} +add_action( 'edd_paypal_commerce_sync_webhooks', __NAMESPACE__ . '\\sync_webhook_on_cron' ); + /** * Retrieves information about the webhook EDD created. * @@ -227,11 +252,13 @@ function get_webhook_details( $mode = '' ) { __( 'Your store is currently not receiving webhook notifications, create the webhooks to reconnect.', 'easy-digital-downloads' ) ); } else { - throw new API_Exception( sprintf( - /* Translators: %d - HTTP response code. */ - __( 'Invalid response code %d while retrieving webhook details.', 'easy-digital-downloads' ), - $api->last_response_code - ) ); + throw new API_Exception( + sprintf( + /* Translators: %d - HTTP response code. */ + __( 'Invalid response code %d while retrieving webhook details.', 'easy-digital-downloads' ), + $api->last_response_code + ) + ); } } @@ -270,15 +297,20 @@ function delete_webhook( $mode = '' ) { $api->make_request( 'v1/notifications/webhooks/' . urlencode( $webhook_id ), array(), array(), 'DELETE' ); if ( 204 !== $api->last_response_code ) { - throw new API_Exception( sprintf( - /* Translators: %d - HTTP response code. */ - __( 'Invalid response code %d while deleting webhook.', 'easy-digital-downloads' ), - $api->last_response_code - ) ); + throw new API_Exception( + sprintf( + /* Translators: %d - HTTP response code. */ + __( 'Invalid response code %d while deleting webhook.', 'easy-digital-downloads' ), + $api->last_response_code + ) + ); } } -add_action( 'rest_api_init', function () { - $handler = new Webhook_Handler(); - $handler->register_routes(); -} ); +add_action( + 'rest_api_init', + function () { + $handler = new Webhook_Handler(); + $handler->register_routes(); + } +); diff --git a/includes/gateways/stripe/includes/admin/upgrade-functions.php b/includes/gateways/stripe/includes/admin/upgrade-functions.php index e8b8435546..5069539ffa 100644 --- a/includes/gateways/stripe/includes/admin/upgrade-functions.php +++ b/includes/gateways/stripe/includes/admin/upgrade-functions.php @@ -1,28 +1,5 @@ rate_limiting = new EDD_Stripe_Rate_Limiting(); $this->application_fee = new EDD\Gateways\Stripe\ApplicationFee(); + new EDD\Gateways\Stripe\Admin\LicenseManager(); } /** diff --git a/includes/payments/class-edd-payment.php b/includes/payments/class-edd-payment.php index 70601fe05c..8a9c7ce456 100644 --- a/includes/payments/class-edd-payment.php +++ b/includes/payments/class-edd-payment.php @@ -2383,7 +2383,7 @@ public function update_meta( $meta_key = '', $meta_value = '', $prev_value = '' $meta_value = array_diff_key( $meta_value, array_flip( $core_meta_keys ) ); // If the above checks fall through, store anything else in a "payment_meta" meta key. - return edd_update_order_meta( $this->ID, 'payment_meta', $meta_value ); + return ! empty( $meta_value ) ? edd_update_order_meta( $this->ID, 'payment_meta', $meta_value ) : false; case '_edd_completed_date': $meta_value = empty( $meta_value ) ? null diff --git a/includes/upgrades/functions.php b/includes/upgrades/functions.php index a5bb1974a2..d60e769622 100644 --- a/includes/upgrades/functions.php +++ b/includes/upgrades/functions.php @@ -191,21 +191,31 @@ function edd_do_automatic_upgrades() { return; } - // Existing stores should set the upgraded version and the onboarding wizard as complete. + $set_stripe_transients = true; if ( ! empty( $edd_version ) ) { update_option( 'edd_version_upgraded_from', $edd_version, false ); + + // Existing stores should set the upgraded version and the onboarding wizard as complete. if ( ! get_option( 'edd_onboarding_completed', false ) && ! get_option( 'edd_onboarding_started', false ) ) { update_option( 'edd_onboarding_completed', true, false ); } + + // Stores upgrading from 3.2.0 or greater should not set the Stripe transients. + if ( version_compare( $edd_version, '3.2.0', '>=' ) ) { + $set_stripe_transients = false; + } } /** - * If PayPal is connected, silently sync the webhooks to ensure the dispute hook is registered. + * If PayPal is connected, schedule a cron event to sync the webhooks in the background. * * @since 3.2.0 */ if ( EDD\Gateways\PayPal\has_rest_api_connection() && EDD\Gateways\PayPal\Webhooks\get_webhook_id() ) { - EDD\Gateways\PayPal\Webhooks\sync_webhook(); + // Schedule a one time cron event to sync the webhooks. + if ( ! wp_next_scheduled( 'edd_paypal_commerce_sync_webhooks' ) ) { + wp_schedule_single_event( time() + ( 5 * MINUTE_IN_SECONDS ), 'edd_paypal_commerce_sync_webhooks' ); + } } /** @@ -213,7 +223,7 @@ function edd_do_automatic_upgrades() { * * @since 3.2.0 */ - if ( edd_is_gateway_active( 'stripe' ) && ( edd_is_pro() || edds_is_pro() ) ) { + if ( $set_stripe_transients && edd_is_gateway_active( 'stripe' ) && ( edd_is_pro() || edds_is_pro() ) ) { set_transient( 'edd_stripe_check_license', true, 30 ); set_transient( 'edd_stripe_new_install', time(), HOUR_IN_SECONDS * 72 ); } diff --git a/languages/easy-digital-downloads.pot b/languages/easy-digital-downloads.pot index de2f2c343f..c1ecc36f4b 100644 --- a/languages/easy-digital-downloads.pot +++ b/languages/easy-digital-downloads.pot @@ -2,19 +2,19 @@ # This file is distributed under the same license as the Easy Digital Downloads (Pro) plugin. msgid "" msgstr "" -"Project-Id-Version: Easy Digital Downloads (Pro) 3.2.0\n" +"Project-Id-Version: Easy Digital Downloads (Pro) 3.2.1\n" "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/easy-digital-downloads-pro\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"POT-Creation-Date: 2023-09-07T19:49:49+00:00\n" +"POT-Creation-Date: 2023-09-12T00:48:37+00:00\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "X-Generator: WP-CLI 2.8.1\n" #. Plugin Name of the plugin -#: src/Gateways/Stripe/Admin/LicenseManager.php:261 +#: src/Gateways/Stripe/Admin/LicenseManager.php:249 msgid "Easy Digital Downloads (Pro)" msgstr "" @@ -5686,9 +5686,9 @@ msgstr "" msgid "Store Status: %s" msgstr "" -#: includes/admin/admin-bar.php:131 +#: includes/admin/admin-bar.php:133 #: includes/admin/admin-deprecated-functions.php:267 -#: includes/admin/plugins.php:38 +#: includes/admin/plugins.php:39 #: src/Admin/Discounts/Generate.php:82 #: src/Admin/Promos/Notices/Lite.php:42 #: src/Admin/Settings/Tabs/Gateways.php:305 @@ -5698,7 +5698,7 @@ msgid "Upgrade to Pro" msgstr "" #. translators: %s: Whether this is a development domain (1 for true, 0 for false) -#: includes/admin/admin-bar.php:146 +#: includes/admin/admin-bar.php:148 msgid "Development Domain %s" msgstr "" @@ -5790,14 +5790,14 @@ msgstr "" #: includes/admin/upgrades/deprecated-upgrade-functions.php:593 #: includes/admin/upgrades/deprecated-upgrade-functions.php:711 #: includes/admin/upgrades/v3/class-base.php:117 -#: includes/api/class-edd-api.php:2030 -#: includes/api/class-edd-api.php:2034 -#: includes/api/class-edd-api.php:2046 -#: includes/api/class-edd-api.php:2048 +#: includes/api/class-edd-api.php:2005 +#: includes/api/class-edd-api.php:2009 +#: includes/api/class-edd-api.php:2021 +#: includes/api/class-edd-api.php:2023 #: includes/blocks/includes/forms/recaptcha.php:180 #: includes/cart/class-edd-cart.php:1445 #: includes/cart/class-edd-cart.php:1459 -#: includes/class-edd-license-handler.php:480 +#: includes/class-edd-license-handler.php:478 #: includes/deprecated-functions.php:489 #: includes/deprecated-functions.php:506 #: includes/deprecated-functions.php:514 @@ -5815,7 +5815,7 @@ msgstr "" #: includes/gateways/paypal/admin/connect.php:613 #: includes/gateways/paypal/admin/connect.php:761 #: includes/gateways/paypal/checkout-actions.php:114 -#: includes/gateways/stripe/includes/admin/upgrade-functions.php:110 +#: includes/gateways/stripe/includes/admin/upgrade-functions.php:87 #: includes/process-download.php:282 #: includes/process-download.php:910 #: includes/query-filters.php:51 @@ -5894,7 +5894,7 @@ msgstr "" #: includes/admin/upgrades/deprecated-upgrade-functions.php:518 #: includes/admin/upgrades/deprecated-upgrade-functions.php:593 #: includes/admin/upgrades/deprecated-upgrade-functions.php:711 -#: includes/gateways/stripe/includes/admin/upgrade-functions.php:110 +#: includes/gateways/stripe/includes/admin/upgrade-functions.php:87 msgid "You do not have permission to do shop upgrades" msgstr "" @@ -5931,7 +5931,7 @@ msgid "EDD Settings" msgstr "" #: includes/admin/admin-pages.php:90 -#: includes/admin/plugins.php:47 +#: includes/admin/plugins.php:48 #: includes/admin/settings/display-settings.php:31 #: includes/admin/settings/display-settings.php:361 #: includes/blocks/build/buy-button/index.js:12 @@ -6015,269 +6015,279 @@ msgid "Generate New API Keys" msgstr "" #. translators: %s: URL to the settings page -#: includes/admin/class-edd-notices.php:273 +#: includes/admin/class-edd-notices.php:275 msgid "No checkout page is configured. Set one in Settings." msgstr "" #. translators: %s: Uploads directory -#: includes/admin/class-edd-notices.php:329 +#: includes/admin/class-edd-notices.php:331 msgid "The files in %s are not currently protected." msgstr "" -#: includes/admin/class-edd-notices.php:330 +#: includes/admin/class-edd-notices.php:332 msgid "To protect them, you must add this NGINX redirect rule." msgstr "" #. translators: %s: Dismiss notice URL -#: includes/admin/class-edd-notices.php:332 -#: includes/admin/class-edd-notices.php:351 +#: includes/admin/class-edd-notices.php:334 +#: includes/admin/class-edd-notices.php:353 msgid "If you have already done this, or it does not apply to your site, you may permenently %s." msgstr "" #. translators: %s: Dismiss notice URL -#: includes/admin/class-edd-notices.php:332 -#: includes/admin/class-edd-notices.php:351 +#: includes/admin/class-edd-notices.php:334 +#: includes/admin/class-edd-notices.php:353 msgid "dismiss this notice" msgstr "" #. translators: the upload directory -#: includes/admin/class-edd-notices.php:349 +#: includes/admin/class-edd-notices.php:351 #: src/Admin/SiteHealth/Direct.php:220 msgid "The .htaccess file is missing from: %s" msgstr "" #. translators: the upload directory -#: includes/admin/class-edd-notices.php:350 +#: includes/admin/class-edd-notices.php:352 #: src/Admin/SiteHealth/Direct.php:225 msgid "First, please resave the Misc settings tab a few times. If this warning continues to appear, create a file called \".htaccess\" in the %s directory, and copy the following into it:" msgstr "" #. translators: 1. link to the recount tool; 2. link to the plugins screen. -#: includes/admin/class-edd-notices.php:373 +#: includes/admin/class-edd-notices.php:375 msgid "Easy Digital Downloads 2.5 contains a built in recount tool. Please deactivate the Easy Digital Downloads - Recount Earnings plugin" msgstr "" -#: includes/admin/class-edd-notices.php:407 +#: includes/admin/class-edd-notices.php:409 msgid "Review Tax Rates" msgstr "" #. translators: Link to review existing tax rates. -#: includes/admin/class-edd-notices.php:414 +#: includes/admin/class-edd-notices.php:416 msgid "A default tax rate was detected." msgstr "" #. translators: Link to review existing tax rates. -#: includes/admin/class-edd-notices.php:414 +#: includes/admin/class-edd-notices.php:416 msgid "This setting is no longer used in this version of Easy Digital Downloads. Please confirm your regional tax rates are properly configured and update tax settings to remove this notice." msgstr "" -#: includes/admin/class-edd-notices.php:436 +#: includes/admin/class-edd-notices.php:438 msgid "Settings updated." msgstr "" #. translators: %s: Next order number -#: includes/admin/class-edd-notices.php:449 +#: includes/admin/class-edd-notices.php:451 msgid "The sequential starting number could not be updated because it could conflict with existing orders. The next assigned order number is %s." msgstr "" -#: includes/admin/class-edd-notices.php:481 +#: includes/admin/class-edd-notices.php:483 msgid "Easy Digital Downloads is migrating orders. Sales and earnings data for your store will be updated when all orders have been migrated." msgstr "" -#: includes/admin/class-edd-notices.php:510 +#. translators: 1. opening link tag; 2. opening link tag; 3. closing link tag. +#: includes/admin/class-edd-notices.php:506 +msgid "You are running an outdated version of the Easy Digital Downloads — Stripe Pro Payment Gateway. You may need to log into %1$syour account%3$s to download the latest version and %2$smanually upgrade%3$s it." +msgstr "" + +#. translators: %1$s: Opening anchor tag; %2$s: Closing anchor tag. +#: includes/admin/class-edd-notices.php:540 +msgid "New webhooks have been registered for PayPal Commerce, but we were unable to update them automatically. Please %1$ssync your webhooks manually%2$s." +msgstr "" + +#: includes/admin/class-edd-notices.php:572 msgid "Discount code added." msgstr "" -#: includes/admin/class-edd-notices.php:516 +#: includes/admin/class-edd-notices.php:578 msgid "There was a problem adding that discount code, please try again." msgstr "" -#: includes/admin/class-edd-notices.php:523 +#: includes/admin/class-edd-notices.php:585 msgid "A discount with that code already exists, please use a different code." msgstr "" -#: includes/admin/class-edd-notices.php:530 +#: includes/admin/class-edd-notices.php:592 msgid "Discount code updated." msgstr "" -#: includes/admin/class-edd-notices.php:536 +#: includes/admin/class-edd-notices.php:598 msgid "No changes were made to that discount code." msgstr "" -#: includes/admin/class-edd-notices.php:542 +#: includes/admin/class-edd-notices.php:604 msgid "There was a problem updating that discount code, please try again." msgstr "" -#: includes/admin/class-edd-notices.php:549 +#: includes/admin/class-edd-notices.php:611 msgid "The discount code could not be added because one or more of the required fields was empty, please try again." msgstr "" -#: includes/admin/class-edd-notices.php:556 +#: includes/admin/class-edd-notices.php:618 msgid "The discount code entered is invalid; only alphanumeric characters are allowed, please try again." msgstr "" -#: includes/admin/class-edd-notices.php:563 +#: includes/admin/class-edd-notices.php:625 msgid "The discount amount must be a valid percentage or numeric flat amount. Please try again." msgstr "" -#: includes/admin/class-edd-notices.php:570 +#: includes/admin/class-edd-notices.php:632 msgid "Discount code deleted." msgstr "" -#: includes/admin/class-edd-notices.php:576 +#: includes/admin/class-edd-notices.php:638 msgid "There was a problem deleting that discount code, please try again." msgstr "" -#: includes/admin/class-edd-notices.php:583 +#: includes/admin/class-edd-notices.php:645 msgid "Discount code activated." msgstr "" -#: includes/admin/class-edd-notices.php:589 +#: includes/admin/class-edd-notices.php:651 msgid "There was a problem activating that discount code, please try again." msgstr "" -#: includes/admin/class-edd-notices.php:596 +#: includes/admin/class-edd-notices.php:658 msgid "Discount code deactivated." msgstr "" -#: includes/admin/class-edd-notices.php:602 +#: includes/admin/class-edd-notices.php:664 msgid "There was a problem deactivating that discount code, please try again." msgstr "" -#: includes/admin/class-edd-notices.php:609 +#: includes/admin/class-edd-notices.php:671 msgid "Discount code archived." msgstr "" -#: includes/admin/class-edd-notices.php:615 +#: includes/admin/class-edd-notices.php:677 msgid "There was a problem archiving that discount code, please try again." msgstr "" -#: includes/admin/class-edd-notices.php:628 +#: includes/admin/class-edd-notices.php:690 msgid "The reports have been refreshed." msgstr "" -#: includes/admin/class-edd-notices.php:640 +#: includes/admin/class-edd-notices.php:702 msgid "The settings have been imported." msgstr "" -#: includes/admin/class-edd-notices.php:646 +#: includes/admin/class-edd-notices.php:708 msgid "API keys successfully generated." msgstr "" -#: includes/admin/class-edd-notices.php:652 +#: includes/admin/class-edd-notices.php:714 msgid "The specified user already has API keys." msgstr "" -#: includes/admin/class-edd-notices.php:659 +#: includes/admin/class-edd-notices.php:721 msgid "API keys successfully regenerated." msgstr "" -#: includes/admin/class-edd-notices.php:665 +#: includes/admin/class-edd-notices.php:727 msgid "API keys successfully revoked." msgstr "" -#: includes/admin/class-edd-notices.php:672 +#: includes/admin/class-edd-notices.php:734 msgid "The test email was sent successfully." msgstr "" -#: includes/admin/class-edd-notices.php:680 +#: includes/admin/class-edd-notices.php:742 msgid "The test email summary was sent successfully." msgstr "" -#: includes/admin/class-edd-notices.php:689 +#: includes/admin/class-edd-notices.php:751 msgid "Your extensions could not be refreshed because you have not verified your license key." msgstr "" -#: includes/admin/class-edd-notices.php:703 +#: includes/admin/class-edd-notices.php:765 msgid "The note has been added successfully." msgstr "" -#: includes/admin/class-edd-notices.php:709 +#: includes/admin/class-edd-notices.php:771 msgid "The order has been updated successfully." msgstr "" -#: includes/admin/class-edd-notices.php:715 +#: includes/admin/class-edd-notices.php:777 msgid "Order successfully created." msgstr "" -#: includes/admin/class-edd-notices.php:721 +#: includes/admin/class-edd-notices.php:783 msgid "The order has been moved to the trash." msgstr "" -#: includes/admin/class-edd-notices.php:727 +#: includes/admin/class-edd-notices.php:789 msgid "The order has been restored." msgstr "" -#: includes/admin/class-edd-notices.php:733 +#: includes/admin/class-edd-notices.php:795 msgid "The order has been deleted." msgstr "" -#: includes/admin/class-edd-notices.php:739 +#: includes/admin/class-edd-notices.php:801 msgid "The purchase receipt has been resent." msgstr "" -#: includes/admin/class-edd-notices.php:745 +#: includes/admin/class-edd-notices.php:807 msgid "Failed to send purchase receipt." msgstr "" -#: includes/admin/class-edd-notices.php:751 +#: includes/admin/class-edd-notices.php:813 msgid "The order note has been deleted." msgstr "" -#: includes/admin/class-edd-notices.php:763 +#: includes/admin/class-edd-notices.php:825 msgid "Customer successfully deleted." msgstr "" -#: includes/admin/class-edd-notices.php:769 +#: includes/admin/class-edd-notices.php:831 msgid "User successfully verified." msgstr "" -#: includes/admin/class-edd-notices.php:775 +#: includes/admin/class-edd-notices.php:837 msgid "Customer email added." msgstr "" -#: includes/admin/class-edd-notices.php:781 +#: includes/admin/class-edd-notices.php:843 msgid "Customer email deleted." msgstr "" -#: includes/admin/class-edd-notices.php:787 +#: includes/admin/class-edd-notices.php:849 msgid "Failed to delete customer email." msgstr "" -#: includes/admin/class-edd-notices.php:794 +#: includes/admin/class-edd-notices.php:856 msgid "Primary email updated for customer." msgstr "" -#: includes/admin/class-edd-notices.php:800 +#: includes/admin/class-edd-notices.php:862 msgid "Failed to set primary email." msgstr "" -#: includes/admin/class-edd-notices.php:807 +#: includes/admin/class-edd-notices.php:869 msgid "Customer address deleted." msgstr "" -#: includes/admin/class-edd-notices.php:813 +#: includes/admin/class-edd-notices.php:875 msgid "Failed to delete customer address." msgstr "" #. Translators: 1. opening strong tag, do not translate; 2. closing strong tag, do not translate -#: includes/admin/class-edd-notices.php:826 +#: includes/admin/class-edd-notices.php:888 msgid "Congratulations! You are now running %1$sEasy Digital Downloads (Pro)%2$s." msgstr "" -#: includes/admin/class-edd-notices.php:871 +#: includes/admin/class-edd-notices.php:933 msgid "Easy Digital Downloads debug logging is enabled. Please only leave it enabled for as long as it is needed for troubleshooting." msgstr "" -#: includes/admin/class-edd-notices.php:874 +#: includes/admin/class-edd-notices.php:936 msgid "View Debug Log" msgstr "" -#: includes/admin/class-edd-notices.php:875 +#: includes/admin/class-edd-notices.php:937 msgid "Delete Log File and Disable Logging" msgstr "" -#: includes/admin/class-edd-notices.php:891 +#: includes/admin/class-edd-notices.php:953 #: includes/admin/customers/customer-actions.php:618 #: includes/admin/emails/email-summary/class-edd-email-summary-admin.php:55 #: includes/admin/tools/class-edd-tools-recount-all-stats.php:78 @@ -6300,7 +6310,7 @@ msgstr "" msgid "You do not have permission to perform this action." msgstr "" -#: includes/admin/class-edd-notices.php:896 +#: includes/admin/class-edd-notices.php:958 msgid "The debug log has been cleared and logging has been disabled." msgstr "" @@ -6579,8 +6589,8 @@ msgstr "" #: includes/admin/import/import-functions.php:25 #: includes/admin/import/import-functions.php:106 #: includes/admin/reporting/export/export-actions.php:24 -#: includes/api/class-edd-api.php:2030 -#: includes/class-edd-license-handler.php:480 +#: includes/api/class-edd-api.php:2005 +#: includes/class-edd-license-handler.php:478 #: includes/user-functions.php:937 #: src/Pro/Admin/Discounts/Generate.php:96 msgid "Nonce verification failed." @@ -11433,9 +11443,9 @@ msgid "Unable to find download. Please refresh the page and try again." msgstr "" #: includes/api/class-edd-api-v2.php:166 -#: includes/api/class-edd-api.php:1131 -#: includes/api/class-edd-api.php:1338 -#: includes/api/class-edd-api.php:1457 +#: includes/api/class-edd-api.php:1128 +#: includes/api/class-edd-api.php:1335 +#: includes/api/class-edd-api.php:1454 msgid "Product %s not found!" msgstr "" @@ -11444,7 +11454,7 @@ msgid "Customer not found!" msgstr "" #: includes/api/class-edd-api-v2.php:354 -#: includes/api/class-edd-api.php:1079 +#: includes/api/class-edd-api.php:1076 msgid "No customers found!" msgstr "" @@ -11464,70 +11474,70 @@ msgstr "" msgid "Invalid API version!" msgstr "" -#: includes/api/class-edd-api.php:688 +#: includes/api/class-edd-api.php:685 msgid "Invalid query!" msgstr "" -#: includes/api/class-edd-api.php:1073 +#: includes/api/class-edd-api.php:1070 msgid "Customer %s not found!" msgstr "" -#: includes/api/class-edd-api.php:1239 -#: includes/api/class-edd-api.php:1354 +#: includes/api/class-edd-api.php:1236 +#: includes/api/class-edd-api.php:1351 msgid "The end date must be later than the start date!" msgstr "" -#: includes/api/class-edd-api.php:1244 -#: includes/api/class-edd-api.php:1359 +#: includes/api/class-edd-api.php:1241 +#: includes/api/class-edd-api.php:1356 msgid "Invalid or no date range specified!" msgstr "" -#: includes/api/class-edd-api.php:1613 +#: includes/api/class-edd-api.php:1610 msgid "No discounts found!" msgstr "" -#: includes/api/class-edd-api.php:1659 +#: includes/api/class-edd-api.php:1656 msgid "Discount %s not found!" msgstr "" -#: includes/api/class-edd-api.php:1730 +#: includes/api/class-edd-api.php:1702 msgid "No download logs found!" msgstr "" -#: includes/api/class-edd-api.php:1986 +#: includes/api/class-edd-api.php:1961 #: includes/user-functions.php:1107 msgid "Downloads API Keys" msgstr "" -#: includes/api/class-edd-api.php:1996 +#: includes/api/class-edd-api.php:1971 #: includes/user-functions.php:1114 msgid "Generate API Key" msgstr "" -#: includes/api/class-edd-api.php:2000 +#: includes/api/class-edd-api.php:1975 msgid "Public key:" msgstr "" -#: includes/api/class-edd-api.php:2003 +#: includes/api/class-edd-api.php:1978 msgid "Secret key:" msgstr "" -#: includes/api/class-edd-api.php:2006 +#: includes/api/class-edd-api.php:1981 #: includes/user-functions.php:1125 msgid "Token:" msgstr "" -#: includes/api/class-edd-api.php:2010 +#: includes/api/class-edd-api.php:1985 #: includes/user-functions.php:1131 msgid "Revoke API Keys" msgstr "" -#: includes/api/class-edd-api.php:2034 +#: includes/api/class-edd-api.php:2009 msgid "User ID Required" msgstr "" -#: includes/api/class-edd-api.php:2046 -#: includes/api/class-edd-api.php:2048 +#: includes/api/class-edd-api.php:2021 +#: includes/api/class-edd-api.php:2023 msgid "You do not have permission to %s API keys for this user" msgstr "" @@ -13231,12 +13241,12 @@ msgid "Required" msgstr "" #. translators: 1. opening anchor tag; 2. closing anchor tag -#: includes/class-edd-license-handler.php:304 +#: includes/class-edd-license-handler.php:301 #: src/Extensions/Handler.php:256 msgid "You have invalid or expired license keys for Easy Digital Downloads. %1$sActivate License(s)%2$s" msgstr "" -#: includes/class-edd-license-handler.php:326 +#: includes/class-edd-license-handler.php:323 #: src/Extensions/Handler.php:275 msgid "Enter valid license key for automatic updates." msgstr "" @@ -14848,38 +14858,38 @@ msgid "An SSL certificate is required to create a PayPal webhook." msgstr "" #. Translators: %d - HTTP response code; %s - Full response from the API. -#: includes/gateways/paypal/webhooks/functions.php:128 -msgid "Invalid response code %d while creating webhook. Response: %s" +#: includes/gateways/paypal/webhooks/functions.php:132 +msgid "Invalid response code %1$d while creating webhook. Response: %2$s" msgstr "" -#: includes/gateways/paypal/webhooks/functions.php:135 +#: includes/gateways/paypal/webhooks/functions.php:140 msgid "Unexpected response from PayPal." msgstr "" -#: includes/gateways/paypal/webhooks/functions.php:162 +#: includes/gateways/paypal/webhooks/functions.php:170 msgid "Webhook not configured." msgstr "" #. Translators: %d - HTTP response code; %s - Full response from the API. -#: includes/gateways/paypal/webhooks/functions.php:192 -msgid "Invalid response code %d while syncing webhook. Response: %s" +#: includes/gateways/paypal/webhooks/functions.php:201 +msgid "Invalid response code %1$d while syncing webhook. Response: %2$s" msgstr "" -#: includes/gateways/paypal/webhooks/functions.php:227 +#: includes/gateways/paypal/webhooks/functions.php:252 msgid "Your store is currently not receiving webhook notifications, create the webhooks to reconnect." msgstr "" #. Translators: %d - HTTP response code. -#: includes/gateways/paypal/webhooks/functions.php:232 +#: includes/gateways/paypal/webhooks/functions.php:258 msgid "Invalid response code %d while retrieving webhook details." msgstr "" -#: includes/gateways/paypal/webhooks/functions.php:239 +#: includes/gateways/paypal/webhooks/functions.php:266 msgid "Unexpected response from PayPal when retrieving webhook details." msgstr "" #. Translators: %d - HTTP response code. -#: includes/gateways/paypal/webhooks/functions.php:275 +#: includes/gateways/paypal/webhooks/functions.php:303 msgid "Invalid response code %d while deleting webhook." msgstr "" @@ -15348,15 +15358,15 @@ msgid "Easy Digital Downloads — Stripe" msgstr "" #. translators: %s Upgrade link. -#: includes/gateways/stripe/includes/admin/upgrade-functions.php:85 +#: includes/gateways/stripe/includes/admin/upgrade-functions.php:62 msgid "Easy Digital Downloads - Stripe Gateway needs to upgrade the customers database; click here to start the upgrade. Learn more about this upgrade" msgstr "" -#: includes/gateways/stripe/includes/admin/upgrade-functions.php:88 +#: includes/gateways/stripe/includes/admin/upgrade-functions.php:65 msgid "About this upgrade:
This upgrade will improve the reliability of associating purchase records with your existing customer records in Stripe by changing their Stripe Customer IDs to be stored locally on their EDD customer record, instead of their user record." msgstr "" -#: includes/gateways/stripe/includes/admin/upgrade-functions.php:90 +#: includes/gateways/stripe/includes/admin/upgrade-functions.php:67 msgid "Advanced User?
This upgrade can also be run via WPCLI with the following command:
wp edd-stripe migrate_customer_ids" msgstr "" @@ -15422,7 +15432,7 @@ msgstr "" msgid "We are unable to process your payment at this time, please try again later or contact support." msgstr "" -#: includes/gateways/stripe/includes/class-edd-stripe.php:231 +#: includes/gateways/stripe/includes/class-edd-stripe.php:232 #: includes/gateways/stripe/includes/template-functions.php:177 msgid "Credit Card" msgstr "" @@ -17503,12 +17513,21 @@ msgstr "" msgid "Add functionality to your Easy Digital Downloads powered store." msgstr "" +#. translators: 1. pass name; 2. opening anchor tag; 3. closing anchor tag. +#: src/Admin/Extensions/ExtensionPage.php:162 +msgid "Using the 1-Click Installation feature requires Easy Digital Downloads (Pro), which you have access to with your %1$s. %2$sInstall (Pro) now%3$s." +msgstr "" + #. translators: 1. opening anchor tag; 2. closing anchor tag. -#: src/Admin/Extensions/ExtensionPage.php:158 +#: src/Admin/Extensions/ExtensionPage.php:180 msgid "Missing access to an extension? %1$sAdd your license key now%2$s." msgstr "" -#: src/Admin/Extensions/ExtensionPage.php:191 +#: src/Admin/Extensions/ExtensionPage.php:214 +msgid "EDD (Pro) Required" +msgstr "" + +#: src/Admin/Extensions/ExtensionPage.php:218 msgid "Upgrade Now" msgstr "" @@ -17965,20 +17984,20 @@ msgstr "" msgid "Go Pro With Easy Digital Downloads" msgstr "" -#: src/Admin/PassHandler/Settings.php:167 +#: src/Admin/PassHandler/Settings.php:175 msgid "You're using Easy Digital Downloads — no license needed. Enjoy!" msgstr "" #. translators: 1. opening link tag; do not translate; 2. closing link tag; do not translate. -#: src/Admin/PassHandler/Settings.php:182 +#: src/Admin/PassHandler/Settings.php:190 msgid "To unlock more features, consider %1$supgrading to Pro%2$s." msgstr "" -#: src/Admin/PassHandler/Settings.php:189 +#: src/Admin/PassHandler/Settings.php:197 msgid "As a valued EDD user you receive 50% off, automatically applied at checkout!" msgstr "" -#: src/Admin/PassHandler/Settings.php:190 +#: src/Admin/PassHandler/Settings.php:198 msgid "Already purchased? Simply enter your license key to enable EDD (Pro)." msgstr "" @@ -19483,66 +19502,66 @@ msgid "Full refund processed in PayPal." msgstr "" #. translators: %1$s is the opening link tag; %2$s is the closing link tag. -#: src/Gateways/Stripe/Admin/LicenseManager.php:160 +#: src/Gateways/Stripe/Admin/LicenseManager.php:148 msgid "Your license is not active. Please %1$sactivate your license%2$s." msgstr "" #. translators: %1$s is the opening link tag; %2$s is the closing link tag. -#: src/Gateways/Stripe/Admin/LicenseManager.php:167 +#: src/Gateways/Stripe/Admin/LicenseManager.php:155 msgid "Your license has expired. Please %1$srenew your license%2$s." msgstr "" -#: src/Gateways/Stripe/Admin/LicenseManager.php:261 +#: src/Gateways/Stripe/Admin/LicenseManager.php:249 msgid "Easy Digital Downloads - Stripe Pro Payment Gateway" msgstr "" -#: src/Gateways/Stripe/Admin/LicenseManager.php:265 +#: src/Gateways/Stripe/Admin/LicenseManager.php:253 msgid "Easy Digital Downloads - Stripe Pro Payment Gateway Is Not Fully Activated!" msgstr "" -#: src/Gateways/Stripe/Admin/LicenseManager.php:266 +#: src/Gateways/Stripe/Admin/LicenseManager.php:254 msgid "Activate your license key to receive important security and feature updates and remove application fees." msgstr "" -#: src/Gateways/Stripe/Admin/LicenseManager.php:271 +#: src/Gateways/Stripe/Admin/LicenseManager.php:259 msgid "Complete Activation" msgstr "" -#: src/Gateways/Stripe/Admin/LicenseManager.php:276 -#: src/Gateways/Stripe/Admin/LicenseManager.php:302 -#: src/Gateways/Stripe/Admin/LicenseManager.php:324 -#: src/Gateways/Stripe/Admin/LicenseManager.php:351 +#: src/Gateways/Stripe/Admin/LicenseManager.php:264 +#: src/Gateways/Stripe/Admin/LicenseManager.php:290 +#: src/Gateways/Stripe/Admin/LicenseManager.php:312 +#: src/Gateways/Stripe/Admin/LicenseManager.php:339 msgid "Learn More" msgstr "" #. translators: %s is the name of the license. -#: src/Gateways/Stripe/Admin/LicenseManager.php:285 -#: src/Gateways/Stripe/Admin/LicenseManager.php:311 +#: src/Gateways/Stripe/Admin/LicenseManager.php:273 +#: src/Gateways/Stripe/Admin/LicenseManager.php:299 msgid "Your %s license has expired!" msgstr "" #. translators: %s is the date the grace period ends. -#: src/Gateways/Stripe/Admin/LicenseManager.php:290 +#: src/Gateways/Stripe/Admin/LicenseManager.php:278 msgid "Renew your license before %s to continue using Stripe without paying additional fees and to continue receiving important security and feature updates." msgstr "" -#: src/Gateways/Stripe/Admin/LicenseManager.php:297 -#: src/Gateways/Stripe/Admin/LicenseManager.php:319 -#: src/Gateways/Stripe/Admin/LicenseManager.php:346 +#: src/Gateways/Stripe/Admin/LicenseManager.php:285 +#: src/Gateways/Stripe/Admin/LicenseManager.php:307 +#: src/Gateways/Stripe/Admin/LicenseManager.php:334 msgid "Renew License" msgstr "" -#: src/Gateways/Stripe/Admin/LicenseManager.php:314 +#: src/Gateways/Stripe/Admin/LicenseManager.php:302 msgid "You are now paying additional fees with every Stripe transaction. You are no longer receiving important security and feature updates for Stripe Pro." msgstr "" #. translators: %s is the name of the license. -#: src/Gateways/Stripe/Admin/LicenseManager.php:333 +#: src/Gateways/Stripe/Admin/LicenseManager.php:321 msgid "Your %s License Is Expiring Soon!" msgstr "" #. translators: 1. the name of the license; 2. the date the license expires. -#: src/Gateways/Stripe/Admin/LicenseManager.php:338 +#: src/Gateways/Stripe/Admin/LicenseManager.php:326 msgid "Your %1$s license is set to expire on %2$s. An active license key is required to create and edit payment forms, enable automatic updates, and to keep Easy Digital Downloads - Stripe Pro Payment Gateway fully activated." msgstr "" @@ -19588,7 +19607,7 @@ msgstr "" #. translators: opening link tag, do not translate; closing link tag, do not translate #: src/Gateways/Stripe/ApplicationFee.php:231 -msgid "%1$sActivate your license%2$s to remove additional fees." +msgid "%1$sActivate or upgrade your license%2$s to remove additional fees." msgstr "" #. translators: %s: Category name diff --git a/package.json b/package.json index 9374b73593..d4b86e4c6d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "easy-digital-downloads", - "version": "3.2.0", + "version": "3.2.1", "description": "The easiest way to sell digital products with WordPress.", "private": true, "author": "Easy Digital Downloads", @@ -75,11 +75,13 @@ "test:unit": "wp-scripts test-unit-js --config tests/jest/jest.config.js", "blocks": "bash bin/update-blocks.sh && grunt replace:blocks", "translate": "grunt clean && wp i18n make-pot . languages/easy-digital-downloads.pot --exclude=node_modules,assets,tests,libraries --ignore-domain", - "translate-lite": "wp i18n make-pot build/easy-digital-downloads build/easy-digital-downloads/languages/easy-digital-downloads.pot --exclude=build/easy-digital-downloads/assets,build/easy-digital-downloads/libraries --ignore-domain", + "translate-lite": "cd build/easy-digital-downloads && wp i18n make-pot . languages/easy-digital-downloads.pot --exclude=assets,libraries --ignore-domain && cd ../../", + "translate-repo": "cd build/easy-digital-downloads-public && wp i18n make-pot . languages/easy-digital-downloads.pot --exclude=assets,libraries --ignore-domain && cd ../../", "update": "composer update --ignore-platform-reqs && composer run mozart", "lite": "grunt clean && grunt copy:lite && grunt replace:pro && npm run translate-lite && grunt compress:lite", "pro": "grunt clean && grunt copy:pro && grunt compress:pro", "local": "grunt clean && grunt copy && grunt replace:pro && npm run translate-lite && grunt compress", - "postinstall": "cd includes/blocks && npm install && cd ../../" + "postinstall": "cd includes/blocks && npm install && cd ../../", + "public": "grunt clean:repo && grunt copy:repo && grunt replace:repo && npm run translate-repo" } } diff --git a/readme.txt b/readme.txt index 204042bb93..ae63d6f2fc 100755 --- a/readme.txt +++ b/readme.txt @@ -6,7 +6,7 @@ Tags: ecommerce, payments, sell, digital store, stripe Requires at least: 5.8 Tested up to: 6.3 Requires PHP: 7.4 -Stable Tag: 3.2.0 +Stable Tag: 3.2.1 License: GNU Version 2 or Any Later Version The #1 ecommerce WordPress plugin to sell digital products. Effortlessly manage orders, maximize revenue, and accept payments through Stripe & PayPal. @@ -227,6 +227,11 @@ Yes, with an Extended Pass you get access to [Recurring Payments](https://easydi == Changelog == += 3.2.1 = +* Stripe: We've improved the error handling and informational messaging related to the Stripe Payments integration. +* PayPal: When new features are added to the PayPal integration, a background process attempts to register new payment endpoints automatically. +* API: Accessing the file download logs via the EDD API now supports querying by both customer ID and customer email address. + = 3.2.0 = * Important: This release requires PHP 7.4 or higher and WordPress 5.8 or higher. * Important: Amazon Pay has been formally deprecated and is no longer available for new installs. Existing stores using Amazon Pay are encouraged to explore other options. diff --git a/src/Admin/Extensions/ExtensionPage.php b/src/Admin/Extensions/ExtensionPage.php index 0f9b67f221..2a15418488 100644 --- a/src/Admin/Extensions/ExtensionPage.php +++ b/src/Admin/Extensions/ExtensionPage.php @@ -147,6 +147,28 @@ protected function show_missing_key_question() { if ( ! empty( $this->pass_manager->highest_pass_id ) && edd_is_pro() ) { return; } + + // If this is Lite, and there is a pass active, mention that (Pro) is needed to install addons. + if ( $this->pass_manager->has_pass() ) { + $url = edd_get_admin_url( + array( + 'page' => 'edd-settings', + ) + ); + + wp_kses_post( + printf( + // translators: 1. pass name; 2. opening anchor tag; 3. closing anchor tag. + __( 'Using the 1-Click Installation feature requires Easy Digital Downloads (Pro), which you have access to with your %1$s. %2$sInstall (Pro) now%3$s.', 'easy-digital-downloads' ), + $this->pass_manager->get_pass_name(), + '', + '' + ) + ); + + return; + } + $url = edd_get_admin_url( array( 'page' => 'edd-settings', @@ -187,10 +209,16 @@ protected function get_configuration( ProductData $product_data ) { protected function get_button_parameters( ProductData $product_data, $item_id = false ) { $button = parent::get_button_parameters( $product_data, $item_id ); - // Lite always shows "Upgrade Now". - $button['button_text'] = __( 'Upgrade Now', 'easy-digital-downloads' ); - $button['button_class'] = 'button-primary edd-promo-notice__trigger'; - $button['type'] = 'extension'; + // Lite can show two cases, since you can have a pass activated on lite, but lite cannot install addons. + if ( $this->pass_manager->has_pass() ) { + $button['button_text'] = __( 'EDD (Pro) Required', 'easy-digital-downloads' ); + $button['disabled'] = true; + unset( $button['href'] ); + } else { + $button['button_text'] = __( 'Upgrade Now', 'easy-digital-downloads' ); + $button['button_class'] = 'button-primary edd-promo-notice__trigger'; + $button['type'] = 'extension'; + } return $button; } diff --git a/src/Admin/PassHandler/Settings.php b/src/Admin/PassHandler/Settings.php index 7a1793c04e..a2b88f8644 100644 --- a/src/Admin/PassHandler/Settings.php +++ b/src/Admin/PassHandler/Settings.php @@ -158,9 +158,17 @@ private function get_heading_text() { * @return void */ private function show_free_message( $pro_license ) { + // If we're running the Pro version of EDD, we don't need to show this. if ( edd_is_pro() ) { return; } + + // The user could have the Lite version, but with a Pass activated on extensions, so we need to check for that. + $pass_manager = new \EDD\Admin\Pass_Manager(); + if ( $pass_manager->has_pass() ) { + return; + } + ?>

diff --git a/src/Core.php b/src/Core.php index 74d531981c..515f95d170 100644 --- a/src/Core.php +++ b/src/Core.php @@ -69,7 +69,6 @@ protected function get_admin_providers() { new Admin\Pointers(), new Admin\Settings\Sanitize(), new Admin\Downloads\Metabox(), - new Gateways\Stripe\Admin\LicenseManager(), ); return $providers; diff --git a/src/Gateways/Stripe/Admin/LicenseManager.php b/src/Gateways/Stripe/Admin/LicenseManager.php index 0f5fe748d1..778399da5e 100644 --- a/src/Gateways/Stripe/Admin/LicenseManager.php +++ b/src/Gateways/Stripe/Admin/LicenseManager.php @@ -9,14 +9,12 @@ defined( 'ABSPATH' ) || exit; -use EDD\EventManagement\SubscriberInterface; - /** * Class to handle the admin notifications. * * @since 3.2.0 */ -final class LicenseManager implements SubscriberInterface { +final class LicenseManager { /** * The license object, if found. @@ -26,24 +24,19 @@ final class LicenseManager implements SubscriberInterface { private $license; /** - * Returns an array of events that this subscriber wants to listen to. + * The class constructor. * - * @since 3.2.0 - * @return array + * @since 3.2.1 */ - public static function get_subscribed_events() { - $events = array( - 'edd_daily_scheduled_events' => 'check_license', - 'edd/license/deleted' => 'license_updated', - 'edd/license/saved' => 'license_updated', - 'admin_notices' => 'register_admin_notices', - 'edd_sales_summary_widget_after_orders' => 'do_dashboard_notice', - ); + public function __construct() { + add_action( 'edd_daily_scheduled_events', array( $this, 'check_license' ) ); + add_action( 'edd/license/deleted', array( $this, 'license_updated' ) ); + add_action( 'edd/license/saved', array( $this, 'license_updated' ) ); + add_action( 'admin_notices', array( $this, 'register_admin_notices' ) ); + add_action( 'edd_sales_summary_widget_after_orders', array( $this, 'do_dashboard_notice' ) ); if ( get_transient( 'edd_stripe_check_license' ) || get_transient( 'edds_stripe_check_license' ) ) { - $events['admin_init'] = 'check_license'; + add_action( 'admin_init', array( $this, 'check_license' ) ); } - - return $events; } /** @@ -116,13 +109,11 @@ public function register_admin_notices() { if ( function_exists( 'edd_is_admin_page' ) && ! edd_is_admin_page() ) { return; } - if ( ! $this->are_requirements_met() ) { - return; - } - $license = $this->get_license(); - if ( $license->is_license_valid() ) { + if ( ! $this->should_show_warnings() ) { return; } + + $license = $this->get_license(); $admin_notice_args = array( 'id' => 'missing', 'type' => 'error', @@ -147,14 +138,11 @@ public function do_dashboard_notice() { if ( ! current_user_can( 'manage_shop_settings' ) ) { return; } - if ( ! $this->are_requirements_met() ) { - return; - } - $license = $this->get_license(); - if ( $license->is_license_valid() ) { + if ( ! $this->should_show_warnings() ) { return; } + $license = $this->get_license(); $message = sprintf( /* translators: %1$s is the opening link tag; %2$s is the closing link tag. */ __( 'Your license is not active. Please %1$sactivate your license%2$s.', 'easy-digital-downloads' ), @@ -438,4 +426,43 @@ private function are_requirements_met() { return edd_is_gateway_active( 'stripe' ); } + + /** + * Whether the admin warnings should be shown. + * + * @since 3.2.1 + * @return bool + */ + private function should_show_warnings() { + + // If Stripe is not connected and active, don't show the warnings. + if ( ! $this->are_requirements_met() ) { + return false; + } + + $license = $this->get_license(); + + // If the requirements are met to remove the application fee, don't show the warnings. + if ( ! edd_stripe()->application_fee->has_application_fee() ) { + // (Unless the license is in a grace period). + return $license->is_in_grace_period(); + } + + // There is an application fee, but Stripe Pro is active, so show the warnings. + if ( edds_is_pro() ) { + return true; + } + + // There isn't a Stripe qualified license, but it's EDD Lite. + if ( empty( $license->license_data->key ) && ! edd_is_pro() ) { + return false; + } + + // There is pass license active, but it's not for a pass that includes Stripe. + if ( ! empty( $license->pass_id ) ) { + return false; + } + + return true; + } } diff --git a/src/Gateways/Stripe/ApplicationFee.php b/src/Gateways/Stripe/ApplicationFee.php index c31a39af22..325b975464 100644 --- a/src/Gateways/Stripe/ApplicationFee.php +++ b/src/Gateways/Stripe/ApplicationFee.php @@ -228,7 +228,7 @@ private function get_license_message() { return ' ' . sprintf( /* translators: opening link tag, do not translate; closing link tag, do not translate */ - __( '%1$sActivate your license%2$s to remove additional fees.', 'easy-digital-downloads' ), + __( '%1$sActivate or upgrade your license%2$s to remove additional fees.', 'easy-digital-downloads' ), '', '' ); diff --git a/src/Gateways/Stripe/License.php b/src/Gateways/Stripe/License.php index 88594f88f1..36b6a783d2 100644 --- a/src/Gateways/Stripe/License.php +++ b/src/Gateways/Stripe/License.php @@ -25,10 +25,32 @@ final class License { */ public $is_pass_license = false; + /** + * The pass ID. + * + * @var int + */ + public $pass_id; + + /** + * Whether the pass is valid for Stripe Pro, even if it's not a pro license. + * + * @var bool + */ + private $is_pass_valid_for_stripe; + + /** + * The item name. + * + * @var string + */ + private $item_name = 'Stripe Pro Payment Gateway'; + /** * The class constructor. */ public function __construct() { + $this->is_pass_valid_for_stripe(); $this->license_data = $this->get_license_data(); } @@ -223,11 +245,15 @@ private function get_license_data() { } // Check for a Stripe Pro license key. - $license = new \EDD\Licensing\License( 'Stripe Pro Payment Gateway' ); + $license = new \EDD\Licensing\License( $this->item_name ); if ( ! empty( $license->key ) ) { return $license; } + if ( $this->is_pass_valid_for_stripe() ) { + return $this->maybe_fix_missing_license(); + } + return false; } @@ -242,17 +268,35 @@ private function get_pass_license() { if ( empty( $pro_license->key ) ) { return false; } - $pass_manager = new \EDD\Admin\Pass_Manager(); - if ( $pass_manager::pass_compare( $pass_manager->highest_pass_id, $pass_manager::EXTENDED_PASS_ID, '>=' ) ) { - return $pro_license; - } - if ( $pass_manager->hasExtendedPass() || $pass_manager->hasAllAccessPass() ) { + if ( ! empty( $pro_license->key ) && $this->is_pass_valid_for_stripe() ) { return $pro_license; } return false; } + /** + * Whether the pass is valid for Stripe Pro, even if it's not a pro license. + * + * @since 3.2.1 + * @return bool + */ + private function is_pass_valid_for_stripe() { + if ( ! is_null( $this->is_pass_valid_for_stripe ) ) { + return $this->is_pass_valid_for_stripe; + } + $this->is_pass_valid_for_stripe = false; + $pass_manager = new \EDD\Admin\Pass_Manager(); + if ( empty( $pass_manager->highest_pass_id ) ) { + return $this->is_pass_valid_for_stripe; + } + + $this->pass_id = $pass_manager->highest_pass_id; + $this->is_pass_valid_for_stripe = $pass_manager::pass_compare( $pass_manager->highest_pass_id, $pass_manager::EXTENDED_PASS_ID, '>=' ); + + return $this->is_pass_valid_for_stripe; + } + /** * Gets the end time for the new install grace period. * @@ -283,4 +327,47 @@ private function get_localized_date( $date ) { $date ); } + + /** + * Fixes a missing Stripe Pro license. + * + * @since 3.2.1 + * @return bool|\EDD\Licensing\License + */ + private function maybe_fix_missing_license() { + if ( ! empty( $this->license_data ) ) { + return false; + } + if ( edd_is_pro() ) { + return false; + } + + $pass_manager = new \EDD\Admin\Pass_Manager(); + $shortname = 'edd_' . preg_replace( '/[^a-zA-Z0-9_\s]/', '', str_replace( ' ', '_', strtolower( $this->item_name ) ) ); + + // Save the license key for Stripe. + edd_update_option( "{$shortname}_license_key", $pass_manager->highest_license_key ); + + $api_params = array( + 'edd_action' => 'activate_license', + 'license' => $pass_manager->highest_license_key, + 'item_name' => $this->item_name, + 'item_id' => 167, + 'environment' => wp_get_environment_type(), + ); + $api = new \EDD\Licensing\API(); + $license_data = $api->make_request( $api_params ); + + // Save the license data, no matter what the response was. + $license = new \EDD\Licensing\License( $this->item_name ); + $license->save( $license_data ); + + // Clear the option for licensed extensions to force regeneration. + if ( ! empty( $license_data->license ) && 'valid' === $license_data->license ) { + delete_option( 'edd_licensed_extensions' ); + } + + // Return a new license object. + return new \EDD\Licensing\License( $this->item_name ); + } } diff --git a/src/Licensing/Traits/Controls.php b/src/Licensing/Traits/Controls.php index e91a04c20a..8c7699f561 100644 --- a/src/Licensing/Traits/Controls.php +++ b/src/Licensing/Traits/Controls.php @@ -1,7 +1,7 @@ assertNotEmpty( $payment ); } + public function test_no_empty_payment_meta_is_saved() { + $this->assertFalse( $this->payment->update_meta( '_edd_payment_meta', array() ) ); + } + /* Helpers ***************************************************************/ public function alter_payment_meta( $meta, $payment_data ) { diff --git a/tests/stripe/admin/tests-license-manager.php b/tests/stripe/admin/tests-license-manager.php index 87f0db9346..b50e7b7be5 100644 --- a/tests/stripe/admin/tests-license-manager.php +++ b/tests/stripe/admin/tests-license-manager.php @@ -47,10 +47,6 @@ public function tearDown(): void { $current_user = self::$original_user; } - public function test_admin_notice_missing_license() { - $this->assertStringContainsString( 'Activate your license key', $this->get_notice() ); - } - public function test_admin_notice_valid_license_empty() { LicenseData::get_pro_license(); diff --git a/tests/stripe/tests-application-fee.php b/tests/stripe/tests-application-fee.php index 9acdadd786..904b5a74b0 100644 --- a/tests/stripe/tests-application-fee.php +++ b/tests/stripe/tests-application-fee.php @@ -170,7 +170,7 @@ public function test_pro_license_disabled_has_application_fee_is_true() { $this->assertFalse( $license->is_license_valid() ); $this->assertTrue( edd_stripe()->application_fee->has_application_fee() ); if ( edd_is_pro() ) { - $this->assertStringContainsString( 'Activate your license', edd_stripe()->application_fee->get_fee_message() ); + $this->assertStringContainsString( 'Activate or upgrade your license', edd_stripe()->application_fee->get_fee_message() ); } remove_filter( 'wp_doing_ajax', '__return_true' ); diff --git a/tests/tests-api.php b/tests/tests-api.php index 5eb56ed003..c45b353e29 100755 --- a/tests/tests-api.php +++ b/tests/tests-api.php @@ -23,6 +23,8 @@ class Tests_API extends EDD_UnitTestCase { protected static $payment_id; + protected static $payment; + /** * Set up fixtures once. */ @@ -157,6 +159,7 @@ public static function wpSetUpBeforeClass() { $_SERVER['REMOTE_ADDR'] = '10.0.0.0'; self::$payment_id = edd_insert_payment( $purchase_data ); + self::$payment = edd_get_payment( self::$payment_id ); // We don't want to trigger purchase receipts here. remove_action( 'edd_complete_purchase', 'edd_trigger_purchase_receipt', 999 ); @@ -169,6 +172,9 @@ public static function wpSetUpBeforeClass() { $_POST['edd_set_api_key'] = 1; EDD()->api->update_key( self::$user_id ); + + // Generate a file download log. + edd_record_download_in_log( self::$post->ID, 0, array(), '127.0.0.1', self::$payment_id, 'EDD\Tests' ); } public function setup(): void { @@ -431,7 +437,7 @@ public function test_get_customers() { $this->assertEquals( 'admin@example.org', $out['customers'][0]['info']['email'] ); $this->assertEquals( 1, $out['customers'][0]['stats']['total_purchases'] ); $this->assertEquals( 100.0, $out['customers'][0]['stats']['total_spent'] ); - $this->assertEquals( 0, $out['customers'][0]['stats']['total_downloads'] ); + $this->assertEquals( 1, $out['customers'][0]['stats']['total_downloads'] ); } catch ( \WPDieException $e ) {} } @@ -603,4 +609,83 @@ public function test_recent_sales_contains_correct_discount_amount() { $this->assertEquals( 20, $sales_output['sales'][0]['discounts']['20OFF'] ); } + public function test_file_download_logs_generic() { + try { + $out = EDD()->api->get_download_logs(); + + $this->assertArrayHasKey( 'download_logs', $out ); + + $logs = $out['download_logs']; + + $this->assertEquals( 1, count( $logs ) ); + + $this->assertArrayHasKey( 'ID', $logs[0] ); + $this->assertArrayHasKey( 'user_id', $logs[0] ); + $this->assertArrayHasKey( 'product_id', $logs[0] ); + $this->assertArrayHasKey( 'product_name', $logs[0] ); + $this->assertArrayHasKey( 'customer_id', $logs[0] ); + $this->assertArrayHasKey( 'payment_id', $logs[0] ); + $this->assertArrayHasKey( 'file', $logs[0] ); + $this->assertArrayHasKey( 'ip', $logs[0] ); + $this->assertArrayHasKey( 'date', $logs[0] ); + + } catch ( \WPDieException $e ) {} + } + + public function test_file_download_logs_by_customer_id() { + try { + $out = EDD()->api->get_download_logs( self::$payment->customer_id ); + + $this->assertArrayHasKey( 'download_logs', $out ); + + $logs = $out['download_logs']; + + $this->assertEquals( 1, count( $logs ) ); + + $this->assertArrayHasKey( 'ID', $logs[0] ); + $this->assertArrayHasKey( 'user_id', $logs[0] ); + $this->assertArrayHasKey( 'product_id', $logs[0] ); + $this->assertArrayHasKey( 'product_name', $logs[0] ); + $this->assertArrayHasKey( 'customer_id', $logs[0] ); + $this->assertArrayHasKey( 'payment_id', $logs[0] ); + $this->assertArrayHasKey( 'file', $logs[0] ); + $this->assertArrayHasKey( 'ip', $logs[0] ); + $this->assertArrayHasKey( 'date', $logs[0] ); + + } catch ( \WPDieException $e ) {} + } + + public function test_file_download_logs_by_customer_email() { + try { + $out = EDD()->api->get_download_logs( self::$payment->email ); + + $this->assertArrayHasKey( 'download_logs', $out ); + + $logs = $out['download_logs']; + + $this->assertEquals( 1, count( $logs ) ); + + $this->assertArrayHasKey( 'ID', $logs[0] ); + $this->assertArrayHasKey( 'user_id', $logs[0] ); + $this->assertArrayHasKey( 'product_id', $logs[0] ); + $this->assertArrayHasKey( 'product_name', $logs[0] ); + $this->assertArrayHasKey( 'customer_id', $logs[0] ); + $this->assertArrayHasKey( 'payment_id', $logs[0] ); + $this->assertArrayHasKey( 'file', $logs[0] ); + $this->assertArrayHasKey( 'ip', $logs[0] ); + $this->assertArrayHasKey( 'date', $logs[0] ); + + } catch ( \WPDieException $e ) {} + } + + public function test_file_download_logs_by_invalid_customer_id() { + try { + $out = EDD()->api->get_download_logs( 99999 ); + + $this->assertArrayHasKey( 'error', $out ); + $this->assertSame( 'No download logs found!', $out['error'] ); + + } catch ( \WPDieException $e ) {} + } + }