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§ion=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 |