PluginProbe ʕ •ᴥ•ʔ
WooCommerce / 5.3.0
WooCommerce v5.3.0
10.8.1 10.8.0 10.8.0-rc.1 10.8.0-beta.2 10.8.0-beta.1 7.8.0-beta.1 7.8.0-beta.2 7.8.0-rc.1 7.8.0-rc.2 7.8.1 7.8.2 7.8.3 7.8.4 7.9.0 7.9.0-beta.1 7.9.0-beta.2 7.9.0-rc.2 7.9.0-rc.3 7.9.1 7.9.2 8.0.0 8.0.0-beta.1 8.0.0-beta.2 8.0.0-rc.1 8.0.0-rc.2 8.0.1 8.0.2 8.0.3 8.0.4 8.0.5 8.1.0 8.1.0-beta.1 8.1.0-rc.1 8.1.0-rc.2 8.1.1 8.1.2 8.1.3 8.1.4 8.2.0 8.2.0-beta.1 8.2.0-rc.1 8.2.0-rc.2 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.3.0 8.3.0-beta.1 8.3.0-rc.1 8.3.0-rc.2 8.3.1 8.3.2 8.3.3 8.3.4 8.4.0 8.4.0-beta.1 8.4.0-rc.1 8.4.1 8.4.2 8.4.3 8.5.0 8.5.0-beta.1 8.5.0-rc.1 8.5.1 8.5.2 8.5.3 8.5.4 8.5.5 8.6.0 8.6.0-beta.1 8.6.0-rc.1 8.6.1 8.6.2 8.6.3 8.6.4 8.7.0 8.7.0-beta.1 8.7.0-beta.2 8.7.0-rc.1 8.7.1 8.7.2 8.7.3 8.8.0 8.8.0-beta.1 8.8.0-rc.1 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.8.6 8.8.7 8.9.0 8.9.0-beta.1 8.9.0-rc.1 8.9.1 8.9.2 8.9.3 8.9.4 8.9.5 9.0.0 9.0.0-beta.1 9.0.0-beta.2 9.0.0-rc.1 9.0.1 9.0.2 9.0.3 9.0.4 9.1.0 9.1.0-beta.1 9.1.0-rc.1 9.1.1 9.1.2 9.1.3 9.1.4 9.1.5 9.1.6 9.2.0 9.2.0-beta.1 9.2.0-rc.1 9.2.1 9.2.2 9.2.3 9.2.4 9.2.5 9.3.0 9.3.0-beta.1 9.3.0-rc.1 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.3.6 9.4.0 9.4.0-beta.1 9.4.0-beta.2 9.4.0-rc.1 9.4.0-rc.2 9.4.0-rc.3 9.4.0-rc.4 9.4.1 9.4.2 9.4.3 9.4.4 9.4.5 9.5.0 9.5.0-beta.1 9.5.0-beta.2 9.5.0-rc.1 9.5.1 9.5.2 9.5.3 9.5.4 9.6.0 9.6.0-beta.1 9.6.0-beta.2 9.6.0-rc.1 9.6.1 9.6.2 9.6.3 9.6.4 9.7.0 9.7.0-beta.1 9.7.0-rc.1 9.7.1 9.7.2 9.7.3 9.8.0 9.8.0-beta.1 9.8.0-rc.1 9.8.1 9.8.2 9.8.3 9.8.4 9.8.5 9.8.6 9.8.7 9.9.0 9.9.0-beta.1 9.9.0-rc.1 9.9.1 9.9.2 9.9.3 9.9.4 9.9.5 9.9.6 9.9.7 3.7.3 7.1.2 3.8.0 7.2.0 3.8.0-beta.1 7.2.0-beta.1 3.8.0-rc.1 7.2.0-beta.2 3.8.0-rc.2 7.2.0-rc.1 3.8.1 7.2.0-rc.2 3.8.2 7.2.1 3.8.3 7.2.2 3.9.0 7.2.3 3.9.0-beta.1 7.2.4 3.9.0-beta.2 7.3.0 3.9.0-rc.1 7.3.0-beta.1 3.9.0-rc.2 7.3.0-beta.2 3.9.0-rc.3 7.3.0-rc.1 3.9.0-rc.4 7.3.0-rc.2 3.9.1 7.3.1 3.9.2 7.4.0 3.9.3 7.4.0-beta.1 3.9.4 7.4.0-beta.2 3.9.5 7.4.0-rc.1 4.0.0 7.4.0-rc.2 4.0.0-beta.1 7.4.1 4.0.0-rc.1 7.4.2 4.0.0-rc.2 7.5.0 4.0.1 7.5.0-beta.1 4.0.2 7.5.0-beta.2 4.0.3 7.5.0-rc.1 4.0.4 7.5.1 4.1.0 7.5.2 4.1.0-beta.1 7.6.0 4.1.0-beta.2 7.6.0-beta.1 4.1.0-rc.1 7.6.0-beta.2 4.1.0-rc.2 7.6.0-rc.1 4.1.1 7.6.0-rc.2 4.1.2 7.6.0-rc.3 4.1.3 7.6.1 4.1.4 7.6.2 4.2.0 7.7.0 4.2.0-RC.1 7.7.0-beta.1 4.2.0-RC.2 7.7.0-beta.2 4.2.0-beta.1 7.7.0-rc.1 4.2.1 7.7.1 4.2.2 7.7.2 4.2.3 7.7.3 4.2.4 7.8.0 4.2.5 4.3.0 4.3.0-beta.1 4.3.0-rc.1 4.3.0-rc.2 4.3.0-rc.3 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 4.3.6 4.4.0 4.4.0-beta.1 4.4.0-rc.1 4.4.1 4.4.2 4.4.3 4.4.4 4.5.0 4.5.0-beta.1 4.5.0-rc.1 4.5.0-rc.3 4.5.1 4.5.2 4.5.3 4.5.4 4.5.5 4.6.0 4.6.0-beta.1 4.6.0-rc.1 4.6.1 4.6.2 4.6.3 4.6.4 4.6.5 4.7.0 4.7.0-beta.1 4.7.0-beta.2 4.7.0-rc.1 4.7.1 4.7.1-beta.1 4.7.2 4.7.3 4.7.4 4.8.0 4.8.0-beta.1 4.8.0-rc.1 4.8.0-rc.2 4.8.1 4.8.2 4.8.3 4.9.0 4.9.0-beta.1 4.9.0-rc.1 4.9.0-rc.2 4.9.1 4.9.2 4.9.3 4.9.4 4.9.5 5.0.0 5.0.0-beta.1 5.0.0-beta.2 5.0.0-rc.1 5.0.0-rc.2 5.0.0-rc.3 5.0.1 5.0.2 5.0.3 5.1.0 5.1.0-beta.1 5.1.0-rc.1 trunk 5.1.1 10.0.0 5.1.2 10.0.0-rc.1 5.1.3 10.0.0-rc.2 5.2.0 10.0.1 5.2.0-beta.1 10.0.2 5.2.0-rc.1 10.0.3 5.2.0-rc.2 10.0.4 5.2.1 10.0.5 5.2.2 10.0.6 5.2.3 10.1.0 5.2.4 10.1.0-rc.1 5.2.5 10.1.0-rc.2 5.3.0 10.1.0-rc.3 5.3.0-beta.1 10.1.0-rc.4 5.3.0-rc.1 10.1.1 5.3.0-rc.2 10.1.2 5.3.1 10.1.3 5.3.2 10.1.4 5.3.3 10.2.0 5.4.0 10.2.0-beta.1 5.4.0-beta.1 10.2.0-beta.2 5.4.0-rc.1 10.2.0-rc.1 5.4.1 10.2.1 5.4.2 10.2.2 5.4.3 10.2.3 5.4.4 10.2.4 5.4.5 10.3.0 5.5.0 10.3.0-beta.1 5.5.0-beta.1 10.3.0-beta.2 5.5.0-rc.1 10.3.0-rc.1 5.5.0-rc.2 10.3.0-rc.2 5.5.1 10.3.1 5.5.2 10.3.2 5.5.3 10.3.3 5.5.4 10.3.4 5.5.5 10.3.5 5.6.0 10.3.6 5.6.0-beta.1 10.3.7 5.6.0-rc.1 10.3.8 5.6.0-rc.2 10.4.0 5.6.1 10.4.0-beta.1 5.6.2 10.4.0-beta.2 5.6.3 10.4.0-rc.1 5.7.0 10.4.1 5.7.0-beta.1 10.4.2 5.7.0-rc.1 10.4.3 5.7.1 10.4.4 5.7.2 10.5.0 5.7.3 10.5.0-beta.1 5.8.0 10.5.0-beta.2 5.8.0-beta.1 10.5.0-rc.1 5.8.0-beta.2 10.5.0-rc.2 5.8.0-rc.1 10.5.0-rc.3 5.8.1 10.5.1 5.8.2 10.5.2 5.9.0 10.5.3 5.9.0-beta.1 10.6.0 5.9.0-rc.1 10.6.0-beta.1 5.9.0-rc.2 10.6.0-beta.2 5.9.1 10.6.0-rc.1 5.9.2 10.6.1 6.0.0 10.6.2 6.0.0-beta.1 10.7.0 6.0.0-rc.1 10.7.0-beta.1 6.0.1 10.7.0-beta.2 6.0.2 10.7.0-rc.1 6.1.0 3.0.0 6.1.0-beta.1 3.0.1 6.1.0-rc.1 3.0.2 6.1.0-rc.2 3.0.3 6.1.1 3.0.4 6.1.2 3.0.5 6.1.3 3.0.6 6.2.0 3.0.7 6.2.0-beta.1 3.0.8 6.2.0-rc.1 3.0.9 6.2.0-rc.2 3.1.0 6.2.1 3.1.1 6.2.2 3.1.2 6.2.3 3.2.0 6.3.0 3.2.1 6.3.0-beta.1 3.2.2 6.3.0-rc.1 3.2.3 6.3.0-rc.2 3.2.4 6.3.1 3.2.5 6.3.2 3.2.6 6.4.0 3.3.0 6.4.0-beta.1 3.3.1 6.4.0-rc.1 3.3.2 6.4.1 3.3.2-rc.1 6.4.2 3.3.3 6.5.0 3.3.4 6.5.0-beta.1 3.3.5 6.5.0-rc.1 3.3.6 6.5.0-rc.2 3.4.0 6.5.1 3.4.0-beta.1 6.5.2 3.4.0-rc.2 6.6.0 3.4.1 6.6.0-beta.1 3.4.2 6.6.0-rc.1 3.4.3 6.6.0-rc.2 3.4.4 6.6.1 3.4.5 6.6.2 3.4.6 6.7.0 3.4.7 6.7.0-beta.1 3.4.8 6.7.0-beta.2 3.5.0 6.7.0-rc.1 3.5.0-beta.1 6.7.1 3.5.0-rc.1 6.8.0 3.5.0-rc.2 6.8.0-beta.1 3.5.1 6.8.0-beta.2 3.5.10 6.8.0-rc.1 3.5.2 6.8.1 3.5.3 6.8.2 3.5.4 6.8.3 3.5.5 6.9.0 3.5.6 6.9.0-beta.1 3.5.7 6.9.0-beta.2 3.5.8 6.9.0-rc.1 3.5.9 6.9.1 3.6.0 6.9.2 3.6.0-beta.1 6.9.3 3.6.0-rc.1 6.9.4 3.6.0-rc.2 6.9.5 3.6.0-rc.3 7.0.0 3.6.1 7.0.0-beta.1 3.6.2 7.0.0-beta.2 3.6.3 7.0.0-beta.3 3.6.4 7.0.0-rc.1 3.6.5 7.0.0-rc.2 3.6.6 7.0.1 3.6.7 7.0.2 3.7.0 7.1.0 3.7.0-beta.1 7.1.0-beta.1 3.7.0-rc.1 7.1.0-beta.2 3.7.0-rc.2 7.1.0-rc.1 3.7.1 7.1.0-rc.2 3.7.2 7.1.1
woocommerce / packages / woocommerce-admin / src / Features / Onboarding.php
woocommerce / packages / woocommerce-admin / src / Features Last commit date
Navigation 5 years ago ActivityPanels.php 5 years ago Analytics.php 5 years ago AnalyticsDashboard.php 5 years ago Coupons.php 5 years ago CouponsMovedTrait.php 5 years ago CustomerEffortScoreTracks.php 5 years ago Features.php 5 years ago Homescreen.php 5 years ago Marketing.php 5 years ago MobileAppBanner.php 5 years ago Onboarding.php 5 years ago OnboardingTasks.php 5 years ago Settings.php 5 years ago ShippingLabelBanner.php 5 years ago ShippingLabelBannerDisplayRules.php 5 years ago
Onboarding.php
1128 lines
1 <?php
2 /**
3 * WooCommerce Onboarding
4 * NOTE: DO NOT edit this file in WooCommerce core, this is generated from woocommerce-admin.
5 */
6
7 namespace Automattic\WooCommerce\Admin\Features;
8
9 use \Automattic\WooCommerce\Admin\Loader;
10 use Automattic\WooCommerce\Admin\PageController;
11 use \Automattic\WooCommerce\Admin\PluginsHelper;
12
13 /**
14 * Contains backend logic for the onboarding profile and checklist feature.
15 */
16 class Onboarding {
17 /**
18 * Class instance.
19 *
20 * @var Onboarding instance
21 */
22 protected static $instance = null;
23
24 /**
25 * Name of themes transient.
26 *
27 * @var string
28 */
29 const THEMES_TRANSIENT = 'wc_onboarding_themes';
30
31 /**
32 * Name of product data transient.
33 *
34 * @var string
35 */
36 const PRODUCT_DATA_TRANSIENT = 'wc_onboarding_product_data';
37
38 /**
39 * Profile data option name.
40 */
41 const PROFILE_DATA_OPTION = 'woocommerce_onboarding_profile';
42
43 /**
44 * Get class instance.
45 */
46 public static function get_instance() {
47 if ( ! self::$instance ) {
48 self::$instance = new self();
49 }
50 return self::$instance;
51 }
52
53 /**
54 * Hook into WooCommerce.
55 */
56 public function __construct() {
57 $this->add_toggle_actions();
58
59 // Include WC Admin Onboarding classes.
60 if ( self::should_show_tasks() ) {
61 OnboardingTasks::get_instance();
62 }
63
64 // Add actions and filters.
65 $this->add_actions();
66 $this->add_filters();
67 }
68
69 /**
70 * Adds the ability to toggle the new onboarding experience on or off.
71 */
72 private function add_toggle_actions() {
73 add_action( 'woocommerce_updated', array( $this, 'maybe_mark_complete' ) );
74 add_action( 'update_option_' . self::PROFILE_DATA_OPTION, array( $this, 'send_profile_data_on_update' ), 10, 2 );
75 add_action( 'woocommerce_helper_connected', array( $this, 'send_profile_data_on_connect' ) );
76 }
77
78 /**
79 * Add onboarding actions.
80 */
81 private function add_actions() {
82 // Rest API hooks need to run before is_admin() checks.
83 add_action( 'woocommerce_theme_installed', array( $this, 'delete_themes_transient' ) );
84 add_action( 'after_switch_theme', array( $this, 'delete_themes_transient' ) );
85 add_action(
86 'update_option_' . self::PROFILE_DATA_OPTION,
87 array(
88 $this,
89 'trigger_profile_completed_action',
90 ),
91 10,
92 2
93 );
94 add_action( 'woocommerce_admin_plugins_pre_activate', array( $this, 'activate_and_install_jetpack_ahead_of_wcpay' ) );
95 add_action( 'woocommerce_admin_plugins_pre_install', array( $this, 'activate_and_install_jetpack_ahead_of_wcpay' ) );
96
97 // Always hook into Jetpack connection even if outside of admin.
98 add_action( 'jetpack_site_registered', array( $this, 'set_woocommerce_setup_jetpack_opted_in' ) );
99
100 if ( ! is_admin() ) {
101 return;
102 }
103
104 add_action( 'admin_init', array( $this, 'admin_redirects' ) );
105 add_action( 'current_screen', array( $this, 'finish_paypal_connect' ) );
106 add_action( 'current_screen', array( $this, 'finish_square_connect' ) );
107 add_action( 'current_screen', array( $this, 'add_help_tab' ), 60 );
108 add_action( 'current_screen', array( $this, 'reset_profiler' ) );
109 add_action( 'current_screen', array( $this, 'reset_task_list' ) );
110 add_action( 'current_screen', array( $this, 'reset_extended_task_list' ) );
111 add_action( 'current_screen', array( $this, 'redirect_wccom_install' ) );
112 add_action( 'current_screen', array( $this, 'redirect_old_onboarding' ) );
113 }
114
115 /**
116 * Test whether the context of execution comes from async action scheduler.
117 * Note: this is a polyfill for wc_is_running_from_async_action_scheduler()
118 * which was introduced in WC 4.0.
119 *
120 * @return bool
121 */
122 public static function is_running_from_async_action_scheduler() {
123 if ( function_exists( '\wc_is_running_from_async_action_scheduler' ) ) {
124 return \wc_is_running_from_async_action_scheduler();
125 }
126
127 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
128 return isset( $_REQUEST['action'] ) && 'as_async_request_queue_runner' === $_REQUEST['action'];
129 }
130
131 /**
132 * Handle redirects to setup/welcome page after install and updates.
133 *
134 * For setup wizard, transient must be present, the user must have access rights, and we must ignore the network/bulk plugin updaters.
135 */
136 public function admin_redirects() {
137 // Don't run this fn from Action Scheduler requests, as it would clear _wc_activation_redirect transient.
138 // That means OBW would never be shown.
139 if ( self::is_running_from_async_action_scheduler() ) {
140 return;
141 }
142
143 // Setup wizard redirect.
144 if ( get_transient( '_wc_activation_redirect' ) && apply_filters( 'woocommerce_enable_setup_wizard', true ) ) {
145 $do_redirect = true;
146 $current_page = isset( $_GET['page'] ) ? wc_clean( wp_unslash( $_GET['page'] ) ) : false; // phpcs:ignore WordPress.Security.NonceVerification
147 $is_onboarding_path = ! isset( $_GET['path'] ) || '/setup-wizard' === wc_clean( wp_unslash( $_GET['page'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
148
149 // On these pages, or during these events, postpone the redirect.
150 if ( wp_doing_ajax() || is_network_admin() || ! current_user_can( 'manage_woocommerce' ) ) {
151 $do_redirect = false;
152 }
153
154 // On these pages, or during these events, disable the redirect.
155 if (
156 ( 'wc-admin' === $current_page && $is_onboarding_path ) ||
157 apply_filters( 'woocommerce_prevent_automatic_wizard_redirect', false ) ||
158 isset( $_GET['activate-multi'] ) // phpcs:ignore WordPress.Security.NonceVerification
159 ) {
160 delete_transient( '_wc_activation_redirect' );
161 $do_redirect = false;
162 }
163
164 if ( $do_redirect ) {
165 delete_transient( '_wc_activation_redirect' );
166 wp_safe_redirect( wc_admin_url() );
167 exit;
168 }
169 }
170 }
171
172 /**
173 * Sets the woocommerce_setup_jetpack_opted_in to true when Jetpack connects to WPCOM.
174 */
175 public function set_woocommerce_setup_jetpack_opted_in() {
176 update_option( 'woocommerce_setup_jetpack_opted_in', true );
177 }
178
179 /**
180 * Trigger the woocommerce_onboarding_profile_completed action
181 *
182 * @param array $old_value Previous value.
183 * @param array $value Current value.
184 */
185 public function trigger_profile_completed_action( $old_value, $value ) {
186 if ( isset( $old_value['completed'] ) && $old_value['completed'] ) {
187 return;
188 }
189
190 if ( ! isset( $value['completed'] ) || ! $value['completed'] ) {
191 return;
192 }
193
194 /**
195 * Action hook fired when the onboarding profile (or onboarding wizard,
196 * or profiler) is completed.
197 *
198 * @since 1.5.0
199 */
200 do_action( 'woocommerce_onboarding_profile_completed' );
201 }
202
203 /**
204 * Add onboarding filters.
205 */
206 private function add_filters() {
207 // Rest API hooks need to run before is_admin() checks.
208 add_filter( 'woocommerce_rest_prepare_themes', array( $this, 'add_uploaded_theme_data' ) );
209 add_filter( 'woocommerce_admin_plugins_whitelist', array( $this, 'get_onboarding_allowed_plugins' ), 10, 2 );
210
211 if ( ! is_admin() ) {
212 return;
213 }
214
215 // Old settings injection.
216 // Run after Automattic\WooCommerce\Admin\Loader.
217 add_filter( 'woocommerce_components_settings', array( $this, 'component_settings' ), 20 );
218 // New settings injection.
219 add_filter( 'woocommerce_shared_settings', array( $this, 'component_settings' ), 20 );
220 add_filter( 'woocommerce_admin_preload_options', array( $this, 'preload_options' ) );
221 add_filter( 'woocommerce_admin_preload_settings', array( $this, 'preload_settings' ) );
222 add_filter( 'woocommerce_admin_is_loading', array( $this, 'is_loading' ) );
223 add_filter( 'woocommerce_show_admin_notice', array( $this, 'remove_install_notice' ), 10, 2 );
224 }
225
226 /**
227 * Send profile data to WooCommerce.com.
228 */
229 public static function send_profile_data() {
230 if ( 'yes' !== get_option( 'woocommerce_allow_tracking', 'no' ) ) {
231 return;
232 }
233
234 if ( ! class_exists( '\WC_Helper_API' ) || ! method_exists( '\WC_Helper_API', 'put' ) ) {
235 return;
236 }
237
238 if ( ! class_exists( '\WC_Helper_Options' ) ) {
239 return;
240 }
241
242 $auth = \WC_Helper_Options::get( 'auth' );
243 if ( empty( $auth['access_token'] ) || empty( $auth['access_token_secret'] ) ) {
244 return false;
245 }
246
247 $profile = get_option( self::PROFILE_DATA_OPTION, array() );
248 $base_location = wc_get_base_location();
249 $defaults = array(
250 'plugins' => 'skipped',
251 'industry' => array(),
252 'product_types' => array(),
253 'product_count' => '0',
254 'selling_venues' => 'no',
255 'revenue' => 'none',
256 'other_platform' => 'none',
257 'business_extensions' => array(),
258 'theme' => get_stylesheet(),
259 'setup_client' => false,
260 'store_location' => $base_location['country'],
261 'default_currency' => get_woocommerce_currency(),
262 );
263
264 // Prepare industries as an array of slugs if they are in array format.
265 if ( isset( $profile['industry'] ) && is_array( $profile['industry'] ) ) {
266 $industry_slugs = array();
267 foreach ( $profile['industry'] as $industry ) {
268 $industry_slugs[] = is_array( $industry ) ? $industry['slug'] : $industry;
269 }
270 $profile['industry'] = $industry_slugs;
271 }
272 $body = wp_parse_args( $profile, $defaults );
273
274 \WC_Helper_API::put(
275 'profile',
276 array(
277 'authenticated' => true,
278 'body' => wp_json_encode( $body ),
279 'headers' => array(
280 'Content-Type' => 'application/json',
281 ),
282 )
283 );
284 }
285
286 /**
287 * Send profiler data on profiler change to completion.
288 *
289 * @param array $old_value Previous value.
290 * @param array $value Current value.
291 */
292 public static function send_profile_data_on_update( $old_value, $value ) {
293 if ( ! isset( $value['completed'] ) || ! $value['completed'] ) {
294 return;
295 }
296
297 self::send_profile_data();
298 }
299
300 /**
301 * Send profiler data after a site is connected.
302 */
303 public static function send_profile_data_on_connect() {
304 $profile = get_option( self::PROFILE_DATA_OPTION, array() );
305 if ( ! isset( $profile['completed'] ) || ! $profile['completed'] ) {
306 return;
307 }
308
309 self::send_profile_data();
310 }
311
312 /**
313 * Redirect the old onboarding wizard to the profiler.
314 */
315 public static function redirect_old_onboarding() {
316 $current_page = isset( $_GET['page'] ) ? wc_clean( wp_unslash( $_GET['page'] ) ) : false; // phpcs:ignore csrf okay.
317
318 if ( 'wc-setup' === $current_page ) {
319 delete_transient( '_wc_activation_redirect' );
320 wp_safe_redirect( wc_admin_url( '&reset_profiler=1' ) );
321 }
322 }
323
324 /**
325 * Returns true if the profiler should be displayed (not completed and not skipped).
326 *
327 * @return bool
328 */
329 public static function should_show_profiler() {
330 /* phpcs:disable WordPress.Security.NonceVerification */
331 $is_current_page = isset( $_GET['page'] ) &&
332 'wc-admin' === $_GET['page'] &&
333 isset( $_GET['path'] ) &&
334 '/setup-wizard' === $_GET['path'];
335 /* phpcs: enable */
336
337 if ( $is_current_page ) {
338 return true;
339 }
340
341 $onboarding_data = get_option( self::PROFILE_DATA_OPTION, array() );
342
343 $is_completed = isset( $onboarding_data['completed'] ) && true === $onboarding_data['completed'];
344 $is_skipped = isset( $onboarding_data['skipped'] ) && true === $onboarding_data['skipped'];
345
346 // @todo When merging to WooCommerce Core, we should set the `completed` flag to true during the upgrade progress.
347 // https://github.com/woocommerce/woocommerce-admin/pull/2300#discussion_r287237498.
348 return ! $is_completed && ! $is_skipped;
349 }
350
351 /**
352 * Returns true if the task list should be displayed (not completed or hidden off the dashboard).
353 *
354 * @return bool
355 */
356 public static function should_show_tasks() {
357 return 'no' === get_option( 'woocommerce_task_list_hidden', 'no' ) || 'no' === get_option( 'woocommerce_extended_task_list_hidden', 'no' );
358 }
359
360 /**
361 * Get a list of allowed industries for the onboarding wizard.
362 *
363 * @return array
364 */
365 public static function get_allowed_industries() {
366 /* With "use_description" we turn the description input on. With "description_label" we set the input label */
367 return apply_filters(
368 'woocommerce_admin_onboarding_industries',
369 array(
370 'fashion-apparel-accessories' => array(
371 'label' => __( 'Fashion, apparel, and accessories', 'woocommerce' ),
372 'use_description' => false,
373 'description_label' => '',
374 ),
375 'health-beauty' => array(
376 'label' => __( 'Health and beauty', 'woocommerce' ),
377 'use_description' => false,
378 'description_label' => '',
379 ),
380 'electronics-computers' => array(
381 'label' => __( 'Electronics and computers', 'woocommerce' ),
382 'use_description' => false,
383 'description_label' => '',
384 ),
385 'food-drink' => array(
386 'label' => __( 'Food and drink', 'woocommerce' ),
387 'use_description' => false,
388 'description_label' => '',
389 ),
390 'home-furniture-garden' => array(
391 'label' => __( 'Home, furniture, and garden', 'woocommerce' ),
392 'use_description' => false,
393 'description_label' => '',
394 ),
395 'cbd-other-hemp-derived-products' => array(
396 'label' => __( 'CBD and other hemp-derived products', 'woocommerce' ),
397 'use_description' => false,
398 'description_label' => '',
399 ),
400 'education-and-learning' => array(
401 'label' => __( 'Education and learning', 'woocommerce' ),
402 'use_description' => false,
403 'description_label' => '',
404 ),
405 'other' => array(
406 'label' => __( 'Other', 'woocommerce' ),
407 'use_description' => true,
408 'description_label' => 'Description',
409 ),
410 )
411 );
412 }
413
414 /**
415 * Get a list of allowed product types for the onboarding wizard.
416 *
417 * @return array
418 */
419 public static function get_allowed_product_types() {
420 $product_types = self::append_product_data(
421 array(
422 'physical' => array(
423 'label' => __( 'Physical products', 'woocommerce' ),
424 'default' => true,
425 ),
426 'downloads' => array(
427 'label' => __( 'Downloads', 'woocommerce' ),
428 ),
429 'subscriptions' => array(
430 'label' => __( 'Subscriptions', 'woocommerce' ),
431 'product' => 27147,
432 ),
433 'memberships' => array(
434 'label' => __( 'Memberships', 'woocommerce' ),
435 'product' => 958589,
436 ),
437 'bookings' => array(
438 'label' => __( 'Bookings', 'woocommerce' ),
439 'product' => 390890,
440 ),
441 'product-bundles' => array(
442 'label' => __( 'Bundles', 'woocommerce' ),
443 'product' => 18716,
444 ),
445 'product-add-ons' => array(
446 'label' => __( 'Customizable products', 'woocommerce' ),
447 'product' => 18618,
448 ),
449 )
450 );
451
452 return apply_filters( 'woocommerce_admin_onboarding_product_types', $product_types );
453 }
454
455 /**
456 * Sort themes returned from WooCommerce.com
457 *
458 * @param array $themes Array of themes from WooCommerce.com.
459 * @return array
460 */
461 public static function sort_woocommerce_themes( $themes ) {
462 usort(
463 $themes,
464 function ( $product_1, $product_2 ) {
465 if ( ! property_exists( $product_1, 'id' ) || ! property_exists( $product_1, 'slug' ) ) {
466 return 1;
467 }
468 if ( ! property_exists( $product_2, 'id' ) || ! property_exists( $product_2, 'slug' ) ) {
469 return 1;
470 }
471 if ( in_array( 'Storefront', array( $product_1->slug, $product_2->slug ), true ) ) {
472 return 'Storefront' === $product_1->slug ? -1 : 1;
473 }
474 return $product_1->id < $product_2->id ? 1 : -1;
475 }
476 );
477 return $themes;
478 }
479
480 /**
481 * Get a list of themes for the onboarding wizard.
482 *
483 * @return array
484 */
485 public static function get_themes() {
486 $themes = get_transient( self::THEMES_TRANSIENT );
487 if ( false === $themes ) {
488 $theme_data = wp_remote_get( 'https://woocommerce.com/wp-json/wccom-extensions/1.0/search?category=themes' );
489 $themes = array();
490
491 if ( ! is_wp_error( $theme_data ) ) {
492 $theme_data = json_decode( $theme_data['body'] );
493 $woo_themes = property_exists( $theme_data, 'products' ) ? $theme_data->products : array();
494 $sorted_themes = self::sort_woocommerce_themes( $woo_themes );
495
496 foreach ( $sorted_themes as $theme ) {
497 $slug = sanitize_title_with_dashes( $theme->slug );
498 $themes[ $slug ] = (array) $theme;
499 $themes[ $slug ]['is_installed'] = false;
500 $themes[ $slug ]['has_woocommerce_support'] = true;
501 $themes[ $slug ]['slug'] = $slug;
502 }
503 }
504
505 $installed_themes = wp_get_themes();
506 $active_theme = get_option( 'stylesheet' );
507
508 foreach ( $installed_themes as $slug => $theme ) {
509 $theme_data = self::get_theme_data( $theme );
510 $themes[ $slug ] = $theme_data;
511 }
512
513 // Add the WooCommerce support tag for default themes that don't explicitly declare support.
514 if ( function_exists( 'wc_is_wp_default_theme_active' ) && wc_is_wp_default_theme_active() ) {
515 $themes[ $active_theme ]['has_woocommerce_support'] = true;
516 }
517
518 $themes = array( $active_theme => $themes[ $active_theme ] ) + $themes;
519
520 set_transient( self::THEMES_TRANSIENT, $themes, DAY_IN_SECONDS );
521 }
522
523 $themes = apply_filters( 'woocommerce_admin_onboarding_themes', $themes );
524 return array_values( $themes );
525 }
526
527 /**
528 * Get theme data used in onboarding theme browser.
529 *
530 * @param WP_Theme $theme Theme to gather data from.
531 * @return array
532 */
533 public static function get_theme_data( $theme ) {
534 return array(
535 'slug' => sanitize_text_field( $theme->stylesheet ),
536 'title' => $theme->get( 'Name' ),
537 'price' => '0.00',
538 'is_installed' => true,
539 'image' => $theme->get_screenshot(),
540 'has_woocommerce_support' => true,
541 );
542 }
543
544 /**
545 * Add theme data to response from themes controller.
546 *
547 * @param WP_REST_Response $response Rest response.
548 * @return WP_REST_Response
549 */
550 public static function add_uploaded_theme_data( $response ) {
551 if ( ! isset( $response->data['theme'] ) ) {
552 return $response;
553 }
554
555 $theme = wp_get_theme( $response->data['theme'] );
556 $response->data['theme_data'] = self::get_theme_data( $theme );
557
558 return $response;
559 }
560
561 /**
562 * Check if theme has declared support for WooCommerce.
563 *
564 * @param WP_Theme $theme Theme to check.
565 * @link https://developer.woocommerce.com/2017/12/09/wc-3-3-will-look-great-on-all-the-themes/
566 * @deprecated 2.2.0
567 * @return bool
568 */
569 public static function has_woocommerce_support( $theme ) {
570 wc_deprecated_function( 'Onboarding::has_woocommerce_support', '5.3' ); // Deprecated since WooCommerce 5.3.
571 return true; // All themes are supported since WooCommerce 3.3.
572 }
573
574 /**
575 * Append dynamic product data from API.
576 *
577 * @param array $product_types Array of product types.
578 * @return array
579 */
580 public static function append_product_data( $product_types ) {
581 $woocommerce_products = get_transient( self::PRODUCT_DATA_TRANSIENT );
582 if ( false === $woocommerce_products ) {
583 $woocommerce_products = wp_remote_get( 'https://woocommerce.com/wp-json/wccom-extensions/1.0/search' );
584 if ( is_wp_error( $woocommerce_products ) ) {
585 return $product_types;
586 }
587
588 set_transient( self::PRODUCT_DATA_TRANSIENT, $woocommerce_products, DAY_IN_SECONDS );
589 }
590
591 $product_data = json_decode( $woocommerce_products['body'] );
592 $products = array();
593
594 // Map product data by ID.
595 if ( isset( $product_data ) && isset( $product_data->products ) ) {
596 foreach ( $product_data->products as $product_datum ) {
597 if ( isset( $product_datum->id ) ) {
598 $products[ $product_datum->id ] = $product_datum;
599 }
600 }
601 }
602
603 // Loop over product types and append data.
604 foreach ( $product_types as $key => $product_type ) {
605 if ( isset( $product_type['product'] ) && isset( $products[ $product_type['product'] ] ) ) {
606 $price = html_entity_decode( $products[ $product_type['product'] ]->price );
607 $yearly_price = (float) str_replace( '$', '', $price );
608
609 $product_types[ $key ]['yearly_price'] = $yearly_price;
610 $product_types[ $key ]['description'] = $products[ $product_type['product'] ]->excerpt;
611 $product_types[ $key ]['more_url'] = $products[ $product_type['product'] ]->link;
612 $product_types[ $key ]['slug'] = strtolower( preg_replace( '~[^\pL\d]+~u', '-', $products[ $product_type['product'] ]->slug ) );
613 } elseif ( isset( $product_type['product'] ) ) {
614 /* translators: site currency symbol (used to show that the product costs money) */
615 $product_types[ $key ]['label'] .= sprintf( __( ' — %s', 'woocommerce' ), html_entity_decode( get_woocommerce_currency_symbol() ) );
616 }
617 }
618
619 return $product_types;
620 }
621
622 /**
623 * Delete the stored themes transient.
624 */
625 public static function delete_themes_transient() {
626 delete_transient( self::THEMES_TRANSIENT );
627 }
628
629 /**
630 * Determine if the current page is home or setup wizard.
631 *
632 * @return bool
633 */
634 protected function is_home_or_setup_wizard_page() {
635 $allowed_paths = array( 'wc-admin', 'wc-admin&path=/setup-wizard' );
636 $current_page = PageController::get_instance()->get_current_page();
637 if ( ! $current_page || ! isset( $current_page['path'] ) ) {
638 return false;
639 }
640
641 return in_array( $current_page['path'], $allowed_paths, true );
642 }
643
644 /**
645 * Add profiler items to component settings.
646 *
647 * @param array $settings Component settings.
648 *
649 * @return array
650 */
651 public function component_settings( $settings ) {
652 $profile = (array) get_option( self::PROFILE_DATA_OPTION, array() );
653 $settings['onboarding'] = array(
654 'profile' => $profile,
655 );
656
657 // Only fetch if the onboarding wizard OR the task list is incomplete or currently shown
658 // or the current page is one of the WooCommerce Admin pages.
659 if (
660 ( ! self::should_show_profiler() && ! self::should_show_tasks()
661 ||
662 ! $this->is_home_or_setup_wizard_page()
663 )
664 ) {
665 return $settings;
666 }
667
668 include_once WC_ABSPATH . 'includes/admin/helper/class-wc-helper-options.php';
669 $wccom_auth = \WC_Helper_Options::get( 'auth' );
670 $profile['wccom_connected'] = empty( $wccom_auth['access_token'] ) ? false : true;
671
672 $settings['onboarding']['activeTheme'] = get_option( 'stylesheet' );
673 $settings['onboarding']['currencySymbols'] = get_woocommerce_currency_symbols();
674 $settings['onboarding']['euCountries'] = WC()->countries->get_european_union_countries();
675 $settings['onboarding']['industries'] = self::get_allowed_industries();
676 $settings['onboarding']['localeInfo'] = include WC()->plugin_path() . '/i18n/locale-info.php';
677 $settings['onboarding']['productTypes'] = self::get_allowed_product_types();
678 $settings['onboarding']['profile'] = $profile;
679 $settings['onboarding']['themes'] = self::get_themes();
680
681 return $settings;
682 }
683
684 /**
685 * Preload options to prime state of the application.
686 *
687 * @param array $options Array of options to preload.
688 * @return array
689 */
690 public function preload_options( $options ) {
691 $options[] = 'woocommerce_task_list_complete';
692 $options[] = 'woocommerce_task_list_do_this_later';
693 $options[] = 'woocommerce_task_list_hidden';
694 $options[] = 'woocommerce_extended_task_list_complete';
695 $options[] = 'woocommerce_extended_task_list_hidden';
696
697 if ( ! self::should_show_tasks() && ! self::should_show_profiler() ) {
698 return $options;
699 }
700
701 $options[] = 'wc_connect_options';
702 $options[] = 'woocommerce_task_list_welcome_modal_dismissed';
703 $options[] = 'woocommerce_welcome_from_calypso_modal_dismissed';
704 $options[] = 'woocommerce_task_list_prompt_shown';
705 $options[] = 'woocommerce_task_list_tracked_completed_tasks';
706 $options[] = 'woocommerce_task_list_dismissed_tasks';
707 $options[] = 'woocommerce_allow_tracking';
708 $options[] = 'woocommerce_woo-mercado-pago-basic_settings';
709 $options[] = 'woocommerce_stripe_settings';
710 $options[] = 'woocommerce-ppcp-settings';
711 $options[] = 'woocommerce_ppcp-gateway_settings';
712 $options[] = 'wc_square_refresh_tokens';
713 $options[] = 'woocommerce_square_credit_card_settings';
714 $options[] = 'woocommerce_payfast_settings';
715 $options[] = 'woocommerce_paystack_settings';
716 $options[] = 'woocommerce_kco_settings';
717 $options[] = 'woocommerce_klarna_payments_settings';
718 $options[] = 'woocommerce_cod_settings';
719 $options[] = 'woocommerce_bacs_settings';
720 $options[] = 'woocommerce_bacs_accounts';
721 $options[] = 'woocommerce_woocommerce_payments_settings';
722 $options[] = 'woocommerce_eway_settings';
723 $options[] = 'woocommerce_razorpay_settings';
724 $options[] = 'woocommerce_payubiz_settings';
725 $options[] = 'woocommerce_mollie_payments_settings';
726
727 return $options;
728 }
729
730 /**
731 * Preload WC setting options to prime state of the application.
732 *
733 * @param array $options Array of options to preload.
734 * @return array
735 */
736 public function preload_settings( $options ) {
737 $options[] = 'general';
738
739 return $options;
740 }
741
742 /**
743 * Gets an array of plugins that can be installed & activated via the onboarding wizard.
744 *
745 * @param array $plugins Array of plugin slugs to be allowed.
746 *
747 * @return array
748 * @todo Handle edgecase of where installed plugins may have versioned folder names (i.e. `jetpack-main/jetpack.php`).
749 */
750 public static function get_onboarding_allowed_plugins( $plugins ) {
751 $onboarding_plugins = apply_filters(
752 'woocommerce_admin_onboarding_plugins_whitelist',
753 array(
754 'facebook-for-woocommerce' => 'facebook-for-woocommerce/facebook-for-woocommerce.php',
755 'mailchimp-for-woocommerce' => 'mailchimp-for-woocommerce/mailchimp-woocommerce.php',
756 'creative-mail-by-constant-contact' => 'creative-mail-by-constant-contact/creative-mail-plugin.php',
757 'kliken-marketing-for-google' => 'kliken-marketing-for-google/kliken-marketing-for-google.php',
758 'jetpack' => 'jetpack/jetpack.php',
759 'woocommerce-services' => 'woocommerce-services/woocommerce-services.php',
760 'woocommerce-gateway-stripe' => 'woocommerce-gateway-stripe/woocommerce-gateway-stripe.php',
761 'woocommerce-paypal-payments' => 'woocommerce-paypal-payments/woocommerce-paypal-payments.php',
762 'klarna-checkout-for-woocommerce' => 'klarna-checkout-for-woocommerce/klarna-checkout-for-woocommerce.php',
763 'klarna-payments-for-woocommerce' => 'klarna-payments-for-woocommerce/klarna-payments-for-woocommerce.php',
764 'woocommerce-square' => 'woocommerce-square/woocommerce-square.php',
765 'woocommerce-shipstation-integration' => 'woocommerce-shipstation-integration/woocommerce-shipstation.php',
766 'woocommerce-payfast-gateway' => 'woocommerce-payfast-gateway/gateway-payfast.php',
767 'woo-paystack' => 'woo-paystack/woo-paystack.php',
768 'woocommerce-payments' => 'woocommerce-payments/woocommerce-payments.php',
769 'woocommerce-gateway-eway' => 'woocommerce-gateway-eway/woocommerce-gateway-eway.php',
770 'woo-razorpay' => 'woo-razorpay/woo-razorpay.php',
771 'mollie-payments-for-woocommerce' => 'mollie-payments-for-woocommerce/mollie-payments-for-woocommerce.php',
772 'payu-india' => 'payu-india/index.php',
773 'mailpoet' => 'mailpoet/mailpoet.php',
774 'woocommerce-mercadopago' => 'woocommerce-mercadopago/woocommerce-mercadopago.php',
775 )
776 );
777 return array_merge( $plugins, $onboarding_plugins );
778 }
779
780 /**
781 * Gets an array of themes that can be installed & activated via the onboarding wizard.
782 *
783 * @return array
784 */
785 public static function get_allowed_themes() {
786 $allowed_themes = array();
787 $themes = self::get_themes();
788
789 foreach ( $themes as $theme ) {
790 $price = preg_replace( '/&#?[a-z0-9]+;/i', '', $theme['price'] );
791
792 if ( $theme['is_installed'] || '0.00' === $price ) {
793 $allowed_themes[] = $theme['slug'];
794 }
795 }
796
797 return apply_filters( 'woocommerce_admin_onboarding_themes_whitelist', $allowed_themes );
798 }
799
800 /**
801 * Let the app know that we will be showing the onboarding route, so wp-admin elements should be hidden while loading.
802 *
803 * @param bool $is_loading Indicates if the `woocommerce-admin-is-loading` should be appended or not.
804 * @return bool
805 */
806 public function is_loading( $is_loading ) {
807 $show_profiler = self::should_show_profiler();
808
809 if ( $show_profiler ) {
810 return true;
811 }
812
813 return $is_loading;
814 }
815
816 /**
817 * Instead of redirecting back to the payment settings page, we will redirect back to the payments task list with our status.
818 *
819 * @param string $location URL of redirect.
820 * @param int $status HTTP response status code.
821 * @return string URL of redirect.
822 */
823 public function overwrite_paypal_redirect( $location, $status ) {
824 $settings_page = 'tab=checkout&section=ppec_paypal';
825 if ( substr( $location, -strlen( $settings_page ) ) === $settings_page ) {
826 $settings_array = (array) get_option( 'woocommerce_ppec_paypal_settings', array() );
827 $connected = isset( $settings_array['api_username'] ) && isset( $settings_array['api_password'] ) ? true : false;
828 return wc_admin_url( '&task=payments&method=paypal&paypal-connect=' . $connected );
829 }
830 return $location;
831 }
832
833 /**
834 * Finishes the PayPal connection process by saving the correct settings.
835 */
836 public function finish_paypal_connect() {
837 if (
838 ! Loader::is_admin_page() ||
839 ! isset( $_GET['paypal-connect-finish'] ) // phpcs:ignore CSRF ok.
840 ) {
841 return;
842 }
843
844 if ( ! function_exists( 'wc_gateway_ppec' ) ) {
845 return false;
846 }
847
848 // @todo This is a bit hacky but works. Ideally, woocommerce-gateway-paypal-express-checkout would contain a filter for us.
849 add_filter( 'wp_redirect', array( $this, 'overwrite_paypal_redirect' ), 10, 2 );
850 wc_gateway_ppec()->ips->maybe_received_credentials();
851 remove_filter( 'wp_redirect', array( $this, 'overwrite_paypal_redirect' ) );
852 }
853
854 /**
855 * Instead of redirecting back to the payment settings page, we will redirect back to the payments task list with our status.
856 *
857 * @param string $location URL of redirect.
858 * @param int $status HTTP response status code.
859 * @return string URL of redirect.
860 */
861 public function overwrite_square_redirect( $location, $status ) {
862 $settings_page = 'page=wc-settings&tab=square';
863 if ( substr( $location, -strlen( $settings_page ) ) === $settings_page ) {
864 return wc_admin_url( '&task=payments&method=square&square-connect=1' );
865 }
866 return $location;
867 }
868
869 /**
870 * Finishes the Square connection process by saving the correct settings.
871 */
872 public function finish_square_connect() {
873 if (
874 ! Loader::is_admin_page() ||
875 ! isset( $_GET['square-connect-finish'] ) // phpcs:ignore CSRF ok.
876 ) {
877 return;
878 }
879
880 if ( ! class_exists( '\WooCommerce\Square\Plugin' ) ) {
881 return false;
882 }
883
884 $square = \WooCommerce\Square\Plugin::instance();
885
886 // @todo This is a bit hacky but works. Ideally, woocommerce-square would contain a filter for us.
887 add_filter( 'wp_redirect', array( $this, 'overwrite_square_redirect' ), 10, 2 );
888 $square->get_connection_handler()->handle_connected();
889 remove_filter( 'wp_redirect', array( $this, 'overwrite_square_redirect' ) );
890 }
891
892 /**
893 * Track changes to the onboarding option.
894 *
895 * @param mixed $mixed Option name or previous value if option previously existed.
896 * @param string $value Value of the updated option.
897 */
898 public static function track_onboarding_toggle( $mixed, $value ) {
899 if ( defined( 'WC_ADMIN_MIGRATING_OPTIONS' ) && WC_ADMIN_MIGRATING_OPTIONS ) {
900 return;
901 };
902
903 wc_admin_record_tracks_event(
904 'onboarding_toggled',
905 array(
906 'previous_value' => ! $value,
907 'new_value' => $value,
908 )
909 );
910 }
911
912 /**
913 * Update the help tab setup link to reset the onboarding profiler.
914 */
915 public static function add_help_tab() {
916 if ( ! function_exists( 'wc_get_screen_ids' ) ) {
917 return;
918 }
919
920 $screen = get_current_screen();
921
922 if ( ! $screen || ! in_array( $screen->id, wc_get_screen_ids(), true ) ) {
923 return;
924 }
925
926 // Remove the old help tab if it exists.
927 $help_tabs = $screen->get_help_tabs();
928 foreach ( $help_tabs as $help_tab ) {
929 if ( 'woocommerce_onboard_tab' !== $help_tab['id'] ) {
930 continue;
931 }
932
933 $screen->remove_help_tab( 'woocommerce_onboard_tab' );
934 }
935
936 // Add the new help tab.
937 $help_tab = array(
938 'title' => __( 'Setup wizard', 'woocommerce' ),
939 'id' => 'woocommerce_onboard_tab',
940 );
941
942 $task_list_hidden = ( 'yes' === get_option( 'woocommerce_task_list_hidden', 'no' ) );
943
944 $extended_task_list_hidden = ( 'yes' === get_option( 'woocommerce_extended_task_list_hidden', 'no' ) );
945
946 $help_tab['content'] = '<h2>' . __( 'WooCommerce Onboarding', 'woocommerce' ) . '</h2>';
947
948 $help_tab['content'] .= '<h3>' . __( 'Profile Setup Wizard', 'woocommerce' ) . '</h3>';
949 $help_tab['content'] .= '<p>' . __( 'If you need to access the setup wizard again, please click on the button below.', 'woocommerce' ) . '</p>' .
950 '<p><a href="' . wc_admin_url( '&path=/setup-wizard' ) . '" class="button button-primary">' . __( 'Setup wizard', 'woocommerce' ) . '</a></p>';
951
952 $help_tab['content'] .= '<h3>' . __( 'Task List', 'woocommerce' ) . '</h3>';
953 $help_tab['content'] .= '<p>' . __( 'If you need to enable or disable the task lists, please click on the button below.', 'woocommerce' ) . '</p>' .
954 ( $task_list_hidden
955 ? '<p><a href="' . wc_admin_url( '&reset_task_list=1' ) . '" class="button button-primary">' . __( 'Enable', 'woocommerce' ) . '</a></p>'
956 : '<p><a href="' . wc_admin_url( '&reset_task_list=0' ) . '" class="button button-primary">' . __( 'Disable', 'woocommerce' ) . '</a></p>'
957 );
958
959 $help_tab['content'] .= '<h3>' . __( 'Extended task List', 'woocommerce' ) . '</h3>';
960 $help_tab['content'] .= '<p>' . __( 'If you need to enable or disable the extended task lists, please click on the button below.', 'woocommerce' ) . '</p>' .
961 ( $extended_task_list_hidden
962 ? '<p><a href="' . wc_admin_url( '&reset_extended_task_list=1' ) . '" class="button button-primary">' . __( 'Enable', 'woocommerce' ) . '</a></p>'
963 : '<p><a href="' . wc_admin_url( '&reset_extended_task_list=0' ) . '" class="button button-primary">' . __( 'Disable', 'woocommerce' ) . '</a></p>'
964 );
965
966 $screen->add_help_tab( $help_tab );
967 }
968
969 /**
970 * Reset the onboarding profiler and redirect to the profiler.
971 */
972 public static function reset_profiler() {
973 if (
974 ! Loader::is_admin_page() ||
975 ! isset( $_GET['reset_profiler'] ) // phpcs:ignore CSRF ok.
976 ) {
977 return;
978 }
979
980 $previous = 1 === absint( $_GET['reset_profiler'] ); // phpcs:ignore CSRF ok.
981 $new_value = ! $previous;
982
983 wc_admin_record_tracks_event(
984 'storeprofiler_toggled',
985 array(
986 'previous' => $previous,
987 'new_value' => $new_value,
988 )
989 );
990
991 $request = new \WP_REST_Request( 'POST', '/wc-admin/onboarding/profile' );
992 $request->set_headers( array( 'content-type' => 'application/json' ) );
993 $request->set_body(
994 wp_json_encode(
995 array(
996 'completed' => $new_value,
997 'skipped' => $new_value,
998 )
999 )
1000 );
1001 $response = rest_do_request( $request );
1002 wp_safe_redirect( wc_admin_url() );
1003 exit;
1004 }
1005
1006 /**
1007 * Reset the onboarding task list and redirect to the dashboard.
1008 */
1009 public static function reset_task_list() {
1010 if (
1011 ! Loader::is_admin_page() ||
1012 ! isset( $_GET['reset_task_list'] ) // phpcs:ignore CSRF ok.
1013 ) {
1014 return;
1015 }
1016
1017 $task_list_hidden = 1 === absint( $_GET['reset_task_list'] ) ? 'no' : 'yes'; // phpcs:ignore CSRF ok.
1018 update_option( 'woocommerce_task_list_hidden', $task_list_hidden );
1019
1020 wc_admin_record_tracks_event(
1021 'tasklist_toggled',
1022 array(
1023 'status' => 'yes' === $task_list_hidden ? 'disabled' : 'enabled',
1024 )
1025 );
1026 wp_safe_redirect( wc_admin_url() );
1027 exit;
1028 }
1029
1030 /**
1031 * Reset the extended task list and redirect to the dashboard.
1032 */
1033 public static function reset_extended_task_list() {
1034 if (
1035 ! Loader::is_admin_page() ||
1036 ! isset( $_GET['reset_extended_task_list'] ) // phpcs:ignore CSRF ok.
1037 ) {
1038 return;
1039 }
1040
1041 $extended_task_list_hidden = 1 === absint( $_GET['reset_extended_task_list'] ) ? 'no' : 'yes'; // phpcs:ignore CSRF ok.
1042 update_option( 'woocommerce_extended_task_list_hidden', $extended_task_list_hidden );
1043
1044 wc_admin_record_tracks_event(
1045 'extended_tasklist_toggled',
1046 array(
1047 'status' => 'yes' === $extended_task_list_hidden ? 'disabled' : 'enabled',
1048 )
1049 );
1050 wp_safe_redirect( wc_admin_url() );
1051 exit;
1052 }
1053
1054 /**
1055 * Remove the install notice that prompts the user to visit the old onboarding setup wizard.
1056 *
1057 * @param bool $show Show or hide the notice.
1058 * @param string $notice The slug of the notice.
1059 * @return bool
1060 */
1061 public static function remove_install_notice( $show, $notice ) {
1062 if ( 'install' === $notice ) {
1063 return false;
1064 }
1065
1066 return $show;
1067 }
1068
1069 /**
1070 * Redirects the user to the task list if the task list is enabled and finishing a wccom checkout.
1071 *
1072 * @todo Once URL params are added to the redirect, we can check those instead of the referer.
1073 */
1074 public static function redirect_wccom_install() {
1075 if (
1076 ! self::should_show_tasks() ||
1077 ! isset( $_SERVER['HTTP_REFERER'] ) ||
1078 0 !== strpos( $_SERVER['HTTP_REFERER'], 'https://woocommerce.com/checkout' ) // phpcs:ignore sanitization ok.
1079 ) {
1080 return;
1081 }
1082
1083 wp_safe_redirect( wc_admin_url() );
1084 }
1085
1086 /**
1087 * When updating WooCommerce, mark the profiler and task list complete.
1088 *
1089 * @todo The `maybe_enable_setup_wizard()` method should be revamped on onboarding enable in core.
1090 * See https://github.com/woocommerce/woocommerce/blob/1ca791f8f2325fe2ee0947b9c47e6a4627366374/includes/class-wc-install.php#L341
1091 */
1092 public static function maybe_mark_complete() {
1093 // The install notice still exists so don't complete the profiler.
1094 if ( ! class_exists( 'WC_Admin_Notices' ) || \WC_Admin_Notices::has_notice( 'install' ) ) {
1095 return;
1096 }
1097
1098 $onboarding_data = get_option( self::PROFILE_DATA_OPTION, array() );
1099 // Don't make updates if the profiler is completed, but task list is potentially incomplete.
1100 if ( isset( $onboarding_data['completed'] ) && $onboarding_data['completed'] ) {
1101 return;
1102 }
1103
1104 $onboarding_data['completed'] = true;
1105 update_option( self::PROFILE_DATA_OPTION, $onboarding_data );
1106 update_option( 'woocommerce_task_list_hidden', 'yes' );
1107 }
1108
1109 /**
1110 * Ensure that Jetpack gets installed and activated ahead of WooCommerce Payments
1111 * if both are being installed/activated at the same time.
1112 *
1113 * See: https://github.com/Automattic/woocommerce-payments/issues/1663
1114 * See: https://github.com/Automattic/jetpack/issues/19624
1115 *
1116 * @param array $plugins A list of plugins to install or activate.
1117 *
1118 * @return array
1119 */
1120 public static function activate_and_install_jetpack_ahead_of_wcpay( $plugins ) {
1121 if ( in_array( 'jetpack', $plugins, true ) && in_array( 'woocommerce-payments', $plugins, true ) ) {
1122 array_unshift( $plugins, 'jetpack' );
1123 $plugins = array_unique( $plugins );
1124 }
1125 return $plugins;
1126 }
1127 }
1128