diff --git a/catalyst/menu-bundle/Menu/Collection.php b/catalyst/menu-bundle/Menu/Collection.php new file mode 100644 index 00000000..2ddfc50d --- /dev/null +++ b/catalyst/menu-bundle/Menu/Collection.php @@ -0,0 +1,71 @@ +position = 0; + $this->array = array(); + $this->index_array = array(); + } + + // iterator stuff + public function rewind() + { + $this->position = 0; + } + + public function current() + { + return $this->array[$this->index_array[$this->position]]; + } + + public function key() + { + return $this->position; + } + + public function next() + { + return ++$this->position; + } + + public function valid() + { + return isset($this->index_array[$this->position]); + } + // end of iterator stuff + + public function add(Item $mi) + { + $id = $mi->getID(); + $this->array[$id] = $mi; + $this->index_array[] = $id; + return $this; + } + + public function get($id) + { + if (isset($this->array[$id])) + return $this->array[$id]; + + return null; + } + + public function unselectAll() + { + foreach ($this->array as $mi) + $mi->setSelected(false, false); + + return $this; + } +} diff --git a/catalyst/menu-bundle/Menu/Generator.php b/catalyst/menu-bundle/Menu/Generator.php new file mode 100644 index 00000000..eba63ab1 --- /dev/null +++ b/catalyst/menu-bundle/Menu/Generator.php @@ -0,0 +1,164 @@ +index = new Collection(); + $this->menu = new Collection(); + $this->router = $router; + $this->cache_dir = $cache_dir; + $this->config_dir = $config_dir; + $this->config_file = $config_file; + } + + public function getMenu($menu_key) + { + // initialize + $menu_data = [ + 'menu' => [], + 'index' => [] + ]; + + // cache config + $cache_file = $this->cache_dir . '/' . $this->config_file . '.' . $menu_key . '.serial'; + $menu_cache = new ConfigCache($cache_file, true); + + // cache not fresh + if (!$menu_cache->isFresh()) + { + $files = []; + $resources = []; + + try + { + // get location of menu config file + $path = $this->config_dir . '/' . $this->config_file; + $files[] = $path; + $resources[] = new FileResource($path); + + // TODO: handle routes changes as well + // NOTE: need to figure out how to handle route changes or require + // a cache clear for every route change + + // process bundle menu + $this->parseMenu($path, $menu_key); + } + catch (\InvalidArgumentException $e) + { + error_log($e->getMessage()); + error_log($menu_key . ' menu not found.'); + return $menu_data; + } + + $menu_data = [ + 'menu' => $this->menu, + 'index' => $this->index, + ]; + $menu_serial = serialize($menu_data); + $menu_cache->write($menu_serial, $resources); + } + else + { + $menu_serial = file_get_contents($cache_file); + $menu_data = unserialize($menu_serial); + $this->menu = $menu_data['menu']; + $this->index = $menu_data['index']; + } + + return $menu_data; + } + + protected function parseMenu($path, $menu_key) + { + $parser = new YamlParser(); + $menu_config = $parser->parse(file_get_contents($path)); + + // check if we have menu items + if (!isset($menu_config[$menu_key])) + { + error_log('No ' . $menu_key . ' found for ' . $path); + return; + } + + // go through each one + foreach ($menu_config[$menu_key] as $mi_data) + { + // check params + if (!isset($mi_data['icon'])) + $mi_data['icon'] = null; + + // instantiate + $mi = $this->newItem($mi_data['id'], $mi_data['label'], $mi_data['icon']); + + // acl + if (isset($mi_data['acl'])) + $mi->setACLKey($mi_data['acl']); + + // check parent + if (isset($mi_data['parent']) && $mi_data['parent'] != null) + { + $parent = $this->index->get($mi_data['parent']); + if ($parent == null) + continue; + + $parent->addChild($mi); + } + else + $this->menu->add($mi); + + } + } + + protected function newItem($id, $label, $icon = null) + { + $mi = new Item(); + $mi->setID($id) + ->setLabel($label); + + try + { + $mi->setLink($this->router->generate($id)); + } + catch (RouteNotFoundException $e) + { + // no route, set to # + $mi->setLink('#'); + } + + if ($icon != null) + $mi->setIcon($icon); + + $this->index->add($mi); + + return $mi; + } + + public function generate() + { + $this->getAllBundleMenus(); + + return $this->menu; + } + + public function getIndex() + { + return $this->index; + } +} diff --git a/catalyst/menu-bundle/Menu/Item.php b/catalyst/menu-bundle/Menu/Item.php new file mode 100644 index 00000000..14e178f0 --- /dev/null +++ b/catalyst/menu-bundle/Menu/Item.php @@ -0,0 +1,138 @@ +id = ''; + $this->icon = null; + $this->link = null; + $this->label = ''; + $this->children = []; + $this->selected = false; + $this->parent = null; + $this->acl_key = null; + } + + // setters + public function setID($id) + { + $this->id = $id; + return $this; + } + + public function setIcon($icon) + { + $this->icon = $icon; + return $this; + } + + public function setLink($link) + { + $this->link = $link; + return $this; + } + + public function setLabel($label) + { + $this->label = $label; + return $this; + } + + public function setParent(self $parent) + { + $this->parent = $parent; + return $this; + } + + public function addChild(self $child) + { + $child->setParent($this); + + // check if selected + if ($child->isSelected()) + $this->setSelected(); + + $this->children[] = $child; + return $this; + } + + public function setSelected($sel = true, $to_bubble = true) + { + if ($sel) + { + $this->selected = true; + // bubble up to parents + if ($this->parent != null && $to_bubble) + $this->parent->setSelected(true, true); + } + else + $this->selected = false; + return $this; + } + + public function setACLKey($key) + { + $this->acl_key = $key; + return $this; + } + + // getters + public function getID() + { + return $this->id; + } + + public function getIcon() + { + return $this->icon; + } + + public function getLink() + { + return $this->link; + } + + public function getLabel() + { + return $this->label; + } + + public function getChildren() + { + return $this->children; + } + + public function hasChildren() + { + if (count($this->children) > 0) + return true; + return false; + } + + public function isSelected() + { + return $this->selected; + } + + public function getParent() + { + return $this->parent; + } + + public function getACLKey() + { + return $this->acl_key; + } +}