Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

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?

share|improve this question

1 Answer 1

up vote 1 down vote accepted

You can use pre_get_posts to filter the query.

So you can

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

To give an UI you can use 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 ) ) ? wp_list_pluck($posts, 'ID') : false;
  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 );
}

Negative of this code is that you have to rune 3 queries to filter the media...

Result on UI:

enter image description here

share|improve this answer
    
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 '13 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 –  G. M. Dec 18 '13 at 15:15
    
thanks! Worked great! Any suggestions for this question I had? –  whodeee Dec 18 '13 at 15:37
    
@G.M. : get_current_screen only works on the backend but pre_get_posts runs front and back. You need an is_admin check. –  s_ha_dum Jan 6 at 15:05

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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