6

I've created a custom taxonomy for attachments. Everything ok, but now I want the ability to bulk assign its terms to attachments using the default wordpress media admin ('upload.php') bulk actions.

Here in wpse I've found a couple of questions/answers regarding bulk actions for admin media table.

Like this one and this other.

These give me a direction on how to add the bulk action on the select menu (there is no filter for it, so I've to use javascript) but my case is different:

In linked questions/answers when a bulk action is selected the page form is immediately submitted, instead I want that when I select my bulk action (e.g. "Assign Terms") and I press the "Apply" button instead of submit the form, I want to show an UI very similar to the one shown when on standard posts the bulk 'Edit' action is chose (see image below).

enter image description here

Here I want to select terms and finally, by clicking 'Update Button', bulk assign terms to attachments.

How can I achieve this?

2 Answers 2

7

As said in the question there is no filter to add bulk actions to the standard select menu, or better, there is one, but it can be used only for remove actions and not for adding. So, even if for php/wp developers (like me) it seems ugly (and probably is ugly) only chance is use js.

Bad news is that to achieve the requests in the question, we need a lot of javascript, too.

There are no alternatives: once there is no filter or actions, or we use javascript or we modify core files. Between the two evils let's choose the lesser.

The workflow

  1. PHP: create a function that output the html markup for the select terms UI. We can copy a lot from the standard bulk edit UI for posts see
  2. PHP: hook the function created at point 1. into an ajax action
  3. JS: create a code that add an option to the bulk select menu
  4. JS: Intercept the click on 'Apply' buttons (one in table header one in footer) and if our action is selected, prevent_default() and make an ajax request that call the function create at point 1. and put the html given as result in the right place on the table
  5. PHP: create a function that accept from $_POST an array of attachments ids and some array of terms (an array for every taxonomy) and just assign the terms to the given attachments
  6. PHP: hook the function created at point 5. in a second ajax action
  7. JS: create an ajax call that runs when the Update button in our UI is clicked. (We have to remember to use jQuery.on() because UI is added via ajax). It call the function created at point 5 and when done, redirect page to upload.php adding a query var that help us to use admin notices to show success or error messages
  8. PHP: after we have saved all js in a file, enqueue it only for 'upload.php' and using wp_localize_script to pass to it some variables like nonces and translation strings

We have to remind that functions that handle ajax requests must do some security checks, like checking the nonce and if the current user can perform the required action.

The following is a preview of how our UI for bulk terms assignment should look like:

enter image description here

Note the different implementation for hierachical and non hierachical taxonomies and the suggest implementation for non hierachical ones.

If someone is interested, I've created a plugin that does what is said here and a bit more, in fact plugin is parted in 2:

  1. first part register a taxonomy for attachments, using some standard arguments
  2. second part implements the bulk terms assignment as described here for all taxonomies registered for attachments (so not only for the one registered by plugin)

If someone want to use the second part but not the first (because has already all needed taxonomies registered) a filter is given to block the registration.

If someone want let plugin register the default taxonomy but doesn't like default args, another filter is provided to change defaults args.

As a bonus feature, using a third filter is possible to use plugin for register other attachment taxonomies, it's easier than use register_taxonomy because in the plugin there are a lot of default arguments setted thinking at attachment taxonomies, on the contrary, defaults arguments for register_taxonomy are setted with post taxonomies in mind.

Plugin also implement its own text domain for easy localization.

Plugin code is on GitHub

0

This question has been around for over 10 years, and WordPress core still doesn't offer a way to add or remove terms in bulk.

The best solution depends on the size of your term list:

For short lists that fit on a few table pages, follow the accepted answer by gmazzap and dynamically add the remove option to your bulk actions: https://github.com/gmazzap/GMMediaTags

For updating thousands of terms at once, the challenge isn't just adding the "remove" option but also processing a large number of terms without:

Manually going through hundreds of pages. Overloading your server with large queries. To address these issues for very large tables, I've developed a plugin that I'm considering adding to the free WordPress marketplace. For now, I'm focusing on supporting and improving it with premium users.

This plugin takes a different approach by moving the workflow outside the table. Tasks are created individually for a specific post type, taxonomy, or user. Items are pre-selected using filters, and you can add or remove terms according to the predefined action.

Once the task is scheduled for each selected item, it is processed either via JavaScript in the frontend or as a CRON job in the background.

If you're interested, check it out: https://code.recuweb.com/get/bulk-task-editor/

Using this method, you can also add custom functions to perform even more complex tasks.

Use the following template to implement a custom post type task.

Register the task:

add_action( 'rewbe_post_type_actions', function($actions,$post_type){

     if( $post_type == 'your-custom-post-type' ){

          $actions[] = array(

               'label'  => 'Name of your task',
               'id'     => 'bulk_task_name',
               'fields' => array(
                    array(
                         'name'    => 'var_1',
                         'type'    => 'select',
                         'options' => array(
                              'value_1' => 'Option 1',
                              'value_2' => 'Option 2',
                              'value_3' => 'Option 3',
                         ),                    
                    ),
                    array(
                         'name' => 'var_2',
                         'type' => 'text',
                    ),
               ),
          );
     }
     
     return $actions;
     
},10,2);

Add the callback function of your task:

add_action('rewbe_do_post_{bulk_task_name}',function($post,$args){
     
     if( !empty($args['var_1']) && !empty($args['var_2']) ){
          
          $var_1 = sanitize_title($args['var_1']);

          $var_2 = sanitize_text_field($args['var_2']);
          
          // your logic here
     }
     
     return $post;
     
},10,2);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.