joomla_test/modules/mod_roknavmenu/lib/librokmenu/AbstractRokMenuProvider.php
2020-01-02 22:20:31 +07:00

159 lines
4.2 KiB
PHP

<?php
/**
* @version $Id: AbstractRokMenuProvider.php 4585 2012-10-27 01:44:54Z btowles $
* @author RocketTheme http://www.rockettheme.com
* @copyright Copyright (C) 2007 - 2013 RocketTheme, LLC
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPLv2 only
*/
require_once(dirname(__FILE__) . '/RokMenuProvider.php');
/**
* The base class for all data providers for menus
*/
abstract class AbstractRokMenuProvider implements RokMenuProvider
{
/**
* @var array
*/
protected $args = array();
/**
* @var array
*/
protected $active_branch = array();
/**
* @var int
*/
protected $current_node = 0;
/**
* @var RokMenuNodeTree
*/
protected $menu;
/**
* @param $args
* @return void
*/
public function __construct(&$args)
{
$this->args =& $args;
}
/**
* @return array
*/
public function getActiveBranch()
{
return $this->active_branch;
}
/**
* @return int
*/
public function getCurrentNodeId()
{
return $this->current_node;
}
/**
* @return RokMenuNodeTree
*/
public function getMenuTree()
{
if (null == $this->menu) {
$this->menu = new RokMenuNodeTree();
$this->populateMenuTree();
}
return $this->menu;
}
/**
* @return void
*/
protected function populateMenuTree()
{
$nodes = $this->getMenuItems();
$this->createMenuTree($nodes, $this->args['maxdepth']);
}
/**
* Takes the menu item nodes and puts them into a tree structure
* @param $nodes
* @param $maxdepth
* @return bool|RokMenuNodeTree
*/
protected function createMenuTree(&$nodes, $maxdepth)
{
// TODO: move maxdepth to higher processing level?
if (!empty($nodes)) {
// Build Menu Tree root down (orphan proof - child might have lower id than parent)
$ids = array();
$ids[0] = true;
$unresolved = array();
// pop the first item until the array is empty if there is any item
if (is_array($nodes)) {
while (count($nodes) && !is_null($node = array_shift($nodes)))
{
if (!$this->menu->addNode($node)) {
if (!array_key_exists($node->getId(), $unresolved) || $unresolved[$node->getId()] < $maxdepth) {
array_push($nodes, $node);
if (!isset($unresolved[$node->getId()])) $unresolved[$node->getId()] = 1;
else $unresolved[$node->getId()]++;
}
}
}
}
}
}
/**
* @param $nodeList
* @return void
*/
protected function populateActiveBranch($nodeList)
{
// setup children array to find parents and children
$children = array();
$list = array();
foreach ($nodeList as $node) {
$thisref = &$children[$node->getId()];
$thisref['parent_id'] = $node->getParent();
if ($node->getParent() == 0) {
$list[$node->getId()] = &$thisref;
} else {
$children[$node->getParent()]['children'][] = $node->getId();
}
}
// Find active branch
if ($this->current_node != 0) {
if (array_key_exists($this->current_node, $nodeList)) {
$parent_id = $children[$this->current_node]['parent_id'];
while ($parent_id != 0) {
$this->active_branch[$parent_id] = $nodeList[$parent_id];
$parent_id = $children[$parent_id]['parent_id'];
}
$this->active_branch = array_reverse($this->active_branch, true);
$this->active_branch[$this->current_node] = $nodeList[$this->current_node];
}
}
}
/**
* This platform specific function should be implemented to get the menu nodes and return them in a RokMenuNodeTree.
* @abstract
* @return array of RokMenuNode objects
*/
protected abstract function getMenuItems();
}