From 56e03c054498bd6b495aef5a337e7d96e7cb009a Mon Sep 17 00:00:00 2001 From: WooCommerce Date: Thu, 8 Jan 2026 10:21:29 +0000 Subject: [PATCH] Updates to 8.3.0 --- assets/css/admin.css | 14 + assets/js/admin/admin.js | 56 +- assets/js/admin/writepanel.js | 31 - assets/js/gifting/wcs-gifting.js | 7 +- build/admin.asset.php | 1 + build/admin.js | 1 + build/gifting-welcome-announcement.asset.php | 1 - build/gifting-welcome-announcement.js | 1 - build/index.asset.php | 2 +- build/index.js | 6 +- ...nouncement-rtl.css => style-admin-rtl.css} | 0 ...lcome-announcement.css => style-admin.css} | 0 build/wcsg-blocks-integration.asset.php | 2 +- build/wcsg-blocks-integration.js | 2 +- changelog.txt | 6 + includes/admin/class-wcs-admin-assets.php | 59 + ...bscriptions-settings-option-controller.php | 1 + includes/class-wc-subscriptions-plugin.php | 11 +- includes/class-wcs-autoloader.php | 1 + includes/core/class-wcs-limiter.php | 213 +- ...ass-wcs-email-customer-renewal-invoice.php | 4 +- .../class-wc-subscriptions-upgrader.php | 5 +- ...php => class-wcs-plugin-upgrade-8-3-0.php} | 2 +- ...n-downloads-admin-welcome-announcement.php | 93 + .../class-wc-subscription-downloads-ajax.php | 36 + ...ass-wc-subscription-downloads-products.php | 640 ++- ...ass-wc-subscription-downloads-settings.php | 9 +- .../class-wcsg-admin-welcome-announcement.php | 39 +- .../class-wc-subscriptions-switcher.php | 88 +- languages/woocommerce-subscriptions.pot | 307 +- phpstan.neon | 3717 +++++++++++++++++ src/Internal/Utilities/Request.php | 102 + templates/admin/html-variation-price.php | 2 + vendor/composer/autoload_classmap.php | 2 + vendor/composer/autoload_static.php | 2 + vendor/composer/installed.php | 12 +- woocommerce-subscriptions.php | 4 +- 37 files changed, 5052 insertions(+), 427 deletions(-) delete mode 100644 assets/js/admin/writepanel.js create mode 100644 build/admin.asset.php create mode 100644 build/admin.js delete mode 100644 build/gifting-welcome-announcement.asset.php delete mode 100644 build/gifting-welcome-announcement.js rename build/{style-gifting-welcome-announcement-rtl.css => style-admin-rtl.css} (100%) rename build/{style-gifting-welcome-announcement.css => style-admin.css} (100%) create mode 100644 includes/admin/class-wcs-admin-assets.php rename includes/core/upgrades/{class-wcs-plugin-upgrade-8-1-0.php => class-wcs-plugin-upgrade-8-3-0.php} (96%) create mode 100644 includes/downloads/class-wc-subscription-downloads-admin-welcome-announcement.php create mode 100644 phpstan.neon create mode 100644 src/Internal/Utilities/Request.php diff --git a/assets/css/admin.css b/assets/css/admin.css index 7ae14ae..447f98e 100644 --- a/assets/css/admin.css +++ b/assets/css/admin.css @@ -77,6 +77,14 @@ a.close-subscriptions-search { display: block; width: 50%; } + +.woocommerce_options_panel ._subscription_downloads_field .description, +.woocommerce_options_panel .subscription_linked_downloadable_products .description { + clear: both; + display: block; + margin: 0; +} + /* Variation Subscription Product Sync Settings */ .variable_subscription_sync .subscription_sync_annual > .select2-container { max-width: 48%; @@ -385,6 +393,12 @@ p._subscription_gifting_field_description.form-field .description { opacity: 0.5; } +#woocommerce-product-data + .form-field._subscription_downloads_field + .select2-selection__choice { + font-size: 14px; +} + /* Variation Pricing Fields with WooCommerce 3.0+ */ .wc-metaboxes-wrapper .variable_subscription_trial label, .wc-metaboxes-wrapper .variable_subscription_pricing label, diff --git a/assets/js/admin/admin.js b/assets/js/admin/admin.js index 3101e78..257b38d 100644 --- a/assets/js/admin/admin.js +++ b/assets/js/admin/admin.js @@ -639,6 +639,53 @@ jQuery( function ( $ ) { }, } ); + /** + * Relocates the linked downloadable product fields in the context of a variable subscription product, and + * selectively shows/hides it, depending on whether the variation is downloadable or not. + */ + function initLinkedDownloadableProductFieldsForVariationProduct() { + $( '#variable_product_options .variable_subscription_linked_downloadable_products' ) + .not( '.wcs_moved' ) + .each( function () { + const $this = $( this ); + const $variablePricing = $( this ).siblings( '.variable_pricing' ); + + const $downloadableFiles = $( this ).siblings( '.form-row.downloadable_files' ).parent( 'div' ); + + $this.insertAfter( $downloadableFiles ); + $this.addClass( 'wcs_gifting_moved' ); + } ); + } + + /** + * Move the linked downloadable product fields to the correct location (which is underneath the downloadable files + * section). + */ + function relocateLinkedDownloadableProductFields() { + const $linkedDownloadableProducts = $( '.subscription_linked_downloadable_products_section' ); + const $productTypeSelector = $('select#product-type'); + + const showHide = () => { + $productTypeSelector.val() === WCSubscriptions.productType + ? $linkedDownloadableProducts.show() + : $linkedDownloadableProducts.hide(); + }; + + $linkedDownloadableProducts + .not( '.wcs_moved' ) + .each( function () { + const $downloadableFilesSection = $( '.form-field.downloadable_files' ).parent( 'div' ); + + if ( $downloadableFilesSection.length === 1 ) { + $( this ).insertAfter( $downloadableFilesSection ); + $( this ).addClass( 'wcs_moved' ); + } + } ); + + showHide(); + $productTypeSelector.on( 'change', showHide ); + } + $( '.options_group.pricing ._sale_price_field .description' ).prepend( '' ); @@ -653,9 +700,9 @@ jQuery( function ( $ ) { $( '.options_group.subscription_pricing' ) ); - // Move the subscription variation pricing and gifting sections to a better location in the DOM on load - // We do this because these sections are initially loaded at the end of the variable product options section, - // which is not the best location for them, so we move to before the "Sale price" section. + // Move the subscription variation pricing, gifting and linked downloadable product sections to a better location in + // the DOM on load. We do this because these sections are initially loaded at the end of the variable product + // options section, which is not the best location for them, so we move to before the "Sale price" section. if ( $( '#variable_product_options .variable_subscription_pricing' ).length > 0 @@ -668,6 +715,7 @@ jQuery( function ( $ ) { ) { $.moveSubscriptionGiftingFields(); } + // When a variation is added $( '#woocommerce-product-data' ).on( 'woocommerce_variations_added woocommerce_variations_loaded', @@ -677,6 +725,7 @@ jQuery( function ( $ ) { $.showHideVariableSubscriptionMeta(); $.showHideSyncOptions(); $.setSubscriptionLengths(); + initLinkedDownloadableProductFieldsForVariationProduct(); } ); @@ -690,6 +739,7 @@ jQuery( function ( $ ) { $.showHideSyncOptions(); $.disableEnableOneTimeShipping(); $.showHideSubscriptionsPanels(); + relocateLinkedDownloadableProductFields(); } // Update subscription ranges when subscription period or interval is changed diff --git a/assets/js/admin/writepanel.js b/assets/js/admin/writepanel.js deleted file mode 100644 index 6b91bd0..0000000 --- a/assets/js/admin/writepanel.js +++ /dev/null @@ -1,31 +0,0 @@ -/* global wc_subscription_downloads_product */ -jQuery( document ).ready( function ( $ ) { - function subscriptionDownloadsChosen() { - $( 'select.subscription-downloads-ids' ).ajaxChosen({ - method: 'GET', - url: wc_subscription_downloads_product.ajax_url, - dataType: 'json', - afterTypeDelay: 100, - minTermLength: 1, - data: { - action: 'wc_subscription_downloads_search', - security: wc_subscription_downloads_product.security - } - }, function ( data ) { - - var orders = {}; - - $.each( data, function ( i, val ) { - orders[i] = val; - }); - - return orders; - }); - } - - subscriptionDownloadsChosen(); - - $( 'body' ).on( 'woocommerce_variations_added', function () { - subscriptionDownloadsChosen(); - }); -}); diff --git a/assets/js/gifting/wcs-gifting.js b/assets/js/gifting/wcs-gifting.js index 65f5d86..2efe9af 100644 --- a/assets/js/gifting/wcs-gifting.js +++ b/assets/js/gifting/wcs-gifting.js @@ -18,7 +18,8 @@ jQuery( document ).ready( function ( $ ) { .find( '.recipient_email' ) .trigger( 'focus' ); } - } ); + } ) + .removeClass( 'hidden' ); const shipToDifferentAddressCheckbox = $( document ).find( '#ship-to-different-address-checkbox' @@ -31,12 +32,14 @@ jQuery( document ).ready( function ( $ ) { $( this ) .closest( '.wcsg_add_recipient_fields_container' ) .find( '.wcsg_add_recipient_fields' ) - .slideUp( 250 ); + .slideUp( 250 ) + .addClass( 'hidden' ); const recipientEmailElement = $( this ) .closest( '.wcsg_add_recipient_fields_container' ) .find( '.recipient_email' ); recipientEmailElement.val( '' ); + hideValidationErrorForEmailField( recipientEmailElement ); setShippingAddressNoticeVisibility( true ); if ( $( 'form.checkout' ).length !== 0 ) { diff --git a/build/admin.asset.php b/build/admin.asset.php new file mode 100644 index 0000000..6c89127 --- /dev/null +++ b/build/admin.asset.php @@ -0,0 +1 @@ + array('react', 'react-dom', 'wp-api-fetch', 'wp-components', 'wp-i18n', 'wp-primitives'), 'version' => '8bad0ce18409676b15d1'); diff --git a/build/admin.js b/build/admin.js new file mode 100644 index 0000000..e9c601d --- /dev/null +++ b/build/admin.js @@ -0,0 +1 @@ +(()=>{"use strict";var e,o={20:(e,o,t)=>{var s=t(609),n=Symbol.for("react.element"),i=(Symbol.for("react.fragment"),Object.prototype.hasOwnProperty),r=s.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,c={key:!0,ref:!0,__self:!0,__source:!0};function a(e,o,t){var s,a={},d=null,l=null;for(s in void 0!==t&&(d=""+t),void 0!==o.key&&(d=""+o.key),void 0!==o.ref&&(l=o.ref),o)i.call(o,s)&&!c.hasOwnProperty(s)&&(a[s]=o[s]);if(e&&e.defaultProps)for(s in o=e.defaultProps)void 0===a[s]&&(a[s]=o[s]);return{$$typeof:n,type:e,key:d,ref:l,props:a,_owner:r.current}}o.jsx=a,o.jsxs=a},175:(e,o,t)=>{var s=t(609),n=t(338);const i=window.wp.components,r=window.wp.primitives;var c=t(848);const a=(0,c.jsx)(r.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,c.jsx)(r.Path,{d:"M12 13.06l3.712 3.713 1.061-1.06L13.061 12l3.712-3.712-1.06-1.06L12 10.938 8.288 7.227l-1.061 1.06L10.939 12l-3.712 3.712 1.06 1.061L12 13.061z"})}),d=window.wp.i18n,l=window.wp.apiFetch;var m=t.n(l);const u=({imagesPath:e,redirectUrl:o,data:t,dismissOption:n,isSubscriptionsListing:r})=>{const[l,u]=(0,s.useState)(r),p=(0,s.useRef)(!1),{headerImage:w,heading:b,description:_,primaryButton:g,secondaryButton:h}=t,f=()=>{if(p.current)return;const e="?page=wc-admin"===window.location.search;u(e)};(0,s.useEffect)(()=>{if(r)return;const{pushState:e,replaceState:o}=window.history;window.history.pushState=function(...o){e.apply(window.history,o),window.dispatchEvent(new Event("pushState"))},window.history.replaceState=function(...e){o.apply(window.history,e),window.dispatchEvent(new Event("replaceState"))},window.addEventListener("popstate",f),window.addEventListener("replaceState",f),window.addEventListener("pushState",f),f()},[]);const v=e=>{var t;t=n,m()({path:`/wc/v3/subscriptions/settings/${t}`,method:"post",data:{value:true}}),p.current=!0,"done-btn"!==e?(u(!1),window.removeEventListener("popstate",f),window.removeEventListener("replaceState",f),window.removeEventListener("pushState",f)):window.location.href=o};return l?(0,c.jsx)("div",{className:"woocommerce-subscriptions-announcement",children:(0,c.jsx)("div",{className:"woocommerce-subscriptions-announcement__container",children:(0,c.jsxs)(i.Card,{className:"woocommerce-tour-kit-step",elevation:2,children:[(0,c.jsx)(i.CardHeader,{isBorderless:!0,size:"small",className:"woocommerce-tour-kit-step__header",children:(0,c.jsx)(i.Flex,{className:"woocommerce-tour-kit-step-controls",justify:"flex-end",children:(0,c.jsx)(i.Button,{className:"woocommerce-tour-kit-step-controls__close-btn",label:(0,d.__)("Close","woocommerce-subscriptions"),icon:(0,c.jsx)(i.Icon,{icon:a,viewBox:"6 4 12 14"}),iconSize:16,onClick:()=>v("close-btn")})})}),w&&(0,c.jsx)(i.CardMedia,{className:"woocommerce-tour-kit-step__header-image",children:(0,c.jsx)("img",{src:e+"/"+w,alt:(0,d.__)("Step image","woocommerce-subscriptions")})}),(0,c.jsxs)(i.CardBody,{className:"woocommerce-tour-kit-step__body",size:"small",children:[(0,c.jsx)("h2",{className:"woocommerce-tour-kit-step__heading",children:b}),(0,c.jsx)("p",{className:"woocommerce-tour-kit-step__description",dangerouslySetInnerHTML:{__html:_}})]}),(0,c.jsx)(i.CardFooter,{isBorderless:!0,size:"small",children:(0,c.jsx)("div",{className:"woocommerce-tour-kit-step-navigation",children:(0,c.jsxs)("div",{children:[(0,c.jsx)(i.Button,{className:"woocommerce-tour-kit-step-navigation__back-btn",variant:"tertiary",onClick:()=>v("close-btn"),children:h.text||(0,d.__)("Close","woocommerce-subscriptions")}),(0,c.jsx)(i.Button,{className:"woocommerce-tour-kit-step-navigation__next-btn",variant:"primary",disabled:g.isDisabled,onClick:()=>v("done-btn"),children:g.text||(0,d.__)("Done","woocommerce-subscriptions")})]})})})]})})}):null};if(window?.wcsDownloadsSettings?.isStandaloneDownloadsEnabled){const{imagesPath:e,pluginsUrl:o,isSubscriptionsListing:t,isStandaloneDownloadsEnabled:s}=window.wcsDownloadsSettings,i=(0,n.H)(document.getElementById("wcs-downloads-welcome-announcement-root")),r=(()=>{const e=(0,d.__)("WooCommerce Subscription Downloads is now part of WooCommerce Subscriptions","woocommerce-subscriptions"),o=`${(0,d.__)("No separate extension required! WooCommerce Subscriptions now allows you to include simple and variable products with your subscriptions. And to make it easier, you can now configure which simple and variable products to include when creating a subscription product.","woocommerce-subscriptions")}\n\t\t

\n\t\t${(0,d.__)("The WooCommerce Subscription Downloads extension can now be disabled via Plugins.","woocommerce-subscriptions")}`,t=(0,d.__)("Go to plugins","woocommerce-subscriptions");return{name:"gifting-announcement",heading:e,headerImage:"gifting-modal-icon.svg",description:o,secondaryButton:{text:(0,d.__)("Maybe later","woocommerce-subscriptions")},primaryButton:{text:t}}})();i.render((0,c.jsx)(u,{imagesPath:e,data:r,dismissOption:"woocommerce_subscriptions_downloads_is_welcome_announcement_dismissed",redirectUrl:o,isSubscriptionsListing:!!t}))}const p=(0,n.H)(document.getElementById("wcs-gifting-welcome-announcement-root")),w=(e=>{const o=e?(0,d.__)("Gifting is now part of WooCommerce Subscriptions","woocommerce-subscriptions"):(0,d.__)("Introducing subscription gifting","woocommerce-subscriptions"),t=e?`${(0,d.__)("No separate extension needed! The built-in gifting feature is fully compatible with product, cart and checkout blocks, plus you can now choose which subscription products can be gifted.","woocommerce-subscriptions")}\n\t\t\t

\n\t\t\t${(0,d.__)("The Gifting for WooCommerce Subscriptions extension can now be disabled via Plugins.","woocommerce-subscriptions")}`:(0,d.__)("Let your shoppers purchase subscriptions as gifts using the new built-in gifting feature in WooCommerce Subscriptions. It works seamlessly with product, cart and checkout blocks, and can be enabled storewide or managed per product.","woocommerce-subscriptions"),s=e?(0,d.__)("Go to plugins","woocommerce-subscriptions"):(0,d.__)("Set up gifting","woocommerce-subscriptions");return{name:"gifting-announcement",heading:o,headerImage:"gifting-modal-icon.svg",description:t,secondaryButton:{text:(0,d.__)("Maybe later","woocommerce-subscriptions")},primaryButton:{text:s}}})(window.wcsGiftingSettings.isStandaloneGiftingEnabled),{imagesPath:b,pluginsUrl:_,subscriptionsUrl:g,isStandaloneGiftingEnabled:h,isSubscriptionsListing:f}=window.wcsGiftingSettings;p.render((0,c.jsx)(u,{imagesPath:b,data:w,dismissOption:"woocommerce_subscriptions_gifting_is_welcome_announcement_dismissed",redirectUrl:h?_:g,isSubscriptionsListing:!!f}))},338:(e,o,t)=>{var s=t(795);o.H=s.createRoot,s.hydrateRoot},609:e=>{e.exports=window.React},795:e=>{e.exports=window.ReactDOM},848:(e,o,t)=>{e.exports=t(20)}},t={};function s(e){var n=t[e];if(void 0!==n)return n.exports;var i=t[e]={exports:{}};return o[e](i,i.exports,s),i.exports}s.m=o,e=[],s.O=(o,t,n,i)=>{if(!t){var r=1/0;for(l=0;l=i)&&Object.keys(s.O).every(e=>s.O[e](t[a]))?t.splice(a--,1):(c=!1,i0&&e[l-1][2]>i;l--)e[l]=e[l-1];e[l]=[t,n,i]},s.n=e=>{var o=e&&e.__esModule?()=>e.default:()=>e;return s.d(o,{a:o}),o},s.d=(e,o)=>{for(var t in o)s.o(o,t)&&!s.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:o[t]})},s.o=(e,o)=>Object.prototype.hasOwnProperty.call(e,o),(()=>{var e={884:0,15:0};s.O.j=o=>0===e[o];var o=(o,t)=>{var n,i,[r,c,a]=t,d=0;if(r.some(o=>0!==e[o])){for(n in c)s.o(c,n)&&(s.m[n]=c[n]);if(a)var l=a(s)}for(o&&o(t);ds(175));n=s.O(n)})(); \ No newline at end of file diff --git a/build/gifting-welcome-announcement.asset.php b/build/gifting-welcome-announcement.asset.php deleted file mode 100644 index c9d1e03..0000000 --- a/build/gifting-welcome-announcement.asset.php +++ /dev/null @@ -1 +0,0 @@ - array('react', 'react-dom', 'wp-api-fetch', 'wp-components', 'wp-element', 'wp-i18n', 'wp-primitives'), 'version' => 'b52cf873a54e347c8f9e'); diff --git a/build/gifting-welcome-announcement.js b/build/gifting-welcome-announcement.js deleted file mode 100644 index c167892..0000000 --- a/build/gifting-welcome-announcement.js +++ /dev/null @@ -1 +0,0 @@ -(()=>{"use strict";var e,o={20:(e,o,t)=>{var i=t(609),n=Symbol.for("react.element"),s=(Symbol.for("react.fragment"),Object.prototype.hasOwnProperty),r=i.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,c={key:!0,ref:!0,__self:!0,__source:!0};function a(e,o,t){var i,a={},d=null,l=null;for(i in void 0!==t&&(d=""+t),void 0!==o.key&&(d=""+o.key),void 0!==o.ref&&(l=o.ref),o)s.call(o,i)&&!c.hasOwnProperty(i)&&(a[i]=o[i]);if(e&&e.defaultProps)for(i in o=e.defaultProps)void 0===a[i]&&(a[i]=o[i]);return{$$typeof:n,type:e,key:d,ref:l,props:a,_owner:r.current}}o.jsx=a,o.jsxs=a},338:(e,o,t)=>{var i=t(795);o.H=i.createRoot,i.hydrateRoot},609:e=>{e.exports=window.React},736:(e,o,t)=>{var i=t(609),n=t(338);const s=window.wp.components,r=window.wp.element,c=window.wp.primitives,a=(0,r.createElement)(c.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},(0,r.createElement)(c.Path,{d:"M12 13.06l3.712 3.713 1.061-1.06L13.061 12l3.712-3.712-1.06-1.06L12 10.938 8.288 7.227l-1.061 1.06L10.939 12l-3.712 3.712 1.06 1.061L12 13.061z"})),d=window.wp.i18n,l=window.wp.apiFetch;var m=t.n(l),p=t(848);const u=({imagesPath:e,redirectUrl:o,data:t,dismissOption:n,isSubscriptionsListing:r})=>{const[c,l]=(0,i.useState)(r),u=(0,i.useRef)(!1),{headerImage:w,heading:h,description:_,primaryButton:b,secondaryButton:g}=t,f=()=>{if(u.current)return;const e="?page=wc-admin"===window.location.search;l(e)};(0,i.useEffect)((()=>{if(r)return;const{pushState:e,replaceState:o}=window.history;window.history.pushState=function(...o){e.apply(window.history,o),window.dispatchEvent(new Event("pushState"))},window.history.replaceState=function(...e){o.apply(window.history,e),window.dispatchEvent(new Event("replaceState"))},window.addEventListener("popstate",f),window.addEventListener("replaceState",f),window.addEventListener("pushState",f),f()}),[]);const v=e=>{var t;t=n,m()({path:`/wc/v3/subscriptions/settings/${t}`,method:"post",data:{value:true}}),u.current=!0,"done-btn"!==e?(l(!1),window.removeEventListener("popstate",f),window.removeEventListener("replaceState",f),window.removeEventListener("pushState",f)):window.location.href=o};return c?(0,p.jsx)("div",{className:"woocommerce-subscriptions-announcement",children:(0,p.jsx)("div",{className:"woocommerce-subscriptions-announcement__container",children:(0,p.jsxs)(s.Card,{className:"woocommerce-tour-kit-step",elevation:2,children:[(0,p.jsx)(s.CardHeader,{isBorderless:!0,size:"small",className:"woocommerce-tour-kit-step__header",children:(0,p.jsx)(s.Flex,{className:"woocommerce-tour-kit-step-controls",justify:"flex-end",children:(0,p.jsx)(s.Button,{className:"woocommerce-tour-kit-step-controls__close-btn",label:(0,d.__)("Close","woocommerce-subscriptions"),icon:(0,p.jsx)(s.Icon,{icon:a,viewBox:"6 4 12 14"}),iconSize:16,onClick:()=>v("close-btn")})})}),w&&(0,p.jsx)(s.CardMedia,{className:"woocommerce-tour-kit-step__header-image",children:(0,p.jsx)("img",{src:e+"/"+w,alt:(0,d.__)("Step image","woocommerce-subscriptions")})}),(0,p.jsxs)(s.CardBody,{className:"woocommerce-tour-kit-step__body",size:"small",children:[(0,p.jsx)("h2",{className:"woocommerce-tour-kit-step__heading",children:h}),(0,p.jsx)("p",{className:"woocommerce-tour-kit-step__description",dangerouslySetInnerHTML:{__html:_}})]}),(0,p.jsx)(s.CardFooter,{isBorderless:!0,size:"small",children:(0,p.jsx)("div",{className:"woocommerce-tour-kit-step-navigation",children:(0,p.jsxs)("div",{children:[(0,p.jsx)(s.Button,{className:"woocommerce-tour-kit-step-navigation__back-btn",variant:"tertiary",onClick:()=>v("close-btn"),children:g.text||(0,d.__)("Close","woocommerce-subscriptions")}),(0,p.jsx)(s.Button,{className:"woocommerce-tour-kit-step-navigation__next-btn",variant:"primary",disabled:b.isDisabled,onClick:()=>v("done-btn"),children:b.text||(0,d.__)("Done","woocommerce-subscriptions")})]})})})]})})}):null},w=(0,n.H)(document.getElementById("wcs-gifting-welcome-announcement-root")),h=(e=>{const o=e?(0,d.__)("Gifting is now part of WooCommerce Subscriptions","woocommerce-subscriptions"):(0,d.__)("Introducing subscription gifting","woocommerce-subscriptions"),t=e?`${(0,d.__)("No separate extension needed! The built-in gifting feature is fully compatible with product, cart and checkout blocks, plus you can now choose which subscription products can be gifted.","woocommerce-subscriptions")}\n\t\t\t

\n\t\t\t${(0,d.__)("The Gifting for WooCommerce Subscriptions extension can now be disabled via Plugins.","woocommerce-subscriptions")}`:(0,d.__)("Let your shoppers purchase subscriptions as gifts using the new built-in gifting feature in WooCommerce Subscriptions. It works seamlessly with product, cart and checkout blocks, and can be enabled storewide or managed per product.","woocommerce-subscriptions"),i=e?(0,d.__)("Go to plugins","woocommerce-subscriptions"):(0,d.__)("Set up gifting","woocommerce-subscriptions");return{name:"gifting-announcement",heading:o,headerImage:"gifting-modal-icon.svg",description:t,secondaryButton:{text:(0,d.__)("Maybe later","woocommerce-subscriptions")},primaryButton:{text:i}}})(window.wcsGiftingSettings.isStandaloneGiftingEnabled),{imagesPath:_,pluginsUrl:b,subscriptionsUrl:g,isStandaloneGiftingEnabled:f,isSubscriptionsListing:v}=window.wcsGiftingSettings;w.render((0,p.jsx)(u,{imagesPath:_,data:h,dismissOption:"woocommerce_subscriptions_gifting_is_welcome_announcement_dismissed",redirectUrl:f?b:g,isSubscriptionsListing:!!v}))},795:e=>{e.exports=window.ReactDOM},848:(e,o,t)=>{e.exports=t(20)}},t={};function i(e){var n=t[e];if(void 0!==n)return n.exports;var s=t[e]={exports:{}};return o[e](s,s.exports,i),s.exports}i.m=o,e=[],i.O=(o,t,n,s)=>{if(!t){var r=1/0;for(l=0;l=s)&&Object.keys(i.O).every((e=>i.O[e](t[a])))?t.splice(a--,1):(c=!1,s0&&e[l-1][2]>s;l--)e[l]=e[l-1];e[l]=[t,n,s]},i.n=e=>{var o=e&&e.__esModule?()=>e.default:()=>e;return i.d(o,{a:o}),o},i.d=(e,o)=>{for(var t in o)i.o(o,t)&&!i.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:o[t]})},i.o=(e,o)=>Object.prototype.hasOwnProperty.call(e,o),(()=>{var e={716:0,601:0};i.O.j=o=>0===e[o];var o=(o,t)=>{var n,s,[r,c,a]=t,d=0;if(r.some((o=>0!==e[o]))){for(n in c)i.o(c,n)&&(i.m[n]=c[n]);if(a)var l=a(i)}for(o&&o(t);di(736)));n=i.O(n)})(); \ No newline at end of file diff --git a/build/index.asset.php b/build/index.asset.php index 6edb859..6ad1087 100644 --- a/build/index.asset.php +++ b/build/index.asset.php @@ -1 +1 @@ - array('react', 'wc-blocks-checkout', 'wc-blocks-data-store', 'wc-price-format', 'wc-settings', 'wp-data', 'wp-element', 'wp-i18n', 'wp-plugins'), 'version' => '841d6ab2fe0080f15a21'); + array('react', 'wc-blocks-checkout', 'wc-blocks-data-store', 'wc-price-format', 'wc-settings', 'wp-data', 'wp-element', 'wp-i18n', 'wp-plugins'), 'version' => '32bfa486d902830f29c7'); diff --git a/build/index.js b/build/index.js index 1e5456a..133e786 100644 --- a/build/index.js +++ b/build/index.js @@ -7,8 +7,8 @@ * translators: %1$s is the price of the product. %2$s is the separator used e.g "every" or "/", * %3$d is the length, %4$s is week, month, year */ -(0,r.__)("%1$s %2$s %3$d %4$s","woocommerce-subscriptions"),t,i,e,n)}function d({subscriptionLength:e,billingInterval:s}){return e===s}const g=(0,c.getSetting)("countryData",{}),m=(0,c.getSetting)("countries",{}),_={...Object.fromEntries(Object.keys(g).filter((e=>!0===g[e].allowBilling)).map((e=>[e,m[e]||""]))),...Object.fromEntries(Object.keys(g).filter((e=>!0===g[e].allowShipping)).map((e=>[e,m[e]||""])))},h=Object.fromEntries(Object.keys(_).map((e=>[e,g[e].locale||{}]))),b={address:["first_name","last_name","company","address_1","address_2","city","postcode","country","state","phone"],contact:["email"],order:[]},w=Object.entries(h).reduce(((e,[s,i])=>(e[s]=Object.entries(i).reduce(((e,[s,i])=>(e[s]=(e=>{const s={};return void 0!==e.label&&(s.label=e.label),void 0!==e.required&&(s.required=e.required),void 0!==e.hidden&&(s.hidden=e.hidden),void 0===e.label||e.optionalLabel||(s.optionalLabel=(0,r.sprintf)(/* translators: %s Field label. */ /* translators: %s Field label. */ -(0,r.__)("%s (optional)","woocommerce-subscriptions"),e.label)),void 0!==e.optionalLabel&&(s.optionalLabel=e.optionalLabel),e.index&&("number"==typeof e.index&&(s.index=e.index),"string"==typeof e.index&&(s.index=parseInt(e.index,10))),e.hidden&&(s.required=!1),s})(i),e)),{}),e)),{}),y=["state","country","postcode","city"],f=e=>e.some((e=>!!e.shipping_rates.length)),v=(0,c.getSetting)("collectableMethodIds",[]),x=(0,c.getSetting)("localPickupEnabled",!1);var k=i(848);const S=(0,c.getSetting)("displayCartPricesIncludingTax",!1),L=({currency:e,values:s,isLoading:i})=>{const{total_discount:t,total_discount_tax:o}=s,c=parseInt(t,10);if(!c)return null;const a=parseInt(o,10),l=S?c+a:c;return(0,k.jsx)(n.TotalsItem,{className:"wc-block-components-totals-discount",currency:e,label:(0,r.__)("Discount","woocommerce-subscriptions"),value:-1*l,showSkeleton:i})},j=({values:e,currency:s,shippingRatePackages:i,isLoading:t,calculatedShipping:n,shippingAddress:o})=>{const p=(0,a.useSelect)((e=>e(l.checkoutStore).prefersCollection()));if(!n)return null;const u=(m=((e,s)=>e.map((e=>({...e,shipping_rates:e.shipping_rates.filter((e=>{const i=(t=e.method_id,!!x&&(Array.isArray(t)?!!t.find((e=>v.includes(e))):v.includes(t)));var t;return s?i:!i}))}))))(i,null!=p&&p),!!f(m)&&m.every((e=>e.shipping_rates.every((e=>!e.selected||(e=>v.includes(e.method_id))(e)))))),d=!!(g=o).country&&((e,s,i="")=>{const t=i&&void 0!==w[i]?w[i]:{};return e.map((e=>({key:e,...s&&e in s?s[e]:{},...t&&e in t?t[e]:{}}))).sort(((e,s)=>e.index-s.index))})((0,c.getSetting)("addressFieldsLocations",b).address,c.defaultFields,g.country).filter((({key:e})=>y.includes(e))).every((({key:e,hidden:s,required:i})=>!0===s||!1===i||e in g&&""!==g[e]));var g,m;return(0,k.jsx)(I,{label:u?(0,r.__)("Pickup","woocommerce-subscriptions"):(0,r.__)("Delivery","woocommerce-subscriptions"),placeholder:(0,k.jsx)("span",{className:"wc-block-components-shipping-placeholder__value",children:d?(0,r.__)("No available delivery option","woocommerce-subscriptions"):(0,r.__)("Enter address to calculate","woocommerce-subscriptions")}),isLoading:t,shippingRatePackages:i,currency:s,values:e})},I=({values:e,currency:s,shippingRatePackages:i,label:t,placeholder:o,isLoading:a})=>{const l=i?.flatMap((e=>e.shipping_rates)).find((({selected:e})=>e))?.name,p=!!f(u=i)&&u.some((e=>e.shipping_rates.some((e=>e.selected))));var u;const d=!p||i?.length>1?t:(0,r.__)("Shipping","woocommerce-subscriptions"),g=S?parseInt(e.total_shipping,10)+parseInt(e.total_shipping_tax,10):parseInt(e.total_shipping,10),m=0===g&&(0,c.isWcVersion)("9.0",">=")?(0,k.jsx)("strong",{children:(0,r.__)("Free","woocommerce-subscriptions")}):g;return(0,k.jsx)(n.TotalsItem,{value:p?m:o,label:d,currency:s,showSkeleton:a,description:!!l&&(0,r.sprintf)( +(0,r.__)("%1$s %2$s %3$d %4$s","woocommerce-subscriptions"),t,i,e,n)}function d({subscriptionLength:e,billingInterval:s}){return e===s}const g=(0,c.getSetting)("countryData",{}),m=(0,c.getSetting)("countries",{}),_={...Object.fromEntries(Object.keys(g).filter(e=>!0===g[e].allowBilling).map(e=>[e,m[e]||""])),...Object.fromEntries(Object.keys(g).filter(e=>!0===g[e].allowShipping).map(e=>[e,m[e]||""]))},h=Object.fromEntries(Object.keys(_).map(e=>[e,g[e].locale||{}])),b={address:["first_name","last_name","company","address_1","address_2","city","postcode","country","state","phone"],contact:["email"],order:[]},w=Object.entries(h).reduce((e,[s,i])=>(e[s]=Object.entries(i).reduce((e,[s,i])=>(e[s]=(e=>{const s={};return void 0!==e.label&&(s.label=e.label),void 0!==e.required&&(s.required=e.required),void 0!==e.hidden&&(s.hidden=e.hidden),void 0===e.label||e.optionalLabel||(s.optionalLabel=(0,r.sprintf)(/* translators: %s Field label. */ /* translators: %s Field label. */ +(0,r.__)("%s (optional)","woocommerce-subscriptions"),e.label)),void 0!==e.optionalLabel&&(s.optionalLabel=e.optionalLabel),e.index&&("number"==typeof e.index&&(s.index=e.index),"string"==typeof e.index&&(s.index=parseInt(e.index,10))),e.hidden&&(s.required=!1),s})(i),e),{}),e),{}),y=["state","country","postcode","city"],f=e=>e.some(e=>!!e.shipping_rates.length),v=(0,c.getSetting)("collectableMethodIds",[]),x=(0,c.getSetting)("localPickupEnabled",!1);var k=i(848);const S=(0,c.getSetting)("displayCartPricesIncludingTax",!1),L=({currency:e,values:s,isLoading:i})=>{const{total_discount:t,total_discount_tax:o}=s,c=parseInt(t,10);if(!c)return null;const a=parseInt(o,10),l=S?c+a:c;return(0,k.jsx)(n.TotalsItem,{className:"wc-block-components-totals-discount",currency:e,label:(0,r.__)("Discount","woocommerce-subscriptions"),value:-1*l,showSkeleton:i})},j=({values:e,currency:s,shippingRatePackages:i,isLoading:t,calculatedShipping:n,shippingAddress:o})=>{const p=(0,a.useSelect)(e=>e(l.checkoutStore).prefersCollection());if(!n)return null;const u=(m=((e,s)=>e.map(e=>({...e,shipping_rates:e.shipping_rates.filter(e=>{const i=(t=e.method_id,!!x&&(Array.isArray(t)?!!t.find(e=>v.includes(e)):v.includes(t)));var t;return s?i:!i})})))(i,null!=p&&p),!!f(m)&&m.every(e=>e.shipping_rates.every(e=>!e.selected||(e=>v.includes(e.method_id))(e)))),d=!!(g=o).country&&((e,s,i="")=>{const t=i&&void 0!==w[i]?w[i]:{};return e.map(e=>({key:e,...s&&e in s?s[e]:{},...t&&e in t?t[e]:{}})).sort((e,s)=>e.index-s.index)})((0,c.getSetting)("addressFieldsLocations",b).address,c.defaultFields,g.country).filter(({key:e})=>y.includes(e)).every(({key:e,hidden:s,required:i})=>!0===s||!1===i||e in g&&""!==g[e]);var g,m;return(0,k.jsx)(I,{label:u?(0,r.__)("Pickup","woocommerce-subscriptions"):(0,r.__)("Delivery","woocommerce-subscriptions"),placeholder:(0,k.jsx)("span",{className:"wc-block-components-shipping-placeholder__value",children:d?(0,r.__)("No available delivery option","woocommerce-subscriptions"):(0,r.__)("Enter address to calculate","woocommerce-subscriptions")}),isLoading:t,shippingRatePackages:i,currency:s,values:e})},I=({values:e,currency:s,shippingRatePackages:i,label:t,placeholder:o,isLoading:a})=>{const l=i?.flatMap(e=>e.shipping_rates).find(({selected:e})=>e)?.name,p=!!f(u=i)&&u.some(e=>e.shipping_rates.some(e=>e.selected));var u;const d=!p||i?.length>1?t:(0,r.__)("Shipping","woocommerce-subscriptions"),g=S?parseInt(e.total_shipping,10)+parseInt(e.total_shipping_tax,10):parseInt(e.total_shipping,10),m=0===g&&(0,c.isWcVersion)("9.0",">=")?(0,k.jsx)("strong",{children:(0,r.__)("Free","woocommerce-subscriptions")}):g;return(0,k.jsx)(n.TotalsItem,{value:p?m:o,label:d,currency:s,showSkeleton:a,description:!!l&&(0,r.sprintf)( // translators: %s selected shipping rate (ex: flat rate) // translators: %s selected shipping rate (ex: flat rate) (0,r.__)("via %s","woocommerce-subscriptions"),l)})},P=({nextPaymentDate:e,subscriptionLength:s,billingPeriod:i,billingInterval:t})=>{const n=function({subscriptionLength:e,billingPeriod:s}){const i=p(e);return(0,r.sprintf)("For %1$d %2$s",e,i[s],"woocommerce-subscriptions")}({subscriptionLength:s,billingPeriod:i}),o=d({subscriptionLength:s,billingInterval:t})?(0,r.sprintf)(/* Translators: %1$s is a date. */ /* Translators: %1$s is a date. */ @@ -16,7 +16,7 @@ (0,r.__)("Starting: %1$s","woocommerce-subscriptions"),e);return(0,k.jsxs)("span",{children:[!!e&&o," ",!!s&&s>=t&&(0,k.jsx)("span",{className:"wcs-recurring-totals__subscription-length",children:n})]})},O=({currency:e,billingInterval:s,billingPeriod:i,nextPaymentDate:t,subscriptionLength:o,totals:c,isLoading:a})=>{const l=d({billingInterval:s,subscriptionLength:o})?(0,r.__)("Total","woocommerce-subscriptions"):function({billingInterval:e,billingPeriod:s}){switch(e){case 1:if("day"===s)return(0,r.__)("Daily recurring total","woocommerce-subscriptions");if("week"===s)return(0,r.__)("Weekly recurring total","woocommerce-subscriptions");if("month"===s)return(0,r.__)("Monthly recurring total","woocommerce-subscriptions");if("year"===s)return(0,r.__)("Yearly recurring total","woocommerce-subscriptions");break;case 2:return(0,r.sprintf)(/* translators: %1$s is week, month, year */ /* translators: %1$s is week, month, year */ (0,r.__)("Recurring total every 2nd %1$s","woocommerce-subscriptions"),s);case 3:return(0,r.sprintf)(/* Translators: %1$s is week, month, year */ /* Translators: %1$s is week, month, year */ (0,r.__)("Recurring total every 3rd %1$s","woocommerce-subscriptions"),s);default:return(0,r.sprintf)(/* Translators: %1$d is number of weeks, months, days, years. %2$s is week, month, year */ /* Translators: %1$d is number of weeks, months, days, years. %2$s is week, month, year */ -(0,r.__)("Recurring total every %1$dth %2$s","woocommerce-subscriptions"),e,s)}}({billingInterval:s,billingPeriod:i});return(0,k.jsx)(n.TotalsItem,{className:"wcs-recurring-totals-panel__title",currency:e,label:l,value:c,showSkeleton:a,description:(0,k.jsx)(P,{nextPaymentDate:t,subscriptionLength:o,billingInterval:s,billingPeriod:i})})},C=({subscription:e,needsShipping:s,calculatedShipping:i,shippingAddress:t})=>{const{isLoading:c}=(()=>{const{cartIsLoading:e,isLoadingRates:s,hasPendingItemsOperations:i,isApplyingCoupon:t,isRemovingCoupon:n}=(0,a.useSelect)((e=>{const s=e(l.cartStore);return{cartIsLoading:!s.hasFinishedResolution("getCartData",[]),isLoadingRates:s.isAddressFieldsForShippingRatesUpdating(),hasPendingItemsOperations:s.hasPendingItemsOperations(),isApplyingCoupon:s.isApplyingCoupon(),isRemovingCoupon:s.isRemovingCoupon()}}),[]),r=(0,a.useSelect)((e=>e(l.checkoutStore).isCalculating()),[]);return{isLoading:e||s||t||n||r||i}})(),{totals:p,billing_interval:u,billing_period:d,next_payment_date:g,subscription_length:m,shipping_rates:_}=e;if(!g)return null;const h=e?.shipping_rates?.some((e=>e.needs_shipping)),b=(0,o.getCurrencyFromPriceResponse)(p);return(0,k.jsxs)("div",{className:"wcs-recurring-totals-panel",children:[(0,k.jsx)(O,{billingInterval:u,billingPeriod:d,nextPaymentDate:g,subscriptionLength:m,totals:parseInt(p.total_price,10),currency:b,isLoading:c}),(0,k.jsxs)(n.Panel,{className:"wcs-recurring-totals-panel__details",initialOpen:!1,title:(0,r.__)("Details","woocommerce-subscriptions"),children:[(0,k.jsxs)(n.TotalsWrapper,{children:[(0,k.jsx)(n.Subtotal,{currency:b,values:p,showSkeleton:c}),(0,k.jsx)(L,{currency:b,values:p,isLoading:c})]}),s&&h&&(0,k.jsx)(n.TotalsWrapper,{className:"wc-block-components-totals-shipping",children:(0,k.jsx)(j,{currency:b,calculatedShipping:i,values:p,shippingAddress:t,shippingRatePackages:_,isLoading:c})}),!S&&(0,k.jsx)(n.TotalsWrapper,{children:(0,k.jsx)(n.TotalsTaxes,{currency:b,values:p})}),(0,k.jsx)(n.TotalsWrapper,{children:(0,k.jsx)(n.TotalsItem,{className:"wcs-recurring-totals-panel__details-total",currency:b,label:(0,r.__)("Total","woocommerce-subscriptions"),value:parseInt(p.total_price,10),showSkeleton:c})})]})]})},R=({extensions:e,cart:s})=>{const{subscriptions:i}=e,{cartNeedsShipping:t,cartHasCalculatedShipping:n,shippingAddress:r}=s;return i&&0!==i.length?i.map((({key:e,...s})=>(0,k.jsx)(C,{subscription:s,needsShipping:t,calculatedShipping:n,shippingAddress:r},e))):null},D=window.wp.element,$=(0,c.getSetting)("collectableMethodIds",[]),T=({extensions:e,collapsible:s,collapse:i,showItems:t,noResultsMessage:n,renderOption:r,components:o,context:c})=>{const{subscriptions:a=[]}=e,{ShippingRatesControlPackage:l}=o,p=(0,D.useMemo)((()=>Object.values(a).map((e=>e.shipping_rates)).filter(Boolean).flat()),[a]),u=(0,D.useMemo)((()=>p.length>1||i),[p.length,i]),d=(0,D.useMemo)((()=>p.length>1||t),[p.length,t]);return p.filter((e=>!e.match_initial_rates&&e.needs_shipping)).map((({package_id:e,...i})=>(i.shipping_rates=i.shipping_rates.filter((e=>!$.includes(e.method_id))),(0,k.jsx)(l,{packageId:e,packageData:i,collapsible:s,collapse:u,showItems:d,noResultsMessage:n,renderOption:r,highlightChecked:"woocommerce/checkout"===c},e))))};var E=i(609);const F=(0,c.getSetting)("collectableMethodIds",[]),N=({packageId:e,packageData:s,showItems:i,renderPickupLocation:t,pickupLocations:n,packageCount:r,LocalPickupSelect:o})=>{var c;const{selectShippingRate:p}=(0,a.useDispatch)(l.cartStore),[u,d]=(0,E.useState)(null!==(c=s.shipping_rates.find((e=>e.selected))?.rate_id)&&void 0!==c?c:s.shipping_rates[0]?.rate_id);return(0,D.useEffect)((()=>{u&&p(u,e)}),[]),(0,k.jsx)(o,{title:s.name,packageData:s,selectedOption:null!=u?u:"",showItems:i,renderPickupLocation:t,pickupLocations:n,packageCount:r,onChange:s=>{d(s),p(s,e)}})},M=({extensions:e,showItems:s,renderPickupLocation:i,components:t})=>{const{subscriptions:n=[]}=e,{LocalPickupSelect:r}=t,o=(0,D.useMemo)((()=>Object.values(n).map((e=>e.shipping_rates)).filter(Boolean).flat()),[n]),c=(0,D.useMemo)((()=>o.length>1||s),[o.length,s]);return o.filter((e=>!e.match_initial_rates&&e.needs_shipping)).map((({package_id:e,...s})=>(s.shipping_rates=s.shipping_rates.filter((e=>F.includes(e.method_id))),(0,k.jsx)(N,{packageId:e,packageData:s,showItems:c,renderPickupLocation:i,pickupLocations:s.shipping_rates,packageCount:o.length,LocalPickupSelect:r},e))))};(0,t.registerPlugin)("woocommerce-subscriptions",{render:()=>(0,k.jsxs)(k.Fragment,{children:[(0,k.jsx)(n.ExperimentalOrderShippingPackages,{children:(0,k.jsx)(T,{})}),(0,k.jsx)(n.ExperimentalOrderLocalPickupPackages,{children:(0,k.jsx)(M,{})}),(0,k.jsx)(n.ExperimentalOrderMeta,{children:(0,k.jsx)(R,{})})]}),scope:"woocommerce-checkout"}),(0,n.registerCheckoutFilters)("woocommerce-subscriptions",{totalLabel:(e,{subscriptions:s})=>s?.length>0?(0,r.__)("Total due today","woocommerce-subscriptions"):e,subtotalPriceFormat:(e,{subscriptions:s})=>{if(s?.billing_period&&s?.billing_interval){const{billing_interval:i,subscription_length:t}=s;return d({subscriptionLength:t,billingInterval:i})?u(s,1===t? +(0,r.__)("Recurring total every %1$dth %2$s","woocommerce-subscriptions"),e,s)}}({billingInterval:s,billingPeriod:i});return(0,k.jsx)(n.TotalsItem,{className:"wcs-recurring-totals-panel__title",currency:e,label:l,value:c,showSkeleton:a,description:(0,k.jsx)(P,{nextPaymentDate:t,subscriptionLength:o,billingInterval:s,billingPeriod:i})})},C=({subscription:e,needsShipping:s,calculatedShipping:i,shippingAddress:t})=>{const{isLoading:c}=(()=>{const{cartIsLoading:e,isLoadingRates:s,hasPendingItemsOperations:i,isApplyingCoupon:t,isRemovingCoupon:n}=(0,a.useSelect)(e=>{const s=e(l.cartStore);return{cartIsLoading:!s.hasFinishedResolution("getCartData",[]),isLoadingRates:s.isAddressFieldsForShippingRatesUpdating(),hasPendingItemsOperations:s.hasPendingItemsOperations(),isApplyingCoupon:s.isApplyingCoupon(),isRemovingCoupon:s.isRemovingCoupon()}},[]),r=(0,a.useSelect)(e=>e(l.checkoutStore).isCalculating(),[]);return{isLoading:e||s||t||n||r||i}})(),{totals:p,billing_interval:u,billing_period:d,next_payment_date:g,subscription_length:m,shipping_rates:_}=e;if(!g)return null;const h=e?.shipping_rates?.some(e=>e.needs_shipping),b=(0,o.getCurrencyFromPriceResponse)(p);return(0,k.jsxs)("div",{className:"wcs-recurring-totals-panel",children:[(0,k.jsx)(O,{billingInterval:u,billingPeriod:d,nextPaymentDate:g,subscriptionLength:m,totals:parseInt(p.total_price,10),currency:b,isLoading:c}),(0,k.jsxs)(n.Panel,{className:"wcs-recurring-totals-panel__details",initialOpen:!1,title:(0,r.__)("Details","woocommerce-subscriptions"),children:[(0,k.jsxs)(n.TotalsWrapper,{children:[(0,k.jsx)(n.Subtotal,{currency:b,values:p,showSkeleton:c}),(0,k.jsx)(L,{currency:b,values:p,isLoading:c})]}),s&&h&&(0,k.jsx)(n.TotalsWrapper,{className:"wc-block-components-totals-shipping",children:(0,k.jsx)(j,{currency:b,calculatedShipping:i,values:p,shippingAddress:t,shippingRatePackages:_,isLoading:c})}),!S&&(0,k.jsx)(n.TotalsWrapper,{children:(0,k.jsx)(n.TotalsTaxes,{currency:b,values:p})}),(0,k.jsx)(n.TotalsWrapper,{children:(0,k.jsx)(n.TotalsItem,{className:"wcs-recurring-totals-panel__details-total",currency:b,label:(0,r.__)("Total","woocommerce-subscriptions"),value:parseInt(p.total_price,10),showSkeleton:c})})]})]})},R=({extensions:e,cart:s})=>{const{subscriptions:i}=e,{cartNeedsShipping:t,cartHasCalculatedShipping:n,shippingAddress:r}=s;return i&&0!==i.length?i.map(({key:e,...s})=>(0,k.jsx)(C,{subscription:s,needsShipping:t,calculatedShipping:n,shippingAddress:r},e)):null},D=window.wp.element,$=(0,c.getSetting)("collectableMethodIds",[]),T=({extensions:e,collapsible:s,collapse:i,showItems:t,noResultsMessage:n,renderOption:r,components:o,context:c})=>{const{subscriptions:a=[]}=e,{ShippingRatesControlPackage:l}=o,p=(0,D.useMemo)(()=>Object.values(a).map(e=>e.shipping_rates).filter(Boolean).flat(),[a]),u=(0,D.useMemo)(()=>p.length>1||i,[p.length,i]),d=(0,D.useMemo)(()=>p.length>1||t,[p.length,t]);return p.filter(e=>!e.match_initial_rates&&e.needs_shipping).map(({package_id:e,...i})=>(i.shipping_rates=i.shipping_rates.filter(e=>!$.includes(e.method_id)),(0,k.jsx)(l,{packageId:e,packageData:i,collapsible:s,collapse:u,showItems:d,noResultsMessage:n,renderOption:r,highlightChecked:"woocommerce/checkout"===c},e)))};var E=i(609);const F=(0,c.getSetting)("collectableMethodIds",[]),N=({packageId:e,packageData:s,showItems:i,renderPickupLocation:t,pickupLocations:n,packageCount:r,LocalPickupSelect:o})=>{var c;const{selectShippingRate:p}=(0,a.useDispatch)(l.cartStore),[u,d]=(0,E.useState)(null!==(c=s.shipping_rates.find(e=>e.selected)?.rate_id)&&void 0!==c?c:s.shipping_rates[0]?.rate_id);return(0,D.useEffect)(()=>{u&&p(u,e)},[]),(0,k.jsx)(o,{title:s.name,packageData:s,selectedOption:null!=u?u:"",showItems:i,renderPickupLocation:t,pickupLocations:n,packageCount:r,onChange:s=>{d(s),p(s,e)}})},M=({extensions:e,showItems:s,renderPickupLocation:i,components:t})=>{const{subscriptions:n=[]}=e,{LocalPickupSelect:r}=t,o=(0,D.useMemo)(()=>Object.values(n).map(e=>e.shipping_rates).filter(Boolean).flat(),[n]),c=(0,D.useMemo)(()=>o.length>1||s,[o.length,s]);return o.filter(e=>!e.match_initial_rates&&e.needs_shipping).map(({package_id:e,...s})=>(s.shipping_rates=s.shipping_rates.filter(e=>F.includes(e.method_id)),(0,k.jsx)(N,{packageId:e,packageData:s,showItems:c,renderPickupLocation:i,pickupLocations:s.shipping_rates,packageCount:o.length,LocalPickupSelect:r},e)))};(0,t.registerPlugin)("woocommerce-subscriptions",{render:()=>(0,k.jsxs)(k.Fragment,{children:[(0,k.jsx)(n.ExperimentalOrderShippingPackages,{children:(0,k.jsx)(T,{})}),(0,k.jsx)(n.ExperimentalOrderLocalPickupPackages,{children:(0,k.jsx)(M,{})}),(0,k.jsx)(n.ExperimentalOrderMeta,{children:(0,k.jsx)(R,{})})]}),scope:"woocommerce-checkout"}),(0,n.registerCheckoutFilters)("woocommerce-subscriptions",{totalLabel:(e,{subscriptions:s})=>s?.length>0?(0,r.__)("Total due today","woocommerce-subscriptions"):e,subtotalPriceFormat:(e,{subscriptions:s})=>{if(s?.billing_period&&s?.billing_interval){const{billing_interval:i,subscription_length:t}=s;return d({subscriptionLength:t,billingInterval:i})?u(s,1===t? // translators: the word used to describe billing frequency, e.g. "for" 1 day or "for" 1 month. // translators: the word used to describe billing frequency, e.g. "for" 1 day or "for" 1 month. (0,r.__)("for 1","woocommerce-subscriptions"): diff --git a/build/style-gifting-welcome-announcement-rtl.css b/build/style-admin-rtl.css similarity index 100% rename from build/style-gifting-welcome-announcement-rtl.css rename to build/style-admin-rtl.css diff --git a/build/style-gifting-welcome-announcement.css b/build/style-admin.css similarity index 100% rename from build/style-gifting-welcome-announcement.css rename to build/style-admin.css diff --git a/build/wcsg-blocks-integration.asset.php b/build/wcsg-blocks-integration.asset.php index 75cd01c..789ee73 100644 --- a/build/wcsg-blocks-integration.asset.php +++ b/build/wcsg-blocks-integration.asset.php @@ -1 +1 @@ - array('react', 'react-dom', 'wc-blocks-checkout', 'wp-components', 'wp-data', 'wp-i18n', 'wp-plugins', 'wp-url'), 'version' => 'e7869a0a766c0f65ff8a'); + array('react', 'react-dom', 'wc-blocks-checkout', 'wp-components', 'wp-data', 'wp-i18n', 'wp-plugins', 'wp-url'), 'version' => 'cf4dd71c0c7418b591fd'); diff --git a/build/wcsg-blocks-integration.js b/build/wcsg-blocks-integration.js index 6c2d95c..5b58fe5 100644 --- a/build/wcsg-blocks-integration.js +++ b/build/wcsg-blocks-integration.js @@ -1 +1 @@ -(()=>{"use strict";var e={20:(e,t,n)=>{var o=n(609),i=Symbol.for("react.element"),c=Symbol.for("react.fragment"),r=Object.prototype.hasOwnProperty,s=o.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,a={key:!0,ref:!0,__self:!0,__source:!0};function l(e,t,n){var o,c={},l=null,u=null;for(o in void 0!==n&&(l=""+n),void 0!==t.key&&(l=""+t.key),void 0!==t.ref&&(u=t.ref),t)r.call(t,o)&&!a.hasOwnProperty(o)&&(c[o]=t[o]);if(e&&e.defaultProps)for(o in t=e.defaultProps)void 0===c[o]&&(c[o]=t[o]);return{$$typeof:i,type:e,key:l,ref:u,props:c,_owner:s.current}}t.Fragment=c,t.jsx=l,t.jsxs=l},338:(e,t,n)=>{var o=n(795);t.H=o.createRoot,o.hydrateRoot},609:e=>{e.exports=window.React},795:e=>{e.exports=window.ReactDOM},848:(e,t,n)=>{e.exports=n(20)}},t={};function n(o){var i=t[o];if(void 0!==i)return i.exports;var c=t[o]={exports:{}};return e[o](c,c.exports,n),c.exports}var o=n(338);const i=window.wp.plugins;var c=n(609);const r=window.wp.i18n,s=window.wp.components,a=window.wp.data,l=window.wp.url,u=window.wc.blocksCheckout;var d=n(848);const m=({lineItem:e,itemKey:t})=>{const[n,o]=(0,c.useState)(!1),[i,m]=(0,c.useState)(!1),[p,w]=(0,c.useState)(""),[_,f]=(0,c.useState)(!0),[g,b]=(0,c.useState)(!1),h=(0,c.useId)(),v="invalid-gifting-recipient",{setValidationErrors:k,clearValidationError:x}=(0,a.useDispatch)("wc/store/validation"),y=(0,a.useSelect)((e=>{if(!t)return null;const n=e("wc/store/cart");if(!n)return null;try{const e=n.getCartData();return e?.items?.find((e=>e.key===t))||null}catch(e){return null}}),[t]),S=(0,c.useMemo)((()=>{if(!y?.item_data)return null;const e=y.item_data.find((e=>"gifting_to_hidden"===e.name));return e?.value||null}),[y]);(0,c.useEffect)((()=>{null!==S&&(w(S),o(!0))}),[S]),(0,c.useEffect)((()=>{if(!e)return;const t=e.querySelector(".wc-block-components-product-details__gifting-to-hidden");if(!t)return;const n=t.querySelector(".wc-block-components-product-details__value");w(n?n.textContent:""),o(!0)}),[e]);const E=e=>{if(!e&&!(0,l.isEmail)(p))return f(!1),void k({[v]:{message:(0,r.__)("Please enter a valid email address","woocommerce-subscriptions"),hidden:!1}});m(!1),f(!0),x(v),(0,u.extensionCartUpdate)({namespace:"wcsg-cart",data:{recipient:!0===e?"":p,itemKey:t}}).then((()=>{m(!1)})).catch((()=>{f(!1),m(!0),k({[v]:{message:(0,r.__)("Please enter a valid email address","woocommerce-subscriptions"),hidden:!1}})}))};return(0,d.jsxs)("div",{className:"wcsg-gifting-to-container",children:[(!n||i)&&(0,d.jsx)(s.CheckboxControl,{"aria-label":window.wcSettings.wcsg_subscriptions_data.gifting_checkbox_text||(0,r.__)("This is a gift","woocommerce-subscriptions"),label:window.wcSettings.wcsg_subscriptions_data.gifting_checkbox_text||(0,r.__)("This is a gift","woocommerce-subscriptions"),checked:n,onChange:e=>{o(e),m(e)}}),n&&!i&&(0,d.jsxs)("div",{className:"wcsg-gifting-to-container-view",children:[(0,d.jsxs)("span",{title:(0,r.__)("Gifting to","woocommerce-subscriptions"),children:[(0,r.__)("Gifting to:","woocommerce-subscriptions")," ",!i&&p]}),(0,d.jsx)(s.Button,{variant:"link",onClick:()=>m(!0),children:(0,r.__)("Edit","woocommerce-subscriptions")}),(0,d.jsx)(s.Button,{variant:"link","aria-label":(0,r.__)("Remove gift recipient","woocommerce-subscriptions"),onClick:()=>(o(!1),w(""),void E(!0)),children:(0,r.__)("Remove","woocommerce-subscriptions")})]}),i&&(0,d.jsxs)("div",{className:"wcsg-gifting-to-container-editing wc-block-components-form",children:[(0,d.jsxs)("div",{className:`wc-block-components-text-input ${_?"":"has-error"} ${g||p?"is-active":""}`,children:[(0,d.jsx)("input",{type:"email",value:p,onChange:e=>w(e.target.value),onFocus:()=>{b(!0),f(!0)},onBlur:()=>{b(!1)},"aria-label":(0,r.__)("Gifting recipient","woocommerce-subscriptions"),id:h,"data-testid":"recipient-input"}),(0,d.jsx)("label",{htmlFor:h,children:(0,r.__)("Recipient's email address","woocommerce-subscriptions")})]}),(0,d.jsx)("button",{className:"wc-block-components-button wp-element-button gifting-update-button",onClick:()=>E(!1),name:"Update",children:(0,r.__)("Update","woocommerce-subscriptions")})]}),i&&!_&&(0,d.jsx)(u.ValidationInputError,{elementId:v,propertyName:v})]})},p=()=>{const{__internalSetUseShippingAsBilling:e,setEditingShippingAddress:t}=(0,a.useDispatch)("wc/store/checkout"),n=(0,a.useSelect)((e=>{const t=e("wc/store/cart");if(!t)return null;try{const e=t.getCartData();return e?.items?.find((e=>e.item_data.find((e=>"gifting_to_hidden"===e.name))))||null}catch(e){return null}}),[]);return(0,c.useEffect)((()=>{n&&(e(!1),t(!0))}),[n,e,t]),(0,d.jsx)(d.Fragment,{})};window.addEventListener("load",(function(){let e=null;function t(){const t=document.querySelectorAll(".wc-block-components-product-metadata");0!==t.length&&(t.length&&e&&e.disconnect(),t.forEach((function(e,t){const n=e?.querySelector(".wc-block-components-product-details__item-key .wc-block-components-product-details__value")?.textContent||"";if(!n)return;const i="gifting-recipient-"+t;if(!document.getElementById(i)){const t=document.createElement("div");t.className="wcsg-block-recipient-container",t.id=i,e.parentNode.insertBefore(t,e)}(0,o.H)(document.getElementById(i)).render((0,d.jsx)(m,{lineItem:e,itemKey:n}))})))}function n(){setTimeout((()=>{e=new MutationObserver(t),t(),e.observe(document.body,{childList:!0,subtree:!0})}),200)}null!==document.querySelector(".wp-block-woocommerce-checkout")?(0,i.registerPlugin)("woocommerce-checkout-gifting",{render:p,icon:"gift",title:"Checkout Gifting Features",scope:"woocommerce-checkout"}):(n(),document.addEventListener("click",(function(e){e.target.matches(".wc-block-mini-cart__button, .wc-block-mini-cart__button *")&&n()})))}))})(); \ No newline at end of file +(()=>{"use strict";var e={20:(e,t,n)=>{var o=n(609),i=Symbol.for("react.element"),c=Symbol.for("react.fragment"),r=Object.prototype.hasOwnProperty,s=o.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,a={key:!0,ref:!0,__self:!0,__source:!0};function l(e,t,n){var o,c={},l=null,u=null;for(o in void 0!==n&&(l=""+n),void 0!==t.key&&(l=""+t.key),void 0!==t.ref&&(u=t.ref),t)r.call(t,o)&&!a.hasOwnProperty(o)&&(c[o]=t[o]);if(e&&e.defaultProps)for(o in t=e.defaultProps)void 0===c[o]&&(c[o]=t[o]);return{$$typeof:i,type:e,key:l,ref:u,props:c,_owner:s.current}}t.Fragment=c,t.jsx=l,t.jsxs=l},338:(e,t,n)=>{var o=n(795);t.H=o.createRoot,o.hydrateRoot},609:e=>{e.exports=window.React},795:e=>{e.exports=window.ReactDOM},848:(e,t,n)=>{e.exports=n(20)}},t={};function n(o){var i=t[o];if(void 0!==i)return i.exports;var c=t[o]={exports:{}};return e[o](c,c.exports,n),c.exports}var o=n(338);const i=window.wp.plugins;var c=n(609);const r=window.wp.i18n,s=window.wp.components,a=window.wp.data,l=window.wp.url,u=window.wc.blocksCheckout;var d=n(848);const m=({lineItem:e,itemKey:t})=>{const[n,o]=(0,c.useState)(!1),[i,m]=(0,c.useState)(!1),[p,w]=(0,c.useState)(""),[_,f]=(0,c.useState)(!0),[g,b]=(0,c.useState)(!1),h=(0,c.useId)(),v="invalid-gifting-recipient",{setValidationErrors:k,clearValidationError:x}=(0,a.useDispatch)("wc/store/validation"),y=(0,a.useSelect)(e=>{if(!t)return null;const n=e("wc/store/cart");if(!n)return null;try{const e=n.getCartData();return e?.items?.find(e=>e.key===t)||null}catch(e){return null}},[t]),S=(0,c.useMemo)(()=>{if(!y?.item_data)return null;const e=y.item_data.find(e=>"gifting_to_hidden"===e.name);return e?.value||null},[y]);(0,c.useEffect)(()=>{null!==S&&(w(S),o(!0))},[S]),(0,c.useEffect)(()=>{if(!e)return;const t=e.querySelector(".wc-block-components-product-details__gifting-to-hidden");if(!t)return;const n=t.querySelector(".wc-block-components-product-details__value");w(n?n.textContent:""),o(!0)},[e]);const E=e=>{if(!e&&!(0,l.isEmail)(p))return f(!1),void k({[v]:{message:(0,r.__)("Please enter a valid email address","woocommerce-subscriptions"),hidden:!1}});m(!1),f(!0),x(v),(0,u.extensionCartUpdate)({namespace:"wcsg-cart",data:{recipient:!0===e?"":p,itemKey:t}}).then(()=>{m(!1)}).catch(()=>{f(!1),m(!0),k({[v]:{message:(0,r.__)("Please enter a valid email address","woocommerce-subscriptions"),hidden:!1}})})};return(0,d.jsxs)("div",{className:"wcsg-gifting-to-container",children:[(!n||i)&&(0,d.jsx)(s.CheckboxControl,{"aria-label":window.wcSettings.wcsg_subscriptions_data.gifting_checkbox_text||(0,r.__)("This is a gift","woocommerce-subscriptions"),label:window.wcSettings.wcsg_subscriptions_data.gifting_checkbox_text||(0,r.__)("This is a gift","woocommerce-subscriptions"),checked:n,onChange:e=>{o(e),m(e)}}),n&&!i&&(0,d.jsxs)("div",{className:"wcsg-gifting-to-container-view",children:[(0,d.jsxs)("span",{title:(0,r.__)("Gifting to","woocommerce-subscriptions"),children:[(0,r.__)("Gifting to:","woocommerce-subscriptions")," ",!i&&p]}),(0,d.jsx)(s.Button,{variant:"link",onClick:()=>m(!0),children:(0,r.__)("Edit","woocommerce-subscriptions")}),(0,d.jsx)(s.Button,{variant:"link","aria-label":(0,r.__)("Remove gift recipient","woocommerce-subscriptions"),onClick:()=>(o(!1),w(""),void E(!0)),children:(0,r.__)("Remove","woocommerce-subscriptions")})]}),i&&(0,d.jsxs)("div",{className:"wcsg-gifting-to-container-editing wc-block-components-form",children:[(0,d.jsxs)("div",{className:`wc-block-components-text-input ${_?"":"has-error"} ${g||p?"is-active":""}`,children:[(0,d.jsx)("input",{type:"email",value:p,onChange:e=>w(e.target.value),onFocus:()=>{b(!0),f(!0)},onBlur:()=>{b(!1)},"aria-label":(0,r.__)("Gifting recipient","woocommerce-subscriptions"),id:h,"data-testid":"recipient-input"}),(0,d.jsx)("label",{htmlFor:h,children:(0,r.__)("Recipient's email address","woocommerce-subscriptions")})]}),(0,d.jsx)("button",{className:"wc-block-components-button wp-element-button gifting-update-button",onClick:()=>E(!1),name:"Update",children:(0,r.__)("Update","woocommerce-subscriptions")})]}),i&&!_&&(0,d.jsx)(u.ValidationInputError,{elementId:v,propertyName:v})]})},p=()=>{const{__internalSetUseShippingAsBilling:e,setEditingShippingAddress:t}=(0,a.useDispatch)("wc/store/checkout"),n=(0,a.useSelect)(e=>{const t=e("wc/store/cart");if(!t)return null;try{const e=t.getCartData();return e?.items?.find(e=>e.item_data.find(e=>"gifting_to_hidden"===e.name))||null}catch(e){return null}},[]);return(0,c.useEffect)(()=>{n&&(e(!1),t(!0))},[n,e,t]),(0,d.jsx)(d.Fragment,{})};window.addEventListener("load",function(){let e=null;function t(){const t=document.querySelectorAll(".wc-block-components-product-metadata");0!==t.length&&(t.length&&e&&e.disconnect(),t.forEach(function(e,t){const n=e?.querySelector(".wc-block-components-product-details__item-key .wc-block-components-product-details__value")?.textContent||"";if(!n)return;const i="gifting-recipient-"+t;if(!document.getElementById(i)){const t=document.createElement("div");t.className="wcsg-block-recipient-container",t.id=i,e.parentNode.insertBefore(t,e)}(0,o.H)(document.getElementById(i)).render((0,d.jsx)(m,{lineItem:e,itemKey:n}))}))}function n(){setTimeout(()=>{e=new MutationObserver(t),t(),e.observe(document.body,{childList:!0,subtree:!0})},200)}null!==document.querySelector(".wp-block-woocommerce-checkout")?(0,i.registerPlugin)("woocommerce-checkout-gifting",{render:p,icon:"gift",title:"Checkout Gifting Features",scope:"woocommerce-checkout"}):(n(),document.addEventListener("click",function(e){e.target.matches(".wc-block-mini-cart__button, .wc-block-mini-cart__button *")&&n()}))})})(); \ No newline at end of file diff --git a/changelog.txt b/changelog.txt index b1a8246..e700a9f 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,11 +1,17 @@ *** WooCommerce Subscriptions Changelog *** +2026-01-06 - version 8.3.0 +* Add: Support for ajax add-to-cart flows from the single product page, when upgrading or downgrading subscriptions. +* Add: Enhanced functionality from the WooCommerce Subscription Downloads plugin has now been integrated directly into WooCommerce Subscriptions. +* Fix: Ensured the subject line for the "Customer Renewal Invoice" email correctly updates. + 2025-12-22 - version 8.2.1 * Fix: Subscription pricing strings now correctly display singular and plural billing intervals like "$10 / month" and "$10 every 3 months" in cart and checkout totals. * Fix: Display all recurring coupon names in the totals section of classic cart and checkout when multiple recurring coupons are applied. * Fix: Payment method selector options on Subscriptions list page are now properly displaying the payment method name for gateways providing multiple payment methods. * Fix: PayPal Standard plugin IPN renewal orders not being created for failed payment retries. * Fix: Prevent fatal errors on shop pages when special characters like % are used in a product name. +* Fix: Prevent an email validation error from briefly and inadvertently flashing on the screen when the "this is a gift" checkbox is used. 2025-12-10 - version 8.2.0 * Fix: Various accessibility issues. diff --git a/includes/admin/class-wcs-admin-assets.php b/includes/admin/class-wcs-admin-assets.php new file mode 100644 index 0000000..a91b501 --- /dev/null +++ b/includes/admin/class-wcs-admin-assets.php @@ -0,0 +1,59 @@ +get_plugin_directory( 'build/admin.asset.php' ); + $script_asset = file_exists( $script_asset_path ) + ? require $script_asset_path + : array( + 'dependencies' => array( + 'react', + 'wc-blocks-checkout', + 'wc-price-format', + 'wc-settings', + 'wp-element', + 'wp-i18n', + 'wp-plugins', + ), + 'version' => WC_Subscriptions::$version, + ); + + wp_enqueue_script( + 'wcs-admin', + plugins_url( '/build/admin.js', WC_Subscriptions::$plugin_file ), + $script_asset['dependencies'], + $script_asset['version'], + true + ); + + wp_enqueue_style( + 'wcs-admin', + plugins_url( '/build/style-admin.css', WC_Subscriptions::$plugin_file ), + array( 'wp-components' ), + $script_asset['version'] + ); + + wp_set_script_translations( + 'wcs-admin', + 'woocommerce-subscriptions', + plugin_dir_path( WC_Subscriptions::$plugin_file ) . 'languages' + ); + } +} diff --git a/includes/api/class-wc-rest-subscriptions-settings-option-controller.php b/includes/api/class-wc-rest-subscriptions-settings-option-controller.php index 598969e..f0cbcd0 100644 --- a/includes/api/class-wc-rest-subscriptions-settings-option-controller.php +++ b/includes/api/class-wc-rest-subscriptions-settings-option-controller.php @@ -24,6 +24,7 @@ class WC_REST_Subscriptions_Settings_Option_Controller extends WP_REST_Controlle */ private const ALLOWED_OPTIONS = [ 'woocommerce_subscriptions_gifting_is_welcome_announcement_dismissed', + 'woocommerce_subscriptions_downloads_is_welcome_announcement_dismissed', ]; /** diff --git a/includes/class-wc-subscriptions-plugin.php b/includes/class-wc-subscriptions-plugin.php index 66f0b7c..dec8d1d 100644 --- a/includes/class-wc-subscriptions-plugin.php +++ b/includes/class-wc-subscriptions-plugin.php @@ -34,6 +34,7 @@ class WC_Subscriptions_Plugin extends WC_Subscriptions_Core_Plugin { WCS_Call_To_Action_Button_Text_Manager::init(); WCS_Subscriber_Role_Manager::init(); WCS_Upgrade_Notice_Manager::init(); + WCS_Admin_Assets::init(); $tracks_events = new WC_Tracks_Events(); $tracks_events->setup(); @@ -300,10 +301,16 @@ class WC_Subscriptions_Plugin extends WC_Subscriptions_Core_Plugin { */ public function init_downloads() { if ( - ! defined( 'WCS_ALLOW_SUBSCRIPTION_DOWNLOADS' ) - || $this->is_plugin_being_activated( 'woocommerce-subscription-downloads' ) + $this->is_plugin_being_activated( 'woocommerce-subscription-downloads' ) || class_exists( WC_Subscription_Downloads::class, false ) ) { + if ( class_exists( WC_Subscription_Downloads::class, false ) ) { + // Will show the welcome announcement if the standalone plugin is active and the welcome announcement has not been dismissed. + if ( ! WC_Subscription_Downloads_Admin_Welcome_Announcement::is_welcome_announcement_dismissed() ) { + WC_Subscription_Downloads_Admin_Welcome_Announcement::init(); + } + } + return; } diff --git a/includes/class-wcs-autoloader.php b/includes/class-wcs-autoloader.php index 5bbadf0..4a1119e 100644 --- a/includes/class-wcs-autoloader.php +++ b/includes/class-wcs-autoloader.php @@ -45,6 +45,7 @@ class WCS_Autoloader extends WCS_Core_Autoloader { 'wcs_webhooks' => true, 'wcs_auth' => true, 'wcs_upgrade_notice_manager' => true, + 'wcs_admin_assets' => true, 'wc_subscriptions_cli' => true, ); diff --git a/includes/core/class-wcs-limiter.php b/includes/core/class-wcs-limiter.php index b3f2590..ed1bde1 100644 --- a/includes/core/class-wcs-limiter.php +++ b/includes/core/class-wcs-limiter.php @@ -57,6 +57,43 @@ class WCS_Limiter { do_action( 'woocommerce_subscriptions_product_options_advanced' ); } + /** + * Checks if the session contains a renewal for a given product. + * Used for the pay for order flow. + * + * @param WC_Product $product The product to check. + * @return bool + */ + private static function session_contains_renewal( $product ) { + if ( ! empty( WC()->session->cart ) ) { + foreach ( WC()->session->cart as $cart_item_key => $cart_item ) { + if ( (int) $product->get_id() === (int) $cart_item['product_id'] && isset( $cart_item['subscription_renewal'] ) ) { + return true; + } + } + } + return false; + } + + /** + * Checks if the session contains a resubscribe for a given product. + * Used for the pay for order flow with limited subscriptions products. + * + * @param WC_Product $product The product to check. + * @return bool + */ + private static function session_contains_resubscribe( $product ) { + if ( ! empty( WC()->session->cart ) ) { + foreach ( WC()->session->cart as $cart_item_key => $cart_item ) { + if ( (int) $product->get_id() === (int) $cart_item['product_id'] && isset( $cart_item['subscription_resubscribe'] ) ) { + return true; + } + } + } + + return false; + } + /** * Canonical is_purchasable method to be called by product classes. * @@ -68,73 +105,62 @@ class WCS_Limiter { */ public static function is_purchasable( $purchasable, $product ) { - // Prevents making a non purchasable product purchasable again. - // This can happen if the product is disabled and limited and the customer is trying to renew the subscription for example. - if ( ! $purchasable ) { - return $purchasable; + // Check if product is private (for variations, also check parent product) + $is_private_product = 'private' === $product->get_status(); + if ( $product->get_parent_id() > 0 ) { + $parent_product = wc_get_product( $product->get_parent_id() ); + if ( $parent_product ) { + $is_private_product = 'private' === $parent_product->get_status(); + } } - switch ( $product->get_type() ) { - case 'subscription': - case 'variable-subscription': - // Checks if the product is limited. - if ( false === self::is_product_limited( $purchasable, $product ) ) { - // Product is limited, so it is not purchasable. + // Checks limits for variable subscription products. + if ( $product->get_type() === 'subscription_variation' && isset( $parent_product ) ) { + + if ( $is_private_product ) { + $purchasable = false; + + // Forces product to be available when processing a renewal order. Allowing people to renew private products. + // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce validation is not required for this context. + if ( self::is_paying_for_failed_renewal_order( $parent_product ) || isset( $_GET['subscription_renewal'] ) || wcs_cart_contains_renewal() || self::session_contains_renewal( $parent_product ) ) { + $purchasable = true; + } + } + + if ( 'no' !== wcs_get_product_limitation( $parent_product ) && ( ! empty( WC()->cart->cart_contents ) || self::session_contains_resubscribe( $parent_product ) ) && ! wcs_is_order_received_page() && ! wcs_is_paypal_api_page() ) { + // When mixed checkout is disabled, the variation is replaceable. + if ( 'yes' === get_option( WC_Subscriptions_Admin::$option_prefix . '_multiple_purchase', 'no' ) ) { + foreach ( WC()->cart->cart_contents as $cart_item ) { + // If the variable product is limited, it can't be purchased if it is the same variation + if ( $product->get_parent_id() === $cart_item['data']->get_parent_id() && $product->get_id() !== $cart_item['data']->get_id() ) { + $purchasable = false; + break; + } + } + } + } + } else { // Checks limits for simple subscription products. + if ( $is_private_product ) { + $purchasable = false; + + // Forces product to be available when processing a renewal order. Allowing people to renew private products. + // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce validation is not required for this context. + if ( self::is_paying_for_failed_renewal_order( $product ) || isset( $_GET['subscription_renewal'] ) || wcs_cart_contains_renewal() || self::session_contains_renewal( $product ) ) { + $purchasable = true; + } + } + + // This actually means the product is limited when returning false. + if ( false === self::is_product_limited( $purchasable, $product ) ) { + $resubscribe_cart_item = wcs_cart_contains_resubscribe(); + // Allows the product to be resubscribed but not purchased again. + // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce validation is not required for this context. + if ( empty( $_GET['resubscribe'] ) && false === $resubscribe_cart_item && false === self::session_contains_resubscribe( $product ) ) { $purchasable = false; - - // Unless it's resubscribing, renewing or restoring cart from session. - $resubscribe_cart_item = wcs_cart_contains_resubscribe(); - - // Resubscribe logic - // phpcs:ignore WordPress.Security.NonceVerification.Recommended - if ( ! empty( $_GET['resubscribe'] ) || false !== $resubscribe_cart_item ) { - // phpcs:ignore WordPress.Security.NonceVerification.Recommended - $subscription_id = ( isset( $_GET['resubscribe'] ) ) ? absint( $_GET['resubscribe'] ) : $resubscribe_cart_item['subscription_resubscribe']['subscription_id']; - $subscription = wcs_get_subscription( $subscription_id ); - - if ( $subscription && $subscription->has_product( $product->get_id() ) && wcs_can_user_resubscribe_to( $subscription ) ) { - $purchasable = true; - } - - // Renewal logic - } elseif ( - // phpcs:ignore WordPress.Security.NonceVerification.Recommended - isset( $_GET['subscription_renewal'] ) || - wcs_cart_contains_renewal() - ) { - $purchasable = true; - - // Restoring cart from session, so need to check the cart in the session (wcs_cart_contains_renewal() only checks the cart). - } elseif ( ! empty( WC()->session->cart ) ) { - foreach ( WC()->session->cart as $cart_item_key => $cart_item ) { - if ( (int) $product->get_id() === (int) $cart_item['product_id'] && ( isset( $cart_item['subscription_renewal'] ) || isset( $cart_item['subscription_resubscribe'] ) ) ) { - $purchasable = true; - break; - } - } - } } - break; - case 'subscription_variation': - $variable_product = wc_get_product( $product->get_parent_id() ); - - if ( 'no' != wcs_get_product_limitation( $variable_product ) && ! empty( WC()->cart->cart_contents ) && ! wcs_is_order_received_page() && ! wcs_is_paypal_api_page() ) { - - // When mixed checkout is disabled, the variation is replaceable - if ( 'no' === get_option( WC_Subscriptions_Admin::$option_prefix . '_multiple_purchase', 'no' ) ) { - $purchasable = true; - } else { // When mixed checkout is enabled - foreach ( WC()->cart->cart_contents as $cart_item ) { - // If the variable product is limited, it can't be purchased if it is the same variation - if ( $product->get_parent_id() === $cart_item['data']->get_parent_id() && $product->get_id() !== $cart_item['data']->get_id() ) { - $purchasable = false; - break; - } - } - } - } - break; + } } + return $purchasable; } @@ -302,12 +328,73 @@ class WCS_Limiter { return self::$order_awaiting_payment_for_product[ $product_id ]; } + /** + * Check if we're currently paying for a failed renewal order containing the product. + * + * @since 8.3.0 - Migrated from WooCommerce Subscriptions v2.1.0 + * @param WC_Product $product The product to check. + * @return bool + */ + protected static function is_paying_for_failed_renewal_order( $product ) { + global $wp; + + // Check if we're on the pay for order page + // phpcs:ignore WordPress.Security.NonceVerification.Recommended + if ( ! isset( $_GET['pay_for_order'] ) || ! isset( $_GET['key'] ) || ! isset( $wp->query_vars['order-pay'] ) ) { + // Also check if cart contains a failed renewal order payment + $failed_renewal_cart_item = wcs_cart_contains_failed_renewal_order_payment(); + if ( false !== $failed_renewal_cart_item ) { + $cart_item_product_id = isset( $failed_renewal_cart_item['variation_id'] ) && $failed_renewal_cart_item['variation_id'] > 0 + ? $failed_renewal_cart_item['variation_id'] + : $failed_renewal_cart_item['product_id']; + // Check both the product ID and parent product ID (for variations) + if ( (int) $product->get_id() === (int) $cart_item_product_id || (int) $product->get_id() === (int) $failed_renewal_cart_item['product_id'] ) { + return true; + } + // Also check if product is a variation and matches the parent + if ( $product->get_parent_id() > 0 && (int) $product->get_parent_id() === (int) $failed_renewal_cart_item['product_id'] ) { + return true; + } + } + return false; + } + + // phpcs:ignore WordPress.Security.NonceVerification.Recommended + $order_key = isset( $_GET['key'] ) ? wc_clean( wp_unslash( $_GET['key'] ) ) : ''; + $order_id = isset( $wp->query_vars['order-pay'] ) ? $wp->query_vars['order-pay'] : 0; + $order = wc_get_order( absint( $order_id ) ); + + if ( ! $order || $order->get_order_key() !== $order_key ) { + return false; + } + + // Check if order is a failed renewal order + if ( ! $order->has_status( 'failed' ) && ! wcs_order_contains_renewal( $order ) ) { + return false; + } + + // Check if the order contains the product + foreach ( $order->get_items() as $item ) { + $item_product_id = isset( $item['variation_id'] ) && $item['variation_id'] > 0 ? $item['variation_id'] : $item['product_id']; + // Check both the product ID and parent product ID (for variations) + if ( (int) $product->get_id() === (int) $item_product_id || (int) $product->get_id() === (int) $item['product_id'] ) { + return true; + } + // Also check if product is a variation and matches the parent + if ( $product->get_parent_id() > 0 && (int) $product->get_parent_id() === (int) $item['product_id'] ) { + return true; + } + } + + return false; + } + /** * Filters the order statuses that enable the order again button and functionality. * * This function will return no statuses if the order contains non purchasable or limited products. * - * @since 1.0.0 - Migrated from WooCommerce Subscriptions v3.0.2 + * @since 8.3.0 - Migrated from WooCommerce Subscriptions v3.0.2 * * @param array $statuses The order statuses that enable the order again button. * @return array $statuses An empty array if the order contains limited products, otherwise the default statuses are returned. diff --git a/includes/core/emails/class-wcs-email-customer-renewal-invoice.php b/includes/core/emails/class-wcs-email-customer-renewal-invoice.php index 38f9589..9c9c5a2 100644 --- a/includes/core/emails/class-wcs-email-customer-renewal-invoice.php +++ b/includes/core/emails/class-wcs-email-customer-renewal-invoice.php @@ -124,7 +124,7 @@ class WCS_Email_Customer_Renewal_Invoice extends WC_Email_Customer_Invoice { * @return string */ function get_subject() { - return apply_filters( 'woocommerce_subscriptions_email_subject_new_renewal_order', parent::get_subject(), $this->object ); + return apply_filters( 'woocommerce_subscriptions_email_subject_new_renewal_order', $this->format_string( $this->get_option( 'subject', $this->get_default_subject() ) ), $this->object ); } /** @@ -134,7 +134,7 @@ class WCS_Email_Customer_Renewal_Invoice extends WC_Email_Customer_Invoice { * @return string */ function get_heading() { - return apply_filters( 'woocommerce_email_heading_customer_renewal_order', parent::get_heading(), $this->object ); + return apply_filters( 'woocommerce_email_heading_customer_renewal_order', $this->format_string( $this->get_option( 'heading', $this->get_default_heading() ) ), $this->object ); } /** diff --git a/includes/core/upgrades/class-wc-subscriptions-upgrader.php b/includes/core/upgrades/class-wc-subscriptions-upgrader.php index 737b4ff..14b37c8 100644 --- a/includes/core/upgrades/class-wc-subscriptions-upgrader.php +++ b/includes/core/upgrades/class-wc-subscriptions-upgrader.php @@ -227,9 +227,8 @@ class WC_Subscriptions_Upgrader { WCS_Plugin_Upgrade_7_8_0::check_gifting_plugin_is_enabled(); } - if ( false && version_compare( self::$stored_plugin_version, '8.2.0', '<' ) ) { - // TODO: remove false from the above conditional, once we are ready to make subscription downloads functionality available. - WCS_Plugin_Upgrade_8_1_0::check_downloads_plugin_is_enabled(); + if ( version_compare( self::$stored_plugin_version, '8.3.0', '<' ) ) { + WCS_Plugin_Upgrade_8_3_0::check_downloads_plugin_is_enabled(); } } diff --git a/includes/core/upgrades/class-wcs-plugin-upgrade-8-1-0.php b/includes/core/upgrades/class-wcs-plugin-upgrade-8-3-0.php similarity index 96% rename from includes/core/upgrades/class-wcs-plugin-upgrade-8-1-0.php rename to includes/core/upgrades/class-wcs-plugin-upgrade-8-3-0.php index 73af66c..d413f99 100644 --- a/includes/core/upgrades/class-wcs-plugin-upgrade-8-1-0.php +++ b/includes/core/upgrades/class-wcs-plugin-upgrade-8-3-0.php @@ -7,7 +7,7 @@ if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } -class WCS_Plugin_Upgrade_8_1_0 { +class WCS_Plugin_Upgrade_8_3_0 { /** * Check if the Gifting plugin is enabled and update the settings. diff --git a/includes/downloads/class-wc-subscription-downloads-admin-welcome-announcement.php b/includes/downloads/class-wc-subscription-downloads-admin-welcome-announcement.php new file mode 100644 index 0000000..34797ba --- /dev/null +++ b/includes/downloads/class-wc-subscription-downloads-admin-welcome-announcement.php @@ -0,0 +1,93 @@ + plugins_url( '/assets/images', WC_Subscriptions::$plugin_file ), + 'pluginsUrl' => admin_url( 'plugins.php' ), + 'subscriptionsUrl' => WC_Subscriptions_Admin::settings_tab_url() . '#woocommerce_subscriptions_downloads_enable', + 'isStandaloneDownloadsEnabled' => is_plugin_active( 'woocommerce-subscription-downloads/woocommerce-subscription-downloads.php' ), + 'isSubscriptionsListing' => 'woocommerce_page_wc-orders--shop_subscription' === $screen->id, + ) + ); + } + + /** + * Output the tour HTML in the admin footer + */ + public static function output_tour() { + if ( ! self::is_woocommerce_admin_or_subscriptions_listing() ) { + return; + } + + // Add a div for the tour to be rendered into + echo '
'; + } + + /** + * Checks if the welcome tour has been dismissed. + * + * @return bool + */ + public static function is_welcome_announcement_dismissed() { + return '1' === get_option( + 'woocommerce_subscriptions_downloads_is_welcome_announcement_dismissed', + '' + ); + } + + /** + * Checks if the current screen is WooCommerce Admin or subscriptions listing. + * + * @return bool + */ + private static function is_woocommerce_admin_or_subscriptions_listing() { + $screen = get_current_screen(); + + if ( ! $screen ) { + return false; + } + + // phpcs:ignore WordPress.Security.NonceVerification.Recommended + $action_param = isset( $_GET['action'] ) ? wc_clean( wp_unslash( $_GET['action'] ) ) : ''; + + $is_woocommerce_admin = 'woocommerce_page_wc-admin' === $screen->id; + $is_subscriptions_listing = 'woocommerce_page_wc-orders--shop_subscription' === $screen->id && empty( $action_param ); + + return $is_woocommerce_admin || $is_subscriptions_listing; + } +} diff --git a/includes/downloads/class-wc-subscription-downloads-ajax.php b/includes/downloads/class-wc-subscription-downloads-ajax.php index b5d91d5..02c1374 100644 --- a/includes/downloads/class-wc-subscription-downloads-ajax.php +++ b/includes/downloads/class-wc-subscription-downloads-ajax.php @@ -17,6 +17,7 @@ class WC_Subscription_Downloads_Ajax { */ public function __construct() { add_action( 'wp_ajax_wc_subscription_downloads_search', array( $this, 'search_subscriptions' ) ); + add_action( 'wp_ajax_wc_subscription_linked_downloadable_products_search', array( $this, 'search_downloadable_products' ) ); } /** @@ -72,4 +73,39 @@ class WC_Subscription_Downloads_Ajax { wp_send_json( $found_subscriptions ); } + + /** + * Searches for downloadable products that are simple or variants. + * + * @return void + */ + public function search_downloadable_products(): void { + $results = array(); + + // Prevent error noise from leaking. + ob_start(); + + if ( isset( $_GET['term'] ) && check_ajax_referer( 'search-products', 'security' ) ) { + $term = wc_clean( wp_unslash( $_GET['term'] ) ); + } + + if ( ! empty( $term ) ) { + $products = wc_get_products( + array( + 'downloadable' => true, + 'limit' => 100, + 's' => $term, + 'type' => array( 'simple', 'variation' ), + 'status' => 'any', + ) + ); + + foreach ( $products as $product ) { + $results[ $product->get_id() ] = sanitize_text_field( $product->get_formatted_name() ); + } + } + + ob_clean(); + wp_send_json( $results ); + } } diff --git a/includes/downloads/class-wc-subscription-downloads-products.php b/includes/downloads/class-wc-subscription-downloads-products.php index 6f6a115..1245a9f 100644 --- a/includes/downloads/class-wc-subscription-downloads-products.php +++ b/includes/downloads/class-wc-subscription-downloads-products.php @@ -7,52 +7,202 @@ if ( ! defined( 'ABSPATH' ) ) { * WooCommerce Subscription Downloads Products. * * @package WC_Subscription_Downloads_Products - * @category Products - * @author WooThemes */ class WC_Subscription_Downloads_Products { + public const EDITOR_UPDATE = 'wcsubs_subscription_download_relationships'; + public const RELATIONSHIP_DOWNLOAD_TO_SUB = 'download-to-sub'; + public const RELATIONSHIP_VAR_DOWNLOAD_TO_SUB = 'var-download-to-sub'; + public const RELATIONSHIP_SUB_TO_DOWNLOAD = 'sub-to-download'; + public const RELATIONSHIP_VAR_SUB_TO_DOWNLOAD = 'var-sub-to-download'; /** * Products actions. */ public function __construct() { - add_action( 'woocommerce_product_options_downloads', array( $this, 'simple_write_panel_options' ), 10 ); + add_action( 'woocommerce_product_options_downloads', array( $this, 'simple_write_panel_options' ) ); add_action( 'woocommerce_variation_options_download', array( $this, 'variable_write_panel_options' ), 10, 3 ); - add_action( 'admin_enqueue_scripts', array( $this, 'scripts' ) ); - add_action( 'woocommerce_process_product_meta_simple', array( $this, 'save_simple_product_data' ), 10 ); - add_action( 'woocommerce_save_product_variation', array( $this, 'save_variation_product_data' ), 10, 2 ); + add_action( 'woocommerce_product_options_pricing', array( $this, 'subscription_product_editor_ui' ) ); + add_action( 'woocommerce_variable_subscription_pricing', array( $this, 'variable_subscription_product_editor_ui' ), 10, 3 ); + + add_action( 'save_post_product', array( $this, 'handle_product_save' ) ); + add_action( 'save_post_product_variation', array( $this, 'handle_product_variation_save' ) ); + add_action( 'woocommerce_save_product_variation', array( $this, 'handle_product_variation_save' ) ); + add_action( 'woocommerce_update_product', array( $this, 'handle_product_save' ) ); + add_action( 'woocommerce_update_product_variation', array( $this, 'handle_product_variation_save' ) ); + add_action( 'init', array( $this, 'init' ) ); } public function init() { - if ( version_compare( WC_VERSION, '3.0', '<' ) ) { - add_action( 'woocommerce_duplicate_product', array( $this, 'save_subscriptions_when_duplicating_product' ), 10, 2 ); - } else { - add_action( 'woocommerce_product_duplicate', array( $this, 'save_subscriptions_when_duplicating_product' ), 10, 2 ); + add_action( 'woocommerce_product_duplicate', array( $this, 'save_subscriptions_when_duplicating_product' ), 10, 2 ); + } + + /** + * Handle product save - generic handler for all product updates. + * + * @param int $post_id Post ID. + * + * @return void + */ + public function handle_product_save( $post_id ) { + // Bail if this is an autosave or revision. + if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { + return; + } + + if ( wp_is_post_revision( $post_id ) ) { + return; + } + + $product = wc_get_product( $post_id ); + + if ( ! $product ) { + return; + } + + $product_is_downloadable = $product->is_downloadable(); + $product_is_subscription = $product->is_type( array( 'subscription', 'variable-subscription' ) ); + + // We do not allow downloadable subscription products to be linked with other subscription products; this is + // principally to avoid confusion (though it would be technically feasible). + if ( $product_is_subscription && ! $product_is_downloadable ) { + $this->handle_subscription_product_save( $post_id ); + } elseif ( ! $product_is_subscription && $product_is_downloadable ) { + $this->handle_downloadable_product_save( $post_id ); } } /** - * Product screen scripts. + * Handle product variation save - generic handler for all variation updates. + * + * @param int $post_id Post ID. * * @return void */ - public function scripts() { - $screen = get_current_screen(); + public function handle_product_variation_save( $post_id ) { + // Bail if this is an autosave or revision. + if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { + return; + } - if ( 'product' == $screen->id && version_compare( WC_VERSION, '2.3.0', '<' ) ) { - $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min'; + if ( wp_is_post_revision( $post_id ) ) { + return; + } - wp_enqueue_script( 'wc_subscription_downloads_writepanel', plugins_url( 'assets/js/admin/writepanel' . $suffix . '.js', plugin_dir_path( __FILE__ ) ), array( 'ajax-chosen', 'chosen' ), WC_Subscriptions::$version, true ); + $variation = wc_get_product( $post_id ); + if ( ! $variation || ! $variation->is_type( 'variation' ) ) { + return; + } - wp_localize_script( - 'wc_subscription_downloads_writepanel', - 'wc_subscription_downloads_product', - array( - 'ajax_url' => admin_url( 'admin-ajax.php' ), - 'security' => wp_create_nonce( 'search-products' ), - ) - ); + // Handle downloadable variations (they link TO subscriptions). + if ( $variation->is_downloadable() ) { + $this->handle_downloadable_product_save( $post_id ); + } + + // Handle subscription variations (they link TO downloadable products). + $parent = wc_get_product( $variation->get_parent_id() ); + + if ( $parent && $parent->is_type( 'variable-subscription' ) ) { + $this->handle_subscription_product_save( $post_id ); + } + } + + /** + * Handle save for downloadable products (simple or variation). + * These products link TO subscription products. + * + * @param int $product_id Product or variation ID. + * + * @return void + */ + private function handle_downloadable_product_save( $product_id ) { + $product = wc_get_product( $product_id ); + + if ( ! $product ) { + return; + } + + // phpcs:disable WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized + if ( + isset( $_POST[ self::RELATIONSHIP_VAR_DOWNLOAD_TO_SUB . $product_id ] ) + && wp_verify_nonce( $_POST[ self::RELATIONSHIP_VAR_DOWNLOAD_TO_SUB . $product_id ], self::EDITOR_UPDATE ) + ) { + $subscription_ids = wc_clean( wp_unslash( $_POST['_variable_subscription_downloads_ids'][ $product_id ] ?? array() ) ); + $subscription_ids = array_filter( (array) $subscription_ids ); + $this->update_subscription_downloads( $product_id, $subscription_ids ); + } + + if ( + isset( $_POST[ self::RELATIONSHIP_DOWNLOAD_TO_SUB ] ) + && wp_verify_nonce( $_POST[ self::RELATIONSHIP_DOWNLOAD_TO_SUB ], self::EDITOR_UPDATE ) + ) { + $subscription_ids = wc_clean( wp_unslash( $_POST['_subscription_downloads_ids'] ?? array() ) ); + $subscription_ids = array_filter( (array) $subscription_ids ); + $this->update_subscription_downloads( $product_id, $subscription_ids ); + } + + // Observe and act on product status changes (regardless of whether they were made from within the product + // editor, therefore we don't care about nonce checks here). + $this->assess_downloadable_product_status( $product_id ); + // phpcs:enable + } + + /** + * Handle save for subscription products (simple subscription or variation). + * These products link TO downloadable products. + * + * @param int $product_id Subscription product or variation ID. + * + * @return void + */ + private function handle_subscription_product_save( $product_id ) { + // phpcs:disable WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized + if ( + isset( $_POST[ self::RELATIONSHIP_VAR_SUB_TO_DOWNLOAD . $product_id ] ) + && wp_verify_nonce( $_POST[ self::RELATIONSHIP_VAR_SUB_TO_DOWNLOAD . $product_id ], self::EDITOR_UPDATE ) + ) { + $product_ids = wc_clean( wp_unslash( $_POST[ '_subscription_linked_downloadable_products_' . $product_id ] ?? array() ) ); + $product_ids = array_filter( (array) $product_ids ); + $this->update_subscription_products( $product_id, $product_ids ); + return; + } + + if ( + isset( $_POST[ self::RELATIONSHIP_SUB_TO_DOWNLOAD ] ) + && wp_verify_nonce( $_POST[ self::RELATIONSHIP_SUB_TO_DOWNLOAD ], self::EDITOR_UPDATE ) + ) { + $product_ids = wc_clean( wp_unslash( (array) $_POST['_subscription_linked_downloadable_products'] ?? array() ) ); + $product_ids = array_filter( (array) $product_ids ); + $this->update_subscription_products( $product_id, $product_ids ); + } + // phpcs:enable + } + + /** + * Assess downloadable product status and adjust permissions accordingly. + * Called when no form data is available (e.g., status change, REST API update, file changes). + * + * @param int $product_id Product ID. + * + * @return void + */ + private function assess_downloadable_product_status( $product_id ) { + $product = wc_get_product( $product_id ); + + if ( ! $product || ! $product->is_downloadable() ) { + return; + } + + $status_object = get_post_status_object( $product->get_status() ); + $is_public = $status_object && $status_object->public; + + // Always revoke existing permissions first to ensure clean state. + // This handles file changes and status transitions. + $this->revoke_permissions_for_product( $product_id ); + + // Grant fresh permissions only if product is public. + if ( $is_public ) { + $this->grant_permissions_for_product( $product_id ); } } @@ -62,8 +212,8 @@ class WC_Subscription_Downloads_Products { public function simple_write_panel_options() { global $post; ?> -

- +

+ - + +

-

- +

+ - ID ); if ( $subscriptions_ids ) { foreach ( $subscriptions_ids as $subscription_id ) { - $_subscription = wc_get_product( $subscription_id ); + $subscription = wc_get_product( $subscription_id ); - if ( $_subscription ) { - echo ''; + if ( $subscription ) { + echo ''; } } } ?> + ID, false ); ?>

warning( + 'Unable to add the downloadable products selector to the product editor (global post object is unavailable).', + array( 'backtrace' => true ) + ); + + return; + } + + $description = esc_html__( 'Select simple and variable downloadable products that will be included with this subscription product.', 'woocommerce-subscriptions' ); + $label = esc_html__( 'Linked downloadable products', 'woocommerce-subscriptions' ); + $linked_products = ''; + $nonce_field = wp_nonce_field( self::EDITOR_UPDATE, self::RELATIONSHIP_SUB_TO_DOWNLOAD, false, false ); + $placeholder = esc_attr__( 'Select products', 'woocommerce-subscriptions' ); + + foreach ( WC_Subscription_Downloads::get_downloadable_products( $post->ID ) as $product_id ) { + $product_id = absint( $product_id ); + $product = wc_get_product( $product_id ); + + if ( $product ) { + $product_name = esc_html( wp_strip_all_tags( $product->get_formatted_name() ) ); + $linked_products .= ""; + } + } + + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- variables are escaped above. + echo " +
+

+ + + $description + $nonce_field +

+
+ "; + } + + /** + * @param int $loop + * @param array $variation_data + * @param WP_Post $variation + * + * @return void + */ + public function variable_subscription_product_editor_ui( $loop, $variation_data, $variation ): void { + if ( ! $variation instanceof WP_Post ) { + wc_get_logger()->warning( + 'Unable to add the downloadable products selector to the variation section of the product editor (we do not have a valid post object).', + array( 'backtrace' => true ) + ); + + return; + } + + $variation_id = (int) $variation->ID; + $label = esc_html__( 'Linked downloadable products', 'woocommerce-subscriptions' ); + $linked_products = ''; + $nonce_field = wp_nonce_field( self::EDITOR_UPDATE, self::RELATIONSHIP_VAR_SUB_TO_DOWNLOAD . $variation_id, false, false ); + $placeholder = esc_attr__( 'Select products', 'woocommerce-subscriptions' ); + $tooltip = wc_help_tip( wc_sanitize_tooltip( __( 'Select simple and variable downloadable products that will be included with this subscription variation.', 'woocommerce-subscriptions' ) ) ); + + foreach ( WC_Subscription_Downloads::get_downloadable_products( $variation->ID ) as $product_id ) { + $product_id = absint( $product_id ); + $product = wc_get_product( $product_id ); + + if ( $product ) { + $product_name = esc_html( wp_strip_all_tags( $product->get_formatted_name() ) ); + $linked_products .= ""; + } + } + + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- variables are escaped above. + echo " + + "; + } + /** * Search orders from subscription product ID. * @@ -164,9 +430,7 @@ class WC_Subscription_Downloads_Products { $orders[] = $order->id; } - $orders = apply_filters( 'woocommerce_subscription_downloads_get_orders', $orders, $subscription_product_id ); - - return $orders; + return apply_filters( 'woocommerce_subscription_downloads_get_orders', $orders, $subscription_product_id ); } /** @@ -181,37 +445,93 @@ class WC_Subscription_Downloads_Products { protected function revoke_access_to_download( $download_id, $product_id, $order_id ) { global $wpdb; - $wpdb->query( $wpdb->prepare( " - DELETE FROM {$wpdb->prefix}woocommerce_downloadable_product_permissions - WHERE order_id = %d AND product_id = %d AND download_id = %s; - ", $order_id, $product_id, $download_id ) ); + $wpdb->query( + $wpdb->prepare( + " + DELETE FROM {$wpdb->prefix}woocommerce_downloadable_product_permissions + WHERE order_id = %d AND product_id = %d AND download_id = %s; + ", + $order_id, + $product_id, + $download_id + ) + ); do_action( 'woocommerce_ajax_revoke_access_to_product_download', $download_id, $product_id, $order_id ); } /** - * Update subscription downloads table and orders. + * Update subscription downloads table and orders according in respect to the described relationship between a + * regular product and zero-to-many regular subscription products. * - * @param int $product_id - * @param array $subscriptions + * @param int $product_id The downloadable product ID. + * @param array $subscriptions Subscription product IDs. * * @return void */ protected function update_subscription_downloads( $product_id, $subscriptions ) { + $current = array_map( 'intval', WC_Subscription_Downloads::get_subscriptions( $product_id ) ); + $subscriptions = array_map( 'intval', (array) $subscriptions ); + + sort( $current ); + sort( $subscriptions ); + + $to_delete = array_diff( $current, $subscriptions ); + $to_create = array_diff( $subscriptions, $current ); + + $this->delete_relationships( $to_delete, array( $product_id ) ); + $this->create_relationships( $to_create, array( $product_id ) ); + } + + /** + * Update subscription downloads table and orders according in respect to the described relationship between a + * subscription product and zero-to-many regular products. + * + * @param int $subscription_product_id Subscription product ID. + * @param int[] $new_ids IDs for downloadable products that should be associated with the subscription product. + * + * @return void + */ + private function update_subscription_products( int $subscription_product_id, array $new_ids ): void { + $existing_ids = array_map( 'intval', WC_Subscription_Downloads::get_downloadable_products( $subscription_product_id ) ); + $new_ids = array_map( 'intval', $new_ids ); + + sort( $existing_ids ); + sort( $new_ids ); + + $to_delete = array_diff( $existing_ids, $new_ids ); + $to_create = array_diff( $new_ids, $existing_ids ); + + $this->delete_relationships( array( $subscription_product_id ), $to_delete ); + $this->create_relationships( array( $subscription_product_id ), $to_create ); + } + + /** + * Deletes relationships that exist between any of the supplied subscription IDs and any of the supplied product + * IDs. + * + * The most common use case will be to supply a single subscription ID and one-or-more product IDs, or else the + * inverse. + * + * @param int[] $subscription_ids + * @param int[] $product_ids + * + * @return void + */ + private function delete_relationships( array $subscription_ids, array $product_ids ): void { global $wpdb; - $subscriptions = (array) $subscriptions; - $current = WC_Subscription_Downloads::get_subscriptions( $product_id ); + foreach ( $product_ids as $product_id ) { + $product_id = (int) $product_id; + + foreach ( $subscription_ids as $subscription_id ) { + $subscription_id = (int) $subscription_id; - // Delete items. - $delete_ids = array_diff( $current, $subscriptions ); - if ( $delete_ids ) { - foreach ( $delete_ids as $delete ) { $wpdb->delete( $wpdb->prefix . 'woocommerce_subscription_downloads', array( 'product_id' => $product_id, - 'subscription_id' => $delete, + 'subscription_id' => $subscription_id, ), array( '%d', @@ -219,10 +539,10 @@ class WC_Subscription_Downloads_Products { ) ); - $_orders = $this->get_orders( $delete ); - foreach ( $_orders as $order_id ) { - $_product = wc_get_product( $product_id ); - $downloads = $_product->get_downloads(); + $orders = $this->get_orders( $subscription_id ); + foreach ( $orders as $order_id ) { + $product = wc_get_product( $product_id ); + $downloads = $product->get_downloads(); // Adds the downloadable files to the order/subscription. foreach ( array_keys( $downloads ) as $download_id ) { @@ -231,16 +551,35 @@ class WC_Subscription_Downloads_Products { } } } + } - // Add items. - $add_ids = array_diff( $subscriptions, $current ); - if ( $add_ids ) { - foreach ( $add_ids as $add ) { - $wpdb->insert( - $wpdb->prefix . 'woocommerce_subscription_downloads', + /** + * Revoke download permissions for a product across all related subscriptions. + * + * @param int $product_id Product ID. + * + * @return void + */ + private function revoke_permissions_for_product( $product_id ) { + global $wpdb; + + $subscription_ids = WC_Subscription_Downloads::get_subscriptions( $product_id ); + + if ( empty( $subscription_ids ) ) { + return; + } + + foreach ( $subscription_ids as $subscription_id ) { + $orders = $this->get_orders( $subscription_id ); + + foreach ( $orders as $order_id ) { + // Delete ALL permissions for this product+order combination. + // This ensures that when files change, old permissions with different download_ids are removed. + $wpdb->delete( + $wpdb->prefix . 'woocommerce_downloadable_product_permissions', array( - 'product_id' => $product_id, - 'subscription_id' => $add, + 'order_id' => $order_id, + 'product_id' => $product_id, ), array( '%d', @@ -248,23 +587,105 @@ class WC_Subscription_Downloads_Products { ) ); - $_orders = $this->get_orders( $add ); - foreach ( $_orders as $order_id ) { - $order = wc_get_order( $order_id ); + do_action( 'woocommerce_revoke_access_to_product_download', $product_id, $order_id ); + } + } + } - if ( ! is_a( $order, 'WC_Subscription' ) ) { - // avoid adding permissions to orders and it's - // subscription for the same user, causing duplicates - // to show up - continue; - } + /** + * Grant download permissions for a product across all related subscriptions. + * + * @param int $product_id Product ID. + * + * @return void + */ + private function grant_permissions_for_product( $product_id ) { + $subscription_product_ids = WC_Subscription_Downloads::get_subscriptions( $product_id ); + $product = wc_get_product( $product_id ); - $_product = wc_get_product( $product_id ); - $downloads = $_product->get_downloads(); + if ( empty( $subscription_product_ids ) || ! $product ) { + return; + } - // Adds the downloadable files to the order/subscription. - foreach ( array_keys( $downloads ) as $download_id ) { - wc_downloadable_file_permission( $download_id, $product_id, $order ); + $downloads = $product->get_downloads(); + + foreach ( $subscription_product_ids as $subscription_id ) { + $orders = $this->get_orders( $subscription_id ); + + foreach ( $orders as $order_id ) { + $order = wc_get_order( $order_id ); + + if ( ! is_a( $order, 'WC_Subscription' ) ) { + continue; + } + + foreach ( array_keys( $downloads ) as $download_id ) { + wc_downloadable_file_permission( $download_id, $product_id, $order ); + } + } + } + } + + /** + * Adds relationships between the specified subscription and product IDs. + * + * The most common use case will be to supply a single subscription ID and one-or-more product IDs, or else the + * inverse. + * + * @param int[] $subscription_ids + * @param int[] $product_ids + * + * @return void + */ + private function create_relationships( array $subscription_ids, array $product_ids ): void { + global $wpdb; + + foreach ( $product_ids as $product_id ) { + $product_id = (int) $product_id; + $product = wc_get_product( $product_id ); + + // Check if product has public status. + $has_public_status = false; + if ( $product ) { + $status_object = get_post_status_object( $product->get_status() ); + $has_public_status = $status_object && $status_object->public; + } + + foreach ( $subscription_ids as $subscription_id ) { + $subscription_id = (int) $subscription_id; + + $wpdb->insert( + $wpdb->prefix . 'woocommerce_subscription_downloads', + array( + 'product_id' => $product_id, + 'subscription_id' => $subscription_id, + ), + array( + '%d', + '%d', + ) + ); + + // Only grant download permissions if product has public status. + if ( $has_public_status ) { + $orders = $this->get_orders( $subscription_id ); + foreach ( $orders as $order_id ) { + $order = wc_get_order( $order_id ); + + if ( ! is_a( $order, 'WC_Subscription' ) ) { + // avoid adding permissions to orders and it's + // subscription for the same user, causing duplicates + // to show up + continue; + } + + $product = wc_get_product( $product_id ); + $downloads = $product->get_downloads(); + + // Adds the downloadable files to the order/subscription. + foreach ( array_keys( $downloads ) as $download_id ) { + wc_downloadable_file_permission( $download_id, $product_id, $order ); + } } } } @@ -289,26 +710,6 @@ class WC_Subscription_Downloads_Products { $this->update_subscription_downloads( $product_id, $subscription_downloads_ids ); } - /** - * Save variable product data. - * - * @param int $variation_id - * @param int $index - * - * @return void - */ - public function save_variation_product_data( $variation_id, $index ) { - if ( ! isset( $_POST['variable_is_downloadable'][ $index ] ) ) { - return; - } - - // phpcs:ignore WordPress.Security.NonceVerification.Missing - $subscription_download_ids = isset( $_POST['_variable_subscription_downloads_ids'][ $index ] ) ? wc_clean( wp_unslash( $_POST['_variable_subscription_downloads_ids'][ $index ] ) ) : array(); - $subscription_download_ids = array_filter( $subscription_download_ids ); // nosemgrep: audit.php.lang.misc.array-filter-no-callback -- $subscription_download_ids are already passed through wc_clean() and wp_unslash(). - - $this->update_subscription_downloads( $variation_id, $subscription_download_ids ); - } - /** * Save subscriptions information when duplicating a product. * @@ -370,4 +771,45 @@ class WC_Subscription_Downloads_Products { return (string) wc_get_formatted_variation( $product_variation, true ); } + + /** + * Deprecated, do not use. Previously took care of saving product data for variations. + * + * @deprecated 8.3.0 + * + * @param int $variation_id + * @param int $index + * + * @return void + */ + // phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed + public function save_variation_product_data( $variation_id, $index ) { + wc_deprecated_function( __METHOD__, '8.3.0', __CLASS__ . '::handle_product_variation_save' ); + } + + /** + * Deprecated, do not use. Previously took care of saving product data. + * + * @deprecated 8.3.0 + * + * @param int $subscription_product_id + * @param int|null $index + * + * @return void + */ + // phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed + public function save_subscription_product_data( int $subscription_product_id, ?int $index = null ) { + wc_deprecated_function( __METHOD__, '8.3.0', __CLASS__ . '::handle_product_save' ); + } + + /** + * Deprecated, do not use. Previously set up assets for the Subscription Downloads extension. + * + * @deprecated 8.3.0 + * + * @return void + */ + public function scripts() { + wc_deprecated_function( __METHOD__, '8.3.0' ); + } } diff --git a/includes/downloads/class-wc-subscription-downloads-settings.php b/includes/downloads/class-wc-subscription-downloads-settings.php index ccd3982..5373363 100644 --- a/includes/downloads/class-wc-subscription-downloads-settings.php +++ b/includes/downloads/class-wc-subscription-downloads-settings.php @@ -19,11 +19,6 @@ class WC_Subscription_Downloads_Settings { * @since 8.0.0 */ public static function add_notice_about_bundled_feature() { - if ( ! Constants::is_true( 'WCS_ALLOW_SUBSCRIPTION_DOWNLOADS' ) ) { - // TODO: remove this conditional as soon as we are ready to make subscription downloads functionality live. - return; - } - $screen = get_current_screen(); if ( ! $screen ) { return false; @@ -65,8 +60,8 @@ class WC_Subscription_Downloads_Settings { 'id' => WC_Subscriptions_Admin::$option_prefix . '_downloads_settings', ), array( - 'name' => __( 'Enable product linking to subscriptions', 'woocommerce-subscriptions' ), - 'desc' => __( 'Allow simple and variable downloadable products to be included with subscription products.', 'woocommerce-subscriptions' ), + 'name' => __( 'Enable downloadable file sharing', 'woocommerce-subscriptions' ), + 'desc' => __( 'Allow downloadable files from simple and variable products to be shared with subscription products so they are available to active subscribers.', 'woocommerce-subscriptions' ), 'id' => WC_Subscriptions_Admin::$option_prefix . '_enable_downloadable_file_linking', 'default' => 'no', 'type' => 'checkbox', diff --git a/includes/gifting/class-wcsg-admin-welcome-announcement.php b/includes/gifting/class-wcsg-admin-welcome-announcement.php index 4df8e15..9a7d11e 100644 --- a/includes/gifting/class-wcsg-admin-welcome-announcement.php +++ b/includes/gifting/class-wcsg-admin-welcome-announcement.php @@ -33,32 +33,8 @@ class WCSG_Admin_Welcome_Announcement { $screen = get_current_screen(); - $script_asset_path = \WC_Subscriptions_Plugin::instance()->get_plugin_directory( 'build/gifting-welcome-announcement.asset.php' ); - $script_asset = file_exists( $script_asset_path ) - ? require $script_asset_path - : array( - 'dependencies' => array( - 'react', - 'wc-blocks-checkout', - 'wc-price-format', - 'wc-settings', - 'wp-element', - 'wp-i18n', - 'wp-plugins', - ), - 'version' => WC_Subscriptions::$version, - ); - - wp_enqueue_script( - 'wcs-gifting-welcome-announcement', - plugins_url( '/build/gifting-welcome-announcement.js', WC_Subscriptions::$plugin_file ), - $script_asset['dependencies'], - $script_asset['version'], - true - ); - wp_localize_script( - 'wcs-gifting-welcome-announcement', + 'wcs-admin', 'wcsGiftingSettings', array( 'imagesPath' => plugins_url( '/assets/images', WC_Subscriptions::$plugin_file ), @@ -68,19 +44,6 @@ class WCSG_Admin_Welcome_Announcement { 'isSubscriptionsListing' => 'woocommerce_page_wc-orders--shop_subscription' === $screen->id, ) ); - - wp_enqueue_style( - 'wcs-gifting-welcome-announcement', - plugins_url( '/build/style-gifting-welcome-announcement.css', WC_Subscriptions::$plugin_file ), - array( 'wp-components' ), - $script_asset['version'] - ); - - wp_set_script_translations( - 'wcs-gifting-welcome-announcement', - 'woocommerce-subscriptions', - plugin_dir_path( WC_Subscriptions::$plugin_file ) . 'languages' - ); } /** diff --git a/includes/switching/class-wc-subscriptions-switcher.php b/includes/switching/class-wc-subscriptions-switcher.php index e242362..d03d7eb 100644 --- a/includes/switching/class-wc-subscriptions-switcher.php +++ b/includes/switching/class-wc-subscriptions-switcher.php @@ -1,4 +1,7 @@ 0 ) { wc_add_notice( _n( 'Your cart contained an invalid subscription switch request. It has been removed.', 'Your cart contained invalid subscription switch requests. They have been removed.', $removed_item_count, 'woocommerce-subscriptions' ), 'error' ); - wp_safe_redirect( wc_get_cart_url() ); - exit(); + Request::redirect( wc_get_cart_url() ); + return; } } elseif ( is_product() && $product = wc_get_product( $post ) ) { // Automatically initiate the switch process for limited variable subscriptions @@ -308,8 +318,8 @@ class WC_Subscriptions_Switcher { } if ( apply_filters( 'wcs_initiate_auto_switch', self::can_item_be_switched_by_user( $item, $subscription ), $item, $subscription ) ) { - wp_safe_redirect( add_query_arg( 'auto-switch', 'true', self::get_switch_url( $item_id, $item, $subscription ) ) ); - exit; + Request::redirect( add_query_arg( 'auto-switch', 'true', self::get_switch_url( $item_id, $item, $subscription ) ) ); + return; } } } @@ -560,6 +570,30 @@ class WC_Subscriptions_Switcher { echo wp_kses( apply_filters( 'woocommerce_subscriptions_switch_link', $switch_link, $item_id, $item, $subscription ), array( 'a' => array( 'href' => array(), 'title' => array(), 'class' => array() ) ) ); // phpcs:ignore WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound } + /** + * Add hidden form inputs for subscription switch parameters. + * + * When a customer is switching subscriptions, the switch parameters are passed via URL query arguments. + * This method outputs them as hidden form inputs so they're included when AJAX add-to-cart plugins + * serialize and submit the form via POST. + * + * @since 8.3.0 + */ + public static function add_switch_hidden_inputs() { + $switch_subscription_id = Request::get_var( 'switch-subscription' ); + $item_id = Request::get_var( 'item' ); + $nonce = Request::get_var( '_wcsnonce' ); + + // Only output if we're in a switch context with a valid nonce + if ( ! $switch_subscription_id || ! $item_id || ! $nonce ) { + return; + } + + echo ''; + echo ''; + echo ''; + } + /** * The link for switching a subscription - the product page for variable subscriptions, or grouped product page for grouped subscriptions. * @@ -1382,21 +1416,25 @@ class WC_Subscriptions_Switcher { try { - if ( ! isset( $_GET['switch-subscription'] ) ) { + $switch_subscription_id = Request::get_var( 'switch-subscription' ); + + if ( ! $switch_subscription_id ) { return $is_valid; } - if ( empty( $_GET['_wcsnonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wcsnonce'] ) ), 'wcs_switch_request' ) ) { + $nonce = Request::get_var( '_wcsnonce' ); + + if ( empty( $nonce ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $nonce ) ), 'wcs_switch_request' ) ) { return false; } - $subscription = wcs_get_subscription( absint( $_GET['switch-subscription'] ) ); + $subscription = wcs_get_subscription( absint( $switch_subscription_id ) ); if ( ! $subscription ) { throw new Exception( __( 'The subscription may have been deleted.', 'woocommerce-subscriptions' ) ); } - $item_id = absint( $_GET['item'] ); + $item_id = absint( Request::get_var( 'item' ) ); $item = wcs_get_order_item( $item_id, $subscription ); // Prevent switching to non-subscription product @@ -1468,11 +1506,13 @@ class WC_Subscriptions_Switcher { public static function set_switch_details_in_cart( $cart_item_data, $product_id, $variation_id ) { try { - if ( ! isset( $_GET['switch-subscription'] ) ) { + $switch_subscription_id = Request::get_var( 'switch-subscription' ); + + if ( ! $switch_subscription_id ) { return $cart_item_data; } - $subscription = wcs_get_subscription( absint( $_GET['switch-subscription'] ) ); + $subscription = wcs_get_subscription( absint( $switch_subscription_id ) ); if ( ! $subscription ) { throw new Exception( __( 'The subscription may have been deleted.', 'woocommerce-subscriptions' ) ); @@ -1482,11 +1522,11 @@ class WC_Subscriptions_Switcher { if ( ! current_user_can( 'switch_shop_subscription', $subscription->get_id() ) ) { wc_add_notice( __( 'You can not switch this subscription. It appears you do not own the subscription.', 'woocommerce-subscriptions' ), 'error' ); WC()->cart->empty_cart( true ); - wp_safe_redirect( get_permalink( $product_id ) ); - exit(); + Request::redirect( get_permalink( $product_id ) ); + return; } - $item = wcs_get_order_item( absint( $_GET['item'] ), $subscription ); + $item = wcs_get_order_item( absint( Request::get_var( 'item' ) ), $subscription ); // Else it's a valid switch $product = wc_get_product( $item['product_id'] ); @@ -1538,7 +1578,7 @@ class WC_Subscriptions_Switcher { $cart_item_data['subscription_switch'] = array( 'subscription_id' => $subscription->get_id(), - 'item_id' => absint( $_GET['item'] ), + 'item_id' => absint( Request::get_var( 'item' ) ), 'next_payment_timestamp' => $next_payment_timestamp, 'upgraded_or_downgraded' => '', ); @@ -1549,8 +1589,8 @@ class WC_Subscriptions_Switcher { wc_add_notice( __( 'There was an error locating the switch details.', 'woocommerce-subscriptions' ), 'error' ); WC()->cart->empty_cart( true ); - wp_safe_redirect( get_permalink( wc_get_page_id( 'cart' ) ) ); - exit(); + Request::redirect( get_permalink( wc_get_page_id( 'cart' ) ) ); + return; } } diff --git a/languages/woocommerce-subscriptions.pot b/languages/woocommerce-subscriptions.pot index 7acd38a..181fd07 100644 --- a/languages/woocommerce-subscriptions.pot +++ b/languages/woocommerce-subscriptions.pot @@ -1,15 +1,15 @@ -# Copyright (C) 2025 WooCommerce +# Copyright (C) 2026 WooCommerce # This file is distributed under the GNU General Public License v3.0. msgid "" msgstr "" -"Project-Id-Version: WooCommerce Subscriptions 8.2.1\n" +"Project-Id-Version: WooCommerce Subscriptions 8.3.0\n" "Report-Msgid-Bugs-To: https://woocommerce.com/contact-us\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: 2025-12-22T21:15:57+00:00\n" +"POT-Creation-Date: 2026-01-06T17:54:09+00:00\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "X-Generator: WP-CLI 2.12.0\n" "X-Domain: woocommerce-subscriptions\n" @@ -889,7 +889,7 @@ msgstr "" msgid "Order already has subscriptions associated with it." msgstr "" -#: includes/api/class-wc-rest-subscriptions-settings-option-controller.php:83 +#: includes/api/class-wc-rest-subscriptions-settings-option-controller.php:84 msgid "Invalid value type; must be either boolean or array" msgstr "" @@ -1123,26 +1123,26 @@ msgid "%1$sWooCommerce Subscriptions is inactive.%2$s This version of Subscripti msgstr "" #. translators: 1-2: opening/closing tags, 3: Subscriptions version. -#: includes/class-wc-subscriptions-plugin.php:70 +#: includes/class-wc-subscriptions-plugin.php:71 #, php-format msgid "%1$sWarning!%2$s We can see the %1$sWooCommerce Subscriptions Early Renewal%2$s plugin is active. Version %3$s of %1$sWooCommerce Subscriptions%2$s comes with that plugin's functionality packaged into the core plugin. Please deactivate WooCommerce Subscriptions Early Renewal to avoid any conflicts." msgstr "" -#: includes/class-wc-subscriptions-plugin.php:74 +#: includes/class-wc-subscriptions-plugin.php:75 msgid "Installed Plugins" msgstr "" #. translators: $1-$2: opening and closing tags, $3-$4: opening and closing tags. -#: includes/class-wc-subscriptions-plugin.php:216 +#: includes/class-wc-subscriptions-plugin.php:217 #, php-format msgid "%1$sWooCommerce Subscriptions Installed%2$s – %3$sYou're ready to start selling subscriptions!%4$s" msgstr "" -#: includes/class-wc-subscriptions-plugin.php:234 +#: includes/class-wc-subscriptions-plugin.php:235 msgid "Add a Subscription Product" msgstr "" -#: includes/class-wc-subscriptions-plugin.php:235 +#: includes/class-wc-subscriptions-plugin.php:236 #: includes/core/class-wc-subscriptions-core-plugin.php:580 #: includes/core/upgrades/templates/wcs-about-2-0.php:35 #: includes/core/upgrades/templates/wcs-about.php:34 @@ -1407,7 +1407,7 @@ msgid "Virtual" msgstr "" #: includes/core/admin/class-wc-subscriptions-admin.php:296 -#: templates/admin/html-variation-price.php:27 +#: templates/admin/html-variation-price.php:29 msgid "Choose the subscription price, billing interval and period." msgstr "" @@ -1421,7 +1421,7 @@ msgstr "" #. translators: %s: currency symbol. #. translators: placeholder is a currency symbol / code #: includes/core/admin/class-wc-subscriptions-admin.php:313 -#: templates/admin/html-variation-price.php:23 +#: templates/admin/html-variation-price.php:25 #, php-format msgid "Subscription price (%s)" msgstr "" @@ -1430,7 +1430,7 @@ msgstr "" #. translators: %s the formatted example price value. #: includes/core/admin/class-wc-subscriptions-admin.php:318 #: includes/core/admin/class-wc-subscriptions-admin.php:360 -#: templates/admin/html-variation-price.php:33 +#: templates/admin/html-variation-price.php:35 #, php-format msgctxt "example price" msgid "e.g. %s" @@ -1447,7 +1447,7 @@ msgstr "" #: includes/core/admin/class-wc-subscriptions-admin.php:344 #: includes/core/admin/class-wc-subscriptions-admin.php:516 -#: templates/admin/html-variation-price.php:53 +#: templates/admin/html-variation-price.php:55 msgid "Stop renewing after" msgstr "" @@ -1457,19 +1457,19 @@ msgstr "" #. translators: %s is a currency symbol / code #: includes/core/admin/class-wc-subscriptions-admin.php:358 -#: templates/admin/html-variation-price.php:69 +#: templates/admin/html-variation-price.php:71 #, php-format msgid "Sign-up fee (%s)" msgstr "" #: includes/core/admin/class-wc-subscriptions-admin.php:361 -#: templates/admin/html-variation-price.php:72 +#: templates/admin/html-variation-price.php:74 msgid "Optionally include an amount to be charged at the outset of the subscription. The sign-up fee will be charged immediately, even if the product has a free trial or the payment dates are synced." msgstr "" #: includes/core/admin/class-wc-subscriptions-admin.php:375 #: includes/core/class-wc-subscriptions-cart.php:2458 -#: templates/admin/html-variation-price.php:79 +#: templates/admin/html-variation-price.php:81 msgid "Free trial" msgstr "" @@ -1480,22 +1480,22 @@ msgstr "" #: includes/core/admin/class-wc-subscriptions-admin.php:403 #: includes/gifting/class-wcsg-admin.php:182 -#: templates/admin/html-variation-price.php:107 +#: templates/admin/html-variation-price.php:109 msgid "Gifting" msgstr "" #: includes/core/admin/class-wc-subscriptions-admin.php:407 -#: templates/admin/html-variation-price.php:117 +#: templates/admin/html-variation-price.php:119 msgid "Enabled" msgstr "" #: includes/core/admin/class-wc-subscriptions-admin.php:408 -#: templates/admin/html-variation-price.php:118 +#: templates/admin/html-variation-price.php:120 msgid "Disabled" msgstr "" #: includes/core/admin/class-wc-subscriptions-admin.php:411 -#: templates/admin/html-variation-price.php:110 +#: templates/admin/html-variation-price.php:112 msgid "Allow shoppers to purchase a subscription as a gift." msgstr "" @@ -3932,13 +3932,13 @@ msgid "Never (charge the full recurring amount at sign-up)" msgstr "" #: includes/core/class-wc-subscriptions-synchroniser.php:226 -#: includes/switching/class-wc-subscriptions-switcher.php:442 +#: includes/switching/class-wc-subscriptions-switcher.php:452 msgctxt "when to prorate first payment / subscription length" msgid "For Virtual Subscription Products Only" msgstr "" #: includes/core/class-wc-subscriptions-synchroniser.php:227 -#: includes/switching/class-wc-subscriptions-switcher.php:443 +#: includes/switching/class-wc-subscriptions-switcher.php:453 msgctxt "when to prorate first payment / subscription length" msgid "For All Subscription Products" msgstr "" @@ -5374,64 +5374,64 @@ msgstr "" msgid "Customers with a subscription are excluded from this setting." msgstr "" -#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:307 +#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:306 msgid "A database upgrade is required to use Subscriptions. Upgrades from the previously installed version is no longer supported. You will need to install an older version of WooCommerce Subscriptions or WooCommerce Payments to proceed with the upgrade before you can use a newer version." msgstr "" #. translators: 1-2: opening/closing tags, 3: active version of Subscriptions, 4: current version of Subscriptions, 5-6: opening/closing tags linked to ticket form, 7-8: opening/closing tags linked to documentation. -#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:369 +#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:368 #, php-format msgid "%1$sWarning!%2$s It appears that you have downgraded %1$sWooCommerce Subscriptions%2$s from %3$s to %4$s. Downgrading the plugin in this way may cause issues. Please update to %3$s or higher, or %5$sopen a new support ticket%6$s for further assistance. %7$sLearn more »%8$s" msgstr "" #. translators: placeholder is a list of version numbers (e.g. "1.3 & 1.4 & 1.5") -#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:508 +#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:507 #, php-format msgid "Database updated to version %s" msgstr "" #. translators: placeholder is number of upgraded subscriptions -#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:516 +#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:515 #, php-format msgctxt "used in the subscriptions upgrader" msgid "Marked %s subscription products as \"sold individually\"." msgstr "" #. translators: 1$: number of action scheduler hooks upgraded, 2$: "{execution_time}", will be replaced on front end with actual time -#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:525 +#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:524 #, php-format msgid "Migrated %1$s subscription related hooks to the new scheduler (in %2$s seconds)." msgstr "" #. translators: 1$: number of subscriptions upgraded, 2$: "{execution_time}", will be replaced on front end with actual time it took -#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:537 +#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:536 #, php-format msgid "Migrated %1$s subscriptions to the new structure (in %2$s seconds)." msgstr "" #. translators: placeholder is "{time_left}", will be replaced on front end with actual time -#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:540 -#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:586 +#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:539 +#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:585 #, php-format msgctxt "Message that gets sent to front end." msgid "Estimated time left (minutes:seconds): %s" msgstr "" #. translators: 1$: error message, 2$: opening link tag, 3$: closing link tag, 4$: break tag -#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:550 +#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:549 #, php-format msgid "Unable to upgrade subscriptions.%4$sError: %1$s%4$sPlease refresh the page and try again. If problem persists, %2$scontact support%3$s." msgstr "" #. translators: placeholder is the number of subscriptions repaired -#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:565 +#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:564 #, php-format msgctxt "Repair message that gets sent to front end." msgid "Repaired %d subscriptions with incorrect dates, line tax data or missing customer notes." msgstr "" #. translators: placeholder is number of subscriptions that were checked and did not need repairs. There's a space at the beginning! -#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:571 +#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:570 #, php-format msgctxt "Repair message that gets sent to front end." msgid " %d other subscription was checked and did not need any repairs." @@ -5440,36 +5440,36 @@ msgstr[0] "" msgstr[1] "" #. translators: placeholder is "{execution_time}", which will be replaced on front end with actual time -#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:575 +#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:574 #, php-format msgctxt "Repair message that gets sent to front end." msgid "(in %s seconds)" msgstr "" #. translators: $1: "Repaired x subs with incorrect dates...", $2: "X others were checked and no repair needed", $3: "(in X seconds)". Ordering for RTL languages. -#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:578 +#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:577 #, php-format msgctxt "The assembled repair message that gets sent to front end." msgid "%1$s%2$s %3$s" msgstr "" #. translators: 1$: error message, 2$: opening link tag, 3$: closing link tag, 4$: break tag -#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:597 +#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:596 #, php-format msgctxt "Error message that gets sent to front end when upgrading Subscriptions" msgid "Unable to repair subscriptions.%4$sError: %1$s%4$sPlease refresh the page and try again. If problem persists, %2$scontact support%3$s." msgstr "" -#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:805 +#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:804 msgid "Welcome to WooCommerce Subscriptions 2.1" msgstr "" -#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:805 +#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:804 msgid "About WooCommerce Subscriptions" msgstr "" #. translators: 1-2: opening/closing tags, 3-4: opening/closing tags linked to ticket form. -#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:1043 +#: includes/core/upgrades/class-wc-subscriptions-upgrader.php:1042 #, php-format msgid "%1$sWarning!%2$s We discovered an issue in %1$sWooCommerce Subscriptions 2.3.0 - 2.3.2%2$s that may cause your subscription renewal order and customer subscription caches to contain invalid data. For information about how to update the cached data, please %3$sopen a new support ticket%4$s." msgstr "" @@ -6457,35 +6457,53 @@ msgstr "" msgid "Available downloads" msgstr "" -#: includes/downloads/class-wc-subscription-downloads-products.php:66 -#: includes/downloads/class-wc-subscription-downloads-products.php:98 -msgid "Included subscription products" +#: includes/downloads/class-wc-subscription-downloads-products.php:216 +#: includes/downloads/class-wc-subscription-downloads-products.php:249 +msgid "Linked subscription products" msgstr "" -#: includes/downloads/class-wc-subscription-downloads-products.php:68 -#: includes/downloads/class-wc-subscription-downloads-products.php:101 +#: includes/downloads/class-wc-subscription-downloads-products.php:218 +#: includes/downloads/class-wc-subscription-downloads-products.php:252 msgid "Select subscriptions" msgstr "" -#: includes/downloads/class-wc-subscription-downloads-products.php:84 -#: includes/downloads/class-wc-subscription-downloads-products.php:99 +#: includes/downloads/class-wc-subscription-downloads-products.php:234 +#: includes/downloads/class-wc-subscription-downloads-products.php:250 msgid "Select subscription products that will include this downloadable product." msgstr "" -#: includes/downloads/class-wc-subscription-downloads-settings.php:41 +#: includes/downloads/class-wc-subscription-downloads-products.php:291 +msgid "Select simple and variable downloadable products that will be included with this subscription product." +msgstr "" + +#: includes/downloads/class-wc-subscription-downloads-products.php:292 +#: includes/downloads/class-wc-subscription-downloads-products.php:348 +msgid "Linked downloadable products" +msgstr "" + +#: includes/downloads/class-wc-subscription-downloads-products.php:295 +#: includes/downloads/class-wc-subscription-downloads-products.php:351 +msgid "Select products" +msgstr "" + +#: includes/downloads/class-wc-subscription-downloads-products.php:352 +msgid "Select simple and variable downloadable products that will be included with this subscription variation." +msgstr "" + +#: includes/downloads/class-wc-subscription-downloads-settings.php:36 msgid "WooCommerce Subscription Downloads is now part of WooCommerce Subscriptions — no extra plugin needed. You can deactivate and uninstall WooCommerce Subscription Downloads via the plugin admin screen." msgstr "" -#: includes/downloads/class-wc-subscription-downloads-settings.php:63 +#: includes/downloads/class-wc-subscription-downloads-settings.php:58 msgid "Downloads" msgstr "" -#: includes/downloads/class-wc-subscription-downloads-settings.php:68 -msgid "Enable product linking to subscriptions" +#: includes/downloads/class-wc-subscription-downloads-settings.php:63 +msgid "Enable downloadable file sharing" msgstr "" -#: includes/downloads/class-wc-subscription-downloads-settings.php:69 -msgid "Allow simple and variable downloadable products to be included with subscription products." +#: includes/downloads/class-wc-subscription-downloads-settings.php:64 +msgid "Allow downloadable files from simple and variable products to be shared with subscription products so they are available to active subscribers." msgstr "" #: includes/early-renewal/class-wcs-cart-early-renewal.php:74 @@ -7234,217 +7252,217 @@ msgstr "" msgid "Automatic renewal payment failed" msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:198 +#: includes/switching/class-wc-subscriptions-switcher.php:208 msgid "You have a subscription to this product. Choosing a new subscription will replace your existing subscription." msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:200 +#: includes/switching/class-wc-subscriptions-switcher.php:210 msgid "Choose a new subscription." msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:240 -#: includes/switching/class-wc-subscriptions-switcher.php:1231 +#: includes/switching/class-wc-subscriptions-switcher.php:250 +#: includes/switching/class-wc-subscriptions-switcher.php:1265 msgid "Your cart contained an invalid subscription switch request. It has been removed." msgid_plural "Your cart contained invalid subscription switch requests. They have been removed." msgstr[0] "" msgstr[1] "" -#: includes/switching/class-wc-subscriptions-switcher.php:282 +#: includes/switching/class-wc-subscriptions-switcher.php:292 msgid "You have already subscribed to this product and it is limited to one per customer. You can not purchase the product again." msgstr "" #. translators: 1$: is the "You have already subscribed to this product" notice, 2$-4$: opening/closing link tags, 3$: an order number -#: includes/switching/class-wc-subscriptions-switcher.php:291 +#: includes/switching/class-wc-subscriptions-switcher.php:301 #, php-format msgid "%1$s Complete payment on %2$sOrder %3$s%4$s to be able to change your subscription." msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:387 +#: includes/switching/class-wc-subscriptions-switcher.php:397 msgid "Switching" msgstr "" #. translators: placeholders are opening and closing link tags -#: includes/switching/class-wc-subscriptions-switcher.php:390 +#: includes/switching/class-wc-subscriptions-switcher.php:400 #, php-format msgid "Allow subscribers to switch (upgrade or downgrade) between different subscriptions. %1$sLearn more%2$s." msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:398 +#: includes/switching/class-wc-subscriptions-switcher.php:408 msgid "Prorate Recurring Payment" msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:399 +#: includes/switching/class-wc-subscriptions-switcher.php:409 msgid "When switching to a subscription with a different recurring payment or billing period, should the price paid for the existing billing period be prorated when switching to the new subscription?" msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:407 -#: includes/switching/class-wc-subscriptions-switcher.php:441 +#: includes/switching/class-wc-subscriptions-switcher.php:417 +#: includes/switching/class-wc-subscriptions-switcher.php:451 msgctxt "when to allow a setting" msgid "Never" msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:408 +#: includes/switching/class-wc-subscriptions-switcher.php:418 msgctxt "when to prorate recurring fee when switching" msgid "For Upgrades of Virtual Subscription Products Only" msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:409 +#: includes/switching/class-wc-subscriptions-switcher.php:419 msgctxt "when to prorate recurring fee when switching" msgid "For Upgrades of All Subscription Products" msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:410 +#: includes/switching/class-wc-subscriptions-switcher.php:420 msgctxt "when to prorate recurring fee when switching" msgid "For Upgrades & Downgrades of Virtual Subscription Products Only" msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:411 +#: includes/switching/class-wc-subscriptions-switcher.php:421 msgctxt "when to prorate recurring fee when switching" msgid "For Upgrades & Downgrades of All Subscription Products" msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:416 +#: includes/switching/class-wc-subscriptions-switcher.php:426 msgid "Prorate Sign up Fee" msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:417 +#: includes/switching/class-wc-subscriptions-switcher.php:427 msgid "When switching to a subscription with a sign up fee, you can require the customer pay only the gap between the existing subscription's sign up fee and the new subscription's sign up fee (if any)." msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:425 +#: includes/switching/class-wc-subscriptions-switcher.php:435 msgctxt "when to prorate signup fee when switching" msgid "Never (do not charge a sign up fee)" msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:426 +#: includes/switching/class-wc-subscriptions-switcher.php:436 msgctxt "when to prorate signup fee when switching" msgid "Never (charge the full sign up fee)" msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:427 +#: includes/switching/class-wc-subscriptions-switcher.php:437 msgctxt "when to prorate signup fee when switching" msgid "Always" msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:432 +#: includes/switching/class-wc-subscriptions-switcher.php:442 msgid "Prorate Subscription Length" msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:433 +#: includes/switching/class-wc-subscriptions-switcher.php:443 msgid "When switching to a subscription with a length, you can take into account the payments already completed by the customer when determining how many payments the subscriber needs to make for the new subscription." msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:448 +#: includes/switching/class-wc-subscriptions-switcher.php:458 msgid "Switch Button Text" msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:449 +#: includes/switching/class-wc-subscriptions-switcher.php:459 msgid "Customise the text displayed on the button next to the subscription on the subscriber's account page. The default is \"Switch Subscription\", but you may wish to change this to \"Upgrade\" or \"Change Subscription\"." msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:453 -#: includes/switching/class-wc-subscriptions-switcher.php:555 +#: includes/switching/class-wc-subscriptions-switcher.php:463 +#: includes/switching/class-wc-subscriptions-switcher.php:565 msgid "Upgrade or Downgrade" msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:492 +#: includes/switching/class-wc-subscriptions-switcher.php:502 msgid "Allow Switching" msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:499 +#: includes/switching/class-wc-subscriptions-switcher.php:509 msgctxt "when to allow switching" msgid "Between Subscription Variations" msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:503 +#: includes/switching/class-wc-subscriptions-switcher.php:513 msgctxt "when to allow switching" msgid "Between Grouped Subscriptions" msgstr "" #. translators: %s: order number. -#: includes/switching/class-wc-subscriptions-switcher.php:1165 +#: includes/switching/class-wc-subscriptions-switcher.php:1199 #, php-format msgid "Switch order cancelled due to a new switch order being created #%s." msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:1396 -#: includes/switching/class-wc-subscriptions-switcher.php:1478 +#: includes/switching/class-wc-subscriptions-switcher.php:1434 +#: includes/switching/class-wc-subscriptions-switcher.php:1518 msgid "The subscription may have been deleted." msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:1404 +#: includes/switching/class-wc-subscriptions-switcher.php:1442 msgid "You can only switch to a subscription product." msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:1410 +#: includes/switching/class-wc-subscriptions-switcher.php:1448 msgid "We can not find your old subscription item." msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:1432 +#: includes/switching/class-wc-subscriptions-switcher.php:1470 msgid "You can not switch to the same subscription." msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:1483 +#: includes/switching/class-wc-subscriptions-switcher.php:1523 msgid "You can not switch this subscription. It appears you do not own the subscription." msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:1550 +#: includes/switching/class-wc-subscriptions-switcher.php:1590 msgid "There was an error locating the switch details." msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:1899 +#: includes/switching/class-wc-subscriptions-switcher.php:1939 msgctxt "a switch type" msgid "Downgrade" msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:1902 +#: includes/switching/class-wc-subscriptions-switcher.php:1942 msgctxt "a switch type" msgid "Upgrade" msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:1905 +#: includes/switching/class-wc-subscriptions-switcher.php:1945 msgctxt "a switch type" msgid "Crossgrade" msgstr "" #. translators: %1: product subtotal, %2: HTML span tag, %3: direction (upgrade, downgrade, crossgrade), %4: closing HTML span tag -#: includes/switching/class-wc-subscriptions-switcher.php:1910 +#: includes/switching/class-wc-subscriptions-switcher.php:1950 #, php-format msgctxt "product subtotal string" msgid "%1$s %2$s(%3$s)%4$s" msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:2026 +#: includes/switching/class-wc-subscriptions-switcher.php:2066 msgid "The original subscription item being switched cannot be found." msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:2028 +#: includes/switching/class-wc-subscriptions-switcher.php:2068 msgid "The item on the switch order cannot be found." msgstr "" #. translators: 1$: old item, 2$: new item when switching -#: includes/switching/class-wc-subscriptions-switcher.php:2039 +#: includes/switching/class-wc-subscriptions-switcher.php:2079 #, php-format msgctxt "used in order notes" msgid "Customer switched from: %1$s to %2$s." msgstr "" #. translators: %s: new item name. -#: includes/switching/class-wc-subscriptions-switcher.php:2042 +#: includes/switching/class-wc-subscriptions-switcher.php:2082 #, php-format msgctxt "used in order notes" msgid "Customer added %s." msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:2454 +#: includes/switching/class-wc-subscriptions-switcher.php:2494 msgid "Switch Order" msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:2469 +#: includes/switching/class-wc-subscriptions-switcher.php:2509 msgid "Switched Subscription" msgstr "" -#: includes/switching/class-wc-subscriptions-switcher.php:2656 +#: includes/switching/class-wc-subscriptions-switcher.php:2696 msgctxt "add to cart button text while switching a subscription" msgid "Switch subscription" msgstr "" @@ -7507,7 +7525,7 @@ msgstr "" #. translators: placeholder is trial period validation message if passed an invalid value (e.g. "Trial period can not exceed 4 weeks") #: templates/admin/deprecated/html-variation-price.php:118 -#: templates/admin/html-variation-price.php:83 +#: templates/admin/html-variation-price.php:85 #, php-format msgctxt "Trial period dropdown's description in pricing fields" msgid "An optional period of time to wait before charging the first recurring payment. Any sign up fee will still be charged at the outset of the subscription. %s" @@ -7571,25 +7589,25 @@ msgstr[1] "" msgid "To see further details about these errors, view the %1$s log file from the %2$sWooCommerce logs screen.%2$s" msgstr "" -#: templates/admin/html-variation-price.php:35 +#: templates/admin/html-variation-price.php:37 msgid "Billing interval:" msgstr "" -#: templates/admin/html-variation-price.php:42 +#: templates/admin/html-variation-price.php:44 msgid "Billing Period:" msgstr "" -#: templates/admin/html-variation-price.php:56 +#: templates/admin/html-variation-price.php:58 msgctxt "Subscription Length dropdown's description in pricing fields" msgid "Automatically stop renewing the subscription after this length of time. This length is in addition to any free trial or amount of time provided before a synchronised first renewal date." msgstr "" -#: templates/admin/html-variation-price.php:75 +#: templates/admin/html-variation-price.php:77 msgctxt "example price" msgid "e.g." msgstr "" -#: templates/admin/html-variation-price.php:90 +#: templates/admin/html-variation-price.php:92 msgid "Subscription trial period:" msgstr "" @@ -8660,7 +8678,7 @@ msgstr "" msgid "Clear" msgstr "" -#: build/gifting-welcome-announcement.js:1 +#: build/admin.js:1 #: client/components/announcement/index.js:112 #: client/components/announcement/index.js:163 #: client/components/announcement/__tests__/index.test.js:118 @@ -8668,7 +8686,7 @@ msgstr "" msgid "Close" msgstr "" -#: build/gifting-welcome-announcement.js:1 +#: build/admin.js:1 #: client/components/announcement/index.js:131 #: client/components/announcement/__tests__/index.test.js:70 #: client/components/announcement/__tests__/index.test.js:95 @@ -8677,52 +8695,69 @@ msgstr "" msgid "Step image" msgstr "" -#: build/gifting-welcome-announcement.js:1 +#: build/admin.js:1 #: client/components/announcement/index.js:175 #: client/components/announcement/__tests__/index.test.js:115 msgid "Done" msgstr "" -#: build/gifting-welcome-announcement.js:1 -#: client/gifting/data/welcome-announcement.js:8 -msgid "Gifting is now part of WooCommerce Subscriptions" +#: build/admin.js:1 +#: client/downloads/data/welcome-announcement.js:7 +msgid "WooCommerce Subscription Downloads is now part of WooCommerce Subscriptions" msgstr "" -#: build/gifting-welcome-announcement.js:1 -#: client/gifting/data/welcome-announcement.js:12 -msgid "Introducing subscription gifting" +#: build/admin.js:1 +#: client/downloads/data/welcome-announcement.js:12 +msgid "No separate extension required! WooCommerce Subscriptions now allows you to include simple and variable products with your subscriptions. And to make it easier, you can now configure which simple and variable products to include when creating a subscription product." msgstr "" -#: build/gifting-welcome-announcement.js:1 -#: client/gifting/data/welcome-announcement.js:15 -msgid "No separate extension needed! The built-in gifting feature is fully compatible with product, cart and checkout blocks, plus you can now choose which subscription products can be gifted." +#: build/admin.js:1 +#: client/downloads/data/welcome-announcement.js:18 +msgid "The WooCommerce Subscription Downloads extension can now be disabled via Plugins." msgstr "" -#: build/gifting-welcome-announcement.js:1 -#: client/gifting/data/welcome-announcement.js:21 -msgid "The Gifting for WooCommerce Subscriptions extension can now be disabled via Plugins." -msgstr "" - -#: build/gifting-welcome-announcement.js:1 -#: client/gifting/data/welcome-announcement.js:26 -msgid "Let your shoppers purchase subscriptions as gifts using the new built-in gifting feature in WooCommerce Subscriptions. It works seamlessly with product, cart and checkout blocks, and can be enabled storewide or managed per product." -msgstr "" - -#: build/gifting-welcome-announcement.js:1 +#: build/admin.js:1 +#: client/downloads/data/welcome-announcement.js:24 #: client/gifting/data/welcome-announcement.js:33 msgid "Go to plugins" msgstr "" -#: build/gifting-welcome-announcement.js:1 -#: client/gifting/data/welcome-announcement.js:34 -msgid "Set up gifting" -msgstr "" - -#: build/gifting-welcome-announcement.js:1 +#: build/admin.js:1 +#: client/downloads/data/welcome-announcement.js:35 #: client/gifting/data/welcome-announcement.js:42 msgid "Maybe later" msgstr "" +#: build/admin.js:1 +#: client/gifting/data/welcome-announcement.js:8 +msgid "Gifting is now part of WooCommerce Subscriptions" +msgstr "" + +#: build/admin.js:1 +#: client/gifting/data/welcome-announcement.js:12 +msgid "Introducing subscription gifting" +msgstr "" + +#: build/admin.js:1 +#: client/gifting/data/welcome-announcement.js:15 +msgid "No separate extension needed! The built-in gifting feature is fully compatible with product, cart and checkout blocks, plus you can now choose which subscription products can be gifted." +msgstr "" + +#: build/admin.js:1 +#: client/gifting/data/welcome-announcement.js:21 +msgid "The Gifting for WooCommerce Subscriptions extension can now be disabled via Plugins." +msgstr "" + +#: build/admin.js:1 +#: client/gifting/data/welcome-announcement.js:26 +msgid "Let your shoppers purchase subscriptions as gifts using the new built-in gifting feature in WooCommerce Subscriptions. It works seamlessly with product, cart and checkout blocks, and can be enabled storewide or managed per product." +msgstr "" + +#: build/admin.js:1 +#: client/gifting/data/welcome-announcement.js:34 +msgid "Set up gifting" +msgstr "" + #: build/index.js:1 #: client/core/utils/index.js:8 msgctxt "Used in recurring totals section in Cart. 2+ will need plural, 1 will need singular." diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..06d563f --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,3717 @@ +parameters: + excludePaths: + analyse: + - includes/api/legacy/* + - includes/core/legacy/* + - includes/core/data-stores/class-wcs-orders-table-subscription-data-store.php + ignoreErrors: + - '#Constant WC_VERSION not found#' + - + message: "#^Function as_next_scheduled_action not found\\.$#" + count: 2 + path: includes/admin/reports/class-wcs-report-cache-manager.php + + - + message: "#^Function as_schedule_single_action not found\\.$#" + count: 2 + path: includes/admin/reports/class-wcs-report-cache-manager.php + + - + message: "#^Function as_unschedule_action not found\\.$#" + count: 1 + path: includes/admin/reports/class-wcs-report-cache-manager.php + + - + message: "#^Access to an undefined property WP_User\\:\\:\\$active_subscriptions\\.$#" + count: 1 + path: includes/admin/reports/class-wcs-report-subscription-by-customer.php + + - + message: "#^Access to an undefined property WP_User\\:\\:\\$customer_id\\.$#" + count: 4 + path: includes/admin/reports/class-wcs-report-subscription-by-customer.php + + - + message: "#^Access to an undefined property WP_User\\:\\:\\$initial_order_count\\.$#" + count: 1 + path: includes/admin/reports/class-wcs-report-subscription-by-customer.php + + - + message: "#^Access to an undefined property WP_User\\:\\:\\$initial_order_total\\.$#" + count: 1 + path: includes/admin/reports/class-wcs-report-subscription-by-customer.php + + - + message: "#^Access to an undefined property WP_User\\:\\:\\$renewal_switch_count\\.$#" + count: 1 + path: includes/admin/reports/class-wcs-report-subscription-by-customer.php + + - + message: "#^Access to an undefined property WP_User\\:\\:\\$renewal_switch_total\\.$#" + count: 1 + path: includes/admin/reports/class-wcs-report-subscription-by-customer.php + + - + message: "#^Access to an undefined property WP_User\\:\\:\\$total_subscriptions\\.$#" + count: 1 + path: includes/admin/reports/class-wcs-report-subscription-by-customer.php + + - + message: "#^Variable \\$this might not be defined\\.$#" + count: 1 + path: includes/admin/views/html-report-by-period.php + + - + message: "#^Call to an undefined method WC_Order_Item\\:\\:get_product\\(\\)\\.$#" + count: 3 + path: includes/api/class-wc-rest-subscriptions-controller.php + + - + message: "#^Call to an undefined method WC_Order_Item\\:\\:get_product\\(\\)\\.$#" + count: 1 + path: includes/api/v1/class-wc-rest-subscriptions-v1-controller.php + + - + message: "#^Call to an undefined method WC_Order_Item\\:\\:get_product_id\\(\\)\\.$#" + count: 1 + path: includes/api/v1/class-wc-rest-subscriptions-v1-controller.php + + - + message: "#^Call to an undefined method WC_Order_Item\\:\\:get_variation_id\\(\\)\\.$#" + count: 1 + path: includes/api/v1/class-wc-rest-subscriptions-v1-controller.php + + - + message: "#^Call to an undefined method WC_Order_Item\\:\\:get_product\\(\\)\\.$#" + count: 3 + path: includes/api/v2/class-wc-rest-subscriptions-v2-controller.php + + - + message: "#^Call to static method is_true\\(\\) on an unknown class Automattic\\\\Jetpack\\\\Constants\\.$#" + count: 1 + path: includes/class-wcs-api.php + + - + message: "#^Access to private property WooCommerce\\:\\:\\$api\\.$#" + count: 2 + path: includes/class-wcs-webhooks.php + + - + message: "#^Access to property \\$WC_API_Subscriptions on an unknown class WC_API\\.$#" + count: 2 + path: includes/class-wcs-webhooks.php + + - + message: "#^Function as_schedule_single_action not found\\.$#" + count: 1 + path: includes/core/abstracts/abstract-wcs-background-repairer.php + + - + message: "#^Function as_next_scheduled_action not found\\.$#" + count: 1 + path: includes/core/abstracts/abstract-wcs-background-updater.php + + - + message: "#^Function as_schedule_single_action not found\\.$#" + count: 1 + path: includes/core/abstracts/abstract-wcs-background-updater.php + + - + message: "#^Function as_unschedule_action not found\\.$#" + count: 1 + path: includes/core/abstracts/abstract-wcs-background-updater.php + + - + message: "#^Call to an undefined method WC_Data_Store\\:\\:get_order_type\\(\\)\\.$#" + count: 1 + path: includes/core/admin/class-wcs-admin-post-types.php + + - + message: "#^Call to an undefined method WC_Data_Store\\:\\:get_subscriptions_count_by_status\\(\\)\\.$#" + count: 1 + path: includes/core/admin/class-wcs-admin-post-types.php + + - + message: "#^Call to an undefined method WC_Data_Store\\:\\:untrash_order\\(\\)\\.$#" + count: 1 + path: includes/core/admin/class-wcs-admin-post-types.php + + - + message: "#^Class Automattic\\\\WooCommerce\\\\Internal\\\\DataStores\\\\Orders\\\\OrdersTableDataStore not found\\.$#" + count: 2 + path: includes/core/admin/class-wcs-admin-post-types.php + + - + message: "#^Access to an undefined property WooCommerce\\:\\:\\$payment_gateways\\.$#" + count: 2 + path: includes/core/admin/class-wcs-admin-system-status.php + + - + message: "#^Call to an undefined method WC_Data_Store\\:\\:get_subscriptions_count_by_status\\(\\)\\.$#" + count: 1 + path: includes/core/admin/class-wcs-admin-system-status.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$cart_contents_total\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-cart.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$coupon_discount_amounts\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-cart.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$dp\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-cart.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$end_date\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-cart.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$fee_total\\.$#" + count: 3 + path: includes/core/class-wc-subscriptions-cart.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$fees\\.$#" + count: 2 + path: includes/core/class-wc-subscriptions-cart.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$next_payment_date\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-cart.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$recurring_cart_key\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-cart.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$recurring_carts\\.$#" + count: 17 + path: includes/core/class-wc-subscriptions-cart.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$shipping_tax_total\\.$#" + count: 3 + path: includes/core/class-wc-subscriptions-cart.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$shipping_taxes\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-cart.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$shipping_total\\.$#" + count: 3 + path: includes/core/class-wc-subscriptions-cart.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$start_date\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-cart.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$tax_display_cart\\.$#" + count: 2 + path: includes/core/class-wc-subscriptions-cart.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$tax_total\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-cart.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$total\\.$#" + count: 2 + path: includes/core/class-wc-subscriptions-cart.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$trial_end_date\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-cart.php + + - + message: "#^Access to an undefined property WC_Checkout\\:\\:\\$shipping_methods\\.$#" + count: 2 + path: includes/core/class-wc-subscriptions-cart.php + + - + message: "#^Access to an undefined property WooCommerce\\:\\:\\$payment_gateways\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-cart.php + + - + message: "#^Access to an undefined property WooCommerce\\:\\:\\$shipping\\.$#" + count: 9 + path: includes/core/class-wc-subscriptions-cart.php + + - + message: "#^Access to an undefined property WooCommerce\\:\\:\\$payment_gateways\\.$#" + count: 2 + path: includes/core/class-wc-subscriptions-change-payment-gateway.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$end_date\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-checkout.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$next_payment_date\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-checkout.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$recurring_cart_key\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-checkout.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$recurring_carts\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-checkout.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$shipping_tax_total\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-checkout.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$shipping_taxes\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-checkout.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$shipping_total\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-checkout.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$start_date\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-checkout.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$tax_total\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-checkout.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$taxes\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-checkout.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$total\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-checkout.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$trial_end_date\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-checkout.php + + - + message: "#^Access to an undefined property WooCommerce\\:\\:\\$checkout\\.$#" + count: 2 + path: includes/core/class-wc-subscriptions-checkout.php + + - + message: "#^Access to an undefined property WooCommerce\\:\\:\\$payment_gateways\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-checkout.php + + - + message: "#^Access to an undefined property WooCommerce\\:\\:\\$shipping\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-checkout.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$coupon_discount_amounts\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-coupon.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$dp\\.$#" + count: 2 + path: includes/core/class-wc-subscriptions-coupon.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$subtotal\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-coupon.php + + - + message: "#^Access to an undefined property object\\:\\:\\$discount_cart\\.$#" + count: 6 + path: includes/core/class-wc-subscriptions-coupon.php + + - + message: "#^Call to an undefined method WC_Order_Item\\:\\:get_product\\(\\)\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-coupon.php + + - + message: "#^Function as_unschedule_all_actions not found\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-email-notifications.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$recurring_carts\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-extend-store-endpoint.php + + - + message: "#^Access to an undefined property WooCommerce\\:\\:\\$shipping\\.$#" + count: 2 + path: includes/core/class-wc-subscriptions-extend-store-endpoint.php + + - + message: "#^Call to an undefined method WC_Data_Store\\:\\:get_order_type\\(\\)\\.$#" + count: 5 + path: includes/core/class-wc-subscriptions-manager.php + + - + message: "#^Call to an undefined method WC_Data_Store\\:\\:untrash_order\\(\\)\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-manager.php + + - + message: "#^Call to an undefined method WC_Order_Item\\:\\:get_product\\(\\)\\.$#" + count: 2 + path: includes/core/class-wc-subscriptions-order.php + + - + message: "#^Call to method get\\(\\) on an unknown class OrdersTableQuery\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-order.php + + - + message: "#^Call to method get_table_name\\(\\) on an unknown class OrdersTableQuery\\.$#" + count: 4 + path: includes/core/class-wc-subscriptions-order.php + + - + message: "#^Cannot access property \\$order_custom_fields on bool\\|WC_Order\\|WC_Order_Refund\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-order.php + + - + message: "#^Parameter \\$order_query of method WC_Subscriptions_Order\\:\\:filter_orders_query_by_parent_orders\\(\\) has invalid type OrdersTableQuery\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-order.php + + - + message: "#^Call to an undefined method WC_Data_Store\\:\\:get_order_type\\(\\)\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-synchroniser.php + + - + message: "#^Call to an undefined method WC_Data_Store\\:\\:get_subscriptions_count_by_status\\(\\)\\.$#" + count: 1 + path: includes/core/class-wc-subscriptions-tracker.php + + - + message: "#^Function as_next_scheduled_action not found\\.$#" + count: 2 + path: includes/core/class-wcs-action-scheduler-customer-notifications.php + + - + message: "#^Function as_schedule_single_action not found\\.$#" + count: 1 + path: includes/core/class-wcs-action-scheduler-customer-notifications.php + + - + message: "#^Function as_unschedule_all_actions not found\\.$#" + count: 1 + path: includes/core/class-wcs-action-scheduler-customer-notifications.php + + - + message: "#^Call to static method instance\\(\\) on an unknown class ActionScheduler_Versions\\.$#" + count: 1 + path: includes/core/class-wcs-action-scheduler.php + + - + message: "#^Function as_next_scheduled_action not found\\.$#" + count: 3 + path: includes/core/class-wcs-action-scheduler.php + + - + message: "#^Function as_schedule_single_action not found\\.$#" + count: 2 + path: includes/core/class-wcs-action-scheduler.php + + - + message: "#^Function as_unschedule_all_actions not found\\.$#" + count: 1 + path: includes/core/class-wcs-action-scheduler.php + + - + message: "#^Function as_has_scheduled_action not found\\.$#" + count: 2 + path: includes/core/class-wcs-batch-processing-controller.php + + - + message: "#^Function as_schedule_single_action not found\\.$#" + count: 2 + path: includes/core/class-wcs-batch-processing-controller.php + + - + message: "#^Function as_unschedule_all_actions not found\\.$#" + count: 3 + path: includes/core/class-wcs-batch-processing-controller.php + + - + message: "#^Call to an undefined method WC_Data_Store\\:\\:get_order_type\\(\\)\\.$#" + count: 3 + path: includes/core/class-wcs-cached-data-manager.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$cart_contents_count\\.$#" + count: 1 + path: includes/core/class-wcs-cart-renewal.php + + - + message: "#^Access to an undefined property WC_Session\\:\\:\\$cart\\.$#" + count: 1 + path: includes/core/class-wcs-cart-renewal.php + + - + message: "#^Access to an undefined property WC_Session\\:\\:\\$order_awaiting_payment\\.$#" + count: 1 + path: includes/core/class-wcs-cart-renewal.php + + - + message: "#^Call to an undefined method WC_Data_Store\\:\\:get_order_type\\(\\)\\.$#" + count: 1 + path: includes/core/class-wcs-cart-renewal.php + + - + message: "#^Call to an undefined method WC_Order_Item\\:\\:get_product_id\\(\\)\\.$#" + count: 1 + path: includes/core/class-wcs-cart-renewal.php + + - + message: "#^Call to an undefined method WC_Order_Item\\:\\:get_variation_id\\(\\)\\.$#" + count: 1 + path: includes/core/class-wcs-cart-renewal.php + + - + message: "#^Call to an undefined method WC_Session\\:\\:destroy_session\\(\\)\\.$#" + count: 3 + path: includes/core/class-wcs-cart-renewal.php + + - + message: "#^Access to an undefined property WooCommerce\\:\\:\\$payment_gateways\\.$#" + count: 2 + path: includes/core/class-wcs-change-payment-method-admin.php + + - + message: "#^Call to an undefined method WC_Data_Store\\:\\:get_order_type\\(\\)\\.$#" + count: 2 + path: includes/core/class-wcs-download-handler.php + + - + message: "#^Call to an undefined method WC_Order_Item\\:\\:get_product\\(\\)\\.$#" + count: 1 + path: includes/core/class-wcs-download-handler.php + + - + message: "#^Call to method get_args\\(\\) on an unknown class ActionScheduler_Action\\.$#" + count: 2 + path: includes/core/class-wcs-failed-scheduled-action-manager.php + + - + message: "#^Call to method get_hook\\(\\) on an unknown class ActionScheduler_Action\\.$#" + count: 3 + path: includes/core/class-wcs-failed-scheduled-action-manager.php + + - + message: "#^Call to static method instance\\(\\) on an unknown class ActionScheduler_Logger\\.$#" + count: 1 + path: includes/core/class-wcs-failed-scheduled-action-manager.php + + - + message: "#^Call to static method instance\\(\\) on an unknown class ActionScheduler_Store\\.$#" + count: 1 + path: includes/core/class-wcs-failed-scheduled-action-manager.php + + - + message: "#^Method WCS_Failed_Scheduled_Action_Manager\\:\\:get_action\\(\\) has invalid return type ActionScheduler_Action\\.$#" + count: 1 + path: includes/core/class-wcs-failed-scheduled-action-manager.php + + - + message: "#^Parameter \\$action of method WCS_Failed_Scheduled_Action_Manager\\:\\:get_context_from_action_error\\(\\) has invalid type ActionScheduler_Action\\.$#" + count: 1 + path: includes/core/class-wcs-failed-scheduled-action-manager.php + + - + message: "#^Call to an undefined method WC_Order_Item\\:\\:get_product\\(\\)\\.$#" + count: 1 + path: includes/core/class-wcs-limiter.php + + - + message: "#^Access to an undefined property object\\:\\:\\$value\\.$#" + count: 2 + path: includes/core/class-wcs-object-data-cache-manager.php + + - + message: "#^Call to an undefined method object\\:\\:get_changes\\(\\)\\.$#" + count: 1 + path: includes/core/class-wcs-object-data-cache-manager.php + + - + message: "#^Call to an undefined method WC_Order_Item\\:\\:get_product\\(\\)\\.$#" + count: 1 + path: includes/core/class-wcs-remove-item.php + + - + message: "#^Call to an undefined method WC_Order_Item\\:\\:get_product\\(\\)\\.$#" + count: 1 + path: includes/core/class-wcs-renewal-cart-stock-manager.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$tax_display_cart\\.$#" + count: 1 + path: includes/core/class-wcs-template-loader.php + + - + message: "#^Access to static property \\$template_path on an unknown class PP_One_Page_Checkout\\.$#" + count: 1 + path: includes/core/class-wcs-template-loader.php + + - + message: "#^Array has 2 duplicate keys with value 'admin\\-new\\-renewal\\-order\\.php' \\('admin\\-new\\-renewal\\-order\\.php', 'admin\\-new\\-renewal\\-order\\.php'\\)\\.$#" + count: 1 + path: includes/core/class-wcs-template-loader.php + + - + message: "#^Array has 2 duplicate keys with value 'admin\\-new\\-switch\\-order\\.php' \\('admin\\-new\\-switch\\-order\\.php', 'admin\\-new\\-switch\\-order\\.php'\\)\\.$#" + count: 1 + path: includes/core/class-wcs-template-loader.php + + - + message: "#^Array has 2 duplicate keys with value 'admin\\-payment\\-retry\\.php' \\('admin\\-payment\\-retry\\.php', 'admin\\-payment\\-retry\\.php'\\)\\.$#" + count: 1 + path: includes/core/class-wcs-template-loader.php + + - + message: "#^Array has 2 duplicate keys with value 'cancelled\\-subscription\\.php' \\('cancelled\\-subscription\\.php', 'cancelled\\-subscription\\.php'\\)\\.$#" + count: 1 + path: includes/core/class-wcs-template-loader.php + + - + message: "#^Array has 2 duplicate keys with value 'customer\\-completed\\-renewal\\-order\\.php' \\('customer\\-completed\\-renewal\\-order\\.php', 'customer\\-completed\\-renewal\\-order\\.php'\\)\\.$#" + count: 1 + path: includes/core/class-wcs-template-loader.php + + - + message: "#^Array has 2 duplicate keys with value 'customer\\-completed\\-switch\\-order\\.php' \\('customer\\-completed\\-switch\\-order\\.php', 'customer\\-completed\\-switch\\-order\\.php'\\)\\.$#" + count: 1 + path: includes/core/class-wcs-template-loader.php + + - + message: "#^Array has 2 duplicate keys with value 'customer\\-on\\-hold\\-renewal\\-order\\.php' \\('customer\\-on\\-hold\\-renewal\\-order\\.php', 'customer\\-on\\-hold\\-renewal\\-order\\.php'\\)\\.$#" + count: 1 + path: includes/core/class-wcs-template-loader.php + + - + message: "#^Array has 2 duplicate keys with value 'customer\\-payment\\-retry\\.php' \\('customer\\-payment\\-retry\\.php', 'customer\\-payment\\-retry\\.php'\\)\\.$#" + count: 1 + path: includes/core/class-wcs-template-loader.php + + - + message: "#^Array has 2 duplicate keys with value 'customer\\-processing\\-renewal\\-order\\.php' \\('customer\\-processing\\-renewal\\-order\\.php', 'customer\\-processing\\-renewal\\-order\\.php'\\)\\.$#" + count: 1 + path: includes/core/class-wcs-template-loader.php + + - + message: "#^Array has 2 duplicate keys with value 'customer\\-renewal\\-invoice\\.php' \\('customer\\-renewal\\-invoice\\.php', 'customer\\-renewal\\-invoice\\.php'\\)\\.$#" + count: 1 + path: includes/core/class-wcs-template-loader.php + + - + message: "#^Array has 2 duplicate keys with value 'email\\-order\\-details\\.php' \\('email\\-order\\-details\\.php', 'email\\-order\\-details\\.php'\\)\\.$#" + count: 1 + path: includes/core/class-wcs-template-loader.php + + - + message: "#^Array has 2 duplicate keys with value 'expired\\-subscription\\.php' \\('expired\\-subscription\\.php', 'expired\\-subscription\\.php'\\)\\.$#" + count: 1 + path: includes/core/class-wcs-template-loader.php + + - + message: "#^Array has 2 duplicate keys with value 'on\\-hold\\-subscription\\.php' \\('on\\-hold\\-subscription\\.php', 'on\\-hold\\-subscription\\.php'\\)\\.$#" + count: 1 + path: includes/core/class-wcs-template-loader.php + + - + message: "#^Array has 2 duplicate keys with value 'subscription\\-info\\.php' \\('subscription\\-info\\.php', 'subscription\\-info\\.php'\\)\\.$#" + count: 1 + path: includes/core/class-wcs-template-loader.php + + - + message: "#^Binary operation \"\\.\" between non\\-falsy\\-string and array results in an error\\.$#" + count: 1 + path: includes/core/class-wcs-template-loader.php + + - + message: "#^Call to an undefined method WCS_Orders_Table_Subscription_Data_Store\\:\\:init\\(\\)\\.$#" + count: 1 + path: includes/core/data-stores/class-wcs-orders-table-data-store-controller.php + + - + message: "#^Class Automattic\\\\WooCommerce\\\\Internal\\\\DataStores\\\\Orders\\\\OrdersTableDataStoreMeta not found\\.$#" + count: 1 + path: includes/core/data-stores/class-wcs-orders-table-data-store-controller.php + + - + message: "#^Class Automattic\\\\WooCommerce\\\\Internal\\\\Utilities\\\\DatabaseUtil not found\\.$#" + count: 1 + path: includes/core/data-stores/class-wcs-orders-table-data-store-controller.php + + - + message: "#^Access to an undefined property WCS_Orders_Table_Subscription_Data_Store\\:\\:\\$data_store_meta\\.$#" + count: 6 + path: includes/core/data-stores/class-wcs-orders-table-subscription-data-store.php + + - + message: "#^Access to an undefined property WCS_Orders_Table_Subscription_Data_Store\\:\\:\\$internal_meta_keys\\.$#" + count: 3 + path: includes/core/data-stores/class-wcs-orders-table-subscription-data-store.php + + - + message: "#^Call to an undefined method WCS_Orders_Table_Subscription_Data_Store\\:\\:clear_caches\\(\\)\\.$#" + count: 2 + path: includes/core/data-stores/class-wcs-orders-table-subscription-data-store.php + + - + message: "#^Call to an undefined method WCS_Orders_Table_Subscription_Data_Store\\:\\:delete_order_data_from_custom_order_tables\\(\\)\\.$#" + count: 1 + path: includes/core/data-stores/class-wcs-orders-table-subscription-data-store.php + + - + message: "#^Call to an undefined method WCS_Orders_Table_Subscription_Data_Store\\:\\:get_cpt_data_store_instance\\(\\)\\.$#" + count: 1 + path: includes/core/data-stores/class-wcs-orders-table-subscription-data-store.php + + - + message: "#^Call to an undefined method WCS_Orders_Table_Subscription_Data_Store\\:\\:get_props_to_update\\(\\)\\.$#" + count: 2 + path: includes/core/data-stores/class-wcs-orders-table-subscription-data-store.php + + - + message: "#^Call to an undefined method WCS_Orders_Table_Subscription_Data_Store\\:\\:persist_updates\\(\\)\\.$#" + count: 1 + path: includes/core/data-stores/class-wcs-orders-table-subscription-data-store.php + + - + message: "#^Call to an undefined method WCS_Orders_Table_Subscription_Data_Store\\:\\:trash_order\\(\\)\\.$#" + count: 1 + path: includes/core/data-stores/class-wcs-orders-table-subscription-data-store.php + + - + message: "#^Call to an undefined method WC_Data_Store\\:\\:update_user_by_order_id\\(\\)\\.$#" + count: 1 + path: includes/core/data-stores/class-wcs-orders-table-subscription-data-store.php + + - + message: "#^Call to an undefined static method WCS_Orders_Table_Subscription_Data_Store\\:\\:get_meta_table_name\\(\\)\\.$#" + count: 1 + path: includes/core/data-stores/class-wcs-orders-table-subscription-data-store.php + + - + message: "#^Call to an undefined static method WCS_Orders_Table_Subscription_Data_Store\\:\\:get_orders_table_name\\(\\)\\.$#" + count: 4 + path: includes/core/data-stores/class-wcs-orders-table-subscription-data-store.php + + - + message: "#^Call to static method get_constant\\(\\) on an unknown class Automattic\\\\Jetpack\\\\Constants\\.$#" + count: 1 + path: includes/core/data-stores/class-wcs-orders-table-subscription-data-store.php + + - + message: "#^Class Automattic\\\\WooCommerce\\\\Internal\\\\DataStores\\\\Orders\\\\DataSynchronizer not found\\.$#" + count: 2 + path: includes/core/data-stores/class-wcs-orders-table-subscription-data-store.php + + - + message: "#^WCS_Orders_Table_Subscription_Data_Store\\:\\:create\\(\\) calls parent\\:\\:create\\(\\) but WCS_Orders_Table_Subscription_Data_Store does not extend any class\\.$#" + count: 1 + path: includes/core/data-stores/class-wcs-orders-table-subscription-data-store.php + + - + message: "#^WCS_Orders_Table_Subscription_Data_Store\\:\\:get_total_refunded\\(\\) calls parent\\:\\:get_total_refunded\\(\\) but WCS_Orders_Table_Subscription_Data_Store does not extend any class\\.$#" + count: 1 + path: includes/core/data-stores/class-wcs-orders-table-subscription-data-store.php + + - + message: "#^WCS_Orders_Table_Subscription_Data_Store\\:\\:get_total_shipping_refunded\\(\\) calls parent\\:\\:get_total_shipping_refunded\\(\\) but WCS_Orders_Table_Subscription_Data_Store does not extend any class\\.$#" + count: 1 + path: includes/core/data-stores/class-wcs-orders-table-subscription-data-store.php + + - + message: "#^WCS_Orders_Table_Subscription_Data_Store\\:\\:get_total_tax_refunded\\(\\) calls parent\\:\\:get_total_tax_refunded\\(\\) but WCS_Orders_Table_Subscription_Data_Store does not extend any class\\.$#" + count: 1 + path: includes/core/data-stores/class-wcs-orders-table-subscription-data-store.php + + - + message: "#^WCS_Orders_Table_Subscription_Data_Store\\:\\:init_order_record\\(\\) calls parent\\:\\:init_order_record\\(\\) but WCS_Orders_Table_Subscription_Data_Store does not extend any class\\.$#" + count: 1 + path: includes/core/data-stores/class-wcs-orders-table-subscription-data-store.php + + - + message: "#^WCS_Orders_Table_Subscription_Data_Store\\:\\:persist_order_to_db\\(\\) calls parent\\:\\:persist_order_to_db\\(\\) but WCS_Orders_Table_Subscription_Data_Store does not extend any class\\.$#" + count: 1 + path: includes/core/data-stores/class-wcs-orders-table-subscription-data-store.php + + - + message: "#^Call to an undefined method WC_Data_Store\\:\\:delete_all_metadata_by_key\\(\\)\\.$#" + count: 1 + path: includes/core/data-stores/class-wcs-related-order-store-cached-cpt.php + + - + message: "#^Access to an undefined static property WC_Subscriptions_Deprecation_Handler\\:\\:\\$version\\.$#" + count: 2 + path: includes/core/deprecated/deprecation-handlers/class-wc-subscriptions-deprecation-handler.php + + - + message: "#^Call to an undefined method WC_Data_Store\\:\\:get_subscriptions_count_by_status\\(\\)\\.$#" + count: 1 + path: includes/core/deprecated/deprecation-handlers/class-wc-subscriptions-deprecation-handler.php + + - + message: "#^Access to an undefined property WC_Email\\:\\:\\$retry\\.$#" + count: 2 + path: includes/core/emails/class-wc-subscriptions-email-preview.php + + - + message: "#^Access to an undefined property WC_Email\\:\\:\\$subscriptions\\.$#" + count: 2 + path: includes/core/emails/class-wc-subscriptions-email-preview.php + + - + message: "#^Call to an undefined method WC_Email\\:\\:get_time_until_date\\(\\)\\.$#" + count: 1 + path: includes/core/emails/class-wc-subscriptions-email-preview.php + + - + message: "#^Call to an undefined method WCS_Email_Customer_Notification\\:\\:get_relevant_date_type\\(\\)\\.$#" + count: 4 + path: includes/core/emails/class-wcs-email-customer-notification.php + + - + message: "#^Cannot call method get_customer_id\\(\\) on bool\\|object\\.$#" + count: 2 + path: includes/core/emails/class-wcs-email-customer-notification.php + + - + message: "#^Cannot call method get_parent\\(\\) on bool\\|object\\.$#" + count: 2 + path: includes/core/emails/class-wcs-email-customer-notification.php + + - + message: "#^Cannot call method get_view_order_url\\(\\) on bool\\|object\\.$#" + count: 2 + path: includes/core/emails/class-wcs-email-customer-notification.php + + - + message: "#^Cannot call method payment_method_supports\\(\\) on bool\\|object\\.$#" + count: 2 + path: includes/core/emails/class-wcs-email-customer-notification.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$recurring_carts\\.$#" + count: 1 + path: includes/core/gateways/class-wc-subscriptions-core-payment-gateways.php + + - + message: "#^Access to an undefined property WooCommerce\\:\\:\\$payment_gateways\\.$#" + count: 2 + path: includes/core/gateways/class-wc-subscriptions-core-payment-gateways.php + + - + message: "#^Access to property \\$id on an unknown class WC_Gateway\\.$#" + count: 2 + path: includes/core/gateways/class-wc-subscriptions-core-payment-gateways.php + + - + message: "#^Class WC_Payments_Subscription_Service not found\\.$#" + count: 1 + path: includes/core/gateways/class-wc-subscriptions-core-payment-gateways.php + + - + message: "#^Parameter \\$gateway of method WC_Subscriptions_Core_Payment_Gateways\\:\\:gateway_supports_subscriptions\\(\\) has invalid type WC_Gateway\\.$#" + count: 1 + path: includes/core/gateways/class-wc-subscriptions-core-payment-gateways.php + + - + message: "#^Access to an undefined property WooCommerce\\:\\:\\$payment_gateways\\.$#" + count: 2 + path: includes/core/gateways/paypal/class-wcs-paypal.php + + - + message: "#^Call to method are_reference_transactions_enabled\\(\\) on an unknown class WCS_PayPal_Express_API\\.$#" + count: 1 + path: includes/core/gateways/paypal/class-wcs-paypal.php + + - + message: "#^Call to method create_billing_agreement\\(\\) on an unknown class WCS_PayPal_Express_API\\.$#" + count: 1 + path: includes/core/gateways/paypal/class-wcs-paypal.php + + - + message: "#^Call to method do_express_checkout\\(\\) on an unknown class WCS_PayPal_Express_API\\.$#" + count: 1 + path: includes/core/gateways/paypal/class-wcs-paypal.php + + - + message: "#^Call to method do_reference_transaction\\(\\) on an unknown class WCS_PayPal_Express_API\\.$#" + count: 1 + path: includes/core/gateways/paypal/class-wcs-paypal.php + + - + message: "#^Call to method get_express_checkout_details\\(\\) on an unknown class WCS_PayPal_Express_API\\.$#" + count: 1 + path: includes/core/gateways/paypal/class-wcs-paypal.php + + - + message: "#^Call to method get_paypal_args\\(\\) on an unknown class WCS_PayPal_Express_API\\.$#" + count: 1 + path: includes/core/gateways/paypal/class-wcs-paypal.php + + - + message: "#^Call to method get_transaction_types\\(\\) on an unknown class WC_PayPal_Express_API\\.$#" + count: 4 + path: includes/core/gateways/paypal/class-wcs-paypal.php + + - + message: "#^Call to method valid_response\\(\\) on an unknown class WC_PayPal_Express_API\\.$#" + count: 2 + path: includes/core/gateways/paypal/class-wcs-paypal.php + + - + message: "#^Class WCS_PayPal_Reference_Transaction_IPN_Handler referenced with incorrect case\\: WCS_Paypal_Reference_Transaction_IPN_Handler\\.$#" + count: 1 + path: includes/core/gateways/paypal/class-wcs-paypal.php + + - + message: "#^Class WCS_PayPal_Standard_IPN_Handler referenced with incorrect case\\: WCS_Paypal_Standard_IPN_Handler\\.$#" + count: 1 + path: includes/core/gateways/paypal/class-wcs-paypal.php + + - + message: "#^Method WCS_PayPal\\:\\:get_api\\(\\) has invalid return type WCS_PayPal_Express_API\\.$#" + count: 1 + path: includes/core/gateways/paypal/class-wcs-paypal.php + + - + message: "#^Method WCS_PayPal\\:\\:get_ipn_handler\\(\\) has invalid return type WC_PayPal_Express_API\\.$#" + count: 1 + path: includes/core/gateways/paypal/class-wcs-paypal.php + + - + message: "#^Property WCS_PayPal\\:\\:\\$api has unknown class WCS_PayPal_Express_API as its type\\.$#" + count: 1 + path: includes/core/gateways/paypal/class-wcs-paypal.php + + - + message: "#^Call to method get_id\\(\\) on an unknown class SV_WC_Plugin\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/abstracts/abstract-wcs-sv-api-base.php + + - + message: "#^Call to method get_plugin_name\\(\\) on an unknown class SV_WC_Plugin\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/abstracts/abstract-wcs-sv-api-base.php + + - + message: "#^Call to method get_version\\(\\) on an unknown class SV_WC_Plugin\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/abstracts/abstract-wcs-sv-api-base.php + + - + message: "#^Method WCS_SV_API_Base\\:\\:get_new_request\\(\\) has invalid return type SV_WC_API_Request\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/abstracts/abstract-wcs-sv-api-base.php + + - + message: "#^Method WCS_SV_API_Base\\:\\:get_plugin\\(\\) has invalid return type SV_WC_Plugin\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/abstracts/abstract-wcs-sv-api-base.php + + - + message: "#^Method WCS_SV_API_Base\\:\\:set_request_header\\(\\) should return string but return statement is missing\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/abstracts/abstract-wcs-sv-api-base.php + + - + message: "#^Method WCS_SV_API_Base\\:\\:set_response_handler\\(\\) should return array but return statement is missing\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/abstracts/abstract-wcs-sv-api-base.php + + - + message: "#^Access to an undefined property WooCommerce\\:\\:\\$payment_gateways\\.$#" + count: 4 + path: includes/core/gateways/paypal/includes/admin/class-wcs-paypal-admin.php + + - + message: "#^Action callback returns array but should not return anything\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/admin/class-wcs-paypal-admin.php + + - + message: "#^Method WCS_PayPal_Change_Payment_Method_Admin\\:\\:validate_payment_meta\\(\\) should return array but return statement is missing\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/admin/class-wcs-paypal-change-payment-method-admin.php + + - + message: "#^PHPDoc tag @param references unknown parameter\\: \\$payment_method_id$#" + count: 1 + path: includes/core/gateways/paypal/includes/admin/class-wcs-paypal-change-payment-method-admin.php + + - + message: "#^@param WC_PayPal_Reference_Transaction_API_Request \\$instance does not accept actual type of parameter\\: \\$this\\(WCS_PayPal_Reference_Transaction_API_Request\\)\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-reference-transaction-api-request.php + + - + message: "#^Binary operation \"\\+\" between float and string results in an error\\.$#" + count: 3 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-reference-transaction-api-request.php + + - + message: "#^Method WCS_PayPal_Reference_Transaction_API_Request\\:\\:get_method\\(\\) should return null but return statement is missing\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-reference-transaction-api-request.php + + - + message: "#^PHPDoc tag @param references unknown parameter\\: \\$type$#" + count: 1 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-reference-transaction-api-request.php + + - + message: "#^PHPDoc tag @param references unknown parameter\\: \\$response$#" + count: 1 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-reference-transaction-api-response.php + + - + message: "#^Access to an undefined property WCS_PayPal_Reference_Transaction_API\\:\\:\\$order\\.$#" + count: 3 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-reference-transaction-api.php + + - + message: "#^Call to method create_billing_agreement\\(\\) on an unknown class WC_PayPal_Reference_Transaction_API_Request\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-reference-transaction-api.php + + - + message: "#^Call to method do_express_checkout\\(\\) on an unknown class WC_PayPal_Reference_Transaction_API_Request\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-reference-transaction-api.php + + - + message: "#^Call to method do_reference_transaction\\(\\) on an unknown class WC_PayPal_Reference_Transaction_API_Request\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-reference-transaction-api.php + + - + message: "#^Call to method get_express_checkout_details\\(\\) on an unknown class WC_PayPal_Reference_Transaction_API_Request\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-reference-transaction-api.php + + - + message: "#^Call to method manage_recurring_payments_profile_status\\(\\) on an unknown class WC_PayPal_Reference_Transaction_API_Request\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-reference-transaction-api.php + + - + message: "#^Call to method set_express_checkout\\(\\) on an unknown class WC_PayPal_Reference_Transaction_API_Request\\.$#" + count: 2 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-reference-transaction-api.php + + - + message: "#^Method WCS_PayPal_Reference_Transaction_API\\:\\:do_reference_transaction\\(\\) has invalid return type SV_WC_Payment_Gateway_API_Response\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-reference-transaction-api.php + + - + message: "#^Method WCS_PayPal_Reference_Transaction_API\\:\\:get_express_checkout_details\\(\\) has invalid return type WC_PayPal_Reference_Transaction_API_Checkout_Response\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-reference-transaction-api.php + + - + message: "#^Method WCS_PayPal_Reference_Transaction_API\\:\\:get_new_request\\(\\) has invalid return type WC_PayPal_Reference_Transaction_API_Request\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-reference-transaction-api.php + + - + message: "#^Method WCS_PayPal_Reference_Transaction_API\\:\\:manage_recurring_payments_profile_status\\(\\) has invalid return type SV_WC_Payment_Gateway_API_Response\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-reference-transaction-api.php + + - + message: "#^PHPDoc tag @throws with type SV_WC_Payment_Gateway_Exception is not subtype of Throwable$#" + count: 2 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-reference-transaction-api.php + + - + message: "#^PHPDoc tag @param references unknown parameter\\: \\$posted$#" + count: 1 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-reference-transaction-ipn-handler.php + + - + message: "#^PHPDoc tag @param references unknown parameter\\: \\$item_name$#" + count: 1 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-standard-change-payment-method.php + + - + message: "#^Default value of the parameter \\#2 \\$error \\(string\\) of method WCS_PayPal_Standard_IPN_Failure_Handler\\:\\:log_ipn_errors\\(\\) is incompatible with type array\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-standard-ipn-failure-handler.php + + - + message: "#^Access to an undefined property WooCommerce\\:\\:\\$payment_gateways\\.$#" + count: 2 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-standard-ipn-handler.php + + - + message: "#^Access to an undefined property object\\:\\:\\$subscription_key\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-standard-ipn-handler.php + + - + message: "#^Binary operation \"\\-\" between string and 1 results in an error\\.$#" + count: 2 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-standard-ipn-handler.php + + - + message: "#^Undefined variable\\: \\$ipn_id$#" + count: 1 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-standard-ipn-handler.php + + - + message: "#^Variable \\$ipn_id in empty\\(\\) is never defined\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-standard-ipn-handler.php + + - + message: "#^Variable \\$ipn_id in isset\\(\\) is never defined\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-standard-ipn-handler.php + + - + message: "#^Variable \\$ipn_transaction_id might not be defined\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-standard-ipn-handler.php + + - + message: "#^Variable \\$transaction_order might not be defined\\.$#" + count: 4 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-standard-ipn-handler.php + + - + message: "#^Variable \\$item_names might not be defined\\.$#" + count: 2 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-standard-request.php + + - + message: "#^Variable \\$next_payment_timestamp in empty\\(\\) always exists and is not falsy\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-standard-request.php + + - + message: "#^Variable \\$second_trial_period might not be defined\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-standard-request.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$total\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-standard-switcher.php + + - + message: "#^Access to an undefined property WooCommerce\\:\\:\\$payment_gateways\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-standard-switcher.php + + - + message: "#^Call to method manage_recurring_payments_profile_status\\(\\) on an unknown class WCS_PayPal_Express_API\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/class-wcs-paypal-status-manager.php + + - + message: "#^Binary operation \"\\.\\=\" between array and ' AND `meta_key` NOT…' results in an error\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/deprecated/class-wc-paypal-standard-subscriptions.php + + - + message: "#^Call to an undefined static method WCS_PayPal_Supports\\:\\:add_feature_support\\(\\)\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/deprecated/class-wc-paypal-standard-subscriptions.php + + - + message: "#^Call to method manage_recurring_payments_profile_status\\(\\) on an unknown class WCS_PayPal_Express_API\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/deprecated/class-wc-paypal-standard-subscriptions.php + + - + message: "#^Class WCS_PayPal_Standard_IPN_Handler referenced with incorrect case\\: WCS_Paypal_Standard_IPN_Handler\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/deprecated/class-wc-paypal-standard-subscriptions.php + + - + message: "#^PHPDoc tag @param references unknown parameter\\: \\$item_name$#" + count: 1 + path: includes/core/gateways/paypal/includes/deprecated/class-wc-paypal-standard-subscriptions.php + + - + message: "#^Variable \\$notices might not be defined\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/templates/admin-notices.php + + - + message: "#^Variable \\$failed_ipn_log_handle might not be defined\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/templates/html-ipn-failure-notice.php + + - + message: "#^Variable \\$log_file_url might not be defined\\.$#" + count: 1 + path: includes/core/gateways/paypal/includes/templates/html-ipn-failure-notice.php + + - + message: "#^Function as_next_scheduled_action not found\\.$#" + count: 3 + path: includes/core/privacy/class-wcs-privacy-background-updater.php + + - + message: "#^Function as_schedule_single_action not found\\.$#" + count: 3 + path: includes/core/privacy/class-wcs-privacy-background-updater.php + + - + message: "#^Function as_unschedule_action not found\\.$#" + count: 2 + path: includes/core/privacy/class-wcs-privacy-background-updater.php + + - + message: "#^Call to an undefined method WC_Data_Store\\:\\:get_orders\\(\\)\\.$#" + count: 1 + path: includes/core/privacy/class-wcs-privacy-erasers.php + + - + message: "#^Call to an undefined method WC_Data_Store\\:\\:get_orders\\(\\)\\.$#" + count: 1 + path: includes/core/privacy/class-wcs-privacy-exporters.php + + - + message: "#^Call to an undefined method WC_Data_Store\\:\\:get_subscription_customer_ids\\(\\)\\.$#" + count: 1 + path: includes/core/privacy/class-wcs-privacy.php + + - + message: "#^Binary operation \"\\+\" between string and 120 results in an error\\.$#" + count: 1 + path: includes/core/upgrades/class-wc-subscriptions-upgrader.php + + - + message: "#^Class WC_Logger referenced with incorrect case\\: WC_logger\\.$#" + count: 2 + path: includes/core/upgrades/class-wc-subscriptions-upgrader.php + + - + message: "#^Constant WP_MAX_MEMORY_LIMIT not found\\.$#" + count: 1 + path: includes/core/upgrades/class-wc-subscriptions-upgrader.php + + - + message: "#^Function remove_action invoked with 4 parameters, 2\\-3 required\\.$#" + count: 1 + path: includes/core/upgrades/class-wc-subscriptions-upgrader.php + + - + message: "#^PHPDoc tag @param references unknown parameter\\: \\$limit$#" + count: 1 + path: includes/core/upgrades/class-wc-subscriptions-upgrader.php + + - + message: "#^Variable \\$results might not be defined\\.$#" + count: 1 + path: includes/core/upgrades/class-wc-subscriptions-upgrader.php + + - + message: "#^Variable \\$upgraded_versions might not be defined\\.$#" + count: 3 + path: includes/core/upgrades/class-wc-subscriptions-upgrader.php + + - + message: "#^Access to constant POST_TYPE on an unknown class ActionScheduler_wpPostStore\\.$#" + count: 1 + path: includes/core/upgrades/class-wcs-repair-2-0-2.php + + - + message: "#^Variable \\$matching_line_item_id might not be defined\\.$#" + count: 1 + path: includes/core/upgrades/class-wcs-repair-2-0-2.php + + - + message: "#^Function as_next_scheduled_action not found\\.$#" + count: 1 + path: includes/core/upgrades/class-wcs-repair-2-0.php + + - + message: "#^PHPDoc tag @param references unknown parameter\\: \\$subscription_key$#" + count: 1 + path: includes/core/upgrades/class-wcs-repair-2-0.php + + - + message: "#^Call to an undefined method WC_Order_Item\\:\\:get_subtotal\\(\\)\\.$#" + count: 2 + path: includes/core/upgrades/class-wcs-repair-subtracted-base-tax-line-item-meta.php + + - + message: "#^Function wc_format_decimalw not found\\.$#" + count: 1 + path: includes/core/upgrades/class-wcs-upgrade-1-2.php + + - + message: "#^Function as_next_scheduled_action not found\\.$#" + count: 1 + path: includes/core/upgrades/class-wcs-upgrade-1-5.php + + - + message: "#^Function as_schedule_single_action not found\\.$#" + count: 1 + path: includes/core/upgrades/class-wcs-upgrade-1-5.php + + - + message: "#^Access to an undefined property object\\:\\:\\$meta_key\\.$#" + count: 1 + path: includes/core/upgrades/class-wcs-upgrade-2-0.php + + - + message: "#^Access to an undefined property object\\:\\:\\$meta_value\\.$#" + count: 2 + path: includes/core/upgrades/class-wcs-upgrade-2-0.php + + - + message: "#^Access to an undefined property object\\:\\:\\$order_id\\.$#" + count: 2 + path: includes/core/upgrades/class-wcs-upgrade-2-0.php + + - + message: "#^Access to an undefined property object\\:\\:\\$order_item_name\\.$#" + count: 1 + path: includes/core/upgrades/class-wcs-upgrade-2-0.php + + - + message: "#^Access to constant POST_TYPE on an unknown class ActionScheduler_wpPostStore\\.$#" + count: 1 + path: includes/core/upgrades/class-wcs-upgrade-2-0.php + + - + message: "#^Function as_next_scheduled_action not found\\.$#" + count: 2 + path: includes/core/upgrades/class-wcs-upgrade-2-0.php + + - + message: "#^Function as_schedule_single_action not found\\.$#" + count: 1 + path: includes/core/upgrades/class-wcs-upgrade-2-0.php + + - + message: "#^Method WCS_Upgrade_2_0\\:\\:migrate_order_items\\(\\) should return null but return statement is missing\\.$#" + count: 1 + path: includes/core/upgrades/class-wcs-upgrade-2-0.php + + - + message: "#^Method WCS_Upgrade_2_0\\:\\:migrate_order_notes\\(\\) should return null but return statement is missing\\.$#" + count: 1 + path: includes/core/upgrades/class-wcs-upgrade-2-0.php + + - + message: "#^Method WCS_Upgrade_2_0\\:\\:migrate_post_meta\\(\\) should return null but return statement is missing\\.$#" + count: 1 + path: includes/core/upgrades/class-wcs-upgrade-2-0.php + + - + message: "#^Method WCS_Upgrade_2_0\\:\\:migrate_renewal_orders\\(\\) should return null but return statement is missing\\.$#" + count: 1 + path: includes/core/upgrades/class-wcs-upgrade-2-0.php + + - + message: "#^Method WCS_Upgrade_2_0\\:\\:migrate_resubscribe_orders\\(\\) should return null but return statement is missing\\.$#" + count: 1 + path: includes/core/upgrades/class-wcs-upgrade-2-0.php + + - + message: "#^PHPDoc tag @param references unknown parameter\\: \\$order$#" + count: 3 + path: includes/core/upgrades/class-wcs-upgrade-2-0.php + + - + message: "#^PHPDoc tag @param references unknown parameter\\: \\$original_order$#" + count: 1 + path: includes/core/upgrades/class-wcs-upgrade-2-0.php + + - + message: "#^PHPDoc tag @param references unknown parameter\\: \\$subscription_id$#" + count: 1 + path: includes/core/upgrades/class-wcs-upgrade-2-0.php + + - + message: "#^Variable \\$dates_to_update in empty\\(\\) always exists and is not falsy\\.$#" + count: 1 + path: includes/core/upgrades/class-wcs-upgrade-2-0.php + + - + message: "#^Binary operation \"\\+\" between string and 180 results in an error\\.$#" + count: 1 + path: includes/core/upgrades/class-wcs-upgrade-2-2-7.php + + - + message: "#^Callback expects 1 parameter, \\$accepted_args is set to 2\\.$#" + count: 1 + path: includes/core/upgrades/class-wcs-upgrade-2-2-7.php + + - + message: "#^Function as_next_scheduled_action not found\\.$#" + count: 1 + path: includes/core/upgrades/class-wcs-upgrade-2-2-7.php + + - + message: "#^Function as_schedule_single_action not found\\.$#" + count: 1 + path: includes/core/upgrades/class-wcs-upgrade-2-2-7.php + + - + message: "#^Binary operation \"\\+\" between string and 180 results in an error\\.$#" + count: 1 + path: includes/core/upgrades/class-wcs-upgrade-2-2-9.php + + - + message: "#^Call to an undefined method WC_Logger_Interface\\:\\:clear\\(\\)\\.$#" + count: 1 + path: includes/core/upgrades/class-wcs-upgrade-logger.php + + - + message: "#^Variable \\$features might not be defined\\.$#" + count: 1 + path: includes/core/upgrades/templates/update-welcome-notice.php + + - + message: "#^Variable \\$version might not be defined\\.$#" + count: 2 + path: includes/core/upgrades/templates/update-welcome-notice.php + + - + message: "#^Function esc_html invoked with 2 parameters, 1 required\\.$#" + count: 1 + path: includes/core/upgrades/templates/wcs-about-2-0.php + + - + message: "#^Variable \\$active_version might not be defined\\.$#" + count: 1 + path: includes/core/upgrades/templates/wcs-about-2-0.php + + - + message: "#^Variable \\$active_version might not be defined\\.$#" + count: 1 + path: includes/core/upgrades/templates/wcs-about.php + + - + message: "#^Variable \\$settings_page might not be defined\\.$#" + count: 4 + path: includes/core/upgrades/templates/wcs-about.php + + - + message: "#^Variable \\$about_page_url might not be defined\\.$#" + count: 1 + path: includes/core/upgrades/templates/wcs-upgrade.php + + - + message: "#^Variable \\$estimated_duration might not be defined\\.$#" + count: 2 + path: includes/core/upgrades/templates/wcs-upgrade.php + + - + message: "#^Variable \\$script_data might not be defined\\.$#" + count: 1 + path: includes/core/upgrades/templates/wcs-upgrade.php + + - + message: "#^Variable \\$subscription_count might not be defined\\.$#" + count: 1 + path: includes/core/upgrades/templates/wcs-upgrade.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$display_cart_ex_tax\\.$#" + count: 1 + path: includes/core/wcs-cart-functions.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$recurring_carts\\.$#" + count: 2 + path: includes/core/wcs-cart-functions.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$tax_display_cart\\.$#" + count: 2 + path: includes/core/wcs-cart-functions.php + + - + message: "#^Access to an undefined property WC_Shipping_Rate\\:\\:\\$cost\\.$#" + count: 1 + path: includes/core/wcs-cart-functions.php + + - + message: "#^Access to an undefined property WooCommerce\\:\\:\\$shipping\\.$#" + count: 2 + path: includes/core/wcs-cart-functions.php + + - + message: "#^Call to an undefined method WC_Data_Store\\:\\:get_order_type\\(\\)\\.$#" + count: 2 + path: includes/core/wcs-functions.php + + - + message: "#^Call to an undefined method WC_Data_Store\\:\\:get_subscriptions_count_by_status\\(\\)\\.$#" + count: 1 + path: includes/core/wcs-functions.php + + - + message: "#^Call to an undefined method WC_Data_Store\\:\\:search_subscriptions\\(\\)\\.$#" + count: 1 + path: includes/core/wcs-functions.php + + - + message: "#^Call to an undefined method WC_Order_Item\\:\\:get_product\\(\\)\\.$#" + count: 1 + path: includes/core/wcs-functions.php + + - + message: "#^Call to an undefined method WC_Order_Item\\:\\:get_product_id\\(\\)\\.$#" + count: 3 + path: includes/core/wcs-functions.php + + - + message: "#^Call to an undefined method WC_Order_Item\\:\\:get_variation_id\\(\\)\\.$#" + count: 4 + path: includes/core/wcs-functions.php + + - + message: "#^Binary operation \"/\" between int and 0\\|86400\\|604800\\|31536000 results in an error\\.$#" + count: 2 + path: includes/core/wcs-time-functions.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$recurring_carts\\.$#" + count: 1 + path: includes/gateways/class-wc-subscriptions-payment-gateways.php + + - + message: "#^Access to an undefined property WC_Subscription\\:\\:\\$recipient_user\\.$#" + count: 2 + path: includes/gifting/class-wcs-gifting.php + + - + message: "#^Call to an undefined method WC_Data_Store\\:\\:get_order_type\\(\\)\\.$#" + count: 1 + path: includes/gifting/class-wcsg-admin.php + + - + message: "#^Constant WC_PLUGIN_FILE not found\\.$#" + count: 1 + path: includes/gifting/class-wcsg-admin.php + + - + message: "#^Call to an undefined method WC_Data_Store\\:\\:get_downloads\\(\\)\\.$#" + count: 1 + path: includes/gifting/class-wcsg-download-handler.php + + - + message: "#^Constant WC_PLUGIN_FILE not found\\.$#" + count: 1 + path: includes/gifting/class-wcsg-download-handler.php + + - + message: "#^Function wc_memberships not found\\.$#" + count: 3 + path: includes/gifting/class-wcsg-memberships-integration.php + + - + message: "#^Function wc_memberships_get_membership_plans not found\\.$#" + count: 1 + path: includes/gifting/class-wcsg-memberships-integration.php + + - + message: "#^Parameter \\$membership_plan of method WCSG_Memberships_Integration\\:\\:update_subscription_id\\(\\) has invalid type WC_Memberships_Membership_Plan\\.$#" + count: 1 + path: includes/gifting/class-wcsg-memberships-integration.php + + - + message: "#^Parameter \\$plan of method WCSG_Memberships_Integration\\:\\:get_user_unique_membership_access_granting_product_ids\\(\\) has invalid type WC_Memberships_Membership_Plan\\.$#" + count: 1 + path: includes/gifting/class-wcsg-memberships-integration.php + + - + message: "#^Call to an undefined method WC_Data_Store\\:\\:get_order_type\\(\\)\\.$#" + count: 1 + path: includes/gifting/class-wcsg-recipient-management.php + + - + message: "#^Cannot access property \\$order_date on bool\\|object\\.$#" + count: 1 + path: includes/gifting/emails/class-wcsg-email-completed-renewal-order.php + + - + message: "#^Cannot call method get_billing_first_name\\(\\) on bool\\|object\\.$#" + count: 1 + path: includes/gifting/emails/class-wcsg-email-customer-new-account.php + + - + message: "#^Cannot call method get_billing_last_name\\(\\) on bool\\|object\\.$#" + count: 1 + path: includes/gifting/emails/class-wcsg-email-customer-new-account.php + + - + message: "#^Cannot access property \\$order_date on bool\\|object\\.$#" + count: 1 + path: includes/gifting/emails/class-wcsg-email-processing-renewal-order.php + + - + message: "#^Call to an undefined method WP_Post\\:\\:get_user_id\\(\\)\\.$#" + count: 1 + path: includes/gifting/emails/class-wcsg-email-recipient-new-initial-order.php + + - + message: "#^Call to an undefined method WC_Data_Store\\:\\:get_order_type\\(\\)\\.$#" + count: 1 + path: includes/payment-retry/class-wcs-retry-manager.php + + - + message: "#^Call to an undefined method WCS_Retry_Store\\:\\:get_full_table_name\\(\\)\\.$#" + count: 1 + path: includes/payment-retry/class-wcs-retry-migrator.php + + - + message: "#^Call to an undefined method WCS_Retry_Store\\:\\:get_table_name\\(\\)\\.$#" + count: 2 + path: includes/payment-retry/class-wcs-retry-table-maker.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$recurring_carts\\.$#" + count: 4 + path: includes/switching/class-wc-subscriptions-switcher.php + + - + message: "#^Access to an undefined property WC_Cart\\:\\:\\$recurring_carts\\.$#" + count: 1 + path: includes/switching/class-wcs-cart-switch.php + + - + message: "#^Call to static method is_true\\(\\) on an unknown class Automattic\\\\Jetpack\\\\Constants\\.$#" + count: 1 + path: src/Internal/Telemetry/Collector.php + + - + message: "#^Access to an undefined property object\\:\\:\\$count\\.$#" + count: 2 + path: src/Internal/Telemetry/Products.php + + - + message: "#^Function as_has_scheduled_action not found\\.$#" + count: 1 + path: src/Internal/Utilities/Scheduled_Actions.php + + - + message: "#^Function as_schedule_recurring_action not found\\.$#" + count: 1 + path: src/Internal/Utilities/Scheduled_Actions.php + + - + message: "#^Call to an undefined method WP_Post\\:\\:get_id\\(\\)\\.$#" + count: 1 + path: templates/admin/deprecated/html-variation-price.php + + - + message: "#^Call to an undefined method WP_Post\\:\\:get_meta\\(\\)\\.$#" + count: 5 + path: templates/admin/deprecated/html-variation-price.php + + - + message: "#^Calling self\\:\\:get_trial_period_validation_message\\(\\) outside of class scope\\.$#" + count: 1 + path: templates/admin/deprecated/html-variation-price.php + + - + message: "#^Class WP_Post referenced with incorrect case\\: WP_POST\\.$#" + count: 1 + path: templates/admin/deprecated/html-variation-price.php + + - + message: "#^Class WP_Post referenced with incorrect case\\: WP_POST\\.$#" + count: 1 + path: templates/admin/deprecated/html-variation-synchronisation.php + + - + message: "#^Variable \\$display_annual_select might not be defined\\.$#" + count: 1 + path: templates/admin/deprecated/html-variation-synchronisation.php + + - + message: "#^Variable \\$display_week_month_select might not be defined\\.$#" + count: 1 + path: templates/admin/deprecated/html-variation-synchronisation.php + + - + message: "#^Variable \\$payment_day might not be defined\\.$#" + count: 2 + path: templates/admin/deprecated/html-variation-synchronisation.php + + - + message: "#^Variable \\$payment_month might not be defined\\.$#" + count: 1 + path: templates/admin/deprecated/html-variation-synchronisation.php + + - + message: "#^Variable \\$chosen_method might not be defined\\.$#" + count: 4 + path: templates/admin/deprecated/order-shipping-html.php + + - + message: "#^Variable \\$item_id might not be defined\\.$#" + count: 2 + path: templates/admin/deprecated/order-shipping-html.php + + - + message: "#^Variable \\$shipping_cost might not be defined\\.$#" + count: 1 + path: templates/admin/deprecated/order-shipping-html.php + + - + message: "#^Variable \\$shipping_methods might not be defined\\.$#" + count: 1 + path: templates/admin/deprecated/order-shipping-html.php + + - + message: "#^Variable \\$shipping_title might not be defined\\.$#" + count: 1 + path: templates/admin/deprecated/order-shipping-html.php + + - + message: "#^Variable \\$item_id might not be defined\\.$#" + count: 6 + path: templates/admin/deprecated/order-tax-html.php + + - + message: "#^Variable \\$tax_codes might not be defined\\.$#" + count: 1 + path: templates/admin/deprecated/order-tax-html.php + + - + message: "#^Calling self\\:\\:get_trial_period_validation_message\\(\\) outside of class scope\\.$#" + count: 1 + path: templates/admin/html-variation-price.php + + - + message: "#^Class WP_Post referenced with incorrect case\\: WP_POST\\.$#" + count: 1 + path: templates/admin/html-variation-price.php + + - + message: "#^Class WP_Post referenced with incorrect case\\: WP_POST\\.$#" + count: 1 + path: templates/admin/html-variation-synchronisation.php + + - + message: "#^Variable \\$display_annual_select might not be defined\\.$#" + count: 1 + path: templates/admin/html-variation-synchronisation.php + + - + message: "#^Variable \\$display_week_month_select might not be defined\\.$#" + count: 1 + path: templates/admin/html-variation-synchronisation.php + + - + message: "#^Variable \\$payment_day might not be defined\\.$#" + count: 2 + path: templates/admin/html-variation-synchronisation.php + + - + message: "#^Variable \\$payment_month might not be defined\\.$#" + count: 2 + path: templates/admin/html-variation-synchronisation.php + + - + message: "#^Variable \\$section_title might not be defined\\.$#" + count: 2 + path: templates/admin/status.php + + - + message: "#^Variable \\$section_tooltip might not be defined\\.$#" + count: 1 + path: templates/admin/status.php + + - + message: "#^Variable \\$available_methods might not be defined\\.$#" + count: 2 + path: templates/cart/cart-recurring-shipping.php + + - + message: "#^Variable \\$chosen_method might not be defined\\.$#" + count: 1 + path: templates/cart/cart-recurring-shipping.php + + - + message: "#^Variable \\$index might not be defined\\.$#" + count: 3 + path: templates/cart/cart-recurring-shipping.php + + - + message: "#^Variable \\$package_details might not be defined\\.$#" + count: 1 + path: templates/cart/cart-recurring-shipping.php + + - + message: "#^Variable \\$package_name might not be defined\\.$#" + count: 2 + path: templates/cart/cart-recurring-shipping.php + + - + message: "#^Variable \\$recurring_cart might not be defined\\.$#" + count: 1 + path: templates/cart/cart-recurring-shipping.php + + - + message: "#^Variable \\$recurring_cart_key might not be defined\\.$#" + count: 2 + path: templates/cart/cart-recurring-shipping.php + + - + message: "#^Variable \\$show_package_details might not be defined\\.$#" + count: 1 + path: templates/cart/cart-recurring-shipping.php + + - + message: "#^Access to an undefined property WooCommerce\\:\\:\\$payment_gateways\\.$#" + count: 1 + path: templates/checkout/form-change-payment-method.php + + - + message: "#^Variable \\$subscription might not be defined\\.$#" + count: 7 + path: templates/checkout/form-change-payment-method.php + + - + message: "#^Variable \\$recurring_carts might not be defined\\.$#" + count: 1 + path: templates/checkout/recurring-coupon-totals.php + + - + message: "#^Variable \\$recurring_carts might not be defined\\.$#" + count: 1 + path: templates/checkout/recurring-fee-totals.php + + - + message: "#^Access to an undefined property object\\:\\:\\$formatted_amount\\.$#" + count: 1 + path: templates/checkout/recurring-itemized-tax-totals.php + + - + message: "#^Access to an undefined property object\\:\\:\\$label\\.$#" + count: 2 + path: templates/checkout/recurring-itemized-tax-totals.php + + - + message: "#^Variable \\$recurring_carts might not be defined\\.$#" + count: 1 + path: templates/checkout/recurring-itemized-tax-totals.php + + - + message: "#^Variable \\$recurring_carts might not be defined\\.$#" + count: 1 + path: templates/checkout/recurring-subscription-totals.php + + - + message: "#^Variable \\$recurring_carts might not be defined\\.$#" + count: 1 + path: templates/checkout/recurring-subtotals.php + + - + message: "#^Variable \\$recurring_carts might not be defined\\.$#" + count: 1 + path: templates/checkout/recurring-tax-totals.php + + - + message: "#^Variable \\$recurring_carts might not be defined\\.$#" + count: 6 + path: templates/checkout/recurring-totals.php + + - + message: "#^Variable \\$subscription might not be defined\\.$#" + count: 7 + path: templates/checkout/subscription-receipt.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/admin-new-renewal-order.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 5 + path: templates/emails/admin-new-renewal-order.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/admin-new-renewal-order.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 4 + path: templates/emails/admin-new-renewal-order.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 3 + path: templates/emails/admin-new-renewal-order.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 3 + path: templates/emails/admin-new-renewal-order.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/admin-new-switch-order.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 6 + path: templates/emails/admin-new-switch-order.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/admin-new-switch-order.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 5 + path: templates/emails/admin-new-switch-order.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 4 + path: templates/emails/admin-new-switch-order.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 4 + path: templates/emails/admin-new-switch-order.php + + - + message: "#^Variable \\$subscriptions might not be defined\\.$#" + count: 2 + path: templates/emails/admin-new-switch-order.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/admin-payment-retry.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 5 + path: templates/emails/admin-payment-retry.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/admin-payment-retry.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 5 + path: templates/emails/admin-payment-retry.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 3 + path: templates/emails/admin-payment-retry.php + + - + message: "#^Variable \\$retry might not be defined\\.$#" + count: 1 + path: templates/emails/admin-payment-retry.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 3 + path: templates/emails/admin-payment-retry.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/cancelled-subscription.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 4 + path: templates/emails/cancelled-subscription.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/cancelled-subscription.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 2 + path: templates/emails/cancelled-subscription.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 2 + path: templates/emails/cancelled-subscription.php + + - + message: "#^Variable \\$subscription might not be defined\\.$#" + count: 11 + path: templates/emails/cancelled-subscription.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/customer-completed-renewal-order.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 5 + path: templates/emails/customer-completed-renewal-order.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/customer-completed-renewal-order.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 4 + path: templates/emails/customer-completed-renewal-order.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 3 + path: templates/emails/customer-completed-renewal-order.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 3 + path: templates/emails/customer-completed-renewal-order.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/customer-completed-switch-order.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 6 + path: templates/emails/customer-completed-switch-order.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/customer-completed-switch-order.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 4 + path: templates/emails/customer-completed-switch-order.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 4 + path: templates/emails/customer-completed-switch-order.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 4 + path: templates/emails/customer-completed-switch-order.php + + - + message: "#^Variable \\$subscriptions might not be defined\\.$#" + count: 1 + path: templates/emails/customer-completed-switch-order.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/customer-notification-auto-renewal.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 3 + path: templates/emails/customer-notification-auto-renewal.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/customer-notification-auto-renewal.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 1 + path: templates/emails/customer-notification-auto-renewal.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 2 + path: templates/emails/customer-notification-auto-renewal.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 2 + path: templates/emails/customer-notification-auto-renewal.php + + - + message: "#^Variable \\$subscription might not be defined\\.$#" + count: 4 + path: templates/emails/customer-notification-auto-renewal.php + + - + message: "#^Variable \\$subscription_event_date might not be defined\\.$#" + count: 1 + path: templates/emails/customer-notification-auto-renewal.php + + - + message: "#^Variable \\$subscription_time_til_event might not be defined\\.$#" + count: 1 + path: templates/emails/customer-notification-auto-renewal.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/customer-notification-auto-trial-ending.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 3 + path: templates/emails/customer-notification-auto-trial-ending.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/customer-notification-auto-trial-ending.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 1 + path: templates/emails/customer-notification-auto-trial-ending.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 2 + path: templates/emails/customer-notification-auto-trial-ending.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 2 + path: templates/emails/customer-notification-auto-trial-ending.php + + - + message: "#^Variable \\$subscription might not be defined\\.$#" + count: 4 + path: templates/emails/customer-notification-auto-trial-ending.php + + - + message: "#^Variable \\$subscription_event_date might not be defined\\.$#" + count: 1 + path: templates/emails/customer-notification-auto-trial-ending.php + + - + message: "#^Variable \\$subscription_time_til_event might not be defined\\.$#" + count: 1 + path: templates/emails/customer-notification-auto-trial-ending.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/customer-notification-expiring-subscription.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 3 + path: templates/emails/customer-notification-expiring-subscription.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/customer-notification-expiring-subscription.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 1 + path: templates/emails/customer-notification-expiring-subscription.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 2 + path: templates/emails/customer-notification-expiring-subscription.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 2 + path: templates/emails/customer-notification-expiring-subscription.php + + - + message: "#^Variable \\$subscription might not be defined\\.$#" + count: 3 + path: templates/emails/customer-notification-expiring-subscription.php + + - + message: "#^Variable \\$subscription_event_date might not be defined\\.$#" + count: 1 + path: templates/emails/customer-notification-expiring-subscription.php + + - + message: "#^Variable \\$subscription_time_til_event might not be defined\\.$#" + count: 1 + path: templates/emails/customer-notification-expiring-subscription.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/customer-notification-manual-renewal.php + + - + message: "#^Variable \\$can_renew_early might not be defined\\.$#" + count: 1 + path: templates/emails/customer-notification-manual-renewal.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 3 + path: templates/emails/customer-notification-manual-renewal.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/customer-notification-manual-renewal.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 1 + path: templates/emails/customer-notification-manual-renewal.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 2 + path: templates/emails/customer-notification-manual-renewal.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 2 + path: templates/emails/customer-notification-manual-renewal.php + + - + message: "#^Variable \\$subscription might not be defined\\.$#" + count: 3 + path: templates/emails/customer-notification-manual-renewal.php + + - + message: "#^Variable \\$subscription_event_date might not be defined\\.$#" + count: 1 + path: templates/emails/customer-notification-manual-renewal.php + + - + message: "#^Variable \\$subscription_time_til_event might not be defined\\.$#" + count: 1 + path: templates/emails/customer-notification-manual-renewal.php + + - + message: "#^Variable \\$url_for_renewal might not be defined\\.$#" + count: 1 + path: templates/emails/customer-notification-manual-renewal.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/customer-notification-manual-trial-ending.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 3 + path: templates/emails/customer-notification-manual-trial-ending.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/customer-notification-manual-trial-ending.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 1 + path: templates/emails/customer-notification-manual-trial-ending.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 2 + path: templates/emails/customer-notification-manual-trial-ending.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 2 + path: templates/emails/customer-notification-manual-trial-ending.php + + - + message: "#^Variable \\$subscription might not be defined\\.$#" + count: 3 + path: templates/emails/customer-notification-manual-trial-ending.php + + - + message: "#^Variable \\$subscription_event_date might not be defined\\.$#" + count: 1 + path: templates/emails/customer-notification-manual-trial-ending.php + + - + message: "#^Variable \\$subscription_time_til_event might not be defined\\.$#" + count: 1 + path: templates/emails/customer-notification-manual-trial-ending.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/customer-on-hold-renewal-order.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 5 + path: templates/emails/customer-on-hold-renewal-order.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/customer-on-hold-renewal-order.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 4 + path: templates/emails/customer-on-hold-renewal-order.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 3 + path: templates/emails/customer-on-hold-renewal-order.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 3 + path: templates/emails/customer-on-hold-renewal-order.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/customer-payment-retry.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 3 + path: templates/emails/customer-payment-retry.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/customer-payment-retry.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 3 + path: templates/emails/customer-payment-retry.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 1 + path: templates/emails/customer-payment-retry.php + + - + message: "#^Variable \\$retry might not be defined\\.$#" + count: 1 + path: templates/emails/customer-payment-retry.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 1 + path: templates/emails/customer-payment-retry.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/customer-processing-renewal-order.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 5 + path: templates/emails/customer-processing-renewal-order.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/customer-processing-renewal-order.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 5 + path: templates/emails/customer-processing-renewal-order.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 3 + path: templates/emails/customer-processing-renewal-order.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 3 + path: templates/emails/customer-processing-renewal-order.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/customer-renewal-invoice.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 3 + path: templates/emails/customer-renewal-invoice.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/customer-renewal-invoice.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 6 + path: templates/emails/customer-renewal-invoice.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 1 + path: templates/emails/customer-renewal-invoice.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 1 + path: templates/emails/customer-renewal-invoice.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 3 + path: templates/emails/email-order-details.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 12 + path: templates/emails/email-order-details.php + + - + message: "#^Variable \\$order_items_table_args might not be defined\\.$#" + count: 1 + path: templates/emails/email-order-details.php + + - + message: "#^Variable \\$order_type might not be defined\\.$#" + count: 3 + path: templates/emails/email-order-details.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 2 + path: templates/emails/email-order-details.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 3 + path: templates/emails/email-order-details.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/expired-subscription.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 4 + path: templates/emails/expired-subscription.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/expired-subscription.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 2 + path: templates/emails/expired-subscription.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 2 + path: templates/emails/expired-subscription.php + + - + message: "#^Variable \\$subscription might not be defined\\.$#" + count: 8 + path: templates/emails/expired-subscription.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/on-hold-subscription.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 4 + path: templates/emails/on-hold-subscription.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/on-hold-subscription.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 2 + path: templates/emails/on-hold-subscription.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 2 + path: templates/emails/on-hold-subscription.php + + - + message: "#^Variable \\$subscription might not be defined\\.$#" + count: 7 + path: templates/emails/on-hold-subscription.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/plain/admin-new-renewal-order.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 3 + path: templates/emails/plain/admin-new-renewal-order.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/plain/admin-new-renewal-order.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 4 + path: templates/emails/plain/admin-new-renewal-order.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 3 + path: templates/emails/plain/admin-new-renewal-order.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 3 + path: templates/emails/plain/admin-new-renewal-order.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/plain/admin-new-switch-order.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 4 + path: templates/emails/plain/admin-new-switch-order.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/plain/admin-new-switch-order.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 4 + path: templates/emails/plain/admin-new-switch-order.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 4 + path: templates/emails/plain/admin-new-switch-order.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 4 + path: templates/emails/plain/admin-new-switch-order.php + + - + message: "#^Variable \\$subscriptions might not be defined\\.$#" + count: 2 + path: templates/emails/plain/admin-new-switch-order.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/plain/admin-payment-retry.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 3 + path: templates/emails/plain/admin-payment-retry.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/plain/admin-payment-retry.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 5 + path: templates/emails/plain/admin-payment-retry.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 3 + path: templates/emails/plain/admin-payment-retry.php + + - + message: "#^Variable \\$retry might not be defined\\.$#" + count: 1 + path: templates/emails/plain/admin-payment-retry.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 3 + path: templates/emails/plain/admin-payment-retry.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/plain/cancelled-subscription.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 3 + path: templates/emails/plain/cancelled-subscription.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/plain/cancelled-subscription.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 3 + path: templates/emails/plain/cancelled-subscription.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 3 + path: templates/emails/plain/cancelled-subscription.php + + - + message: "#^Variable \\$subscription might not be defined\\.$#" + count: 7 + path: templates/emails/plain/cancelled-subscription.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-completed-renewal-order.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 3 + path: templates/emails/plain/customer-completed-renewal-order.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-completed-renewal-order.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 4 + path: templates/emails/plain/customer-completed-renewal-order.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 3 + path: templates/emails/plain/customer-completed-renewal-order.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 3 + path: templates/emails/plain/customer-completed-renewal-order.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-completed-switch-order.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 4 + path: templates/emails/plain/customer-completed-switch-order.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-completed-switch-order.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 5 + path: templates/emails/plain/customer-completed-switch-order.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 4 + path: templates/emails/plain/customer-completed-switch-order.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 4 + path: templates/emails/plain/customer-completed-switch-order.php + + - + message: "#^Variable \\$subscriptions might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-completed-switch-order.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-notification-auto-renewal.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-notification-auto-renewal.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-notification-auto-renewal.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-notification-auto-renewal.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 2 + path: templates/emails/plain/customer-notification-auto-renewal.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 2 + path: templates/emails/plain/customer-notification-auto-renewal.php + + - + message: "#^Variable \\$subscription might not be defined\\.$#" + count: 3 + path: templates/emails/plain/customer-notification-auto-renewal.php + + - + message: "#^Variable \\$subscription_event_date might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-notification-auto-renewal.php + + - + message: "#^Variable \\$subscription_time_til_event might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-notification-auto-renewal.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-notification-auto-trial-ending.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-notification-auto-trial-ending.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-notification-auto-trial-ending.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-notification-auto-trial-ending.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 2 + path: templates/emails/plain/customer-notification-auto-trial-ending.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 2 + path: templates/emails/plain/customer-notification-auto-trial-ending.php + + - + message: "#^Variable \\$subscription might not be defined\\.$#" + count: 3 + path: templates/emails/plain/customer-notification-auto-trial-ending.php + + - + message: "#^Variable \\$subscription_event_date might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-notification-auto-trial-ending.php + + - + message: "#^Variable \\$subscription_time_til_event might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-notification-auto-trial-ending.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-notification-expiring-subscription.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-notification-expiring-subscription.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-notification-expiring-subscription.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-notification-expiring-subscription.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 2 + path: templates/emails/plain/customer-notification-expiring-subscription.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 2 + path: templates/emails/plain/customer-notification-expiring-subscription.php + + - + message: "#^Variable \\$subscription might not be defined\\.$#" + count: 3 + path: templates/emails/plain/customer-notification-expiring-subscription.php + + - + message: "#^Variable \\$subscription_event_date might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-notification-expiring-subscription.php + + - + message: "#^Variable \\$subscription_time_til_event might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-notification-expiring-subscription.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-notification-manual-renewal.php + + - + message: "#^Variable \\$can_renew_early might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-notification-manual-renewal.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-notification-manual-renewal.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-notification-manual-renewal.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-notification-manual-renewal.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 2 + path: templates/emails/plain/customer-notification-manual-renewal.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 2 + path: templates/emails/plain/customer-notification-manual-renewal.php + + - + message: "#^Variable \\$subscription might not be defined\\.$#" + count: 3 + path: templates/emails/plain/customer-notification-manual-renewal.php + + - + message: "#^Variable \\$subscription_event_date might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-notification-manual-renewal.php + + - + message: "#^Variable \\$subscription_time_til_event might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-notification-manual-renewal.php + + - + message: "#^Variable \\$url_for_renewal might not be defined\\.$#" + count: 2 + path: templates/emails/plain/customer-notification-manual-renewal.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-notification-manual-trial-ending.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-notification-manual-trial-ending.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-notification-manual-trial-ending.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-notification-manual-trial-ending.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 2 + path: templates/emails/plain/customer-notification-manual-trial-ending.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 2 + path: templates/emails/plain/customer-notification-manual-trial-ending.php + + - + message: "#^Variable \\$subscription might not be defined\\.$#" + count: 3 + path: templates/emails/plain/customer-notification-manual-trial-ending.php + + - + message: "#^Variable \\$subscription_event_date might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-notification-manual-trial-ending.php + + - + message: "#^Variable \\$subscription_time_til_event might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-notification-manual-trial-ending.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-on-hold-renewal-order.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 3 + path: templates/emails/plain/customer-on-hold-renewal-order.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-on-hold-renewal-order.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 4 + path: templates/emails/plain/customer-on-hold-renewal-order.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 3 + path: templates/emails/plain/customer-on-hold-renewal-order.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 3 + path: templates/emails/plain/customer-on-hold-renewal-order.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-payment-retry.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-payment-retry.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-payment-retry.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 3 + path: templates/emails/plain/customer-payment-retry.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-payment-retry.php + + - + message: "#^Variable \\$retry might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-payment-retry.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-payment-retry.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-processing-renewal-order.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 3 + path: templates/emails/plain/customer-processing-renewal-order.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-processing-renewal-order.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 5 + path: templates/emails/plain/customer-processing-renewal-order.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 3 + path: templates/emails/plain/customer-processing-renewal-order.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 3 + path: templates/emails/plain/customer-processing-renewal-order.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-renewal-invoice.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-renewal-invoice.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-renewal-invoice.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 6 + path: templates/emails/plain/customer-renewal-invoice.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-renewal-invoice.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 1 + path: templates/emails/plain/customer-renewal-invoice.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 2 + path: templates/emails/plain/email-order-details.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 7 + path: templates/emails/plain/email-order-details.php + + - + message: "#^Variable \\$order_items_table_args might not be defined\\.$#" + count: 1 + path: templates/emails/plain/email-order-details.php + + - + message: "#^Variable \\$order_type might not be defined\\.$#" + count: 3 + path: templates/emails/plain/email-order-details.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 2 + path: templates/emails/plain/email-order-details.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 2 + path: templates/emails/plain/email-order-details.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/plain/expired-subscription.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 3 + path: templates/emails/plain/expired-subscription.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/plain/expired-subscription.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 3 + path: templates/emails/plain/expired-subscription.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 3 + path: templates/emails/plain/expired-subscription.php + + - + message: "#^Variable \\$subscription might not be defined\\.$#" + count: 7 + path: templates/emails/plain/expired-subscription.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/emails/plain/on-hold-subscription.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 3 + path: templates/emails/plain/on-hold-subscription.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/emails/plain/on-hold-subscription.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 3 + path: templates/emails/plain/on-hold-subscription.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 3 + path: templates/emails/plain/on-hold-subscription.php + + - + message: "#^Variable \\$subscription might not be defined\\.$#" + count: 6 + path: templates/emails/plain/on-hold-subscription.php + + - + message: "#^Variable \\$is_admin_email might not be defined\\.$#" + count: 2 + path: templates/emails/plain/subscription-info.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 1 + path: templates/emails/plain/subscription-info.php + + - + message: "#^Variable \\$skip_my_account_link might not be defined\\.$#" + count: 1 + path: templates/emails/plain/subscription-info.php + + - + message: "#^Variable \\$subscription might not be defined\\.$#" + count: 1 + path: templates/emails/plain/subscription-info.php + + - + message: "#^Variable \\$is_admin_email might not be defined\\.$#" + count: 2 + path: templates/emails/subscription-info.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 1 + path: templates/emails/subscription-info.php + + - + message: "#^Variable \\$skip_my_account_link might not be defined\\.$#" + count: 1 + path: templates/emails/subscription-info.php + + - + message: "#^Variable \\$subscription might not be defined\\.$#" + count: 1 + path: templates/emails/subscription-info.php + + - + message: "#^Variable \\$section_title might not be defined\\.$#" + count: 2 + path: templates/gifting/admin/status.php + + - + message: "#^Variable \\$section_tooltip might not be defined\\.$#" + count: 1 + path: templates/gifting/admin/status.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/new-recipient-customer.php + + - + message: "#^Variable \\$blogname might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/new-recipient-customer.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 2 + path: templates/gifting/emails/new-recipient-customer.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/new-recipient-customer.php + + - + message: "#^Variable \\$reset_key might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/new-recipient-customer.php + + - + message: "#^Variable \\$subscription_purchaser might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/new-recipient-customer.php + + - + message: "#^Variable \\$user_id might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/new-recipient-customer.php + + - + message: "#^Variable \\$user_login might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/new-recipient-customer.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/plain/new-recipient-customer.php + + - + message: "#^Variable \\$blogname might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/plain/new-recipient-customer.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/plain/new-recipient-customer.php + + - + message: "#^Variable \\$reset_key might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/plain/new-recipient-customer.php + + - + message: "#^Variable \\$subscription_purchaser might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/plain/new-recipient-customer.php + + - + message: "#^Variable \\$user_id might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/plain/new-recipient-customer.php + + - + message: "#^Variable \\$user_login might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/plain/new-recipient-customer.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 4 + path: templates/gifting/emails/plain/recipient-completed-renewal-order.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/plain/recipient-completed-renewal-order.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 4 + path: templates/gifting/emails/plain/recipient-completed-renewal-order.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 4 + path: templates/gifting/emails/plain/recipient-completed-renewal-order.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 4 + path: templates/gifting/emails/plain/recipient-completed-renewal-order.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 2 + path: templates/gifting/emails/plain/recipient-email-address-table.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/plain/recipient-email-order-details.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/plain/recipient-email-order-details.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 2 + path: templates/gifting/emails/plain/recipient-email-order-details.php + + - + message: "#^Variable \\$title might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/plain/recipient-email-order-details.php + + - + message: "#^Variable \\$items might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/plain/recipient-email-order-items.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 2 + path: templates/gifting/emails/plain/recipient-email-order-items.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 2 + path: templates/gifting/emails/plain/recipient-email-order-items.php + + - + message: "#^Variable \\$show_purchase_note might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/plain/recipient-email-order-items.php + + - + message: "#^Variable \\$show_sku might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/plain/recipient-email-order-items.php + + - + message: "#^Variable \\$subscriptions might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/plain/recipient-email-subscriptions-table.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/plain/recipient-new-initial-order.php + + - + message: "#^Variable \\$blogname might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/plain/recipient-new-initial-order.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 2 + path: templates/gifting/emails/plain/recipient-new-initial-order.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/plain/recipient-new-initial-order.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 2 + path: templates/gifting/emails/plain/recipient-new-initial-order.php + + - + message: "#^Variable \\$recipient_user might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/plain/recipient-new-initial-order.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 2 + path: templates/gifting/emails/plain/recipient-new-initial-order.php + + - + message: "#^Variable \\$subscription_purchaser might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/plain/recipient-new-initial-order.php + + - + message: "#^Variable \\$subscriptions might not be defined\\.$#" + count: 4 + path: templates/gifting/emails/plain/recipient-new-initial-order.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 4 + path: templates/gifting/emails/plain/recipient-processing-renewal-order.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/plain/recipient-processing-renewal-order.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 4 + path: templates/gifting/emails/plain/recipient-processing-renewal-order.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 4 + path: templates/gifting/emails/plain/recipient-processing-renewal-order.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 4 + path: templates/gifting/emails/plain/recipient-processing-renewal-order.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 6 + path: templates/gifting/emails/recipient-completed-renewal-order.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/recipient-completed-renewal-order.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 4 + path: templates/gifting/emails/recipient-completed-renewal-order.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 4 + path: templates/gifting/emails/recipient-completed-renewal-order.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 4 + path: templates/gifting/emails/recipient-completed-renewal-order.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 2 + path: templates/gifting/emails/recipient-email-address-table.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/recipient-email-order-details.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/recipient-email-order-details.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 2 + path: templates/gifting/emails/recipient-email-order-details.php + + - + message: "#^Variable \\$title might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/recipient-email-order-details.php + + - + message: "#^Variable \\$image_size might not be defined\\.$#" + count: 2 + path: templates/gifting/emails/recipient-email-order-items.php + + - + message: "#^Variable \\$items might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/recipient-email-order-items.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 3 + path: templates/gifting/emails/recipient-email-order-items.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 2 + path: templates/gifting/emails/recipient-email-order-items.php + + - + message: "#^Variable \\$show_image might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/recipient-email-order-items.php + + - + message: "#^Variable \\$show_purchase_note might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/recipient-email-order-items.php + + - + message: "#^Variable \\$show_sku might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/recipient-email-order-items.php + + - + message: "#^Variable \\$subscriptions might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/recipient-email-subscriptions-table.php + + - + message: "#^Variable \\$additional_content might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/recipient-new-initial-order.php + + - + message: "#^Variable \\$blogname might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/recipient-new-initial-order.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 4 + path: templates/gifting/emails/recipient-new-initial-order.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/recipient-new-initial-order.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 2 + path: templates/gifting/emails/recipient-new-initial-order.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 2 + path: templates/gifting/emails/recipient-new-initial-order.php + + - + message: "#^Variable \\$subscription_purchaser might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/recipient-new-initial-order.php + + - + message: "#^Variable \\$subscriptions might not be defined\\.$#" + count: 4 + path: templates/gifting/emails/recipient-new-initial-order.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 6 + path: templates/gifting/emails/recipient-processing-renewal-order.php + + - + message: "#^Variable \\$email_heading might not be defined\\.$#" + count: 1 + path: templates/gifting/emails/recipient-processing-renewal-order.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 4 + path: templates/gifting/emails/recipient-processing-renewal-order.php + + - + message: "#^Variable \\$plain_text might not be defined\\.$#" + count: 4 + path: templates/gifting/emails/recipient-processing-renewal-order.php + + - + message: "#^Variable \\$sent_to_admin might not be defined\\.$#" + count: 4 + path: templates/gifting/emails/recipient-processing-renewal-order.php + + - + message: "#^Variable \\$checkbox_field_args might not be defined\\.$#" + count: 4 + path: templates/gifting/html-add-recipient.php + + - + message: "#^Variable \\$container_css_class might not be defined\\.$#" + count: 1 + path: templates/gifting/html-add-recipient.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 2 + path: templates/gifting/html-add-recipient.php + + - + message: "#^Variable \\$email_field_args might not be defined\\.$#" + count: 3 + path: templates/gifting/html-add-recipient.php + + - + message: "#^Variable \\$id might not be defined\\.$#" + count: 4 + path: templates/gifting/html-add-recipient.php + + - + message: "#^Variable \\$nonce_field might not be defined\\.$#" + count: 1 + path: templates/gifting/html-add-recipient.php + + - + message: "#^Variable \\$email might not be defined\\.$#" + count: 1 + path: templates/gifting/html-flat-gifting-recipient-details.php + + - + message: "#^Variable \\$name might not be defined\\.$#" + count: 1 + path: templates/gifting/html-view-subscription-gifting-information.php + + - + message: "#^Variable \\$user_title might not be defined\\.$#" + count: 2 + path: templates/gifting/html-view-subscription-gifting-information.php + + - + message: "#^Variable \\$order might not be defined\\.$#" + count: 3 + path: templates/gifting/order-details-customer.php + + - + message: "#^Cannot access property \\$order_date on bool\\|WC_Order\\|WC_Order_Refund\\.$#" + count: 1 + path: templates/gifting/related-orders.php + + - + message: "#^Variable \\$subscription might not be defined\\.$#" + count: 2 + path: templates/gifting/related-orders.php + + - + message: "#^Variable \\$subscription_orders might not be defined\\.$#" + count: 1 + path: templates/gifting/related-orders.php + + - + message: "#^Variable \\$subscription might not be defined\\.$#" + count: 10 + path: templates/gifting/subscription-totals.php + + - + message: "#^Variable \\$current_page might not be defined\\.$#" + count: 2 + path: templates/myaccount/my-subscriptions.php + + - + message: "#^Variable \\$max_num_pages might not be defined\\.$#" + count: 1 + path: templates/myaccount/my-subscriptions.php + + - + message: "#^Variable \\$order_id might not be defined\\.$#" + count: 1 + path: templates/myaccount/related-subscriptions.php + + - + message: "#^Variable \\$subscriptions might not be defined\\.$#" + count: 1 + path: templates/myaccount/related-subscriptions.php + + - + message: "#^Variable \\$subscription might not be defined\\.$#" + count: 16 + path: templates/myaccount/subscription-details.php + + - + message: "#^Variable \\$allow_item_removal might not be defined\\.$#" + count: 1 + path: templates/myaccount/subscription-totals-table.php + + - + message: "#^Variable \\$subscription might not be defined\\.$#" + count: 10 + path: templates/myaccount/subscription-totals-table.php + + - + message: "#^Variable \\$totals might not be defined\\.$#" + count: 1 + path: templates/myaccount/subscription-totals-table.php + + - + message: "#^Variable \\$subscription might not be defined\\.$#" + count: 3 + path: templates/myaccount/subscription-totals.php + + - + message: "#^Variable \\$current_page might not be defined\\.$#" + count: 1 + path: templates/myaccount/subscriptions.php + + - + message: "#^Variable \\$subscription might not be defined\\.$#" + count: 4 + path: templates/myaccount/view-subscription.php + + - + message: "#^Variable \\$attributes might not be defined\\.$#" + count: 2 + path: templates/single-product/add-to-cart/variable-subscription.php + + - + message: "#^Variable \\$available_variations might not be defined\\.$#" + count: 1 + path: templates/single-product/add-to-cart/variable-subscription.php diff --git a/src/Internal/Utilities/Request.php b/src/Internal/Utilities/Request.php new file mode 100644 index 0000000..d1fc9b4 --- /dev/null +++ b/src/Internal/Utilities/Request.php @@ -0,0 +1,102 @@ + $location, + 'status' => $status, + ); + return; + } + wp_safe_redirect( $location, $status ); + + if ( $should_exit ) { + self::exit(); + } + } + + /** + * Supplies the value of the POST or URL query parameter matching $key, or else returns $default. + * + * Essentially, this is an alternative to inspecting the $_REQUEST super-global and is intended for cases where we + * are interested in a key:value pair, regardless of whether it was sent as a post var or URL query var. + * + * Its advantages are that it only ever examines the POST and GET inputs (POST taking priority, if both contain the + * same key): cookies are always ignored. It also looks directly at the inputs, instead of using the $_POST or $_GET + * superglobals (which can be manipulated). + * + * @since 8.3.0 + * + * @param string $key The key to look up. + * @param mixed $default_value The value to return if the key is not found. Defaults to null. + * + * @return mixed + */ + public static function get_var( string $key, $default_value = null ) { + if ( null === self::$post_vars ) { + self::$post_vars = filter_input_array( INPUT_POST ) ?? array(); + self::$url_vars = filter_input_array( INPUT_GET ) ?? array(); + } + + if ( isset( self::$post_vars[ $key ] ) ) { + return self::$post_vars[ $key ]; + } elseif ( isset( self::$url_vars[ $key ] ) ) { + return self::$url_vars[ $key ]; + } + + return $default_value; + } +} diff --git a/templates/admin/html-variation-price.php b/templates/admin/html-variation-price.php index d2da2c9..7130e63 100644 --- a/templates/admin/html-variation-price.php +++ b/templates/admin/html-variation-price.php @@ -2,6 +2,8 @@ /** * Outputs a subscription variation's pricing fields for WooCommerce 2.3+ * + * You may also be interested in assets/js/admin/admin.js, which dynamically relocates some of these fields. + * * @version 1.0.0 - Migrated from WooCommerce Subscriptions v2.2.12 * * @var int $loop diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index d1add03..b139c5f 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -12,6 +12,7 @@ return array( 'Automattic\\WooCommerce_Subscriptions\\Internal\\Telemetry\\Orders' => $baseDir . '/src/Internal/Telemetry/Orders.php', 'Automattic\\WooCommerce_Subscriptions\\Internal\\Telemetry\\Products' => $baseDir . '/src/Internal/Telemetry/Products.php', 'Automattic\\WooCommerce_Subscriptions\\Internal\\Telemetry\\Subscriptions' => $baseDir . '/src/Internal/Telemetry/Subscriptions.php', + 'Automattic\\WooCommerce_Subscriptions\\Internal\\Utilities\\Request' => $baseDir . '/src/Internal/Utilities/Request.php', 'Automattic\\WooCommerce_Subscriptions\\Internal\\Utilities\\Scheduled_Actions' => $baseDir . '/src/Internal/Utilities/Scheduled_Actions.php', 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php', 'Composer\\Installers\\AglInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/AglInstaller.php', @@ -138,6 +139,7 @@ return array( 'WCSG_Template_Loader' => $baseDir . '/includes/gifting/class-wcsg-template-loader.php', 'WCS_Gifting' => $baseDir . '/includes/gifting/class-wcs-gifting.php', 'WC_Subscription_Downloads' => $baseDir . '/includes/downloads/class-wc-subscription-downloads.php', + 'WC_Subscription_Downloads_Admin_Welcome_Announcement' => $baseDir . '/includes/downloads/class-wc-subscription-downloads-admin-welcome-announcement.php', 'WC_Subscription_Downloads_Ajax' => $baseDir . '/includes/downloads/class-wc-subscription-downloads-ajax.php', 'WC_Subscription_Downloads_Install' => $baseDir . '/includes/downloads/class-wc-subscription-downloads-install.php', 'WC_Subscription_Downloads_Order' => $baseDir . '/includes/downloads/class-wc-subscription-downloads-order.php', diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 0b9ff43..5efa01b 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -35,6 +35,7 @@ class ComposerStaticInitcb45de1ca955f89ec737c442c7cf101c 'Automattic\\WooCommerce_Subscriptions\\Internal\\Telemetry\\Orders' => __DIR__ . '/../..' . '/src/Internal/Telemetry/Orders.php', 'Automattic\\WooCommerce_Subscriptions\\Internal\\Telemetry\\Products' => __DIR__ . '/../..' . '/src/Internal/Telemetry/Products.php', 'Automattic\\WooCommerce_Subscriptions\\Internal\\Telemetry\\Subscriptions' => __DIR__ . '/../..' . '/src/Internal/Telemetry/Subscriptions.php', + 'Automattic\\WooCommerce_Subscriptions\\Internal\\Utilities\\Request' => __DIR__ . '/../..' . '/src/Internal/Utilities/Request.php', 'Automattic\\WooCommerce_Subscriptions\\Internal\\Utilities\\Scheduled_Actions' => __DIR__ . '/../..' . '/src/Internal/Utilities/Scheduled_Actions.php', 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', 'Composer\\Installers\\AglInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/AglInstaller.php', @@ -161,6 +162,7 @@ class ComposerStaticInitcb45de1ca955f89ec737c442c7cf101c 'WCSG_Template_Loader' => __DIR__ . '/../..' . '/includes/gifting/class-wcsg-template-loader.php', 'WCS_Gifting' => __DIR__ . '/../..' . '/includes/gifting/class-wcs-gifting.php', 'WC_Subscription_Downloads' => __DIR__ . '/../..' . '/includes/downloads/class-wc-subscription-downloads.php', + 'WC_Subscription_Downloads_Admin_Welcome_Announcement' => __DIR__ . '/../..' . '/includes/downloads/class-wc-subscription-downloads-admin-welcome-announcement.php', 'WC_Subscription_Downloads_Ajax' => __DIR__ . '/../..' . '/includes/downloads/class-wc-subscription-downloads-ajax.php', 'WC_Subscription_Downloads_Install' => __DIR__ . '/../..' . '/includes/downloads/class-wc-subscription-downloads-install.php', 'WC_Subscription_Downloads_Order' => __DIR__ . '/../..' . '/includes/downloads/class-wc-subscription-downloads-order.php', diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index 43a7468..4ffbe49 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -1,9 +1,9 @@ array( 'name' => 'woocommerce/woocommerce-subscriptions', - 'pretty_version' => 'dev-release/8.2.1', - 'version' => 'dev-release/8.2.1', - 'reference' => '8bb99631f731722b758f4702dc319ae43043ed67', + 'pretty_version' => 'dev-release/8.3.0', + 'version' => 'dev-release/8.3.0', + 'reference' => '38b39c285d0bae952d5746ba460ae914e4ac0f60', 'type' => 'wordpress-plugin', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -29,9 +29,9 @@ 'dev_requirement' => false, ), 'woocommerce/woocommerce-subscriptions' => array( - 'pretty_version' => 'dev-release/8.2.1', - 'version' => 'dev-release/8.2.1', - 'reference' => '8bb99631f731722b758f4702dc319ae43043ed67', + 'pretty_version' => 'dev-release/8.3.0', + 'version' => 'dev-release/8.3.0', + 'reference' => '38b39c285d0bae952d5746ba460ae914e4ac0f60', 'type' => 'wordpress-plugin', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), diff --git a/woocommerce-subscriptions.php b/woocommerce-subscriptions.php index a47d978..07be272 100644 --- a/woocommerce-subscriptions.php +++ b/woocommerce-subscriptions.php @@ -5,7 +5,7 @@ * Description: Sell products and services with recurring payments in your WooCommerce Store. * Author: WooCommerce * Author URI: https://woocommerce.com/ - * Version: 8.2.1 + * Version: 8.3.0 * Requires Plugins: woocommerce * * WC requires at least: 10.3.0 @@ -84,7 +84,7 @@ class WC_Subscriptions { public static $plugin_file = __FILE__; /** @var string */ - public static $version = '8.2.1'; // WRCS: DEFINED_VERSION. + public static $version = '8.3.0'; // WRCS: DEFINED_VERSION. /** @var string */ public static $wc_minimum_supported_version = '7.7';