From 1ff28fd174414478f57cec8864646485cafa9c74 Mon Sep 17 00:00:00 2001 From: Vlad Olaru Date: Fri, 20 Sep 2024 15:53:10 +0300 Subject: [PATCH] Update Payments menu item display and linking behavior (#51541) * Minor cleanup * refact: Rename must_be_visible to is_incentive_visible for clarity * refact: Rename register_payments_welcome_page to register_menu_and_page for clarity * Don't show the incentive page if the user can't manage WC * Introduce menu item when no incentive * Don't recommend additional gateways when WCPay is present * Render gateway suggestions on the WCPay task page, also * Add changelog entry * Remove short array syntax * Lint fixes * Simplify Payments task view logic * Simplify WooPayments task view logic * Improve WooPayments task complete logic * WooPayments can't be connected or onboarded if it is not active * refact: Rename private static method * Improve logic to determine the Payments task slug by factoring in the extended task list also * docs: Add details about our use of the Payments task logic * Add type hint * Do not recommend offline methods when WooPayments is supported * On suggestion enablement redirect to the same task page * Lint fixes * test: Fix unit tests * Maintain deprecated navigation logic --- .../fills/PaymentGatewaySuggestions/index.js | 22 +- .../task-lists/fills/woocommerce-payments.tsx | 51 ++-- .../changelog/update-51111-payments-menu-item | 5 + .../Tasks/AdditionalPayments.php | 4 +- .../OnboardingTasks/Tasks/Payments.php | 13 +- .../Tasks/WooCommercePayments.php | 45 +++- .../Admin/Notes/PaymentsMoreInfoNeeded.php | 4 +- .../Admin/Notes/PaymentsRemindMeLater.php | 4 +- .../src/Internal/Admin/WcPayWelcomePage.php | 223 +++++++++++++----- .../tasks/woocommerce-payments.php | 9 +- 10 files changed, 249 insertions(+), 131 deletions(-) create mode 100644 plugins/woocommerce/changelog/update-51111-payments-menu-item diff --git a/plugins/woocommerce-admin/client/task-lists/fills/PaymentGatewaySuggestions/index.js b/plugins/woocommerce-admin/client/task-lists/fills/PaymentGatewaySuggestions/index.js index 1b6752f98b1..5beacca652f 100644 --- a/plugins/woocommerce-admin/client/task-lists/fills/PaymentGatewaySuggestions/index.js +++ b/plugins/woocommerce-admin/client/task-lists/fills/PaymentGatewaySuggestions/index.js @@ -13,7 +13,7 @@ import { recordEvent } from '@woocommerce/tracks'; import { useMemo, useCallback, useEffect } from '@wordpress/element'; import { registerPlugin } from '@wordpress/plugins'; import { WooOnboardingTask } from '@woocommerce/onboarding'; -import { getNewPath } from '@woocommerce/navigation'; +import { getNewPath, getQuery } from '@woocommerce/navigation'; import { Button } from '@wordpress/components'; import ExternalIcon from 'gridicons/dist/external'; @@ -91,11 +91,15 @@ export const PaymentGatewaySuggestions = ( { onComplete, query } ) => { // gateway variable doesn't have hasPlugins property. ! paymentGateways.get( id )?.hasPlugins ? { - redirectPath: getNewPath( - { task: 'payments' }, - {}, - '/' - ), + // If we are already on a task page, don't redirect. + // Otherwise, redirect to Payments task page. + redirectPath: getQuery()?.task + ? getNewPath( + { task: getQuery().task }, + {}, + '/' + ) + : getNewPath( { task: 'payments' }, {}, '/' ), } : {} ); @@ -245,7 +249,8 @@ export const PaymentGatewaySuggestions = ( { onComplete, query } ) => { { const offlineSection = !! offlineGateways.length && ( diff --git a/plugins/woocommerce-admin/client/task-lists/fills/woocommerce-payments.tsx b/plugins/woocommerce-admin/client/task-lists/fills/woocommerce-payments.tsx index 336c60e0cc8..004ceee6921 100644 --- a/plugins/woocommerce-admin/client/task-lists/fills/woocommerce-payments.tsx +++ b/plugins/woocommerce-admin/client/task-lists/fills/woocommerce-payments.tsx @@ -1,7 +1,7 @@ /** * External dependencies */ -import React, { useEffect } from 'react'; +import React from 'react'; import { registerPlugin } from '@wordpress/plugins'; import { WooOnboardingTaskListItem, @@ -9,12 +9,12 @@ import { } from '@woocommerce/onboarding'; import { PLUGINS_STORE_NAME } from '@woocommerce/data'; import { useDispatch } from '@wordpress/data'; -import { Spinner } from '@woocommerce/components'; /** * Internal dependencies */ import { installActivateAndConnectWcpay } from './PaymentGatewaySuggestions/components/WCPay'; +import { PaymentGatewaySuggestions } from './PaymentGatewaySuggestions'; const WoocommercePaymentsTaskItem = () => { const { installAndActivatePlugins } = useDispatch( PLUGINS_STORE_NAME ); @@ -52,42 +52,21 @@ registerPlugin( 'woocommerce-admin-task-wcpay', { render: WoocommercePaymentsTaskItem, } ); -const ReadyWcPay = () => { - const { installAndActivatePlugins } = useDispatch( PLUGINS_STORE_NAME ); - const { createNotice } = useDispatch( 'core/notices' ); - - useEffect( () => { - new Promise( ( resolve, reject ) => { - return installActivateAndConnectWcpay( - reject, - createNotice, - installAndActivatePlugins - ); - } ); - }, [ createNotice, installAndActivatePlugins ] ); - - return ( -
- -
- Preparing payment settings... -
-
- ); -}; - -// shows up at http://host/wp-admin/admin.php?page=wc-admin&task=woocommerce-payments which is the default url for woocommerce-payments task +// Shows up at http://host/wp-admin/admin.php?page=wc-admin&task=woocommerce-payments which is the default url for woocommerce-payments task const WoocommercePaymentsTaskPage = () => ( - + { ( { + onComplete, + query, + }: { + onComplete: () => void; + query: { id: string }; + } ) => ( + + ) } ); diff --git a/plugins/woocommerce/changelog/update-51111-payments-menu-item b/plugins/woocommerce/changelog/update-51111-payments-menu-item new file mode 100644 index 00000000000..80de5edcf45 --- /dev/null +++ b/plugins/woocommerce/changelog/update-51111-payments-menu-item @@ -0,0 +1,5 @@ +Significance: patch +Type: update +Comment: Detach the Payment menu item and page from an active incentive. + + diff --git a/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/AdditionalPayments.php b/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/AdditionalPayments.php index f5cdd68fedd..548313c5786 100644 --- a/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/AdditionalPayments.php +++ b/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/AdditionalPayments.php @@ -4,8 +4,6 @@ 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; /** @@ -98,7 +96,7 @@ class AdditionalPayments extends Payments { return $this->can_view_result; } - // Show task if woocommerce-payments is connected or if there are any suggested gateways in other category enabled. + // Show task if WooPayments 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() diff --git a/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/Payments.php b/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/Payments.php index 27166aeaf25..574b684baa0 100644 --- a/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/Payments.php +++ b/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/Payments.php @@ -76,13 +76,13 @@ class Payments extends Task { * @return bool */ public function can_view() { - $woocommerce_payments = $this->task_list->get_task( 'woocommerce-payments' ); - // Make sure the task is mutually exclusive with the WooPayments task. - return Features::is_enabled( 'payment-gateway-suggestions' ) && ! $woocommerce_payments->can_view(); + // The task is visible if WooPayments is not supported in the current store location country. + // Otherwise, the WooPayments task will be shown. + return Features::is_enabled( 'payment-gateway-suggestions' ) && ! WooCommercePayments::is_supported(); } /** - * Check if the store has any enabled gateways, other than WooPayments. + * Check if the store has any enabled gateways. * * @return bool */ @@ -91,8 +91,7 @@ class Payments extends Task { $enabled_gateways = array_filter( $gateways, function( $gateway ) { - // Filter out any WooPayments gateways as this task is mutually exclusive with the WooPayments task. - return 'yes' === $gateway->enabled && 0 !== strpos( $gateway->id, 'woocommerce_payments' ); + return 'yes' === $gateway->enabled; } ); @@ -117,7 +116,7 @@ class Payments extends Task { } // Check if there is an active WooPayments incentive via the welcome page. - if ( WcPayWelcomePage::instance()->must_be_visible() ) { + if ( WcPayWelcomePage::instance()->is_incentive_visible() ) { // Point to the WooPayments welcome page. return add_query_arg( 'from', 'WCADMIN_PAYMENT_TASK', admin_url( 'admin.php?page=wc-admin&path=/wc-pay-welcome-page' ) ); } diff --git a/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/WooCommercePayments.php b/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/WooCommercePayments.php index 64f7cf1b4e7..b5ca8bc21df 100644 --- a/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/WooCommercePayments.php +++ b/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/WooCommercePayments.php @@ -105,7 +105,9 @@ class WooCommercePayments extends Task { */ public function is_complete() { if ( null === $this->is_complete_result ) { - $this->is_complete_result = self::is_connected() && ! self::is_account_partially_onboarded(); + // This task is complete if there are other ecommerce gateways enabled (offline payment methods are excluded), + // or if WooPayments is active and has a connected, fully onboarded account. + $this->is_complete_result = self::has_other_ecommerce_gateways() || ( self::is_connected() && ! self::is_account_partially_onboarded() ); } return $this->is_complete_result; @@ -117,10 +119,7 @@ class WooCommercePayments extends Task { * @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 general "Payments" task has already been completed. - self::is_supported(); + return self::is_supported(); } /** @@ -162,7 +161,11 @@ class WooCommercePayments extends Task { * @return bool */ public static function is_connected() { - $wc_payments_gateway = self::get_woo_payments_gateway(); + if ( ! self::is_wcpay_active() ) { + return false; + } + + $wc_payments_gateway = self::get_gateway(); if ( $wc_payments_gateway && method_exists( $wc_payments_gateway, 'is_connected' ) ) { return $wc_payments_gateway->is_connected(); } @@ -177,7 +180,11 @@ class WooCommercePayments extends Task { * @return bool */ public static function is_account_partially_onboarded() { - $wc_payments_gateway = self::get_woo_payments_gateway(); + if ( ! self::is_wcpay_active() ) { + return false; + } + + $wc_payments_gateway = self::get_gateway(); if ( $wc_payments_gateway && method_exists( $wc_payments_gateway, 'is_account_partially_onboarded' ) ) { return $wc_payments_gateway->is_account_partially_onboarded(); } @@ -212,11 +219,33 @@ class WooCommercePayments extends Task { * * @return \WC_Payments|null */ - private static function get_woo_payments_gateway() { + private static function get_gateway() { $payment_gateways = WC()->payment_gateways->payment_gateways(); if ( isset( $payment_gateways['woocommerce_payments'] ) ) { return $payment_gateways['woocommerce_payments']; } return null; } + + /** + * Check if the store has any enabled ecommerce gateways, other than WooPayments. + * + * We exclude offline payment methods from this check. + * + * @return bool + */ + public static function has_other_ecommerce_gateways(): bool { + $gateways = WC()->payment_gateways->get_available_payment_gateways(); + $enabled_gateways = array_filter( + $gateways, + function ( $gateway ) { + // Filter out any WooPayments-related or offline gateways. + return 'yes' === $gateway->enabled + && 0 !== strpos( $gateway->id, 'woocommerce_payments' ) + && ! in_array( $gateway->id, array( 'bacs', 'cheque', 'cod' ), true ); + } + ); + + return ! empty( $enabled_gateways ); + } } diff --git a/plugins/woocommerce/src/Internal/Admin/Notes/PaymentsMoreInfoNeeded.php b/plugins/woocommerce/src/Internal/Admin/Notes/PaymentsMoreInfoNeeded.php index 2cdf60498a9..15103391f11 100644 --- a/plugins/woocommerce/src/Internal/Admin/Notes/PaymentsMoreInfoNeeded.php +++ b/plugins/woocommerce/src/Internal/Admin/Notes/PaymentsMoreInfoNeeded.php @@ -38,8 +38,8 @@ class PaymentsMoreInfoNeeded { * @return bool */ public static function should_display_note() { - // WCPay welcome page must not be visible. - if ( WcPayWelcomePage::instance()->must_be_visible() ) { + // WooPayments incentive must not be visible. + if ( WcPayWelcomePage::instance()->is_incentive_visible() ) { return false; } diff --git a/plugins/woocommerce/src/Internal/Admin/Notes/PaymentsRemindMeLater.php b/plugins/woocommerce/src/Internal/Admin/Notes/PaymentsRemindMeLater.php index 459e82a0567..01f5998add8 100644 --- a/plugins/woocommerce/src/Internal/Admin/Notes/PaymentsRemindMeLater.php +++ b/plugins/woocommerce/src/Internal/Admin/Notes/PaymentsRemindMeLater.php @@ -38,8 +38,8 @@ class PaymentsRemindMeLater { * @return bool */ public static function should_display_note() { - // WCPay welcome page must be visible. - if ( ! WcPayWelcomePage::instance()->must_be_visible() ) { + // WooPayments incentive must be visible. + if ( ! WcPayWelcomePage::instance()->is_incentive_visible() ) { return false; } diff --git a/plugins/woocommerce/src/Internal/Admin/WcPayWelcomePage.php b/plugins/woocommerce/src/Internal/Admin/WcPayWelcomePage.php index 446c336d9b1..99666f6d479 100644 --- a/plugins/woocommerce/src/Internal/Admin/WcPayWelcomePage.php +++ b/plugins/woocommerce/src/Internal/Admin/WcPayWelcomePage.php @@ -2,6 +2,8 @@ namespace Automattic\WooCommerce\Internal\Admin; +use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task; +use Automattic\WooCommerce\Admin\Features\OnboardingTasks\TaskLists; use Automattic\WooCommerce\Admin\WCAdminHelper; use Automattic\WooCommerce\Admin\PageController; use WC_Abstract_Order; @@ -43,7 +45,7 @@ class WcPayWelcomePage { * WCPayWelcomePage constructor. */ public function __construct() { - add_action( 'admin_menu', array( $this, 'register_payments_welcome_page' ) ); + add_action( 'admin_menu', array( $this, 'register_menu_and_page' ) ); add_filter( 'woocommerce_admin_shared_settings', array( $this, 'shared_settings' ) ); add_filter( 'woocommerce_admin_allowed_promo_notes', array( $this, 'allowed_promo_notes' ) ); add_filter( 'woocommerce_admin_woopayments_onboarding_task_badge', array( $this, 'onboarding_task_badge' ) ); @@ -51,18 +53,23 @@ class WcPayWelcomePage { } /** - * Whether the WooPayments welcome page should be visible. + * Whether the WooPayments incentive should be visible. * * @param bool $skip_wcpay_active Whether to skip the check for the WooPayments plugin being active. * * @return boolean */ - public function must_be_visible( $skip_wcpay_active = false ): bool { + public function is_incentive_visible( bool $skip_wcpay_active = false ): bool { // The WooPayments plugin must not be active. if ( ! $skip_wcpay_active && $this->is_wcpay_active() ) { return false; } + // The current WP user must have the capabilities required to set up WooPayments. + if ( ! current_user_can( 'manage_woocommerce' ) ) { + return false; + } + // Suggestions not disabled via a setting. if ( get_option( 'woocommerce_show_marketplace_suggestions', 'yes' ) === 'no' ) { return false; @@ -95,61 +102,89 @@ class WcPayWelcomePage { /** * Registers the WooPayments welcome page. */ - public function register_payments_welcome_page() { + public function register_menu_and_page() { global $menu; - if ( ! $this->must_be_visible() ) { + // The WooPayments plugin must not be active. + if ( $this->is_wcpay_active() ) { return; } - $menu_icon = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI4NTIiIGhlaWdodD0iNjg0Ij48cGF0aCBmaWxsPSIjYTJhYWIyIiBkPSJNODIgODZ2NTEyaDY4NFY4NlptMCA1OThjLTQ4IDAtODQtMzgtODQtODZWODZDLTIgMzggMzQgMCA4MiAwaDY4NGM0OCAwIDg0IDM4IDg0IDg2djUxMmMwIDQ4LTM2IDg2LTg0IDg2em0zODQtNTU2djQ0aDg2djg0SDM4MnY0NGgxMjhjMjQgMCA0MiAxOCA0MiA0MnYxMjhjMCAyNC0xOCA0Mi00MiA0MmgtNDR2NDRoLTg0di00NGgtODZ2LTg0aDE3MHYtNDRIMzM4Yy0yNCAwLTQyLTE4LTQyLTQyVjIxNGMwLTI0IDE4LTQyIDQyLTQyaDQ0di00NHoiLz48L3N2Zz4='; + $menu_title = esc_html__( 'Payments', 'woocommerce' ); + $menu_icon = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI4NTIiIGhlaWdodD0iNjg0Ij48cGF0aCBmaWxsPSIjYTJhYWIyIiBkPSJNODIgODZ2NTEyaDY4NFY4NlptMCA1OThjLTQ4IDAtODQtMzgtODQtODZWODZDLTIgMzggMzQgMCA4MiAwaDY4NGM0OCAwIDg0IDM4IDg0IDg2djUxMmMwIDQ4LTM2IDg2LTg0IDg2em0zODQtNTU2djQ0aDg2djg0SDM4MnY0NGgxMjhjMjQgMCA0MiAxOCA0MiA0MnYxMjhjMCAyNC0xOCA0Mi00MiA0MmgtNDR2NDRoLTg0di00NGgtODZ2LTg0aDE3MHYtNDRIMzM4Yy0yNCAwLTQyLTE4LTQyLTQyVjIxNGMwLTI0IDE4LTQyIDQyLTQyaDQ0di00NHoiLz48L3N2Zz4='; - $menu_data = [ - 'id' => 'wc-calypso-bridge-payments-welcome-page', - 'title' => esc_html__( 'Payments', 'woocommerce' ), - 'path' => '/wc-pay-welcome-page', - 'position' => '56', - 'nav_args' => [ - 'title' => esc_html__( 'WooPayments', 'woocommerce' ), - 'is_category' => false, - 'menuId' => 'plugins', - 'is_top_level' => true, - ], - 'icon' => $menu_icon, - ]; + // If an incentive is visible, we register the WooPayments welcome/incentives page. + // Otherwise, we register a menu item that links to the Payments task page. + if ( $this->is_incentive_visible() ) { + $page_id = 'wc-calypso-bridge-payments-welcome-page'; + $page_options = array( + 'id' => $page_id, + 'title' => $menu_title, + 'capability' => 'manage_woocommerce', + 'path' => '/wc-pay-welcome-page', + 'position' => '56', + 'nav_args' => array( + 'title' => 'WooPayments', // Do not translate the brand name. + 'is_category' => false, + 'menuId' => 'plugins', + 'is_top_level' => true, + ), + 'icon' => $menu_icon, + ); - wc_admin_register_page( $menu_data ); + wc_admin_register_page( $page_options ); - // Registering a top level menu via wc_admin_register_page doesn't work when the new - // nav is enabled. The new nav disabled everything, except the 'WooCommerce' menu. - // We need to register this menu via add_menu_page so that it doesn't become a child of - // WooCommerce menu. - if ( get_option( 'woocommerce_navigation_enabled', 'no' ) === 'yes' ) { - $menu_with_nav_data = [ - esc_html__( 'Payments', 'woocommerce' ), - esc_html__( 'Payments', 'woocommerce' ), - 'view_woocommerce_reports', - 'admin.php?page=wc-admin&path=/wc-pay-welcome-page', + $menu_path = PageController::get_instance()->get_path_from_id( $page_id ); + + // Registering a top level menu via wc_admin_register_page doesn't work when the new + // nav is enabled. The new nav disabled everything, except the 'WooCommerce' menu. + // We need to register this menu via add_menu_page so that it doesn't become a child of + // WooCommerce menu. + if ( get_option( 'woocommerce_navigation_enabled', 'no' ) === 'yes' ) { + $menu_path = 'admin.php?page=wc-admin&path=/wc-pay-welcome-page'; + $menu_with_nav_data = array( + $menu_title, + $menu_title, + 'manage_woocommerce', + $menu_path, + null, + $menu_icon, + 56, + ); + + call_user_func_array( 'add_menu_page', $menu_with_nav_data ); + } + } else { + // Determine the path to the active Payments task page. + $menu_path = 'admin.php?page=wc-admin&task=' . $this->get_active_payments_task_slug(); + + add_menu_page( + $menu_title, + $menu_title, + 'manage_woocommerce', + $menu_path, null, $menu_icon, 56, - ]; - - call_user_func_array( 'add_menu_page', $menu_with_nav_data ); + ); } - // Add badge. - $badge = ' 1'; - foreach ( $menu as $index => $menu_item ) { - // Only add the badge markup if not already present and the menu item is the WooPayments menu item. - if ( false === strpos( $menu_item[0], $badge ) - && ( 'wc-admin&path=/wc-pay-welcome-page' === $menu_item[2] - || 'admin.php?page=wc-admin&path=/wc-pay-welcome-page' === $menu_item[2] ) - ) { - $menu[ $index ][0] .= $badge; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited + // Maybe add a badge to the menu. + // If the main Payments task is not complete, we add a badge to the Payments menu item. + // We use the complete logic of the main Payments task because it is the most general one. + if ( ! empty( $this->get_payments_task() ) && ! $this->is_payments_task_complete() ) { + $badge = ' 1'; + foreach ( $menu as $index => $menu_item ) { + // Only add the badge markup if not already present and the menu item is the Payments menu item. + if ( 0 === strpos( $menu_item[0], $menu_title ) + && $menu_path === $menu_item[2] + && false === strpos( $menu_item[0], $badge ) ) { - // One menu item with a badge is more than enough. - break; + $menu[ $index ][0] .= $badge; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited + + // One menu item with a badge is more than enough. + break; + } } } } @@ -167,7 +202,7 @@ class WcPayWelcomePage { } // Return early if the incentive must not be visible. - if ( ! $this->must_be_visible() ) { + if ( ! $this->is_incentive_visible() ) { return $settings; } @@ -182,11 +217,11 @@ class WcPayWelcomePage { * @param array $promo_notes Allowed promo notes. * @return array */ - public function allowed_promo_notes( $promo_notes = [] ): array { + public function allowed_promo_notes( $promo_notes = array() ): array { // Note: We need to disregard if WooPayments is active when adding the promo note to the list of // allowed promo notes. The AJAX call that adds the promo note happens after WooPayments is installed and activated. // Return early if the incentive page must not be visible, without checking if WooPayments is active. - if ( ! $this->must_be_visible( true ) ) { + if ( ! $this->is_incentive_visible( true ) ) { return $promo_notes; } @@ -205,7 +240,7 @@ class WcPayWelcomePage { */ public function onboarding_task_badge( string $badge ): string { // Return early if the incentive must not be visible. - if ( ! $this->must_be_visible() ) { + if ( ! $this->is_incentive_visible() ) { return $badge; } @@ -221,7 +256,7 @@ class WcPayWelcomePage { */ public function onboarding_task_additional_data( ?array $additional_data ): ?array { // Return early if the incentive must not be visible. - if ( ! $this->must_be_visible() ) { + if ( ! $this->is_incentive_visible() ) { return $additional_data; } @@ -266,11 +301,11 @@ class WcPayWelcomePage { // If there is at least one order processed with WooPayments, we consider the store to have WooPayments. if ( false === $had_wcpay && ! empty( wc_get_orders( - [ + array( 'payment_method' => 'woocommerce_payments', 'return' => 'ids', 'limit' => 1, - ] + ) ) ) ) { $had_wcpay = true; @@ -402,13 +437,13 @@ class WcPayWelcomePage { // it means there was an API error previously and we should not retry just yet. if ( is_wp_error( $cache ) ) { // Initialize the in-memory cache and return it. - $this->incentive = []; + $this->incentive = array(); return $this->incentive; } // Gather the store context data. - $store_context = [ + $store_context = array( // Store ISO-2 country code, e.g. `US`. 'country' => WC()->countries->get_base_country(), // Store locale, e.g. `en_US`. @@ -419,7 +454,7 @@ class WcPayWelcomePage { // Whether the store has at least one payment gateway enabled. 'has_payments' => ! empty( WC()->payment_gateways()->get_available_payment_gateways() ), 'has_wcpay' => $this->has_wcpay(), - ]; + ); // Fingerprint the store context through a hash of certain entries. $store_context_hash = $this->generate_context_hash( $store_context ); @@ -447,9 +482,9 @@ class WcPayWelcomePage { $response = wp_remote_get( $url, - [ + array( 'user-agent' => 'WooCommerce/' . WC()->version . '; ' . get_bloginfo( 'url' ), - ] + ) ); // Return early if there is an error, waiting 6 hours before the next attempt. @@ -470,11 +505,11 @@ class WcPayWelcomePage { $cache_for = wp_remote_retrieve_header( $response, 'cache-for' ); // Initialize the in-memory cache. - $this->incentive = []; + $this->incentive = array(); if ( 200 === wp_remote_retrieve_response_code( $response ) ) { // Decode the results, falling back to an empty array. - $results = json_decode( wp_remote_retrieve_body( $response ), true ) ?? []; + $results = json_decode( wp_remote_retrieve_body( $response ), true ) ?? array(); // Find all `welcome_page` incentives. $incentives = array_filter( @@ -486,7 +521,7 @@ class WcPayWelcomePage { // Use the first found matching incentive or empty array if none was found. // Store incentive in the in-memory cache. - $this->incentive = empty( $incentives ) ? [] : reset( $incentives ); + $this->incentive = empty( $incentives ) ? array() : reset( $incentives ); } // Skip transient cache if `cache-for` header equals zero. @@ -503,11 +538,11 @@ class WcPayWelcomePage { // or 1 day in seconds. Also attach a timestamp to the transient data so we know when we last fetched. set_transient( self::CACHE_TRANSIENT_NAME, - [ + array( 'incentive' => $this->incentive, 'context_hash' => $store_context_hash, 'timestamp' => time(), - ], + ), ! empty( $cache_for ) ? (int) $cache_for : DAY_IN_SECONDS ); @@ -527,14 +562,76 @@ class WcPayWelcomePage { // Entries like `active_for` have no place in the hash generation since they change automatically. return md5( wp_json_encode( - [ + array( 'country' => $context['country'] ?? '', 'locale' => $context['locale'] ?? '', 'has_orders' => $context['has_orders'] ?? false, 'has_payments' => $context['has_payments'] ?? false, 'has_wcpay' => $context['has_wcpay'] ?? false, - ] + ) ) ); } + + /** + * Get the slug of the active payments task. + * + * It can be either 'woocommerce-payments' or 'payments'. + * + * @return string Either 'woocommerce-payments' or 'payments'. Empty string if no task is found. + */ + private function get_active_payments_task_slug(): string { + $setup_task_list = TaskLists::get_list( 'setup' ); + $extended_task_list = TaskLists::get_list( 'extended' ); + if ( empty( $setup_task_list ) && empty( $extended_task_list ) ) { + return ''; + } + + $payments_task = $setup_task_list->get_task( 'payments' ); + if ( ! empty( $payments_task ) && $payments_task->can_view() ) { + return 'payments'; + } + + $payments_task = $extended_task_list->get_task( 'payments' ); + if ( ! empty( $payments_task ) && $payments_task->can_view() ) { + return 'payments'; + } + + $woopayments_task = $setup_task_list->get_task( 'woocommerce-payments' ); + if ( ! empty( $woopayments_task ) && $woopayments_task->can_view() ) { + return 'woocommerce-payments'; + } + + return ''; + } + + /** + * Get the WooCommerce setup task list Payments task instance. + * + * @return Task|null The Payments task instance. null if the task is not found. + */ + private function get_payments_task(): ?Task { + $task_list = TaskLists::get_list( 'setup' ); + if ( empty( $task_list ) ) { + return null; + } + + $payments_task = $task_list->get_task( 'payments' ); + if ( empty( $payments_task ) ) { + return null; + } + + return $payments_task; + } + + /** + * Determine if the WooCommerce setup task list Payments task is complete. + * + * @return bool True if the Payments task is complete, false otherwise. + */ + private function is_payments_task_complete(): bool { + $payments_task = $this->get_payments_task(); + + return ! empty( $payments_task ) && $payments_task->is_complete(); + } } diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/features/onboarding-tasks/tasks/woocommerce-payments.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/features/onboarding-tasks/tasks/woocommerce-payments.php index dc4e1e3e28b..cdca0bc9fda 100644 --- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/features/onboarding-tasks/tasks/woocommerce-payments.php +++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/features/onboarding-tasks/tasks/woocommerce-payments.php @@ -7,8 +7,6 @@ declare(strict_types=1); - -use Automattic\WooCommerce\Internal\Admin\Onboarding\OnboardingProfile; use Automattic\WooCommerce\Admin\Features\OnboardingTasks\TaskList; use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks\WooCommercePayments; @@ -167,3 +165,10 @@ class Fake_WC_Payments_Gateway extends WC_Payment_Gateway { $this->partially_onboarded = $partially_onboarded; } } + +if ( ! class_exists( '\WC_Payments' ) ) { + /** + * Fake WooPayments main class for testing. + */ + class WC_Payments {} +}