url = $url; parent::__construct($menu, RecursiveIteratorIterator::CHILD_FIRST); } /** * Register the outer ul opening html-tag */ public function beginIteration() { $this->tags[] = ''; } /** * Register a inner ul opening html-tag */ public function beginChildren() { // The iterator runs in mode CHILD_FIRST so we need to remember // where to insert the parent's opening html tag once its rendered $parent = $this->getSubIterator(0)->current(); $this->tags[$parent->getId() . '_begin'] = null; $this->tags[] = ''; // Remember the position of the parent's closing html-tag $parent = $this->getSubIterator(0)->current(); $this->tags[$parent->getId() . '_end'] = null; } /** * Render the given child * * @param Menu $child The menu's child to render * * @return string The child rendered as html */ public function renderChild(Menu $child) { return sprintf( '%s%s', $child->getUrl() ? Url::fromPath($child->getUrl()) : '#', $child->getIcon() ? ' ' : '', htmlspecialchars($child->getTitle()) ); } /** * Return the menu rendered as html * * @return string */ public function render() { $passedActiveChild = false; foreach ($this as $child) { $childIsActive = $this->isActive($child); if ($childIsActive && $this->getDepth() > 0) { $passedActiveChild = true; } if ($childIsActive || ($passedActiveChild && $this->getDepth() === 0)) { $passedActiveChild &= $this->getDepth() !== 0; $openTag = '
  • '; } else { $openTag = '
  • '; } $content = $this->renderChild($child); $closingTag = '
  • '; if (array_key_exists($child->getId() . '_begin', $this->tags)) { $this->tags[$child->getId() . '_begin'] = $openTag . $content; $this->tags[$child->getId() . '_end'] = $closingTag; } else { $this->tags[] = $openTag . $content . $closingTag; } } return implode("\n", $this->tags); } /** * @see MenuRenderer::render() */ public function __toString() { return $this->render(); } /** * Return whether the current request url references the child's url * * @param Menu $child The menu's child to check * * @return bool */ protected function isActive(Menu $child) { return html_entity_decode(rawurldecode($this->url)) === html_entity_decode(rawurldecode($child->getUrl())); } }