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,
level: task.level ? parseInt( task.level, 10 ) : 3,
list_id: task.type || 'extended',
is_visible: task.visible,
can_view: task.visible,
id: task.key,
is_snoozeable: task.allowRemindMeLater,
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\OnboardingTasks\Init as OnboardingTasksFeature;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\TaskLists;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\DeprecatedExtendedTask;
defined( 'ABSPATH' ) || exit;
@ -694,7 +694,6 @@ class OnboardingTasks extends \WC_REST_Data_Controller {
public function get_tasks( $request ) {
$extended_tasks = $request->get_param( 'extended_tasks' );
TaskLists::maybe_add_default_tasks();
TaskLists::maybe_add_extended_tasks( $extended_tasks );
$lists = TaskLists::get_lists();
@ -716,21 +715,19 @@ class OnboardingTasks extends \WC_REST_Data_Controller {
* @return WP_REST_Request|WP_Error
*/
public function dismiss_task( $request ) {
TaskLists::maybe_add_default_tasks();
$id = $request->get_param( 'id' );
$task = TaskLists::get_task( $id );
if ( ! $task && $id ) {
$task = new Task(
$task = new DeprecatedExtendedTask(
array(
'id' => $id,
'is_dismissable' => true,
'parent_id' => 'extended',
)
);
}
if ( ! $task || ! $task->is_dismissable ) {
if ( ! $task || ! $task->is_dismissable() ) {
return new \WP_Error(
'woocommerce_rest_invalid_task',
__( '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
*/
public function undo_dismiss_task( $request ) {
TaskLists::maybe_add_default_tasks();
$id = $request->get_param( 'id' );
$task = TaskLists::get_task( $id );
if ( ! $task && $id ) {
$task = new Task(
$task = new DeprecatedExtendedTask(
array(
'id' => $id,
'is_dismissable' => true,
'parent_id' => 'extended',
)
);
}
if ( ! $task || ! $task->is_dismissable ) {
if ( ! $task || ! $task->is_dismissable() ) {
return new \WP_Error(
'woocommerce_rest_invalid_task',
__( '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
*/
public function snooze_task( $request ) {
TaskLists::maybe_add_default_tasks();
$task_id = $request->get_param( 'id' );
$task_list_id = $request->get_param( 'task_list_id' );
$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 );
if ( ! $task && $task_id ) {
$task = new Task(
$task = new DeprecatedExtendedTask(
array(
'id' => $task_id,
'is_snoozeable' => true,
'parent_id' => 'extended',
)
);
}
if ( ! $task || ! $task->is_snoozeable ) {
if ( ! $task || ! $task->is_snoozeable() ) {
return new \WP_Error(
'woocommerce_rest_invalid_task',
__( '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
*/
public function undo_snooze_task( $request ) {
TaskLists::maybe_add_default_tasks();
$id = $request->get_param( 'id' );
$task = TaskLists::get_task( $id );
if ( ! $task && $id ) {
$task = new Task(
$task = new DeprecatedExtendedTask(
array(
'id' => $id,
'is_snoozeable' => true,
'parent_id' => 'extended',
)
);
}
if ( ! $task || ! $task->is_snoozeable ) {
if ( ! $task || ! $task->is_snoozeable() ) {
return new \WP_Error(
'woocommerce_rest_invalid_task',
__( '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
*/
public function hide_task_list( $request ) {
TaskLists::maybe_add_default_tasks();
$id = $request->get_param( 'id' );
$task_list = TaskLists::get_list( $id );
@ -916,15 +906,13 @@ class OnboardingTasks extends \WC_REST_Data_Controller {
* @return WP_REST_Request|WP_Error
*/
public function action_task( $request ) {
TaskLists::maybe_add_default_tasks();
$id = $request->get_param( 'id' );
$task = TaskLists::get_task( $id );
if ( ! $task && $id ) {
$task = new Task(
$task = new DeprecatedExtendedTask(
array(
'id' => $id,
'parent_id' => 'extended',
'id' => $id,
)
);
}

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.
*/
class Task {
abstract class Task {
/**
* Task traits.
*/
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.
*
@ -159,50 +61,92 @@ class Task {
);
/**
* Constructor
* ID.
*
* @param array $data Task list data.
* @return string
*/
public function __construct( $data = array() ) {
$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(),
);
abstract public function get_id();
$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'];
$this->title = (string) $data['title'];
$this->content = (string) $data['content'];
$this->action_label = (string) $data['action_label'];
$this->action_url = (string) $data['action_url'];
$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'];
/**
* Title.
*
* @return string
*/
abstract public function get_title();
$snoozed_tasks = get_option( self::SNOOZED_OPTION, array() );
if ( isset( $snoozed_tasks[ $this->id ] ) ) {
$this->snoozed_until = $snoozed_tasks[ $this->id ];
}
/**
* Content.
*
* @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
*/
public function is_dismissed() {
if ( ! $this->is_dismissable ) {
if ( ! $this->is_dismissable() ) {
return false;
}
$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
*/
public function dismiss() {
if ( ! $this->is_dismissable ) {
if ( ! $this->is_dismissable() ) {
return false;
}
$dismissed = get_option( self::DISMISSED_OPTION, array() );
$dismissed[] = $this->id;
$dismissed[] = $this->get_id();
$update = update_option( self::DISMISSED_OPTION, array_unique( $dismissed ) );
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;
@ -248,29 +192,52 @@ class Task {
*/
public function undo_dismiss() {
$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 );
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;
}
/**
* 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.
*
* @return bool
*/
public function is_snoozed() {
if ( ! $this->is_snoozeable ) {
if ( ! $this->is_snoozeable() ) {
return false;
}
$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
*/
public function snooze( $duration = 'day' ) {
if ( ! $this->is_snoozeable ) {
if ( ! $this->is_snoozeable() ) {
return false;
}
$snoozed = get_option( self::SNOOZED_OPTION, array() );
$snoozed_until = $this->duration_to_ms[ $duration ] + ( time() * 1000 );
$snoozed[ $this->id ] = $snoozed_until;
$update = update_option( self::SNOOZED_OPTION, $snoozed );
$snoozed = get_option( self::SNOOZED_OPTION, array() );
$snoozed_until = $this->duration_to_ms[ $duration ] + ( time() * 1000 );
$snoozed[ $this->get_id() ] = $snoozed_until;
$update = update_option( self::SNOOZED_OPTION, $snoozed );
if ( $update ) {
if ( $update ) {
$this->record_tracks_event( 'remindmelater_task', array( 'task_name' => $this->id ) );
$this->snoozed_until = $snoozed_until;
$this->record_tracks_event( 'remindmelater_task', array( 'task_name' => $this->get_id() ) );
}
}
@ -306,11 +272,11 @@ class Task {
*/
public function undo_snooze() {
$snoozed = get_option( self::SNOOZED_OPTION, array() );
unset( $snoozed[ $this->id ] );
unset( $snoozed[ $this->get_id() ] );
$update = update_option( self::SNOOZED_OPTION, $snoozed );
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;
@ -323,18 +289,18 @@ class Task {
*/
public function has_previously_completed() {
$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.
*/
public function possibly_track_completion() {
if ( ! $this->can_view ) {
if ( ! $this->can_view() ) {
return;
}
if ( ! $this->is_complete ) {
if ( ! $this->is_complete() ) {
return;
}
@ -343,9 +309,9 @@ class Task {
}
$completed_tasks = get_option( self::COMPLETED_OPTION, array() );
$completed_tasks[] = $this->id;
$completed_tasks[] = $this->get_id();
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(
self::ACTIVE_TASK_TRANSIENT,
$this->id,
$this->get_id(),
DAY_IN_SECONDS
);
}
@ -367,7 +333,25 @@ class Task {
* Check if this is the active task.
*/
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();
return array(
'id' => $this->id,
'parentId' => $this->parent_id,
'title' => $this->title,
'canView' => $this->can_view,
'content' => $this->content,
'additionalInfo' => $this->additional_info,
'actionLabel' => $this->action_label,
'actionUrl' => $this->action_url,
'isComplete' => $this->is_complete,
'time' => $this->time,
'level' => $this->level,
'id' => $this->get_id(),
'parentId' => $this->get_parent_id(),
'title' => $this->get_title(),
'canView' => $this->can_view(),
'content' => $this->get_content(),
'additionalInfo' => $this->get_additional_info(),
'actionLabel' => $this->get_action_label(),
'actionUrl' => $this->get_action_url(),
'isComplete' => $this->is_complete(),
'time' => $this->get_time(),
'level' => $this->get_level(),
'isActioned' => $this->is_actioned(),
'isDismissed' => $this->is_dismissed(),
'isDismissable' => $this->is_dismissable,
'isDismissable' => $this->is_dismissable(),
'isSnoozed' => $this->is_snoozed(),
'isSnoozeable' => $this->is_snoozeable,
'snoozedUntil' => $this->snoozed_until,
'additionalData' => self::convert_object_to_camelcase( $this->additional_data ),
'isSnoozeable' => $this->is_snoozeable(),
'snoozedUntil' => $this->get_snoozed_until(),
'additionalData' => self::convert_object_to_camelcase( $this->get_additional_data() ),
);
}
/**
* Convert object keys to camelcase.
*
* @param object $object Object to convert.
* @param array $data Data to convert.
* @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();
foreach ( $object as $key => $value ) {
foreach ( $data as $key => $value ) {
$new_key = lcfirst( implode( '', array_map( 'ucfirst', explode( '_', $key ) ) ) );
$new_object->$new_key = $value;
}
@ -426,11 +414,11 @@ class Task {
public function mark_actioned() {
$actioned = get_option( self::ACTIONED_OPTION, array() );
$actioned[] = $this->id;
$actioned[] = $this->get_id();
$update = update_option( self::ACTIONED_OPTION, array_unique( $actioned ) );
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;
@ -442,7 +430,7 @@ class Task {
* @return bool
*/
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(
$viewable_tasks,
function( $total, $task ) {
return $task->is_complete ? $total + 1 : $total;
return $task->is_complete() ? $total + 1 : $total;
},
0
);
@ -149,7 +149,7 @@ class TaskList {
return array_reduce(
$viewable_tasks,
function( $is_complete, $task ) {
return ! $task->is_complete ? false : $is_complete;
return ! $task->is_complete() ? false : $is_complete;
},
true
);
@ -168,14 +168,17 @@ class TaskList {
/**
* Add task to the task list.
*
* @param array $args Task properties.
* @param Task $task Task class.
*/
public function add_task( $args ) {
$task_args = wp_parse_args(
$args,
array( 'parent_id' => $this->id )
);
$this->tasks[] = new Task( $task_args );
public function add_task( $task ) {
if ( ! is_subclass_of( $task, 'Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task' ) ) {
return new \WP_Error(
'woocommerce_task_list_invalid_task',
__( 'Task is not a subclass of `Task`', 'woocommerce-admin' )
);
}
$this->tasks[] = $task;
}
/**
@ -188,7 +191,7 @@ class TaskList {
array_filter(
$this->tasks,
function( $task ) {
return $task->can_view;
return $task->can_view();
}
)
);
@ -238,7 +241,6 @@ class TaskList {
*/
public function get_json() {
$this->possibly_track_completion();
return array(
'id' => $this->id,
'title' => $this->title,

View File

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

View File

@ -9,48 +9,82 @@ use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks\Products;
/**
* Appearance Task
*/
class Appearance {
class Appearance extends Task {
/**
* Initialize.
*/
public static function init() {
add_action( 'admin_enqueue_scripts', array( __CLASS__, 'add_media_scripts' ) );
add_action( 'admin_enqueue_scripts', array( __CLASS__, 'possibly_add_return_notice_script' ) );
public function __construct() {
add_action( 'admin_enqueue_scripts', array( $this, 'add_media_scripts' ) );
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
*/
public static function get_task() {
public function get_additional_data() {
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' => 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(),
),
'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.
*/
public static function add_media_scripts() {
$task = new Task( self::get_task() );
if ( ! $task->can_view ) {
public function add_media_scripts() {
if ( ! Loader::is_admin_page() || ! $this->can_view() ) {
return;
}
@ -63,15 +97,14 @@ class Appearance {
*
* @param string $hook Page hook.
*/
public static function possibly_add_return_notice_script( $hook ) {
public function possibly_add_return_notice_script( $hook ) {
global $post;
$task = new Task( self::get_task() );
if ( $task->is_complete || ! $task->is_active() ) {
if ( 'post.php' !== $hook || 'page' !== $post->post_type ) {
return;
}
if ( 'post.php' !== $hook || 'page' !== $post->post_type ) {
if ( $this->is_complete() || ! $this->is_active() ) {
return;
}

View File

@ -9,26 +9,73 @@ use Automattic\WooCommerce\Admin\Features\RemoteFreeExtensions\Init as RemoteFre
/**
* Marketing Task
*/
class Marketing {
class Marketing extends Task {
/**
* Get the task arguments.
* ID.
*
* @return array
* @return string
*/
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_plugins() ) > 0,
'time' => __( '1 minute', 'woocommerce-admin' ),
public function get_id() {
return 'marketing';
}
/**
* Parent ID.
*
* @return string
*/
public function get_parent_id() {
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.
*

View File

@ -4,33 +4,81 @@ namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;
use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks\WooCommercePayments;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
/**
* Payments Task
*/
class Payments {
class Payments extends Task {
/**
* Get the task arguments.
* ID.
*
* @return array
* @return string
*/
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() ||
WooCommercePayments::is_connected()
),
'time' => __( '2 minutes', 'woocommerce-admin' ),
public function get_id() {
return 'payments';
}
/**
* Parent ID.
*
* @return string
*/
public function get_parent_id() {
return 'setup';
}
/**
* Title.
*
* @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
*/
class Products {
class Products extends Task {
/**
* Initialize.
*/
public static function init() {
add_action( 'admin_enqueue_scripts', array( __CLASS__, 'possibly_add_manual_return_notice_script' ) );
add_action( 'admin_enqueue_scripts', array( __CLASS__, 'possibly_add_import_return_notice_script' ) );
public function __construct() {
add_action( 'admin_enqueue_scripts', array( $this, 'possibly_add_manual_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.
*
* @param string $hook Page hook.
*/
public static function possibly_add_manual_return_notice_script( $hook ) {
$task = new Task( self::get_task() );
if ( $task->is_complete || ! $task->is_active() ) {
public function possibly_add_manual_return_notice_script( $hook ) {
global $post;
if ( 'post.php' !== $hook || 'product' !== $post->post_type ) {
return;
}
global $post;
if ( 'post.php' !== $hook || 'product' !== $post->post_type ) {
if ( ! $this->is_active() || $this->is_complete() ) {
return;
}
@ -51,15 +118,14 @@ class Products {
*
* @param string $hook Page hook.
*/
public static function possibly_add_import_return_notice_script( $hook ) {
$task = new Task( self::get_task() );
public function possibly_add_import_return_notice_script( $hook ) {
$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;
}
if ( 'product_page_product_importer' !== $hook || 'done' !== $step ) {
if ( ! $this->is_active() || $this->is_complete() ) {
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.
*

View File

@ -3,18 +3,18 @@
namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;
use Automattic\WooCommerce\Admin\Features\Onboarding;
use Automattic\WooCommerce\Admin\PluginsHelper;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
use Automattic\WooCommerce\Admin\PluginsHelper;
/**
* Purchase Task
*/
class Purchase {
class Purchase extends Task {
/**
* Initialize.
*/
public static function init() {
add_action( 'update_option_woocommerce_onboarding_profile', array( __CLASS__, 'clear_dismissal' ), 10, 2 );
public function __construct() {
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 $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();
$previous_product_types = isset( $old_value['product_types'] ) ? (array) $old_value['product_types'] : array();
@ -31,50 +31,118 @@ class Purchase {
return;
}
$task = new Task( self::get_task() );
$task->undo_dismiss();
$this->undo_dismiss();
}
/**
* 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();
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',
return 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'
),
'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'] )
$products['remaining'][0]
)
: __(
'Add paid extensions to my store',
'woocommerce-admin'
);
}
/**
* 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' ),
'is_complete' => count( $products['remaining'] ) === 0,
'can_view' => count( $products['purchaseable'] ) > 0,
'time' => __( '2 minutes', 'woocommerce-admin' ),
'is_dismissable' => true,
);
implode( ', ', array_slice( $products['remaining'], 0, -1 ) ) . ( count( $products['remaining'] ) > 2 ? ',' : '' ),
end( $products['remaining'] )
);
}
/**
* 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;
use Automattic\WooCommerce\Admin\Features\Onboarding;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
/**
* Shipping Task
*/
class Shipping {
class Shipping extends Task {
/**
* Get the task arguments.
* ID.
*
* @return array
* @return string
*/
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' ),
public function get_id() {
return 'shipping';
}
/**
* Parent ID.
*
* @return string
*/
public function get_parent_id() {
return 'setup';
}
/**
* 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.
*

View File

@ -3,31 +3,76 @@
namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;
use Automattic\WooCommerce\Admin\Features\Onboarding;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
/**
* Store Details Task
*/
class StoreDetails {
class StoreDetails extends Task {
/**
* Get the task arguments.
* ID.
*
* @return array
* @return string
*/
public static function get_task() {
$profiler_data = get_option( Onboarding::PROFILE_DATA_OPTION, array() );
public function get_id() {
return 'store_details';
}
return 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'
),
'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' ),
/**
* Parent ID.
*
* @return string
*/
public function get_parent_id() {
return 'setup';
}
/**
* Title.
*
* @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
*/
class Tax {
class Tax extends Task {
/**
* Initialize.
*/
public static function init() {
add_action( 'admin_enqueue_scripts', array( __CLASS__, 'possibly_add_return_notice_script' ) );
public function __construct() {
add_action( 'admin_enqueue_scripts', array( $this, 'possibly_add_return_notice_script' ) );
}
/**
* Adds a return to task list notice when completing the task.
*/
public static function possibly_add_return_notice_script() {
$task = new Task( self::get_task() );
public function possibly_add_return_notice_script() {
$page = isset( $_GET['page'] ) ? $_GET['page'] : ''; // 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;
}
if ( 'wc-settings' !== $page || 'tax' !== $tab ) {
if ( ! $this->is_active() || $this->is_complete() ) {
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
*/
public static function get_task() {
public function get_additional_data() {
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' ) ||
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(),
),
'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;
use Automattic\WooCommerce\Admin\Features\Onboarding;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
use Automattic\WooCommerce\Admin\PluginsHelper;
/**
* WooCommercePayments Task
*/
class WooCommercePayments {
class WooCommercePayments extends Task {
/**
* Get the task arguments.
* ID.
*
* @return array
* @return string
*/
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() &&
! self::is_connected(),
'time' => __( '2 minutes', 'woocommerce-admin' ),
'additional_info' => __(
'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_id() {
return 'woocommerce-payments';
}
/**
* Parent ID.
*
* @return string
*/
public function get_parent_id() {
return 'setup';
}
/**
* Title.
*
* @return string
*/
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.
*

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\Task;
require_once __DIR__ . '/../features/onboarding-tasks/test-task.php';
/**
* WC Tests API Onboarding Tasks
*/
@ -190,10 +192,12 @@ class WC_Tests_API_Onboarding_Tasks extends WC_REST_Unit_Test_Case {
TaskLists::add_task(
'test-list',
array(
'id' => 'test-task',
'title' => 'Test Task',
'is_snoozeable' => true,
new TestTask(
array(
'id' => 'test-task',
'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( isset( $data['snoozedUntil'] ), 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(
'test-list',
array(
'id' => 'test-task',
'title' => 'Test Task',
'is_snoozeable' => true,
new TestTask(
array(
'id' => 'test-task',
'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( isset( $data['snoozedUntil'] ), 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(
'test-list',
array(
'id' => 'test-task',
'title' => 'Test Task',
'is_snoozeable' => true,
new TestTask(
array(
'id' => 'test-task',
'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(
'test-list',
array(
'id' => 'test-task',
'title' => 'Test Task',
'is_snoozeable' => true,
new TestTask(
array(
'id' => 'test-task',
'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(
'test-list',
array(
'id' => 'test-task',
'title' => 'Test Task',
'is_dismissable' => true,
new TestTask(
array(
'id' => 'test-task',
'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(
'test-list',
array(
'id' => 'test-task',
'title' => 'Test Task',
'is_dismissable' => true,
new TestTask(
array(
'id' => 'test-task',
'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(
'test-list',
array(
'id' => 'test-task',
'title' => 'Test Task',
'is_dismissable' => true,
new TestTask(
array(
'id' => 'test-task',
'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(
'test-list',
array(
'id' => 'test-task',
'title' => 'Test Task',
'is_dismissable' => true,
new TestTask(
array(
'id' => 'test-task',
'title' => 'Test Task',
'is_dismissable' => true,
)
)
);

View File

@ -7,6 +7,8 @@
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\TaskList;
require_once __DIR__ . '/test-task.php';
/**
* class WC_Tests_OnboardingTasks_TaskList
*/
@ -86,7 +88,11 @@ class WC_Tests_OnboardingTasks_TaskList extends WC_Unit_Test_Case {
* Tests adding a 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 );
}
@ -95,15 +101,19 @@ class WC_Tests_OnboardingTasks_TaskList extends WC_Unit_Test_Case {
*/
public function test_get_viewable_tasks() {
$this->list->add_task(
array(
'id' => 'viewable-task',
'can_view' => true,
new TestTask(
array(
'id' => 'viewable-task',
'can_view' => true,
)
)
);
$this->list->add_task(
array(
'id' => 'not-viewable-task',
'can_view' => false,
new TestTask(
array(
'id' => 'not-viewable-task',
'can_view' => false,
)
)
);
$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() {
$this->list->add_task(
array(
'id' => 'complete-task',
'is_complete' => true,
new TestTask(
array(
'id' => 'complete-task',
'is_complete' => true,
)
)
);
$this->list->add_task(
array(
'id' => 'incomplete-task',
'is_complete' => false,
new TestTask(
array(
'id' => 'incomplete-task',
'is_complete' => false,
)
)
);
$this->assertFalse( $this->list->is_complete() );
@ -136,15 +150,19 @@ class WC_Tests_OnboardingTasks_TaskList extends WC_Unit_Test_Case {
*/
public function test_complete() {
$this->list->add_task(
array(
'id' => 'complete-task1',
'is_complete' => true,
new TestTask(
array(
'id' => 'complete-task1',
'is_complete' => true,
)
)
);
$this->list->add_task(
array(
'id' => 'complete-task-2',
'is_complete' => true,
new TestTask(
array(
'id' => 'complete-task-2',
'is_complete' => true,
)
)
);
$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() {
$this->list->add_task(
array(
'id' => 'complete-task1',
'is_complete' => true,
new TestTask(
array(
'id' => 'complete-task1',
'is_complete' => true,
)
)
);
$this->list->add_task(
array(
'id' => 'complete-task2',
'is_complete' => true,
new TestTask(
array(
'id' => 'complete-task2',
'is_complete' => true,
)
)
);
$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() {
$this->list->add_task(
array(
'id' => 'my-task',
'is_complete' => true,
new TestTask(
array(
'id' => 'my-task',
'is_complete' => true,
)
)
);
$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 ) {
$list->add_task(
array(
'id' => 'task-1',
'can_view' => true,
'level' => 1,
'is_complete' => true,
new TestTask(
array(
'id' => 'task-1',
'can_view' => true,
'level' => 1,
'is_complete' => true,
)
)
);
$list->add_task(
array(
'id' => 'task-2',
'can_view' => true,
'is_complete' => false,
new TestTask(
array(
'id' => 'task-2',
'can_view' => true,
'is_complete' => false,
)
)
);
$list->add_task(
array(
'id' => 'task-3',
'can_view' => true,
'level' => 2,
'is_complete' => false,
new TestTask(
array(
'id' => 'task-3',
'can_view' => true,
'level' => 2,
'is_complete' => false,
)
)
);
$list->add_task(
array(
'id' => 'task-4',
'can_view' => true,
'level' => 1,
'is_complete' => false,
new TestTask(
array(
'id' => 'task-4',
'can_view' => true,
'level' => 1,
'is_complete' => false,
)
)
);
}

View File

@ -7,6 +7,8 @@
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
require_once __DIR__ . '/test-task.php';
/**
* 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.
*/
public function test_capability_visible() {
$task = new Task(
$task = new TestTask(
array(
'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.
*/
public function test_capability_not_visible() {
$task = new Task(
$task = new TestTask(
array(
'id' => 'wc-unit-test-task',
'can_view' => false,
)
);
$this->assertEquals( false, $task->can_view );
$this->assertEquals( false, $task->can_view() );
}
/**
* Tests that a task can be dismissed.
*/
public function test_dismiss() {
$task = new Task(
$task = new TestTask(
array(
'id' => 'wc-unit-test-task',
'is_dismissable' => true,
@ -53,14 +55,14 @@ class WC_Tests_OnboardingTasks_Task extends WC_Unit_Test_Case {
$update = $task->dismiss();
$dismissed = get_option( Task::DISMISSED_OPTION, array() );
$this->assertEquals( true, $update );
$this->assertContains( $task->id, $dismissed );
$this->assertContains( $task->get_id(), $dismissed );
}
/**
* Tests that a dismissal can be undone.
*/
public function test_undo_dismiss() {
$task = new Task(
$task = new TestTask(
array(
'id' => 'wc-unit-test-task',
'is_dismissable' => true,
@ -70,14 +72,14 @@ class WC_Tests_OnboardingTasks_Task extends WC_Unit_Test_Case {
$task->dismiss();
$task->undo_dismiss();
$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.
*/
public function test_not_dismissable() {
$task = new Task(
$task = new TestTask(
array(
'id' => 'wc-unit-test-non-dismissable-task',
'is_dismissable' => false,
@ -87,7 +89,7 @@ class WC_Tests_OnboardingTasks_Task extends WC_Unit_Test_Case {
$update = $task->dismiss();
$dismissed = get_option( Task::DISMISSED_OPTION, array() );
$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.
*/
public function test_snooze() {
$task = new Task(
$task = new TestTask(
array(
'id' => 'wc-unit-test-snoozeable-task',
'is_snoozeable' => true,
@ -105,14 +107,14 @@ class WC_Tests_OnboardingTasks_Task extends WC_Unit_Test_Case {
$update = $task->snooze();
$snoozed = get_option( Task::SNOOZED_OPTION, array() );
$this->assertEquals( true, $update );
$this->assertArrayHasKey( $task->id, $snoozed );
$this->assertArrayHasKey( $task->get_id(), $snoozed );
}
/**
* Tests that a task can be unsnoozed.
*/
public function test_undo_snooze() {
$task = new Task(
$task = new TestTask(
array(
'id' => 'wc-unit-test-snoozeable-task',
'is_snoozeable' => true,
@ -122,7 +124,7 @@ class WC_Tests_OnboardingTasks_Task extends WC_Unit_Test_Case {
$task->snooze();
$task->undo_snooze();
$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;
update_option( Task::SNOOZED_OPTION, $snoozed );
$task = new Task(
$task = new TestTask(
array(
'id' => 'wc-unit-test-task',
'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.
*/
public function test_not_snoozeable() {
$task = new Task(
$task = new TestTask(
array(
'id' => 'wc-unit-test-snoozeable-task',
'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.
*/
public function test_snooze_time() {
$task = new Task(
$task = new TestTask(
array(
'id' => 'wc-unit-test-snoozeable-task',
'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.
*/
public function test_json() {
$task = new Task(
$task = new TestTask(
array(
'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.
*/
public function test_action_task() {
$task = new Task(
$task = new TestTask(
array(
'id' => 'wc-unit-test-task',
)
@ -220,19 +222,19 @@ class WC_Tests_OnboardingTasks_Task extends WC_Unit_Test_Case {
$update = $task->mark_actioned();
$actioned = get_option( Task::ACTIONED_OPTION, array() );
$this->assertEquals( true, $update );
$this->assertContains( $task->id, $actioned );
$this->assertContains( $task->get_id(), $actioned );
}
/**
* Test task sort with empty config.
*/
public function test_sort_with_empty_sort_by_config() {
$task_a = new Task(
$task_a = new TestTask(
array(
'id' => 'a',
)
);
$task_b = new Task(
$task_b = new TestTask(
array(
'id' => 'b',
)
@ -245,12 +247,12 @@ class WC_Tests_OnboardingTasks_Task extends WC_Unit_Test_Case {
* Test task sort with config with invalid key.
*/
public function test_sort_with_sort_by_config_with_invalid_key() {
$task_a = new Task(
$task_a = new TestTask(
array(
'id' => 'a',
)
);
$task_b = new Task(
$task_b = new TestTask(
array(
'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.
*/
public function test_sort_with_sort_by_config_with_valid_key_asc() {
$task_a = new Task(
$task_a = new TestTask(
array(
'id' => 'a',
'level' => 1,
)
);
$task_b = new Task(
$task_b = new TestTask(
array(
'id' => 'b',
'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.
*/
public function test_sort_with_sort_by_config_with_valid_key_desc() {
$task_a = new Task(
$task_a = new TestTask(
array(
'id' => 'a',
'level' => 1,
)
);
$task_b = new Task(
$task_b = new TestTask(
array(
'id' => 'b',
'level' => 2,
@ -330,14 +332,14 @@ class WC_Tests_OnboardingTasks_Task extends WC_Unit_Test_Case {
* Test task sort with config with multiple keys.
*/
public function test_sort_with_sort_by_config_with_multiple_keys() {
$task_a = new Task(
$task_a = new TestTask(
array(
'id' => 'a',
'level' => 2,
'is_complete' => false,
)
);
$task_b = new Task(
$task_b = new TestTask(
array(
'id' => 'b',
'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;
}
}