diff --git a/modules/ppcp-settings/node_modules/.gitkeep b/modules/ppcp-settings/node_modules/.gitkeep
deleted file mode 100644
index e69de29bb..000000000
diff --git a/modules/ppcp-settings/package.json b/modules/ppcp-settings/package.json
index 94018d509..dfcad023c 100644
--- a/modules/ppcp-settings/package.json
+++ b/modules/ppcp-settings/package.json
@@ -15,6 +15,7 @@
"dependencies": {
"@paypal/paypal-js": "^8.1.2",
"@woocommerce/settings": "^1.0.0",
+ "deepmerge": "^4.3.1",
"react-select": "^5.8.3"
}
}
diff --git a/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabStyling.js b/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabStyling.js
index d3eff525b..4eafbb665 100644
--- a/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabStyling.js
+++ b/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabStyling.js
@@ -2,6 +2,7 @@ import { __, sprintf } from '@wordpress/i18n';
import { SelectControl, RadioControl } from '@wordpress/components';
import { PayPalCheckboxGroup } from '../../ReusableComponents/Fields';
import { useState, useMemo, useEffect } from '@wordpress/element';
+import Renderer from '../../../../../../ppcp-button/resources/js/modules/Renderer/Renderer';
import {
defaultLocationSettings,
paymentMethodOptions,
@@ -10,7 +11,6 @@ import {
buttonLayoutOptions,
buttonLabelOptions,
} from '../../../data/settings/tab-styling-data';
-import Renderer from '../../../utils/renderer';
const TabStyling = () => {
useEffect( () => {
@@ -178,11 +178,8 @@ const TabStyling = () => {
) }
-
);
@@ -229,28 +226,73 @@ const SectionIntro = () => {
};
const generatePreview = () => {
- const settings = {
- button: {
- wrapper: '#ppcp-r-styling-preview',
- style: {
- color: 'gold',
- shape: 'rect',
- label: 'paypal',
- tagline: false,
- layout: 'horizontal',
+ const render = () => {
+ const settings = {
+ button: {
+ wrapper: '#ppcp-r-styling-preview',
+ style: {
+ color: 'gold',
+ shape: 'rect',
+ label: 'paypal',
+ tagline: false,
+ layout: 'horizontal',
+ },
},
- },
- separate_buttons: {},
+ separate_buttons: {},
+ };
+ const wrapperSelector =
+ Object.values( settings.separate_buttons ).length > 0
+ ? Object.values( settings.separate_buttons )[ 0 ].wrapper
+ : settings.button.wrapper;
+ const wrapper = document.querySelector( wrapperSelector );
+ if ( ! wrapper ) {
+ return;
+ }
+ wrapper.innerHTML = '';
+
+ const renderer = new Renderer(
+ null,
+ settings,
+ ( data, actions ) => actions.reject(),
+ null
+ );
+
+ try {
+ renderer.render( {} );
+ jQuery( document ).trigger(
+ 'ppcp_paypal_render_preview',
+ settings
+ );
+ } catch ( err ) {
+ console.error( err );
+ }
};
- const renderer = new Renderer(
- null,
- settings,
- ( data, actions ) => actions.reject(),
- null
- );
- jQuery( document ).trigger( 'ppcp_paypal_render_preview', settings );
- renderer.render( {} );
+ renderPreview( () => {
+ console.log( 'CALLBACK' );
+ }, render );
};
+function renderPreview( settingsCallback, render ) {
+ let oldSettings = settingsCallback();
+ const form = jQuery( '#mainform' );
+ form.on( 'change', ':input', () => {
+ const newSettings = settingsCallback();
+ if ( JSON.stringify( oldSettings ) === JSON.stringify( newSettings ) ) {
+ return;
+ }
+
+ render( newSettings );
+
+ oldSettings = newSettings;
+ } );
+
+ jQuery( document ).on( 'ppcp_paypal_script_loaded', () => {
+ oldSettings = settingsCallback();
+
+ render( oldSettings );
+ } );
+
+ render( oldSettings );
+}
export default TabStyling;
diff --git a/modules/ppcp-settings/resources/js/utils/Helper/ApmButtons.js b/modules/ppcp-settings/resources/js/utils/Helper/ApmButtons.js
deleted file mode 100644
index 385432357..000000000
--- a/modules/ppcp-settings/resources/js/utils/Helper/ApmButtons.js
+++ /dev/null
@@ -1,129 +0,0 @@
-export const apmButtonsInit = ( config, selector = '.ppcp-button-apm' ) => {
- let selectorInContainer = selector;
-
- if ( window.ppcpApmButtons ) {
- return;
- }
-
- if ( config && config.button ) {
- // If it's separate gateways, modify wrapper to account for the individual buttons as individual APMs.
- const wrapper = config.button.wrapper;
- const isSeparateGateways =
- jQuery( wrapper ).children( 'div[class^="item-"]' ).length > 0;
-
- if ( isSeparateGateways ) {
- selector += `, ${ wrapper } div[class^="item-"]`;
- selectorInContainer += `, div[class^="item-"]`;
- }
- }
-
- window.ppcpApmButtons = new ApmButtons( selector, selectorInContainer );
-};
-
-export class ApmButtons {
- constructor( selector, selectorInContainer ) {
- this.selector = selector;
- this.selectorInContainer = selectorInContainer;
- this.containers = [];
-
- // Reloads button containers.
- this.reloadContainers();
-
- // Refresh button layout.
- jQuery( window )
- .resize( () => {
- this.refresh();
- } )
- .resize();
-
- jQuery( document ).on( 'ppcp-smart-buttons-init', () => {
- this.refresh();
- } );
-
- jQuery( document ).on(
- 'ppcp-shown ppcp-hidden ppcp-enabled ppcp-disabled',
- ( ev, data ) => {
- this.refresh();
- setTimeout( this.refresh.bind( this ), 200 );
- }
- );
-
- // Observes for new buttons.
- new MutationObserver(
- this.observeElementsCallback.bind( this )
- ).observe( document.body, { childList: true, subtree: true } );
- }
-
- observeElementsCallback( mutationsList, observer ) {
- const observeSelector =
- this.selector +
- ', .widget_shopping_cart, .widget_shopping_cart_content';
-
- let shouldReload = false;
- for ( const mutation of mutationsList ) {
- if ( mutation.type === 'childList' ) {
- mutation.addedNodes.forEach( ( node ) => {
- if ( node.matches && node.matches( observeSelector ) ) {
- shouldReload = true;
- }
- } );
- }
- }
-
- if ( shouldReload ) {
- this.reloadContainers();
- this.refresh();
- }
- }
-
- reloadContainers() {
- jQuery( this.selector ).each( ( index, el ) => {
- const parent = jQuery( el ).parent();
- if ( ! this.containers.some( ( $el ) => $el.is( parent ) ) ) {
- this.containers.push( parent );
- }
- } );
- }
-
- refresh() {
- for ( const container of this.containers ) {
- const $container = jQuery( container );
-
- // Check width and add classes
- const width = $container.width();
-
- $container.removeClass(
- 'ppcp-width-500 ppcp-width-300 ppcp-width-min'
- );
-
- if ( width >= 500 ) {
- $container.addClass( 'ppcp-width-500' );
- } else if ( width >= 300 ) {
- $container.addClass( 'ppcp-width-300' );
- } else {
- $container.addClass( 'ppcp-width-min' );
- }
-
- // Check first apm button
- const $firstElement = $container.children( ':visible' ).first();
-
- // Assign margins to buttons
- $container.find( this.selectorInContainer ).each( ( index, el ) => {
- const $el = jQuery( el );
-
- if ( $el.is( $firstElement ) ) {
- $el.css( 'margin-top', `0px` );
- return true;
- }
-
- const minMargin = 11; // Minimum margin.
- const height = $el.height();
- const margin = Math.max(
- minMargin,
- Math.round( height * 0.3 )
- );
- $el.css( 'margin-top', `${ margin }px` );
- } );
- }
- }
-}
diff --git a/modules/ppcp-settings/resources/js/utils/Helper/BootstrapHelper.js b/modules/ppcp-settings/resources/js/utils/Helper/BootstrapHelper.js
deleted file mode 100644
index f30b2ade6..000000000
--- a/modules/ppcp-settings/resources/js/utils/Helper/BootstrapHelper.js
+++ /dev/null
@@ -1,54 +0,0 @@
-import { disable, enable, isDisabled } from './ButtonDisabler';
-import merge from 'deepmerge';
-
-/**
- * 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;
-
- const wasDisabled = isDisabled( options.wrapper );
- const shouldEnable = bs.shouldEnable();
-
- // Handle enable / disable
- if ( shouldEnable && wasDisabled ) {
- bs.renderer.enableSmartButtons( options.wrapper );
- enable( options.wrapper );
- } else if ( ! shouldEnable && ! wasDisabled ) {
- bs.renderer.disableSmartButtons( options.wrapper );
- disable( options.wrapper, options.formSelector || null );
- }
-
- if ( wasDisabled !== ! shouldEnable ) {
- jQuery( options.wrapper ).trigger( 'ppcp_buttons_enabled_changed', [
- shouldEnable,
- ] );
- }
- }
-
- static shouldEnable( bs, options ) {
- options = options || {};
- if ( typeof options.isDisabled === 'undefined' ) {
- options.isDisabled = bs.gateway.button.is_disabled;
- }
-
- return bs.shouldRender() && options.isDisabled !== true;
- }
-
- static updateScriptData( bs, newData ) {
- const newObj = merge( bs.gateway, newData );
-
- const isChanged =
- JSON.stringify( bs.gateway ) !== JSON.stringify( newObj );
-
- bs.gateway = newObj;
-
- if ( isChanged ) {
- jQuery( document.body ).trigger( 'ppcp_script_data_changed', [
- newObj,
- ] );
- }
- }
-}
diff --git a/modules/ppcp-settings/resources/js/utils/Helper/ButtonDisabler.js b/modules/ppcp-settings/resources/js/utils/Helper/ButtonDisabler.js
deleted file mode 100644
index 30cc3f31b..000000000
--- a/modules/ppcp-settings/resources/js/utils/Helper/ButtonDisabler.js
+++ /dev/null
@@ -1,86 +0,0 @@
-/**
- * @param selectorOrElement
- * @return {Element}
- */
-const getElement = ( selectorOrElement ) => {
- if ( typeof selectorOrElement === 'string' ) {
- return document.querySelector( selectorOrElement );
- }
- return selectorOrElement;
-};
-
-const triggerEnabled = ( selectorOrElement, element ) => {
- jQuery( document ).trigger( 'ppcp-enabled', {
- handler: 'ButtonsDisabler.setEnabled',
- action: 'enable',
- selector: selectorOrElement,
- element,
- } );
-};
-
-const triggerDisabled = ( selectorOrElement, element ) => {
- jQuery( document ).trigger( 'ppcp-disabled', {
- handler: 'ButtonsDisabler.setEnabled',
- action: 'disable',
- selector: selectorOrElement,
- element,
- } );
-};
-
-export const setEnabled = ( selectorOrElement, enable, form = null ) => {
- const element = getElement( selectorOrElement );
-
- if ( ! element ) {
- return;
- }
-
- if ( enable ) {
- jQuery( element )
- .removeClass( 'ppcp-disabled' )
- .off( 'mouseup' )
- .find( '> *' )
- .css( 'pointer-events', '' );
-
- triggerEnabled( selectorOrElement, element );
- } else {
- jQuery( element )
- .addClass( 'ppcp-disabled' )
- .on( 'mouseup', function ( event ) {
- event.stopImmediatePropagation();
-
- if ( form ) {
- // Trigger form submit to show the error message
- const $form = jQuery( form );
- if (
- $form
- .find( '.single_add_to_cart_button' )
- .hasClass( 'disabled' )
- ) {
- $form.find( ':submit' ).trigger( 'click' );
- }
- }
- } )
- .find( '> *' )
- .css( 'pointer-events', 'none' );
-
- triggerDisabled( selectorOrElement, element );
- }
-};
-
-export const isDisabled = ( selectorOrElement ) => {
- const element = getElement( selectorOrElement );
-
- if ( ! element ) {
- return false;
- }
-
- return jQuery( element ).hasClass( 'ppcp-disabled' );
-};
-
-export const disable = ( selectorOrElement, form = null ) => {
- setEnabled( selectorOrElement, false, form );
-};
-
-export const enable = ( selectorOrElement ) => {
- setEnabled( selectorOrElement, true );
-};
diff --git a/modules/ppcp-settings/resources/js/utils/Helper/ButtonRefreshHelper.js b/modules/ppcp-settings/resources/js/utils/Helper/ButtonRefreshHelper.js
deleted file mode 100644
index 7620547c0..000000000
--- a/modules/ppcp-settings/resources/js/utils/Helper/ButtonRefreshHelper.js
+++ /dev/null
@@ -1,46 +0,0 @@
-import { debounce } from '../../../../../ppcp-blocks/resources/js/Helper/debounce';
-
-const REFRESH_BUTTON_EVENT = 'ppcp_refresh_payment_buttons';
-
-/**
- * Triggers a refresh of the payment buttons.
- * This function dispatches a custom event that the button components listen for.
- *
- * Use this function on the front-end to update payment buttons after the checkout form was updated.
- */
-export function refreshButtons() {
- document.dispatchEvent( new Event( REFRESH_BUTTON_EVENT ) );
-}
-
-/**
- * Sets up event listeners for various cart and checkout update events.
- * When these events occur, it triggers a refresh of the payment buttons.
- *
- * @param {Function} refresh - Callback responsible to re-render the payment button.
- */
-export function setupButtonEvents( refresh ) {
- const miniCartInitDelay = 1000;
- const debouncedRefresh = debounce( refresh, 50 );
-
- // Listen for our custom refresh event.
- document.addEventListener( REFRESH_BUTTON_EVENT, debouncedRefresh );
-
- // Listen for cart and checkout update events.
- // Note: we need jQuery here, because WooCommerce uses jQuery.trigger() to dispatch the events.
- window
- .jQuery( 'body' )
- .on( 'updated_cart_totals', debouncedRefresh )
- .on( 'updated_checkout', debouncedRefresh );
-
- // Use setTimeout for fragment events to avoid unnecessary refresh on initial render.
- setTimeout( () => {
- document.body.addEventListener(
- 'wc_fragments_loaded',
- debouncedRefresh
- );
- document.body.addEventListener(
- 'wc_fragments_refreshed',
- debouncedRefresh
- );
- }, miniCartInitDelay );
-}
diff --git a/modules/ppcp-settings/resources/js/utils/Helper/CartHelper.js b/modules/ppcp-settings/resources/js/utils/Helper/CartHelper.js
deleted file mode 100644
index 746df7b40..000000000
--- a/modules/ppcp-settings/resources/js/utils/Helper/CartHelper.js
+++ /dev/null
@@ -1,77 +0,0 @@
-class CartHelper {
- constructor( cartItemKeys = [] ) {
- this.cartItemKeys = cartItemKeys;
- }
-
- getEndpoint() {
- let ajaxUrl = '/?wc-ajax=%%endpoint%%';
-
- if (
- typeof wc_cart_fragments_params !== 'undefined' &&
- wc_cart_fragments_params.wc_ajax_url
- ) {
- ajaxUrl = wc_cart_fragments_params.wc_ajax_url;
- }
-
- return ajaxUrl.toString().replace( '%%endpoint%%', 'remove_from_cart' );
- }
-
- addFromPurchaseUnits( purchaseUnits ) {
- for ( const purchaseUnit of purchaseUnits || [] ) {
- for ( const item of purchaseUnit.items || [] ) {
- if ( ! item.cart_item_key ) {
- continue;
- }
- this.cartItemKeys.push( item.cart_item_key );
- }
- }
-
- return this;
- }
-
- removeFromCart() {
- return new Promise( ( resolve, reject ) => {
- if ( ! this.cartItemKeys || ! this.cartItemKeys.length ) {
- resolve();
- return;
- }
-
- const numRequests = this.cartItemKeys.length;
- let numResponses = 0;
-
- const tryToResolve = () => {
- numResponses++;
- if ( numResponses >= numRequests ) {
- resolve();
- }
- };
-
- for ( const cartItemKey of this.cartItemKeys ) {
- const params = new URLSearchParams();
- params.append( 'cart_item_key', cartItemKey );
-
- if ( ! cartItemKey ) {
- tryToResolve();
- continue;
- }
-
- fetch( this.getEndpoint(), {
- method: 'POST',
- credentials: 'same-origin',
- body: params,
- } )
- .then( function ( res ) {
- return res.json();
- } )
- .then( () => {
- tryToResolve();
- } )
- .catch( () => {
- tryToResolve();
- } );
- }
- } );
- }
-}
-
-export default CartHelper;
diff --git a/modules/ppcp-settings/resources/js/utils/Helper/CheckoutFormValidation.js b/modules/ppcp-settings/resources/js/utils/Helper/CheckoutFormValidation.js
deleted file mode 100644
index 26070ecf2..000000000
--- a/modules/ppcp-settings/resources/js/utils/Helper/CheckoutFormValidation.js
+++ /dev/null
@@ -1,55 +0,0 @@
-import Spinner from './Spinner';
-import FormValidator from './FormValidator';
-import ErrorHandler from '../ErrorHandler';
-
-const validateCheckoutForm = function ( config ) {
- return new Promise( async ( resolve, reject ) => {
- try {
- const spinner = new Spinner();
- const errorHandler = new ErrorHandler(
- config.labels.error.generic,
- document.querySelector( '.woocommerce-notices-wrapper' )
- );
-
- const formSelector =
- config.context === 'checkout'
- ? 'form.checkout'
- : 'form#order_review';
- const formValidator = config.early_checkout_validation_enabled
- ? new FormValidator(
- config.ajax.validate_checkout.endpoint,
- config.ajax.validate_checkout.nonce
- )
- : null;
-
- if ( ! formValidator ) {
- resolve();
- return;
- }
-
- formValidator
- .validate( document.querySelector( formSelector ) )
- .then( ( errors ) => {
- if ( errors.length > 0 ) {
- spinner.unblock();
- errorHandler.clear();
- errorHandler.messages( errors );
-
- // fire WC event for other plugins
- jQuery( document.body ).trigger( 'checkout_error', [
- errorHandler.currentHtml(),
- ] );
-
- reject();
- } else {
- resolve();
- }
- } );
- } catch ( error ) {
- console.error( error );
- reject();
- }
- } );
-};
-
-export default validateCheckoutForm;
diff --git a/modules/ppcp-settings/resources/js/utils/Helper/CheckoutMethodState.js b/modules/ppcp-settings/resources/js/utils/Helper/CheckoutMethodState.js
deleted file mode 100644
index 4275e48d4..000000000
--- a/modules/ppcp-settings/resources/js/utils/Helper/CheckoutMethodState.js
+++ /dev/null
@@ -1,48 +0,0 @@
-export const PaymentMethods = {
- PAYPAL: 'ppcp-gateway',
- CARDS: 'ppcp-credit-card-gateway',
- OXXO: 'ppcp-oxxo-gateway',
- CARD_BUTTON: 'ppcp-card-button-gateway',
- GOOGLEPAY: 'ppcp-googlepay',
- APPLEPAY: 'ppcp-applepay',
-};
-
-/**
- * List of valid context values that the button can have.
- *
- * The "context" describes the placement or page where a payment button might be displayed.
- *
- * @type {Object}
- */
-export const PaymentContext = {
- Cart: 'cart', // Classic cart.
- Checkout: 'checkout', // Classic checkout.
- BlockCart: 'cart-block', // Block cart.
- BlockCheckout: 'checkout-block', // Block checkout.
- Product: 'product', // Single product page.
- MiniCart: 'mini-cart', // Mini cart available on all pages except checkout & cart.
- PayNow: 'pay-now', // Pay for order, via admin generated link.
- Preview: 'preview', // Layout preview on settings page.
-
- // Contexts that use blocks to render payment methods.
- Blocks: [ 'cart-block', 'checkout-block' ],
-
- // Contexts that display "classic" payment gateways.
- Gateways: [ 'checkout', 'pay-now' ],
-};
-
-export const ORDER_BUTTON_SELECTOR = '#place_order';
-
-export const getCurrentPaymentMethod = () => {
- const el = document.querySelector( 'input[name="payment_method"]:checked' );
- if ( ! el ) {
- return null;
- }
-
- return el.value;
-};
-
-export const isSavedCardSelected = () => {
- const savedCardList = document.querySelector( '#saved-credit-card' );
- return savedCardList && savedCardList.value !== '';
-};
diff --git a/modules/ppcp-settings/resources/js/utils/Helper/ConfigProcessor.js b/modules/ppcp-settings/resources/js/utils/Helper/ConfigProcessor.js
deleted file mode 100644
index b8736d0e1..000000000
--- a/modules/ppcp-settings/resources/js/utils/Helper/ConfigProcessor.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import merge from 'deepmerge';
-import { v4 as uuidv4 } from 'uuid';
-import { keysToCamelCase } from './Utils';
-
-const processAxoConfig = ( config ) => {
- const scriptOptions = {};
- const sdkClientToken = config?.axo?.sdk_client_token;
- const uuid = uuidv4().replace( /-/g, '' );
- if ( sdkClientToken && config?.user?.is_logged !== true ) {
- scriptOptions[ 'data-sdk-client-token' ] = sdkClientToken;
- scriptOptions[ 'data-client-metadata-id' ] = uuid;
- }
- return scriptOptions;
-};
-
-const processUserIdToken = ( config ) => {
- const userIdToken = config?.save_payment_methods?.id_token;
- return userIdToken && config?.user?.is_logged === true
- ? { 'data-user-id-token': userIdToken }
- : {};
-};
-
-export const processConfig = ( config ) => {
- let scriptOptions = keysToCamelCase( config.url_params );
- if ( config.script_attributes ) {
- scriptOptions = merge( scriptOptions, config.script_attributes );
- }
- const axoOptions = processAxoConfig( config );
- const userIdTokenOptions = processUserIdToken( config );
- return merge.all( [ scriptOptions, axoOptions, userIdTokenOptions ] );
-};
diff --git a/modules/ppcp-settings/resources/js/utils/Helper/DccInputFactory.js b/modules/ppcp-settings/resources/js/utils/Helper/DccInputFactory.js
deleted file mode 100644
index 114c9102e..000000000
--- a/modules/ppcp-settings/resources/js/utils/Helper/DccInputFactory.js
+++ /dev/null
@@ -1,21 +0,0 @@
-const dccInputFactory = ( original ) => {
- const styles = window.getComputedStyle( original );
- const newElement = document.createElement( 'span' );
-
- newElement.setAttribute( 'id', original.id );
- newElement.setAttribute( 'class', original.className );
-
- Object.values( styles ).forEach( ( prop ) => {
- if (
- ! styles[ prop ] ||
- ! isNaN( prop ) ||
- prop === 'background-image'
- ) {
- return;
- }
- newElement.style.setProperty( prop, '' + styles[ prop ] );
- } );
- return newElement;
-};
-
-export default dccInputFactory;
diff --git a/modules/ppcp-settings/resources/js/utils/Helper/FormHelper.js b/modules/ppcp-settings/resources/js/utils/Helper/FormHelper.js
deleted file mode 100644
index 0fc5cdbe4..000000000
--- a/modules/ppcp-settings/resources/js/utils/Helper/FormHelper.js
+++ /dev/null
@@ -1,52 +0,0 @@
-/**
- * Common Form utility methods
- */
-export default class FormHelper {
- static getPrefixedFields( formElement, prefix ) {
- const formData = new FormData( formElement );
- const fields = {};
-
- for ( const [ name, value ] of formData.entries() ) {
- if ( ! prefix || name.startsWith( prefix ) ) {
- fields[ name ] = value;
- }
- }
-
- return fields;
- }
-
- static getFilteredFields( formElement, exactFilters, prefixFilters ) {
- const formData = new FormData( formElement );
- const fields = {};
- const counters = {};
-
- for ( let [ name, value ] of formData.entries() ) {
- // Handle array format
- if ( name.indexOf( '[]' ) !== -1 ) {
- const k = name;
- counters[ k ] = counters[ k ] || 0;
- name = name.replace( '[]', `[${ counters[ k ] }]` );
- counters[ k ]++;
- }
-
- if ( ! name ) {
- continue;
- }
- if ( exactFilters && exactFilters.indexOf( name ) !== -1 ) {
- continue;
- }
- if (
- prefixFilters &&
- prefixFilters.some( ( prefixFilter ) =>
- name.startsWith( prefixFilter )
- )
- ) {
- continue;
- }
-
- fields[ name ] = value;
- }
-
- return fields;
- }
-}
diff --git a/modules/ppcp-settings/resources/js/utils/Helper/FormSaver.js b/modules/ppcp-settings/resources/js/utils/Helper/FormSaver.js
deleted file mode 100644
index dfc27ceff..000000000
--- a/modules/ppcp-settings/resources/js/utils/Helper/FormSaver.js
+++ /dev/null
@@ -1,28 +0,0 @@
-export default class FormSaver {
- constructor( url, nonce ) {
- this.url = url;
- this.nonce = nonce;
- }
-
- async save( form ) {
- const formData = new FormData( form );
-
- const res = await fetch( this.url, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- credentials: 'same-origin',
- body: JSON.stringify( {
- nonce: this.nonce,
- form_encoded: new URLSearchParams( formData ).toString(),
- } ),
- } );
-
- const data = await res.json();
-
- if ( ! data.success ) {
- throw Error( data.data.message );
- }
- }
-}
diff --git a/modules/ppcp-settings/resources/js/utils/Helper/FormValidator.js b/modules/ppcp-settings/resources/js/utils/Helper/FormValidator.js
deleted file mode 100644
index 01fdfa20b..000000000
--- a/modules/ppcp-settings/resources/js/utils/Helper/FormValidator.js
+++ /dev/null
@@ -1,37 +0,0 @@
-export default class FormValidator {
- constructor( url, nonce ) {
- this.url = url;
- this.nonce = nonce;
- }
-
- async validate( form ) {
- const formData = new FormData( form );
-
- const res = await fetch( this.url, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- credentials: 'same-origin',
- body: JSON.stringify( {
- nonce: this.nonce,
- form_encoded: new URLSearchParams( formData ).toString(),
- } ),
- } );
-
- const data = await res.json();
-
- if ( ! data.success ) {
- if ( data.data.refresh ) {
- jQuery( document.body ).trigger( 'update_checkout' );
- }
-
- if ( data.data.errors ) {
- return data.data.errors;
- }
- throw Error( data.data.message );
- }
-
- return [];
- }
-}
diff --git a/modules/ppcp-settings/resources/js/utils/Helper/Hiding.js b/modules/ppcp-settings/resources/js/utils/Helper/Hiding.js
deleted file mode 100644
index e5b937a52..000000000
--- a/modules/ppcp-settings/resources/js/utils/Helper/Hiding.js
+++ /dev/null
@@ -1,92 +0,0 @@
-/**
- * @param selectorOrElement
- * @return {Element}
- */
-const getElement = ( selectorOrElement ) => {
- if ( typeof selectorOrElement === 'string' ) {
- return document.querySelector( selectorOrElement );
- }
- return selectorOrElement;
-};
-
-const triggerHidden = ( handler, selectorOrElement, element ) => {
- jQuery( document ).trigger( 'ppcp-hidden', {
- handler,
- action: 'hide',
- selector: selectorOrElement,
- element,
- } );
-};
-
-const triggerShown = ( handler, selectorOrElement, element ) => {
- jQuery( document ).trigger( 'ppcp-shown', {
- handler,
- action: 'show',
- selector: selectorOrElement,
- element,
- } );
-};
-
-export const isVisible = ( element ) => {
- return !! (
- element.offsetWidth ||
- element.offsetHeight ||
- element.getClientRects().length
- );
-};
-
-export const setVisible = ( selectorOrElement, show, important = false ) => {
- const element = getElement( selectorOrElement );
- if ( ! element ) {
- return;
- }
-
- const currentValue = element.style.getPropertyValue( 'display' );
-
- if ( ! show ) {
- if ( currentValue === 'none' ) {
- return;
- }
-
- element.style.setProperty(
- 'display',
- 'none',
- important ? 'important' : ''
- );
- triggerHidden( 'Hiding.setVisible', selectorOrElement, element );
- } else {
- if ( currentValue === 'none' ) {
- element.style.removeProperty( 'display' );
- triggerShown( 'Hiding.setVisible', selectorOrElement, element );
- }
-
- // still not visible (if something else added display: none in CSS)
- if ( ! isVisible( element ) ) {
- element.style.setProperty( 'display', 'block' );
- triggerShown( 'Hiding.setVisible', selectorOrElement, element );
- }
- }
-};
-
-export const setVisibleByClass = ( selectorOrElement, show, hiddenClass ) => {
- const element = getElement( selectorOrElement );
- if ( ! element ) {
- return;
- }
-
- if ( show ) {
- element.classList.remove( hiddenClass );
- triggerShown( 'Hiding.setVisibleByClass', selectorOrElement, element );
- } else {
- element.classList.add( hiddenClass );
- triggerHidden( 'Hiding.setVisibleByClass', selectorOrElement, element );
- }
-};
-
-export const hide = ( selectorOrElement, important = false ) => {
- setVisible( selectorOrElement, false, important );
-};
-
-export const show = ( selectorOrElement ) => {
- setVisible( selectorOrElement, true );
-};
diff --git a/modules/ppcp-settings/resources/js/utils/Helper/LocalStorage.js b/modules/ppcp-settings/resources/js/utils/Helper/LocalStorage.js
deleted file mode 100644
index 65494369e..000000000
--- a/modules/ppcp-settings/resources/js/utils/Helper/LocalStorage.js
+++ /dev/null
@@ -1,179 +0,0 @@
-/* global localStorage */
-
-function checkLocalStorageAvailability() {
- try {
- const testKey = '__ppcp_test__';
- localStorage.setItem( testKey, 'test' );
- localStorage.removeItem( testKey );
- return true;
- } catch ( e ) {
- return false;
- }
-}
-
-function sanitizeKey( name ) {
- return name
- .toLowerCase()
- .trim()
- .replace( /[^a-z0-9_-]/g, '_' );
-}
-
-function deserializeEntry( serialized ) {
- try {
- const payload = JSON.parse( serialized );
-
- return {
- data: payload.data,
- expires: payload.expires || 0,
- };
- } catch ( e ) {
- return null;
- }
-}
-
-function serializeEntry( data, timeToLive ) {
- const payload = {
- data,
- expires: calculateExpiration( timeToLive ),
- };
-
- return JSON.stringify( payload );
-}
-
-function calculateExpiration( timeToLive ) {
- return timeToLive ? Date.now() + timeToLive * 1000 : 0;
-}
-
-/**
- * A reusable class for handling data storage in the browser's local storage,
- * with optional expiration.
- *
- * Can be extended for module specific logic.
- *
- * @see GooglePaySession
- */
-export class LocalStorage {
- /**
- * @type {string}
- */
- #group = '';
-
- /**
- * @type {null|boolean}
- */
- #canUseLocalStorage = null;
-
- /**
- * @param {string} group - Group name for all storage keys managed by this instance.
- */
- constructor( group ) {
- this.#group = sanitizeKey( group ) + ':';
- this.#removeExpired();
- }
-
- /**
- * Removes all items in the current group that have reached the expiry date.
- */
- #removeExpired() {
- if ( ! this.canUseLocalStorage ) {
- return;
- }
-
- Object.keys( localStorage ).forEach( ( key ) => {
- if ( ! key.startsWith( this.#group ) ) {
- return;
- }
-
- const entry = deserializeEntry( localStorage.getItem( key ) );
- if ( entry && entry.expires > 0 && entry.expires < Date.now() ) {
- localStorage.removeItem( key );
- }
- } );
- }
-
- /**
- * Sanitizes the given entry name and adds the group prefix.
- *
- * @throws {Error} If the name is empty after sanitization.
- * @param {string} name - Entry name.
- * @return {string} Prefixed and sanitized entry name.
- */
- #entryKey( name ) {
- const sanitizedName = sanitizeKey( name );
-
- if ( sanitizedName.length === 0 ) {
- throw new Error( 'Name cannot be empty after sanitization' );
- }
-
- return `${ this.#group }${ sanitizedName }`;
- }
-
- /**
- * Indicates, whether localStorage is available.
- *
- * @return {boolean} True means the localStorage API is available.
- */
- get canUseLocalStorage() {
- if ( null === this.#canUseLocalStorage ) {
- this.#canUseLocalStorage = checkLocalStorageAvailability();
- }
-
- return this.#canUseLocalStorage;
- }
-
- /**
- * Stores data in the browser's local storage, with an optional timeout.
- *
- * @param {string} name - Name of the item in the storage.
- * @param {any} data - The data to store.
- * @param {number} [timeToLive=0] - Lifespan in seconds. 0 means the data won't expire.
- * @throws {Error} If local storage is not available.
- */
- set( name, data, timeToLive = 0 ) {
- if ( ! this.canUseLocalStorage ) {
- throw new Error( 'Local storage is not available' );
- }
-
- const entry = serializeEntry( data, timeToLive );
- const entryKey = this.#entryKey( name );
-
- localStorage.setItem( entryKey, entry );
- }
-
- /**
- * Retrieves previously stored data from the browser's local storage.
- *
- * @param {string} name - Name of the stored item.
- * @return {any|null} The stored data, or null when no valid entry is found or it has expired.
- * @throws {Error} If local storage is not available.
- */
- get( name ) {
- if ( ! this.canUseLocalStorage ) {
- throw new Error( 'Local storage is not available' );
- }
-
- const itemKey = this.#entryKey( name );
- const entry = deserializeEntry( localStorage.getItem( itemKey ) );
-
- if ( ! entry ) {
- return null;
- }
-
- return entry.data;
- }
-
- /**
- * Removes the specified entry from the browser's local storage.
- *
- * @param {string} name - Name of the stored item.
- * @throws {Error} If local storage is not available.
- */
- clear( name ) {
- if ( ! this.canUseLocalStorage ) {
- throw new Error( 'Local storage is not available' );
- }
-
- const itemKey = this.#entryKey( name );
- localStorage.removeItem( itemKey );
- }
-}
diff --git a/modules/ppcp-settings/resources/js/utils/Helper/MultistepCheckoutHelper.js b/modules/ppcp-settings/resources/js/utils/Helper/MultistepCheckoutHelper.js
deleted file mode 100644
index 1e71d6bb7..000000000
--- a/modules/ppcp-settings/resources/js/utils/Helper/MultistepCheckoutHelper.js
+++ /dev/null
@@ -1,123 +0,0 @@
-import { refreshButtons } from './ButtonRefreshHelper';
-
-const DEFAULT_TRIGGER_ELEMENT_SELECTOR = '.woocommerce-checkout-payment';
-
-/**
- * The MultistepCheckoutHelper class ensures the initialization of payment buttons
- * on websites using a multistep checkout plugin. These plugins usually hide the
- * payment button on page load up and reveal it later using JS. During the
- * invisibility period of wrappers, some payment buttons fail to initialize,
- * so we wait for the payment element to be visible.
- *
- * @property {HTMLElement} form - Checkout form element.
- * @property {HTMLElement} triggerElement - Element, which visibility we need to detect.
- * @property {boolean} isVisible - Whether the triggerElement is visible.
- */
-class MultistepCheckoutHelper {
- /**
- * Selector that defines the HTML element we are waiting to become visible.
- * @type {string}
- */
- #triggerElementSelector;
-
- /**
- * Interval (in milliseconds) in which the visibility of the trigger element is checked.
- * @type {number}
- */
- #intervalTime = 150;
-
- /**
- * The interval ID returned by the setInterval() method.
- * @type {number|false}
- */
- #intervalId;
-
- /**
- * Selector passed to the constructor that identifies the checkout form
- * @type {string}
- */
- #formSelector;
-
- /**
- * @param {string} formSelector - Selector of the checkout form
- * @param {string} triggerElementSelector - Optional. Selector of the dependant element.
- */
- constructor( formSelector, triggerElementSelector = '' ) {
- this.#formSelector = formSelector;
- this.#triggerElementSelector =
- triggerElementSelector || DEFAULT_TRIGGER_ELEMENT_SELECTOR;
- this.#intervalId = false;
-
- /*
- Start the visibility checker after a brief delay. This allows eventual multistep plugins to
- dynamically prepare the checkout page, so we can decide whether this helper is needed.
- */
- setTimeout( () => {
- if ( this.form && ! this.isVisible ) {
- this.start();
- }
- }, 250 );
- }
-
- /**
- * The checkout form element.
- * @return {Element|null} - Form element or null.
- */
- get form() {
- return document.querySelector( this.#formSelector );
- }
-
- /**
- * The element which must be visible before payment buttons should be initialized.
- * @return {Element|null} - Trigger element or null.
- */
- get triggerElement() {
- return this.form?.querySelector( this.#triggerElementSelector );
- }
-
- /**
- * Checks the visibility of the payment button wrapper.
- * @return {boolean} - returns boolean value on the basis of visibility of element.
- */
- get isVisible() {
- const box = this.triggerElement?.getBoundingClientRect();
-
- return !! ( box && box.width && box.height );
- }
-
- /**
- * Starts the observation of the DOM, initiates monitoring the checkout form.
- * To ensure multiple calls to start don't create multiple intervals, we first call stop.
- */
- start() {
- this.stop();
- this.#intervalId = setInterval(
- () => this.checkElement(),
- this.#intervalTime
- );
- }
-
- /**
- * Stops the observation of the checkout form.
- * Multiple calls to stop are safe as clearInterval doesn't throw if provided ID doesn't exist.
- */
- stop() {
- if ( this.#intervalId ) {
- clearInterval( this.#intervalId );
- this.#intervalId = false;
- }
- }
-
- /**
- * Checks if the trigger element is visible.
- * If visible, it initialises the payment buttons and stops the observation.
- */
- checkElement() {
- if ( this.isVisible ) {
- refreshButtons();
- this.stop();
- }
- }
-}
-
-export default MultistepCheckoutHelper;
diff --git a/modules/ppcp-settings/resources/js/utils/Helper/PayPalScriptLoading.js b/modules/ppcp-settings/resources/js/utils/Helper/PayPalScriptLoading.js
deleted file mode 100644
index 48134d2bc..000000000
--- a/modules/ppcp-settings/resources/js/utils/Helper/PayPalScriptLoading.js
+++ /dev/null
@@ -1,101 +0,0 @@
-import { loadScript } from '@paypal/paypal-js';
-import dataClientIdAttributeHandler from '../DataClientIdAttributeHandler';
-import widgetBuilder from '../Renderer/WidgetBuilder';
-import { processConfig } from './ConfigProcessor';
-
-const loadedScripts = new Map();
-const scriptPromises = new Map();
-
-const handleDataClientIdAttribute = async ( scriptOptions, config ) => {
- if (
- config.data_client_id?.set_attribute &&
- config.vault_v3_enabled !== true
- ) {
- return new Promise( ( resolve, reject ) => {
- dataClientIdAttributeHandler(
- scriptOptions,
- config.data_client_id,
- ( paypal ) => {
- widgetBuilder.setPaypal( paypal );
- resolve( paypal );
- },
- reject
- );
- } );
- }
- return null;
-};
-
-export const loadPayPalScript = async ( namespace, config ) => {
- if ( ! namespace ) {
- throw new Error( 'Namespace is required' );
- }
-
- if ( loadedScripts.has( namespace ) ) {
- console.log( `Script already loaded for namespace: ${ namespace }` );
- return loadedScripts.get( namespace );
- }
-
- if ( scriptPromises.has( namespace ) ) {
- console.log(
- `Script loading in progress for namespace: ${ namespace }`
- );
- return scriptPromises.get( namespace );
- }
-
- const scriptOptions = {
- ...processConfig( config ),
- 'data-namespace': namespace,
- };
-
- const dataClientIdResult = await handleDataClientIdAttribute(
- scriptOptions,
- config
- );
- if ( dataClientIdResult ) {
- return dataClientIdResult;
- }
-
- const scriptPromise = new Promise( ( resolve, reject ) => {
- loadScript( scriptOptions )
- .then( ( script ) => {
- widgetBuilder.setPaypal( script );
- loadedScripts.set( namespace, script );
- console.log( `Script loaded for namespace: ${ namespace }` );
- resolve( script );
- } )
- .catch( ( error ) => {
- console.error(
- `Failed to load script for namespace: ${ namespace }`,
- error
- );
- reject( error );
- } )
- .finally( () => {
- scriptPromises.delete( namespace );
- } );
- } );
-
- scriptPromises.set( namespace, scriptPromise );
- return scriptPromise;
-};
-
-export const loadAndRenderPayPalScript = async (
- namespace,
- options,
- renderFunction,
- renderTarget
-) => {
- if ( ! namespace ) {
- throw new Error( 'Namespace is required' );
- }
-
- const scriptOptions = {
- ...options,
- 'data-namespace': namespace,
- };
-
- const script = await loadScript( scriptOptions );
- widgetBuilder.setPaypal( script );
- await renderFunction( script, renderTarget );
-};
diff --git a/modules/ppcp-settings/resources/js/utils/Helper/PayerData.js b/modules/ppcp-settings/resources/js/utils/Helper/PayerData.js
deleted file mode 100644
index 5695facb0..000000000
--- a/modules/ppcp-settings/resources/js/utils/Helper/PayerData.js
+++ /dev/null
@@ -1,196 +0,0 @@
-/**
- * Name details.
- *
- * @typedef {Object} NameDetails
- * @property {string} [given_name] - First name, e.g. "John".
- * @property {string} [surname] - Last name, e.g. "Doe".
- */
-
-/**
- * Postal address details.
- *
- * @typedef {Object} AddressDetails
- * @property {string} [country_code] - Country code (2-letter).
- * @property {string} [address_line_1] - Address details, line 1 (street, house number).
- * @property {string} [address_line_2] - Address details, line 2.
- * @property {string} [admin_area_1] - State or region.
- * @property {string} [admin_area_2] - State or region.
- * @property {string} [postal_code] - Zip code.
- */
-
-/**
- * Phone details.
- *
- * @typedef {Object} PhoneDetails
- * @property {string} [phone_type] - Type, usually 'HOME'
- * @property {{national_number: string}} [phone_number] - Phone number details.
- */
-
-/**
- * Payer details.
- *
- * @typedef {Object} PayerDetails
- * @property {string} [email_address] - Email address for billing communication.
- * @property {PhoneDetails} [phone] - Phone number for billing communication.
- * @property {NameDetails} [name] - Payer's name.
- * @property {AddressDetails} [address] - Postal billing address.
- */
-
-// Map checkout fields to PayerData object properties.
-const FIELD_MAP = {
- '#billing_email': [ 'email_address' ],
- '#billing_last_name': [ 'name', 'surname' ],
- '#billing_first_name': [ 'name', 'given_name' ],
- '#billing_country': [ 'address', 'country_code' ],
- '#billing_address_1': [ 'address', 'address_line_1' ],
- '#billing_address_2': [ 'address', 'address_line_2' ],
- '#billing_state': [ 'address', 'admin_area_1' ],
- '#billing_city': [ 'address', 'admin_area_2' ],
- '#billing_postcode': [ 'address', 'postal_code' ],
- '#billing_phone': [ 'phone' ],
-};
-
-function normalizePayerDetails( details ) {
- return {
- email_address: details.email_address,
- phone: details.phone,
- name: {
- surname: details.name?.surname,
- given_name: details.name?.given_name,
- },
- address: {
- country_code: details.address?.country_code,
- address_line_1: details.address?.address_line_1,
- address_line_2: details.address?.address_line_2,
- admin_area_1: details.address?.admin_area_1,
- admin_area_2: details.address?.admin_area_2,
- postal_code: details.address?.postal_code,
- },
- };
-}
-
-function mergePayerDetails( firstPayer, secondPayer ) {
- const mergeNestedObjects = ( target, source ) => {
- for ( const [ key, value ] of Object.entries( source ) ) {
- if ( null !== value && undefined !== value ) {
- if ( 'object' === typeof value ) {
- target[ key ] = mergeNestedObjects(
- target[ key ] || {},
- value
- );
- } else {
- target[ key ] = value;
- }
- }
- }
- return target;
- };
-
- return mergeNestedObjects(
- normalizePayerDetails( firstPayer ),
- normalizePayerDetails( secondPayer )
- );
-}
-
-function getCheckoutBillingDetails() {
- const getElementValue = ( selector ) =>
- document.querySelector( selector )?.value;
-
- const setNestedValue = ( obj, path, value ) => {
- let current = obj;
- for ( let i = 0; i < path.length - 1; i++ ) {
- current = current[ path[ i ] ] = current[ path[ i ] ] || {};
- }
- current[ path[ path.length - 1 ] ] = value;
- };
-
- const data = {};
-
- Object.entries( FIELD_MAP ).forEach( ( [ selector, path ] ) => {
- const value = getElementValue( selector );
- if ( value ) {
- setNestedValue( data, path, value );
- }
- } );
-
- if ( data.phone && 'string' === typeof data.phone ) {
- data.phone = {
- phone_type: 'HOME',
- phone_number: { national_number: data.phone },
- };
- }
-
- return data;
-}
-
-function setCheckoutBillingDetails( payer ) {
- const setValue = ( path, field, value ) => {
- if ( null === value || undefined === value || ! field ) {
- return;
- }
-
- if ( 'phone' === path[ 0 ] && 'object' === typeof value ) {
- value = value.phone_number?.national_number;
- }
-
- field.value = value;
- };
-
- const getNestedValue = ( obj, path ) =>
- path.reduce( ( current, key ) => current?.[ key ], obj );
-
- Object.entries( FIELD_MAP ).forEach( ( [ selector, path ] ) => {
- const value = getNestedValue( payer, path );
- const element = document.querySelector( selector );
-
- setValue( path, element, value );
- } );
-}
-
-export function getWooCommerceCustomerDetails() {
- // Populated on server-side with details about the current WooCommerce customer.
- return window?.PayPalCommerceGateway?.payer;
-}
-
-export function getSessionBillingDetails() {
- // Populated by JS via `setSessionBillingDetails()`
- return window._PpcpPayerSessionDetails;
-}
-
-/**
- * Stores customer details in the current JS context for use in the same request.
- * Details that are set are not persisted during navigation.
- *
- * @param {unknown} details - New payer details
- */
-export function setSessionBillingDetails( details ) {
- if ( ! details || 'object' !== typeof details ) {
- return;
- }
-
- window._PpcpPayerSessionDetails = normalizePayerDetails( details );
-}
-
-export function payerData() {
- const payer = getWooCommerceCustomerDetails() ?? getSessionBillingDetails();
-
- if ( ! payer ) {
- return null;
- }
-
- const formData = getCheckoutBillingDetails();
-
- if ( formData ) {
- return mergePayerDetails( payer, formData );
- }
-
- return normalizePayerDetails( payer );
-}
-
-export function setPayerData( payerDetails, updateCheckoutForm = false ) {
- setSessionBillingDetails( payerDetails );
-
- if ( updateCheckoutForm ) {
- setCheckoutBillingDetails( payerDetails );
- }
-}
diff --git a/modules/ppcp-settings/resources/js/utils/Helper/PaymentButtonHelpers.js b/modules/ppcp-settings/resources/js/utils/Helper/PaymentButtonHelpers.js
deleted file mode 100644
index f9a066a23..000000000
--- a/modules/ppcp-settings/resources/js/utils/Helper/PaymentButtonHelpers.js
+++ /dev/null
@@ -1,117 +0,0 @@
-/**
- * Helper function used by PaymentButton instances.
- *
- * @file
- */
-
-/**
- * Collection of recognized event names for payment button events.
- *
- * @type {Object}
- */
-export const ButtonEvents = Object.freeze( {
- INVALIDATE: 'ppcp_invalidate_methods',
- RENDER: 'ppcp_render_method',
- REDRAW: 'ppcp_redraw_method',
-} );
-
-/**
- *
- * @param {string} defaultId - Default wrapper ID.
- * @param {string} miniCartId - Wrapper inside the mini-cart.
- * @param {string} smartButtonId - ID of the smart button wrapper.
- * @param {string} blockId - Block wrapper ID (express checkout, block cart).
- * @param {string} gatewayId - Gateway wrapper ID (classic checkout).
- * @return {{MiniCart, Gateway, Block, SmartButton, Default}} List of all wrapper IDs, by context.
- */
-export function combineWrapperIds(
- defaultId = '',
- miniCartId = '',
- smartButtonId = '',
- blockId = '',
- gatewayId = ''
-) {
- const sanitize = ( id ) => id.replace( /^#/, '' );
-
- return {
- Default: sanitize( defaultId ),
- SmartButton: sanitize( smartButtonId ),
- Block: sanitize( blockId ),
- Gateway: sanitize( gatewayId ),
- MiniCart: sanitize( miniCartId ),
- };
-}
-
-/**
- * Returns full payment button styles by combining the global ppcpConfig with
- * payment-method-specific styling provided via buttonConfig.
- *
- * @param {Object} ppcpConfig - Global plugin configuration.
- * @param {Object} buttonConfig - Payment method specific configuration.
- * @return {{MiniCart: (*), Default: (*)}} Combined styles, separated by context.
- */
-export function combineStyles( ppcpConfig, buttonConfig ) {
- return {
- Default: {
- ...ppcpConfig.style,
- ...buttonConfig.style,
- },
- MiniCart: {
- ...ppcpConfig.mini_cart_style,
- ...buttonConfig.mini_cart_style,
- },
- };
-}
-
-/**
- * Verifies if the given event name is a valid Payment Button event.
- *
- * @param {string} event - The event name to verify.
- * @return {boolean} True, if the event name is valid.
- */
-export function isValidButtonEvent( event ) {
- const buttonEventValues = Object.values( ButtonEvents );
-
- return buttonEventValues.includes( event );
-}
-
-/**
- * Dispatches a payment button event.
- *
- * @param {Object} options - The options for dispatching the event.
- * @param {string} options.event - Event to dispatch.
- * @param {string} [options.paymentMethod] - Optional. Name of payment method, to target a specific button only.
- * @throws {Error} Throws an error if the event is invalid.
- */
-export function dispatchButtonEvent( { event, paymentMethod = '' } ) {
- if ( ! isValidButtonEvent( event ) ) {
- throw new Error( `Invalid event: ${ event }` );
- }
-
- const fullEventName = paymentMethod
- ? `${ event }-${ paymentMethod }`
- : event;
-
- document.body.dispatchEvent( new Event( fullEventName ) );
-}
-
-/**
- * Adds an event listener for the provided button event.
- *
- * @param {Object} options - The options for the event listener.
- * @param {string} options.event - Event to observe.
- * @param {string} [options.paymentMethod] - The payment method name (optional).
- * @param {Function} options.callback - The callback function to execute when the event is triggered.
- * @throws {Error} Throws an error if the event is invalid.
- */
-export function observeButtonEvent( { event, paymentMethod = '', callback } ) {
- if ( ! isValidButtonEvent( event ) ) {
- throw new Error( `Invalid event: ${ event }` );
- }
-
- const fullEventName = paymentMethod
- ? `${ event }-${ paymentMethod }`
- : event;
-
- document.body.addEventListener( fullEventName, callback );
-}
diff --git a/modules/ppcp-settings/resources/js/utils/Helper/ScriptLoading.js b/modules/ppcp-settings/resources/js/utils/Helper/ScriptLoading.js
deleted file mode 100644
index 00ae98a9c..000000000
--- a/modules/ppcp-settings/resources/js/utils/Helper/ScriptLoading.js
+++ /dev/null
@@ -1,128 +0,0 @@
-import dataClientIdAttributeHandler from '../DataClientIdAttributeHandler';
-import { loadScript } from '@paypal/paypal-js';
-import widgetBuilder from '../Renderer/WidgetBuilder';
-import merge from 'deepmerge';
-import { keysToCamelCase } from './Utils';
-import { getCurrentPaymentMethod } from './CheckoutMethodState';
-import { v4 as uuidv4 } from 'uuid';
-
-// This component may be used by multiple modules. This assures that options are shared between all instances.
-const scriptOptionsMap = {};
-
-const getNamespaceOptions = ( namespace ) => {
- if ( ! scriptOptionsMap[ namespace ] ) {
- scriptOptionsMap[ namespace ] = {
- isLoading: false,
- onLoadedCallbacks: [],
- onErrorCallbacks: [],
- };
- }
- return scriptOptionsMap[ namespace ];
-};
-
-export const loadPaypalScript = ( config, onLoaded, onError = null ) => {
- const dataNamespace = config?.data_namespace || '';
- const options = getNamespaceOptions( dataNamespace );
-
- // If PayPal is already loaded for this namespace, call the onLoaded callback and return.
- if ( typeof window.paypal !== 'undefined' && ! dataNamespace ) {
- onLoaded();
- return;
- }
-
- // Add the onLoaded callback to the onLoadedCallbacks stack.
- options.onLoadedCallbacks.push( onLoaded );
- if ( onError ) {
- options.onErrorCallbacks.push( onError );
- }
-
- // Return if it's still loading.
- if ( options.isLoading ) {
- return;
- }
- options.isLoading = true;
-
- const resetState = () => {
- options.isLoading = false;
- options.onLoadedCallbacks = [];
- options.onErrorCallbacks = [];
- };
-
- // Callback to be called once the PayPal script is loaded.
- const callback = ( paypal ) => {
- widgetBuilder.setPaypal( paypal );
-
- for ( const onLoadedCallback of options.onLoadedCallbacks ) {
- onLoadedCallback();
- }
-
- resetState();
- };
- const errorCallback = ( err ) => {
- for ( const onErrorCallback of options.onErrorCallbacks ) {
- onErrorCallback( err );
- }
-
- resetState();
- };
-
- // Build the PayPal script options.
- let scriptOptions = keysToCamelCase( config.url_params );
- if ( config.script_attributes ) {
- scriptOptions = merge( scriptOptions, config.script_attributes );
- }
-
- // Axo SDK options
- const sdkClientToken = config?.axo?.sdk_client_token;
- const uuid = uuidv4().replace( /-/g, '' );
- if ( sdkClientToken && config?.user?.is_logged !== true ) {
- scriptOptions[ 'data-sdk-client-token' ] = sdkClientToken;
- scriptOptions[ 'data-client-metadata-id' ] = uuid;
- }
-
- // Load PayPal script for special case with data-client-token
- if (
- config.data_client_id?.set_attribute &&
- config.vault_v3_enabled !== '1'
- ) {
- dataClientIdAttributeHandler(
- scriptOptions,
- config.data_client_id,
- callback,
- errorCallback
- );
- return;
- }
-
- // Adds data-user-id-token to script options.
- const userIdToken = config?.save_payment_methods?.id_token;
- if ( userIdToken && config?.user?.is_logged === true ) {
- scriptOptions[ 'data-user-id-token' ] = userIdToken;
- }
-
- // Adds data-namespace to script options.
- if ( dataNamespace ) {
- scriptOptions.dataNamespace = dataNamespace;
- }
-
- // Load PayPal script
- loadScript( scriptOptions ).then( callback ).catch( errorCallback );
-};
-
-export const loadPaypalScriptPromise = ( config ) => {
- return new Promise( ( resolve, reject ) => {
- loadPaypalScript( config, resolve, reject );
- } );
-};
-
-export const loadPaypalJsScript = ( options, buttons, container ) => {
- loadScript( options ).then( ( paypal ) => {
- paypal.Buttons( buttons ).render( container );
- } );
-};
-
-export const loadPaypalJsScriptPromise = ( options ) => {
- return new Promise( ( resolve, reject ) => {
- loadScript( options ).then( resolve ).catch( reject );
- } );
-};
diff --git a/modules/ppcp-settings/resources/js/utils/Helper/ShippingHandler.js b/modules/ppcp-settings/resources/js/utils/Helper/ShippingHandler.js
deleted file mode 100644
index ae86ddea0..000000000
--- a/modules/ppcp-settings/resources/js/utils/Helper/ShippingHandler.js
+++ /dev/null
@@ -1,151 +0,0 @@
-import { paypalAddressToWc } from '../../../../../ppcp-blocks/resources/js/Helper/Address.js';
-import { convertKeysToSnakeCase } from '../../../../../ppcp-blocks/resources/js/Helper/Helper.js';
-
-/**
- * Handles the shipping option change in PayPal.
- *
- * @param data
- * @param actions
- * @param config
- * @return {Promise}
- */
-export const handleShippingOptionsChange = async ( data, actions, config ) => {
- try {
- const shippingOptionId = data.selectedShippingOption?.id;
-
- if ( shippingOptionId ) {
- await fetch(
- config.ajax.update_customer_shipping.shipping_options.endpoint,
- {
- method: 'POST',
- credentials: 'same-origin',
- headers: {
- 'Content-Type': 'application/json',
- 'X-WC-Store-API-Nonce':
- config.ajax.update_customer_shipping.wp_rest_nonce,
- },
- body: JSON.stringify( {
- rate_id: shippingOptionId,
- } ),
- }
- )
- .then( ( response ) => {
- return response.json();
- } )
- .then( ( cardData ) => {
- const shippingMethods =
- document.querySelectorAll( '.shipping_method' );
-
- shippingMethods.forEach( function ( method ) {
- if ( method.value === shippingOptionId ) {
- method.checked = true;
- }
- } );
- } );
- }
-
- if ( ! config.data_client_id.has_subscriptions ) {
- const res = await fetch( config.ajax.update_shipping.endpoint, {
- method: 'POST',
- credentials: 'same-origin',
- body: JSON.stringify( {
- nonce: config.ajax.update_shipping.nonce,
- order_id: data.orderID,
- } ),
- } );
-
- const json = await res.json();
-
- if ( ! json.success ) {
- throw new Error( json.data.message );
- }
- }
- } catch ( e ) {
- console.error( e );
-
- actions.reject();
- }
-};
-
-/**
- * Handles the shipping address change in PayPal.
- *
- * @param data
- * @param actions
- * @param config
- * @return {Promise}
- */
-export const handleShippingAddressChange = async ( data, actions, config ) => {
- try {
- const address = paypalAddressToWc(
- convertKeysToSnakeCase( data.shippingAddress )
- );
-
- // Retrieve current cart contents
- await fetch(
- config.ajax.update_customer_shipping.shipping_address.cart_endpoint
- )
- .then( ( response ) => {
- return response.json();
- } )
- .then( ( cartData ) => {
- // Update shipping address in the cart data
- cartData.shipping_address.address_1 = address.address_1;
- cartData.shipping_address.address_2 = address.address_2;
- cartData.shipping_address.city = address.city;
- cartData.shipping_address.state = address.state;
- cartData.shipping_address.postcode = address.postcode;
- cartData.shipping_address.country = address.country;
-
- // Send update request
- return fetch(
- config.ajax.update_customer_shipping.shipping_address
- .update_customer_endpoint,
- {
- method: 'POST',
- credentials: 'same-origin',
- headers: {
- 'Content-Type': 'application/json',
- 'X-WC-Store-API-Nonce':
- config.ajax.update_customer_shipping
- .wp_rest_nonce,
- },
- body: JSON.stringify( {
- shipping_address: cartData.shipping_address,
- } ),
- }
- )
- .then( function ( res ) {
- return res.json();
- } )
- .then( function ( customerData ) {
- jQuery( '.cart_totals .shop_table' ).load(
- location.href +
- ' ' +
- '.cart_totals .shop_table' +
- '>*',
- ''
- );
- } );
- } );
-
- const res = await fetch( config.ajax.update_shipping.endpoint, {
- method: 'POST',
- credentials: 'same-origin',
- body: JSON.stringify( {
- nonce: config.ajax.update_shipping.nonce,
- order_id: data.orderID,
- } ),
- } );
-
- const json = await res.json();
-
- if ( ! json.success ) {
- throw new Error( json.data.message );
- }
- } catch ( e ) {
- console.error( e );
-
- actions.reject();
- }
-};
diff --git a/modules/ppcp-settings/resources/js/utils/Helper/SimulateCart.js b/modules/ppcp-settings/resources/js/utils/Helper/SimulateCart.js
deleted file mode 100644
index 4dd67be76..000000000
--- a/modules/ppcp-settings/resources/js/utils/Helper/SimulateCart.js
+++ /dev/null
@@ -1,42 +0,0 @@
-class SimulateCart {
- constructor( endpoint, nonce ) {
- this.endpoint = endpoint;
- this.nonce = nonce;
- }
-
- /**
- *
- * @param onResolve
- * @param {Product[]} products
- * @return {Promise}
- */
- simulate( onResolve, products ) {
- return new Promise( ( resolve, reject ) => {
- fetch( this.endpoint, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- credentials: 'same-origin',
- body: JSON.stringify( {
- nonce: this.nonce,
- products,
- } ),
- } )
- .then( ( result ) => {
- return result.json();
- } )
- .then( ( result ) => {
- if ( ! result.success ) {
- reject( result.data );
- return;
- }
-
- const resolved = onResolve( result.data );
- resolve( resolved );
- } );
- } );
- }
-}
-
-export default SimulateCart;
diff --git a/modules/ppcp-settings/resources/js/utils/Helper/Spinner.js b/modules/ppcp-settings/resources/js/utils/Helper/Spinner.js
deleted file mode 100644
index 30d0830f9..000000000
--- a/modules/ppcp-settings/resources/js/utils/Helper/Spinner.js
+++ /dev/null
@@ -1,25 +0,0 @@
-class Spinner {
- constructor( target = 'form.woocommerce-checkout' ) {
- this.target = target;
- }
-
- setTarget( target ) {
- this.target = target;
- }
-
- block() {
- jQuery( this.target ).block( {
- message: null,
- overlayCSS: {
- background: '#fff',
- opacity: 0.6,
- },
- } );
- }
-
- unblock() {
- jQuery( this.target ).unblock();
- }
-}
-
-export default Spinner;
diff --git a/modules/ppcp-settings/resources/js/utils/Helper/Style.js b/modules/ppcp-settings/resources/js/utils/Helper/Style.js
deleted file mode 100644
index 3f3f64e04..000000000
--- a/modules/ppcp-settings/resources/js/utils/Helper/Style.js
+++ /dev/null
@@ -1,20 +0,0 @@
-export const normalizeStyleForFundingSource = ( style, fundingSource ) => {
- const commonProps = {};
- [ 'shape', 'height' ].forEach( ( prop ) => {
- if ( style[ prop ] ) {
- commonProps[ prop ] = style[ prop ];
- }
- } );
-
- switch ( fundingSource ) {
- case 'paypal':
- return style;
- case 'paylater':
- return {
- color: style.color,
- ...commonProps,
- };
- default:
- return commonProps;
- }
-};
diff --git a/modules/ppcp-settings/resources/js/utils/Helper/Subscriptions.js b/modules/ppcp-settings/resources/js/utils/Helper/Subscriptions.js
deleted file mode 100644
index e4bf0f389..000000000
--- a/modules/ppcp-settings/resources/js/utils/Helper/Subscriptions.js
+++ /dev/null
@@ -1,28 +0,0 @@
-export const isChangePaymentPage = () => {
- const urlParams = new URLSearchParams( window.location.search );
- return urlParams.has( 'change_payment_method' );
-};
-
-export const getPlanIdFromVariation = ( variation ) => {
- let subscription_plan = '';
- PayPalCommerceGateway.variable_paypal_subscription_variations.forEach(
- ( element ) => {
- const obj = {};
- variation.forEach( ( { name, value } ) => {
- Object.assign( obj, {
- [ name.replace( 'attribute_', '' ) ]: value,
- } );
- } );
-
- if (
- JSON.stringify( obj ) ===
- JSON.stringify( element.attributes ) &&
- element.subscription_plan !== ''
- ) {
- subscription_plan = element.subscription_plan;
- }
- }
- );
-
- return subscription_plan;
-};
diff --git a/modules/ppcp-settings/resources/js/utils/Helper/UpdateCart.js b/modules/ppcp-settings/resources/js/utils/Helper/UpdateCart.js
deleted file mode 100644
index 454eacfc6..000000000
--- a/modules/ppcp-settings/resources/js/utils/Helper/UpdateCart.js
+++ /dev/null
@@ -1,45 +0,0 @@
-import Product from '../Entity/Product';
-class UpdateCart {
- constructor( endpoint, nonce ) {
- this.endpoint = endpoint;
- this.nonce = nonce;
- }
-
- /**
- *
- * @param onResolve
- * @param {Product[]} products
- * @param {Object} options
- * @return {Promise}
- */
- update( onResolve, products, options = {} ) {
- return new Promise( ( resolve, reject ) => {
- fetch( this.endpoint, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- credentials: 'same-origin',
- body: JSON.stringify( {
- nonce: this.nonce,
- products,
- ...options,
- } ),
- } )
- .then( ( result ) => {
- return result.json();
- } )
- .then( ( result ) => {
- if ( ! result.success ) {
- reject( result.data );
- return;
- }
-
- const resolved = onResolve( result.data );
- resolve( resolved );
- } );
- } );
- }
-}
-
-export default UpdateCart;
diff --git a/modules/ppcp-settings/resources/js/utils/Helper/Utils.js b/modules/ppcp-settings/resources/js/utils/Helper/Utils.js
deleted file mode 100644
index cf4121ead..000000000
--- a/modules/ppcp-settings/resources/js/utils/Helper/Utils.js
+++ /dev/null
@@ -1,69 +0,0 @@
-export const toCamelCase = ( str ) => {
- return str.replace( /([-_]\w)/g, function ( match ) {
- return match[ 1 ].toUpperCase();
- } );
-};
-
-export const keysToCamelCase = ( obj ) => {
- const output = {};
- for ( const key in obj ) {
- if ( Object.prototype.hasOwnProperty.call( obj, key ) ) {
- output[ toCamelCase( key ) ] = obj[ key ];
- }
- }
- return output;
-};
-
-export const strAddWord = ( str, word, separator = ',' ) => {
- const arr = str.split( separator );
- if ( ! arr.includes( word ) ) {
- arr.push( word );
- }
- return arr.join( separator );
-};
-
-export const strRemoveWord = ( str, word, separator = ',' ) => {
- const arr = str.split( separator );
- const index = arr.indexOf( word );
- if ( index !== -1 ) {
- arr.splice( index, 1 );
- }
- return arr.join( separator );
-};
-
-export const throttle = ( func, limit ) => {
- let inThrottle, lastArgs, lastContext;
-
- function execute() {
- inThrottle = true;
- func.apply( this, arguments );
- setTimeout( () => {
- inThrottle = false;
- if ( lastArgs ) {
- const nextArgs = lastArgs;
- const nextContext = lastContext;
- lastArgs = lastContext = null;
- execute.apply( nextContext, nextArgs );
- }
- }, limit );
- }
-
- return function () {
- if ( ! inThrottle ) {
- execute.apply( this, arguments );
- } else {
- lastArgs = arguments;
- lastContext = this;
- }
- };
-};
-
-const Utils = {
- toCamelCase,
- keysToCamelCase,
- strAddWord,
- strRemoveWord,
- throttle,
-};
-
-export default Utils;
diff --git a/modules/ppcp-settings/resources/js/utils/renderer.js b/modules/ppcp-settings/resources/js/utils/renderer.js
deleted file mode 100644
index b7a80f687..000000000
--- a/modules/ppcp-settings/resources/js/utils/renderer.js
+++ /dev/null
@@ -1,264 +0,0 @@
-import merge from 'deepmerge';
-import { loadScript } from '@paypal/paypal-js';
-import { keysToCamelCase } from './Helper/Utils';
-import widgetBuilder from './widget-builder';
-import { normalizeStyleForFundingSource } from './Helper/Style';
-
-class Renderer {
- constructor(
- creditCardRenderer,
- defaultSettings,
- onSmartButtonClick,
- onSmartButtonsInit
- ) {
- this.defaultSettings = defaultSettings;
- this.creditCardRenderer = creditCardRenderer;
- this.onSmartButtonClick = onSmartButtonClick;
- this.onSmartButtonsInit = onSmartButtonsInit;
-
- this.buttonsOptions = {};
- this.onButtonsInitListeners = {};
-
- this.renderedSources = new Set();
-
- this.reloadEventName = 'ppcp-reload-buttons';
- }
-
- render(
- contextConfig,
- settingsOverride = {},
- contextConfigOverride = () => {}
- ) {
- const settings = merge( this.defaultSettings, settingsOverride );
- const enabledSeparateGateways = Object.fromEntries(
- Object.entries( settings.separate_buttons ).filter(
- ( [ s, data ] ) => document.querySelector( data.wrapper )
- )
- );
- const hasEnabledSeparateGateways =
- Object.keys( enabledSeparateGateways ).length !== 0;
-
- if ( ! hasEnabledSeparateGateways ) {
- console.log( 'RENDER 1', settings );
- this.renderButtons(
- settings.button.wrapper,
- settings.button.style,
- contextConfig,
- hasEnabledSeparateGateways
- );
- } else {
- // render each button separately
- for ( const fundingSource of paypal
- .getFundingSources()
- .filter( ( s ) => ! ( s in enabledSeparateGateways ) ) ) {
- const style = normalizeStyleForFundingSource(
- settings.button.style,
- fundingSource
- );
- console.log( 'RENDER' );
- this.renderButtons(
- settings.button.wrapper,
- style,
- contextConfig,
- hasEnabledSeparateGateways,
- fundingSource
- );
- }
- }
-
- if ( this.creditCardRenderer ) {
- this.creditCardRenderer.render(
- settings.hosted_fields.wrapper,
- contextConfigOverride
- );
- }
-
- for ( const [ fundingSource, data ] of Object.entries(
- enabledSeparateGateways
- ) ) {
- this.renderButtons(
- data.wrapper,
- data.style,
- contextConfig,
- hasEnabledSeparateGateways,
- fundingSource
- );
- }
- }
-
- renderButtons(
- wrapper,
- style,
- contextConfig,
- hasEnabledSeparateGateways,
- fundingSource = null
- ) {
- if (
- ! document.querySelector( wrapper ) ||
- this.isAlreadyRendered(
- wrapper,
- fundingSource,
- hasEnabledSeparateGateways
- )
- ) {
- // Try to render registered buttons again in case they were removed from the DOM by an external source.
- widgetBuilder.renderButtons( [ wrapper, fundingSource ] );
- return;
- }
-
- if ( fundingSource ) {
- contextConfig.fundingSource = fundingSource;
- }
-
- let venmoButtonClicked = false;
-
- const buttonsOptions = () => {
- const options = {
- style,
- ...contextConfig,
- onClick: ( data, actions ) => {
- if ( this.onSmartButtonClick ) {
- this.onSmartButtonClick( data, actions );
- }
-
- venmoButtonClicked = false;
- if ( data.fundingSource === 'venmo' ) {
- venmoButtonClicked = true;
- }
- },
- onInit: ( data, actions ) => {
- if ( this.onSmartButtonsInit ) {
- this.onSmartButtonsInit( data, actions );
- }
- this.handleOnButtonsInit( wrapper, data, actions );
- },
- };
-
- return options;
- };
-
- jQuery( document )
- .off( this.reloadEventName, wrapper )
- .on(
- this.reloadEventName,
- wrapper,
- ( event, settingsOverride = {}, triggeredFundingSource ) => {
- // Only accept events from the matching funding source
- if (
- fundingSource &&
- triggeredFundingSource &&
- triggeredFundingSource !== fundingSource
- ) {
- return;
- }
-
- const settings = merge(
- this.defaultSettings,
- settingsOverride
- );
- let scriptOptions = keysToCamelCase( settings.url_params );
- scriptOptions = merge(
- scriptOptions,
- settings.script_attributes
- );
-
- loadScript( scriptOptions ).then( ( paypal ) => {
- widgetBuilder.setPaypal( paypal );
- widgetBuilder.registerButtons(
- [ wrapper, fundingSource ],
- buttonsOptions()
- );
- widgetBuilder.renderAll();
- } );
- }
- );
-
- this.renderedSources.add( wrapper + ( fundingSource ?? '' ) );
-
- if (
- typeof paypal !== 'undefined' &&
- typeof paypal.Buttons !== 'undefined'
- ) {
- widgetBuilder.registerButtons(
- [ wrapper, fundingSource ],
- buttonsOptions()
- );
- widgetBuilder.renderButtons( [ wrapper, fundingSource ] );
- }
- }
-
- isVenmoButtonClickedWhenVaultingIsEnabled = ( venmoButtonClicked ) => {
- return venmoButtonClicked && this.defaultSettings.vaultingEnabled;
- };
-
- shouldEnableShippingCallback = () => {
- const needShipping =
- this.defaultSettings.needShipping ||
- this.defaultSettings.context === 'product';
- return (
- this.defaultSettings.should_handle_shipping_in_paypal &&
- needShipping
- );
- };
-
- isAlreadyRendered( wrapper, fundingSource ) {
- return this.renderedSources.has( wrapper + ( fundingSource ?? '' ) );
- }
-
- disableCreditCardFields() {
- this.creditCardRenderer.disableFields();
- }
-
- enableCreditCardFields() {
- this.creditCardRenderer.enableFields();
- }
-
- onButtonsInit( wrapper, handler, reset ) {
- this.onButtonsInitListeners[ wrapper ] = reset
- ? []
- : this.onButtonsInitListeners[ wrapper ] || [];
- this.onButtonsInitListeners[ wrapper ].push( handler );
- }
-
- handleOnButtonsInit( wrapper, data, actions ) {
- this.buttonsOptions[ wrapper ] = {
- data,
- actions,
- };
-
- if ( this.onButtonsInitListeners[ wrapper ] ) {
- for ( const handler of this.onButtonsInitListeners[ wrapper ] ) {
- if ( typeof handler === 'function' ) {
- handler( {
- wrapper,
- ...this.buttonsOptions[ wrapper ],
- } );
- }
- }
- }
- }
-
- disableSmartButtons( wrapper ) {
- if ( ! this.buttonsOptions[ wrapper ] ) {
- return;
- }
- try {
- this.buttonsOptions[ wrapper ].actions.disable();
- } catch ( err ) {
- console.log( 'Failed to disable buttons: ' + err );
- }
- }
-
- enableSmartButtons( wrapper ) {
- if ( ! this.buttonsOptions[ wrapper ] ) {
- return;
- }
- try {
- this.buttonsOptions[ wrapper ].actions.enable();
- } catch ( err ) {
- console.log( 'Failed to enable buttons: ' + err );
- }
- }
-}
-
-export default Renderer;
diff --git a/modules/ppcp-settings/resources/js/utils/widget-builder.js b/modules/ppcp-settings/resources/js/utils/widget-builder.js
deleted file mode 100644
index 9481cc029..000000000
--- a/modules/ppcp-settings/resources/js/utils/widget-builder.js
+++ /dev/null
@@ -1,179 +0,0 @@
-/**
- * Handles the registration and rendering of PayPal widgets: Buttons and Messages.
- * To have several Buttons per wrapper, an array should be provided, ex: [wrapper, fundingSource].
- */
-class WidgetBuilder {
- constructor() {
- this.paypal = null;
- this.buttons = new Map();
- this.messages = new Map();
-
- this.renderEventName = 'ppcp-render';
-
- document.ppcpWidgetBuilderStatus = () => {
- console.log( {
- buttons: this.buttons,
- messages: this.messages,
- } );
- };
-
- jQuery( document )
- .off( this.renderEventName )
- .on( this.renderEventName, () => {
- this.renderAll();
- } );
- }
-
- setPaypal( paypal ) {
- this.paypal = paypal;
- jQuery( document ).trigger( 'ppcp-paypal-loaded', paypal );
- }
-
- registerButtons( wrapper, options ) {
- wrapper = this.sanitizeWrapper( wrapper );
-
- this.buttons.set( this.toKey( wrapper ), {
- wrapper,
- options,
- } );
- }
-
- renderButtons( wrapper ) {
- wrapper = this.sanitizeWrapper( wrapper );
-
- if ( ! this.buttons.has( this.toKey( wrapper ) ) ) {
- return;
- }
-
- if ( this.hasRendered( wrapper ) ) {
- return;
- }
-
- const entry = this.buttons.get( this.toKey( wrapper ) );
- const btn = this.paypal.Buttons( entry.options );
-
- if ( ! btn.isEligible() ) {
- this.buttons.delete( this.toKey( wrapper ) );
- return;
- }
-
- const target = this.buildWrapperTarget( wrapper );
-
- if ( ! target ) {
- return;
- }
-
- btn.render( target );
- }
-
- renderAllButtons() {
- for ( const [ wrapper, entry ] of this.buttons ) {
- this.renderButtons( wrapper );
- }
- }
-
- registerMessages( wrapper, options ) {
- this.messages.set( wrapper, {
- wrapper,
- options,
- } );
- }
-
- renderMessages( wrapper ) {
- if ( ! this.messages.has( wrapper ) ) {
- return;
- }
-
- const entry = this.messages.get( wrapper );
-
- if ( this.hasRendered( wrapper ) ) {
- const element = document.querySelector( wrapper );
- element.setAttribute( 'data-pp-amount', entry.options.amount );
- return;
- }
-
- const btn = this.paypal.Messages( entry.options );
-
- btn.render( entry.wrapper );
-
- // watchdog to try to handle some strange cases where the wrapper may not be present
- setTimeout( () => {
- if ( ! this.hasRendered( wrapper ) ) {
- btn.render( entry.wrapper );
- }
- }, 100 );
- }
-
- renderAllMessages() {
- for ( const [ wrapper, entry ] of this.messages ) {
- this.renderMessages( wrapper );
- }
- }
-
- renderAll() {
- this.renderAllButtons();
- this.renderAllMessages();
- }
-
- hasRendered( wrapper ) {
- let selector = wrapper;
-
- if ( Array.isArray( wrapper ) ) {
- selector = wrapper[ 0 ];
- for ( const item of wrapper.slice( 1 ) ) {
- selector += ' .item-' + item;
- }
- }
-
- const element = document.querySelector( selector );
- return element && element.hasChildNodes();
- }
-
- sanitizeWrapper( wrapper ) {
- if ( Array.isArray( wrapper ) ) {
- wrapper = wrapper.filter( ( item ) => !! item );
- if ( wrapper.length === 1 ) {
- wrapper = wrapper[ 0 ];
- }
- }
- return wrapper;
- }
-
- buildWrapperTarget( wrapper ) {
- let target = wrapper;
-
- if ( Array.isArray( wrapper ) ) {
- const $wrapper = jQuery( wrapper[ 0 ] );
-
- if ( ! $wrapper.length ) {
- return;
- }
-
- const itemClass = 'item-' + wrapper[ 1 ];
-
- // Check if the parent element exists and it doesn't already have the div with the class
- let $item = $wrapper.find( '.' + itemClass );
-
- if ( ! $item.length ) {
- $item = jQuery( `` );
- $wrapper.append( $item );
- }
-
- target = $item.get( 0 );
- }
-
- if ( ! jQuery( target ).length ) {
- return null;
- }
-
- return target;
- }
-
- toKey( wrapper ) {
- if ( Array.isArray( wrapper ) ) {
- return JSON.stringify( wrapper );
- }
- return wrapper;
- }
-}
-export default window.widgetBuilder;
diff --git a/modules/ppcp-settings/webpack.config.js b/modules/ppcp-settings/webpack.config.js
index 70372b646..a3a6d709d 100644
--- a/modules/ppcp-settings/webpack.config.js
+++ b/modules/ppcp-settings/webpack.config.js
@@ -14,19 +14,5 @@ module.exports = {
),
style: path.resolve( process.cwd(), 'resources/css', 'style.scss' ),
},
- resolve: {
- ...defaultConfig.resolve,
- ...{
- alias: {
- ...defaultConfig.resolve.alias,
- ...{
- ppcpButton: path.resolve(
- __dirname,
- '../ppcp-button/resources/js'
- ),
- },
- },
- },
- },
},
};
diff --git a/modules/ppcp-wc-gateway/resources/css/gateway-settings.scss b/modules/ppcp-wc-gateway/resources/css/gateway-settings.scss
index 768f95c75..537d035b4 100644
--- a/modules/ppcp-wc-gateway/resources/css/gateway-settings.scss
+++ b/modules/ppcp-wc-gateway/resources/css/gateway-settings.scss
@@ -8,7 +8,7 @@
}
}
-.ppcp-preview {
+.ppcp-preview:not(.ppcp-r-styling__preview) {
width: var(--box-width, 100%);
padding: 15px;
border: 1px solid lightgray;