* Move purchase task

* Move products task

* Move WC Pay task

* Fix property casing

* Move payments task

* Move tax task

* Migrate shipping task

* Move marketing task

* Migrate appearance task

* Remove deprecated task filters

* Move logic to respective model

* Fix task list methods

* Update visibility to can_view property

* Add default tasks on demand

* Handle PR feedback
This commit is contained in:
Joshua T Flowers 2021-09-27 16:55:55 -04:00 committed by GitHub
parent 14c38190ac
commit a2f78f156b
15 changed files with 601 additions and 423 deletions

View File

@ -85,7 +85,6 @@ export type TasksStatusState = {
isAppearanceComplete: boolean;
isTaxComplete: boolean;
shippingZonesCount: number;
stripeSupportedCountries: string[];
stylesheet: string;
taxJarActivated: boolean;
// TODO - fill out this type

View File

@ -712,15 +712,6 @@ class OnboardingTasks extends \WC_REST_Data_Controller {
'context' => array( 'view' ),
'readonly' => true,
),
'stripeSupportedCountries' => array(
'type' => 'array',
'description' => __( 'Country codes that are supported by Stripe.', 'woocommerce-admin' ),
'context' => array( 'view' ),
'readonly' => true,
'items' => array(
'type' => 'string',
),
),
'taxJarActivated' => array(
'type' => 'boolean',
'description' => __( 'If the store has the TaxJar extension active.', 'woocommerce-admin' ),
@ -762,8 +753,14 @@ class OnboardingTasks extends \WC_REST_Data_Controller {
* @return WP_REST_Response|WP_Error
*/
public function get_tasks() {
$task_lists = TaskLists::get_all();
return rest_ensure_response( $task_lists );
$lists = TaskLists::get_lists();
$json = array_map(
function( $list ) {
return $list->get_json();
},
$lists
);
return rest_ensure_response( array_values( apply_filters( 'woocommerce_admin_onboarding_tasks', $json ) ) );
}
/**

View File

@ -8,6 +8,7 @@ namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks;
use \Automattic\WooCommerce\Admin\Loader;
use Automattic\WooCommerce\Admin\API\Reports\Taxes\Stats\DataStore as TaxDataStore;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks\Tax;
/**
* Contains the logic for completing onboarding tasks.
@ -47,14 +48,10 @@ class Init {
add_action( 'add_option_woocommerce_task_list_tracked_completed_tasks', array( $this, 'track_task_completion' ), 10, 2 );
add_action( 'update_option_woocommerce_task_list_tracked_completed_tasks', array( $this, 'track_task_completion' ), 10, 2 );
add_action( 'admin_enqueue_scripts', array( $this, 'update_option_extended_task_list' ), 15 );
add_filter( 'woocommerce_admin_onboarding_tasks', array( $this, 'add_task_dismissal' ), 20 );
add_filter( 'woocommerce_admin_onboarding_tasks', array( $this, 'add_task_snoozed' ), 20 );
add_filter( 'woocommerce_admin_onboarding_tasks', array( $this, 'add_task_list_hidden' ), 20 );
add_filter( 'pre_option_woocommerce_task_list_hidden', array( $this, 'get_deprecated_options' ), 10, 2 );
add_filter( 'pre_option_woocommerce_extended_task_list_hidden', array( $this, 'get_deprecated_options' ), 10, 2 );
add_action( 'pre_update_option_woocommerce_task_list_hidden', array( $this, 'update_deprecated_options' ), 10, 3 );
add_action( 'pre_update_option_woocommerce_extended_task_list_hidden', array( $this, 'update_deprecated_options' ), 10, 3 );
TaskLists::add_defaults();
if ( ! is_admin() ) {
return;
@ -81,8 +78,6 @@ class Init {
wp_enqueue_media();
}
/**
* Get task item data for settings filter.
*
@ -108,7 +103,7 @@ class Init {
// @todo We may want to consider caching some of these and use to check against
// task completion along with cache busting for active tasks.
$settings['automatedTaxSupportedCountries'] = self::get_automated_tax_supported_countries();
$settings['automatedTaxSupportedCountries'] = Tax::get_automated_tax_supported_countries();
$settings['hasHomepage'] = self::check_task_completion( 'homepage' ) || 'classic' === get_option( 'classic-editor-replace' );
$settings['hasPaymentGateway'] = ! empty( $enabled_gateways );
$settings['enabledPaymentGateways'] = array_keys( $enabled_gateways );
@ -124,7 +119,6 @@ class Init {
$settings['isAppearanceComplete'] = get_option( 'woocommerce_task_list_appearance_complete' );
$settings['isTaxComplete'] = self::check_task_completion( 'tax' );
$settings['shippingZonesCount'] = count( \WC_Shipping_Zones::get_zones() );
$settings['stripeSupportedCountries'] = self::get_stripe_supported_countries();
$settings['stylesheet'] = get_option( 'stylesheet' );
$settings['taxJarActivated'] = class_exists( 'WC_Taxjar' );
$settings['themeMods'] = get_theme_mods();
@ -336,93 +330,6 @@ class Init {
}
}
/**
* Get an array of countries that support automated tax.
*
* @return array
*/
public static function get_automated_tax_supported_countries() {
// https://developers.taxjar.com/api/reference/#countries .
$tax_supported_countries = array_merge(
array( 'US', 'CA', 'AU' ),
WC()->countries->get_european_union_countries()
);
return $tax_supported_countries;
}
/**
* Returns a list of Stripe supported countries. This method can be removed once merged to core.
*
* @return array
*/
public static function get_stripe_supported_countries() {
// https://stripe.com/global.
return array(
'AU',
'AT',
'BE',
'BG',
'BR',
'CA',
'CY',
'CZ',
'DK',
'EE',
'FI',
'FR',
'DE',
'GR',
'HK',
'IN',
'IE',
'IT',
'JP',
'LV',
'LT',
'LU',
'MY',
'MT',
'MX',
'NL',
'NZ',
'NO',
'PL',
'PT',
'RO',
'SG',
'SK',
'SI',
'ES',
'SE',
'CH',
'GB',
'US',
'PR',
);
}
/**
* Returns a list of WooCommerce Payments supported countries.
*
* @return array
*/
public static function get_woocommerce_payments_supported_countries() {
return array(
'US',
'PR',
'AU',
'CA',
'DE',
'ES',
'FR',
'GB',
'IE',
'IT',
'NZ',
);
}
/**
* Records an event when all tasks are completed in the task list.
*
@ -485,63 +392,6 @@ class Init {
}
}
/**
* Add the dismissal status to each task.
*
* @param array $task_lists Task lists.
* @return array
*/
public function add_task_dismissal( $task_lists ) {
$dismissed = get_option( 'woocommerce_task_list_dismissed_tasks', array() );
foreach ( $task_lists as $task_list_key => $task_list ) {
foreach ( $task_list['tasks'] as $task_key => $task ) {
if ( isset( $task['isDismissable'] ) && in_array( $task['id'], $dismissed, true ) ) {
$task_lists[ $task_list_key ]['tasks'][ $task_key ]['isDismissed'] = true;
}
}
}
return $task_lists;
}
/**
* Add the snoozed status to each task.
*
* @param array $task_lists Task lists.
* @return array
*/
public function add_task_snoozed( $task_lists ) {
$snoozed_tasks = get_option( 'woocommerce_task_list_remind_me_later_tasks', array() );
foreach ( $task_lists as $task_list_key => $task_list ) {
foreach ( $task_list['tasks'] as $task_key => $task ) {
if ( isset( $task['isSnoozeable'] ) && in_array( $task['id'], array_keys( $snoozed_tasks ), true ) ) {
$task_lists[ $task_list_key ]['tasks'][ $task_key ]['isSnoozed'] = $snoozed_tasks[ $task['id'] ] > ( time() * 1000 );
$task_lists[ $task_list_key ]['tasks'][ $task_key ]['snoozedUntil'] = $snoozed_tasks[ $task['id'] ];
}
}
}
return $task_lists;
}
/**
* Add the task list isHidden attribute to each list.
*
* @param array $task_lists Task lists.
* @return array
*/
public function add_task_list_hidden( $task_lists ) {
$hidden = get_option( 'woocommerce_task_list_hidden_lists', array() );
foreach ( $task_lists as $key => $task_list ) {
$task_lists[ $key ]['isHidden'] = in_array( $task_list['id'], $hidden, true );
}
return $task_lists;
}
/**
* Get the values from the correct source when attempting to retrieve deprecated options.
*

View File

@ -26,14 +26,14 @@ class TaskList {
*
* @var string
*/
protected $id = '';
public $id = '';
/**
* Title.
*
* @var string
*/
protected $title = '';
public $title = '';
/**
* Title.

View File

@ -5,13 +5,16 @@
namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks;
use Automattic\WooCommerce\Admin\API\Reports\Taxes\Stats\DataStore as TaxDataStore;
use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Admin\Features\Onboarding;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Init as OnboardingTasks;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks\Appearance;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks\Marketing;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks\Payments;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks\Products;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks\Purchase;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks\Shipping;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks\StoreDetails;
use Automattic\WooCommerce\Admin\Features\RemoteFreeExtensions\Init as RemoteFreeExtensions;
use Automattic\WooCommerce\Admin\PluginsHelper;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks\Tax;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks\WooCommercePayments;
use Automattic\WooCommerce\Admin\Loader;
/**
* Task Lists class.
@ -79,7 +82,13 @@ class TaskLists {
/**
* Add default task lists.
*/
public static function add_defaults() {
public static function maybe_add_default_tasks() {
$added = isset( self::$lists['setup'] );
if ( ! apply_filters( 'woocommerce_admin_onboarding_tasks_add_default_tasks', ! $added ) ) {
return;
}
self::add_list(
array(
'id' => 'setup',
@ -88,6 +97,14 @@ class TaskLists {
);
self::add_task( 'setup', StoreDetails::get_task() );
self::add_task( 'setup', Purchase::get_task() );
self::add_task( 'setup', Products::get_task() );
self::add_task( 'setup', WooCommercePayments::get_task() );
self::add_task( 'setup', Payments::get_task() );
self::add_task( 'setup', Tax::get_task() );
self::add_task( 'setup', Shipping::get_task() );
self::add_task( 'setup', Marketing::get_task() );
self::add_task( 'setup', Appearance::get_task() );
}
/**
@ -95,241 +112,9 @@ class TaskLists {
*
* @return array
*/
public static function get_all() {
$profiler_data = get_option( Onboarding::PROFILE_DATA_OPTION, array() );
$installed_plugins = PluginsHelper::get_installed_plugin_slugs();
$product_types = isset( $profiler_data['product_types'] ) ? $profiler_data['product_types'] : array();
$allowed_product_types = Onboarding::get_allowed_product_types();
$purchaseable_products = array();
$remaining_products = array();
foreach ( $product_types as $product_type ) {
if ( ! isset( $allowed_product_types[ $product_type ]['slug'] ) ) {
continue;
}
$purchaseable_products[] = $allowed_product_types[ $product_type ];
if ( ! in_array( $allowed_product_types[ $product_type ]['slug'], $installed_plugins, true ) ) {
$remaining_products[] = $allowed_product_types[ $product_type ]['label'];
}
}
$business_extensions = isset( $profiler_data['business_extensions'] ) ? $profiler_data['business_extensions'] : array();
$product_query = new \WC_Product_Query(
array(
'limit' => 1,
'return' => 'ids',
'status' => array( 'publish' ),
)
);
$products = $product_query->get_products();
$wc_pay_is_connected = false;
if ( class_exists( '\WC_Payments' ) ) {
$wc_payments_gateway = \WC_Payments::get_gateway();
$wc_pay_is_connected = method_exists( $wc_payments_gateway, 'is_connected' )
? $wc_payments_gateway->is_connected()
: false;
}
$gateways = WC()->payment_gateways->get_available_payment_gateways();
$enabled_gateways = array_filter(
$gateways,
function( $gateway ) {
return 'yes' === $gateway->enabled;
}
);
$can_use_automated_taxes = ! class_exists( 'WC_Taxjar' ) &&
in_array( WC()->countries->get_base_country(), OnboardingTasks::get_automated_tax_supported_countries(), true );
$marketing_extension_bundles = RemoteFreeExtensions::get_extensions(
array(
'reach',
'grow',
)
);
$has_installed_marketing_extensions = array_reduce(
$marketing_extension_bundles,
function( $has_installed, $bundle ) {
if ( $has_installed ) {
return true;
}
foreach ( $bundle['plugins'] as $plugin ) {
if ( $plugin->is_installed ) {
return true;
}
}
return false;
},
false
);
$task_lists = array(
array(
'id' => 'setup',
'isComplete' => get_option( 'woocommerce_task_list_complete' ) === 'yes',
'title' => __( 'Get ready to start selling', 'woocommerce-admin' ),
'tasks' => array(
array(
'id' => 'store_details',
'title' => __( 'Store details', 'woocommerce-admin' ),
'content' => __(
'Your store address is required to set the origin country for shipping, currencies, and payment options.',
'woocommerce-admin'
),
'actionLabel' => __( "Let's go", 'woocommerce-admin' ),
'actionUrl' => '/setup-wizard',
'isComplete' => isset( $profiler_data['completed'] ) && true === $profiler_data['completed'],
'isVisible' => true,
'time' => __( '4 minutes', 'woocommerce-admin' ),
),
array(
'id' => 'purchase',
'title' => count( $remaining_products ) === 1
? sprintf(
/* translators: %1$s: list of product names comma separated, %2%s the last product name */
__(
'Add %s to my store',
'woocommerce-admin'
),
$remaining_products[0]
)
: __(
'Add paid extensions to my store',
'woocommerce-admin'
),
'content' => count( $remaining_products ) === 1
? $purchaseable_products[0]['description']
: sprintf(
/* translators: %1$s: list of product names comma separated, %2%s the last product name */
__(
'Good choice! You chose to add %1$s and %2$s to your store.',
'woocommerce-admin'
),
implode( ', ', array_slice( $remaining_products, 0, -1 ) ) . ( count( $remaining_products ) > 2 ? ',' : '' ),
end( $remaining_products )
),
'actionLabel' => __( 'Purchase & install now', 'woocommerce-admin' ),
'actionUrl' => '/setup-wizard',
'isComplete' => count( $remaining_products ) === 0,
'isVisible' => count( $purchaseable_products ) > 0,
'time' => __( '2 minutes', 'woocommerce-admin' ),
'isDismissable' => true,
),
array(
'id' => 'products',
'title' => __( 'Add my products', 'woocommerce-admin' ),
'content' => __(
'Start by adding the first product to your store. You can add your products manually, via CSV, or import them from another service.',
'woocommerce-admin'
),
'isComplete' => 0 !== count( $products ),
'isVisible' => true,
'time' => __( '1 minute per product', 'woocommerce-admin' ),
),
array(
'id' => 'woocommerce-payments',
'title' => __( 'Get paid with WooCommerce Payments', 'woocommerce-admin' ),
'content' => __(
"You're only one step away from getting paid. Verify your business details to start managing transactions with WooCommerce Payments.",
'woocommerce-admin'
),
'actionLabel' => __( 'Finish setup', 'woocommerce-admin' ),
'expanded' => true,
'isComplete' => $wc_pay_is_connected,
'isVisible' => in_array( 'woocommerce-payments', $business_extensions, true ) &&
in_array( 'woocommerce-payments', $installed_plugins, true ) &&
in_array( WC()->countries->get_base_country(), OnboardingTasks::get_woocommerce_payments_supported_countries(), true ),
'time' => __( '2 minutes', 'woocommerce-admin' ),
),
array(
'id' => 'payments',
'title' => __( 'Set up payments', 'woocommerce-admin' ),
'content' => __(
'Choose payment providers and enable payment methods at checkout.',
'woocommerce-admin'
),
'isComplete' => ! empty( $enabled_gateways ),
'isVisible' => Features::is_enabled( 'payment-gateway-suggestions' ) &&
(
! in_array( 'woocommerce-payments', $business_extensions, true ) ||
! in_array( 'woocommerce-payments', $installed_plugins, true ) ||
! in_array( WC()->countries->get_base_country(), OnboardingTasks::get_woocommerce_payments_supported_countries(), true )
),
'time' => __( '2 minutes', 'woocommerce-admin' ),
),
array(
'id' => 'tax',
'title' => __( 'Set up tax', 'woocommerce-admin' ),
'content' => $can_use_automated_taxes
? __(
'Good news! WooCommerce Services and Jetpack can automate your sales tax calculations for you.',
'woocommerce-admin'
)
: __(
'Set your store location and configure tax rate settings.',
'woocommerce-admin'
),
'actionLabel' => $can_use_automated_taxes
? __( 'Yes please', 'woocommerce-admin' )
: __( "Let's go", 'woocommerce-admin' ),
'isComplete' => get_option( 'wc_connect_taxes_enabled' ) ||
count( TaxDataStore::get_taxes( array() ) ) > 0 ||
false !== get_option( 'woocommerce_no_sales_tax' ),
'isVisible' => true,
'time' => __( '1 minute', 'woocommerce-admin' ),
),
array(
'id' => 'shipping',
'title' => __( 'Set up shipping', 'woocommerce-admin' ),
'content' => __(
"Set your store location and where you'll ship to.",
'woocommerce-admin'
),
'actionUrl' => count( \WC_Shipping_Zones::get_zones() ) > 0
? admin_url( 'admin.php?page=wc-settings&tab=shipping' )
: null,
'actionLabel' => __( "Let's go", 'woocommerce-admin' ),
'isComplete' => count( \WC_Shipping_Zones::get_zones() ) > 0,
'isVisible' => in_array( 'physical', $product_types, true ) ||
count(
wc_get_products(
array(
'virtual' => false,
'limit' => 1,
)
)
) > 0,
'time' => __( '1 minute', 'woocommerce-admin' ),
),
array(
'id' => 'marketing',
'title' => __( 'Set up marketing tools', 'woocommerce-admin' ),
'content' => __(
'Add recommended marketing tools to reach new customers and grow your business',
'woocommerce-admin'
),
'isComplete' => $has_installed_marketing_extensions,
'isVisible' => Features::is_enabled( 'remote-free-extensions' ) && count( $marketing_extension_bundles ) > 0,
'time' => __( '1 minute', 'woocommerce-admin' ),
),
array(
'id' => 'appearance',
'title' => __( 'Personalize my store', 'woocommerce-admin' ),
'content' => __(
'Add your logo, create a homepage, and start designing your store.',
'woocommerce-admin'
),
'actionLabel' => __( "Let's go", 'woocommerce-admin' ),
'isComplete' => get_option( 'woocommerce_task_list_appearance_complete' ),
'isVisible' => true,
'time' => __( '2 minutes', 'woocommerce-admin' ),
),
),
),
);
return apply_filters( 'woocommerce_admin_onboarding_tasks', $task_lists );
public static function get_lists() {
self::maybe_add_default_tasks();
return self::$lists;
}
/**
@ -337,9 +122,9 @@ class TaskLists {
*/
public static function get_visible() {
return array_filter(
self::get_all(),
self::get_lists(),
function ( $task_list ) {
return ! $task_list['isHidden'];
return ! $task_list->is_hidden();
}
);
}
@ -353,9 +138,9 @@ class TaskLists {
* @return TaskList|null
*/
public static function get_list( $id ) {
foreach ( self::get_all() as $task_list ) {
if ( $task_list['id'] === $id ) {
return new TaskList( $task_list );
foreach ( self::get_lists() as $task_list ) {
if ( $task_list->id === $id ) {
return $task_list;
}
}
@ -378,7 +163,7 @@ class TaskLists {
}
$tasks_to_search = $task_list ? $task_list['tasks'] : array_reduce(
self::get_all(),
self::get_lists(),
function ( $all, $curr ) {
return array_merge( $all, $curr['tasks'] );
},

View File

@ -0,0 +1,28 @@
<?php
namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;
/**
* Appearance Task
*/
class Appearance {
/**
* Get the task arguments.
*
* @return array
*/
public static function get_task() {
return array(
'id' => 'appearance',
'title' => __( 'Personalize my store', 'woocommerce-admin' ),
'content' => __(
'Add your logo, create a homepage, and start designing your store.',
'woocommerce-admin'
),
'action_label' => __( "Let's go", 'woocommerce-admin' ),
'is_complete' => get_option( 'woocommerce_task_list_appearance_complete' ),
'can_view' => true,
'time' => __( '2 minutes', 'woocommerce-admin' ),
);
}
}

View File

@ -0,0 +1,69 @@
<?php
namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;
use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Admin\Features\RemoteFreeExtensions\Init as RemoteFreeExtensions;
/**
* Marketing Task
*/
class Marketing {
/**
* Get the task arguments.
*
* @return array
*/
public static function get_task() {
return array(
'id' => 'marketing',
'title' => __( 'Set up marketing tools', 'woocommerce-admin' ),
'content' => __(
'Add recommended marketing tools to reach new customers and grow your business',
'woocommerce-admin'
),
'is_complete' => self::has_installed_extensions(),
'can_view' => Features::is_enabled( 'remote-free-extensions' ) && count( self::get_bundles() ) > 0,
'time' => __( '1 minute', 'woocommerce-admin' ),
);
}
/**
* Get the marketing bundles.
*
* @return array
*/
public static function get_bundles() {
return RemoteFreeExtensions::get_extensions(
array(
'reach',
'grow',
)
);
}
/**
* Check if the store has installed marketing extensions.
*
* @return bool
*/
public static function has_installed_extensions() {
$bundles = self::get_bundles();
return array_reduce(
$bundles,
function( $has_installed, $bundle ) {
if ( $has_installed ) {
return true;
}
foreach ( $bundle['plugins'] as $plugin ) {
if ( $plugin->is_installed ) {
return true;
}
}
return false;
},
false
);
}
}

View File

@ -0,0 +1,52 @@
<?php
namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;
use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks\WooCommercePayments;
/**
* Payments Task
*/
class Payments {
/**
* Get the task arguments.
*
* @return array
*/
public static function get_task() {
return array(
'id' => 'payments',
'title' => __( 'Set up payments', 'woocommerce-admin' ),
'content' => __(
'Choose payment providers and enable payment methods at checkout.',
'woocommerce-admin'
),
'is_complete' => self::has_gateways(),
'can_view' => Features::is_enabled( 'payment-gateway-suggestions' ) &&
(
! WooCommercePayments::is_requested() ||
! WooCommercePayments::is_installed() ||
! WooCommercePayments::is_supported()
),
'time' => __( '2 minutes', 'woocommerce-admin' ),
);
}
/**
* Check if the store has any enabled gateways.
*
* @return bool
*/
public static function has_gateways() {
$gateways = WC()->payment_gateways->get_available_payment_gateways();
$enabled_gateways = array_filter(
$gateways,
function( $gateway ) {
return 'yes' === $gateway->enabled;
}
);
return ! empty( $enabled_gateways );
}
}

View File

@ -0,0 +1,45 @@
<?php
namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;
/**
* Products Task
*/
class Products {
/**
* Get the task arguments.
*
* @return array
*/
public static function get_task() {
return array(
'id' => 'products',
'title' => __( 'Add my products', 'woocommerce-admin' ),
'content' => __(
'Start by adding the first product to your store. You can add your products manually, via CSV, or import them from another service.',
'woocommerce-admin'
),
'is_complete' => self::has_products(),
'can_view' => true,
'time' => __( '1 minute per product', 'woocommerce-admin' ),
);
}
/**
* Check if the store has any published products.
*
* @return bool
*/
public static function has_products() {
$product_query = new \WC_Product_Query(
array(
'limit' => 1,
'return' => 'ids',
'status' => array( 'publish' ),
)
);
$products = $product_query->get_products();
return 0 !== count( $products );
}
}

View File

@ -0,0 +1,83 @@
<?php
namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;
use Automattic\WooCommerce\Admin\Features\Onboarding;
use Automattic\WooCommerce\Admin\PluginsHelper;
/**
* Purchase Task
*/
class Purchase {
/**
* Get the task arguments.
*
* @return array
*/
public static function get_task() {
$products = self::get_products();
return array(
'id' => 'purchase',
'title' => count( $products['remaining'] ) === 1
? sprintf(
/* translators: %1$s: list of product names comma separated, %2%s the last product name */
__(
'Add %s to my store',
'woocommerce-admin'
),
$products['remaining'][0]
)
: __(
'Add paid extensions to my store',
'woocommerce-admin'
),
'content' => count( $products['remaining'] ) === 1
? $products['purchaseable'][0]['description']
: sprintf(
/* translators: %1$s: list of product names comma separated, %2%s the last product name */
__(
'Good choice! You chose to add %1$s and %2$s to your store.',
'woocommerce-admin'
),
implode( ', ', array_slice( $products['remaining'], 0, -1 ) ) . ( count( $products['remaining'] ) > 2 ? ',' : '' ),
end( $products['remaining'] )
),
'action_label' => __( 'Purchase & install now', 'woocommerce-admin' ),
'is_complete' => count( $products['remaining'] ) === 0,
'can_view' => count( $products['purchaseable'] ) > 0,
'time' => __( '2 minutes', 'woocommerce-admin' ),
'is_dismissable' => true,
);
}
/**
* Get purchaseable and remaining products.
*
* @return array
*/
public static function get_products() {
$profiler_data = get_option( Onboarding::PROFILE_DATA_OPTION, array() );
$installed = PluginsHelper::get_installed_plugin_slugs();
$product_types = isset( $profiler_data['product_types'] ) ? $profiler_data['product_types'] : array();
$allowed = Onboarding::get_allowed_product_types();
$purchaseable = array();
$remaining = array();
foreach ( $product_types as $type ) {
if ( ! isset( $allowed[ $type ]['slug'] ) ) {
continue;
}
$purchaseable[] = $allowed[ $type ];
if ( ! in_array( $allowed[ $type ]['slug'], $installed, true ) ) {
$remaining[] = $allowed[ $type ]['label'];
}
}
return array(
'purchaseable' => $purchaseable,
'remaining' => $remaining,
);
}
}

View File

@ -0,0 +1,62 @@
<?php
namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;
use Automattic\WooCommerce\Admin\Features\Onboarding;
/**
* Shipping Task
*/
class Shipping {
/**
* Get the task arguments.
*
* @return array
*/
public static function get_task() {
return array(
'id' => 'shipping',
'title' => __( 'Set up shipping', 'woocommerce-admin' ),
'content' => __(
"Set your store location and where you'll ship to.",
'woocommerce-admin'
),
'action_url' => self::has_shipping_zones()
? admin_url( 'admin.php?page=wc-settings&tab=shipping' )
: null,
'action_label' => __( "Let's go", 'woocommerce-admin' ),
'is_complete' => self::has_shipping_zones(),
'can_view' => self::has_physical_products(),
'time' => __( '1 minute', 'woocommerce-admin' ),
);
}
/**
* Check if the store has any shipping zones.
*
* @return bool
*/
public static function has_shipping_zones() {
return count( \WC_Shipping_Zones::get_zones() ) > 0;
}
/**
* Check if the store has physical products.
*
* @return bool
*/
public static function has_physical_products() {
$profiler_data = get_option( Onboarding::PROFILE_DATA_OPTION, array() );
$product_types = isset( $profiler_data['product_types'] ) ? $profiler_data['product_types'] : array();
return in_array( 'physical', $product_types, true ) ||
count(
wc_get_products(
array(
'virtual' => false,
'limit' => 1,
)
)
) > 0;
}
}

View File

@ -17,17 +17,17 @@ class StoreDetails {
$profiler_data = get_option( Onboarding::PROFILE_DATA_OPTION, array() );
return array(
'id' => 'store_details',
'title' => __( 'Store details', 'woocommerce-admin' ),
'content' => __(
'id' => 'store_details',
'title' => __( 'Store details', 'woocommerce-admin' ),
'content' => __(
'Your store address is required to set the origin country for shipping, currencies, and payment options.',
'woocommerce-admin'
),
'actionLabel' => __( "Let's go", 'woocommerce-admin' ),
'actionUrl' => '/setup-wizard',
'isComplete' => isset( $profiler_data['completed'] ) && true === $profiler_data['completed'],
'isVisible' => true,
'time' => __( '4 minutes', 'woocommerce-admin' ),
'action_label' => __( "Let's go", 'woocommerce-admin' ),
'action_url' => '/setup-wizard',
'is_complete' => isset( $profiler_data['completed'] ) && true === $profiler_data['completed'],
'can_view' => true,
'time' => __( '4 minutes', 'woocommerce-admin' ),
);
}
}

View File

@ -0,0 +1,68 @@
<?php
namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;
use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Admin\API\Reports\Taxes\Stats\DataStore as TaxDataStore;
/**
* Tax Task
*/
class Tax {
/**
* Get the task arguments.
*
* @return array
*/
public static function get_task() {
return array(
'id' => 'tax',
'title' => __( 'Set up tax', 'woocommerce-admin' ),
'content' => self::can_use_automated_taxes()
? __(
'Good news! WooCommerce Services and Jetpack can automate your sales tax calculations for you.',
'woocommerce-admin'
)
: __(
'Set your store location and configure tax rate settings.',
'woocommerce-admin'
),
'action_label' => self::can_use_automated_taxes()
? __( 'Yes please', 'woocommerce-admin' )
: __( "Let's go", 'woocommerce-admin' ),
'is_complete' => get_option( 'wc_connect_taxes_enabled' ) ||
count( TaxDataStore::get_taxes( array() ) ) > 0 ||
false !== get_option( 'woocommerce_no_sales_tax' ),
'is_visible' => true,
'time' => __( '1 minute', 'woocommerce-admin' ),
);
}
/**
* Check if the store has any enabled gateways.
*
* @return bool
*/
public static function can_use_automated_taxes() {
if ( ! class_exists( 'WC_Taxjar' ) ) {
return false;
}
return in_array( WC()->countries->get_base_country(), self::get_automated_tax_supported_countries(), true );
}
/**
* Get an array of countries that support automated tax.
*
* @return array
*/
public static function get_automated_tax_supported_countries() {
// https://developers.taxjar.com/api/reference/#countries .
$tax_supported_countries = array_merge(
array( 'US', 'CA', 'AU' ),
WC()->countries->get_european_union_countries()
);
return $tax_supported_countries;
}
}

View File

@ -0,0 +1,96 @@
<?php
namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;
use Automattic\WooCommerce\Admin\Features\Onboarding;
use Automattic\WooCommerce\Admin\PluginsHelper;
/**
* WooCommercePayments Task
*/
class WooCommercePayments {
/**
* Get the task arguments.
*
* @return array
*/
public static function get_task() {
return array(
'id' => 'woocommerce-payments',
'title' => __( 'Get paid with WooCommerce Payments', 'woocommerce-admin' ),
'content' => __(
"You're only one step away from getting paid. Verify your business details to start managing transactions with WooCommerce Payments.",
'woocommerce-admin'
),
'action_label' => __( 'Finish setup', 'woocommerce-admin' ),
'expanded' => true,
'is_complete' => self::is_connected(),
'can_view' => self::is_requested() &&
self::is_installed() &&
self::is_supported(),
'time' => __( '2 minutes', 'woocommerce-admin' ),
);
}
/**
* Check if the plugin was requested during onboarding.
*
* @return bool
*/
public static function is_requested() {
$profiler_data = get_option( Onboarding::PROFILE_DATA_OPTION, array() );
$business_extensions = isset( $profiler_data['business_extensions'] ) ? $profiler_data['business_extensions'] : array();
return in_array( 'woocommerce-payments', $business_extensions, true );
}
/**
* Check if the plugin is installed.
*
* @return bool
*/
public static function is_installed() {
$installed_plugins = PluginsHelper::get_installed_plugin_slugs();
return in_array( 'woocommerce-payments', $installed_plugins, true );
}
/**
* Check if WooCommerce Payments is connected.
*
* @return bool
*/
public static function is_connected() {
if ( class_exists( '\WC_Payments' ) ) {
$wc_payments_gateway = \WC_Payments::get_gateway();
return method_exists( $wc_payments_gateway, 'is_connected' )
? $wc_payments_gateway->is_connected()
: false;
}
return false;
}
/**
* Check if the store is in a supported country.
*
* @return bool
*/
public static function is_supported() {
return in_array(
WC()->countries->get_base_country(),
array(
'US',
'PR',
'AU',
'CA',
'DE',
'ES',
'FR',
'GB',
'IE',
'IT',
'NZ',
),
true
);
}
}

View File

@ -43,7 +43,51 @@ class DefaultPaymentGateways {
'image' => WC()->plugin_url() . '/assets/images/stripe.png',
'plugins' => array( 'woocommerce-gateway-stripe' ),
'is_visible' => array(
self::get_rules_for_countries( OnboardingTasks::get_stripe_supported_countries() ),
// https://stripe.com/global.
self::get_rules_for_countries(
array(
'AU',
'AT',
'BE',
'BG',
'BR',
'CA',
'CY',
'CZ',
'DK',
'EE',
'FI',
'FR',
'DE',
'GR',
'HK',
'IN',
'IE',
'IT',
'JP',
'LV',
'LT',
'LU',
'MY',
'MT',
'MX',
'NL',
'NZ',
'NO',
'PL',
'PT',
'RO',
'SG',
'SK',
'SI',
'ES',
'SE',
'CH',
'GB',
'US',
'PR',
)
),
self::get_rules_for_cbd( false ),
),
'recommendation_priority' => 3,