Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- /**
- * Klasse zum Erstellen von Navigationen, v0.1.
- *
- * @package redaxo\structure
- */
- /*
- * Beispiel-Konfiguration einer Haupt-Navigation:
- *
- * $it = rex_navigation_iterator::factory()
- * ->ignoreOfflines(true)
- * ;
- *
- * foreach($it as $navItem) {
- * list($ooObj, $depth, $nth, $count) = $navItem;
- *
- * if ($nth == 1) {
- * if ($depth == 1) {
- * $class = "nav navbar-nav";
- * } else {
- * $class = "dropdown";
- * }
- * echo '<ul class="'. $class .'">';
- * }
- *
- * echo "<li class='rex-navi-depth-". $depth ." rex-nav-". $nth ."nth-child'>";
- * echo "<a href='". $ooObj->getUrl() ."'>". $ooObj->getName() ."</a>";
- * echo "</li>\n";
- *
- * if ($nth == $count) {
- * echo '</ul>';
- * }
- * }
- *
- * Bespiel-Konfiguration einer Seiten-Navigation
- *
- * $it = rex_navigation_iterator::factory()
- * ->startCategory(27)
- * ->depthLimit(3)
- * ->ignoreOfflines(true)
- *
- * foreach($it as $navItem) {
- * list($ooObj, $depth, $nth, $count) = $navItem;
- *
- * if ($nth == 1) {
- * if ($depth == 1) {
- * $class = "nav side-nav";
- * } else {
- * $class = "";
- * }
- * echo '<ul class="'. $class .'">';
- * }
- *
- * echo "<li class='rex-navi-depth-". $depth ." rex-nav-". $nth ."nth-child'>";
- * echo "<a href='". $ooObj->getUrl() ."'>". $ooObj->getName() ."</a>";
- * echo "</li>\n";
- *
- * if ($nth == $count) {
- * echo '</ul>';
- * }
- * }
- *
- * Bespiel-Konfiguration einer Breadcrumb-Navigation
- *
- * $it = rex_navigation_iterator::factory()
- * ->activePath(true)
- * ->ignoreOfflines(true)
- *
- * echo '<ul class="breadcrumb-nav">';
- * echo '<li><a href="' . rex_getUrl(rex_article::getSiteStartArticleId()) . '">STARTSEITE</a></li>';
- * foreach($it as $navItem) {
- * list($ooObj, $depth, $nth, $count) = $navItem;
- *
- * echo "<li>";
- * echo "<a href='". $ooObj->getUrl() ."'>". $ooObj->getName() ."</a>";
- * echo "</li>\n";
- * }
- * echo '</ul>';
- */
- class rex_navigation_iterator implements IteratorAggregate
- {
- use rex_factory_trait;
- private $startCategory = 0;
- private $ignoreOfflines = false;
- private $activePath = false;
- private $depthLimit = -1; // Wieviele Ebene tief, ab der Startebene
- private $path = [];
- private $filter = [];
- private $current_category_id = -1; // Aktuelle Katgorie
- private function __construct()
- {
- // nichts zu tun
- }
- /**
- * @return static
- */
- public static function factory()
- {
- $class = self::getFactoryClass();
- return new $class();
- }
- /**
- * @param int $categoryId Id der Wurzelkategorie, -1 für alle Kategorien (default)
- *
- * @return $this
- */
- public function startCategory($categoryId) {
- $this->startCategory = $categoryId;
- return $this;
- }
- /**
- * @param int $limit Anzahl der Ebenen die angezeigt werden sollen, -1 kein Limit (default)
- *
- * @return $this
- */
- public function depthLimit($limit) {
- $this->depthLimit = $limit;
- return $this;
- }
- /**
- * @param bool $ignoreOfflines FALSE, wenn offline Elemente angezeigt werden (default), sonst TRUE
- *
- * @return $this
- */
- public function ignoreOfflines($ignoreOfflines) {
- $this->ignoreOfflines = $ignoreOfflines;
- return $this;
- }
- /**
- * @param bool $activePath True, wenn nur Elemente der aktiven Kategorie angezeigt werden sollen, sonst FALSE (default)
- *
- * @return $this
- */
- public function activePath($activePath) {
- $this->activePath = $activePath;
- return $this;
- }
- /**
- * Fügt einen Filter hinzu.
- *
- * @param string $metafield Datenbankfeld der Kategorie
- * @param mixed $value Wert für den Vergleich
- * @param string $type Art des Vergleichs =/</.
- * @param int|string $depth "" wenn auf allen Ebenen, wenn definiert, dann wird der Filter nur auf dieser Ebene angewendet
- */
- public function addFilter($metafield = 'id', $value = '1', $type = '=', $depth = '')
- {
- $this->filter[] = ['metafield' => $metafield, 'value' => $value, 'type' => $type, 'depth' => $depth];
- }
- public function getIterator()
- {
- $this->_setActivePath();
- if ($this->ignoreOfflines) {
- $this->addFilter('status', 1, '==');
- }
- yield from ($this->_getNavigation($this->startCategory));
- }
- private function _setActivePath()
- {
- $article_id = rex_article::getCurrentId();
- if (!$OOArt = rex_article::get($article_id)) {
- throw new Exception("Unable to determine current article-id");
- }
- $path = trim($OOArt->getPath(), '|');
- $this->path = [];
- if ($path != '') {
- $this->path = explode('|', $path);
- }
- $this->current_category_id = $OOArt->getCategoryId();
- }
- private function checkFilter(rex_category $category, $depth)
- {
- foreach ($this->filter as $f) {
- if ($f['depth'] == '' || $f['depth'] == $depth) {
- $mf = $category->getValue($f['metafield']);
- $va = $f['value'];
- switch ($f['type']) {
- case '<>':
- case '!=':
- if ($mf == $va) {
- return false;
- }
- break;
- case '>':
- if ($mf <= $va) {
- return false;
- }
- break;
- case '<':
- if ($mf >= $va) {
- return false;
- }
- break;
- case '=>':
- case '>=':
- if ($mf < $va) {
- return false;
- }
- break;
- case '=<':
- case '<=':
- if ($mf > $va) {
- return false;
- }
- break;
- case 'regex':
- if (!preg_match($va, $mf)) {
- return false;
- }
- break;
- case '=':
- case '==':
- default:
- // =
- if ($mf != $va) {
- return false;
- }
- }
- }
- }
- return true;
- }
- protected function _getNavigation($category_id, $depth = 1)
- {
- if ($category_id < 1) {
- $nav_obj = rex_category::getRootCategories();
- } else {
- $nav_obj = rex_category::get($category_id)->getChildren();
- }
- $checked = [];
- foreach ($nav_obj as $nav) {
- if ($this->checkFilter($nav, $depth)) {
- $checked[] = $nav;
- }
- }
- $nth = 1;
- foreach($checked as $nav) {
- if (!$this->activePath || $this->activePath && ($nav->getId() == $this->current_category_id || in_array($nav->getId(), $this->path))
- ) {
- yield [$nav, $depth, $nth, count($checked)];
- ++$depth;
- if ($this->depthLimit >= $depth || $this->depthLimit < 0) {
- yield from ($this->_getNavigation($nav->getId(), $depth));
- }
- --$depth;
- $nth++;
- }
- }
- }
- }
Add Comment
Please, Sign In to add comment