birzha/plugins/rainlab/pages/classes/Router.php

179 lines
5.1 KiB
PHP

<?php namespace RainLab\Pages\Classes;
use Lang;
use Cache;
use Event;
use Config;
use Cms\Classes\Theme;
use RainLab\Pages\Classes\Page;
use October\Rain\Support\Str;
use October\Rain\Router\Helper as RouterHelper;
/**
* A router for static pages.
*
* @package rainlab\pages
* @author Alexey Bobkov, Samuel Georges
*/
class Router
{
/**
* @var \Cms\Classes\Theme A reference to the CMS theme containing the object.
*/
protected $theme;
/**
* @var array Contains the URL map - the list of page file names and corresponding URL patterns.
*/
private static $urlMap = [];
/**
* @var array Request-level cache
*/
private static $cache = [];
/**
* Creates the router instance.
* @param \Cms\Classes\Theme $theme Specifies the theme being processed.
*/
public function __construct(Theme $theme)
{
$this->theme = $theme;
}
/**
* Finds a static page by its URL.
* @param string $url The requested URL string.
* @return \RainLab\Pages\Classes\Page Returns \RainLab\Pages\Classes\Page object or null if the page cannot be found.
*/
public function findByUrl($url)
{
$url = Str::lower(RouterHelper::normalizeUrl($url));
if (array_key_exists($url, self::$cache)) {
return self::$cache[$url];
}
$urlMap = $this->getUrlMap();
$urlMap = array_key_exists('urls', $urlMap) ? $urlMap['urls'] : [];
if (!array_key_exists($url, $urlMap)) {
return null;
}
$fileName = $urlMap[$url];
if (($page = Page::loadCached($this->theme, $fileName)) === null) {
/*
* If the page was not found on the disk, clear the URL cache
* and try again.
*/
$this->clearCache();
return self::$cache[$url] = Page::loadCached($this->theme, $fileName);
}
return self::$cache[$url] = $page;
}
/**
* Autoloads the URL map only allowing a single execution.
* @return array Returns the URL map.
*/
protected function getUrlMap()
{
if (!count(self::$urlMap)) {
$this->loadUrlMap();
}
return self::$urlMap;
}
/**
* 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', Config::get('cms.enable_route_cache', false));
$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) {
$comboConfig = Config::get('cms.urlCacheTtl', Config::get('cms.url_cache_ttl', 10));
$expiresAt = now()->addMinutes($comboConfig);
Cache::put($key, serialize($map), $expiresAt);
}
return false;
}
self::$urlMap = $unserialized;
return true;
}
/**
* Returns the caching URL key depending on the theme.
* @param string $keyName Specifies the base key name.
* @return string Returns the theme-specific key name.
*/
protected function getCacheKey($keyName)
{
$key = crc32($this->theme->getPath()).$keyName;
/**
* @event pages.router.getCacheKey
* Enables modifying the key used to reference cached RainLab.Pages routes
*
* Example usage:
*
* Event::listen('pages.router.getCacheKey', function (&$key) {
* $key = $key . '-' . App::getLocale();
* });
*
*/
Event::fire('pages.router.getCacheKey', [&$key]);
return $key;
}
/**
* Clears the router cache.
*/
public function clearCache()
{
Cache::forget($this->getCacheKey('static-page-url-map'));
}
}