Refactor button renderer and filter woocommerce_paypal_payments_<context>_button_disabled

This commit is contained in:
Pedro Silva 2023-07-03 17:35:01 +01:00
parent 74f28ca921
commit 6b03960de7
No known key found for this signature in database
GPG key ID: E2EE20C0669D24B3
7 changed files with 131 additions and 83 deletions

View file

@ -122,21 +122,10 @@ const bootstrap = () => {
} }
}; };
let smartButtonsOptions = { const onSmartButtonsInit = () => {
onInit: null,
init: function (actions) {
this.actions = actions;
if (typeof this.onInit === 'function') {
this.onInit();
}
}
};
const onSmartButtonsInit = (data, actions) => {
buttonsSpinner.unblock(); buttonsSpinner.unblock();
smartButtonsOptions.init(actions);
}; };
const renderer = new Renderer(creditCardRenderer, PayPalCommerceGateway, onSmartButtonClick, onSmartButtonsInit, smartButtonsOptions); const renderer = new Renderer(creditCardRenderer, PayPalCommerceGateway, onSmartButtonClick, onSmartButtonsInit);
const messageRenderer = new MessageRenderer(PayPalCommerceGateway.messages); const messageRenderer = new MessageRenderer(PayPalCommerceGateway.messages);
const context = PayPalCommerceGateway.context; const context = PayPalCommerceGateway.context;
if (context === 'mini-cart' || context === 'product') { if (context === 'mini-cart' || context === 'product') {

View file

@ -1,12 +1,16 @@
import CartActionHandler from '../ActionHandler/CartActionHandler'; import CartActionHandler from '../ActionHandler/CartActionHandler';
import {setVisible} from "../Helper/Hiding"; import {setVisible} from "../Helper/Hiding";
import {disable} from "../Helper/ButtonDisabler"; import {disable, enable} from "../Helper/ButtonDisabler";
class CartBootstrap { class CartBootstrap {
constructor(gateway, renderer, errorHandler) { constructor(gateway, renderer, errorHandler) {
this.gateway = gateway; this.gateway = gateway;
this.renderer = renderer; this.renderer = renderer;
this.errorHandler = errorHandler; this.errorHandler = errorHandler;
this.renderer.onButtonsInit(this.gateway.button.wrapper, () => {
this.handleButtonStatus();
}, true);
} }
init() { init() {
@ -15,16 +19,11 @@ class CartBootstrap {
} }
this.render(); this.render();
this.handleButtonStatus();
if (!this.shouldEnable()) {
this.renderer.disableSmartButtons();
disable(this.gateway.button.wrapper);
disable(this.gateway.messages.wrapper);
return;
}
jQuery(document.body).on('updated_cart_totals updated_checkout', () => { jQuery(document.body).on('updated_cart_totals updated_checkout', () => {
this.render(); this.render();
this.handleButtonStatus();
fetch( fetch(
this.gateway.ajax.cart_script_params.endpoint, this.gateway.ajax.cart_script_params.endpoint,
@ -48,6 +47,18 @@ class CartBootstrap {
}); });
} }
handleButtonStatus() {
if (!this.shouldEnable()) {
this.renderer.disableSmartButtons(this.gateway.button.wrapper);
disable(this.gateway.button.wrapper);
disable(this.gateway.messages.wrapper);
return;
}
this.renderer.enableSmartButtons(this.gateway.button.wrapper);
enable(this.gateway.button.wrapper);
enable(this.gateway.messages.wrapper);
}
shouldRender() { shouldRender() {
return document.querySelector(this.gateway.button.wrapper) !== null; return document.querySelector(this.gateway.button.wrapper) !== null;
} }

View file

@ -5,7 +5,7 @@ import {
isSavedCardSelected, ORDER_BUTTON_SELECTOR, isSavedCardSelected, ORDER_BUTTON_SELECTOR,
PaymentMethods PaymentMethods
} from "../Helper/CheckoutMethodState"; } from "../Helper/CheckoutMethodState";
import {disable} from "../Helper/ButtonDisabler"; import {disable, enable} from "../Helper/ButtonDisabler";
class CheckoutBootstap { class CheckoutBootstap {
constructor(gateway, renderer, messages, spinner, errorHandler) { constructor(gateway, renderer, messages, spinner, errorHandler) {
@ -16,17 +16,15 @@ class CheckoutBootstap {
this.errorHandler = errorHandler; this.errorHandler = errorHandler;
this.standardOrderButtonSelector = ORDER_BUTTON_SELECTOR; this.standardOrderButtonSelector = ORDER_BUTTON_SELECTOR;
this.renderer.onButtonsInit(this.gateway.button.wrapper, () => {
this.handleButtonStatus();
}, true);
} }
init() { init() {
this.render(); this.render();
this.handleButtonStatus();
if (!this.shouldEnable()) {
this.renderer.disableSmartButtons();
disable(this.gateway.button.wrapper);
disable(this.gateway.messages.wrapper);
return;
}
// Unselect saved card. // Unselect saved card.
// WC saves form values, so with our current UI it would be a bit weird // WC saves form values, so with our current UI it would be a bit weird
@ -36,6 +34,7 @@ class CheckoutBootstap {
jQuery(document.body).on('updated_checkout', () => { jQuery(document.body).on('updated_checkout', () => {
this.render() this.render()
this.handleButtonStatus();
}); });
jQuery(document.body).on('updated_checkout payment_method_selected', () => { jQuery(document.body).on('updated_checkout payment_method_selected', () => {
@ -51,6 +50,18 @@ class CheckoutBootstap {
this.updateUi(); this.updateUi();
} }
handleButtonStatus() {
if (!this.shouldEnable()) {
this.renderer.disableSmartButtons(this.gateway.button.wrapper);
disable(this.gateway.button.wrapper);
disable(this.gateway.messages.wrapper);
return;
}
this.renderer.enableSmartButtons(this.gateway.button.wrapper);
enable(this.gateway.button.wrapper);
enable(this.gateway.messages.wrapper);
}
shouldRender() { shouldRender() {
if (document.querySelector(this.gateway.button.cancel_wrapper)) { if (document.querySelector(this.gateway.button.cancel_wrapper)) {
return false; return false;

View file

@ -1,5 +1,5 @@
import CartActionHandler from '../ActionHandler/CartActionHandler'; import CartActionHandler from '../ActionHandler/CartActionHandler';
import {disable} from "../Helper/ButtonDisabler"; import {disable, enable} from "../Helper/ButtonDisabler";
class MiniCartBootstap { class MiniCartBootstap {
constructor(gateway, renderer, errorHandler) { constructor(gateway, renderer, errorHandler) {
@ -16,17 +16,26 @@ class MiniCartBootstap {
this.errorHandler, this.errorHandler,
); );
this.render(); this.render();
this.handleButtonStatus();
if (!this.shouldEnable()) {
this.renderer.disableSmartButtons();
disable(this.gateway.button.wrapper);
disable(this.gateway.messages.wrapper);
return;
}
jQuery(document.body).on('wc_fragments_loaded wc_fragments_refreshed', () => { jQuery(document.body).on('wc_fragments_loaded wc_fragments_refreshed', () => {
this.render(); this.render();
this.handleButtonStatus();
}); });
this.renderer.onButtonsInit(this.gateway.button.mini_cart_wrapper, () => {
this.handleButtonStatus();
}, true);
}
handleButtonStatus() {
if (!this.shouldEnable()) {
this.renderer.disableSmartButtons(this.gateway.button.mini_cart_wrapper);
disable(this.gateway.button.mini_cart_wrapper);
return;
}
this.renderer.enableSmartButtons(this.gateway.button.mini_cart_wrapper);
enable(this.gateway.button.mini_cart_wrapper);
} }
shouldRender() { shouldRender() {
@ -36,7 +45,7 @@ class MiniCartBootstap {
shouldEnable() { shouldEnable() {
return this.shouldRender() return this.shouldRender()
&& this.gateway.button.is_disabled !== true; && this.gateway.button.is_mini_cart_disabled !== true;
} }
render() { render() {

View file

@ -12,11 +12,9 @@ class SingleProductBootstap {
this.mutationObserver = new MutationObserver(this.handleChange.bind(this)); this.mutationObserver = new MutationObserver(this.handleChange.bind(this));
this.formSelector = 'form.cart'; this.formSelector = 'form.cart';
if (this.renderer && this.renderer.smartButtonsOptions) { this.renderer.onButtonsInit(this.gateway.button.wrapper, () => {
this.renderer.smartButtonsOptions.onInit = () => {
this.handleChange(); this.handleChange();
}; }, true);
}
} }
form() { form() {
@ -25,7 +23,7 @@ class SingleProductBootstap {
handleChange() { handleChange() {
if (!this.shouldRender()) { if (!this.shouldRender()) {
this.renderer.disableSmartButtons(); this.renderer.disableSmartButtons(this.gateway.button.wrapper);
hide(this.gateway.button.wrapper, this.formSelector); hide(this.gateway.button.wrapper, this.formSelector);
hide(this.gateway.messages.wrapper); hide(this.gateway.messages.wrapper);
return; return;
@ -33,7 +31,7 @@ class SingleProductBootstap {
this.render(); this.render();
this.renderer.enableSmartButtons(); this.renderer.enableSmartButtons(this.gateway.button.wrapper);
show(this.gateway.button.wrapper); show(this.gateway.button.wrapper);
show(this.gateway.messages.wrapper); show(this.gateway.messages.wrapper);
@ -42,12 +40,12 @@ class SingleProductBootstap {
handleButtonStatus() { handleButtonStatus() {
if (!this.shouldEnable()) { if (!this.shouldEnable()) {
this.renderer.disableSmartButtons(); this.renderer.disableSmartButtons(this.gateway.button.wrapper);
disable(this.gateway.button.wrapper, this.formSelector); disable(this.gateway.button.wrapper, this.formSelector);
disable(this.gateway.messages.wrapper); disable(this.gateway.messages.wrapper);
return; return;
} }
this.renderer.enableSmartButtons(); this.renderer.enableSmartButtons(this.gateway.button.wrapper);
enable(this.gateway.button.wrapper); enable(this.gateway.button.wrapper);
enable(this.gateway.messages.wrapper); enable(this.gateway.messages.wrapper);
} }

View file

@ -1,12 +1,14 @@
import merge from "deepmerge"; import merge from "deepmerge";
class Renderer { class Renderer {
constructor(creditCardRenderer, defaultSettings, onSmartButtonClick, onSmartButtonsInit, smartButtonsOptions) { constructor(creditCardRenderer, defaultSettings, onSmartButtonClick, onSmartButtonsInit) {
this.defaultSettings = defaultSettings; this.defaultSettings = defaultSettings;
this.creditCardRenderer = creditCardRenderer; this.creditCardRenderer = creditCardRenderer;
this.onSmartButtonClick = onSmartButtonClick; this.onSmartButtonClick = onSmartButtonClick;
this.onSmartButtonsInit = onSmartButtonsInit; this.onSmartButtonsInit = onSmartButtonsInit;
this.smartButtonsOptions = smartButtonsOptions;
this.buttonsOptions = {};
this.onButtonsInitListeners = {};
this.renderedSources = new Set(); this.renderedSources = new Set();
} }
@ -78,7 +80,10 @@ class Renderer {
style, style,
...contextConfig, ...contextConfig,
onClick: this.onSmartButtonClick, onClick: this.onSmartButtonClick,
onInit: this.onSmartButtonsInit, onInit: (data, actions) => {
this.onSmartButtonsInit(data, actions);
this.handleOnButtonsInit(wrapper, data, actions);
},
}); });
if (!btn.isEligible()) { if (!btn.isEligible()) {
return; return;
@ -108,18 +113,42 @@ class Renderer {
this.creditCardRenderer.enableFields(); this.creditCardRenderer.enableFields();
} }
disableSmartButtons() { onButtonsInit(wrapper, handler, reset) {
if (!this.smartButtonsOptions || !this.smartButtonsOptions.actions) { this.onButtonsInitListeners[wrapper] = reset ? [] : (this.onButtonsInitListeners[wrapper] || []);
return; this.onButtonsInitListeners[wrapper].push(handler);
}
this.smartButtonsOptions.actions.disable();
} }
enableSmartButtons() { handleOnButtonsInit(wrapper, data, actions) {
if (!this.smartButtonsOptions || !this.smartButtonsOptions.actions) {
this.buttonsOptions[wrapper] = {
data: data,
actions: actions
}
if (this.onButtonsInitListeners[wrapper]) {
for (let handler of this.onButtonsInitListeners[wrapper]) {
if (typeof handler === 'function') {
handler({
wrapper: wrapper,
...this.buttonsOptions[wrapper]
});
}
}
}
}
disableSmartButtons(wrapper) {
if (!this.buttonsOptions[wrapper]) {
return; return;
} }
this.smartButtonsOptions.actions.enable(); this.buttonsOptions[wrapper].actions.disable();
}
enableSmartButtons(wrapper) {
if (!this.buttonsOptions[wrapper]) {
return;
}
this.buttonsOptions[wrapper].actions.enable();
} }
} }

View file

@ -858,9 +858,10 @@ class SmartButton implements SmartButtonInterface {
'payer' => $this->payerData(), 'payer' => $this->payerData(),
'button' => array( 'button' => array(
'wrapper' => '#ppc-button-' . PayPalGateway::ID, 'wrapper' => '#ppc-button-' . PayPalGateway::ID,
'mini_cart_wrapper' => '#ppc-button-minicart',
'cancel_wrapper' => '#ppcp-cancel',
'is_disabled' => $this->is_button_disabled(), 'is_disabled' => $this->is_button_disabled(),
'mini_cart_wrapper' => '#ppc-button-minicart',
'is_mini_cart_disabled' => $this->is_button_disabled( 'mini-cart' ),
'cancel_wrapper' => '#ppcp-cancel',
'mini_cart_style' => array( 'mini_cart_style' => array(
'layout' => $this->style_for_context( 'layout', 'mini-cart' ), 'layout' => $this->style_for_context( 'layout', 'mini-cart' ),
'color' => $this->style_for_context( 'color', 'mini-cart' ), 'color' => $this->style_for_context( 'color', 'mini-cart' ),
@ -1354,10 +1355,14 @@ class SmartButton implements SmartButtonInterface {
/** /**
* Checks if PayPal buttons/messages should be rendered for the current page. * Checks if PayPal buttons/messages should be rendered for the current page.
* *
* @param string|null $context The context that should be checked, use default otherwise.
*
* @return bool * @return bool
*/ */
protected function is_button_disabled(): bool { protected function is_button_disabled( string $context = null ): bool {
if ( null === $context ) {
$context = $this->context(); $context = $this->context();
}
if ( 'product' === $context ) { if ( 'product' === $context ) {
$product = wc_get_product(); $product = wc_get_product();
@ -1365,32 +1370,28 @@ class SmartButton implements SmartButtonInterface {
/** /**
* Allows to decide if the button should be disabled for a given product * Allows to decide if the button should be disabled for a given product
*/ */
if ( ( $isDisabled = apply_filters( $is_disabled = apply_filters(
'woocommerce_paypal_payments_product_button_disabled', 'woocommerce_paypal_payments_product_button_disabled',
null, null,
$product ) $product
) !== null) { );
return $isDisabled;
if ( $is_disabled !== null ) {
return $is_disabled;
}
} }
} else {
$filterName = 'woocommerce_paypal_payments_'
. str_replace('-', '_', $context)
. '_button_disabled';
/** /**
* Allows to decide if the button should be disabled in a given context * Allows to decide if the button should be disabled globally or on a given context
*/ */
if ( ( $isDisabled = apply_filters( $filterName, null ) ) !== null ) { $is_disabled = apply_filters(
return $isDisabled;
}
}
if ( ( $isDisabled = apply_filters(
'woocommerce_paypal_payments_button_disabled', 'woocommerce_paypal_payments_button_disabled',
null, null,
$context $context
) ) !== null ) { );
return $isDisabled;
if ( $is_disabled !== null ) {
return $is_disabled;
} }
return false; return false;