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.5.2'; 
  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. $parent = $parent->post_parent; 
  247. //Grab the frontpage, we'll need it shortly 
  248. $bcn_frontpage = get_option('page_on_front'); 
  249. //If there is a parent page let's find it 
  250. if($parent && $id != $parent && $bcn_frontpage != $parent) 
  251. $parent = $this->post_parents($parent, $bcn_frontpage); 
  252. else 
  253. $taxonomy = $this->opt['Spost_' . $type . '_taxonomy_type']; 
  254. //Possibly let the referer influence the taxonomy used 
  255. if($this->opt['bpost_' . $type . '_taxonomy_referer'] && $referrer_taxonomy = $this->determine_taxonomy()) 
  256. //See if there were any terms, if so, we can use the referrer influenced taxonomy 
  257. $terms = get_the_terms($id, $referrer_taxonomy); 
  258. if(is_array($terms)) 
  259. $taxonomy = $referrer_taxonomy; 
  260. //Handle all hierarchical taxonomies, including categories 
  261. if(is_taxonomy_hierarchical($taxonomy)) 
  262. //Filter the results of post_pick_term 
  263. $term = apply_filters('bcn_pick_post_term', $this->pick_post_term($id, $type, $taxonomy), $id, $type, $taxonomy); 
  264. //Only do something if we found a term 
  265. if($term instanceof WP_Term) 
  266. //Fill out the term hiearchy 
  267. $parent = $this->term_parents($term->term_id, $taxonomy); 
  268. //Handle the rest of the taxonomies, including tags 
  269. else 
  270. $this->post_terms($id, $taxonomy); 
  271. //If we never got a good parent for the type_archive, make it now 
  272. if(!($parent instanceof WP_Post)) 
  273. $parent = get_post($id); 
  274. //Finish off with trying to find the type archive 
  275. $this->type_archive($parent); 
  276. /** 
  277. * A Breadcrumb Trail Filling Function 
  278. *  
  279. * This functions fills a breadcrumb for the terms of a post 
  280. * @param int $id The id of the post to find the terms for 
  281. * @param string $taxonomy The name of the taxonomy that the term belongs to 
  282. *  
  283. * TODO Need to implement this cleaner 
  284. */ 
  285. protected function post_terms($id, $taxonomy) 
  286. //Apply a filter to the terms for the post referred to by ID 
  287. $bcn_terms = apply_filters('bcn_post_terms', get_the_terms($id, $taxonomy), $taxonomy, $id); 
  288. //Only process if we have terms 
  289. if(is_array($bcn_terms)) 
  290. $title = '';  
  291. $is_first = true; 
  292. //Loop through all of the term results 
  293. foreach($bcn_terms as $term) 
  294. //Everything but the first term needs a comma separator 
  295. if($is_first == false) 
  296. $title .= ', '; 
  297. //This is a bit hackish, but it compiles the term anchor and appends it to the current breadcrumb title 
  298. $title .= str_replace( 
  299. array('%title%', '%link%', '%htitle%', '%type%'),  
  300. array($term->name, $this->maybe_add_post_type_arg(get_term_link($term), NULL, $term->taxonomy), $term->name, $term->taxonomy),  
  301. $this->opt['Htax_' . $term->taxonomy . '_template']); 
  302. $is_first = false; 
  303. //Place the breadcrumb in the trail, uses the constructor to set the title, template, and type, get a pointer to it in return 
  304. $breadcrumb = $this->add(new bcn_breadcrumb($title, NULL, array('taxonomy', $taxonomy))); 
  305. /** 
  306. * A Breadcrumb Trail Filling Function 
  307. *  
  308. * This recursive functions fills the trail with breadcrumbs for parent terms. 
  309. * @param int $id The id of the term. 
  310. * @param string $taxonomy The name of the taxonomy that the term belongs to 
  311. * @return WP_Term The term we stopped at 
  312. */ 
  313. protected function term_parents($id, $taxonomy) 
  314. //Get the current category object, filter applied within this call 
  315. $term = get_term($id, $taxonomy); 
  316. //Place the breadcrumb in the trail, uses the constructor to set the title, template, and type, get a pointer to it in return 
  317. $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)); 
  318. //Make sure the id is valid, and that we won't end up spinning in a loop 
  319. if($term->parent && $term->parent != $id) 
  320. //Figure out the rest of the term hiearchy via recursion 
  321. $term = $this->term_parents($term->parent, $taxonomy); 
  322. return $term; 
  323. /** 
  324. * A Breadcrumb Trail Filling Function 
  325. *  
  326. * This recursive functions fills the trail with breadcrumbs for parent posts/pages. 
  327. * @param int $id The id of the parent page. 
  328. * @param int $frontpage The id of the front page. 
  329. * @return WP_Post The parent we stopped at 
  330. */ 
  331. protected function post_parents($id, $frontpage) 
  332. //Use WordPress API, though a bit heavier than the old method, this will ensure compatibility with other plug-ins 
  333. $parent = get_post($id); 
  334. //Place the breadcrumb in the trail, uses the constructor to set the title, template, and type, get a pointer to it in return 
  335. $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)); 
  336. //Make sure the id is valid, and that we won't end up spinning in a loop 
  337. if($parent->post_parent >= 0 && $parent->post_parent != false && $id != $parent->post_parent && $frontpage != $parent->post_parent) 
  338. //If valid, recursively call this function 
  339. $parent = $this->post_parents($parent->post_parent, $frontpage); 
  340. return $parent; 
  341. /** 
  342. * A Breadcrumb Trail Filling Function 
  343. *  
  344. * This functions fills a breadcrumb for posts 
  345. *  
  346. * @param $post WP_Post Instance of WP_Post object to create a breadcrumb for 
  347. */ 
  348. protected function do_post($post) 
  349. //If we did not get a WP_Post object, warn developer and return early 
  350. if(!($post instanceof WP_Post)) 
  351. _doing_it_wrong(__CLASS__ . '::' . __FUNCTION__, __('$post global is not of type WP_Post', 'breadcrumb-navxt'), '5.1.1'); 
  352. return; 
  353. //Place the breadcrumb in the trail, uses the bcn_breadcrumb constructor to set the title, template, and type 
  354. $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)); 
  355. //If the current item is to be linked, or this is a paged post, add in links 
  356. if(is_attachment() || $this->opt['bcurrent_item_linked'] || (get_query_var('page') > 1 && $this->opt['bpaged_display'])) 
  357. //Change the template over to the normal, linked one 
  358. $breadcrumb->set_template($this->opt['Hpost_' . $post->post_type . '_template']); 
  359. //Add the link 
  360. $breadcrumb->set_url(get_permalink($post)); 
  361. //If we have page, force it to go through the parent tree 
  362. if($post->post_type === 'page') 
  363. //Done with the current item, now on to the parents 
  364. $frontpage = get_option('page_on_front'); 
  365. //If there is a parent page let's find it 
  366. if($post->post_parent && $post->ID != $post->post_parent && $frontpage != $post->post_parent) 
  367. $this->post_parents($post->post_parent, $frontpage); 
  368. //Otherwise we need the follow the hiearchy tree 
  369. else 
  370. //Handle the post's hiearchy 
  371. $this->post_hierarchy($post->ID, $post->post_type, $post->post_parent); 
  372. /** 
  373. * A Breadcrumb Trail Filling Function 
  374. *  
  375. * This functions fills a breadcrumb for an attachment page. 
  376. */ 
  377. protected function do_attachment() 
  378. $post = get_post(); 
  379. //Place the breadcrumb in the trail, uses the constructor to set the title, template, and type, get a pointer to it in return 
  380. $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)); 
  381. if($this->opt['bcurrent_item_linked']) 
  382. //Change the template over to the normal, linked one 
  383. $breadcrumb->set_template($this->opt['Hpost_attachment_template']); 
  384. //Add the link 
  385. $breadcrumb->set_url(get_permalink()); 
  386. //Done with the current item, now on to the parents 
  387. $frontpage = get_option('page_on_front'); 
  388. //Make sure the id is valid, and that we won't end up spinning in a loop 
  389. if($post->post_parent >= 0 && $post->post_parent != false && $post->ID != $post->post_parent && $frontpage != $post->post_parent) 
  390. //Get the parent's information 
  391. $parent = get_post($post->post_parent); 
  392. //Take care of the parent's breadcrumb 
  393. $this->do_post($parent); 
  394. /** 
  395. * A Breadcrumb Trail Filling Function 
  396. *  
  397. * This function fills a breadcrumb for any taxonomy archive, was previously two separate functions 
  398. */ 
  399. protected function do_archive_by_term() 
  400. global $wp_query; 
  401. //Simmilar to using $post, but for things $post doesn't cover 
  402. $term = $wp_query->get_queried_object(); 
  403. //Place the breadcrumb in the trail, uses the constructor to set the title, template, and type, get a pointer to it in return 
  404. $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)); 
  405. //If we're paged, let's link to the first page 
  406. if($this->opt['bcurrent_item_linked'] || (is_paged() && $this->opt['bpaged_display'])) 
  407. $breadcrumb->set_template($this->opt['Htax_' . $term->taxonomy . '_template']); 
  408. //Figure out the anchor for current category 
  409. $breadcrumb->set_url($this->maybe_add_post_type_arg(get_term_link($term), NULL, $term->taxonomy)); 
  410. //Get parents of current term 
  411. if($term->parent) 
  412. $this->term_parents($term->parent, $term->taxonomy); 
  413. /** 
  414. * A Breadcrumb Trail Filling Function 
  415. *  
  416. * This functions fills a breadcrumb for a date archive. 
  417. *  
  418. * @param string $type The type to restrict the date archives to 
  419. */ 
  420. protected function do_archive_by_date($type) 
  421. global $wp_query; 
  422. //First deal with the day breadcrumb 
  423. if(is_day() || is_single()) 
  424. //Place the breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return 
  425. $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'))); 
  426. //If this is a day archive, add current-item type 
  427. if(is_day()) 
  428. $breadcrumb->add_type('current-item'); 
  429. //If we're paged, let's link to the first page 
  430. if($this->opt['bcurrent_item_linked'] || is_paged() && $this->opt['bpaged_display'] || is_single()) 
  431. //We're linking, so set the linked template 
  432. $breadcrumb->set_template($this->opt['Hdate_template']); 
  433. $url = get_day_link(get_the_time('Y'), get_the_time('m'), get_the_time('d')); 
  434. //Deal with the anchor 
  435. $breadcrumb->set_url($this->maybe_add_post_type_arg($url, $type)); 
  436. //Now deal with the month breadcrumb 
  437. if(is_month() || is_day() || is_single()) 
  438. //Place the breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return 
  439. $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'))); 
  440. //If this is a month archive, add current-item type 
  441. if(is_month()) 
  442. $breadcrumb->add_type('current-item'); 
  443. //If we're paged, or not in the archive by month let's link to the first archive by month page 
  444. if($this->opt['bcurrent_item_linked'] || is_day() || is_single() || (is_month() && is_paged() && $this->opt['bpaged_display'])) 
  445. //We're linking, so set the linked template 
  446. $breadcrumb->set_template($this->opt['Hdate_template']); 
  447. $url = get_month_link(get_the_time('Y'), get_the_time('m')); 
  448. //Deal with the anchor 
  449. $breadcrumb->set_url($this->maybe_add_post_type_arg($url, $type)); 
  450. //Place the year breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return 
  451. $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'))); 
  452. //If this is a year archive, add current-item type 
  453. if(is_year()) 
  454. $breadcrumb->add_type('current-item'); 
  455. //If we're paged, or not in the archive by year let's link to the first archive by year page 
  456. if($this->opt['bcurrent_item_linked'] || is_day() || is_month() || is_single() || (is_paged() && $this->opt['bpaged_display'])) 
  457. //We're linking, so set the linked template 
  458. $breadcrumb->set_template($this->opt['Hdate_template']); 
  459. $url = get_year_link(get_the_time('Y')); 
  460. //Deal with the anchor 
  461. $breadcrumb->set_url($this->maybe_add_post_type_arg($url, $type)); 
  462. /** 
  463. * A Breadcrumb Trail Filling Function 
  464. *  
  465. * This functions fills a breadcrumb for a post type archive (WP 3.1 feature) 
  466. */ 
  467. protected function do_archive_by_post_type() 
  468. $type_str = $this->get_type_string_query_var(); 
  469. //Place the breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return 
  470. $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'))); 
  471. if($this->opt['bcurrent_item_linked'] || is_paged() && $this->opt['bpaged_display']) 
  472.  
  473. $breadcrumb->set_template($this->opt['Hpost_' . $type_str . '_template']); 
  474. //Deal with the anchor 
  475. $breadcrumb->set_url(get_post_type_archive_link($type_str)); 
  476. /** 
  477. * A Breadcrumb Trail Filling Function 
  478. *  
  479. * This functions fills a breadcrumb for the front page. 
  480. */ 
  481. protected function do_front_page() 
  482. global $current_site; 
  483. //Get the site name 
  484. $site_name = get_option('blogname'); 
  485. //Place the breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return 
  486. $breadcrumb = $this->add(new bcn_breadcrumb($site_name, $this->opt['Hhome_template_no_anchor'], array('home', 'current-item'))); 
  487. //If we're paged, let's link to the first page 
  488. if($this->opt['bcurrent_item_linked'] || (is_paged() && $this->opt['bpaged_display'])) 
  489. $breadcrumb->set_template($this->opt['Hhome_template']); 
  490. //Figure out the anchor for home page 
  491. $breadcrumb->set_url(get_home_url()); 
  492. //If we have a multi site and are not on the main site we may need to add a breadcrumb for the main site 
  493. if($this->opt['bmainsite_display'] && !is_main_site()) 
  494. //Get the site name 
  495. $site_name = get_site_option('site_name'); 
  496. //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 
  497. $breadcrumb = $this->add(new bcn_breadcrumb($site_name, $this->opt['Hmainsite_template'], array('main-home'), get_home_url($current_site->blog_id))); 
  498. /** 
  499. * A Breadcrumb Trail Filling Function 
  500. *  
  501. * This functions fills a breadcrumb for the home page. 
  502. */ 
  503. protected function do_home() 
  504. global $current_site; 
  505. //On everything else we need to link, but no current item (pre/suf)fixes 
  506. if($this->opt['bhome_display']) 
  507. //Get the site name 
  508. $site_name = get_option('blogname'); 
  509. //Place the breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return 
  510. $breadcrumb = $this->add(new bcn_breadcrumb($site_name, $this->opt['Hhome_template'], array('home'), get_home_url())); 
  511. //If we have a multi site and are not on the main site we need to add a breadcrumb for the main site 
  512. if($this->opt['bmainsite_display'] && !is_main_site()) 
  513. //Get the site name 
  514. $site_name = get_site_option('site_name'); 
  515. //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 
  516. $breadcrumb = $this->add(new bcn_breadcrumb($site_name, $this->opt['Hmainsite_template'], array('main-home'), get_home_url($current_site->blog_id))); 
  517. /** 
  518. * A modified version of WordPress' function of the same name 
  519. *  
  520. * @param object $object the post or taxonomy object used to attempt to find the title 
  521. * @return string the title 
  522. */ 
  523. protected function post_type_archive_title($object) 
  524. if(isset($object->labels->name)) 
  525. //Core filter use here is ok for time being 
  526. //TODO: Recheck validitiy prior to each release 
  527. return apply_filters('post_type_archive_title', $object->labels->name, $object->name); 
  528. /** 
  529. * Determines if a post type is a built in type or not 
  530. *  
  531. * @param string $post_type the name of the post type 
  532. * @return bool 
  533. */ 
  534. protected function is_builtin($post_type) 
  535. $type = get_post_type_object($post_type); 
  536. //If we get a null, that means either then type wasn't found, or we had 'any' as a type, treat as builtin 
  537. if($type === null) 
  538. return true; 
  539. else 
  540. return $type->_builtin; 
  541. /** 
  542. * Determines if the current location is a for a root page or not 
  543. *  
  544. * @param string $post_type the name of the post type 
  545. * @return bool 
  546. */ 
  547. protected function treat_as_root_page($post_type) 
  548. return (is_home() || (is_post_type_archive() && is_numeric($this->opt['apost_' . $post_type . '_root']) && !$this->opt['bpost_' . $post_type . '_archive_display'])); 
  549. /** 
  550. * Determines if a post type has archives enabled or not 
  551. *  
  552. * @param string $post_type the name of the post type 
  553. * @return bool 
  554. */ 
  555. protected function has_archive($post_type) 
  556. $type = get_post_type_object($post_type); 
  557. return $type->has_archive; 
  558. /** 
  559. * Retrieves the query var for 'post_type', sets default to post, and escapes 
  560. *  
  561. * @param string $default[optional] The default value to return if nothing was found/set or if post_type was an array 
  562. *  
  563. * @return string The post type string found in the post_type query var 
  564. */ 
  565. protected function get_type_string_query_var($default = 'post') 
  566. $type_str = get_query_var('post_type', $default); 
  567. if($type_str === '' || is_array($type_str)) 
  568. $type_str = $default; 
  569. return esc_attr($type_str); 
  570. /** 
  571. * Retrieves the query var for 'post_type', and returns whether or not it is an array 
  572. *  
  573. * @return bool Whether or not the post_type query var is an array 
  574. */ 
  575. protected function is_type_query_var_array() 
  576. return is_array(get_query_var('post_type')); 
  577. /** 
  578. * Adds the post type argument to the URL iff the passed in type is not post 
  579. *  
  580. * @param string $url The URL to possibly add the post_type argument to 
  581. * @param string $type[optional] The type to possibly add to the URL 
  582. * @param string $taxonomy[optional] If we're dealing with a taxonomy term, the taxonomy of that term 
  583. *  
  584. * @return string The possibly modified URL 
  585. */ 
  586. protected function maybe_add_post_type_arg($url, $type = NULL, $taxonomy = NULL) 
  587. global $wp_taxonomies; 
  588. //Rather than default to post, we should try to find the type 
  589. if($type == NULL) 
  590. $type = $this->get_type_string_query_var(); 
  591. //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 
  592. $add_query_arg = (!($taxonomy && $type === $wp_taxonomies[$taxonomy]->object_type[0]) && $type !== 'post'); 
  593. //Filter the add_query_arg logic, only add the query arg if necessary 
  594. if(apply_filters('bcn_add_post_type_arg', $add_query_arg, $type, $taxonomy)) 
  595. $url = add_query_arg(array('post_type' => $type), $url); 
  596. return $url; 
  597. /** 
  598. * A Breadcrumb Trail Filling Function 
  599. *  
  600. * Deals with the post type archive and taxonomy archives 
  601. *  
  602. * @param WP_Post|WP_Taxonomy $type The post or taxonomy to generate the archive breadcrumb for 
  603. */ 
  604. protected function type_archive($type) 
  605. global $wp_taxonomies; 
  606. $type_str = false; 
  607. if(!isset($type->taxonomy)) 
  608. $type_str = $this->get_type_string_query_var(); 
  609. //If this is a custom post type with a post type archive, add it 
  610. if($type_str && !$this->is_builtin($type_str) && $this->opt['bpost_' . $type_str . '_archive_display'] && $this->has_archive($type_str)) 
  611. //Place the breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return 
  612. $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))); 
  613. //Otherwise, if this is a custom taxonomy with an archive, add it 
  614. else if(isset($type->taxonomy) && isset($wp_taxonomies[$type->taxonomy]->object_type[0])  
  615. && !$this->is_builtin($this->get_type_string_query_var($wp_taxonomies[$type->taxonomy]->object_type[0]))  
  616. && $this->opt['bpost_' . $this->get_type_string_query_var($wp_taxonomies[$type->taxonomy]->object_type[0]) . '_archive_display']  
  617. && $this->has_archive($this->get_type_string_query_var($wp_taxonomies[$type->taxonomy]->object_type[0])) 
  618. && !$this->is_type_query_var_array()) 
  619. //We end up using the post type in several places, give it a variable 
  620. $post_type = apply_filters('bcn_type_archive_post_type', $this->get_type_string_query_var($wp_taxonomies[$type->taxonomy]->object_type[0])); 
  621. //Place the breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return 
  622. $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))); 
  623. /** 
  624. * This function populates our type_str and root_id variables 
  625. *  
  626. * @param post $type A post object we are using to figureout the type 
  627. * @param string $type_str The type string variable, passed by reference 
  628. * @param int $root_id The ID for the post type root 
  629. *  
  630. * TODO, can probably clean up all the logic here and use the code for the CPT archives for all paths 
  631. */ 
  632. protected function find_type($type, &$type_str, &$root_id) 
  633. global $wp_taxonomies; 
  634. //We need to do special things for custom post types 
  635. if(is_singular() && !$this->is_builtin($type->post_type)) 
  636. //We need the type for later, so save it 
  637. $type_str = $type->post_type; 
  638. //This will assign a ID for root page of a custom post 
  639. if(is_numeric($this->opt['apost_' . $type_str . '_root'])) 
  640. $root_id = $this->opt['apost_' . $type_str . '_root']; 
  641. //For CPT archives 
  642. else if(is_post_type_archive() && !isset($type->taxonomy)) 
  643. //We need the type for later, so save it 
  644. $type_str = get_query_var('post_type'); 
  645. //May be an array, if so, rewind the iterator and grab first item 
  646. if(is_array($type_str)) 
  647. $type_str = reset($type_str); 
  648. //This will assign a ID for root page of a custom post's taxonomy archive 
  649. if(is_numeric($this->opt['apost_' . $type_str . '_root'])) 
  650. $root_id = $this->opt['apost_' . $type_str . '_root']; 
  651. //We need to do special things for custom post type archives, but not author or date archives 
  652. else if(is_archive() && !is_author() && !is_date() && !$this->is_builtin($this->get_type_string_query_var($wp_taxonomies[$type->taxonomy]->object_type[0]))) 
  653. //We need the type for later, so save it 
  654. $type_str = $this->get_type_string_query_var($wp_taxonomies[$type->taxonomy]->object_type[0]); 
  655. //This will assign a ID for root page of a custom post's taxonomy archive 
  656. if(is_numeric($this->opt['apost_' . $type_str . '_root'])) 
  657. $root_id = $this->opt['apost_' . $type_str . '_root']; 
  658. else if(is_singular() && $type instanceof WP_Post && $type->post_type == 'page') 
  659. $type_str = 'page'; 
  660. $root_id = get_option('page_on_front'); 
  661. else if($this->opt['bblog_display'] || is_home()) 
  662. $type_str = 'post'; 
  663. $root_id = get_option('page_for_posts'); 
  664. /** 
  665. * A Breadcrumb Trail Filling Function  
  666. * Handles only the root page stuff for post types, including the "page for posts" 
  667. */ 
  668. protected function do_root() 
  669. global $wp_query; 
  670. //If this is an attachment then we need to change the queried object to the parent post 
  671. if(is_attachment()) 
  672. //Could use the $post global, but we can't really trust it 
  673. $post = get_post(); 
  674. $type = get_post($post->post_parent); 
  675. //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) 
  676. if($type->post_type == 'page') 
  677. return; 
  678. else 
  679. //Simmilar to using $post, but for things $post doesn't cover 
  680. $type = $wp_query->get_queried_object(); 
  681. $root_id = -1; 
  682. $type_str = ''; 
  683. //Find our type string and root_id 
  684. $this->find_type($type, $type_str, $root_id); 
  685. //Continue only if we have a valid root_id 
  686. if($root_id > 1) 
  687. $frontpage_id = get_option('page_on_front'); 
  688. //We'll have to check if this ID is valid, e.g. user has specified a posts page 
  689. if($root_id && $root_id != $frontpage_id) 
  690. //Place the breadcrumb in the trail, uses the constructor to set the title, template, and type, we get a pointer to it in return 
  691. $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)); 
  692. //If we are at home, or any root page archive then we need to add the current item type 
  693. if($this->treat_as_root_page($type_str)) 
  694. $breadcrumb->add_type('current-item'); 
  695. //If we're not on the current item we need to setup the anchor 
  696. if(!$this->treat_as_root_page($type_str) 
  697. || (is_paged() && $this->opt['bpaged_display']) 
  698. || ($this->treat_as_root_page($type_str) && $this->opt['bcurrent_item_linked'])) 
  699. $breadcrumb->set_template($this->opt['Hpost_' . $type_str . '_template']); 
  700. //Figure out the anchor for home page 
  701. $breadcrumb->set_url(get_permalink($root_id)); 
  702. //Done with the "root", now on to the parents 
  703. //Get the blog page 
  704. $bcn_post = get_post($root_id); 
  705. //If there is a parent post let's find it 
  706. if($bcn_post->post_parent && $bcn_post->ID != $bcn_post->post_parent && $frontpage_id != $bcn_post->post_parent) 
  707. $this->post_parents($bcn_post->post_parent, $frontpage_id); 
  708. /** 
  709. * A Breadcrumb Trail Filling Function 
  710. *  
  711. * This functions fills a breadcrumb for 404 pages. 
  712. */ 
  713. protected function do_404() 
  714. //Place the breadcrumb in the trail, uses the bcn_breadcrumb constructor to set the title, prefix, and suffix 
  715. $this->breadcrumbs[] = new bcn_breadcrumb($this->opt['S404_title'], $this->opt['H404_template'], array('404', 'current-item')); 
  716. /** 
  717. * A Breadcrumb Trail Filling Function 
  718. *  
  719. * This functions fills a breadcrumb for paged pages. 
  720. */ 
  721. protected function do_paged() 
  722. //Need to switch between paged and page for archives and singular (posts) 
  723. if(get_query_var('paged') > 0) 
  724. //Can use simple type hinting here to int since we already checked for greater than 0 
  725. $page_number = (int) get_query_var('paged'); 
  726. else 
  727. $page_number = absint(get_query_var('page')); 
  728. //Place the breadcrumb in the trail, uses the bcn_breadcrumb constructor to set the title, prefix, and suffix 
  729. $this->breadcrumbs[] = new bcn_breadcrumb($page_number, $this->opt['Hpaged_template'], array('paged')); 
  730. /** 
  731. * Breadcrumb Trail Filling Function 
  732. *  
  733. * This functions fills the breadcrumb trail. 
  734. */ 
  735. public function fill() 
  736. global $wpdb, $wp_query, $wp; 
  737. //Check to see if the trail is already populated 
  738. if(count($this->breadcrumbs) > 0) 
  739. //Exit early since we have breadcrumbs in the trail 
  740. return NULL; 
  741. //Do any actions if necessary, we past through the current object instance to keep life simple 
  742. do_action('bcn_before_fill', $this); 
  743. //Do specific opperations for the various page types 
  744. //Check if this isn't the first of a multi paged item 
  745. if($this->opt['bpaged_display'] && (is_paged() || is_singular() && get_query_var('page') > 1)) 
  746. $this->do_paged(); 
  747. //For the front page, as it may also validate as a page, do it first 
  748. if(is_front_page()) 
  749. //Must have two seperate branches so that we don't evaluate it as a page 
  750. if($this->opt['bhome_display']) 
  751. $this->do_front_page(); 
  752. //For posts 
  753. else if(is_singular()) 
  754. //For attachments 
  755. if(is_attachment()) 
  756. $this->do_attachment(); 
  757. //For all other post types 
  758. else 
  759. $this->do_post(get_post()); 
  760. //For searches 
  761. else if(is_search()) 
  762. $this->do_search(); 
  763. //For author pages 
  764. else if(is_author()) 
  765. $this->do_author(); 
  766. //For archives 
  767. else if(is_archive()) 
  768. $type = $wp_query->get_queried_object(); 
  769. //We need the type for later, so save it 
  770. $type_str = get_query_var('post_type'); 
  771. //May be an array, if so, rewind the iterator and grab first item 
  772. if(is_array($type_str)) 
  773. $type_str = reset($type_str); 
  774. //For date based archives 
  775. if(is_date()) 
  776. $this->do_archive_by_date($this->get_type_string_query_var()); 
  777. $this->type_archive($type); 
  778. //If we have a post type archive, and it does not have a root page generate the archive 
  779. else if(is_post_type_archive() && !isset($type->taxonomy) 
  780. && (!is_numeric($this->opt['apost_' . $type_str . '_root']) || $this->opt['bpost_' . $type_str . '_archive_display'])) 
  781. $this->do_archive_by_post_type(); 
  782. //For taxonomy based archives 
  783. else if(is_category() || is_tag() || is_tax()) 
  784. $this->do_archive_by_term(); 
  785. $this->type_archive($type); 
  786. else 
  787. $this->type_archive($type); 
  788. //For 404 pages 
  789. else if(is_404()) 
  790. $this->do_404(); 
  791. else 
  792. //If we are here, there may have been problems detecting the type 
  793. $type = $wp_query->get_queried_object(); 
  794. //If it looks, walks, and quacks like a taxonomy, treat is as one 
  795. if(isset($type->taxonomy)) 
  796. $this->do_archive_by_term(); 
  797. $this->type_archive($type); 
  798. //We always do the home link last, unless on the frontpage 
  799. if(!is_front_page()) 
  800. $this->do_root(); 
  801. $this->do_home(); 
  802. //Do any actions if necessary, we past through the current object instance to keep life simple 
  803. do_action('bcn_after_fill', $this); 
  804. /** 
  805. * This function will either set the order of the trail to reverse key  
  806. * order, or make sure it is forward key ordered. 
  807. *  
  808. * @param bool $reverse[optional] Whether to reverse the trail or not. 
  809. */ 
  810. protected function order($reverse = false) 
  811. if($reverse) 
  812. //Since there may be multiple calls our trail may be in a non-standard order 
  813. ksort($this->breadcrumbs); 
  814. else 
  815. //For normal opperation we must reverse the array by key 
  816. krsort($this->breadcrumbs); 
  817. /** 
  818. * This functions outputs or returns the breadcrumb trail in string form. 
  819. * @return void Void if Option to print out breadcrumb trail was chosen. 
  820. * @return string String-Data of breadcrumb trail. 
  821. * @param bool $return Whether to return data or to echo it. 
  822. * @param bool $linked[optional] Whether to allow hyperlinks in the trail or not. 
  823. * @param bool $reverse[optional] Whether to reverse the output or not. 
  824. *  
  825. * TODO: Fold display and display_list together, two functions are very simmilar  
  826. */ 
  827. public function display($return = false, $linked = true, $reverse = false) 
  828. //Set trail order based on reverse flag 
  829. $this->order($reverse); 
  830. //Initilize the string which will hold the assembled trail 
  831. $trail_str = ''; 
  832. $position = 1; 
  833. //The main compiling loop 
  834. foreach($this->breadcrumbs as $key => $breadcrumb) 
  835. //We do different things for the separator based on the breadcrumb order 
  836. if($reverse) 
  837. //Add in the separator only if we are the 2nd or greater element 
  838. if($key > 0) 
  839. $trail_str .= $this->opt['hseparator']; 
  840. else 
  841. //Only show the separator when necessary 
  842. if($key < count($this->breadcrumbs) - 1) 
  843. $trail_str .= $this->opt['hseparator']; 
  844. //Trim titles, if needed 
  845. if($this->opt['blimit_title'] && $this->opt['amax_title_length'] > 0) 
  846. //Trim the breadcrumb's title 
  847. $breadcrumb->title_trim($this->opt['amax_title_length']); 
  848. //Place in the breadcrumb's assembled elements 
  849. $trail_str .= $breadcrumb->assemble($linked, $position); 
  850. $position++; 
  851. //Should we return or echo the assembled trail? 
  852. if($return) 
  853. return $trail_str; 
  854. else 
  855. //Helps track issues, please don't remove it 
  856. $credits = "<!-- Breadcrumb NavXT " . $this::version . " -->\n"; 
  857. echo $credits . $trail_str; 
  858. /** 
  859. * This functions outputs or returns the breadcrumb trail in list form. 
  860. * @return void Void if option to print out breadcrumb trail was chosen. 
  861. * @return string String version of the breadcrumb trail. 
  862. * @param bool $return Whether to return data or to echo it. 
  863. * @param bool $linked[optional] Whether to allow hyperlinks in the trail or not. 
  864. * @param bool $reverse[optional] Whether to reverse the output or not.  
  865. *  
  866. * TODO: Can probably write this one in a smarter way now 
  867. */ 
  868. public function display_list($return = false, $linked = true, $reverse = false) 
  869. //Set trail order based on reverse flag 
  870. $this->order($reverse); 
  871. //Initilize the string which will hold the assembled trail 
  872. $trail_str = ''; 
  873. $position = 1; 
  874. //The main compiling loop 
  875. foreach($this->breadcrumbs as $key => $breadcrumb) 
  876. $li_class = ''; 
  877. //On the first run we need to add in a class for the home breadcrumb 
  878. if($trail_str === '') 
  879. $li_class .= ' class="home'; 
  880. if($key === 0) 
  881. $li_class .= ' current_item'; 
  882. $li_class .= '"'; 
  883. //If we are on the current item there are some things that must be done 
  884. else if($key === 0) 
  885. //Add in a class for current_item 
  886. $li_class .= ' class="current_item"'; 
  887. //Filter li_attributes adding attributes to the li element 
  888. $li_attribs = apply_filters('bcn_li_attributes', $li_class, $breadcrumb->type, $breadcrumb->get_id()); 
  889. //Trim titles, if requested 
  890. if($this->opt['blimit_title'] && $this->opt['amax_title_length'] > 0) 
  891. //Trim the breadcrumb's title 
  892. $breadcrumb->title_trim($this->opt['amax_title_length']); 
  893. //Assemble the breadrumb and wrap with li's 
  894. $trail_str .= sprintf("<li%s>%s</li>\n", $li_attribs, $breadcrumb->assemble($linked, $position)); 
  895. $position++; 
  896. //Should we return or echo the assembled trail? 
  897. if($return) 
  898. return $trail_str; 
  899. else 
  900. //Helps track issues, please don't remove it 
  901. $credits = "<!-- Breadcrumb NavXT " . $this::version . " -->\n"; 
  902. echo $credits . $trail_str;