Skip to content

Commit

Permalink
menu tree var available in menu templates
Browse files Browse the repository at this point in the history
  • Loading branch information
Neil Jennings committed Jan 23, 2018
1 parent 41a30e5 commit c8f3e21
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 14 deletions.
2 changes: 1 addition & 1 deletion config/site.php
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
3 changes: 3 additions & 0 deletions resources/views/frontend/menu/items.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@foreach($itemsData as $itemData)
{!! $itemData !!}
@endforeach
48 changes: 35 additions & 13 deletions src/Libraries/Builder/MenuBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
class MenuBuilder
{

/**
* @var MenuTree
*/
protected $_tree;

/**
* @var int
*/
Expand Down Expand Up @@ -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',
Expand All @@ -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);
}

/**
Expand Down Expand Up @@ -149,15 +155,15 @@ 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)
{
// remove deleted pages and hidden ones from array
$items = $this->_returnExistingLiveItems($items);

$total = count($items);
$renderedMenuItems = '';
$menuItems = [];

foreach ($items as $count => $item) {
$isFirst = ($count == 0);
Expand All @@ -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[]
Expand Down
155 changes: 155 additions & 0 deletions src/Libraries/Builder/MenuTree.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
<?php namespace CoasterCms\Libraries\Builder;

use CoasterCms\Libraries\Builder\ViewClasses\MenuItemDetails;
use Illuminate\Support\Arr;

class MenuTree
{

/**
* @var array
*/
protected $_currentKey = [];

/**
* @var array
*/
protected $_tree = [];

/**
* @var MenuItemDetails[]
*/
protected $_itemData;

/**
* @param string $key
*/
public function downLevel($key)
{
array_push($this->_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;
}

}


0 comments on commit c8f3e21

Please sign in to comment.