From a9f99213c3b42d58b00641cf1b6ca134a9ef3a41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20H=C3=BCsken?= Date: Thu, 12 Dec 2024 13:36:32 +0100 Subject: [PATCH 01/32] add logic that prevents from not allowed periods. --- .../src/SubscriptionsApiHandler.php | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/modules/ppcp-paypal-subscriptions/src/SubscriptionsApiHandler.php b/modules/ppcp-paypal-subscriptions/src/SubscriptionsApiHandler.php index 64439f70d..9b214824e 100644 --- a/modules/ppcp-paypal-subscriptions/src/SubscriptionsApiHandler.php +++ b/modules/ppcp-paypal-subscriptions/src/SubscriptionsApiHandler.php @@ -263,10 +263,31 @@ class SubscriptionsApiHandler { $sequence++; } + $interval = $product->get_meta( '_subscription_period' ); + $period_interval = (int) $product->get_meta( '_subscription_period_interval' ); + $update = false; + if ( $interval === 'day' && $period_interval > 365 ) { + $period_interval = 365; + $update = true; + } elseif ( $interval === 'week' && $period_interval > 52 ) { + $period_interval = 52; + $update = true; + } elseif ( $interval === 'month' && $period_interval > 12 ) { + $period_interval = 12; + $update = true; + } elseif ( $interval === 'year' && $period_interval > 1 ) { + $period_interval = 1; + $update = true; + } + if ( $update ) { + $product->add_meta_data( '_subscription_period_interval', $period_interval, true ); + $product->save(); + } + $billing_cycles[] = ( new BillingCycle( array( - 'interval_unit' => $product->get_meta( '_subscription_period' ), - 'interval_count' => $product->get_meta( '_subscription_period_interval' ), + 'interval_unit' => $interval, + 'interval_count' => $period_interval, ), $sequence, 'REGULAR', From 915e755c76c726837f9d412858ed8792f560c479 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20H=C3=BCsken?= Date: Thu, 12 Dec 2024 13:40:11 +0100 Subject: [PATCH 02/32] convert to sting --- .../ppcp-paypal-subscriptions/src/SubscriptionsApiHandler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ppcp-paypal-subscriptions/src/SubscriptionsApiHandler.php b/modules/ppcp-paypal-subscriptions/src/SubscriptionsApiHandler.php index 9b214824e..aa248fe6a 100644 --- a/modules/ppcp-paypal-subscriptions/src/SubscriptionsApiHandler.php +++ b/modules/ppcp-paypal-subscriptions/src/SubscriptionsApiHandler.php @@ -280,7 +280,7 @@ class SubscriptionsApiHandler { $update = true; } if ( $update ) { - $product->add_meta_data( '_subscription_period_interval', $period_interval, true ); + $product->add_meta_data( '_subscription_period_interval', (string) $period_interval, true ); $product->save(); } From 1776df200b17aca6a4a6c5f5cbe6a1baa9819304 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20H=C3=BCsken?= Date: Mon, 16 Dec 2024 08:57:36 +0100 Subject: [PATCH 03/32] add warning to log if interval is changed --- .../ppcp-paypal-subscriptions/src/SubscriptionsApiHandler.php | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/ppcp-paypal-subscriptions/src/SubscriptionsApiHandler.php b/modules/ppcp-paypal-subscriptions/src/SubscriptionsApiHandler.php index aa248fe6a..045c898c6 100644 --- a/modules/ppcp-paypal-subscriptions/src/SubscriptionsApiHandler.php +++ b/modules/ppcp-paypal-subscriptions/src/SubscriptionsApiHandler.php @@ -282,6 +282,7 @@ class SubscriptionsApiHandler { if ( $update ) { $product->add_meta_data( '_subscription_period_interval', (string) $period_interval, true ); $product->save(); + $this->logger->warning( sprintf( 'Subscription plan on PayPal is to high for %1$s interval change it to maximum of %2$d', $interval, $period_interval ) ); } $billing_cycles[] = ( new BillingCycle( From 0f1750617f27e5922e4fb8bb48ef035f70138ce4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20H=C3=BCsken?= Date: Mon, 16 Dec 2024 13:09:45 +0100 Subject: [PATCH 04/32] add js to not allow selecting not allowed period intervals --- .../resources/js/paypal-subscription.js | 65 ++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/modules/ppcp-paypal-subscriptions/resources/js/paypal-subscription.js b/modules/ppcp-paypal-subscriptions/resources/js/paypal-subscription.js index 3e511a569..58d9567c6 100644 --- a/modules/ppcp-paypal-subscriptions/resources/js/paypal-subscription.js +++ b/modules/ppcp-paypal-subscriptions/resources/js/paypal-subscription.js @@ -68,12 +68,75 @@ document.addEventListener( 'DOMContentLoaded', () => { soldIndividually.setAttribute( 'disabled', 'disabled' ); }; + const updateInterval = () => { + const subscriptionPeriodInterval = document.querySelector('#_subscription_period_interval'); + const subscriptionPeriod = document.querySelector('#_subscription_period'); + const subscriptionProduct = document.querySelector('#ppcp_enable_subscription_product'); + const optionsDisable = (start = 0) => { + const subscriptionPeriodIntervalChildren = subscriptionPeriodInterval.children; + for (let i = 0; i < subscriptionPeriodIntervalChildren.length; i++) { + if ( start === 0 || parseInt( subscriptionPeriodIntervalChildren[i].value ) <= start ) { + subscriptionPeriodIntervalChildren[i].disabled = false; + subscriptionPeriodIntervalChildren[i].removeAttribute('disabled'); + } else { + subscriptionPeriodIntervalChildren[i].disabled = true; + subscriptionPeriodIntervalChildren[i].setAttribute('disabled', 'disabled'); + } + } + jQuery( '#_subscription_period_interval' ).trigger('change.select2'); + }; + + const updateSubscriptionPeriodInterval = () => { + if (subscriptionProduct?.checked === false) { + optionsDisable(); + return; + } + if ( subscriptionPeriod.value === 'year' ) { + optionsDisable( 1 ); + if ( parseInt( subscriptionPeriodInterval.value ) > 1 ) { + subscriptionPeriodInterval.value = '1'; + } + } + if ( subscriptionPeriod.value === 'month' ) { + optionsDisable( 12 ); + if ( parseInt( subscriptionPeriodInterval.value ) > 12 ) { + subscriptionPeriodInterval.value = '12'; + } + } + if ( subscriptionPeriod.value === 'week' ) { + optionsDisable( 52 ); + if ( parseInt( subscriptionPeriodInterval.value ) > 52 ) { + subscriptionPeriodInterval.value = '52'; + } + } + if ( subscriptionPeriod.value === 'day' ) { + optionsDisable( 365 ); + if ( parseInt( subscriptionPeriodInterval.value ) > 365 ) { + subscriptionPeriodInterval.value = '365'; + } + } + jQuery( '#_subscription_period_interval' ).trigger( 'change.select2' ); + } + + subscriptionProduct?.addEventListener( 'change', (e) => { + updateSubscriptionPeriodInterval(); + }); + jQuery( '#_subscription_period' ).on( 'change', (e) => { + updateSubscriptionPeriodInterval(); + }); + jQuery( '#_subscription_period_interval' ).on( 'change', (e) => { + updateSubscriptionPeriodInterval(); + }); + }; + const setupProducts = () => { PayPalCommerceGatewayPayPalSubscriptionProducts?.forEach( ( product ) => { if ( product.product_connected === 'yes' ) { disableFields( product.product_id ); - } + } else { + updateInterval(); + } const unlinkBtn = document.getElementById( `ppcp-unlink-sub-plan-${ product.product_id }` From 39f88b7346f661f70bcdc0e45128401eb9531b1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20H=C3=BCsken?= Date: Tue, 17 Dec 2024 16:05:36 +0100 Subject: [PATCH 05/32] Changed and improved logic. Checkbox will be grayed out when period interval is not allowed. --- .../ppcp-paypal-subscriptions/package.json | 1 + .../resources/js/paypal-subscription.js | 153 +++++++++--------- .../src/DeactivatePlanEndpoint.php | 2 +- .../src/PayPalSubscriptionsModule.php | 38 ++--- modules/ppcp-paypal-subscriptions/yarn.lock | 97 ++++++++++- 5 files changed, 197 insertions(+), 94 deletions(-) diff --git a/modules/ppcp-paypal-subscriptions/package.json b/modules/ppcp-paypal-subscriptions/package.json index 844bcec31..52c9163ee 100644 --- a/modules/ppcp-paypal-subscriptions/package.json +++ b/modules/ppcp-paypal-subscriptions/package.json @@ -15,6 +15,7 @@ "devDependencies": { "@babel/core": "^7.26", "@babel/preset-env": "^7.26", + "@wordpress/i18n": "^5.11", "babel-loader": "^9.2", "cross-env": "^7.0.3", "file-loader": "^6.2.0", diff --git a/modules/ppcp-paypal-subscriptions/resources/js/paypal-subscription.js b/modules/ppcp-paypal-subscriptions/resources/js/paypal-subscription.js index 58d9567c6..6435f8b0a 100644 --- a/modules/ppcp-paypal-subscriptions/resources/js/paypal-subscription.js +++ b/modules/ppcp-paypal-subscriptions/resources/js/paypal-subscription.js @@ -1,6 +1,8 @@ +import { __ } from '@wordpress/i18n'; document.addEventListener( 'DOMContentLoaded', () => { - const variations = document.querySelector( '.woocommerce_variations' ); + const disableFields = ( productId ) => { + const variations = document.querySelector( '.woocommerce_variations' ); if ( variations ) { const children = variations.children; for ( let i = 0; i < children.length; i++ ) { @@ -68,79 +70,83 @@ document.addEventListener( 'DOMContentLoaded', () => { soldIndividually.setAttribute( 'disabled', 'disabled' ); }; - const updateInterval = () => { - const subscriptionPeriodInterval = document.querySelector('#_subscription_period_interval'); - const subscriptionPeriod = document.querySelector('#_subscription_period'); - const subscriptionProduct = document.querySelector('#ppcp_enable_subscription_product'); - const optionsDisable = (start = 0) => { - const subscriptionPeriodIntervalChildren = subscriptionPeriodInterval.children; - for (let i = 0; i < subscriptionPeriodIntervalChildren.length; i++) { - if ( start === 0 || parseInt( subscriptionPeriodIntervalChildren[i].value ) <= start ) { - subscriptionPeriodIntervalChildren[i].disabled = false; - subscriptionPeriodIntervalChildren[i].removeAttribute('disabled'); - } else { - subscriptionPeriodIntervalChildren[i].disabled = true; - subscriptionPeriodIntervalChildren[i].setAttribute('disabled', 'disabled'); - } - } - jQuery( '#_subscription_period_interval' ).trigger('change.select2'); - }; - - const updateSubscriptionPeriodInterval = () => { - if (subscriptionProduct?.checked === false) { - optionsDisable(); - return; - } - if ( subscriptionPeriod.value === 'year' ) { - optionsDisable( 1 ); - if ( parseInt( subscriptionPeriodInterval.value ) > 1 ) { - subscriptionPeriodInterval.value = '1'; - } - } - if ( subscriptionPeriod.value === 'month' ) { - optionsDisable( 12 ); - if ( parseInt( subscriptionPeriodInterval.value ) > 12 ) { - subscriptionPeriodInterval.value = '12'; - } - } - if ( subscriptionPeriod.value === 'week' ) { - optionsDisable( 52 ); - if ( parseInt( subscriptionPeriodInterval.value ) > 52 ) { - subscriptionPeriodInterval.value = '52'; - } - } - if ( subscriptionPeriod.value === 'day' ) { - optionsDisable( 365 ); - if ( parseInt( subscriptionPeriodInterval.value ) > 365 ) { - subscriptionPeriodInterval.value = '365'; - } - } - jQuery( '#_subscription_period_interval' ).trigger( 'change.select2' ); - } - - subscriptionProduct?.addEventListener( 'change', (e) => { - updateSubscriptionPeriodInterval(); - }); - jQuery( '#_subscription_period' ).on( 'change', (e) => { - updateSubscriptionPeriodInterval(); - }); - jQuery( '#_subscription_period_interval' ).on( 'change', (e) => { - updateSubscriptionPeriodInterval(); - }); - }; - const setupProducts = () => { + jQuery( '.wc_input_subscription_period' ).on( 'change', (e) => { + const linkBtn = e.target.parentElement.parentElement.parentElement.parentElement.querySelector('input[name="_ppcp_enable_subscription_product"]'); + const period_interval = e.target.parentElement.querySelector('select.wc_input_subscription_period_interval')?.value; + const period = e.target.value; + + if ( + ( period === 'year' && parseInt( period_interval ) > 1 ) || + ( period === 'month' && parseInt( period_interval ) > 12 ) || + ( period === 'week' && parseInt( period_interval ) > 52 ) || + ( period === 'day' && parseInt( period_interval ) > 356 ) + ) { + linkBtn.disabled = true; + linkBtn.checked = false; + linkBtn.setAttribute('title', __( 'Not allowed period intervall combination!', 'woocommerce-paypal-subscriptions' ) ); + } else { + linkBtn.disabled = false; + linkBtn.removeAttribute('title'); + } + }); + + jQuery( '.wc_input_subscription_period_interval' ).on( 'change', (e) => { + const linkBtn = e.target.parentElement.parentElement.parentElement.parentElement.querySelector('input[name="_ppcp_enable_subscription_product"]'); + const period_interval = e.target.value; + const period = e.target.parentElement.querySelector('select.wc_input_subscription_period')?.value; + + if ( + ( period === 'year' && parseInt( period_interval ) > 1 ) || + ( period === 'month' && parseInt( period_interval ) > 12 ) || + ( period === 'week' && parseInt( period_interval ) > 52 ) || + ( period === 'day' && parseInt( period_interval ) > 356 ) + ) { + linkBtn.disabled = true; + linkBtn.checked = false; + linkBtn.setAttribute('title', __( 'Not allowed period intervall combination!', 'woocommerce-paypal-subscriptions' ) ); + } else { + linkBtn.disabled = false; + linkBtn.removeAttribute('title'); + } + }); + PayPalCommerceGatewayPayPalSubscriptionProducts?.forEach( ( product ) => { if ( product.product_connected === 'yes' ) { disableFields( product.product_id ); - } else { - updateInterval(); - } + } - const unlinkBtn = document.getElementById( - `ppcp-unlink-sub-plan-${ product.product_id }` - ); + const linkBtn = document.getElementById( + `ppcp_enable_subscription_product-${ product.product_id }` + ); + linkBtn?.addEventListener( 'click', ( event ) => { + const unlinkBtnP = document.getElementById( + `ppcp-enable-subscription-${ product.product_id }` + ); + const titleP = document.getElementById( + `ppcp_subscription_plan_name_p-${ product.product_id }` + ); + if (event.target.checked === true) { + if ( unlinkBtnP ) { + unlinkBtnP.style.display = 'none'; + } + if ( titleP ) { + titleP.style.display = 'block'; + } + } else { + if ( unlinkBtnP ) { + unlinkBtnP.style.display = 'block'; + } + if ( titleP ) { + titleP.style.display = 'none'; + } + } + }); + + const unlinkBtn = document.getElementById( + `ppcp-unlink-sub-plan-${ product.product_id }` + ); unlinkBtn?.addEventListener( 'click', ( event ) => { event.preventDefault(); unlinkBtn.disabled = true; @@ -173,23 +179,22 @@ document.addEventListener( 'DOMContentLoaded', () => { } const enableSubscription = document.getElementById( - 'ppcp-enable-subscription' + 'ppcp-enable-subscription-' + data.data.product_id ); - const product = - document.getElementById( 'pcpp-product' ); - const plan = document.getElementById( 'pcpp-plan' ); + const product = document.getElementById( 'pcpp-product-' + data.data.product_id ); + const plan = document.getElementById( 'pcpp-plan-' + data.data.product_id ); enableSubscription.style.display = 'none'; product.style.display = 'none'; plan.style.display = 'none'; const enable_subscription_product = document.getElementById( - 'ppcp_enable_subscription_product' + 'ppcp_enable_subscription_product-' + data.data.product_id ); enable_subscription_product.disabled = true; const planUnlinked = - document.getElementById( 'pcpp-plan-unlinked' ); + document.getElementById( 'pcpp-plan-unlinked-' + data.data.product_id ); planUnlinked.style.display = 'block'; setTimeout( () => { diff --git a/modules/ppcp-paypal-subscriptions/src/DeactivatePlanEndpoint.php b/modules/ppcp-paypal-subscriptions/src/DeactivatePlanEndpoint.php index 4bbdc4e28..a092b3c51 100644 --- a/modules/ppcp-paypal-subscriptions/src/DeactivatePlanEndpoint.php +++ b/modules/ppcp-paypal-subscriptions/src/DeactivatePlanEndpoint.php @@ -78,7 +78,7 @@ class DeactivatePlanEndpoint { } } - wp_send_json_success(); + wp_send_json_success( array( 'product_id' => (string) $product_id ) ); } catch ( Exception $error ) { wp_send_json_error(); } diff --git a/modules/ppcp-paypal-subscriptions/src/PayPalSubscriptionsModule.php b/modules/ppcp-paypal-subscriptions/src/PayPalSubscriptionsModule.php index 48c3a71af..04007a188 100644 --- a/modules/ppcp-paypal-subscriptions/src/PayPalSubscriptionsModule.php +++ b/modules/ppcp-paypal-subscriptions/src/PayPalSubscriptionsModule.php @@ -780,10 +780,10 @@ class PayPalSubscriptionsModule implements ServiceModule, ExtendingModule, Execu echo sprintf( // translators: %1$s and %2$s are label open and close tags. esc_html__( '%1$sConnect to PayPal%2$s', 'woocommerce-paypal-payments' ), - '