Automattic\WooCommerce\Admin\Features\OnboardingTasks

TaskLists{}WC 1.0

Task Lists class.

No Hooks.

Usage

$TaskLists = new TaskLists();
// use class methods

Methods

  1. public static add_list( $args )
  2. public static add_task( $list_id, $args )
  3. public static clear_lists()
  4. public static get_list( $id )
  5. public static get_list_ids()
  6. public static get_lists()
  7. public static get_lists_by_ids( $ids )
  8. public static get_task( $id, $task_list_id = null )
  9. public static get_visible()
  10. public static init()
  11. public static init_default_lists()
  12. public static init_tasks()
  13. public instance()
  14. public static is_experiment_treatment( $name )
  15. public static maybe_add_extended_tasks( $extended_tasks )
  16. public static menu_task_count()
  17. public static set_active_task()
  18. public static setup_tasks_remaining()
  19. public static task_list_preloaded_settings( $settings )

Code of TaskLists{} WC 6.7.0

class TaskLists {
	/**
	 * Class instance.
	 *
	 * @var TaskLists instance
	 */
	protected static $instance = null;

	/**
	 * An array of all registered lists.
	 *
	 * @var array
	 */
	protected static $lists = array();

	/**
	 * Boolean value to indicate if default tasks have been added.
	 *
	 * @var boolean
	 */
	protected static $default_tasks_loaded = false;

	/**
	 * Array of default tasks.
	 *
	 * @var array
	 */
	const DEFAULT_TASKS = array(
		'StoreDetails',
		'Purchase',
		'Products',
		'WooCommercePayments',
		'Payments',
		'Tax',
		'Shipping',
		'Marketing',
		'Appearance',
		'AdditionalPayments',
	);

	/**
	 * Get class instance.
	 */
	final public static function instance() {
		if ( ! static::$instance ) {
			static::$instance = new static();
		}
		return static::$instance;
	}

	/**
	 * Initialize the task lists.
	 */
	public static function init() {
		self::init_default_lists();
		add_action( 'admin_init', array( __CLASS__, 'set_active_task' ), 5 );
		add_action( 'init', array( __CLASS__, 'init_tasks' ) );
		add_action( 'admin_menu', array( __CLASS__, 'menu_task_count' ) );
		add_filter( 'woocommerce_admin_shared_settings', array( __CLASS__, 'task_list_preloaded_settings' ), 20 );
	}

	/**
	 * Check if an experiment is the treatment or control.
	 *
	 * @param string $name Name prefix of experiment.
	 * @return bool
	 */
	public static function is_experiment_treatment( $name ) {
		$anon_id        = isset( $_COOKIE['tk_ai'] ) ? sanitize_text_field( wp_unslash( $_COOKIE['tk_ai'] ) ) : '';
		$allow_tracking = 'yes' === get_option( 'woocommerce_allow_tracking' );
		$abtest         = new \WooCommerce\Admin\Experimental_Abtest(
			$anon_id,
			'woocommerce',
			$allow_tracking
		);

		$date = new \DateTime();
		$date->setTimeZone( new \DateTimeZone( 'UTC' ) );

		$experiment_name = sprintf(
			'%s_%s_%s',
			$name,
			$date->format( 'Y' ),
			$date->format( 'm' )
		);
		return $abtest->get_variation( $experiment_name ) === 'treatment';
	}

