Improve `setup_tasks_remaining()` performance to make `menu_task_count` safer (#50655)

* feat: Update TaskLists.php to improve performance and fix bugs

The code changes in TaskLists.php optimize the performance by reducing unnecessary checks and improve the functionality by fixing bugs related to the "setup tasks remaining" feature.

* Update tests

* Add changelog

* Fix lint

* Update TaskLists.php to fix completed tasks array initialization
This commit is contained in:
Chi-Hsuan Huang 2024-08-20 11:46:55 +08:00 committed by GitHub
parent 6733c22f3f
commit 855d94b42d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 78 additions and 15 deletions

View File

@ -0,0 +1,4 @@
Significance: patch
Type: performance
Improve setup_tasks_remaining performance

View File

@ -297,7 +297,6 @@ class TaskLists {
$task_list->add_task( $task ); $task_list->add_task( $task );
} }
} }
} }
/** /**
@ -318,8 +317,8 @@ class TaskLists {
public static function get_lists_by_ids( $ids ) { public static function get_lists_by_ids( $ids ) {
return array_filter( return array_filter(
self::$lists, self::$lists,
function( $list ) use ( $ids ) { function ( $task_list ) use ( $ids ) {
return in_array( $list->get_list_id(), $ids, true ); return in_array( $task_list->get_list_id(), $ids, true );
} }
); );
} }
@ -404,25 +403,31 @@ class TaskLists {
/** /**
* Return number of setup tasks remaining * Return number of setup tasks remaining
* *
* @return number * This is not updated immediately when a task is completed, but rather when task is marked as complete in the database to reduce performance impact.
*
* @return int|null
*/ */
public static function setup_tasks_remaining() { public static function setup_tasks_remaining() {
$setup_list = self::get_list( 'setup' ); $setup_list = self::get_list( 'setup' );
if ( ! $setup_list || $setup_list->is_hidden() || $setup_list->has_previously_completed() || $setup_list->is_complete() ) { if ( ! $setup_list || $setup_list->is_hidden() || $setup_list->has_previously_completed() ) {
return; return;
} }
$remaining_tasks = array_values( $viewable_tasks = $setup_list->get_viewable_tasks();
$completed_tasks = get_option( Task::COMPLETED_OPTION, array() );
if ( ! is_array( $completed_tasks ) ) {
$completed_tasks = array();
}
return count(
array_filter( array_filter(
$setup_list->get_viewable_tasks(), $viewable_tasks,
function( $task ) { function ( $task ) use ( $completed_tasks ) {
return ! $task->is_complete(); return ! in_array( $task->get_id(), $completed_tasks, true );
} }
) )
); );
return count( $remaining_tasks );
} }
/** /**
@ -443,7 +448,6 @@ class TaskLists {
break; break;
} }
} }
} }
/** /**

View File

@ -10,8 +10,9 @@
*/ */
require_once __DIR__ . '/test-task.php'; require_once __DIR__ . '/test-task.php';
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\TaskList;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\TaskLists; use Automattic\WooCommerce\Admin\Features\OnboardingTasks\TaskLists;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\TaskList;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
/** /**
* Class WC_Tests_OnboardingTasks_TaskLists * Class WC_Tests_OnboardingTasks_TaskLists
@ -42,8 +43,8 @@ class WC_Tests_OnboardingTasks_TaskLists extends WC_Unit_Test_Case {
// Filter the default task lists. // Filter the default task lists.
add_filter( add_filter(
'woocommerce_admin_experimental_onboarding_tasklists', 'woocommerce_admin_experimental_onboarding_tasklists',
function( function (
$task_lists $task_lists
) { ) {
$this->assertIsArray( $task_lists ); $this->assertIsArray( $task_lists );
@ -138,4 +139,58 @@ class WC_Tests_OnboardingTasks_TaskLists extends WC_Unit_Test_Case {
// Assert we have the task we added. // Assert we have the task we added.
$this->assertEquals( 'wc-unit-test_tasklists_get_json_visible_list', $json['tasks'][0]['id'] ); $this->assertEquals( 'wc-unit-test_tasklists_get_json_visible_list', $json['tasks'][0]['id'] );
} }
/**
* Tests the setup_tasks_remaining method.
*/
public function test_setup_tasks_remaining() {
// Initialize the default task lists.
TaskLists::add_list(
array(
'id' => 'setup',
'title' => 'Setup',
'tasks' => array(),
'display_progress_header' => true,
'event_prefix' => 'tasklist_',
'options' => array(
'use_completed_title' => true,
),
'visible' => true,
)
);
$setup_list = TaskLists::get_list( 'setup' );
for ( $i = 1; $i <= 3; $i++ ) {
TaskLists::add_task(
'setup',
new TestTask(
$setup_list,
array(
'id' => "setup-task-{$i}",
)
)
);
}
// Test when no tasks are completed.
$this->assertEquals( 3, TaskLists::setup_tasks_remaining() );
// Complete one task.
update_option( Task::COMPLETED_OPTION, array( 'setup-task-1' ) );
$this->assertEquals( 2, TaskLists::setup_tasks_remaining() );
// Complete all tasks.
update_option( Task::COMPLETED_OPTION, array( 'setup-task-1', 'setup-task-2', 'setup-task-3' ) );
$this->assertEquals( 0, TaskLists::setup_tasks_remaining() );
// Test when the setup list is hidden.
$setup_list->hide();
$this->assertNull( TaskLists::setup_tasks_remaining() );
// Test when the setup list has been previously completed.
$setup_list->unhide();
update_option( TaskList::COMPLETED_OPTION, array( 'setup' ) );
$this->assertNull( TaskLists::setup_tasks_remaining() );
}
} }