6

I am trying to find a way to filter the Media Library by the Post Category that a Media item is assigned with. I can see that you can sort by "attached to" but this only get me a little of the way there. Any suggestions?

1 Answer 1

3

You can use pre_get_posts to filter the query.

So you can

  1. retrieve a category from query vars
  2. retrieve the post with that category
  3. set the media query to include only posts having that post as the parent

To give a UI, you can use the restrict_manage_posts hook to output a category dropdown.

add_action('pre_get_posts', 'my_filter_media_by_cat');
add_action( 'restrict_manage_posts', 'my_add_media_cat_dropdown' );

function my_filter_media_by_cat( $q ) {
  $scr = get_current_screen();
  $cat = filter_input(INPUT_GET, 'postcat', FILTER_SANITIZE_STRING );   
  if ( ! $q->is_main_query() || ! is_admin() || (int)$cat <= 0 || $scr->base !== 'upload' )
      return;
  // get the posts
  $posts = get_posts( 'nopaging=1&category=' . $cat );
  // get post ids
  $pids = empty( $posts ) ? false : wp_list_pluck($posts, 'ID');
  if ( ! empty($pids) ) {
    $pidsTxt = implode( ',', $pids );
    global $wpdb;
    // Get the ids of media having retrieved posts as parent
    $mids = $wpdb->get_col("SELECT ID FROM $wpdb->posts WHERE post_parent IN ($pidsTxt)");
    if ( ! empty($mids) ) {
      // Force media query to retrieve only media having retrieved posts as parent
      $q->set( 'post__in', $mids );
    } else {
      // force media query to return no posts
      $q->set( 'p', -1 ); // Let query found nothing
    }
  }
}

function my_add_media_cat_dropdown() {
  $scr = get_current_screen();
  if ( $scr->base !== 'upload' ) return;
  $cat = filter_input(INPUT_GET, 'postcat', FILTER_SANITIZE_STRING );   
  $selected = (int)$cat > 0 ? $cat : '-1';  
  $args = array(
      'show_option_none'   => 'All Post Categories',
      'name'               => 'postcat',
      'selected'           => $selected
  ); 
  wp_dropdown_categories( $args );
}

The negative of this code is that you have to run 3 queries to filter the media...

Result on UI:

enter image description here

7
  • thanks, I will check this out - looks like it is what I am looking for. One question though - where is postcat coming from in the my_add_media_cat_dropdown function
    – whodeee
    Dec 18, 2013 at 15:09
  • $cat = filter_input(INPUT_GET, 'postcat', FILTER_SANITIZE_STRING ); is an alternate (better and safer) way of $cat = $_GET['postcat'];. See PHP docs @whodeee
    – gmazzap
    Dec 18, 2013 at 15:15
  • thanks! Worked great! Any suggestions for this question I had?
    – whodeee
    Dec 18, 2013 at 15:37
  • 1
    gmazzap's solution inspired me to write a plugin to do this. You can now filter your media by Taxonomies and Terms with the Media Library Filter plugin.
    – Eric
    Jan 27, 2016 at 14:50
  • 1
    NOTE: $pidstxt = implode($pids, ','); to $pidstxt = implode( ',', $pids );
    – Litalino
    Jul 28, 2023 at 5:25

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