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.
Between the two evils let's choose the lesser.
- 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
- PHP: hook the function created at point 1. into an ajax action
- JS: create a code that add an option to the bulk select menu
- 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
- 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
- PHP: hook the function created at point 5. in a second ajax action
- 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
- 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:
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:
- first part register a taxonomy for attachments, using some standard arguments
- 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