Bulk Actions in Tables: Posts, Pages, Users, Comments…

Almost every table in the WordPress admin panel allows bulk editing of items: posts, plugins, users, comments, etc. Since WP 4.7, special hooks have been introduced to add custom actions to these bulk actions and then process them. This functionality will definitely come in handy, so let's dive into it urgently. Moreover, it's very simple to do!

Let's go through the steps and see how to add our own bulk actions and their handlers using an example.

We will need three hooks to add an "action" to any "native WP table" type like WP_List_Table :

To find the screen ID, refer to the description of the get_current_screen() function or the current_screen hook.

Step 1. Adding an Element (Option) to the Dropdown List

You need to attach a function to the dynamic filter bulk_actions-(screen_id) that will add our new element (option) to the array of existing actions.

Replace (screen_id) with the ID of the current admin screen. For the posts list page, it will be edit-post, so the hook will look like this:

add_filter( 'bulk_actions-'.'edit-post', 'register_my_bulk_actions' );
function register_my_bulk_actions( $bulk_actions ){
	$bulk_actions['my_action'] = 'My Action';

	return $bulk_actions;
}

Step 2. Intercepting the Request and Processing (Form Submission)

Use the filter hook handle_bulk_actions-(screen_id). Replace (screen_id) with the screen ID.

Upon successful operation, you need to return the modified parameter $redirect_to. You need to modify the URL in it, add a query parameter to display a message about the successful operation or an error later. Changing the $redirect_to parameter signals that the page needs to be reloaded and determines which URL to redirect to.

add_filter( 'handle_bulk_actions-'.'edit-post', 'my_bulk_action_handler', 10, 3 );
function my_bulk_action_handler( $redirect_to, $doaction, $post_ids ){

	// do nothing if it's not our action
	if( $doaction !== 'my_action' ){
		return $redirect_to;
	}

	foreach( $post_ids as $post_id ){
		// action for each post
	}

	$redirect_to = add_query_arg( 'my_bulk_action_done', count( $post_ids ), $redirect_to );

	return $redirect_to;
}

The last parameter of the hook may vary depending on the page to which we add the bulk action: for users, it will be the IDs of selected users, for comments, it will be the comments IDs, and so on. See the hook description for more details (link above).

Step 3. Displaying a Message

To let users know that something has happened and what exactly has happened: whether the operation was successful or there was an error, you need to display a message about the operation's result.

It's very simple to do this: check for the presence of the specified variable in the URL, and if it exists, display the required message using the admin_notices hook.

add_action( 'admin_notices', 'my_bulk_action_admin_notice' );
function my_bulk_action_admin_notice(){

	if( empty( $_GET['my_bulk_action_done'] ) ){
		return;
	}

	$data = $_GET['my_bulk_action_done'];

	$msg = sprintf( 'My action processed records: %d.', intval($data) );

	echo '<div id="message" class="updated"><p>'. $msg .'</p></div>';
}

-

That's it. Good luck!