Merge pull request #1827 from woocommerce/PCP-1771-separate-card-button-style

Add Standard Card Button gateway styling settings & preview (1771)
This commit is contained in:
Emili Castells 2023-11-21 15:03:31 +01:00 committed by GitHub
commit af638334ae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 249 additions and 28 deletions

View file

@ -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',
),
),
),
@ -1342,9 +1343,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
@ -1367,13 +1368,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';
}

View file

@ -62,17 +62,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
)
);
},
);

View file

@ -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'));
});
}
}

View file

@ -11,6 +11,8 @@ namespace WooCommerce\PayPalCommerce\WcGateway\Assets;
use WooCommerce\PayPalCommerce\Onboarding\Environment;
use WooCommerce\PayPalCommerce\Subscription\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' ),

View file

@ -0,0 +1,126 @@
<?php
/**
* The services of the Gateway module.
*
* @package WooCommerce\PayPalCommerce\WcGateway
*/
declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\WcGateway\Settings;
use WooCommerce\PayPalCommerce\Onboarding\State;
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CardButtonGateway;
return function ( ContainerInterface $container, array $fields ): array {
$current_page_id = $container->get( 'wcgateway.current-ppcp-settings-page-id' );
if ( $current_page_id !== CardButtonGateway::ID ) {
return $fields;
}
$render_preview_element = function ( string $id ): string {
return '
<div class="ppcp-preview ppcp-button-preview">
<h4>' . __( 'Standard Card Button Styling Preview', 'woocommerce-paypal-payments' ) . '</h4>
<div id="' . $id . '" class="ppcp-button-preview-inner"></div>
</div>';
};
$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 <a> tag.
__(
'Customize the appearance of the Standard Card Button on the %1$sCheckout page%2$s.',
'woocommerce-paypal-payments'
),
'<a href="https://woocommerce.com/document/woocommerce-paypal-payments/#button-on-checkout" target="_blank">',
'</a>',
'</ br>'
),
'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 );
};

View file

@ -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();
}

View file

@ -28,7 +28,8 @@ class SettingsPagesAssetsTest extends TestCase
true,
array(),
array(),
true
true,
false
);
when('is_admin')