Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 3
CRAP
82.95% covered (success)
82.95%
73 / 88
Application\View\Helper\Navigation\Menu
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 3
43.78
82.95% covered (success)
82.95%
73 / 88
 renderNormalMenu
0.00% covered (danger)
0.00%
0 / 1
31.49
81.67% covered (success)
81.67%
49 / 60
 htmlify
0.00% covered (danger)
0.00%
0 / 1
8.11
88.00% covered (success)
88.00%
22 / 25
 getPresentUserEmailAddress
0.00% covered (danger)
0.00%
0 / 1
2.15
66.67% covered (warning)
66.67%
2 / 3
<?php
/**
 * Class Menu Override Zend\View\Helper\Navigation\Menu for specific requirements of
 * present application.
 *
 * @package     Application\View\Helper\Navigation
 * @author      Nigel Hurnell
 * @version     v 1.0.0
 * @license     BSD
 * @copyright   Copyright (c) 2017, Nigel Hurnell
 */
namespace Application\View\Helper\Navigation;
use Zend\View\Helper\Navigation\Menu as ZendMenu;
use Zend\Navigation\Page\AbstractPage;
use Zend\Navigation\AbstractContainer;
use RecursiveIteratorIterator;
/**
 * Class Menu render an HTML menu for the application updated to conform
 * to the specific requirements of present application
 *
 * @package     Application\View\Helper\Navigation
 * @author      Nigel Hurnell
 * @version     v 1.0.0
 * @license     BSD
 * @copyright   Copyright (c) 2017, Nigel Hurnell
 */
class Menu extends ZendMenu
{
    /**
     * Renders a normal menu (called from {@link renderMenu()}).
     *
     * @param  AbstractContainer $container          container to render
     * @param  string            $ulClass            CSS class for first UL
     * @param  string            $indent             initial indentation
     * @param  int|null          $minDepth           minimum depth
     * @param  int|null          $maxDepth           maximum depth
     * @param  bool              $onlyActive         render only active branch?
     * @param  bool              $escapeLabels       Whether or not to escape the labels
     * @param  bool              $addClassToListItem Whether or not page class applied to <li> element
     * @param  string            $liActiveClass      CSS class for active LI
     * @return string
     */
    protected function renderNormalMenu(
            AbstractContainer $container, $ulClass, $indent, $minDepth, $maxDepth, $onlyActive, $escapeLabels, $addClassToListItem, $liActiveClass
    )
    {
        $html = '';
        // find deepest active
        $found = $this->findActive($container, $minDepth, $maxDepth);
        /* @var $escaper \Zend\View\Helper\EscapeHtmlAttr */
        $escaper = $this->view->plugin('escapeHtmlAttr');
        if ($found) {
            $foundPage = $found['page'];
            $foundDepth = $found['depth'];
        } else {
            $foundPage = null;
        }
        // create iterator
        $iterator = new RecursiveIteratorIterator(
                $container, RecursiveIteratorIterator::SELF_FIRST
        );
        if (is_int($maxDepth)) {
            $iterator->setMaxDepth($maxDepth);
        }
        // iterate container
        $prevDepth = -1;
        foreach ($iterator as $page) {
            $depth = $iterator->getDepth();
            $isActive = $page->isActive(true);
            if ($depth < $minDepth || !$this->accept($page)) {
                // page is below minDepth or not accepted by acl/visibility
                continue;
            } elseif ($onlyActive && !$isActive) {
                // page is not active itself, but might be in the active branch
                $accept = false;
                if ($foundPage) {
                    if ($foundPage->hasPage($page)) {
                        // accept if page is a direct child of the active page
                        $accept = true;
                    } elseif ($foundPage->getParent()->hasPage($page)) {
                        // page is a sibling of the active page...
                        if (!$foundPage->hasPages(!$this->renderInvisible) || is_int($maxDepth) && $foundDepth + 1 > $maxDepth
                        ) {
                            // accept if active page has no children, or the
                            // children are too deep to be rendered
                            $accept = true;
                        }
                    }
                }
                if (!$accept) {
                    continue;
                }
            }
            // make sure indentation is correct
            $depth -= $minDepth;
            $myIndent = $indent . str_repeat('        ', $depth);
            if ($depth > $prevDepth) {
                // start new ul tag
                if ($ulClass && $depth == 0) {
                    $addClassToListItem = true;
                    $ulClass = ' class="' . $escaper($ulClass) . '"';
                } else if ($depth == 1) {
                    $ulClass = ' class="dropdown-menu" ';
                } else {
                    $ulClass = '';
                }
                $html .= $myIndent . '<ul' . $ulClass . '>' . PHP_EOL;
            } elseif ($prevDepth > $depth) {
                // close li/ul tags until we're at current depth
                for ($i = $prevDepth; $i > $depth; $i--) {
                    $ind = $indent . str_repeat('        ', $i);
                    $html .= $ind . '    </li>' . PHP_EOL;
                    $html .= $ind . '</ul>' . PHP_EOL;
                }
                // close previous li tag
                $html .= $myIndent . '    </li>' . PHP_EOL;
            } else {
                // close previous li tag
                $html .= $myIndent . '    </li>' . PHP_EOL;
            }
            // render li tag and page
            $liClasses = [];
            // Is page active?
            if ($isActive) {
                $liClasses[] = $liActiveClass;
            }
            // Add CSS class from page to <li>
            if ($addClassToListItem && $page->getClass()) {
                $liClasses[] = $page->getClass();
            }
            $liClass = empty($liClasses) ? '' : ' class="' . $escaper(implode(' ', $liClasses)) . '"';
            $html .= $myIndent . '    <li' . $liClass . '>' . PHP_EOL
                    . $myIndent . '        ' . $this->htmlify($page, $escapeLabels, $addClassToListItem) . PHP_EOL;
            // store as previous depth for next iteration
            $prevDepth = $depth;
        }
        if ($html) {
            // done iterating container; close open ul/li tags
            for ($i = $prevDepth + 1; $i > 0; $i--) {
                $myIndent = $indent . str_repeat('        ', $i - 1);
                $html .= $myIndent . '    </li>' . PHP_EOL
                        . $myIndent . '</ul>' . PHP_EOL;
            }
            $html = rtrim($html, PHP_EOL);
        }
        return $html;
    }
    /**
     * Returns an HTML string containing an 'a' element for the given page if
     * the page's href is not empty, and a 'span' element if it is empty.
     * 
     * @param AbstractPage $page
     * @param type $escapeLabel
     * @param type $addClassToListItem
     * @return string
     */
    public function htmlify(AbstractPage $page, $escapeLabel = true, $addClassToListItem = false)
    {
        // get attribs for element
        $attribs = [
            'id' => $page->getId(),
            'title' => $this->translate($page->getTitle(), $page->getTextDomain()),
        ];
        $properties = $page->getCustomProperties();
        foreach ($properties as $k => $v) {
            $attribs[$k] = $v;
        }
        if ($addClassToListItem === false) {
            $attribs['class'] = $page->getClass();
        }
        $href = $page->getHref();
        if ($href) {
            $element = 'a';
            $attribs['href'] = $href;
            $attribs['target'] = $page->getTarget();
        } else {
            $element = 'span';
        }
        $html = '<' . $element . $this->htmlAttribs($attribs) . '>';
        if ($page->getLabel() === 'Identity') {
            $label = $this->getPresentUserEmailAddress();
        } else {
            $label = $this->translate($page->getLabel(), $page->getTextDomain());
        }
        if ($escapeLabel === true) {
            /** @var \Zend\View\Helper\EscapeHtml $escaper */
            $escaper = $this->view->plugin('escapeHtml');
            $html .= $escaper($label);
        } else {
            $html .= $label;
        }
        if (array_key_exists('data-toggle', $attribs) && $attribs['data-toggle'] == 'dropdown') {
            $html .= ' <b class="caret"></b>';
        }
        $html .= '</' . $element . '>';
        return $html;
    }
    /**
     * Get logged in user's e-mail address
     * 
     * @uses \AclUser\Permissions\Acl\Acl::joinAclToNavigation() where setDefaultAcl is called on navigation
     * @return string
     */
    protected function getPresentUserEmailAddress()
    {
        if ($this->getAcl()) {
            return $this->getAcl()->getPresentUserEmailAddress();
        }
        return 'e-mail';
    }
}