	/**
	 * Initialize default lists.
	 */
	public static function init_default_lists() {
		self::add_list(
			array(
				'id'           => 'setup',
				'title'        => __( 'Get ready to start selling', 'woocommerce' ),
				'tasks'        => array(
					'StoreDetails',
					'Purchase',
					'Products',
					'WooCommercePayments',
					'Payments',
					'Tax',
					'Shipping',
					'Marketing',
					'Appearance',
				),
				'event_prefix' => 'tasklist_',
				'visible'      => ! self::is_experiment_treatment( 'woocommerce_tasklist_setup_experiment_1' )
					&& ! self::is_experiment_treatment( 'woocommerce_tasklist_setup_experiment_2' ),
			)
		);

		self::add_list(
			array(
				'id'                      => 'setup_experiment_1',
				'hidden_id'               => 'setup',
				'title'                   => __( 'Get ready to start selling', 'woocommerce' ),
				'tasks'                   => array(
					'StoreDetails',
					'Purchase',
					'Products',
					'WooCommercePayments',
					'Payments',
					'Tax',
					'Shipping',
					'Marketing',
					'Appearance',
				),
				'display_progress_header' => true,
				'event_prefix'            => 'tasklist_',
				'options'                 => array(
					'use_completed_title' => true,
				),
				'visible'                 => self::is_experiment_treatment( 'woocommerce_tasklist_setup_experiment_1' ),
			)
		);

		self::add_list(
			array(
				'id'           => 'setup_experiment_2',
				'hidden_id'    => 'setup',
				'title'        => __( 'Get ready to start selling', 'woocommerce' ),
				'tasks'        => array(
					'StoreCreation',
					'StoreDetails',
					'Purchase',
					'Products',
					'WooCommercePayments',
					'Payments',
					'Tax',
					'Shipping',
					'Marketing',
					'Appearance',
				),
				'event_prefix' => 'tasklist_',
				'visible'      => self::is_experiment_treatment( 'woocommerce_tasklist_setup_experiment_2' )
					&& ! self::is_experiment_treatment( 'woocommerce_tasklist_setup_experiment_1' ),
				'options'      => array(
					'use_completed_title' => true,
				),
				'display_progress_header' => true,
				'sections'     => array(
					array(
						'id'          => 'basics',
						'title'       => __( 'Cover the basics', 'woocommerce' ),
						'description' => __( 'Make sure you’ve got everything you need to start selling—from business details to products.', 'woocommerce' ),
						'image'       => plugins_url(
							'/assets/images/task_list/basics-section-illustration.png',
							WC_ADMIN_PLUGIN_FILE
						),
						'task_names'  => array( 'StoreCreation', 'StoreDetails', 'Purchase', 'Products', 'Payments', 'WooCommercePayments' ),
					),
					array(
						'id'          => 'sales',
						'title'       => __( 'Get ready to sell', 'woocommerce' ),
						'description' => __( 'Easily set up the backbone of your store’s operations and get ready to accept first orders.', 'woocommerce' ),
						'image'       => plugins_url(
							'/assets/images/task_list/sales-section-illustration.png',
							WC_ADMIN_PLUGIN_FILE
						),
						'task_names'  => array( 'Shipping', 'Tax' ),
					),
					array(
						'id'          => 'expand',
						'title'       => __( 'Customize & expand', 'woocommerce' ),
						'description' => __( 'Personalize your store’s design and grow your business by enabling new sales channels.', 'woocommerce' ),
						'image'       => plugins_url(
							'/assets/images/task_list/expand-section-illustration.png',
							WC_ADMIN_PLUGIN_FILE
						),
						'task_names'  => array( 'Appearance', 'Marketing' ),
					),
				),
			)
		);

		self::add_list(
			array(
				'id'      => 'extended',
				'title'   => __( 'Things to do next', 'woocommerce' ),
				'sort_by' => array(
					array(
						'key'   => 'is_complete',
						'order' => 'asc',
					),
					array(
						'key'   => 'level',
						'order' => 'asc',
					),
				),
				'tasks'   => array(
					'AdditionalPayments',
				),
			)
		);
		self::add_list(
			array(
				'id'           => 'setup_two_column',
				'hidden_id'    => 'setup',
				'title'        => __( 'Get ready to start selling', 'woocommerce' ),
				'tasks'        => array(
					'Products',
					'WooCommercePayments',
					'Payments',
					'Tax',
					'Shipping',
					'Marketing',
					'Appearance',
				),
				'event_prefix' => 'tasklist_',
			)
		);
		self::add_list(
			array(
				'id'           => 'extended_two_column',
				'hidden_id'    => 'extended',
				'title'        => __( 'Things to do next', 'woocommerce' ),
				'sort_by'      => array(
					array(
						'key'   => 'is_complete',
						'order' => 'asc',
					),
					array(
						'key'   => 'level',
						'order' => 'asc',
					),
				),
				'tasks'        => array(
					'AdditionalPayments',
				),
				'event_prefix' => 'extended_tasklist_',
			)
		);

	}

	/**
	 * Initialize tasks.
	 */
	public static function init_tasks() {
		foreach ( self::DEFAULT_TASKS as $task ) {
			$class = 'Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks\\' . $task;
			if ( ! method_exists( $class, 'init' ) ) {
				continue;
			}
			$class::init();
		}
	}

	/**
	 * Temporarily store the active task to persist across page loads when neccessary.
	 * Most tasks do not need this.
	 */
	public static function set_active_task() {
		if ( ! isset( $_GET[ Task::ACTIVE_TASK_TRANSIENT ] ) || ! current_user_can( 'manage_woocommerce' ) ) { // phpcs:ignore csrf ok.
			return;
		}
		$referer = wp_get_referer();
		if ( ! $referer || 0 !== strpos( $referer, wc_admin_url() ) ) {
			return;
		}

		$task_id = sanitize_title_with_dashes( wp_unslash( $_GET[ Task::ACTIVE_TASK_TRANSIENT ] ) ); // phpcs:ignore csrf ok.

		$task = self::get_task( $task_id );

		if ( ! $task ) {
			return;
		}

		$task->set_active();
	}

	/**
	 * Add a task list.
	 *
	 * @param array $args Task list properties.
	 * @return WP_Error|TaskList
	 */
	public static function add_list( $args ) {
		if ( isset( self::$lists[ $args['id'] ] ) ) {
			return new \WP_Error(
				'woocommerce_task_list_exists',
				__( 'Task list ID already exists', 'woocommerce' )
			);
		}

		self::$lists[ $args['id'] ] = new TaskList( $args );
		return self::$lists[ $args['id'] ];
	}

