HEX
Server: LiteSpeed
System: Linux eko108.isimtescil.net 4.18.0-477.21.1.lve.1.el8.x86_64 #1 SMP Tue Sep 5 23:08:35 UTC 2023 x86_64
User: uyarreklamcomtr (11202)
PHP: 7.4.33
Disabled: opcache_get_status
Upload Files
File: /var/www/vhosts/uyarreklam.com.tr/httpdocs/OnboardingTasks.tar
DeprecatedExtendedTask.php000064400000006322151546372500011634 0ustar00<?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 = '';

	/**
	 * Additional info.
	 *
	 * @var string|null
	 */
	public $additional_info = '';

	/**
	 * Content.
	 *
	 * @var string
	 */
	public $content = '';

	/**
	 * Whether the task is complete or not.
	 *
	 * @var boolean
	 */
	public $is_complete = false;

	/**
	 * Snoozeable.
	 *
	 * @var boolean
	 */
	public $is_snoozeable = false;

	/**
	 * Dismissable.
	 *
	 * @var boolean
	 */
	public $is_dismissable = false;

	/**
	 * Whether the store is capable of viewing the task.
	 *
	 * @var bool
	 */
	public $can_view = true;

	/**
	 * Level.
	 *
	 * @var int
	 */
	public $level = 3;

	/**
	 * Time.
	 *
	 * @var string|null
	 */
	public $time;

	/**
	 * Title.
	 *
	 * @var string
	 */
	public $title = '';


	/**
	 * Constructor.
	 *
	 * @param TaskList $task_list Parent task list.
	 * @param array    $args Array of task args.
	 */
	public function __construct( $task_list, $args ) {
		parent::__construct( $task_list );
		$task_args = wp_parse_args(
			$args,
			array(
				'id'              => null,
				'is_dismissable'  => 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;
	}

	/**
	 * Additional info.
	 *
	 * @return string
	 */
	public function get_additional_info() {
		return $this->additional_info;
	}

	/**
	 * Content.
	 *
	 * @return string
	 */
	public function get_content() {
		return $this->content;
	}

	/**
	 * 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;
	}
}
DeprecatedOptions.php000064400000005000151546372500010674 0ustar00<?php
/**
 * Filters for maintaining backwards compatibility with deprecated options.
 */

namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks;

use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks\TaskList;
use WC_Install;

/**
 * DeprecatedOptions class.
 */
class DeprecatedOptions {
	/**
	 * Initialize.
	 */
	public static function init() {
		add_filter( 'pre_option_woocommerce_task_list_hidden', array( __CLASS__, 'get_deprecated_options' ), 10, 2 );
		add_filter( 'pre_option_woocommerce_extended_task_list_hidden', array( __CLASS__, 'get_deprecated_options' ), 10, 2 );
		add_action( 'pre_update_option_woocommerce_task_list_hidden', array( __CLASS__, 'update_deprecated_options' ), 10, 3 );
		add_action( 'pre_update_option_woocommerce_extended_task_list_hidden', array( __CLASS__, 'update_deprecated_options' ), 10, 3 );
	}

	/**
	 * Get the values from the correct source when attempting to retrieve deprecated options.
	 *
	 * @param string $pre_option Pre option value.
	 * @param string $option Option name.
	 * @return string
	 */
	public static function get_deprecated_options( $pre_option, $option ) {
		if ( defined( 'WC_INSTALLING' ) && WC_INSTALLING === true ) {
			return $pre_option;
		}

		$hidden = get_option( 'woocommerce_task_list_hidden_lists', array() );
		switch ( $option ) {
			case 'woocommerce_task_list_hidden':
				return in_array( 'setup', $hidden, true ) ? 'yes' : 'no';
			case 'woocommerce_extended_task_list_hidden':
				return in_array( 'extended', $hidden, true ) ? 'yes' : 'no';
		}
	}

	/**
	 * Updates the new option names when deprecated options are updated.
	 * This is a temporary fallback until we can fully remove the old task list components.
	 *
	 * @param string $value New value.
	 * @param string $old_value Old value.
	 * @param string $option Option name.
	 * @return string
	 */
	public static function update_deprecated_options( $value, $old_value, $option ) {
		switch ( $option ) {
			case 'woocommerce_task_list_hidden':
				$task_list = TaskLists::get_list( 'setup' );
				if ( ! $task_list ) {
					return;
				}
				$update = 'yes' === $value ? $task_list->hide() : $task_list->unhide();
				delete_option( 'woocommerce_task_list_hidden' );
				return false;
			case 'woocommerce_extended_task_list_hidden':
				$task_list = TaskLists::get_list( 'extended' );
				if ( ! $task_list ) {
					return;
				}
				$update = 'yes' === $value ? $task_list->hide() : $task_list->unhide();
				delete_option( 'woocommerce_extended_task_list_hidden' );
				return false;
		}
	}
}
Init.php000064400000002116151546372500006170 0ustar00<?php
/**
 * WooCommerce Onboarding Tasks
 */

namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks;

use Automattic\WooCommerce\Admin\Features\OnboardingTasks\DeprecatedOptions;

/**
 * Contains the logic for completing onboarding tasks.
 */
class Init {
	/**
	 * Class instance.
	 *
	 * @var OnboardingTasks instance
	 */
	protected static $instance = null;

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

	/**
	 * Constructor
	 */
	public function __construct() {
		DeprecatedOptions::init();
		TaskLists::init();
	}

	/**
	 * Get task item data for settings filter.
	 *
	 * @return array
	 */
	public static function get_settings() {
		$settings            = array();
		$wc_pay_is_connected = false;
		if ( class_exists( '\WC_Payments' ) ) {
			$wc_payments_gateway = \WC_Payments::get_gateway();
			$wc_pay_is_connected = method_exists( $wc_payments_gateway, 'is_connected' )
				? $wc_payments_gateway->is_connected()
				: false;
		}

		return $settings;
	}
}
Task.php000064400000030111151546372500006163 0ustar00<?php
/**
 * Handles task related methods.
 */

namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks;

use Automattic\WooCommerce\Internal\Admin\WCAdminUser;

/**
 * Task class.
 */
abstract class Task {
	/**
	 * Task traits.
	 */
	use TaskTraits;

	/**
	 * Name of the dismiss option.
	 *
	 * @var string
	 */
	const DISMISSED_OPTION = 'woocommerce_task_list_dismissed_tasks';

	/**
	 * Name of the snooze option.
	 *
	 * @var string
	 *
	 * @deprecated 7.2.0
	 */
	const SNOOZED_OPTION = 'woocommerce_task_list_remind_me_later_tasks';

	/**
	 * Name of the actioned option.
	 *
	 * @var string
	 */
	const ACTIONED_OPTION = 'woocommerce_task_list_tracked_completed_actions';

	/**
	 * Option name of completed tasks.
	 *
	 * @var string
	 */
	const COMPLETED_OPTION = 'woocommerce_task_list_tracked_completed_tasks';

	/**
	 * Name of the active task transient.
	 *
	 * @var string
	 */
	const ACTIVE_TASK_TRANSIENT = 'wc_onboarding_active_task';

	/**
	 * Parent task list.
	 *
	 * @var TaskList
	 */
	protected $task_list;

	/**
	 * Duration to milisecond mapping.
	 *
	 * @var string
	 */
	protected $duration_to_ms = array(
		'day'  => DAY_IN_SECONDS * 1000,
		'hour' => HOUR_IN_SECONDS * 1000,
		'week' => WEEK_IN_SECONDS * 1000,
	);

	/**
	 * Constructor
	 *
	 * @param TaskList|null $task_list Parent task list.
	 */
	public function __construct( $task_list = null ) {
		$this->task_list = $task_list;
	}

	/**
	 * ID.
	 *
	 * @return string
	 */
	abstract public function get_id();

	/**
	 * Title.
	 *
	 * @return string
	 */
	abstract public function get_title();

	/**
	 * Content.
	 *
	 * @return string
	 */
	abstract public function get_content();

	/**
	 * Time.
	 *
	 * @return string
	 */
	abstract public function get_time();

	/**
	 * Parent ID.
	 *
	 * @return string
	 */
	public function get_parent_id() {
		if ( ! $this->task_list ) {
			return '';
		}
		return $this->task_list->get_list_id();
	}

	/**
	 * Get task list options.
	 *
	 * @return array
	 */
	public function get_parent_options() {
		if ( ! $this->task_list ) {
			return array();
		}
		return $this->task_list->options;
	}

	/**
	 * Get custom option.
	 *
	 * @param string $option_name name of custom option.
	 * @return mixed|null
	 */
	public function get_parent_option( $option_name ) {
		if ( $this->task_list && isset( $this->task_list->options[ $option_name ] ) ) {
			return $this->task_list->options[ $option_name ];
		}
		return null;
	}


	/**
	 * Prefix event for track event naming.
	 *
	 * @param string $event_name Event name.
	 * @return string
	 */
	public function prefix_event( $event_name ) {
		if ( ! $this->task_list ) {
			return '';
		}
		return $this->task_list->prefix_event( $event_name );
	}

	/**
	 * Additional info.
	 *
	 * @return string
	 */
	public function get_additional_info() {
		return '';
	}

	/**
	 * Additional data.
	 *
	 * @return mixed
	 */
	public function get_additional_data() {
		return null;
	}

	/**
	 * Badge.
	 *
	 * @return string
	 */
	public function get_badge() {
		return '';
	}

	/**
	 * Level.
	 *
	 * @deprecated 7.2.0
	 *
	 * @return string
	 */
	public function get_level() {
		wc_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '7.2.0' );

		return 3;
	}

	/**
	 * Action label.
	 *
	 * @return string
	 */
	public function get_action_label() {
		return __( "Let's go", 'woocommerce' );
	}

	/**
	 * 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;
	}

	/**
	 * Bool for task dismissal.
	 *
	 * @return bool
	 */
	public function is_dismissed() {
		if ( ! $this->is_dismissable() ) {
			return false;
		}

		$dismissed = get_option( self::DISMISSED_OPTION, array() );

		return in_array( $this->get_id(), $dismissed, true );
	}

	/**
	 * Dismiss the task.
	 *
	 * @return bool
	 */
	public function dismiss() {
		if ( ! $this->is_dismissable() ) {
			return false;
		}

		$dismissed   = get_option( self::DISMISSED_OPTION, array() );
		$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->get_id() ) );
		}

		return $update;
	}

	/**
	 * Undo task dismissal.
	 *
	 * @return bool
	 */
	public function undo_dismiss() {
		$dismissed = get_option( self::DISMISSED_OPTION, array() );
		$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->get_id() ) );
		}

		return $update;
	}

	/**
	 * Check if a task is snoozeable.
	 *
	 * @deprecated 7.2.0
	 *
	 * @return bool
	 */
	public function is_snoozeable() {
		wc_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '7.2.0' );

		return false;
	}

	/**
	 * Get the snoozed until datetime.
	 *
	 * @deprecated 7.2.0
	 *
	 * @return string
	 */
	public function get_snoozed_until() {
		wc_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '7.2.0' );

		$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.
	 *
	 * @deprecated 7.2.0
	 *
	 * @return bool
	 */
	public function is_snoozed() {
		wc_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '7.2.0' );

		if ( ! $this->is_snoozeable() ) {
			return false;
		}

		$snoozed = get_option( self::SNOOZED_OPTION, array() );

		return isset( $snoozed[ $this->get_id() ] ) && $snoozed[ $this->get_id() ] > ( time() * 1000 );
	}

	/**
	 * Snooze the task.
	 *
	 * @param string $duration Duration to snooze. day|hour|week.
	 *
	 * @deprecated 7.2.0
	 *
	 * @return bool
	 */
	public function snooze( $duration = 'day' ) {
		wc_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '7.2.0' );

		if ( ! $this->is_snoozeable() ) {
			return false;
		}

		$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->get_id() ) );
			}
		}

		return $update;
	}

	/**
	 * Undo task snooze.
	 *
	 * @deprecated 7.2.0
	 *
	 * @return bool
	 */
	public function undo_snooze() {
		wc_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '7.2.0' );

		$snoozed = get_option( self::SNOOZED_OPTION, array() );
		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->get_id() ) );
		}

		return $update;
	}

	/**
	 * Check if a task list has previously been marked as complete.
	 *
	 * @return bool
	 */
	public function has_previously_completed() {
		$complete = get_option( self::COMPLETED_OPTION, array() );
		return in_array( $this->get_id(), $complete, true );
	}

	/**
	 * Track task completion if task is viewable.
	 */
	public function possibly_track_completion() {
		if ( ! $this->is_complete() ) {
			return;
		}

		if ( $this->has_previously_completed() ) {
			return;
		}

		$completed_tasks   = get_option( self::COMPLETED_OPTION, array() );
		$completed_tasks[] = $this->get_id();
		update_option( self::COMPLETED_OPTION, $completed_tasks );
		$this->record_tracks_event( 'task_completed', array( 'task_name' => $this->get_id() ) );
	}

	/**
	 * Set this as the active task across page loads.
	 */
	public function set_active() {
		if ( $this->is_complete() ) {
			return;
		}

		set_transient(
			self::ACTIVE_TASK_TRANSIENT,
			$this->get_id(),
			DAY_IN_SECONDS
		);
	}

	/**
	 * Check if this is the active task.
	 */
	public function is_active() {
		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 task is disabled.
	 *
	 * @deprecated 7.2.0
	 *
	 * @return bool
	 */
	public function is_disabled() {
		wc_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '7.2.0' );

		return false;
	}

	/**
	 * Check if the task is complete.
	 *
	 * @return bool
	 */
	public function is_complete() {
		return self::is_actioned();
	}

	/**
	 * Check if the task has been visited.
	 *
	 * @return bool
	 */
	public function is_visited() {
		$user_id       = get_current_user_id();
		$response      = WCAdminUser::get_user_data_field( $user_id, 'task_list_tracked_started_tasks' );
		$tracked_tasks = $response ? json_decode( $response, true ) : array();

		return isset( $tracked_tasks[ $this->get_id() ] ) && $tracked_tasks[ $this->get_id() ] > 0;
	}

	/**
	 * Check if should record event when task is viewed
	 *
	 * @return bool
	 */
	public function get_record_view_event(): bool {
		return false;
	}

	/**
	 * Get the task as JSON.
	 *
	 * @return array
	 */
	public function get_json() {
		$this->possibly_track_completion();

		return array(
			'id'              => $this->get_id(),
			'parentId'        => $this->get_parent_id(),
			'title'           => $this->get_title(),
			'badge'           => $this->get_badge(),
			'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'           => 3,
			'isActioned'      => $this->is_actioned(),
			'isDismissed'     => $this->is_dismissed(),
			'isDismissable'   => $this->is_dismissable(),
			'isSnoozed'       => false,
			'isSnoozeable'    => false,
			'isVisited'       => $this->is_visited(),
			'isDisabled'      => false,
			'snoozedUntil'    => null,
			'additionalData'  => self::convert_object_to_camelcase( $this->get_additional_data() ),
			'eventPrefix'     => $this->prefix_event( '' ),
			'recordViewEvent' => $this->get_record_view_event(),
		);
	}

	/**
	 * Convert object keys to camelcase.
	 *
	 * @param array $data Data to convert.
	 * @return object
	 */
	public static function convert_object_to_camelcase( $data ) {
		if ( ! is_array( $data ) ) {
			return $data;
		}

		$new_object = (object) array();

		foreach ( $data as $key => $value ) {
			$new_key              = lcfirst( implode( '', array_map( 'ucfirst', explode( '_', $key ) ) ) );
			$new_object->$new_key = $value;
		}

		return $new_object;
	}

	/**
	 * Mark a task as actioned.  Used to verify an action has taken place in some tasks.
	 *
	 * @return bool
	 */
	public function mark_actioned() {
		$actioned = get_option( self::ACTIONED_OPTION, array() );

		$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->get_id() ) );
		}

		return $update;
	}

	/**
	 * Check if a task has been actioned.
	 *
	 * @return bool
	 */
	public function is_actioned() {
		return self::is_task_actioned( $this->get_id() );
	}

	/**
	 * Check if a provided task ID has been actioned.
	 *
	 * @param string $id Task ID.
	 * @return bool
	 */
	public static function is_task_actioned( $id ) {
		$actioned = get_option( self::ACTIONED_OPTION, array() );
		return in_array( $id, $actioned, true );
	}

	/**
	 * Sorting function for tasks.
	 *
	 * @param Task  $a Task a.
	 * @param Task  $b Task b.
	 * @param array $sort_by list of columns with sort order.
	 * @return int
	 */
	public static function sort( $a, $b, $sort_by = array() ) {
		$result = 0;
		foreach ( $sort_by as $data ) {
			$key   = $data['key'];
			$a_val = $a->$key ?? false;
			$b_val = $b->$key ?? false;
			if ( 'asc' === $data['order'] ) {
				$result = $a_val <=> $b_val;
			} else {
				$result = $b_val <=> $a_val;
			}

			if ( 0 !== $result ) {
				break;
			}
		}
		return $result;
	}

}
TaskList.php000064400000022162151546372510007027 0ustar00<?php
/**
 * Handles storage and retrieval of a task list
 */

namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks;

use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
use Automattic\WooCommerce\Admin\WCAdminHelper;


/**
 * Task List class.
 */
class TaskList {
	/**
	 * Task traits.
	 */
	use TaskTraits;

	/**
	 * Option name hidden task lists.
	 */
	const HIDDEN_OPTION = 'woocommerce_task_list_hidden_lists';

	/**
	 * Option name of completed task lists.
	 */
	const COMPLETED_OPTION = 'woocommerce_task_list_completed_lists';

	/**
	 * Option name of hidden reminder bar.
	 */
	const REMINDER_BAR_HIDDEN_OPTION = 'woocommerce_task_list_reminder_bar_hidden';

	/**
	 * ID.
	 *
	 * @var string
	 */
	public $id = '';

	/**
	 * ID.
	 *
	 * @var string
	 */
	public $hidden_id = '';

	/**
	 * ID.
	 *
	 * @var boolean
	 */
	public $display_progress_header = false;

	/**
	 * Title.
	 *
	 * @var string
	 */
	public $title = '';

	/**
	 * Tasks.
	 *
	 * @var array
	 */
	public $tasks = array();

	/**
	 * Sort keys.
	 *
	 * @var array
	 */
	public $sort_by = array();

	/**
	 * Event prefix.
	 *
	 * @var string|null
	 */
	public $event_prefix = null;

	/**
	 * Task list visibility.
	 *
	 * @var boolean
	 */
	public $visible = true;

	/**
	 * Array of custom options.
	 *
	 * @var array
	 */
	public $options = array();

	/**
	 * Array of TaskListSection.
	 *
	 * @deprecated 7.2.0
	 *
	 * @var array
	 */
	private $sections = array();

	/**
	 * Key value map of task class and id used for sections.
	 *
	 * @deprecated 7.2.0
	 *
	 * @var array
	 */
	public $task_class_id_map = array();

	/**
	 * Constructor
	 *
	 * @param array $data Task list data.
	 */
	public function __construct( $data = array() ) {
		$defaults = array(
			'id'                      => null,
			'hidden_id'               => null,
			'title'                   => '',
			'tasks'                   => array(),
			'sort_by'                 => array(),
			'event_prefix'            => null,
			'options'                 => array(),
			'visible'                 => true,
			'display_progress_header' => false,
		);

		$data = wp_parse_args( $data, $defaults );

		$this->id                      = $data['id'];
		$this->hidden_id               = $data['hidden_id'];
		$this->title                   = $data['title'];
		$this->sort_by                 = $data['sort_by'];
		$this->event_prefix            = $data['event_prefix'];
		$this->options                 = $data['options'];
		$this->visible                 = $data['visible'];
		$this->display_progress_header = $data['display_progress_header'];

		foreach ( $data['tasks'] as $task_name ) {
			$class = 'Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks\\' . $task_name;
			$task  = new $class( $this );
			$this->add_task( $task );
		}

		$this->possibly_remove_reminder_bar();
	}

	/**
	 * Check if the task list is hidden.
	 *
	 * @return bool
	 */
	public function is_hidden() {
		$hidden = get_option( self::HIDDEN_OPTION, array() );
		return in_array( $this->hidden_id ? $this->hidden_id : $this->id, $hidden, true );
	}

	/**
	 * Check if the task list is visible.
	 *
	 * @return bool
	 */
	public function is_visible() {
		if ( ! $this->visible || ! count( $this->get_viewable_tasks() ) > 0 ) {
			return false;
		}
		return ! $this->is_hidden();
	}

