The WP Media Category Management plug-in (WP MCM) is created to ease the management of media categories. You can define categories and assign them to media on the Media Library page. You can even assign them in bulk for multiple media at once. To ease management even further, it is also possible to filter the media on a specific category. In both list and grid view.
On the support page of my plugin, there was a request to be able to filter on those media that have no category assigned. Ok, this is an easy question, I thought. So I started to analyse how to do this. On the list view, I already had a filter drop down with the options showing all categories or filter on a specific category. Adding the option “No category” was easy enough: add the option “show_option_none” to the “wp_dropdown_categories()” function generating the drop down list. As this new option generated “No results”, I had to change the filter function itself. This proved to be harder than I thought.
Determine No Category Filter
My first analysis showed that the filter function used the WP_Query object in “get_post()“, using the settings provided in the _REQUEST data. So my first challenge was to recognise the different filter requests. The value of “filter_action” being “Filter” proved to be a good start. Determining the “No category” option however was more difficult, so I added the option “option_none_value” with a distinct value to the “wp_dropdown_categories()” function. Now I could determine the situation where I should filter on “No category”.
To manage the query function itself, there are a number of filters available. The one I thought were the most promising were: “posts_search“, “posts_where“, “posts_where_request“, “posts_request” and “posts_results“. The first parameter of these hooks is either a part of the query or the results. Manipulating these values didn’t seem to work, looking at the remainder of the query processing. The second parameter is a reference to the query parameters directly. This looked more promising as I could recognise the parameters generated by the filter requests. I could also manipulate the parameters within the function but soon found out that these changes didn’t propagate to the parameter processing after the filter hook was processed. So after a couple of hours trying to get this working, I tried a different approach.
A second analysis showed that the _REQUEST parameters are parsed before they are passed to the WP_Query processing. For the manipulation of these parameters, there is a filter hook “request“. Using the same analysis as described above, I could determine when a media filter action is required. The approach that worked is the following:
- Find all media attachment ids that do have at least one category assigned.
- Exclude all attachment posts found using the “post__not_in” parameter.
- Change the filter settings to find all attachments.
The resulting WP_Query will find all attachments and exclude all attachments with a category assigned. Which is exactly what I was looking for.
Now for the grid view
The solution above only proved to work for the list view as that works with a round-trip page refresh. The filter on the grid view works with an Ajax function, which is a bit different. The analysis I did before helped with the solution for this option. Adding the new “No category” option was different, the analysis for the filter action was similar. The Ajax function used a “tax_query” for generating the results. The approach is the same as described above: find all media with a category and exclude them using “operator” = “NOT IN”.