diff --git a/modules/ppcp-button/src/Assets/SmartButton.php b/modules/ppcp-button/src/Assets/SmartButton.php index 5b59dcd66..7f801d095 100644 --- a/modules/ppcp-button/src/Assets/SmartButton.php +++ b/modules/ppcp-button/src/Assets/SmartButton.php @@ -1007,8 +1007,9 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages 'id' => CardButtonGateway::ID, 'wrapper' => '#ppc-button-' . CardButtonGateway::ID, 'style' => array( - 'shape' => $this->style_for_context( 'shape', $this->context() ), - // TODO: color black, white from the gateway settings. + 'shape' => $this->style_for_apm( 'shape', 'card' ), + 'color' => $this->style_for_apm( 'color', 'card', 'black' ), + 'layout' => $this->style_for_apm( 'poweredby_tagline', 'card', false ) === $this->normalize_style_value( true ) ? 'vertical' : 'horizontal', ), ), ), @@ -1343,9 +1344,9 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages } /** - * Determines the style for a given indicator in a given context. + * Determines the style for a given property in a given context. * - * @param string $style The style. + * @param string $style The name of the style property. * @param string $context The context. * * @return string @@ -1368,13 +1369,46 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages $context = 'general'; } - $value = isset( $defaults[ $style ] ) ? - $defaults[ $style ] : ''; - $value = $this->settings->has( 'button_' . $style ) ? - $this->settings->get( 'button_' . $style ) : $value; - $value = $this->settings->has( 'button_' . $context . '_' . $style ) ? - $this->settings->get( 'button_' . $context . '_' . $style ) : $value; + return $this->get_style_value( "button_{$context}_${style}" ) + ?? $this->get_style_value( "button_${style}" ) + ?? $this->normalize_style_value( $defaults[ $style ] ?? '' ); + } + /** + * Determines the style for a given property in a given APM. + * + * @param string $style The name of the style property. + * @param string $apm The APM name, such as 'card'. + * @param ?mixed $default The default value. + * + * @return string + */ + private function style_for_apm( string $style, string $apm, $default = null ): string { + return $this->get_style_value( "${apm}_button_${style}" ) + ?? ( $default ? $this->normalize_style_value( $default ) : null ) + ?? $this->style_for_context( $style, 'checkout' ); + } + + /** + * Returns the style property value or null. + * + * @param string $key The style property key in the settings. + * @return string|null + */ + private function get_style_value( string $key ): ?string { + if ( ! $this->settings->has( $key ) ) { + return null; + } + return $this->normalize_style_value( $this->settings->get( $key ) ); + } + + /** + * Converts the style property value to string. + * + * @param mixed $value The style property value. + * @return string + */ + private function normalize_style_value( $value ): string { if ( is_bool( $value ) ) { $value = $value ? 'true' : 'false'; } diff --git a/modules/ppcp-wc-gateway/extensions.php b/modules/ppcp-wc-gateway/extensions.php index 5ab1fc8ab..aca11f1b1 100644 --- a/modules/ppcp-wc-gateway/extensions.php +++ b/modules/ppcp-wc-gateway/extensions.php @@ -61,17 +61,27 @@ return array( ); }, 'wcgateway.settings.fields' => function ( ContainerInterface $container, array $fields ): array { - $path_to_settings_fields = __DIR__ . '/src/Settings/Fields'; + $files = array( + 'paypal-smart-button-fields.php', + 'connection-tab-fields.php', + 'pay-later-tab-fields.php', + 'card-button-fields.php', + ); - $get_paypal_button_fields = require $path_to_settings_fields . '/paypal-smart-button-fields.php'; - $paypal_button_fields = $get_paypal_button_fields( $container, $fields ) ?? array(); - - $get_connection_tab_fields = require $path_to_settings_fields . '/connection-tab-fields.php'; - $connection_tab_fields = $get_connection_tab_fields( $container, $fields ) ?? array(); - - $get_pay_later_tab_fields = require $path_to_settings_fields . '/pay-later-tab-fields.php'; - $pay_later_tab_fields = $get_pay_later_tab_fields( $container, $fields ) ?? array(); - - return array_merge( $paypal_button_fields, $connection_tab_fields, $pay_later_tab_fields ); + return array_merge( + ...array_map( + function ( string $file ) use ( $container, $fields ): array { + $path_to_settings_fields = __DIR__ . '/src/Settings/Fields/'; + /** + * Skip path check. + * + * @psalm-suppress UnresolvableInclude + */ + $get_fields = require $path_to_settings_fields . $file; + return $get_fields( $container, $fields ) ?? array(); + }, + $files + ) + ); }, ); diff --git a/modules/ppcp-wc-gateway/resources/js/gateway-settings.js b/modules/ppcp-wc-gateway/resources/js/gateway-settings.js index afec3a426..65b96e1d1 100644 --- a/modules/ppcp-wc-gateway/resources/js/gateway-settings.js +++ b/modules/ppcp-wc-gateway/resources/js/gateway-settings.js @@ -77,7 +77,8 @@ document.addEventListener( function createButtonPreview(settingsCallback) { const render = (settings) => { - const wrapper = document.querySelector(settings.button.wrapper); + 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; } @@ -96,6 +97,11 @@ document.addEventListener( renderPreview(settingsCallback, render); } + function currentTabId() { + const params = new URLSearchParams(location.search); + return params.has('ppcp-tab') ? params.get('ppcp-tab') : params.get('section'); + } + function shouldShowPayLaterButton() { const payLaterButtonLocations = document.querySelector('[name="ppcp[pay_later_button_locations][]"]'); @@ -106,6 +112,14 @@ document.addEventListener( return payLaterButtonInput.checked && payLaterButtonLocations.selectedOptions.length > 0 } + function shouldDisableCardButton() { + if (currentTabId() === 'ppcp-card-button-gateway') { + return false; + } + + return PayPalCommerceGatewaySettings.is_acdc_enabled || jQuery('#ppcp-allow_card_button_gateway').is(':checked'); + } + function getPaypalScriptSettings() { const disableFundingInput = jQuery('[name="ppcp[disable_funding][]"]'); let disabledSources = disableFundingInput.length > 0 ? disableFundingInput.val() : PayPalCommerceGatewaySettings.disabled_sources; @@ -130,6 +144,10 @@ document.addEventListener( disabledSources = disabledSources.concat('credit') } + if (shouldDisableCardButton()) { + disabledSources = disabledSources.concat('card'); + } + if (disabledSources?.length) { settings['disable-funding'] = disabledSources; } @@ -154,7 +172,7 @@ document.addEventListener( .catch((error) => console.error('failed to load the PayPal JS SDK script', error)); } - function getButtonSettings(wrapperSelector, fields) { + function getButtonSettings(wrapperSelector, fields, apm = null) { const layoutElement = jQuery(fields['layout']); const layout = (layoutElement.length && layoutElement.is(':visible')) ? layoutElement.val() : 'vertical'; const style = { @@ -167,13 +185,24 @@ document.addEventListener( if ('height' in fields) { style['height'] = parseInt(jQuery(fields['height']).val()); } - return { + if ('poweredby_tagline' in fields) { + style['layout'] = jQuery(fields['poweredby_tagline']).is(':checked') ? 'vertical' : 'horizontal'; + } + const settings = { 'button': { 'wrapper': wrapperSelector, 'style': style, }, 'separate_buttons': {}, }; + if (apm) { + settings.separate_buttons[apm] = { + 'wrapper': wrapperSelector, + 'style': style, + }; + settings.button.wrapper = null; + } + return settings; } function createMessagesPreview(settingsCallback) { @@ -316,6 +345,13 @@ document.addEventListener( }); createButtonPreview(() => getButtonDefaultSettings('#ppcpPayLaterButtonPreview')); + + const apmFieldPrefix = '#ppcp-card_button_'; + createButtonPreview(() => getButtonSettings('#ppcpCardButtonPreview', { + 'color': apmFieldPrefix + 'color', + 'shape': apmFieldPrefix + 'shape', + 'poweredby_tagline': apmFieldPrefix + 'poweredby_tagline', + }, 'card')); }); } } diff --git a/modules/ppcp-wc-gateway/src/Assets/SettingsPageAssets.php b/modules/ppcp-wc-gateway/src/Assets/SettingsPageAssets.php index 02e5eecd8..4e8bee586 100644 --- a/modules/ppcp-wc-gateway/src/Assets/SettingsPageAssets.php +++ b/modules/ppcp-wc-gateway/src/Assets/SettingsPageAssets.php @@ -11,6 +11,8 @@ namespace WooCommerce\PayPalCommerce\WcGateway\Assets; use WooCommerce\PayPalCommerce\Onboarding\Environment; use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; +use WooCommerce\PayPalCommerce\WcGateway\Gateway\CardButtonGateway; +use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; /** * Class SettingsPageAssets @@ -94,6 +96,13 @@ class SettingsPageAssets { */ private $is_settings_page; + /** + * Whether the ACDC gateway is enabled. + * + * @var bool + */ + private $is_acdc_enabled; + /** * Assets constructor. * @@ -108,6 +117,7 @@ class SettingsPageAssets { * @param array $disabled_sources The list of disabled funding sources. * @param array $all_funding_sources The list of all existing funding sources. * @param bool $is_settings_page Whether it's a settings page of this plugin. + * @param bool $is_acdc_enabled Whether the ACDC gateway is enabled. */ public function __construct( string $module_url, @@ -120,7 +130,8 @@ class SettingsPageAssets { bool $is_pay_later_button_enabled, array $disabled_sources, array $all_funding_sources, - bool $is_settings_page + bool $is_settings_page, + bool $is_acdc_enabled ) { $this->module_url = $module_url; $this->version = $version; @@ -133,6 +144,7 @@ class SettingsPageAssets { $this->disabled_sources = $disabled_sources; $this->all_funding_sources = $all_funding_sources; $this->is_settings_page = $is_settings_page; + $this->is_acdc_enabled = $is_acdc_enabled; } /** @@ -181,7 +193,7 @@ class SettingsPageAssets { $section = wc_clean( wp_unslash( $_GET['section'] ?? '' ) ); // phpcs:enable WordPress.Security.NonceVerification.Recommended - return 'checkout' === $tab && 'ppcp-gateway' === $section; + return 'checkout' === $tab && in_array( $section, array( PayPalGateway::ID, CardButtonGateway::ID ), true ); } /** @@ -221,6 +233,7 @@ class SettingsPageAssets { 'environment' => $this->environment->current_environment(), 'integration_date' => PAYPAL_INTEGRATION_DATE, 'is_pay_later_button_enabled' => $this->is_pay_later_button_enabled, + 'is_acdc_enabled' => $this->is_acdc_enabled, 'disabled_sources' => $this->disabled_sources, 'all_funding_sources' => $this->all_funding_sources, 'components' => array( 'buttons', 'funding-eligibility', 'messages' ), diff --git a/modules/ppcp-wc-gateway/src/Settings/Fields/card-button-fields.php b/modules/ppcp-wc-gateway/src/Settings/Fields/card-button-fields.php new file mode 100644 index 000000000..d941f0de3 --- /dev/null +++ b/modules/ppcp-wc-gateway/src/Settings/Fields/card-button-fields.php @@ -0,0 +1,126 @@ +get( 'wcgateway.current-ppcp-settings-page-id' ); + + if ( $current_page_id !== CardButtonGateway::ID ) { + return $fields; + } + + $render_preview_element = function ( string $id ): string { + return ' +
+

' . __( 'Standard Card Button Styling Preview', 'woocommerce-paypal-payments' ) . '

+
+
'; + }; + + $new_fields = array( + 'card_button_styling_heading' => array( + 'heading' => __( 'Standard Card Button Styling', 'woocommerce-paypal-payments' ), + 'description' => sprintf( + // translators: %1$s and %2$s are the opening and closing of HTML tag. + __( + 'Customize the appearance of the Standard Card Button on the %1$sCheckout page%2$s.', + 'woocommerce-paypal-payments' + ), + '', + '', + '' + ), + 'type' => 'ppcp-heading', + 'screens' => array( + State::STATE_START, + State::STATE_ONBOARDED, + ), + 'requirements' => array(), + 'gateway' => CardButtonGateway::ID, + ), + 'card_button_poweredby_tagline' => array( + 'title' => __( 'Tagline', 'woocommerce-paypal-payments' ), + 'type' => 'checkbox', + 'label' => __( 'Enable "Powered by PayPal" tagline', 'woocommerce-paypal-payments' ), + 'default' => false, + 'desc_tip' => true, + 'description' => __( + 'Add the "Powered by PayPal" line below the button.', + 'woocommerce-paypal-payments' + ), + 'screens' => array( + State::STATE_START, + State::STATE_ONBOARDED, + ), + 'requirements' => array(), + 'gateway' => CardButtonGateway::ID, + ), + 'card_button_color' => array( + 'title' => __( 'Color', 'woocommerce-paypal-payments' ), + 'type' => 'select', + 'class' => array(), + 'input_class' => array( 'wc-enhanced-select' ), + 'default' => 'black', + 'desc_tip' => true, + 'description' => __( + 'Controls the background color of the button. Change it to match your site design or aesthetic.', + 'woocommerce-paypal-payments' + ), + 'options' => array( + 'black' => __( 'Black', 'woocommerce-paypal-payments' ), + 'white' => __( 'White', 'woocommerce-paypal-payments' ), + ), + 'screens' => array( + State::STATE_START, + State::STATE_ONBOARDED, + ), + 'requirements' => array(), + 'gateway' => CardButtonGateway::ID, + ), + 'card_button_shape' => array( + 'title' => __( 'Shape', 'woocommerce-paypal-payments' ), + 'type' => 'select', + 'class' => array(), + 'input_class' => array( 'wc-enhanced-select' ), + 'default' => 'rect', + 'desc_tip' => true, + 'description' => __( + 'The pill-shaped button\'s unique and powerful shape signifies PayPal in people\'s minds. Use the rectangular button as an alternative when pill-shaped buttons might pose design challenges.', + 'woocommerce-paypal-payments' + ), + 'options' => array( + 'pill' => __( 'Pill', 'woocommerce-paypal-payments' ), + 'rect' => __( 'Rectangle', 'woocommerce-paypal-payments' ), + ), + 'screens' => array( + State::STATE_START, + State::STATE_ONBOARDED, + ), + 'requirements' => array(), + 'gateway' => CardButtonGateway::ID, + ), + 'card_button_preview' => array( + 'type' => 'ppcp-text', + 'text' => $render_preview_element( 'ppcpCardButtonPreview' ), + 'screens' => array( + State::STATE_ONBOARDED, + ), + 'requirements' => array(), + 'gateway' => CardButtonGateway::ID, + ), + ); + + return array_merge( $fields, $new_fields ); +}; diff --git a/modules/ppcp-wc-gateway/src/WCGatewayModule.php b/modules/ppcp-wc-gateway/src/WCGatewayModule.php index 2784635f7..a30be4d5a 100644 --- a/modules/ppcp-wc-gateway/src/WCGatewayModule.php +++ b/modules/ppcp-wc-gateway/src/WCGatewayModule.php @@ -185,7 +185,8 @@ class WCGatewayModule implements ModuleInterface { $settings_status->is_pay_later_button_enabled(), $settings->has( 'disable_funding' ) ? $settings->get( 'disable_funding' ) : array(), $c->get( 'wcgateway.settings.funding-sources' ), - $c->get( 'wcgateway.is-ppcp-settings-page' ) + $c->get( 'wcgateway.is-ppcp-settings-page' ), + $settings->has( 'dcc_enabled' ) && $settings->get( 'dcc_enabled' ) ); $assets->register_assets(); } diff --git a/tests/PHPUnit/WcGateway/Assets/SettingsPagesAssetsTest.php b/tests/PHPUnit/WcGateway/Assets/SettingsPagesAssetsTest.php index 9751a6c2c..1cfcab8a9 100644 --- a/tests/PHPUnit/WcGateway/Assets/SettingsPagesAssetsTest.php +++ b/tests/PHPUnit/WcGateway/Assets/SettingsPagesAssetsTest.php @@ -28,7 +28,8 @@ class SettingsPagesAssetsTest extends TestCase true, array(), array(), - true + true, + false ); when('is_admin')