args = array(
'home' => __( 'Home', 'baltic' ),
'sep' => __( ' / ', 'baltic' ),
'list_sep' => ', ',
'prefix' => '',
'heirarchial_attachments' => true,
'heirarchial_categories' => true,
'labels' => array(
'prefix' => '',
'author' => '',
'category' => '',
'tag' => '',
'date' => '',
'search' => '',
'tax' => '',
'post_type' => '',
'404' => ''
)
);
}
/**
* Return the final completed breadcrumb in markup wrapper.
*
* @since 1.0.0
*
* @param array $args Breadcrumb arguments.
* @return string HTML markup for final completed markup.
*/
public function get_output( $args = array() ) {
/**
* Filter the Baltic breadcrumb arguments.
*
* @since 1.0.0
*
* @param array $args {
* Arguments for generating breadcrumbs.
*
* @type string $home Homepage link text.
* @type string $sep Separator.
* @type string $list_set List format separator.
* @type string $prefix Prefix before breadcrumb list.
* @type string $suffix Suffix after breadcrumb list.
* @type bool $heirarchial_attachments Whether attachments are hierarchical.
* @type bool $heirarchial_categories Whether categories are hierarchical.
* @type array $labels Labels including the following keys: 'prefix', 'author', 'category',
* 'tag', 'date', 'search', 'tax', 'post_type', '404'.
* }
*/
$this->args = apply_filters( 'baltic_breadcrumb_args', wp_parse_args( $args, $this->args ) );
return $this->args['prefix'] . $this->args['labels']['prefix'] . $this->build_crumbs() . $this->args['suffix'];
}
/**
* Echo the final completed breadcrumb in markup wrapper.
*
* @since 1.0.0
*
* @param array $args Breadcrumb arguments.
*/
public function output( $args = array() ) {
echo $this->get_output( $args ); // WPCS: XSS ok.
}
/**
* Return anchor link for a single crumb.
*
* @since 1.0.0
*
* @param string $url URL for href attribute.
* @param string $title Title attribute.
* @param string $content Linked content.
* @param bool|string $sep Optional. Separator. Default is empty string.
*
* @return string HTML markup for anchor link and optional separator.
*/
public function get_breadcrumb_link( $url, $title, $content, $sep = '' ) {
// Empty title, for backward compatibility.
$title = '';
$link = sprintf( '%s', esc_attr( $url ), esc_attr( $title ), esc_html( $content ) );
/**
* Filter the anchor link for a single breadcrumb.
*
* @since 1.0.0
*
* @param string $link HTML markup for anchor link, before optional separator is added.
* @param string $url URL for href attribute.
* @param string $title Title attribute.
* @param string $content Link content.
* @param array $args Arguments used to generate the breadcrumbs. Documented in Baltic_Breadcrumbs::get_output().
*/
$link = apply_filters( 'baltic_breadcrumb_link', $link, $url, $title, $content, $this->args );
if ( $sep ) {
$link .= $sep;
}
return $link;
}
/**
* Return the correct crumbs for this query, combined together.
*
* @since 1.0.0
*
* @return string HTML markup for the crumbs, combined together.
*/
protected function build_crumbs() {
$crumbs[] = $this->get_home_crumb();
if ( is_home() ) {
$crumbs[] = $this->get_blog_crumb();
} elseif ( is_search() ) {
$crumbs[] = $this->get_search_crumb();
} elseif ( is_404() ) {
$crumbs[] = $this->get_404_crumb();
} elseif ( is_page() ) {
$crumbs[] = $this->get_page_crumb();
} elseif ( is_archive() ) {
$crumbs[] = $this->get_archive_crumb();
} elseif ( is_singular() ) {
$crumbs[] = $this->get_single_crumb();
}
/**
* Filter the Baltic breadcrumbs.
*
* @since 1.0.0
*
* @param string $crumbs HTML markup for the breadcrumbs.
* @param array $args Arguments used to generate the breadcrumbs. Documented in Baltic_Breadcrumbs::get_output().
*/
$crumbs = apply_filters( 'baltic_build_crumbs', $crumbs, $this->args );
return implode( $this->args['sep'], array_filter( array_unique( $crumbs ) ) );
}
/**
* Return archive breadcrumb.
*
* @since 1.0.0
*
* @return string HTML markup for archive breadcrumb.
*/
protected function get_archive_crumb() {
if ( is_category() ) {
$crumb = $this->get_category_crumb();
} elseif ( is_tag() ) {
$crumb = $this->get_tag_crumb();
} elseif ( is_tax() ) {
$crumb = $this->get_tax_crumb();
} elseif ( is_year() ) {
$crumb = $this->get_year_crumb();
} elseif ( is_month() ) {
$crumb = $this->get_month_crumb();
} elseif ( is_day() ) {
$crumb = $this->get_day_crumb();
} elseif ( is_author() ) {
$crumb = $this->get_author_crumb();
} elseif ( is_post_type_archive() ) {
$crumb = $this->get_post_type_crumb();
}
/**
* Filter the Baltic archive breadcrumb.
*
* @since 1.0.0
*
* @param string $crumb HTML markup for the archive breadcrumb.
* @param array $args Arguments used to generate the breadcrumbs. Documented in Baltic_Breadcrumbs::get_output().
*/
return apply_filters( 'baltic_archive_crumb', $crumb, $this->args );
}
/**
* Get single breadcrumb, including any parent crumbs.
*
* @since 1.0.0
*
* @return string HTML markup for single breadcrumb, including any parent breadcrumbs.
*/
protected function get_single_crumb() {
if ( is_attachment() ) {
$crumb = $this->get_attachment_crumb();
} elseif ( is_singular( 'post' ) ) {
$crumb = $this->get_post_crumb();
} else {
$crumb = $this->get_cpt_crumb();
}
/**
* Filter the Baltic single breadcrumb.
*
* @since 1.0.0
*
* @param string $crumb HTML markup for the single breadcrumb.
* @param array $args Arguments used to generate the breadcrumbs. Documented in Baltic_Breadcrumbs::get_output().
*/
return apply_filters( 'baltic_single_crumb', $crumb, $this->args );
}
/**
* Return home breadcrumb.
*
* Default is Home, linked on all occasions except when is_home() is true.
*
* @since 1.0.0
*
* @return string HTML markup for home breadcrumb.
*/
protected function get_home_crumb() {
$url = $this->page_shown_on_front() ? get_permalink( get_option( 'page_on_front' ) ) : trailingslashit( home_url() );
$crumb = ( is_home() && is_front_page() ) ? $this->args['home'] : $this->get_breadcrumb_link( $url, '', $this->args['home'] );
/**
* Filter the Baltic home breadcrumb.
*
* @since 1.0.0
*
* @param string $crumb HTML markup for the home breadcrumb.
* @param array $args Arguments used to generate the breadcrumbs. Documented in Baltic_Breadcrumbs::get_output().
*/
return apply_filters( 'baltic_home_crumb', $crumb, $this->args );
}
/**
* Return blog posts page breadcrumb.
*
* Defaults to the home crumb (later removed as a duplicate). If using a
* static front page, then the title of the Page is returned.
*
* @since 1.0.0
*
* @return string HTML markup for blog posts page breadcrumb.
*/
protected function get_blog_crumb() {
$crumb = $this->get_home_crumb();
if ( $this->page_shown_on_front() ) {
$crumb = get_the_title( get_option( 'page_for_posts' ) );
}
/**
* Filter the Baltic blog posts breadcrumb.
*
* @since 1.0.0
*
* @param string $crumb HTML markup for the blog posts breadcrumb.
* @param array $args Arguments used to generate the breadcrumbs. Documented in Baltic_Breadcrumbs::get_output().
*/
return apply_filters( 'baltic_blog_crumb', $crumb, $this->args );
}
/**
* Return search results page breadcrumb.
*
* @since 1.0.0
*
* @return string HTML markup for search results page breadcrumb.
*/
protected function get_search_crumb() {
$crumb = $this->args['labels']['search'] . '"' . esc_html( apply_filters( 'the_search_query', get_search_query() ) ) . '"';
/**
* Filter the Search page breadcrumb.
*
* @since 1.0.0
*
* @param string $crumb HTML markup for the search page breadcrumb.
* @param array $args Arguments used to generate the breadcrumbs. Documented in Baltic_Breadcrumbs::get_output().
*/
return apply_filters( 'baltic_search_crumb', $crumb, $this->args );
}
/**
* Return 404 (page not found) breadcrumb.
*
* @since 1.0.0
*
* @return string HTML markup for 404 (page not found) breadcrumb.
*/
protected function get_404_crumb() {
$crumb = $this->args['labels']['404'];
/**
* Filter the 404 page breadcrumb.
*
* @since 1.0.0
*
* @param string $crumb HTML markup for the 404 page breadcrumb.
* @param array $args Arguments used to generate the breadcrumbs. Documented in Baltic_Breadcrumbs::get_output().
*/
return apply_filters( 'baltic_404_crumb', $crumb, $this->args );
}
/**
* Return content page breadcrumb.
*
* @since 1.0.0
*
* @global WP_Query $wp_query Query object.
*
* @return string HTML markup for a page breadcrumb.
*/
protected function get_page_crumb() {
global $wp_query;
if ( $this->page_shown_on_front() && is_front_page() ) {
// Don't do anything - we're on the front page and we've already dealt with that elsewhere.
$crumb = $this->get_home_crumb();
} else {
$post = $wp_query->get_queried_object();
// If this is a top level Page, it's simple to output the breadcrumb.
if ( ! $post->post_parent ) {
$crumb = get_the_title();
} else {
if ( isset( $post->ancestors ) ) {
if ( is_array( $post->ancestors ) ) {
$ancestors = array_values( $post->ancestors );
} else {
$ancestors = array( $post->ancestors );
}
} else {
$ancestors = array( $post->post_parent );
}
$crumbs = array();
foreach ( $ancestors as $ancestor ) {
array_unshift(
$crumbs,
$this->get_breadcrumb_link(
get_permalink( $ancestor ),
'',
get_the_title( $ancestor )
)
);
}
// Add the current page title.
$crumbs[] = get_the_title( $post->ID );
$crumb = implode( $this->args['sep'], $crumbs );
}
}
/**
* Filter the content page breadcrumb.
*
* @since 1.0.0
*
* @param string $crumb HTML markup for the content page breadcrumb.
* @param array $args Arguments used to generate the breadcrumbs. Documented in Baltic_Breadcrumbs::get_output().
*/
return apply_filters( 'baltic_page_crumb', $crumb, $this->args );
}
/**
* Get breadcrumb for single attachment, including any parent crumbs.
*
* @since 2.0.0
*
* @return string HTML markup for a single attachment breadcrumb, including any parent breadcrumbs.
*/
protected function get_attachment_crumb() {
$post = get_post();
$crumb = '';
if ( $this->args['heirarchial_attachments'] ) {
// If showing attachment parent.
$attachment_parent = get_post( $post->post_parent );
$crumb = $this->get_breadcrumb_link(
get_permalink( $post->post_parent ),
'',
$attachment_parent->post_title,
$this->args['sep']
);
}
$crumb .= single_post_title( '', false );
/**
* Filter the Baltic attachment breadcrumb.
*
* @since 2.0.0
*
* @param string $crumb HTML markup for the attachment breadcrumb.
* @param array $args Arguments used to generate the breadcrumbs. Documented in Baltic_Breadcrumbs::get_output().
*/
return apply_filters( 'baltic_attachment_crumb', $crumb, $this->args );
}
/**
* Get breadcrumb for single post, including any parent (category) crumbs.
*
* @since 2.0.0
*
* @return string HTML markup for a single post breadcrumb, including any parent (category) breadcrumbs.
*/
protected function get_post_crumb() {
$categories = get_the_category();
$cat_crumb = '';
if ( 1 === count( $categories ) ) {
// If in single category, show it, and any parent categories.
$cat_crumb = $this->get_term_parents( $categories[0]->cat_ID, 'category', true ) . $this->args['sep'];
}
if ( count( $categories ) > 1 ) {
if ( ! $this->args['heirarchial_categories'] ) {
// Don't show parent categories (unless the post happen to be explicitly in them).
foreach ( $categories as $category ) {
$crumbs[] = $this->get_breadcrumb_link(
get_category_link( $category->term_id ),
'',
$category->name
);
}
$cat_crumb = implode( $this->args['list_sep'], $crumbs ) . $this->args['sep'];
} else {
// Show parent categories - see if one is marked as primary and try to use that.
$primary_category_id = get_post_meta( get_the_ID(), '_category_permalink', true ); // Support for sCategory Permalink plugin.
if ( ! $primary_category_id && function_exists( 'yoast_get_primary_term_id' ) ) {
// Support for Yoast SEO plugin, even if the Yoast Breadcrumb feature is not enabled.
$primary_category_id = yoast_get_primary_term_id();
}
if ( $primary_category_id ) {
$cat_crumb = $this->get_term_parents( $primary_category_id, 'category', true ) . $this->args['sep'];
} else {
$cat_crumb = $this->get_term_parents( $categories[0]->cat_ID, 'category', true ) . $this->args['sep'];
}
}
}
$crumb = $cat_crumb . single_post_title( '', false );
/**
* Filter the Baltic post breadcrumb.
*
* @since 2.0.0
*
* @param string $crumb HTML markup for the post breadcrumb.
* @param array $args Arguments used to generate the breadcrumbs. Documented in Baltic_Breadcrumbs::get_output().
*/
return apply_filters( 'baltic_post_crumb', $crumb, $this->args, $cat_crumb );
}
/**
* Get breadcrumb for single custom post type entry, including any parent (CPT name) crumbs.
*
* @since 2.0.0
*
* @return string HTML markup for a single custom post type entry breadcrumb, including
* any parent (CPT name) breadcrumbs.
*/
protected function get_cpt_crumb() {
$post_type = get_query_var( 'post_type' );
$post_type_object = get_post_type_object( $post_type );
$cpt_archive_link = get_post_type_archive_link( $post_type );
if ( $cpt_archive_link ) {
$crumb = $this->get_breadcrumb_link(
$cpt_archive_link,
'',
$post_type_object->labels->name
);
} else {
$crumb = $post_type_object->labels->name;
}
$crumb .= $this->args['sep'] . single_post_title( '', false );
/**
* Filter the Baltic CPT breadcrumb.
*
* @since 2.0.0
*
* @param string $crumb HTML markup for the CPT breadcrumb.
* @param array $args Arguments used to generate the breadcrumbs. Documented in Baltic_Breadcrumbs::get_output().
*/
return apply_filters( 'baltic_cpt_crumb', $crumb, $this->args );
}
/**
* Return the category archive crumb.
*
* @since 1.0.0
*
* @return string HTML markup for a category archive breadcrumb.
*/
protected function get_category_crumb() {
$crumb = $this->args['labels']['category'] . $this->get_term_parents( get_query_var( 'cat' ), 'category' );
/**
* Filter the category archive breadcrumb.
*
* @since 1.0.0
*
* @param string $crumb HTML markup for the category archive crumb.
* @param array $args Arguments used to generate the breadcrumbs. Documented in Baltic_Breadcrumbs::get_output().
*/
return apply_filters( 'baltic_category_crumb', $crumb, $this->args );
}
/**
* Return the tag archive crumb.
*
* @since 1.0.0
*
* @return string HTML markup for a tag archive breadcrumb.
*/
protected function get_tag_crumb() {
$crumb = $this->args['labels']['tag'] . single_term_title( '', false );
/**
* Filter the tag archive breadcrumb.
*
* @since 1.0.0
*
* @param string $crumb HTML markup for the tag archive crumb.
* @param array $args Arguments used to generate the breadcrumbs. Documented in Baltic_Breadcrumbs::get_output().
*/
return apply_filters( 'baltic_tag_crumb', $crumb, $this->args );
}
/**
* Return the taxonomy archive crumb.
*
* @since 1.0.0
*
* @global WP_Query $wp_query Query object.
*
* @return string HTML markup for a taxonomy archive breadcrumb.
*/
protected function get_tax_crumb() {
global $wp_query;
$term = $wp_query->get_queried_object();
$crumb = $this->args['labels']['tax'] . $this->get_term_parents( $term->term_id, $term->taxonomy );
/**
* Filter the taxonomy archive breadcrumb.
*
* @since 1.0.0
*
* @param string $crumb HTML markup for the taxonomy archive breadcrumb.
* @param array $args Arguments used to generate the breadcrumbs. Documented in Baltic_Breadcrumbs::get_output().
*/
return apply_filters( 'baltic_tax_crumb', $crumb, $this->args );
}
/**
* Return the year archive crumb.
*
* @since 1.0.0
*
* @return string HTML markup for a year archive breadcrumb.
*/
protected function get_year_crumb() {
$year = get_query_var( 'm' ) ? get_query_var( 'm' ) : get_query_var( 'year' );
$crumb = $this->args['labels']['date'] . $year;
/**
* Filter the year archive breadcrumb.
*
* @since 1.0.0
*
* @param string $crumb HTML markup for the year archive breadcrumb.
* @param array $args Arguments used to generate the breadcrumbs. Documented in Baltic_Breadcrumbs::get_output().
*/
return apply_filters( 'baltic_year_crumb', $crumb, $this->args );
}
/**
* Return the month archive crumb.
*
* @since 1.0.0
*
* @return string HTML markup for a month archive breadcrumb.
*/
protected function get_month_crumb() {
$year = get_query_var( 'm' ) ? mb_substr( get_query_var( 'm' ), 0, 4 ) : get_query_var( 'year' );
$crumb = $this->get_breadcrumb_link(
get_year_link( $year ),
'',
$year,
$this->args['sep']
);
$crumb .= $this->args['labels']['date'] . single_month_title( ' ', false );
/**
* Filter the month archive breadcrumb.
*
* @since 1.0.0
*
* @param string $crumb HTML markup for the month archive breadcrumb.
* @param array $args Arguments used to generate the breadcrumbs. Documented in Baltic_Breadcrumbs::get_output().
*/
return apply_filters( 'baltic_month_crumb', $crumb, $this->args );
}
/**
* Return the day archive crumb.
*
* @since 1.0.0
*
* @global mixed $wp_locale The locale object, used for getting the
* auto-translated name of the month for month or
* day archives.
*
* @return string HTML markup for a day archive breadcrumb.
*/
protected function get_day_crumb() {
global $wp_locale;
$year = get_query_var( 'm' ) ? mb_substr( get_query_var( 'm' ), 0, 4 ) : get_query_var( 'year' );
$month = get_query_var( 'm' ) ? mb_substr( get_query_var( 'm' ), 4, 2 ) : get_query_var( 'monthnum' );
$day = get_query_var( 'm' ) ? mb_substr( get_query_var( 'm' ), 6, 2 ) : get_query_var( 'day' );
$crumb = $this->get_breadcrumb_link(
get_year_link( $year ),
'',
$year,
$this->args['sep']
);
$crumb .= $this->get_breadcrumb_link(
get_month_link( $year, $month ),
'',
$wp_locale->get_month( $month ),
$this->args['sep']
);
$crumb .= $this->args['labels']['date'] . $day . date( 'S', mktime( 0, 0, 0, 1, $day ) );
/**
* Filter the day archive breadcrumb.
*
* @since 1.0.0
*
* @param string $crumb HTML markup for the day archive breadcrumb.
* @param array $args Arguments used to generate the breadcrumbs. Documented in Baltic_Breadcrumbs::get_output().
*/
return apply_filters( 'baltic_day_crumb', $crumb, $this->args );
}
/**
* Return the author archive crumb.
*
* @since 1.0.0
*
* @global WP_Query $wp_query Query object.
*
* @return string HTML markup for an author archive breadcrumb.
*/
protected function get_author_crumb() {
global $wp_query;
$crumb = $this->args['labels']['author'] . esc_html( $wp_query->queried_object->display_name );
/**
* Filter the author archive breadcrumb.
*
* @since 1.0.0
*
* @param string $crumb HTML markup for the author archive crumb.
* @param array $args Arguments used to generate the breadcrumbs. Documented in Baltic_Breadcrumbs::get_output().
*/
return apply_filters( 'baltic_author_crumb', $crumb, $this->args );
}
/**
* Return the post type archive crumb.
*
* @since 1.0.0
*
* @return string HTML markup for a post type archive breadcrumb.
*/
protected function get_post_type_crumb() {
$crumb = $this->args['labels']['post_type'] . esc_html( post_type_archive_title( '', false ) );
/**
* Filter the post type archive breadcrumb.
*
* @since 1.0.0
*
* @param string $crumb HTML markup for the post type archive breadcrumb.
* @param array $args Arguments used to generate the breadcrumbs. Documented in Baltic_Breadcrumbs::get_output().
*/
return apply_filters( 'baltic_post_type_crumb', $crumb, $this->args );
}
/**
* Return recursive linked crumbs of category, tag or custom taxonomy parents.
*
* @since 1.0.0
*
* @param int $parent_id Initial ID of object to get parents of.
* @param string $taxonomy Name of the taxonomy. May be 'category', 'post_tag' or something custom.
* @param bool $link Whether to link last item in chain. Default false.
* @param array $visited Array of IDs already included in the chain.
*
* @return string HTML markup of recursive linked crumbs of category, tag or custom taxonomy parents.
*/
protected function get_term_parents( $parent_id, $taxonomy, $link = false, array $visited = array() ) {
$parent = get_term( (int)$parent_id, $taxonomy );
if ( is_wp_error( $parent ) ) {
return array();
}
if ( $parent->parent && ( $parent->parent != $parent->term_id ) && ! in_array( $parent->parent, $visited ) ) {
$visited[] = $parent->parent;
$chain[] = $this->get_term_parents( $parent->parent, $taxonomy, true, $visited );
}
if ( $link && !is_wp_error( get_term_link( get_term( $parent->term_id, $taxonomy ), $taxonomy ) ) ) {
$chain[] = $this->get_breadcrumb_link(
get_term_link( get_term( $parent->term_id, $taxonomy ), $taxonomy ),
'',
$parent->name
);
} else {
$chain[] = $parent->name;
}
return implode( $this->args['sep'], $chain );
}
/**
* Determine if static page is shown on front page.
*
* @return bool True if page is shown on front, false otherwise.
*/
protected function page_shown_on_front() {
return 'page' === get_option( 'show_on_front' );
}
}