Instantly share code, notes, and snippets.
Last active
August 29, 2015 13:58
-
Star
(1)
1
You must be signed in to star a gist -
Fork
(1)
1
You must be signed in to fork a gist
-
Save chipbennett/10013478 to your computer and use it in GitHub Desktop.
Breadcrumb Navigation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Add navigation breadcrumb | |
*/ | |
function wp_nav_breadcrumb( $args = array() ) { | |
$defaults = array( | |
'wrapper' => 'div', | |
'wrapper_id' => 'breadcrumbs', | |
'wrapper_class' => '', | |
'container' => 'nav', | |
'container_id' => 'crumbs', | |
'container_class' => '', | |
'current_before' => '<strong>', | |
'current_after' => '</strong>', | |
'delimiter' => ' » ', | |
'home_text' => __( 'Home' ), | |
'blog_text' => __( 'Blog' ), | |
'error404_text' => __( 'Page Not Found' ), | |
'search_text' => __( 'Search Results' ), | |
'category_archive_text' => __( 'Category Archive' ), | |
'tag_archive_text' => __( 'Tag Archive' ), | |
'post_format_archive_text' => __( 'Post Format Archive' ), | |
'tax_archive_text' => __( 'Taxonomy Archive' ), | |
'author_archive_text' => __( 'Posts Published By' ), | |
'date_archive_text' => __( 'Posts Published in %s' ), | |
'post_type_archive_text' => __( 'Post Type Archive' ), | |
'paged_archive_text' => sprintf( __( 'Page %s' ), get_query_var( 'paged' ) ), | |
'paged_post_text' => sprintf( __( 'Page %s' ), get_query_var( 'page' ) ), | |
'show_category_hierarchy' => true, | |
'show_tax_hierarchy' => true, | |
'show_page_hierarchy' => true, | |
'attachment_tax' => false, | |
'single_post_tax' => 'category', | |
'single_post_type_tax' => false, | |
'output' => 'string', | |
'echo' => true | |
); | |
/** | |
* Parse arguments | |
*/ | |
$args = wp_parse_args( $defaults, $args ); | |
/** | |
* Filter arguments | |
*/ | |
$args = apply_filters( 'wp_nav_breadcrumb_args', $args ); | |
$args = (object) $args; | |
/** | |
* Early filter override | |
*/ | |
$breadcrumbs = apply_filters( 'pre_wp_nav_breadcrumb', NULL ); | |
if ( NULL !== $breadcrumbs ) { | |
if ( $args->echo ) { | |
echo $breadcrumbs; | |
} else { | |
return $breadcrumbs; | |
} | |
} | |
/** | |
* Get breadcrumb context | |
*/ | |
$context = wp_nav_breadcrumb_context( $args ); | |
/** | |
* Construct the breadcrumbs array, with late filter override | |
*/ | |
$breadcrumbs = apply_filters( 'wp_nav_breadcrumb', wp_nav_breadcrumb_construct( $args, $context ) ); | |
/** | |
* Output breadcrumb | |
*/ | |
$output = ( 'string' == $args->output ? implode( '', array_values( $breadcrumbs ) : $breadcrumbs ); | |
if ( $args->echo && 'string' == $args->output ) { | |
echo $output; | |
} else { | |
return $output; | |
} | |
} | |
/** | |
* Get breadcrumb context | |
*/ | |
function wp_nav_breadcrumb_context( $args ) { | |
$defaults = array( | |
'base_link' => '<a href="' . home_url( '/' ) . '">' . $args->home_text . '</a>', | |
'hierarchy' => $args->delimiter, | |
'current_location' => '', | |
'pagination' => false | |
); | |
// Base link | |
if ( is_front_page() ) { | |
$context = wp_parse_args( | |
$defaults, | |
apply_filters( 'wp_nav_breadcrumb_front_page', array( | |
'base_link' => false, | |
'hierarchy' => false, | |
'current_location' => $defaults->base_link | |
) ) | |
); | |
} | |
// Define current location for 404 Error page | |
elseif ( is_404() ) { | |
$context = wp_parse_args( | |
$defaults, | |
apply_filters( 'wp_nav_breadcrumb_404', array( | |
'hierarchy' => false, | |
'current_location' => $args->error404_text | |
) ) | |
); | |
} | |
// Define current location for Search Results page | |
elseif ( is_search() ) { | |
$context = wp_parse_args( | |
$defaults, | |
apply_filters( 'wp_nav_breadcrumb_search', array( | |
'hierarchy' => $args->search_textt . $args->delimiter, | |
'current_location' => get_search_query() | |
) ) | |
); | |
} | |
// Define current location for the blog posts index | |
elseif ( is_home() ) ) { | |
$context = wp_parse_args( | |
$defaults, | |
apply_filters( 'wp_nav_breadcrumb_blog', array( | |
'hierarchy' => false, | |
'current_location' => ( ! is_paged() ? $args->blog_text : '<a href="' . get_permalink( get_option( 'page_for_posts' ) ) . '">' . $args->blog_text . '</a>' ); | |
) ) | |
); | |
} | |
// Define current location for archive pages | |
elseif( is_archive() ) { | |
// Define Category Hierarchy Crumbs for Category Archive | |
if ( is_category() ) { | |
$hierarchy = $args->category_archive_text . $args->delimiter; | |
if ( $args->show_category_hierarchy ) { | |
global $wp_query; | |
$cat_obj = $wp_query->get_queried_object(); | |
$cat = get_category( $cat_obj->term_id ); | |
$parentCat = get_category ($cat->parent ); | |
if ( $cat->parent != 0 ) { | |
$hierarchy .= get_category_parents( $parentCat, TRUE, $args->delimiter ); | |
} | |
} | |
$context = wp_parse_args( | |
$defaults, | |
apply_filters( 'wp_nav_breadcrumb_category', array( | |
'hierarchy' => $hierarchy, | |
'current_location' => single_cat_title( '' , FALSE ) | |
) ) | |
); | |
} | |
// Define current location for Tag Archives | |
elseif ( is_tag() ) { | |
$context = wp_parse_args( | |
$defaults, | |
apply_filters( 'wp_nav_breadcrumb_tag', array( | |
'hierarchy' => $args->tag_archive_text . $args->delimiter, | |
'current_location' => single_tag_title( '' , FALSE ) | |
) ) | |
); | |
} | |
// Define current location for Post Format Archives | |
elseif ( is_tax( 'post_format' ) ) { | |
$context = wp_parse_args( | |
$defaults, | |
apply_filters( 'wp_nav_breadcrumb_post_format', array( | |
'hierarchy' => $args->post_format_archive_text . $args->delimiter, | |
'current_location' => get_post_format_string( get_post_format() ) | |
) ) | |
); | |
} | |
// Define current location for Custom Taxonomy Archives | |
elseif ( is_tax() ) { | |
$hierarchy = $args->tax_archive_text . $args->delimiter; | |
if ( $args->show_tax_hierarchy ) { | |
global $wp_query; | |
$custom_tax = $wp_query->query_vars['taxonomy']; | |
$custom_tax_object = get_taxonomy( $custom_tax ); | |
$post_type_object = get_post_type_object( get_post_type() ); | |
$custom_tax_link = '<a href="' . get_post_type_archive_link( $post_type_object->name ) . '">' . $post_type_object->labels->name . '</a>'; | |
$hierarchy = $custom_tax_link . $args->delimiter . $args->tax_archive_text . $args->delimiter; | |
} | |
$context = wp_parse_args( | |
$defaults, | |
apply_filters( 'wp_nav_breadcrumb_tax', array( | |
'hierarchy' => $hierarchy, | |
'current_location' => single_term_title( '', false ); | |
) ) | |
); | |
} | |
// Define current location for Author Archives | |
elseif ( is_author() ) { | |
$context = wp_parse_args( | |
$defaults, | |
apply_filters( 'wp_nav_breadcrumb_author', array( | |
'hierarchy' => $args->author_archive_text . $args->delimiter;, | |
'current_location' => get_the_author_meta( 'display_name', get_query_var( 'author' ) ) | |
) ) | |
); | |
} | |
// Define Crumbs for Day/Year/Month Date-based Archives | |
elseif ( is_date() ) { | |
$year_string = sprintf( | |
'<a href="%1$s">%2$s</a>', | |
get_year_link( get_the_time( 'Y' ) ), | |
get_the_time( 'Y' ) | |
); | |
$month_string = sprint( | |
'<a href="%1$s">%2$s</a>', | |
get_month_link( get_the_time( 'Y' ), get_the_time( 'm' ) ), | |
get_the_time( 'F' ) | |
); | |
// Define Year/Month Hierarchy Crumbs for Day Archive | |
if ( is_day() ) { | |
$date_string = $year_string . $args->delimiter . $month_string . $args->delimiter; | |
$currentLocation = get_the_time('d'); | |
} | |
// Define Year Hierarchy Crumb for Month Archive | |
elseif ( is_month() ) { | |
$date_string = $year_string . $args->delimiter; | |
$currentLocation = get_the_time( 'F' ); | |
} | |
// Set CurrentLocation for Year Archive | |
elseif ( is_year() ) { | |
$date_string = ''; | |
$currentLocation = get_the_time( 'Y' ); | |
} | |
$context = wp_parse_args( | |
$defaults, | |
apply_filters( 'wp_nav_breadcrumb_date', array( | |
'hierarchy' => sprintf( $args->date_archive_text, $date_string ), | |
'current_location' => $currentLocation | |
) ) | |
); | |
} | |
// Define current location for Custom Post Type Archives | |
elseif ( is_post_type_archive( get_post_type() ) ) { | |
$post_type_object = get_post_type_object( get_post_type() ); | |
$context = wp_parse_args( | |
$defaults, | |
apply_filters( 'wp_nav_breadcrumb_post_type_archive', array( | |
'hierarchy' => $args->post_type_archive_text . $args->delimiter, | |
'current_location' => $post_type_object->labels->name | |
) ) | |
); | |
} | |
// Define pagination for paged Archive pages | |
if ( get_query_var( 'paged' ) ) { | |
$context['pagination'] = $args->delimiter . $args->paged_archive_text; | |
} | |
} | |
// Define current location for singular pages | |
elseif ( is_singular() ) { | |
if ( is_page() & ! is_front_page() ) { | |
$context = wp_parse_args( | |
$defaults, | |
apply_filters( 'wp_nav_breadcrumb_page', array( | |
'hierarchy' => ( $args->show_page_hierarchy ? wp_nav_breadcrumb_page_hierarchy( $args->delimiter ) : false ), | |
'current_location' => get_the_title() | |
) ) | |
); | |
} | |
// Define Category and Parent Post Crumbs for Post Attachments | |
elseif ( is_attachment() ) { | |
if ( $args->attachment_tax ) { | |
if ( 'category' == $args->attachment_tax ) { | |
$hierarchy = wp_nav_breadcrumb_cat_hierarchy( $args->delimiter ); | |
} else if ( 'post_tag' == $args->attachment_tax ) { | |
$hierarchy = wp_nav_breadcrumb_tag_hierarchy( $args->delimiter ); | |
} else if ( 'post_format' == $args->attachment_tax ) { | |
$hierarchy = wp_nav_breadcrumb_post_format_hierarchy( $args->delimiter ); | |
} else { | |
$hierarchy = wp_nav_breadcrumb_tax_hierarchy( $args->attachment_tax, $args->delimiter ); | |
} | |
} | |
// Get parent post | |
global $post; | |
$parent = get_post( $post->post_parent ); | |
$hierarchy .= '<a href="' . get_permalink ( $parent->ID ) . '">' . $parent->post_title . '</a> ' . $args->delimiter; | |
$context = wp_parse_args( | |
$defaults, | |
apply_filters( 'wp_nav_breadcrumb_attachment', array( | |
'hierarchy' => $hierarchy, | |
'current_location' => get_the_title() | |
) ) | |
); | |
} | |
// Define Category Hierarchy Crumbs for Single Posts | |
elseif ( is_singular( 'post' ) ) { | |
if ( $args->single_post_tax ) { | |
if ( 'category' == $args->single_post_tax ) { | |
$hierarchy = wp_nav_breadcrumb_cat_hierarchy( $args->delimiter ); | |
} else if ( 'post_tag' == $args->single_post_tax ) { | |
$hierarchy = wp_nav_breadcrumb_tag_hierarchy( $args->delimiter ); | |
} else if ( 'post_format' == $args->single_post_tax ) { | |
$hierarchy = wp_nav_breadcrumb_post_format_hierarchy( $args->delimiter ); | |
} else { | |
$hierarchy = wp_nav_breadcrumb_tax_hierarchy( $args->single_post_tax, $args->delimiter ); | |
} | |
} | |
$context = wp_parse_args( | |
$defaults, | |
apply_filters( 'wp_nav_breadcrumb_single_blog_post', array( | |
'hierarchy' => $hierarchy, | |
'current_location' => get_the_title() | |
) ) | |
); | |
} | |
// Define current location for Custom Post Types | |
elseif ( is_singular( get_post_type() ) ) { | |
$post_type_object = get_post_type_object( get_post_type() ); | |
$hierarchy .= '<a href="' . get_post_type_archive_link( $post_type_object->name ) . '">' . $post_type_object->labels->name . '</a>' . $args->delimiter; | |
if ( $args->single_post_type_tax ) { | |
global $post; | |
if ( $args->single_post_type_tax && in_array( $post->post_type, get_object_taxonomies( $post->post_type, $args->single_post_type_tax ) ) ) { | |
$hierarchy .= wp_nav_breadcrumb_tax_hierarchy( $args->single_post_type_tax, $args->delimiter ); | |
} else { | |
$taxonomies = get_object_taxonomies( get_post_type() ); | |
$tax = ( ! empty( $taxonomies ) ? $taxonomies[0] : false ); | |
if ( $tax ) { | |
$hierarchy .= wp_nav_breadcrumb_tax_hierarchy( $tax, $args->delimiter ); | |
} | |
} | |
} | |
$context = wp_parse_args( | |
$defaults, | |
apply_filters( 'wp_nav_breadcrumb_single_post_type', array( | |
'hierarchy' => $hierarchy, | |
'current_location' => get_the_title() | |
) ) | |
); | |
} | |
// Define pagination for singular pages | |
if ( get_query_var( 'page' ) ) { | |
$context['pagination'] = $args->delimiter . $args->paged_post_text; | |
} | |
} | |
// Return $context | |
return ( isset( $context ) ? $context : $defaults ); | |
} | |
/** | |
* Breadcrumb construct | |
*/ | |
function wp_nav_breadcrumb_construct( $args, $context ) { | |
$breadcrumbs = array(); | |
// Opening wrapper | |
$wrapper_id = ( $args->wrapper_id ? ' id="' . esc_attr( $args->wrapper_id ) . '"'; | |
$wrapper_class = ( $args->wrapper_class ? ' class="' . esc_attr( $args->wrapper_class ) . '"'; | |
$breadcrumbs['wrapper_open'] = '<' . $args->wrapper . $wrapper_id . $wrapper_class . '>'; | |
// Opening container | |
$container_id = ( $args->container_id ? ' id="' . esc_attr( $args->container_id ) . '"'; | |
$container_class = ( $args->container_class ? ' class="' . esc_attr( $args->container_class ) . '"'; | |
$breadcrumbs['container_open'] = '<' . $args->container . $container_id . $container_class . '>'; | |
// Base link | |
if ( $context['base_link'] ) { | |
$breadcrumbs['base_link'] = $context['base_link']; | |
} | |
// Contextual hierarchy | |
$breadcrumbs['hierarchy'] = $context['hierarchy']; | |
// Opening element that wraps the current page breadcrumb link | |
$breadcrumbs['current_before'] = $args->current_before; | |
// Current location | |
$breadcrumbs['current_location'] = $context['current_location']; | |
//Closing element that wraps the current page breadcrumb link | |
$breadcrumbs['current_after'] = $args->current_after; | |
// Pagination | |
if ( $context['pagination'] ) { | |
$breadcrumbs['pagination'] = $context['pagination']; | |
} | |
// Closing element that wraps entire breadcrumb output | |
$breadcrumbs['container_close'] = '</' . $args->container . '>'; | |
// Closing breadcrumb element | |
$breadcrumbs['wrapper_close'] = '</' . $args->wrapper . '>'; | |
// Return $breadcrumbs | |
return $breadcrumbs; | |
} | |
/** | |
* Page hierarchy | |
*/ | |
function wp_nav_breadcrumb_page_hierarchy( $delimiter ) { | |
global $post; | |
if ( ! $post->post_parent ) { | |
return false; | |
} else { | |
$hierarchy = false; | |
$parent_id = $post->post_parent; | |
$pagecrumbs = array(); | |
while ( $parent_id ) { | |
$page = get_page( $parent_id ); | |
$pagecrumbs[] = '<a href="' . get_permalink( $page->ID ) . '">' . get_the_title( $page->ID ) . '</a>'; | |
$parent_id = $page->post_parent; | |
} | |
$pagecrumbs = array_reverse( $pagecrumbs ); | |
foreach ( $pagecrumbs as $crumb ) { | |
$hierarchy .= $crumb . $delimiter; | |
} | |
return $hierarchy; | |
} | |
} | |
/** | |
* Category hierarchy | |
*/ | |
function wp_nav_breadcrumb_cat_hierarchy( $delimiter ) { | |
global $post; | |
// Ensure post type supports 'category' taxonomy | |
if ( ! in_array( $post->post_type, get_object_taxonomies( $post->post_type, 'category' ) ) ) { | |
return false; | |
} else { | |
$hierarchy = false; | |
$cats = get_the_category(); | |
$cat = ( ! empty( $cats ) ? $cats[0] : false ); | |
// Determine if category is hierarchical | |
if ( $cat ) { | |
$hierarchy .= get_category_parents( $cat->ID, TRUE, $delimiter ); | |
} | |
return $hierarchy; | |
} | |
} | |
/** | |
* Tag hierarchy | |
*/ | |
function wp_nav_breadcrumb_tag_hierarchy( $delimiter ) { | |
global $post; | |
// Ensure post type supports 'post_tag' taxonomy | |
if ( ! in_array( $post->post_type, get_object_taxonomies( $post->post_type, 'post_tag' ) ) ) { | |
return false; | |
} else { | |
$tags = get_the_tags( $post->ID ); | |
if ( ! $tags ) { | |
return false; | |
} | |
return '<a href="' . get_tag_link( $tags[0]->ID ) . '">' . $tags[0]->name . '</a>' . $delimiter; | |
} | |
} | |
/** | |
* Post Format hierarchy | |
*/ | |
function wp_nav_breadcrumb_post_format_hierarchy( $delimiter ) { | |
global $post; | |
// Ensure post type supports 'post_tag' taxonomy | |
if ( ! in_array( $post->post_type, get_object_taxonomies( $post->post_type, 'post_format' ) ) || ! get_post_format( $post->ID ) ) { | |
return false; | |
} else { | |
$post_format = get_post_format( $post->ID ); | |
return '<a href="' . get_post_format_link( $post_format ) . '">' . get_post_format_string( $post_format ) . '</a>' . $delimiter; | |
} | |
} | |
/** | |
* Tax hierarchy | |
*/ | |
function wp_nav_breadcrumb_tax_hierarchy( $tax, $delimiter ) { | |
global $post; | |
// Ensure post type supports 'category' taxonomy | |
if ( ! in_array( $post->post_type, get_object_taxonomies( $post->post_type, $tax ) ) ) { | |
return false; | |
} else { | |
$hierarchy = false; | |
$terms = get_the_terms( $post->ID, $tax ); | |
if ( ! $terms ) { | |
return false; | |
} | |
if ( $terms[0]->parent ) { | |
// Get term hierarchy | |
$parent_id = $terms[0]->parent; | |
$term_crumbs = array(); | |
while ( $parent_id ) { | |
$crumb = get_term_by( 'id', $parent_id, $tax ); | |
$term_crumbs[] = '<a href="' . get_term_link( $crumb->term_id ) . '">' . $crumb->name . '</a>'; | |
$parent_id = $crumb->parent; | |
} | |
$term_crumbs = array_reverse( $term_crumbs ); | |
foreach ( $term_crumbs as $crumb ) { | |
$hierarchy .= $crumb . $delimiter; | |
} | |
} | |
$hierarchy .= '<a href="' . get_term_link( $terms[0]->ID ) . '">' . $terms[0]->name . '</a>' . $delimiter; | |
return $hierarchy; | |
} | |
} |
Added args array and defaults, in preparation of making args array filterable, and refactoring.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Broke out contextual breadcrumbs into subordinate functions. H/T @Kaiser