Merge pull request #3127 from woocommerce/PCP-4178-things-to-do-add-pay-pal-buttons-implement-logic-for-the-todo-item

Todos: Add logic for the Add PayPal buttons todos (4178)
This commit is contained in:
Emili Castells 2025-02-18 16:12:26 +01:00 committed by GitHub
commit df076e13bc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 362 additions and 140 deletions

View file

@ -34,6 +34,7 @@ use WooCommerce\PayPalCommerce\Settings\Service\AuthenticationManager;
use WooCommerce\PayPalCommerce\Settings\Service\ConnectionUrlGenerator;
use WooCommerce\PayPalCommerce\Settings\Service\OnboardingUrlManager;
use WooCommerce\PayPalCommerce\Settings\Service\TodosEligibilityService;
use WooCommerce\PayPalCommerce\Settings\Service\TodosSortingAndFilteringService;
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
use WooCommerce\PayPalCommerce\Settings\Service\DataSanitizer;
use WooCommerce\PayPalCommerce\Settings\Service\SettingsDataManager;
@ -337,7 +338,8 @@ return array(
return new TodosRestEndpoint(
$container->get( 'settings.data.todos' ),
$container->get( 'settings.data.definition.todos' ),
$container->get( 'settings.rest.settings' )
$container->get( 'settings.rest.settings' ),
$container->get( 'settings.service.todos_sorting' )
);
},
'settings.data.todos' => static function ( ContainerInterface $container ) : TodosModel {
@ -355,17 +357,10 @@ return array(
$container->get( 'settings.data.payment' ),
);
},
'settings.service.todos_eligibilities' => static function ( ContainerInterface $container ) : TodosEligibilityService {
$features = apply_filters(
'woocommerce_paypal_payments_rest_common_merchant_features',
array()
);
$payment_endpoint = $container->get( 'settings.rest.payment' );
$settings = $payment_endpoint->get_details()->get_data();
'settings.service.pay_later_status' => static function ( ContainerInterface $container ) : array {
$pay_later_endpoint = $container->get( 'settings.rest.pay_later_messaging' );
$pay_later_settings = $pay_later_endpoint->get_details()->get_data();
$pay_later_statuses = array(
'cart' => $pay_later_settings['data']['cart']['status'] === 'enabled',
'checkout' => $pay_later_settings['data']['checkout']['status'] === 'enabled',
@ -376,16 +371,41 @@ return array(
$pay_later_settings['data']['custom_placement'][0]['status'] === 'enabled',
);
// Settings status.
$gateways = array(
$is_pay_later_messaging_enabled_for_any_location = ! array_filter( $pay_later_statuses );
return array(
'statuses' => $pay_later_statuses,
'is_enabled_for_any_location' => $is_pay_later_messaging_enabled_for_any_location,
);
},
'settings.service.button_locations' => static function ( ContainerInterface $container ) : array {
$styling_endpoint = $container->get( 'settings.rest.styling' );
$styling_data = $styling_endpoint->get_details()->get_data()['data'];
return array(
'cart_enabled' => $styling_data['cart']->enabled ?? false,
'block_checkout_enabled' => $styling_data['expressCheckout']->enabled ?? false,
'product_enabled' => $styling_data['product']->enabled ?? false,
);
},
'settings.service.gateways_status' => static function ( ContainerInterface $container ) : array {
$payment_endpoint = $container->get( 'settings.rest.payment' );
$settings = $payment_endpoint->get_details()->get_data();
return array(
'apple_pay' => $settings['data']['ppcp-applepay']['enabled'] ?? false,
'google_pay' => $settings['data']['ppcp-googlepay']['enabled'] ?? false,
'axo' => $settings['data']['ppcp-axo-gateway']['enabled'] ?? false,
'card-button' => $settings['data']['ppcp-card-button-gateway']['enabled'] ?? false,
);
},
'settings.service.merchant_capabilities' => static function ( ContainerInterface $container ) : array {
$features = apply_filters(
'woocommerce_paypal_payments_rest_common_merchant_features',
array()
);
// Merchant eligibility.
$capabilities = array(
return array(
'apple_pay' => $features['apple_pay']['enabled'] ?? false,
'google_pay' => $features['google_pay']['enabled'] ?? false,
'acdc' => $features['advanced_credit_and_debit_cards']['enabled'] ?? false,
@ -393,25 +413,67 @@ return array(
'apm' => $features['alternative_payment_methods']['enabled'] ?? false,
'paylater' => $features['pay_later_messaging']['enabled'] ?? false,
);
},
$is_pay_later_messaging_enabled_for_any_location = ! array_filter( $pay_later_statuses );
'settings.service.todos_eligibilities' => static function ( ContainerInterface $container ) : TodosEligibilityService {
$pay_later_service = $container->get( 'settings.service.pay_later_status' );
$pay_later_statuses = $pay_later_service['statuses'];
$is_pay_later_messaging_enabled_for_any_location = $pay_later_service['is_enabled_for_any_location'];
$button_locations = $container->get( 'settings.service.button_locations' );
$gateways = $container->get( 'settings.service.gateways_status' );
$capabilities = $container->get( 'settings.service.merchant_capabilities' );
/**
* Initializes TodosEligibilityService with eligibility conditions for various PayPal features.
* Each parameter determines whether a specific feature should be shown in the Things To Do list.
*
* Logic relies on two main factors:
* 1. $capabilities - Whether the merchant is eligible for specific features on their PayPal account.
* 2. $gateways, $pay_later_statuses, $button_locations - Plugin settings (enabled/disabled status).
*
* @param bool $is_fastlane_eligible - Show if merchant is eligible (ACDC) but hasn't enabled Fastlane gateway.
* @param bool $is_card_payment_eligible - Show if merchant is eligible (ACDC) but hasn't enabled card button gateway.
* @param bool $is_pay_later_messaging_eligible - Show if Pay Later messaging is enabled for at least one location.
* @param bool $is_pay_later_messaging_product_eligible - Show if Pay Later is not enabled anywhere and specifically not on product page.
* @param bool $is_pay_later_messaging_cart_eligible - Show if Pay Later is not enabled anywhere and specifically not on cart.
* @param bool $is_pay_later_messaging_checkout_eligible - Show if Pay Later is not enabled anywhere and specifically not on checkout.
* @param bool $is_subscription_eligible - Show if WooCommerce Subscriptions plugin is active but merchant is not eligible for PayPal Vaulting.
* @param bool $is_paypal_buttons_cart_eligible - Show if PayPal buttons are not enabled on cart page.
* @param bool $is_paypal_buttons_block_checkout_eligible - Show if PayPal buttons are not enabled on blocks checkout.
* @param bool $is_paypal_buttons_product_eligible - Show if PayPal buttons are not enabled on product page.
* @param bool $is_apple_pay_domain_eligible - Show if merchant has Apple Pay capability on PayPal account.
* @param bool $is_digital_wallet_eligible - Show if merchant is eligible (ACDC) but doesn't have both wallet types on PayPal.
* @param bool $is_apple_pay_eligible - Show if merchant is eligible (ACDC) but doesn't have Apple Pay on PayPal.
* @param bool $is_google_pay_eligible - Show if merchant is eligible (ACDC) but doesn't have Google Pay on PayPal.
* @param bool $is_enable_apple_pay_eligible - Show if merchant has Apple Pay capability but hasn't enabled the gateway.
* @param bool $is_enable_google_pay_eligible - Show if merchant has Google Pay capability but hasn't enabled the gateway.
*/
return new TodosEligibilityService(
$capabilities['acdc'] && ! $gateways['axo'], // Enable Fastlane.
$capabilities['acdc'] && ! $gateways['card-button'], // Enable Credit and Debit Cards on your checkout.
$is_pay_later_messaging_enabled_for_any_location, // Enable Pay Later messaging.
! $is_pay_later_messaging_enabled_for_any_location && ! $pay_later_statuses['product'], // Add Pay Later messaging (Product page).
$capabilities['acdc'] && ! $gateways['axo'], // Enable Fastlane.
$capabilities['acdc'] && ! $gateways['card-button'], // Enable Credit and Debit Cards on your checkout.
$is_pay_later_messaging_enabled_for_any_location, // Enable Pay Later messaging.
! $is_pay_later_messaging_enabled_for_any_location && ! $pay_later_statuses['product'], // Add Pay Later messaging (Product page).
! $is_pay_later_messaging_enabled_for_any_location && ! $pay_later_statuses['cart'], // Add Pay Later messaging (Cart).
! $is_pay_later_messaging_enabled_for_any_location && ! $pay_later_statuses['checkout'], // Add Pay Later messaging (Checkout).
$container->has( 'save-payment-methods.eligible' ) && ! $container->get( 'save-payment-methods.eligible' ) && $container->has( 'wc-subscriptions.helper' ) && $container->get( 'wc-subscriptions.helper' )
->plugin_is_active(), // Configure a PayPal Subscription.
true, // Add PayPal buttons.
$capabilities['apple_pay'], // Register Domain for Apple Pay.
$capabilities['acdc'] && ! ( $capabilities['apple_pay'] && $capabilities['google_pay'] ), // Add digital wallets to your account.
$capabilities['acdc'] && ! $capabilities['apple_pay'], // Add Apple Pay to your account.
$capabilities['acdc'] && ! $capabilities['google_pay'], // Add Google Pay to your account.
$capabilities['apple_pay'] && ! $gateways['apple_pay'], // Enable Apple Pay.
$capabilities['google_pay'] && ! $gateways['google_pay'], // Enable Google Pay.
! $is_pay_later_messaging_enabled_for_any_location && ! $pay_later_statuses['checkout'], // Add Pay Later messaging (Checkout).
$container->has( 'save-payment-methods.eligible' ) &&
! $container->get( 'save-payment-methods.eligible' ) &&
$container->has( 'wc-subscriptions.helper' ) &&
$container->get( 'wc-subscriptions.helper' )->plugin_is_active(), // Configure a PayPal Subscription.
! $button_locations['cart_enabled'], // Add PayPal buttons to cart.
! $button_locations['block_checkout_enabled'], // Add PayPal buttons to block checkout.
! $button_locations['product_enabled'], // Add PayPal buttons to product.
$capabilities['apple_pay'], // Register Domain for Apple Pay.
$capabilities['acdc'] && ! ( $capabilities['apple_pay'] && $capabilities['google_pay'] ), // Add digital wallets to your account.
$capabilities['acdc'] && ! $capabilities['apple_pay'], // Add Apple Pay to your account.
$capabilities['acdc'] && ! $capabilities['google_pay'], // Add Google Pay to your account.
$capabilities['apple_pay'] && ! $gateways['apple_pay'], // Enable Apple Pay.
$capabilities['google_pay'] && ! $gateways['google_pay'],
);
},
'settings.service.todos_sorting' => static function ( ContainerInterface $container ) : TodosSortingAndFilteringService {
return new TodosSortingAndFilteringService(
$container->get( 'settings.data.todos' )
);
},
);

View file

@ -1,6 +1,6 @@
<?php
/**
* PayPal Commerce Todos Definitions
* Todos Definitions
*
* @package WooCommerce\PayPalCommerce\Settings\Data\Definition
*/
@ -145,10 +145,30 @@ class TodosDefinition {
),
'priority' => 5,
),
'add_paypal_buttons' => array(
'title' => __( 'Add PayPal buttons', 'woocommerce-paypal-payments' ),
'description' => __( 'Allow customers to check out quickly and securely from the <x> page. Customers save time and get through checkout in fewer clicks.', 'woocommerce-paypal-payments' ),
'isEligible' => $eligibility_checks['add_paypal_buttons'],
'add_paypal_buttons_cart' => array(
'title' => __( 'Add PayPal buttons to the Cart page', 'woocommerce-paypal-payments' ),
'description' => __( 'Allow customers to check out quickly and securely from the Cart page. Customers save time and get through checkout in fewer clicks.', 'woocommerce-paypal-payments' ),
'isEligible' => $eligibility_checks['add_paypal_buttons_cart'],
'action' => array(
'type' => 'tab',
'tab' => 'styling',
),
'priority' => 6,
),
'add_paypal_buttons_block_checkout' => array(
'title' => __( 'Add PayPal buttons to the Express Checkout page', 'woocommerce-paypal-payments' ),
'description' => __( 'Allow customers to check out quickly and securely from the Express Checkout page. Customers save time and get through checkout in fewer clicks.', 'woocommerce-paypal-payments' ),
'isEligible' => $eligibility_checks['add_paypal_buttons_block_checkout'],
'action' => array(
'type' => 'tab',
'tab' => 'styling',
),
'priority' => 6,
),
'add_paypal_buttons_product' => array(
'title' => __( 'Add PayPal buttons to the Product page', 'woocommerce-paypal-payments' ),
'description' => __( 'Allow customers to check out quickly and securely from the Product page. Customers save time and get through checkout in fewer clicks.', 'woocommerce-paypal-payments' ),
'isEligible' => $eligibility_checks['add_paypal_buttons_product'],
'action' => array(
'type' => 'tab',
'tab' => 'styling',

View file

@ -17,6 +17,7 @@ use WP_REST_Response;
use WP_REST_Request;
use WooCommerce\PayPalCommerce\Settings\Data\TodosModel;
use WooCommerce\PayPalCommerce\Settings\Data\Definition\TodosDefinition;
use WooCommerce\PayPalCommerce\Settings\Service\TodosSortingAndFilteringService;
/**
* REST controller for the "Things To Do" items in the Overview tab.
@ -33,17 +34,6 @@ class TodosRestEndpoint extends RestEndpoint {
*/
protected $rest_base = 'todos';
/**
* Pay Later messaging todo IDs in priority order.
*
* @var array
*/
private const PAY_LATER_IDS = array(
'add_pay_later_messaging_product_page',
'add_pay_later_messaging_cart',
'add_pay_later_messaging_checkout',
);
/**
* The todos model instance.
*
@ -65,21 +55,31 @@ class TodosRestEndpoint extends RestEndpoint {
*/
protected SettingsRestEndpoint $settings;
/**
* The todos sorting service.
*
* @var TodosSortingAndFilteringService
*/
protected TodosSortingAndFilteringService $sorting_service;
/**
* TodosRestEndpoint constructor.
*
* @param TodosModel $todos The todos model instance.
* @param TodosDefinition $todos_definition The todos definition instance.
* @param SettingsRestEndpoint $settings The settings endpoint instance.
* @param TodosModel $todos The todos model instance.
* @param TodosDefinition $todos_definition The todos definition instance.
* @param SettingsRestEndpoint $settings The settings endpoint instance.
* @param TodosSortingAndFilteringService $sorting_service The todos sorting service.
*/
public function __construct(
TodosModel $todos,
TodosDefinition $todos_definition,
SettingsRestEndpoint $settings
SettingsRestEndpoint $settings,
TodosSortingAndFilteringService $sorting_service
) {
$this->todos = $todos;
$this->todos_definition = $todos_definition;
$this->settings = $settings;
$this->sorting_service = $sorting_service;
}
/**
@ -157,8 +157,7 @@ class TodosRestEndpoint extends RestEndpoint {
}
}
$sorted_todos = $this->sort_todos_by_priority( $todos );
$filtered_todos = $this->filter_pay_later_todos( $sorted_todos );
$filtered_todos = $this->sorting_service->apply_all_priority_filters( $todos );
return $this->return_success(
array(
@ -245,67 +244,4 @@ class TodosRestEndpoint extends RestEndpoint {
);
}
}
/**
* Filters Pay Later messaging todos to show only the highest priority eligible todo.
*
* @param array $todos The array of todos to filter.
* @return array Filtered todos with only one Pay Later messaging todo.
*/
private function filter_pay_later_todos( array $todos ): array {
$pay_later_todos = array_filter(
$todos,
function( $todo ) {
return in_array( $todo['id'], self::PAY_LATER_IDS, true );
}
);
$other_todos = array_filter(
$todos,
function( $todo ) {
return ! in_array( $todo['id'], self::PAY_LATER_IDS, true );
}
);
// Find the highest priority Pay Later todo that's eligible.
$priority_pay_later_todo = null;
foreach ( self::PAY_LATER_IDS as $pay_later_id ) {
$matching_todo = current(
array_filter(
$pay_later_todos,
function( $todo ) use ( $pay_later_id ) {
return $todo['id'] === $pay_later_id;
}
)
);
if ( $matching_todo ) {
$priority_pay_later_todo = $matching_todo;
break;
}
}
return $priority_pay_later_todo
? array_merge( $other_todos, array( $priority_pay_later_todo ) )
: $other_todos;
}
/**
* Sorts todos by their priority value.
*
* @param array $todos Array of todos to sort.
* @return array Sorted array of todos.
*/
private function sort_todos_by_priority( array $todos ): array {
usort(
$todos,
function( $a, $b ) {
$priority_a = $a['priority'] ?? 999;
$priority_b = $b['priority'] ?? 999;
return $priority_a <=> $priority_b;
}
);
return $todos;
}
}

View file

@ -1,9 +1,9 @@
<?php
/**
* PayPal Commerce eligibility service for WooCommerce.
* Eligibility service for Todos.
*
* This file contains the TodosEligibilityService class which manages eligibility checks
* for various PayPal Commerce features including Fastlane, card payments, Pay Later messaging,
* for various features including Fastlane, card payments, Pay Later messaging,
* subscriptions, Apple Pay, Google Pay, and other digital wallet features.
*
* @package WooCommerce\PayPalCommerce\Settings\Service
@ -66,6 +66,27 @@ class TodosEligibilityService {
*/
private bool $is_subscription_eligible;
/**
* Whether PayPal buttons for cart are eligible.
*
* @var bool
*/
private bool $is_paypal_buttons_cart_eligible;
/**
* Whether PayPal buttons for block checkout are eligible.
*
* @var bool
*/
private bool $is_paypal_buttons_block_checkout_eligible;
/**
* Whether PayPal buttons for product page are eligible.
*
* @var bool
*/
private bool $is_paypal_buttons_product_eligible;
/**
* Whether Apple Pay domain registration is eligible.
*
@ -94,13 +115,6 @@ class TodosEligibilityService {
*/
private bool $is_google_pay_eligible;
/**
* Whether PayPal buttons are eligible.
*
* @var bool
*/
private bool $is_paypal_buttons_eligible;
/**
* Whether enabling Apple Pay is eligible.
*
@ -125,7 +139,9 @@ class TodosEligibilityService {
* @param bool $is_pay_later_messaging_cart_eligible Whether Pay Later messaging for cart is eligible.
* @param bool $is_pay_later_messaging_checkout_eligible Whether Pay Later messaging for checkout is eligible.
* @param bool $is_subscription_eligible Whether subscriptions are eligible.
* @param bool $is_paypal_buttons_eligible Whether PayPal buttons are eligible.
* @param bool $is_paypal_buttons_cart_eligible Whether PayPal buttons for cart are eligible.
* @param bool $is_paypal_buttons_block_checkout_eligible Whether PayPal buttons for block checkout are eligible.
* @param bool $is_paypal_buttons_product_eligible Whether PayPal buttons for product page are eligible.
* @param bool $is_apple_pay_domain_eligible Whether Apple Pay domain registration is eligible.
* @param bool $is_digital_wallet_eligible Whether digital wallet features are eligible.
* @param bool $is_apple_pay_eligible Whether Apple Pay is eligible.
@ -141,7 +157,9 @@ class TodosEligibilityService {
bool $is_pay_later_messaging_cart_eligible,
bool $is_pay_later_messaging_checkout_eligible,
bool $is_subscription_eligible,
bool $is_paypal_buttons_eligible,
bool $is_paypal_buttons_cart_eligible,
bool $is_paypal_buttons_block_checkout_eligible,
bool $is_paypal_buttons_product_eligible,
bool $is_apple_pay_domain_eligible,
bool $is_digital_wallet_eligible,
bool $is_apple_pay_eligible,
@ -149,20 +167,22 @@ class TodosEligibilityService {
bool $is_enable_apple_pay_eligible,
bool $is_enable_google_pay_eligible
) {
$this->is_fastlane_eligible = $is_fastlane_eligible;
$this->is_card_payment_eligible = $is_card_payment_eligible;
$this->is_pay_later_messaging_eligible = $is_pay_later_messaging_eligible;
$this->is_pay_later_messaging_product_eligible = $is_pay_later_messaging_product_eligible;
$this->is_pay_later_messaging_cart_eligible = $is_pay_later_messaging_cart_eligible;
$this->is_pay_later_messaging_checkout_eligible = $is_pay_later_messaging_checkout_eligible;
$this->is_subscription_eligible = $is_subscription_eligible;
$this->is_paypal_buttons_eligible = $is_paypal_buttons_eligible;
$this->is_apple_pay_domain_eligible = $is_apple_pay_domain_eligible;
$this->is_digital_wallet_eligible = $is_digital_wallet_eligible;
$this->is_apple_pay_eligible = $is_apple_pay_eligible;
$this->is_google_pay_eligible = $is_google_pay_eligible;
$this->is_enable_apple_pay_eligible = $is_enable_apple_pay_eligible;
$this->is_enable_google_pay_eligible = $is_enable_google_pay_eligible;
$this->is_fastlane_eligible = $is_fastlane_eligible;
$this->is_card_payment_eligible = $is_card_payment_eligible;
$this->is_pay_later_messaging_eligible = $is_pay_later_messaging_eligible;
$this->is_pay_later_messaging_product_eligible = $is_pay_later_messaging_product_eligible;
$this->is_pay_later_messaging_cart_eligible = $is_pay_later_messaging_cart_eligible;
$this->is_pay_later_messaging_checkout_eligible = $is_pay_later_messaging_checkout_eligible;
$this->is_subscription_eligible = $is_subscription_eligible;
$this->is_paypal_buttons_cart_eligible = $is_paypal_buttons_cart_eligible;
$this->is_paypal_buttons_block_checkout_eligible = $is_paypal_buttons_block_checkout_eligible;
$this->is_paypal_buttons_product_eligible = $is_paypal_buttons_product_eligible;
$this->is_apple_pay_domain_eligible = $is_apple_pay_domain_eligible;
$this->is_digital_wallet_eligible = $is_digital_wallet_eligible;
$this->is_apple_pay_eligible = $is_apple_pay_eligible;
$this->is_google_pay_eligible = $is_google_pay_eligible;
$this->is_enable_apple_pay_eligible = $is_enable_apple_pay_eligible;
$this->is_enable_google_pay_eligible = $is_enable_google_pay_eligible;
}
/**
@ -179,7 +199,9 @@ class TodosEligibilityService {
'add_pay_later_messaging_cart' => fn() => $this->is_pay_later_messaging_cart_eligible,
'add_pay_later_messaging_checkout' => fn() => $this->is_pay_later_messaging_checkout_eligible,
'configure_paypal_subscription' => fn() => $this->is_subscription_eligible,
'add_paypal_buttons' => fn() => $this->is_paypal_buttons_eligible,
'add_paypal_buttons_cart' => fn() => $this->is_paypal_buttons_cart_eligible,
'add_paypal_buttons_block_checkout' => fn() => $this->is_paypal_buttons_block_checkout_eligible,
'add_paypal_buttons_product' => fn() => $this->is_paypal_buttons_product_eligible,
'register_domain_apple_pay' => fn() => $this->is_apple_pay_domain_eligible,
'add_digital_wallets' => fn() => $this->is_digital_wallet_eligible,
'add_apple_pay' => fn() => $this->is_apple_pay_eligible,

View file

@ -0,0 +1,182 @@
<?php
/**
* Service for sorting and filtering todo items.
*
* @package WooCommerce\PayPalCommerce\Settings\Service
*/
declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\Settings\Service;
use WooCommerce\PayPalCommerce\Settings\Data\TodosModel;
/**
* Service class that provides todo sorting and filtering functionality.
*/
class TodosSortingAndFilteringService {
/**
* Pay Later messaging todo IDs in priority order.
*
* @var array
*/
private const PAY_LATER_IDS = array(
'add_pay_later_messaging_product_page',
'add_pay_later_messaging_cart',
'add_pay_later_messaging_checkout',
);
/**
* Button placement todo IDs in priority order.
*
* @var array
*/
private const BUTTON_PLACEMENT_IDS = array(
'add_paypal_buttons_cart',
'add_paypal_buttons_block_checkout',
'add_paypal_buttons_product',
);
/**
* The TodosModel instance.
*
* @var TodosModel
*/
private TodosModel $todos_model;
/**
* Constructor.
*
* @param TodosModel $todos_model The TodosModel instance.
*/
public function __construct( TodosModel $todos_model ) {
$this->todos_model = $todos_model;
}
/**
* Returns Pay Later messaging todo IDs in priority order.
*
* @return array Pay Later messaging todo IDs.
*/
public function get_pay_later_ids(): array {
return self::PAY_LATER_IDS;
}
/**
* Returns Button Placement todo IDs in priority order.
*
* @return array Button Placement todo IDs.
*/
public function get_button_placement_ids(): array {
return self::BUTTON_PLACEMENT_IDS;
}
/**
* Sorts todos by their priority value.
*
* @param array $todos Array of todos to sort.
* @return array Sorted array of todos.
*/
public function sort_todos_by_priority( array $todos ): array {
usort(
$todos,
function( $a, $b ) {
$priority_a = $a['priority'] ?? 999;
$priority_b = $b['priority'] ?? 999;
return $priority_a <=> $priority_b;
}
);
return $todos;
}
/**
* Filters a group of todos to show only the highest priority one.
* Takes into account dismissed todos.
*
* @param array $todos The array of todos to filter.
* @param array $group_ids Array of todo IDs in priority order.
* @return array Filtered todos with only one todo from the specified group.
*/
public function filter_highest_priority_todo( array $todos, array $group_ids ): array {
$dismissed_todos = $this->todos_model->get_dismissed_todos();
$group_todos = array_filter(
$todos,
function( $todo ) use ( $group_ids ) {
return in_array( $todo['id'], $group_ids, true );
}
);
$other_todos = array_filter(
$todos,
function( $todo ) use ( $group_ids ) {
return ! in_array( $todo['id'], $group_ids, true );
}
);
// Find the highest priority todo from the group that's eligible AND not dismissed.
$priority_todo = null;
foreach ( $group_ids as $todo_id ) {
// Skip if this todo ID is dismissed.
if ( in_array( $todo_id, $dismissed_todos, true ) ) {
continue;
}
$matching_todo = current(
array_filter(
$group_todos,
function( $todo ) use ( $todo_id ) {
return $todo['id'] === $todo_id;
}
)
);
if ( $matching_todo ) {
$priority_todo = $matching_todo;
break;
}
}
return $priority_todo
? array_merge( $other_todos, array( $priority_todo ) )
: $other_todos;
}
/**
* Filter pay later todos to show only the highest priority eligible one.
*
* @param array $todos The array of todos to filter.
* @return array Filtered todos.
*/
public function filter_pay_later_todos( array $todos ): array {
return $this->filter_highest_priority_todo( $todos, self::PAY_LATER_IDS );
}
/**
* Filter button placement todos to show only the highest priority eligible one.
*
* @param array $todos The array of todos to filter.
* @return array Filtered todos.
*/
public function filter_button_placement_todos( array $todos ): array {
return $this->filter_highest_priority_todo( $todos, self::BUTTON_PLACEMENT_IDS );
}
/**
* Apply all priority filters to the todos list.
*
* This method applies sorting and all priority filtering in the correct order.
*
* @param array $todos The original todos array.
* @return array Fully filtered and sorted todos.
*/
public function apply_all_priority_filters( array $todos ): array {
$sorted_todos = $this->sort_todos_by_priority( $todos );
$filtered_todos = $this->filter_pay_later_todos( $sorted_todos );
$filtered_todos = $this->filter_button_placement_todos( $filtered_todos );
return $filtered_todos;
}
}