From c8f3e211ad235be19707d343f58ab8a9470c7f47 Mon Sep 17 00:00:00 2001 From: Neil Jennings Date: Tue, 23 Jan 2018 16:40:36 +0000 Subject: [PATCH] menu tree var available in menu templates --- config/site.php | 2 +- resources/views/frontend/menu/items.blade.php | 3 + src/Libraries/Builder/MenuBuilder.php | 48 ++++-- src/Libraries/Builder/MenuTree.php | 155 ++++++++++++++++++ 4 files changed, 194 insertions(+), 14 deletions(-) create mode 100644 resources/views/frontend/menu/items.blade.php create mode 100644 src/Libraries/Builder/MenuTree.php diff --git a/config/site.php b/config/site.php index eea212d..05dba35 100644 --- a/config/site.php +++ b/config/site.php @@ -4,7 +4,7 @@ 'name' => 'Coaster CMS', 'email' => 'info@example.com', - 'version' => 'v5.4.34', + 'version' => 'v5.4.35', 'pages' => '0', 'groups' => '0', 'secure_folders' => 'secure', diff --git a/resources/views/frontend/menu/items.blade.php b/resources/views/frontend/menu/items.blade.php new file mode 100644 index 0000000..5ebc8f5 --- /dev/null +++ b/resources/views/frontend/menu/items.blade.php @@ -0,0 +1,3 @@ +@foreach($itemsData as $itemData) + {!! $itemData !!} +@endforeach \ No newline at end of file diff --git a/src/Libraries/Builder/MenuBuilder.php b/src/Libraries/Builder/MenuBuilder.php index 89c4ffb..27891e6 100644 --- a/src/Libraries/Builder/MenuBuilder.php +++ b/src/Libraries/Builder/MenuBuilder.php @@ -12,6 +12,11 @@ class MenuBuilder { + /** + * @var MenuTree + */ + protected $_tree; + /** * @var int */ @@ -108,6 +113,7 @@ public function __construct($menuItems, $rootPageId = 0, $subLevels = 0, $startL $this->rootItems = $this->_convertPagesToItems($menuItems); $this->subLevels = $subLevels; $this->startLevel = $startLevel; + $this->_tree = new MenuTree(); $this->options = array_merge([ 'view' => 'default', @@ -121,7 +127,7 @@ public function __construct($menuItems, $rootPageId = 0, $subLevels = 0, $startL public function render() { $menuItems = $this->_buildMenuItems($this->rootItems, $this->rootPageId, $this->startLevel, $this->subLevels); - return $this->_getRenderedView('menu', ['items' => $menuItems]); + return $this->_getView('menu', ['items' => $this->_getSubItemsView($menuItems), 'tree' => $this->_tree], true); } /** @@ -149,7 +155,7 @@ protected function _convertPagesToItems($items, $baseItem = null) * @param int $parentPageId * @param int $level * @param int $subLevels - * @return string + * @return array */ protected function _buildMenuItems($items, $parentPageId, $level = 1, $subLevels = 0) { @@ -157,7 +163,7 @@ protected function _buildMenuItems($items, $parentPageId, $level = 1, $subLevels $items = $this->_returnExistingLiveItems($items); $total = count($items); - $renderedMenuItems = ''; + $menuItems = []; foreach ($items as $count => $item) { $isFirst = ($count == 0); @@ -167,45 +173,61 @@ protected function _buildMenuItems($items, $parentPageId, $level = 1, $subLevels $active = $this->_isActivePage($pageId); // or active parent page $itemData = new MenuItemDetails($item, $active, $parentPageId, $this->options['canonicals']); - $renderedSubMenu = ''; + $this->_tree->add($itemData); + + $subItemsToRender = []; if ($subLevelsToRender = is_null($item->sub_levels) ? $subLevels : $item->sub_levels) { if ($subPages = Page::category_pages($pageId)) { $subPages = $this->_convertPagesToItems($subPages, $item); - $renderedSubMenu = $this->_buildMenuItems($subPages, $pageId, $level + 1, $subLevelsToRender - 1); + $this->_tree->downLevel($pageId); + $subItemsToRender = $this->_buildMenuItems($subPages, $pageId, $level + 1, $subLevelsToRender - 1); + $this->_tree->upLevel(); } } - $view = $renderedSubMenu ? 'submenu_' . $level : 'item'; - $renderedMenuItems .= $this->_getRenderedView($view, [ + $view = $subItemsToRender ? 'submenu_' . $level : 'item'; + $menuItems[] = $this->_getView($view, [ 'item' => $itemData, - 'items' => $renderedSubMenu, + 'items' => $this->_getSubItemsView($subItemsToRender), 'is_first' => $isFirst, 'is_last' => $isLast, 'count' => $count + 1, 'total' => $total, 'level' => $level, - 'further_levels' => $subLevelsToRender + 'further_levels' => $subLevelsToRender, + 'tree' => $this->_tree->newInstance($item->page_id) ]); } - return $renderedMenuItems; + return $menuItems; } /** * @param string $viewPath * @param array $data - * @return string + * @param bool $render + * @return \Illuminate\Contracts\View\View|string */ - protected function _getRenderedView($viewPath, $data = []) + protected function _getView($viewPath, $data = [], $render = false) { $viewPath = 'themes.' . PageBuilder::getData('theme') . '.menus.' . $this->options['view'] . '.' . $viewPath; if (View::exists($viewPath)) { - return View::make($viewPath, array_merge($this->options, $data))->render(); + $view = View::make($viewPath, array_merge($this->options, $data)); + return $render ? $view->render() : $view; } else { return 'View not found (' . $viewPath . ')'; } } + /** + * @param $subItemsToRender + * @return \Illuminate\Contracts\View\View|string + */ + protected function _getSubItemsView($subItemsToRender) + { + return $subItemsToRender ? View::make('coasterCms::menu.items', ['itemsData' => $subItemsToRender]) : ''; + } + /** * @param MenuItem[] $items * @return MenuItem[] diff --git a/src/Libraries/Builder/MenuTree.php b/src/Libraries/Builder/MenuTree.php new file mode 100644 index 0000000..4aae195 --- /dev/null +++ b/src/Libraries/Builder/MenuTree.php @@ -0,0 +1,155 @@ +_currentKey, $key); + } + + /** + * + */ + public function upLevel() + { + array_pop($this->_currentKey); + } + + /** + * @param MenuItemDetails $item + */ + public function add($item) + { + $key = implode('.', array_merge($this->_currentKey, [$item->item->page_id])); + $this->_tree = Arr::add($this->_tree, $key, []); + $this->_itemData[$key] = $item; + } + + /** + * MenuTree constructor. + * @param array $itemData + * @param array $currentKey + * @param null $tree + */ + public function __construct(&$itemData = [], $currentKey = [], &$tree = null) + { + $this->_itemData = &$itemData; + $this->_currentKey = $currentKey; + $this->_tree = &$tree; + } + + /** + * @param string $pageId + * @return static + */ + public function newInstance($pageId) + { + return new static($this->_itemData, array_merge($this->_currentKey, [$pageId]), $this->_tree); + } + + /** + * @param bool $parent + * @return string + */ + public function getKey($parent = false) + { + $key = $parent ? array_slice($this->_currentKey, 0, -1) : $this->_currentKey; + return $key ? implode('.', $key) : null; + } + + /** + * @return array + */ + public function getTree() + { + return $this->_tree; + } + + /** + * @return array|mixed|null + */ + public function getCurrentLevelItems() + { + $key = $this->getKey(true); + $itemIds = Arr::get($this->_tree, $key); + $items = []; + foreach ($itemIds as $itemId => $value) { + $itemKey = ($key ? $key . '.' : '') . $itemId; + $items[$itemKey] = $this->_itemData[$itemKey]; + } + return $items; + } + + /** + * @return array|mixed + */ + public function getSubItems() + { + $key = $this->getKey(); + $itemIds = Arr::get($this->_tree, $key); + $items = []; + foreach ($itemIds as $itemId => $value) { + $itemKey = ($key ? $key . '.' : '') . $itemId; + $items[$itemKey] = $this->_itemData[$itemKey]; + } + return $items; + } + + /** + * Recursive and flatten + * @return array|mixed + */ + public function getFlatSubItems() + { + $key = $this->getKey(); + $itemIds = Arr::get($this->_tree, $key); + $flatItemIds = $this->_dot($itemIds, $key ? $key . '.' : ''); + $items = []; + foreach ($flatItemIds as $itemId => $value) { + $items[$itemId] = $this->_itemData[$itemId]; + } + return $items; + } + + /** + * @param $array + * @param $prepend + * @return array + */ + protected function _dot($array, $prepend) + { + $results = []; + foreach ($array as $key => $value) { + $results[$prepend.$key] = $value; + if (is_array($value) && ! empty($value)) { + $results = array_merge($results, Arr::dot($value, $prepend.$key.'.')); + } + } + return $results; + } + +} + +