Use abstraction to add and retrieve task data (https://github.com/woocommerce/woocommerce-admin/pull/7918)

* Add class check to added tasks

* Make Task class asbtract

* Update tasks to use abstraction

* Update task property calls to methods and add extended class

* Fix up task tests

* Reorder script enqueing to check less expensive operations first

* Fix up dismissable and snoozeable checks

* Fix up typos

* Load default task classes on init

* Handle PR feedback

* Fix extended tasks not showing

* Update is_visible to can_view in deprecated tasks

* Use TestTask class for unit tests

* Add changelog entry

* Fix up API tests

* Update ExtendedClass name to DeprecatedExtendedClass

* Fix up rebase
This commit is contained in:
Joshua T Flowers 2021-11-16 08:59:55 -05:00 committed by GitHub
parent dc03c6fbb5
commit 8ff08ea0c9
20 changed files with 1394 additions and 568 deletions

View File

@ -0,0 +1,4 @@
Significance: major
Type: Dev
Use abstraction to add and retrieve task data #7918

View File

@ -54,7 +54,7 @@ export class DeprecatedTasks {
time: task.time, time: task.time,
level: task.level ? parseInt( task.level, 10 ) : 3, level: task.level ? parseInt( task.level, 10 ) : 3,
list_id: task.type || 'extended', list_id: task.type || 'extended',
is_visible: task.visible, can_view: task.visible,
id: task.key, id: task.key,
is_snoozeable: task.allowRemindMeLater, is_snoozeable: task.allowRemindMeLater,
is_dismissable: task.isDismissable, is_dismissable: task.isDismissable,

View File

@ -10,7 +10,7 @@ namespace Automattic\WooCommerce\Admin\API;
use Automattic\WooCommerce\Admin\Features\Onboarding; use Automattic\WooCommerce\Admin\Features\Onboarding;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Init as OnboardingTasksFeature; use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Init as OnboardingTasksFeature;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\TaskLists; use Automattic\WooCommerce\Admin\Features\OnboardingTasks\TaskLists;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task; use Automattic\WooCommerce\Admin\Features\OnboardingTasks\DeprecatedExtendedTask;
defined( 'ABSPATH' ) || exit; defined( 'ABSPATH' ) || exit;
@ -694,7 +694,6 @@ class OnboardingTasks extends \WC_REST_Data_Controller {
public function get_tasks( $request ) { public function get_tasks( $request ) {
$extended_tasks = $request->get_param( 'extended_tasks' ); $extended_tasks = $request->get_param( 'extended_tasks' );
TaskLists::maybe_add_default_tasks();
TaskLists::maybe_add_extended_tasks( $extended_tasks ); TaskLists::maybe_add_extended_tasks( $extended_tasks );
$lists = TaskLists::get_lists(); $lists = TaskLists::get_lists();
@ -716,21 +715,19 @@ class OnboardingTasks extends \WC_REST_Data_Controller {
* @return WP_REST_Request|WP_Error * @return WP_REST_Request|WP_Error
*/ */
public function dismiss_task( $request ) { public function dismiss_task( $request ) {
TaskLists::maybe_add_default_tasks();
$id = $request->get_param( 'id' ); $id = $request->get_param( 'id' );
$task = TaskLists::get_task( $id ); $task = TaskLists::get_task( $id );
if ( ! $task && $id ) { if ( ! $task && $id ) {
$task = new Task( $task = new DeprecatedExtendedTask(
array( array(
'id' => $id, 'id' => $id,
'is_dismissable' => true, 'is_dismissable' => true,
'parent_id' => 'extended',
) )
); );
} }
if ( ! $task || ! $task->is_dismissable ) { if ( ! $task || ! $task->is_dismissable() ) {
return new \WP_Error( return new \WP_Error(
'woocommerce_rest_invalid_task', 'woocommerce_rest_invalid_task',
__( 'Sorry, no dismissable task with that ID was found.', 'woocommerce-admin' ), __( 'Sorry, no dismissable task with that ID was found.', 'woocommerce-admin' ),
@ -751,21 +748,19 @@ class OnboardingTasks extends \WC_REST_Data_Controller {
* @return WP_REST_Request|WP_Error * @return WP_REST_Request|WP_Error
*/ */
public function undo_dismiss_task( $request ) { public function undo_dismiss_task( $request ) {
TaskLists::maybe_add_default_tasks();
$id = $request->get_param( 'id' ); $id = $request->get_param( 'id' );
$task = TaskLists::get_task( $id ); $task = TaskLists::get_task( $id );
if ( ! $task && $id ) { if ( ! $task && $id ) {
$task = new Task( $task = new DeprecatedExtendedTask(
array( array(
'id' => $id, 'id' => $id,
'is_dismissable' => true, 'is_dismissable' => true,
'parent_id' => 'extended',
) )
); );
} }
if ( ! $task || ! $task->is_dismissable ) { if ( ! $task || ! $task->is_dismissable() ) {
return new \WP_Error( return new \WP_Error(
'woocommerce_rest_invalid_task', 'woocommerce_rest_invalid_task',
__( 'Sorry, no dismissable task with that ID was found.', 'woocommerce-admin' ), __( 'Sorry, no dismissable task with that ID was found.', 'woocommerce-admin' ),
@ -788,7 +783,6 @@ class OnboardingTasks extends \WC_REST_Data_Controller {
* @return WP_REST_Response|WP_Error * @return WP_REST_Response|WP_Error
*/ */
public function snooze_task( $request ) { public function snooze_task( $request ) {
TaskLists::maybe_add_default_tasks();
$task_id = $request->get_param( 'id' ); $task_id = $request->get_param( 'id' );
$task_list_id = $request->get_param( 'task_list_id' ); $task_list_id = $request->get_param( 'task_list_id' );
$duration = $request->get_param( 'duration' ); $duration = $request->get_param( 'duration' );
@ -796,16 +790,15 @@ class OnboardingTasks extends \WC_REST_Data_Controller {
$task = TaskLists::get_task( $task_id, $task_list_id ); $task = TaskLists::get_task( $task_id, $task_list_id );
if ( ! $task && $task_id ) { if ( ! $task && $task_id ) {
$task = new Task( $task = new DeprecatedExtendedTask(
array( array(
'id' => $task_id, 'id' => $task_id,
'is_snoozeable' => true, 'is_snoozeable' => true,
'parent_id' => 'extended',
) )
); );
} }
if ( ! $task || ! $task->is_snoozeable ) { if ( ! $task || ! $task->is_snoozeable() ) {
return new \WP_Error( return new \WP_Error(
'woocommerce_rest_invalid_task', 'woocommerce_rest_invalid_task',
__( 'Sorry, no snoozeable task with that ID was found.', 'woocommerce-admin' ), __( 'Sorry, no snoozeable task with that ID was found.', 'woocommerce-admin' ),
@ -826,21 +819,19 @@ class OnboardingTasks extends \WC_REST_Data_Controller {
* @return WP_REST_Request|WP_Error * @return WP_REST_Request|WP_Error
*/ */
public function undo_snooze_task( $request ) { public function undo_snooze_task( $request ) {
TaskLists::maybe_add_default_tasks();
$id = $request->get_param( 'id' ); $id = $request->get_param( 'id' );
$task = TaskLists::get_task( $id ); $task = TaskLists::get_task( $id );
if ( ! $task && $id ) { if ( ! $task && $id ) {
$task = new Task( $task = new DeprecatedExtendedTask(
array( array(
'id' => $id, 'id' => $id,
'is_snoozeable' => true, 'is_snoozeable' => true,
'parent_id' => 'extended',
) )
); );
} }
if ( ! $task || ! $task->is_snoozeable ) { if ( ! $task || ! $task->is_snoozeable() ) {
return new \WP_Error( return new \WP_Error(
'woocommerce_rest_invalid_task', 'woocommerce_rest_invalid_task',
__( 'Sorry, no snoozeable task with that ID was found.', 'woocommerce-admin' ), __( 'Sorry, no snoozeable task with that ID was found.', 'woocommerce-admin' ),
@ -862,7 +853,6 @@ class OnboardingTasks extends \WC_REST_Data_Controller {
* @return WP_REST_Response|WP_Error * @return WP_REST_Response|WP_Error
*/ */
public function hide_task_list( $request ) { public function hide_task_list( $request ) {
TaskLists::maybe_add_default_tasks();
$id = $request->get_param( 'id' ); $id = $request->get_param( 'id' );
$task_list = TaskLists::get_list( $id ); $task_list = TaskLists::get_list( $id );
@ -916,15 +906,13 @@ class OnboardingTasks extends \WC_REST_Data_Controller {
* @return WP_REST_Request|WP_Error * @return WP_REST_Request|WP_Error
*/ */
public function action_task( $request ) { public function action_task( $request ) {
TaskLists::maybe_add_default_tasks();
$id = $request->get_param( 'id' ); $id = $request->get_param( 'id' );
$task = TaskLists::get_task( $id ); $task = TaskLists::get_task( $id );
if ( ! $task && $id ) { if ( ! $task && $id ) {
$task = new Task( $task = new DeprecatedExtendedTask(
array( array(
'id' => $id, 'id' => $id,
'parent_id' => 'extended',
) )
); );
} }

View File

@ -0,0 +1,166 @@
<?php
/**
* A temporary class for creating tasks on the fly from deprecated tasks.
*/
namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks;
/**
* DeprecatedExtendedTask class.
*/
class DeprecatedExtendedTask extends Task {
/**
* ID.
*
* @var string
*/
public $id = '';
/**
* Snoozeable.
*
* @var boolean
*/
public $is_snoozeable = false;
/**
* Dismissable.
*
* @var boolean
*/
public $is_dismissable = false;
/**
* Constructor.
*
* @param array $args Array of task args.
*/
public function __construct( $args ) {
$task_args = wp_parse_args(
$args,
array(
'id' => null,
'is_dismissable' => false,
'is_snoozeable' => false,
'is_snoozeable' => false,
'can_view' => true,
'level' => 3,
'additional_info' => null,
'content' => '',
'title' => '',
'is_complete' => false,
'time' => null,
)
);
$this->id = $task_args['id'];
$this->additional_info = $task_args['additional_info'];
$this->content = $task_args['content'];
$this->is_complete = $task_args['is_complete'];
$this->is_dismissable = $task_args['is_dismissable'];
$this->is_snoozeable = $task_args['is_snoozeable'];
$this->can_view = $task_args['can_view'];
$this->level = $task_args['level'];
$this->time = $task_args['time'];
$this->title = $task_args['title'];
}
/**
* ID.
*
* @return string
*/
public function get_id() {
return $this->id;
}
/**
* Additonal info.
*
* @return string
*/
public function get_additional_info() {
return $this->additional_info;
}
/**
* Content.
*
* @return string
*/
public function get_content() {
return $this->content;
}
/**
* Parent ID.
*
* @return string
*/
public function get_parent_id() {
return 'extended';
}
/**
* Level.
*
* @return int
*/
public function get_level() {
return $this->level;
}
/**
* Title
*
* @return string
*/
public function get_title() {
return $this->title;
}
/**
* Time
*
* @return string|null
*/
public function get_time() {
return $this->time;
}
/**
* Check if a task is snoozeable.
*
* @return bool
*/
public function is_snoozeable() {
return $this->is_snoozeable;
}
/**
* Check if a task is dismissable.
*
* @return bool
*/
public function is_dismissable() {
return $this->is_dismissable;
}
/**
* Check if a task is dismissable.
*
* @return bool
*/
public function is_complete() {
return $this->is_complete;
}
/**
* Check if a task is dismissable.
*
* @return bool
*/
public function can_view() {
return $this->can_view;
}
}

View File

@ -8,110 +8,12 @@ namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks;
/** /**
* Task class. * Task class.
*/ */
class Task { abstract class Task {
/** /**
* Task traits. * Task traits.
*/ */
use TaskTraits; use TaskTraits;
/**
* ID.
*
* @var string
*/
public $id = '';
/**
* Parent task list ID.
*
* @var string
*/
public $parent_id = '';
/**
* Title.
*
* @var string
*/
public $title = '';
/**
* Content.
*
* @var string
*/
public $content = '';
/**
* Additional info.
*
* @var string
*/
public $additional_info = '';
/**
* Action label.
*
* @var string
*/
public $action_label = '';
/**
* Action URL.
*
* @var string|null
*/
public $action_url = null;
/**
* Task completion.
*
* @var bool
*/
public $is_complete = false;
/**
* Viewing capability.
*
* @var bool
*/
public $can_view = true;
/**
* Time string.
*
* @var string|null
*/
public $time = null;
/**
* Level of task importance.
*
* @var int|null
*/
public $level = null;
/**
* Dismissability.
*
* @var bool
*/
public $is_dismissable = false;
/**
* Snoozeability.
*
* @var bool
*/
public $is_snoozeable = false;
/**
* Snoozeability.
*
* @var string|null
*/
public $snoozed_until = null;
/** /**
* Name of the dismiss option. * Name of the dismiss option.
* *
@ -159,50 +61,92 @@ class Task {
); );
/** /**
* Constructor * ID.
* *
* @param array $data Task list data. * @return string
*/ */
public function __construct( $data = array() ) { abstract public function get_id();
$defaults = array(
'id' => null,
'parent_id' => null,
'title' => '',
'content' => '',
'action_label' => __( "Let's go", 'woocommerce-admin' ),
'action_url' => null,
'is_complete' => false,
'can_view' => true,
'level' => 3,
'time' => null,
'is_dismissable' => false,
'is_snoozeable' => false,
'snoozed_until' => null,
'additional_info' => '',
'additional_data' => (object) array(),
);
$data = wp_parse_args( $data, $defaults ); /**
* Parent ID.
*
* @return string
*/
abstract public function get_parent_id();
$this->id = (string) $data['id']; /**
$this->parent_id = (string) $data['parent_id']; * Title.
$this->title = (string) $data['title']; *
$this->content = (string) $data['content']; * @return string
$this->action_label = (string) $data['action_label']; */
$this->action_url = (string) $data['action_url']; abstract public function get_title();
$this->is_complete = (bool) $data['is_complete'];
$this->can_view = (bool) $data['can_view'];
$this->level = (int) $data['level'];
$this->additional_info = (string) $data['additional_info'];
$this->time = (string) $data['time'];
$this->is_dismissable = (bool) $data['is_dismissable'];
$this->is_snoozeable = (bool) $data['is_snoozeable'];
$this->additional_data = (object) $data['additional_data'];
$snoozed_tasks = get_option( self::SNOOZED_OPTION, array() ); /**
if ( isset( $snoozed_tasks[ $this->id ] ) ) { * Content.
$this->snoozed_until = $snoozed_tasks[ $this->id ]; *
} * @return string
*/
abstract public function get_content();
/**
* Time.
*
* @return string
*/
abstract public function get_time();
/**
* Additional info.
*
* @return string
*/
public function get_additional_info() {
return '';
}
/**
* Additional data.
*
* @return mixed
*/
public function get_additional_data() {
return null;
}
/**
* Level.
*
* @return string
*/
public function get_level() {
return 3;
}
/**
* Action label.
*
* @return string
*/
public function get_action_label() {
return __( "Let's go", 'woocommerce-admin' );
}
/**
* Action URL.
*
* @return string
*/
public function get_action_url() {
return null;
}
/**
* Check if a task is dismissable.
*
* @return bool
*/
public function is_dismissable() {
return false;
} }
/** /**
@ -211,13 +155,13 @@ class Task {
* @return bool * @return bool
*/ */
public function is_dismissed() { public function is_dismissed() {
if ( ! $this->is_dismissable ) { if ( ! $this->is_dismissable() ) {
return false; return false;
} }
$dismissed = get_option( self::DISMISSED_OPTION, array() ); $dismissed = get_option( self::DISMISSED_OPTION, array() );
return in_array( $this->id, $dismissed, true ); return in_array( $this->get_id(), $dismissed, true );
} }
/** /**
@ -226,16 +170,16 @@ class Task {
* @return bool * @return bool
*/ */
public function dismiss() { public function dismiss() {
if ( ! $this->is_dismissable ) { if ( ! $this->is_dismissable() ) {
return false; return false;
} }
$dismissed = get_option( self::DISMISSED_OPTION, array() ); $dismissed = get_option( self::DISMISSED_OPTION, array() );
$dismissed[] = $this->id; $dismissed[] = $this->get_id();
$update = update_option( self::DISMISSED_OPTION, array_unique( $dismissed ) ); $update = update_option( self::DISMISSED_OPTION, array_unique( $dismissed ) );
if ( $update ) { if ( $update ) {
$this->record_tracks_event( 'dismiss_task', array( 'task_name' => $this->id ) ); $this->record_tracks_event( 'dismiss_task', array( 'task_name' => $this->get_id() ) );
} }
return $update; return $update;
@ -248,29 +192,52 @@ class Task {
*/ */
public function undo_dismiss() { public function undo_dismiss() {
$dismissed = get_option( self::DISMISSED_OPTION, array() ); $dismissed = get_option( self::DISMISSED_OPTION, array() );
$dismissed = array_diff( $dismissed, array( $this->id ) ); $dismissed = array_diff( $dismissed, array( $this->get_id() ) );
$update = update_option( self::DISMISSED_OPTION, $dismissed ); $update = update_option( self::DISMISSED_OPTION, $dismissed );
if ( $update ) { if ( $update ) {
$this->record_tracks_event( 'undo_dismiss_task', array( 'task_name' => $this->id ) ); $this->record_tracks_event( 'undo_dismiss_task', array( 'task_name' => $this->get_id() ) );
} }
return $update; return $update;
} }
/**
* Check if a task is snoozeable.
*
* @return bool
*/
public function is_snoozeable() {
return false;
}
/**
* Get the snoozed until datetime.
*
* @return string
*/
public function get_snoozed_until() {
$snoozed_tasks = get_option( self::SNOOZED_OPTION, array() );
if ( isset( $snoozed_tasks[ $this->get_id() ] ) ) {
return $snoozed_tasks[ $this->get_id() ];
}
return null;
}
/** /**
* Bool for task snoozed. * Bool for task snoozed.
* *
* @return bool * @return bool
*/ */
public function is_snoozed() { public function is_snoozed() {
if ( ! $this->is_snoozeable ) { if ( ! $this->is_snoozeable() ) {
return false; return false;
} }
$snoozed = get_option( self::SNOOZED_OPTION, array() ); $snoozed = get_option( self::SNOOZED_OPTION, array() );
return isset( $snoozed[ $this->id ] ) && $snoozed[ $this->id ] > ( time() * 1000 ); return isset( $snoozed[ $this->get_id() ] ) && $snoozed[ $this->get_id() ] > ( time() * 1000 );
} }
/** /**
@ -280,19 +247,18 @@ class Task {
* @return bool * @return bool
*/ */
public function snooze( $duration = 'day' ) { public function snooze( $duration = 'day' ) {
if ( ! $this->is_snoozeable ) { if ( ! $this->is_snoozeable() ) {
return false; return false;
} }
$snoozed = get_option( self::SNOOZED_OPTION, array() ); $snoozed = get_option( self::SNOOZED_OPTION, array() );
$snoozed_until = $this->duration_to_ms[ $duration ] + ( time() * 1000 ); $snoozed_until = $this->duration_to_ms[ $duration ] + ( time() * 1000 );
$snoozed[ $this->id ] = $snoozed_until; $snoozed[ $this->get_id() ] = $snoozed_until;
$update = update_option( self::SNOOZED_OPTION, $snoozed ); $update = update_option( self::SNOOZED_OPTION, $snoozed );
if ( $update ) { if ( $update ) {
if ( $update ) { if ( $update ) {
$this->record_tracks_event( 'remindmelater_task', array( 'task_name' => $this->id ) ); $this->record_tracks_event( 'remindmelater_task', array( 'task_name' => $this->get_id() ) );
$this->snoozed_until = $snoozed_until;
} }
} }
@ -306,11 +272,11 @@ class Task {
*/ */
public function undo_snooze() { public function undo_snooze() {
$snoozed = get_option( self::SNOOZED_OPTION, array() ); $snoozed = get_option( self::SNOOZED_OPTION, array() );
unset( $snoozed[ $this->id ] ); unset( $snoozed[ $this->get_id() ] );
$update = update_option( self::SNOOZED_OPTION, $snoozed ); $update = update_option( self::SNOOZED_OPTION, $snoozed );
if ( $update ) { if ( $update ) {
$this->record_tracks_event( 'undo_remindmelater_task', array( 'task_name' => $this->id ) ); $this->record_tracks_event( 'undo_remindmelater_task', array( 'task_name' => $this->get_id() ) );
} }
return $update; return $update;
@ -323,18 +289,18 @@ class Task {
*/ */
public function has_previously_completed() { public function has_previously_completed() {
$complete = get_option( self::COMPLETED_OPTION, array() ); $complete = get_option( self::COMPLETED_OPTION, array() );
return in_array( $this->id, $complete, true ); return in_array( $this->get_id(), $complete, true );
} }
/** /**
* Track task completion if task is viewable. * Track task completion if task is viewable.
*/ */
public function possibly_track_completion() { public function possibly_track_completion() {
if ( ! $this->can_view ) { if ( ! $this->can_view() ) {
return; return;
} }
if ( ! $this->is_complete ) { if ( ! $this->is_complete() ) {
return; return;
} }
@ -343,9 +309,9 @@ class Task {
} }
$completed_tasks = get_option( self::COMPLETED_OPTION, array() ); $completed_tasks = get_option( self::COMPLETED_OPTION, array() );
$completed_tasks[] = $this->id; $completed_tasks[] = $this->get_id();
update_option( self::COMPLETED_OPTION, $completed_tasks ); update_option( self::COMPLETED_OPTION, $completed_tasks );
$this->record_tracks_event( 'task_completed', array( 'task_name' => $this->id ) ); $this->record_tracks_event( 'task_completed', array( 'task_name' => $this->get_id() ) );
} }
/** /**
@ -358,7 +324,7 @@ class Task {
set_transient( set_transient(
self::ACTIVE_TASK_TRANSIENT, self::ACTIVE_TASK_TRANSIENT,
$this->id, $this->get_id(),
DAY_IN_SECONDS DAY_IN_SECONDS
); );
} }
@ -367,7 +333,25 @@ class Task {
* Check if this is the active task. * Check if this is the active task.
*/ */
public function is_active() { public function is_active() {
return get_transient( self::ACTIVE_TASK_TRANSIENT ) === $this->id; return get_transient( self::ACTIVE_TASK_TRANSIENT ) === $this->get_id();
}
/**
* Check if the store is capable of viewing the task.
*
* @return bool
*/
public function can_view() {
return true;
}
/**
* Check if the task is complete.
*
* @return bool
*/
public function is_complete() {
return self::is_actioned();
} }
@ -380,37 +364,41 @@ class Task {
$this->possibly_track_completion(); $this->possibly_track_completion();
return array( return array(
'id' => $this->id, 'id' => $this->get_id(),
'parentId' => $this->parent_id, 'parentId' => $this->get_parent_id(),
'title' => $this->title, 'title' => $this->get_title(),
'canView' => $this->can_view, 'canView' => $this->can_view(),
'content' => $this->content, 'content' => $this->get_content(),
'additionalInfo' => $this->additional_info, 'additionalInfo' => $this->get_additional_info(),
'actionLabel' => $this->action_label, 'actionLabel' => $this->get_action_label(),
'actionUrl' => $this->action_url, 'actionUrl' => $this->get_action_url(),
'isComplete' => $this->is_complete, 'isComplete' => $this->is_complete(),
'time' => $this->time, 'time' => $this->get_time(),
'level' => $this->level, 'level' => $this->get_level(),
'isActioned' => $this->is_actioned(), 'isActioned' => $this->is_actioned(),
'isDismissed' => $this->is_dismissed(), 'isDismissed' => $this->is_dismissed(),
'isDismissable' => $this->is_dismissable, 'isDismissable' => $this->is_dismissable(),
'isSnoozed' => $this->is_snoozed(), 'isSnoozed' => $this->is_snoozed(),
'isSnoozeable' => $this->is_snoozeable, 'isSnoozeable' => $this->is_snoozeable(),
'snoozedUntil' => $this->snoozed_until, 'snoozedUntil' => $this->get_snoozed_until(),
'additionalData' => self::convert_object_to_camelcase( $this->additional_data ), 'additionalData' => self::convert_object_to_camelcase( $this->get_additional_data() ),
); );
} }
/** /**
* Convert object keys to camelcase. * Convert object keys to camelcase.
* *
* @param object $object Object to convert. * @param array $data Data to convert.
* @return object * @return object
*/ */
public static function convert_object_to_camelcase( $object ) { public static function convert_object_to_camelcase( $data ) {
if ( ! is_array( $data ) ) {
return $data;
}
$new_object = (object) array(); $new_object = (object) array();
foreach ( $object as $key => $value ) { foreach ( $data as $key => $value ) {
$new_key = lcfirst( implode( '', array_map( 'ucfirst', explode( '_', $key ) ) ) ); $new_key = lcfirst( implode( '', array_map( 'ucfirst', explode( '_', $key ) ) ) );
$new_object->$new_key = $value; $new_object->$new_key = $value;
} }
@ -426,11 +414,11 @@ class Task {
public function mark_actioned() { public function mark_actioned() {
$actioned = get_option( self::ACTIONED_OPTION, array() ); $actioned = get_option( self::ACTIONED_OPTION, array() );
$actioned[] = $this->id; $actioned[] = $this->get_id();
$update = update_option( self::ACTIONED_OPTION, array_unique( $actioned ) ); $update = update_option( self::ACTIONED_OPTION, array_unique( $actioned ) );
if ( $update ) { if ( $update ) {
$this->record_tracks_event( 'actioned_task', array( 'task_name' => $this->id ) ); $this->record_tracks_event( 'actioned_task', array( 'task_name' => $this->get_id() ) );
} }
return $update; return $update;
@ -442,7 +430,7 @@ class Task {
* @return bool * @return bool
*/ */
public function is_actioned() { public function is_actioned() {
return self::is_task_actioned( $this->id ); return self::is_task_actioned( $this->get_id() );
} }
/** /**

View File

@ -108,7 +108,7 @@ class TaskList {
$completed_count = array_reduce( $completed_count = array_reduce(
$viewable_tasks, $viewable_tasks,
function( $total, $task ) { function( $total, $task ) {
return $task->is_complete ? $total + 1 : $total; return $task->is_complete() ? $total + 1 : $total;
}, },
0 0
); );
@ -149,7 +149,7 @@ class TaskList {
return array_reduce( return array_reduce(
$viewable_tasks, $viewable_tasks,
function( $is_complete, $task ) { function( $is_complete, $task ) {
return ! $task->is_complete ? false : $is_complete; return ! $task->is_complete() ? false : $is_complete;
}, },
true true
); );
@ -168,14 +168,17 @@ class TaskList {
/** /**
* Add task to the task list. * Add task to the task list.
* *
* @param array $args Task properties. * @param Task $task Task class.
*/ */
public function add_task( $args ) { public function add_task( $task ) {
$task_args = wp_parse_args( if ( ! is_subclass_of( $task, 'Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task' ) ) {
$args, return new \WP_Error(
array( 'parent_id' => $this->id ) 'woocommerce_task_list_invalid_task',
); __( 'Task is not a subclass of `Task`', 'woocommerce-admin' )
$this->tasks[] = new Task( $task_args ); );
}
$this->tasks[] = $task;
} }
/** /**
@ -188,7 +191,7 @@ class TaskList {
array_filter( array_filter(
$this->tasks, $this->tasks,
function( $task ) { function( $task ) {
return $task->can_view; return $task->can_view();
} }
) )
); );
@ -238,7 +241,6 @@ class TaskList {
*/ */
public function get_json() { public function get_json() {
$this->possibly_track_completion(); $this->possibly_track_completion();
return array( return array(
'id' => $this->id, 'id' => $this->id,
'title' => $this->title, 'title' => $this->title,

View File

@ -5,6 +5,7 @@
namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks; namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\DeprecatedExtendedTask;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task; use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
use Automattic\WooCommerce\Admin\Loader; use Automattic\WooCommerce\Admin\Loader;
@ -65,6 +66,7 @@ class TaskLists {
*/ */
public static function init() { public static function init() {
self::init_default_lists(); self::init_default_lists();
self::maybe_add_default_tasks();
add_action( 'admin_init', array( __CLASS__, 'set_active_task' ), 5 ); add_action( 'admin_init', array( __CLASS__, 'set_active_task' ), 5 );
add_action( 'init', array( __CLASS__, 'init_tasks' ) ); add_action( 'init', array( __CLASS__, 'init_tasks' ) );
} }
@ -176,9 +178,10 @@ class TaskLists {
self::$default_tasks_loaded = true; self::$default_tasks_loaded = true;
foreach ( self::DEFAULT_TASKS as $task ) { foreach ( self::DEFAULT_TASKS as $task_name ) {
$class = 'Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks\\' . $task; $class = 'Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks\\' . $task_name;
self::add_task( 'setup', $class::get_task() ); $task = new $class();
self::add_task( $task->get_parent_id(), $task );
} }
} }
@ -190,8 +193,9 @@ class TaskLists {
public static function maybe_add_extended_tasks( $extended_tasks ) { public static function maybe_add_extended_tasks( $extended_tasks ) {
$tasks = $extended_tasks ? $extended_tasks : array(); $tasks = $extended_tasks ? $extended_tasks : array();
foreach ( $tasks as $extended_task ) { foreach ( $tasks as $args ) {
self::add_task( $extended_task['list_id'], $extended_task ); $task = new DeprecatedExtendedTask( $args );
self::add_task( $task->get_parent_id(), $task );
} }
} }
@ -266,7 +270,7 @@ class TaskLists {
); );
foreach ( $tasks_to_search as $task ) { foreach ( $tasks_to_search as $task ) {
if ( $id === $task->id ) { if ( $id === $task->get_id() ) {
return $task; return $task;
} }
} }

View File

@ -9,48 +9,82 @@ use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks\Products;
/** /**
* Appearance Task * Appearance Task
*/ */
class Appearance { class Appearance extends Task {
/** /**
* Initialize. * Initialize.
*/ */
public static function init() { public function __construct() {
add_action( 'admin_enqueue_scripts', array( __CLASS__, 'add_media_scripts' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'add_media_scripts' ) );
add_action( 'admin_enqueue_scripts', array( __CLASS__, 'possibly_add_return_notice_script' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'possibly_add_return_notice_script' ) );
} }
/** /**
* Get the task arguments. * ID.
*
* @return string
*/
public function get_id() {
return 'appearance';
}
/**
* Parent ID.
*
* @return string
*/
public function get_parent_id() {
return 'setup';
}
/**
* Title.
*
* @return string
*/
public function get_title() {
return __( 'Personalize my store', 'woocommerce-admin' );
}
/**
* Content.
*
* @return string
*/
public function get_content() {
return __(
'Add your logo, create a homepage, and start designing your store.',
'woocommerce-admin'
);
}
/**
* Time.
*
* @return string
*/
public function get_time() {
return __( '2 minutes', 'woocommerce-admin' );
}
/**
* Addtional data.
* *
* @return array * @return array
*/ */
public static function get_task() { public function get_additional_data() {
return array( return array(
'id' => 'appearance', 'has_homepage' => self::has_homepage(),
'title' => __( 'Personalize my store', 'woocommerce-admin' ), 'has_products' => Products::has_products(),
'content' => __( 'stylesheet' => get_option( 'stylesheet' ),
'Add your logo, create a homepage, and start designing your store.', 'theme_mods' => get_theme_mods(),
'woocommerce-admin'
),
'action_label' => __( "Let's go", 'woocommerce-admin' ),
'is_complete' => Task::is_task_actioned( 'appearance' ),
'can_view' => true,
'time' => __( '2 minutes', 'woocommerce-admin' ),
'additional_data' => array(
'has_homepage' => self::has_homepage(),
'has_products' => Products::has_products(),
'stylesheet' => get_option( 'stylesheet' ),
'theme_mods' => get_theme_mods(),
),
); );
} }
/** /**
* Add media scripts for image uploader. * Add media scripts for image uploader.
*/ */
public static function add_media_scripts() { public function add_media_scripts() {
$task = new Task( self::get_task() ); if ( ! Loader::is_admin_page() || ! $this->can_view() ) {
if ( ! $task->can_view ) {
return; return;
} }
@ -63,15 +97,14 @@ class Appearance {
* *
* @param string $hook Page hook. * @param string $hook Page hook.
*/ */
public static function possibly_add_return_notice_script( $hook ) { public function possibly_add_return_notice_script( $hook ) {
global $post; global $post;
$task = new Task( self::get_task() );
if ( $task->is_complete || ! $task->is_active() ) { if ( 'post.php' !== $hook || 'page' !== $post->post_type ) {
return; return;
} }
if ( 'post.php' !== $hook || 'page' !== $post->post_type ) { if ( $this->is_complete() || ! $this->is_active() ) {
return; return;
} }

View File

@ -9,26 +9,73 @@ use Automattic\WooCommerce\Admin\Features\RemoteFreeExtensions\Init as RemoteFre
/** /**
* Marketing Task * Marketing Task
*/ */
class Marketing { class Marketing extends Task {
/** /**
* Get the task arguments. * ID.
* *
* @return array * @return string
*/ */
public static function get_task() { public function get_id() {
return array( return 'marketing';
'id' => 'marketing', }
'title' => __( 'Set up marketing tools', 'woocommerce-admin' ),
'content' => __( /**
'Add recommended marketing tools to reach new customers and grow your business', * Parent ID.
'woocommerce-admin' *
), * @return string
'is_complete' => self::has_installed_extensions(), */
'can_view' => Features::is_enabled( 'remote-free-extensions' ) && count( self::get_plugins() ) > 0, public function get_parent_id() {
'time' => __( '1 minute', 'woocommerce-admin' ), return 'setup';
}
/**
* Title.
*
* @return string
*/
public function get_title() {
return __( 'Set up marketing tools', 'woocommerce-admin' );
}
/**
* Content.
*
* @return string
*/
public function get_content() {
return __(
'Add recommended marketing tools to reach new customers and grow your business',
'woocommerce-admin'
); );
} }
/**
* Time.
*
* @return string
*/
public function get_time() {
return __( '1 minute', 'woocommerce-admin' );
}
/**
* Task completion.
*
* @return bool
*/
public function is_complete() {
return self::has_installed_extensions();
}
/**
* Task visibility.
*
* @return bool
*/
public function can_view() {
return Features::is_enabled( 'remote-free-extensions' ) && count( self::get_plugins() ) > 0;
}
/** /**
* Get the marketing plugins. * Get the marketing plugins.
* *

View File

@ -4,33 +4,81 @@ namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;
use Automattic\WooCommerce\Admin\Features\Features; use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks\WooCommercePayments; use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks\WooCommercePayments;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
/** /**
* Payments Task * Payments Task
*/ */
class Payments { class Payments extends Task {
/** /**
* Get the task arguments. * ID.
* *
* @return array * @return string
*/ */
public static function get_task() { public function get_id() {
return array( return 'payments';
'id' => 'payments', }
'title' => __( 'Set up payments', 'woocommerce-admin' ),
'content' => __( /**
'Choose payment providers and enable payment methods at checkout.', * Parent ID.
'woocommerce-admin' *
), * @return string
'is_complete' => self::has_gateways(), */
'can_view' => Features::is_enabled( 'payment-gateway-suggestions' ) && public function get_parent_id() {
( return 'setup';
! WooCommercePayments::is_requested() || }
! WooCommercePayments::is_installed() ||
! WooCommercePayments::is_supported() || /**
WooCommercePayments::is_connected() * Title.
), *
'time' => __( '2 minutes', 'woocommerce-admin' ), * @return string
*/
public function get_title() {
return __( 'Set up payments', 'woocommerce-admin' );
}
/**
* Content.
*
* @return string
*/
public function get_content() {
return __(
'Choose payment providers and enable payment methods at checkout.',
'woocommerce-admin'
);
}
/**
* Time.
*
* @return string
*/
public function get_time() {
return __( '2 minutes', 'woocommerce-admin' );
}
/**
* Task completion.
*
* @return bool
*/
public function is_complete() {
return self::has_gateways();
}
/**
* Task visibility.
*
* @return bool
*/
public function can_view() {
return Features::is_enabled( 'payment-gateway-suggestions' ) &&
(
! WooCommercePayments::is_requested() ||
! WooCommercePayments::is_installed() ||
! WooCommercePayments::is_supported() ||
WooCommercePayments::is_connected()
); );
} }

View File

@ -8,29 +8,96 @@ use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
/** /**
* Products Task * Products Task
*/ */
class Products { class Products extends Task {
/** /**
* Initialize. * Initialize.
*/ */
public static function init() { public function __construct() {
add_action( 'admin_enqueue_scripts', array( __CLASS__, 'possibly_add_manual_return_notice_script' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'possibly_add_manual_return_notice_script' ) );
add_action( 'admin_enqueue_scripts', array( __CLASS__, 'possibly_add_import_return_notice_script' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'possibly_add_import_return_notice_script' ) );
} }
/**
* ID.
*
* @return string
*/
public function get_id() {
return 'products';
}
/**
* Parent ID.
*
* @return string
*/
public function get_parent_id() {
return 'setup';
}
/**
* Title.
*
* @return string
*/
public function get_title() {
return __( 'Add my products', 'woocommerce-admin' );
}
/**
* Content.
*
* @return string
*/
public function get_content() {
return __(
'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'
);
}
/**
* Time.
*
* @return string
*/
public function get_time() {
return __( '1 minute per product', 'woocommerce-admin' );
}
/**
* Task completion.
*
* @return bool
*/
public function is_complete() {
return self::has_products();
}
/**
* Addtional data.
*
* @return array
*/
public function get_additional_data() {
return array(
'has_products' => self::has_products(),
);
}
/** /**
* Adds a return to task list notice when completing the manual product task. * Adds a return to task list notice when completing the manual product task.
* *
* @param string $hook Page hook. * @param string $hook Page hook.
*/ */
public static function possibly_add_manual_return_notice_script( $hook ) { public function possibly_add_manual_return_notice_script( $hook ) {
$task = new Task( self::get_task() ); global $post;
if ( 'post.php' !== $hook || 'product' !== $post->post_type ) {
if ( $task->is_complete || ! $task->is_active() ) {
return; return;
} }
global $post; if ( ! $this->is_active() || $this->is_complete() ) {
if ( 'post.php' !== $hook || 'product' !== $post->post_type ) {
return; return;
} }
@ -51,15 +118,14 @@ class Products {
* *
* @param string $hook Page hook. * @param string $hook Page hook.
*/ */
public static function possibly_add_import_return_notice_script( $hook ) { public function possibly_add_import_return_notice_script( $hook ) {
$task = new Task( self::get_task() );
$step = isset( $_GET['step'] ) ? $_GET['step'] : ''; // phpcs:ignore csrf ok, sanitization ok. $step = isset( $_GET['step'] ) ? $_GET['step'] : ''; // phpcs:ignore csrf ok, sanitization ok.
if ( $task->is_complete || ! $task->is_active() ) { if ( 'product_page_product_importer' !== $hook || 'done' !== $step ) {
return; return;
} }
if ( 'product_page_product_importer' !== $hook || 'done' !== $step ) { if ( ! $this->is_active() || $this->is_complete() ) {
return; return;
} }
@ -75,28 +141,6 @@ 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' ),
'additional_data' => array(
'has_products' => self::has_products(),
),
);
}
/** /**
* Check if the store has any published products. * Check if the store has any published products.
* *

View File

@ -3,18 +3,18 @@
namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks; namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;
use Automattic\WooCommerce\Admin\Features\Onboarding; use Automattic\WooCommerce\Admin\Features\Onboarding;
use Automattic\WooCommerce\Admin\PluginsHelper;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task; use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
use Automattic\WooCommerce\Admin\PluginsHelper;
/** /**
* Purchase Task * Purchase Task
*/ */
class Purchase { class Purchase extends Task {
/** /**
* Initialize. * Initialize.
*/ */
public static function init() { public function __construct() {
add_action( 'update_option_woocommerce_onboarding_profile', array( __CLASS__, 'clear_dismissal' ), 10, 2 ); add_action( 'update_option_woocommerce_onboarding_profile', array( $this, 'clear_dismissal' ), 10, 2 );
} }
/** /**
@ -23,7 +23,7 @@ class Purchase {
* @param array $old_value Old value. * @param array $old_value Old value.
* @param array $new_value New value. * @param array $new_value New value.
*/ */
public static function clear_dismissal( $old_value, $new_value ) { public function clear_dismissal( $old_value, $new_value ) {
$product_types = isset( $new_value['product_types'] ) ? (array) $new_value['product_types'] : array(); $product_types = isset( $new_value['product_types'] ) ? (array) $new_value['product_types'] : array();
$previous_product_types = isset( $old_value['product_types'] ) ? (array) $old_value['product_types'] : array(); $previous_product_types = isset( $old_value['product_types'] ) ? (array) $old_value['product_types'] : array();
@ -31,50 +31,118 @@ class Purchase {
return; return;
} }
$task = new Task( self::get_task() ); $this->undo_dismiss();
$task->undo_dismiss();
} }
/** /**
* Get the task arguments. * Get the task arguments.
* ID.
* *
* @return array * @return string
*/ */
public static function get_task() { public function get_id() {
return 'purchase';
}
/**
* Parent ID.
*
* @return string
*/
public function get_parent_id() {
return 'setup';
}
/**
* Title.
*
* @return string
*/
public function get_title() {
$products = self::get_products(); $products = self::get_products();
return array( return count( $products['remaining'] ) === 1
'id' => 'purchase', ? sprintf(
'title' => count( $products['remaining'] ) === 1 /* translators: %1$s: list of product names comma separated, %2%s the last product name */
? sprintf( __(
/* translators: %1$s: list of product names comma separated, %2%s the last product name */ 'Add %s to my store',
__(
'Add %s to my store',
'woocommerce-admin'
),
$products['remaining'][0]
)
: __(
'Add paid extensions to my store',
'woocommerce-admin' 'woocommerce-admin'
), ),
'content' => count( $products['remaining'] ) === 1 $products['remaining'][0]
? $products['purchaseable'][0]['description'] )
: sprintf( : __(
/* translators: %1$s: list of product names comma separated, %2%s the last product name */ 'Add paid extensions to my store',
__( 'woocommerce-admin'
'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'] ) * Content.
*
* @return string
*/
public function get_content() {
$products = self::get_products();
return 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'
), ),
'action_label' => __( 'Purchase & install now', 'woocommerce-admin' ), implode( ', ', array_slice( $products['remaining'], 0, -1 ) ) . ( count( $products['remaining'] ) > 2 ? ',' : '' ),
'is_complete' => count( $products['remaining'] ) === 0, end( $products['remaining'] )
'can_view' => count( $products['purchaseable'] ) > 0, );
'time' => __( '2 minutes', 'woocommerce-admin' ), }
'is_dismissable' => true,
); /**
* Action label.
*
* @return string
*/
public function get_action_label() {
return __( 'Purchase & install now', 'woocommerce-admin' );
}
/**
* Time.
*
* @return string
*/
public function get_time() {
return __( '2 minutes', 'woocommerce-admin' );
}
/**
* Task completion.
*
* @return bool
*/
public function is_complete() {
$products = self::get_products();
return count( $products['remaining'] ) === 0;
}
/**
* Dismissable.
*
* @return bool
*/
public function is_dismissable() {
return true;
}
/**
* Task visibility.
*
* @return bool
*/
public function can_view() {
$products = self::get_products();
return count( $products['purchaseable'] ) > 0;
} }
/** /**

View File

@ -3,34 +3,89 @@
namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks; namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;
use Automattic\WooCommerce\Admin\Features\Onboarding; use Automattic\WooCommerce\Admin\Features\Onboarding;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
/** /**
* Shipping Task * Shipping Task
*/ */
class Shipping { class Shipping extends Task {
/** /**
* Get the task arguments. * ID.
* *
* @return array * @return string
*/ */
public static function get_task() { public function get_id() {
return array( return 'shipping';
'id' => 'shipping', }
'title' => __( 'Set up shipping', 'woocommerce-admin' ),
'content' => __( /**
"Set your store location and where you'll ship to.", * Parent ID.
'woocommerce-admin' *
), * @return string
'action_url' => self::has_shipping_zones() */
? admin_url( 'admin.php?page=wc-settings&tab=shipping' ) public function get_parent_id() {
: null, return 'setup';
'action_label' => __( "Let's go", 'woocommerce-admin' ), }
'is_complete' => self::has_shipping_zones(),
'can_view' => self::has_physical_products(), /**
'time' => __( '1 minute', 'woocommerce-admin' ), * Title.
*
* @return string
*/
public function get_title() {
return __( 'Set up shipping', 'woocommerce-admin' );
}
/**
* Content.
*
* @return string
*/
public function get_content() {
return __(
"Set your store location and where you'll ship to.",
'woocommerce-admin'
); );
} }
/**
* Time.
*
* @return string
*/
public function get_time() {
return __( '1 minute', 'woocommerce-admin' );
}
/**
* Task completion.
*
* @return bool
*/
public function is_complete() {
return self::has_shipping_zones();
}
/**
* Task visibility.
*
* @return bool
*/
public function can_view() {
return self::has_physical_products();
}
/**
* Action URL.
*
* @return string
*/
public function get_action_url() {
return self::has_shipping_zones()
? admin_url( 'admin.php?page=wc-settings&tab=shipping' )
: null;
}
/** /**
* Check if the store has any shipping zones. * Check if the store has any shipping zones.
* *

View File

@ -3,31 +3,76 @@
namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks; namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;
use Automattic\WooCommerce\Admin\Features\Onboarding; use Automattic\WooCommerce\Admin\Features\Onboarding;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
/** /**
* Store Details Task * Store Details Task
*/ */
class StoreDetails { class StoreDetails extends Task {
/** /**
* Get the task arguments. * ID.
* *
* @return array * @return string
*/ */
public static function get_task() { public function get_id() {
$profiler_data = get_option( Onboarding::PROFILE_DATA_OPTION, array() ); return 'store_details';
}
return array( /**
'id' => 'store_details', * Parent ID.
'title' => __( 'Store details', 'woocommerce-admin' ), *
'content' => __( * @return string
'Your store address is required to set the origin country for shipping, currencies, and payment options.', */
'woocommerce-admin' public function get_parent_id() {
), return 'setup';
'action_label' => __( "Let's go", 'woocommerce-admin' ), }
'action_url' => '/setup-wizard',
'is_complete' => isset( $profiler_data['completed'] ) && true === $profiler_data['completed'], /**
'can_view' => true, * Title.
'time' => __( '4 minutes', 'woocommerce-admin' ), *
* @return string
*/
public function get_title() {
return __( 'Store details', 'woocommerce-admin' );
}
/**
* Content.
*
* @return string
*/
public function get_content() {
return __(
'Your store address is required to set the origin country for shipping, currencies, and payment options.',
'woocommerce-admin'
); );
} }
/**
* Time.
*
* @return string
*/
public function get_time() {
return __( '4 minutes', 'woocommerce-admin' );
}
/**
* Time.
*
* @return string
*/
public function get_action_url() {
return '/setup-wizard';
}
/**
* Task completion.
*
* @return bool
*/
public function is_complete() {
$profiler_data = get_option( Onboarding::PROFILE_DATA_OPTION, array() );
return isset( $profiler_data['completed'] ) && true === $profiler_data['completed'];
}
} }

View File

@ -11,27 +11,26 @@ use Automattic\WooCommerce\Admin\PluginsHelper;
/** /**
* Tax Task * Tax Task
*/ */
class Tax { class Tax extends Task {
/** /**
* Initialize. * Initialize.
*/ */
public static function init() { public function __construct() {
add_action( 'admin_enqueue_scripts', array( __CLASS__, 'possibly_add_return_notice_script' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'possibly_add_return_notice_script' ) );
} }
/** /**
* Adds a return to task list notice when completing the task. * Adds a return to task list notice when completing the task.
*/ */
public static function possibly_add_return_notice_script() { public function possibly_add_return_notice_script() {
$task = new Task( self::get_task() );
$page = isset( $_GET['page'] ) ? $_GET['page'] : ''; // phpcs:ignore csrf ok, sanitization ok. $page = isset( $_GET['page'] ) ? $_GET['page'] : ''; // phpcs:ignore csrf ok, sanitization ok.
$tab = isset( $_GET['tab'] ) ? $_GET['tab'] : ''; // phpcs:ignore csrf ok, sanitization ok. $tab = isset( $_GET['tab'] ) ? $_GET['tab'] : ''; // phpcs:ignore csrf ok, sanitization ok.
if ( $task->is_complete || ! $task->is_active() ) { if ( 'wc-settings' !== $page || 'tax' !== $tab ) {
return; return;
} }
if ( 'wc-settings' !== $page || 'tax' !== $tab ) { if ( ! $this->is_active() || $this->is_complete() ) {
return; return;
} }
@ -48,37 +47,90 @@ class Tax {
} }
/** /**
* Get the task arguments. * ID.
*
* @return string
*/
public function get_id() {
return 'tax';
}
/**
* Parent ID.
*
* @return string
*/
public function get_parent_id() {
return 'setup';
}
/**
* Title.
*
* @return string
*/
public function get_title() {
return __( 'Set up tax', 'woocommerce-admin' );
}
/**
* Content.
*
* @return string
*/
public function get_content() {
return 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'
);
}
/**
* Time.
*
* @return string
*/
public function get_time() {
return __( '1 minute', 'woocommerce-admin' );
}
/**
* Action label.
*
* @return string
*/
public function get_action_label() {
return self::can_use_automated_taxes()
? __( 'Yes please', 'woocommerce-admin' )
: __( "Let's go", 'woocommerce-admin' );
}
/**
* Task completion.
*
* @return bool
*/
public function is_complete() {
return get_option( 'wc_connect_taxes_enabled' ) ||
count( TaxDataStore::get_taxes( array() ) ) > 0 ||
false !== get_option( 'woocommerce_no_sales_tax' );
}
/**
* Addtional data.
* *
* @return array * @return array
*/ */
public static function get_task() { public function get_additional_data() {
return array( return array(
'id' => 'tax', 'avalara_activated' => PluginsHelper::is_plugin_active( 'woocommerce-avatax' ),
'title' => __( 'Set up tax', 'woocommerce-admin' ), 'tax_jar_activated' => class_exists( 'WC_Taxjar' ),
'content' => self::can_use_automated_taxes() 'woocommerce_tax_countries' => self::get_automated_support_countries(),
? __(
'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' ) ||
PluginsHelper::is_plugin_active( 'woocommerce-avatax' ),
'is_visible' => true,
'time' => __( '1 minute', 'woocommerce-admin' ),
'additional_data' => array(
'avalara_activated' => PluginsHelper::is_plugin_active( 'woocommerce-avatax' ),
'tax_jar_activated' => class_exists( 'WC_Taxjar' ),
'woocommerce_tax_countries' => self::get_automated_support_countries(),
),
); );
} }

View File

@ -3,40 +3,103 @@
namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks; namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;
use Automattic\WooCommerce\Admin\Features\Onboarding; use Automattic\WooCommerce\Admin\Features\Onboarding;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
use Automattic\WooCommerce\Admin\PluginsHelper; use Automattic\WooCommerce\Admin\PluginsHelper;
/** /**
* WooCommercePayments Task * WooCommercePayments Task
*/ */
class WooCommercePayments { class WooCommercePayments extends Task {
/** /**
* Get the task arguments. * ID.
* *
* @return array * @return string
*/ */
public static function get_task() { public function get_id() {
return array( return 'woocommerce-payments';
'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.", * Parent ID.
'woocommerce-admin' *
), * @return string
'action_label' => __( 'Finish setup', 'woocommerce-admin' ), */
'expanded' => true, public function get_parent_id() {
'is_complete' => self::is_connected(), return 'setup';
'can_view' => self::is_requested() && }
self::is_installed() &&
self::is_supported() && /**
! self::is_connected(), * Title.
'time' => __( '2 minutes', 'woocommerce-admin' ), *
'additional_info' => __( * @return string
'By setting up, you are agreeing to the <a href="https://wordpress.com/tos/" target="_blank">Terms of Service</a>', */
'woocommerce-admin' public function get_title() {
), return __( 'Get paid with WooCommerce Payments', 'woocommerce-admin' );
}
/**
* Content.
*
* @return string
*/
public function get_content() {
return __(
"You're only one step away from getting paid. Verify your business details to start managing transactions with WooCommerce Payments.",
'woocommerce-admin'
); );
} }
/**
* Time.
*
* @return string
*/
public function get_time() {
return __( '2 minutes', 'woocommerce-admin' );
}
/**
* Action label.
*
* @return string
*/
public function get_action_label() {
return __( 'Finish setup', 'woocommerce-admin' );
}
/**
* Additional info.
*
* @return string
*/
public function get_additional_info() {
return __(
'By setting up, you are agreeing to the <a href="https://wordpress.com/tos/" target="_blank">Terms of Service</a>',
'woocommerce-admin'
);
}
/**
* Task completion.
*
* @return bool
*/
public function is_complete() {
return self::is_connected();
}
/**
* Task visibility.
*
* @return bool
*/
public function can_view() {
return self::is_requested() &&
self::is_installed() &&
self::is_supported() &&
! self::is_connected();
}
/** /**
* Check if the plugin was requested during onboarding. * Check if the plugin was requested during onboarding.
* *

View File

@ -9,6 +9,8 @@ use \Automattic\WooCommerce\Admin\API\OnboardingTasks;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\TaskLists; use Automattic\WooCommerce\Admin\Features\OnboardingTasks\TaskLists;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task; use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
require_once __DIR__ . '/../features/onboarding-tasks/test-task.php';
/** /**
* WC Tests API Onboarding Tasks * WC Tests API Onboarding Tasks
*/ */
@ -190,10 +192,12 @@ class WC_Tests_API_Onboarding_Tasks extends WC_REST_Unit_Test_Case {
TaskLists::add_task( TaskLists::add_task(
'test-list', 'test-list',
array( new TestTask(
'id' => 'test-task', array(
'title' => 'Test Task', 'id' => 'test-task',
'is_snoozeable' => true, 'title' => 'Test Task',
'is_snoozeable' => true,
)
) )
); );
@ -207,7 +211,7 @@ class WC_Tests_API_Onboarding_Tasks extends WC_REST_Unit_Test_Case {
$this->assertEquals( $data['isSnoozed'], true ); $this->assertEquals( $data['isSnoozed'], true );
$this->assertEquals( isset( $data['snoozedUntil'] ), true ); $this->assertEquals( isset( $data['snoozedUntil'] ), true );
$this->assertEquals( $task->is_snoozed(), true ); $this->assertEquals( $task->is_snoozed(), true );
$this->assertEquals( isset( $task->snoozed_until ), true ); $this->assertNotNull( $task->get_snoozed_until() );
} }
@ -226,10 +230,12 @@ class WC_Tests_API_Onboarding_Tasks extends WC_REST_Unit_Test_Case {
TaskLists::add_task( TaskLists::add_task(
'test-list', 'test-list',
array( new TestTask(
'id' => 'test-task', array(
'title' => 'Test Task', 'id' => 'test-task',
'is_snoozeable' => true, 'title' => 'Test Task',
'is_snoozeable' => true,
)
) )
); );
@ -244,8 +250,7 @@ class WC_Tests_API_Onboarding_Tasks extends WC_REST_Unit_Test_Case {
$this->assertEquals( $data['isSnoozed'], true ); $this->assertEquals( $data['isSnoozed'], true );
$this->assertEquals( isset( $data['snoozedUntil'] ), true ); $this->assertEquals( isset( $data['snoozedUntil'] ), true );
$this->assertEquals( $task->is_snoozed(), true ); $this->assertEquals( $task->is_snoozed(), true );
$this->assertEquals( isset( $task->snoozed_until ), true ); $this->assertNotNull( $task->get_snoozed_until() );
} }
/** /**
@ -263,10 +268,12 @@ class WC_Tests_API_Onboarding_Tasks extends WC_REST_Unit_Test_Case {
TaskLists::add_task( TaskLists::add_task(
'test-list', 'test-list',
array( new TestTask(
'id' => 'test-task', array(
'title' => 'Test Task', 'id' => 'test-task',
'is_snoozeable' => true, 'title' => 'Test Task',
'is_snoozeable' => true,
)
) )
); );
@ -299,10 +306,12 @@ class WC_Tests_API_Onboarding_Tasks extends WC_REST_Unit_Test_Case {
TaskLists::add_task( TaskLists::add_task(
'test-list', 'test-list',
array( new TestTask(
'id' => 'test-task', array(
'title' => 'Test Task', 'id' => 'test-task',
'is_snoozeable' => true, 'title' => 'Test Task',
'is_snoozeable' => true,
)
) )
); );
@ -355,10 +364,12 @@ class WC_Tests_API_Onboarding_Tasks extends WC_REST_Unit_Test_Case {
TaskLists::add_task( TaskLists::add_task(
'test-list', 'test-list',
array( new TestTask(
'id' => 'test-task', array(
'title' => 'Test Task', 'id' => 'test-task',
'is_dismissable' => true, 'title' => 'Test Task',
'is_dismissable' => true,
)
) )
); );
@ -388,10 +399,12 @@ class WC_Tests_API_Onboarding_Tasks extends WC_REST_Unit_Test_Case {
TaskLists::add_task( TaskLists::add_task(
'test-list', 'test-list',
array( new TestTask(
'id' => 'test-task', array(
'title' => 'Test Task', 'id' => 'test-task',
'is_dismissable' => true, 'title' => 'Test Task',
'is_dismissable' => true,
)
) )
); );
@ -443,10 +456,12 @@ class WC_Tests_API_Onboarding_Tasks extends WC_REST_Unit_Test_Case {
TaskLists::add_task( TaskLists::add_task(
'test-list', 'test-list',
array( new TestTask(
'id' => 'test-task', array(
'title' => 'Test Task', 'id' => 'test-task',
'is_dismissable' => true, 'title' => 'Test Task',
'is_dismissable' => true,
)
) )
); );
@ -493,10 +508,12 @@ class WC_Tests_API_Onboarding_Tasks extends WC_REST_Unit_Test_Case {
TaskLists::add_task( TaskLists::add_task(
'test-list', 'test-list',
array( new TestTask(
'id' => 'test-task', array(
'title' => 'Test Task', 'id' => 'test-task',
'is_dismissable' => true, 'title' => 'Test Task',
'is_dismissable' => true,
)
) )
); );

View File

@ -7,6 +7,8 @@
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\TaskList; use Automattic\WooCommerce\Admin\Features\OnboardingTasks\TaskList;
require_once __DIR__ . '/test-task.php';
/** /**
* class WC_Tests_OnboardingTasks_TaskList * class WC_Tests_OnboardingTasks_TaskList
*/ */
@ -86,7 +88,11 @@ class WC_Tests_OnboardingTasks_TaskList extends WC_Unit_Test_Case {
* Tests adding a task. * Tests adding a task.
*/ */
public function test_add_task() { public function test_add_task() {
$this->list->add_task( array( 'id' => 'my-task' ) ); $this->list->add_task(
new TestTask(
array( 'id' => 'my-task' )
)
);
$this->assertEquals( 'my-task', $this->list->tasks[0]->id ); $this->assertEquals( 'my-task', $this->list->tasks[0]->id );
} }
@ -95,15 +101,19 @@ class WC_Tests_OnboardingTasks_TaskList extends WC_Unit_Test_Case {
*/ */
public function test_get_viewable_tasks() { public function test_get_viewable_tasks() {
$this->list->add_task( $this->list->add_task(
array( new TestTask(
'id' => 'viewable-task', array(
'can_view' => true, 'id' => 'viewable-task',
'can_view' => true,
)
) )
); );
$this->list->add_task( $this->list->add_task(
array( new TestTask(
'id' => 'not-viewable-task', array(
'can_view' => false, 'id' => 'not-viewable-task',
'can_view' => false,
)
) )
); );
$viewable_tasks = $this->list->get_viewable_tasks(); $viewable_tasks = $this->list->get_viewable_tasks();
@ -117,15 +127,19 @@ class WC_Tests_OnboardingTasks_TaskList extends WC_Unit_Test_Case {
*/ */
public function test_incomplete() { public function test_incomplete() {
$this->list->add_task( $this->list->add_task(
array( new TestTask(
'id' => 'complete-task', array(
'is_complete' => true, 'id' => 'complete-task',
'is_complete' => true,
)
) )
); );
$this->list->add_task( $this->list->add_task(
array( new TestTask(
'id' => 'incomplete-task', array(
'is_complete' => false, 'id' => 'incomplete-task',
'is_complete' => false,
)
) )
); );
$this->assertFalse( $this->list->is_complete() ); $this->assertFalse( $this->list->is_complete() );
@ -136,15 +150,19 @@ class WC_Tests_OnboardingTasks_TaskList extends WC_Unit_Test_Case {
*/ */
public function test_complete() { public function test_complete() {
$this->list->add_task( $this->list->add_task(
array( new TestTask(
'id' => 'complete-task1', array(
'is_complete' => true, 'id' => 'complete-task1',
'is_complete' => true,
)
) )
); );
$this->list->add_task( $this->list->add_task(
array( new TestTask(
'id' => 'complete-task-2', array(
'is_complete' => true, 'id' => 'complete-task-2',
'is_complete' => true,
)
) )
); );
$this->assertTrue( $this->list->is_complete() ); $this->assertTrue( $this->list->is_complete() );
@ -155,15 +173,19 @@ class WC_Tests_OnboardingTasks_TaskList extends WC_Unit_Test_Case {
*/ */
public function test_previous_completion() { public function test_previous_completion() {
$this->list->add_task( $this->list->add_task(
array( new TestTask(
'id' => 'complete-task1', array(
'is_complete' => true, 'id' => 'complete-task1',
'is_complete' => true,
)
) )
); );
$this->list->add_task( $this->list->add_task(
array( new TestTask(
'id' => 'complete-task2', array(
'is_complete' => true, 'id' => 'complete-task2',
'is_complete' => true,
)
) )
); );
$this->assertFalse( $this->list->has_previously_completed() ); $this->assertFalse( $this->list->has_previously_completed() );
@ -176,9 +198,11 @@ class WC_Tests_OnboardingTasks_TaskList extends WC_Unit_Test_Case {
*/ */
public function test_get_json() { public function test_get_json() {
$this->list->add_task( $this->list->add_task(
array( new TestTask(
'id' => 'my-task', array(
'is_complete' => true, 'id' => 'my-task',
'is_complete' => true,
)
) )
); );
$json = $this->list->get_json(); $json = $this->list->get_json();
@ -198,34 +222,42 @@ class WC_Tests_OnboardingTasks_TaskList extends WC_Unit_Test_Case {
*/ */
public function add_test_tasks( $list ) { public function add_test_tasks( $list ) {
$list->add_task( $list->add_task(
array( new TestTask(
'id' => 'task-1', array(
'can_view' => true, 'id' => 'task-1',
'level' => 1, 'can_view' => true,
'is_complete' => true, 'level' => 1,
'is_complete' => true,
)
) )
); );
$list->add_task( $list->add_task(
array( new TestTask(
'id' => 'task-2', array(
'can_view' => true, 'id' => 'task-2',
'is_complete' => false, 'can_view' => true,
'is_complete' => false,
)
) )
); );
$list->add_task( $list->add_task(
array( new TestTask(
'id' => 'task-3', array(
'can_view' => true, 'id' => 'task-3',
'level' => 2, 'can_view' => true,
'is_complete' => false, 'level' => 2,
'is_complete' => false,
)
) )
); );
$list->add_task( $list->add_task(
array( new TestTask(
'id' => 'task-4', array(
'can_view' => true, 'id' => 'task-4',
'level' => 1, 'can_view' => true,
'is_complete' => false, 'level' => 1,
'is_complete' => false,
)
) )
); );
} }

View File

@ -7,6 +7,8 @@
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task; use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
require_once __DIR__ . '/test-task.php';
/** /**
* class WC_Tests_OnboardingTasks_Task * class WC_Tests_OnboardingTasks_Task
*/ */
@ -16,34 +18,34 @@ class WC_Tests_OnboardingTasks_Task extends WC_Unit_Test_Case {
* Tests that a task is visible by default. * Tests that a task is visible by default.
*/ */
public function test_capability_visible() { public function test_capability_visible() {
$task = new Task( $task = new TestTask(
array( array(
'id' => 'wc-unit-test-task', 'id' => 'wc-unit-test-task',
) )
); );
$this->assertEquals( true, $task->can_view ); $this->assertEquals( true, $task->can_view() );
} }
/** /**
* Tests that a task is not visible when not capable of being viewed. * Tests that a task is not visible when not capable of being viewed.
*/ */
public function test_capability_not_visible() { public function test_capability_not_visible() {
$task = new Task( $task = new TestTask(
array( array(
'id' => 'wc-unit-test-task', 'id' => 'wc-unit-test-task',
'can_view' => false, 'can_view' => false,
) )
); );
$this->assertEquals( false, $task->can_view ); $this->assertEquals( false, $task->can_view() );
} }
/** /**
* Tests that a task can be dismissed. * Tests that a task can be dismissed.
*/ */
public function test_dismiss() { public function test_dismiss() {
$task = new Task( $task = new TestTask(
array( array(
'id' => 'wc-unit-test-task', 'id' => 'wc-unit-test-task',
'is_dismissable' => true, 'is_dismissable' => true,
@ -53,14 +55,14 @@ class WC_Tests_OnboardingTasks_Task extends WC_Unit_Test_Case {
$update = $task->dismiss(); $update = $task->dismiss();
$dismissed = get_option( Task::DISMISSED_OPTION, array() ); $dismissed = get_option( Task::DISMISSED_OPTION, array() );
$this->assertEquals( true, $update ); $this->assertEquals( true, $update );
$this->assertContains( $task->id, $dismissed ); $this->assertContains( $task->get_id(), $dismissed );
} }
/** /**
* Tests that a dismissal can be undone. * Tests that a dismissal can be undone.
*/ */
public function test_undo_dismiss() { public function test_undo_dismiss() {
$task = new Task( $task = new TestTask(
array( array(
'id' => 'wc-unit-test-task', 'id' => 'wc-unit-test-task',
'is_dismissable' => true, 'is_dismissable' => true,
@ -70,14 +72,14 @@ class WC_Tests_OnboardingTasks_Task extends WC_Unit_Test_Case {
$task->dismiss(); $task->dismiss();
$task->undo_dismiss(); $task->undo_dismiss();
$dismissed = get_option( Task::DISMISSED_OPTION, array() ); $dismissed = get_option( Task::DISMISSED_OPTION, array() );
$this->assertNotContains( $task->id, $dismissed ); $this->assertNotContains( $task->get_id(), $dismissed );
} }
/** /**
* Tests that a non-dismissable task cannot be dismissed. * Tests that a non-dismissable task cannot be dismissed.
*/ */
public function test_not_dismissable() { public function test_not_dismissable() {
$task = new Task( $task = new TestTask(
array( array(
'id' => 'wc-unit-test-non-dismissable-task', 'id' => 'wc-unit-test-non-dismissable-task',
'is_dismissable' => false, 'is_dismissable' => false,
@ -87,7 +89,7 @@ class WC_Tests_OnboardingTasks_Task extends WC_Unit_Test_Case {
$update = $task->dismiss(); $update = $task->dismiss();
$dismissed = get_option( Task::DISMISSED_OPTION, array() ); $dismissed = get_option( Task::DISMISSED_OPTION, array() );
$this->assertEquals( false, $update ); $this->assertEquals( false, $update );
$this->assertNotContains( $task->id, $dismissed ); $this->assertNotContains( $task->get_id(), $dismissed );
} }
@ -95,7 +97,7 @@ class WC_Tests_OnboardingTasks_Task extends WC_Unit_Test_Case {
* Tests that a task can be snoozed. * Tests that a task can be snoozed.
*/ */
public function test_snooze() { public function test_snooze() {
$task = new Task( $task = new TestTask(
array( array(
'id' => 'wc-unit-test-snoozeable-task', 'id' => 'wc-unit-test-snoozeable-task',
'is_snoozeable' => true, 'is_snoozeable' => true,
@ -105,14 +107,14 @@ class WC_Tests_OnboardingTasks_Task extends WC_Unit_Test_Case {
$update = $task->snooze(); $update = $task->snooze();
$snoozed = get_option( Task::SNOOZED_OPTION, array() ); $snoozed = get_option( Task::SNOOZED_OPTION, array() );
$this->assertEquals( true, $update ); $this->assertEquals( true, $update );
$this->assertArrayHasKey( $task->id, $snoozed ); $this->assertArrayHasKey( $task->get_id(), $snoozed );
} }
/** /**
* Tests that a task can be unsnoozed. * Tests that a task can be unsnoozed.
*/ */
public function test_undo_snooze() { public function test_undo_snooze() {
$task = new Task( $task = new TestTask(
array( array(
'id' => 'wc-unit-test-snoozeable-task', 'id' => 'wc-unit-test-snoozeable-task',
'is_snoozeable' => true, 'is_snoozeable' => true,
@ -122,7 +124,7 @@ class WC_Tests_OnboardingTasks_Task extends WC_Unit_Test_Case {
$task->snooze(); $task->snooze();
$task->undo_snooze(); $task->undo_snooze();
$snoozed = get_option( Task::SNOOZED_OPTION, array() ); $snoozed = get_option( Task::SNOOZED_OPTION, array() );
$this->assertArrayNotHasKey( $task->id, $snoozed ); $this->assertArrayNotHasKey( $task->get_id(), $snoozed );
} }
/** /**
@ -134,14 +136,14 @@ class WC_Tests_OnboardingTasks_Task extends WC_Unit_Test_Case {
$snoozed['wc-unit-test-task'] = $time; $snoozed['wc-unit-test-task'] = $time;
update_option( Task::SNOOZED_OPTION, $snoozed ); update_option( Task::SNOOZED_OPTION, $snoozed );
$task = new Task( $task = new TestTask(
array( array(
'id' => 'wc-unit-test-task', 'id' => 'wc-unit-test-task',
'is_snoozeable' => true, 'is_snoozeable' => true,
) )
); );
$this->assertEquals( $time, $task->snoozed_until ); $this->assertEquals( $time, $task->get_snoozed_until() );
} }
@ -149,7 +151,7 @@ class WC_Tests_OnboardingTasks_Task extends WC_Unit_Test_Case {
* Tests that a non snoozeable task cannot be snoozed. * Tests that a non snoozeable task cannot be snoozed.
*/ */
public function test_not_snoozeable() { public function test_not_snoozeable() {
$task = new Task( $task = new TestTask(
array( array(
'id' => 'wc-unit-test-snoozeable-task', 'id' => 'wc-unit-test-snoozeable-task',
'is_snoozeable' => false, 'is_snoozeable' => false,
@ -164,7 +166,7 @@ class WC_Tests_OnboardingTasks_Task extends WC_Unit_Test_Case {
* Tests that a task is no longer consider snoozed after the time has passed. * Tests that a task is no longer consider snoozed after the time has passed.
*/ */
public function test_snooze_time() { public function test_snooze_time() {
$task = new Task( $task = new TestTask(
array( array(
'id' => 'wc-unit-test-snoozeable-task', 'id' => 'wc-unit-test-snoozeable-task',
'is_snoozeable' => true, 'is_snoozeable' => true,
@ -184,7 +186,7 @@ class WC_Tests_OnboardingTasks_Task extends WC_Unit_Test_Case {
* Tests that a task's properties are returned as JSON. * Tests that a task's properties are returned as JSON.
*/ */
public function test_json() { public function test_json() {
$task = new Task( $task = new TestTask(
array( array(
'id' => 'wc-unit-test-task', 'id' => 'wc-unit-test-task',
) )
@ -211,7 +213,7 @@ class WC_Tests_OnboardingTasks_Task extends WC_Unit_Test_Case {
* Tests that a task can be actioned. * Tests that a task can be actioned.
*/ */
public function test_action_task() { public function test_action_task() {
$task = new Task( $task = new TestTask(
array( array(
'id' => 'wc-unit-test-task', 'id' => 'wc-unit-test-task',
) )
@ -220,19 +222,19 @@ class WC_Tests_OnboardingTasks_Task extends WC_Unit_Test_Case {
$update = $task->mark_actioned(); $update = $task->mark_actioned();
$actioned = get_option( Task::ACTIONED_OPTION, array() ); $actioned = get_option( Task::ACTIONED_OPTION, array() );
$this->assertEquals( true, $update ); $this->assertEquals( true, $update );
$this->assertContains( $task->id, $actioned ); $this->assertContains( $task->get_id(), $actioned );
} }
/** /**
* Test task sort with empty config. * Test task sort with empty config.
*/ */
public function test_sort_with_empty_sort_by_config() { public function test_sort_with_empty_sort_by_config() {
$task_a = new Task( $task_a = new TestTask(
array( array(
'id' => 'a', 'id' => 'a',
) )
); );
$task_b = new Task( $task_b = new TestTask(
array( array(
'id' => 'b', 'id' => 'b',
) )
@ -245,12 +247,12 @@ class WC_Tests_OnboardingTasks_Task extends WC_Unit_Test_Case {
* Test task sort with config with invalid key. * Test task sort with config with invalid key.
*/ */
public function test_sort_with_sort_by_config_with_invalid_key() { public function test_sort_with_sort_by_config_with_invalid_key() {
$task_a = new Task( $task_a = new TestTask(
array( array(
'id' => 'a', 'id' => 'a',
) )
); );
$task_b = new Task( $task_b = new TestTask(
array( array(
'id' => 'b', 'id' => 'b',
) )
@ -272,13 +274,13 @@ class WC_Tests_OnboardingTasks_Task extends WC_Unit_Test_Case {
* Test task sort with config with valid key asc. * Test task sort with config with valid key asc.
*/ */
public function test_sort_with_sort_by_config_with_valid_key_asc() { public function test_sort_with_sort_by_config_with_valid_key_asc() {
$task_a = new Task( $task_a = new TestTask(
array( array(
'id' => 'a', 'id' => 'a',
'level' => 1, 'level' => 1,
) )
); );
$task_b = new Task( $task_b = new TestTask(
array( array(
'id' => 'b', 'id' => 'b',
'level' => 2, 'level' => 2,
@ -301,13 +303,13 @@ class WC_Tests_OnboardingTasks_Task extends WC_Unit_Test_Case {
* Test task sort with config with valid key desc. * Test task sort with config with valid key desc.
*/ */
public function test_sort_with_sort_by_config_with_valid_key_desc() { public function test_sort_with_sort_by_config_with_valid_key_desc() {
$task_a = new Task( $task_a = new TestTask(
array( array(
'id' => 'a', 'id' => 'a',
'level' => 1, 'level' => 1,
) )
); );
$task_b = new Task( $task_b = new TestTask(
array( array(
'id' => 'b', 'id' => 'b',
'level' => 2, 'level' => 2,
@ -330,14 +332,14 @@ class WC_Tests_OnboardingTasks_Task extends WC_Unit_Test_Case {
* Test task sort with config with multiple keys. * Test task sort with config with multiple keys.
*/ */
public function test_sort_with_sort_by_config_with_multiple_keys() { public function test_sort_with_sort_by_config_with_multiple_keys() {
$task_a = new Task( $task_a = new TestTask(
array( array(
'id' => 'a', 'id' => 'a',
'level' => 2, 'level' => 2,
'is_complete' => false, 'is_complete' => false,
) )
); );
$task_b = new Task( $task_b = new TestTask(
array( array(
'id' => 'b', 'id' => 'b',
'level' => 2, 'level' => 2,

View File

@ -0,0 +1,168 @@
<?php
/**
* Class for creating testable tasks.
*
* @package WooCommerce\Admin\Tests\OnboardingTasks
*/
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
/**
* TestTask class.
*/
class TestTask extends Task {
/**
* ID.
*
* @var string
*/
public $id = '';
/**
* Snoozeable.
*
* @var boolean
*/
public $is_snoozeable = false;
/**
* Dismissable.
*
* @var boolean
*/
public $is_dismissable = false;
/**
* Constructor.
*
* @param array $args Array of task args.
*/
public function __construct( $args ) {
$task_args = wp_parse_args(
$args,
array(
'id' => null,
'is_dismissable' => false,
'is_snoozeable' => false,
'is_snoozeable' => false,
'can_view' => true,
'level' => 3,
'additional_info' => null,
'content' => '',
'title' => '',
'is_complete' => false,
'time' => null,
)
);
$this->id = $task_args['id'];
$this->additional_info = $task_args['additional_info'];
$this->content = $task_args['content'];
$this->is_complete = $task_args['is_complete'];
$this->is_dismissable = $task_args['is_dismissable'];
$this->is_snoozeable = $task_args['is_snoozeable'];
$this->can_view = $task_args['can_view'];
$this->level = $task_args['level'];
$this->time = $task_args['time'];
$this->title = $task_args['title'];
}
/**
* ID.
*
* @return string
*/
public function get_id() {
return $this->id;
}
/**
* Additonal info.
*
* @return string
*/
public function get_additional_info() {
return $this->additional_info;
}
/**
* Content.
*
* @return string
*/
public function get_content() {
return $this->content;
}
/**
* Parent ID.
*
* @return string
*/
public function get_parent_id() {
return 'extended';
}
/**
* Level.
*
* @return int
*/
public function get_level() {
return $this->level;
}
/**
* Title
*
* @return string
*/
public function get_title() {
return $this->title;
}
/**
* Time
*
* @return string|null
*/
public function get_time() {
return $this->time;
}
/**
* Check if a task is snoozeable.
*
* @return bool
*/
public function is_snoozeable() {
return $this->is_snoozeable;
}
/**
* Check if a task is dismissable.
*
* @return bool
*/
public function is_dismissable() {
return $this->is_dismissable;
}
/**
* Check if a task is dismissable.
*
* @return bool
*/
public function is_complete() {
return $this->is_complete;
}
/**
* Check if a task is dismissable.
*
* @return bool
*/
public function can_view() {
return $this->can_view;
}
}