Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Branch: master
Fetching contributors…

Cannot retrieve contributors at this time

286 lines (240 sloc) 7.037 kB
<?php
Class Extension_Url_Router extends Extension{
private $_hasrun = false;
public function install()
{
Symphony::Database()->query("
CREATE TABLE IF NOT EXISTS `tbl_url_router` (
`id` int(11) NOT NULL auto_increment,
`from` varchar(255) NOT NULL,
`to` varchar(255) NOT NULL,
`type` enum('route','redirect') DEFAULT 'route',
`http301` enum('yes','no') DEFAULT 'no',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
");
}
public function fetchNavigation() {
return array(
array(
'location' => __('Blueprints'),
'name' => __('URL Routes'),
'link' => '/routes/'
)
);
}
public function uninstall()
{
return Symphony::Database()->query("DROP TABLE `tbl_url_router`");
}
public function getSubscribedDelegates()
{
return array(
array(
'page' => '/frontend/',
'delegate' => 'FrontendPrePageResolve',
'callback' => 'frontendPrePageResolve'
)
);
}
/**
* Get all routes
*
* @return Array Array of routes from the database
*/
public function getRoutes()
{
$routes = Symphony::Database()->fetch("SELECT * FROM tbl_url_router");
foreach ($routes as $i => $route)
{
preg_match_all('/[$:]([0-9a-zA-Z_]+)/', $route['from'], $names, PREG_PATTERN_ORDER);
$names = $names[0];
if (!$names) continue;
$new = preg_replace('/[$:][[0-9a-zA-Z_]+/', '([a-zA-Z0-9_\+\-%]+)', $route['from']);
$new = '/'. trim($new, '/');
$new = '/'. str_replace('/', "\/", $new);
$new .= '/i';
$to = $this->isExternal($route['to'])
? $route['to']
: '/'. trim($route['to'], '/');
foreach ($names as $k => $n)
$to = str_replace($n, '$'. ($k +1), $to);
$route['from-clean'] = $route['from'];
$route['to-clean'] = $route['to'];
$route['from'] = $new;
$route['to'] = $to;
$routes[$i] = $route;
}
return $routes;
}
/**
* Get the first route that matches the given path
*
* @param String $path Thepath to regex match on
*
* @return Array Array of matched page details
* @return Boolean False if no page matched
*/
public function getRoute($path)
{
$routes = $this->getRoutes();
$return = array();
foreach($routes as $route)
{
if(preg_match($route['from'], $path, $matches) == 1)
{
$route['routed'] = preg_replace($route['from'], $route['to'], $path);
$route['original'] = $path;
if($this->isExternal($route['to'])) {
$route['external'] = true;
$route['routed'] = rtrim($route['routed'], '/');
}
else {
$route['external'] = false;
}
$return = $route;
break;
}
}
return $return;
}
public function isExternal($route) {
return (strstr($route, 'http') !== false) ? true : false;
}
/**
* Filter out any params that are in the 'to' route as a querystring, unless the route contains 'http://'
* @param String $route The 'to' route as a string
* @return String the filtered string, or full string if it contains 'http://'
*/
public function filterGetParams($route) {
$return = $route;
if(strpos($route, '?')) {
$parts = preg_split('/(\?|&)/', $route);
$return = $parts[0];
unset($parts[0]);
foreach($parts as $part) {
if(!empty($part)) {
$bits = explode('=', $part);
$_GET[$bits[0]] = $bits[1];
}
}
}
return $return;
}
/**
* Save the routes from the preferences into the database
*
* @param unknown $context Symphony context
*/
public function saveRoutes()
{
$routes = array();
if(!empty($_POST['settings']['url-router']['routes']))
{
$route = array(
'type' => '',
'from' => '',
'to' => '',
'http301' => 'no'
);
foreach($_POST['settings']['url-router']['routes'] as $item)
{
if(isset($item['type']) && !empty($item['type']))
{
$route = array(
'type' => '',
'from' => '',
'to' => '',
'http301' => 'no'
);
$route['type'] = $item['type'];
}
if(isset($item['from']) && !empty($item['from']))
{
$route['from'] = $item['from'];
}
if(isset($item['to']) && !empty($item['to']))
{
$route['to'] = $item['to'];
$routes[] = $route;
}
if(isset($item['http301']) && !empty($item['http301']))
{
$key = count($routes) - 1;
$routes[$key]['http301'] = $item['http301'];
}
}
}
Symphony::Database()->query("DELETE FROM tbl_url_router");
if(count($routes) > 0) {
Symphony::Database()->insert($routes, "tbl_url_router");
unset($_POST['settings']['url-router']['routes']);
}
redirect(SYMPHONY_URL . '/extension/url_router/routes/index/saved/');
}
public function frontendPrePageResolve($context)
{
if(!$this->_hasrun)
{
// Prevent an infinity loop of delegate callbacks to this function - @creativedutchmen
$this->_hasrun = true;
// Used to check page resolution, would cause loop.
$frontend = Frontend::Page();
// Get route or empty array
$route = $this->getRoute($context['page']);
// Check whether the current page resolves as it is
$page_can_resolve = $frontend->resolvePage($context['page']);
if(!empty($route))
{
// If it is not an external route
if ($route['type'] == 'route' && $route['external'] === false) {
// Check to see what has already resolved.
if (isset($page_can_resolve['filelocation'])) {
// Remove the PAGES path, .xsl and replace any _ with /.
// Basically reconstruct the 'path' as if it was a URL request
$resolved_path = '/' . str_replace(
array(PAGES . '/', '.xsl', '_'),
array('', '', '/'),
$page_can_resolve['filelocation']
) . '/';
// Now does the page we're routing from already exist in Symphony? No? Redirect.
if (preg_match('~^' . preg_quote($resolved_path) . '~i', $route['original']) == false) {
$route['routed'] = $this->filterGetParams($route['routed']);
$context['page'] = $route['routed'];
}
}
// Nothing exists in Symphony, redirect.
else {
$route['routed'] = $this->filterGetParams($route['routed']);
$context['page'] = $route['routed'];
}
}
// If is redirect or an external route
elseif($route['type'] == 'redirect' || $route['external']) {
$context['page'] = $route['routed'];
$url = ($route['external'])
? $context['page']
: URL . $context['page'];
if($route['http301'] === 'yes')
{
header("Location:" . $url, true, 301);
}
else
{
header("Location:" . $url);
}
exit;
}
}
else
{
$index = PageManager::fetchPageByType('index');
if(!$page_can_resolve)
{
$context['page'] = "/" . $index['handle'] . $context['page'];
}
}
unset($frontend, $route, $page_can_resolve);
}
}
}
Jump to Line
Something went wrong with that request. Please try again.