Including version 4.6 it was quite difficult to add custom bulk actions to the WordPress admin pages. In version 4.7 a hook is added that simplifies the task a lot:
add_action('bulk_actions-{screen_id}', 'my_bulk_action');
Defining the hook
As an example we’ll use the post page, the variables are named accordingly.
add_filter( 'bulk_actions-edit-post', 'register_my_bulk_actions' );
Definig the hook
function register_my_bulk_actions($bulk_actions) {
$bulk_actions['my_bulk_action'] = __( 'My Bulk Action', 'domain');
$bulk_actions['my_other_bulk_action'] = __( 'My Other Bulk Action', 'domain');
return $bulk_actions;
}
You can define more than one bulk action in this function because it merely adds an additional element to the array $bulk_actions
. You simply have to take care that you use different names for the element keys and, logically, for the display texts.
The screen ids
The screen id of an admin page can be displayed this code snippet:
$screen = get_current_screen();
var_dump($screen);
This table shows the ids for some admin pages:
Page | $screen_id | File |
---|---|---|
Media Library | upload | upload.php |
Comments | edit-comments | edit-comments.php |
Tags | edit-post_tag | edit-tags.php |
Plugins | plugins | plugins.php |
Links | link-manager | link-manager.php |
Users | users | users.php |
Posts | edit-post | edit.php |
Pages | edit-page | edit.php |
Edit Site: Themes | site-themes-network | network/site-themes.php |
Themes | themes-network | network/themes |
Users | users-network | network/users |
Edit Site: Users | site-users-network | network/site-users |
Sites | sites-network | network/sites |
Defining the callback function
Here’s an overview of the whole function:
add_filter( 'handle_bulk_actions-edit-post', 'my_bulk_action_handler', 10, 3 );
function my_bulk_action_handler( $redirect_to, $action_name, $post_ids ) {
if ( 'my_bulk_action' === $action_name ) {
foreach ( $post_ids as $post_id ) {
$post = get_post($post_id);
// process $post wp_update_post($post);
}
$redirect_to = add_query_arg( 'bulk_posts_processed', count( $post_ids ), $redirect_to );
return $redirect_to;
}
elseif ( 'my_other_bulk_action' === $action_name ) {
foreach ( $post_ids as $post_id ) {
$post_meta = get_post_meta( $post_id );
// process $post_meta update_post_meta( $post_meta );
}
$redirect_to = add_query_arg( 'other_bulk_posts_precessed', count( $post_ids ), $redirect_to );
return $redirect_to;
}
else
return $redirect_to; }
As mentioned above you can define more than one custom bulk action but only a single callback function. So you first have to test which bulk action has been selected (lines 4 and 13).
Next the posts are processed in a foreach
loop (lines 5 and 14). In this loop you can load the post with get_post
or the post meta with get_post_meta()
and process the data. Next the changed data is written back to the database with wp_update_post()
or update_post_meta()
.
The variable $redirect_to
(lines 9 and 18) is used to define the URL the browser will change to after the bulk actions have been completed, in our case it is set to .../wp-admin/edit.php?paged=1
. We do not want to change the location but to use the variable to pass a value to the page the browser is redirected to.
With the function add_query_arg()
we add an argument to the URL that specifies the number of processed posts: /wp-admin/edit.php?paged=1&bulk_posts_processed=1
.
Display a success notification
After completing processing all posts you can display an admin notice using the action admin_notices()
. The second parameter of the function call needs to contain the text string we have defined in our filter bulk_actions-{screen-id}
:
function my_bulk_action_admin_notice() {
if ( ! empty( $_REQUEST['bulk_posts_processed'] ) ) {
$posts_count = intval( $_REQUEST['bulk_posts_processed'] ); printf( '
' . _n( 'Processed %s post.', 'Processed %s posts.', $posts_count, 'domain' ) . ' ', $posts_count );
}
}
Trivia
A little fun fact at the end: The corresponding ticket (#16031) was opened six years ago, 2010, in that times we used WordPress v3.0.