bcn_breadcrumb_trail

The Breadcrumb NavXT bcn breadcrumb trail class.

Defined (1)

The class is defined in the following location(s).

/class.bcn_breadcrumb_trail.php  
  1. class bcn_breadcrumb_trail 
  2. //Our member variables 
  3. const version = '5.6.0'; 
  4. //An array of breadcrumbs 
  5. public $breadcrumbs = array(); 
  6. public $trail = array(); 
  7. //The options 
  8. public $opt; 
  9. //Default constructor 
  10. public function __construct() 
  11. //@see https://core.trac.wordpress.org/ticket/10527 
  12. if(!is_textdomain_loaded('breadcrumb-navxt')) 
  13. load_plugin_textdomain('breadcrumb-navxt', false, 'breadcrumb-navxt/languages'); 
  14. $this->trail = &$this->breadcrumbs; 
  15. //Initilize with default option values 
  16. $this->opt = array( 
  17. //Should the mainsite be shown 
  18. 'bmainsite_display' => true,  
  19. //The breadcrumb template for the main site 
  20. 'Hmainsite_template' => bcn_breadcrumb::get_default_template(),  
  21. //The breadcrumb template for the main site, used when an anchor is not needed 
  22. 'Hmainsite_template_no_anchor' => bcn_breadcrumb::default_template_no_anchor,  
  23. //Should the home page be shown 
  24. 'bhome_display' => true,  
  25. //The breadcrumb template for the home page 
  26. 'Hhome_template' => bcn_breadcrumb::get_default_template(),  
  27. //The breadcrumb template for the home page, used when an anchor is not needed 
  28. 'Hhome_template_no_anchor' => bcn_breadcrumb::default_template_no_anchor,  
  29. //Should the blog page be shown globally 
  30. 'bblog_display' => true,  
  31. //The breadcrumb template for the blog page only in static front page mode 
  32. 'Hblog_template' => bcn_breadcrumb::get_default_template(),  
  33. //The breadcrumb template for the blog page only in static front page mode, used when an anchor is not needed 
  34. 'Hblog_template_no_anchor' => bcn_breadcrumb::default_template_no_anchor,  
  35. //Separator that is placed between each item in the breadcrumb trial, but not placed before 
  36. //the first and not after the last breadcrumb 
  37. 'hseparator' => ' > ',  
  38. //Whether or not we should trim the breadcrumb titles 
  39. 'blimit_title' => false,  
  40. //The maximum title length 
  41. 'amax_title_length' => 20,  
  42. //Current item options 
  43. 'bcurrent_item_linked' => false,  
  44. //Static page options 
  45. //The anchor template for page breadcrumbs 
  46. 'Hpost_page_template' => bcn_breadcrumb::get_default_template(),  
  47. //The anchor template for page breadcrumbs, used when an anchor is not needed 
  48. 'Hpost_page_template_no_anchor' => bcn_breadcrumb::default_template_no_anchor,  
  49. //Just a link to the page on front property 
  50. 'apost_page_root' => get_option('page_on_front'),  
  51. //Paged options 
  52. //The template for paged breadcrumb 
  53. 'Hpaged_template' => __('<span property="itemListElement" typeof="ListItem"><span property="name">Page %htitle%</span><meta property="position" content="%position%"></span>', 'breadcrumb-navxt'),  
  54. //Should we try filling out paged information 
  55. 'bpaged_display' => false,  
  56. //The post options previously singleblogpost 
  57. //The breadcrumb template for post breadcrumbs 
  58. 'Hpost_post_template' => bcn_breadcrumb::get_default_template(),  
  59. //The breadcrumb template for post breadcrumbs, used when an anchor is not needed 
  60. 'Hpost_post_template_no_anchor' => bcn_breadcrumb::default_template_no_anchor,  
  61. //Just a link for the page for posts 
  62. 'apost_post_root' => get_option('page_for_posts'),  
  63. //Should the trail include the taxonomy of the post 
  64. 'bpost_post_taxonomy_display' => true,  
  65. //Should the trail reflect the referer taxonomy or not 
  66. 'bpost_post_taxonomy_referer' => false,  
  67. //What taxonomy should be shown leading to the post, tag or category 
  68. 'Spost_post_taxonomy_type' => 'category',  
  69. //Attachment settings 
  70. //The breadcrumb template for attachment breadcrumbs 
  71. 'Hpost_attachment_template' => bcn_breadcrumb::get_default_template(),  
  72. //The breadcrumb template for attachment breadcrumbs, used when an anchor is not needed 
  73. 'Hpost_attachment_template_no_anchor' => bcn_breadcrumb::default_template_no_anchor,  
  74. //404 page settings 
  75. //The template for 404 breadcrumbs 
  76. 'H404_template' => bcn_breadcrumb::default_template_no_anchor,  
  77. //The text to be shown in the breadcrumb for a 404 page 
  78. 'S404_title' => __('404', 'breadcrumb-navxt'),  
  79. //Search page options 
  80. //The breadcrumb template for search breadcrumbs 
  81. 'Hsearch_template' => __('<span property="itemListElement" typeof="ListItem"><span property="name">Search results for '<a property="item" typeof="WebPage" title="Go to the first page of search results for %title%." href="%link%" class="%type%">%htitle%</a>'</span><meta property="position" content="%position%"></span>', 'breadcrumb-navxt'),  
  82. //The breadcrumb template for search breadcrumbs, used when an anchor is not necessary 
  83. 'Hsearch_template_no_anchor' => __('<span property="itemListElement" typeof="ListItem"><span property="name">Search results for '%htitle%'</span><meta property="position" content="%position%"></span>', 'breadcrumb-navxt'),  
  84. //Tag related stuff 
  85. //The breadcrumb template for tag breadcrumbs 
  86. 'Htax_post_tag_template' => __('<span property="itemListElement" typeof="ListItem"><a property="item" typeof="WebPage" title="Go to the %title% tag archives." href="%link%" class="%type%"><span property="name">%htitle%</span></a><meta property="position" content="%position%"></span>', 'breadcrumb-navxt'),  
  87. //The breadcrumb template for tag breadcrumbs, used when an anchor is not necessary 
  88. 'Htax_post_tag_template_no_anchor' => bcn_breadcrumb::default_template_no_anchor,  
  89. //Post format related stuff 
  90. //The breadcrumb template for post format breadcrumbs, used when an anchor is not necessary 
  91. 'Htax_post_format_template' => __('<span property="itemListElement" typeof="ListItem"><a property="item" typeof="WebPage" title="Go to the %title% archives." href="%link%" class="%type%"><span property="name">%htitle%</span></a><meta property="position" content="%position%"></span>', 'breadcrumb-navxt'),  
  92. //The breadcrumb template for post format breadcrumbs 
  93. 'Htax_post_format_template_no_anchor' => bcn_breadcrumb::default_template_no_anchor,  
  94. //Author page stuff 
  95. //The anchor template for author breadcrumbs 
  96. 'Hauthor_template' => __('<span property="itemListElement" typeof="ListItem"><span property="name">Articles by: <a title="Go to the first page of posts by %title%." href="%link%" class="%type%">%htitle%</a>', 'breadcrumb-navxt'),  
  97. //The anchor template for author breadcrumbs, used when anchors are not needed 
  98. 'Hauthor_template_no_anchor' => __('<span property="itemListElement" typeof="ListItem"><span property="name">Articles by: %htitle%</span><meta property="position" content="%position%"></span>', 'breadcrumb-navxt'),  
  99. //Which of the various WordPress display types should the author breadcrumb display 
  100. 'Sauthor_name' => 'display_name',  
  101. //Category stuff 
  102. //The breadcrumb template for category breadcrumbs 
  103. 'Htax_category_template' => __('<span property="itemListElement" typeof="ListItem"><a property="item" typeof="WebPage" title="Go to the %title% category archives." href="%link%" class="%type%"><span property="name">%htitle%</span></a><meta property="position" content="%position%"></span>', 'breadcrumb-navxt'),  
  104. //The breadcrumb template for category breadcrumbs, used when anchors are not needed 
  105. 'Htax_category_template_no_anchor' => bcn_breadcrumb::default_template_no_anchor,  
  106. //The breadcrumb template for date breadcrumbs 
  107. 'Hdate_template' => __('<span property="itemListElement" typeof="ListItem"><a property="item" typeof="WebPage" title="Go to the %title% archives." href="%link%" class="%type%"><span property="name">%htitle%</span></a><meta property="position" content="%position%"></span>', 'breadcrumb-navxt'),  
  108. //The breadcrumb template for date breadcrumbs, used when anchors are not needed 
  109. 'Hdate_template_no_anchor' => bcn_breadcrumb::default_template_no_anchor 
  110. ); 
  111. /** 
  112. * This returns the internal version 
  113. * @return string internal version of the Breadcrumb trail 
  114. */ 
  115. public function get_version() 
  116. _deprecated_function( __FUNCTION__, '5.2', 'bcn_breadcrumb_trail::version' ); 
  117. return self::version; 
  118. /** 
  119. * Adds a breadcrumb to the breadcrumb trail 
  120. *  
  121. * @param bcn_breadcrumb $object Breadcrumb to add to the trail 
  122. * @return pointer to the just added Breadcrumb 
  123. */ 
  124. public function &add(bcn_breadcrumb $object) 
  125. $this->breadcrumbs[] = $object; 
  126. //Return the just added object 
  127. return $this->breadcrumbs[count($this->breadcrumbs) - 1]; 
  128. /** 
  129. * A Breadcrumb Trail Filling Function 
  130. *  
  131. * This functions fills a breadcrumb for a search page. 
  132. */ 
  133. protected function do_search() 
  134. //Place the breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return 
  135. $breadcrumb = $this->add(new bcn_breadcrumb(get_search_query(), $this->opt['Hsearch_template_no_anchor'], array('search', 'current-item'))); 
  136. //If we're paged, or allowing the current item to be linked, let's link to the first page 
  137. if($this->opt['bcurrent_item_linked'] || (is_paged() && $this->opt['bpaged_display'])) 
  138. //Since we are paged and are linking the root breadcrumb, time to change to the regular template 
  139. $breadcrumb->set_template($this->opt['Hsearch_template']); 
  140. //Figure out the anchor for the search 
  141. $breadcrumb->set_url(get_search_link()); 
  142. /** 
  143. * A Breadcrumb Trail Filling Function 
  144. *  
  145. * This functions fills a breadcrumb for an author page. 
  146. */ 
  147. protected function do_author() 
  148. if(get_query_var('author_name')) 
  149. $authordata = get_user_by('slug', get_query_var('author_name')); 
  150. else 
  151. $authordata = get_userdata(get_query_var('author')); 
  152. //Setup array of valid author_name values 
  153. $valid_author_name = array('display_name', 'nickname', 'first_name', 'last_name'); 
  154. //Make sure user picks only safe values 
  155. if(in_array($this->opt['Sauthor_name'], $valid_author_name)) 
  156. //Place the breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return 
  157. $breadcrumb = $this->add(new bcn_breadcrumb(get_the_author_meta($this->opt['Sauthor_name'], $authordata->ID), $this->opt['Hauthor_template_no_anchor'], array('author', 'current-item'), NULL, $authordata->ID)); 
  158. //If we're paged, or allowing the current item to be linked, let's link to the first page 
  159. if($this->opt['bcurrent_item_linked'] || (is_paged() && $this->opt['bpaged_display'])) 
  160. //Set the template to our one containing an anchor 
  161. $breadcrumb->set_template($this->opt['Hauthor_template']); 
  162. $breadcrumb->set_url(get_author_posts_url($authordata->ID)); 
  163. /** 
  164. * Determines the taxonomy name represented by the specified query var 
  165. *  
  166. * @param string $query_var The query var to attempt to find the corresponding taxonomy 
  167. * @return string|bool Either the name of the taxonomy corresponding to the query_var or false if no taxonomy exists for the specified query_var 
  168. */ 
  169. protected function query_var_to_taxonomy($query_var) 
  170. global $wp_taxonomies; 
  171. foreach($wp_taxonomies as $taxonomy) 
  172. if($taxonomy->query_var === $query_var) 
  173. return $taxonomy->name; 
  174. return false; 
  175. /** 
  176. * Determines the referer taxonomy 
  177. *  
  178. * @return string|bool Either the name of the taxonomy to use or false if a referer taxonomy wasn't found 
  179. */ 
  180. protected function determine_taxonomy() 
  181. global $wp; 
  182. //Backup the server request variable 
  183. $bk_req = $_SERVER['REQUEST_URI']; 
  184. //Now set the request URL to the referrer URL 
  185. //Could just chain the [1] selection, but that's not PHP5.3 compatible 
  186. $url_split = explode(home_url(), esc_url(wp_get_referer())); 
  187. if(isset($url_split[1])) 
  188. $_SERVER['REQUEST_URI'] = $url_split[1]; 
  189. else 
  190. return false; 
  191. //Create our own new instance of WP, and have it parse our faux request 
  192. $bcn_wp = new WP(); 
  193. //Copy over the current global wp object's query_vars since CPTs and taxonomies are added directly to the global $wp 
  194. $bcn_wp->public_query_vars = $wp->public_query_vars; 
  195. $bcn_wp->parse_request(); 
  196. $_SERVER['REQUEST_URI'] = $bk_req; 
  197. if(is_array($bcn_wp->query_vars)) 
  198. foreach($bcn_wp->query_vars as $query_var => $value) 
  199. if($taxonomy = $this->query_var_to_taxonomy($query_var)) 
  200. return $taxonomy; 
  201. return false; 
  202. /** 
  203. * This function selects the term that should be used for a post's hierarchy 
  204. *  
  205. * @param int $id The ID of the post to find the term for 
  206. * @param string $type The post type of the post to figure out the taxonomy for 
  207. * @param string $taxonomy The taxonomy to use 
  208. * @return WP_Term|bool The term object to use for the post hierarchy or false if no suitable term was found  
  209. */ 
  210. protected function pick_post_term($id, $type, $taxonomy) 
  211. //Fill a temporary object with the terms 
  212. $bcn_object = get_the_terms($id, $taxonomy); 
  213. $potential_parent = 0; 
  214. //Make sure we have an non-empty array 
  215. if(is_array($bcn_object)) 
  216. //Now try to find the deepest term of those that we know of 
  217. $bcn_use_term = key($bcn_object); 
  218. foreach($bcn_object as $key => $object) 
  219. //Can't use the next($bcn_object) trick since order is unknown 
  220. if($object->parent > 0 && ($potential_parent === 0 || $object->parent === $potential_parent)) 
  221. $bcn_use_term = $key; 
  222. $potential_parent = $object->term_id; 
  223. return $bcn_object[$bcn_use_term]; 
  224. return false; 
  225. /** 
  226. * A Breadcrumb Trail Filling Function 
  227. *  
  228. * This function fills breadcrumbs for any post taxonomy 
  229. * @param int $id The id of the post to figure out the taxonomy for 
  230. * @param string $type The post type of the post to figure out the taxonomy for 
  231. * @param int $parent (optional) The id of the parent of the current post, used if hiearchal posts will be the "taxonomy" for the current post 
  232. */ 
  233. protected function post_hierarchy($id, $type, $parent = NULL) 
  234. //Check to see if breadcrumbs for the taxonomy of the post needs to be generated 
  235. if($this->opt['bpost_' . $type . '_taxonomy_display']) 
  236. //TODO: Remove deprecated type selection 
  237. //Check if we have a date 'taxonomy' request 
  238. if($this->opt['Spost_' . $type . '_taxonomy_type'] === 'BCN_DATE' || $this->opt['Spost_' . $type . '_taxonomy_type'] === 'date') 
  239. $this->do_archive_by_date($type); 
  240. //TODO: Remove deprecated type selection 
  241. //Handle the use of hierarchical posts as the 'taxonomy' 
  242. else if($this->opt['Spost_' . $type . '_taxonomy_type'] === 'BCN_POST_PARENT' || $this->opt['Spost_' . $type . '_taxonomy_type'] === 'page') 
  243. if($parent == NULL) 
  244. //We have to grab the post to find its parent, can't use $post for this one 
  245. $parent = get_post($id); 
  246. //TODO should we check that we have a WP_Post object here? 
  247. $parent = $parent->post_parent; 
  248. //Grab the frontpage, we'll need it shortly 
  249. $bcn_frontpage = get_option('page_on_front'); 
  250. //If there is a parent page let's find it 
  251. if($parent && $id != $parent && $bcn_frontpage != $parent) 
  252. $parent = $this->post_parents($parent, $bcn_frontpage); 
  253. else 
  254. $taxonomy = $this->opt['Spost_' . $type . '_taxonomy_type']; 
  255. //Possibly let the referer influence the taxonomy used 
  256. if($this->opt['bpost_' . $type . '_taxonomy_referer'] && $referrer_taxonomy = $this->determine_taxonomy()) 
  257. //See if there were any terms, if so, we can use the referrer influenced taxonomy 
  258. $terms = get_the_terms($id, $referrer_taxonomy); 
  259. if(is_array($terms)) 
  260. $taxonomy = $referrer_taxonomy; 
  261. //Handle all hierarchical taxonomies, including categories 
  262. if(is_taxonomy_hierarchical($taxonomy)) 
  263. //Filter the results of post_pick_term 
  264. $term = apply_filters('bcn_pick_post_term', $this->pick_post_term($id, $type, $taxonomy), $id, $type, $taxonomy); 
  265. //Only do something if we found a term 
  266. if($term instanceof WP_Term) 
  267. //Fill out the term hiearchy 
  268. $parent = $this->term_parents($term->term_id, $taxonomy); 
  269. //Handle the rest of the taxonomies, including tags 
  270. else 
  271. $this->post_terms($id, $taxonomy); 
  272. //If we never got a good parent for the type_archive, make it now 
  273. if(!($parent instanceof WP_Post)) 
  274. $parent = get_post($id); 
  275. //Finish off with trying to find the type archive 
  276. $this->type_archive($parent); 
  277. /** 
  278. * A Breadcrumb Trail Filling Function 
  279. *  
  280. * This functions fills a breadcrumb for the terms of a post 
  281. * @param int $id The id of the post to find the terms for 
  282. * @param string $taxonomy The name of the taxonomy that the term belongs to 
  283. *  
  284. * TODO Need to implement this cleaner 
  285. */ 
  286. protected function post_terms($id, $taxonomy) 
  287. //Apply a filter to the terms for the post referred to by ID 
  288. $bcn_terms = apply_filters('bcn_post_terms', get_the_terms($id, $taxonomy), $taxonomy, $id); 
  289. //Only process if we have terms 
  290. if(is_array($bcn_terms)) 
  291. $title = '';  
  292. $is_first = true; 
  293. //Loop through all of the term results 
  294. foreach($bcn_terms as $term) 
  295. //Everything but the first term needs a comma separator 
  296. if($is_first == false) 
  297. $title .= ', '; 
  298. //This is a bit hackish, but it compiles the term anchor and appends it to the current breadcrumb title 
  299. $title .= str_replace( 
  300. array('%title%', '%link%', '%htitle%', '%type%'),  
  301. array($term->name, $this->maybe_add_post_type_arg(get_term_link($term), NULL, $term->taxonomy), $term->name, $term->taxonomy),  
  302. $this->opt['Htax_' . $term->taxonomy . '_template']); 
  303. $is_first = false; 
  304. //Place the breadcrumb in the trail, uses the constructor to set the title, template, and type, get a pointer to it in return 
  305. $breadcrumb = $this->add(new bcn_breadcrumb($title, NULL, array('taxonomy', $taxonomy))); 
  306. /** 
  307. * A Breadcrumb Trail Filling Function 
  308. *  
  309. * This recursive functions fills the trail with breadcrumbs for parent terms. 
  310. * @param int $id The id of the term. 
  311. * @param string $taxonomy The name of the taxonomy that the term belongs to 
  312. * @return WP_Term The term we stopped at 
  313. */ 
  314. protected function term_parents($id, $taxonomy) 
  315. //Get the current category object, filter applied within this call 
  316. $term = get_term($id, $taxonomy); 
  317. //Place the breadcrumb in the trail, uses the constructor to set the title, template, and type, get a pointer to it in return 
  318. $breadcrumb = $this->add(new bcn_breadcrumb($term->name, $this->opt['Htax_' . $taxonomy . '_template'], array('taxonomy', $taxonomy), $this->maybe_add_post_type_arg(get_term_link($term), NULL, $taxonomy), $id)); 
  319. //Make sure the id is valid, and that we won't end up spinning in a loop 
  320. if($term->parent && $term->parent != $id) 
  321. //Figure out the rest of the term hiearchy via recursion 
  322. $term = $this->term_parents($term->parent, $taxonomy); 
  323. return $term; 
  324. /** 
  325. * A Breadcrumb Trail Filling Function 
  326. *  
  327. * This recursive functions fills the trail with breadcrumbs for parent posts/pages. 
  328. * @param int $id The id of the parent page. 
  329. * @param int $frontpage The id of the front page. 
  330. * @return WP_Post The parent we stopped at 
  331. */ 
  332. protected function post_parents($id, $frontpage) 
  333. //Use WordPress API, though a bit heavier than the old method, this will ensure compatibility with other plug-ins 
  334. $parent = get_post($id); 
  335. //Place the breadcrumb in the trail, uses the constructor to set the title, template, and type, get a pointer to it in return 
  336. $breadcrumb = $this->add(new bcn_breadcrumb(get_the_title($id), $this->opt['Hpost_' . $parent->post_type . '_template'], array('post', 'post-' . $parent->post_type), get_permalink($id), $id)); 
  337. //Make sure the id is valid, and that we won't end up spinning in a loop 
  338. if($parent->post_parent >= 0 && $parent->post_parent != false && $id != $parent->post_parent && $frontpage != $parent->post_parent) 
  339. //If valid, recursively call this function 
  340. $parent = $this->post_parents($parent->post_parent, $frontpage); 
  341. return $parent; 
  342. /** 
  343. * A Breadcrumb Trail Filling Function 
  344. *  
  345. * This functions fills a breadcrumb for posts 
  346. *  
  347. * @param $post WP_Post Instance of WP_Post object to create a breadcrumb for 
  348. */ 
  349. protected function do_post($post) 
  350. //If we did not get a WP_Post object, warn developer and return early 
  351. if(!($post instanceof WP_Post)) 
  352. _doing_it_wrong(__CLASS__ . '::' . __FUNCTION__, __('$post global is not of type WP_Post', 'breadcrumb-navxt'), '5.1.1'); 
  353. return; 
  354. //Place the breadcrumb in the trail, uses the bcn_breadcrumb constructor to set the title, template, and type 
  355. $breadcrumb = $this->add(new bcn_breadcrumb(get_the_title($post), $this->opt['Hpost_' . $post->post_type . '_template_no_anchor'], array('post', 'post-' . $post->post_type, 'current-item'), NULL, $post->ID)); 
  356. //If the current item is to be linked, or this is a paged post, add in links 
  357. if(is_attachment() || $this->opt['bcurrent_item_linked'] || (get_query_var('page') > 1 && $this->opt['bpaged_display'])) 
  358. //Change the template over to the normal, linked one 
  359. $breadcrumb->set_template($this->opt['Hpost_' . $post->post_type . '_template']); 
  360. //Add the link 
  361. $breadcrumb->set_url(get_permalink($post)); 
  362. //If we have page, force it to go through the parent tree 
  363. if($post->post_type === 'page') 
  364. //Done with the current item, now on to the parents 
  365. $frontpage = get_option('page_on_front'); 
  366. //If there is a parent page let's find it 
  367. if($post->post_parent && $post->ID != $post->post_parent && $frontpage != $post->post_parent) 
  368. $this->post_parents($post->post_parent, $frontpage); 
  369. //Otherwise we need the follow the hiearchy tree 
  370. else 
  371. //Handle the post's hiearchy 
  372. $this->post_hierarchy($post->ID, $post->post_type, $post->post_parent); 
  373. /** 
  374. * A Breadcrumb Trail Filling Function 
  375. *  
  376. * This functions fills a breadcrumb for an attachment page. 
  377. */ 
  378. protected function do_attachment() 
  379. $post = get_post(); 
  380. //Place the breadcrumb in the trail, uses the constructor to set the title, template, and type, get a pointer to it in return 
  381. $breadcrumb = $this->add(new bcn_breadcrumb(get_the_title(), $this->opt['Hpost_attachment_template_no_anchor'], array('post', 'post-attachment', 'current-item'), NULL, $post->ID)); 
  382. if($this->opt['bcurrent_item_linked']) 
  383. //Change the template over to the normal, linked one 
  384. $breadcrumb->set_template($this->opt['Hpost_attachment_template']); 
  385. //Add the link 
  386. $breadcrumb->set_url(get_permalink()); 
  387. //Done with the current item, now on to the parents 
  388. $frontpage = get_option('page_on_front'); 
  389. //Make sure the id is valid, and that we won't end up spinning in a loop 
  390. if($post->post_parent >= 0 && $post->post_parent != false && $post->ID != $post->post_parent && $frontpage != $post->post_parent) 
  391. //Get the parent's information 
  392. $parent = get_post($post->post_parent); 
  393. //Take care of the parent's breadcrumb 
  394. $this->do_post($parent); 
  395. /** 
  396. * A Breadcrumb Trail Filling Function 
  397. *  
  398. * This function fills a breadcrumb for any taxonomy archive, was previously two separate functions 
  399. */ 
  400. protected function do_archive_by_term() 
  401. global $wp_query; 
  402. //Simmilar to using $post, but for things $post doesn't cover 
  403. $term = $wp_query->get_queried_object(); 
  404. //Place the breadcrumb in the trail, uses the constructor to set the title, template, and type, get a pointer to it in return 
  405. $breadcrumb = $this->add(new bcn_breadcrumb($term->name, $this->opt['Htax_' . $term->taxonomy . '_template_no_anchor'], array('archive', 'taxonomy', $term->taxonomy, 'current-item'), NULL, $term->term_id)); 
  406. //If we're paged, let's link to the first page 
  407. if($this->opt['bcurrent_item_linked'] || (is_paged() && $this->opt['bpaged_display'])) 
  408. $breadcrumb->set_template($this->opt['Htax_' . $term->taxonomy . '_template']); 
  409. //Figure out the anchor for current category 
  410. $breadcrumb->set_url($this->maybe_add_post_type_arg(get_term_link($term), NULL, $term->taxonomy)); 
  411. //Get parents of current term 
  412. if($term->parent) 
  413. $this->term_parents($term->parent, $term->taxonomy); 
  414. /** 
  415. * A Breadcrumb Trail Filling Function 
  416. *  
  417. * This functions fills a breadcrumb for a date archive. 
  418. *  
  419. * @param string $type The type to restrict the date archives to 
  420. */ 
  421. protected function do_archive_by_date($type) 
  422. global $wp_query; 
  423. //First deal with the day breadcrumb 
  424. if(is_day() || is_single()) 
  425. //Place the breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return 
  426. $breadcrumb = $this->add(new bcn_breadcrumb(get_the_time(_x('d', 'day archive breadcrumb date format', 'breadcrumb-navxt')), $this->opt['Hdate_template_no_anchor'], array('archive', 'date-day'))); 
  427. //If this is a day archive, add current-item type 
  428. if(is_day()) 
  429. $breadcrumb->add_type('current-item'); 
  430. //If we're paged, let's link to the first page 
  431. if($this->opt['bcurrent_item_linked'] || is_paged() && $this->opt['bpaged_display'] || is_single()) 
  432. //We're linking, so set the linked template 
  433. $breadcrumb->set_template($this->opt['Hdate_template']); 
  434. $url = get_day_link(get_the_time('Y'), get_the_time('m'), get_the_time('d')); 
  435. //Deal with the anchor 
  436. $breadcrumb->set_url($this->maybe_add_post_type_arg($url, $type)); 
  437. //Now deal with the month breadcrumb 
  438. if(is_month() || is_day() || is_single()) 
  439. //Place the breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return 
  440. $breadcrumb = $this->add(new bcn_breadcrumb(get_the_time(_x('F', 'month archive breadcrumb date format', 'breadcrumb-navxt')), $this->opt['Hdate_template_no_anchor'], array('archive', 'date-month'))); 
  441. //If this is a month archive, add current-item type 
  442. if(is_month()) 
  443. $breadcrumb->add_type('current-item'); 
  444. //If we're paged, or not in the archive by month let's link to the first archive by month page 
  445. if($this->opt['bcurrent_item_linked'] || is_day() || is_single() || (is_month() && is_paged() && $this->opt['bpaged_display'])) 
  446. //We're linking, so set the linked template 
  447. $breadcrumb->set_template($this->opt['Hdate_template']); 
  448. $url = get_month_link(get_the_time('Y'), get_the_time('m')); 
  449. //Deal with the anchor 
  450. $breadcrumb->set_url($this->maybe_add_post_type_arg($url, $type)); 
  451. //Place the year breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return 
  452. $breadcrumb = $this->add(new bcn_breadcrumb(get_the_time(_x('Y', 'year archive breadcrumb date format', 'breadcrumb-navxt')), $this->opt['Hdate_template_no_anchor'], array('archive', 'date-year'))); 
  453. //If this is a year archive, add current-item type 
  454. if(is_year()) 
  455. $breadcrumb->add_type('current-item'); 
  456. //If we're paged, or not in the archive by year let's link to the first archive by year page 
  457. if($this->opt['bcurrent_item_linked'] || is_day() || is_month() || is_single() || (is_paged() && $this->opt['bpaged_display'])) 
  458. //We're linking, so set the linked template 
  459. $breadcrumb->set_template($this->opt['Hdate_template']); 
  460. $url = get_year_link(get_the_time('Y')); 
  461. //Deal with the anchor 
  462. $breadcrumb->set_url($this->maybe_add_post_type_arg($url, $type)); 
  463. /** 
  464. * A Breadcrumb Trail Filling Function 
  465. *  
  466. * This functions fills a breadcrumb for a post type archive (WP 3.1 feature) 
  467. */ 
  468. protected function do_archive_by_post_type() 
  469. $type_str = $this->get_type_string_query_var(); 
  470. //Place the breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return 
  471. $breadcrumb = $this->add(new bcn_breadcrumb(post_type_archive_title('', false), $this->opt['Hpost_' . $type_str . '_template_no_anchor'], array('archive', 'post-' . $type_str . '-archive', 'current-item'))); 
  472. if($this->opt['bcurrent_item_linked'] || is_paged() && $this->opt['bpaged_display']) 
  473.  
  474. $breadcrumb->set_template($this->opt['Hpost_' . $type_str . '_template']); 
  475. //Deal with the anchor 
  476. $breadcrumb->set_url(get_post_type_archive_link($type_str)); 
  477. /** 
  478. * A Breadcrumb Trail Filling Function 
  479. *  
  480. * This functions fills a breadcrumb for the front page. 
  481. */ 
  482. protected function do_front_page() 
  483. global $current_site; 
  484. //Get the site name 
  485. $site_name = get_option('blogname'); 
  486. //Place the breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return 
  487. $breadcrumb = $this->add(new bcn_breadcrumb($site_name, $this->opt['Hhome_template_no_anchor'], array('home', 'current-item'))); 
  488. //If we're paged, let's link to the first page 
  489. if($this->opt['bcurrent_item_linked'] || (is_paged() && $this->opt['bpaged_display'])) 
  490. $breadcrumb->set_template($this->opt['Hhome_template']); 
  491. //Figure out the anchor for home page 
  492. $breadcrumb->set_url(get_home_url()); 
  493. //If we have a multi site and are not on the main site we may need to add a breadcrumb for the main site 
  494. if($this->opt['bmainsite_display'] && !is_main_site()) 
  495. //Get the site name 
  496. $site_name = get_site_option('site_name'); 
  497. //Place the main site breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return 
  498. $breadcrumb = $this->add(new bcn_breadcrumb($site_name, $this->opt['Hmainsite_template'], array('main-home'), get_home_url($current_site->blog_id))); 
  499. /** 
  500. * A Breadcrumb Trail Filling Function 
  501. *  
  502. * This functions fills a breadcrumb for the home page. 
  503. */ 
  504. protected function do_home() 
  505. global $current_site; 
  506. //On everything else we need to link, but no current item (pre/suf)fixes 
  507. if($this->opt['bhome_display']) 
  508. //Get the site name 
  509. $site_name = get_option('blogname'); 
  510. //Place the breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return 
  511. $breadcrumb = $this->add(new bcn_breadcrumb($site_name, $this->opt['Hhome_template'], array('home'), get_home_url())); 
  512. //If we have a multi site and are not on the main site we need to add a breadcrumb for the main site 
  513. if($this->opt['bmainsite_display'] && !is_main_site()) 
  514. //Get the site name 
  515. $site_name = get_site_option('site_name'); 
  516. //Place the main site breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return 
  517. $breadcrumb = $this->add(new bcn_breadcrumb($site_name, $this->opt['Hmainsite_template'], array('main-home'), get_home_url($current_site->blog_id))); 
  518. /** 
  519. * A modified version of WordPress' function of the same name 
  520. *  
  521. * @param object $object the post or taxonomy object used to attempt to find the title 
  522. * @return string the title 
  523. */ 
  524. protected function post_type_archive_title($object) 
  525. if(isset($object->labels->name)) 
  526. //Core filter use here is ok for time being 
  527. //TODO: Recheck validitiy prior to each release 
  528. return apply_filters('post_type_archive_title', $object->labels->name, $object->name); 
  529. /** 
  530. * Determines if a post type is a built in type or not 
  531. *  
  532. * @param string $post_type the name of the post type 
  533. * @return bool 
  534. */ 
  535. protected function is_builtin($post_type) 
  536. $type = get_post_type_object($post_type); 
  537. //If we get a null, that means either then type wasn't found, or we had 'any' as a type, treat as builtin 
  538. if($type === null) 
  539. return true; 
  540. else 
  541. return $type->_builtin; 
  542. /** 
  543. * Determines if the current location is a for a root page or not 
  544. *  
  545. * @param string $post_type the name of the post type 
  546. * @return bool 
  547. */ 
  548. protected function treat_as_root_page($post_type) 
  549. return (is_home() || (is_post_type_archive() && !$this->opt['bpost_' . $post_type . '_archive_display'])); 
  550. /** 
  551. * Determines if a post type has archives enabled or not 
  552. *  
  553. * @param string $post_type the name of the post type 
  554. * @return bool 
  555. */ 
  556. protected function has_archive($post_type) 
  557. $type = get_post_type_object($post_type); //TODO need a check on this for WP_Error? 
  558. return $type->has_archive; 
  559. /** 
  560. * Retrieves the query var for 'post_type', sets default to post, and escapes 
  561. *  
  562. * @param string $default[optional] The default value to return if nothing was found/set or if post_type was an array 
  563. *  
  564. * @return string The post type string found in the post_type query var 
  565. */ 
  566. protected function get_type_string_query_var($default = 'post') 
  567. $type_str = get_query_var('post_type', $default); 
  568. if($type_str === '' || is_array($type_str)) 
  569. $type_str = $default; 
  570. return esc_attr($type_str); 
  571. /** 
  572. * Retrieves the query var for 'post_type', and returns whether or not it is an array 
  573. *  
  574. * @return bool Whether or not the post_type query var is an array 
  575. */ 
  576. protected function is_type_query_var_array() 
  577. return is_array(get_query_var('post_type')); 
  578. /** 
  579. * Adds the post type argument to the URL iff the passed in type is not post 
  580. *  
  581. * @param string $url The URL to possibly add the post_type argument to 
  582. * @param string $type[optional] The type to possibly add to the URL 
  583. * @param string $taxonomy[optional] If we're dealing with a taxonomy term, the taxonomy of that term 
  584. *  
  585. * @return string The possibly modified URL 
  586. */ 
  587. protected function maybe_add_post_type_arg($url, $type = NULL, $taxonomy = NULL) 
  588. global $wp_taxonomies; 
  589. //Rather than default to post, we should try to find the type 
  590. if($type == NULL) 
  591. $type = $this->get_type_string_query_var(); 
  592. //Add a query arg if we are not on the default post type for the archive in question and the post type is not post 
  593. $add_query_arg = (!($taxonomy && $type === $wp_taxonomies[$taxonomy]->object_type[0]) && $type !== 'post'); 
  594. //Filter the add_query_arg logic, only add the query arg if necessary 
  595. if(apply_filters('bcn_add_post_type_arg', $add_query_arg, $type, $taxonomy)) 
  596. $url = add_query_arg(array('post_type' => $type), $url); 
  597. return $url; 
  598. /** 
  599. * A Breadcrumb Trail Filling Function 
  600. *  
  601. * Deals with the post type archive and taxonomy archives 
  602. *  
  603. * @param WP_Post|WP_Taxonomy $type The post or taxonomy to generate the archive breadcrumb for 
  604. */ 
  605. protected function type_archive($type) 
  606. global $wp_taxonomies; 
  607. $type_str = false; 
  608. if(!isset($type->taxonomy)) //TODO could probably check the class type here 
  609. $type_str = $this->get_type_string_query_var(); 
  610. //If this is a custom post type with a post type archive, add it 
  611. if($type_str && !$this->is_builtin($type_str) && $this->opt['bpost_' . $type_str . '_archive_display'] && $this->has_archive($type_str)) 
  612. //Place the breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return 
  613. $breadcrumb = $this->add(new bcn_breadcrumb($this->post_type_archive_title(get_post_type_object($type_str)), $this->opt['Hpost_' . $type_str . '_template'], array('post', 'post-' . $type_str . '-archive'), get_post_type_archive_link($type_str))); 
  614. //Otherwise, if this is a custom taxonomy with an archive, add it 
  615. else if(isset($type->taxonomy) && isset($wp_taxonomies[$type->taxonomy]->object_type[0])  
  616. && !$this->is_builtin($this->get_type_string_query_var($wp_taxonomies[$type->taxonomy]->object_type[0]))  
  617. && $this->opt['bpost_' . $this->get_type_string_query_var($wp_taxonomies[$type->taxonomy]->object_type[0]) . '_archive_display']  
  618. && $this->has_archive($this->get_type_string_query_var($wp_taxonomies[$type->taxonomy]->object_type[0])) 
  619. && !$this->is_type_query_var_array()) 
  620. //We end up using the post type in several places, give it a variable 
  621. $post_type = apply_filters('bcn_type_archive_post_type', $this->get_type_string_query_var($wp_taxonomies[$type->taxonomy]->object_type[0])); 
  622. //Place the breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return 
  623. $breadcrumb = $this->add(new bcn_breadcrumb($this->post_type_archive_title(get_post_type_object($post_type)), $this->opt['Hpost_' . $post_type . '_template'], array('post', 'post-' . $post_type . '-archive'), get_post_type_archive_link($post_type))); 
  624. /** 
  625. * This function populates our type_str and root_id variables 
  626. *  
  627. * @param post $type A post object we are using to figureout the type 
  628. * @param string $type_str The type string variable, passed by reference 
  629. * @param int $root_id The ID for the post type root 
  630. *  
  631. * TODO, can probably clean up all the logic here and use the code for the CPT archives for all paths 
  632. */ 
  633. protected function find_type($type, &$type_str, &$root_id) 
  634. global $wp_taxonomies; 
  635. //We need to do special things for custom post types 
  636. if(is_singular() && !$this->is_builtin($type->post_type)) 
  637. //We need the type for later, so save it 
  638. $type_str = $type->post_type; 
  639. //This will assign a ID for root page of a custom post 
  640. if(is_numeric($this->opt['apost_' . $type_str . '_root'])) 
  641. $root_id = $this->opt['apost_' . $type_str . '_root']; 
  642. //For CPT archives 
  643. else if(is_post_type_archive() && !isset($type->taxonomy)) 
  644. //We need the type for later, so save it 
  645. $type_str = get_query_var('post_type'); 
  646. //May be an array, if so, rewind the iterator and grab first item 
  647. if(is_array($type_str)) 
  648. $type_str = reset($type_str); 
  649. //This will assign a ID for root page of a custom post's taxonomy archive 
  650. if(is_numeric($this->opt['apost_' . $type_str . '_root'])) 
  651. $root_id = $this->opt['apost_' . $type_str . '_root']; 
  652. //We need to do special things for custom post type archives, but not author or date archives 
  653. else if(is_archive() && !is_author() && !is_date() && !$this->is_builtin($this->get_type_string_query_var($wp_taxonomies[$type->taxonomy]->object_type[0]))) 
  654. //We need the type for later, so save it 
  655. $type_str = $this->get_type_string_query_var($wp_taxonomies[$type->taxonomy]->object_type[0]); 
  656. //This will assign a ID for root page of a custom post's taxonomy archive 
  657. if(is_numeric($this->opt['apost_' . $type_str . '_root'])) 
  658. $root_id = $this->opt['apost_' . $type_str . '_root']; 
  659. else if(is_singular() && $type instanceof WP_Post && $type->post_type == 'page') 
  660. $type_str = 'page'; 
  661. $root_id = get_option('page_on_front'); 
  662. else if(($this->opt['bblog_display'] || is_home()) && !is_search()) 
  663. $type_str = 'post'; 
  664. $root_id = get_option('page_for_posts'); 
  665. /** 
  666. * A Breadcrumb Trail Filling Function  
  667. * Handles only the root page stuff for post types, including the "page for posts" 
  668. */ 
  669. protected function do_root() 
  670. global $wp_query; 
  671. //If this is an attachment then we need to change the queried object to the parent post 
  672. if(is_attachment()) 
  673. //Could use the $post global, but we can't really trust it 
  674. $post = get_post(); 
  675. $type = get_post($post->post_parent); //TODO check for WP_Error? 
  676. //If the parent of the attachment is a page, exit early (works around bug where is_single() returns true for an attachment to a page) 
  677. if($type->post_type == 'page') 
  678. return; 
  679. else 
  680. //Simmilar to using $post, but for things $post doesn't cover 
  681. $type = $wp_query->get_queried_object(); 
  682. $root_id = -1; 
  683. $type_str = ''; 
  684. //Find our type string and root_id 
  685. $this->find_type($type, $type_str, $root_id); 
  686. //Continue only if we have a valid root_id 
  687. if($root_id > 1) 
  688. $frontpage_id = get_option('page_on_front'); 
  689. //We'll have to check if this ID is valid, e.g. user has specified a posts page 
  690. if($root_id && $root_id != $frontpage_id) 
  691. //Place the breadcrumb in the trail, uses the constructor to set the title, template, and type, we get a pointer to it in return 
  692. $breadcrumb = $this->add(new bcn_breadcrumb(get_the_title($root_id), $this->opt['Hpost_' . $type_str . '_template_no_anchor'], array($type_str . '-root', 'post', 'post-' . $type_str), NULL, $root_id)); 
  693. //If we are at home, or any root page archive then we need to add the current item type 
  694. if($this->treat_as_root_page($type_str)) 
  695. $breadcrumb->add_type('current-item'); 
  696. //If we're not on the current item we need to setup the anchor 
  697. if(!$this->treat_as_root_page($type_str) 
  698. || (is_paged() && $this->opt['bpaged_display']) 
  699. || ($this->treat_as_root_page($type_str) && $this->opt['bcurrent_item_linked'])) 
  700. $breadcrumb->set_template($this->opt['Hpost_' . $type_str . '_template']); 
  701. //Figure out the anchor for home page 
  702. $breadcrumb->set_url(get_permalink($root_id)); 
  703. //Done with the "root", now on to the parents 
  704. //Get the blog page 
  705. $bcn_post = get_post($root_id); 
  706. //If there is a parent post let's find it 
  707. if($bcn_post->post_parent && $bcn_post->ID != $bcn_post->post_parent && $frontpage_id != $bcn_post->post_parent) 
  708. $this->post_parents($bcn_post->post_parent, $frontpage_id); 
  709. /** 
  710. * A Breadcrumb Trail Filling Function 
  711. *  
  712. * This functions fills a breadcrumb for 404 pages. 
  713. */ 
  714. protected function do_404() 
  715. //Place the breadcrumb in the trail, uses the bcn_breadcrumb constructor to set the title, prefix, and suffix 
  716. $this->breadcrumbs[] = new bcn_breadcrumb($this->opt['S404_title'], $this->opt['H404_template'], array('404', 'current-item')); 
  717. /** 
  718. * A Breadcrumb Trail Filling Function 
  719. *  
  720. * This functions fills a breadcrumb for paged pages. 
  721. */ 
  722. protected function do_paged() 
  723. //Need to switch between paged and page for archives and singular (posts) 
  724. if(get_query_var('paged') > 0) 
  725. //Can use simple type hinting here to int since we already checked for greater than 0 
  726. $page_number = (int) get_query_var('paged'); 
  727. else 
  728. $page_number = absint(get_query_var('page')); 
  729. //Place the breadcrumb in the trail, uses the bcn_breadcrumb constructor to set the title, prefix, and suffix 
  730. $this->breadcrumbs[] = new bcn_breadcrumb($page_number, $this->opt['Hpaged_template'], array('paged')); 
  731. /** 
  732. * Breadcrumb Trail Filling Function 
  733. *  
  734. * This functions fills the breadcrumb trail. 
  735. */ 
  736. public function fill() 
  737. global $wpdb, $wp_query, $wp; 
  738. //Check to see if the trail is already populated 
  739. if(count($this->breadcrumbs) > 0) 
  740. //Exit early since we have breadcrumbs in the trail 
  741. return NULL; 
  742. //Do any actions if necessary, we past through the current object instance to keep life simple 
  743. do_action('bcn_before_fill', $this); 
  744. //Do specific opperations for the various page types 
  745. //Check if this isn't the first of a multi paged item 
  746. if($this->opt['bpaged_display'] && (is_paged() || is_singular() && get_query_var('page') > 1)) 
  747. $this->do_paged(); 
  748. //For the front page, as it may also validate as a page, do it first 
  749. if(is_front_page()) 
  750. //Must have two seperate branches so that we don't evaluate it as a page 
  751. if($this->opt['bhome_display']) 
  752. $this->do_front_page(); 
  753. //For posts 
  754. else if(is_singular()) 
  755. //For attachments 
  756. if(is_attachment()) 
  757. $this->do_attachment(); 
  758. //For all other post types 
  759. else 
  760. $this->do_post(get_post()); 
  761. //For searches 
  762. else if(is_search()) 
  763. $this->do_search(); 
  764. //For author pages 
  765. else if(is_author()) 
  766. $this->do_author(); 
  767. //For archives 
  768. else if(is_archive()) 
  769. $type = $wp_query->get_queried_object(); 
  770. //We need the type for later, so save it 
  771. $type_str = get_query_var('post_type'); 
  772. //May be an array, if so, rewind the iterator and grab first item 
  773. if(is_array($type_str)) 
  774. $type_str = reset($type_str); 
  775. //For date based archives 
  776. if(is_date()) 
  777. $this->do_archive_by_date($this->get_type_string_query_var()); 
  778. $this->type_archive($type); 
  779. //If we have a post type archive, and it does not have a root page generate the archive 
  780. else if(is_post_type_archive() && !isset($type->taxonomy) 
  781. && (!is_numeric($this->opt['apost_' . $type_str . '_root']) || $this->opt['bpost_' . $type_str . '_archive_display'])) 
  782. $this->do_archive_by_post_type(); 
  783. //For taxonomy based archives 
  784. else if(is_category() || is_tag() || is_tax()) 
  785. $this->do_archive_by_term(); 
  786. $this->type_archive($type); 
  787. else 
  788. $this->type_archive($type); 
  789. //For 404 pages 
  790. else if(is_404()) 
  791. $this->do_404(); 
  792. else 
  793. //If we are here, there may have been problems detecting the type 
  794. $type = $wp_query->get_queried_object(); 
  795. //If it looks, walks, and quacks like a taxonomy, treat is as one 
  796. if(isset($type->taxonomy)) 
  797. $this->do_archive_by_term(); 
  798. $this->type_archive($type); 
  799. //We always do the home link last, unless on the frontpage 
  800. if(!is_front_page()) 
  801. $this->do_root(); 
  802. $this->do_home(); 
  803. //Do any actions if necessary, we past through the current object instance to keep life simple 
  804. do_action('bcn_after_fill', $this); 
  805. /** 
  806. * This function will either set the order of the trail to reverse key  
  807. * order, or make sure it is forward key ordered. 
  808. *  
  809. * @param bool $reverse[optional] Whether to reverse the trail or not. 
  810. */ 
  811. protected function order($reverse = false) 
  812. if($reverse) 
  813. //Since there may be multiple calls our trail may be in a non-standard order 
  814. ksort($this->breadcrumbs); 
  815. else 
  816. //For normal opperation we must reverse the array by key 
  817. krsort($this->breadcrumbs); 
  818. /** 
  819. * This functions outputs or returns the breadcrumb trail in string form. 
  820. * @return void Void if Option to print out breadcrumb trail was chosen. 
  821. * @return string String-Data of breadcrumb trail. 
  822. * @param bool $return Whether to return data or to echo it. 
  823. * @param bool $linked[optional] Whether to allow hyperlinks in the trail or not. 
  824. * @param bool $reverse[optional] Whether to reverse the output or not. 
  825. *  
  826. * TODO: Fold display and display_list together, two functions are very simmilar  
  827. */ 
  828. public function display($return = false, $linked = true, $reverse = false) 
  829. //Set trail order based on reverse flag 
  830. $this->order($reverse); 
  831. //Initilize the string which will hold the assembled trail 
  832. $trail_str = ''; 
  833. $position = 1; 
  834. //The main compiling loop 
  835. foreach($this->breadcrumbs as $key => $breadcrumb) 
  836. //We do different things for the separator based on the breadcrumb order 
  837. if($reverse) 
  838. //Add in the separator only if we are the 2nd or greater element 
  839. if($key > 0) 
  840. $trail_str .= $this->opt['hseparator']; 
  841. else 
  842. //Only show the separator when necessary 
  843. if($key < count($this->breadcrumbs) - 1) 
  844. $trail_str .= $this->opt['hseparator']; 
  845. //Trim titles, if needed 
  846. if($this->opt['blimit_title'] && $this->opt['amax_title_length'] > 0) 
  847. //Trim the breadcrumb's title 
  848. $breadcrumb->title_trim($this->opt['amax_title_length']); 
  849. //Place in the breadcrumb's assembled elements 
  850. $trail_str .= $breadcrumb->assemble($linked, $position); 
  851. $position++; 
  852. //Should we return or echo the assembled trail? 
  853. if($return) 
  854. return $trail_str; 
  855. else 
  856. //Helps track issues, please don't remove it 
  857. $credits = "<!-- Breadcrumb NavXT " . $this::version . " -->\n"; 
  858. echo $credits . $trail_str; 
  859. /** 
  860. * This functions outputs or returns the breadcrumb trail in list form. 
  861. * @return void Void if option to print out breadcrumb trail was chosen. 
  862. * @return string String version of the breadcrumb trail. 
  863. * @param bool $return Whether to return data or to echo it. 
  864. * @param bool $linked[optional] Whether to allow hyperlinks in the trail or not. 
  865. * @param bool $reverse[optional] Whether to reverse the output or not.  
  866. *  
  867. * TODO: Can probably write this one in a smarter way now 
  868. */ 
  869. public function display_list($return = false, $linked = true, $reverse = false) 
  870. //Set trail order based on reverse flag 
  871. $this->order($reverse); 
  872. //Initilize the string which will hold the assembled trail 
  873. $trail_str = ''; 
  874. $position = 1; 
  875. //The main compiling loop 
  876. foreach($this->breadcrumbs as $key => $breadcrumb) 
  877. $li_class = ''; 
  878. //On the first run we need to add in a class for the home breadcrumb 
  879. if($trail_str === '') 
  880. $li_class .= ' class="home'; 
  881. if($key === 0) 
  882. $li_class .= ' current_item'; 
  883. $li_class .= '"'; 
  884. //If we are on the current item there are some things that must be done 
  885. else if($key === 0) 
  886. //Add in a class for current_item 
  887. $li_class .= ' class="current_item"'; 
  888. //Filter li_attributes adding attributes to the li element 
  889. $li_attribs = apply_filters('bcn_li_attributes', $li_class, $breadcrumb->type, $breadcrumb->get_id()); 
  890. //Trim titles, if requested 
  891. if($this->opt['blimit_title'] && $this->opt['amax_title_length'] > 0) 
  892. //Trim the breadcrumb's title 
  893. $breadcrumb->title_trim($this->opt['amax_title_length']); 
  894. //Assemble the breadrumb and wrap with li's 
  895. $trail_str .= sprintf("<li%s>%s</li>\n", $li_attribs, $breadcrumb->assemble($linked, $position)); 
  896. $position++; 
  897. //Should we return or echo the assembled trail? 
  898. if($return) 
  899. return $trail_str; 
  900. else 
  901. //Helps track issues, please don't remove it 
  902. $credits = "<!-- Breadcrumb NavXT " . $this::version . " -->\n"; 
  903. echo $credits . $trail_str;