@@ -38,7 +38,7 @@ const StepBusiness = ( {
) }
icon="icon-business-casual-seller.svg"
name={ BUSINESS_RADIO_GROUP_NAME }
- value={ CASUAL_SELLER_CHECKBOX_VALUE }
+ value={ BUSINESS_TYPES.CASUAL_SELLER }
changeCallback={ setBusinessCategory }
currentValue={ businessCategory }
checked={
@@ -69,7 +69,7 @@ const StepBusiness = ( {
) }
icon="icon-business-business.svg"
name={ BUSINESS_RADIO_GROUP_NAME }
- value={ BUSINESS_CHECKBOX_VALUE }
+ value={ BUSINESS_TYPES.BUSINESS }
currentValue={ businessCategory }
changeCallback={ setBusinessCategory }
checked={
diff --git a/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/StepProducts.js b/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/StepProducts.js
index efc477d2b..c2ce87012 100644
--- a/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/StepProducts.js
+++ b/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/StepProducts.js
@@ -4,6 +4,9 @@ import { __ } from '@wordpress/i18n';
import SelectBox from '../../ReusableComponents/SelectBox';
import SelectBoxWrapper from '../../ReusableComponents/SelectBoxWrapper';
import { useState } from '@wordpress/element';
+import { PRODUCT_TYPES } from '../../../data/constants';
+
+const PRODUCTS_CHECKBOX_GROUP_NAME = 'products';
const StepProducts = ( {
setStep,
@@ -12,10 +15,6 @@ const StepProducts = ( {
setCompleted,
} ) => {
const [ products, setProducts ] = useState( [] );
- const PRODUCTS_CHECKBOX_GROUP_NAME = 'products';
- const VIRTUAL_CHECKBOX_VALUE = 'virtual';
- const PHYSICAL_CHECKBOX_VALUE = 'physical';
- const SUBSCRIPTIONS_CHECKBOX_VALUE = 'subscriptions';
return (
@@ -35,7 +34,7 @@ const StepProducts = ( {
) }
icon="icon-product-virtual.svg"
name={ PRODUCTS_CHECKBOX_GROUP_NAME }
- value={ VIRTUAL_CHECKBOX_VALUE }
+ value={ PRODUCT_TYPES.VIRTUAL }
changeCallback={ setProducts }
currentValue={ products }
type="checkbox"
@@ -78,7 +77,7 @@ const StepProducts = ( {
) }
icon="icon-product-physical.svg"
name={ PRODUCTS_CHECKBOX_GROUP_NAME }
- value={ PHYSICAL_CHECKBOX_VALUE }
+ value={ PRODUCT_TYPES.PHYSICAL }
changeCallback={ setProducts }
currentValue={ products }
type="checkbox"
@@ -106,7 +105,7 @@ const StepProducts = ( {
) }
icon="icon-product-subscription.svg"
name={ PRODUCTS_CHECKBOX_GROUP_NAME }
- value={ SUBSCRIPTIONS_CHECKBOX_VALUE }
+ value={ PRODUCT_TYPES.SUBSCRIPTIONS }
changeCallback={ setProducts }
currentValue={ products }
type="checkbox"
diff --git a/modules/ppcp-settings/resources/js/data/constants.js b/modules/ppcp-settings/resources/js/data/constants.js
index 61ebf948e..e6f8f9de5 100644
--- a/modules/ppcp-settings/resources/js/data/constants.js
+++ b/modules/ppcp-settings/resources/js/data/constants.js
@@ -1,2 +1,13 @@
export const NAMESPACE = '/wc/v3/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',
+};
From fcf2a972a71b4f3f694a18158e079f174c6cbebb Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Wed, 30 Oct 2024 17:17:36 +0100
Subject: [PATCH 05/15] =?UTF-8?q?=F0=9F=91=94=20Introduce=20new=20hook=20d?=
=?UTF-8?q?etails?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../resources/js/data/onboarding/hooks.js | 24 ++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/modules/ppcp-settings/resources/js/data/onboarding/hooks.js b/modules/ppcp-settings/resources/js/data/onboarding/hooks.js
index 66bfec24a..5db54f95c 100644
--- a/modules/ppcp-settings/resources/js/data/onboarding/hooks.js
+++ b/modules/ppcp-settings/resources/js/data/onboarding/hooks.js
@@ -1,5 +1,5 @@
import { useSelect, useDispatch } from '@wordpress/data';
-import { STORE_NAME } from '../constants';
+import { PRODUCT_TYPES, STORE_NAME } from '../constants';
export const useOnboardingDetails = () => {
const {
@@ -8,6 +8,8 @@ export const useOnboardingDetails = () => {
setManualConnectionMode,
setClientId,
setClientSecret,
+ setIsCasualSeller,
+ setProducts,
} = useDispatch( STORE_NAME );
// Transient accessors.
@@ -32,6 +34,21 @@ export const useOnboardingDetails = () => {
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 ) => {
setter( value );
await persist();
@@ -50,6 +67,11 @@ export const useOnboardingDetails = () => {
setDetailAndPersist( setSandboxMode, state ),
setManualConnectionMode: ( state ) =>
setDetailAndPersist( setManualConnectionMode, state ),
+ isCasualSeller,
+ setIsCasualSeller: ( value ) =>
+ setDetailAndPersist( setIsCasualSeller, value ),
+ products,
+ toggleProduct,
};
};
From cff9919c7810a891785eb6be8db68cdbf1280945 Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Wed, 30 Oct 2024 17:19:47 +0100
Subject: [PATCH 06/15] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Consolidate=20hook?=
=?UTF-8?q?=20props?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../resources/js/data/onboarding/hooks.js | 56 +++++++++----------
1 file changed, 26 insertions(+), 30 deletions(-)
diff --git a/modules/ppcp-settings/resources/js/data/onboarding/hooks.js b/modules/ppcp-settings/resources/js/data/onboarding/hooks.js
index 5db54f95c..b5f478afb 100644
--- a/modules/ppcp-settings/resources/js/data/onboarding/hooks.js
+++ b/modules/ppcp-settings/resources/js/data/onboarding/hooks.js
@@ -4,6 +4,8 @@ import { PRODUCT_TYPES, STORE_NAME } from '../constants';
export const useOnboardingDetails = () => {
const {
persist,
+ setOnboardingStep,
+ setCompleted,
setSandboxMode,
setManualConnectionMode,
setClientId,
@@ -17,7 +19,19 @@ export const useOnboardingDetails = () => {
return select( STORE_NAME ).getTransientData().isSaving;
}, [] );
+ const isReady = useSelect( ( select ) => {
+ return select( STORE_NAME ).getTransientData().isReady;
+ } );
+
// 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 ) => {
return select( STORE_NAME ).getPersistentData().clientId;
}, [] );
@@ -56,17 +70,22 @@ export const useOnboardingDetails = () => {
return {
isSaving,
+ isReady,
+ step,
+ setStep: ( value ) => setDetailAndPersist( setOnboardingStep, value ),
+ completed,
+ 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 ),
- setSandboxMode: ( state ) =>
- setDetailAndPersist( setSandboxMode, state ),
- setManualConnectionMode: ( state ) =>
- setDetailAndPersist( setManualConnectionMode, state ),
isCasualSeller,
setIsCasualSeller: ( value ) =>
setDetailAndPersist( setIsCasualSeller, value ),
@@ -76,31 +95,8 @@ export const useOnboardingDetails = () => {
};
export const useOnboardingStep = () => {
- const { persist, setOnboardingStep, setCompleted } =
- useDispatch( STORE_NAME );
+ const { isReady, step, setStep, completed, setCompleted } =
+ useOnboardingDetails();
- 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,
- step,
- setStep: ( value ) => setDetailAndPersist( setOnboardingStep, value ),
- completed,
- setCompleted: ( state ) => setDetailAndPersist( setCompleted, state ),
- };
+ return { isReady, step, setStep, completed, setCompleted };
};
From 6e3664ade80771ae0c4af0484dbd1c2f5cccbf02 Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Wed, 30 Oct 2024 17:33:48 +0100
Subject: [PATCH 07/15] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Extract=20onboarding?=
=?UTF-8?q?=20state=20to=20custom=20hooks?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Screens/Onboarding/StepBusiness.js | 37 ++++++++++-------
.../Screens/Onboarding/StepProducts.js | 10 ++---
.../Screens/Onboarding/StepWelcome.js | 4 +-
.../resources/js/data/onboarding/hooks.js | 40 ++++++++++++++++++-
4 files changed, 69 insertions(+), 22 deletions(-)
diff --git a/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/StepBusiness.js b/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/StepBusiness.js
index fe7deeb90..1c38ecc86 100644
--- a/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/StepBusiness.js
+++ b/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/StepBusiness.js
@@ -3,7 +3,7 @@ import SelectBoxWrapper from '../../ReusableComponents/SelectBoxWrapper.js';
import SelectBox from '../../ReusableComponents/SelectBox.js';
import { __ } from '@wordpress/i18n';
import PaymentMethodIcons from '../../ReusableComponents/PaymentMethodIcons';
-import { useState } from '@wordpress/element';
+import { useOnboardingStepBusiness } from '../../../data';
import Navigation from '../../ReusableComponents/Navigation';
import { BUSINESS_TYPES } from '../../../data/constants';
@@ -15,7 +15,21 @@ const StepBusiness = ( {
stepperOrder,
setCompleted,
} ) => {
- const [ businessCategory, setBusinessCategory ] = useState( null );
+ const { isCasualSeller, setIsCasualSeller } = useOnboardingStepBusiness();
+
+ const handleSellerTypeChange = ( value ) => {
+ setIsCasualSeller( BUSINESS_TYPES.CASUAL_SELLER === value );
+ };
+
+ const getCurrentValue = () => {
+ if ( isCasualSeller === null ) {
+ return '';
+ }
+
+ return isCasualSeller
+ ? BUSINESS_TYPES.CASUAL_SELLER
+ : BUSINESS_TYPES.BUSINESS;
+ };
return (
@@ -39,12 +53,9 @@ const StepBusiness = ( {
icon="icon-business-casual-seller.svg"
name={ BUSINESS_RADIO_GROUP_NAME }
value={ BUSINESS_TYPES.CASUAL_SELLER }
- changeCallback={ setBusinessCategory }
- currentValue={ businessCategory }
- checked={
- businessCategory ===
- { CASUAL_SELLER_CHECKBOX_VALUE }
- }
+ changeCallback={ handleSellerTypeChange }
+ currentValue={ getCurrentValue() }
+ checked={ isCasualSeller === true }
type="radio"
>
businessCategory !== null }
+ canProceeedCallback={ () => isCasualSeller !== null }
/>
diff --git a/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/StepProducts.js b/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/StepProducts.js
index c2ce87012..fecdc6029 100644
--- a/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/StepProducts.js
+++ b/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/StepProducts.js
@@ -3,7 +3,7 @@ import Navigation from '../../ReusableComponents/Navigation';
import { __ } from '@wordpress/i18n';
import SelectBox from '../../ReusableComponents/SelectBox';
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';
@@ -14,7 +14,7 @@ const StepProducts = ( {
stepperOrder,
setCompleted,
} ) => {
- const [ products, setProducts ] = useState( [] );
+ const { products, toggleProduct } = useOnboardingStepProducts();
return (
@@ -35,7 +35,7 @@ const StepProducts = ( {
icon="icon-product-virtual.svg"
name={ PRODUCTS_CHECKBOX_GROUP_NAME }
value={ PRODUCT_TYPES.VIRTUAL }
- changeCallback={ setProducts }
+ changeCallback={ toggleProduct }
currentValue={ products }
type="checkbox"
>
@@ -78,7 +78,7 @@ const StepProducts = ( {
icon="icon-product-physical.svg"
name={ PRODUCTS_CHECKBOX_GROUP_NAME }
value={ PRODUCT_TYPES.PHYSICAL }
- changeCallback={ setProducts }
+ changeCallback={ toggleProduct }
currentValue={ products }
type="checkbox"
>
@@ -106,7 +106,7 @@ const StepProducts = ( {
icon="icon-product-subscription.svg"
name={ PRODUCTS_CHECKBOX_GROUP_NAME }
value={ PRODUCT_TYPES.SUBSCRIPTIONS }
- changeCallback={ setProducts }
+ changeCallback={ toggleProduct }
currentValue={ products }
type="checkbox"
>
diff --git a/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/StepWelcome.js b/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/StepWelcome.js
index b6a5bb097..368b4d9c9 100644
--- a/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/StepWelcome.js
+++ b/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/StepWelcome.js
@@ -4,7 +4,7 @@ import { Button, TextControl } from '@wordpress/components';
import PaymentMethodIcons from '../../ReusableComponents/PaymentMethodIcons';
import SettingsToggleBlock from '../../ReusableComponents/SettingsToggleBlock';
import Separator from '../../ReusableComponents/Separator';
-import { useOnboardingDetails } from '../../../data';
+import { useOnboardingStepWelcome } from '../../../data';
import DataStoreControl from '../../ReusableComponents/DataStoreControl';
const StepWelcome = ( { setStep, currentStep } ) => {
@@ -84,7 +84,7 @@ const WelcomeForm = () => {
setClientId,
clientSecret,
setClientSecret,
- } = useOnboardingDetails();
+ } = useOnboardingStepWelcome();
const advancedUsersDescription = sprintf(
// translators: %s: Link to PayPal REST application guide
diff --git a/modules/ppcp-settings/resources/js/data/onboarding/hooks.js b/modules/ppcp-settings/resources/js/data/onboarding/hooks.js
index b5f478afb..9481e047d 100644
--- a/modules/ppcp-settings/resources/js/data/onboarding/hooks.js
+++ b/modules/ppcp-settings/resources/js/data/onboarding/hooks.js
@@ -1,7 +1,7 @@
import { useSelect, useDispatch } from '@wordpress/data';
import { PRODUCT_TYPES, STORE_NAME } from '../constants';
-export const useOnboardingDetails = () => {
+const useOnboardingDetails = () => {
const {
persist,
setOnboardingStep,
@@ -94,6 +94,44 @@ export const useOnboardingDetails = () => {
};
};
+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 } =
useOnboardingDetails();
From e28b6e35aa2b73a7bcc04f5d31dd42a3729b30bd Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Wed, 30 Oct 2024 18:52:10 +0100
Subject: [PATCH 08/15] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Rename=20boolean=20g?=
=?UTF-8?q?etters/setters=20for=20data=20models?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
To make the function names more semantic
---
.../src/Data/AbstractDataModel.php | 32 +++++++++++++++++--
.../src/Data/OnboardingProfile.php | 8 ++---
2 files changed, 34 insertions(+), 6 deletions(-)
diff --git a/modules/ppcp-settings/src/Data/AbstractDataModel.php b/modules/ppcp-settings/src/Data/AbstractDataModel.php
index 1d711cbe5..780ad40bd 100644
--- a/modules/ppcp-settings/src/Data/AbstractDataModel.php
+++ b/modules/ppcp-settings/src/Data/AbstractDataModel.php
@@ -89,10 +89,38 @@ abstract class AbstractDataModel {
continue;
}
- $setter = "set_$key";
- if ( method_exists( $this, $setter ) ) {
+ $setter = $this->get_setter_name( $key );
+
+ if ( $setter && method_exists( $this, $setter ) ) {
$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" : '';
+ }
+
}
diff --git a/modules/ppcp-settings/src/Data/OnboardingProfile.php b/modules/ppcp-settings/src/Data/OnboardingProfile.php
index b0f4b5121..df894e85a 100644
--- a/modules/ppcp-settings/src/Data/OnboardingProfile.php
+++ b/modules/ppcp-settings/src/Data/OnboardingProfile.php
@@ -116,7 +116,7 @@ class OnboardingProfile extends AbstractDataModel {
*
* @return bool
*/
- public function get_use_sandbox() : bool {
+ public function get_sandbox() : bool {
return (bool) $this->data['use_sandbox'];
}
@@ -125,7 +125,7 @@ class OnboardingProfile extends AbstractDataModel {
*
* @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;
}
@@ -134,7 +134,7 @@ class OnboardingProfile extends AbstractDataModel {
*
* @return bool
*/
- public function get_use_manual_connection() : bool {
+ public function get_manual_connection() : bool {
return (bool) $this->data['use_manual_connection'];
}
@@ -143,7 +143,7 @@ class OnboardingProfile extends AbstractDataModel {
*
* @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;
}
From 4102ba285b601dc2eb5a24b1521452360eab2f39 Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Wed, 30 Oct 2024 18:55:07 +0100
Subject: [PATCH 09/15] =?UTF-8?q?=F0=9F=91=94=20Add=20server-side=20onboar?=
=?UTF-8?q?ding=20profile=20details?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/Data/OnboardingProfile.php | 38 +++++++++++++++++++
.../src/Endpoint/OnboardingRestEndpoint.php | 7 ++++
2 files changed, 45 insertions(+)
diff --git a/modules/ppcp-settings/src/Data/OnboardingProfile.php b/modules/ppcp-settings/src/Data/OnboardingProfile.php
index df894e85a..e1f9e16b4 100644
--- a/modules/ppcp-settings/src/Data/OnboardingProfile.php
+++ b/modules/ppcp-settings/src/Data/OnboardingProfile.php
@@ -70,6 +70,8 @@ class OnboardingProfile extends AbstractDataModel {
'use_manual_connection' => false,
'client_id' => '',
'client_secret' => '',
+ 'is_casual_seller' => null,
+ 'products' => array(),
);
}
@@ -183,6 +185,42 @@ class OnboardingProfile extends AbstractDataModel {
$this->data['client_secret'] = sanitize_text_field( $client_secret );
}
+ /**
+ * Gets the casual seller flag.
+ *
+ * @return bool|null
+ */
+ public function get_casual_seller() : ?bool {
+ return $this->data['is_casual_seller'];
+ }
+
+ /**
+ * Sets the casual-seller flag.
+ *
+ * @param bool|null $casual_seller Whether the merchant uses a personal account for selling.
+ */
+ public function set_casual_seller( ?bool $casual_seller ) : void {
+ $this->data['is_casual_seller'] = $casual_seller;
+ }
+
+ /**
+ * Gets the active product types for this store.
+ *
+ * @return string[]
+ */
+ public function get_products() : array {
+ 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
*
diff --git a/modules/ppcp-settings/src/Endpoint/OnboardingRestEndpoint.php b/modules/ppcp-settings/src/Endpoint/OnboardingRestEndpoint.php
index bd8e57eee..afb2d7f1f 100644
--- a/modules/ppcp-settings/src/Endpoint/OnboardingRestEndpoint.php
+++ b/modules/ppcp-settings/src/Endpoint/OnboardingRestEndpoint.php
@@ -65,6 +65,13 @@ class OnboardingRestEndpoint extends RestEndpoint {
'js_name' => 'clientSecret',
'sanitize' => 'sanitize_text_field',
),
+ 'is_casual_seller' => array(
+ 'js_name' => 'isCasualSeller',
+ 'sanitize' => 'to_boolean',
+ ),
+ 'products' => array(
+ 'js_name' => 'products',
+ ),
);
/**
From 37beb591d5b17365a120b25eb9e2e8074554d948 Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Wed, 30 Oct 2024 18:57:51 +0100
Subject: [PATCH 10/15] =?UTF-8?q?=F0=9F=94=92=EF=B8=8F=20Add=20array=20san?=
=?UTF-8?q?itizer=20for=20products=20field?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
modules/ppcp-settings/src/Endpoint/OnboardingRestEndpoint.php | 2 ++
modules/ppcp-settings/src/Endpoint/RestEndpoint.php | 2 +-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/modules/ppcp-settings/src/Endpoint/OnboardingRestEndpoint.php b/modules/ppcp-settings/src/Endpoint/OnboardingRestEndpoint.php
index afb2d7f1f..6c59b1622 100644
--- a/modules/ppcp-settings/src/Endpoint/OnboardingRestEndpoint.php
+++ b/modules/ppcp-settings/src/Endpoint/OnboardingRestEndpoint.php
@@ -98,6 +98,8 @@ class OnboardingRestEndpoint extends RestEndpoint {
*/
public function __construct( OnboardingProfile $profile ) {
$this->profile = $profile;
+
+ $this->field_map['products']['sanitize'] = fn( $list ) => array_map( 'sanitize_text_field', $list );
}
/**
diff --git a/modules/ppcp-settings/src/Endpoint/RestEndpoint.php b/modules/ppcp-settings/src/Endpoint/RestEndpoint.php
index 9bb98dfac..08191276b 100644
--- a/modules/ppcp-settings/src/Endpoint/RestEndpoint.php
+++ b/modules/ppcp-settings/src/Endpoint/RestEndpoint.php
@@ -65,7 +65,7 @@ class RestEndpoint extends WC_REST_Controller {
if ( null === $sanitation_cb ) {
$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 );
} elseif ( is_callable( $sanitation_cb ) ) {
$sanitized[ $key ] = $sanitation_cb( $value );
From 847bce3510afee90a87e9c77c01095ddebee7a55 Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Thu, 31 Oct 2024 14:44:45 +0100
Subject: [PATCH 11/15] =?UTF-8?q?=F0=9F=8E=A8=20Standardize=20imports,=20r?=
=?UTF-8?q?emove=20unneccesary=20consts?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../js/Components/ReusableComponents/Container.js | 3 ---
.../js/Components/Screens/Onboarding/Onboarding.js | 12 +++++-------
.../js/Components/Screens/Onboarding/StepBusiness.js | 6 +++---
.../js/Components/Screens/Onboarding/StepWelcome.js | 2 +-
4 files changed, 9 insertions(+), 14 deletions(-)
diff --git a/modules/ppcp-settings/resources/js/Components/ReusableComponents/Container.js b/modules/ppcp-settings/resources/js/Components/ReusableComponents/Container.js
index e6b83e691..fd91017bf 100644
--- a/modules/ppcp-settings/resources/js/Components/ReusableComponents/Container.js
+++ b/modules/ppcp-settings/resources/js/Components/ReusableComponents/Container.js
@@ -1,6 +1,3 @@
-export const PAGE_ONBOARDING = 'onboarding';
-export const PAGE_SETTINGS = 'settings';
-
const Container = ( { isCard = true, page, children } ) => {
let className = 'ppcp-r-container';
diff --git a/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/Onboarding.js b/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/Onboarding.js
index 195e3a089..712b17f86 100644
--- a/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/Onboarding.js
+++ b/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/Onboarding.js
@@ -1,16 +1,14 @@
-import Container, {
- PAGE_ONBOARDING,
-} from '../../ReusableComponents/Container.js';
-import StepWelcome from './StepWelcome.js';
-import StepBusiness from './StepBusiness.js';
-import StepProducts from './StepProducts.js';
+import Container from '../../ReusableComponents/Container';
+import StepWelcome from './StepWelcome';
+import StepBusiness from './StepBusiness';
+import StepProducts from './StepProducts';
import { useOnboardingStep } from '../../../data';
const Onboarding = () => {
const { step, setStep, setCompleted } = useOnboardingStep();
return (
-
+
Date: Thu, 31 Oct 2024 15:03:25 +0100
Subject: [PATCH 12/15] =?UTF-8?q?=F0=9F=8F=97=EF=B8=8F=20Add=20conditional?=
=?UTF-8?q?=20routing=20to=20onboarding=20steps?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../js/Components/Screens/Onboarding/Onboarding.js | 11 +++++------
.../Screens/Onboarding/availableSteps.js | 14 ++++++++++++++
.../resources/js/data/onboarding/hooks.js | 11 +++++++++--
3 files changed, 28 insertions(+), 8 deletions(-)
create mode 100644 modules/ppcp-settings/resources/js/Components/Screens/Onboarding/availableSteps.js
diff --git a/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/Onboarding.js b/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/Onboarding.js
index 712b17f86..212776a0a 100644
--- a/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/Onboarding.js
+++ b/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/Onboarding.js
@@ -1,11 +1,9 @@
import Container from '../../ReusableComponents/Container';
-import StepWelcome from './StepWelcome';
-import StepBusiness from './StepBusiness';
-import StepProducts from './StepProducts';
import { useOnboardingStep } from '../../../data';
+import { getSteps } from './availableSteps';
const Onboarding = () => {
- const { step, setStep, setCompleted } = useOnboardingStep();
+ const { step, setStep, setCompleted, flags } = useOnboardingStep();
return (
@@ -14,14 +12,15 @@ const Onboarding = () => {
currentStep={ step }
setStep={ setStep }
setCompleted={ setCompleted }
+ flags={ flags }
/>
);
};
-const OnboardingStep = ( { currentStep, setStep, setCompleted } ) => {
- const stepperOrder = [ StepWelcome, StepBusiness, StepProducts ];
+const OnboardingStep = ( { currentStep, setStep, setCompleted, flags } ) => {
+ const stepperOrder = getSteps( flags );
const isValidStep = ( step ) =>
typeof step === 'number' &&
diff --git a/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/availableSteps.js b/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/availableSteps.js
new file mode 100644
index 000000000..dbb25f57e
--- /dev/null
+++ b/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/availableSteps.js
@@ -0,0 +1,14 @@
+import StepWelcome from './StepWelcome';
+import StepBusiness from './StepBusiness';
+import StepProducts from './StepProducts';
+
+export const getSteps = ( flags ) => {
+ console.log( 'Step Flags:', flags );
+ const allSteps = [ StepWelcome, StepBusiness, StepProducts ];
+
+ if ( ! flags.canUseCasualSelling ) {
+ return allSteps.filter( ( step ) => step !== StepBusiness );
+ }
+
+ return allSteps;
+};
diff --git a/modules/ppcp-settings/resources/js/data/onboarding/hooks.js b/modules/ppcp-settings/resources/js/data/onboarding/hooks.js
index 9481e047d..e21cc5016 100644
--- a/modules/ppcp-settings/resources/js/data/onboarding/hooks.js
+++ b/modules/ppcp-settings/resources/js/data/onboarding/hooks.js
@@ -1,5 +1,6 @@
import { useSelect, useDispatch } from '@wordpress/data';
import { PRODUCT_TYPES, STORE_NAME } from '../constants';
+import { getFlags } from './selectors';
const useOnboardingDetails = () => {
const {
@@ -23,6 +24,11 @@ const useOnboardingDetails = () => {
return select( STORE_NAME ).getTransientData().isReady;
} );
+ // Read-only flags.
+ const flags = useSelect( ( select ) => {
+ return select( STORE_NAME ).getFlags();
+ } );
+
// Persistent accessors.
const step = useSelect( ( select ) => {
return select( STORE_NAME ).getPersistentData().step || 0;
@@ -91,6 +97,7 @@ const useOnboardingDetails = () => {
setDetailAndPersist( setIsCasualSeller, value ),
products,
toggleProduct,
+ flags,
};
};
@@ -133,8 +140,8 @@ export const useOnboardingStepProducts = () => {
};
export const useOnboardingStep = () => {
- const { isReady, step, setStep, completed, setCompleted } =
+ const { isReady, step, setStep, completed, setCompleted, flags } =
useOnboardingDetails();
- return { isReady, step, setStep, completed, setCompleted };
+ return { isReady, step, setStep, completed, setCompleted, flags };
};
From 05657b8b27d7996c7cc179ef9c54ff0eae42e070 Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Thu, 31 Oct 2024 15:11:36 +0100
Subject: [PATCH 13/15] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Refactor=20Onboardin?=
=?UTF-8?q?g=20component=20and=20step=20handling?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Screens/Onboarding/Onboarding.js | 43 ++++++++-----------
1 file changed, 17 insertions(+), 26 deletions(-)
diff --git a/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/Onboarding.js b/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/Onboarding.js
index 212776a0a..20c18fc33 100644
--- a/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/Onboarding.js
+++ b/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/Onboarding.js
@@ -2,44 +2,35 @@ import Container from '../../ReusableComponents/Container';
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 { step, setStep, setCompleted, flags } = useOnboardingStep();
+ const steps = getSteps( flags );
+
+ const CurrentStepComponent = getCurrentStep( step, steps );
return (
-
);
};
-const OnboardingStep = ( { currentStep, setStep, setCompleted, flags } ) => {
- const stepperOrder = getSteps( flags );
-
- 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 (
-
- );
-};
-
export default Onboarding;
From 654b2e40e99456686be869ba7929642542e95121 Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Thu, 31 Oct 2024 16:17:15 +0100
Subject: [PATCH 14/15] =?UTF-8?q?=E2=9C=A8=20Add=20casual=20selling=20elig?=
=?UTF-8?q?ibility=20check?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
modules/ppcp-settings/services.php | 28 ++++++++++++++++++++++++----
1 file changed, 24 insertions(+), 4 deletions(-)
diff --git a/modules/ppcp-settings/services.php b/modules/ppcp-settings/services.php
index f34257f79..3620957f9 100644
--- a/modules/ppcp-settings/services.php
+++ b/modules/ppcp-settings/services.php
@@ -14,7 +14,7 @@ use WooCommerce\PayPalCommerce\Settings\Endpoint\OnboardingRestEndpoint;
use WooCommerce\PayPalCommerce\Settings\Data\OnboardingProfile;
return array(
- 'settings.url' => static function ( ContainerInterface $container ) : string {
+ 'settings.url' => static function ( ContainerInterface $container ) : string {
/**
* The path cannot be false.
*
@@ -25,12 +25,13 @@ return array(
dirname( realpath( __FILE__ ), 3 ) . '/woocommerce-paypal-payments.php'
);
},
- 'settings.data.onboarding' => static function ( ContainerInterface $container ) : OnboardingProfile {
- $can_use_casual_selling = false;
+ 'settings.data.onboarding' => static function ( ContainerInterface $container ) : OnboardingProfile {
+ $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_card_payments = $container->has( 'card-fields.eligible' ) && $container->get( 'card-fields.eligible' );
// 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' ) ) {
$can_use_card_payments = false;
}
@@ -41,7 +42,26 @@ return array(
$can_use_card_payments
);
},
- 'settings.rest.onboarding' => static function ( ContainerInterface $container ) : OnboardingRestEndpoint {
+ 'settings.rest.onboarding' => static function ( ContainerInterface $container ) : OnboardingRestEndpoint {
return new OnboardingRestEndpoint( $container->get( 'settings.data.onboarding' ) );
},
+ '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 );
+ },
);
From a881838cf44eca7ec2848513c6519afec98572b2 Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Thu, 31 Oct 2024 16:22:07 +0100
Subject: [PATCH 15/15] =?UTF-8?q?=F0=9F=94=87=20Remove=20console.log=20fro?=
=?UTF-8?q?m=20getSteps=20function?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../resources/js/Components/Screens/Onboarding/availableSteps.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/availableSteps.js b/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/availableSteps.js
index dbb25f57e..32034ec57 100644
--- a/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/availableSteps.js
+++ b/modules/ppcp-settings/resources/js/Components/Screens/Onboarding/availableSteps.js
@@ -3,7 +3,6 @@ import StepBusiness from './StepBusiness';
import StepProducts from './StepProducts';
export const getSteps = ( flags ) => {
- console.log( 'Step Flags:', flags );
const allSteps = [ StepWelcome, StepBusiness, StepProducts ];
if ( ! flags.canUseCasualSelling ) {