/** * Builds and caches a menu item tree. * This method is used internally for menu items and breadcrumbs. * @param \Cms\Classes\Theme $theme Specifies the current theme. * @return array Returns an array containing the page information */ public static function buildMenuTree($theme) { if (self::$menuTreeCache !== null) { return self::$menuTreeCache; } $key = crc32($theme->getPath()) . 'static-page-menu-tree'; $cached = Cache::get($key, false); $unserialized = $cached ? @unserialize($cached) : false; if ($unserialized !== false) { return self::$menuTreeCache = $unserialized; } $menuTree = ['--root-pages--' => []]; $iterator = function ($items, $parent, $level) use(&$menuTree, &$iterator) { $result = []; foreach ($items as $item) { $viewBag = $item->page->getViewBag(); $pageCode = $item->page->getBaseFileName(); $itemData = ['url' => Str::lower(RouterHelper::normalizeUrl($viewBag->property('url'))), 'title' => $viewBag->property('title'), 'mtime' => $item->page->mtime, 'items' => $iterator($item->subpages, $pageCode, $level + 1), 'parent' => $parent, 'navigation_hidden' => $viewBag->property('navigation_hidden')]; if ($level == 0) { $menuTree['--root-pages--'][] = $pageCode; } $result[] = $pageCode; $menuTree[$pageCode] = $itemData; } return $result; }; $pageList = new PageList($theme); $iterator($pageList->getPageTree(), null, 0); self::$menuTreeCache = $menuTree; Cache::put($key, serialize($menuTree), Config::get('cms.parsedPageCacheTTL', 10)); return self::$menuTreeCache; }
/** * Loads the URL map - a list of page file names and corresponding URL patterns. * The URL map can is cached. The clearUrlMap() method resets the cache. By default * the map is updated every time when a page is saved in the back-end, or * when the interval defined with the cms.urlCacheTtl expires. * @return boolean Returns true if the URL map was loaded from the cache. Otherwise returns false. */ protected function loadUrlMap() { $key = $this->getCacheKey('static-page-url-map'); $cacheable = Config::get('cms.enableRoutesCache'); $cached = $cacheable ? Cache::get($key, false) : false; if (!$cached || ($unserialized = @unserialize($cached)) === false) { /* * The item doesn't exist in the cache, create the map */ $pageList = new PageList($this->theme); $pages = $pageList->listPages(); $map = ['urls' => [], 'files' => [], 'titles' => []]; foreach ($pages as $page) { $url = $page->getViewBag()->property('url'); if (!$url) { continue; } $url = Str::lower(RouterHelper::normalizeUrl($url)); $file = $page->getBaseFileName(); $map['urls'][$url] = $file; $map['files'][$file] = $url; $map['titles'][$file] = $page->getViewBag()->property('title'); } self::$urlMap = $map; if ($cacheable) { Cache::put($key, serialize($map), Config::get('cms.urlCacheTtl', 1)); } return false; } self::$urlMap = $unserialized; return true; }
/** * Returns the menu item references. * This function is used on the front-end. * @param Cms\Classes\Page $page The current page object. * @return array Returns an array of the \RainLab\Pages\Classes\MenuItemReference objects. */ public function generateReferences($page) { $currentUrl = Request::path(); if (!strlen($currentUrl)) { $currentUrl = '/'; } $currentUrl = Str::lower(URL::to($currentUrl)); $activeMenuItem = $page->activeMenuItem ?: false; $iterator = function ($items) use($currentUrl, &$iterator, $activeMenuItem) { $result = []; foreach ($items as $item) { $parentReference = new MenuItemReference(); $parentReference->title = $item->title; $parentReference->code = $item->code; $parentReference->viewBag = $item->viewBag; /* * If the item type is URL, assign the reference the item's URL and compare the current URL with the item URL * to determine whether the item is active. */ if ($item->type == 'url') { $parentReference->url = $item->url; $parentReference->isActive = $currentUrl == Str::lower($item->url) || $activeMenuItem === $item->code; } else { /* * If the item type is not URL, use the API to request the item type's provider to * return the item URL, subitems and determine whether the item is active. */ $apiResult = Event::fire('pages.menuitem.resolveItem', [$item->type, $item, $currentUrl, $this->theme]); if (is_array($apiResult)) { foreach ($apiResult as $itemInfo) { if (!is_array($itemInfo)) { continue; } if (!$item->replace && isset($itemInfo['url'])) { $parentReference->url = $itemInfo['url']; $parentReference->isActive = $itemInfo['isActive'] || $activeMenuItem === $item->code; } if (isset($itemInfo['items'])) { $itemIterator = function ($items) use(&$itemIterator, $parentReference) { $result = []; foreach ($items as $item) { $reference = new MenuItemReference(); $reference->title = isset($item['title']) ? $item['title'] : '--no title--'; $reference->url = isset($item['url']) ? $item['url'] : '#'; $reference->isActive = isset($item['isActive']) ? $item['isActive'] : false; if (!strlen($parentReference->url)) { $parentReference->url = $reference->url; $parentReference->isActive = $reference->isActive; } if (isset($item['items'])) { $reference->items = $itemIterator($item['items']); } $result[] = $reference; } return $result; }; $parentReference->items = $itemIterator($itemInfo['items']); } } } } if ($item->items) { $parentReference->items = $iterator($item->items); } if (!$item->replace) { $result[] = $parentReference; } else { foreach ($parentReference->items as $subItem) { $result[] = $subItem; } } } return $result; }; $items = $iterator($this->items); /* * Populate the isChildActive property */ $hasActiveChild = function ($items) use(&$hasActiveChild) { foreach ($items as $item) { if ($item->isActive) { return true; } $result = $hasActiveChild($item->items); if ($result) { return $result; } } }; $iterator = function ($items) use(&$iterator, &$hasActiveChild) { foreach ($items as $item) { $item->isChildActive = $hasActiveChild($item->items); $iterator($item->items); } }; $iterator($items); return $items; }
/** * Convert the given string to lower-case. * * @param string $value * @return string * @static */ public static function lower($value) { //Method inherited from \Illuminate\Support\Str return \October\Rain\Support\Str::lower($value); }