diff --git a/modules/ppcp-settings/resources/js/data/onboarding/reducer.js b/modules/ppcp-settings/resources/js/data/onboarding/reducer.js index 954801995..e37d145b0 100644 --- a/modules/ppcp-settings/resources/js/data/onboarding/reducer.js +++ b/modules/ppcp-settings/resources/js/data/onboarding/reducer.js @@ -8,6 +8,9 @@ const defaultState = { useManualConnection: false, clientId: '', clientSecret: '', + canUseCasualSelling: false, + canUseVaulting: false, + canUseCardPayments: false, }, }; diff --git a/modules/ppcp-settings/resources/js/data/store.js b/modules/ppcp-settings/resources/js/data/store.js index f5a1a4b13..f416cb94f 100644 --- a/modules/ppcp-settings/resources/js/data/store.js +++ b/modules/ppcp-settings/resources/js/data/store.js @@ -27,4 +27,23 @@ export const initStore = () => { } ); register( store ); + + /* eslint-disable no-console */ + // Provide a debug tool to inspect the Redux store via the JS console. + if ( window.ppcpSettings?.debug && console?.groupCollapsed ) { + window.ppcpSettings.dumpStore = () => { + const storeSelector = `wp.data.select('${ STORE_NAME }')`; + console.group( `[STORE] ${ storeSelector }` ); + + const storeState = wp.data.select( STORE_NAME ); + Object.keys( selectors ).forEach( ( selector ) => { + console.groupCollapsed( `[SELECTOR] .${ selector }()` ); + console.table( storeState[ selector ]() ); + console.groupEnd(); + } ); + + console.groupEnd(); + }; + } + /* eslint-enable no-console */ }; diff --git a/modules/ppcp-settings/services.php b/modules/ppcp-settings/services.php index c8bb64144..f34257f79 100644 --- a/modules/ppcp-settings/services.php +++ b/modules/ppcp-settings/services.php @@ -26,7 +26,20 @@ return array( ); }, 'settings.data.onboarding' => static function ( ContainerInterface $container ) : OnboardingProfile { - return new OnboardingProfile(); + $can_use_casual_selling = false; + $can_use_vaulting = $container->has( 'save-payment-methods.eligible' ) && $container->get( 'save-payment-methods.eligible' ); + $can_use_card_payments = $container->has( 'card-fields.eligible' ) && $container->get( 'card-fields.eligible' ); + + // Card payments are disabled for this plugin when WooPayments is active. + if ( class_exists( '\WC_Payments' ) ) { + $can_use_card_payments = false; + } + + return new OnboardingProfile( + $can_use_casual_selling, + $can_use_vaulting, + $can_use_card_payments + ); }, 'settings.rest.onboarding' => static function ( ContainerInterface $container ) : OnboardingRestEndpoint { return new OnboardingRestEndpoint( $container->get( 'settings.data.onboarding' ) ); diff --git a/modules/ppcp-settings/src/Data/AbstractDataModel.php b/modules/ppcp-settings/src/Data/AbstractDataModel.php index d9cd0fbae..1d711cbe5 100644 --- a/modules/ppcp-settings/src/Data/AbstractDataModel.php +++ b/modules/ppcp-settings/src/Data/AbstractDataModel.php @@ -57,8 +57,9 @@ abstract class AbstractDataModel { * Loads the model data from WordPress options. */ public function load() : void { - $saved_data = get_option( static::OPTION_KEY, array() ); - $this->data = array_merge( $this->data, $saved_data ); + $saved_data = get_option( static::OPTION_KEY, array() ); + $filtered_data = array_intersect_key( $saved_data, $this->data ); + $this->data = array_merge( $this->data, $filtered_data ); } /** @@ -91,8 +92,6 @@ abstract class AbstractDataModel { $setter = "set_$key"; if ( method_exists( $this, $setter ) ) { $this->$setter( $value ); - } else { - $this->data[ $key ] = $value; } } } diff --git a/modules/ppcp-settings/src/Data/OnboardingProfile.php b/modules/ppcp-settings/src/Data/OnboardingProfile.php index 9cfd29d46..c9a45ead0 100644 --- a/modules/ppcp-settings/src/Data/OnboardingProfile.php +++ b/modules/ppcp-settings/src/Data/OnboardingProfile.php @@ -9,12 +9,16 @@ declare( strict_types = 1 ); namespace WooCommerce\PayPalCommerce\Settings\Data; +use RuntimeException; + /** * Class OnboardingProfile * * This class serves as a container for managing the onboarding profile details - * within the WooCommerce PayPal Commerce plugin. It provides methods to retrieve - * and save the onboarding profile data using WordPress options. + * within the WooCommerce PayPal Commerce plugin. + * + * This profile impacts the onboarding wizard and help to apply default + * settings. The details here should not be used outside the onboarding process. */ class OnboardingProfile extends AbstractDataModel { @@ -25,6 +29,27 @@ class OnboardingProfile extends AbstractDataModel { */ protected const OPTION_KEY = 'woocommerce-ppcp-data-onboarding'; + /** + * Constructor. + * + * @param bool $can_use_casual_selling Whether casual selling is enabled in the store's country. + * @param bool $can_use_vaulting Whether vaulting is enabled in the store's country. + * @param bool $can_use_card_payments Whether credit card payments are possible. + * + * @throws RuntimeException If the OPTION_KEY is not defined in the child class. + */ + public function __construct( + bool $can_use_casual_selling = false, + bool $can_use_vaulting = false, + bool $can_use_card_payments = false + ) { + parent::__construct(); + + $this->data['can_use_casual_selling'] = $can_use_casual_selling; + $this->data['can_use_vaulting'] = $can_use_vaulting; + $this->data['can_use_card_payments'] = $can_use_card_payments; + } + /** * Get default values for the model. * @@ -32,11 +57,14 @@ class OnboardingProfile extends AbstractDataModel { */ protected function get_defaults() : array { return array( - 'step' => 0, - 'use_sandbox' => false, - 'use_manual_connection' => false, - 'client_id' => '', - 'client_secret' => '', + 'step' => 0, + 'use_sandbox' => false, + 'use_manual_connection' => false, + 'client_id' => '', + 'client_secret' => '', + 'can_use_casual_selling' => null, + 'can_use_vaulting' => null, + 'can_use_card_payments' => null, ); } @@ -131,4 +159,31 @@ class OnboardingProfile extends AbstractDataModel { public function set_client_secret( string $client_secret ) : void { $this->data['client_secret'] = sanitize_text_field( $client_secret ); } + + /** + * Gets whether casual selling can be used. + * + * @return bool + */ + public function get_can_use_casual_selling() : bool { + return (bool) $this->data['can_use_casual_selling']; + } + + /** + * Gets whether vaulting can be used. + * + * @return bool + */ + public function get_can_use_vaulting() : bool { + return (bool) $this->data['can_use_vaulting']; + } + + /** + * Gets whether Credit Card payments can be used. + * + * @return bool + */ + public function get_can_use_card_payments() : bool { + return (bool) $this->data['can_use_card_payments']; + } } diff --git a/modules/ppcp-settings/src/Endpoint/OnboardingRestEndpoint.php b/modules/ppcp-settings/src/Endpoint/OnboardingRestEndpoint.php index dd8f19e67..e5a38af5d 100644 --- a/modules/ppcp-settings/src/Endpoint/OnboardingRestEndpoint.php +++ b/modules/ppcp-settings/src/Endpoint/OnboardingRestEndpoint.php @@ -41,26 +41,38 @@ class OnboardingRestEndpoint extends RestEndpoint { * @var array */ private array $field_map = array( - 'step' => array( + 'step' => array( 'js_name' => 'step', 'sanitize' => 'to_number', ), - 'use_sandbox' => array( + 'use_sandbox' => array( 'js_name' => 'useSandbox', 'sanitize' => 'to_boolean', ), - 'use_manual_connection' => array( + 'use_manual_connection' => array( 'js_name' => 'useManualConnection', 'sanitize' => 'to_boolean', ), - 'client_id' => array( + 'client_id' => array( 'js_name' => 'clientId', 'sanitize' => 'sanitize_text_field', ), - 'client_secret' => array( + 'client_secret' => array( 'js_name' => 'clientSecret', 'sanitize' => 'sanitize_text_field', ), + 'can_use_casual_selling' => array( + 'js_name' => 'canUseCasualSelling', + 'sanitize' => 'read_only', + ), + 'can_use_vaulting' => array( + 'js_name' => 'canUseVaulting', + 'sanitize' => 'read_only', + ), + 'can_use_card_payments' => array( + 'js_name' => 'canUseCardPayments', + 'sanitize' => 'read_only', + ), ); /** diff --git a/modules/ppcp-settings/src/Endpoint/RestEndpoint.php b/modules/ppcp-settings/src/Endpoint/RestEndpoint.php index 63e543d59..9bb98dfac 100644 --- a/modules/ppcp-settings/src/Endpoint/RestEndpoint.php +++ b/modules/ppcp-settings/src/Endpoint/RestEndpoint.php @@ -53,7 +53,11 @@ class RestEndpoint extends WC_REST_Controller { $source_key = $details['js_name'] ?? ''; $sanitation_cb = $details['sanitize'] ?? null; - if ( ! $source_key || ! isset( $params[ $source_key ] ) ) { + if ( + ! $source_key + || ! isset( $params[ $source_key ] ) + || 'read_only' === $sanitation_cb + ) { continue; } @@ -121,5 +125,4 @@ class RestEndpoint extends WC_REST_Controller { protected function to_number( $value ) { return $value !== null ? ( is_numeric( $value ) ? $value + 0 : null ) : null; } - } diff --git a/modules/ppcp-settings/src/SettingsModule.php b/modules/ppcp-settings/src/SettingsModule.php index fdc286521..3533c2394 100644 --- a/modules/ppcp-settings/src/SettingsModule.php +++ b/modules/ppcp-settings/src/SettingsModule.php @@ -86,6 +86,7 @@ class SettingsModule implements ServiceModule, ExecutableModule { 'assets' => array( 'imagesUrl' => $module_url . '/images/', ), + 'debug' => defined( 'WP_DEBUG' ) && WP_DEBUG, ) ); }