	/**
	 * Hide the task list.
	 *
	 * @return bool
	 */
	public function hide() {
		if ( $this->is_hidden() ) {
			return;
		}

		$viewable_tasks  = $this->get_viewable_tasks();
		$completed_count = array_reduce(
			$viewable_tasks,
			function( $total, $task ) {
				return $task->is_complete() ? $total + 1 : $total;
			},
			0
		);

		$this->record_tracks_event(
			'completed',
			array(
				'action'                => 'remove_card',
				'completed_task_count'  => $completed_count,
				'incomplete_task_count' => count( $viewable_tasks ) - $completed_count,
			)
		);

		$hidden   = get_option( self::HIDDEN_OPTION, array() );
		$hidden[] = $this->hidden_id ? $this->hidden_id : $this->id;
		$this->maybe_set_default_layout( $hidden );
		return update_option( self::HIDDEN_OPTION, array_unique( $hidden ) );
	}

	/**
	 * Sets the default homepage layout to two_columns if "setup" tasklist is completed or hidden.
	 *
	 * @param array $completed_or_hidden_tasklist_ids Array of tasklist ids.
	 */
	public function maybe_set_default_layout( $completed_or_hidden_tasklist_ids ) {
		if ( in_array( 'setup', $completed_or_hidden_tasklist_ids, true ) ) {
			update_option( 'woocommerce_default_homepage_layout', 'two_columns' );
		}
	}

	/**
	 * Undo hiding of the task list.
	 *
	 * @return bool
	 */
	public function unhide() {
		$hidden = get_option( self::HIDDEN_OPTION, array() );
		$hidden = array_diff( $hidden, array( $this->hidden_id ? $this->hidden_id : $this->id ) );
		return update_option( self::HIDDEN_OPTION, $hidden );
	}

	/**
	 * Check if all viewable tasks are complete.
	 *
	 * @return bool
	 */
	public function is_complete() {
		foreach ( $this->get_viewable_tasks() as $viewable_task ) {
			if ( $viewable_task->is_complete() === false ) {
				return false;
			}
		}

		return true;
	}

	/**
	 * Check if a task list has previously been marked as complete.
	 *
	 * @return bool
	 */
	public function has_previously_completed() {
		$complete = get_option( self::COMPLETED_OPTION, array() );
		return in_array( $this->get_list_id(), $complete, true );
	}

	/**
	 * Add task to the task list.
	 *
	 * @param Task $task Task class.
	 */
	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' )
			);
		}
		if ( array_search( $task, $this->tasks, true ) ) {
			return;
		}

		$this->tasks[] = $task;
	}

	/**
	 * Get only visible tasks in list.
	 *
	 * @param string $task_id id of task.
	 * @return Task
	 */
	public function get_task( $task_id ) {
		return current(
			array_filter(
				$this->tasks,
				function( $task ) use ( $task_id ) {
					return $task->get_id() === $task_id;
				}
			)
		);
	}

	/**
	 * Get only visible tasks in list.
	 *
	 * @return array
	 */
	public function get_viewable_tasks() {
		return array_values(
			array_filter(
				$this->tasks,
				function( $task ) {
					return $task->can_view();
				}
			)
		);
	}

	/**
	 * Get task list sections.
	 *
	 * @deprecated 7.2.0
	 *
	 * @return array
	 */
	public function get_sections() {
		wc_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '7.2.0' );

		return $this->sections;
	}

	/**
	 * Track list completion of viewable tasks.
	 */
	public function possibly_track_completion() {
		if ( ! $this->is_complete() ) {
			return;
		}

		if ( $this->has_previously_completed() ) {
			return;
		}

		$completed_lists   = get_option( self::COMPLETED_OPTION, array() );
		$completed_lists[] = $this->get_list_id();
		update_option( self::COMPLETED_OPTION, $completed_lists );
		$this->maybe_set_default_layout( $completed_lists );
		$this->record_tracks_event( 'tasks_completed' );
	}

	/**
	 * Sorts the attached tasks array.
	 *
	 * @param array $sort_by list of columns with sort order.
	 * @return TaskList returns $this, for chaining.
	 */
	public function sort_tasks( $sort_by = array() ) {
		$sort_by = count( $sort_by ) > 0 ? $sort_by : $this->sort_by;
		if ( 0 !== count( $sort_by ) ) {
			usort(
				$this->tasks,
				function( $a, $b ) use ( $sort_by ) {
					return Task::sort( $a, $b, $sort_by );
				}
			);
		}
		return $this;
	}

	/**
	 * Prefix event for track event naming.
	 *
	 * @param string $event_name Event name.
	 * @return string
	 */
	public function prefix_event( $event_name ) {
		if ( null !== $this->event_prefix ) {
			return $this->event_prefix . $event_name;
		}
		return $this->get_list_id() . '_tasklist_' . $event_name;
	}

	/**
	 * Returns option to keep completed task list.
	 *
	 * @return string
	 */
	public function get_keep_completed_task_list() {
		return get_option( 'woocommerce_task_list_keep_completed', 'no' );
	}

	/**
	 * Remove reminder bar four weeks after store creation.
	 */
	public static function possibly_remove_reminder_bar() {
		$bar_hidden            = get_option( self::REMINDER_BAR_HIDDEN_OPTION, 'no' );
		$active_for_four_weeks = WCAdminHelper::is_wc_admin_active_for( WEEK_IN_SECONDS * 4 );

		if ( 'yes' === $bar_hidden || ! $active_for_four_weeks ) {
			return;
		}

		update_option( self::REMINDER_BAR_HIDDEN_OPTION, 'yes' );
	}

	/**
	 * Get the list for use in JSON.
	 *
	 * @return array
	 */
	public function get_json() {
		$this->possibly_track_completion();
		$tasks_json = array();
		foreach ( $this->tasks as $task ) {
			$json = $task->get_json();
			if ( $json['canView'] ) {
				$tasks_json[] = $json;
			}
		}

		return array(
			'id'                    => $this->get_list_id(),
			'title'                 => $this->title,
			'isHidden'              => $this->is_hidden(),
			'isVisible'             => $this->is_visible(),
			'isComplete'            => $this->is_complete(),
			'tasks'                 => $tasks_json,
			'eventPrefix'           => $this->prefix_event( '' ),
			'displayProgressHeader' => $this->display_progress_header,
			'keepCompletedTaskList' => $this->get_keep_completed_task_list(),
		);
	}
}
TaskListSection.php000064400000004466151546372510010363 0ustar00<?php
/**
 * Handles storage and retrieval of a task list section
 */

namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks;

/**
 * Task List section class.
 *
 * @deprecated 7.2.0
 */
class TaskListSection {

	/**
	 * Title.
	 *
	 * @var string
	 */
	public $id = '';

	/**
	 * Title.
	 *
	 * @var string
	 */
	public $title = '';

	/**
	 * Description.
	 *
	 * @var string
	 */
	public $description = '';

	/**
	 * Image.
	 *
	 * @var string
	 */
	public $image = '';

	/**
	 * Tasks.
	 *
	 * @var array
	 */
	public $task_names = array();

	/**
	 * Parent task list.
	 *
	 * @var TaskList
	 */
	protected $task_list;

	/**
	 * Constructor
	 *
	 * @param array         $data Task list data.
	 * @param TaskList|null $task_list Parent task list.
	 */
	public function __construct( $data = array(), $task_list = null ) {
		$defaults = array(
			'id'          => '',
			'title'       => '',
			'description' => '',
			'image'       => '',
			'tasks'       => array(),
		);

		$data = wp_parse_args( $data, $defaults );

		$this->task_list   = $task_list;
		$this->id          = $data['id'];
		$this->title       = $data['title'];
		$this->description = $data['description'];
		$this->image       = $data['image'];
		$this->task_names  = $data['task_names'];
	}

	/**
	 * Returns if section is complete.
	 *
	 * @return boolean;
	 */
	private function is_complete() {
		$complete = true;
		foreach ( $this->task_names as $task_name ) {
			if ( null !== $this->task_list && isset( $this->task_list->task_class_id_map[ $task_name ] ) ) {
				$task = $this->task_list->get_task( $this->task_list->task_class_id_map[ $task_name ] );
				if ( $task->can_view() && ! $task->is_complete() ) {
					$complete = false;
					break;
				}
			}
		}
		return $complete;
	}

	/**
	 * Get the list for use in JSON.
	 *
	 * @return array
	 */
	public function get_json() {
		return array(
			'id'          => $this->id,
			'title'       => $this->title,
			'description' => $this->description,
			'image'       => $this->image,
			'tasks'       => array_map(
				function( $task_name ) {
					if ( null !== $this->task_list && isset( $this->task_list->task_class_id_map[ $task_name ] ) ) {
						return $this->task_list->task_class_id_map[ $task_name ];
					}
					return '';
				},
				$this->task_names
			),
			'isComplete'  => $this->is_complete(),
		);
	}
}
TaskLists.php000064400000025177151546372510007223 0ustar00<?php
/**
 * Handles storage and retrieval of task lists
 */

namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks;

use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\DeprecatedExtendedTask;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks\ReviewShippingOptions;
/**
 * Task Lists class.
 */
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;

	/**
	 * The contents of this array is used in init_tasks() to run their init() methods.
	 * If the classes do not have an init() method then nothing is executed.
	 * Beyond that, adding tasks to this list has no effect, see init_default_lists() for the list of tasks.
	 * that are added for each task list.
	 *
	 * @var array
	 */
	const DEFAULT_TASKS = array(
		'StoreDetails',
		'Products',
		'WooCommercePayments',
		'Payments',
		'Tax',
		'Shipping',
		'Marketing',
		'Appearance',
		'AdditionalPayments',
		'ReviewShippingOptions',
		'GetMobileApp',
	);

	/**
	 * 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() {
		$tasks = array(
			'CustomizeStore',
			'StoreDetails',
			'Products',
			'Appearance',
			'WooCommercePayments',
			'Payments',
			'Tax',
			'Shipping',
			'Marketing',
		);

		if ( Features::is_enabled( 'core-profiler' ) ) {
			$key = array_search( 'StoreDetails', $tasks, true );
			if ( false !== $key ) {
				unset( $tasks[ $key ] );
			}
		}

		// Remove the old Personalize your store task if the new CustomizeStore is enabled.
		$task_to_remove                 = Features::is_enabled( 'customize-store' ) ? 'Appearance' : 'CustomizeStore';
		$store_customisation_task_index = array_search( $task_to_remove, $tasks, true );

		if ( false !== $store_customisation_task_index ) {
			unset( $tasks[ $store_customisation_task_index ] );
		}

		self::add_list(
			array(
				'id'                      => 'setup',
				'title'                   => __( 'Get ready to start selling', 'woocommerce' ),
				'tasks'                   => $tasks,
				'display_progress_header' => true,
				'event_prefix'            => 'tasklist_',
				'options'                 => array(
					'use_completed_title' => true,
				),
				'visible'                 => true,
			)
		);

		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',
					'GetMobileApp',
				),
			)
		);

		if ( Features::is_enabled( 'shipping-smart-defaults' ) ) {
			self::add_task(
				'extended',
				new ReviewShippingOptions(
					self::get_list( 'extended' )
				)
			);

			// Tasklist that will never be shown in homescreen,
			// used for having tasks that are accessed by other means.
			self::add_list(
				array(
					'id'           => 'secret_tasklist',
					'hidden_id'    => 'setup',
					'tasks'        => array(
						'ExperimentalShippingRecommendation',
					),
					'event_prefix' => 'secret_tasklist_',
					'visible'      => false,
				)
			);
		}

		if ( has_filter( 'woocommerce_admin_experimental_onboarding_tasklists' ) ) {
			/**
			 * Filter to override default task lists.
			 *
			 * @since 7.4
			 * @param array     $lists Array of tasklists.
			 */
			self::$lists = apply_filters( 'woocommerce_admin_experimental_onboarding_tasklists', self::$lists );
		}
	}

	/**
	 * 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 necessary.
	 * 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 Task   $task Task object.
	 *
	 * @return \WP_Error|Task
	 */
	public static function add_task( $list_id, $task ) {
		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( $task );
	}

	/**
	 * 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() {
		$setup_list = self::get_list( 'setup' );

		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 woocommerce-task-list-remaining-tasks-badge"><span class="count-' . esc_attr( $tasks_count ) . '">' . absint( $tasks_count ) . '</span></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;
	}
}
TaskTraits.php000064400000001713151546372510007361 0ustar00<?php
/**
 * Task and TaskList Traits
 */

namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks;

defined( 'ABSPATH' ) || exit;

/**
 * TaskTraits class.
 */
trait TaskTraits {
	/**
	 * Record a tracks event with the prefixed event name.
	 *
	 * @param string $event_name Event name.
	 * @param array  $args Array of tracks arguments.
	 * @return string Prefixed event name.
	 */
	public function record_tracks_event( $event_name, $args = array() ) {
		if ( ! $this->get_list_id() ) {
			return;
		}

		$prefixed_event_name = $this->prefix_event( $event_name );

		wc_admin_record_tracks_event(
			$prefixed_event_name,
			$args
		);

		return $prefixed_event_name;
	}

	/**
	 * Get the task list ID.
	 *
	 * @return string
	 */
	public function get_list_id() {
		$namespaced_class = get_class( $this );
		return is_subclass_of( $namespaced_class, 'Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task' )
			? $this->get_parent_id()
			: $this->id;
	}
}
Tasks/AdditionalPayments.php000064400000011066151546372510012150 0ustar00<?php


namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;

use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks\Payments;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks\WooCommercePayments;
use Automattic\WooCommerce\Admin\Features\PaymentGatewaySuggestions\Init;

/**
 * Payments Task
 */
class AdditionalPayments extends Payments {

	/**
	 * Used to cache is_complete() method result.
	 *
	 * @var null
	 */
	private $is_complete_result = null;

	/**
	 * Used to cache can_view() method result.
	 *
	 * @var null
	 */
	private $can_view_result = null;


	/**
	 * ID.
	 *
	 * @return string
	 */
	public function get_id() {
		return 'payments';
	}

	/**
	 * Title.
	 *
	 * @return string
	 */
	public function get_title() {
		return __(
			'Set up additional payment options',
			'woocommerce'
		);
	}

	/**
	 * Content.
	 *
	 * @return string
	 */
	public function get_content() {
		return __(
			'Choose payment providers and enable payment methods at checkout.',
			'woocommerce'
		);
	}

	/**
	 * Time.
	 *
	 * @return string
	 */
	public function get_time() {
		return __( '2 minutes', 'woocommerce' );
	}

	/**
	 * Task completion.
	 *
	 * @return bool
	 */
	public function is_complete() {
		if ( null === $this->is_complete_result ) {
			$this->is_complete_result = self::has_enabled_additional_gateways();
		}

		return $this->is_complete_result;
	}

	/**
	 * Task visibility.
	 *
	 * @return bool
	 */
	public function can_view() {
		if ( ! Features::is_enabled( 'payment-gateway-suggestions' ) ) {
			// Hide task if feature not enabled.
			return false;
		}

		if ( null !== $this->can_view_result ) {
			return $this->can_view_result;
		}

		// Show task if woocommerce-payments is connected or if there are any suggested gateways in other category enabled.
		$this->can_view_result = (
			WooCommercePayments::is_connected() ||
			self::has_enabled_other_category_gateways()
		);

		// Early return if task is not visible.
		if ( ! $this->can_view_result ) {
			return false;
		}

		// Show task if there are any suggested gateways in additional category.
		$this->can_view_result = ! empty( self::get_suggestion_gateways( 'category_additional' ) );

		return $this->can_view_result;
	}


	/**
	 * Check if the store has any enabled gateways in other category.
	 *
	 * @return bool
	 */
	private static function has_enabled_other_category_gateways() {
		$other_gateways     = self::get_suggestion_gateways( 'category_other' );
		$other_gateways_ids = wp_list_pluck( $other_gateways, 'id' );

		return self::has_enabled_gateways(
			function( $gateway ) use ( $other_gateways_ids ) {
				return in_array( $gateway->id, $other_gateways_ids, true );
			}
		);
	}

	/**
	 * Check if the store has any enabled gateways in additional category.
	 *
	 * @return bool
	 */
	private static function has_enabled_additional_gateways() {
		$additional_gateways     = self::get_suggestion_gateways( 'category_additional' );
		$additional_gateways_ids = wp_list_pluck( $additional_gateways, 'id' );

		return self::has_enabled_gateways(
			function( $gateway ) use ( $additional_gateways_ids ) {
				return 'yes' === $gateway->enabled
				&& in_array( $gateway->id, $additional_gateways_ids, true );
			}
		);
	}

	/**
	 * Check if the store has any enabled gateways based on the given criteria.
	 *
	 * @param callable|null $filter A callback function to filter the gateways.
	 * @return bool
	 */
	private static function has_enabled_gateways( $filter = null ) {
		$gateways         = WC()->payment_gateways->get_available_payment_gateways();
		$enabled_gateways = array_filter(
			$gateways,
			function( $gateway ) use ( $filter ) {
				if ( is_callable( $filter ) ) {
					return 'yes' === $gateway->enabled && call_user_func( $filter, $gateway );
				} else {
					return 'yes' === $gateway->enabled;
				}
			}
		);

		return ! empty( $enabled_gateways );
	}

	/**
	 * Get the list of gateways to suggest.
	 *
	 * @param string $filter_by Filter by category. "category_additional" or "category_other".
	 *
	 * @return array
	 */
	private static function get_suggestion_gateways( $filter_by = 'category_additional' ) {
		$country            = wc_get_base_location()['country'];
		$plugin_suggestions = Init::get_suggestions();
		$plugin_suggestions = array_filter(
			$plugin_suggestions,
			function( $plugin ) use ( $country, $filter_by ) {
				if ( ! isset( $plugin->{$filter_by} ) || ! isset( $plugin->plugins[0] ) ) {
					return false;
				}
				return in_array( $country, $plugin->{$filter_by}, true );
			}
		);
		return $plugin_suggestions;
	}
}
Tasks/Appearance.php000064400000002513151546372510010413 0ustar00<?php

namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;

use Automattic\WooCommerce\Admin\PageController;
use Automattic\WooCommerce\Internal\Admin\Loader;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks\Products;
use Automattic\WooCommerce\Internal\Admin\WCAdminAssets;

/**
 * Appearance Task
 */
class Appearance extends Task {

	/**
	 * Constructor.
	 */
	public function __construct() {
		if ( ! $this->is_complete() ) {
			add_action( 'load-theme-install.php', array( $this, 'mark_actioned' ) );
		}
	}

	/**
	 * ID.
	 *
	 * @return string
	 */
	public function get_id() {
		return 'appearance';
	}

	/**
	 * Title.
	 *
	 * @return string
	 */
	public function get_title() {
		return __( 'Choose your theme', 'woocommerce' );
	}

	/**
	 * Content.
	 *
	 * @return string
	 */
	public function get_content() {
		return __(
			"Choose a theme that best fits your brand's look and feel, then make it your own. Change the colors, add your logo, and create pages.",
			'woocommerce'
		);
	}

	/**
	 * Time.
	 *
	 * @return string
	 */
	public function get_time() {
		return __( '2 minutes', 'woocommerce' );
	}

	/**
	 * Action label.
	 *
	 * @return string
	 */
	public function get_action_label() {
		return __( 'Choose theme', 'woocommerce' );
	}
}
Tasks/CustomizeStore.php000064400000013237151546372510011360 0ustar00<?php

namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;

use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
use Jetpack_Gutenberg;

/**
 * Customize Your Store Task
 */
class CustomizeStore extends Task {
	/**
	 * Constructor
	 *
	 * @param TaskList $task_list Parent task list.
	 */
	public function __construct( $task_list ) {
		parent::__construct( $task_list );

		add_action( 'admin_enqueue_scripts', array( $this, 'possibly_add_site_editor_scripts' ) );
		add_action( 'after_switch_theme', array( $this, 'mark_task_as_complete' ) );
	}

	/**
	 * ID.
	 *
	 * @return string
	 */
	public function get_id() {
		return 'customize-store';
	}

	/**
	 * Title.
	 *
	 * @return string
	 */
	public function get_title() {
		return __( 'Customize your store ', 'woocommerce' );
	}

	/**
	 * Content.
	 *
	 * @return string
	 */
	public function get_content() {
		return '';
	}

	/**
	 * Time.
	 *
	 * @return string
	 */
	public function get_time() {
		return '';
	}

	/**
	 * Task completion.
	 *
	 * @return bool
	 */
	public function is_complete() {
		return get_option( 'woocommerce_admin_customize_store_completed' ) === 'yes';
	}

	/**
	 * Task visibility.
	 *
	 * @return bool
	 */
	public function can_view() {
		return true;
	}

