current()->getSubmenus()); } function hasChildren() { return count($this->current()->getSubmenus()) > 0; } } class Menu { private $parent; private $href; private $title; private $submenus = array(); private $aliases = array(); function __construct ($title = null, $href = null, $aliases = null) { if (isset($href)) { $this->setHref (url::href("/$href")); } $this->setTitle ($title); $this->addAlias ($aliases); } function getSelectedItem () { $iterator = new RecursiveIteratorIterator(new Menu_Iterator(array($this)), RecursiveIteratorIterator::SELF_FIRST); $url = '//' . Router::$current_uri; foreach($iterator as $item) { if ($item->hasHref()) { if ($item->isEqualTo($url)) { return $item; } } } } function isEqualTo ($href) { $href = url::href ($href); foreach ($this->getPossibleHrefs() as $possible_href) { if ($href == $possible_href) { return true; } $x = "$possible_href/"; if (substr($href, 0, strlen($x)) == $x) { return true; } } } private function getPossibleHrefs () { $result = array(); $result[] = $this->getHref(); foreach ($this->getAliases() as $alias) { $result[] = preg_replace('~^(.*/).*~', '$1'.$alias, $this->getHref()); } return $result; } function render () { $result = array(); $active = $this->getSelectedItem(); if (!isset($active)) { $active = $this->getFirstAvailable(); } $item = $active; $depth = $item->getDepth(); while ($item !== $this) { if (!isset($item)) { break; } $item = $item->getParent(); $submenu_iterator = new Menu_Iterator($item->getSubmenus()); foreach ($submenu_iterator as $menu) { $a = array(); $a['title'] = $menu->getTitle(); $first_available = $menu->getFirstAvailable (); if ($first_available) { $a['href'] = $first_available->getHref (); } if ($menu === $active) { $a['active'] = true; $active = $active->getParent(); } $result[$depth][] = $a; } $depth--; } return $result; } function setHref($href) { $this->href = $href; } function getHref() { return $this->href; } function hasHref() { return isset($this->href); } function getFirstAvailable () { if ($this->hasHref()) { return $this; } elseif ($this->hasSubmenus()) { $iterator = new RecursiveIteratorIterator(new Menu_Iterator($this->getSubmenus())); foreach ($iterator as $item) { if ($item->hasHref()) { return $item; } } } } function getDepth () { $result = 0; $i = $this; while ($i = $i->getParent()) { $result++; } return $result; } function setTitle($title) { $this->title = $title; } function getTitle() { return $this->title; } function addSubmenu(Menu $submenu) { $this->submenus[] = $submenu; $submenu->setParent($this); return $submenu; } function getSubmenus() { return $this->submenus; } function hasSubmenus () { return count($this->getSubmenus() > 0); } function setParent($parent) { $this->parent = $parent; } function getParent() { return $this->parent; } function addAlias($aliases) { if (isset($aliases)) { if (!is_array($aliases)) { $aliases = array($aliases); } foreach (new RecursiveIteratorIterator(new RecursiveArrayIterator($aliases)) as $alias) { $this->aliases[] = $alias; } } } function getAliases() { return $this->aliases; } }