From 4ae82b704ae5539adcf14c1e60131df5e121d455 Mon Sep 17 00:00:00 2001 From: Alex P Date: Wed, 15 Feb 2023 16:03:49 +0200 Subject: [PATCH] Make SmartButton more reusable --- modules/ppcp-button/resources/js/button.js | 18 +-------- .../js/modules/Helper/ScriptLoading.js | 24 ++++++++++++ .../src/Assets/DisabledSmartButton.php | 23 ++++++++--- .../ppcp-button/src/Assets/SmartButton.php | 39 ++++++++++++------- .../src/Assets/SmartButtonInterface.php | 18 +++++++-- 5 files changed, 82 insertions(+), 40 deletions(-) create mode 100644 modules/ppcp-button/resources/js/modules/Helper/ScriptLoading.js diff --git a/modules/ppcp-button/resources/js/button.js b/modules/ppcp-button/resources/js/button.js index 8dc519a6c..d5a7dc5ee 100644 --- a/modules/ppcp-button/resources/js/button.js +++ b/modules/ppcp-button/resources/js/button.js @@ -6,7 +6,6 @@ import PayNowBootstrap from "./modules/ContextBootstrap/PayNowBootstrap"; import Renderer from './modules/Renderer/Renderer'; import ErrorHandler from './modules/ErrorHandler'; import CreditCardRenderer from "./modules/Renderer/CreditCardRenderer"; -import dataClientIdAttributeHandler from "./modules/DataClientIdAttributeHandler"; import MessageRenderer from "./modules/Renderer/MessageRenderer"; import Spinner from "./modules/Helper/Spinner"; import { @@ -19,6 +18,7 @@ import {isChangePaymentPage} from "./modules/Helper/Subscriptions"; import FreeTrialHandler from "./modules/ActionHandler/FreeTrialHandler"; import FormSaver from './modules/Helper/FormSaver'; import FormValidator from "./modules/Helper/FormValidator"; +import {loadPaypalScript} from "./modules/Helper/ScriptLoading"; // TODO: could be a good idea to have a separate spinner for each gateway, // but I think we care mainly about the script loading, so one spinner should be enough. @@ -255,24 +255,10 @@ document.addEventListener( hideOrderButtonIfPpcpGateway(); }); - const script = document.createElement('script'); - script.addEventListener('load', (event) => { + loadPaypalScript(PayPalCommerceGateway, () => { bootstrapped = true; bootstrap(); }); - script.setAttribute('src', PayPalCommerceGateway.button.url); - Object.entries(PayPalCommerceGateway.script_attributes).forEach( - (keyValue) => { - script.setAttribute(keyValue[0], keyValue[1]); - } - ); - - if (PayPalCommerceGateway.data_client_id.set_attribute) { - dataClientIdAttributeHandler(script, PayPalCommerceGateway.data_client_id); - return; - } - - document.body.appendChild(script); }, ); diff --git a/modules/ppcp-button/resources/js/modules/Helper/ScriptLoading.js b/modules/ppcp-button/resources/js/modules/Helper/ScriptLoading.js new file mode 100644 index 000000000..c5742ab19 --- /dev/null +++ b/modules/ppcp-button/resources/js/modules/Helper/ScriptLoading.js @@ -0,0 +1,24 @@ +import dataClientIdAttributeHandler from "../DataClientIdAttributeHandler"; + +export const loadPaypalScript = (config, onLoaded) => { + if (typeof paypal !== 'undefined') { + onLoaded(); + return; + } + + const script = document.createElement('script'); + script.addEventListener('load', onLoaded); + script.setAttribute('src', config.url); + Object.entries(config.script_attributes).forEach( + (keyValue) => { + script.setAttribute(keyValue[0], keyValue[1]); + } + ); + + if (config.data_client_id.set_attribute) { + dataClientIdAttributeHandler(script, config.data_client_id); + return; + } + + document.body.appendChild(script); +} diff --git a/modules/ppcp-button/src/Assets/DisabledSmartButton.php b/modules/ppcp-button/src/Assets/DisabledSmartButton.php index 9fe537163..04cee3eab 100644 --- a/modules/ppcp-button/src/Assets/DisabledSmartButton.php +++ b/modules/ppcp-button/src/Assets/DisabledSmartButton.php @@ -24,12 +24,16 @@ class DisabledSmartButton implements SmartButtonInterface { } /** - * Enqueues necessary scripts. - * - * @return bool + * Whether the scripts should be loaded. */ - public function enqueue(): bool { - return true; + public function should_load(): bool { + return false; + } + + /** + * Enqueues necessary scripts. + */ + public function enqueue(): void { } /** @@ -41,4 +45,13 @@ class DisabledSmartButton implements SmartButtonInterface { return false; } + + /** + * The configuration for the smart buttons. + * + * @return array + */ + public function script_data(): array { + return array(); + } } diff --git a/modules/ppcp-button/src/Assets/SmartButton.php b/modules/ppcp-button/src/Assets/SmartButton.php index 725c6e559..747d91047 100644 --- a/modules/ppcp-button/src/Assets/SmartButton.php +++ b/modules/ppcp-button/src/Assets/SmartButton.php @@ -506,17 +506,25 @@ class SmartButton implements SmartButtonInterface { } /** - * Enqueues the script. - * - * @return bool - * @throws NotFoundException When a setting was not found. + * Whether the scripts should be loaded. */ - public function enqueue(): bool { + public function should_load(): bool { $buttons_enabled = $this->settings->has( 'enabled' ) && $this->settings->get( 'enabled' ); if ( ! is_checkout() && ! $buttons_enabled ) { return false; } + return true; + } + + /** + * Enqueues the scripts. + */ + public function enqueue(): void { + if ( ! $this->should_load() ) { + return; + } + $load_script = false; if ( is_checkout() && $this->settings->has( 'dcc_enabled' ) && $this->settings->get( 'dcc_enabled' ) ) { $load_script = true; @@ -554,10 +562,9 @@ class SmartButton implements SmartButtonInterface { wp_localize_script( 'ppcp-smart-button', 'PayPalCommerceGateway', - $this->localize_script() + $this->script_data() ); } - return true; } /** @@ -751,18 +758,22 @@ class SmartButton implements SmartButtonInterface { } /** - * The localized data for the smart button. + * The configuration for the smart buttons. * * @return array * @throws NotFoundException If a setting hasn't been found. */ - private function localize_script(): array { + public function script_data(): array { global $wp; $is_free_trial_cart = $this->is_free_trial_cart(); + $url_params = $this->url_params(); + $this->request_data->enqueue_nonce_fix(); $localize = array( + 'url' => add_query_arg( $url_params, 'https://www.paypal.com/sdk/js' ), + 'url_params' => $url_params, 'script_attributes' => $this->attributes(), 'data_client_id' => array( 'set_attribute' => ( is_checkout() && $this->dcc_is_enabled() ) || $this->can_save_vault_token(), @@ -809,7 +820,6 @@ class SmartButton implements SmartButtonInterface { 'wrapper' => '#ppc-button-' . PayPalGateway::ID, 'mini_cart_wrapper' => '#ppc-button-minicart', 'cancel_wrapper' => '#ppcp-cancel', - 'url' => $this->url(), 'mini_cart_style' => array( 'layout' => $this->style_for_context( 'layout', 'mini-cart' ), 'color' => $this->style_for_context( 'color', 'mini-cart' ), @@ -916,12 +926,12 @@ class SmartButton implements SmartButtonInterface { } /** - * The JavaScript SDK url to load. + * The JavaScript SDK url parameters. * - * @return string + * @return array * @throws NotFoundException If a setting was not found. */ - private function url(): string { + private function url_params(): array { $intent = ( $this->settings->has( 'intent' ) ) ? $this->settings->get( 'intent' ) : 'capture'; $product_intent = $this->subscription_helper->current_product_is_subscription() ? 'authorize' : $intent; $other_context_intent = $this->subscription_helper->cart_contains_subscription() ? 'authorize' : $intent; @@ -993,8 +1003,7 @@ class SmartButton implements SmartButtonInterface { $params['enable-funding'] = implode( ',', array_unique( $enable_funding ) ); } - $smart_button_url = add_query_arg( $params, 'https://www.paypal.com/sdk/js' ); - return $smart_button_url; + return $params; } /** diff --git a/modules/ppcp-button/src/Assets/SmartButtonInterface.php b/modules/ppcp-button/src/Assets/SmartButtonInterface.php index a574bc649..be5f5d015 100644 --- a/modules/ppcp-button/src/Assets/SmartButtonInterface.php +++ b/modules/ppcp-button/src/Assets/SmartButtonInterface.php @@ -22,11 +22,14 @@ interface SmartButtonInterface { public function render_wrapper(): bool; /** - * Enqueues the necessary scripts. - * - * @return bool + * Whether the scripts should be loaded. */ - public function enqueue(): bool; + public function should_load(): bool; + + /** + * Enqueues the necessary scripts. + */ + public function enqueue(): void; /** * Whether the running installation could save vault tokens or not. @@ -34,4 +37,11 @@ interface SmartButtonInterface { * @return bool */ public function can_save_vault_token(): bool; + + /** + * The configuration for the smart buttons. + * + * @return array + */ + public function script_data(): array; }