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 have a site with multiple custom post types and taxonomies. The taxonomies are shared across all of the post types.

On the archive page of the 'videos' post type, I want to show a list of all of the 'country' tags that are associated with videos. When this link is clicked on, I'd like to be able to go to an archive for that country but that only shows the 'videos', not the other post types that may have the same country tag.

I also need to be able to do the same for other post types and taxonomies, e.g. when on the 'galleries' post type archive, a tag cloud is shown that links to the tag archive showing only the galleries.

I think that this should be easy, but I just can't figure it out!

Will I need to create archive templates that take arguments passed via the url? E.g. mysite.com/country/canada?type=video

..and then manipulate the get_tags function somehow? I really just can't get my head around this one.

Cheers for your help.

share|improve this question
    
Probably by extending this core.trac.wordpress.org/browser/tags/3.3.1/wp-includes/…? Let us know if you do. –  soulseekah Mar 23 '12 at 14:37
add comment

3 Answers

up vote 2 down vote accepted

I've worked out a solution to this. I hope this can help someone else.

First add the following two functions to your functions.php (or plugin) file:

function get_terms_by_post_type( $taxonomies, $post_types ) {
    global $wpdb;
    $query = $wpdb->prepare( "SELECT t.*, COUNT(*) from $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id INNER JOIN $wpdb->term_relationships AS r ON r.term_taxonomy_id = tt.term_taxonomy_id INNER JOIN $wpdb->posts AS p ON p.ID = r.object_id WHERE p.post_type IN('".join( "', '", $post_types )."') AND tt.taxonomy IN('".join( "', '", $taxonomies )."') GROUP BY t.term_id");
    $results = $wpdb->get_results( $query );
    return $results;
}

function show_post_type_terms($taxonomy, $posttype = null ) {
    global $post;
    if(!isset($posttype)) $posttype = get_post_type( $post->ID );
    $terms = get_terms_by_post_type( array($taxonomy), array($posttype) );
    echo '<ul>';
    foreach($terms as $term) {
        $output = '<li><a href="'.get_bloginfo('url').'/'.$taxonomy.'/'.$term->slug.'/?post_type='.$posttype.'">'.$term->name.'</a></li>';
        echo $output;
    }
    echo '</ul>';
}

Now on your custom post type archive pages you can use <?php show_post_type_terms('country'); ?>, changing 'country' for the taxonomy that you wish to return.

The links created have a query appended to the end to return only the post type that you are currently viewing. If you are on a 'videos' archive page it will link to a taxonomy archive showing only video posts.

share|improve this answer
add comment

I think I can answer part of this. You need a filter in your functions.php to force the loop in your tag.php template to co-operate.

/**
 * Function and filter to force tag.php (tag archives) to display only video custom post types. 
 */
function add_custom_types_to_tag_archives( $query ) {
    if( is_tag() && empty( $query->query_vars['suppress_filters'] ) ) {
        $post_types = array( 'video' );
        $query->set( 'post_type', $post_types );
        return $query;
    }
}
add_filter( 'pre_get_posts', 'add_custom_types_to_tag_archives' ); 

Hope this helps. It's my first go at answering a question on here :)

share|improve this answer
    
Thanks for the answer. Would this method mean that only 'video' would ever be shown on a tag.php template? I'll need to be able to do this for all post types. E.g. I have a 'galleries' post type that I will need to do the same thing for. I.e. the tag cloud on the 'galleries' archive links to a tag archive showing only galleries. –  kdev Mar 28 '12 at 8:39
    
I guess you edit the code above to show both videos and galleries and then change the query for your loop in tag.php to show only one or the other. I don't know what sort of conditional you would use in tag.php though. Sorry. –  thegonzobeat Mar 29 '12 at 7:07
add comment

OK, I have a partial answer to my own question.

I can use the following to output a list of taxonomy terms with links showing only the current post type:

$args = array( 'taxonomy' => 'country' );

$terms = get_terms('country', $args);

$count = count($terms); $i=0;

if ($count > 0) {
    $term_list = '<ul class="my_term-archive">';
    foreach ($terms as $term) {
        $i++;
        $term_list .= '<li><a href="/country/' . $term->slug . '/?post_type='.get_post_type( $post->ID ).'" title="' . sprintf('View all posts filed under %s', $term->name) . '">' . $term->name . '</a></li>';
    }
    echo $term_list.'</ul>';
}

My remaining problem is that this still lists taxonomy terms that have no videos attached. E.g. maybe another post type has been given a 'country' tag of 'Canada'. Even if there are no 'videos' tagged with 'Canada', 'Canada' will still show up in this list.

share|improve this answer
add comment

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.