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