PageRenderTime 49ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/htdocs/wp-content/plugins/breadcrumb-navxt/breadcrumb_navxt_class.php

https://bitbucket.org/dkrzos/phc
PHP | 1198 lines | 696 code | 1 blank | 501 comment | 199 complexity | 41da00fecb27bd4f272be825c40b287b MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. /*
  3. Copyright 2007-2013 John Havlik (email : mtekkmonkey@gmail.com)
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  15. */
  16. require_once(dirname(__FILE__) . '/includes/block_direct_access.php');
  17. //The breadcrumb class
  18. class bcn_breadcrumb
  19. {
  20. //Our member variables
  21. //The main text that will be shown
  22. protected $title;
  23. //The breadcrumb's template, used durring assembly
  24. protected $template;
  25. //The breadcrumb's no anchor template, used durring assembly when there won't be an anchor
  26. protected $template_no_anchor = '%title%';
  27. //Boolean, is this element linked
  28. protected $linked;
  29. //The link the breadcrumb leads to, null if $linked == false
  30. protected $url;
  31. //The corresponding resource ID
  32. protected $id = NULL;
  33. private $_title = NULL;
  34. //The type of this breadcrumb
  35. public $type;
  36. protected $allowed_html = array();
  37. /**
  38. * The enhanced default constructor, ends up setting all parameters via the set_ functions
  39. *
  40. * @param string $title (optional) The title of the breadcrumb
  41. * @param string $template (optional) The html template for the breadcrumb
  42. * @param string $type (optional) The breadcrumb type
  43. * @param string $url (optional) The url the breadcrumb links to
  44. */
  45. public function bcn_breadcrumb($title = '', $template = '', $type = '', $url = NULL, $id = NULL)
  46. {
  47. //Filter allowed_html array to allow others to add acceptable tags
  48. $this->allowed_html = apply_filters('bcn_allowed_html', wp_kses_allowed_html('post'));
  49. //The breadcrumb type
  50. $this->type = $type;
  51. //Set the resource id
  52. $this->set_id($id);
  53. //Set the title
  54. $this->set_title($title);
  55. //Assign the breadcrumb template
  56. if($template == NULL)
  57. {
  58. if($url == NULL)
  59. {
  60. $template = $this->template = __('%htitle%', 'breadcrumb-navxt');
  61. }
  62. else
  63. {
  64. $template = __('<a title="Go to %ftitle%." href="%link%" class="%type%">%htitle%</a>', 'breadcrumb-navxt');
  65. }
  66. }
  67. if($url == NULL)
  68. {
  69. $this->template_no_anchor = wp_kses($template, $this->allowed_html);
  70. }
  71. else
  72. {
  73. $this->set_template($template);
  74. }
  75. //Always NULL if unlinked
  76. $this->set_url($url);
  77. }
  78. /**
  79. * Function to set the protected title member
  80. *
  81. * @param string $title The title of the breadcrumb
  82. */
  83. public function set_title($title)
  84. {
  85. //Set the title
  86. $this->title = apply_filters('bcn_breadcrumb_title', $title, $this->type, $this->id);
  87. $this->_title = $this->title;
  88. }
  89. /**
  90. * Function to get the protected title member
  91. *
  92. * @return $this->title
  93. */
  94. public function get_title()
  95. {
  96. //Return the title
  97. return $this->title;
  98. }
  99. /**
  100. * Function to set the internal URL variable
  101. *
  102. * @param string $url the url to link to
  103. */
  104. public function set_url($url)
  105. {
  106. $this->url = esc_url(apply_filters('bcn_breadcrumb_url', $url, $this->type, $this->id));
  107. //Set linked to true if we set a non-null $url
  108. if($url)
  109. {
  110. $this->linked = true;
  111. }
  112. }
  113. /**
  114. * Sets the internal breadcrumb template
  115. *
  116. * @param string $template the template to use durring assebly
  117. */
  118. public function set_template($template)
  119. {
  120. //Assign the breadcrumb template
  121. $this->template = wp_kses(apply_filters('bcn_breadcrumb_template', $template, $this->type, $this->id), $this->allowed_html);
  122. }
  123. /**
  124. * Sets the internal breadcrumb ID
  125. *
  126. * @param int $id the id of the resource this breadcrumb represents
  127. */
  128. public function set_id($id)
  129. {
  130. $this->id = $id;
  131. }
  132. /**
  133. * Append a type entry to the type array
  134. *
  135. * @param string $type the type to append
  136. */
  137. public function add_type($type)
  138. {
  139. $this->type[] = $type;
  140. }
  141. /**
  142. * This function will intelligently trim the title to the value passed in through $max_length.
  143. *
  144. * @param int $max_length of the title.
  145. */
  146. public function title_trim($max_length)
  147. {
  148. //To preserve HTML entities, must decode before splitting
  149. $this->title = html_entity_decode($this->title, ENT_COMPAT, 'UTF-8');
  150. $title_length = mb_strlen($this->title);
  151. //Make sure that we are not making it longer with that ellipse
  152. if($title_length > $max_length && ($title_length + 2) > $max_length)
  153. {
  154. //Trim the title
  155. $this->title = mb_substr($this->title, 0, $max_length - 1);
  156. //Make sure we can split a, but we want to limmit to cutting at max an additional 25%
  157. if(mb_strpos($this->title, ' ', .75 * $max_length) > 0)
  158. {
  159. //Don't split mid word
  160. while(mb_substr($this->title,-1) != ' ')
  161. {
  162. $this->title = mb_substr($this->title, 0, -1);
  163. }
  164. }
  165. //Remove the whitespace at the end and add the hellip
  166. $this->title = rtrim($this->title) . html_entity_decode('&hellip;', ENT_COMPAT, 'UTF-8');
  167. }
  168. //Return to the encoded version of all HTML entities (keep standards complance)
  169. $this->title = htmlentities($this->title, ENT_COMPAT, 'UTF-8');
  170. }
  171. /**
  172. * Assembles the parts of the breadcrumb into a html string
  173. *
  174. * @param bool $linked (optional) Allow the output to contain anchors?
  175. * @return string The compiled breadcrumb string
  176. */
  177. public function assemble($linked = true)
  178. {
  179. //Build our replacements array
  180. $replacements = array(
  181. '%title%' => esc_attr(strip_tags($this->title)),
  182. '%link%' => $this->url,
  183. '%htitle%' => $this->title,
  184. '%type%' => $this->type,
  185. '%ftitle%' => esc_attr(strip_tags($this->_title)),
  186. '%fhtitle%' => $this->_title
  187. );
  188. //The type may be an array, implode it if that is the case
  189. if(is_array($replacements['%type%']))
  190. {
  191. $replacements['%type%'] = implode(' ', $replacements['%type%']);
  192. }
  193. $replacements = apply_filters('bcn_template_tags', $replacements, $this->type, $this->id);
  194. //If we are linked we'll need to use the normal template
  195. if($this->linked && $linked)
  196. {
  197. //Return the assembled breadcrumb string
  198. return str_replace(array_keys($replacements), $replacements, $this->template);
  199. }
  200. //Otherwise we use the no anchor template
  201. else
  202. {
  203. //Return the assembled breadcrumb string
  204. return str_replace(array_keys($replacements), $replacements, $this->template_no_anchor);
  205. }
  206. }
  207. }
  208. //The trail class
  209. class bcn_breadcrumb_trail
  210. {
  211. //Our member variables
  212. private $version = '4.4.0';
  213. //An array of breadcrumbs
  214. public $trail = array();
  215. //The options
  216. public $opt;
  217. //Default constructor
  218. function bcn_breadcrumb_trail()
  219. {
  220. global $l10n;
  221. // the global and the check might become obsolete in
  222. // further wordpress versions
  223. // @see https://core.trac.wordpress.org/ticket/10527
  224. if(!isset($l10n['breadcrumb-navxt']))
  225. {
  226. load_plugin_textdomain('breadcrumb-navxt', false, 'breadcrumb-navxt/languages');
  227. }
  228. //Load the translation domain as the next part needs it
  229. //load_plugin_textdomain('breadcrumb-navxt', false, 'breadcrumb-navxt/languages');
  230. //Initilize with default option values
  231. $this->opt = array(
  232. //Should the mainsite be shown
  233. 'bmainsite_display' => true,
  234. //The breadcrumb template for the main site, this is global, four keywords are available %link%, %title%, %htitle%, and %type%
  235. 'Hmainsite_template' => __('<a title="Go to %ftitle%." href="%link%" class="%type%">%htitle%</a>', 'breadcrumb-navxt'),
  236. //The breadcrumb template for the main site, used when an anchor is not needed, this is global, four keywords are available %link%, %title%, %htitle%, and %type%
  237. 'Hmainsite_template_no_anchor' => '%htitle%',
  238. //Should the home page be shown
  239. 'bhome_display' => true,
  240. //The breadcrumb template for the home page, this is global, four keywords are available %link%, %title%, %htitle%, and %type%
  241. 'Hhome_template' => __('<a title="Go to %ftitle%." href="%link%" class="%type%">%htitle%</a>', 'breadcrumb-navxt'),
  242. //The breadcrumb template for the home page, used when an anchor is not needed, this is global, four keywords are available %link%, %title%, %htitle%, and %type%
  243. 'Hhome_template_no_anchor' => '%htitle%',
  244. //Should the blog page be shown globally
  245. 'bblog_display' => true,
  246. //The breadcrumb template for the blog page only in static front page mode, this is global, four keywords are available %link%, %title%, %htitle%, and %type%
  247. 'Hblog_template' => __('<a title="Go to %ftitle%." href="%link%" class="%type%">%htitle%</a>', 'breadcrumb-navxt'),
  248. //The breadcrumb template for the blog page only in static front page mode, used when an anchor is not needed, this is global, four keywords are available %link%, %title%, %htitle%, and %type%
  249. 'Hblog_template_no_anchor' => '%htitle%',
  250. //Separator that is placed between each item in the breadcrumb trial, but not placed before
  251. //the first and not after the last breadcrumb
  252. 'hseparator' => ' &gt; ',
  253. //Whether or not we should trim the breadcrumb titles
  254. 'blimit_title' => false,
  255. //The maximum title lenght
  256. 'amax_title_length' => 20,
  257. //Current item options, really only applies to static pages and posts unless other current items are linked
  258. 'bcurrent_item_linked' => false,
  259. //Static page options
  260. //The anchor template for page breadcrumbs, four keywords are available %link%, %title%, %htitle%, and %type%
  261. 'Hpost_page_template' => __('<a title="Go to %ftitle%." href="%link%" class="%type%">%htitle%</a>', 'breadcrumb-navxt'),
  262. //The anchor template for page breadcrumbs, used when an anchor is not needed, four keywords are available %link%, %title%, %htitle%, and %type%
  263. 'Hpost_page_template_no_anchor' => '%htitle%',
  264. //Just a link to the page on front property
  265. 'apost_page_root' => get_option('page_on_front'),
  266. //Paged options
  267. //The template for paged breadcrumbs, four keywords are available %link%, %title%, %htitle%, and %type%
  268. 'Hpaged_template' => __('Page %htitle%', 'breadcrumb-navxt'),
  269. //Should we try filling out paged information
  270. 'bpaged_display' => false,
  271. //The post options previously singleblogpost
  272. //The breadcrumb template for post breadcrumbs, four keywords are available %link%, %title%, %htitle%, and %type%
  273. 'Hpost_post_template' => __('<a title="Go to %ftitle%." href="%link%" class="%type%">%htitle%</a>', 'breadcrumb-navxt'),
  274. //The breadcrumb template for post breadcrumbs, used when an anchor is not needed, four keywords are available %link%, %title%, %htitle%, and %type%
  275. 'Hpost_post_template_no_anchor' => '%htitle%',
  276. //Just a link for the page for posts
  277. 'apost_post_root' => get_option('page_for_posts'),
  278. //Should the trail include the taxonomy of the post
  279. 'bpost_post_taxonomy_display' => true,
  280. //What taxonomy should be shown leading to the post, tag or category
  281. 'Spost_post_taxonomy_type' => 'category',
  282. //Attachment settings
  283. //TODO: Need to move attachments to support via normal post handlers
  284. //The breadcrumb template for attachment breadcrumbs, four keywords are available %link%, %title%, %htitle%, and %type%
  285. 'Hpost_attachment_template' => __('<a title="Go to %ftitle%." href="%link%" class="%type%">%htitle%</a>', 'breadcrumb-navxt'),
  286. //The breadcrumb template for attachment breadcrumbs, used when an anchor is not needed, four keywords are available %link%, %title%, %htitle%, and %type%
  287. 'Hpost_attachment_template_no_anchor' => '%htitle%',
  288. //404 page settings
  289. //The template for 404 breadcrumbs, four keywords are available %link%, %title%, %htitle%, and %type%
  290. 'H404_template' => '%htitle%',
  291. //The text to be shown in the breadcrumb for a 404 page
  292. 'S404_title' => __('404', 'breadcrumb-navxt'),
  293. //Search page options
  294. //The breadcrumb template for search breadcrumbs, four keywords are available %link%, %title%, %htitle%, and %type%
  295. 'Hsearch_template' => __('Search results for &#39;<a title="Go to the first page of search results for %ftitle%." href="%link%" class="%type%">%htitle%</a>&#39;', 'breadcrumb-navxt'),
  296. //The breadcrumb template for search breadcrumbs, used when an anchor is not necessary, four keywords are available %link%, %title%, %htitle%, and %type%
  297. 'Hsearch_template_no_anchor' => __('Search results for &#39;%htitle%&#39;', 'breadcrumb-navxt'),
  298. //Tag related stuff
  299. //The breadcrumb template for tag breadcrumbs, four keywords are available %link%, %title%, %htitle%, and %type%
  300. 'Hpost_tag_template' => __('<a title="Go to the %ftitle% tag archives." href="%link%" class="%type%">%htitle%</a>', 'breadcrumb-navxt'),
  301. //The breadcrumb template for tag breadcrumbs, used when an anchor is not needed, four keywords are available %link%, %title%, %htitle%, and %type%
  302. 'Hpost_tag_template_no_anchor' => '%htitle%',
  303. //Post format related stuff
  304. //The breadcrumb template for post format breadcrumbs, four keywords are available %link%, %title%, %htitle%, and %type%
  305. 'Hpost_format_template' => __('<a title="Go to the %ftitle% tag archives." href="%link%" class="%type%">%htitle%</a>', 'breadcrumb-navxt'),
  306. //The breadcrumb template for post format breadcrumbs, used when an anchor is not needed, four keywords are available %link%, %title%, %htitle%, and %type%
  307. 'Hpost_format_template_no_anchor' => '%htitle%',
  308. //Author page stuff
  309. //The anchor template for author breadcrumbs, four keywords are available %link%, %title%, %htitle%, and %type%
  310. 'Hauthor_template' => __('Articles by: <a title="Go to the first page of posts by %ftitle%." href="%link%" class="%type%">%htitle%</a>', 'breadcrumb-navxt'),
  311. //The anchor template for author breadcrumbs, used when anchors are not needed, four keywords are available %link%, %title%, %htitle%, and %type%
  312. 'Hauthor_template_no_anchor' => __('Articles by: %htitle%', 'breadcrumb-navxt'),
  313. //Which of the various WordPress display types should the author breadcrumb display
  314. 'Sauthor_name' => 'display_name',
  315. //Category stuff
  316. //The breadcrumb template for category breadcrumbs, four keywords are available %link%, %title%, %htitle%, and %type%
  317. 'Hcategory_template' => __('<a title="Go to the %ftitle% category archives." href="%link%" class="%type%">%htitle%</a>', 'breadcrumb-navxt'),
  318. //The breadcrumb template for category breadcrumbs, used when anchors are not needed, four keywords are available %link%, %title%, %htitle%, and %type%
  319. 'Hcategory_template_no_anchor' => '%htitle%',
  320. //The breadcrumb template for date breadcrumbs, four keywords are available %link%, %title%, %htitle%, and %type%
  321. 'Hdate_template' => __('<a title="Go to the %ftitle% archives." href="%link%" class="%type%">%htitle%</a>', 'breadcrumb-navxt'),
  322. //The breadcrumb template for date breadcrumbs, used when anchors are not needed, four keywords are available %link%, %title%, %htitle%, and %type%
  323. 'Hdate_template_no_anchor' => '%htitle%'
  324. );
  325. }
  326. /**
  327. * This returns the internal version
  328. *
  329. * @return string internal version of the Breadcrumb trail
  330. */
  331. public function get_version()
  332. {
  333. return $this->version;
  334. }
  335. /**
  336. * Adds a breadcrumb to the breadcrumb trail
  337. *
  338. * @return pointer to the just added Breadcrumb
  339. * @param bcn_breadcrumb $object Breadcrumb to add to the trail
  340. */
  341. function &add(bcn_breadcrumb $object)
  342. {
  343. $this->trail[] = $object;
  344. //Return the just added object
  345. return $this->trail[count($this->trail) - 1];
  346. }
  347. /**
  348. * A Breadcrumb Trail Filling Function
  349. *
  350. * This functions fills a breadcrumb for a search page.
  351. */
  352. function do_search()
  353. {
  354. //Place the breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return
  355. $breadcrumb = $this->add(new bcn_breadcrumb(get_search_query(), $this->opt['Hsearch_template_no_anchor'], array('search', 'current-item')));
  356. //If we're paged, or allowing the current item to be linked, let's link to the first page
  357. if($this->opt['bcurrent_item_linked'] || (is_paged() && $this->opt['bpaged_display']))
  358. {
  359. //Since we are paged and are linking the root breadcrumb, time to change to the regular template
  360. $breadcrumb->set_template($this->opt['Hsearch_template']);
  361. //Figure out the hyperlink for the anchor
  362. $url = get_option('home') . '?s=' . str_replace(' ', '+', get_search_query());
  363. //Figure out the anchor for the search
  364. $breadcrumb->set_url($url);
  365. }
  366. }
  367. /**
  368. * A Breadcrumb Trail Filling Function
  369. *
  370. * This functions fills a breadcrumb for an author page.
  371. */
  372. function do_author()
  373. {
  374. global $author;
  375. //Get the Author name, note it is an object
  376. $curauth = (isset($_GET['author_name'])) ? get_userdatabylogin($author_name) : get_userdata(intval($author));
  377. //Setup array of valid author_name values
  378. $valid_author_name = array('display_name', 'nickname', 'first_name', 'last_name');
  379. //This translation allows us to easily select the display type later on
  380. $author_name = $this->opt['Sauthor_name'];
  381. //Make sure user picks only safe values
  382. if(in_array($author_name, $valid_author_name))
  383. {
  384. //TODO Evaluate the need for this filter call
  385. //Place the breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return
  386. $breadcrumb = $this->add(new bcn_breadcrumb(apply_filters('the_author', $curauth->$author_name), $this->opt['Hauthor_template_no_anchor'], array('author', 'current-item'), NULL, $curauth->ID));
  387. //If we're paged, or allowing the current item to be linked, let's link to the first page
  388. if($this->opt['bcurrent_item_linked'] || (is_paged() && $this->opt['bpaged_display']))
  389. {
  390. //Set the template to our one containing an anchor
  391. $breadcrumb->set_template($this->opt['Hauthor_template']);
  392. $breadcrumb->set_url(get_author_posts_url($curauth->ID));
  393. }
  394. }
  395. }
  396. /**
  397. * A Breadcrumb Trail Filling Function
  398. *
  399. * This function fills breadcrumbs for any post taxonomy.
  400. * @param int $id The id of the post to figure out the taxonomy for.
  401. * @param string $type The post type of the post to figure out the taxonomy for.
  402. * @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
  403. *
  404. * TODO: Add logic for contextual taxonomy selection
  405. */
  406. function post_hierarchy($id, $type, $parent = NULL)
  407. {
  408. //Check to see if breadcrumbs for the taxonomy of the post needs to be generated
  409. if($this->opt['bpost_' . $type . '_taxonomy_display'])
  410. {
  411. //Check if we have a date 'taxonomy' request
  412. if($this->opt['Spost_' . $type . '_taxonomy_type'] == 'date')
  413. {
  414. $this->do_archive_by_date();
  415. }
  416. //Handle all hierarchical taxonomies, including categories
  417. else if(is_taxonomy_hierarchical($this->opt['Spost_' . $type . '_taxonomy_type']))
  418. {
  419. //Fill a temporary object with the terms
  420. $bcn_object = get_the_terms($id, $this->opt['Spost_' . $type . '_taxonomy_type']);
  421. if(is_array($bcn_object))
  422. {
  423. //Now find which one has a parent, pick the first one that does
  424. $bcn_use_term = key($bcn_object);
  425. foreach($bcn_object as $key=>$object)
  426. {
  427. //We want the first term hiearchy
  428. if($object->parent > 0)
  429. {
  430. $bcn_use_term = $key;
  431. //We found our first term hiearchy, can exit loop now
  432. break;
  433. }
  434. }
  435. //Fill out the term hiearchy
  436. $this->term_parents($bcn_object[$bcn_use_term]->term_id, $this->opt['Spost_' . $type . '_taxonomy_type']);
  437. }
  438. }
  439. //Handle the use of hierarchical posts as the 'taxonomy'
  440. else if(is_post_type_hierarchical($this->opt['Spost_' . $type . '_taxonomy_type']))
  441. {
  442. if($parent == NULL)
  443. {
  444. //We have to grab the post to find its parent, can't use $post for this one
  445. $parent = get_post($id);
  446. $parent = $parent->post_parent;
  447. }
  448. //Done with the current item, now on to the parents
  449. $bcn_frontpage = get_option('page_on_front');
  450. //If there is a parent page let's find it
  451. if($parent && $id != $parent && $bcn_frontpage != $parent)
  452. {
  453. $this->post_parents($parent, $bcn_frontpage);
  454. }
  455. }
  456. //Handle the rest of the taxonomies, including tags
  457. else
  458. {
  459. $this->post_terms($id, $this->opt['Spost_' . $type . '_taxonomy_type']);
  460. }
  461. }
  462. }
  463. /**
  464. * A Breadcrumb Trail Filling Function
  465. *
  466. * This functions fills a breadcrumb for the terms of a post
  467. * @param int $id The id of the post to find the terms for.
  468. * @param string $taxonomy The name of the taxonomy that the term belongs to
  469. *
  470. * TODO Need to implement this cleaner, fix up the entire tag_ thing, as this is now generic
  471. * TODO This still needs to be updated to the new method of adding breadcrumbs to the trail
  472. */
  473. function post_terms($id, $taxonomy)
  474. {
  475. //Fills a temporary object with the terms for the post
  476. $bcn_object = get_the_terms($id, $taxonomy);
  477. //Only process if we have terms
  478. if(is_array($bcn_object))
  479. {
  480. //Add new breadcrumb to the trail
  481. $this->trail[] = new bcn_breadcrumb();
  482. //Figure out where we placed the crumb, make a nice pointer to it
  483. $bcn_breadcrumb = &$this->trail[count($this->trail) - 1];
  484. $is_first = true;
  485. //Loop through all of the term results
  486. foreach($bcn_object as $term)
  487. {
  488. //Everything but the first term needs a comma separator
  489. if($is_first == false)
  490. {
  491. $bcn_breadcrumb->set_title($bcn_breadcrumb->get_title() . ', ');
  492. }
  493. //This is a bit hackish, but it compiles the term anchor and appends it to the current breadcrumb title
  494. $bcn_breadcrumb->set_title($bcn_breadcrumb->get_title() . str_replace(
  495. array('%title%', '%link%', '%htitle%', '%type%'),
  496. array($term->name, get_term_link($term, $taxonomy), $term->name, $term->taxonomy),
  497. $this->opt['H' . $term->taxonomy . '_template']));
  498. $is_first = false;
  499. }
  500. }
  501. }
  502. /**
  503. * A Breadcrumb Trail Filling Function
  504. *
  505. * This recursive functions fills the trail with breadcrumbs for parent terms.
  506. * @param int $id The id of the term.
  507. * @param string $taxonomy The name of the taxonomy that the term belongs to
  508. * @TODO Evaluate if we need to do tax_ for a prefix
  509. */
  510. function term_parents($id, $taxonomy)
  511. {
  512. global $post;
  513. //Get the current category object, filter applied within this call
  514. $term = get_term($id, $taxonomy);
  515. //Place the breadcrumb in the trail, uses the constructor to set the title, template, and type, get a pointer to it in return
  516. $breadcrumb = $this->add(new bcn_breadcrumb($term->name, $this->opt['H' . $taxonomy . '_template'], array($taxonomy), get_term_link($term, $taxonomy), $id));
  517. //Make sure the id is valid, and that we won't end up spinning in a loop
  518. if($term->parent && $term->parent != $id)
  519. {
  520. //Figure out the rest of the term hiearchy via recursion
  521. $this->term_parents($term->parent, $taxonomy);
  522. }
  523. }
  524. /**
  525. * A Breadcrumb Trail Filling Function
  526. *
  527. * This recursive functions fills the trail with breadcrumbs for parent posts/pages.
  528. * @param int $id The id of the parent page.
  529. * @param int $frontpage The id of the front page.
  530. */
  531. function post_parents($id, $frontpage)
  532. {
  533. //Use WordPress API, though a bit heavier than the old method, this will ensure compatibility with other plug-ins
  534. $parent = get_post($id);
  535. //Place the breadcrumb in the trail, uses the constructor to set the title, template, and type, get a pointer to it in return
  536. $breadcrumb = $this->add(new bcn_breadcrumb(get_the_title($id), $this->opt['Hpost_' . $parent->post_type . '_template'], array($parent->post_type), get_permalink($id), $id));
  537. //Make sure the id is valid, and that we won't end up spinning in a loop
  538. if($parent->post_parent >= 0 && $parent->post_parent != false && $id != $parent->post_parent && $frontpage != $parent->post_parent)
  539. {
  540. //If valid, recursively call this function
  541. $this->post_parents($parent->post_parent, $frontpage);
  542. }
  543. }
  544. /**
  545. * A Breadcrumb Trail Filling Function
  546. *
  547. * This functions fills a breadcrumb for posts
  548. *
  549. */
  550. function do_post()
  551. {
  552. global $post, $page;
  553. //Place the breadcrumb in the trail, uses the bcn_breadcrumb constructor to set the title, template, and type
  554. $breadcrumb = $this->add(new bcn_breadcrumb(get_the_title(), $this->opt['Hpost_' . $post->post_type . '_template_no_anchor'], array('post-' . $post->post_type, 'current-item'), NULL, $post->ID));
  555. //If the current item is to be linked, or this is a paged post, add in links
  556. if($this->opt['bcurrent_item_linked'] || ($page > 1 && $this->opt['bpaged_display']))
  557. {
  558. //Change the template over to the normal, linked one
  559. $breadcrumb->set_template($this->opt['Hpost_' . $post->post_type . '_template']);
  560. //Add the link
  561. $breadcrumb->set_url(get_permalink());
  562. }
  563. //If we have page, force it to go through the parent tree
  564. if($post->post_type === 'page')
  565. {
  566. //Done with the current item, now on to the parents
  567. $frontpage = get_option('page_on_front');
  568. //If there is a parent page let's find it
  569. if($post->post_parent && $post->ID != $post->post_parent && $frontpage != $post->post_parent)
  570. {
  571. $this->post_parents($post->post_parent, $frontpage);
  572. }
  573. }
  574. //Otherwise we need the follow the hiearchy tree
  575. else
  576. {
  577. //Handle the post's hiearchy
  578. $this->post_hierarchy($post->ID, $post->post_type, $post->post_parent);
  579. }
  580. }
  581. /**
  582. * A Breadcrumb Trail Filling Function
  583. *
  584. * This functions fills a breadcrumb for an attachment page.
  585. *
  586. * @TODO Evaluate if this can be merged in with the do_post function
  587. */
  588. function do_attachment()
  589. {
  590. global $post;
  591. //Place the breadcrumb in the trail, uses the constructor to set the title, template, and type, get a pointer to it in return
  592. $breadcrumb = $this->add(new bcn_breadcrumb(get_the_title(), $this->opt['Hpost_attachment_template_no_anchor'], array('post-attachment', 'current-item'), NULL, $post->ID));
  593. if($this->opt['bcurrent_item_linked'])
  594. {
  595. //Change the template over to the normal, linked one
  596. $breadcrumb->set_template($this->opt['Hpost_attachment_template']);
  597. //Add the link
  598. $breadcrumb->set_url(get_permalink());
  599. }
  600. //Get the parent's information
  601. $parent = get_post($post->post_parent);
  602. //Place the breadcrumb in the trail, uses the constructor to set the title, template, and type, get a pointer to it in return
  603. $breadcrumb = $this->add(new bcn_breadcrumb(get_the_title($post->post_parent), $this->opt['Hpost_' . $parent->post_type . '_template'], array($parent->post_type), get_permalink($post->post_parent), $post->post_parent));
  604. //We need to treat flat and hiearchical post attachment hierachies differently
  605. if(is_post_type_hierarchical($parent->post_type))
  606. {
  607. //Done with the current item, now on to the parents
  608. $frontpage = get_option('page_on_front');
  609. //If there is a parent page let's find it
  610. if($parent->post_parent && $parent->ID != $parent->post_parent && $frontpage != $parent->post_parent)
  611. {
  612. $this->post_parents($parent->post_parent, $frontpage);
  613. }
  614. else if(!$this->is_builtin($parent->post_type))
  615. {
  616. //Handle the post's taxonomy
  617. $this->post_hierarchy($post->post_parent, $parent->post_type);
  618. }
  619. }
  620. else
  621. {
  622. //Handle the post's taxonomy
  623. $this->post_hierarchy($post->post_parent, $parent->post_type);
  624. }
  625. }
  626. /**
  627. * A Breadcrumb Trail Filling Function
  628. *
  629. * This function fills a breadcrumb for any taxonomy archive, was previously two separate functions
  630. *
  631. */
  632. function do_archive_by_term()
  633. {
  634. global $wp_query;
  635. //Simmilar to using $post, but for things $post doesn't cover
  636. $term = $wp_query->get_queried_object();
  637. //Place the breadcrumb in the trail, uses the constructor to set the title, template, and type, get a pointer to it in return
  638. $breadcrumb = $this->add(new bcn_breadcrumb($term->name, $this->opt['H' . $term->taxonomy . '_template_no_anchor'], array($term->taxonomy, 'current-item'), NULL, $term->term_id));
  639. //If we're paged, let's link to the first page
  640. if($this->opt['bcurrent_item_linked'] || (is_paged() && $this->opt['bpaged_display']))
  641. {
  642. $breadcrumb->set_template($this->opt['H' . $term->taxonomy . '_template']);
  643. //Figure out the anchor for current category
  644. $breadcrumb->set_url(get_term_link($term, $term->taxonomy));
  645. }
  646. //Get parents of current category
  647. if($term->parent)
  648. {
  649. $this->term_parents($term->parent, $term->taxonomy);
  650. }
  651. }
  652. /**
  653. * A Breadcrumb Trail Filling Function
  654. *
  655. * This functions fills a breadcrumb for a date archive.
  656. *
  657. */
  658. function do_archive_by_date()
  659. {
  660. global $wp_query;
  661. //First deal with the day breadcrumb
  662. if(is_day() || is_single())
  663. {
  664. //Place the breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return
  665. $breadcrumb = $this->add(new bcn_breadcrumb(get_the_time('d'), $this->opt['Hdate_template_no_anchor'], array('date-day')));
  666. //If this is a day archive, add current-item type
  667. if(is_day())
  668. {
  669. $breadcrumb->add_type('current-item');
  670. }
  671. //If we're paged, let's link to the first page
  672. if($this->opt['bcurrent_item_linked'] || is_paged() && $this->opt['bpaged_display'] || is_single())
  673. {
  674. //We're linking, so set the linked template
  675. $breadcrumb->set_template($this->opt['Hdate_template']);
  676. //Deal with the anchor
  677. $breadcrumb->set_url(get_day_link(get_the_time('Y'), get_the_time('m'), get_the_time('d')));
  678. }
  679. }
  680. //Now deal with the month breadcrumb
  681. if(is_month() || is_day() || is_single())
  682. {
  683. //Place the breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return
  684. $breadcrumb = $this->add(new bcn_breadcrumb(get_the_time('F'), $this->opt['Hdate_template_no_anchor'], array('date-month')));
  685. //If this is a month archive, add current-item type
  686. if(is_month())
  687. {
  688. $breadcrumb->add_type('current-item');
  689. }
  690. //If we're paged, or not in the archive by month let's link to the first archive by month page
  691. if($this->opt['bcurrent_item_linked'] || is_day() || is_single() || (is_month() && is_paged() && $this->opt['bpaged_display']))
  692. {
  693. //We're linking, so set the linked template
  694. $breadcrumb->set_template($this->opt['Hdate_template']);
  695. //Deal with the anchor
  696. $breadcrumb->set_url(get_month_link(get_the_time('Y'), get_the_time('m')));
  697. }
  698. }
  699. //Place the year breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return
  700. $breadcrumb = $this->add(new bcn_breadcrumb(get_the_time('Y'), $this->opt['Hdate_template_no_anchor'], array('date-year')));
  701. //If this is a year archive, add current-item type
  702. if(is_year())
  703. {
  704. $breadcrumb->add_type('current-item');
  705. }
  706. //If we're paged, or not in the archive by year let's link to the first archive by year page
  707. if($this->opt['bcurrent_item_linked'] || is_day() || is_month() || is_single() || (is_paged() && $this->opt['bpaged_display']))
  708. {
  709. //We're linking, so set the linked template
  710. $breadcrumb->set_template($this->opt['Hdate_template']);
  711. //Deal with the anchor
  712. $breadcrumb->set_url(get_year_link(get_the_time('Y')));
  713. }
  714. }
  715. /**
  716. * A Breadcrumb Trail Filling Function
  717. *
  718. * This functions fills a breadcrumb for a post type archive (WP 3.1 feature)
  719. */
  720. function do_archive_by_post_type()
  721. {
  722. //Place the breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return
  723. $breadcrumb = $this->add(new bcn_breadcrumb(post_type_archive_title('', false), $this->opt['Hpost_' . get_post_type() . '_template_no_anchor'], array('post-' . get_post_type() . '-archive', 'current-item')));
  724. if($this->opt['bcurrent_item_linked'] || is_paged() && $this->opt['bpaged_display'])
  725. {
  726. $breadcrumb->set_template($this->opt['Hpost_' . get_post_type() . '_template']);
  727. //Deal with the anchor
  728. $breadcrumb->set_url(get_post_type_archive_link(get_post_type()));
  729. }
  730. }
  731. /**
  732. * A Breadcrumb Trail Filling Function
  733. *
  734. * This functions fills a breadcrumb for the front page.
  735. */
  736. function do_front_page()
  737. {
  738. global $post, $current_site;
  739. //Get the site name
  740. $site_name = get_option('blogname');
  741. //Place the breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return
  742. $breadcrumb = $this->add(new bcn_breadcrumb($site_name, $this->opt['Hhome_template_no_anchor'], array('home', 'current-item')));
  743. //If we're paged, let's link to the first page
  744. if($this->opt['bcurrent_item_linked'] || (is_paged() && $this->opt['bpaged_display']))
  745. {
  746. $breadcrumb->set_template($this->opt['Hhome_template']);
  747. //Figure out the anchor for home page
  748. $breadcrumb->set_url(get_home_url());
  749. }
  750. //If we have a multi site and are not on the main site we may need to add a breadcrumb for the main site
  751. if($this->opt['bmainsite_display'] && !is_main_site())
  752. {
  753. //Get the site name
  754. $site_name = get_site_option('site_name');
  755. //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
  756. $breadcrumb = $this->add(new bcn_breadcrumb($site_name, $this->opt['Hmainsite_template'], array('main-home'), get_home_url($current_site->blog_id)));
  757. }
  758. }
  759. /**
  760. * A Breadcrumb Trail Filling Function
  761. *
  762. * This functions fills a breadcrumb for the home page.
  763. */
  764. function do_home()
  765. {
  766. global $post, $current_site;
  767. //On everything else we need to link, but no current item (pre/suf)fixes
  768. if($this->opt['bhome_display'])
  769. {
  770. //Get the site name
  771. $site_name = get_option('blogname');
  772. //Place the breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return
  773. $breadcrumb = $this->add(new bcn_breadcrumb($site_name, $this->opt['Hhome_template'], array('home'), get_home_url()));
  774. //If we have a multi site and are not on the main site we need to add a breadcrumb for the main site
  775. if($this->opt['bmainsite_display'] && !is_main_site())
  776. {
  777. //Get the site name
  778. $site_name = get_site_option('site_name');
  779. //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
  780. $breadcrumb = $this->add(new bcn_breadcrumb($site_name, $this->opt['Hmainsite_template'], array('main-home'), get_home_url($current_site->blog_id)));
  781. }
  782. }
  783. }
  784. /**
  785. * A modified version of WordPress' function of the same name
  786. *
  787. * @param object $object the post or taxonomy object used to attempt to find the title
  788. * @return string the title
  789. */
  790. function post_type_archive_title($object)
  791. {
  792. if(isset($object->labels->name))
  793. {
  794. //Core filter use here is ok for time being
  795. //TODO: Recheck validitiy prior to each release
  796. return apply_filters('post_type_archive_title', $object->labels->name);
  797. }
  798. }
  799. /**
  800. * Determines if a post type is a built in type or not
  801. *
  802. * @param string $post_type the name of the post type
  803. * @return bool
  804. */
  805. function is_builtin($post_type)
  806. {
  807. $type = get_post_type_object($post_type);
  808. return $type->_builtin;
  809. }
  810. /**
  811. * Determines if a post type has archives enabled or not
  812. *
  813. * @param string $post_type the name of the post type
  814. * @return bool
  815. */
  816. function has_archive($post_type)
  817. {
  818. $type = get_post_type_object($post_type);
  819. return $type->has_archive;
  820. }
  821. /**
  822. * This function populates our type_str and posts_id variables
  823. *
  824. * @param post $type A post object we are using to figureout the type
  825. * @param string $type_str The type string variable, passed by reference
  826. * @param int $root_id The ID for the post type root
  827. */
  828. function find_type($type, &$type_str, &$root_id)
  829. {
  830. global $wp_taxonomies;
  831. //We need to do special things for custom post types
  832. if(is_singular() && !$this->is_builtin($type->post_type))
  833. {
  834. //We need the type for later, so save it
  835. $type_str = $type->post_type;
  836. //This will assign a ID for root page of a custom post
  837. if(is_numeric($this->opt['apost_' . $type_str . '_root']))
  838. {
  839. $root_id = $this->opt['apost_' . $type_str . '_root'];
  840. }
  841. }
  842. //For CPT archives
  843. else if(is_post_type_archive() && !isset($type->taxonomy))
  844. {
  845. //We need the type for later, so save it
  846. $type_str = $type->name;
  847. //This will assign a ID for root page of a custom post's taxonomy archive
  848. if(is_numeric($this->opt['apost_' . $type_str . '_root']))
  849. {
  850. $root_id = $this->opt['apost_' . $type_str . '_root'];
  851. }
  852. }
  853. //We need to do special things for custom post type archives, but not author or date archives
  854. else if(is_archive() && !is_author() && !is_date() && !$this->is_builtin($wp_taxonomies[$type->taxonomy]->object_type[0]))
  855. {
  856. //We need the type for later, so save it
  857. $type_str = $wp_taxonomies[$type->taxonomy]->object_type[0];
  858. //This will assign a ID for root page of a custom post's taxonomy archive
  859. if(is_numeric($this->opt['apost_' . $type_str . '_root']))
  860. {
  861. $root_id = $this->opt['apost_' . $type_str . '_root'];
  862. }
  863. }
  864. else
  865. {
  866. $type_str = "post";
  867. }
  868. }
  869. /**
  870. * A Breadcrumb Trail Filling Function
  871. *
  872. * Handles only the root page stuff for post types, including the "page for posts"
  873. *
  874. * TODO: this still needs to be cleaned up
  875. */
  876. function do_root()
  877. {
  878. global $post, $wp_query, $wp_taxonomies, $current_site;
  879. //If this is an attachment then we need to change the queried object to the parent post
  880. if(is_attachment())
  881. {
  882. $type = get_post($post->post_parent);
  883. }
  884. else
  885. {
  886. //Simmilar to using $post, but for things $post doesn't cover
  887. $type = $wp_query->get_queried_object();
  888. }
  889. $root_id = -1;
  890. //Find our type string and root_id
  891. $this->find_type($type, $type_str, $root_id);
  892. //These two are for taxonomy archives and for a single custom post type
  893. if(isset($type->post_type) && !$this->is_builtin($type->post_type) && $this->opt['bpost_' . $type->post_type . '_archive_display'] && $this->has_archive($type->post_type))
  894. {
  895. //Place the breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return
  896. $breadcrumb = $this->add(new bcn_breadcrumb($this->post_type_archive_title(get_post_type_object($type->post_type)), $this->opt['Hpost_' . $type->post_type . '_template'], array('post-' . $type->post_type . '-archive'), get_post_type_archive_link($type->post_type)));
  897. }
  898. else if(isset($type->taxonomy) && !$this->is_builtin($wp_taxonomies[$type->taxonomy]->object_type[0]) && $this->opt['bpost_' . $wp_taxonomies[$type->taxonomy]->object_type[0] . '_archive_display'] && $this->has_archive($wp_taxonomies[$type->taxonomy]->object_type[0]))
  899. {
  900. //We end up using the post type in several places, give it a variable
  901. $post_type = $wp_taxonomies[$type->taxonomy]->object_type[0];
  902. //Place the breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return
  903. $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_type . '-archive'), get_post_type_archive_link($post_type)));
  904. }
  905. //We only need the "blog" portion on members of the blog, and only if we're in a static frontpage environment
  906. if($root_id > 1 || $this->opt['bblog_display'] && get_option('show_on_front') == 'page' && (is_home() || is_single() || is_tax() || is_category() || is_tag() || is_date()))
  907. {
  908. //If we entered here with a posts page, we need to set the id
  909. if($root_id < 0)
  910. {
  911. $root_id = get_option('page_for_posts');
  912. }
  913. $frontpage_id = get_option('page_on_front');
  914. //We'll have to check if this ID is valid, e.g. user has specified a posts page
  915. if($root_id && $root_id != $frontpage_id)
  916. {
  917. //Place the breadcrumb in the trail, uses the constructor to set the title, template, and type, we get a pointer to it in return
  918. $breadcrumb = $this->add(new bcn_breadcrumb(get_the_title($root_id), $this->opt['Hpost_' . $type_str . '_template_no_anchor'], array($type_str . '-root', 'post-' . $type_str)));
  919. //If we are at home, then we need to add the current item type
  920. if(is_home())
  921. {
  922. $breadcrumb->add_type('current-item');
  923. }
  924. //If we're not on the current item we need to setup the anchor
  925. if(!is_home() || (is_paged() && $this->opt['bpaged_display']) || (is_home() && $this->opt['bcurrent_item_linked']))
  926. {
  927. $breadcrumb->set_template($this->opt['Hpost_' . $type_str . '_template']);
  928. //Figure out the anchor for home page
  929. $breadcrumb->set_url(get_permalink($root_id));
  930. }
  931. //Done with the "root", now on to the parents
  932. //Get the blog page
  933. $bcn_post = get_post($root_id);
  934. //If there is a parent post let's find it
  935. if($bcn_post->post_parent && $bcn_post->ID != $bcn_post->post_parent && $frontpage_id != $bcn_post->post_parent)
  936. {
  937. $this->post_parents($bcn_post->post_parent, $frontpage_id);
  938. }
  939. }
  940. }
  941. }
  942. /**
  943. * A Breadcrumb Trail Filling Function
  944. *
  945. * This functions fills a breadcrumb for 404 pages.
  946. */
  947. function do_404()
  948. {
  949. //Place the breadcrumb in the trail, uses the bcn_breadcrumb constructor to set the title, prefix, and suffix
  950. $this->trail[] = new bcn_breadcrumb($this->opt['S404_title'], $this->opt['H404_template'], array('404', 'current-item'));
  951. }
  952. /**
  953. * A Breadcrumb Trail Filling Function
  954. *
  955. * This functions fills a breadcrumb for paged pages.
  956. */
  957. function do_paged()
  958. {
  959. global $paged, $page;
  960. //Need to switch between paged and page for archives and singular (posts)
  961. if($paged > 0)
  962. {
  963. $page_number = $paged;
  964. }
  965. else
  966. {
  967. $page_number = $page;
  968. }
  969. //Place the breadcrumb in the trail, uses the bcn_breadcrumb constructor to set the title, prefix, and suffix
  970. $this->trail[] = new bcn_breadcrumb($page_number, $this->opt['Hpaged_template'], array('paged'));
  971. }
  972. /**
  973. * Breadcrumb Trail Filling Function
  974. *
  975. * This functions fills the breadcrumb trail.
  976. */
  977. function fill()
  978. {
  979. global $wpdb, $post, $wp_query, $paged, $page;
  980. //Check to see if the trail is already populated
  981. if(count($this->trail) > 0)
  982. {
  983. //Exit early since we have breadcrumbs in the trail
  984. return NULL;
  985. }
  986. //Do any actions if necessary, we past through the current object instance to keep life simple
  987. do_action('bcn_before_fill', $this);
  988. //Do specific opperations for the various page types
  989. //Check if this isn't the first of a multi paged item
  990. if($this->opt['bpaged_display'] && (is_paged() || is_singular() && $page > 1))
  991. {
  992. $this->do_paged();
  993. }
  994. //For the front page, as it may also validate as a page, do it first
  995. if(is_front_page())
  996. {
  997. //Must have two seperate branches so that we don't evaluate it as a page
  998. if($this->opt['bhome_display'])
  999. {
  1000. $this->do_front_page();
  1001. }
  1002. }
  1003. //For posts
  1004. else if(is_singular())
  1005. {
  1006. //For attachments
  1007. if(is_attachment())
  1008. {
  1009. $this->do_attachment();
  1010. }
  1011. //For all other post types
  1012. else
  1013. {
  1014. $this->do_post();
  1015. }
  1016. }
  1017. //For searches
  1018. else if(is_search())
  1019. {
  1020. $this->do_search();
  1021. }
  1022. //For author pages
  1023. else if(is_author())
  1024. {
  1025. $this->do_author();
  1026. }
  1027. //For archives
  1028. else if(is_archive())
  1029. {
  1030. $type = $wp_query->get_queried_object();
  1031. //For date based archives
  1032. if(is_date())
  1033. {
  1034. $this->do_archive_by_date();
  1035. }
  1036. else if(is_post_type_archive() && !isset($type->taxonomy))
  1037. {
  1038. $this->do_archive_by_post_type();
  1039. }
  1040. //For taxonomy based archives
  1041. else if(is_category() || is_tag() || is_tax())
  1042. {
  1043. $this->do_archive_by_term();
  1044. }
  1045. }
  1046. //For 404 pages
  1047. else if(is_404())
  1048. {
  1049. $this->do_404();
  1050. }
  1051. //We always do the home link last, unless on the frontpage
  1052. if(!is_front_page())
  1053. {
  1054. $this->do_root();
  1055. $this->do_home();
  1056. }
  1057. //Do any actions if necessary, we past through the current object instance to keep life simple
  1058. do_action('bcn_after_fill', $this);
  1059. }
  1060. /**
  1061. * This function will either set the order of the trail to reverse key
  1062. * order, or make sure it is forward key ordered.
  1063. *
  1064. * @param bool $reverse[optional] Whether to reverse the trail or not.
  1065. */
  1066. function order($reverse = false)
  1067. {
  1068. if($reverse)
  1069. {
  1070. //Since there may be multiple calls our trail may be in a non-standard order
  1071. ksort($this->trail);
  1072. }
  1073. else
  1074. {
  1075. //For normal opperation we must reverse the array by key
  1076. krsort($this->trail);
  1077. }
  1078. }
  1079. /**
  1080. * This functions outputs or returns the breadcrumb trail in string form.
  1081. *
  1082. * @return void Void if Option to print out breadcrumb trail was chosen.
  1083. * @return string String-Data of breadcrumb trail.
  1084. * @param bool $return Whether to return data or to echo it.
  1085. * @param bool $linked[optional] Whether to allow hyperlinks in the trail or not.
  1086. * @param bool $reverse[optional] Whether to reverse the output or not.
  1087. */
  1088. function display($return = false, $linked = true, $reverse = false)
  1089. {
  1090. //Set trail order based on reverse flag
  1091. $this->order($reverse);
  1092. //Initilize the string which will hold the assembled trail
  1093. $trail_str = '';
  1094. //The main compiling loop
  1095. foreach($this->trail as $key => $breadcrumb)
  1096. {
  1097. //Must branch if we are reversing the output or not
  1098. if($reverse)
  1099. {
  1100. //Add in the separator only if we are the 2nd or greater element
  1101. if($key > 0)
  1102. {
  1103. $trail_str .= $this->opt['hseparator'];
  1104. }
  1105. }
  1106. else
  1107. {
  1108. //Only show the separator when necessary
  1109. if($key < count($this->trail) - 1)
  1110. {
  1111. $trail_str .= $this->opt['hseparator'];
  1112. }
  1113. }
  1114. //Trim titles, if needed
  1115. if($this->opt['blimit_title'] && $this->opt['amax_title_length'] > 0)
  1116. {
  1117. //Trim the breadcrumb's title
  1118. $breadcrumb->title_trim($this->opt['amax_title_length']);
  1119. }
  1120. //Place in the breadcrumb's assembled elements
  1121. $trail_str .= $breadcrumb->assemble($linked);
  1122. }
  1123. //Should we return or echo the assembled trail?
  1124. if($return)
  1125. {
  1126. return $trail_str;
  1127. }
  1128. else
  1129. {
  1130. //Helps track issues, please don't remove it
  1131. $credits = "<!-- Breadcrumb NavXT " . $this->version . " -->\n";
  1132. echo $credits . $trail_str;
  1133. }
  1134. }
  1135. /**
  1136. * This functions outputs or returns the breadcrumb trail in list form.
  1137. *
  1138. * @return void Void if Option to print out breadcrumb trail was chosen.
  1139. * @return string String-Data of breadcrumb trail.
  1140. * @param bool $return Whether to return data or to echo it.
  1141. * @param bool $linked[optional] Whether to allow hyperlinks in the trail or not.
  1142. * @param bool $reverse[optional] Whether to reverse the output or not.
  1143. *
  1144. * TODO: Can probably write this one in a smarter way now
  1145. */
  1146. function display_list($return = false, $linked = true, $reverse = false)
  1147. {
  1148. //Set trail order based on reverse flag
  1149. $this->order($reverse);
  1150. //Initilize the string which will hold the assembled trail
  1151. $trail_str = '';
  1152. //The main compiling loop
  1153. foreach($this->trail as $key => $breadcrumb)
  1154. {
  1155. $trail_str .= '<li';
  1156. //On the first run we need to add in a class for the home breadcrumb
  1157. if($trail_str === '<li')
  1158. {
  1159. $trail_str .= ' class="home';
  1160. if($key === 0)
  1161. {
  1162. $trail_str .= ' current_item';
  1163. }
  1164. $trail_str .= '"';
  1165. }
  1166. //If we are on the current item there are some things that must be done
  1167. else if($key === 0)
  1168. {
  1169. //Add in a class for current_item
  1170. $trail_str .= ' class="current_item"';
  1171. }
  1172. //Trim titles, if needed
  1173. if($this->opt['blimit_title'] && $this->opt['amax_title_length'] > 0)
  1174. {
  1175. //Trim the breadcrumb's title
  1176. $breadcrumb->title_trim($this->opt['amax_title_length']);
  1177. }
  1178. //Place in the breadcrumb's assembled elements
  1179. $trail_str .= '>' . $breadcrumb->assemble($linked);
  1180. $trail_str .= "</li>\n";
  1181. }
  1182. //Should we return or echo the assembled trail?
  1183. if($return)
  1184. {
  1185. return $trail_str;
  1186. }
  1187. else
  1188. {
  1189. //Helps track issues, please don't remove it
  1190. $credits = "<!-- Breadcrumb NavXT " . $this->version . " -->\n";
  1191. echo $credits . $trail_str;
  1192. }
  1193. }
  1194. }