	/**
	 * Possibly add site editor scripts.
	 */
	public function possibly_add_site_editor_scripts() {
		$is_customize_store_pages = (
			isset( $_GET['page'] ) &&
			'wc-admin' === $_GET['page'] &&
			isset( $_GET['path'] ) &&
			str_starts_with( wc_clean( wp_unslash( $_GET['path'] ) ), '/customize-store' )
		);
		if ( ! $is_customize_store_pages ) {
			return;
		}

		// See: https://github.com/WordPress/WordPress/blob/master/wp-admin/site-editor.php.
		if ( ! wp_is_block_theme() ) {
			wp_die( esc_html__( 'The theme you are currently using is not compatible.', 'woocommerce' ) );
		}
		global $editor_styles;

		// Flag that we're loading the block editor.
		$current_screen = get_current_screen();
		$current_screen->is_block_editor( true );

		// Default to is-fullscreen-mode to avoid jumps in the UI.
		add_filter(
			'admin_body_class',
			static function( $classes ) {
				return "$classes is-fullscreen-mode";
			}
		);

		$block_editor_context   = new \WP_Block_Editor_Context( array( 'name' => 'core/edit-site' ) );
		$indexed_template_types = array();
		foreach ( get_default_block_template_types() as $slug => $template_type ) {
			$template_type['slug']    = (string) $slug;
			$indexed_template_types[] = $template_type;
		}

		$custom_settings = array(
			'siteUrl'                   => site_url(),
			'postsPerPage'              => get_option( 'posts_per_page' ),
			'styles'                    => get_block_editor_theme_styles(),
			'defaultTemplateTypes'      => $indexed_template_types,
			'defaultTemplatePartAreas'  => get_allowed_block_template_part_areas(),
			'supportsLayout'            => wp_theme_has_theme_json(),
			'supportsTemplatePartsMode' => ! wp_is_block_theme() && current_theme_supports( 'block-template-parts' ),
		);

		// Add additional back-compat patterns registered by `current_screen` et al.
		$custom_settings['__experimentalAdditionalBlockPatterns']          = \WP_Block_Patterns_Registry::get_instance()->get_all_registered( true );
		$custom_settings['__experimentalAdditionalBlockPatternCategories'] = \WP_Block_Pattern_Categories_Registry::get_instance()->get_all_registered( true );

		$editor_settings         = get_block_editor_settings( $custom_settings, $block_editor_context );
		$active_global_styles_id = \WP_Theme_JSON_Resolver::get_user_global_styles_post_id();
		$active_theme            = get_stylesheet();
		$preload_paths           = array(
			array( '/wp/v2/media', 'OPTIONS' ),
			'/wp/v2/types?context=view',
			'/wp/v2/types/wp_template?context=edit',
			'/wp/v2/types/wp_template-part?context=edit',
			'/wp/v2/templates?context=edit&per_page=-1',
			'/wp/v2/template-parts?context=edit&per_page=-1',
			'/wp/v2/themes?context=edit&status=active',
			'/wp/v2/global-styles/' . $active_global_styles_id . '?context=edit',
			'/wp/v2/global-styles/' . $active_global_styles_id,
			'/wp/v2/global-styles/themes/' . $active_theme,
		);

		block_editor_rest_api_preload( $preload_paths, $block_editor_context );

		wp_add_inline_script(
			'wp-blocks',
			sprintf(
				'window.wcBlockSettings = %s;',
				wp_json_encode( $editor_settings )
			)
		);

		// Preload server-registered block schemas.
		wp_add_inline_script(
			'wp-blocks',
			'wp.blocks.unstable__bootstrapServerSideBlockDefinitions(' . wp_json_encode( get_block_editor_server_block_settings() ) . ');'
		);

		wp_add_inline_script(
			'wp-blocks',
			sprintf( 'wp.blocks.setCategories( %s );', wp_json_encode( isset( $editor_settings['blockCategories'] ) ? $editor_settings['blockCategories'] : array() ) ),
			'after'
		);

		wp_enqueue_script( 'wp-editor' );
		wp_enqueue_script( 'wp-format-library' ); // Not sure if this is needed.
		wp_enqueue_script( 'wp-router' );
		wp_enqueue_style( 'wp-editor' );
		wp_enqueue_style( 'wp-edit-site' );
		wp_enqueue_style( 'wp-format-library' );
		wp_enqueue_media();

		if (
				current_theme_supports( 'wp-block-styles' ) &&
				( ! is_array( $editor_styles ) || count( $editor_styles ) === 0 )
			) {
			wp_enqueue_style( 'wp-block-library-theme' );
		}
		/** This action is documented in wp-admin/edit-form-blocks.php
		 *
		 * @since 8.0.3
		*/
		do_action( 'enqueue_block_editor_assets' );

		// Load Jetpack's block editor assets because they are not enqueued by default.
		if ( class_exists( 'Jetpack_Gutenberg' ) ) {
			Jetpack_Gutenberg::enqueue_block_editor_assets();
		}
	}

	/**
	 * Mark task as complete.
	 */
	public function mark_task_as_complete() {
		update_option( 'woocommerce_admin_customize_store_completed', 'yes' );
	}
}
Tasks/ExperimentalShippingRecommendation.php000064400000003216151546372510015401 0ustar00<?php

namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;

use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
use Automattic\WooCommerce\Admin\PluginsHelper;

/**
 * Shipping Task
 */
class ExperimentalShippingRecommendation extends Task {
	/**
	 * ID.
	 *
	 * @return string
	 */
	public function get_id() {
		return 'shipping-recommendation';
	}

	/**
	 * Title.
	 *
	 * @return string
	 */
	public function get_title() {
		return __( 'Set up shipping', 'woocommerce' );
	}

	/**
	 * Content.
	 *
	 * @return string
	 */
	public function get_content() {
		return '';
	}

	/**
	 * Time.
	 *
	 * @return string
	 */
	public function get_time() {
		return '';
	}

	/**
	 * Task completion.
	 *
	 * @return bool
	 */
	public function is_complete() {
		return self::has_plugins_active() && self::has_jetpack_connected();
	}

	/**
	 * Task visibility.
	 *
	 * @return bool
	 */
	public function can_view() {
		return Features::is_enabled( 'shipping-smart-defaults' );
	}

	/**
	 * Action URL.
	 *
	 * @return string
	 */
	public function get_action_url() {
		return '';
	}

	/**
	 * Check if the store has any shipping zones.
	 *
	 * @return bool
	 */
	public static function has_plugins_active() {
		return PluginsHelper::is_plugin_active( 'woocommerce-services' ) &&
		PluginsHelper::is_plugin_active( 'jetpack' );
	}

	/**
	 * Check if the Jetpack is connected.
	 *
	 * @return bool
	 */
	public static function has_jetpack_connected() {
		if ( class_exists( '\Jetpack' ) && is_callable( '\Jetpack::is_connection_ready' ) ) {
			return \Jetpack::is_connection_ready();
		}
		return false;
	}
}
Tasks/GetMobileApp.php000064400000005014151546372510010663 0ustar00<?php

namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;

use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
use Automattic\Jetpack\Connection\Manager; // https://github.com/Automattic/jetpack/blob/trunk/projects/packages/connection/src/class-manager.php .

/**
 * Get Mobile App Task
 */
class GetMobileApp extends Task {
	/**
	 * ID.
	 *
	 * @return string
	 */
	public function get_id() {
		return 'get-mobile-app';
	}

	/**
	 * Title.
	 *
	 * @return string
	 */
	public function get_title() {
		return __( 'Get the free WooCommerce mobile app', 'woocommerce' );
	}

	/**
	 * Content.
	 *
	 * @return string
	 */
	public function get_content() {
		return '';
	}

	/**
	 * Time.
	 *
	 * @return string
	 */
	public function get_time() {
		return '';
	}

	/**
	 * Task completion.
	 *
	 * @return bool
	 */
	public function is_complete() {
		return get_option( 'woocommerce_admin_dismissed_mobile_app_modal' ) === 'yes';
	}

	/**
	 * Task visibility.
	 * Can view under these conditions:
	 *  - Jetpack is installed and connected && current site user has a wordpress.com account connected to jetpack
	 *  - Jetpack is not connected && current user is capable of installing plugins
	 *
	 * @return bool
	 */
	public function can_view() {
		$jetpack_can_be_installed                        = current_user_can( 'manage_woocommerce' ) && current_user_can( 'install_plugins' ) && ! self::is_jetpack_connected();
		$jetpack_is_installed_and_current_user_connected = self::is_current_user_connected();

		return $jetpack_can_be_installed || $jetpack_is_installed_and_current_user_connected;
	}

	/**
	 * Determines if site has any users connected to WordPress.com via JetPack
	 *
	 * @return bool
	 */
	private static function is_jetpack_connected() {
		if ( class_exists( '\Automattic\Jetpack\Connection\Manager' ) && method_exists( '\Automattic\Jetpack\Connection\Manager', 'is_active' ) ) {
			$connection = new Manager();
			return $connection->is_active();
		}
		return false;
	}

	/**
	 * Determines if the current user is connected to Jetpack.
	 *
	 * @return bool
	 */
	private static function is_current_user_connected() {
		if ( class_exists( '\Automattic\Jetpack\Connection\Manager' ) && method_exists( '\Automattic\Jetpack\Connection\Manager', 'is_user_connected' ) ) {
			$connection = new Manager();
			return $connection->is_connection_owner();
		}
		return false;
	}

	/**
	 * Action URL.
	 *
	 * @return string
	 */
	public function get_action_url() {
		return admin_url( 'admin.php?page=wc-admin&mobileAppModal=true' );
	}
}
Tasks/Marketing.php000064400000004736151546372510010306 0ustar00<?php

namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;

use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
use Automattic\WooCommerce\Internal\Admin\RemoteFreeExtensions\Init as RemoteFreeExtensions;

/**
 * Marketing Task
 */
class Marketing extends Task {
	/**
	 * ID.
	 *
	 * @return string
	 */
	public function get_id() {
		return 'marketing';
	}

	/**
	 * Title.
	 *
	 * @return string
	 */
	public function get_title() {
		if ( true === $this->get_parent_option( 'use_completed_title' ) ) {
			if ( $this->is_complete() ) {
				return __( 'You added sales channels', 'woocommerce' );
			}
			return __( 'Get more sales', 'woocommerce' );
		}
		return __( 'Set up marketing tools', 'woocommerce' );
	}

	/**
	 * Content.
	 *
	 * @return string
	 */
	public function get_content() {
		return __(
			'Add recommended marketing tools to reach new customers and grow your business',
			'woocommerce'
		);
	}

	/**
	 * Time.
	 *
	 * @return string
	 */
	public function get_time() {
		return __( '2 minutes', 'woocommerce' );
	}

