522 lines
9.2 KiB
PHP
522 lines
9.2 KiB
PHP
<?php
|
|
/**
|
|
* @package Joomla.Platform
|
|
* @subpackage Application
|
|
*
|
|
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
|
* @license GNU General Public License version 2 or later; see LICENSE
|
|
*/
|
|
|
|
defined('JPATH_PLATFORM') or die;
|
|
|
|
/**
|
|
* Set the available masks for the routing mode
|
|
*/
|
|
const JROUTER_MODE_RAW = 0;
|
|
const JROUTER_MODE_SEF = 1;
|
|
|
|
/**
|
|
* Class to create and parse routes
|
|
*
|
|
* @package Joomla.Platform
|
|
* @subpackage Application
|
|
* @since 11.1
|
|
*/
|
|
class JRouter
|
|
{
|
|
/**
|
|
* The rewrite mode
|
|
*
|
|
* @var integer
|
|
* @since 11.1
|
|
*/
|
|
protected $mode = null;
|
|
|
|
/**
|
|
* The rewrite mode
|
|
*
|
|
* @var integer
|
|
* @since 11.1
|
|
* @deprecated use $mode declare as private
|
|
*/
|
|
protected $_mode = null;
|
|
|
|
/**
|
|
* An array of variables
|
|
*
|
|
* @var array
|
|
* @since 11.1
|
|
*/
|
|
protected $vars = array();
|
|
|
|
/**
|
|
* An array of variables
|
|
*
|
|
* @var array
|
|
* @since 11.1
|
|
* @deprecated use $vars declare as private
|
|
*/
|
|
protected $_vars = array();
|
|
|
|
/**
|
|
* An array of rules
|
|
*
|
|
* @var array
|
|
* @since 11.1
|
|
*/
|
|
protected $rules = array(
|
|
'build' => array(),
|
|
'parse' => array()
|
|
);
|
|
|
|
/**
|
|
* An array of rules
|
|
*
|
|
* @var array
|
|
* @since 11.1
|
|
* @deprecated use $rules declare as private
|
|
*/
|
|
protected $_rules = array(
|
|
'build' => array(),
|
|
'parse' => array()
|
|
);
|
|
|
|
/**
|
|
* @var array JRouter instances container.
|
|
* @since 11.3
|
|
*/
|
|
protected static $instances = array();
|
|
|
|
/**
|
|
* Class constructor
|
|
*
|
|
* @param array $options Array of options
|
|
*
|
|
* @since 11.1
|
|
*/
|
|
public function __construct($options = array())
|
|
{
|
|
if (array_key_exists('mode', $options))
|
|
{
|
|
$this->_mode = $options['mode'];
|
|
}
|
|
else
|
|
{
|
|
$this->_mode = JROUTER_MODE_RAW;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the global JRouter object, only creating it if it
|
|
* doesn't already exist.
|
|
*
|
|
* @param string $client The name of the client
|
|
* @param array $options An associative array of options
|
|
*
|
|
* @return JRouter A JRouter object.
|
|
*
|
|
* @since 11.1
|
|
* @throws RuntimeException
|
|
*/
|
|
public static function getInstance($client, $options = array())
|
|
{
|
|
if (empty(self::$instances[$client]))
|
|
{
|
|
// Create a JRouter object
|
|
$classname = 'JRouter' . ucfirst($client);
|
|
|
|
if (!class_exists($classname))
|
|
{
|
|
JLog::add('Non-autoloadable JRouter subclasses are deprecated.', JLog::WARNING, 'deprecated');
|
|
|
|
// Load the router object
|
|
$info = JApplicationHelper::getClientInfo($client, true);
|
|
|
|
if (is_object($info))
|
|
{
|
|
$path = $info->path . '/includes/router.php';
|
|
|
|
if (file_exists($path))
|
|
{
|
|
include_once $path;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (class_exists($classname))
|
|
{
|
|
self::$instances[$client] = new $classname($options);
|
|
}
|
|
else
|
|
{
|
|
throw new RuntimeException(JText::sprintf('JLIB_APPLICATION_ERROR_ROUTER_LOAD', $client), 500);
|
|
}
|
|
}
|
|
|
|
return self::$instances[$client];
|
|
}
|
|
|
|
/**
|
|
* Function to convert a route to an internal URI
|
|
*
|
|
* @param JUri $uri The uri.
|
|
*
|
|
* @return array
|
|
*
|
|
* @since 11.1
|
|
*/
|
|
public function parse($uri)
|
|
{
|
|
// Process the parsed variables based on custom defined rules
|
|
$vars = $this->_processParseRules($uri);
|
|
|
|
// Parse RAW URL
|
|
if ($this->_mode == JROUTER_MODE_RAW)
|
|
{
|
|
$vars += $this->_parseRawRoute($uri);
|
|
}
|
|
|
|
// Parse SEF URL
|
|
if ($this->_mode == JROUTER_MODE_SEF)
|
|
{
|
|
$vars += $this->_parseSefRoute($uri);
|
|
}
|
|
|
|
return array_merge($this->getVars(), $vars);
|
|
}
|
|
|
|
/**
|
|
* Function to convert an internal URI to a route
|
|
*
|
|
* @param string $url The internal URL
|
|
*
|
|
* @return string The absolute search engine friendly URL
|
|
*
|
|
* @since 11.1
|
|
*/
|
|
public function build($url)
|
|
{
|
|
// Create the URI object
|
|
$uri = $this->_createURI($url);
|
|
|
|
// Process the uri information based on custom defined rules
|
|
$this->_processBuildRules($uri);
|
|
|
|
// Build RAW URL
|
|
if ($this->_mode == JROUTER_MODE_RAW)
|
|
{
|
|
$this->_buildRawRoute($uri);
|
|
}
|
|
|
|
// Build SEF URL : mysite/route/index.php?var=x
|
|
if ($this->_mode == JROUTER_MODE_SEF)
|
|
{
|
|
$this->_buildSefRoute($uri);
|
|
}
|
|
|
|
return $uri;
|
|
}
|
|
|
|
/**
|
|
* Get the router mode
|
|
*
|
|
* @return integer
|
|
*
|
|
* @since 11.1
|
|
*/
|
|
public function getMode()
|
|
{
|
|
return $this->_mode;
|
|
}
|
|
|
|
/**
|
|
* Set the router mode
|
|
*
|
|
* @param integer $mode The routing mode.
|
|
*
|
|
* @return void
|
|
*
|
|
* @since 11.1
|
|
*/
|
|
public function setMode($mode)
|
|
{
|
|
$this->_mode = $mode;
|
|
}
|
|
|
|
/**
|
|
* Set a router variable, creating it if it doesn't exist
|
|
*
|
|
* @param string $key The name of the variable
|
|
* @param mixed $value The value of the variable
|
|
* @param boolean $create If True, the variable will be created if it doesn't exist yet
|
|
*
|
|
* @return void
|
|
*
|
|
* @since 11.1
|
|
*/
|
|
public function setVar($key, $value, $create = true)
|
|
{
|
|
if ($create || array_key_exists($key, $this->_vars))
|
|
{
|
|
$this->_vars[$key] = $value;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set the router variable array
|
|
*
|
|
* @param array $vars An associative array with variables
|
|
* @param boolean $merge If True, the array will be merged instead of overwritten
|
|
*
|
|
* @return void
|
|
*
|
|
* @since 11.1
|
|
*/
|
|
public function setVars($vars = array(), $merge = true)
|
|
{
|
|
if ($merge)
|
|
{
|
|
$this->_vars = array_merge($this->_vars, $vars);
|
|
}
|
|
else
|
|
{
|
|
$this->_vars = $vars;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get a router variable
|
|
*
|
|
* @param string $key The name of the variable
|
|
*
|
|
* @return mixed Value of the variable
|
|
*
|
|
* @since 11.1
|
|
*/
|
|
public function getVar($key)
|
|
{
|
|
$result = null;
|
|
|
|
if (isset($this->_vars[$key]))
|
|
{
|
|
$result = $this->_vars[$key];
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Get the router variable array
|
|
*
|
|
* @return array An associative array of router variables
|
|
*
|
|
* @since 11.1
|
|
*/
|
|
public function getVars()
|
|
{
|
|
return $this->_vars;
|
|
}
|
|
|
|
/**
|
|
* Attach a build rule
|
|
*
|
|
* @param callback $callback The function to be called
|
|
*
|
|
* @return void
|
|
*
|
|
* @since 11.1.
|
|
*/
|
|
public function attachBuildRule($callback)
|
|
{
|
|
$this->_rules['build'][] = $callback;
|
|
}
|
|
|
|
/**
|
|
* Attach a parse rule
|
|
*
|
|
* @param callback $callback The function to be called.
|
|
*
|
|
* @return void
|
|
*
|
|
* @since 11.1
|
|
*/
|
|
public function attachParseRule($callback)
|
|
{
|
|
$this->_rules['parse'][] = $callback;
|
|
}
|
|
|
|
/**
|
|
* Function to convert a raw route to an internal URI
|
|
*
|
|
* @param JUri $uri The raw route
|
|
*
|
|
* @return boolean
|
|
*
|
|
* @since 11.1
|
|
*/
|
|
protected function _parseRawRoute($uri)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Function to convert a sef route to an internal URI
|
|
*
|
|
* @param JUri $uri The sef URI
|
|
*
|
|
* @return string Internal URI
|
|
*
|
|
* @since 11.1
|
|
*/
|
|
protected function _parseSefRoute($uri)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Function to build a raw route
|
|
*
|
|
* @param JUri $uri The internal URL
|
|
*
|
|
* @return string Raw Route
|
|
*
|
|
* @since 11.1
|
|
*/
|
|
protected function _buildRawRoute($uri)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Function to build a sef route
|
|
*
|
|
* @param JUri $uri The uri
|
|
*
|
|
* @return string The SEF route
|
|
*
|
|
* @since 11.1
|
|
*/
|
|
protected function _buildSefRoute($uri)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Process the parsed router variables based on custom defined rules
|
|
*
|
|
* @param JUri $uri The URI to parse
|
|
*
|
|
* @return array The array of processed URI variables
|
|
*
|
|
* @since 11.1
|
|
*/
|
|
protected function _processParseRules($uri)
|
|
{
|
|
$vars = array();
|
|
|
|
foreach ($this->_rules['parse'] as $rule)
|
|
{
|
|
$vars += call_user_func_array($rule, array(&$this, &$uri));
|
|
}
|
|
|
|
return $vars;
|
|
}
|
|
|
|
/**
|
|
* Process the build uri query data based on custom defined rules
|
|
*
|
|
* @param JUri $uri The URI
|
|
*
|
|
* @return void
|
|
*
|
|
* @since 11.1
|
|
*/
|
|
protected function _processBuildRules($uri)
|
|
{
|
|
foreach ($this->_rules['build'] as $rule)
|
|
{
|
|
call_user_func_array($rule, array(&$this, &$uri));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create a uri based on a full or partial url string
|
|
*
|
|
* @param string $url The URI
|
|
*
|
|
* @return JUri
|
|
*
|
|
* @since 11.1
|
|
*/
|
|
protected function _createURI($url)
|
|
{
|
|
// Create full URL if we are only appending variables to it
|
|
if (substr($url, 0, 1) == '&')
|
|
{
|
|
$vars = array();
|
|
|
|
if (strpos($url, '&') !== false)
|
|
{
|
|
$url = str_replace('&', '&', $url);
|
|
}
|
|
|
|
parse_str($url, $vars);
|
|
|
|
$vars = array_merge($this->getVars(), $vars);
|
|
|
|
foreach ($vars as $key => $var)
|
|
{
|
|
if ($var == "")
|
|
{
|
|
unset($vars[$key]);
|
|
}
|
|
}
|
|
|
|
$url = 'index.php?' . JUri::buildQuery($vars);
|
|
}
|
|
|
|
// Decompose link into url component parts
|
|
return new JUri($url);
|
|
}
|
|
|
|
/**
|
|
* Encode route segments
|
|
*
|
|
* @param array $segments An array of route segments
|
|
*
|
|
* @return array Array of encoded route segments
|
|
*
|
|
* @since 11.1
|
|
*/
|
|
protected function _encodeSegments($segments)
|
|
{
|
|
$total = count($segments);
|
|
|
|
for ($i = 0; $i < $total; $i++)
|
|
{
|
|
$segments[$i] = str_replace(':', '-', $segments[$i]);
|
|
}
|
|
|
|
return $segments;
|
|
}
|
|
|
|
/**
|
|
* Decode route segments
|
|
*
|
|
* @param array $segments An array of route segments
|
|
*
|
|
* @return array Array of decoded route segments
|
|
*
|
|
* @since 11.1
|
|
*/
|
|
protected function _decodeSegments($segments)
|
|
{
|
|
$total = count($segments);
|
|
|
|
for ($i = 0; $i < $total; $i++)
|
|
{
|
|
$segments[$i] = preg_replace('/-/', ':', $segments[$i], 1);
|
|
}
|
|
|
|
return $segments;
|
|
}
|
|
}
|