PageRenderTime 54ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/fuel/application/libraries/Menu.php

https://github.com/santanu4php/FUEL-CMS
PHP | 1058 lines | 643 code | 128 blank | 287 comment | 134 complexity | 4d598f00b968931dceeb2d2bf1a9465b MD5 | raw file
  1. <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
  2. /**
  3. * FUEL CMS
  4. * http://www.getfuelcms.com
  5. *
  6. * An open source Content Management System based on the
  7. * Codeigniter framework (http://codeigniter.com)
  8. *
  9. * @package FUEL CMS
  10. * @author David McReynolds @ Daylight Studio
  11. * @copyright Copyright (c) 2011, Run for Daylight LLC.
  12. * @license http://www.getfuelcms.com/user_guide/general/license
  13. * @link http://www.getfuelcms.com
  14. */
  15. // ------------------------------------------------------------------------
  16. /**
  17. * A menu builder
  18. *
  19. * This class takes an array of elements that you can create a parent
  20. * child relationship by creating an array like so:
  21. *
  22. * $nav['about/history'] = array('label' => 'About', 'parent_id' => 'about');
  23. * OR
  24. * $nav['about/history'] = array('location' => 'about_us/history', label' => 'About', 'parent_id' => 'about');
  25. * The documentation gives more detail
  26. *
  27. * @package FUEL CMS
  28. * @subpackage Libraries
  29. * @category Libraries
  30. * @author David McReynolds @ Daylight Studio
  31. * @link http://www.getfuelcms.com/user_guide/libraries/menu
  32. */
  33. class Menu {
  34. public $active_class = 'active'; // the active css class
  35. public $active = ''; // the active menu item
  36. public $styles = array(); // css class styles to apply to menu items... can be a nested array
  37. public $first_class = 'first'; // the css class for the first menu item
  38. public $last_class = 'last'; // the css class for the last menu item
  39. public $depth = NULL; // the depth of the menu to render at
  40. public $use_titles = TRUE; // use the title attribute in the links
  41. public $root_value = NULL; // the root parent value... can be NULL or 0
  42. public $container_tag = 'ul'; // the html tag for the container of a set of menu items
  43. public $container_tag_attrs = ''; // html attributes for the container tag
  44. public $container_tag_id = ''; // html container id
  45. public $container_tag_class = ''; // html container class
  46. public $cascade_selected = TRUE; // cascade the selected items
  47. public $include_hidden = FALSE; // include menu items with the hidden attribute
  48. public $item_tag = 'li'; // the html list item element
  49. public $item_id_prefix = ''; // the prefix to the item id
  50. public $item_id_key = 'id'; // either id or location
  51. public $use_nav_key = 'AUTO'; // use the nav_key value to match active
  52. public $render_type = 'basic'; // basic, breadcrumb, page_title, collapsible, delimited, array
  53. public $pre_render_func = ''; // function to apply to menu labels before rendering
  54. // for breadcrumb AND/OR page_title
  55. public $delimiter = FALSE; // the html element between the links
  56. public $display_current = TRUE; // display the current active breadcrumb item?
  57. public $home_link = 'Home'; // the root home link
  58. // for breadcrumb ONLY
  59. public $arrow_class = 'arrow'; // the class for the arrows
  60. // for page_title ONLY
  61. public $order = 'asc'; // the order to display... for page_title ONLY
  62. protected $_items = array(); // the items in the menu
  63. protected $_active_items = array(); // the active menu items
  64. protected $_reset_params = array(); // reset params
  65. /**
  66. * Constructor - Sets Menu preferences
  67. *
  68. * The constructor can be passed an array of config values
  69. */
  70. public function __construct($params = array())
  71. {
  72. $CI =& get_instance();
  73. $CI->load->helper('url');
  74. $ignore = array('_reset_params');
  75. $class_vars = get_class_vars(get_class($this));
  76. foreach($class_vars as $key => $val)
  77. {
  78. if (!in_array($key, $ignore)) $this->_reset_params[$key] = $val;
  79. }
  80. $this->initialize($params);
  81. }
  82. // --------------------------------------------------------------------
  83. /**
  84. * Initialize preferences
  85. *
  86. * @access public
  87. * @param array
  88. * @return void
  89. */
  90. public function initialize($params = array())
  91. {
  92. $valid_null = array('root_value', 'depth');
  93. foreach ($params as $key => $val)
  94. {
  95. if (isset($this->$key) OR in_array($key, $valid_null))
  96. {
  97. $this->$key = $val;
  98. }
  99. }
  100. }
  101. // --------------------------------------------------------------------
  102. /**
  103. * Clear class values
  104. *
  105. * @access public
  106. * @param array
  107. * @return void
  108. */
  109. public function reset()
  110. {
  111. foreach ($this->_reset_params as $key => $val)
  112. {
  113. $this->$key = $val;
  114. }
  115. }
  116. // --------------------------------------------------------------------
  117. /**
  118. * Normalizes the menu data
  119. *
  120. * @access protected
  121. * @param array menu item data
  122. * @return array
  123. */
  124. public function normalize_items($items)
  125. {
  126. $return = array();
  127. if (is_array($items))
  128. {
  129. $active = $this->active;
  130. $selected = array();
  131. $auto_nav_key = FALSE;
  132. if (is_string($this->use_nav_key) AND strtoupper($this->use_nav_key) == 'AUTO')
  133. {
  134. $this->use_nav_key = TRUE;
  135. $auto_nav_key = TRUE;
  136. }
  137. foreach($items as $key => $val)
  138. {
  139. $id = (is_array($val) AND !empty($val['id'])) ? $val['id'] : trim($key);
  140. $defaults[$key] = array('id' => $id, 'label' => '', 'location' => $key, 'attributes' => array(), 'active' => NULL, 'parent_id' => $this->root_value, 'hidden' => FALSE);
  141. if (!is_array($val))
  142. {
  143. $val = array('id' => $key, 'label' => $val);
  144. }
  145. $return[$id] = array_merge($defaults[$key], $val);
  146. // check to make sure parent_id does not equal id to prevent infinite loops
  147. if ($return[$id]['id'] == $return[$id]['parent_id'])
  148. {
  149. $return[$id]['parent_id'] = $this->root_value;
  150. }
  151. // Capture all that have selected states so we can loop through later
  152. if (isset($return[$id]['active']) OR isset($return[$id]['selected']))
  153. {
  154. $selected[$id] = (isset($return[$id]['active'])) ? $return[$id]['active'] : $return[$id]['selected'];
  155. }
  156. if ($auto_nav_key AND !is_numeric($id))
  157. {
  158. $this->use_nav_key = FALSE;
  159. }
  160. }
  161. if ($this->use_nav_key !== FALSE AND isset($return[$this->active]['nav_key']))
  162. {
  163. $active = $return[$this->active]['nav_key'];
  164. }
  165. // now loop through the selected states
  166. foreach($selected as $s_id => $active_regex)
  167. {
  168. $match = str_replace(':children', $s_id.'$|'.$s_id.'/.+', $active_regex);
  169. $match = str_replace(':any', '.+', str_replace(':num', '[0-9]+', $match));
  170. if (empty($active))
  171. {
  172. $this->active = 'home';
  173. }
  174. // Does the RegEx match?
  175. else if (preg_match('#^'.$match.'$#', $active))
  176. {
  177. $this->active = $s_id;
  178. }
  179. }
  180. }
  181. return $return;
  182. }
  183. // --------------------------------------------------------------------
  184. /**
  185. * Renders the menu output
  186. *
  187. * @access protected
  188. * @param array menu item data
  189. * @return string
  190. */
  191. protected function _render($root_items)
  192. {
  193. switch($this->render_type)
  194. {
  195. case 'collapsible':
  196. $output = $this->_render_collabsible($root_items);
  197. break;
  198. case 'breadcrumb':
  199. $output = $this->_render_breadcrumb($root_items);
  200. break;
  201. case 'page_title':
  202. $output = $this->_render_page_title($root_items);
  203. break;
  204. case 'delimited':
  205. $output = $this->_render_delimited($root_items);
  206. break;
  207. case 'array':
  208. $output = $this->_render_array($root_items);
  209. break;
  210. default:
  211. $output = $this->_render_basic($root_items);
  212. }
  213. return $output;
  214. }
  215. // --------------------------------------------------------------------
  216. /**
  217. * Renders the menu output
  218. *
  219. * @access public
  220. * @param array menu item data
  221. * @param string the active menu item
  222. * @param mixed int or string of the parent id to begin rendering the menu items
  223. * @param string basic, breadcrumb, page_title, collapsible
  224. * @return string
  225. */
  226. public function render($items, $active = NULL, $parent_id = NULL, $render_type = NULL)
  227. {
  228. if (empty($render_type))
  229. {
  230. $render_type = $this->render_type;
  231. }
  232. else
  233. {
  234. $this->render_type = $render_type;
  235. }
  236. if (!empty($active)) $this->active = $active;
  237. if (!isset($parent_id)) $parent_id = $this->root_value;
  238. $this->_items = $this->normalize_items($items);
  239. $root_items = $this->_get_menu_items($parent_id);
  240. $this->_active_items = $this->get_items_in_path($this->active);
  241. return $this->_render($root_items);
  242. }
  243. // --------------------------------------------------------------------
  244. /**
  245. * Renders collapsible menu menu output
  246. *
  247. * @access public
  248. * @param array menu item data
  249. * @param string the active menu item
  250. * @param mixed int or string of the parent id to begin rendering the menu items
  251. * @return string
  252. */
  253. public function render_collapsible($items, $active = NULL, $parent_id = NULL)
  254. {
  255. return $this->render($items, $active, $parent_id, 'collapsible');
  256. }
  257. // --------------------------------------------------------------------
  258. /**
  259. * Renders breadcrumb menu output
  260. *
  261. * @access public
  262. * @param array menu item data
  263. * @param string the active menu item
  264. * @param mixed int or string of the parent id to begin rendering the menu items
  265. * @return string
  266. */
  267. public function render_breadcrumb($items, $active = NULL, $parent_id = NULL)
  268. {
  269. return $this->render($items, $active, $parent_id, 'breadcrumb');
  270. }
  271. // --------------------------------------------------------------------
  272. /**
  273. * Renders page_title menu output
  274. *
  275. * @access public
  276. * @param array menu item data
  277. * @param string the active menu item
  278. * @param mixed int or string of the parent id to begin rendering the menu items
  279. * @return string
  280. */
  281. public function render_page_title($items, $active = NULL, $parent_id = NULL)
  282. {
  283. return $this->render($items, $active, $parent_id, 'page_title');
  284. }
  285. // --------------------------------------------------------------------
  286. /**
  287. * Renders page_title menu output
  288. *
  289. * @access public
  290. * @param array menu item data
  291. * @param string the active menu item
  292. * @param mixed int or string of the parent id to begin rendering the menu items
  293. * @return string
  294. */
  295. public function render_delimited($items, $active = NULL, $parent_id = NULL)
  296. {
  297. return $this->render($items, $active, $parent_id, 'delimited');
  298. }
  299. // --------------------------------------------------------------------
  300. /**
  301. * Renders page_title menu output
  302. *
  303. * @access public
  304. * @param array menu item data
  305. * @param string the active menu item
  306. * @param mixed int or string of the parent id to begin rendering the menu items
  307. * @return string
  308. */
  309. public function render_array($items, $active = NULL, $parent_id = NULL)
  310. {
  311. return $this->render($items, $active, $parent_id, 'array');
  312. }
  313. // --------------------------------------------------------------------
  314. /**
  315. * Renders a basic menu
  316. *
  317. * @access protected
  318. * @param array nested array of menu elements
  319. * @param int depth of menu to render
  320. * @return string
  321. */
  322. protected function _render_basic($menu, $level = -1)
  323. {
  324. $str = '';
  325. if (!empty($menu) AND (isset($this->depth) AND $level < $this->depth) OR !isset($this->depth))
  326. {
  327. // filter out hidden ones first. Need to do in seperate loop in case there is a hidden one at the end
  328. $menu = $this->_filter_hidden($menu);
  329. if (!empty($menu))
  330. {
  331. if (!empty($this->container_tag)) $str .= "\n".str_repeat("\t", ($level + 1))."<".$this->container_tag.$this->_get_attrs($this->container_tag_attrs);
  332. if (!empty($this->container_tag_id) AND $level == -1) $str .= " id=\"".$this->container_tag_id."\"";
  333. if (!empty($this->container_tag_class) AND $level == -1) $str .= " class=\"".$this->container_tag_class."\"";
  334. if (!empty($this->container_tag)) $str .= ">\n";
  335. $active_index = (count($this->_active_items) -1) - $level;
  336. $level = $level + 1;
  337. $i = 0;
  338. foreach($menu as $key => $val)
  339. {
  340. $str .= $this->_create_open_li($val, $level, $i, ($i == (count($menu) -1)));
  341. $subitems = $this->_get_menu_items($val['id']);
  342. if (!empty($subitems))
  343. {
  344. $str .= $this->_render_basic($subitems, $level);
  345. }
  346. if (!empty($this->item_tag))
  347. {
  348. $str .= "</".$this->item_tag.">\n";
  349. }
  350. $i++;
  351. }
  352. if (!empty($this->container_tag)) $str .= str_repeat("\t", $level)."</".$this->container_tag.">\n".str_repeat("\t", $level);
  353. }
  354. }
  355. return $str;
  356. }
  357. // --------------------------------------------------------------------
  358. /**
  359. * Renders the menu output in a collapsible format
  360. *
  361. * @access protected
  362. * @param array menu item data
  363. * @param int level to render menu data at
  364. * @return string
  365. */
  366. protected function _render_collabsible($menu, $level = 0)
  367. {
  368. // filter out hidden ones first. Need to do in seperate loop in case there is a hidden on e at the end
  369. $menu = $this->_filter_hidden($menu);
  370. $str = '';
  371. if (!empty($menu))
  372. {
  373. if (!empty($this->container_tag)) $str .= "\n".str_repeat("\t", $level)."<".$this->container_tag.$this->_get_attrs($this->container_tag_attrs);
  374. if (!empty($this->container_tag_id) AND $level == 0) $str .= " id=\"".$this->container_tag_id."\"";
  375. if (!empty($this->container_tag_class) AND $level == 0) $str .= " class=\"".$this->container_tag_class."\"";
  376. if (!empty($this->container_tag)) $str .= ">\n";
  377. $i = 0;
  378. // find start index
  379. $active_index = 0;
  380. if (!empty($this->_active_items))
  381. {
  382. foreach($this->_active_items as $index => $item)
  383. {
  384. if (!empty($menu[$item]))
  385. {
  386. $active_index = $index;
  387. break;
  388. }
  389. }
  390. }
  391. // loop through base menu items and start drill down
  392. foreach($menu as $key => $val)
  393. {
  394. $label = $this->_get_label($val['label']);
  395. if ($active_index > -1 AND $key == $this->_active_items[$active_index])
  396. {
  397. $level = $level + 1;
  398. $subitems = $this->_get_menu_items($key);
  399. $str .= str_repeat("\t", $level);
  400. if (!empty($this->item_tag))
  401. {
  402. $str .= "<".$this->item_tag;
  403. $str .= $this->_get_li_classes($key, $val['id'], $level, ($i == (count($menu) -1)));
  404. // set id
  405. if (!empty($this->item_id_prefix))
  406. {
  407. $str .= ' id="'.$this->_get_id($val).'"';
  408. }
  409. $str .= '>';
  410. }
  411. $str .= anchor($val['location'], $label, $val['attributes']);
  412. if (!empty($subitems))
  413. {
  414. $str .= $this->_render_collabsible($subitems, $level);
  415. }
  416. if (!empty($this->item_tag))
  417. {
  418. $str .= "</".$this->item_tag.">\n";
  419. }
  420. }
  421. else
  422. {
  423. $str .= $this->_create_open_li($val, ($level -1), $i, ($i == (count($menu) -1)));
  424. if (!empty($this->item_tag))
  425. {
  426. $str .= "</".$this->item_tag.">\n";
  427. }
  428. }
  429. $i++;
  430. }
  431. if (!empty($this->container_tag))
  432. {
  433. if ($level > 1) $str .= str_repeat("\t", ($level -1));
  434. $str .= "</".$this->container_tag.">\n";
  435. if ($level > 1) $str .= str_repeat("\t", ($level -1));
  436. }
  437. }
  438. return $str;
  439. }
  440. // --------------------------------------------------------------------
  441. /**
  442. * Renders the menu output in a breadcrumb format
  443. *
  444. * @access protected
  445. * @param array menu item data
  446. * @return string
  447. */
  448. protected function _render_breadcrumb($menu)
  449. {
  450. // filter out hidden ones first. Need to do in seperate loop in case there is a hidden on e at the end
  451. $menu = $this->_filter_hidden($menu);
  452. if (empty($this->delimiter))
  453. {
  454. $this->delimiter = ' &gt; ';
  455. }
  456. $str = '';
  457. $num = count($this->_active_items) -1;
  458. if (!empty($this->home_link))
  459. {
  460. if (is_array($this->home_link))
  461. {
  462. $home_link = each($this->home_link);
  463. $home_anchor = anchor($home_link['key'], $home_link['value']);
  464. }
  465. else
  466. {
  467. $home_anchor = anchor('', $this->home_link);
  468. }
  469. if (!empty($this->item_tag))
  470. {
  471. $str .= "\t<".$this->item_tag.">";
  472. }
  473. $str .= $home_anchor;
  474. if ($num >= 0) $str .= ' <span class="'.$this->arrow_class.'">'.$this->delimiter.'</span> ';
  475. if (!empty($this->item_tag))
  476. {
  477. $str .= "</".$this->item_tag.">\n";
  478. }
  479. }
  480. for ($i = $num; $i >= 0; $i--)
  481. {
  482. $val = $this->_active_items[$i];
  483. $label = $this->_get_label($this->_items[$val]['label']);
  484. if (!empty($this->item_tag))
  485. {
  486. $str .= "\t<".$this->item_tag.">";
  487. }
  488. if ($i != 0)
  489. {
  490. $str .= anchor($this->_items[$val]['location'], $label);
  491. $str .= ' <span class="'.$this->arrow_class.'">'.$this->delimiter.'</span> ';
  492. }
  493. else if ($this->display_current)
  494. {
  495. $str .= $label;
  496. }
  497. if (!empty($this->item_tag))
  498. {
  499. $str .= "</".$this->item_tag.">\n";
  500. }
  501. }
  502. $return = '';
  503. if (!empty($str))
  504. {
  505. if (!empty($this->container_tag)) $return .= "\n<".$this->container_tag.$this->_get_attrs($this->container_tag_attrs);
  506. if (!empty($this->container_tag_id)) $return .= " id=\"".$this->container_tag_id."\"";
  507. if (!empty($this->container_tag_class)) $return .= " class=\"".$this->container_tag_class."\"";
  508. if (!empty($this->container_tag)) $return .= ">\n";
  509. $return .= $str;
  510. if (!empty($this->container_tag)) $return .= "</".$this->container_tag.">\n";
  511. }
  512. return $return;
  513. }
  514. // --------------------------------------------------------------------
  515. /**
  516. * Renders the menu output in a page title format
  517. *
  518. * @access protected
  519. * @param array menu item data
  520. * @return string
  521. */
  522. protected function _render_page_title($menu)
  523. {
  524. // filter out hidden ones first. Need to do in seperate loop in case there is a hidden on e at the end
  525. $menu = $this->_filter_hidden($menu);
  526. if (empty($this->delimiter))
  527. {
  528. $this->delimiter = ' &gt; ';
  529. }
  530. $str = '';
  531. $num = count($this->_active_items) -1;
  532. $home_link = '';
  533. if (!empty($this->home_link)){
  534. if (is_array($this->home_link))
  535. {
  536. $home_link = reset($this->home_link);
  537. }
  538. else
  539. {
  540. $home_link = $this->home_link;
  541. }
  542. }
  543. if ($this->order == 'desc')
  544. {
  545. for ($i = 0; $i <= $num; $i++)
  546. {
  547. $val = $this->_active_items[$i];
  548. $label = $this->_get_label(strip_tags($this->_items[$val]['label']));
  549. if ($i != 0)
  550. {
  551. $str .= $this->delimiter;
  552. }
  553. $str .= $label;
  554. }
  555. if (($num >= 0 AND !empty($home_link)) OR (empty($home_link) AND $num > 0)) $str .= $this->delimiter;
  556. $str .= strip_tags($home_link);
  557. }
  558. else
  559. {
  560. $str .= $home_link;
  561. if (($num >= 0 AND !empty($home_link)) OR (empty($home_link) AND $num > 0)) $str .= $this->delimiter;
  562. for ($i = $num; $i >= 0; $i--)
  563. {
  564. $val = $this->_active_items[$i];
  565. $label = $this->_get_label(strip_tags($this->_items[$val]['label']));
  566. $str .= $label;
  567. if ($i != 0)
  568. {
  569. $str .= $this->delimiter;
  570. }
  571. }
  572. }
  573. return $str;
  574. }
  575. // --------------------------------------------------------------------
  576. /**
  577. * Renders the menu output in a delimited format
  578. *
  579. * @access protected
  580. * @param array menu item data
  581. * @return string
  582. */
  583. protected function _render_delimited($menu)
  584. {
  585. // filter out hidden ones first. Need to do in seperate loop in case there is a hidden on e at the end
  586. $menu = $this->_filter_hidden($menu);
  587. if ($this->container_tag !== FALSE)
  588. {
  589. $this->container_tag = 'div';
  590. }
  591. if (empty($this->delimiter))
  592. {
  593. $this->delimiter = ' &nbsp;|&nbsp; ';
  594. }
  595. $links = array();
  596. foreach($menu as $val)
  597. {
  598. if (!empty($this->item_id_prefix))
  599. {
  600. if (is_array($val['attributes']))
  601. {
  602. if (!in_array('id', $val['attributes'])) $val['attributes']['id'] = $this->_get_id($val);
  603. }
  604. else if (strpos($val['id'], 'id=') === FALSE)
  605. {
  606. $val['attributes'] .= ' id="'.$this->_get_id($val).'"';
  607. }
  608. }
  609. $links[] = $this->_create_link($val);
  610. }
  611. $str = implode($this->delimiter, $links);
  612. $return = '';
  613. if (!empty($str))
  614. {
  615. if (!empty($this->container_tag)) $return .= "\n<".$this->container_tag.$this->_get_attrs($this->container_tag_attrs);
  616. if (!empty($this->container_tag_id)) $return .= " id=\"".$this->container_tag_id."\"";
  617. if (!empty($this->container_tag_class)) $return .= " class=\"".$this->container_tag_class."\"";
  618. if (!empty($this->container_tag)) $return .= ">\n";
  619. $return .= $str;
  620. if (!empty($this->container_tag)) $return .= "</".$this->container_tag.">\n";
  621. }
  622. return $return;
  623. }
  624. // --------------------------------------------------------------------
  625. /**
  626. * Outputs a nested array
  627. *
  628. * @access protected
  629. * @param array menu item data
  630. * @return string
  631. */
  632. protected function _render_array($menu, $level = 0)
  633. {
  634. $return = array();
  635. if (!empty($menu) AND (isset($this->depth) AND $level < $this->depth) OR !isset($this->depth))
  636. {
  637. foreach($menu as $key => $val)
  638. {
  639. $subitems = $this->_get_menu_items($val['id']);
  640. $new_key = (isset($val['nav_key'])) ? $val['nav_key'] : $val['location'];
  641. $return[$new_key] = $val;
  642. if (!empty($subitems))
  643. {
  644. $level = $level + 1;
  645. $return[$new_key]['children'] = $this->_render_array($subitems, $level);
  646. }
  647. }
  648. }
  649. return $return;
  650. }
  651. // --------------------------------------------------------------------
  652. /**
  653. * Get attributes of of the container tag elment
  654. *
  655. * @access protected
  656. * @param mixed takes a string or an array
  657. * @return string
  658. */
  659. protected function _get_attrs($attrs)
  660. {
  661. $str = '';
  662. if (is_array($attrs))
  663. {
  664. foreach($this->container_tag_attrs as $key => $val)
  665. {
  666. $str .= ' '.$key.'="'.$val.'"';
  667. }
  668. }
  669. else
  670. {
  671. if (!empty($attrs)) $str .= " ".$attrs;
  672. }
  673. return $str;
  674. }
  675. // --------------------------------------------------------------------
  676. /**
  677. * Create the ID for a item element
  678. *
  679. * @access protected
  680. * @param mixed takes a string or an array
  681. * @return string
  682. */
  683. protected function _get_id($val)
  684. {
  685. if (empty($this->item_id_prefix)) return;
  686. $id = strtolower(str_replace('/', '_', $val[$this->item_id_key]));
  687. if (empty($id))
  688. {
  689. $id = 'home';
  690. }
  691. return $this->item_id_prefix.$id;
  692. }
  693. // --------------------------------------------------------------------
  694. /**
  695. * Creates an open list item element
  696. *
  697. * @access protected
  698. * @param array menu item data
  699. * @param int current level
  700. * @param int current item index
  701. * @param boolean whether the item is the last in the list
  702. * @return string
  703. */
  704. protected function _create_open_li($val, $level, $i, $is_last = FALSE)
  705. {
  706. $str = '';
  707. $str .= str_repeat("\t", ($level + 1));
  708. if (!empty($this->item_tag))
  709. {
  710. $str .= "<".$this->item_tag;
  711. // set id
  712. if (!empty($this->item_id_prefix))
  713. {
  714. $str .= ' id="'.$this->_get_id($val).'"';
  715. }
  716. // set styles
  717. $str .= $this->_get_li_classes($val, $level, $i, $is_last);
  718. $str .= '>';
  719. }
  720. $str .= $this->_create_link($val);
  721. return $str;
  722. }
  723. // --------------------------------------------------------------------
  724. /**
  725. * Creates an open list item element
  726. *
  727. * @access protected
  728. * @param array menu item data
  729. * @param int current level
  730. * @param int current item index
  731. * @param boolean whether the item is the last in the list
  732. * @return string
  733. */
  734. protected function _create_link($val)
  735. {
  736. $str = '';
  737. $label = $this->_get_label($val['label']);
  738. $attrs = '';
  739. if (!empty($val['location']))
  740. {
  741. if (!empty($val['attributes']))
  742. {
  743. if (is_array($val['attributes']))
  744. {
  745. foreach($val['attributes'] as $key2 => $val2)
  746. {
  747. $attrs .= ' '.$key2.'="'.$val2.'"';
  748. }
  749. } else {
  750. $attrs .= $val['attributes'];
  751. }
  752. }
  753. if ($this->use_titles AND (empty($attrs) OR strpos($attrs, 'title=') === FALSE))
  754. {
  755. $attrs .= ' title="'.strip_tags($val['label']).'"';
  756. }
  757. $location = (preg_match('/^#/', $val['location'])) ? $val['location'] : site_url($val['location']);
  758. $str .= '<a href="'.$location.'"'.$attrs.'>'.$label.'</a>';
  759. }
  760. else
  761. {
  762. $str .= $label;
  763. }
  764. return $str;
  765. }
  766. // --------------------------------------------------------------------
  767. /**
  768. * Gets the css classes for the list item styling
  769. *
  770. * @access protected
  771. * @param array menu item data
  772. * @param int current level
  773. * @param int current item index
  774. * @param boolean whether the item is the last in the list
  775. * @return string
  776. */
  777. protected function _get_li_classes($val, $level, $i, $is_last = FALSE)
  778. {
  779. $str = '';
  780. $css_classes = array();
  781. $active = (is_array($val)) ? $val['id'] : $val;
  782. if (!empty($this->first_class) AND $i == 0) $css_classes[] = $this->first_class;
  783. if (!empty($this->last_class) AND $is_last) $css_classes[] = $this->last_class;
  784. if ($this->active == $active OR ($this->cascade_selected AND
  785. is_array($this->_active_items) AND
  786. in_array($active, $this->_active_items)))
  787. {
  788. $css_classes[] = $this->active_class;
  789. }
  790. if (!empty($this->styles[$level][$i]))
  791. {
  792. if (is_array($this->styles[$level]))
  793. {
  794. $css_classes[] = $this->styles[$level][$i];
  795. }
  796. else if (is_string($this->styles[$level]))
  797. {
  798. $css_classes[] = $this->styles[$level];
  799. }
  800. }
  801. if (!empty($css_classes))
  802. {
  803. $str .= ' class="';
  804. $str .= implode(' ', $css_classes);
  805. $str .= '"';
  806. }
  807. return $str;
  808. }
  809. // --------------------------------------------------------------------
  810. /**
  811. * Generates the label of the menu item
  812. *
  813. * @access protected
  814. * @param string active element
  815. * @param boolean first time iterating through?
  816. * @return string
  817. */
  818. protected function _get_label($label)
  819. {
  820. if (!empty($this->pre_render_func))
  821. {
  822. $label = call_user_func($this->pre_render_func, $label);
  823. }
  824. return $label;
  825. }
  826. // --------------------------------------------------------------------
  827. /**
  828. * Gets the items in the active menu path
  829. *
  830. * @access public
  831. * @param string active element
  832. * @param boolean first time iterating through?
  833. * @return string
  834. */
  835. public function get_items_in_path($active, $first_time = TRUE){
  836. static $active_items = array();
  837. // reset it if is called more then once
  838. if ($first_time)
  839. {
  840. $active_items = array();
  841. }
  842. if (isset($this->_items[$active]))
  843. {
  844. $active_parent = $this->_items[$active]['parent_id'];
  845. // to normalize so we can do a strict comparison
  846. if (ctype_digit($active_parent))
  847. {
  848. $active_parent = (int) $active_parent;
  849. }
  850. }
  851. else
  852. {
  853. return;
  854. }
  855. if (!in_array($active, $active_items)) $active_items[] = $active;
  856. foreach($this->_items as $key => $val)
  857. {
  858. // to normalize so we can do a strict comparison
  859. if (ctype_digit($key))
  860. {
  861. $key = (int) $key;
  862. }
  863. if ($key === $active_parent AND !empty($key))
  864. {
  865. //echo $key .' - '.$active_parent.'<br>';
  866. if (isset($this->_items[$key]))
  867. {
  868. $active_items[] = $key;
  869. }
  870. $this->get_items_in_path($key, FALSE);
  871. }
  872. }
  873. return $active_items;
  874. }
  875. // --------------------------------------------------------------------
  876. /**
  877. * Gets the menu items based on the parent
  878. *
  879. * @access protected
  880. * @param mixed parent id
  881. * @param array menu items
  882. * @return array
  883. */
  884. protected function _get_menu_items($parent, $items = NULL)
  885. {
  886. if (empty($items)) $items = $this->_items;
  887. $str = '';
  888. $subitems = array();
  889. foreach($items as $key => $val)
  890. {
  891. // force numbers to be integers if numeric so we can do a strict comparison
  892. if (is_numeric($val['parent_id'])) $val['parent_id'] = (int) $val['parent_id'];
  893. if (is_numeric($parent)) $parent = (int) $parent;
  894. if ($parent === $val['parent_id'])
  895. {
  896. $subitems[$key] = $val;
  897. }
  898. }
  899. return $subitems;
  900. }
  901. // --------------------------------------------------------------------
  902. /**
  903. * Filter out hidden menu items
  904. *
  905. * @access protected
  906. * @param array menu items
  907. * @return array
  908. */
  909. protected function _filter_hidden($menu)
  910. {
  911. $filtered_menu = array();
  912. if (!$this->include_hidden)
  913. {
  914. foreach($menu as $key => $val)
  915. {
  916. if (!$val['hidden'] OR strtolower($val['hidden']) == 'no')
  917. {
  918. $filtered_menu[$key] = $val;
  919. }
  920. }
  921. }
  922. else
  923. {
  924. $filtered_menu = $menu;
  925. }
  926. return $filtered_menu;
  927. }
  928. }
  929. /* End of file Menu.php */
  930. /* Location: ./application/libraries/Menu.php */