/**
* Traverse the config object
*
* @param array $tree
* @param int $depth
* @param string $parentHref
* @throws Exception
* @return \Pop\Dom\Child
*/
protected function traverse(array $tree, $depth = 1, $parentHref = null)
{
// Create overriding top level parent, if set
if ($depth == 1 && isset($this->config['top'])) {
$parent = isset($this->config['top']) && isset($this->config['top']['node']) ? $this->config['top']['node'] : 'ul';
$child = null;
if (isset($this->config['child']) && isset($this->config['child']['node'])) {
$child = $this->config['child']['node'];
} else {
if ($parent == 'ul') {
$child = 'li';
}
}
// Create parent node
$nav = new Child($parent);
// Set top attributes if they exist
if (isset($this->config['top']) && isset($this->config['top']['id'])) {
$nav->setAttributes('id', $this->config['top']['id']);
}
if (isset($this->config['top']) && isset($this->config['top']['class'])) {
$nav->setAttributes('class', $this->config['top']['class']);
}
if (isset($this->config['top']['attributes'])) {
foreach ($this->config['top']['attributes'] as $attrib => $value) {
$nav->setAttributes($attrib, $value);
}
}
} else {
// Set up parent/child node names
$parent = isset($this->config['parent']) && isset($this->config['parent']['node']) ? $this->config['parent']['node'] : 'ul';
$child = null;
if (isset($this->config['child']) && isset($this->config['child']['node'])) {
$child = $this->config['child']['node'];
} else {
if ($parent == 'ul') {
$child = 'li';
}
}
// Create parent node
$nav = new Child($parent);
// Set parent attributes if they exist
if (isset($this->config['parent']) && isset($this->config['parent']['id'])) {
$nav->setAttributes('id', $this->config['parent']['id'] . '-' . $this->parentLevel);
}
if (isset($this->config['parent']) && isset($this->config['parent']['class'])) {
$nav->setAttributes('class', $this->config['parent']['class'] . '-' . $depth);
}
if (isset($this->config['parent']['attributes'])) {
foreach ($this->config['parent']['attributes'] as $attrib => $value) {
$nav->setAttributes($attrib, $value);
}
}
}
$this->parentLevel++;
$depth++;
// Recursively loop through the nodes
foreach ($tree as $node) {
$allowed = true;
if (isset($node['acl'])) {
if (null === $this->acl) {
throw new Exception('The access control object is not set.');
}
if (null === $this->role) {
throw new Exception('The current role is not set.');
}
$resource = isset($node['acl']['resource']) ? $node['acl']['resource'] : null;
$permission = isset($node['acl']['permission']) ? $node['acl']['permission'] : null;
$allowed = $this->acl->isAllowed($this->role, $resource, $permission);
}
if ($allowed && isset($node['name']) && isset($node['href'])) {
// Create child node and child link node
$a = new Child('a', $node['name']);
if (substr($node['href'], 0, 1) == '/' || substr($node['href'], 0, 1) == '#' || substr($node['href'], -1) == '#' || substr($node['href'], 0, 4) == 'http') {
$href = $node['href'];
} else {
if (substr($parentHref, -1) == '/') {
$href = $parentHref . $node['href'];
} else {
$href = $parentHref . '/' . $node['href'];
}
}
$a->setAttributes('href', $href);
if ($this->returnFalse && ($href == '#' || substr($href, -1) == '#')) {
$a->setAttributes('onclick', 'return false;');
}
$url = $_SERVER['REQUEST_URI'];
if (strpos($url, '?') !== false) {
$url = substr($url, strpos($url, '?'));
}
$linkClass = null;
if ($href == $url) {
if (isset($this->config['on'])) {
$linkClass = $this->config['on'];
}
} else {
if (isset($this->config['off'])) {
$linkClass = $this->config['off'];
}
}
// If the node has any attributes
if (isset($node['attributes'])) {
foreach ($node['attributes'] as $attrib => $value) {
$value = $attrib == 'class' && null !== $linkClass ? $value . ' ' . $linkClass : $value;
$a->setAttributes($attrib, $value);
}
} else {
if (null !== $linkClass) {
$a->setAttributes('class', $linkClass);
}
}
if (null !== $child) {
$navChild = new Child($child);
// Set child attributes if they exist
if (isset($this->config['child']) && isset($this->config['child']['id'])) {
$navChild->setAttributes('id', $this->config['child']['id'] . '-' . $this->childLevel);
}
if (isset($this->config['child']) && isset($this->config['child']['class'])) {
$navChild->setAttributes('class', $this->config['child']['class'] . '-' . ($depth - 1));
}
if (isset($this->config['child']['attributes'])) {
foreach ($this->config['child']['attributes'] as $attrib => $value) {
$navChild->setAttributes($attrib, $value);
}
}
// Add link node
$navChild->addChild($a);
$this->childLevel++;
// If there are children, loop through and add them
if (isset($node['children']) && is_array($node['children']) && count($node['children']) > 0) {
$childrenAllowed = true;
// Check if the children are allowed
if (isset($node['acl'])) {
$i = 0;
foreach ($node['children'] as $nodeChild) {
if (null === $this->acl) {
throw new Exception('The access control object is not set.');
}
if (null === $this->role) {
throw new Exception('The current role is not set.');
}
$resource = isset($nodeChild['acl']['resource']) ? $nodeChild['acl']['resource'] : null;
$permission = isset($nodeChild['acl']['permission']) ? $nodeChild['acl']['permission'] : null;
if (!$this->acl->isAllowed($this->role, $resource, $permission)) {
$i++;
}
}
if ($i == count($node['children'])) {
$childrenAllowed = false;
}
}
if ($childrenAllowed) {
$navChild->addChild($this->traverse($node['children'], $depth, $href));
}
}
// Add child node
$nav->addChild($navChild);
} else {
$nav->addChild($a);
}
}
}
return $nav;
}