0

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.

0
0

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;
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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