From 83912f2b93e2b0aea8f6657631ff35caadef9c60 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Wed, 29 Jan 2025 16:41:50 +0100 Subject: [PATCH 01/37] Add rest endpoint boilerplate --- modules/ppcp-settings/services.php | 4 + .../Endpoint/PayLaterMessagingEndpoint.php | 88 +++++++++++++++++++ modules/ppcp-settings/src/SettingsModule.php | 1 + 3 files changed, 93 insertions(+) create mode 100644 modules/ppcp-settings/src/Endpoint/PayLaterMessagingEndpoint.php diff --git a/modules/ppcp-settings/services.php b/modules/ppcp-settings/services.php index cf397b8bf..cc993f0d6 100644 --- a/modules/ppcp-settings/services.php +++ b/modules/ppcp-settings/services.php @@ -21,6 +21,7 @@ use WooCommerce\PayPalCommerce\Settings\Endpoint\AuthenticationRestEndpoint; use WooCommerce\PayPalCommerce\Settings\Endpoint\CommonRestEndpoint; use WooCommerce\PayPalCommerce\Settings\Endpoint\LoginLinkRestEndpoint; use WooCommerce\PayPalCommerce\Settings\Endpoint\OnboardingRestEndpoint; +use WooCommerce\PayPalCommerce\Settings\Endpoint\PayLaterMessagingEndpoint; use WooCommerce\PayPalCommerce\Settings\Endpoint\PaymentRestEndpoint; use WooCommerce\PayPalCommerce\Settings\Endpoint\RefreshFeatureStatusEndpoint; use WooCommerce\PayPalCommerce\Settings\Endpoint\WebhookSettingsEndpoint; @@ -120,6 +121,9 @@ return array( $container->get( 'webhook.status.simulation' ) ); }, + 'settings.rest.pay_later_messaging' => static function ( ContainerInterface $container ) : PayLaterMessagingEndpoint { + return new PayLaterMessagingEndpoint(); + }, 'settings.casual-selling.supported-countries' => static function ( ContainerInterface $container ) : array { return array( 'AR', diff --git a/modules/ppcp-settings/src/Endpoint/PayLaterMessagingEndpoint.php b/modules/ppcp-settings/src/Endpoint/PayLaterMessagingEndpoint.php new file mode 100644 index 000000000..5e5643261 --- /dev/null +++ b/modules/ppcp-settings/src/Endpoint/PayLaterMessagingEndpoint.php @@ -0,0 +1,88 @@ +namespace, + '/' . $this->rest_base, + array( + 'methods' => WP_REST_Server::READABLE, + 'callback' => array( $this, 'get_details' ), + 'permission_callback' => array( $this, 'check_permission' ), + ) + ); + + /** + * POST wc/v3/wc_paypal/pay_later_messaging + * { + * [gateway_id]: { + * enabled + * title + * description + * } + * } + */ + register_rest_route( + $this->namespace, + '/' . $this->rest_base, + array( + 'methods' => WP_REST_Server::EDITABLE, + 'callback' => array( $this, 'update_details' ), + 'permission_callback' => array( $this, 'check_permission' ), + ) + ); + } + + /** + * Returns all payment methods details. + * + * @return WP_REST_Response The current payment methods details. + */ + public function get_details() : WP_REST_Response { + return $this->return_success( array() ); + } + + /** + * Updates payment methods details based on the request. + * + * @param WP_REST_Request $request Full data about the request. + * + * @return WP_REST_Response The updated payment methods details. + */ + public function update_details( WP_REST_Request $request ) : WP_REST_Response { + return $this->get_details(); + } + +} diff --git a/modules/ppcp-settings/src/SettingsModule.php b/modules/ppcp-settings/src/SettingsModule.php index b7c334425..c6fea6621 100644 --- a/modules/ppcp-settings/src/SettingsModule.php +++ b/modules/ppcp-settings/src/SettingsModule.php @@ -238,6 +238,7 @@ class SettingsModule implements ServiceModule, ExecutableModule { 'settings' => $container->get( 'settings.rest.settings' ), 'styling' => $container->get( 'settings.rest.styling' ), 'todos' => $container->get( 'settings.rest.todos' ), + 'pay_later_messaging' => $container->get( 'settings.rest.pay_later_messaging' ), ); foreach ( $endpoints as $endpoint ) { From 40edcdfc3d57db84a72dcb62420746456d91dbac Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Wed, 29 Jan 2025 16:51:12 +0100 Subject: [PATCH 02/37] Add get response details --- modules/ppcp-settings/services.php | 4 ++- .../Endpoint/PayLaterMessagingEndpoint.php | 27 +++++++++++++------ 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/modules/ppcp-settings/services.php b/modules/ppcp-settings/services.php index 97f561a9e..0016a0096 100644 --- a/modules/ppcp-settings/services.php +++ b/modules/ppcp-settings/services.php @@ -127,7 +127,9 @@ return array( ); }, 'settings.rest.pay_later_messaging' => static function ( ContainerInterface $container ) : PayLaterMessagingEndpoint { - return new PayLaterMessagingEndpoint(); + return new PayLaterMessagingEndpoint( + $container->get( 'wcgateway.settings' ) + ); }, 'settings.rest.settings' => static function ( ContainerInterface $container ) : SettingsRestEndpoint { return new SettingsRestEndpoint( diff --git a/modules/ppcp-settings/src/Endpoint/PayLaterMessagingEndpoint.php b/modules/ppcp-settings/src/Endpoint/PayLaterMessagingEndpoint.php index 5e5643261..5dfbe7613 100644 --- a/modules/ppcp-settings/src/Endpoint/PayLaterMessagingEndpoint.php +++ b/modules/ppcp-settings/src/Endpoint/PayLaterMessagingEndpoint.php @@ -9,6 +9,8 @@ declare( strict_types = 1 ); namespace WooCommerce\PayPalCommerce\Settings\Endpoint; +use WooCommerce\PayPalCommerce\PayLaterConfigurator\Factory\ConfigFactory; +use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; use WP_REST_Request; use WP_REST_Response; use WP_REST_Server; @@ -27,6 +29,22 @@ class PayLaterMessagingEndpoint extends RestEndpoint { */ protected $rest_base = 'pay_later_messaging'; + /** + * The settings. + * + * @var Settings + */ + protected $settings; + + /** + * PayLaterMessagingEndpoint constructor. + * + * @param Settings $settings The settings. + */ + public function __construct( Settings $settings ) { + $this->settings = $settings; + } + /** * Configure REST API routes. */ @@ -46,13 +64,6 @@ class PayLaterMessagingEndpoint extends RestEndpoint { /** * POST wc/v3/wc_paypal/pay_later_messaging - * { - * [gateway_id]: { - * enabled - * title - * description - * } - * } */ register_rest_route( $this->namespace, @@ -71,7 +82,7 @@ class PayLaterMessagingEndpoint extends RestEndpoint { * @return WP_REST_Response The current payment methods details. */ public function get_details() : WP_REST_Response { - return $this->return_success( array() ); + return $this->return_success( ( new ConfigFactory() )->from_settings( $this->settings ) ); } /** From 442a33778fdd6993f8d4e85ff587046adcf6d2cf Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Wed, 29 Jan 2025 17:20:10 +0100 Subject: [PATCH 03/37] Add endpoint save config --- .../src/Endpoint/SaveConfig.php | 2 +- modules/ppcp-settings/services.php | 3 ++- .../Endpoint/PayLaterMessagingEndpoint.php | 23 ++++++++++++++----- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/modules/ppcp-paylater-configurator/src/Endpoint/SaveConfig.php b/modules/ppcp-paylater-configurator/src/Endpoint/SaveConfig.php index df4e4affa..b1f77de85 100644 --- a/modules/ppcp-paylater-configurator/src/Endpoint/SaveConfig.php +++ b/modules/ppcp-paylater-configurator/src/Endpoint/SaveConfig.php @@ -94,7 +94,7 @@ class SaveConfig { * * @param array $config The configurator config. */ - private function save_config( array $config ): void { + public function save_config( array $config ): void { $this->settings->set( 'pay_later_enable_styling_per_messaging_location', true ); $this->settings->set( 'pay_later_messaging_enabled', true ); diff --git a/modules/ppcp-settings/services.php b/modules/ppcp-settings/services.php index 0016a0096..3ce60b18e 100644 --- a/modules/ppcp-settings/services.php +++ b/modules/ppcp-settings/services.php @@ -128,7 +128,8 @@ return array( }, 'settings.rest.pay_later_messaging' => static function ( ContainerInterface $container ) : PayLaterMessagingEndpoint { return new PayLaterMessagingEndpoint( - $container->get( 'wcgateway.settings' ) + $container->get( 'wcgateway.settings' ), + $container->get( 'paylater-configurator.endpoint.save-config' ) ); }, 'settings.rest.settings' => static function ( ContainerInterface $container ) : SettingsRestEndpoint { diff --git a/modules/ppcp-settings/src/Endpoint/PayLaterMessagingEndpoint.php b/modules/ppcp-settings/src/Endpoint/PayLaterMessagingEndpoint.php index 5dfbe7613..c39fa056f 100644 --- a/modules/ppcp-settings/src/Endpoint/PayLaterMessagingEndpoint.php +++ b/modules/ppcp-settings/src/Endpoint/PayLaterMessagingEndpoint.php @@ -9,6 +9,7 @@ declare( strict_types = 1 ); namespace WooCommerce\PayPalCommerce\Settings\Endpoint; +use WooCommerce\PayPalCommerce\PayLaterConfigurator\Endpoint\SaveConfig; use WooCommerce\PayPalCommerce\PayLaterConfigurator\Factory\ConfigFactory; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; use WP_REST_Request; @@ -36,13 +37,22 @@ class PayLaterMessagingEndpoint extends RestEndpoint { */ protected $settings; + /** + * Save config handler. + * + * @var SaveConfig + */ + private $save_config; + /** * PayLaterMessagingEndpoint constructor. * - * @param Settings $settings The settings. + * @param Settings $settings The settings. + * @param SaveConfig $save_config Save config handler. */ - public function __construct( Settings $settings ) { - $this->settings = $settings; + public function __construct( Settings $settings, SaveConfig $save_config ) { + $this->settings = $settings; + $this->save_config = $save_config; } /** @@ -77,7 +87,7 @@ class PayLaterMessagingEndpoint extends RestEndpoint { } /** - * Returns all payment methods details. + * Returns Pay Later Messaging configuration details. * * @return WP_REST_Response The current payment methods details. */ @@ -86,14 +96,15 @@ class PayLaterMessagingEndpoint extends RestEndpoint { } /** - * Updates payment methods details based on the request. + * Updates Pay Later Messaging configuration details based on the request. * * @param WP_REST_Request $request Full data about the request. * * @return WP_REST_Response The updated payment methods details. */ public function update_details( WP_REST_Request $request ) : WP_REST_Response { + $this->save_config->save_config( $request->get_params() ); + return $this->get_details(); } - } From 0e89cde688d0357cf8f5f864bc815e95868942f3 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Wed, 29 Jan 2025 17:57:50 +0100 Subject: [PATCH 04/37] Add data store boilerplate --- .../ppcp-settings/resources/js/data/index.js | 13 ++- .../js/data/pay-later-messaging/README.md | 45 +++++++++++ .../data/pay-later-messaging/action-types.js | 18 +++++ .../js/data/pay-later-messaging/actions.js | 80 +++++++++++++++++++ .../js/data/pay-later-messaging/constants.js | 28 +++++++ .../js/data/pay-later-messaging/controls.js | 23 ++++++ .../js/data/pay-later-messaging/hooks.js | 50 ++++++++++++ .../js/data/pay-later-messaging/index.js | 32 ++++++++ .../js/data/pay-later-messaging/reducer.js | 62 ++++++++++++++ .../js/data/pay-later-messaging/resolvers.js | 39 +++++++++ .../js/data/pay-later-messaging/selectors.js | 21 +++++ .../Endpoint/PayLaterMessagingEndpoint.php | 2 +- 12 files changed, 411 insertions(+), 2 deletions(-) create mode 100644 modules/ppcp-settings/resources/js/data/pay-later-messaging/README.md create mode 100644 modules/ppcp-settings/resources/js/data/pay-later-messaging/action-types.js create mode 100644 modules/ppcp-settings/resources/js/data/pay-later-messaging/actions.js create mode 100644 modules/ppcp-settings/resources/js/data/pay-later-messaging/constants.js create mode 100644 modules/ppcp-settings/resources/js/data/pay-later-messaging/controls.js create mode 100644 modules/ppcp-settings/resources/js/data/pay-later-messaging/hooks.js create mode 100644 modules/ppcp-settings/resources/js/data/pay-later-messaging/index.js create mode 100644 modules/ppcp-settings/resources/js/data/pay-later-messaging/reducer.js create mode 100644 modules/ppcp-settings/resources/js/data/pay-later-messaging/resolvers.js create mode 100644 modules/ppcp-settings/resources/js/data/pay-later-messaging/selectors.js diff --git a/modules/ppcp-settings/resources/js/data/index.js b/modules/ppcp-settings/resources/js/data/index.js index 0985aa972..227a62226 100644 --- a/modules/ppcp-settings/resources/js/data/index.js +++ b/modules/ppcp-settings/resources/js/data/index.js @@ -5,8 +5,17 @@ import * as Payment from './payment'; import * as Settings from './settings'; import * as Styling from './styling'; import * as Todos from './todos'; +import * as PayLaterMessaging from './pay-later-messaging'; -const stores = [ Onboarding, Common, Payment, Settings, Styling, Todos ]; +const stores = [ + Onboarding, + Common, + Payment, + Settings, + Styling, + Todos, + PayLaterMessaging, +]; stores.forEach( ( store ) => { try { @@ -30,6 +39,7 @@ export const PaymentHooks = Payment.hooks; export const SettingsHooks = Settings.hooks; export const StylingHooks = Styling.hooks; export const TodosHooks = Todos.hooks; +export const PayLaterMessagingHooks = PayLaterMessaging.hooks; export const OnboardingStoreName = Onboarding.STORE_NAME; export const CommonStoreName = Common.STORE_NAME; @@ -37,6 +47,7 @@ export const PaymentStoreName = Payment.STORE_NAME; export const SettingsStoreName = Settings.STORE_NAME; export const StylingStoreName = Styling.STORE_NAME; export const TodosStoreName = Todos.STORE_NAME; +export const PayLaterMessagingStoreName = PayLaterMessaging.STORE_NAME; export * from './configuration'; diff --git a/modules/ppcp-settings/resources/js/data/pay-later-messaging/README.md b/modules/ppcp-settings/resources/js/data/pay-later-messaging/README.md new file mode 100644 index 000000000..b97f6ca4c --- /dev/null +++ b/modules/ppcp-settings/resources/js/data/pay-later-messaging/README.md @@ -0,0 +1,45 @@ +# Store template + +This template contains all files for a Redux store. + +## New Store: Redux integration + +1. Copy this folder, give it a correct name. +2. Check each file for `` placeholders and `TODO` remarks. +3. Edit the main store-index file and add the relevant store integration there. +4. Check the debug-module, and add relevant debug code. + - Register the store in the `reset()` method. + +--- + +Main store-index: +`modules/ppcp-settings/resources/js/data/index.js` + +Sample store integration: +```js +import * as YourStore from './yourStore'; +// ... +YourStore.initStore(); +// ... +export const YourStoreHooks = YourStore.hooks; +// ... +export const YourStoreName = YourStore.STORE_NAME; +// ... +addDebugTools( window.ppcpSettings, [ ..., YourStoreName ] ); +``` + +--- + +### New Store: PHP integration + +1. Create the **REST endpoint** for hydrating and persisting data. + - `modules/ppcp-settings/src/Endpoint/YourStoreRestEndpoint.php` + - Extend from base class `RestEndpoint` +2. Create the **data model** class to manage the DB interaction. + - `modules/ppcp-settings/src/Data/YourStoreSettings.php` + - Extend from base class `AbstractDataModel` +3. Create relevant **DI services** for both files. + - `modules/ppcp-settings/services.php` +4. Register the REST endpoint in the **service module**. + - `modules/ppcp-settings/src/SettingsModule.php` + - Find the action `rest_api_init` diff --git a/modules/ppcp-settings/resources/js/data/pay-later-messaging/action-types.js b/modules/ppcp-settings/resources/js/data/pay-later-messaging/action-types.js new file mode 100644 index 000000000..70913ddd6 --- /dev/null +++ b/modules/ppcp-settings/resources/js/data/pay-later-messaging/action-types.js @@ -0,0 +1,18 @@ +/** + * Action Types: Define unique identifiers for actions across all store modules. + * + * @file + */ + +export default { + // Transient data. + SET_TRANSIENT: 'PAY_LATER_MESSAGING:SET_TRANSIENT', + + // Persistent data. + SET_PERSISTENT: 'PAY_LATER_MESSAGING:SET_PERSISTENT', + RESET: 'PAY_LATER_MESSAGING:RESET', + HYDRATE: 'PAY_LATER_MESSAGING:HYDRATE', + + // Controls - always start with "DO_". + DO_PERSIST_DATA: 'PAY_LATER_MESSAGING:DO_PERSIST_DATA', +}; diff --git a/modules/ppcp-settings/resources/js/data/pay-later-messaging/actions.js b/modules/ppcp-settings/resources/js/data/pay-later-messaging/actions.js new file mode 100644 index 000000000..59d68d37c --- /dev/null +++ b/modules/ppcp-settings/resources/js/data/pay-later-messaging/actions.js @@ -0,0 +1,80 @@ +/** + * Action Creators: Define functions to create action objects. + * + * These functions update state or trigger side effects (e.g., async operations). + * Actions are categorized as Transient, Persistent, or Side effect. + * + * @file + */ + +import { select } from '@wordpress/data'; + +import ACTION_TYPES from './action-types'; +import { STORE_NAME } from './constants'; + +/** + * @typedef {Object} Action An action object that is handled by a reducer or control. + * @property {string} type - The action type. + * @property {Object?} payload - Optional payload for the action. + */ + +/** + * Special. Resets all values in the store to initial defaults. + * + * @return {Action} The action. + */ +export const reset = () => ( { type: ACTION_TYPES.RESET } ); + +/** + * Persistent. Set the full store details during app initialization. + * + * @param {{data: {}, flags?: {}}} payload + * @return {Action} The action. + */ +export const hydrate = ( payload ) => ( { + type: ACTION_TYPES.HYDRATE, + payload, +} ); + +/** + * Generic transient-data updater. + * + * @param {string} prop Name of the property to update. + * @param {any} value The new value of the property. + * @return {Action} The action. + */ +export const setTransient = ( prop, value ) => ( { + type: ACTION_TYPES.SET_TRANSIENT, + payload: { [ prop ]: value }, +} ); + +/** + * Generic persistent-data updater. + * + * @param {string} prop Name of the property to update. + * @param {any} value The new value of the property. + * @return {Action} The action. + */ +export const setPersistent = ( prop, value ) => ( { + type: ACTION_TYPES.SET_PERSISTENT, + payload: { [ prop ]: value }, +} ); + +/** + * Transient. Marks the store as "ready", i.e., fully initialized. + * + * @param {boolean} isReady + * @return {Action} The action. + */ +export const setIsReady = ( isReady ) => setTransient( 'isReady', isReady ); + +/** + * Side effect. Triggers the persistence of store data to the server. + * + * @return {Action} The action. + */ +export const persist = function* () { + const data = yield select( STORE_NAME ).persistentData(); + + yield { type: ACTION_TYPES.DO_PERSIST_DATA, data }; +}; diff --git a/modules/ppcp-settings/resources/js/data/pay-later-messaging/constants.js b/modules/ppcp-settings/resources/js/data/pay-later-messaging/constants.js new file mode 100644 index 000000000..09f3bab52 --- /dev/null +++ b/modules/ppcp-settings/resources/js/data/pay-later-messaging/constants.js @@ -0,0 +1,28 @@ +/** + * Name of the Redux store module. + * + * Used by: Reducer, Selector, Index + * + * @type {string} + */ +export const STORE_NAME = 'wc/paypal/pay_later_messaging'; + +/** + * REST path to hydrate data of this module by loading data from the WP DB. + * + * Used by: Resolvers + * See: PayLaterMessagingEndpoint.php + * + * @type {string} + */ +export const REST_HYDRATE_PATH = '/wc/v3/wc_paypal/pay_later_messaging'; + +/** + * REST path to persist data of this module to the WP DB. + * + * Used by: Controls + * See: PayLaterMessagingEndpoint.php + * + * @type {string} + */ +export const REST_PERSIST_PATH = '/wc/v3/wc_paypal/pay_later_messaging'; diff --git a/modules/ppcp-settings/resources/js/data/pay-later-messaging/controls.js b/modules/ppcp-settings/resources/js/data/pay-later-messaging/controls.js new file mode 100644 index 000000000..9295b62bc --- /dev/null +++ b/modules/ppcp-settings/resources/js/data/pay-later-messaging/controls.js @@ -0,0 +1,23 @@ +/** + * Controls: Implement side effects, typically asynchronous operations. + * + * Controls use ACTION_TYPES keys as identifiers. + * They are triggered by corresponding actions and handle external interactions. + * + * @file + */ + +import apiFetch from '@wordpress/api-fetch'; + +import { REST_PERSIST_PATH } from './constants'; +import ACTION_TYPES from './action-types'; + +export const controls = { + async [ ACTION_TYPES.DO_PERSIST_DATA ]( { data } ) { + return await apiFetch( { + path: REST_PERSIST_PATH, + method: 'POST', + data, + } ); + }, +}; diff --git a/modules/ppcp-settings/resources/js/data/pay-later-messaging/hooks.js b/modules/ppcp-settings/resources/js/data/pay-later-messaging/hooks.js new file mode 100644 index 000000000..b6878c2a9 --- /dev/null +++ b/modules/ppcp-settings/resources/js/data/pay-later-messaging/hooks.js @@ -0,0 +1,50 @@ +/** + * Hooks: Provide the main API for components to interact with the store. + * + * These encapsulate store interactions, offering a consistent interface. + * Hooks simplify data access and manipulation for components. + * + * @file + */ + +import { useDispatch } from '@wordpress/data'; + +import { createHooksForStore } from '../utils'; +import { STORE_NAME } from './constants'; + +const useHooks = () => { + const { useTransient, usePersistent } = createHooksForStore( STORE_NAME ); + const { persist } = useDispatch( STORE_NAME ); + + // Read-only flags and derived state. + // Nothing here yet. + + // Transient accessors. + const [ isReady ] = useTransient( 'isReady' ); + + // Persistent accessors. + // TODO: Replace with real property. + const [ sampleValue, setSampleValue ] = usePersistent( 'sampleValue' ); + + return { + persist, + isReady, + sampleValue, + setSampleValue, + }; +}; + +export const useState = () => { + const { persist, isReady } = useHooks(); + return { persist, isReady }; +}; + +// TODO: Replace with real hook. +export const useSampleValue = () => { + const { sampleValue, setSampleValue } = useHooks(); + + return { + sampleValue, + setSampleValue, + }; +}; diff --git a/modules/ppcp-settings/resources/js/data/pay-later-messaging/index.js b/modules/ppcp-settings/resources/js/data/pay-later-messaging/index.js new file mode 100644 index 000000000..3bd6e4459 --- /dev/null +++ b/modules/ppcp-settings/resources/js/data/pay-later-messaging/index.js @@ -0,0 +1,32 @@ +import { createReduxStore, register } from '@wordpress/data'; +import { controls as wpControls } from '@wordpress/data-controls'; + +import { STORE_NAME } from './constants'; +import reducer from './reducer'; +import * as selectors from './selectors'; +import * as actions from './actions'; +import * as hooks from './hooks'; +import { resolvers } from './resolvers'; +import { controls } from './controls'; + +/** + * Initializes and registers the settings store with WordPress data layer. + * Combines custom controls with WordPress data controls. + * + * @return {boolean} True if initialization succeeded, false otherwise. + */ +export const initStore = () => { + const store = createReduxStore( STORE_NAME, { + reducer, + controls: { ...wpControls, ...controls }, + actions, + selectors, + resolvers, + } ); + + register( store ); + + return Boolean( wp.data.select( STORE_NAME ) ); +}; + +export { hooks, selectors, STORE_NAME }; diff --git a/modules/ppcp-settings/resources/js/data/pay-later-messaging/reducer.js b/modules/ppcp-settings/resources/js/data/pay-later-messaging/reducer.js new file mode 100644 index 000000000..7111d9302 --- /dev/null +++ b/modules/ppcp-settings/resources/js/data/pay-later-messaging/reducer.js @@ -0,0 +1,62 @@ +/** + * Reducer: Defines store structure and state updates for this module. + * + * Manages both transient (temporary) and persistent (saved) state. + * The initial state must define all properties, as dynamic additions are not supported. + * + * @file + */ + +import { createReducer, createReducerSetters } from '../utils'; +import ACTION_TYPES from './action-types'; + +// Store structure. + +// Transient: Values that are _not_ saved to the DB (like app lifecycle-flags). +const defaultTransient = Object.freeze( { + isReady: false, +} ); + +// Persistent: Values that are loaded from the DB. +const defaultPersistent = Object.freeze( { + // TODO: Add real DB properties here. + sampleValue: 'foo', + cart: {}, + checkout: {}, + product: {}, + shop: {}, + home: {}, + custom_placement: [], +} ); + +// Reducer logic. + +const [ changeTransient, changePersistent ] = createReducerSetters( + defaultTransient, + defaultPersistent +); + +const reducer = createReducer( defaultTransient, defaultPersistent, { + [ ACTION_TYPES.SET_TRANSIENT ]: ( state, payload ) => + changeTransient( state, payload ), + + [ ACTION_TYPES.SET_PERSISTENT ]: ( state, payload ) => + changePersistent( state, payload ), + + [ ACTION_TYPES.RESET ]: ( state ) => { + const cleanState = changeTransient( + changePersistent( state, defaultPersistent ), + defaultTransient + ); + + // Keep "read-only" details and initialization flags. + cleanState.isReady = true; + + return cleanState; + }, + + [ ACTION_TYPES.HYDRATE ]: ( state, payload ) => + changePersistent( state, payload.data ), +} ); + +export default reducer; diff --git a/modules/ppcp-settings/resources/js/data/pay-later-messaging/resolvers.js b/modules/ppcp-settings/resources/js/data/pay-later-messaging/resolvers.js new file mode 100644 index 000000000..4b9bc4230 --- /dev/null +++ b/modules/ppcp-settings/resources/js/data/pay-later-messaging/resolvers.js @@ -0,0 +1,39 @@ +/** + * Resolvers: Handle asynchronous data fetching for the store. + * + * These functions update store state with data from external sources. + * Each resolver corresponds to a specific selector (selector with same name must exist). + * Resolvers are called automatically when selectors request unavailable data. + * + * @file + */ + +import { dispatch } from '@wordpress/data'; +import { __ } from '@wordpress/i18n'; +import { apiFetch } from '@wordpress/data-controls'; + +import { STORE_NAME, REST_HYDRATE_PATH } from './constants'; + +export const resolvers = { + /** + * Retrieve settings from the site's REST API. + */ + *persistentData() { + try { + const result = yield apiFetch( { path: REST_HYDRATE_PATH } ); + + console.log( result ); + + yield dispatch( STORE_NAME ).hydrate( result ); + yield dispatch( STORE_NAME ).setIsReady( true ); + } catch ( e ) { + yield dispatch( 'core/notices' ).createErrorNotice( + // TODO: Add the module name to the error message. + __( + 'Error retrieving Pay Later Messaging config details.', + 'woocommerce-paypal-payments' + ) + ); + } + }, +}; diff --git a/modules/ppcp-settings/resources/js/data/pay-later-messaging/selectors.js b/modules/ppcp-settings/resources/js/data/pay-later-messaging/selectors.js new file mode 100644 index 000000000..14334fcf3 --- /dev/null +++ b/modules/ppcp-settings/resources/js/data/pay-later-messaging/selectors.js @@ -0,0 +1,21 @@ +/** + * Selectors: Extract specific pieces of state from the store. + * + * These functions provide a consistent interface for accessing store data. + * They allow components to retrieve data without knowing the store structure. + * + * @file + */ + +const EMPTY_OBJ = Object.freeze( {} ); + +const getState = ( state ) => state || EMPTY_OBJ; + +export const persistentData = ( state ) => { + return getState( state ).data || EMPTY_OBJ; +}; + +export const transientData = ( state ) => { + const { data, ...transientState } = getState( state ); + return transientState || EMPTY_OBJ; +}; diff --git a/modules/ppcp-settings/src/Endpoint/PayLaterMessagingEndpoint.php b/modules/ppcp-settings/src/Endpoint/PayLaterMessagingEndpoint.php index c39fa056f..d448e1a9b 100644 --- a/modules/ppcp-settings/src/Endpoint/PayLaterMessagingEndpoint.php +++ b/modules/ppcp-settings/src/Endpoint/PayLaterMessagingEndpoint.php @@ -100,7 +100,7 @@ class PayLaterMessagingEndpoint extends RestEndpoint { * * @param WP_REST_Request $request Full data about the request. * - * @return WP_REST_Response The updated payment methods details. + * @return WP_REST_Response The updated Pay Later Messaging configuration details. */ public function update_details( WP_REST_Request $request ) : WP_REST_Response { $this->save_config->save_config( $request->get_params() ); From a652f21629a51b556522a559a36ded6bf09c9f01 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Thu, 30 Jan 2025 10:50:44 +0100 Subject: [PATCH 05/37] Read config from store --- .../resources/js/paylater-configurator.js | 1 + .../Screens/Overview/TabPayLaterMessaging.js | 5 ++-- .../js/data/pay-later-messaging/hooks.js | 28 +++++++++++++++++++ .../js/data/pay-later-messaging/resolvers.js | 2 -- 4 files changed, 32 insertions(+), 4 deletions(-) diff --git a/modules/ppcp-paylater-configurator/resources/js/paylater-configurator.js b/modules/ppcp-paylater-configurator/resources/js/paylater-configurator.js index f3daad01e..27145de16 100644 --- a/modules/ppcp-paylater-configurator/resources/js/paylater-configurator.js +++ b/modules/ppcp-paylater-configurator/resources/js/paylater-configurator.js @@ -51,6 +51,7 @@ document.addEventListener( 'DOMContentLoaded', () => { .then( ( data ) => { if ( data.success ) { const config = data.data; + console.log( config ); merchantConfigurators.Messaging( { config, diff --git a/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabPayLaterMessaging.js b/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabPayLaterMessaging.js index a3a3083c9..d22318d26 100644 --- a/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabPayLaterMessaging.js +++ b/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabPayLaterMessaging.js @@ -1,7 +1,8 @@ import React, { useEffect } from 'react'; +import { PayLaterMessagingHooks } from '../../../data'; const TabPayLaterMessaging = () => { - const config = {}; // Replace with the appropriate/saved configuration. + const { config } = PayLaterMessagingHooks.usePayLaterMessaging(); const PcpPayLaterConfigurator = window.ppcpSettings?.PcpPayLaterConfigurator; @@ -37,7 +38,7 @@ const TabPayLaterMessaging = () => { }, } ); } - }, [ PcpPayLaterConfigurator ] ); + }, [ PcpPayLaterConfigurator, config ] ); return (
{ // TODO: Replace with real property. const [ sampleValue, setSampleValue ] = usePersistent( 'sampleValue' ); + const [ cart ] = usePersistent( 'cart' ); + const [ checkout ] = usePersistent( 'checkout' ); + const [ product ] = usePersistent( 'product' ); + const [ shop ] = usePersistent( 'shop' ); + const [ home ] = usePersistent( 'home' ); + const [ custom_placement ] = usePersistent( 'custom_placement' ); + return { persist, isReady, sampleValue, setSampleValue, + cart, + checkout, + product, + shop, + home, + custom_placement, }; }; @@ -48,3 +61,18 @@ export const useSampleValue = () => { setSampleValue, }; }; + +export const usePayLaterMessaging = () => { + const { cart, checkout, product, shop, home, customPlacement } = useHooks(); + + return { + config: { + cart, + checkout, + product, + shop, + home, + customPlacement, + }, + }; +}; diff --git a/modules/ppcp-settings/resources/js/data/pay-later-messaging/resolvers.js b/modules/ppcp-settings/resources/js/data/pay-later-messaging/resolvers.js index 4b9bc4230..39ff6c343 100644 --- a/modules/ppcp-settings/resources/js/data/pay-later-messaging/resolvers.js +++ b/modules/ppcp-settings/resources/js/data/pay-later-messaging/resolvers.js @@ -22,8 +22,6 @@ export const resolvers = { try { const result = yield apiFetch( { path: REST_HYDRATE_PATH } ); - console.log( result ); - yield dispatch( STORE_NAME ).hydrate( result ); yield dispatch( STORE_NAME ).setIsReady( true ); } catch ( e ) { From 917a147af8a39a0d285ec7eb85d1feb20acf5316 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Thu, 30 Jan 2025 13:36:57 +0100 Subject: [PATCH 06/37] =?UTF-8?q?=F0=9F=A5=85=20Catch=20failed=20eligibili?= =?UTF-8?q?ty=20checks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ppcp-wc-gateway/src/WCGatewayModule.php | 86 ++++++++++++------- 1 file changed, 54 insertions(+), 32 deletions(-) diff --git a/modules/ppcp-wc-gateway/src/WCGatewayModule.php b/modules/ppcp-wc-gateway/src/WCGatewayModule.php index da8bf00cb..c10813c86 100644 --- a/modules/ppcp-wc-gateway/src/WCGatewayModule.php +++ b/modules/ppcp-wc-gateway/src/WCGatewayModule.php @@ -551,42 +551,64 @@ class WCGatewayModule implements ServiceModule, ExtendingModule, ExecutableModul add_filter( 'woocommerce_paypal_payments_rest_common_merchant_data', - function( array $features ) use ( $c ): array { - $billing_agreements_endpoint = $c->get( 'api.endpoint.billing-agreements' ); - assert( $billing_agreements_endpoint instanceof BillingAgreementsEndpoint ); + static function ( array $features ) use ( $c ) : array { + try { + $billing_agreements_endpoint = $c->get( 'api.endpoint.billing-agreements' ); + assert( $billing_agreements_endpoint instanceof BillingAgreementsEndpoint ); - $reference_transactions_enabled = $billing_agreements_endpoint->reference_transaction_enabled(); - $features['save_paypal_and_venmo'] = array( - 'enabled' => $reference_transactions_enabled, - ); - - $dcc_product_status = $c->get( 'wcgateway.helper.dcc-product-status' ); - assert( $dcc_product_status instanceof DCCProductStatus ); - - $dcc_enabled = $dcc_product_status->dcc_is_active(); - $features['advanced_credit_and_debit_cards'] = array( - 'enabled' => $dcc_enabled, - ); - - $partners_endpoint = $c->get( 'api.endpoint.partners' ); - assert( $partners_endpoint instanceof PartnersEndpoint ); - $seller_status = $partners_endpoint->seller_status(); - - $apms_enabled = false; - foreach ( $seller_status->products() as $product ) { - if ( $product->name() === 'PAYMENT_METHODS' ) { - $apms_enabled = true; - break; - } + $reference_transactions_enabled = $billing_agreements_endpoint->reference_transaction_enabled(); + $features['save_paypal_and_venmo'] = array( + 'enabled' => $reference_transactions_enabled, + ); + } catch ( Exception $ex ) { + $features['save_paypal_and_venmo'] = array( + 'enabled' => false, + ); } - $features['alternative_payment_methods'] = array( - 'enabled' => $apms_enabled, - ); + try { + $dcc_product_status = $c->get( 'wcgateway.helper.dcc-product-status' ); + assert( $dcc_product_status instanceof DCCProductStatus ); + $dcc_enabled = $dcc_product_status->dcc_is_active(); + $features['advanced_credit_and_debit_cards'] = array( + 'enabled' => $dcc_enabled, + ); + } catch ( Exception $ex ) { + $features['advanced_credit_and_debit_cards'] = array( + 'enabled' => false, + ); + } - $features['pay_later_messaging'] = array( - 'enabled' => true, - ); + try { + // TODO: The `seller_status()` call throws a PayPalApiException. Why? + $partners_endpoint = $c->get( 'api.endpoint.partners' ); + assert( $partners_endpoint instanceof PartnersEndpoint ); + $seller_status = $partners_endpoint->seller_status(); + + $apms_enabled = false; + foreach ( $seller_status->products() as $product ) { + if ( $product->name() === 'PAYMENT_METHODS' ) { + $apms_enabled = true; + break; + } + } + + $features['alternative_payment_methods'] = array( + 'enabled' => $apms_enabled, + ); + + $features['pay_later_messaging'] = array( + 'enabled' => true, + ); + } catch ( Exception $ex ) { + $features['alternative_payment_methods'] = array( + 'enabled' => false, + ); + + $features['pay_later_messaging'] = array( + 'enabled' => false, + ); + } return $features; } From 66c6fb17b81e2da4e3ae25bff92426d20914b60e Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Thu, 30 Jan 2025 16:39:26 +0100 Subject: [PATCH 07/37] Save pay later messaging config to database --- .../Screens/Overview/TabPayLaterMessaging.js | 23 +++++--- .../resources/js/data/_example/hooks.js | 2 +- .../js/data/pay-later-messaging/hooks.js | 59 +++++++++++-------- .../js/data/pay-later-messaging/reducer.js | 2 - .../resources/js/hooks/useSaveSettings.js | 19 +++++- .../Endpoint/PayLaterMessagingEndpoint.php | 2 +- 6 files changed, 70 insertions(+), 37 deletions(-) diff --git a/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabPayLaterMessaging.js b/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabPayLaterMessaging.js index d22318d26..274ef91c2 100644 --- a/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabPayLaterMessaging.js +++ b/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabPayLaterMessaging.js @@ -2,7 +2,15 @@ import React, { useEffect } from 'react'; import { PayLaterMessagingHooks } from '../../../data'; const TabPayLaterMessaging = () => { - const { config } = PayLaterMessagingHooks.usePayLaterMessaging(); + const { + config, + setCart, + setCheckout, + setProduct, + setShop, + setHome, + setCustom_placement, + } = PayLaterMessagingHooks.usePayLaterMessaging(); const PcpPayLaterConfigurator = window.ppcpSettings?.PcpPayLaterConfigurator; @@ -28,13 +36,12 @@ const TabPayLaterMessaging = () => { subheader: 'ppcp-r-paylater-configurator__subheader', }, onSave: ( data ) => { - /* - TODO: - - The saving will be handled in a separate PR. - - One option could be: - - When saving the settings, programmatically click on the configurator's - "Save Changes" button and send the request to PHP. - */ + setCart( data.config.cart ); + setCheckout( data.config.checkout ); + setProduct( data.config.product ); + setShop( data.config.shop ); + setHome( data.config.home ); + setCustom_placement( data.config.custom_placement ); }, } ); } diff --git a/modules/ppcp-settings/resources/js/data/_example/hooks.js b/modules/ppcp-settings/resources/js/data/_example/hooks.js index b6878c2a9..95db3765e 100644 --- a/modules/ppcp-settings/resources/js/data/_example/hooks.js +++ b/modules/ppcp-settings/resources/js/data/_example/hooks.js @@ -34,7 +34,7 @@ const useHooks = () => { }; }; -export const useState = () => { +export const useStore = () => { const { persist, isReady } = useHooks(); return { persist, isReady }; }; diff --git a/modules/ppcp-settings/resources/js/data/pay-later-messaging/hooks.js b/modules/ppcp-settings/resources/js/data/pay-later-messaging/hooks.js index 174e618e7..0f51051cd 100644 --- a/modules/ppcp-settings/resources/js/data/pay-later-messaging/hooks.js +++ b/modules/ppcp-settings/resources/js/data/pay-later-messaging/hooks.js @@ -23,47 +23,52 @@ const useHooks = () => { const [ isReady ] = useTransient( 'isReady' ); // Persistent accessors. - // TODO: Replace with real property. - const [ sampleValue, setSampleValue ] = usePersistent( 'sampleValue' ); - - const [ cart ] = usePersistent( 'cart' ); - const [ checkout ] = usePersistent( 'checkout' ); - const [ product ] = usePersistent( 'product' ); - const [ shop ] = usePersistent( 'shop' ); - const [ home ] = usePersistent( 'home' ); - const [ custom_placement ] = usePersistent( 'custom_placement' ); + const [ cart, setCart ] = usePersistent( 'cart' ); + const [ checkout, setCheckout ] = usePersistent( 'checkout' ); + const [ product, setProduct ] = usePersistent( 'product' ); + const [ shop, setShop ] = usePersistent( 'shop' ); + const [ home, setHome ] = usePersistent( 'home' ); + const [ custom_placement, setCustom_placement ] = + usePersistent( 'custom_placement' ); return { persist, isReady, - sampleValue, - setSampleValue, cart, + setCart, checkout, + setCheckout, product, + setProduct, shop, + setShop, home, + setHome, custom_placement, + setCustom_placement, }; }; -export const useState = () => { +export const useStore = () => { const { persist, isReady } = useHooks(); return { persist, isReady }; }; -// TODO: Replace with real hook. -export const useSampleValue = () => { - const { sampleValue, setSampleValue } = useHooks(); - - return { - sampleValue, - setSampleValue, - }; -}; - export const usePayLaterMessaging = () => { - const { cart, checkout, product, shop, home, customPlacement } = useHooks(); + const { + cart, + setCart, + checkout, + setCheckout, + product, + setProduct, + shop, + setShop, + home, + setHome, + custom_placement, + setCustom_placement, + } = useHooks(); return { config: { @@ -72,7 +77,13 @@ export const usePayLaterMessaging = () => { product, shop, home, - customPlacement, + custom_placement, }, + setCart, + setCheckout, + setProduct, + setShop, + setHome, + setCustom_placement, }; }; diff --git a/modules/ppcp-settings/resources/js/data/pay-later-messaging/reducer.js b/modules/ppcp-settings/resources/js/data/pay-later-messaging/reducer.js index 7111d9302..5843ef400 100644 --- a/modules/ppcp-settings/resources/js/data/pay-later-messaging/reducer.js +++ b/modules/ppcp-settings/resources/js/data/pay-later-messaging/reducer.js @@ -19,8 +19,6 @@ const defaultTransient = Object.freeze( { // Persistent: Values that are loaded from the DB. const defaultPersistent = Object.freeze( { - // TODO: Add real DB properties here. - sampleValue: 'foo', cart: {}, checkout: {}, product: {}, diff --git a/modules/ppcp-settings/resources/js/hooks/useSaveSettings.js b/modules/ppcp-settings/resources/js/hooks/useSaveSettings.js index f268d3214..ca594e39d 100644 --- a/modules/ppcp-settings/resources/js/hooks/useSaveSettings.js +++ b/modules/ppcp-settings/resources/js/hooks/useSaveSettings.js @@ -2,6 +2,7 @@ import { useCallback } from '@wordpress/element'; import { CommonHooks, + PayLaterMessagingHooks, PaymentHooks, SettingsHooks, StylingHooks, @@ -13,8 +14,13 @@ export const useSaveSettings = () => { const { persist: persistPayment } = PaymentHooks.useStore(); const { persist: persistSettings } = SettingsHooks.useStore(); const { persist: persistStyling } = StylingHooks.useStore(); + const { persist: persistPayLaterMessaging } = + PayLaterMessagingHooks.useStore(); const persistAll = useCallback( () => { + // Executes onSave on TabPayLaterMessaging component. + document.getElementById( 'configurator-publishButton' )?.click(); + withActivity( 'persist-methods', 'Save payment methods', @@ -30,7 +36,18 @@ export const useSaveSettings = () => { 'Save styling details', persistStyling ); - }, [ persistPayment, persistSettings, persistStyling, withActivity ] ); + withActivity( + 'persist-pay-later-messaging', + 'Save pay later messaging details', + persistPayLaterMessaging + ); + }, [ + persistPayment, + persistSettings, + persistStyling, + persistPayLaterMessaging, + withActivity, + ] ); return { persistAll }; }; diff --git a/modules/ppcp-settings/src/Endpoint/PayLaterMessagingEndpoint.php b/modules/ppcp-settings/src/Endpoint/PayLaterMessagingEndpoint.php index d448e1a9b..5713ce570 100644 --- a/modules/ppcp-settings/src/Endpoint/PayLaterMessagingEndpoint.php +++ b/modules/ppcp-settings/src/Endpoint/PayLaterMessagingEndpoint.php @@ -103,7 +103,7 @@ class PayLaterMessagingEndpoint extends RestEndpoint { * @return WP_REST_Response The updated Pay Later Messaging configuration details. */ public function update_details( WP_REST_Request $request ) : WP_REST_Response { - $this->save_config->save_config( $request->get_params() ); + $this->save_config->save_config( $request->get_json_params() ); return $this->get_details(); } From 84a30d84d9e8b2534c43332fb395c1275d58f229 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Thu, 30 Jan 2025 16:48:06 +0100 Subject: [PATCH 08/37] Remove readme boilerplace example --- .../js/data/pay-later-messaging/README.md | 45 ------------------- 1 file changed, 45 deletions(-) delete mode 100644 modules/ppcp-settings/resources/js/data/pay-later-messaging/README.md diff --git a/modules/ppcp-settings/resources/js/data/pay-later-messaging/README.md b/modules/ppcp-settings/resources/js/data/pay-later-messaging/README.md deleted file mode 100644 index b97f6ca4c..000000000 --- a/modules/ppcp-settings/resources/js/data/pay-later-messaging/README.md +++ /dev/null @@ -1,45 +0,0 @@ -# Store template - -This template contains all files for a Redux store. - -## New Store: Redux integration - -1. Copy this folder, give it a correct name. -2. Check each file for `` placeholders and `TODO` remarks. -3. Edit the main store-index file and add the relevant store integration there. -4. Check the debug-module, and add relevant debug code. - - Register the store in the `reset()` method. - ---- - -Main store-index: -`modules/ppcp-settings/resources/js/data/index.js` - -Sample store integration: -```js -import * as YourStore from './yourStore'; -// ... -YourStore.initStore(); -// ... -export const YourStoreHooks = YourStore.hooks; -// ... -export const YourStoreName = YourStore.STORE_NAME; -// ... -addDebugTools( window.ppcpSettings, [ ..., YourStoreName ] ); -``` - ---- - -### New Store: PHP integration - -1. Create the **REST endpoint** for hydrating and persisting data. - - `modules/ppcp-settings/src/Endpoint/YourStoreRestEndpoint.php` - - Extend from base class `RestEndpoint` -2. Create the **data model** class to manage the DB interaction. - - `modules/ppcp-settings/src/Data/YourStoreSettings.php` - - Extend from base class `AbstractDataModel` -3. Create relevant **DI services** for both files. - - `modules/ppcp-settings/services.php` -4. Register the REST endpoint in the **service module**. - - `modules/ppcp-settings/src/SettingsModule.php` - - Find the action `rest_api_init` From f907558262b18982d48a062e156b2a8683f9490b Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Thu, 30 Jan 2025 16:50:34 +0100 Subject: [PATCH 09/37] Remove console.log --- .../resources/js/paylater-configurator.js | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/ppcp-paylater-configurator/resources/js/paylater-configurator.js b/modules/ppcp-paylater-configurator/resources/js/paylater-configurator.js index 27145de16..f3daad01e 100644 --- a/modules/ppcp-paylater-configurator/resources/js/paylater-configurator.js +++ b/modules/ppcp-paylater-configurator/resources/js/paylater-configurator.js @@ -51,7 +51,6 @@ document.addEventListener( 'DOMContentLoaded', () => { .then( ( data ) => { if ( data.success ) { const config = data.data; - console.log( config ); merchantConfigurators.Messaging( { config, From 70abceeee03eb74c45d6ae987eb4a1da4d63a312 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Thu, 30 Jan 2025 17:12:19 +0100 Subject: [PATCH 10/37] =?UTF-8?q?=E2=9C=A8=20New=20base=20class=20to=20che?= =?UTF-8?q?ck=20feature=20eligibility?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/Helper/ProductStatus.php | 195 ++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 modules/ppcp-api-client/src/Helper/ProductStatus.php diff --git a/modules/ppcp-api-client/src/Helper/ProductStatus.php b/modules/ppcp-api-client/src/Helper/ProductStatus.php new file mode 100644 index 000000000..a6c575a3e --- /dev/null +++ b/modules/ppcp-api-client/src/Helper/ProductStatus.php @@ -0,0 +1,195 @@ +is_connected = $is_connected; + $this->partners_endpoint = $partners_endpoint; + $this->api_failure_registry = $api_failure_registry; + } + + /** + * Uses local data (DB values, hooks) to determine if the feature is eligible. + * + * Returns true when the feature is available, and false if ineligible. + * On failure, an RuntimeException is thrown. + * + * @return null|bool Boolean to indicate the status; null if the status not locally defined. + * @throws RuntimeException When the check failed. + */ + abstract protected function check_local_state() : ?bool; + + /** + * Inspects the API response of the SellerStatus to determine feature eligibility. + * + * Returns true when the feature is available, and false if ineligible. + * On failure, an RuntimeException is thrown. + * + * @param SellerStatus $seller_status The seller status, returned from the API. + * @return bool + * @throws RuntimeException When the check failed. + */ + abstract protected function check_active_state( SellerStatus $seller_status ) : bool; + + /** + * Clears the eligibility status from the local cache/DB to enforce a new + * API call on the next eligibility check. + * + * @param Settings|null $settings See description in {@see self::clear()}. + * @return void + */ + abstract protected function clear_state( Settings $settings = null ) : void; + + /** + * Whether the merchant has access to the feature. + * + * @return bool + */ + public function is_active() : bool { + if ( null !== $this->is_eligible ) { + return $this->is_eligible; + } + + $this->is_eligible = false; + $this->has_request_failure = false; + + if ( ! $this->is_onboarded() ) { + return $this->is_eligible; + } + + try { + // Try to use filters and DB values to determine the state. + $local_state = $this->check_local_state(); + if ( null !== $local_state ) { + $this->is_eligible = $local_state; + + return $this->is_eligible; + } + + // Check using the merchant-API. + $seller_status = $this->get_seller_status_object(); + $this->is_eligible = $this->check_active_state( $seller_status ); + } catch ( RuntimeException $exception ) { + $this->has_request_failure = true; + } + + return $this->is_eligible; + } + + /** + * Fetches the seller-status object from the PayPal merchant API. + * + * TODO: We might cache the SellerStatus, as it's usually accessed multiple times during one request. + * + * @return SellerStatus + * @throws RuntimeException When the check failed. + */ + protected function get_seller_status_object() : SellerStatus { + // Check API failure registry to prevent multiple failed API requests. + if ( $this->api_failure_registry->has_failure_in_timeframe( FailureRegistry::SELLER_STATUS_KEY, HOUR_IN_SECONDS ) ) { + throw new RuntimeException( 'Timeout for re-check not reached yet' ); + } + + // Request seller status via PayPal API, might throw an Exception. + return $this->partners_endpoint->seller_status(); + } + + /** + * Whether the merchant was fully onboarded, and we have valid API credentials. + * + * @return bool True, if we can use the merchant API endpoints. + */ + public function is_onboarded() : bool { + return $this->is_connected; + } + + /** + * Returns if there was a request failure. + * + * @return bool + */ + public function has_request_failure() : bool { + return $this->has_request_failure; + } + + /** + * Clears the persisted result to force a recheck. + * + * Accepts a Settings object to don't override other sequential settings that are being updated + * elsewhere. + * + * @param Settings|null $settings The settings object. + * @return void + */ + public function clear( Settings $settings = null ) : void { + $this->is_eligible = null; + $this->has_request_failure = false; + + $this->clear_state( $settings ); + } +} From 11f30715792fd85acb89f1ea9c3b2d9a2259c1b8 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Thu, 30 Jan 2025 17:12:50 +0100 Subject: [PATCH 11/37] =?UTF-8?q?=E2=9C=A8=20New=20services=20to=20check?= =?UTF-8?q?=20the=20onboarding=20status?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ppcp-onboarding/services.php | 10 ++++++++++ modules/ppcp-settings/services.php | 9 +++++++++ 2 files changed, 19 insertions(+) diff --git a/modules/ppcp-onboarding/services.php b/modules/ppcp-onboarding/services.php index 2a6de82d8..85f3d4219 100644 --- a/modules/ppcp-onboarding/services.php +++ b/modules/ppcp-onboarding/services.php @@ -117,6 +117,16 @@ return array( $settings = $container->get( 'wcgateway.settings' ); return new State( $settings ); }, + /** + * Checks if the onboarding process is completed and the merchant API can be used. + * This service is overwritten by the ppcp-settings module, when it's active. + */ + 'settings.flag.is-connected' => static function ( ContainerInterface $container ) : bool { + $state = $container->get( 'onboarding.state' ); + assert( $state instanceof State ); + + return $state->current_state() >= State::STATE_ONBOARDED; + }, 'onboarding.environment' => function( ContainerInterface $container ) : Environment { $settings = $container->get( 'wcgateway.settings' ); return new Environment( $settings ); diff --git a/modules/ppcp-settings/services.php b/modules/ppcp-settings/services.php index 1326f4a4a..cbfb9f1ed 100644 --- a/modules/ppcp-settings/services.php +++ b/modules/ppcp-settings/services.php @@ -86,6 +86,15 @@ return array( $container->get( 'settings.service.sanitizer' ) ); }, + /** + * Checks if valid merchant connection details are stored in the DB. + */ + 'settings.flag.is-connected' => static function ( ContainerInterface $container ) : bool { + $data = $container->get( 'settings.data.general' ); + assert( $data instanceof GeneralSettings ); + + return $data->is_merchant_connected(); + }, 'settings.rest.onboarding' => static function ( ContainerInterface $container ) : OnboardingRestEndpoint { return new OnboardingRestEndpoint( $container->get( 'settings.data.onboarding' ) ); }, From 3bd118de1bfd0741e0df42ee436163d7762f5046 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Thu, 30 Jan 2025 17:13:56 +0100 Subject: [PATCH 12/37] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Use=20new=20base=20c?= =?UTF-8?q?lass=20for=20ApplePay=20status=20check?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ppcp-applepay/services.php | 2 +- .../src/Assets/AppleProductStatus.php | 148 ++++-------------- 2 files changed, 29 insertions(+), 121 deletions(-) diff --git a/modules/ppcp-applepay/services.php b/modules/ppcp-applepay/services.php index 1ba23ca08..963891f48 100644 --- a/modules/ppcp-applepay/services.php +++ b/modules/ppcp-applepay/services.php @@ -79,7 +79,7 @@ return array( return new AppleProductStatus( $container->get( 'wcgateway.settings' ), $container->get( 'api.endpoint.partners' ), - $container->get( 'onboarding.state' ), + $container->get( 'settings.flag.is-connected' ), $container->get( 'api.helper.failure-registry' ) ); } diff --git a/modules/ppcp-applepay/src/Assets/AppleProductStatus.php b/modules/ppcp-applepay/src/Assets/AppleProductStatus.php index d5409ddaf..fb728696f 100644 --- a/modules/ppcp-applepay/src/Assets/AppleProductStatus.php +++ b/modules/ppcp-applepay/src/Assets/AppleProductStatus.php @@ -5,134 +5,71 @@ * @package WooCommerce\PayPalCommerce\Applepay\Assets */ -declare(strict_types=1); +declare( strict_types = 1 ); namespace WooCommerce\PayPalCommerce\Applepay\Assets; -use Throwable; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PartnersEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerStatusCapability; use WooCommerce\PayPalCommerce\ApiClient\Helper\FailureRegistry; -use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; +use WooCommerce\PayPalCommerce\ApiClient\Helper\ProductStatus; +use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerStatus; /** * Class AppleProductStatus */ -class AppleProductStatus { - const CAPABILITY_NAME = 'APPLE_PAY'; - const SETTINGS_KEY = 'products_apple_enabled'; +class AppleProductStatus extends ProductStatus { + public const CAPABILITY_NAME = 'APPLE_PAY'; + public const SETTINGS_KEY = 'products_apple_enabled'; - const SETTINGS_VALUE_ENABLED = 'yes'; - const SETTINGS_VALUE_DISABLED = 'no'; - const SETTINGS_VALUE_UNDEFINED = ''; - - /** - * The current status stored in memory. - * - * @var bool|null - */ - private $current_status = null; - - /** - * If there was a request failure. - * - * @var bool - */ - private $has_request_failure = false; + public const SETTINGS_VALUE_ENABLED = 'yes'; + public const SETTINGS_VALUE_DISABLED = 'no'; + public const SETTINGS_VALUE_UNDEFINED = ''; /** * The settings. * * @var Settings */ - private $settings; - - /** - * The partners endpoint. - * - * @var PartnersEndpoint - */ - private $partners_endpoint; - - /** - * The onboarding status - * - * @var State - */ - private $onboarding_state; - - /** - * The API failure registry - * - * @var FailureRegistry - */ - private $api_failure_registry; + private Settings $settings; /** * AppleProductStatus constructor. * - * @param Settings $settings The Settings. - * @param PartnersEndpoint $partners_endpoint The Partner Endpoint. - * @param State $onboarding_state The onboarding state. + * @param Settings $settings The Settings. + * @param PartnersEndpoint $partners_endpoint The Partner Endpoint. + * @param bool $is_connected The onboarding state. * @param FailureRegistry $api_failure_registry The API failure registry. */ public function __construct( Settings $settings, PartnersEndpoint $partners_endpoint, - State $onboarding_state, + bool $is_connected, FailureRegistry $api_failure_registry ) { - $this->settings = $settings; - $this->partners_endpoint = $partners_endpoint; - $this->onboarding_state = $onboarding_state; - $this->api_failure_registry = $api_failure_registry; + parent::__construct( $is_connected, $partners_endpoint, $api_failure_registry ); + + $this->settings = $settings; } - /** - * Whether the active/subscribed products support Applepay. - * - * @return bool - */ - public function is_active() : bool { - - // If not onboarded then makes no sense to check status. - if ( ! $this->is_onboarded() ) { - return false; - } - + /** {@inheritDoc} */ + protected function check_local_state() : ?bool { $status_override = apply_filters( 'woocommerce_paypal_payments_apple_pay_product_status', null ); if ( null !== $status_override ) { return $status_override; } - // If status was already checked on this request return the same result. - if ( null !== $this->current_status ) { - return $this->current_status; - } - // Check if status was checked on previous requests. if ( $this->settings->has( self::SETTINGS_KEY ) && ( $this->settings->get( self::SETTINGS_KEY ) ) ) { - $this->current_status = wc_string_to_bool( $this->settings->get( self::SETTINGS_KEY ) ); - return $this->current_status; + return wc_string_to_bool( $this->settings->get( self::SETTINGS_KEY ) ); } - // Check API failure registry to prevent multiple failed API requests. - if ( $this->api_failure_registry->has_failure_in_timeframe( FailureRegistry::SELLER_STATUS_KEY, HOUR_IN_SECONDS ) ) { - $this->has_request_failure = true; - $this->current_status = false; - return $this->current_status; - } - - // Request seller status via PayPal API. - try { - $seller_status = $this->partners_endpoint->seller_status(); - } catch ( Throwable $error ) { - $this->has_request_failure = true; - $this->current_status = false; - return $this->current_status; - } + return null; + } + /** {@inheritDoc} */ + protected function check_active_state( SellerStatus $seller_status ) : bool { // Check the seller status for the intended capability. $has_capability = false; foreach ( $seller_status->products() as $product ) { @@ -156,54 +93,25 @@ class AppleProductStatus { $this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_ENABLED ); $this->settings->persist(); - $this->current_status = true; - return $this->current_status; + return true; } // Capability not found, persist status and return false. $this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_DISABLED ); $this->settings->persist(); - $this->current_status = false; - return $this->current_status; + return false; } - /** - * Returns if the seller is onboarded. - * - * @return bool - */ - public function is_onboarded(): bool { - return $this->onboarding_state->current_state() >= State::STATE_ONBOARDED; - } - - /** - * Returns if there was a request failure. - * - * @return bool - */ - public function has_request_failure(): bool { - return $this->has_request_failure; - } - - /** - * Clears the persisted result to force a recheck. - * - * @param Settings|null $settings The settings object. - * We accept a Settings object to don't override other sequential settings that are being updated elsewhere. - * @return void - */ - public function clear( Settings $settings = null ): void { + /** {@inheritDoc} */ + protected function clear_state( Settings $settings = null ) : void { if ( null === $settings ) { $settings = $this->settings; } - $this->current_status = null; - if ( $settings->has( self::SETTINGS_KEY ) ) { $settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_UNDEFINED ); $settings->persist(); } } - } From 00edc1139217ae7996ba03a096a7ea5e26ba403a Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Thu, 30 Jan 2025 17:26:24 +0100 Subject: [PATCH 13/37] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Use=20new=20base=20c?= =?UTF-8?q?lass=20for=20GooglePay=20status=20check?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ppcp-googlepay/services.php | 2 +- .../src/Helper/ApmProductStatus.php | 161 ++++-------------- 2 files changed, 34 insertions(+), 129 deletions(-) diff --git a/modules/ppcp-googlepay/services.php b/modules/ppcp-googlepay/services.php index b1cccaebd..18c48f3ad 100644 --- a/modules/ppcp-googlepay/services.php +++ b/modules/ppcp-googlepay/services.php @@ -75,7 +75,7 @@ return array( return new ApmProductStatus( $container->get( 'wcgateway.settings' ), $container->get( 'api.endpoint.partners' ), - $container->get( 'onboarding.state' ), + $container->get( 'settings.flag.is-connected' ), $container->get( 'api.helper.failure-registry' ) ); } diff --git a/modules/ppcp-googlepay/src/Helper/ApmProductStatus.php b/modules/ppcp-googlepay/src/Helper/ApmProductStatus.php index 3639a1717..1da8379df 100644 --- a/modules/ppcp-googlepay/src/Helper/ApmProductStatus.php +++ b/modules/ppcp-googlepay/src/Helper/ApmProductStatus.php @@ -9,130 +9,67 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Googlepay\Helper; -use Throwable; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PartnersEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerStatusCapability; use WooCommerce\PayPalCommerce\ApiClient\Helper\FailureRegistry; -use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; +use WooCommerce\PayPalCommerce\ApiClient\Helper\ProductStatus; +use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerStatus; /** * Class ApmProductStatus */ -class ApmProductStatus { - const CAPABILITY_NAME = 'GOOGLE_PAY'; - const SETTINGS_KEY = 'products_googlepay_enabled'; +class ApmProductStatus extends ProductStatus { + public const CAPABILITY_NAME = 'GOOGLE_PAY'; + public const SETTINGS_KEY = 'products_googlepay_enabled'; - const SETTINGS_VALUE_ENABLED = 'yes'; - const SETTINGS_VALUE_DISABLED = 'no'; - const SETTINGS_VALUE_UNDEFINED = ''; - - /** - * The current status stored in memory. - * - * @var bool|null - */ - private $current_status = null; - - /** - * If there was a request failure. - * - * @var bool - */ - private $has_request_failure = false; + public const SETTINGS_VALUE_ENABLED = 'yes'; + public const SETTINGS_VALUE_DISABLED = 'no'; + public const SETTINGS_VALUE_UNDEFINED = ''; /** * The settings. * * @var Settings */ - private $settings; - - /** - * The partners endpoint. - * - * @var PartnersEndpoint - */ - private $partners_endpoint; - - /** - * The onboarding status - * - * @var State - */ - private $onboarding_state; - - /** - * The API failure registry - * - * @var FailureRegistry - */ - private $api_failure_registry; + private Settings $settings; /** * ApmProductStatus constructor. * - * @param Settings $settings The Settings. - * @param PartnersEndpoint $partners_endpoint The Partner Endpoint. - * @param State $onboarding_state The onboarding state. + * @param Settings $settings The Settings. + * @param PartnersEndpoint $partners_endpoint The Partner Endpoint. + * @param bool $is_connected The onboarding state. * @param FailureRegistry $api_failure_registry The API failure registry. */ public function __construct( Settings $settings, PartnersEndpoint $partners_endpoint, - State $onboarding_state, + bool $is_connected, FailureRegistry $api_failure_registry ) { - $this->settings = $settings; - $this->partners_endpoint = $partners_endpoint; - $this->onboarding_state = $onboarding_state; - $this->api_failure_registry = $api_failure_registry; + parent::__construct( $is_connected, $partners_endpoint, $api_failure_registry ); + + $this->settings = $settings; } - /** - * Whether the active/subscribed products support Googlepay. - * - * @return bool - */ - public function is_active() : bool { - - // If not onboarded then makes no sense to check status. - if ( ! $this->is_onboarded() ) { - return false; - } - + /** {@inheritDoc} */ + protected function check_local_state() : ?bool { $status_override = apply_filters( 'woocommerce_paypal_payments_google_pay_product_status', null ); if ( null !== $status_override ) { return $status_override; } - // If status was already checked on this request return the same result. - if ( null !== $this->current_status ) { - return $this->current_status; - } - // Check if status was checked on previous requests. if ( $this->settings->has( self::SETTINGS_KEY ) && ( $this->settings->get( self::SETTINGS_KEY ) ) ) { - $this->current_status = wc_string_to_bool( $this->settings->get( self::SETTINGS_KEY ) ); - return $this->current_status; + return wc_string_to_bool( $this->settings->get( self::SETTINGS_KEY ) ); } - // Check API failure registry to prevent multiple failed API requests. - if ( $this->api_failure_registry->has_failure_in_timeframe( FailureRegistry::SELLER_STATUS_KEY, HOUR_IN_SECONDS ) ) { - $this->has_request_failure = true; - $this->current_status = false; - return $this->current_status; - } - - // Request seller status via PayPal API. - try { - $seller_status = $this->partners_endpoint->seller_status(); - } catch ( Throwable $error ) { - $this->has_request_failure = true; - $this->current_status = false; - return $this->current_status; - } + return null; + } + /** {@inheritDoc} */ + protected function check_active_state( SellerStatus $seller_status ) : bool { // Check the seller status for the intended capability. $has_capability = false; foreach ( $seller_status->products() as $product ) { @@ -145,65 +82,33 @@ class ApmProductStatus { } } - foreach ( $seller_status->capabilities() as $capability ) { - if ( $capability->name() === self::CAPABILITY_NAME && $capability->status() === SellerStatusCapability::STATUS_ACTIVE ) { - $has_capability = true; + if ( ! $has_capability ) { + foreach ( $seller_status->capabilities() as $capability ) { + if ( $capability->name() === self::CAPABILITY_NAME && $capability->status() === SellerStatusCapability::STATUS_ACTIVE ) { + $has_capability = true; + } } } if ( $has_capability ) { - // Capability found, persist status and return true. $this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_ENABLED ); - $this->settings->persist(); - - $this->current_status = true; - return $this->current_status; + } else { + $this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_DISABLED ); } - - // Capability not found, persist status and return false. - $this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_DISABLED ); $this->settings->persist(); - $this->current_status = false; - return $this->current_status; + return $has_capability; } - /** - * Returns if the seller is onboarded. - * - * @return bool - */ - public function is_onboarded(): bool { - return $this->onboarding_state->current_state() >= State::STATE_ONBOARDED; - } - - /** - * Returns if there was a request failure. - * - * @return bool - */ - public function has_request_failure(): bool { - return $this->has_request_failure; - } - - /** - * Clears the persisted result to force a recheck. - * - * @param Settings|null $settings The settings object. - * We accept a Settings object to don't override other sequential settings that are being updated elsewhere. - * @return void - */ - public function clear( Settings $settings = null ): void { + /** {@inheritDoc} */ + protected function clear_state( Settings $settings = null ) : void { if ( null === $settings ) { $settings = $this->settings; } - $this->current_status = null; - if ( $settings->has( self::SETTINGS_KEY ) ) { $settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_UNDEFINED ); $settings->persist(); } } - } From c985573d1dd5742321c5bf3f488d044f23061072 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Thu, 30 Jan 2025 17:27:37 +0100 Subject: [PATCH 14/37] =?UTF-8?q?=F0=9F=A5=85=20Annotate=20all=20throwable?= =?UTF-8?q?=20errors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ppcp-api-client/src/Helper/ProductStatus.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/ppcp-api-client/src/Helper/ProductStatus.php b/modules/ppcp-api-client/src/Helper/ProductStatus.php index a6c575a3e..eeda4ad22 100644 --- a/modules/ppcp-api-client/src/Helper/ProductStatus.php +++ b/modules/ppcp-api-client/src/Helper/ProductStatus.php @@ -10,9 +10,11 @@ declare( strict_types = 1 ); namespace WooCommerce\PayPalCommerce\ApiClient\Helper; use RuntimeException; +use Exception; +use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PartnersEndpoint; -use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerStatus; +use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; /** * Class ProductStatus @@ -81,6 +83,7 @@ abstract class ProductStatus { * * @return null|bool Boolean to indicate the status; null if the status not locally defined. * @throws RuntimeException When the check failed. + * @throws NotFoundException When a relevant service or setting was not found. */ abstract protected function check_local_state() : ?bool; @@ -134,7 +137,7 @@ abstract class ProductStatus { // Check using the merchant-API. $seller_status = $this->get_seller_status_object(); $this->is_eligible = $this->check_active_state( $seller_status ); - } catch ( RuntimeException $exception ) { + } catch ( Exception $exception ) { $this->has_request_failure = true; } From 4006605964079e66662d07c7b0cb3c9b4131cc40 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Thu, 30 Jan 2025 17:29:23 +0100 Subject: [PATCH 15/37] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Slightly=20shorten?= =?UTF-8?q?=20ApplePay=20status=20check?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/Assets/AppleProductStatus.php | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/modules/ppcp-applepay/src/Assets/AppleProductStatus.php b/modules/ppcp-applepay/src/Assets/AppleProductStatus.php index fb728696f..61668c26d 100644 --- a/modules/ppcp-applepay/src/Assets/AppleProductStatus.php +++ b/modules/ppcp-applepay/src/Assets/AppleProductStatus.php @@ -60,7 +60,6 @@ class AppleProductStatus extends ProductStatus { return $status_override; } - // Check if status was checked on previous requests. if ( $this->settings->has( self::SETTINGS_KEY ) && ( $this->settings->get( self::SETTINGS_KEY ) ) ) { return wc_string_to_bool( $this->settings->get( self::SETTINGS_KEY ) ); } @@ -82,25 +81,22 @@ class AppleProductStatus extends ProductStatus { } } - foreach ( $seller_status->capabilities() as $capability ) { - if ( $capability->name() === self::CAPABILITY_NAME && $capability->status() === SellerStatusCapability::STATUS_ACTIVE ) { - $has_capability = true; + if ( ! $has_capability ) { + foreach ( $seller_status->capabilities() as $capability ) { + if ( $capability->name() === self::CAPABILITY_NAME && $capability->status() === SellerStatusCapability::STATUS_ACTIVE ) { + $has_capability = true; + } } } if ( $has_capability ) { - // Capability found, persist status and return true. $this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_ENABLED ); - $this->settings->persist(); - - return true; + } else { + $this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_DISABLED ); } - - // Capability not found, persist status and return false. - $this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_DISABLED ); $this->settings->persist(); - return false; + return $has_capability; } /** {@inheritDoc} */ From e6a6cbb7b18ba5f910d9f41c4e5e3be8d234455a Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Thu, 30 Jan 2025 17:43:15 +0100 Subject: [PATCH 16/37] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Use=20new=20base=20c?= =?UTF-8?q?lass=20for=20DCC=20status=20check?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ppcp-settings/src/SettingsModule.php | 4 +- modules/ppcp-wc-gateway/services.php | 4 +- .../src/Helper/DCCProductStatus.php | 161 +++++------------- .../src/Settings/SectionsRenderer.php | 2 +- .../src/Settings/SettingsRenderer.php | 2 +- .../ppcp-wc-gateway/src/WCGatewayModule.php | 4 +- 6 files changed, 51 insertions(+), 126 deletions(-) diff --git a/modules/ppcp-settings/src/SettingsModule.php b/modules/ppcp-settings/src/SettingsModule.php index b7c334425..63b913e02 100644 --- a/modules/ppcp-settings/src/SettingsModule.php +++ b/modules/ppcp-settings/src/SettingsModule.php @@ -299,7 +299,7 @@ class SettingsModule implements ServiceModule, ExecutableModule { assert( $dcc_applies instanceof DCCApplies ); // Unset BCDC if merchant is eligible for ACDC. - if ( $dcc_product_status->dcc_is_active() && ! $container->get( 'wcgateway.settings.allow_card_button_gateway' ) ) { + if ( $dcc_product_status->is_active() && ! $container->get( 'wcgateway.settings.allow_card_button_gateway' ) ) { unset( $payment_methods[ CardButtonGateway::ID ] ); } @@ -319,7 +319,7 @@ class SettingsModule implements ServiceModule, ExecutableModule { } // Unset Fastlane if store location is not United States or merchant is not eligible for ACDC. - if ( $container->get( 'api.shop.country' ) !== 'US' || ! $dcc_product_status->dcc_is_active() ) { + if ( $container->get( 'api.shop.country' ) !== 'US' || ! $dcc_product_status->is_active() ) { unset( $payment_methods['ppcp-axo-gateway'] ); } diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index 1bac9b14e..fe868743e 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -1431,7 +1431,7 @@ return array( $partner_endpoint, $container->get( 'dcc.status-cache' ), $container->get( 'api.helpers.dccapplies' ), - $container->get( 'onboarding.state' ), + $container->get( 'settings.flag.is-connected' ), $container->get( 'api.helper.failure-registry' ) ); }, @@ -1728,7 +1728,7 @@ return array( $environment = $container->get( 'onboarding.environment' ); assert( $environment instanceof Environment ); - $dcc_enabled = $dcc_product_status->dcc_is_active(); + $dcc_enabled = $dcc_product_status->is_active(); $enabled_status_text = esc_html__( 'Status: Available', 'woocommerce-paypal-payments' ); $disabled_status_text = esc_html__( 'Status: Not yet enabled', 'woocommerce-paypal-payments' ); diff --git a/modules/ppcp-wc-gateway/src/Helper/DCCProductStatus.php b/modules/ppcp-wc-gateway/src/Helper/DCCProductStatus.php index 3ca5b9998..d82271b60 100644 --- a/modules/ppcp-wc-gateway/src/Helper/DCCProductStatus.php +++ b/modules/ppcp-wc-gateway/src/Helper/DCCProductStatus.php @@ -9,86 +9,55 @@ declare( strict_types=1 ); namespace WooCommerce\PayPalCommerce\WcGateway\Helper; -use Throwable; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PartnersEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerStatusProduct; use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache; use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies; use WooCommerce\PayPalCommerce\ApiClient\Helper\FailureRegistry; -use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; +use WooCommerce\PayPalCommerce\ApiClient\Helper\ProductStatus; +use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerStatus; /** * Class DccProductStatus */ -class DCCProductStatus { +class DCCProductStatus extends ProductStatus { + public const SETTINGS_KEY = 'products_dcc_enabled'; + public const DCC_STATUS_CACHE_KEY = 'dcc_status_cache'; - const DCC_STATUS_CACHE_KEY = 'dcc_status_cache'; + public const SETTINGS_VALUE_ENABLED = 'yes'; + public const SETTINGS_VALUE_DISABLED = 'no'; + public const SETTINGS_VALUE_UNDEFINED = ''; /** * The Cache. * * @var Cache */ - protected $cache; - - /** - * Caches the status for the current load. - * - * @var bool|null - */ - private $current_status_cache; - - /** - * If there was a request failure. - * - * @var bool - */ - private $has_request_failure = false; + protected Cache $cache; /** * The settings. * * @var Settings */ - private $settings; - - /** - * The partners endpoint. - * - * @var PartnersEndpoint - */ - private $partners_endpoint; + private Settings $settings; /** * The dcc applies helper. * * @var DccApplies */ - protected $dcc_applies; - - /** - * The onboarding state. - * - * @var State - */ - private $onboarding_state; - - /** - * The API failure registry - * - * @var FailureRegistry - */ - private $api_failure_registry; + protected DccApplies $dcc_applies; /** * DccProductStatus constructor. * - * @param Settings $settings The Settings. - * @param PartnersEndpoint $partners_endpoint The Partner Endpoint. - * @param Cache $cache The cache. - * @param DccApplies $dcc_applies The dcc applies helper. - * @param State $onboarding_state The onboarding state. + * @param Settings $settings The Settings. + * @param PartnersEndpoint $partners_endpoint The Partner Endpoint. + * @param Cache $cache The cache. + * @param DccApplies $dcc_applies The dcc applies helper. + * @param bool $is_connected The onboarding state. * @param FailureRegistry $api_failure_registry The API failure registry. */ public function __construct( @@ -96,55 +65,31 @@ class DCCProductStatus { PartnersEndpoint $partners_endpoint, Cache $cache, DccApplies $dcc_applies, - State $onboarding_state, + bool $is_connected, FailureRegistry $api_failure_registry ) { - $this->settings = $settings; - $this->partners_endpoint = $partners_endpoint; - $this->cache = $cache; - $this->dcc_applies = $dcc_applies; - $this->onboarding_state = $onboarding_state; - $this->api_failure_registry = $api_failure_registry; + parent::__construct( $is_connected, $partners_endpoint, $api_failure_registry ); + + $this->settings = $settings; + $this->cache = $cache; + $this->dcc_applies = $dcc_applies; } - /** - * Whether the active/subscribed products support DCC. - * - * @return bool - */ - public function dcc_is_active() : bool { - if ( $this->onboarding_state->current_state() < State::STATE_ONBOARDED ) { - return false; - } - + /** {@inheritDoc} */ + protected function check_local_state() : ?bool { if ( $this->cache->has( self::DCC_STATUS_CACHE_KEY ) ) { - return $this->cache->get( self::DCC_STATUS_CACHE_KEY ) === 'true'; + return wc_string_to_bool( $this->cache->get( self::DCC_STATUS_CACHE_KEY ) ); } - if ( $this->current_status_cache === true ) { - return $this->current_status_cache; + if ( $this->settings->has( self::SETTINGS_KEY ) && ( $this->settings->get( self::SETTINGS_KEY ) ) ) { + return wc_string_to_bool( $this->settings->get( self::SETTINGS_KEY ) ); } - if ( $this->settings->has( 'products_dcc_enabled' ) && $this->settings->get( 'products_dcc_enabled' ) === true ) { - $this->current_status_cache = true; - return true; - } - - // Check API failure registry to prevent multiple failed API requests. - if ( $this->api_failure_registry->has_failure_in_timeframe( FailureRegistry::SELLER_STATUS_KEY, HOUR_IN_SECONDS ) ) { - $this->has_request_failure = true; - $this->current_status_cache = false; - return $this->current_status_cache; - } - - try { - $seller_status = $this->partners_endpoint->seller_status(); - } catch ( Throwable $error ) { - $this->has_request_failure = true; - $this->current_status_cache = false; - return false; - } + return null; + } + /** {@inheritDoc} */ + protected function check_active_state( SellerStatus $seller_status ) : bool { foreach ( $seller_status->products() as $product ) { if ( ! in_array( $product->vetting_status(), @@ -159,57 +104,37 @@ class DCCProductStatus { } if ( in_array( 'CUSTOM_CARD_PROCESSING', $product->capabilities(), true ) ) { - $this->settings->set( 'products_dcc_enabled', true ); + $this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_ENABLED ); $this->settings->persist(); - $this->current_status_cache = true; - $this->cache->set( self::DCC_STATUS_CACHE_KEY, 'true', MONTH_IN_SECONDS ); + + $this->cache->set( self::DCC_STATUS_CACHE_KEY, self::SETTINGS_VALUE_ENABLED, MONTH_IN_SECONDS ); + return true; } } - $expiration = MONTH_IN_SECONDS; if ( $this->dcc_applies->for_country_currency() ) { $expiration = 3 * HOUR_IN_SECONDS; + } else { + $expiration = MONTH_IN_SECONDS; } - $this->cache->set( self::DCC_STATUS_CACHE_KEY, 'false', $expiration ); - $this->current_status_cache = false; + $this->cache->set( self::DCC_STATUS_CACHE_KEY, self::SETTINGS_VALUE_DISABLED, $expiration ); + return false; } - /** - * Returns if there was a request failure. - * - * @return bool - */ - public function has_request_failure(): bool { - return $this->has_request_failure; - } - - /** - * Clears the persisted result to force a recheck. - * - * @param Settings|null $settings The settings object. - * We accept a Settings object to don't override other sequential settings that are being updated elsewhere. - * @return void - */ - public function clear( Settings $settings = null ): void { + /** {@inheritDoc} */ + protected function clear_state( Settings $settings = null ): void { if ( null === $settings ) { $settings = $this->settings; } - // Unset check stored in memory. - $this->current_status_cache = null; - - // Unset settings flag. - $settings_key = 'products_dcc_enabled'; - if ( $settings->has( $settings_key ) ) { - $settings->set( $settings_key, false ); + if ( $settings->has( self::SETTINGS_KEY ) ) { + $settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_UNDEFINED ); $settings->persist(); } - // Delete cached value. $this->cache->delete( self::DCC_STATUS_CACHE_KEY ); } - } diff --git a/modules/ppcp-wc-gateway/src/Settings/SectionsRenderer.php b/modules/ppcp-wc-gateway/src/Settings/SectionsRenderer.php index bc61c64a9..09f9bd734 100644 --- a/modules/ppcp-wc-gateway/src/Settings/SectionsRenderer.php +++ b/modules/ppcp-wc-gateway/src/Settings/SectionsRenderer.php @@ -168,7 +168,7 @@ class SectionsRenderer { } } - if ( ! $this->dcc_product_status->dcc_is_active() || ! $this->dcc_applies->for_country_currency() ) { + if ( ! $this->dcc_product_status->is_active() || ! $this->dcc_applies->for_country_currency() ) { unset( $sections['ppcp-credit-card-gateway'] ); } diff --git a/modules/ppcp-wc-gateway/src/Settings/SettingsRenderer.php b/modules/ppcp-wc-gateway/src/Settings/SettingsRenderer.php index ccf91d019..e32cbf0c4 100644 --- a/modules/ppcp-wc-gateway/src/Settings/SettingsRenderer.php +++ b/modules/ppcp-wc-gateway/src/Settings/SettingsRenderer.php @@ -465,7 +465,7 @@ $data_rows_html if ( $this->dcc_applies->for_country_currency() ) { if ( State::STATE_ONBOARDED > $this->state->current_state() ) { $this->render_dcc_onboarding_info(); - } elseif ( ! $this->dcc_product_status->dcc_is_active() ) { + } elseif ( ! $this->dcc_product_status->is_active() ) { $this->render_dcc_not_active_yet(); } } else { diff --git a/modules/ppcp-wc-gateway/src/WCGatewayModule.php b/modules/ppcp-wc-gateway/src/WCGatewayModule.php index c10813c86..95f0eb97d 100644 --- a/modules/ppcp-wc-gateway/src/WCGatewayModule.php +++ b/modules/ppcp-wc-gateway/src/WCGatewayModule.php @@ -341,7 +341,7 @@ class WCGatewayModule implements ServiceModule, ExtendingModule, ExecutableModul // Update caches. $dcc_status = $c->get( 'wcgateway.helper.dcc-product-status' ); assert( $dcc_status instanceof DCCProductStatus ); - $dcc_status->dcc_is_active(); + $dcc_status->is_active(); $pui_status = $c->get( 'wcgateway.pay-upon-invoice-product-status' ); assert( $pui_status instanceof PayUponInvoiceProductStatus ); @@ -668,7 +668,7 @@ class WCGatewayModule implements ServiceModule, ExtendingModule, ExecutableModul // Performing the full DCCProductStatus check only when on the gateway list page // to avoid sending the API requests all the time. ( $is_our_page || - ( $is_gateways_list_page && $dcc_product_status->dcc_is_active() ) || + ( $is_gateways_list_page && $dcc_product_status->is_active() ) || ( $settings->has( 'products_dcc_enabled' ) && $settings->get( 'products_dcc_enabled' ) ) ) ) { From 5ac70e26c283a0b4ae347921a2b4ae57888ff0b5 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Thu, 30 Jan 2025 18:15:40 +0100 Subject: [PATCH 17/37] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Use=20new=20base=20c?= =?UTF-8?q?lass=20for=20PUI=20status=20check?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ppcp-wc-gateway/services.php | 4 +- .../Gateway/PayUponInvoice/PayUponInvoice.php | 4 +- .../Helper/PayUponInvoiceProductStatus.php | 149 +++++------------- .../src/Settings/SectionsRenderer.php | 2 +- .../ppcp-wc-gateway/src/WCGatewayModule.php | 4 +- 5 files changed, 43 insertions(+), 120 deletions(-) diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index fe868743e..459dc8b1b 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -1515,7 +1515,7 @@ return array( $container->get( 'wcgateway.settings' ), $container->get( 'api.endpoint.partners' ), $container->get( 'pui.status-cache' ), - $container->get( 'onboarding.state' ), + $container->get( 'settings.flag.is-connected' ), $container->get( 'api.helper.failure-registry' ) ); }, @@ -1799,7 +1799,7 @@ return array( $environment = $container->get( 'onboarding.environment' ); assert( $environment instanceof Environment ); - $pui_enabled = $pui_product_status->pui_is_active(); + $pui_enabled = $pui_product_status->is_active(); $enabled_status_text = esc_html__( 'Status: Available', 'woocommerce-paypal-payments' ); $disabled_status_text = esc_html__( 'Status: Not yet enabled', 'woocommerce-paypal-payments' ); diff --git a/modules/ppcp-wc-gateway/src/Gateway/PayUponInvoice/PayUponInvoice.php b/modules/ppcp-wc-gateway/src/Gateway/PayUponInvoice/PayUponInvoice.php index 94ed7240a..5b1fc0d36 100644 --- a/modules/ppcp-wc-gateway/src/Gateway/PayUponInvoice/PayUponInvoice.php +++ b/modules/ppcp-wc-gateway/src/Gateway/PayUponInvoice/PayUponInvoice.php @@ -445,7 +445,7 @@ class PayUponInvoice { } if ( - ! $this->pui_product_status->pui_is_active() + ! $this->pui_product_status->is_active() || ! $this->pui_helper->is_checkout_ready_for_pui() ) { unset( $methods[ PayUponInvoiceGateway::ID ] ); @@ -478,7 +478,7 @@ class PayUponInvoice { function() { if ( PayUponInvoiceGateway::ID === $this->current_ppcp_settings_page_id - && $this->pui_product_status->pui_is_active() + && $this->pui_product_status->is_active() ) { $error_messages = array(); $pui_gateway = WC()->payment_gateways->payment_gateways()[ PayUponInvoiceGateway::ID ]; diff --git a/modules/ppcp-wc-gateway/src/Helper/PayUponInvoiceProductStatus.php b/modules/ppcp-wc-gateway/src/Helper/PayUponInvoiceProductStatus.php index dfbcb0380..250138089 100644 --- a/modules/ppcp-wc-gateway/src/Helper/PayUponInvoiceProductStatus.php +++ b/modules/ppcp-wc-gateway/src/Helper/PayUponInvoiceProductStatus.php @@ -9,130 +9,76 @@ declare( strict_types=1 ); namespace WooCommerce\PayPalCommerce\WcGateway\Helper; -use Throwable; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PartnersEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerStatusProduct; use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache; use WooCommerce\PayPalCommerce\ApiClient\Helper\FailureRegistry; -use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; +use WooCommerce\PayPalCommerce\ApiClient\Helper\ProductStatus; +use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerStatus; /** * Class PayUponInvoiceProductStatus */ -class PayUponInvoiceProductStatus { +class PayUponInvoiceProductStatus extends ProductStatus { + public const SETTINGS_KEY = 'products_pui_enabled'; + public const PUI_STATUS_CACHE_KEY = 'pui_status_cache'; - const PUI_STATUS_CACHE_KEY = 'pui_status_cache'; + public const SETTINGS_VALUE_ENABLED = 'yes'; + public const SETTINGS_VALUE_DISABLED = 'no'; + public const SETTINGS_VALUE_UNDEFINED = ''; /** * The Cache. * * @var Cache */ - protected $cache; - - /** - * Caches the status for the current load. - * - * @var bool|null - */ - private $current_status_cache; - - /** - * If there was a request failure. - * - * @var bool - */ - private $has_request_failure = false; + protected Cache $cache; /** * The settings. * * @var Settings */ - private $settings; - - /** - * The partners endpoint. - * - * @var PartnersEndpoint - */ - private $partners_endpoint; - - /** - * The onboarding status - * - * @var State - */ - private $onboarding_state; - - /** - * The API failure registry - * - * @var FailureRegistry - */ - private $api_failure_registry; + private Settings $settings; /** * PayUponInvoiceProductStatus constructor. * - * @param Settings $settings The Settings. - * @param PartnersEndpoint $partners_endpoint The Partner Endpoint. - * @param Cache $cache The cache. - * @param State $onboarding_state The onboarding state. + * @param Settings $settings The Settings. + * @param PartnersEndpoint $partners_endpoint The Partner Endpoint. + * @param Cache $cache The cache. + * @param bool $is_connected The onboarding state. * @param FailureRegistry $api_failure_registry The API failure registry. */ public function __construct( Settings $settings, PartnersEndpoint $partners_endpoint, Cache $cache, - State $onboarding_state, + bool $is_connected, FailureRegistry $api_failure_registry ) { - $this->settings = $settings; - $this->partners_endpoint = $partners_endpoint; - $this->cache = $cache; - $this->onboarding_state = $onboarding_state; - $this->api_failure_registry = $api_failure_registry; + parent::__construct( $is_connected, $partners_endpoint, $api_failure_registry ); + + $this->settings = $settings; + $this->cache = $cache; } - /** - * Whether the active/subscribed products support PUI. - * - * @return bool - */ - public function pui_is_active() : bool { - if ( $this->onboarding_state->current_state() < State::STATE_ONBOARDED ) { - return false; - } - + /** {@inheritDoc} */ + protected function check_local_state() : ?bool { if ( $this->cache->has( self::PUI_STATUS_CACHE_KEY ) ) { - return $this->cache->get( self::PUI_STATUS_CACHE_KEY ) === 'true'; + return wc_string_to_bool( $this->cache->get( self::PUI_STATUS_CACHE_KEY ) ); } - if ( $this->current_status_cache === true ) { - return $this->current_status_cache; - } - if ( $this->settings->has( 'products_pui_enabled' ) && $this->settings->get( 'products_pui_enabled' ) === true ) { - $this->current_status_cache = true; - return true; + if ( $this->settings->has( self::SETTINGS_KEY ) && ( $this->settings->get( self::SETTINGS_KEY ) ) ) { + return wc_string_to_bool( $this->settings->get( self::SETTINGS_KEY ) ); } - // Check API failure registry to prevent multiple failed API requests. - if ( $this->api_failure_registry->has_failure_in_timeframe( FailureRegistry::SELLER_STATUS_KEY, HOUR_IN_SECONDS ) ) { - $this->has_request_failure = true; - $this->current_status_cache = false; - return $this->current_status_cache; - } - - try { - $seller_status = $this->partners_endpoint->seller_status(); - } catch ( Throwable $error ) { - $this->has_request_failure = true; - $this->current_status_cache = false; - return false; - } + return null; + } + /** {@inheritDoc} */ + protected function check_active_state( SellerStatus $seller_status ) : bool { foreach ( $seller_status->products() as $product ) { if ( $product->name() !== 'PAYMENT_METHODS' ) { continue; @@ -151,52 +97,29 @@ class PayUponInvoiceProductStatus { } if ( in_array( 'PAY_UPON_INVOICE', $product->capabilities(), true ) ) { - $this->settings->set( 'products_pui_enabled', true ); + $this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_ENABLED ); $this->settings->persist(); - $this->current_status_cache = true; - $this->cache->set( self::PUI_STATUS_CACHE_KEY, 'true', MONTH_IN_SECONDS ); + $this->cache->set( self::PUI_STATUS_CACHE_KEY, self::SETTINGS_VALUE_ENABLED, MONTH_IN_SECONDS ); return true; } } - $this->cache->set( self::PUI_STATUS_CACHE_KEY, 'false', MONTH_IN_SECONDS ); - $this->current_status_cache = false; + $this->cache->set( self::PUI_STATUS_CACHE_KEY, self::SETTINGS_VALUE_DISABLED, MONTH_IN_SECONDS ); + return false; } - /** - * Returns if there was a request failure. - * - * @return bool - */ - public function has_request_failure(): bool { - return $this->has_request_failure; - } - - /** - * Clears the persisted result to force a recheck. - * - * @param Settings|null $settings The settings object. - * We accept a Settings object to don't override other sequential settings that are being updated elsewhere. - * @return void - */ - public function clear( Settings $settings = null ): void { + /** {@inheritDoc} */ + protected function clear_state( Settings $settings = null ) : void { if ( null === $settings ) { $settings = $this->settings; } - // Unset check stored in memory. - $this->current_status_cache = null; - - // Unset settings flag. - $settings_key = 'products_pui_enabled'; - if ( $settings->has( $settings_key ) ) { - $settings->set( $settings_key, false ); + if ( $settings->has( self::SETTINGS_KEY ) ) { + $settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_UNDEFINED ); $settings->persist(); } - // Delete cached value. $this->cache->delete( self::PUI_STATUS_CACHE_KEY ); } - } diff --git a/modules/ppcp-wc-gateway/src/Settings/SectionsRenderer.php b/modules/ppcp-wc-gateway/src/Settings/SectionsRenderer.php index 09f9bd734..f8f05f4ff 100644 --- a/modules/ppcp-wc-gateway/src/Settings/SectionsRenderer.php +++ b/modules/ppcp-wc-gateway/src/Settings/SectionsRenderer.php @@ -176,7 +176,7 @@ class SectionsRenderer { unset( $sections[ Settings::PAY_LATER_TAB_ID ] ); } - if ( ! $this->pui_product_status->pui_is_active() ) { + if ( ! $this->pui_product_status->is_active() ) { unset( $sections[ PayUponInvoiceGateway::ID ] ); } diff --git a/modules/ppcp-wc-gateway/src/WCGatewayModule.php b/modules/ppcp-wc-gateway/src/WCGatewayModule.php index 95f0eb97d..4885bdbf6 100644 --- a/modules/ppcp-wc-gateway/src/WCGatewayModule.php +++ b/modules/ppcp-wc-gateway/src/WCGatewayModule.php @@ -345,7 +345,7 @@ class WCGatewayModule implements ServiceModule, ExtendingModule, ExecutableModul $pui_status = $c->get( 'wcgateway.pay-upon-invoice-product-status' ); assert( $pui_status instanceof PayUponInvoiceProductStatus ); - $pui_status->pui_is_active(); + $pui_status->is_active(); } ); @@ -686,7 +686,7 @@ class WCGatewayModule implements ServiceModule, ExtendingModule, ExecutableModul if ( 'DE' === $shop_country && ( $is_our_page || - ( $is_gateways_list_page && $pui_product_status->pui_is_active() ) || + ( $is_gateways_list_page && $pui_product_status->is_active() ) || ( $settings->has( 'products_pui_enabled' ) && $settings->get( 'products_pui_enabled' ) ) ) ) { From 5f517620259099adc6eb267055def1c5ad00f9a7 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Thu, 30 Jan 2025 18:22:12 +0100 Subject: [PATCH 18/37] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20More=20appropriate?= =?UTF-8?q?=20hook=20name?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ppcp-applepay/src/ApplepayModule.php | 2 +- modules/ppcp-googlepay/src/GooglepayModule.php | 2 +- modules/ppcp-googlepay/src/Helper/ApmProductStatus.php | 1 - modules/ppcp-settings/src/Endpoint/CommonRestEndpoint.php | 2 +- modules/ppcp-wc-gateway/src/WCGatewayModule.php | 2 +- 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/modules/ppcp-applepay/src/ApplepayModule.php b/modules/ppcp-applepay/src/ApplepayModule.php index dc7b3cf11..ea58b4d89 100644 --- a/modules/ppcp-applepay/src/ApplepayModule.php +++ b/modules/ppcp-applepay/src/ApplepayModule.php @@ -183,7 +183,7 @@ class ApplepayModule implements ServiceModule, ExtendingModule, ExecutableModule ); add_filter( - 'woocommerce_paypal_payments_rest_common_merchant_data', + 'woocommerce_paypal_payments_rest_common_merchant_features', function( array $features ) use ( $c ): array { $product_status = $c->get( 'applepay.apple-product-status' ); assert( $product_status instanceof AppleProductStatus ); diff --git a/modules/ppcp-googlepay/src/GooglepayModule.php b/modules/ppcp-googlepay/src/GooglepayModule.php index dd7320011..a50408bd3 100644 --- a/modules/ppcp-googlepay/src/GooglepayModule.php +++ b/modules/ppcp-googlepay/src/GooglepayModule.php @@ -233,7 +233,7 @@ class GooglepayModule implements ServiceModule, ExtendingModule, ExecutableModul ); add_filter( - 'woocommerce_paypal_payments_rest_common_merchant_data', + 'woocommerce_paypal_payments_rest_common_merchant_features', function ( array $features ) use ( $c ): array { $product_status = $c->get( 'googlepay.helpers.apm-product-status' ); assert( $product_status instanceof ApmProductStatus ); diff --git a/modules/ppcp-googlepay/src/Helper/ApmProductStatus.php b/modules/ppcp-googlepay/src/Helper/ApmProductStatus.php index 1da8379df..dbe812837 100644 --- a/modules/ppcp-googlepay/src/Helper/ApmProductStatus.php +++ b/modules/ppcp-googlepay/src/Helper/ApmProductStatus.php @@ -60,7 +60,6 @@ class ApmProductStatus extends ProductStatus { return $status_override; } - // Check if status was checked on previous requests. if ( $this->settings->has( self::SETTINGS_KEY ) && ( $this->settings->get( self::SETTINGS_KEY ) ) ) { return wc_string_to_bool( $this->settings->get( self::SETTINGS_KEY ) ); } diff --git a/modules/ppcp-settings/src/Endpoint/CommonRestEndpoint.php b/modules/ppcp-settings/src/Endpoint/CommonRestEndpoint.php index 35af6c093..e453a1a87 100644 --- a/modules/ppcp-settings/src/Endpoint/CommonRestEndpoint.php +++ b/modules/ppcp-settings/src/Endpoint/CommonRestEndpoint.php @@ -218,7 +218,7 @@ class CommonRestEndpoint extends RestEndpoint { if ( $this->settings->is_merchant_connected() ) { $extra_data['features'] = apply_filters( - 'woocommerce_paypal_payments_rest_common_merchant_data', + 'woocommerce_paypal_payments_rest_common_merchant_features', array(), ); } diff --git a/modules/ppcp-wc-gateway/src/WCGatewayModule.php b/modules/ppcp-wc-gateway/src/WCGatewayModule.php index 4885bdbf6..fa2c76cc8 100644 --- a/modules/ppcp-wc-gateway/src/WCGatewayModule.php +++ b/modules/ppcp-wc-gateway/src/WCGatewayModule.php @@ -550,7 +550,7 @@ class WCGatewayModule implements ServiceModule, ExtendingModule, ExecutableModul ); add_filter( - 'woocommerce_paypal_payments_rest_common_merchant_data', + 'woocommerce_paypal_payments_rest_common_merchant_features', static function ( array $features ) use ( $c ) : array { try { $billing_agreements_endpoint = $c->get( 'api.endpoint.billing-agreements' ); From 49665f680f41bfab10fb67d03b1c1fa378416fce Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Thu, 30 Jan 2025 18:37:01 +0100 Subject: [PATCH 19/37] =?UTF-8?q?=E2=9C=A8=20New=20Local=20APM=20product?= =?UTF-8?q?=20status=20check?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../services.php | 9 ++ .../src/LocalApmProductStatus.php | 95 +++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 modules/ppcp-local-alternative-payment-methods/src/LocalApmProductStatus.php diff --git a/modules/ppcp-local-alternative-payment-methods/services.php b/modules/ppcp-local-alternative-payment-methods/services.php index c0a66c11e..5408288c0 100644 --- a/modules/ppcp-local-alternative-payment-methods/services.php +++ b/modules/ppcp-local-alternative-payment-methods/services.php @@ -10,6 +10,7 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; +use WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods\LocalApmProductStatus; return array( 'ppcp-local-apms.url' => static function ( ContainerInterface $container ): string { @@ -67,6 +68,14 @@ return array( ), ); }, + 'ppcp-local-apms.product-status' => static function ( ContainerInterface $container ): LocalApmProductStatus { + return new LocalApmProductStatus( + $container->get( 'wcgateway.settings' ), + $container->get( 'api.endpoint.partners' ), + $container->get( 'settings.flag.is-connected' ), + $container->get( 'api.helper.failure-registry' ) + ); + }, 'ppcp-local-apms.bancontact.wc-gateway' => static function ( ContainerInterface $container ): BancontactGateway { return new BancontactGateway( $container->get( 'api.endpoint.orders' ), diff --git a/modules/ppcp-local-alternative-payment-methods/src/LocalApmProductStatus.php b/modules/ppcp-local-alternative-payment-methods/src/LocalApmProductStatus.php new file mode 100644 index 000000000..2a89146be --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/src/LocalApmProductStatus.php @@ -0,0 +1,95 @@ +settings = $settings; + } + + /** {@inheritDoc} */ + protected function check_local_state() : ?bool { + if ( $this->settings->has( self::SETTINGS_KEY ) && ( $this->settings->get( self::SETTINGS_KEY ) ) ) { + return wc_string_to_bool( $this->settings->get( self::SETTINGS_KEY ) ); + } + + return null; + } + + /** {@inheritDoc} */ + protected function check_active_state( SellerStatus $seller_status ) : bool { + $has_capability = false; + + foreach ( $seller_status->products() as $product ) { + if ( $product->name() === 'PAYMENT_METHODS' ) { + $has_capability = true; + break; + } + } + + if ( $has_capability ) { + $this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_ENABLED ); + } else { + $this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_DISABLED ); + } + $this->settings->persist(); + + return $has_capability; + } + + /** {@inheritDoc} */ + protected function clear_state( Settings $settings = null ) : void { + if ( null === $settings ) { + $settings = $this->settings; + } + + if ( $settings->has( self::SETTINGS_KEY ) ) { + $settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_UNDEFINED ); + $settings->persist(); + } + } +} From 44cb17f1cc0281bdf26a490621ccf18eeb1be0e1 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Thu, 30 Jan 2025 18:40:43 +0100 Subject: [PATCH 20/37] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20More=20robust=20feat?= =?UTF-8?q?ure=20checks=20in=20new=20UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ppcp-wc-gateway/src/WCGatewayModule.php | 71 ++++++------------- 1 file changed, 22 insertions(+), 49 deletions(-) diff --git a/modules/ppcp-wc-gateway/src/WCGatewayModule.php b/modules/ppcp-wc-gateway/src/WCGatewayModule.php index fa2c76cc8..f8b54f534 100644 --- a/modules/ppcp-wc-gateway/src/WCGatewayModule.php +++ b/modules/ppcp-wc-gateway/src/WCGatewayModule.php @@ -63,6 +63,7 @@ use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use WooCommerce\PayPalCommerce\WcGateway\Settings\WcTasks\Registrar\TaskRegistrarInterface; use WooCommerce\PayPalCommerce\WcGateway\Helper\DCCGatewayConfiguration; +use WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods\LocalApmProductStatus; /** * Class WcGatewayModule @@ -552,63 +553,35 @@ class WCGatewayModule implements ServiceModule, ExtendingModule, ExecutableModul add_filter( 'woocommerce_paypal_payments_rest_common_merchant_features', static function ( array $features ) use ( $c ) : array { - try { - $billing_agreements_endpoint = $c->get( 'api.endpoint.billing-agreements' ); - assert( $billing_agreements_endpoint instanceof BillingAgreementsEndpoint ); + $is_connected = $c->get( 'settings.flag.is-connected' ); - $reference_transactions_enabled = $billing_agreements_endpoint->reference_transaction_enabled(); - $features['save_paypal_and_venmo'] = array( - 'enabled' => $reference_transactions_enabled, - ); - } catch ( Exception $ex ) { - $features['save_paypal_and_venmo'] = array( - 'enabled' => false, - ); + if ( ! $is_connected ) { + return $features; } - try { - $dcc_product_status = $c->get( 'wcgateway.helper.dcc-product-status' ); - assert( $dcc_product_status instanceof DCCProductStatus ); - $dcc_enabled = $dcc_product_status->dcc_is_active(); - $features['advanced_credit_and_debit_cards'] = array( - 'enabled' => $dcc_enabled, - ); - } catch ( Exception $ex ) { - $features['advanced_credit_and_debit_cards'] = array( - 'enabled' => false, - ); - } + $billing_agreements_endpoint = $c->get( 'api.endpoint.billing-agreements' ); + assert( $billing_agreements_endpoint instanceof BillingAgreementsEndpoint ); - try { - // TODO: The `seller_status()` call throws a PayPalApiException. Why? - $partners_endpoint = $c->get( 'api.endpoint.partners' ); - assert( $partners_endpoint instanceof PartnersEndpoint ); - $seller_status = $partners_endpoint->seller_status(); + $dcc_product_status = $c->get( 'wcgateway.helper.dcc-product-status' ); + assert( $dcc_product_status instanceof DCCProductStatus ); - $apms_enabled = false; - foreach ( $seller_status->products() as $product ) { - if ( $product->name() === 'PAYMENT_METHODS' ) { - $apms_enabled = true; - break; - } - } + $apms_product_status = $c->get( 'ppcp-local-apms.product-status' ); + assert( $apms_product_status instanceof LocalApmProductStatus ); - $features['alternative_payment_methods'] = array( - 'enabled' => $apms_enabled, - ); + $features['save_paypal_and_venmo'] = array( + 'enabled' => $billing_agreements_endpoint->reference_transaction_enabled(), + ); - $features['pay_later_messaging'] = array( - 'enabled' => true, - ); - } catch ( Exception $ex ) { - $features['alternative_payment_methods'] = array( - 'enabled' => false, - ); + $features['advanced_credit_and_debit_cards'] = array( + 'enabled' => $dcc_product_status->is_active(), + ); - $features['pay_later_messaging'] = array( - 'enabled' => false, - ); - } + $features['alternative_payment_methods'] = array( + 'enabled' => $apms_product_status->is_active(), + ); + + // When local APMs are available, then PayLater messaging is also available. + $features['pay_later_messaging'] = $features['alternative_payment_methods']; return $features; } From 2387902a18a9e6bc42834585d01ad941836b661c Mon Sep 17 00:00:00 2001 From: carmenmaymo Date: Fri, 31 Jan 2025 10:46:16 +0100 Subject: [PATCH 21/37] Change UK to GB --- .../resources/js/utils/countryPriceInfo.js | 126 +++++++++--------- tests/PHPUnit/ApiClient/Entity/PayerTest.php | 10 +- 2 files changed, 68 insertions(+), 68 deletions(-) diff --git a/modules/ppcp-settings/resources/js/utils/countryPriceInfo.js b/modules/ppcp-settings/resources/js/utils/countryPriceInfo.js index c5cf52a3e..e32d8e6ce 100644 --- a/modules/ppcp-settings/resources/js/utils/countryPriceInfo.js +++ b/modules/ppcp-settings/resources/js/utils/countryPriceInfo.js @@ -2,139 +2,139 @@ export const countryPriceInfo = { US: { fixedFee: { USD: 0.49, - GBP: 0.39, - CAD: 0.59, - AUD: 0.59, - EUR: 0.39, + GBP: 0.39, + CAD: 0.59, + AUD: 0.59, + EUR: 0.39, }, checkout: 3.49, - plater: 4.99, - ccf: { - percentage: 2.59, - fixedFee: 0.29, - }, + plater: 4.99, + ccf: { + percentage: 2.59, + fixedFee: 0.29, + }, dw: { - percentage: 2.59, - fixedFee: 0.29, - }, + percentage: 2.59, + fixedFee: 0.29, + }, apm: { - percentage: 2.89, - fixedFee: 0.29, - }, - fast: { - percentage: 2.59, - fixedFee: 0.29, - }, + percentage: 2.89, + fixedFee: 0.29, + }, + fast: { + percentage: 2.59, + fixedFee: 0.29, + }, standardCardFields: 2.99, }, - UK: { + GB: { fixedFee: { GPB: 0.3, - USD: 0.3, - CAD: 0.3, - AUD: 0.3, - EUR: 0.35, + USD: 0.3, + CAD: 0.3, + AUD: 0.3, + EUR: 0.35, }, checkout: 2.9, - plater: 2.9, + plater: 2.9, ccf: 1.2, dw: 1.2, - fast: 1.2, + fast: 1.2, apm: 1.2, standardCardFields: 1.2, }, CA: { fixedFee: { CAD: 0.3, - USD: 0.3, - GBP: 0.2, - AUD: 0.3, - EUR: 0.35, + USD: 0.3, + GBP: 0.2, + AUD: 0.3, + EUR: 0.35, }, checkout: 2.9, ccf: 2.7, dw: 2.7, - fast: 2.7, + fast: 2.7, apm: 2.9, standardCardFields: 2.9, }, AU: { fixedFee: { AUD: 0.3, - USD: 0.3, - GBP: 0.2, - CAD: 0.3, - EUR: 0.35, + USD: 0.3, + GBP: 0.2, + CAD: 0.3, + EUR: 0.35, }, checkout: 2.6, - plater: 2.6, + plater: 2.6, ccf: 1.75, dw: 1.75, - fast: 1.75, + fast: 1.75, apm: 2.6, standardCardFields: 2.6, }, FR: { fixedFee: { EUR: 0.35, - USD: 0.3, - GBP: 0.3, - CAD: 0.3, - AUD: 0.3, + USD: 0.3, + GBP: 0.3, + CAD: 0.3, + AUD: 0.3, }, checkout: 2.9, - plater: 2.9, + plater: 2.9, ccf: 1.2, dw: 1.2, - fast: 1.2, + fast: 1.2, apm: 1.2, standardCardFields: 1.2, }, IT: { fixedFee: { - EUR: 0.35, - USD: 0.3, - GBP: 0.3, - CAD: 0.3, - AUD: 0.3, + EUR: 0.35, + USD: 0.3, + GBP: 0.3, + CAD: 0.3, + AUD: 0.3, }, checkout: 3.4, - plater: 3.4, + plater: 3.4, ccf: 1.2, dw: 1.2, - fast: 1.2, + fast: 1.2, apm: 1.2, standardCardFields: 1.2, }, DE: { fixedFee: { EUR: 0.39, - USD: 0.49, - GBP: 0.29, - CAD: 0.59, - AUD: 0.59, + USD: 0.49, + GBP: 0.29, + CAD: 0.59, + AUD: 0.59, }, checkout: 2.99, - plater: 2.99, + plater: 2.99, ccf: 2.99, dw: 2.99, - fast: 2.99, + fast: 2.99, apm: 2.99, standardCardFields: 2.99, }, ES: { fixedFee: { - EUR: 0.35, - USD: 0.3, - GBP: 0.3, - CAD: 0.3, - AUD: 0.3, + EUR: 0.35, + USD: 0.3, + GBP: 0.3, + CAD: 0.3, + AUD: 0.3, }, checkout: 2.9, - plater: 2.9, + plater: 2.9, ccf: 1.2, dw: 1.2, - fast: 1.2, + fast: 1.2, apm: 1.2, standardCardFields: 1.2, }, diff --git a/tests/PHPUnit/ApiClient/Entity/PayerTest.php b/tests/PHPUnit/ApiClient/Entity/PayerTest.php index affdc206d..9efc603d5 100644 --- a/tests/PHPUnit/ApiClient/Entity/PayerTest.php +++ b/tests/PHPUnit/ApiClient/Entity/PayerTest.php @@ -18,7 +18,7 @@ class PayerTest extends TestCase ->andReturn(['address']); $address ->expects('country_code') - ->andReturn('UK'); + ->andReturn('GB'); $phone = Mockery::mock(PhoneWithType::class); $phone ->expects('to_array') @@ -70,7 +70,7 @@ class PayerTest extends TestCase ->andReturn(['address']); $address ->expects('country_code') - ->andReturn('UK'); + ->andReturn('GB'); $phone = Mockery::mock(PhoneWithType::class); $phone ->expects('to_array') @@ -110,7 +110,7 @@ class PayerTest extends TestCase ->andReturn(['address']); $address ->expects('country_code') - ->andReturn('UK'); + ->andReturn('GB'); $phone = null; $taxInfo = Mockery::mock(PayerTaxInfo::class); $taxInfo @@ -147,7 +147,7 @@ class PayerTest extends TestCase ->andReturn(['address']); $address ->expects('country_code') - ->andReturn('UK'); + ->andReturn('GB'); $phone = Mockery::mock(PhoneWithType::class); $phone ->expects('to_array') @@ -184,7 +184,7 @@ class PayerTest extends TestCase ->andReturn(['address']); $address ->expects('country_code') - ->andReturn('UK'); + ->andReturn('GB'); $phone = Mockery::mock(PhoneWithType::class); $phone ->expects('to_array') From 401e2556567522c79a91e04d40d8fd154c0f2aab Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Mon, 3 Feb 2025 12:02:30 +0100 Subject: [PATCH 22/37] =?UTF-8?q?=F0=9F=94=A7=20Add=20settings-mapping=20f?= =?UTF-8?q?or=20=E2=80=9Cmerchant=5Fid=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ppcp-compat/services.php | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/ppcp-compat/services.php b/modules/ppcp-compat/services.php index 7982366e0..e5f6bcd74 100644 --- a/modules/ppcp-compat/services.php +++ b/modules/ppcp-compat/services.php @@ -145,6 +145,7 @@ return array( * the credentials are used for. */ array( + 'merchant_id' => 'merchant_id', 'is_sandbox' => 'sandbox_merchant', 'live_client_id' => 'client_id', 'live_client_secret' => 'client_secret', From 3d185090e26bdd9aac3779077f89aee867486bde Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Mon, 3 Feb 2025 12:06:12 +0100 Subject: [PATCH 23/37] =?UTF-8?q?=F0=9F=90=9B=20Cache=20the=20SellerStatus?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/Helper/ProductStatus.php | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/modules/ppcp-api-client/src/Helper/ProductStatus.php b/modules/ppcp-api-client/src/Helper/ProductStatus.php index eeda4ad22..bab84ed24 100644 --- a/modules/ppcp-api-client/src/Helper/ProductStatus.php +++ b/modules/ppcp-api-client/src/Helper/ProductStatus.php @@ -22,6 +22,14 @@ use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; * Base class to check the eligibility of a product for the current merchant. */ abstract class ProductStatus { + /** + * Caches the SellerStatus API response to avoid duplicate API calls + * during the same request. + * + * @var ?SellerStatus + */ + private static ?SellerStatus $seller_status = null; + /** * The current status stored in memory. * @@ -147,19 +155,21 @@ abstract class ProductStatus { /** * Fetches the seller-status object from the PayPal merchant API. * - * TODO: We might cache the SellerStatus, as it's usually accessed multiple times during one request. - * * @return SellerStatus * @throws RuntimeException When the check failed. */ protected function get_seller_status_object() : SellerStatus { - // Check API failure registry to prevent multiple failed API requests. - if ( $this->api_failure_registry->has_failure_in_timeframe( FailureRegistry::SELLER_STATUS_KEY, HOUR_IN_SECONDS ) ) { - throw new RuntimeException( 'Timeout for re-check not reached yet' ); + if ( null === self::$seller_status ) { + // Check API failure registry to prevent multiple failed API requests. + if ( $this->api_failure_registry->has_failure_in_timeframe( FailureRegistry::SELLER_STATUS_KEY, MINUTE_IN_SECONDS ) ) { + throw new RuntimeException( 'Timeout for re-check not reached yet' ); + } + + // Request seller status via PayPal API, might throw an Exception. + self::$seller_status = $this->partners_endpoint->seller_status(); } - // Request seller status via PayPal API, might throw an Exception. - return $this->partners_endpoint->seller_status(); + return self::$seller_status; } /** From d186677a581ea53adf37cc56b89b7090f724d14c Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Mon, 3 Feb 2025 12:37:34 +0100 Subject: [PATCH 24/37] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Simplify=20settings-?= =?UTF-8?q?map?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ppcp-compat/services.php | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/modules/ppcp-compat/services.php b/modules/ppcp-compat/services.php index e5f6bcd74..91370dff0 100644 --- a/modules/ppcp-compat/services.php +++ b/modules/ppcp-compat/services.php @@ -128,13 +128,6 @@ return array( } return array( - new SettingsMap( - $container->get( 'settings.data.general' ), - array( - 'client_id' => 'client_id', - 'client_secret' => 'client_secret', - ) - ), new SettingsMap( $container->get( 'settings.data.general' ), /** @@ -146,6 +139,8 @@ return array( */ array( 'merchant_id' => 'merchant_id', + 'client_id' => 'client_id', + 'client_secret' => 'client_secret', 'is_sandbox' => 'sandbox_merchant', 'live_client_id' => 'client_id', 'live_client_secret' => 'client_secret', From 90d2c77a5a37fdc7f86900718f70c25091b49894 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Mon, 3 Feb 2025 13:34:30 +0100 Subject: [PATCH 25/37] =?UTF-8?q?=F0=9F=9A=9A=20Extract=20Environment=20cl?= =?UTF-8?q?ass=20to=20gateway=20module?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ppcp-applepay/extensions.php | 2 +- modules/ppcp-applepay/services.php | 2 +- modules/ppcp-applepay/src/ApplepayModule.php | 2 +- modules/ppcp-axo-block/src/AxoBlockPaymentMethod.php | 2 +- modules/ppcp-axo/src/Assets/AxoManager.php | 2 +- modules/ppcp-axo/src/Gateway/AxoGateway.php | 2 +- modules/ppcp-button/services.php | 2 +- modules/ppcp-button/src/Assets/SmartButton.php | 2 +- modules/ppcp-googlepay/services.php | 2 +- modules/ppcp-googlepay/src/Assets/Button.php | 2 +- .../ppcp-onboarding/src/Assets/OnboardingAssets.php | 2 +- .../src/PayPalSubscriptionsModule.php | 2 +- .../ppcp-vaulting/src/VaultedCreditCardHandler.php | 2 +- modules/ppcp-wc-gateway/extensions.php | 2 +- modules/ppcp-wc-gateway/services.php | 2 +- modules/ppcp-wc-gateway/src/Assets/FraudNetAssets.php | 2 +- .../ppcp-wc-gateway/src/Assets/SettingsPageAssets.php | 2 +- .../ppcp-wc-gateway/src/Gateway/CardButtonGateway.php | 3 +-- .../ppcp-wc-gateway/src/Gateway/CreditCardGateway.php | 2 +- .../ppcp-wc-gateway/src/Gateway/OXXO/OXXOGateway.php | 2 +- modules/ppcp-wc-gateway/src/Gateway/PayPalGateway.php | 2 +- .../Gateway/PayUponInvoice/PayUponInvoiceGateway.php | 2 +- .../src/Helper}/Environment.php | 11 +++++------ .../ppcp-wc-gateway/src/Processor/OrderMetaTrait.php | 2 +- .../ppcp-wc-gateway/src/Processor/OrderProcessor.php | 2 +- .../src/Settings/Fields/connection-tab-fields.php | 2 +- modules/ppcp-wc-subscriptions/src/RenewalHandler.php | 2 +- .../src/Status/Assets/WebhooksStatusPageAssets.php | 2 +- 28 files changed, 32 insertions(+), 34 deletions(-) rename modules/{ppcp-onboarding/src => ppcp-wc-gateway/src/Helper}/Environment.php (79%) diff --git a/modules/ppcp-applepay/extensions.php b/modules/ppcp-applepay/extensions.php index 5eb6e47d6..53068c506 100644 --- a/modules/ppcp-applepay/extensions.php +++ b/modules/ppcp-applepay/extensions.php @@ -10,7 +10,7 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Applepay; use WooCommerce\PayPalCommerce\Applepay\Assets\PropertiesDictionary; -use WooCommerce\PayPalCommerce\Onboarding\Environment; +use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use WooCommerce\PayPalCommerce\WcGateway\Helper\DisplayManager; diff --git a/modules/ppcp-applepay/services.php b/modules/ppcp-applepay/services.php index 963891f48..feb087731 100644 --- a/modules/ppcp-applepay/services.php +++ b/modules/ppcp-applepay/services.php @@ -19,7 +19,7 @@ use WooCommerce\PayPalCommerce\Applepay\Assets\PropertiesDictionary; use WooCommerce\PayPalCommerce\Applepay\Helper\ApmApplies; use WooCommerce\PayPalCommerce\Applepay\Helper\AvailabilityNotice; use WooCommerce\PayPalCommerce\Common\Pattern\SingletonDecorator; -use WooCommerce\PayPalCommerce\Onboarding\Environment; +use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; diff --git a/modules/ppcp-applepay/src/ApplepayModule.php b/modules/ppcp-applepay/src/ApplepayModule.php index ea58b4d89..8015e0a4d 100644 --- a/modules/ppcp-applepay/src/ApplepayModule.php +++ b/modules/ppcp-applepay/src/ApplepayModule.php @@ -17,7 +17,7 @@ use WooCommerce\PayPalCommerce\Applepay\Assets\PropertiesDictionary; use WooCommerce\PayPalCommerce\Button\Assets\ButtonInterface; use WooCommerce\PayPalCommerce\Button\Assets\SmartButtonInterface; use WooCommerce\PayPalCommerce\Applepay\Helper\AvailabilityNotice; -use WooCommerce\PayPalCommerce\Onboarding\Environment; +use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule; use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; diff --git a/modules/ppcp-axo-block/src/AxoBlockPaymentMethod.php b/modules/ppcp-axo-block/src/AxoBlockPaymentMethod.php index 78bafdae3..db4d5438e 100644 --- a/modules/ppcp-axo-block/src/AxoBlockPaymentMethod.php +++ b/modules/ppcp-axo-block/src/AxoBlockPaymentMethod.php @@ -13,7 +13,7 @@ use WC_Payment_Gateway; use Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType; use WooCommerce\PayPalCommerce\Axo\FrontendLoggerEndpoint; use WooCommerce\PayPalCommerce\Button\Assets\SmartButtonInterface; -use WooCommerce\PayPalCommerce\Onboarding\Environment; +use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; use WooCommerce\PayPalCommerce\Axo\Gateway\AxoGateway; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; use WooCommerce\PayPalCommerce\WcGateway\Helper\DCCGatewayConfiguration; diff --git a/modules/ppcp-axo/src/Assets/AxoManager.php b/modules/ppcp-axo/src/Assets/AxoManager.php index d02e27355..0263adb3c 100644 --- a/modules/ppcp-axo/src/Assets/AxoManager.php +++ b/modules/ppcp-axo/src/Assets/AxoManager.php @@ -12,7 +12,7 @@ namespace WooCommerce\PayPalCommerce\Axo\Assets; use Psr\Log\LoggerInterface; use WooCommerce\PayPalCommerce\ApiClient\Helper\CurrencyGetter; use WooCommerce\PayPalCommerce\Axo\FrontendLoggerEndpoint; -use WooCommerce\PayPalCommerce\Onboarding\Environment; +use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; use WooCommerce\PayPalCommerce\Session\SessionHandler; use WooCommerce\PayPalCommerce\WcGateway\Helper\SettingsStatus; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; diff --git a/modules/ppcp-axo/src/Gateway/AxoGateway.php b/modules/ppcp-axo/src/Gateway/AxoGateway.php index cd0ec8579..3f699a44a 100644 --- a/modules/ppcp-axo/src/Gateway/AxoGateway.php +++ b/modules/ppcp-axo/src/Gateway/AxoGateway.php @@ -19,7 +19,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentSource; use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\ShippingPreferenceFactory; use WooCommerce\PayPalCommerce\ApiClient\Entity\Order; -use WooCommerce\PayPalCommerce\Onboarding\Environment; +use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use WooCommerce\PayPalCommerce\WcGateway\Gateway\GatewaySettingsRendererTrait; use WooCommerce\PayPalCommerce\WcGateway\Gateway\TransactionUrlProvider; diff --git a/modules/ppcp-button/services.php b/modules/ppcp-button/services.php index 6844a08d0..5a489d330 100644 --- a/modules/ppcp-button/services.php +++ b/modules/ppcp-button/services.php @@ -35,7 +35,7 @@ use WooCommerce\PayPalCommerce\Button\Exception\RuntimeException; use WooCommerce\PayPalCommerce\Button\Helper\EarlyOrderHandler; use WooCommerce\PayPalCommerce\Button\Helper\MessagesApply; use WooCommerce\PayPalCommerce\Button\Helper\ThreeDSecure; -use WooCommerce\PayPalCommerce\Onboarding\Environment; +use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\WcGateway\Helper\SettingsStatus; use WooCommerce\PayPalCommerce\WcGateway\Helper\DCCGatewayConfiguration; diff --git a/modules/ppcp-button/src/Assets/SmartButton.php b/modules/ppcp-button/src/Assets/SmartButton.php index fd1b93404..81ced3a68 100644 --- a/modules/ppcp-button/src/Assets/SmartButton.php +++ b/modules/ppcp-button/src/Assets/SmartButton.php @@ -36,7 +36,7 @@ use WooCommerce\PayPalCommerce\Button\Endpoint\ValidateCheckoutEndpoint; use WooCommerce\PayPalCommerce\Button\Helper\ContextTrait; use WooCommerce\PayPalCommerce\Button\Helper\DisabledFundingSources; use WooCommerce\PayPalCommerce\Button\Helper\MessagesApply; -use WooCommerce\PayPalCommerce\Onboarding\Environment; +use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; use WooCommerce\PayPalCommerce\PayLaterBlock\PayLaterBlockModule; use WooCommerce\PayPalCommerce\PayLaterWCBlocks\PayLaterWCBlocksModule; use WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint\CreatePaymentToken; diff --git a/modules/ppcp-googlepay/services.php b/modules/ppcp-googlepay/services.php index 18c48f3ad..f92aa0bd8 100644 --- a/modules/ppcp-googlepay/services.php +++ b/modules/ppcp-googlepay/services.php @@ -18,7 +18,7 @@ use WooCommerce\PayPalCommerce\Googlepay\Endpoint\UpdatePaymentDataEndpoint; use WooCommerce\PayPalCommerce\Googlepay\Helper\ApmApplies; use WooCommerce\PayPalCommerce\Googlepay\Helper\ApmProductStatus; use WooCommerce\PayPalCommerce\Googlepay\Helper\AvailabilityNotice; -use WooCommerce\PayPalCommerce\Onboarding\Environment; +use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; diff --git a/modules/ppcp-googlepay/src/Assets/Button.php b/modules/ppcp-googlepay/src/Assets/Button.php index 1d85b982f..f3ff90611 100644 --- a/modules/ppcp-googlepay/src/Assets/Button.php +++ b/modules/ppcp-googlepay/src/Assets/Button.php @@ -16,7 +16,7 @@ use WooCommerce\PayPalCommerce\Button\Assets\ButtonInterface; use WooCommerce\PayPalCommerce\Button\Helper\ContextTrait; use WooCommerce\PayPalCommerce\Googlepay\Endpoint\UpdatePaymentDataEndpoint; use WooCommerce\PayPalCommerce\Googlepay\GooglePayGateway; -use WooCommerce\PayPalCommerce\Onboarding\Environment; +use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; use WooCommerce\PayPalCommerce\Session\SessionHandler; use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException; use WooCommerce\PayPalCommerce\WcGateway\Helper\SettingsStatus; diff --git a/modules/ppcp-onboarding/src/Assets/OnboardingAssets.php b/modules/ppcp-onboarding/src/Assets/OnboardingAssets.php index 663bdfee1..959aad775 100644 --- a/modules/ppcp-onboarding/src/Assets/OnboardingAssets.php +++ b/modules/ppcp-onboarding/src/Assets/OnboardingAssets.php @@ -11,7 +11,7 @@ namespace WooCommerce\PayPalCommerce\Onboarding\Assets; use WooCommerce\PayPalCommerce\Onboarding\Endpoint\LoginSellerEndpoint; use WooCommerce\PayPalCommerce\Onboarding\Endpoint\UpdateSignupLinksEndpoint; -use WooCommerce\PayPalCommerce\Onboarding\Environment; +use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; diff --git a/modules/ppcp-paypal-subscriptions/src/PayPalSubscriptionsModule.php b/modules/ppcp-paypal-subscriptions/src/PayPalSubscriptionsModule.php index 48c3a71af..0d55965f7 100644 --- a/modules/ppcp-paypal-subscriptions/src/PayPalSubscriptionsModule.php +++ b/modules/ppcp-paypal-subscriptions/src/PayPalSubscriptionsModule.php @@ -21,7 +21,7 @@ use WC_Subscriptions_Product; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingSubscriptions; use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; -use WooCommerce\PayPalCommerce\Onboarding\Environment; +use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule; use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; diff --git a/modules/ppcp-vaulting/src/VaultedCreditCardHandler.php b/modules/ppcp-vaulting/src/VaultedCreditCardHandler.php index 3261e4b8e..134d9f4e7 100644 --- a/modules/ppcp-vaulting/src/VaultedCreditCardHandler.php +++ b/modules/ppcp-vaulting/src/VaultedCreditCardHandler.php @@ -18,7 +18,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; use WooCommerce\PayPalCommerce\ApiClient\Factory\PayerFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\ShippingPreferenceFactory; -use WooCommerce\PayPalCommerce\Onboarding\Environment; +use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; use WooCommerce\PayPalCommerce\WcSubscriptions\FreeTrialHandlerTrait; use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor; diff --git a/modules/ppcp-wc-gateway/extensions.php b/modules/ppcp-wc-gateway/extensions.php index fe2de006b..77fea0abd 100644 --- a/modules/ppcp-wc-gateway/extensions.php +++ b/modules/ppcp-wc-gateway/extensions.php @@ -9,7 +9,7 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\WcGateway; -use WooCommerce\PayPalCommerce\Onboarding\Environment; +use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; use WooCommerce\WooCommerce\Logging\Logger\NullLogger; use WooCommerce\WooCommerce\Logging\Logger\WooCommerceLogger; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index 459dc8b1b..1bff438dd 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -21,7 +21,7 @@ use WooCommerce\PayPalCommerce\Axo\Gateway\AxoGateway; use WooCommerce\PayPalCommerce\Button\Helper\MessagesDisclaimers; use WooCommerce\PayPalCommerce\Common\Pattern\SingletonDecorator; use WooCommerce\PayPalCommerce\Googlepay\GooglePayGateway; -use WooCommerce\PayPalCommerce\Onboarding\Environment; +use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingOptionsRenderer; use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\Settings\SettingsModule; diff --git a/modules/ppcp-wc-gateway/src/Assets/FraudNetAssets.php b/modules/ppcp-wc-gateway/src/Assets/FraudNetAssets.php index 074a57c2e..3ee217887 100644 --- a/modules/ppcp-wc-gateway/src/Assets/FraudNetAssets.php +++ b/modules/ppcp-wc-gateway/src/Assets/FraudNetAssets.php @@ -10,7 +10,7 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\WcGateway\Assets; use WooCommerce\PayPalCommerce\Button\Helper\ContextTrait; -use WooCommerce\PayPalCommerce\Onboarding\Environment; +use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; use WooCommerce\PayPalCommerce\Session\SessionHandler; use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException; use WooCommerce\PayPalCommerce\WcGateway\FraudNet\FraudNet; diff --git a/modules/ppcp-wc-gateway/src/Assets/SettingsPageAssets.php b/modules/ppcp-wc-gateway/src/Assets/SettingsPageAssets.php index bfda515ac..4ab12b13b 100644 --- a/modules/ppcp-wc-gateway/src/Assets/SettingsPageAssets.php +++ b/modules/ppcp-wc-gateway/src/Assets/SettingsPageAssets.php @@ -11,7 +11,7 @@ namespace WooCommerce\PayPalCommerce\WcGateway\Assets; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingAgreementsEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Helper\CurrencyGetter; -use WooCommerce\PayPalCommerce\Onboarding\Environment; +use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; use WooCommerce\PayPalCommerce\WcGateway\Endpoint\RefreshFeatureStatusEndpoint; use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; diff --git a/modules/ppcp-wc-gateway/src/Gateway/CardButtonGateway.php b/modules/ppcp-wc-gateway/src/Gateway/CardButtonGateway.php index ffb0fe55c..846f8e7e3 100644 --- a/modules/ppcp-wc-gateway/src/Gateway/CardButtonGateway.php +++ b/modules/ppcp-wc-gateway/src/Gateway/CardButtonGateway.php @@ -13,8 +13,7 @@ use Exception; use Psr\Log\LoggerInterface; use WC_Order; use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException; -use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; -use WooCommerce\PayPalCommerce\Onboarding\Environment; +use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\Session\SessionHandler; use WooCommerce\PayPalCommerce\WcSubscriptions\FreeTrialHandlerTrait; diff --git a/modules/ppcp-wc-gateway/src/Gateway/CreditCardGateway.php b/modules/ppcp-wc-gateway/src/Gateway/CreditCardGateway.php index a5e897548..7a41a40ef 100644 --- a/modules/ppcp-wc-gateway/src/Gateway/CreditCardGateway.php +++ b/modules/ppcp-wc-gateway/src/Gateway/CreditCardGateway.php @@ -18,7 +18,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentsEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokensEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; -use WooCommerce\PayPalCommerce\Onboarding\Environment; +use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\Session\SessionHandler; use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository; diff --git a/modules/ppcp-wc-gateway/src/Gateway/OXXO/OXXOGateway.php b/modules/ppcp-wc-gateway/src/Gateway/OXXO/OXXOGateway.php index 009018558..dfc2d6a24 100644 --- a/modules/ppcp-wc-gateway/src/Gateway/OXXO/OXXOGateway.php +++ b/modules/ppcp-wc-gateway/src/Gateway/OXXO/OXXOGateway.php @@ -17,7 +17,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\ShippingPreferenceFactory; -use WooCommerce\PayPalCommerce\Onboarding\Environment; +use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; use WooCommerce\PayPalCommerce\WcGateway\Gateway\TransactionUrlProvider; use WooCommerce\PayPalCommerce\WcGateway\Processor\OrderMetaTrait; diff --git a/modules/ppcp-wc-gateway/src/Gateway/PayPalGateway.php b/modules/ppcp-wc-gateway/src/Gateway/PayPalGateway.php index 5ffbeec9d..192955d80 100644 --- a/modules/ppcp-wc-gateway/src/Gateway/PayPalGateway.php +++ b/modules/ppcp-wc-gateway/src/Gateway/PayPalGateway.php @@ -18,7 +18,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokensEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Entity\OrderStatus; use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentToken; use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException; -use WooCommerce\PayPalCommerce\Onboarding\Environment; +use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\Session\SessionHandler; use WooCommerce\PayPalCommerce\Vaulting\WooCommercePaymentTokens; diff --git a/modules/ppcp-wc-gateway/src/Gateway/PayUponInvoice/PayUponInvoiceGateway.php b/modules/ppcp-wc-gateway/src/Gateway/PayUponInvoice/PayUponInvoiceGateway.php index dbd6629bd..ecd6c1df1 100644 --- a/modules/ppcp-wc-gateway/src/Gateway/PayUponInvoice/PayUponInvoiceGateway.php +++ b/modules/ppcp-wc-gateway/src/Gateway/PayUponInvoice/PayUponInvoiceGateway.php @@ -16,7 +16,7 @@ use WC_Payment_Gateway; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PayUponInvoiceOrderEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException; use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory; -use WooCommerce\PayPalCommerce\Onboarding\Environment; +use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\WcGateway\Gateway\TransactionUrlProvider; use WooCommerce\PayPalCommerce\WcGateway\Helper\CheckoutHelper; diff --git a/modules/ppcp-onboarding/src/Environment.php b/modules/ppcp-wc-gateway/src/Helper/Environment.php similarity index 79% rename from modules/ppcp-onboarding/src/Environment.php rename to modules/ppcp-wc-gateway/src/Helper/Environment.php index 9bd136ed0..9c4599333 100644 --- a/modules/ppcp-onboarding/src/Environment.php +++ b/modules/ppcp-wc-gateway/src/Helper/Environment.php @@ -1,13 +1,13 @@ Date: Mon, 3 Feb 2025 13:36:45 +0100 Subject: [PATCH 26/37] =?UTF-8?q?=E2=9C=A8=20Create=20new=20environment=20?= =?UTF-8?q?detection=20helper=20methods?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/Helper/Environment.php | 37 ++++++++++++++++--- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/modules/ppcp-wc-gateway/src/Helper/Environment.php b/modules/ppcp-wc-gateway/src/Helper/Environment.php index 9c4599333..a603e9179 100644 --- a/modules/ppcp-wc-gateway/src/Helper/Environment.php +++ b/modules/ppcp-wc-gateway/src/Helper/Environment.php @@ -5,7 +5,7 @@ * @package WooCommerce\PayPalCommerce\WcGateway\Helper */ -declare(strict_types=1); +declare( strict_types = 1 ); namespace WooCommerce\PayPalCommerce\WcGateway\Helper; @@ -16,20 +16,27 @@ use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; */ class Environment { + /** + * Name of the production environment. + */ public const PRODUCTION = 'production'; - public const SANDBOX = 'sandbox'; + + /** + * Name of the sandbox environment. + */ + public const SANDBOX = 'sandbox'; /** * The Settings. * * @var ContainerInterface */ - private $settings; + private ContainerInterface $settings; /** * Environment constructor. * - * @param ContainerInterface $settings The Settings. + * @param ContainerInterface $settings The settings. */ public function __construct( ContainerInterface $settings ) { $this->settings = $settings; @@ -40,7 +47,7 @@ class Environment { * * @return string */ - public function current_environment(): string { + public function current_environment() : string { return ( $this->settings->has( 'sandbox_on' ) && $this->settings->get( 'sandbox_on' ) ) ? self::SANDBOX : self::PRODUCTION; @@ -53,7 +60,25 @@ class Environment { * * @return bool */ - public function current_environment_is( string $environment ): bool { + public function current_environment_is( string $environment ) : bool { return $this->current_environment() === $environment; } + + /** + * Returns whether the current environment is sandbox. + * + * @return bool + */ + public function is_sandbox() : bool { + return $this->current_environment_is( self::SANDBOX ); + } + + /** + * Returns whether the current environment is production. + * + * @return bool + */ + public function is_production() : bool { + return $this->current_environment_is( self::PRODUCTION ); + } } From d6310f30827f3b0b7761c43bae8ce6da584b291b Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Mon, 3 Feb 2025 13:38:12 +0100 Subject: [PATCH 27/37] =?UTF-8?q?=E2=9C=A8=20Support=20Environment=20objec?= =?UTF-8?q?t=20in=20EnvironmentConfig?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ppcp-wc-gateway/src/Helper/EnvironmentConfig.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/modules/ppcp-wc-gateway/src/Helper/EnvironmentConfig.php b/modules/ppcp-wc-gateway/src/Helper/EnvironmentConfig.php index 1542de783..c05776603 100644 --- a/modules/ppcp-wc-gateway/src/Helper/EnvironmentConfig.php +++ b/modules/ppcp-wc-gateway/src/Helper/EnvironmentConfig.php @@ -70,10 +70,14 @@ class EnvironmentConfig { /** * Get the value for the specified environment. * - * @param bool $for_sandbox Whether to get the sandbox value. + * @param bool|Environment $for_sandbox Whether to get the sandbox value. * @return T The value for the specified environment. */ - public function get_value( bool $for_sandbox = false ) { + public function get_value( $for_sandbox = false ) { + if ( $for_sandbox instanceof Environment ) { + return $for_sandbox->is_sandbox() ? $this->sandbox_value : $this->production_value; + } + return $for_sandbox ? $this->sandbox_value : $this->production_value; } } From 5c7fc56d127a7b0610818967311a4d1c06220275 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Mon, 3 Feb 2025 13:39:16 +0100 Subject: [PATCH 28/37] =?UTF-8?q?=F0=9F=90=9B=20Add=20missing=20`use`=20st?= =?UTF-8?q?atement?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ppcp-onboarding/services.php | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/ppcp-onboarding/services.php b/modules/ppcp-onboarding/services.php index 85f3d4219..c1bccbba1 100644 --- a/modules/ppcp-onboarding/services.php +++ b/modules/ppcp-onboarding/services.php @@ -20,6 +20,7 @@ use WooCommerce\PayPalCommerce\Onboarding\Endpoint\LoginSellerEndpoint; use WooCommerce\PayPalCommerce\Onboarding\Endpoint\UpdateSignupLinksEndpoint; use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingSendOnlyNoticeRenderer; use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingRenderer; +use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; return array( 'api.sandbox-host' => static function ( ContainerInterface $container ): string { From 0b77ff9e55739abf79dff6da33c0fe4aec00c0cf Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Mon, 3 Feb 2025 13:40:12 +0100 Subject: [PATCH 29/37] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Extract=20bearer-log?= =?UTF-8?q?ic=20from=20onboarding=20module?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ppcp-api-client/services.php | 6 ++++++ modules/ppcp-onboarding/services.php | 31 ---------------------------- 2 files changed, 6 insertions(+), 31 deletions(-) diff --git a/modules/ppcp-api-client/services.php b/modules/ppcp-api-client/services.php index b2f489da5..244690926 100644 --- a/modules/ppcp-api-client/services.php +++ b/modules/ppcp-api-client/services.php @@ -116,6 +116,12 @@ return array( return 'WC-'; }, 'api.bearer' => static function ( ContainerInterface $container ): Bearer { + $is_connected = $container->get( 'settings.flag.is-connected' ); + + if ( ! $is_connected ) { + return new ConnectBearer(); + } + return new PayPalBearer( $container->get( 'api.paypal-bearer-cache' ), $container->get( 'api.host' ), diff --git a/modules/ppcp-onboarding/services.php b/modules/ppcp-onboarding/services.php index c1bccbba1..8198f3a7c 100644 --- a/modules/ppcp-onboarding/services.php +++ b/modules/ppcp-onboarding/services.php @@ -11,9 +11,6 @@ namespace WooCommerce\PayPalCommerce\Onboarding; use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingOptionsRenderer; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; -use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer; -use WooCommerce\PayPalCommerce\ApiClient\Authentication\ConnectBearer; -use WooCommerce\PayPalCommerce\ApiClient\Authentication\PayPalBearer; use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache; use WooCommerce\PayPalCommerce\Onboarding\Assets\OnboardingAssets; use WooCommerce\PayPalCommerce\Onboarding\Endpoint\LoginSellerEndpoint; @@ -86,34 +83,6 @@ return array( return $container->get( 'api.paypal-website-url-production' ); }, - - 'api.bearer' => static function ( ContainerInterface $container ): Bearer { - - $state = $container->get( 'onboarding.state' ); - - /** - * The State. - * - * @var State $state - */ - if ( $state->current_state() < State::STATE_ONBOARDED ) { - return new ConnectBearer(); - } - $cache = new Cache( 'ppcp-paypal-bearer' ); - $key = $container->get( 'api.key' ); - $secret = $container->get( 'api.secret' ); - $host = $container->get( 'api.host' ); - $logger = $container->get( 'woocommerce.logger.woocommerce' ); - $settings = $container->get( 'wcgateway.settings' ); - return new PayPalBearer( - $cache, - $host, - $key, - $secret, - $logger, - $settings - ); - }, 'onboarding.state' => function( ContainerInterface $container ) : State { $settings = $container->get( 'wcgateway.settings' ); return new State( $settings ); From 81ca5dd00e646b89d601331e3853ad32b6258abd Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Mon, 3 Feb 2025 13:42:26 +0100 Subject: [PATCH 30/37] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Use=20cache=20servic?= =?UTF-8?q?e=20instead=20of=20direct=20creation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ppcp-api-client/services.php | 2 +- modules/ppcp-onboarding/services.php | 4 ++-- modules/ppcp-wc-gateway/services.php | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/ppcp-api-client/services.php b/modules/ppcp-api-client/services.php index 244690926..bee10d72f 100644 --- a/modules/ppcp-api-client/services.php +++ b/modules/ppcp-api-client/services.php @@ -817,7 +817,7 @@ return array( return new OrderHelper(); }, 'api.helper.order-transient' => static function( ContainerInterface $container ): OrderTransient { - $cache = new Cache( 'ppcp-paypal-bearer' ); + $cache = $container->get( 'api.paypal-bearer-cache' ); $purchase_unit_sanitizer = $container->get( 'api.helper.purchase-unit-sanitizer' ); return new OrderTransient( $cache, $purchase_unit_sanitizer ); }, diff --git a/modules/ppcp-onboarding/services.php b/modules/ppcp-onboarding/services.php index 8198f3a7c..7756b69db 100644 --- a/modules/ppcp-onboarding/services.php +++ b/modules/ppcp-onboarding/services.php @@ -129,8 +129,8 @@ return array( $login_seller_sandbox = $container->get( 'api.endpoint.login-seller-sandbox' ); $partner_referrals_data = $container->get( 'api.repository.partner-referrals-data' ); $settings = $container->get( 'wcgateway.settings' ); - $cache = new Cache( 'ppcp-paypal-bearer' ); - $logger = $container->get( 'woocommerce.logger.woocommerce' ); + $cache = $container->get( 'api.paypal-bearer-cache' ); + $logger = $container->get( 'woocommerce.logger.woocommerce' ); return new LoginSellerEndpoint( $request_data, $login_seller_production, diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index 1bff438dd..77c6438e3 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -570,10 +570,10 @@ return array( $settings = $container->get( 'wcgateway.settings' ); $fields = $container->get( 'wcgateway.settings.fields' ); $webhook_registrar = $container->get( 'webhook.registrar' ); - $state = $container->get( 'onboarding.state' ); - $cache = new Cache( 'ppcp-paypal-bearer' ); - $bearer = $container->get( 'api.bearer' ); - $page_id = $container->get( 'wcgateway.current-ppcp-settings-page-id' ); + $state = $container->get( 'onboarding.state' ); + $cache = $container->get( 'api.paypal-bearer-cache' ); + $bearer = $container->get( 'api.bearer' ); + $page_id = $container->get( 'wcgateway.current-ppcp-settings-page-id' ); $signup_link_cache = $container->get( 'onboarding.signup-link-cache' ); $signup_link_ids = $container->get( 'onboarding.signup-link-ids' ); $pui_status_cache = $container->get( 'pui.status-cache' ); From aa0a8d41828c11f782891a45676f85633864b85f Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Mon, 3 Feb 2025 13:49:16 +0100 Subject: [PATCH 31/37] =?UTF-8?q?=F0=9F=97=91=EF=B8=8F=20Deprecate=20`curr?= =?UTF-8?q?ent=5Fenvironment=5Fis()`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ppcp-wc-gateway/src/Helper/Environment.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/ppcp-wc-gateway/src/Helper/Environment.php b/modules/ppcp-wc-gateway/src/Helper/Environment.php index a603e9179..143ebd843 100644 --- a/modules/ppcp-wc-gateway/src/Helper/Environment.php +++ b/modules/ppcp-wc-gateway/src/Helper/Environment.php @@ -56,6 +56,9 @@ class Environment { /** * Detect whether the current environment equals $environment * + * @deprecated Use the is_sandbox() and is_production() methods instead. + * These methods provide better encapsulation, are less error-prone, + * and improve code readability by removing the need to pass environment constants. * @param string $environment The value to check against. * * @return bool @@ -70,7 +73,7 @@ class Environment { * @return bool */ public function is_sandbox() : bool { - return $this->current_environment_is( self::SANDBOX ); + return $this->current_environment() === self::SANDBOX; } /** @@ -79,6 +82,6 @@ class Environment { * @return bool */ public function is_production() : bool { - return $this->current_environment_is( self::PRODUCTION ); + return $this->current_environment() === self::PRODUCTION; } } From 1c70334721159a53c6455a92636443544efc6070 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Mon, 3 Feb 2025 14:21:03 +0100 Subject: [PATCH 32/37] =?UTF-8?q?=F0=9F=90=9B=20Add=20missing=20`use`=20st?= =?UTF-8?q?atement?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ppcp-onboarding/src/State.php | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/ppcp-onboarding/src/State.php b/modules/ppcp-onboarding/src/State.php index 492d180b6..59963dcdf 100644 --- a/modules/ppcp-onboarding/src/State.php +++ b/modules/ppcp-onboarding/src/State.php @@ -10,6 +10,7 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Onboarding; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; +use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; /** * Class State From abb80f99575e2e935d7e89c16a8b6602901c8472 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Mon, 3 Feb 2025 14:22:44 +0100 Subject: [PATCH 33/37] =?UTF-8?q?=F0=9F=90=9B=20Rename=20incorrect=20setti?= =?UTF-8?q?ngs=20mapping?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ppcp-compat/services.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ppcp-compat/services.php b/modules/ppcp-compat/services.php index 91370dff0..65ee1e3d8 100644 --- a/modules/ppcp-compat/services.php +++ b/modules/ppcp-compat/services.php @@ -141,7 +141,7 @@ return array( 'merchant_id' => 'merchant_id', 'client_id' => 'client_id', 'client_secret' => 'client_secret', - 'is_sandbox' => 'sandbox_merchant', + 'sandbox_on' => 'sandbox_merchant', 'live_client_id' => 'client_id', 'live_client_secret' => 'client_secret', 'live_merchant_id' => 'merchant_id', From 1286d0866e5e3069a3a65e1151838728bdd62a92 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Mon, 3 Feb 2025 14:34:25 +0100 Subject: [PATCH 34/37] =?UTF-8?q?=F0=9F=9A=9A=20Extract=20services=20from?= =?UTF-8?q?=20onboarding=20module?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ppcp-api-client/services.php | 31 ++++++++++++++++++++++++++++ modules/ppcp-onboarding/services.php | 29 -------------------------- 2 files changed, 31 insertions(+), 29 deletions(-) diff --git a/modules/ppcp-api-client/services.php b/modules/ppcp-api-client/services.php index bee10d72f..a0d04ae3f 100644 --- a/modules/ppcp-api-client/services.php +++ b/modules/ppcp-api-client/services.php @@ -80,6 +80,8 @@ use WooCommerce\PayPalCommerce\ApiClient\Repository\PayeeRepository; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; use WooCommerce\PayPalCommerce\ApiClient\Authentication\ConnectBearer; use WooCommerce\PayPalCommerce\WcGateway\Helper\EnvironmentConfig; +use WooCommerce\PayPalCommerce\Onboarding\State; +use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; return array( 'api.host' => function( ContainerInterface $container ) : string { @@ -933,4 +935,33 @@ return array( $container->get( 'api.endpoint.partner-referrals-sandbox' ) ); }, + 'api.sandbox-host' => static function ( ContainerInterface $container ): string { + + $state = $container->get( 'onboarding.state' ); + + /** + * The State object. + * + * @var State $state + */ + if ( $state->current_state() >= State::STATE_ONBOARDED ) { + return PAYPAL_SANDBOX_API_URL; + } + return CONNECT_WOO_SANDBOX_URL; + }, + 'api.production-host' => static function ( ContainerInterface $container ): string { + + $state = $container->get( 'onboarding.state' ); + + /** + * The Environment and State variables. + * + * @var Environment $environment + * @var State $state + */ + if ( $state->current_state() >= State::STATE_ONBOARDED ) { + return PAYPAL_API_URL; + } + return CONNECT_WOO_URL; + }, ); diff --git a/modules/ppcp-onboarding/services.php b/modules/ppcp-onboarding/services.php index 7756b69db..17c9ba8c0 100644 --- a/modules/ppcp-onboarding/services.php +++ b/modules/ppcp-onboarding/services.php @@ -20,35 +20,6 @@ use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingRenderer; use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; return array( - 'api.sandbox-host' => static function ( ContainerInterface $container ): string { - - $state = $container->get( 'onboarding.state' ); - - /** - * The State object. - * - * @var State $state - */ - if ( $state->current_state() >= State::STATE_ONBOARDED ) { - return PAYPAL_SANDBOX_API_URL; - } - return CONNECT_WOO_SANDBOX_URL; - }, - 'api.production-host' => static function ( ContainerInterface $container ): string { - - $state = $container->get( 'onboarding.state' ); - - /** - * The Environment and State variables. - * - * @var Environment $environment - * @var State $state - */ - if ( $state->current_state() >= State::STATE_ONBOARDED ) { - return PAYPAL_API_URL; - } - return CONNECT_WOO_URL; - }, 'api.host' => static function ( ContainerInterface $container ): string { $environment = $container->get( 'onboarding.environment' ); From af6cc7e56b0511199ff603e65eff73ac4bf27cc9 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Mon, 3 Feb 2025 14:39:12 +0100 Subject: [PATCH 35/37] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Use=20new=20connecti?= =?UTF-8?q?on-check=20for=20API=20host=20services?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ppcp-api-client/services.php | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/modules/ppcp-api-client/services.php b/modules/ppcp-api-client/services.php index a0d04ae3f..e7cc9e878 100644 --- a/modules/ppcp-api-client/services.php +++ b/modules/ppcp-api-client/services.php @@ -936,32 +936,21 @@ return array( ); }, 'api.sandbox-host' => static function ( ContainerInterface $container ): string { + $is_connected = $container->get( 'settings.flag.is-connected' ); - $state = $container->get( 'onboarding.state' ); - - /** - * The State object. - * - * @var State $state - */ - if ( $state->current_state() >= State::STATE_ONBOARDED ) { + if ( $is_connected ) { return PAYPAL_SANDBOX_API_URL; } + return CONNECT_WOO_SANDBOX_URL; }, 'api.production-host' => static function ( ContainerInterface $container ): string { + $is_connected = $container->get( 'settings.flag.is-connected' ); - $state = $container->get( 'onboarding.state' ); - - /** - * The Environment and State variables. - * - * @var Environment $environment - * @var State $state - */ - if ( $state->current_state() >= State::STATE_ONBOARDED ) { + if ( $is_connected ) { return PAYPAL_API_URL; } + return CONNECT_WOO_URL; }, ); From 04aeb6acf29a1e532809c0014802cf3c138aded2 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Mon, 3 Feb 2025 14:47:52 +0100 Subject: [PATCH 36/37] =?UTF-8?q?=E2=9C=85=20Update=20`use`=20statements?= =?UTF-8?q?=20in=20unit=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/PHPUnit/Vaulting/VaultedCreditCardHandlerTest.php | 2 +- tests/PHPUnit/WcGateway/Gateway/CreditCardGatewayTest.php | 2 +- tests/PHPUnit/WcGateway/Gateway/OXXO/OXXOGatewayTest.php | 2 +- .../Gateway/PayUponInvoice/PayUponInvoiceGatewayTest.php | 2 +- tests/PHPUnit/WcGateway/Gateway/WcGatewayTest.php | 2 +- tests/PHPUnit/WcGateway/Processor/OrderProcessorTest.php | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/PHPUnit/Vaulting/VaultedCreditCardHandlerTest.php b/tests/PHPUnit/Vaulting/VaultedCreditCardHandlerTest.php index c7d176c8e..c084559a4 100644 --- a/tests/PHPUnit/Vaulting/VaultedCreditCardHandlerTest.php +++ b/tests/PHPUnit/Vaulting/VaultedCreditCardHandlerTest.php @@ -19,7 +19,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Entity\PurchaseUnit; use WooCommerce\PayPalCommerce\ApiClient\Factory\PayerFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\ShippingPreferenceFactory; -use WooCommerce\PayPalCommerce\Onboarding\Environment; +use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\TestCase; use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository; diff --git a/tests/PHPUnit/WcGateway/Gateway/CreditCardGatewayTest.php b/tests/PHPUnit/WcGateway/Gateway/CreditCardGatewayTest.php index 1489da4ff..72b90e030 100644 --- a/tests/PHPUnit/WcGateway/Gateway/CreditCardGatewayTest.php +++ b/tests/PHPUnit/WcGateway/Gateway/CreditCardGatewayTest.php @@ -9,7 +9,7 @@ use WC_Order; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentsEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokensEndpoint; -use WooCommerce\PayPalCommerce\Onboarding\Environment; +use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\Session\SessionHandler; use WooCommerce\PayPalCommerce\TestCase; diff --git a/tests/PHPUnit/WcGateway/Gateway/OXXO/OXXOGatewayTest.php b/tests/PHPUnit/WcGateway/Gateway/OXXO/OXXOGatewayTest.php index 0f70f801c..30e106152 100644 --- a/tests/PHPUnit/WcGateway/Gateway/OXXO/OXXOGatewayTest.php +++ b/tests/PHPUnit/WcGateway/Gateway/OXXO/OXXOGatewayTest.php @@ -12,7 +12,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Entity\PurchaseUnit; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\ShippingPreferenceFactory; -use WooCommerce\PayPalCommerce\Onboarding\Environment; +use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; use WooCommerce\PayPalCommerce\TestCase; use WooCommerce\PayPalCommerce\WcGateway\Gateway\TransactionUrlProvider; use function Brain\Monkey\Functions\when; diff --git a/tests/PHPUnit/WcGateway/Gateway/PayUponInvoice/PayUponInvoiceGatewayTest.php b/tests/PHPUnit/WcGateway/Gateway/PayUponInvoice/PayUponInvoiceGatewayTest.php index 82c88449f..d806037ee 100644 --- a/tests/PHPUnit/WcGateway/Gateway/PayUponInvoice/PayUponInvoiceGatewayTest.php +++ b/tests/PHPUnit/WcGateway/Gateway/PayUponInvoice/PayUponInvoiceGatewayTest.php @@ -10,7 +10,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PayUponInvoiceOrderEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Entity\Order; use WooCommerce\PayPalCommerce\ApiClient\Entity\PurchaseUnit; use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory; -use WooCommerce\PayPalCommerce\Onboarding\Environment; +use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\TestCase; use WooCommerce\PayPalCommerce\WcGateway\Gateway\TransactionUrlProvider; diff --git a/tests/PHPUnit/WcGateway/Gateway/WcGatewayTest.php b/tests/PHPUnit/WcGateway/Gateway/WcGatewayTest.php index 8c8a238ae..a9e64ebb0 100644 --- a/tests/PHPUnit/WcGateway/Gateway/WcGatewayTest.php +++ b/tests/PHPUnit/WcGateway/Gateway/WcGatewayTest.php @@ -9,7 +9,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokensEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Entity\Order; use WooCommerce\PayPalCommerce\ApiClient\Entity\OrderStatus; -use WooCommerce\PayPalCommerce\Onboarding\Environment; +use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\Session\SessionHandler; use WooCommerce\PayPalCommerce\Vaulting\WooCommercePaymentTokens; diff --git a/tests/PHPUnit/WcGateway/Processor/OrderProcessorTest.php b/tests/PHPUnit/WcGateway/Processor/OrderProcessorTest.php index 207d31967..951c3d9af 100644 --- a/tests/PHPUnit/WcGateway/Processor/OrderProcessorTest.php +++ b/tests/PHPUnit/WcGateway/Processor/OrderProcessorTest.php @@ -20,7 +20,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Entity\PurchaseUnit; use WooCommerce\PayPalCommerce\ApiClient\Factory\OrderFactory; use WooCommerce\PayPalCommerce\ApiClient\Helper\OrderHelper; use WooCommerce\PayPalCommerce\Button\Helper\ThreeDSecure; -use WooCommerce\PayPalCommerce\Onboarding\Environment; +use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; use WooCommerce\PayPalCommerce\Session\SessionHandler; use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Container\ReadOnlyContainer; use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; From 70c44b1f18e9f5e4c7c9313d2be3724eb149b7d1 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Mon, 3 Feb 2025 14:50:41 +0100 Subject: [PATCH 37/37] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Consolidate=20?= =?UTF-8?q?=E2=80=98api.host=E2=80=99=20service=20logic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ppcp-api-client/services.php | 11 +++++++++-- modules/ppcp-onboarding/services.php | 12 ------------ 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/modules/ppcp-api-client/services.php b/modules/ppcp-api-client/services.php index e7cc9e878..272bfdaf7 100644 --- a/modules/ppcp-api-client/services.php +++ b/modules/ppcp-api-client/services.php @@ -84,8 +84,15 @@ use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; return array( - 'api.host' => function( ContainerInterface $container ) : string { - return PAYPAL_API_URL; + 'api.host' => static function( ContainerInterface $container ) : string { + $environment = $container->get( 'onboarding.environment' ); + assert( $environment instanceof Environment ); + + if ( $environment->is_sandbox() ) { + return (string) $container->get( 'api.sandbox-host' ); + } + + return (string) $container->get( 'api.production-host' ); }, 'api.paypal-host' => function( ContainerInterface $container ) : string { return PAYPAL_API_URL; diff --git a/modules/ppcp-onboarding/services.php b/modules/ppcp-onboarding/services.php index 17c9ba8c0..cbbd02da5 100644 --- a/modules/ppcp-onboarding/services.php +++ b/modules/ppcp-onboarding/services.php @@ -20,18 +20,6 @@ use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingRenderer; use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment; return array( - 'api.host' => static function ( ContainerInterface $container ): string { - $environment = $container->get( 'onboarding.environment' ); - - /** - * The Environment and State variables. - * - * @var Environment $environment - */ - return $environment->current_environment_is( Environment::SANDBOX ) - ? (string) $container->get( 'api.sandbox-host' ) : (string) $container->get( 'api.production-host' ); - - }, 'api.paypal-host' => function( ContainerInterface $container ) : string { $environment = $container->get( 'onboarding.environment' ); /**