Skip to content

Commit

Permalink
Administration: Allow WP_List_Table::get_bulk_items() to receive a …
Browse files Browse the repository at this point in the history
…nested array in order to output optgroups.

The allowed format for bulk actions is now 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.

Props goldenapples, mattkeys, valentinbora, davidbaumwald

Fixes #19278


git-svn-id: https://develop.svn.wordpress.org/trunk@49190 602fd350-edb4-49c9-b593-d223f7449a82
  • Loading branch information
johnbillion committed Oct 18, 2020
1 parent 1f1adbe commit f41b6b4
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 11 deletions.
47 changes: 38 additions & 9 deletions src/wp-admin/includes/class-wp-list-table.php
Expand Up @@ -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
*/
Expand All @@ -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

Expand All @@ -469,10 +487,21 @@ protected function bulk_actions( $which = '' ) {
echo '<select name="action' . $two . '" id="bulk-action-selector-' . esc_attr( $which ) . "\">\n";
echo '<option value="-1">' . __( 'Bulk actions' ) . "</option>\n";

foreach ( $this->_actions as $name => $title ) {
$class = 'edit' === $name ? ' class="hide-if-no-js"' : '';
foreach ( $this->_actions as $key => $value ) {
if ( is_array( $value ) ) {
echo "\t" . '<optgroup label="' . esc_attr( $key ) . '">' . "\n";

echo "\t" . '<option value="' . $name . '"' . $class . '>' . $title . "</option>\n";
foreach ( $value as $name => $title ) {
$class = ( 'edit' === $name ) ? ' class="hide-if-no-js"' : '';

echo "\t\t" . '<option value="' . esc_attr( $name ) . '"' . $class . '>' . $title . "</option>\n";
}
echo "\t" . "</optgroup>\n";
} else {
$class = ( 'edit' === $key ) ? ' class="hide-if-no-js"' : '';

echo "\t" . '<option value="' . esc_attr( $key ) . '"' . $class . '>' . $value . "</option>\n";
}
}

echo "</select>\n";
Expand Down
2 changes: 1 addition & 1 deletion src/wp-admin/includes/class-wp-privacy-requests-table.php
Expand Up @@ -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(
Expand Down
2 changes: 1 addition & 1 deletion src/wp-admin/includes/class-wp-users-list-table.php
Expand Up @@ -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();
Expand Down
36 changes: 36 additions & 0 deletions tests/phpunit/tests/admin/includesListTable.php
Expand Up @@ -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'
<option value="delete">Delete</option>
<optgroup label="Change State">
<option value="feature">Featured</option>
<option value="sale">On Sale</option>
</optgroup>
OPTIONS
,
$output
);
}

/**
* @ticket 45089
*/
Expand Down

0 comments on commit f41b6b4

Please sign in to comment.