diff --git a/src/wp-admin/includes/class-wp-list-table.php b/src/wp-admin/includes/class-wp-list-table.php index 0b20f6be0c99..8ccd02998fd4 100644 --- a/src/wp-admin/includes/class-wp-list-table.php +++ b/src/wp-admin/includes/class-wp-list-table.php @@ -419,12 +419,29 @@ public function views() { } /** - * Gets the list of bulk actions available on this table. + * Retrieves the list of bulk actions available for this table. * - * The format is an associative array: - * - `'option_name' => 'option_title'` + * The format is an associative array where each element represents either a top level option value and label, or + * an array representing an optgroup and its options. + * + * For a standard option, the array element key is the field value and the array element value is the field label. + * + * For an optgroup, the array element key is the label and the array element value is an associative array of + * options as above. + * + * Example: + * + * [ + * 'edit' => 'Edit', + * 'delete' => 'Delete', + * 'Change State' => [ + * 'feature' => 'Featured', + * 'sale' => 'On Sale', + * ] + * ] * * @since 3.1.0 + * @since 5.6.0 A bulk action can now contain an array of options in order to create an optgroup. * * @return array */ @@ -445,14 +462,15 @@ protected function bulk_actions( $which = '' ) { $this->_actions = $this->get_bulk_actions(); /** - * Filters the list table bulk actions drop-down. + * Filters the items in the bulk actions menu of the list table. * * The dynamic portion of the hook name, `$this->screen->id`, refers - * to the ID of the current screen, usually a string. + * to the ID of the current screen. * * @since 3.1.0 + * @since 5.6.0 A bulk action can now contain an array of options in order to create an optgroup. * - * @param string[] $actions An array of the available bulk actions. + * @param array $actions An array of the available bulk actions. */ $this->_actions = apply_filters( "bulk_actions-{$this->screen->id}", $this->_actions ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores @@ -469,10 +487,21 @@ protected function bulk_actions( $which = '' ) { echo '\n"; diff --git a/src/wp-admin/includes/class-wp-privacy-requests-table.php b/src/wp-admin/includes/class-wp-privacy-requests-table.php index c75edcf2c07c..d2772bd60a8a 100644 --- a/src/wp-admin/includes/class-wp-privacy-requests-table.php +++ b/src/wp-admin/includes/class-wp-privacy-requests-table.php @@ -206,7 +206,7 @@ protected function get_views() { * * @since 4.9.6 * - * @return string[] Array of bulk action labels keyed by their action. + * @return array Array of bulk action labels keyed by their action. */ protected function get_bulk_actions() { return array( diff --git a/src/wp-admin/includes/class-wp-users-list-table.php b/src/wp-admin/includes/class-wp-users-list-table.php index ae5223884477..42cf19f5f887 100644 --- a/src/wp-admin/includes/class-wp-users-list-table.php +++ b/src/wp-admin/includes/class-wp-users-list-table.php @@ -259,7 +259,7 @@ protected function get_views() { * * @since 3.1.0 * - * @return string[] Array of bulk action labels keyed by their action. + * @return array Array of bulk action labels keyed by their action. */ protected function get_bulk_actions() { $actions = array(); diff --git a/tests/phpunit/tests/admin/includesListTable.php b/tests/phpunit/tests/admin/includesListTable.php index a6b77af5b8d4..22e504537245 100644 --- a/tests/phpunit/tests/admin/includesListTable.php +++ b/tests/phpunit/tests/admin/includesListTable.php @@ -352,6 +352,42 @@ public function test_empty_trash_button_should_not_be_shown_if_there_are_no_comm $this->assertNotContains( 'id="delete_all"', $output ); } + /** + * @ticket 19278 + */ + public function test_bulk_action_menu_supports_options_and_optgroups() { + $table = _get_list_table( 'WP_Comments_List_Table', array( 'screen' => 'edit-comments' ) ); + + add_filter( + 'bulk_actions-edit-comments', + function() { + return array( + 'delete' => 'Delete', + 'Change State' => array( + 'feature' => 'Featured', + 'sale' => 'On Sale', + ), + ); + } + ); + + ob_start(); + $table->bulk_actions(); + $output = ob_get_clean(); + + $this->assertContains( + <<<'OPTIONS' + + + + + +OPTIONS + , + $output + ); + } + /** * @ticket 45089 */