Skip to content

Instantly share code, notes, and snippets.

@julien731
Last active December 22, 2015 08:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save julien731/6448820 to your computer and use it in GitHub Desktop.
Save julien731/6448820 to your computer and use it in GitHub Desktop.
Generates a very customizable breadcrumb for WordPress. It supports all kind of content (pages, posts, archives, CPT...).
<?php
/**
* Generates a breadcrumb for WordPress
*
* This function will generate a very customizable breadcrumb
* for WordPress. It supports all kind of content (pages, posts,
* archives, CPT...).
*
* @author Julien Liabeuf <julien@liabeuf.fr>
* @copyright 2013 ThemeAvenue
* @package ThemeAvenue Framework
* @param (array) $args Breadcrumb parameters
* @since 3.0
*/
function tav_breadcrumbs( $args = array() ) {
global $post, $wp_query;
/* Prepare default arguments */
$defaults = array(
'front_page_label' => __( 'Home', 'tav' ),
'home_page_label' => __( 'Blog', 'tav' ),
'search_results_label' => __( 'Search', 'tav' ),
'page_404_label' => __( 'Not Found', 'tav' ),
'show_current_page' => true,
'link_current_page' => false,
'show_on_front' => false,
'show_on_home' => true,
'link_on_home' => true,
'container' => 'div',
'container_id' => '',
'container_class' => '',
'container_attr' => '',
'home_url' => home_url(),
'item_before' => '',
'item_after' => '',
'home_before' => false, // If false, item_before will be used instead
'home_after' => false, // If false, item_after will be used instead
'link_attr' => '',
'delimiter' => ' / '
);
/**
* Let's merge the default settings
* with the user defined ones and return
* each option in a variable.
*/
extract(
shortcode_atts(
$defaults,
$args
)
);
$open = ''; // Breadcrumb opening tag
$close = ''; // Breadcrumb closing tag
$items = array(); // We will store the items to be imploded later
$first = ''; // First item label
$home_before = !$home_before ? $item_before : $home_before;
$home_after = !$home_after ? $item_after : $home_after;
/**
* We identify which is the homepage.
*/
$home = get_option( 'page_on_front', false );
/**
* If the current page is the front page
* and breadcrumb is hidden on this page,
* we return nothing.
*/
if( is_front_page() && !$show_on_front ) {
return;
}
if( is_home() && !$show_on_home ) {
return;
}
/* Open the breadcrumbs container */
$open .= '<' . $container;
/* Add the container ID if defined */
if( '' != $container_id ) {
$open .= ' id="' . $container_id . '"';
}
/* Add the container class if defined */
if( '' != $container_class ) {
$open .= ' class="' . $container_class . '"';
}
/* Then we close the opening tag */
$open .= '>';
/* Preapare the closing tag. Easy! */
$close .= '</' . $container . '>';
/**
* Now we need to prepare the first
* item which will depend on the page on front
* we identified earlier as $home
*/
$first = ( $home ) ? $front_page_label : $home_page_label;
/* If the link must be displayed on the first item we add it now */
if( $link_on_home ) {
$first = '<a href="' . $home_url . '" class="home" ' . $link_attr . '>' . $first . '</a>';
}
/* Add the before and after elements to first item */
$first = $home_before . $first . $home_after;
/* The first item is now ready, it's time to add it to the items list */
array_push( $items, $first );
/**
* Let's go through the items now...
*/
if( is_archive() ) {
if( is_tax() ) {
if( isset( $wp_query->queried_object ) ) {
$item = $wp_query->queried_object->name;
$slug = $wp_query->queried_object->slug;
/* Get item label to display */
$label = apply_filters( "tav_bc_label_$slug", $wp_query->queried_object->name );
if( $link_current_page ) {
$item = '<a href="' . get_term_link( $wp_query->queried_object ) . '" ' . $link_attr . '>' . $label . '</a>';
}
$parent_tax = $wp_query->queried_object->parent; // Get parent ID
$taxonomy = $wp_query->queried_object->taxonomy; // Get taxonomy
$parent_label = array(); // Prepare parents array
/* Iterate through parent terms */
for( $ptax = $parent_tax; $ptax != 0; $ptax = $parent_tax ) {
$parent_object = get_term( $parent_tax, $taxonomy );
$parent_slug = $parent_object->slug;
$label = apply_filters( "tav_bc_label_$parent_slug", $parent_object->name );
$parent_tax = $parent_object->parent;
$parent_label[] = array( 'object' => $parent_object, 'label' => $label );
}
}
} elseif( is_post_type_archive() ) {
if( isset( $wp_query->queried_object ) ) {
$item = $wp_query->queried_object->label;
$slug = $wp_query->queried_object->name;
$label = apply_filters( "tav_bc_label_$slug", $wp_query->queried_object->label );
if( $link_current_page ) {
$item = '<a href="' . get_post_type_archive_link( $wp_query->queried_object->name ) . '" ' . $link_attr . '>' . $label . '</a>';
}
}
}
} elseif( is_single() ) {
$item = esc_html( $post->post_title );
$cats = get_the_category( $post->ID );
$family = array();
$highest = 0;
$keep = false;
/* If this post has categorie(s) */
if( !empty( $cats ) ) {
foreach( $cats as $key => $cat ) {
$tax = $cat->taxonomy;
$curr_id = $cat->term_id;
$parents = array();
while ( $cat->parent != 0 ) {
$cat = get_term( $cat->parent, $tax );
$parents[] = $cat;
}
// $parents = array_reverse( $parents );
$family[$curr_id] = $parents;
}
if( is_array( $family ) && !empty( $family ) ) {
foreach( $family as $ct => $dat ) {
$count = count( $dat );
if( $count > $highest ) {
$highest = $count;
$keep = $ct;
}
}
}
if( is_array( $family[$keep] ) && !empty( $family[$keep] ) ) {
foreach( $family[$keep] as $categorie => $object ) {
$slug = $object->slug;
$label = apply_filters( "tav_bc_label_$slug", $object->name );
$parent_label[] = array( 'object' => $object, 'label' => $label );
}
}
}
/* Now let's check if the post is a custom post type */
if( !in_array( $post->post_type, array( 'post', 'page' ) ) ) {
$pt = get_post_type_object( $post->post_type );
$link = apply_filters( 'tav_bc_link_parent_' . $post->post_type, get_post_type_archive_link( $post->post_type ) );
$parent_label = '<a href="' . $link . '">' . $pt->label . '</a>';
}
} elseif( is_page() ) {
/* Ok, we have the page name, easy... */
$item = $post->post_title;
/* Current page is the first children */
$upper = $post->post_parent;
/* Now let's find all possible parent pages */
for( $i = 0; $upper != 0; $i++ ) {
$new_page = get_post( $upper );
$parent_label[] = array( 'id' => $new_page->ID, 'label' => $new_page->post_title );
$upper = $new_page->post_parent;
}
} elseif( is_404() ) {
/* 404 is a very easy case, isn't it? */
$item = $page_404_label;
} else {
}
$item = $item_before . $item . $item_after;
/* If there's a parent item let's handle it */
if( isset( $parent_label ) && $parent_label ) {
/* In case we have multiple parents, let's add them all */
if( is_array( $parent_label ) ) {
/* Normally it goes from children to parents. We want the reverse order. */
$parent_label = array_reverse( $parent_label );
foreach( $parent_label as $key => $parent ) {
if( is_single() || is_tax() ) {
$link = apply_filters( "tav_bc_link_cat_", get_term_link( $parent['object'] ) );
} elseif( is_page() ) {
$link = get_permalink( $parent['id'] );
} else {
$link = '#';
}
$parent_tmp = $item_before . '<a href="' . $link . '" ' . $link_attr . '>' . $parent['label'] . '</a>' . $item_after;
/* Add it to the list */
array_push( $items, $parent_tmp );
}
} else {
/* Finalize the item */
$parent_label = $item_before . $parent_label . $item_after;
/* Add it to the list */
array_push( $items, $parent_label );
}
/* Reset parent */
$parent_label = false;
}
/* Now we can add the (child) item */
array_push( $items, $item );
/**
* Now that all items are ready, it's time
* to merge them all and add the delimiter
* between all of them.
*/
$items = implode( $delimiter, $items );
/**
* SHOW TIME!
* We now echo all the markup. First the opening tag
* we prepared at the begining of the function, then
* the items we just imploded, and finally
* the closing tag.
*/
echo $open . $items . $close;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment