From 14d25b5f887c4fb7e5b4879d61f431c6a651136e Mon Sep 17 00:00:00 2001
From: arunshenoy99
Date: Mon, 17 Apr 2023 22:07:47 +0530
Subject: [PATCH 1/3] switch to commerce flow when selling is top priority
---
includes/Data/Data.php | 29 +--
includes/Data/Flows.php | 13 ++
includes/Data/Plugins.php | 14 +-
includes/Data/Preview.php | 55 +++--
includes/RestApi/FlowController.php | 214 +++++-------------
includes/Services/FlowService.php | 202 +++++++++++++++++
includes/Services/PluginInstaller.php | 131 ++++++-----
.../TaskManagers/PluginInstallTaskManager.php | 127 +++++++----
src/OnboardingSPA/components/Content/index.js | 28 +--
.../Loaders/Step/Ecommerce/contents.js | 22 ++
.../Loaders/Step/Ecommerce/index.js | 19 ++
.../Sidebar/components/LearnMore/Menu.js | 2 +-
.../components/SkipButton/index.js | 14 +-
.../StateHandlers/Ecommerce/contents.js | 17 +-
.../StateHandlers/Ecommerce/index.js | 12 +-
.../components/StateHandlers/Flow/index.js | 90 ++++++++
.../data/routes/ecommerce-flow.js | 9 +-
.../pages/Steps/TopPriority/index.js | 74 ++++--
src/OnboardingSPA/utils/api/flow.js | 12 +
src/OnboardingSPA/utils/index.js | 23 +-
src/constants.js | 1 +
21 files changed, 738 insertions(+), 370 deletions(-)
create mode 100644 includes/Services/FlowService.php
create mode 100644 src/OnboardingSPA/components/Loaders/Step/Ecommerce/contents.js
create mode 100644 src/OnboardingSPA/components/Loaders/Step/Ecommerce/index.js
create mode 100644 src/OnboardingSPA/components/StateHandlers/Flow/index.js
diff --git a/includes/Data/Data.php b/includes/Data/Data.php
index ea316b139..bba53189e 100644
--- a/includes/Data/Data.php
+++ b/includes/Data/Data.php
@@ -80,6 +80,15 @@ public static function current_plan() {
}
}
+ $current_flow = Flows::get_flow_from_top_priority();
+ if ( false !== $current_flow ) {
+ return array(
+ 'flow' => 'ecommerce',
+ 'subtype' => 'wc_priority',
+ 'type' => null,
+ );
+ }
+
return array(
'flow' => Flows::get_default_flow(),
'subtype' => null,
@@ -93,24 +102,8 @@ public static function current_plan() {
* @return string
*/
public static function current_flow() {
-
- $current_flow = Flows::get_flow_from_params();
- if ( false !== $current_flow ) {
- return $current_flow;
- }
-
- $current_flow = Flows::get_flow_from_plugins();
- if ( false !== $current_flow ) {
- return $current_flow;
- }
-
- $customer_data = self::customer_data();
- $current_flow = Flows::get_flow_from_customer_data( $customer_data );
- if ( false !== $current_flow ) {
- return $current_flow;
- }
-
- return Flows::get_default_flow();
+ $current_plan = self::current_plan();
+ return $current_plan['flow'];
}
/**
diff --git a/includes/Data/Flows.php b/includes/Data/Flows.php
index 128b78bce..7a531aabf 100644
--- a/includes/Data/Flows.php
+++ b/includes/Data/Flows.php
@@ -1,6 +1,7 @@
'jetpack/jetpack.php',
),
'woocommerce' => array(
- 'approved' => true,
- 'path' => 'woocommerce/woocommerce.php',
+ 'approved' => true,
+ 'path' => 'woocommerce/woocommerce.php',
+ 'post_install_callback' => array( __CLASS__, 'wc_prevent_redirect_on_activation' ),
),
'wordpress-seo' => array(
'approved' => true,
@@ -420,4 +421,13 @@ public static function get_init() {
return $init_list;
}
+ /**
+ * Prevent redirect to woo wizard after activation of woocommerce.
+ *
+ * @return void
+ */
+ public static function wc_prevent_redirect_on_activation() {
+ \delete_transient( '_wc_activation_redirect' );
+ }
+
}
diff --git a/includes/Data/Preview.php b/includes/Data/Preview.php
index c4f7930b8..886994f35 100644
--- a/includes/Data/Preview.php
+++ b/includes/Data/Preview.php
@@ -4,12 +4,25 @@
use NewfoldLabs\WP\Module\Onboarding\Services\PluginInstaller;
use NewfoldLabs\WP\Module\Onboarding\Services\ThemeInstaller;
+/**
+ * Class Preview
+ */
final class Preview {
-
+ /**
+ * Convert boolean to plugin/theme status.
+ *
+ * @param boolean $boolean The boolean value.
+ * @return string
+ */
private static function boolean_to_status( $boolean ) {
- return $boolean ? 'activated' : 'init';
+ return $boolean ? 'activated' : 'init';
}
+ /**
+ * Map of pre requisites to show the live preview successfully for a flow.
+ *
+ * @return array
+ */
private static function pre_requisites() {
$theme_map = Themes::get();
return array(
@@ -30,21 +43,35 @@ private static function pre_requisites() {
);
}
- public static function get_pre_requisites() {
- $pre_requisites = self::pre_requisites();
- return isset( $pre_requisites[ Data::current_flow() ] ) ? $pre_requisites[ Data::current_flow() ] : array();
+ /**
+ * Get the pre requisites for a given flow.
+ *
+ * @param string $flow A valid Onboarding flow.
+ * @return array
+ */
+ public static function get_pre_requisites( $flow = null ) {
+ $pre_requisites = self::pre_requisites();
+ if ( ! isset( $flow ) ) {
+ $flow = Data::current_flow();
+ }
+ return isset( $pre_requisites[ $flow ] ) ? $pre_requisites[ $flow ] : array();
}
+ /**
+ * Get all the settings necessary to load the live preview
+ *
+ * @return array
+ */
public static function get_settings() {
- $block_editor_context = new \WP_Block_Editor_Context( array( 'name' => 'core/edit-site' ) );
- $custom_settings = array(
- 'siteUrl' => \site_url(),
- );
+ $block_editor_context = new \WP_Block_Editor_Context( array( 'name' => 'core/edit-site' ) );
+ $custom_settings = array(
+ 'siteUrl' => \site_url(),
+ );
- return array(
- 'settings' => \get_block_editor_settings( $custom_settings, $block_editor_context ),
- 'globalStyles' => \wp_get_global_styles(),
- 'preRequisites' => self::get_pre_requisites(),
- );
+ return array(
+ 'settings' => \get_block_editor_settings( $custom_settings, $block_editor_context ),
+ 'globalStyles' => \wp_get_global_styles(),
+ 'preRequisites' => self::get_pre_requisites(),
+ );
}
}
diff --git a/includes/RestApi/FlowController.php b/includes/RestApi/FlowController.php
index 363ebd113..34fed044b 100644
--- a/includes/RestApi/FlowController.php
+++ b/includes/RestApi/FlowController.php
@@ -1,11 +1,8 @@
namespace,
+ $this->rest_base . '/switch',
+ array(
+ array(
+ 'methods' => \WP_REST_Server::CREATABLE,
+ 'callback' => array( $this, 'switch' ),
+ 'permission_callback' => array( Permissions::class, 'rest_is_authorized_admin' ),
+ 'args' => $this->get_switch_args(),
+ ),
+ )
+ );
}
/**
- * Fetch onboarding flow details from database.
+ * Get the valid request params for the switch endpoint.
*
- * @param \WP_REST_Request $request Request model.
+ * @return array
+ */
+ public function get_switch_args() {
+ return array(
+ 'flow' => array(
+ 'required' => true,
+ 'type' => 'string',
+ 'sanitize_callback' => 'sanitize_text_field',
+ ),
+ );
+ }
+
+ /**
+ * Get Onboarding flow data.
*
* @return \WP_REST_Response
*/
- public function get_onboarding_flow_data( \WP_REST_Request $request ) {
- // check if data is available in the database if not then fetch the default dataset
- $result = $this->read_details_from_wp_options();
- if ( ! $result ) {
- $result = Flows::get_data();
- $result['createdAt'] = time();
- // update default data if flow type is ecommerce
- $result = $this->update_default_data_for_ecommerce( $result );
- $this->save_details_to_wp_options( $result );
- }
-
+ public function get_onboarding_flow_data() {
return new \WP_REST_Response(
- $result,
+ FlowService::get_flow_data(),
200
);
}
/**
- * Save / Update onboarding flow details to database.
+ * Update the Onboarding flow data.
*
- * @param \WP_REST_Request $request Request model.
+ * @param \WP_REST_Request $request The incoming request.
*
- * @return \WP_REST_Response|\WP_Error
+ * @return \WP_Error|\WP_REST_Response
*/
public function save_onboarding_flow_data( \WP_REST_Request $request ) {
- $flow_data = array();
- $params = json_decode( $request->get_body(), true );
-
- if ( is_null( $params ) ) {
- return new \WP_Error(
- 'no_post_data',
- 'No Data Provided',
- array( 'status' => 404 )
- );
- }
-
- $flow_data = $this->read_details_from_wp_options();
- if ( ! $flow_data ) {
- $flow_data = Flows::get_data();
- $flow_data['createdAt'] = time();
- // update default data if flow type is ecommerce
- $flow_data = $this->update_default_data_for_ecommerce( $flow_data );
- $this->save_details_to_wp_options( $flow_data );
- }
-
- foreach ( $params as $key => $param ) {
- $value = $this->array_search_key( $key, $flow_data );
- if ( false === $value ) {
- return new \WP_Error(
- 'wrong_param_provided',
- "Wrong Parameter Provided : $key",
- array( 'status' => 404 )
- );
- }
- }
-
- $flow_data = array_replace_recursive( $flow_data, $params );
-
- // update timestamp once data is updated
- $flow_data['updatedAt'] = time();
-
- // Update Blog Information from Basic Info
- if ( ( ! empty( $flow_data['data']['blogName'] ) ) ) {
- \update_option( Options::get_option_name( 'blog_name', false ), $flow_data['data']['blogName'] );
- }
-
- if ( ( ! empty( $flow_data['data']['blogDescription'] ) ) ) {
- \update_option( Options::get_option_name( 'blog_description', false ), $flow_data['data']['blogDescription'] );
- }
-
- if ( ( ! empty( $flow_data['data']['siteLogo'] ) ) && ! empty( $flow_data['data']['siteLogo']['id'] ) ) {
- \update_option( Options::get_option_name( 'site_icon', false ), $flow_data['data']['siteLogo']['id'] );
- \update_option( Options::get_option_name( 'site_logo', false ), $flow_data['data']['siteLogo']['id'] );
- } else {
- \update_option( Options::get_option_name( 'site_icon', false ), 0 );
- \delete_option( Options::get_option_name( 'site_logo', false ) );
- }
+ $params = json_decode( $request->get_body(), true );
- // save data to database
- if ( ! $this->update_wp_options_data_in_database( $flow_data ) ) {
- return new \WP_Error(
- 'database_update_failed',
- 'There was an error saving the data',
- array( 'status' => 404 )
- );
+ $flow_data = FlowService::update_flow_data( $params );
+ if ( \is_wp_error( $flow_data ) ) {
+ return $flow_data;
}
return new \WP_REST_Response(
@@ -162,82 +120,7 @@ public function save_onboarding_flow_data( \WP_REST_Request $request ) {
}
/**
- * Check the current flow type and update default data if flowtype is ecommerce.
- *
- * @param array $data default blueprint flow data.
- *
- * @return array
- */
- private function update_default_data_for_ecommerce( $data ) {
- // get current flow type
- $flow_type = Data::current_flow();
- if ( 'ecommerce' === $flow_type ) {
- // update default data with ecommerce data
- $data['data']['topPriority']['priority1'] = 'selling';
- $data['data']['siteType'] = array(
- 'label' => '',
- 'referTo' => 'business',
- );
- }
- return $data;
- }
-
- /**
- * Read onboarding flow options from database
- *
- * @return array
- */
- public function read_details_from_wp_options() {
- return \get_option( Options::get_option_name( 'flow' ) );
- }
-
- /**
- * Add onboarding flow options
- *
- * @param array $data default blueprint flow data.
- *
- * @return array
- */
- private function save_details_to_wp_options( $data ) {
- return \add_option( Options::get_option_name( 'flow' ), $data );
- }
-
- /**
- * Update onboarding flow options
- *
- * @param array $data default blueprint flow data.
- *
- * @return array
- */
- private function update_wp_options_data_in_database( $data ) {
- return \update_option( Options::get_option_name( 'flow' ), $data );
- }
-
- /**
- * Function to search for key in array recursively with case sensitive exact match
- *
- * @param array $needle_key specific key in flow data.
- * @param array $array WP Options Data.
- *
- * @return boolean
- */
- private function array_search_key( $needle_key, $array ) {
- foreach ( $array as $key => $value ) {
- if ( strcmp( $key, $needle_key ) === 0 ) {
- return true;
- }
- if ( is_array( $value ) ) {
- $result = $this->array_search_key( $needle_key, $value );
- if ( false !== $result ) {
- return $result;
- }
- }
- }
- return false;
- }
-
- /**
- * Flow completion API for child theme generation, verify child theme and publish site pages
+ * Flow completion API for child theme generation, verify child theme and publish site pages.
*
* @return \WP_REST_Response
*/
@@ -264,4 +147,23 @@ public function complete() {
201
);
}
+
+ /**
+ * Switch the Onboarding flow.
+ *
+ * @param \WP_REST_Request $request The incoming switch request.
+ * @return \WP_Error|\WP_REST_Response
+ */
+ public function switch( \WP_REST_Request $request ) {
+ $flow = $request->get_param( 'flow' );
+ $status = FlowService::switch_flow( $flow );
+ if ( \is_wp_error( $status ) ) {
+ return $status;
+ }
+
+ return new \WP_REST_Response(
+ array(),
+ 200
+ );
+ }
}
diff --git a/includes/Services/FlowService.php b/includes/Services/FlowService.php
new file mode 100644
index 000000000..e5edc09c5
--- /dev/null
+++ b/includes/Services/FlowService.php
@@ -0,0 +1,202 @@
+ 404 )
+ );
+ }
+
+ $flow_data = self::get_flow_data();
+
+ foreach ( $params as $key => $param ) {
+ $value = self::array_search_key( $key, $flow_data );
+ if ( false === $value ) {
+ return new \WP_Error(
+ 'wrong_param_provided',
+ "Wrong Parameter Provided : $key",
+ array( 'status' => 404 )
+ );
+ }
+ }
+
+ $flow_data = array_replace_recursive( $flow_data, $params );
+
+ // Update timestamp everytime the Onboarding flow data is updated.
+ $flow_data['updatedAt'] = time();
+
+ // Update Blog Information from Basic Info
+ if ( ( ! empty( $flow_data['data']['blogName'] ) ) ) {
+ \update_option( Options::get_option_name( 'blog_name', false ), $flow_data['data']['blogName'] );
+ }
+
+ if ( ( ! empty( $flow_data['data']['blogDescription'] ) ) ) {
+ \update_option( Options::get_option_name( 'blog_description', false ), $flow_data['data']['blogDescription'] );
+ }
+
+ if ( ( ! empty( $flow_data['data']['siteLogo'] ) ) && ! empty( $flow_data['data']['siteLogo']['id'] ) ) {
+ \update_option( Options::get_option_name( 'site_icon', false ), $flow_data['data']['siteLogo']['id'] );
+ \update_option( Options::get_option_name( 'site_logo', false ), $flow_data['data']['siteLogo']['id'] );
+ } else {
+ \update_option( Options::get_option_name( 'site_icon', false ), 0 );
+ \delete_option( Options::get_option_name( 'site_logo', false ) );
+ }
+
+ if ( ! self::update_data_in_wp_option( $flow_data ) ) {
+ return new \WP_Error(
+ 'database_update_failed',
+ 'There was an error saving the data',
+ array( 'status' => 404 )
+ );
+ }
+
+ return $flow_data;
+ }
+
+ /**
+ * Switch the Onboarding flow.
+ *
+ * @param string $flow A valid Onboarding flow for a brand.
+ * @return \WP_Error|boolean
+ */
+ public static function switch_flow( $flow ) {
+ // Get all the enabled flows for a brand.
+ $enabled_flows = Flows::get_flows();
+ // If the request flow does not exist or is not enabled then return an error.
+ if ( ! isset( $enabled_flows[ $flow ] ) || true !== $enabled_flows[ $flow ] ) {
+ return new \WP_Error(
+ 'nfd_onboarding_error',
+ 'Flow not enabled.',
+ array( 'status' => 400 )
+ );
+ }
+
+ // Reset the Plugin Install Status and Queue.
+ PluginInstallTaskManager::reset_install_status();
+
+ // Get the pre requisites for a flow.
+ $pre_requisites = Preview::get_pre_requisites( $flow );
+ if ( ! isset( $pre_requisites ) || ! isset( $pre_requisites['plugins'] ) ) {
+ return true;
+ }
+
+ // Install and activate all the required plugins.
+ foreach ( $pre_requisites['plugins'] as $plugin => $active ) {
+ // Skip if the plugin installation if it is already active.
+ if ( 'activated' === $active ) {
+ continue;
+ }
+
+ $plugin_install_task = new PluginInstallTask( $plugin, true );
+ $status = $plugin_install_task->execute();
+
+ if ( \is_wp_error( $status ) ) {
+ return $status;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Read Onboarding flow data from the wp_option.
+ *
+ * @return array
+ */
+ public static function read_data_from_wp_option() {
+ return \get_option( Options::get_option_name( 'flow' ), false );
+ }
+
+ /**
+ * Update flow data params if the current flow is ecommerce.
+ *
+ * @param array $data The flow data.
+ *
+ * @return array
+ */
+ private static function update_data_for_ecommerce( $data ) {
+ // get current flow type
+ $flow_type = Data::current_flow();
+ if ( 'ecommerce' === $flow_type ) {
+ // update default data with ecommerce data
+ $data['data']['topPriority']['priority1'] = 'selling';
+ $data['data']['siteType'] = array(
+ 'label' => '',
+ 'referTo' => 'business',
+ );
+ }
+ return $data;
+ }
+
+ /**
+ * Update Onboarding flow data in the wp_option.
+ *
+ * @param array $data default blueprint flow data.
+ *
+ * @return array
+ */
+ private static function update_data_in_wp_option( $data ) {
+ return \update_option( Options::get_option_name( 'flow' ), $data );
+ }
+
+ /**
+ * Search for $needle_key in $array recursively.
+ *
+ * @param string $needle_key The key to be searched for.
+ * @param array $array The array in which the search occurs.
+ *
+ * @return boolean
+ */
+ private static function array_search_key( $needle_key, $array ) {
+ foreach ( $array as $key => $value ) {
+ if ( strcmp( $key, $needle_key ) === 0 ) {
+ return true;
+ }
+ if ( is_array( $value ) ) {
+ $result = self::array_search_key( $needle_key, $value );
+ if ( false !== $result ) {
+ return $result;
+ }
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/includes/Services/PluginInstaller.php b/includes/Services/PluginInstaller.php
index 5dc155e39..86423afd1 100644
--- a/includes/Services/PluginInstaller.php
+++ b/includes/Services/PluginInstaller.php
@@ -2,10 +2,20 @@
namespace NewfoldLabs\WP\Module\Onboarding\Services;
use NewfoldLabs\WP\Module\Onboarding\Data\Plugins;
-use NewfoldLabs\WP\Module\Onboarding\Data\Options;
+/**
+ * Class PluginInstaller
+ */
class PluginInstaller {
+ /**
+ * Install a whitelisted plugin.
+ *
+ * @param string $plugin The plugin slug from Plugins.php.
+ * @param boolean $activate Whether to activate the plugin after install.
+ *
+ * @return \WP_Error|\WP_REST_Response
+ */
public static function install( $plugin, $activate ) {
$plugins_list = Plugins::get();
@@ -36,23 +46,23 @@ public static function install( $plugin, $activate ) {
// If it is not a zip URL then check if it is an approved slug.
$plugin = \sanitize_text_field( $plugin );
if ( self::is_nfd_slug( $plugin ) ) {
- // [TODO] Better handle mu-plugins and direct file downloads.
- if ( $plugin === 'nfd_slug_endurance_page_cache' ) {
+ // [TODO] Better handle mu-plugins and direct file downloads.
+ if ( 'nfd_slug_endurance_page_cache' === $plugin ) {
return self::install_endurance_page_cache();
}
- $plugin_path = $plugins_list['nfd_slugs'][ $plugin ]['path'];
+ $plugin_path = $plugins_list['nfd_slugs'][ $plugin ]['path'];
if ( ! self::is_plugin_installed( $plugin_path ) ) {
- $status = self::install_from_zip( $plugins_list['nfd_slugs'][ $plugin ]['url'], $activate );
+ $status = self::install_from_zip( $plugins_list['nfd_slugs'][ $plugin ]['url'], $activate );
if ( \is_wp_error( $status ) ) {
return $status;
}
}
if ( $activate && ! \is_plugin_active( $plugin_path ) ) {
- $status = \activate_plugin( $plugin_path );
+ $status = \activate_plugin( $plugin_path );
if ( \is_wp_error( $status ) ) {
- $status->add_data( array( 'status' => 500 ) );
+ $status->add_data( array( 'status' => 500 ) );
- return $status;
+ return $status;
}
}
return new \WP_REST_Response(
@@ -69,20 +79,26 @@ public static function install( $plugin, $activate ) {
);
}
- $plugin_path = $plugins_list['wp_slugs'][ $plugin ]['path'];
+ $plugin_path = $plugins_list['wp_slugs'][ $plugin ]['path'];
+ $plugin_post_install_callback = isset( $plugins_list['wp_slugs'][ $plugin ]['post_install_callback'] )
+ ? $plugins_list['wp_slugs'][ $plugin ]['post_install_callback']
+ : false;
if ( ! self::is_plugin_installed( $plugin_path ) ) {
- $status = self::install_from_wordpress( $plugin, $activate );
+ $status = self::install_from_wordpress( $plugin, $activate );
if ( \is_wp_error( $status ) ) {
- return $status;
+ return $status;
}
}
if ( $activate && ! \is_plugin_active( $plugin_path ) ) {
- $status = \activate_plugin( $plugin_path );
+ $status = \activate_plugin( $plugin_path );
if ( \is_wp_error( $status ) ) {
- $status->add_data( array( 'status' => 500 ) );
+ $status->add_data( array( 'status' => 500 ) );
- return $status;
+ return $status;
+ }
+ if ( is_callable( $plugin_post_install_callback ) ) {
+ $plugin_post_install_callback();
}
}
@@ -93,12 +109,14 @@ public static function install( $plugin, $activate ) {
}
/**
- * @param string $slug Representing the wordpress.org slug.
+ * Install a plugin from wordpress.org.
*
+ * @param string $plugin The wp_slug to install.
+ * @param boolean $activate Whether to activate the plugin after install.
* @return \WP_REST_Response|\WP_Error
*/
public static function install_from_wordpress( $plugin, $activate ) {
- require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
+ require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
$api = \plugins_api(
'plugin_information',
@@ -121,9 +139,9 @@ public static function install_from_wordpress( $plugin, $activate ) {
return $api;
}
- $status = self::install_from_zip( $api->download_link, $activate );
+ $status = self::install_from_zip( $api->download_link, $activate );
if ( \is_wp_error( $status ) ) {
- return $status;
+ return $status;
}
return new \WP_REST_Response(
@@ -133,8 +151,10 @@ public static function install_from_wordpress( $plugin, $activate ) {
}
/**
- * @param string $url URL to the zip for the plugin.
+ * Install the plugin from a custom ZIP.
*
+ * @param string $url The ZIP URL to install from.
+ * @param boolean $activate Whether to activate the plugin after install.
* @return \WP_REST_Response|\WP_Error
*/
public static function install_from_zip( $url, $activate ) {
@@ -192,11 +212,11 @@ public static function install_from_zip( $url, $activate ) {
}
if ( $activate && ! \is_plugin_active( $plugin_file ) ) {
- $status = \activate_plugin( $plugin_file );
+ $status = \activate_plugin( $plugin_file );
if ( \is_wp_error( $status ) ) {
- $status->add_data( array( 'status' => 500 ) );
+ $status->add_data( array( 'status' => 500 ) );
- return $status;
+ return $status;
}
}
@@ -207,25 +227,23 @@ public static function install_from_zip( $url, $activate ) {
}
/**
- * @param string $plugin Slug of the plugin.
- *
* Checks if a given slug is a valid nfd_slug. Ref: includes/Data/Plugins.php for nfd_slug.
*
+ * @param string $plugin Slug of the plugin.
* @return boolean
*/
public static function is_nfd_slug( $plugin ) {
- $plugins_list = Plugins::get();
+ $plugins_list = Plugins::get();
if ( isset( $plugins_list['nfd_slugs'][ $plugin ]['approved'] ) ) {
- return true;
+ return true;
}
- return false;
+ return false;
}
/**
- * @param string $plugin_path Path to the plugin's header file.
- *
* Determines if a plugin has already been installed.
*
+ * @param string $plugin_path Path to the plugin's header file.
* @return boolean
*/
public static function is_plugin_installed( $plugin_path ) {
@@ -241,50 +259,51 @@ public static function is_plugin_installed( $plugin_path ) {
}
/**
- * @param string $plugin
+ * Get the type of plugin slug. Ref: includes/Data/Plugins.php for the different types.
*
- * @return string Type of plugin. Ref: includes/Data/Plugins.php for the different types.
+ * @param string $plugin The plugin slug to retrieve the type.
+ * @return string
*/
public static function get_plugin_type( $plugin ) {
if ( \wp_http_validate_url( $plugin ) ) {
- return 'urls';
+ return 'urls';
}
if ( self::is_nfd_slug( $plugin ) ) {
- return 'nfd_slugs';
+ return 'nfd_slugs';
}
- return 'wp_slugs';
+ return 'wp_slugs';
}
/**
- * @param string $plugin
- * @param string $plugin_type
+ * Get the path to the Plugin's header file.
*
- * @return string Path to the Plugin's header file.
+ * @param string $plugin The slug of the plugin.
+ * @param string $plugin_type The type of plugin.
+ * @return string
*/
public static function get_plugin_path( $plugin, $plugin_type ) {
- $plugin_list = Plugins::get();
- return $plugin_list[ $plugin_type ][ $plugin ]['path'];
+ $plugin_list = Plugins::get();
+ return $plugin_list[ $plugin_type ][ $plugin ]['path'];
}
/**
- * @param string $plugin
- * @param string $activate
- *
* Checks if a plugin with the given slug and activation criteria already exists.
*
+ * @param string $plugin The slug of the plugin to check for
+ * @param boolean $activate The activation criteria.
* @return boolean
*/
public static function exists( $plugin, $activate ) {
- $plugin_type = self::get_plugin_type( $plugin );
- $plugin_path = self::get_plugin_path( $plugin, $plugin_type );
+ $plugin_type = self::get_plugin_type( $plugin );
+ $plugin_path = self::get_plugin_path( $plugin, $plugin_type );
if ( ! self::is_plugin_installed( $plugin_path ) ) {
- return false;
+ return false;
}
if ( $activate && ! \is_plugin_active( $plugin_path ) ) {
- return false;
+ return false;
}
- return true;
+ return true;
}
/**
@@ -303,11 +322,11 @@ public static function install_endurance_page_cache() {
);
}
- global $wp_filesystem;
+ global $wp_filesystem;
- $plugin_list = Plugins::get();
- $plugin_url = $plugin_list['nfd_slugs']['nfd_slug_endurance_page_cache']['url'];
- $plugin_path = $plugin_list['nfd_slugs']['nfd_slug_endurance_page_cache']['path'];
+ $plugin_list = Plugins::get();
+ $plugin_url = $plugin_list['nfd_slugs']['nfd_slug_endurance_page_cache']['url'];
+ $plugin_path = $plugin_list['nfd_slugs']['nfd_slug_endurance_page_cache']['path'];
if ( $wp_filesystem->exists( $plugin_path ) ) {
return new \WP_REST_Response(
@@ -317,15 +336,15 @@ public static function install_endurance_page_cache() {
}
if ( ! $wp_filesystem->is_dir( WP_CONTENT_DIR . '/mu-plugins' ) ) {
- $wp_filesystem->mkdir( WP_CONTENT_DIR . '/mu-plugins' );
+ $wp_filesystem->mkdir( WP_CONTENT_DIR . '/mu-plugins' );
}
- $request = \wp_remote_get( $plugin_url );
+ $request = \wp_remote_get( $plugin_url );
if ( \is_wp_error( $request ) ) {
- return $request;
+ return $request;
}
- $wp_filesystem->put_contents( $plugin_path, $request['body'], FS_CHMOD_FILE );
+ $wp_filesystem->put_contents( $plugin_path, $request['body'], FS_CHMOD_FILE );
return new \WP_REST_Response(
array(),
@@ -343,7 +362,7 @@ protected static function connect_to_filesystem() {
// We want to ensure that the user has direct access to the filesystem.
$access_type = \get_filesystem_method();
- if ( $access_type !== 'direct' ) {
+ if ( 'direct' !== $access_type ) {
return false;
}
diff --git a/includes/TaskManagers/PluginInstallTaskManager.php b/includes/TaskManagers/PluginInstallTaskManager.php
index c03014281..f5e1d7e4f 100644
--- a/includes/TaskManagers/PluginInstallTaskManager.php
+++ b/includes/TaskManagers/PluginInstallTaskManager.php
@@ -12,16 +12,24 @@
*/
class PluginInstallTaskManager {
- /**
- * The number of times a PluginInstallTask can be retried.
- *
- * @var int
- */
+ /**
+ * The number of times a PluginInstallTask can be retried.
+ *
+ * @var int
+ */
private static $retry_limit = 1;
+ /**
+ * The name of the queue, might be prefixed.
+ *
+ * @var string
+ */
private static $queue_name = 'plugin_install_queue';
- function __construct() {
+ /**
+ * Schedules the crons.
+ */
+ public function __construct() {
// Ensure there is a thirty second option in the cron schedules
add_filter( 'cron_schedules', array( $this, 'add_thirty_seconds_schedule' ) );
@@ -34,10 +42,21 @@ function __construct() {
}
}
+ /**
+ * Returns the queue name, might be prefixed.
+ *
+ * @return string
+ */
public static function get_queue_name() {
- return self::$queue_name;
+ return self::$queue_name;
}
+ /**
+ * Adds a 30 second cron schedule.
+ *
+ * @param array $schedules The existing cron schedule.
+ * @return array
+ */
public function add_thirty_seconds_schedule( $schedules ) {
if ( ! array_key_exists( 'thirty_seconds', $schedules ) || 30 !== $schedules['thirty_seconds']['interval'] ) {
$schedules['thirty_seconds'] = array(
@@ -46,9 +65,14 @@ public function add_thirty_seconds_schedule( $schedules ) {
);
}
- return $schedules;
+ return $schedules;
}
+ /**
+ * Queues the initial list of Plugin Installs for a flow.
+ *
+ * @return boolean
+ */
public static function queue_initial_installs() {
// Checks if the init_list of plugins have already been queued.
@@ -57,7 +81,7 @@ public static function queue_initial_installs() {
}
// Set option to installing to prevent re-queueing the init_list again on page load.
- \update_option( Options::get_option_name( 'plugins_init_status' ), 'installing' );
+ \update_option( Options::get_option_name( 'plugins_init_status' ), 'installing' );
// Get the initial list of plugins to be installed based on the plan.
$init_plugins = Plugins::get_init();
@@ -86,17 +110,19 @@ public static function queue_initial_installs() {
*/
public function install() {
/*
- Get the plugins queued up to be installed, the PluginInstall task gets
- converted to an associative array before storing it in the option. */
+ Get the plugins queued up to be installed, the PluginInstall task gets
+ converted to an associative array before storing it in the option.
+ */
$plugins = \get_option( Options::get_option_name( self::$queue_name ), array() );
/*
- Conversion of the max heap to an array will always place the PluginInstallTask with the highest
- priority at the beginning of the array */
+ Conversion of the max heap to an array will always place the PluginInstallTask with the highest
+ priority at the beginning of the array
+ */
$plugin_to_install = array_shift( $plugins );
// Update the plugin install queue.
- \update_option( Options::get_option_name( self::$queue_name ), $plugins );
+ \update_option( Options::get_option_name( self::$queue_name ), $plugins );
// Recreate the PluginInstall task from the associative array.
$plugin_install_task = new PluginInstallTask(
@@ -113,15 +139,16 @@ public function install() {
$status = $plugin_install_task->execute();
if ( \is_wp_error( $status ) ) {
- // If there is an error, then increase the retry count for the task.
- $plugin_install_task->increment_retries();
+ // If there is an error, then increase the retry count for the task.
+ $plugin_install_task->increment_retries();
- // Get Latest Value of the install queue
- $plugins = \get_option( Options::get_option_name( self::$queue_name ), array() );
+ // Get Latest Value of the install queue
+ $plugins = \get_option( Options::get_option_name( self::$queue_name ), array() );
- /*
- If the number of retries have not exceeded the limit
- then re-queue the task at the end of the queue to be retried. */
+ /*
+ If the number of retries have not exceeded the limit
+ then re-queue the task at the end of the queue to be retried.
+ */
if ( $plugin_install_task->get_retries() <= self::$retry_limit ) {
array_push( $plugins, $plugin_install_task->to_array() );
@@ -139,30 +166,30 @@ public function install() {
}
/**
- * @param PluginInstallTask $plugin_install_task
- *
* Adds a new PluginInstallTask to the Plugin Install queue.
* The Task will be inserted at an appropriate position in the queue based on it's priority.
*
+ * @param PluginInstallTask $plugin_install_task The task to be inserted.
* @return array|false
*/
public static function add_to_queue( PluginInstallTask $plugin_install_task ) {
/*
- Get the plugins queued up to be installed, the PluginInstall task gets
- converted to an associative array before storing it in the option. */
+ Get the plugins queued up to be installed, the PluginInstall task gets
+ converted to an associative array before storing it in the option.
+ */
$plugins = \get_option( Options::get_option_name( self::$queue_name ), array() );
$queue = new PriorityQueue();
foreach ( $plugins as $queued_plugin ) {
-
/*
- Check if there is an already existing PluginInstallTask in the queue
- for a given slug and activation criteria. */
+ Check if there is an already existing PluginInstallTask in the queue
+ for a given slug and activation criteria.
+ */
if ( $queued_plugin['slug'] === $plugin_install_task->get_slug()
- && $queued_plugin['activate'] === $plugin_install_task->get_activate() ) {
- return false;
+ && $queued_plugin['activate'] === $plugin_install_task->get_activate() ) {
+ return false;
}
- $queue->insert( $queued_plugin, $queued_plugin['priority'] );
+ $queue->insert( $queued_plugin, $queued_plugin['priority'] );
}
// Insert a new PluginInstallTask at the appropriate position in the queue.
@@ -171,29 +198,53 @@ public static function add_to_queue( PluginInstallTask $plugin_install_task ) {
$plugin_install_task->get_priority()
);
- return \update_option( Options::get_option_name( self::$queue_name ), $queue->to_array() );
+ return \update_option( Options::get_option_name( self::$queue_name ), $queue->to_array() );
}
+ /**
+ * Removes a PluginInstallTask from the queue.
+ *
+ * @param string $plugin The slug of the task to remove.
+ * @return array
+ */
public static function remove_from_queue( $plugin ) {
/*
- Get the plugins queued up to be installed, the PluginInstall task gets
- converted to an associative array before storing it in the option. */
+ Get the plugins queued up to be installed, the PluginInstall task gets
+ converted to an associative array before storing it in the option.
+ */
$plugins = \get_option( Options::get_option_name( self::$queue_name ), array() );
$queue = new PriorityQueue();
foreach ( $plugins as $queued_plugin ) {
/*
- If the Plugin slug does not match add it back to the queue. */
+ If the Plugin slug does not match add it back to the queue.
+ */
if ( $queued_plugin['slug'] !== $plugin ) {
- $queue->insert( $queued_plugin, $queued_plugin['priority'] );
+ $queue->insert( $queued_plugin, $queued_plugin['priority'] );
}
}
- return \update_option( Options::get_option_name( self::$queue_name ), $queue->to_array() );
+ return \update_option( Options::get_option_name( self::$queue_name ), $queue->to_array() );
}
+ /**
+ * Get the status of a given plugin slug from the queue.
+ *
+ * @param string $plugin The slug of the plugin.
+ * @return boolean
+ */
public static function status( $plugin ) {
$plugins = \get_option( Options::get_option_name( self::$queue_name ), array() );
- return array_search( $plugin, array_column( $plugins, 'slug' ) );
+ return array_search( $plugin, array_column( $plugins, 'slug' ), true );
+ }
+
+ /**
+ * Reset the Plugin install status and the queue.
+ *
+ * @return void
+ */
+ public static function reset_install_status() {
+ \delete_option( Options::get_option_name( 'plugins_init_status' ) );
+ \delete_option( Options::get_option_name( 'plugin_install_queue' ) );
}
}
diff --git a/src/OnboardingSPA/components/Content/index.js b/src/OnboardingSPA/components/Content/index.js
index f111868d9..46a050b79 100644
--- a/src/OnboardingSPA/components/Content/index.js
+++ b/src/OnboardingSPA/components/Content/index.js
@@ -3,6 +3,7 @@ import { Fragment, memo, Suspense, useCallback } from '@wordpress/element';
import { store as nfdOnboardingStore } from '../../store';
import { useSelect } from '@wordpress/data';
+import FlowStateHandler from '../StateHandlers/Flow';
/**
* Primary content area within the .
@@ -17,24 +18,23 @@ const Content = () => {
};
} );
- const getMappedPages = useCallback(
- ( routes ) => {
- return routes?.map( ( route ) => (
- }
- />
- ) );
- },
- [ routes ]
- );
+ const getMappedPages = useCallback( () => {
+ return routes?.map( ( route ) => (
+ }
+ />
+ ) );
+ }, [ routes ] );
return (
}>
- { getMappedPages( routes ) }
+
+ { getMappedPages( routes ) }
+
);
diff --git a/src/OnboardingSPA/components/Loaders/Step/Ecommerce/contents.js b/src/OnboardingSPA/components/Loaders/Step/Ecommerce/contents.js
new file mode 100644
index 000000000..a9feb7449
--- /dev/null
+++ b/src/OnboardingSPA/components/Loaders/Step/Ecommerce/contents.js
@@ -0,0 +1,22 @@
+import { __, sprintf } from '@wordpress/i18n';
+import { translations } from '../../../../utils/locales/translations';
+
+const getContents = ( brandName ) => {
+ return {
+ title: sprintf(
+ /* translators: 1: Brand 2: Site */
+ __(
+ 'Making the keys to your %1$s Online %2$s',
+ 'wp-module-onboarding'
+ ),
+ brandName,
+ translations( 'Site' )
+ ),
+ subtitle: __(
+ 'We’re installing WooCommerce for you to fill with your amazing products & services!',
+ 'wp-module-onboarding'
+ ),
+ };
+};
+
+export default getContents;
diff --git a/src/OnboardingSPA/components/Loaders/Step/Ecommerce/index.js b/src/OnboardingSPA/components/Loaders/Step/Ecommerce/index.js
new file mode 100644
index 000000000..71a7dd320
--- /dev/null
+++ b/src/OnboardingSPA/components/Loaders/Step/Ecommerce/index.js
@@ -0,0 +1,19 @@
+import StepLoader from '..';
+import getContents from './contents';
+import { useSelect } from '@wordpress/data';
+
+import { store as nfdOnboardingStore } from '../../../../store';
+
+const EcommerceStepLoader = () => {
+ const { brandName } = useSelect( ( select ) => {
+ return {
+ brandName: select( nfdOnboardingStore ).getNewfoldBrandName(),
+ };
+ }, [] );
+ const contents = getContents( brandName );
+ return (
+
+ );
+};
+
+export default EcommerceStepLoader;
diff --git a/src/OnboardingSPA/components/Sidebar/components/LearnMore/Menu.js b/src/OnboardingSPA/components/Sidebar/components/LearnMore/Menu.js
index f95b9b86f..355a41cc1 100644
--- a/src/OnboardingSPA/components/Sidebar/components/LearnMore/Menu.js
+++ b/src/OnboardingSPA/components/Sidebar/components/LearnMore/Menu.js
@@ -33,7 +33,7 @@ const LearnMoreMenu = () => {
return (
<>
- { currentStep?.sidebars?.LearnMore && (
+ { sideBarView && currentStep?.sidebars?.LearnMore && (
diff --git a/src/OnboardingSPA/components/SkipButton/index.js b/src/OnboardingSPA/components/SkipButton/index.js
index 96a475971..d47cb3636 100644
--- a/src/OnboardingSPA/components/SkipButton/index.js
+++ b/src/OnboardingSPA/components/SkipButton/index.js
@@ -9,12 +9,7 @@ import { store as nfdOnboardingStore } from '../../store';
import { getSettings, setSettings } from '../../utils/api/settings';
import { wpAdminPage, pluginDashboardPage } from '../../../constants';
-/**
- * Interface Text Inputs with standard design.
- *
- * @return {WPComponent} SkipButton Component
- */
-const SkipButton = () => {
+const SkipButton = ( { callback = false } ) => {
const navigate = useNavigate();
const location = useLocation();
const { nextStep, currentData, socialData } = useSelect( ( select ) => {
@@ -75,7 +70,12 @@ const SkipButton = () => {
return (
diff --git a/src/OnboardingSPA/components/StateHandlers/Ecommerce/contents.js b/src/OnboardingSPA/components/StateHandlers/Ecommerce/contents.js
index 6090ca529..e9d1b5707 100644
--- a/src/OnboardingSPA/components/StateHandlers/Ecommerce/contents.js
+++ b/src/OnboardingSPA/components/StateHandlers/Ecommerce/contents.js
@@ -3,26 +3,11 @@ import { translations } from '../../../utils/locales/translations';
const getContents = ( brandName ) => {
return {
- loader: {
- title: sprintf(
- /* translators: 1: Brand 2: Site */
- __(
- 'Making the keys to your %s Online %s',
- 'wp-module-onboarding'
- ),
- brandName,
- translations( 'Site' )
- ),
- subtitle: __(
- 'We’re installing WooCommerce for you to fill with your amazing products & services!',
- 'wp-module-onboarding'
- ),
- },
errorState: {
title: sprintf(
/* translators: 1: Brand 2: Site */
__(
- 'Making the keys to your %s Online %s',
+ 'Making the keys to your %1$s Online %2$s',
'wp-module-onboarding'
),
brandName,
diff --git a/src/OnboardingSPA/components/StateHandlers/Ecommerce/index.js b/src/OnboardingSPA/components/StateHandlers/Ecommerce/index.js
index bf3d7af1a..af582f672 100644
--- a/src/OnboardingSPA/components/StateHandlers/Ecommerce/index.js
+++ b/src/OnboardingSPA/components/StateHandlers/Ecommerce/index.js
@@ -2,7 +2,6 @@ import { useViewportMatch } from '@wordpress/compose';
import { useSelect, useDispatch } from '@wordpress/data';
import { useEffect, useState } from '@wordpress/element';
-import { StepLoader } from '../../Loaders';
import { store as nfdOnboardingStore } from '../../../store';
import { getPluginStatus } from '../../../utils/api/plugins';
import {
@@ -15,6 +14,7 @@ import {
} from '../../../../constants';
import { StepErrorState } from '../../ErrorState';
import getContents from './contents';
+import EcommerceStepLoader from '../../Loaders/Step/Ecommerce';
const EcommerceStateHandler = ( {
children,
@@ -110,8 +110,7 @@ const EcommerceStateHandler = ( {
window.location.reload();
break;
default:
- pluginsStatus[ ECOMMERCE_STEPS_PLUGIN ] =
- pluginStatus;
+ pluginsStatus[ ECOMMERCE_STEPS_PLUGIN ] = pluginStatus;
setWoocommerceStatus( pluginStatus );
updatePluginsStatus( pluginsStatus );
}
@@ -139,12 +138,7 @@ const EcommerceStateHandler = ( {
case PLUGIN_STATUS_ACTIVE:
return children;
default:
- return (
-
- );
+ return ;
}
};
diff --git a/src/OnboardingSPA/components/StateHandlers/Flow/index.js b/src/OnboardingSPA/components/StateHandlers/Flow/index.js
new file mode 100644
index 000000000..71c187119
--- /dev/null
+++ b/src/OnboardingSPA/components/StateHandlers/Flow/index.js
@@ -0,0 +1,90 @@
+import { useEffect, useState } from '@wordpress/element';
+import { useLocation } from 'react-router-dom';
+import { useSelect, useDispatch } from '@wordpress/data';
+
+import { store as nfdOnboardingStore } from '../../../store';
+import { getFirstEcommerceStep } from '../../../data/routes/ecommerce-flow';
+import EcommerceStepLoader from '../../Loaders/Step/Ecommerce';
+import { switchFlow } from '../../../utils/api/flow';
+import { removeQueryParam } from '../../../utils';
+import { MAX_RETRIES_FLOW_SWITCH } from '../../../../constants';
+import { getFragment } from '@wordpress/url';
+
+const FlowStateHandler = ( { children } ) => {
+ const location = useLocation();
+ const [ newFlow, setNewFlow ] = useState( false );
+
+ const { brandConfig } = useSelect( ( select ) => {
+ return {
+ brandName: select( nfdOnboardingStore ).getNewfoldBrandName(),
+ brandConfig: select( nfdOnboardingStore ).getNewfoldBrandConfig(),
+ };
+ }, [] );
+
+ const {
+ setIsDrawerOpened,
+ setIsDrawerSuppressed,
+ setIsHeaderNavigationEnabled,
+ setSidebarActiveView,
+ } = useDispatch( nfdOnboardingStore );
+
+ const disableNavigation = () => {
+ setIsDrawerOpened( false );
+ setIsDrawerSuppressed( true );
+ setIsHeaderNavigationEnabled( false );
+ setSidebarActiveView( false );
+ };
+
+ const handleCommerceFlow = async ( flow, retries = 0 ) => {
+ if ( retries >= MAX_RETRIES_FLOW_SWITCH ) {
+ return setNewFlow( false );
+ }
+ const response = await switchFlow( flow );
+ if ( response?.error ) {
+ retries = retries + 1;
+ return handleCommerceFlow( flow, retries );
+ }
+ const firstEcommerceStep = getFirstEcommerceStep();
+ const fragment = getFragment( window.location.href );
+ const redirect = removeQueryParam( window.location.href, 'flow' ).replace( fragment, '' );
+ window.location.replace( `${ redirect }#${ firstEcommerceStep.path }` );
+ window.location.reload();
+ };
+
+ const switchToNewFlow = async ( flow ) => {
+ const enabledFlows = brandConfig?.enabled_flows ?? {};
+ if ( ! ( flow in enabledFlows ) || enabledFlows[ flow ] !== true ) {
+ return setNewFlow( false );
+ }
+
+ switch ( flow ) {
+ case 'ecommerce':
+ handleCommerceFlow( flow );
+ break;
+ default:
+ setNewFlow( false );
+ }
+ };
+
+ useEffect( () => {
+ if ( window.nfdOnboarding?.newFlow ) {
+ const flow = window.nfdOnboarding.newFlow;
+ disableNavigation();
+ setNewFlow( flow );
+ switchToNewFlow( flow );
+ window.nfdOnboarding.newFlow = undefined;
+ }
+ }, [ location.pathname ] );
+
+ const handleRender = () => {
+ switch ( newFlow ) {
+ case 'ecommerce':
+ return ;
+ default:
+ return children;
+ }
+ };
+ return <>{ handleRender() }>;
+};
+
+export default FlowStateHandler;
diff --git a/src/OnboardingSPA/data/routes/ecommerce-flow.js b/src/OnboardingSPA/data/routes/ecommerce-flow.js
index 014c2cd85..1a23100a9 100644
--- a/src/OnboardingSPA/data/routes/ecommerce-flow.js
+++ b/src/OnboardingSPA/data/routes/ecommerce-flow.js
@@ -1,6 +1,7 @@
import { __ } from '@wordpress/i18n';
import { store, institution, shipping } from '@wordpress/icons';
import { lazy } from '@wordpress/element';
+// eslint-disable-next-line import/no-extraneous-dependencies
import { orderBy, filter } from 'lodash';
import {
@@ -37,11 +38,11 @@ export const ecommerceSteps = [
title: __( 'Street Address', 'wp-module-onboarding' ),
heading: __( 'Street Address', 'wp-module-onboarding' ),
subheading: __(
- 'In this step you confirm the business address of your store. Simply confirm the one you provided during your initial Bluehost account setup or provide a new one.',
+ 'In this step you confirm the business address of your store. Simply confirm the one you provided during your initial Bluehost account setup or provide a new one.',
'wp-module-onboarding'
),
description: __(
- 'In this step you confirm the business address of your store. Simply confirm the one you provided during your initial Bluehost account setup or provide a new one.',
+ 'In this step you confirm the business address of your store. Simply confirm the one you provided during your initial Bluehost account setup or provide a new one.',
'wp-module-onboarding'
),
Component: StepAddress,
@@ -156,3 +157,7 @@ export const ecommerceGetStartedSteps = () => {
( step ) => ! step.path.includes( '/step/get-started/site-primary' )
);
};
+
+export const getFirstEcommerceStep = () => {
+ return ecommerceSteps[ 0 ];
+};
diff --git a/src/OnboardingSPA/pages/Steps/TopPriority/index.js b/src/OnboardingSPA/pages/Steps/TopPriority/index.js
index 29d59ec5f..f4f5155b0 100644
--- a/src/OnboardingSPA/pages/Steps/TopPriority/index.js
+++ b/src/OnboardingSPA/pages/Steps/TopPriority/index.js
@@ -1,5 +1,4 @@
import { __ } from '@wordpress/i18n';
-import { useNavigate } from 'react-router-dom';
import { useViewportMatch } from '@wordpress/compose';
import { useEffect, useState } from '@wordpress/element';
import { useDispatch, useSelect } from '@wordpress/data';
@@ -11,7 +10,7 @@ import CommonLayout from '../../../components/Layouts/Common';
import HeadingWithSubHeading from '../../../components/HeadingWithSubHeading';
import SelectableCardList from '../../../components/SelectableCardList/selectable-card-list';
-const StepTopPriority = ( props ) => {
+const StepTopPriority = () => {
const priorityTypes = {
0: 'publishing',
1: 'selling',
@@ -21,22 +20,30 @@ const StepTopPriority = ( props ) => {
const priorities = [
{
icon: '--nfd-publish-icon',
- title: 'Publishing',
- desc: 'From blogs, to newsletters, to podcasts and videos, we help the web find your content.',
+ title: __( 'Publishing', 'wp-module-onboarding' ),
+ desc: __(
+ 'From blogs, to newsletters, to podcasts and videos, we help the web find your content.',
+ 'wp-module-onboarding'
+ ),
},
{
icon: '--nfd-selling-icon',
- title: 'Selling',
- desc: "Startup or seasoned business, drop-shipping or downloads, we've got ecommerce covered.",
+ title: __( 'Selling', 'wp-module-onboarding' ),
+ desc: __(
+ "Startup or seasoned business, drop-shipping or downloads, we've got ecommerce covered.",
+ 'wp-module-onboarding'
+ ),
},
{
icon: '--nfd-design-icon',
- title: 'Designing',
- desc: 'With smart style presets and powerful options, we help your site look and feel polished.',
+ title: __( 'Designing', 'wp-module-onboarding' ),
+ desc: __(
+ 'With smart style presets and powerful options, we help your site look and feel polished.',
+ 'wp-module-onboarding'
+ ),
},
];
- const navigate = useNavigate();
const [ selected, setSelected ] = useState( 0 );
const [ isLoaded, setisLoaded ] = useState( false );
const isLargeViewport = useViewportMatch( 'medium' );
@@ -47,17 +54,18 @@ const StepTopPriority = ( props ) => {
setSidebarActiveView,
setCurrentOnboardingData,
setIsDrawerSuppressed,
- setIsHeaderNavigationEnabled
+ setIsHeaderNavigationEnabled,
} = useDispatch( nfdOnboardingStore );
const { currentStep, currentData } = useSelect( ( select ) => {
return {
- currentStep: select(nfdOnboardingStore).getCurrentStep(),
- currentData: select( nfdOnboardingStore ).getCurrentOnboardingData(),
+ currentStep: select( nfdOnboardingStore ).getCurrentStep(),
+ currentData:
+ select( nfdOnboardingStore ).getCurrentOnboardingData(),
};
}, [] );
- const getKey = ( priorityTypes, value ) => {
+ const getKey = ( value ) => {
return Object?.keys( priorityTypes ).find(
( key ) => priorityTypes[ key ] === value
);
@@ -68,7 +76,7 @@ const StepTopPriority = ( props ) => {
setIsDrawerOpened( true );
}
setSidebarActiveView( SIDEBAR_LEARN_MORE );
- setIsDrawerSuppressed( false );
+ setIsDrawerSuppressed( false );
setDrawerActiveView( VIEW_NAV_PRIMARY );
setIsHeaderNavigationEnabled( true );
}, [] );
@@ -77,9 +85,9 @@ const StepTopPriority = ( props ) => {
async function setInitialData() {
if ( currentData ) {
const val = await currentData?.data.topPriority.priority1;
- if ( val != '' )
- setSelected( parseInt( getKey( priorityTypes, val ) ) );
- else {
+ if ( val !== '' ) {
+ setSelected( parseInt( getKey( val ) ) );
+ } else {
currentData.data.topPriority.priority1 =
priorityTypes[ selected ];
setCurrentOnboardingData( currentData );
@@ -87,20 +95,40 @@ const StepTopPriority = ( props ) => {
}
setisLoaded( true );
}
- if ( ! isLoaded ) setInitialData();
+ if ( ! isLoaded ) {
+ setInitialData();
+ }
}, [ isLoaded ] );
+ const handleSelling = () => {
+ if ( 'ecommerce' !== window.nfdOnboarding.currentFlow ) {
+ window.nfdOnboarding.newFlow = 'ecommerce';
+ }
+ };
+
useEffect( () => {
- if ( isLoaded ) {
- currentData.data.topPriority.priority1 = priorityTypes[ selected ];
- setCurrentOnboardingData( currentData );
+ const selectedPriorityType = priorityTypes[ selected ];
+ currentData.data.topPriority.priority1 = selectedPriorityType;
+ setCurrentOnboardingData( currentData );
+ if ( 'selling' === selectedPriorityType ) {
+ handleSelling();
+ } else {
+ window.nfdOnboarding.newFlow = undefined;
}
}, [ selected ] );
+ const handleSkip = () => {
+ window.nfdOnboarding.newFlow = undefined;
+ currentData.data.topPriority.priority1 = priorityTypes[0] ;
+ setCurrentOnboardingData( currentData );
+ }
+
return (
+ title={ currentStep?.heading }
+ subtitle={ currentStep?.subheading }
+ />
{
'wp-module-onboarding'
) }
-
+
);
diff --git a/src/OnboardingSPA/utils/api/flow.js b/src/OnboardingSPA/utils/api/flow.js
index 3bb55b706..f33758e37 100644
--- a/src/OnboardingSPA/utils/api/flow.js
+++ b/src/OnboardingSPA/utils/api/flow.js
@@ -27,3 +27,15 @@ export async function completeFlow() {
} ).then()
);
}
+
+export async function switchFlow( flow ) {
+ return await resolve(
+ apiFetch( {
+ url: onboardingRestURL( 'flow/switch' ),
+ method: 'POST',
+ data: {
+ flow,
+ },
+ } ).then()
+ );
+}
diff --git a/src/OnboardingSPA/utils/index.js b/src/OnboardingSPA/utils/index.js
index 6202713d3..5abb1f9f2 100644
--- a/src/OnboardingSPA/utils/index.js
+++ b/src/OnboardingSPA/utils/index.js
@@ -1,18 +1,13 @@
-import { findIndex } from 'lodash';
-
-export const insertBeforeStep = (steps, path, newStep) => {};
-
-export const insertAfterStep = (steps, path, newStep) => {};
-
-export const insertStepAtIndex = (steps, index, newStep) => {};
-
-export const findStepIndex = ( steps, path ) => {
- const index = findIndex( steps, { path } );
-
- return -1 !== index ? index : false;
-};
+import { removeQueryArgs, hasQueryArg } from '@wordpress/url';
export const getQueryParam = ( paramName ) => {
- const urlParams = new URLSearchParams( location.search );
+ const urlParams = new URLSearchParams( window.location.search );
return urlParams.get( paramName );
};
+
+export const removeQueryParam = ( url, paramName ) => {
+ if ( hasQueryArg( url, paramName ) ) {
+ return removeQueryArgs( url, paramName );
+ }
+ return url;
+};
diff --git a/src/constants.js b/src/constants.js
index 75b5df22d..89d277e18 100644
--- a/src/constants.js
+++ b/src/constants.js
@@ -31,6 +31,7 @@ export const SIDEBAR_MENU_SLOTFILL_PREFIX = 'HeaderMenu';
export const SIDEBAR_LEARN_MORE = 'LearnMore';
export const MAX_RETRIES_SETTINGS_INIT = 2;
+export const MAX_RETRIES_FLOW_SWITCH = 2;
export const NFD_PLUGINS_QUERY_PARAM = 'nfd_plugins';
export const NFD_THEMES_QUERY_PARAM = 'nfd_themes';
From c04e2f24c352fb1ff1a292b4c9d5c7f8146e8325 Mon Sep 17 00:00:00 2001
From: arunshenoy99
Date: Mon, 17 Apr 2023 22:12:39 +0530
Subject: [PATCH 2/3] fix js lint
---
src/OnboardingSPA/components/StateHandlers/Flow/index.js | 5 ++++-
src/OnboardingSPA/pages/Steps/TopPriority/index.js | 6 +++---
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/src/OnboardingSPA/components/StateHandlers/Flow/index.js b/src/OnboardingSPA/components/StateHandlers/Flow/index.js
index 71c187119..d562e3845 100644
--- a/src/OnboardingSPA/components/StateHandlers/Flow/index.js
+++ b/src/OnboardingSPA/components/StateHandlers/Flow/index.js
@@ -46,7 +46,10 @@ const FlowStateHandler = ( { children } ) => {
}
const firstEcommerceStep = getFirstEcommerceStep();
const fragment = getFragment( window.location.href );
- const redirect = removeQueryParam( window.location.href, 'flow' ).replace( fragment, '' );
+ const redirect = removeQueryParam(
+ window.location.href,
+ 'flow'
+ ).replace( fragment, '' );
window.location.replace( `${ redirect }#${ firstEcommerceStep.path }` );
window.location.reload();
};
diff --git a/src/OnboardingSPA/pages/Steps/TopPriority/index.js b/src/OnboardingSPA/pages/Steps/TopPriority/index.js
index f4f5155b0..f19fc265b 100644
--- a/src/OnboardingSPA/pages/Steps/TopPriority/index.js
+++ b/src/OnboardingSPA/pages/Steps/TopPriority/index.js
@@ -119,9 +119,9 @@ const StepTopPriority = () => {
const handleSkip = () => {
window.nfdOnboarding.newFlow = undefined;
- currentData.data.topPriority.priority1 = priorityTypes[0] ;
+ currentData.data.topPriority.priority1 = priorityTypes[ 0 ];
setCurrentOnboardingData( currentData );
- }
+ };
return (
@@ -146,7 +146,7 @@ const StepTopPriority = () => {
'wp-module-onboarding'
) }
-
+
);
From af7a7cfa08e62441e0d0fce4a78b2cc8f1e26b3d Mon Sep 17 00:00:00 2001
From: arunshenoy99
Date: Wed, 19 Apr 2023 18:18:09 +0530
Subject: [PATCH 3/3] run the post install callback earlier
---
includes/Services/PluginInstaller.php | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/includes/Services/PluginInstaller.php b/includes/Services/PluginInstaller.php
index 86423afd1..89d2eb497 100644
--- a/includes/Services/PluginInstaller.php
+++ b/includes/Services/PluginInstaller.php
@@ -88,6 +88,9 @@ public static function install( $plugin, $activate ) {
if ( \is_wp_error( $status ) ) {
return $status;
}
+ if ( is_callable( $plugin_post_install_callback ) ) {
+ $plugin_post_install_callback();
+ }
}
if ( $activate && ! \is_plugin_active( $plugin_path ) ) {
@@ -97,9 +100,6 @@ public static function install( $plugin, $activate ) {
return $status;
}
- if ( is_callable( $plugin_post_install_callback ) ) {
- $plugin_post_install_callback();
- }
}
return new \WP_REST_Response(