7 private $triggers = array();
10 $this->items = array();
11 $this->urlMap = array();
30 if ( !isset($parent) ){
36 $parent = $p[
'menuItem'];
38 $parent = $p[
'menuItem']->getParent();
44 $parent->addChild($item, $reorganize);
59 while ( isset($this->items[$this->
nextID]) ) $this->nextID++;
65 $menuID = $item->
getId();
66 if ( !isset($menuID) ) $item->
setId($this->
nextID());
67 $this->items[$item->
getId()] = $item;
77 $this->urlMap[$url] = $mapper;
81 if ( !isset($this->items[$id]) )
throw new Exception(
"Attempt to access item that doesn't exists: ".$id);
82 return $this->items[$id];
86 $parts = explode(
'/', $url);
89 while ( count($parts) > 0 ){
90 $curr = implode(
'/', $parts);
92 if ( isset($this->urlMap[$curr]) ){
94 $map = $this->urlMap[$curr];
95 $menuID = $map->getMenuID();
96 if ( isset($this->items[$menuID]) ){
98 if ( !isset($type) ) $type = $map->getType();
105 'menuItem'=>$this->items[$menuID],
109 else throw new Exception(
"Menu with id $menuID could not be found.");
128 if ( !isset($item) )
return array();
130 $path = array($item, $type);
131 while (($curr = $item->getParent() ) !== null ){
132 array_unshift(
$path, $curr);
148 ) ? $item[
'menuItem']->getLabel() : ucwords(str_replace(array(
'-',
'_',
'+'), array(
' ',
' ',
' '), basename($url)));
152 $this->
getRoot()->buildMenu(
$path, 0, $pageTitle, $menu);
160 'nextID' => $this->
nextID,
162 'root' => $this->
getRoot()->getId()
165 foreach ($this->items as $key=>$val){
166 $out[
'items'][$key] = $val->toJSON(
false);
169 foreach ($this->urlMap as $key=>$val ){
170 $out[
'urlMap'][$key] = $val->toJSON(
false);
172 return json_encode(
$out);
176 $this->triggers[$name][] = $callback;
180 while ( isset($this->triggers[$name]) and count($this->triggers[$name])>0 ){
181 $callback = array_shift($this->triggers[$name]);
182 if ( is_array($callback) ){
183 $obj =& $callback[0];
184 $method = $callback[1];
194 $in = json_decode($in);
195 $this->items = array();
196 $this->urlMap = array();
197 $this->
nextID = $in->nextID;
199 foreach ( $in->items as $key=>$val ){
204 foreach ($in->urlMap as $key=>$val ){
216 public function toHtml($url, $id=
'main_nav'){
222 if ( $i[
'level'] > $level ){
223 while ( $level < $i[
'level'] ){
224 if ( $level>0 )
$out[] =
'<li>';
225 $out[] =
'<ul '.($level==0?
'id="'.htmlspecialchars($id).
'"':
'').
'>';
232 else if ( $i[
'level'] < $level ){
233 while ( $level > $i[
'level'] ){
238 $class = array(
'menu-level-'.$i[
'level']);
239 if ( $i[
'selected'] ) $class[] =
'menu-selected';
240 if ( $i[
'breadCrumb'] ) $class[] =
'menu-breadCrumb current';
241 if ( $i[
'parent'] ) $class[] =
'menu-parent';
242 $out[] =
'<li class="'.implode(
' ',$class).
'"><a href="'.htmlspecialchars($i[
'url']).
'">'.htmlspecialchars($i[
'label']).
'</a></li>';
245 while ( $level > 0 ){
248 if ( $level > 0 )
$out[] =
'</li>';
251 return implode(
"\n",
$out);
267 if ( is_int($menu) ) $this->menuID = $menu;
268 else if ( is_a($menu,
'Dataface_Menu_Item') ){
269 $this->menuID = $menu->getId();
271 throw Exception(
"2nd parameter of URLMap constructor takes either an integer ID or a Dataface_Menu_Item class but received a ".get_class($menu).
" object instead.");
282 'menuID'=>$this->menuID,
285 if ( $serialize )
$out = json_encode(
$out);
289 public static function fromJSON($in, $menu, $serialized=
true){
290 if ( $serialized ) $in = json_decode($data);
298 'menuID'=>$this->menuID,
305 return $this->menuID;
329 private $sorted =
false;
336 private $showChildrenSetting;
338 private $_loadChildIDs = array();
339 private $_loadParent = null;
342 $this->children = array();
343 $this->label = $label;
344 $this->parent = $parent;
347 if ( !isset($this->menu) ) $this->menu = $this->parent->menu;
348 $this->showChildrenSetting = 1;
352 unset($this->parent);
353 unset($this->children);
360 'label'=>$this->label,
361 'menuID'=>$this->menuID,
364 'order'=>$this->order,
365 'showChildrenSetting'=>$this->showChildrenSetting
367 if ( isset($this->parent) )
$out[
'parent'] = $this->parent->getId();
369 $out[
'children'][$key] = $val->getId();
371 if ( $serialize )
$out = json_encode(
$out);
375 public static function fromJSON($in, $menu, $serialized=
true){
376 if ( $serialized ) $in = json_decode($in);
379 $item->menuID = $in->menuID;
380 $item->setOrder($in->order);
381 $item->setShowChildrenSetting($in->showChildrenSetting);
382 $item->setLoadData(array(
383 'childIDs' => $in->children,
384 'parent'=>$in->parent
386 $menu->registerTrigger(
'afterLoadJSON', array(&$item,
'afterFromJSON'));
392 if ( isset($params[
'childIDs']) ) $this->_loadChildIDs = $params[
'childIDs'];
393 if ( isset($params[
'parent']) ) $this->_loadParent = $params[
'parent'];
397 if ( isset($this->_loadParent) ){
398 $this->parent = $this->menu->getItemById($this->_loadParent);
400 foreach ( $this->_loadChildIDs as $childID ){
401 $this->children[] = $this->menu->getItemById($childID);
413 foreach ( $this->children as $key=>$sibling ){
414 if ( stristr( $sibling->getURL(), $menuItem->
getURL() ) == $sibling->getURL() ){
415 unset($this->children[$key]);
422 $menuItem->parent = $this;
423 $this->children[] = $menuItem;
424 $this->sorted =
false;
427 if ( !isset($menuItem->menuID) ){
428 $menuItem->menuID = $this->menu->nextID();
429 $this->menu->addItem($menuItem);
439 $oldOrder = $this->order;
440 $this->order = $order;
441 if ( $order != $oldOrder and isset($this->parent) ){
442 $this->parent->sorted =
false;
449 if ( !$this->sorted ){
516 if ( $level < count(
$path)-1 ){
519 $breadCrumb = (
$path[$level]->menuID == $this->menuID );
523 $level == count(
$path)-2 and (
527 $level == count(
$path)-3 and (
537 $this->showChildrenSetting & (
538 self::$SHOW_CHILDREN_ALWAYS |
539 self::$SHOW_CHILDREN_WHEN_SELECTED
544 $this->showChildrenSetting & (
545 self::$SHOW_CHILDREN_ALWAYS |
546 self::$SHOW_CHILDREN_WHEN_PARENT |
547 self::$SHOW_CHILDREN_WHEN_ANCESTOR
551 ($breadCrumb and !$parent and !$selected) and (
552 $this->showChildrenSetting & (
553 self::$SHOW_CHILDREN_ALWAYS |
554 self::$SHOW_CHILDREN_WHEN_ANCESTOR
563 'selected'=>$selected,
565 'breadCrumb'=>$breadCrumb,
571 $menu[] = $item->selfToMenuStruct(array(
577 if ( $showChildren or $path[$level+1]->menuID == $child->menuID ){
579 $child->buildMenu($path, $level+1, $pageTitle, $menu);
591 if ( $this->showChildrenSetting & self::$SHOW_CHILDREN_ALWAYS ){
592 foreach ($this->children as $child ){
593 $child->buildMenu(
$path, $level+1, $pageTitle, $menu);
609 'menuID'=>$this->menuID,
611 'label'=>$this->label,
618 return array_merge($defaults, $params);
621 private function _sort(){
622 uasort($this->children, array(&$this,
'_cmp'));
623 $this->sorted =
true;
627 private function _cmp($a, $b){
628 if ( $a->order == $b->order )
return 0;
629 else return ($a->order<$b->order)?-1:1;
634 public function getId(){
return $this->menuID;}
636 public function getURL(){
return $this->url;}
638 public function setId($id){ $this->menuID = $id;}
640 $this->showChildrenSetting = $setting;
646 if ( !$this->sorted ) $this->_sort();
647 return $this->children;