/administrator/modules/mod_menu/menu.php

https://bitbucket.org/eternaware/joomus · PHP · 395 lines · 194 code · 47 blank · 154 comment · 36 complexity · 203ca6e9d895872932afabddfb0b2b42 MD5 · raw file

  1. <?php
  2. /**
  3. * @package Joomla.Administrator
  4. * @subpackage mod_menu
  5. *
  6. * @copyright Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved.
  7. * @license GNU General Public License version 2 or later; see LICENSE.txt
  8. */
  9. defined('_JEXEC') or die;
  10. /**
  11. * Tree based class to render the admin menu
  12. *
  13. * @package Joomla.Administrator
  14. * @subpackage mod_menu
  15. * @since 1.5
  16. */
  17. class JAdminCssMenu extends JObject
  18. {
  19. /**
  20. * CSS string to add to document head
  21. * @var string
  22. */
  23. protected $_css = null;
  24. /**
  25. * Root node
  26. *
  27. * @var object
  28. */
  29. protected $_root = null;
  30. /**
  31. * Current working node
  32. *
  33. * @var object
  34. */
  35. protected $_current = null;
  36. /**
  37. * Constructor
  38. */
  39. public function __construct()
  40. {
  41. $this->_root = new JMenuNode('ROOT');
  42. $this->_current = & $this->_root;
  43. }
  44. /**
  45. * Method to add a child
  46. *
  47. * @param JMenuNode &$node The node to process
  48. * @param boolean $setCurrent True to set as current working node
  49. *
  50. * @return void
  51. */
  52. public function addChild(JMenuNode &$node, $setCurrent = false)
  53. {
  54. $this->_current->addChild($node);
  55. if ($setCurrent)
  56. {
  57. $this->_current = &$node;
  58. }
  59. }
  60. /**
  61. * Method to get the parent
  62. *
  63. * @return void
  64. */
  65. public function getParent()
  66. {
  67. $this->_current = &$this->_current->getParent();
  68. }
  69. /**
  70. * Method to get the parent
  71. *
  72. * @return void
  73. */
  74. public function reset()
  75. {
  76. $this->_current = &$this->_root;
  77. }
  78. public function addSeparator()
  79. {
  80. $this->addChild(new JMenuNode(null, null, 'separator', false));
  81. }
  82. public function renderMenu($id = 'menu', $class = '')
  83. {
  84. $depth = 1;
  85. if (!empty($id)) {
  86. $id = 'id="' . $id . '"';
  87. }
  88. if (!empty($class)) {
  89. $class = 'class="' . $class . '"';
  90. }
  91. /*
  92. * Recurse through children if they exist
  93. */
  94. while ($this->_current->hasChildren())
  95. {
  96. echo "<ul ".$id." ".$class.">\n";
  97. foreach ($this->_current->getChildren() as $child)
  98. {
  99. $this->_current = & $child;
  100. $this->renderLevel($depth++);
  101. }
  102. echo "</ul>\n";
  103. }
  104. if ($this->_css) {
  105. // Add style to document head
  106. $doc = JFactory::getDocument();
  107. $doc->addStyleDeclaration($this->_css);
  108. }
  109. }
  110. public function renderLevel($depth)
  111. {
  112. /*
  113. * Build the CSS class suffix
  114. */
  115. $class = '';
  116. if ($this->_current->hasChildren()) {
  117. $class = ' class="dropdown"';
  118. }
  119. if ($this->_current->class == 'separator') {
  120. $class = ' class="divider"';
  121. }
  122. if ($this->_current->class == 'disabled') {
  123. $class = ' class="disabled"';
  124. }
  125. /*
  126. * Print the item
  127. */
  128. echo "<li".$class.">";
  129. /*
  130. * Print a link if it exists
  131. */
  132. $linkClass = '';
  133. $dataToggle = '';
  134. $dropdownCaret = '';
  135. if ($this->_current->hasChildren()) {
  136. $linkClass = ' class="dropdown-toggle"';
  137. $dataToggle = ' data-toggle="dropdown"';
  138. $dropdownCaret = ' <span class="caret"></span>';
  139. }
  140. if ($this->_current->link != null && $this->_current->target != null) {
  141. echo "<a".$linkClass." ".$dataToggle." href=\"".$this->_current->link."\" target=\"".$this->_current->target."\" >".$this->_current->title.$dropdownCaret."</a>";
  142. } elseif ($this->_current->link != null && $this->_current->target == null) {
  143. echo "<a".$linkClass." ".$dataToggle." href=\"".$this->_current->link."\">".$this->_current->title.$dropdownCaret."</a>";
  144. } elseif ($this->_current->title != null) {
  145. echo "<a".$linkClass." ".$dataToggle.">".$this->_current->title.$dropdownCaret."</a>";
  146. } else {
  147. echo "<span></span>";
  148. }
  149. /*
  150. * Recurse through children if they exist
  151. */
  152. while ($this->_current->hasChildren())
  153. {
  154. if ($this->_current->class) {
  155. $id = '';
  156. if (!empty($this->_current->id)) {
  157. $id = ' id="menu-'.strtolower($this->_current->id).'"';
  158. }
  159. echo '<ul'.$id.' class="dropdown-menu menu-component">'."\n";
  160. } else {
  161. echo '<ul class="dropdown-menu">'."\n";
  162. }
  163. foreach ($this->_current->getChildren() as $child)
  164. {
  165. $this->_current = & $child;
  166. $this->renderLevel($depth++);
  167. }
  168. echo "</ul>\n";
  169. }
  170. echo "</li>\n";
  171. }
  172. /**
  173. * Method to get the CSS class name for an icon identifier or create one if
  174. * a custom image path is passed as the identifier
  175. *
  176. * @access public
  177. * @param string $identifier Icon identification string
  178. * @return string CSS class name
  179. * @since 1.5
  180. */
  181. public function getIconClass($identifier)
  182. {
  183. static $classes;
  184. // Initialise the known classes array if it does not exist
  185. if (!is_array($classes)) {
  186. $classes = array();
  187. }
  188. /*
  189. * If we don't already know about the class... build it and mark it
  190. * known so we don't have to build it again
  191. */
  192. if (!isset($classes[$identifier])) {
  193. if (substr($identifier, 0, 6) == 'class:') {
  194. // We were passed a class name
  195. $class = substr($identifier, 6);
  196. $classes[$identifier] = "icon-16-$class";
  197. } else {
  198. if ($identifier == null) {
  199. return null;
  200. }
  201. // Build the CSS class for the icon
  202. $class = preg_replace('#\.[^.]*$#', '', basename($identifier));
  203. $class = preg_replace('#\.\.[^A-Za-z0-9\.\_\- ]#', '', $class);
  204. $this->_css .= "\n.icon-16-$class {\n" .
  205. "\tbackground: url($identifier) no-repeat;\n" .
  206. "}\n";
  207. $classes[$identifier] = "icon-16-$class";
  208. }
  209. }
  210. return $classes[$identifier];
  211. }
  212. }
  213. /**
  214. * A Node for JAdminCssMenu
  215. *
  216. * @package Joomla.Administrator
  217. * @subpackage mod_menu
  218. * @since 1.5
  219. * @see JAdminCssMenu
  220. */
  221. class JMenuNode extends JObject
  222. {
  223. /**
  224. * Node Title
  225. */
  226. public $title = null;
  227. /**
  228. * Node Id
  229. */
  230. public $id = null;
  231. /**
  232. * Node Link
  233. */
  234. public $link = null;
  235. /**
  236. * Link Target
  237. */
  238. public $target = null;
  239. /**
  240. * CSS Class for node
  241. */
  242. public $class = null;
  243. /**
  244. * Active Node?
  245. */
  246. public $active = false;
  247. /**
  248. * Parent node
  249. * @var object
  250. */
  251. protected $_parent = null;
  252. /**
  253. * Array of Children
  254. *
  255. * @var array
  256. */
  257. protected $_children = array();
  258. public function __construct($title, $link = null, $class = null, $active = false, $target = null, $titleicon = null)
  259. {
  260. $this->title = $titleicon ? $title.$titleicon : $title;
  261. $this->link = JFilterOutput::ampReplace($link);
  262. $this->class = $class;
  263. $this->active = $active;
  264. $this->id = null;
  265. if (!empty($link) && $link !== '#') {
  266. $uri = new JURI($link);
  267. $params = $uri->getQuery(true);
  268. $parts = array();
  269. foreach ($params as $name => $value)
  270. {
  271. $parts[] = str_replace(array('.', '_'), '-', $value);
  272. }
  273. $this->id = implode('-', $parts);
  274. }
  275. $this->target = $target;
  276. }
  277. /**
  278. * Add child to this node
  279. *
  280. * If the child already has a parent, the link is unset
  281. *
  282. * @param JMenuNode &$child The child to be added
  283. *
  284. * @return void
  285. */
  286. public function addChild(JMenuNode &$child)
  287. {
  288. $child->setParent($this);
  289. }
  290. /**
  291. * Set the parent of a this node
  292. *
  293. * If the node already has a parent, the link is unset
  294. *
  295. * @param JMenuNode &$parent The JMenuNode for parent to be set or null
  296. *
  297. * @return void
  298. */
  299. public function setParent(JMenuNode &$parent = null)
  300. {
  301. $hash = spl_object_hash($this);
  302. if (!is_null($this->_parent))
  303. {
  304. unset($this->_parent->children[$hash]);
  305. }
  306. if (!is_null($parent))
  307. {
  308. $parent->_children[$hash] = & $this;
  309. }
  310. $this->_parent = & $parent;
  311. }
  312. /**
  313. * Get the children of this node
  314. *
  315. * @return array The children
  316. */
  317. public function &getChildren()
  318. {
  319. return $this->_children;
  320. }
  321. /**
  322. * Get the parent of this node
  323. *
  324. * @return mixed JMenuNode object with the parent or null for no parent
  325. */
  326. public function &getParent()
  327. {
  328. return $this->_parent;
  329. }
  330. /**
  331. * Test if this node has children
  332. *
  333. * @return boolean True if there are children
  334. */
  335. public function hasChildren()
  336. {
  337. return (bool) count($this->_children);
  338. }
  339. /**
  340. * Test if this node has a parent
  341. *
  342. * @return boolean True if there is a parent
  343. */
  344. public function hasParent()
  345. {
  346. return $this->getParent() != null;
  347. }
  348. }