mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-06 13:44:42 +08:00
Merge pull request #1485 from woocommerce/PCP-1788-filter-to-conditionally-block-the-pay-pal-buttons
Filter to conditionally block the PayPal buttons (1788)
This commit is contained in:
commit
17a346cfc9
9 changed files with 199 additions and 48 deletions
|
@ -132,21 +132,10 @@ const bootstrap = () => {
|
|||
}
|
||||
};
|
||||
|
||||
let smartButtonsOptions = {
|
||||
onInit: null,
|
||||
init: function (actions) {
|
||||
this.actions = actions;
|
||||
if (typeof this.onInit === 'function') {
|
||||
this.onInit();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const onSmartButtonsInit = (data, actions) => {
|
||||
const onSmartButtonsInit = () => {
|
||||
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);
|
||||
if (context === 'mini-cart' || context === 'product') {
|
||||
if (PayPalCommerceGateway.mini_cart_buttons_enabled === '1') {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import CartActionHandler from '../ActionHandler/CartActionHandler';
|
||||
import BootstrapHelper from "../Helper/BootstrapHelper";
|
||||
import {setVisible} from "../Helper/Hiding";
|
||||
|
||||
class CartBootstrap {
|
||||
|
@ -6,6 +7,10 @@ class CartBootstrap {
|
|||
this.gateway = gateway;
|
||||
this.renderer = renderer;
|
||||
this.errorHandler = errorHandler;
|
||||
|
||||
this.renderer.onButtonsInit(this.gateway.button.wrapper, () => {
|
||||
this.handleButtonStatus();
|
||||
}, true);
|
||||
}
|
||||
|
||||
init() {
|
||||
|
@ -14,9 +19,11 @@ class CartBootstrap {
|
|||
}
|
||||
|
||||
this.render();
|
||||
this.handleButtonStatus();
|
||||
|
||||
jQuery(document.body).on('updated_cart_totals updated_checkout', () => {
|
||||
this.render();
|
||||
this.handleButtonStatus();
|
||||
|
||||
fetch(
|
||||
this.gateway.ajax.cart_script_params.endpoint,
|
||||
|
@ -40,10 +47,18 @@ class CartBootstrap {
|
|||
});
|
||||
}
|
||||
|
||||
handleButtonStatus() {
|
||||
BootstrapHelper.handleButtonStatus(this);
|
||||
}
|
||||
|
||||
shouldRender() {
|
||||
return document.querySelector(this.gateway.button.wrapper) !== null;
|
||||
}
|
||||
|
||||
shouldEnable() {
|
||||
return BootstrapHelper.shouldEnable(this);
|
||||
}
|
||||
|
||||
render() {
|
||||
const actionHandler = new CartActionHandler(
|
||||
PayPalCommerceGateway,
|
||||
|
|
|
@ -5,6 +5,8 @@ import {
|
|||
isSavedCardSelected, ORDER_BUTTON_SELECTOR,
|
||||
PaymentMethods
|
||||
} from "../Helper/CheckoutMethodState";
|
||||
import BootstrapHelper from "../Helper/BootstrapHelper";
|
||||
import {disable, enable} from "../Helper/ButtonDisabler";
|
||||
|
||||
class CheckoutBootstap {
|
||||
constructor(gateway, renderer, messages, spinner, errorHandler) {
|
||||
|
@ -15,10 +17,15 @@ class CheckoutBootstap {
|
|||
this.errorHandler = errorHandler;
|
||||
|
||||
this.standardOrderButtonSelector = ORDER_BUTTON_SELECTOR;
|
||||
|
||||
this.renderer.onButtonsInit(this.gateway.button.wrapper, () => {
|
||||
this.handleButtonStatus();
|
||||
}, true);
|
||||
}
|
||||
|
||||
init() {
|
||||
this.render();
|
||||
this.handleButtonStatus();
|
||||
|
||||
// Unselect saved card.
|
||||
// WC saves form values, so with our current UI it would be a bit weird
|
||||
|
@ -28,6 +35,7 @@ class CheckoutBootstap {
|
|||
|
||||
jQuery(document.body).on('updated_checkout', () => {
|
||||
this.render()
|
||||
this.handleButtonStatus();
|
||||
});
|
||||
|
||||
jQuery(document.body).on('updated_checkout payment_method_selected', () => {
|
||||
|
@ -43,6 +51,10 @@ class CheckoutBootstap {
|
|||
this.updateUi();
|
||||
}
|
||||
|
||||
handleButtonStatus() {
|
||||
BootstrapHelper.handleButtonStatus(this);
|
||||
}
|
||||
|
||||
shouldRender() {
|
||||
if (document.querySelector(this.gateway.button.cancel_wrapper)) {
|
||||
return false;
|
||||
|
@ -51,6 +63,10 @@ class CheckoutBootstap {
|
|||
return document.querySelector(this.gateway.button.wrapper) !== null || document.querySelector(this.gateway.hosted_fields.wrapper) !== null;
|
||||
}
|
||||
|
||||
shouldEnable() {
|
||||
return BootstrapHelper.shouldEnable(this);
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.shouldRender()) {
|
||||
return;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import CartActionHandler from '../ActionHandler/CartActionHandler';
|
||||
import BootstrapHelper from "../Helper/BootstrapHelper";
|
||||
|
||||
class MiniCartBootstap {
|
||||
constructor(gateway, renderer, errorHandler) {
|
||||
|
@ -15,9 +16,22 @@ class MiniCartBootstap {
|
|||
this.errorHandler,
|
||||
);
|
||||
this.render();
|
||||
this.handleButtonStatus();
|
||||
|
||||
jQuery(document.body).on('wc_fragments_loaded wc_fragments_refreshed', () => {
|
||||
this.render();
|
||||
this.handleButtonStatus();
|
||||
});
|
||||
|
||||
this.renderer.onButtonsInit(this.gateway.button.mini_cart_wrapper, () => {
|
||||
this.handleButtonStatus();
|
||||
}, true);
|
||||
}
|
||||
|
||||
handleButtonStatus() {
|
||||
BootstrapHelper.handleButtonStatus(this, {
|
||||
wrapper: this.gateway.button.mini_cart_wrapper,
|
||||
skipMessages: true
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -26,6 +40,12 @@ class MiniCartBootstap {
|
|||
|| document.querySelector(this.gateway.hosted_fields.mini_cart_wrapper) !== null;
|
||||
}
|
||||
|
||||
shouldEnable() {
|
||||
return BootstrapHelper.shouldEnable(this, {
|
||||
isDisabled: !!this.gateway.button.is_mini_cart_disabled
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.shouldRender()) {
|
||||
return;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import UpdateCart from "../Helper/UpdateCart";
|
||||
import SingleProductActionHandler from "../ActionHandler/SingleProductActionHandler";
|
||||
import {hide, show} from "../Helper/Hiding";
|
||||
import {disable, enable} from "../Helper/ButtonDisabler";
|
||||
import BootstrapHelper from "../Helper/BootstrapHelper";
|
||||
|
||||
class SingleProductBootstap {
|
||||
constructor(gateway, renderer, messages, errorHandler) {
|
||||
|
@ -12,11 +12,9 @@ class SingleProductBootstap {
|
|||
this.mutationObserver = new MutationObserver(this.handleChange.bind(this));
|
||||
this.formSelector = 'form.cart';
|
||||
|
||||
if (this.renderer && this.renderer.smartButtonsOptions) {
|
||||
this.renderer.smartButtonsOptions.onInit = () => {
|
||||
this.renderer.onButtonsInit(this.gateway.button.wrapper, () => {
|
||||
this.handleChange();
|
||||
};
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
form() {
|
||||
|
@ -25,7 +23,7 @@ class SingleProductBootstap {
|
|||
|
||||
handleChange() {
|
||||
if (!this.shouldRender()) {
|
||||
this.renderer.disableSmartButtons();
|
||||
this.renderer.disableSmartButtons(this.gateway.button.wrapper);
|
||||
hide(this.gateway.button.wrapper, this.formSelector);
|
||||
hide(this.gateway.messages.wrapper);
|
||||
return;
|
||||
|
@ -33,7 +31,7 @@ class SingleProductBootstap {
|
|||
|
||||
this.render();
|
||||
|
||||
this.renderer.enableSmartButtons();
|
||||
this.renderer.enableSmartButtons(this.gateway.button.wrapper);
|
||||
show(this.gateway.button.wrapper);
|
||||
show(this.gateway.messages.wrapper);
|
||||
|
||||
|
@ -41,15 +39,9 @@ class SingleProductBootstap {
|
|||
}
|
||||
|
||||
handleButtonStatus() {
|
||||
if (!this.shouldEnable()) {
|
||||
this.renderer.disableSmartButtons();
|
||||
disable(this.gateway.button.wrapper, this.formSelector);
|
||||
disable(this.gateway.messages.wrapper);
|
||||
return;
|
||||
}
|
||||
this.renderer.enableSmartButtons();
|
||||
enable(this.gateway.button.wrapper);
|
||||
enable(this.gateway.messages.wrapper);
|
||||
BootstrapHelper.handleButtonStatus(this, {
|
||||
formSelector: this.formSelector
|
||||
});
|
||||
}
|
||||
|
||||
init() {
|
||||
|
@ -94,7 +86,7 @@ class SingleProductBootstap {
|
|||
const form = this.form();
|
||||
const addToCartButton = form ? form.querySelector('.single_add_to_cart_button') : null;
|
||||
|
||||
return this.shouldRender()
|
||||
return BootstrapHelper.shouldEnable(this)
|
||||
&& !this.priceAmountIsZero()
|
||||
&& ((null === addToCartButton) || !addToCartButton.classList.contains('disabled'));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
import {disable, enable} from "./ButtonDisabler";
|
||||
|
||||
/**
|
||||
* Common Bootstrap methods to avoid code repetition.
|
||||
*/
|
||||
export default class BootstrapHelper {
|
||||
|
||||
static handleButtonStatus(bs, options) {
|
||||
options = options || {};
|
||||
options.wrapper = options.wrapper || bs.gateway.button.wrapper;
|
||||
options.messagesWrapper = options.messagesWrapper || bs.gateway.messages.wrapper;
|
||||
options.skipMessages = options.skipMessages || false;
|
||||
|
||||
if (!bs.shouldEnable()) {
|
||||
bs.renderer.disableSmartButtons(options.wrapper);
|
||||
disable(options.wrapper, options.formSelector || null);
|
||||
|
||||
if (!options.skipMessages) {
|
||||
disable(options.messagesWrapper);
|
||||
}
|
||||
return;
|
||||
}
|
||||
bs.renderer.enableSmartButtons(options.wrapper);
|
||||
enable(options.wrapper);
|
||||
|
||||
if (!options.skipMessages) {
|
||||
enable(options.messagesWrapper);
|
||||
}
|
||||
}
|
||||
|
||||
static shouldEnable(bs, options) {
|
||||
options = options || {};
|
||||
if (typeof options.isDisabled === 'undefined') {
|
||||
options.isDisabled = bs.gateway.button.is_disabled;
|
||||
}
|
||||
|
||||
return bs.shouldRender()
|
||||
&& options.isDisabled !== true;
|
||||
}
|
||||
}
|
|
@ -36,7 +36,10 @@ export const setEnabled = (selectorOrElement, enable, form = null) => {
|
|||
|
||||
if (form) {
|
||||
// Trigger form submit to show the error message
|
||||
jQuery(form).find(':submit').trigger('click');
|
||||
let $form = jQuery(form);
|
||||
if ($form.find('.single_add_to_cart_button').hasClass('disabled')) {
|
||||
$form.find(':submit').trigger('click');
|
||||
}
|
||||
}
|
||||
})
|
||||
.find('> *')
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
import merge from "deepmerge";
|
||||
|
||||
class Renderer {
|
||||
constructor(creditCardRenderer, defaultSettings, onSmartButtonClick, onSmartButtonsInit, smartButtonsOptions) {
|
||||
constructor(creditCardRenderer, defaultSettings, onSmartButtonClick, onSmartButtonsInit) {
|
||||
this.defaultSettings = defaultSettings;
|
||||
this.creditCardRenderer = creditCardRenderer;
|
||||
this.onSmartButtonClick = onSmartButtonClick;
|
||||
this.onSmartButtonsInit = onSmartButtonsInit;
|
||||
this.smartButtonsOptions = smartButtonsOptions;
|
||||
|
||||
this.buttonsOptions = {};
|
||||
this.onButtonsInitListeners = {};
|
||||
|
||||
this.renderedSources = new Set();
|
||||
}
|
||||
|
@ -78,7 +80,10 @@ class Renderer {
|
|||
style,
|
||||
...contextConfig,
|
||||
onClick: this.onSmartButtonClick,
|
||||
onInit: this.onSmartButtonsInit,
|
||||
onInit: (data, actions) => {
|
||||
this.onSmartButtonsInit(data, actions);
|
||||
this.handleOnButtonsInit(wrapper, data, actions);
|
||||
},
|
||||
});
|
||||
if (!btn.isEligible()) {
|
||||
return;
|
||||
|
@ -108,18 +113,42 @@ class Renderer {
|
|||
this.creditCardRenderer.enableFields();
|
||||
}
|
||||
|
||||
disableSmartButtons() {
|
||||
if (!this.smartButtonsOptions || !this.smartButtonsOptions.actions) {
|
||||
return;
|
||||
}
|
||||
this.smartButtonsOptions.actions.disable();
|
||||
onButtonsInit(wrapper, handler, reset) {
|
||||
this.onButtonsInitListeners[wrapper] = reset ? [] : (this.onButtonsInitListeners[wrapper] || []);
|
||||
this.onButtonsInitListeners[wrapper].push(handler);
|
||||
}
|
||||
|
||||
enableSmartButtons() {
|
||||
if (!this.smartButtonsOptions || !this.smartButtonsOptions.actions) {
|
||||
handleOnButtonsInit(wrapper, data, 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;
|
||||
}
|
||||
this.smartButtonsOptions.actions.enable();
|
||||
this.buttonsOptions[wrapper].actions.disable();
|
||||
}
|
||||
|
||||
enableSmartButtons(wrapper) {
|
||||
if (!this.buttonsOptions[wrapper]) {
|
||||
return;
|
||||
}
|
||||
this.buttonsOptions[wrapper].actions.enable();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -868,7 +868,9 @@ class SmartButton implements SmartButtonInterface {
|
|||
'payer' => $this->payerData(),
|
||||
'button' => array(
|
||||
'wrapper' => '#ppc-button-' . PayPalGateway::ID,
|
||||
'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(
|
||||
'layout' => $this->style_for_context( 'layout', 'mini-cart' ),
|
||||
|
@ -1361,6 +1363,51 @@ class SmartButton implements SmartButtonInterface {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
protected function is_button_disabled( string $context = null ): bool {
|
||||
if ( null === $context ) {
|
||||
$context = $this->context();
|
||||
}
|
||||
|
||||
if ( 'product' === $context ) {
|
||||
$product = wc_get_product();
|
||||
|
||||
/**
|
||||
* Allows to decide if the button should be disabled for a given product
|
||||
*/
|
||||
$is_disabled = apply_filters(
|
||||
'woocommerce_paypal_payments_product_buttons_disabled',
|
||||
null,
|
||||
$product
|
||||
);
|
||||
|
||||
if ( $is_disabled !== null ) {
|
||||
return $is_disabled;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to decide if the button should be disabled globally or on a given context
|
||||
*/
|
||||
$is_disabled = apply_filters(
|
||||
'woocommerce_paypal_payments_buttons_disabled',
|
||||
null,
|
||||
$context
|
||||
);
|
||||
|
||||
if ( $is_disabled !== null ) {
|
||||
return $is_disabled;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all payment tokens for the user, via API or cached if already queried.
|
||||
*
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue