Question

I'm building a product catalog site and I created a product custom post type and a related product_type taxonomy. I added some products and created the following product_type terms:

  • Books
    • Classics
    • Fantasy
    • Mystery
  • Toys
    • Puzzles
    • Dolls
    • Cars

When a user visits the catalog I want to show him a product_type terms navigation by level. That is, when he enters the main catalog page I only want him to see the first level of terms: Books, Toys and a special link named All that when clicked shows all products.

enter image description here

When the user clicks one of the root terms, for example, Books, I want to show its child terms in addition to the root terms, that is: Classics, Fantasy, Mystery and a special link named All that when clicked shows all products under the Books term.

enter image description here

Likewise, when the user clicks the Toys root term, I want to show the its child terms in addition to the root terms, that is: Puzzles, Dolls, Cars and a special link named All that when clicked shows all products under the Toys term.

enter image description here

I'm using the following recursive function to get all the terms hierarchically:

function get_taxonomy_hierarchy( $taxonomy, $parent = 0 ) {
    $taxonomy = is_array( $taxonomy ) ? array_shift( $taxonomy ) : $taxonomy;
    $terms = get_terms( $taxonomy, array( 'parent' => $parent ) );
    $children = array();
    foreach ( $terms as $term ){
        $term->children = get_taxonomy_hierarchy( $taxonomy, $term->term_id );
        $children[ $term->term_id ] = $term;
    }
    return $children;
}

But I'm hitting a wall trying to handle the All links in all of this structure because they are not actual terms per se. Any ideas would be appreciated.

Was it helpful?

Solution

I managed to find a solution myself. This code is to be used in taxonomy templates.

PHP:

function show_taxonomy_navigation( $post_type = 'post', $taxonomy = 'category', $parent = 0 ) {
    $html = get_taxonomy_hierarchy( $post_type, $taxonomy, $parent );
    echo $html;
}

function get_taxonomy_hierarchy( $post_type, $taxonomy, $parent = 0, $depth = 0 ) {
    $taxonomy = is_array( $taxonomy ) ? array_shift( $taxonomy ) : $taxonomy;
    $html = '';
    // get the id of the currently queried term
    $current_term_id = get_queried_object_id();
    $args = array(
        'taxonomy' => $taxonomy,
        'parent'   => $parent,
        'order_by' => 'name',
    );
    // Get the child terms of $parent
    $terms = get_terms( $args );
    if ( $terms ) {
        if ( $depth == 0 ) {
            $html .= '<nav class="taxonomy-navigation">';
        }
        $ul_classes = [];
        $ul_classes[] = 'terms';
        $html .= '<ul class="' . esc_attr( implode( ' ', array_filter( $ul_classes ) ) ) . '">';
        // Add 'All' link
        $all_link = ( $parent > 0 ) ? get_term_link( $parent ) : get_post_type_archive_link( $post_type );
        $html .= '<li><a href="' . $all_link . '">' . esc_html__( 'All', 'my-taxonomy-navigation' ) . '</a></li>';
        foreach ( $terms as $term ) {
            $li_classes = [];
            $li_classes[] = 'term-item';
            // Add class if term corresponds to the currently queried term
            $li_classes[] = ( $term->term_id == $current_term_id ) ? 'current-term' : null;
            // Add class if term is a parent of the currently queried term
            $li_classes[] = ( term_is_ancestor_of( $term->term_id, $current_term_id, $taxonomy ) ) ? 'current-term-parent' : '';
            $html .= '<li class="' . esc_attr( implode( ' ', array_filter( $li_classes ) ) ) . '">';
            $html .= '<a href="' . get_term_link( $term->term_id ) . '">' . $term->name . '</a>';
            // Recursively go deeper in the hierarchy
            $html .= get_taxonomy_hierarchy( $post_type, $taxonomy, $term->term_id, $depth + 1 );
            $html .= '</a>';
            $html .= '</li>';
        }
        $html .= '</ul>';
        if ( $depth == 0 ) {
            $html .= '</nav>';
        }
    }
    return $html;
}

CSS:

.taxonomy-navigation ul.terms {
    position: relative;
    list-style: none;
    text-align: center;
}

.taxonomy-navigation ul.terms li {
    display: inline-block;
    margin: 0;
    padding: 0 15px;
}

.taxonomy-navigation ul.terms li.current-term > a,
.taxonomy-navigation ul.terms li.current-term-parent > a {
    font-weight: 700;
}

.taxonomy-navigation ul.terms li ul.terms {
    display: none;
    position: absolute;
    top: auto;
    left: 0;
    right: 0;
    margin: 0 auto;
}

.taxonomy-navigation ul.terms li.current-term > ul.terms,
.taxonomy-navigation ul.terms li.current-term-parent > ul.terms {
    display: block;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with wordpress.stackexchange
scroll top