mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-04 08:47:23 +08:00
Merge pull request #3202 from woocommerce/PCP-4300-fix-broken-toggle-sync-for-payment-and-setting-dependencies
Fix broken payment method toggle sync (4300)
This commit is contained in:
commit
bab13f2524
3 changed files with 166 additions and 4 deletions
|
@ -8,6 +8,7 @@ import * as hooks from './hooks';
|
|||
import * as resolvers from './resolvers';
|
||||
import { initTodoSync } from '../sync/todo-state-sync';
|
||||
import { initPaymentDependencySync } from '../sync/payment-methods-sync';
|
||||
import { initSettingBasedPaymentMethodsSync } from '../sync/setting-based-payment-methods-sync';
|
||||
|
||||
/**
|
||||
* Initializes and registers the settings store with WordPress data layer.
|
||||
|
@ -30,6 +31,7 @@ export const initStore = () => {
|
|||
|
||||
// Initialize payment method dependency sync.
|
||||
initPaymentDependencySync();
|
||||
initSettingBasedPaymentMethodsSync();
|
||||
|
||||
return Boolean( wp.data.select( STORE_NAME ) );
|
||||
};
|
||||
|
|
|
@ -61,8 +61,10 @@ export const initPaymentDependencySync = () => {
|
|||
( [ key, method ] ) =>
|
||||
key !== '__meta' &&
|
||||
method &&
|
||||
method.depends_on &&
|
||||
method.depends_on.includes( changedId )
|
||||
method.depends_on_payment_methods &&
|
||||
method.depends_on_payment_methods.includes(
|
||||
changedId
|
||||
)
|
||||
)
|
||||
.map( ( [ key ] ) => key );
|
||||
|
||||
|
@ -115,11 +117,11 @@ const handleRestoreDependents = ( dependentIds, methods ) => {
|
|||
|
||||
const checkAllDependenciesSatisfied = ( methodId, methods ) => {
|
||||
const method = methods[ methodId ];
|
||||
if ( ! method || ! method.depends_on ) {
|
||||
if ( ! method || ! method.depends_on_payment_methods ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return ! method.depends_on.some( ( parentId ) => {
|
||||
return ! method.depends_on_payment_methods.some( ( parentId ) => {
|
||||
const parent = methods[ parentId ];
|
||||
return ! parent || parent.enabled === false;
|
||||
} );
|
||||
|
|
|
@ -0,0 +1,158 @@
|
|||
import { subscribe, select } from '@wordpress/data';
|
||||
|
||||
// Store names
|
||||
const PAYMENT_STORE = 'wc/paypal/payment';
|
||||
const SETTINGS_STORE = 'wc/paypal/settings';
|
||||
|
||||
// Track original states of methods affected by settings
|
||||
const settingDependentStates = {};
|
||||
|
||||
/**
|
||||
* Initialize setting dependency synchronization
|
||||
*/
|
||||
export const initSettingBasedPaymentMethodsSync = () => {
|
||||
let previousSettingsState = null;
|
||||
let isProcessing = false;
|
||||
|
||||
const unsubscribe = subscribe( () => {
|
||||
if ( isProcessing ) {
|
||||
return;
|
||||
}
|
||||
|
||||
isProcessing = true;
|
||||
|
||||
try {
|
||||
// Get both settings and payment stores
|
||||
const settingsHooks = select( SETTINGS_STORE );
|
||||
const paymentHooks = select( PAYMENT_STORE );
|
||||
|
||||
if ( ! settingsHooks || ! paymentHooks ) {
|
||||
isProcessing = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const settings = settingsHooks.persistentData();
|
||||
const methods = paymentHooks.persistentData();
|
||||
|
||||
if ( ! settings || ! methods ) {
|
||||
isProcessing = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! previousSettingsState ) {
|
||||
previousSettingsState = { ...settings };
|
||||
isProcessing = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Find which settings changed
|
||||
const changedSettings = Object.keys( settings ).filter(
|
||||
( key ) =>
|
||||
previousSettingsState[ key ] !== undefined &&
|
||||
settings[ key ] !== previousSettingsState[ key ]
|
||||
);
|
||||
|
||||
if ( changedSettings.length > 0 ) {
|
||||
// Process affected payment methods for each changed setting
|
||||
for ( const methodId in methods ) {
|
||||
if ( methodId === '__meta' || ! methods[ methodId ] ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const method = methods[ methodId ];
|
||||
|
||||
// Skip methods without setting dependencies
|
||||
if ( ! method.depends_on_settings?.settings ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const { settings: dependencySettings } =
|
||||
method.depends_on_settings;
|
||||
|
||||
// Check if any of the changed settings affects this method
|
||||
const relevantSettings = Object.values(
|
||||
dependencySettings
|
||||
).filter( ( setting ) =>
|
||||
changedSettings.includes( setting.id )
|
||||
);
|
||||
|
||||
if ( relevantSettings.length > 0 ) {
|
||||
// Determine if method should be disabled based on new setting values
|
||||
const shouldBeDisabled = relevantSettings.some(
|
||||
( setting ) =>
|
||||
settings[ setting.id ] !== setting.value
|
||||
);
|
||||
|
||||
if ( shouldBeDisabled ) {
|
||||
// Store original state before disabling
|
||||
if ( ! ( methodId in settingDependentStates ) ) {
|
||||
settingDependentStates[ methodId ] =
|
||||
method.enabled;
|
||||
}
|
||||
|
||||
// Disable the method
|
||||
methods[ methodId ].enabled = false;
|
||||
methods[ methodId ].isDisabled = true;
|
||||
} else {
|
||||
// Check if all setting dependencies are now satisfied
|
||||
const allSettingsSatisfied = Object.values(
|
||||
dependencySettings
|
||||
).every(
|
||||
( setting ) =>
|
||||
settings[ setting.id ] === setting.value
|
||||
);
|
||||
|
||||
// Also check payment method dependencies
|
||||
const paymentDependenciesSatisfied =
|
||||
checkPaymentDependenciesSatisfied(
|
||||
methodId,
|
||||
methods
|
||||
);
|
||||
|
||||
// If all dependencies are satisfied, restore the original state
|
||||
if (
|
||||
allSettingsSatisfied &&
|
||||
paymentDependenciesSatisfied &&
|
||||
methodId in settingDependentStates
|
||||
) {
|
||||
methods[ methodId ].enabled =
|
||||
settingDependentStates[ methodId ];
|
||||
methods[ methodId ].isDisabled = false;
|
||||
delete settingDependentStates[ methodId ];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
previousSettingsState = { ...settings };
|
||||
} catch ( error ) {
|
||||
// Silent error handling
|
||||
} finally {
|
||||
isProcessing = false;
|
||||
}
|
||||
} );
|
||||
|
||||
return unsubscribe;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if all payment method dependencies are satisfied for a method
|
||||
*
|
||||
* @param {string} methodId - ID of the method to check
|
||||
* @param {Object} methods - All payment methods
|
||||
* @return {boolean} True if all dependencies are satisfied
|
||||
*/
|
||||
const checkPaymentDependenciesSatisfied = ( methodId, methods ) => {
|
||||
const method = methods[ methodId ];
|
||||
if ( ! method || ! method.depends_on_payment_methods ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return ! method.depends_on_payment_methods.some( ( parentId ) => {
|
||||
const parent = methods[ parentId ];
|
||||
return ! parent || parent.enabled === false;
|
||||
} );
|
||||
};
|
||||
|
||||
export default initSettingBasedPaymentMethodsSync;
|
Loading…
Add table
Add a link
Reference in a new issue