mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-06 14:57:26 +08:00
Merge branch 'trunk' into PCP-3786-manual-input
This commit is contained in:
commit
6d0a6c8653
18 changed files with 412 additions and 162 deletions
|
@ -1,6 +1,3 @@
|
||||||
export const PAGE_ONBOARDING = 'onboarding';
|
|
||||||
export const PAGE_SETTINGS = 'settings';
|
|
||||||
|
|
||||||
const Container = ( { isCard = true, page, children } ) => {
|
const Container = ( { isCard = true, page, children } ) => {
|
||||||
let className = 'ppcp-r-container';
|
let className = 'ppcp-r-container';
|
||||||
|
|
||||||
|
|
|
@ -1,48 +1,36 @@
|
||||||
import Container, {
|
import Container from '../../ReusableComponents/Container';
|
||||||
PAGE_ONBOARDING,
|
|
||||||
} from '../../ReusableComponents/Container.js';
|
|
||||||
import StepWelcome from './StepWelcome.js';
|
|
||||||
import StepBusiness from './StepBusiness.js';
|
|
||||||
import StepProducts from './StepProducts.js';
|
|
||||||
import { useOnboardingStep } from '../../../data';
|
import { useOnboardingStep } from '../../../data';
|
||||||
|
import { getSteps } from './availableSteps';
|
||||||
|
|
||||||
|
const getCurrentStep = ( requestedStep, steps ) => {
|
||||||
|
const isValidStep = ( step ) =>
|
||||||
|
typeof step === 'number' &&
|
||||||
|
Number.isInteger( step ) &&
|
||||||
|
step >= 0 &&
|
||||||
|
step < steps.length;
|
||||||
|
|
||||||
|
const safeCurrentStep = isValidStep( requestedStep ) ? requestedStep : 0;
|
||||||
|
return steps[ safeCurrentStep ];
|
||||||
|
};
|
||||||
|
|
||||||
const Onboarding = () => {
|
const Onboarding = () => {
|
||||||
const { step, setStep, setCompleted } = useOnboardingStep();
|
const { step, setStep, setCompleted, flags } = useOnboardingStep();
|
||||||
|
const steps = getSteps( flags );
|
||||||
|
|
||||||
|
const CurrentStepComponent = getCurrentStep( step, steps );
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container page={ PAGE_ONBOARDING }>
|
<Container page="onboarding">
|
||||||
<div className="ppcp-r-card">
|
<div className="ppcp-r-card">
|
||||||
<OnboardingStep
|
<CurrentStepComponent
|
||||||
currentStep={ step }
|
|
||||||
setStep={ setStep }
|
setStep={ setStep }
|
||||||
|
currentStep={ step }
|
||||||
setCompleted={ setCompleted }
|
setCompleted={ setCompleted }
|
||||||
|
stepperOrder={ steps }
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const OnboardingStep = ( { currentStep, setStep, setCompleted } ) => {
|
|
||||||
const stepperOrder = [ StepWelcome, StepBusiness, StepProducts ];
|
|
||||||
|
|
||||||
const isValidStep = ( step ) =>
|
|
||||||
typeof step === 'number' &&
|
|
||||||
Number.isInteger( step ) &&
|
|
||||||
step >= 0 &&
|
|
||||||
step < stepperOrder.length;
|
|
||||||
|
|
||||||
const safeCurrentStep = isValidStep( currentStep ) ? currentStep : 0;
|
|
||||||
|
|
||||||
const CurrentStepComponent = stepperOrder[ safeCurrentStep ];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<CurrentStepComponent
|
|
||||||
setStep={ setStep }
|
|
||||||
currentStep={ safeCurrentStep }
|
|
||||||
setCompleted={ setCompleted }
|
|
||||||
stepperOrder={ stepperOrder }
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Onboarding;
|
export default Onboarding;
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
import OnboardingHeader from '../../ReusableComponents/OnboardingHeader.js';
|
import OnboardingHeader from '../../ReusableComponents/OnboardingHeader';
|
||||||
import SelectBoxWrapper from '../../ReusableComponents/SelectBoxWrapper.js';
|
import SelectBoxWrapper from '../../ReusableComponents/SelectBoxWrapper';
|
||||||
import SelectBox from '../../ReusableComponents/SelectBox.js';
|
import SelectBox from '../../ReusableComponents/SelectBox';
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
import PaymentMethodIcons from '../../ReusableComponents/PaymentMethodIcons';
|
import PaymentMethodIcons from '../../ReusableComponents/PaymentMethodIcons';
|
||||||
import { useState } from '@wordpress/element';
|
import { useOnboardingStepBusiness } from '../../../data';
|
||||||
import Navigation from '../../ReusableComponents/Navigation';
|
import Navigation from '../../ReusableComponents/Navigation';
|
||||||
|
import { BUSINESS_TYPES } from '../../../data/constants';
|
||||||
|
|
||||||
|
const BUSINESS_RADIO_GROUP_NAME = 'business';
|
||||||
|
|
||||||
const StepBusiness = ( {
|
const StepBusiness = ( {
|
||||||
setStep,
|
setStep,
|
||||||
|
@ -12,10 +15,21 @@ const StepBusiness = ( {
|
||||||
stepperOrder,
|
stepperOrder,
|
||||||
setCompleted,
|
setCompleted,
|
||||||
} ) => {
|
} ) => {
|
||||||
const [ businessCategory, setBusinessCategory ] = useState( null );
|
const { isCasualSeller, setIsCasualSeller } = useOnboardingStepBusiness();
|
||||||
const BUSINESS_RADIO_GROUP_NAME = 'business';
|
|
||||||
const CASUAL_SELLER_CHECKBOX_VALUE = 'casual_seller';
|
const handleSellerTypeChange = ( value ) => {
|
||||||
const BUSINESS_CHECKBOX_VALUE = 'business';
|
setIsCasualSeller( BUSINESS_TYPES.CASUAL_SELLER === value );
|
||||||
|
};
|
||||||
|
|
||||||
|
const getCurrentValue = () => {
|
||||||
|
if ( isCasualSeller === null ) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return isCasualSeller
|
||||||
|
? BUSINESS_TYPES.CASUAL_SELLER
|
||||||
|
: BUSINESS_TYPES.BUSINESS;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="ppcp-r-page-business">
|
<div className="ppcp-r-page-business">
|
||||||
|
@ -38,13 +52,10 @@ const StepBusiness = ( {
|
||||||
) }
|
) }
|
||||||
icon="icon-business-casual-seller.svg"
|
icon="icon-business-casual-seller.svg"
|
||||||
name={ BUSINESS_RADIO_GROUP_NAME }
|
name={ BUSINESS_RADIO_GROUP_NAME }
|
||||||
value={ CASUAL_SELLER_CHECKBOX_VALUE }
|
value={ BUSINESS_TYPES.CASUAL_SELLER }
|
||||||
changeCallback={ setBusinessCategory }
|
changeCallback={ handleSellerTypeChange }
|
||||||
currentValue={ businessCategory }
|
currentValue={ getCurrentValue() }
|
||||||
checked={
|
checked={ isCasualSeller === true }
|
||||||
businessCategory ===
|
|
||||||
{ CASUAL_SELLER_CHECKBOX_VALUE }
|
|
||||||
}
|
|
||||||
type="radio"
|
type="radio"
|
||||||
>
|
>
|
||||||
<PaymentMethodIcons
|
<PaymentMethodIcons
|
||||||
|
@ -69,12 +80,10 @@ const StepBusiness = ( {
|
||||||
) }
|
) }
|
||||||
icon="icon-business-business.svg"
|
icon="icon-business-business.svg"
|
||||||
name={ BUSINESS_RADIO_GROUP_NAME }
|
name={ BUSINESS_RADIO_GROUP_NAME }
|
||||||
value={ BUSINESS_CHECKBOX_VALUE }
|
value={ BUSINESS_TYPES.BUSINESS }
|
||||||
currentValue={ businessCategory }
|
changeCallback={ handleSellerTypeChange }
|
||||||
changeCallback={ setBusinessCategory }
|
currentValue={ getCurrentValue() }
|
||||||
checked={
|
checked={ isCasualSeller === false }
|
||||||
businessCategory === { BUSINESS_CHECKBOX_VALUE }
|
|
||||||
}
|
|
||||||
type="radio"
|
type="radio"
|
||||||
>
|
>
|
||||||
<PaymentMethodIcons
|
<PaymentMethodIcons
|
||||||
|
@ -97,7 +106,7 @@ const StepBusiness = ( {
|
||||||
currentStep={ currentStep }
|
currentStep={ currentStep }
|
||||||
stepperOrder={ stepperOrder }
|
stepperOrder={ stepperOrder }
|
||||||
setCompleted={ setCompleted }
|
setCompleted={ setCompleted }
|
||||||
canProceeedCallback={ () => businessCategory !== null }
|
canProceeedCallback={ () => isCasualSeller !== null }
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,7 +3,10 @@ import Navigation from '../../ReusableComponents/Navigation';
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
import SelectBox from '../../ReusableComponents/SelectBox';
|
import SelectBox from '../../ReusableComponents/SelectBox';
|
||||||
import SelectBoxWrapper from '../../ReusableComponents/SelectBoxWrapper';
|
import SelectBoxWrapper from '../../ReusableComponents/SelectBoxWrapper';
|
||||||
import { useState } from '@wordpress/element';
|
import { useOnboardingStepProducts } from '../../../data';
|
||||||
|
import { PRODUCT_TYPES } from '../../../data/constants';
|
||||||
|
|
||||||
|
const PRODUCTS_CHECKBOX_GROUP_NAME = 'products';
|
||||||
|
|
||||||
const StepProducts = ( {
|
const StepProducts = ( {
|
||||||
setStep,
|
setStep,
|
||||||
|
@ -11,11 +14,7 @@ const StepProducts = ( {
|
||||||
stepperOrder,
|
stepperOrder,
|
||||||
setCompleted,
|
setCompleted,
|
||||||
} ) => {
|
} ) => {
|
||||||
const [ products, setProducts ] = useState( [] );
|
const { products, toggleProduct } = useOnboardingStepProducts();
|
||||||
const PRODUCTS_CHECKBOX_GROUP_NAME = 'products';
|
|
||||||
const VIRTUAL_CHECKBOX_VALUE = 'virtual';
|
|
||||||
const PHYSICAL_CHECKBOX_VALUE = 'physical';
|
|
||||||
const SUBSCRIPTIONS_CHECKBOX_VALUE = 'subscriptions';
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="ppcp-r-page-products">
|
<div className="ppcp-r-page-products">
|
||||||
|
@ -35,8 +34,8 @@ const StepProducts = ( {
|
||||||
) }
|
) }
|
||||||
icon="icon-product-virtual.svg"
|
icon="icon-product-virtual.svg"
|
||||||
name={ PRODUCTS_CHECKBOX_GROUP_NAME }
|
name={ PRODUCTS_CHECKBOX_GROUP_NAME }
|
||||||
value={ VIRTUAL_CHECKBOX_VALUE }
|
value={ PRODUCT_TYPES.VIRTUAL }
|
||||||
changeCallback={ setProducts }
|
changeCallback={ toggleProduct }
|
||||||
currentValue={ products }
|
currentValue={ products }
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
>
|
>
|
||||||
|
@ -78,8 +77,8 @@ const StepProducts = ( {
|
||||||
) }
|
) }
|
||||||
icon="icon-product-physical.svg"
|
icon="icon-product-physical.svg"
|
||||||
name={ PRODUCTS_CHECKBOX_GROUP_NAME }
|
name={ PRODUCTS_CHECKBOX_GROUP_NAME }
|
||||||
value={ PHYSICAL_CHECKBOX_VALUE }
|
value={ PRODUCT_TYPES.PHYSICAL }
|
||||||
changeCallback={ setProducts }
|
changeCallback={ toggleProduct }
|
||||||
currentValue={ products }
|
currentValue={ products }
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
>
|
>
|
||||||
|
@ -106,8 +105,8 @@ const StepProducts = ( {
|
||||||
) }
|
) }
|
||||||
icon="icon-product-subscription.svg"
|
icon="icon-product-subscription.svg"
|
||||||
name={ PRODUCTS_CHECKBOX_GROUP_NAME }
|
name={ PRODUCTS_CHECKBOX_GROUP_NAME }
|
||||||
value={ SUBSCRIPTIONS_CHECKBOX_VALUE }
|
value={ PRODUCT_TYPES.SUBSCRIPTIONS }
|
||||||
changeCallback={ setProducts }
|
changeCallback={ toggleProduct }
|
||||||
currentValue={ products }
|
currentValue={ products }
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import OnboardingHeader from '../../ReusableComponents/OnboardingHeader.js';
|
import OnboardingHeader from '../../ReusableComponents/OnboardingHeader';
|
||||||
import { __, sprintf } from '@wordpress/i18n';
|
import { __, sprintf } from '@wordpress/i18n';
|
||||||
import { Button, TextControl } from '@wordpress/components';
|
import { Button, TextControl } from '@wordpress/components';
|
||||||
import PaymentMethodIcons from '../../ReusableComponents/PaymentMethodIcons';
|
import PaymentMethodIcons from '../../ReusableComponents/PaymentMethodIcons';
|
||||||
import SettingsToggleBlock from '../../ReusableComponents/SettingsToggleBlock';
|
import SettingsToggleBlock from '../../ReusableComponents/SettingsToggleBlock';
|
||||||
import Separator from '../../ReusableComponents/Separator';
|
import Separator from '../../ReusableComponents/Separator';
|
||||||
import { useManualConnect, useOnboardingDetails } from '../../../data';
|
import { useOnboardingStepWelcome, useManualConnect } from '../../../data';
|
||||||
|
|
||||||
import DataStoreControl from '../../ReusableComponents/DataStoreControl';
|
import DataStoreControl from '../../ReusableComponents/DataStoreControl';
|
||||||
|
|
||||||
const StepWelcome = ( { setStep, currentStep, setCompleted } ) => {
|
const StepWelcome = ( { setStep, currentStep, setCompleted } ) => {
|
||||||
|
@ -84,7 +85,8 @@ const WelcomeForm = ( { setCompleted } ) => {
|
||||||
setClientId,
|
setClientId,
|
||||||
clientSecret,
|
clientSecret,
|
||||||
setClientSecret,
|
setClientSecret,
|
||||||
} = useOnboardingDetails();
|
} =
|
||||||
|
();
|
||||||
|
|
||||||
const { connectManual } = useManualConnect();
|
const { connectManual } = useManualConnect();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
import StepWelcome from './StepWelcome';
|
||||||
|
import StepBusiness from './StepBusiness';
|
||||||
|
import StepProducts from './StepProducts';
|
||||||
|
|
||||||
|
export const getSteps = ( flags ) => {
|
||||||
|
const allSteps = [ StepWelcome, StepBusiness, StepProducts ];
|
||||||
|
|
||||||
|
if ( ! flags.canUseCasualSelling ) {
|
||||||
|
return allSteps.filter( ( step ) => step !== StepBusiness );
|
||||||
|
}
|
||||||
|
|
||||||
|
return allSteps;
|
||||||
|
};
|
|
@ -1,2 +1,13 @@
|
||||||
export const NAMESPACE = '/wc/v3/wc_paypal';
|
export const NAMESPACE = '/wc/v3/wc_paypal';
|
||||||
export const STORE_NAME = 'wc/paypal';
|
export const STORE_NAME = 'wc/paypal';
|
||||||
|
|
||||||
|
export const BUSINESS_TYPES = {
|
||||||
|
CASUAL_SELLER: 'casual_seller',
|
||||||
|
BUSINESS: 'business',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const PRODUCT_TYPES = {
|
||||||
|
VIRTUAL: 'virtual',
|
||||||
|
PHYSICAL: 'physical',
|
||||||
|
SUBSCRIPTIONS: 'subscriptions',
|
||||||
|
};
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
export default {
|
export default {
|
||||||
|
RESET_ONBOARDING: 'RESET_ONBOARDING',
|
||||||
|
|
||||||
// Transient data.
|
// Transient data.
|
||||||
SET_ONBOARDING_IS_READY: 'SET_ONBOARDING_IS_READY',
|
SET_ONBOARDING_IS_READY: 'SET_ONBOARDING_IS_READY',
|
||||||
SET_IS_SAVING_ONBOARDING: 'SET_IS_SAVING_ONBOARDING',
|
SET_IS_SAVING_ONBOARDING: 'SET_IS_SAVING_ONBOARDING',
|
||||||
|
@ -11,4 +13,6 @@ export default {
|
||||||
SET_MANUAL_CONNECTION_MODE: 'SET_MANUAL_CONNECTION_MODE',
|
SET_MANUAL_CONNECTION_MODE: 'SET_MANUAL_CONNECTION_MODE',
|
||||||
SET_CLIENT_ID: 'SET_CLIENT_ID',
|
SET_CLIENT_ID: 'SET_CLIENT_ID',
|
||||||
SET_CLIENT_SECRET: 'SET_CLIENT_SECRET',
|
SET_CLIENT_SECRET: 'SET_CLIENT_SECRET',
|
||||||
|
SET_IS_CASUAL_SELLER: 'SET_IS_CASUAL_SELLER',
|
||||||
|
SET_PRODUCTS: 'SET_PRODUCTS',
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,6 +3,15 @@ import { apiFetch } from '@wordpress/data-controls';
|
||||||
import ACTION_TYPES from './action-types';
|
import ACTION_TYPES from './action-types';
|
||||||
import { NAMESPACE, STORE_NAME } from '../constants';
|
import { NAMESPACE, STORE_NAME } from '../constants';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Special. Resets all values in the onboarding store to initial defaults.
|
||||||
|
*
|
||||||
|
* @return {{type: string}} The action.
|
||||||
|
*/
|
||||||
|
export const resetOnboarding = () => {
|
||||||
|
return { type: ACTION_TYPES.RESET_ONBOARDING };
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Non-persistent. Marks the onboarding details as "ready", i.e., fully initialized.
|
* Non-persistent. Marks the onboarding details as "ready", i.e., fully initialized.
|
||||||
*
|
*
|
||||||
|
@ -32,7 +41,7 @@ export const setIsSaving = ( isSaving ) => {
|
||||||
/**
|
/**
|
||||||
* Persistent. Set the full onboarding details, usually during app initialization.
|
* Persistent. Set the full onboarding details, usually during app initialization.
|
||||||
*
|
*
|
||||||
* @param {Object} payload
|
* @param {{data: {}, flags?: {}}} payload
|
||||||
* @return {{type: string, payload}} The action.
|
* @return {{type: string, payload}} The action.
|
||||||
*/
|
*/
|
||||||
export const setOnboardingDetails = ( payload ) => {
|
export const setOnboardingDetails = ( payload ) => {
|
||||||
|
@ -120,6 +129,32 @@ export const setClientSecret = ( clientSecret ) => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Persistent. Sets the "isCasualSeller" value.
|
||||||
|
*
|
||||||
|
* @param {boolean} isCasualSeller
|
||||||
|
* @return {{type: string, isCasualSeller}} The action.
|
||||||
|
*/
|
||||||
|
export const setIsCasualSeller = ( isCasualSeller ) => {
|
||||||
|
return {
|
||||||
|
type: ACTION_TYPES.SET_IS_CASUAL_SELLER,
|
||||||
|
isCasualSeller,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Persistent. Sets the "products" array.
|
||||||
|
*
|
||||||
|
* @param {string[]} products
|
||||||
|
* @return {{type: string, products}} The action.
|
||||||
|
*/
|
||||||
|
export const setProducts = ( products ) => {
|
||||||
|
return {
|
||||||
|
type: ACTION_TYPES.SET_PRODUCTS,
|
||||||
|
products,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the persistent details to the WP database.
|
* Saves the persistent details to the WP database.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,14 +1,19 @@
|
||||||
import { useSelect, useDispatch } from '@wordpress/data';
|
import { useSelect, useDispatch } from '@wordpress/data';
|
||||||
import { NAMESPACE, STORE_NAME } from '../constants';
|
|
||||||
import apiFetch from '@wordpress/api-fetch';
|
import apiFetch from '@wordpress/api-fetch';
|
||||||
|
import { NAMESPACE, PRODUCT_TYPES, STORE_NAME } from '../constants';
|
||||||
|
import { getFlags } from './selectors';
|
||||||
|
|
||||||
export const useOnboardingDetails = () => {
|
const useOnboardingDetails = () => {
|
||||||
const {
|
const {
|
||||||
persist,
|
persist,
|
||||||
|
setOnboardingStep,
|
||||||
|
setCompleted,
|
||||||
setSandboxMode,
|
setSandboxMode,
|
||||||
setManualConnectionMode,
|
setManualConnectionMode,
|
||||||
setClientId,
|
setClientId,
|
||||||
setClientSecret,
|
setClientSecret,
|
||||||
|
setIsCasualSeller,
|
||||||
|
setProducts,
|
||||||
} = useDispatch( STORE_NAME );
|
} = useDispatch( STORE_NAME );
|
||||||
|
|
||||||
// Transient accessors.
|
// Transient accessors.
|
||||||
|
@ -16,7 +21,24 @@ export const useOnboardingDetails = () => {
|
||||||
return select( STORE_NAME ).getTransientData().isSaving;
|
return select( STORE_NAME ).getTransientData().isSaving;
|
||||||
}, [] );
|
}, [] );
|
||||||
|
|
||||||
|
const isReady = useSelect( ( select ) => {
|
||||||
|
return select( STORE_NAME ).getTransientData().isReady;
|
||||||
|
} );
|
||||||
|
|
||||||
|
// Read-only flags.
|
||||||
|
const flags = useSelect( ( select ) => {
|
||||||
|
return select( STORE_NAME ).getFlags();
|
||||||
|
} );
|
||||||
|
|
||||||
// Persistent accessors.
|
// Persistent accessors.
|
||||||
|
const step = useSelect( ( select ) => {
|
||||||
|
return select( STORE_NAME ).getPersistentData().step || 0;
|
||||||
|
} );
|
||||||
|
|
||||||
|
const completed = useSelect( ( select ) => {
|
||||||
|
return select( STORE_NAME ).getPersistentData().completed;
|
||||||
|
} );
|
||||||
|
|
||||||
const clientId = useSelect( ( select ) => {
|
const clientId = useSelect( ( select ) => {
|
||||||
return select( STORE_NAME ).getPersistentData().clientId;
|
return select( STORE_NAME ).getPersistentData().clientId;
|
||||||
}, [] );
|
}, [] );
|
||||||
|
@ -33,6 +55,21 @@ export const useOnboardingDetails = () => {
|
||||||
return select( STORE_NAME ).getPersistentData().useManualConnection;
|
return select( STORE_NAME ).getPersistentData().useManualConnection;
|
||||||
}, [] );
|
}, [] );
|
||||||
|
|
||||||
|
const isCasualSeller = useSelect( ( select ) => {
|
||||||
|
return select( STORE_NAME ).getPersistentData().isCasualSeller;
|
||||||
|
}, [] );
|
||||||
|
|
||||||
|
const products = useSelect( ( select ) => {
|
||||||
|
return select( STORE_NAME ).getPersistentData().products || [];
|
||||||
|
}, [] );
|
||||||
|
|
||||||
|
const toggleProduct = ( list ) => {
|
||||||
|
const validProducts = list.filter( ( item ) =>
|
||||||
|
Object.values( PRODUCT_TYPES ).includes( item )
|
||||||
|
);
|
||||||
|
return setDetailAndPersist( setProducts, validProducts );
|
||||||
|
};
|
||||||
|
|
||||||
const setDetailAndPersist = async ( setter, value ) => {
|
const setDetailAndPersist = async ( setter, value ) => {
|
||||||
setter( value );
|
setter( value );
|
||||||
await persist();
|
await persist();
|
||||||
|
@ -40,50 +77,76 @@ export const useOnboardingDetails = () => {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isSaving,
|
isSaving,
|
||||||
isSandboxMode,
|
|
||||||
isManualConnectionMode,
|
|
||||||
clientId,
|
|
||||||
setClientId: ( value ) => setDetailAndPersist( setClientId, value ),
|
|
||||||
clientSecret,
|
|
||||||
setClientSecret: ( value ) =>
|
|
||||||
setDetailAndPersist( setClientSecret, value ),
|
|
||||||
setSandboxMode: ( state ) =>
|
|
||||||
setDetailAndPersist( setSandboxMode, state ),
|
|
||||||
setManualConnectionMode: ( state ) =>
|
|
||||||
setDetailAndPersist( setManualConnectionMode, state ),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useOnboardingStep = () => {
|
|
||||||
const { persist, setOnboardingStep, setCompleted } =
|
|
||||||
useDispatch( STORE_NAME );
|
|
||||||
|
|
||||||
const isReady = useSelect( ( select ) => {
|
|
||||||
return select( STORE_NAME ).getTransientData().isReady;
|
|
||||||
} );
|
|
||||||
|
|
||||||
const step = useSelect( ( select ) => {
|
|
||||||
return select( STORE_NAME ).getPersistentData().step || 0;
|
|
||||||
} );
|
|
||||||
|
|
||||||
const completed = useSelect( ( select ) => {
|
|
||||||
return select( STORE_NAME ).getPersistentData().completed;
|
|
||||||
} );
|
|
||||||
|
|
||||||
const setDetailAndPersist = async ( setter, value ) => {
|
|
||||||
setter( value );
|
|
||||||
await persist();
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
isReady,
|
isReady,
|
||||||
step,
|
step,
|
||||||
setStep: ( value ) => setDetailAndPersist( setOnboardingStep, value ),
|
setStep: ( value ) => setDetailAndPersist( setOnboardingStep, value ),
|
||||||
completed,
|
completed,
|
||||||
setCompleted: ( state ) => setDetailAndPersist( setCompleted, state ),
|
setCompleted: ( state ) => setDetailAndPersist( setCompleted, state ),
|
||||||
|
isSandboxMode,
|
||||||
|
setSandboxMode: ( state ) =>
|
||||||
|
setDetailAndPersist( setSandboxMode, state ),
|
||||||
|
isManualConnectionMode,
|
||||||
|
setManualConnectionMode: ( state ) =>
|
||||||
|
setDetailAndPersist( setManualConnectionMode, state ),
|
||||||
|
clientId,
|
||||||
|
setClientId: ( value ) => setDetailAndPersist( setClientId, value ),
|
||||||
|
clientSecret,
|
||||||
|
setClientSecret: ( value ) =>
|
||||||
|
setDetailAndPersist( setClientSecret, value ),
|
||||||
|
isCasualSeller,
|
||||||
|
setIsCasualSeller: ( value ) =>
|
||||||
|
setDetailAndPersist( setIsCasualSeller, value ),
|
||||||
|
products,
|
||||||
|
toggleProduct,
|
||||||
|
flags,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useOnboardingStepWelcome = () => {
|
||||||
|
const {
|
||||||
|
isSaving,
|
||||||
|
isSandboxMode,
|
||||||
|
setSandboxMode,
|
||||||
|
isManualConnectionMode,
|
||||||
|
setManualConnectionMode,
|
||||||
|
clientId,
|
||||||
|
setClientId,
|
||||||
|
clientSecret,
|
||||||
|
setClientSecret,
|
||||||
|
} = useOnboardingDetails();
|
||||||
|
|
||||||
|
return {
|
||||||
|
isSaving,
|
||||||
|
isSandboxMode,
|
||||||
|
setSandboxMode,
|
||||||
|
isManualConnectionMode,
|
||||||
|
setManualConnectionMode,
|
||||||
|
clientId,
|
||||||
|
setClientId,
|
||||||
|
clientSecret,
|
||||||
|
setClientSecret,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useOnboardingStepBusiness = () => {
|
||||||
|
const { isCasualSeller, setIsCasualSeller } = useOnboardingDetails();
|
||||||
|
|
||||||
|
return { isCasualSeller, setIsCasualSeller };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useOnboardingStepProducts = () => {
|
||||||
|
const { products, toggleProduct } = useOnboardingDetails();
|
||||||
|
|
||||||
|
return { products, toggleProduct };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useOnboardingStep = () => {
|
||||||
|
const { isReady, step, setStep, completed, setCompleted, flags } =
|
||||||
|
useOnboardingDetails();
|
||||||
|
|
||||||
|
return { isReady, step, setStep, completed, setCompleted, flags };
|
||||||
|
};
|
||||||
|
|
||||||
export const useManualConnect = () => {
|
export const useManualConnect = () => {
|
||||||
const connectManual = async ( clientId, clientSecret, isSandboxMode ) => {
|
const connectManual = async ( clientId, clientSecret, isSandboxMode ) => {
|
||||||
return await apiFetch( {
|
return await apiFetch( {
|
||||||
|
|
|
@ -3,6 +3,8 @@ import ACTION_TYPES from './action-types';
|
||||||
const defaultState = {
|
const defaultState = {
|
||||||
isReady: false,
|
isReady: false,
|
||||||
isSaving: false,
|
isSaving: false,
|
||||||
|
|
||||||
|
// Data persisted to the server.
|
||||||
data: {
|
data: {
|
||||||
completed: false,
|
completed: false,
|
||||||
step: 0,
|
step: 0,
|
||||||
|
@ -10,6 +12,12 @@ const defaultState = {
|
||||||
useManualConnection: false,
|
useManualConnection: false,
|
||||||
clientId: '',
|
clientId: '',
|
||||||
clientSecret: '',
|
clientSecret: '',
|
||||||
|
isCasualSeller: null, // null value will uncheck both options in the UI.
|
||||||
|
products: [],
|
||||||
|
},
|
||||||
|
|
||||||
|
// Read only values, provided by the server.
|
||||||
|
flags: {
|
||||||
canUseCasualSelling: false,
|
canUseCasualSelling: false,
|
||||||
canUseVaulting: false,
|
canUseVaulting: false,
|
||||||
canUseCardPayments: false,
|
canUseCardPayments: false,
|
||||||
|
@ -40,6 +48,10 @@ export const onboardingReducer = (
|
||||||
};
|
};
|
||||||
|
|
||||||
switch ( type ) {
|
switch ( type ) {
|
||||||
|
// Reset store to initial state.
|
||||||
|
case ACTION_TYPES.RESET_ONBOARDING:
|
||||||
|
return setPersistent( defaultState.data );
|
||||||
|
|
||||||
// Transient data.
|
// Transient data.
|
||||||
case ACTION_TYPES.SET_ONBOARDING_IS_READY:
|
case ACTION_TYPES.SET_ONBOARDING_IS_READY:
|
||||||
return setTransient( { isReady: action.isReady } );
|
return setTransient( { isReady: action.isReady } );
|
||||||
|
@ -49,7 +61,13 @@ export const onboardingReducer = (
|
||||||
|
|
||||||
// Persistent data.
|
// Persistent data.
|
||||||
case ACTION_TYPES.SET_ONBOARDING_DETAILS:
|
case ACTION_TYPES.SET_ONBOARDING_DETAILS:
|
||||||
return setPersistent( action.payload );
|
const newState = setPersistent( action.payload.data );
|
||||||
|
|
||||||
|
if ( action.payload.flags ) {
|
||||||
|
newState.flags = { ...newState.flags, ...action.payload.flags };
|
||||||
|
}
|
||||||
|
|
||||||
|
return newState;
|
||||||
|
|
||||||
case ACTION_TYPES.SET_ONBOARDING_COMPLETED:
|
case ACTION_TYPES.SET_ONBOARDING_COMPLETED:
|
||||||
return setPersistent( { completed: action.completed } );
|
return setPersistent( { completed: action.completed } );
|
||||||
|
@ -71,6 +89,12 @@ export const onboardingReducer = (
|
||||||
useManualConnection: action.useManualConnection,
|
useManualConnection: action.useManualConnection,
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
case ACTION_TYPES.SET_IS_CASUAL_SELLER:
|
||||||
|
return setPersistent( { isCasualSeller: action.isCasualSeller } );
|
||||||
|
|
||||||
|
case ACTION_TYPES.SET_PRODUCTS:
|
||||||
|
return setPersistent( { products: action.products } );
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,10 @@ export const getPersistentData = ( state ) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getTransientData = ( state ) => {
|
export const getTransientData = ( state ) => {
|
||||||
const { data, ...transientState } = getOnboardingState( state );
|
const { data, flags, ...transientState } = getOnboardingState( state );
|
||||||
return transientState || EMPTY_OBJ;
|
return transientState || EMPTY_OBJ;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getFlags = ( state ) => {
|
||||||
|
return getOnboardingState( state ).flags || EMPTY_OBJ;
|
||||||
|
};
|
||||||
|
|
|
@ -44,9 +44,14 @@ export const initStore = () => {
|
||||||
|
|
||||||
console.groupEnd();
|
console.groupEnd();
|
||||||
};
|
};
|
||||||
|
window.ppcpSettings.resetStore = () => {
|
||||||
|
wp.data.dispatch( STORE_NAME ).resetOnboarding();
|
||||||
|
wp.data.dispatch( STORE_NAME ).persist();
|
||||||
|
};
|
||||||
window.ppcpSettings.startOnboarding = () => {
|
window.ppcpSettings.startOnboarding = () => {
|
||||||
wp.data.dispatch( STORE_NAME ).setCompleted( false );
|
wp.data.dispatch( STORE_NAME ).setCompleted( false );
|
||||||
wp.data.dispatch( STORE_NAME ).setOnboardingStep( 0 );
|
wp.data.dispatch( STORE_NAME ).setOnboardingStep( 0 );
|
||||||
|
wp.data.dispatch( STORE_NAME ).persist();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
/* eslint-enable no-console */
|
/* eslint-enable no-console */
|
||||||
|
|
|
@ -27,11 +27,12 @@ return array(
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
'settings.data.onboarding' => static function ( ContainerInterface $container ) : OnboardingProfile {
|
'settings.data.onboarding' => static function ( ContainerInterface $container ) : OnboardingProfile {
|
||||||
$can_use_casual_selling = false;
|
$can_use_casual_selling = $container->get( 'settings.casual-selling.eligible' );
|
||||||
$can_use_vaulting = $container->has( 'save-payment-methods.eligible' ) && $container->get( 'save-payment-methods.eligible' );
|
$can_use_vaulting = $container->has( 'save-payment-methods.eligible' ) && $container->get( 'save-payment-methods.eligible' );
|
||||||
$can_use_card_payments = $container->has( 'card-fields.eligible' ) && $container->get( 'card-fields.eligible' );
|
$can_use_card_payments = $container->has( 'card-fields.eligible' ) && $container->get( 'card-fields.eligible' );
|
||||||
|
|
||||||
// Card payments are disabled for this plugin when WooPayments is active.
|
// Card payments are disabled for this plugin when WooPayments is active.
|
||||||
|
// TODO: Move this condition to the card-fields.eligible service?
|
||||||
if ( class_exists( '\WC_Payments' ) ) {
|
if ( class_exists( '\WC_Payments' ) ) {
|
||||||
$can_use_card_payments = false;
|
$can_use_card_payments = false;
|
||||||
}
|
}
|
||||||
|
@ -48,4 +49,23 @@ return array(
|
||||||
'settings.rest.connect_manual' => static function ( ContainerInterface $container ) : ConnectManualRestEndpoint {
|
'settings.rest.connect_manual' => static function ( ContainerInterface $container ) : ConnectManualRestEndpoint {
|
||||||
return new ConnectManualRestEndpoint();
|
return new ConnectManualRestEndpoint();
|
||||||
},
|
},
|
||||||
|
'settings.casual-selling.supported-countries' => static function ( ContainerInterface $container ) : array {
|
||||||
|
// TODO: This is a dummy list, while we wait for the official eligibility list.
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'US',
|
||||||
|
'CA',
|
||||||
|
'DE',
|
||||||
|
'ES',
|
||||||
|
'AT',
|
||||||
|
'CH',
|
||||||
|
'NL',
|
||||||
|
);
|
||||||
|
},
|
||||||
|
'settings.casual-selling.eligible' => static function ( ContainerInterface $container ) : bool {
|
||||||
|
$country = $container->get( 'api.shop.country' );
|
||||||
|
$eligible_countries = $container->get( 'settings.casual-selling.supported-countries' );
|
||||||
|
|
||||||
|
return in_array( $country, $eligible_countries, true );
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -89,10 +89,38 @@ abstract class AbstractDataModel {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$setter = "set_$key";
|
$setter = $this->get_setter_name( $key );
|
||||||
if ( method_exists( $this, $setter ) ) {
|
|
||||||
|
if ( $setter && method_exists( $this, $setter ) ) {
|
||||||
$this->$setter( $value );
|
$this->$setter( $value );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a setter method name for a given key, stripping the prefix from
|
||||||
|
* boolean fields (is_, use_, has_).
|
||||||
|
*
|
||||||
|
* @param int|string $field_key The key for which to generate a setter name.
|
||||||
|
*
|
||||||
|
* @return string The generated setter method name.
|
||||||
|
*/
|
||||||
|
private function get_setter_name( $field_key ) : string {
|
||||||
|
if ( ! is_string( $field_key ) ) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$prefixes_to_strip = array( 'is_', 'use_', 'has_' );
|
||||||
|
$stripped_key = $field_key;
|
||||||
|
|
||||||
|
foreach ( $prefixes_to_strip as $prefix ) {
|
||||||
|
if ( str_starts_with( $field_key, $prefix ) ) {
|
||||||
|
$stripped_key = substr( $field_key, strlen( $prefix ) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $stripped_key ? "set_$stripped_key" : '';
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,13 @@ class OnboardingProfile extends AbstractDataModel {
|
||||||
*/
|
*/
|
||||||
protected const OPTION_KEY = 'woocommerce-ppcp-data-onboarding';
|
protected const OPTION_KEY = 'woocommerce-ppcp-data-onboarding';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of customization flags, provided by the server (read-only).
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected array $flags = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
|
@ -45,9 +52,9 @@ class OnboardingProfile extends AbstractDataModel {
|
||||||
) {
|
) {
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|
||||||
$this->data['can_use_casual_selling'] = $can_use_casual_selling;
|
$this->flags['can_use_casual_selling'] = $can_use_casual_selling;
|
||||||
$this->data['can_use_vaulting'] = $can_use_vaulting;
|
$this->flags['can_use_vaulting'] = $can_use_vaulting;
|
||||||
$this->data['can_use_card_payments'] = $can_use_card_payments;
|
$this->flags['can_use_card_payments'] = $can_use_card_payments;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,9 +70,8 @@ class OnboardingProfile extends AbstractDataModel {
|
||||||
'use_manual_connection' => false,
|
'use_manual_connection' => false,
|
||||||
'client_id' => '',
|
'client_id' => '',
|
||||||
'client_secret' => '',
|
'client_secret' => '',
|
||||||
'can_use_casual_selling' => null,
|
'is_casual_seller' => null,
|
||||||
'can_use_vaulting' => null,
|
'products' => array(),
|
||||||
'can_use_card_payments' => null,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +118,7 @@ class OnboardingProfile extends AbstractDataModel {
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function get_use_sandbox() : bool {
|
public function get_sandbox() : bool {
|
||||||
return (bool) $this->data['use_sandbox'];
|
return (bool) $this->data['use_sandbox'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +127,7 @@ class OnboardingProfile extends AbstractDataModel {
|
||||||
*
|
*
|
||||||
* @param bool $use_sandbox Whether to use sandbox mode.
|
* @param bool $use_sandbox Whether to use sandbox mode.
|
||||||
*/
|
*/
|
||||||
public function set_use_sandbox( bool $use_sandbox ) : void {
|
public function set_sandbox( bool $use_sandbox ) : void {
|
||||||
$this->data['use_sandbox'] = $use_sandbox;
|
$this->data['use_sandbox'] = $use_sandbox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,7 +136,7 @@ class OnboardingProfile extends AbstractDataModel {
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function get_use_manual_connection() : bool {
|
public function get_manual_connection() : bool {
|
||||||
return (bool) $this->data['use_manual_connection'];
|
return (bool) $this->data['use_manual_connection'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,7 +145,7 @@ class OnboardingProfile extends AbstractDataModel {
|
||||||
*
|
*
|
||||||
* @param bool $use_manual_connection Whether to use manual connection.
|
* @param bool $use_manual_connection Whether to use manual connection.
|
||||||
*/
|
*/
|
||||||
public function set_use_manual_connection( bool $use_manual_connection ) : void {
|
public function set_manual_connection( bool $use_manual_connection ) : void {
|
||||||
$this->data['use_manual_connection'] = $use_manual_connection;
|
$this->data['use_manual_connection'] = $use_manual_connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,29 +186,47 @@ class OnboardingProfile extends AbstractDataModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets whether casual selling can be used.
|
* Gets the casual seller flag.
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool|null
|
||||||
*/
|
*/
|
||||||
public function get_can_use_casual_selling() : bool {
|
public function get_casual_seller() : ?bool {
|
||||||
return (bool) $this->data['can_use_casual_selling'];
|
return $this->data['is_casual_seller'];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets whether vaulting can be used.
|
* Sets the casual-seller flag.
|
||||||
*
|
*
|
||||||
* @return bool
|
* @param bool|null $casual_seller Whether the merchant uses a personal account for selling.
|
||||||
*/
|
*/
|
||||||
public function get_can_use_vaulting() : bool {
|
public function set_casual_seller( ?bool $casual_seller ) : void {
|
||||||
return (bool) $this->data['can_use_vaulting'];
|
$this->data['is_casual_seller'] = $casual_seller;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets whether Credit Card payments can be used.
|
* Gets the active product types for this store.
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return string[]
|
||||||
*/
|
*/
|
||||||
public function get_can_use_card_payments() : bool {
|
public function get_products() : array {
|
||||||
return (bool) $this->data['can_use_card_payments'];
|
return $this->data['products'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the list of active product types.
|
||||||
|
*
|
||||||
|
* @param string[] $products Any of ['virtual'|'physical'|'subscriptions'].
|
||||||
|
*/
|
||||||
|
public function set_products( array $products ) : void {
|
||||||
|
$this->data['products'] = $products;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the list of read-only customization flags
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function get_flags() : array {
|
||||||
|
return $this->flags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,17 +65,29 @@ class OnboardingRestEndpoint extends RestEndpoint {
|
||||||
'js_name' => 'clientSecret',
|
'js_name' => 'clientSecret',
|
||||||
'sanitize' => 'sanitize_text_field',
|
'sanitize' => 'sanitize_text_field',
|
||||||
),
|
),
|
||||||
|
'is_casual_seller' => array(
|
||||||
|
'js_name' => 'isCasualSeller',
|
||||||
|
'sanitize' => 'to_boolean',
|
||||||
|
),
|
||||||
|
'products' => array(
|
||||||
|
'js_name' => 'products',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map the internal flags to JS names.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private array $flag_map = array(
|
||||||
'can_use_casual_selling' => array(
|
'can_use_casual_selling' => array(
|
||||||
'js_name' => 'canUseCasualSelling',
|
'js_name' => 'canUseCasualSelling',
|
||||||
'sanitize' => 'read_only',
|
|
||||||
),
|
),
|
||||||
'can_use_vaulting' => array(
|
'can_use_vaulting' => array(
|
||||||
'js_name' => 'canUseVaulting',
|
'js_name' => 'canUseVaulting',
|
||||||
'sanitize' => 'read_only',
|
|
||||||
),
|
),
|
||||||
'can_use_card_payments' => array(
|
'can_use_card_payments' => array(
|
||||||
'js_name' => 'canUseCardPayments',
|
'js_name' => 'canUseCardPayments',
|
||||||
'sanitize' => 'read_only',
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -86,6 +98,8 @@ class OnboardingRestEndpoint extends RestEndpoint {
|
||||||
*/
|
*/
|
||||||
public function __construct( OnboardingProfile $profile ) {
|
public function __construct( OnboardingProfile $profile ) {
|
||||||
$this->profile = $profile;
|
$this->profile = $profile;
|
||||||
|
|
||||||
|
$this->field_map['products']['sanitize'] = fn( $list ) => array_map( 'sanitize_text_field', $list );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -128,7 +142,17 @@ class OnboardingRestEndpoint extends RestEndpoint {
|
||||||
$this->field_map
|
$this->field_map
|
||||||
);
|
);
|
||||||
|
|
||||||
return rest_ensure_response( $js_data );
|
$js_flags = $this->sanitize_for_javascript(
|
||||||
|
$this->profile->get_flags(),
|
||||||
|
$this->flag_map
|
||||||
|
);
|
||||||
|
|
||||||
|
return rest_ensure_response(
|
||||||
|
array(
|
||||||
|
'data' => $js_data,
|
||||||
|
'flags' => $js_flags,
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -65,7 +65,7 @@ class RestEndpoint extends WC_REST_Controller {
|
||||||
|
|
||||||
if ( null === $sanitation_cb ) {
|
if ( null === $sanitation_cb ) {
|
||||||
$sanitized[ $key ] = $value;
|
$sanitized[ $key ] = $value;
|
||||||
} elseif ( method_exists( $this, $sanitation_cb ) ) {
|
} elseif ( is_string( $sanitation_cb ) && method_exists( $this, $sanitation_cb ) ) {
|
||||||
$sanitized[ $key ] = $this->{$sanitation_cb}( $value );
|
$sanitized[ $key ] = $this->{$sanitation_cb}( $value );
|
||||||
} elseif ( is_callable( $sanitation_cb ) ) {
|
} elseif ( is_callable( $sanitation_cb ) ) {
|
||||||
$sanitized[ $key ] = $sanitation_cb( $value );
|
$sanitized[ $key ] = $sanitation_cb( $value );
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue