1

I am using a custom post type to add/display PDF documents (posts) on my website.

taxonomy - wpl_documents_category

post type - post_documents

All is working well. However, I want to display the posts exclusively in their category - whether it be in a parent or child category.

Example Below

Hierarchy: Parent Cat -> Child Cat 1 -> Child Cat 2

Post Name: Dummy Doc

Post Category: Child Cat 2

By default, WordPress will show this post in all 3x levels. However, what I want is to display it in the category it belongs to (Child Cat 2) only.

Query Below

<?php if ( $wp_query->have_posts() ) : while ( $wp_query->have_posts() ) : $wp_query->the_post(); ?>

I can't figure this out and have tried various methods/solutions, but to no avail.

Any ideas/information on the above is greatly appreciated!

EDIT

Complete Query

<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<?php
$pid = $post->ID;
$document_file = get_post_meta( $pid, 'wpl_document_file', true);
$document_file_size = get_post_meta( $pid, 'wpl_document_file_size', true);
$document_authors = get_post_meta( $pid, 'wpl_document_authors', true);
?>

HTML markup goes here with calls to echo the above information

Display Categories

<?php $term = get_term_by( 'slug', get_query_var( 'term' ), get_query_var( 'taxonomy' ) ); if ($term->parent == 0) { ?>
<?php wp_list_categories('taxonomy=wpl_documents_category&depth=1&title_li=&child_of=' . $term->term_id); ?>

Here is my complete archive-post_documents.php

<?php
/**
 * The default template for displaying documents archive
 *
 * @package WordPress
 */
?>

<?php get_header(); ?>
<div id="main" class="site-main container_12">
    <div id="primary" class="content-area ms grid_12"> 
        <div id="content" class="site-content">    
            <?php if (category_description( $category ) == '') { ?>
            <?php } else { ?>
            <article class="single">
                <div id="subcats" class="entry-content">          
                    <h2>Description</h2>
                    <?php echo category_description( $category_id ); ?>
                </div> 
            </article> 
            <?php } ?>             
            <?php
                $term = get_queried_object();
                $children = get_terms( $term->taxonomy, array(
                'parent'    => $term->term_id,
                'hide_empty' => 0,
                'show_count' => 0
                ) );
            if($children) {
            ?>
            <article class="single">
                <div id="subcats" class="entry-content">             
                    <?php 
                    $term = get_term_by( 'slug', get_query_var( 'term' ), get_query_var( 'taxonomy' ) ); 
                    if ($term->parent == 0) { ?>
                    <h2>Browse Sub-categories:</h2> 
                    <ul>
                        <?php wp_list_categories('taxonomy=wpl_documents_category&depth=1&title_li=&child_of=' . $term->term_id); ?>
                    </ul>   
                        <?php } else { ?>
                    <h2>Browse Sub-categories:</h2> 
                    <ul>
                        <?php wp_list_categories('taxonomy=wpl_documents_category&&title_li=&child_of=' . $term->term_id); } ?>
                    </ul>     
                </div> 
            </article> 
            <?php } ?>             
            <div>&nbsp;</div>
        </div>    
    
        <div id="content" class="site-content js-masonry">
            <?php if ( have_posts() ) : ?>
            <?php while ( have_posts() ) : the_post(); ?>
            <?php //if ( $wp_query->have_posts() ) : while ( $wp_query->have_posts() ) : $wp_query->the_post(); ?>
                <?php
                    $pid = $post->ID;
                    $document_file = get_post_meta( $pid, 'wpl_document_file', true);
                    $document_file_size = get_post_meta( $pid, 'wpl_document_file_size', true);
                    $document_authors = get_post_meta( $pid, 'wpl_document_authors', true);
                    $icon = wplook_get_icon_name($document_file);
                ?>

                    <article id="post-<?php the_ID(); ?>" <?php post_class('item'); ?>>
                        <?php if ( has_post_thumbnail() ) {?> 
                            <figure>
                                <a title="<?php the_title();?>" href="<?php echo $document_file; ?>" download="<?php preg_replace("/[^a-zA-Z0-9_-]/", "", the_title);?>">
                                    <?php the_post_thumbnail('document-image'); ?>
                                </a>
                            </figure>
                        <?php } else {?> 
                            <figure>
                                <a title="<?php the_title();?>" href="<?php echo $document_file; ?>" download="<?php preg_replace("/[^a-zA-Z0-9_-]/", "", the_title);?>">
                                    <img data-lazy-loaded="true" style="display: block;" src="http://www.absa.asn.au/absainc/wp-content/uploads/2014/09/pdficon-260x173.jpg" class="attachment-document-image wp-post-image" alt="pdficon" height="173" width="260">
                                </a>
                            </figure>
                        <?php } ?>
                        
                        <div class="box-conten-margins">
                            <h1 class="entry-header">
                                <a title="<?php the_title(); ?>" href="<?php echo $document_file; ?>" download="<?php preg_replace("/[^a-zA-Z0-9_-]/", "", the_title);?>"><?php the_title(); ?></a>
                            </h1>
                            
                            <div class="short-description">
                                <p><i class="<?php echo $icon; ?>"></i> <strong>Size:</strong> <span class="filesize"><?php echo $document_file_size; ?></span></p>
                                <?php if ($document_authors) { ?>
                                <p><strong>Author(s):</strong> <?php echo $document_authors; ?></p>
                                <?php } ?>
                            </div>
                            
                            <div class="clear"></div>
                            
                            <div class="entry-meta">
                                <a class="buttonsx" href="<?php echo $document_file; ?>" download="<?php preg_replace("/[^a-zA-Z0-9_-]/", "", the_title);?>"><i class="<?php echo $icon; ?>"></i> <?php _e('Download PDF', 'wplook'); ?></a>
                                <div class="clear"></div>
                            </div>
                            
                        </div>
                    </article>
            
            <?php endwhile; wp_reset_postdata(); ?>
            <?php else : ?>
                <p><?php _e('Sorry, there are no documents to list. This could either be because you are not an ABSA member or, there are simply no documents in this category.', 'wplook'); ?></p>
            <?php endif; ?>
                
        </div>
        <div class="pagination-grid">
            <?php wplook_content_navigation('postnav' ) ?>
        </div>
    </div>
    
    <div class="clear"></div>

</div><!-- #main .site-main -->
<?php get_footer(); ?>
4
  • Hi Pieter, No, I am not using any template redirect or include to set the terms. Thank you very much for all of your support with this. You've been a great help and I look forward to seeing what solution you come up with.
    – SamNabz
    Dec 15, 2014 at 11:38
  • Please see my update. Hope this works Dec 15, 2014 at 17:15
  • Hi Pieter, thank you for the very detailed post and solution! However, I haven't been able to try it yet as I am getting an error on this line: 'tax_query' => [ - any ideas?
    – SamNabz
    Dec 15, 2014 at 23:04
  • You should update your php version to atleast 5.4. PHP 5.2 and 5.3 is dead. Will update my code to make it work with older versions. I have used syntax that was only introduced in 5.4 Dec 16, 2014 at 6:55

1 Answer 1

0

Here is an interesting approach to this

CONCEPT

We need a term list where the posts is listed under the specific term, but using the conventional methods posts are listed under the parent, child and grandchild terms. What we want is to only list posts in the last term, if it is a grandchild, then the post should only be listed under the grandchild term

PROBLEMS WITH YOUR CURRENT CODE

As this is an archive page only that is not used as a taxonomy page, you have a couple of serious errors here. The following code

<div id="content" class="site-content">    
    <?php if (category_description( $category ) == '') { ?>
    <?php } else { ?>
    <article class="single">
        <div id="subcats" class="entry-content">          
            <h2>Description</h2>
            <?php echo category_description( $category_id ); ?>
        </div> 
    </article> 
    <?php } ?>             
    <?php
        $term = get_queried_object();
        $children = get_terms( $term->taxonomy, array(
        'parent'    => $term->term_id,
        'hide_empty' => 0,
        'show_count' => 0
        ) );
    if($children) {
    ?>
    <article class="single">
        <div id="subcats" class="entry-content">             
            <?php 
            $term = get_term_by( 'slug', get_query_var( 'term' ), get_query_var( 'taxonomy' ) ); 
            if ($term->parent == 0) { ?>
            <h2>Browse Sub-categories:</h2> 
            <ul>
                <?php wp_list_categories('taxonomy=wpl_documents_category&depth=1&title_li=&child_of=' . $term->term_id); ?>
            </ul>   
                <?php } else { ?>
            <h2>Browse Sub-categories:</h2> 
            <ul>
                <?php wp_list_categories('taxonomy=wpl_documents_category&&title_li=&child_of=' . $term->term_id); } ?>
            </ul>     
        </div> 
    </article> 
    <?php } ?>             
    <div>&nbsp;</div>
</div>  

should be deleted. It leads to a big list of bugs. If you turn debug on, you will see what I am talking about. This code will only work in a taxonomy or category template with a few tweaks, or if the archive page is actually used as a taxonomy page with the proper conditional tag.

WORKSFLOW

This is a very basic list that list terms in alphabetical order, regardless of parent, child or grandchild term

What we need to do is, get a list of all the posts for the specific post type in the archive specific to a taxonomy. This will be done using a tax_query with WP_Query. get_terms() will be used to get a list of the terms that belongs to the specified taxonomy. This will be used in the tax_query to get the posts.

I have decided to write a function that can be used globally to display the term list.

When all the posts are returned, we need to get the terms that each post belongs to. For this, we are making use of get_the_terms()

To make provision for posts that belongs to a parent and/or child and/or grandchild term, I have sorted the returned array of terms with usort according to term ID so that the last term in line appear first. This term will be the grandchild or child.

A post, however, cannot belong to two terms on the same level, for example have two child terms. When ever that happens, the term with the highest term ID will still be used

The first term in the sorted array will be used to create this list and add the post title under it

This new array that is created will be sorted with ksort so that the term list is sorted alphabetically. The posts are sorted according to post date

I have also added a transient to make the function faster and less resource intensive. This list will update every 24 hours, you can just change this as needed, make it longer. Choose a timelenght that correspond to how frequently you add new posts. If you add new posts weekly, make the transient time to expire once a week

To make sure that the list is updated whenever a post is deleted, published or updated, the transition_post_status action is used to delete the transient whenever a post is published, deleted or updated

LETS CODE

Here is the code, paste all this in your functions.php

function get_term_post_list( $taxonomy = 'category', $post_type = 'post' ) {

    if ( false === ( $q = get_transient( 'term_list' ) ) ) {

        $q = '';

        $term_ids = get_terms( $taxonomy, 'fields=ids' );
        if ( ! empty( $term_ids ) && ! is_wp_error( $term_ids ) ){

            $args = array( 
                'posts_per_page' => -1,
                'post_type' => $post_type,
                'fields' => 'names',
                'tax_query' => array(
                    array(
                        'taxonomy' => $taxonomy,
                        'field'    => 'term_id',
                        'terms'    => $term_ids,
                    ),
                ),
            );

            $query = new WP_Query($args); 
            ?><   
            if( $query->have_posts() ) {

                while ( $query->have_posts() ) { 

                    $query->the_post(); 

                    $a = '<a href="'. get_permalink() .'">' . get_the_title() .'</a>';

                    $all_terms = get_the_terms( $query->post->ID, $taxonomy );
                    $terms = array_values( $all_terms );        

                    usort( $terms, function ( $a, $b ) {
                        return ($a->term_id < $b->term_id) ? 1 : -1;
                    });

                    $b = ucfirst( $terms[0]->name );    

                    $q[$b][] = $a; // Create an array with the category names and post titles
                }

                /* Restore original Post Data */
                wp_reset_postdata();

            }

            ksort( $q );
        }

        set_transient( 'term_list', $q, 24 * HOUR_IN_SECONDS );
    }
    return $q;
}

add_action( 'transition_post_status', function ( $new_status, $old_status, $post )
{

    delete_transient( 'term_list' );

}, 10, 3 );

HOW TO USE

This is how the code will be used in your template file, archive-post_documents.php

$lists = get_term_post_list( $taxonomy = 'wpl_documents_category', $post_type = 'post_documents'  );
foreach ($lists as $key=>$values) {

    echo $key;

    echo '<ul>';
        foreach ($values as $value){
            echo '<li>' . $value . '</li>';
        }
    echo '</ul>';
}
4
  • Hi Pieter, Thanks for the reply. However, that all went a bit above my head.. Any chance you can simplify this by adding an example query I should use?
    – SamNabz
    Dec 11, 2014 at 22:14
  • Hi Pieter, Apologies for the late response. The information you asked for has been added to the original post.
    – SamNabz
    Dec 15, 2014 at 0:29
  • This is on its own page template - archive-post_documents.php You can download the full file here: expirebox.com/download/1de375947c31835120c433f94710c898.html
    – SamNabz
    Dec 15, 2014 at 4:53
  • See my update. Should work now with older php versions Dec 16, 2014 at 7:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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