	/**
	 * 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.
	 *
	 * @return array
	 */
	public static function get_plugins() {
		$bundles = RemoteFreeExtensions::get_extensions(
			array(
				'task-list/reach',
				'task-list/grow',
			)
		);

		return array_reduce(
			$bundles,
			function( $plugins, $bundle ) {
				$visible = array();
				foreach ( $bundle['plugins'] as $plugin ) {
					if ( $plugin->is_visible ) {
						$visible[] = $plugin;
					}
				}
				return array_merge( $plugins, $visible );
			},
			array()
		);
	}

	/**
	 * Check if the store has installed marketing extensions.
	 *
	 * @return bool
	 */
	public static function has_installed_extensions() {
		$plugins   = self::get_plugins();
		$remaining = array();
		$installed = array();

		foreach ( $plugins as $plugin ) {
			if ( ! $plugin->is_installed ) {
				$remaining[] = $plugin;
			} else {
				$installed[] = $plugin;
			}
		}

		// Make sure the task has been actioned and a marketing extension has been installed.
		if ( count( $installed ) > 0 && Task::is_task_actioned( 'marketing' ) ) {
			return true;
		}

		return false;
	}
}
Tasks/Payments.php000064400000003746151546372510010165 0ustar00<?php

namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;

use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;

/**
 * Payments Task
 */
class Payments extends Task {

	/**
	 * Used to cache is_complete() method result.
	 * @var null
	 */
	private $is_complete_result = null;

	/**
	 * ID.
	 *
	 * @return string
	 */
	public function get_id() {
		return 'payments';
	}

	/**
	 * Title.
	 *
	 * @return string
	 */
	public function get_title() {
		if ( true === $this->get_parent_option( 'use_completed_title' ) ) {
			if ( $this->is_complete() ) {
				return __( 'You set up payments', 'woocommerce' );
			}
			return __( 'Set up payments', 'woocommerce' );
		}
		return __( 'Set up payments', 'woocommerce' );
	}

	/**
	 * Content.
	 *
	 * @return string
	 */
	public function get_content() {
		return __(
			'Choose payment providers and enable payment methods at checkout.',
			'woocommerce'
		);
	}

	/**
	 * Time.
	 *
	 * @return string
	 */
	public function get_time() {
		return __( '2 minutes', 'woocommerce' );
	}

	/**
	 * Task completion.
	 *
	 * @return bool
	 */
	public function is_complete() {
		if ( $this->is_complete_result === null ) {
			$this->is_complete_result = self::has_gateways();
		}

		return $this->is_complete_result;
	}

	/**
	 * Task visibility.
	 *
	 * @return bool
	 */
	public function can_view() {
		$woocommerce_payments = $this->task_list->get_task( 'woocommerce-payments' );
		return Features::is_enabled( 'payment-gateway-suggestions' ) && ! $woocommerce_payments->can_view();
	}

	/**
	 * Check if the store has any enabled gateways.
	 *
	 * @return bool
	 */
	public static function has_gateways() {
		$gateways         = WC()->payment_gateways->get_available_payment_gateways();
		$enabled_gateways = array_filter(
			$gateways,
			function( $gateway ) {
				return 'yes' === $gateway->enabled && 'woocommerce_payments' !== $gateway->id;
			}
		);

		return ! empty( $enabled_gateways );
	}
}
Tasks/Products.php000064400000007634151546372510010170 0ustar00<?php

namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;

use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
use Automattic\WooCommerce\Internal\Admin\WCAdminAssets;

/**
 * Products Task
 */
class Products extends Task {

	/**
	 * Constructor
	 *
	 * @param TaskList $task_list Parent task list.
	 */
	public function __construct( $task_list ) {
		parent::__construct( $task_list );
		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' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'possibly_add_load_sample_return_notice_script' ) );
	}

	/**
	 * ID.
	 *
	 * @return string
	 */
	public function get_id() {
		return 'products';
	}

	/**
	 * Title.
	 *
	 * @return string
	 */
	public function get_title() {
		if ( $this->get_parent_option( 'use_completed_title' ) === true ) {
			if ( $this->is_complete() ) {
				return __( 'You added products', 'woocommerce' );
			}
			return __( 'Add products', 'woocommerce' );
		}
		return __( 'Add my products', 'woocommerce' );
	}

	/**
	 * 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'
		);
	}

	/**
	 * Time.
	 *
	 * @return string
	 */
	public function get_time() {
		return __( '1 minute per product', 'woocommerce' );
	}

	/**
	 * 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 function possibly_add_manual_return_notice_script( $hook ) {
		global $post;
		if ( $hook !== 'post.php' || $post->post_type !== 'product' ) {
			return;
		}

		if ( ! $this->is_active() || ! $this->is_complete() ) {
			return;
		}

		WCAdminAssets::register_script( 'wp-admin-scripts', 'onboarding-product-notice', true );

		// Clear the active task transient to only show notice once per active session.
		delete_transient( self::ACTIVE_TASK_TRANSIENT );
	}

	/**
	 * Adds a return to task list notice when completing the import product task.
	 *
	 * @param string $hook Page hook.
	 */
	public function possibly_add_import_return_notice_script( $hook ) {
		$step = isset( $_GET['step'] ) ? $_GET['step'] : ''; // phpcs:ignore csrf ok, sanitization ok.

		if ( $hook !== 'product_page_product_importer' || $step !== 'done' ) {
			return;
		}

		if ( ! $this->is_active() || $this->is_complete() ) {
			return;
		}

		WCAdminAssets::register_script( 'wp-admin-scripts', 'onboarding-product-import-notice', true );
	}

	/**
	 * Adds a return to task list notice when completing the loading sample products action.
	 *
	 * @param string $hook Page hook.
	 */
	public function possibly_add_load_sample_return_notice_script( $hook ) {
		if ( $hook !== 'edit.php' || get_query_var( 'post_type' ) !== 'product' ) {
			return;
		}

		$referer = wp_get_referer();
		if ( ! $referer || strpos( $referer, wc_admin_url() ) !== 0 ) {
			return;
		}

		if ( ! isset( $_GET[ Task::ACTIVE_TASK_TRANSIENT ] ) ) {
			return;
		}

		$task_id = sanitize_title_with_dashes( wp_unslash( $_GET[ Task::ACTIVE_TASK_TRANSIENT ] ) );
		if ( $task_id !== $this->get_id() || ! $this->is_complete() ) {
			return;
		}

		WCAdminAssets::register_script( 'wp-admin-scripts', 'onboarding-load-sample-products-notice', true );
	}

	/**
	 * Check if the store has any published products.
	 *
	 * @return bool
	 */
	public static function has_products() {
		$counts = wp_count_posts('product');
		return isset( $counts->publish ) && $counts->publish > 0;
	}
}
Tasks/Purchase.php000064400000012127151546372510010130 0ustar00<?php

namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;

use Automattic\WooCommerce\Internal\Admin\Onboarding\OnboardingProducts;
use Automattic\WooCommerce\Internal\Admin\Onboarding\OnboardingThemes;
use Automattic\WooCommerce\Internal\Admin\Onboarding\OnboardingProfile;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;

/**
 * Purchase Task
 */
class Purchase extends Task {
	/**
	 * Constructor
	 *
	 * @param TaskList $task_list Parent task list.
	 */
	public function __construct( $task_list ) {
		parent::__construct( $task_list );
		add_action( 'update_option_woocommerce_onboarding_profile', array( $this, 'clear_dismissal' ), 10, 2 );
	}

	/**
	 * Clear dismissal on onboarding product type changes.
	 *
	 * @param array $old_value Old value.
	 * @param array $new_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();

		if ( empty( array_diff( $product_types, $previous_product_types ) ) ) {
			return;
		}

		$this->undo_dismiss();
	}

	/**
	 * Get the task arguments.
	 * ID.
	 *
	 * @return string
	 */
	public function get_id() {
		return 'purchase';
	}

	/**
	 * Title.
	 *
	 * @return string
	 */
	public function get_title() {
		$products   = $this->get_paid_products_and_themes();
		$first_product    = count( $products['purchaseable'] ) >= 1 ? $products['purchaseable'][0] : false;

		if ( ! $first_product ) {
			return null;
		}

		$product_label    = isset( $first_product['label'] ) ? $first_product['label'] : $first_product['title'];
		$additional_count = count( $products['purchaseable'] ) - 1;

		if ( $this->get_parent_option( 'use_completed_title' ) && $this->is_complete() ) {
			return count( $products['purchaseable'] ) === 1
				? sprintf(
					/* translators: %1$s: a purchased product name */
					__(
						'You added %1$s',
						'woocommerce'
					),
					$product_label
				)
				: sprintf(
					/* translators: %1$s: a purchased product name, %2$d the number of other products purchased */
					_n(
						'You added %1$s and %2$d other product',
						'You added %1$s and %2$d other products',
						$additional_count,
						'woocommerce'
					),
					$product_label,
					$additional_count
				);
		}

		return count( $products['purchaseable'] ) === 1
			? sprintf(
				/* translators: %1$s: a purchaseable product name */
				__(
					'Add %s to my store',
					'woocommerce'
				),
				$product_label
			)
			: sprintf(
				/* translators: %1$s: a purchaseable product name, %2$d the number of other products to purchase */
				_n(
					'Add %1$s and %2$d more product to my store',
					'Add %1$s and %2$d more products to my store',
					$additional_count,
					'woocommerce'
				),
				$product_label,
				$additional_count
			);
	}

	/**
	 * Content.
	 *
	 * @return string
	 */
	public function get_content() {
		$products = $this->get_paid_products_and_themes();

		if ( count( $products['remaining'] ) === 1 ) {
			return isset( $products['purchaseable'][0]['description'] ) ? $products['purchaseable'][0]['description'] : $products['purchaseable'][0]['excerpt'];
		}
		return 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'
			),
			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' );
	}


	/**
	 * Time.
	 *
	 * @return string
	 */
	public function get_time() {
		return __( '2 minutes', 'woocommerce' );
	}

	/**
	 * Task completion.
	 *
	 * @return bool
	 */
	public function is_complete() {
		$products = $this->get_paid_products_and_themes();
		return count( $products['remaining'] ) === 0;
	}

	/**
	 * Dismissable.
	 *
	 * @return bool
	 */
	public function is_dismissable() {
		return true;
	}

	/**
	 * Task visibility.
	 *
	 * @return bool
	 */
	public function can_view() {
		$products = $this->get_paid_products_and_themes();
		return count( $products['purchaseable'] ) > 0;
	}

	/**
	 * Get purchaseable and remaining products.
	 *
	 * @return array purchaseable and remaining products and themes.
	 */
	public static function get_paid_products_and_themes() {
		$relevant_products = OnboardingProducts::get_relevant_products();

		$profiler_data = get_option( OnboardingProfile::DATA_OPTION, array() );
		$theme         = isset( $profiler_data['theme'] ) ? $profiler_data['theme'] : null;
		$paid_theme    = $theme ? OnboardingThemes::get_paid_theme_by_slug( $theme ) : null;
		if ( $paid_theme ) {

			$relevant_products['purchaseable'][] = $paid_theme;

			if ( isset( $paid_theme['is_installed'] ) && false === $paid_theme['is_installed'] ) {
				$relevant_products['remaining'][] = $paid_theme['title'];
			}
		}
		return $relevant_products;
	}
}
Tasks/ReviewShippingOptions.php000064400000002177151546372510012701 0ustar00<?php

namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;

use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;

/**
 * Review Shipping Options Task
 */
class ReviewShippingOptions extends Task {
	/**
	 * ID.
	 *
	 * @return string
	 */
	public function get_id() {
		return 'review-shipping';
	}

	/**
	 * Title.
	 *
	 * @return string
	 */
	public function get_title() {
		return __( 'Review shipping options', 'woocommerce' );
	}

	/**
	 * Content.
	 *
	 * @return string
	 */
	public function get_content() {
		return '';
	}

	/**
	 * Time.
	 *
	 * @return string
	 */
	public function get_time() {
		return '';
	}

	/**
	 * Task completion.
	 *
	 * @return bool
	 */
	public function is_complete() {
		return get_option( 'woocommerce_admin_reviewed_default_shipping_zones' ) === 'yes';
	}

	/**
	 * Task visibility.
	 *
	 * @return bool
	 */
	public function can_view() {
		return get_option( 'woocommerce_admin_created_default_shipping_zones' ) === 'yes';
	}

	/**
	 * Action URL.
	 *
	 * @return string
	 */
	public function get_action_url() {
		return admin_url( 'admin.php?page=wc-settings&tab=shipping' );
	}
}
Tasks/Shipping.php000064400000012244151546372510010137 0ustar00<?php

namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;

use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Internal\Admin\Onboarding\OnboardingProfile;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
use WC_Data_Store;

/**
 * Shipping Task
 */
class Shipping extends Task {

	const ZONE_COUNT_TRANSIENT_NAME = 'woocommerce_shipping_task_zone_count_transient';

	/**
	 * Constructor
	 *
	 * @param TaskList $task_list Parent task list.
	 */
	public function __construct( $task_list = null ) {
		parent::__construct( $task_list );
		// wp_ajax_woocommerce_shipping_zone_methods_save_changes
		// and wp_ajax_woocommerce_shipping_zones_save_changes get fired
		// when a new zone is added or an existing one has been changed.
		add_action( 'wp_ajax_woocommerce_shipping_zones_save_changes', array( __CLASS__, 'delete_zone_count_transient' ), 9 );
		add_action( 'wp_ajax_woocommerce_shipping_zone_methods_save_changes', array( __CLASS__, 'delete_zone_count_transient' ), 9 );
		add_action( 'woocommerce_shipping_zone_method_added', array( __CLASS__, 'delete_zone_count_transient' ), 9 );
		add_action( 'woocommerce_after_shipping_zone_object_save', array( __CLASS__, 'delete_zone_count_transient' ), 9 );
	}

	/**
	 * ID.
	 *
	 * @return string
	 */
	public function get_id() {
		return 'shipping';
	}

	/**
	 * Title.
	 *
	 * @return string
	 */
	public function get_title() {
		if ( true === $this->get_parent_option( 'use_completed_title' ) ) {
			if ( $this->is_complete() ) {
				return __( 'You added shipping costs', 'woocommerce' );
			}
			return __( 'Add shipping costs', 'woocommerce' );
		}
		return __( 'Set up shipping', 'woocommerce' );
	}

	/**
	 * Content.
	 *
	 * @return string
	 */
	public function get_content() {
		return __(
			"Set your store location and where you'll ship to.",
			'woocommerce'
		);
	}

	/**
	 * Time.
	 *
	 * @return string
	 */
	public function get_time() {
		return __( '1 minute', 'woocommerce' );
	}

	/**
	 * Task completion.
	 *
	 * @return bool
	 */
	public function is_complete() {
		return self::has_shipping_zones();
	}

	/**
	 * Task visibility.
	 *
	 * @return bool
	 */
	public function can_view() {
		if ( Features::is_enabled( 'shipping-smart-defaults' ) ) {
			if ( 'yes' === get_option( 'woocommerce_admin_created_default_shipping_zones' ) ) {
				// If the user has already created a default shipping zone, we don't need to show the task.
				return false;
			}

			/**
			 * Do not display the task when:
			 * - The store sells digital products only
			 * Display the task when:
			 * - We don't know where the store's located
			 * - The store is located in the UK, Australia or Canada
			*/

			if ( self::is_selling_digital_type_only() ) {
				return false;
			}

			$default_store_country = wc_format_country_state_string( get_option( 'woocommerce_default_country', '' ) )['country'];

			// Check if a store address is set so that we don't default to WooCommerce's default country US.
			// Similar logic: https://github.com/woocommerce/woocommerce/blob/059d542394b48468587f252dcb6941c6425cd8d3/plugins/woocommerce-admin/client/profile-wizard/steps/store-details/index.js#L511-L516.
			$store_country = '';
			if ( ! empty( get_option( 'woocommerce_store_address', '' ) ) || 'US' !== $default_store_country ) {
				$store_country = $default_store_country;
			}

			// Unknown country.
			if ( empty( $store_country ) ) {
				return true;
			}

			return in_array( $store_country, array( 'CA', 'AU', 'GB', 'ES', 'IT', 'DE', 'FR', 'MX', 'CO', 'CL', 'AR', 'PE', 'BR', 'UY', 'GT', 'NL', 'AT', 'BE' ), true );
		}

		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.
	 *
	 * @return bool
	 */
	public static function has_shipping_zones() {
		$zone_count = get_transient( self::ZONE_COUNT_TRANSIENT_NAME );
		if ( false !== $zone_count ) {
			return (int) $zone_count > 0;
		}

		$zone_count = count( WC_Data_Store::load( 'shipping-zone' )->get_zones() );
		set_transient( self::ZONE_COUNT_TRANSIENT_NAME, $zone_count );

		return $zone_count > 0;
	}

	/**
	 * Check if the store has physical products.
	 *
	 * @return bool
	 */
	public static function has_physical_products() {
		$profiler_data = get_option( OnboardingProfile::DATA_OPTION, array() );
		$product_types = isset( $profiler_data['product_types'] ) ? $profiler_data['product_types'] : array();

		return in_array( 'physical', $product_types, true );
	}

	/**
	 * Delete the zone count transient used in has_shipping_zones() method
	 * to refresh the cache.
	 */
	public static function delete_zone_count_transient() {
		delete_transient( self::ZONE_COUNT_TRANSIENT_NAME );
	}

	/**
	 * Check if the store sells digital products only.
	 *
	 * @return bool
	 */
	private static function is_selling_digital_type_only() {
		$profiler_data = get_option( OnboardingProfile::DATA_OPTION, array() );
		$product_types = isset( $profiler_data['product_types'] ) ? $profiler_data['product_types'] : array();

		return array( 'downloads' ) === $product_types;
	}
}
Tasks/StoreCreation.php000064400000002044151546372510011134 0ustar00<?php

namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;

use Automattic\WooCommerce\Admin\Features\Onboarding;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;

/**
 * Store Details Task
 */
class StoreCreation extends Task {

	/**
	 * ID.
	 *
	 * @return string
	 */
	public function get_id() {
		return 'store_creation';
	}

	/**
	 * Title.
	 *
	 * @return string
	 */
	public function get_title() {
		/* translators: Store name */
		return sprintf( __( 'You created %s', 'woocommerce' ), get_bloginfo( 'name' ) );
	}

	/**
	 * Content.
	 *
	 * @return string
	 */
	public function get_content() {
		return '';
	}

	/**
	 * Time.
	 *
	 * @return string
	 */
	public function get_time() {
		return '';
	}

	/**
	 * Time.
	 *
	 * @return string
	 */
	public function get_action_url() {
		return '';
	}

	/**
	 * Task completion.
	 *
	 * @return bool
	 */
	public function is_complete() {
		return true;
	}

	/**
	 * Check if task is disabled.
	 *
	 * @return bool
	 */
	public function is_disabled() {
		return true;
	}
}

Tasks/StoreDetails.php000064400000004207151546372510010760 0ustar00<?php

namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;

use Automattic\WooCommerce\Internal\Admin\Onboarding\OnboardingProfile;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;

/**
 * Store Details Task
 */
class StoreDetails extends Task {
	/**
	 * ID.
	 *
	 * @return string
	 */
	public function get_id() {
		return 'store_details';
	}

	/**
	 * Title.
	 *
	 * @return string
	 */
	public function get_title() {
		if ( true === $this->get_parent_option( 'use_completed_title' ) ) {
			if ( $this->is_complete() ) {
				return __( 'You added store details', 'woocommerce' );
			}
			return __( 'Add store details', 'woocommerce' );
		}
		return __( 'Store details', 'woocommerce' );
	}

	/**
	 * 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'
		);
	}

	/**
	 * Time.
	 *
	 * @return string
	 */
	public function get_time() {
		return __( '4 minutes', 'woocommerce' );
	}

	/**
	 * Time.
	 *
	 * @return string
	 */
	public function get_action_url() {
		return ! $this->is_complete() ? admin_url( 'admin.php?page=wc-settings&tab=general&tutorial=true' ) : admin_url( 'admin.php?page=wc-settings&tab=general' );
	}

	/**
	 * Task completion.
	 *
	 * @return bool
	 */
	public function is_complete() {
		$country        = WC()->countries->get_base_country();
		$country_locale = WC()->countries->get_country_locale();
		$locale         = $country_locale[ $country ] ?? array();

		$hide_postcode = $locale['postcode']['hidden'] ?? false;
		// If postcode is hidden, just check that the store address and city are set.
		if ( $hide_postcode ) {
			return get_option( 'woocommerce_store_address', '' ) !== '' && get_option( 'woocommerce_store_city', '' ) !== '';
		}

		// Mark as completed if the store address, city and postcode are set. We don't need to check the country because it's set by default.
		return get_option( 'woocommerce_store_address', '' ) !== '' && get_option( 'woocommerce_store_city', '' ) !== '' &&
		get_option( 'woocommerce_store_postcode', '' ) !== '';
	}
}
Tasks/Tax.php000064400000010045151546372510007107 0ustar00<?php

namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;

use Automattic\WooCommerce\Admin\API\Reports\Taxes\Stats\DataStore as TaxDataStore;
use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
use Automattic\WooCommerce\Admin\PluginsHelper;
use Automattic\WooCommerce\Internal\Admin\WCAdminAssets;

/**
 * Tax Task
 */
class Tax extends Task {

