diff --git a/modules/ppcp-button/resources/js/modules/Renderer/PaymentButton.js b/modules/ppcp-button/resources/js/modules/Renderer/PaymentButton.js new file mode 100644 index 000000000..8843ca662 --- /dev/null +++ b/modules/ppcp-button/resources/js/modules/Renderer/PaymentButton.js @@ -0,0 +1,101 @@ +import ConsoleLogger from '../Helper/ConsoleLogger'; +import { apmButtonsInit } from '../Helper/ApmButtons'; + +/** + * Base class for APM payment buttons, like GooglePay and ApplePay. + * + * This class is not intended for the PayPal button. + */ +export default class PaymentButton { + /** + * @type {ConsoleLogger} + */ + #logger; + + /** + * Whether the payment button is initialized. + * + * @type {boolean} + */ + #isInitialized = false; + + /** + * The button's context. + */ + #context; + + #buttonConfig; + + #ppcpConfig; + + constructor( gatewayName, context, buttonConfig, ppcpConfig ) { + this.#logger = new ConsoleLogger( gatewayName, context ); + this.#logger.enabled = !! buttonConfig?.is_debug; + + this.#context = context; + this.#buttonConfig = buttonConfig; + this.#ppcpConfig = ppcpConfig; + + apmButtonsInit( ppcpConfig ); + } + + /** + * Whether the payment button was fully initialized. Read-only. + * + * @return {boolean} True indicates, that the button was fully initialized. + */ + get isInitialized() { + return this.#isInitialized; + } + + /** + * The button's context. Read-only. + * + * TODO: Convert the string to a context-object (primitive obsession smell) + * + * @return {string} The button context. + */ + get context() { + return this.#context; + } + + /** + * Log a debug detail to the browser console. + * + * @param {any} args + */ + log( ...args ) { + this.#logger.log( ...args ); + } + + /** + * Log an error message to the browser console. + * + * @param {any} args + */ + error( ...args ) { + this.#logger.error( ...args ); + } + + /** + * Must be named `init()` to simulate "protected" visibility: + * Since the derived class also implements a method with the same name, this method can only + * be called by the derived class, but not from any other code. + * + * @protected + */ + init() { + this.#isInitialized = true; + } + + /** + * Must be named `reinit()` to simulate "protected" visibility: + * Since the derived class also implements a method with the same name, this method can only + * be called by the derived class, but not from any other code. + * + * @protected + */ + reinit() { + this.#isInitialized = false; + } +} diff --git a/modules/ppcp-googlepay/resources/js/GooglepayButton.js b/modules/ppcp-googlepay/resources/js/GooglepayButton.js index a21f803a4..f778ff8e2 100644 --- a/modules/ppcp-googlepay/resources/js/GooglepayButton.js +++ b/modules/ppcp-googlepay/resources/js/GooglepayButton.js @@ -1,9 +1,8 @@ /* global google */ -import ConsoleLogger from '../../../ppcp-button/resources/js/modules/Helper/ConsoleLogger'; +import PaymentButton from '../../../ppcp-button/resources/js/modules/Renderer/PaymentButton'; import widgetBuilder from '../../../ppcp-button/resources/js/modules/Renderer/WidgetBuilder'; import UpdatePaymentData from './Helper/UpdatePaymentData'; -import { apmButtonsInit } from '../../../ppcp-button/resources/js/modules/Helper/ApmButtons'; import { PaymentMethods, PaymentContext as CONTEXT, @@ -28,22 +27,10 @@ import { * @property {string} language - The locale; an empty string will apply the user-agent's language. */ -class GooglepayButton { - /** - * @type {ConsoleLogger} - */ - #logger; - +class GooglepayButton extends PaymentButton { #wrapperId = ''; #ppcpButtonWrapperId = ''; - /** - * Whether the payment button is initialized. - * - * @type {boolean} - */ - #isInitialized = false; - /** * Whether the current client support the payment button. * This state is mainly dependent on the response of `PaymentClient.isReadyToPay()` @@ -72,12 +59,8 @@ class GooglepayButton { ppcpConfig, contextHandler ) { - this.#logger = new ConsoleLogger( 'GooglePayButton', context ); - this.#logger.enabled = !! buttonConfig?.is_debug; + super( 'GooglePayButton', context, buttonConfig, ppcpConfig ); - apmButtonsInit( ppcpConfig ); - - this.context = context; this.externalHandler = externalHandler; this.buttonConfig = buttonConfig; this.ppcpConfig = ppcpConfig; @@ -88,14 +71,6 @@ class GooglepayButton { this.log( 'Create instance' ); } - log( ...args ) { - this.#logger.log( ...args ); - } - - error( ...args ) { - this.#logger.error( ...args ); - } - /** * Determines if the current payment button should be rendered as a stand-alone gateway. * The return value `false` usually means, that the payment button is bundled with all available @@ -301,8 +276,21 @@ class GooglepayButton { this.refresh(); } - init( config, transactionInfo ) { - if ( this.#isInitialized ) { + init( config = null, transactionInfo = null ) { + if ( this.isInitialized ) { + return; + } + if ( config ) { + this.googlePayConfig = config; + } + if ( transactionInfo ) { + this.transactionInfo = transactionInfo; + } + + if ( ! this.googlePayConfig || ! this.transactionInfo ) { + this.error( + 'Init called without providing config or transactionInfo' + ); return; } @@ -314,11 +302,8 @@ class GooglepayButton { return; } - this.log( 'Init' ); - this.#isInitialized = true; + super.init(); - this.googlePayConfig = config; - this.transactionInfo = transactionInfo; this.allowedPaymentMethods = config.allowedPaymentMethods; this.baseCardPaymentMethod = this.allowedPaymentMethods[ 0 ]; @@ -353,12 +338,12 @@ class GooglepayButton { } reinit() { - if ( ! this.googlePayConfig ) { + if ( ! this.isInitialized ) { return; } - this.#isInitialized = false; - this.init( this.googlePayConfig, this.transactionInfo ); + super.reinit(); + this.init(); } validateConfig() {