	/**
	 * Add task to a given task list.
	 *
	 * @param string $list_id List ID to add the task to.
	 * @param array  $args Task properties.
	 * @return WP_Error|Task
	 */
	public static function add_task( $list_id, $args ) {
		if ( ! isset( self::$lists[ $list_id ] ) ) {
			return new \WP_Error(
				'woocommerce_task_list_invalid_list',
				__( 'Task list ID does not exist', 'woocommerce' )
			);
		}

		self::$lists[ $list_id ]->add_task( $args );
	}

	/**
	 * Add default extended task lists.
	 *
	 * @param array $extended_tasks list of extended tasks.
	 */
	public static function maybe_add_extended_tasks( $extended_tasks ) {
		$tasks = $extended_tasks ?? array();

		foreach ( self::$lists as $task_list ) {
			if ( 'extended' !== substr( $task_list->id, 0, 8 ) ) {
				continue;
			}
			foreach ( $tasks as $args ) {
				$task = new DeprecatedExtendedTask( $task_list, $args );
				$task_list->add_task( $task );
			}
		}

	}

	/**
	 * Get all task lists.
	 *
	 * @return array
	 */
	public static function get_lists() {
		return self::$lists;
	}

	/**
	 * Get all task lists.
	 *
	 * @param array $ids list of task list ids.
	 * @return array
	 */
	public static function get_lists_by_ids( $ids ) {
		return array_filter(
			self::$lists,
			function( $list ) use ( $ids ) {
				return in_array( $list->get_list_id(), $ids, true );
			}
		);
	}

	/**
	 * Get all task list ids.
	 *
	 * @return array
	 */
	public static function get_list_ids() {
		return array_keys( self::$lists );
	}

	/**
	 * Clear all task lists.
	 */
	public static function clear_lists() {
		self::$lists = array();
		return self::$lists;
	}

	/**
	 * Get visible task lists.
	 */
	public static function get_visible() {
		return array_filter(
			self::get_lists(),
			function ( $task_list ) {
				return $task_list->is_visible();
			}
		);
	}


	/**
	 * Retrieve a task list by ID.
	 *
	 * @param String $id Task list ID.
	 *
	 * @return TaskList|null
	 */
	public static function get_list( $id ) {
		if ( isset( self::$lists[ $id ] ) ) {
			return self::$lists[ $id ];
		}

		return null;
	}

	/**
	 * Retrieve single task.
	 *
	 * @param String $id Task ID.
	 * @param String $task_list_id Task list ID.
	 *
	 * @return Object
	 */
	public static function get_task( $id, $task_list_id = null ) {
		$task_list = $task_list_id ? self::get_list( $task_list_id ) : null;

		if ( $task_list_id && ! $task_list ) {
			return null;
		}

		$tasks_to_search = $task_list ? $task_list->tasks : array_reduce(
			self::get_lists(),
			function ( $all, $curr ) {
				return array_merge( $all, $curr->tasks );
			},
			array()
		);

		foreach ( $tasks_to_search as $task ) {
			if ( $id === $task->get_id() ) {
				return $task;
			}
		}

		return null;
	}

	/**
	 * Return number of setup tasks remaining
	 *
	 * @return number
	 */
	public static function setup_tasks_remaining() {

		$active_list = self::is_experiment_treatment( 'woocommerce_tasklist_setup_experiment_1' ) ? 'setup_experiment_1' : ( self::is_experiment_treatment( 'woocommerce_tasklist_setup_experiment_2' ) ? 'setup_experiment_2' : 'setup' );

		$setup_list = self::get_list( $active_list );

		if ( ! $setup_list || $setup_list->is_hidden() || $setup_list->is_complete() ) {
			return;
		}

		$remaining_tasks = array_values(
			array_filter(
				$setup_list->get_viewable_tasks(),
				function( $task ) {
					return ! $task->is_complete();
				}
			)
		);

		return count( $remaining_tasks );
	}

	/**
	 * Add badge to homescreen menu item for remaining tasks
	 */
	public static function menu_task_count() {
		global $submenu;

		$tasks_count = self::setup_tasks_remaining();

		if ( ! $tasks_count || ! isset( $submenu['woocommerce'] ) ) {
			return;
		}

		foreach ( $submenu['woocommerce'] as $key => $menu_item ) {
			if ( 0 === strpos( $menu_item[0], _x( 'Home', 'Admin menu name', 'woocommerce' ) ) ) {
				$submenu['woocommerce'][ $key ][0] .= ' <span class="awaiting-mod update-plugins remaining-tasks-badge count-' . esc_attr( $tasks_count ) . '">' . number_format_i18n( $tasks_count ) . '</span>'; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
				break;
			}
		}

	}

	/**
	 * Add visible list ids to component settings.
	 *
	 * @param array $settings Component settings.
	 *
	 * @return array
	 */
	public static function task_list_preloaded_settings( $settings ) {
		$settings['visibleTaskListIds'] = array_keys( self::get_visible() );

		return $settings;
	}
}