	/**
	 * Used to cache is_complete() method result.
	 * @var null
	 */
	private $is_complete_result = null;

	/**
	 * Constructor
	 *
	 * @param TaskList $task_list Parent task list.
	 */
	public function __construct( $task_list ) {
		parent::__construct( $task_list );
		add_action( 'admin_enqueue_scripts', array( $this, 'possibly_add_return_notice_script' ) );
	}

	/**
	 * Adds a return to task list notice when completing the 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 ( $page !== 'wc-settings' || $tab !== 'tax' ) {
			return;
		}

		if ( ! $this->is_active() || $this->is_complete() ) {
			return;
		}

		WCAdminAssets::register_script( 'wp-admin-scripts', 'onboarding-tax-notice', true );
	}

	/**
	 * ID.
	 *
	 * @return string
	 */
	public function get_id() {
		return 'tax';
	}

	/**
	 * Title.
	 *
	 * @return string
	 */
	public function get_title() {
		if ( $this->get_parent_option( 'use_completed_title' ) === true ) {
			if ( $this->is_complete() ) {
				return __( 'You added tax rates', 'woocommerce' );
			}
			return __( 'Add tax rates', 'woocommerce' );
		}
		return __( 'Set up tax rates', 'woocommerce' );
	}

	/**
	 * 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'
			)
			: __(
				'Set your store location and configure tax rate settings.',
				'woocommerce'
			);
	}

	/**
	 * Time.
	 *
	 * @return string
	 */
	public function get_time() {
		return __( '1 minute', 'woocommerce' );
	}

	/**
	 * Action label.
	 *
	 * @return string
	 */
	public function get_action_label() {
		return self::can_use_automated_taxes()
			? __( 'Yes please', 'woocommerce' )
			: __( "Let's go", 'woocommerce' );
	}

	/**
	 * Task completion.
	 *
	 * @return bool
	 */
	public function is_complete() {
		if ( $this->is_complete_result === null ) {
			$wc_connect_taxes_enabled = get_option( 'wc_connect_taxes_enabled' );
			$is_wc_connect_taxes_enabled = ( $wc_connect_taxes_enabled === 'yes' ) || ( $wc_connect_taxes_enabled === true ); // seems that in some places boolean is used, and other places 'yes' | 'no' is used

			$this->is_complete_result = $is_wc_connect_taxes_enabled ||
				count( TaxDataStore::get_taxes( array() ) ) > 0 ||
				get_option( 'woocommerce_no_sales_tax' ) !== false;
		}

		return $this->is_complete_result;
	}

	/**
	 * Addtional data.
	 *
	 * @return array
	 */
	public function get_additional_data() {
		return array(
			'avalara_activated'         => PluginsHelper::is_plugin_active( 'woocommerce-avatax' ),
			'tax_jar_activated'         => class_exists( 'WC_Taxjar' ),
			'woocommerce_tax_countries' => self::get_automated_support_countries(),
		);
	}

	/**
	 * Check if the store has any enabled gateways.
	 *
	 * @return bool
	 */
	public static function can_use_automated_taxes() {
		if ( ! class_exists( 'WC_Taxjar' ) ) {
			return false;
		}

		return in_array( WC()->countries->get_base_country(), self::get_automated_support_countries(), true );
	}

	/**
	 * Get an array of countries that support automated tax.
	 *
	 * @return array
	 */
	public static function get_automated_support_countries() {
		// https://developers.taxjar.com/api/reference/#countries .
		$tax_supported_countries = array_merge(
			array( 'US', 'CA', 'AU', 'GB' ),
			WC()->countries->get_european_union_countries()
		);

		return $tax_supported_countries;
	}
}
Tasks/TourInAppMarketplace.php000064400000002277151546372510012415 0ustar00<?php

namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;

use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;

/**
 * Tour In-App Marketplace task
 */
class TourInAppMarketplace extends Task {
	/**
	 * ID.
	 *
	 * @return string
	 */
	public function get_id() {
		return 'tour-in-app-marketplace';
	}

	/**
	 * Title.
	 *
	 * @return string
	 */
	public function get_title() {
		return __(
			'Discover ways of extending your store with a tour of the Woo Marketplace',
			'woocommerce'
		);
	}

	/**
	 * Content.
	 *
	 * @return string
	 */
	public function get_content() {
		return '';
	}

	/**
	 * Time.
	 *
	 * @return string
	 */
	public function get_time() {
		return '';
	}

	/**
	 * Task completion.
	 *
	 * @return bool
	 */
	public function is_complete() {
		return get_option( 'woocommerce_admin_dismissed_in_app_marketplace_tour' ) === 'yes';
	}

	/**
	 * Action URL.
	 *
	 * @return string
	 */
	public function get_action_url() {
		return admin_url( 'admin.php?page=wc-admin&path=%2Fextensions&tutorial=true' );
	}

	/**
	 * Check if should record event when task is viewed
	 *
	 * @return bool
	 */
	public function get_record_view_event(): bool {
		return true;
	}
}
Tasks/WooCommercePayments.php000064400000011433151546372510012315 0ustar00<?php

namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;

use Automattic\WooCommerce\Internal\Admin\Onboarding\OnboardingProfile;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
use Automattic\WooCommerce\Admin\PluginsHelper;
use Automattic\WooCommerce\Admin\Features\PaymentGatewaySuggestions\Init as Suggestions;
use Automattic\WooCommerce\Internal\Admin\WCPayPromotion\Init as WCPayPromotionInit;

/**
 * WooCommercePayments Task
 */
class WooCommercePayments extends Task {
	/**
	 * Used to cache is_complete() method result.
	 *
	 * @var null
	 */
	private $is_complete_result = null;

	/**
	 * ID.
	 *
	 * @return string
	 */
	public function get_id() {
		return 'woocommerce-payments';
	}

	/**
	 * Title.
	 *
	 * @return string
	 */
	public function get_title() {
		return __( 'Set up WooPayments', 'woocommerce' );
	}

	/**
	 * Badge.
	 *
	 * @return string
	 */
	public function get_badge() {
		/**
		 * Filter WooPayments onboarding task badge.
		 *
		 * @param string     $badge    Badge content.
		 * @since 8.2.0
		 */
		return apply_filters( 'woocommerce_admin_woopayments_onboarding_task_badge', '' );
	}

	/**
	 * 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 WooPayments.",
			'woocommerce'
		);
	}

	/**
	 * Time.
	 *
	 * @return string
	 */
	public function get_time() {
		return __( '2 minutes', 'woocommerce' );
	}

	/**
	 * Action label.
	 *
	 * @return string
	 */
	public function get_action_label() {
		return __( 'Finish setup', 'woocommerce' );
	}

	/**
	 * Additional info.
	 *
	 * @return string
	 */
	public function get_additional_info() {
		if ( WCPayPromotionInit::is_woopay_eligible() ) {
			return __(
				'By using WooPayments you agree to be bound by our <a href="https://wordpress.com/tos/" target="_blank">Terms of Service</a> (including WooPay <a href="https://wordpress.com/tos/#more-woopay-specifically" target="_blank">merchant terms</a>) and acknowledge that you have read our <a href="https://automattic.com/privacy/" target="_blank">Privacy Policy</a>',
				'woocommerce'
			);
		}

		return __(
			'By using WooPayments you agree to be bound by our <a href="https://wordpress.com/tos/" target="_blank">Terms of Service</a> and acknowledge that you have read our <a href="https://automattic.com/privacy/" target="_blank">Privacy Policy</a>',
			'woocommerce'
		);
	}

	/**
	 * Task completion.
	 *
	 * @return bool
	 */
	public function is_complete() {
		if ( null === $this->is_complete_result ) {
			$this->is_complete_result = self::is_connected();
		}

		return $this->is_complete_result;
	}

	/**
	 * Task visibility.
	 *
	 * @return bool
	 */
	public function can_view() {
		$payments = $this->task_list->get_task( 'payments' );

		return ! $payments->is_complete() && // Do not re-display the task if the "add payments" task has already been completed.
			self::is_installed() &&
			self::is_supported();
	}

	/**
	 * Check if the plugin was requested during onboarding.
	 *
	 * @return bool
	 */
	public static function is_requested() {
		$profiler_data       = get_option( OnboardingProfile::DATA_OPTION, array() );
		$product_types       = isset( $profiler_data['product_types'] ) ? $profiler_data['product_types'] : array();
		$business_extensions = isset( $profiler_data['business_extensions'] ) ? $profiler_data['business_extensions'] : array();

		$subscriptions_and_us = in_array( 'subscriptions', $product_types, true ) && 'US' === WC()->countries->get_base_country();
		return in_array( 'woocommerce-payments', $business_extensions, true ) || $subscriptions_and_us;
	}

	/**
	 * Check if the plugin is installed.
	 *
	 * @return bool
	 */
	public static function is_installed() {
		$installed_plugins = PluginsHelper::get_installed_plugin_slugs();
		return in_array( 'woocommerce-payments', $installed_plugins, true );
	}

	/**
	 * Check if WooCommerce Payments is connected.
	 *
	 * @return bool
	 */
	public static function is_connected() {
		if ( class_exists( '\WC_Payments' ) ) {
			$wc_payments_gateway = \WC_Payments::get_gateway();
			return method_exists( $wc_payments_gateway, 'is_connected' )
				? $wc_payments_gateway->is_connected()
				: false;
		}

		return false;
	}

	/**
	 * Check if the store is in a supported country.
	 *
	 * @return bool
	 */
	public static function is_supported() {
		$suggestions              = Suggestions::get_suggestions();
		$suggestion_plugins       = array_merge(
			...array_filter(
				array_column( $suggestions, 'plugins' ),
				function( $plugins ) {
					return is_array( $plugins );
				}
			)
		);
		$woocommerce_payments_ids = array_search( 'woocommerce-payments', $suggestion_plugins, true );
		if ( false !== $woocommerce_payments_ids ) {
			return true;
		}
		return false;
	}
}