You've already forked joomla_test
first commit
This commit is contained in:
516
libraries/joomla/application/web/client.php
Normal file
516
libraries/joomla/application/web/client.php
Normal file
@ -0,0 +1,516 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* Class to model a Web Client.
|
||||
*
|
||||
* @property-read integer $platform The detected platform on which the web client runs.
|
||||
* @property-read boolean $mobile True if the web client is a mobile device.
|
||||
* @property-read integer $engine The detected rendering engine used by the web client.
|
||||
* @property-read integer $browser The detected browser used by the web client.
|
||||
* @property-read string $browserVersion The detected browser version used by the web client.
|
||||
* @property-read array $languages The priority order detected accepted languages for the client.
|
||||
* @property-read array $encodings The priority order detected accepted encodings for the client.
|
||||
* @property-read string $userAgent The web client's user agent string.
|
||||
* @property-read string $acceptEncoding The web client's accepted encoding string.
|
||||
* @property-read string $acceptLanguage The web client's accepted languages string.
|
||||
* @property-read array $detection An array of flags determining whether or not a detection routine has been run.
|
||||
* @property-read boolean $robot True if the web client is a robot
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Application
|
||||
* @since 12.1
|
||||
*/
|
||||
class JApplicationWebClient
|
||||
{
|
||||
const WINDOWS = 1;
|
||||
const WINDOWS_PHONE = 2;
|
||||
const WINDOWS_CE = 3;
|
||||
const IPHONE = 4;
|
||||
const IPAD = 5;
|
||||
const IPOD = 6;
|
||||
const MAC = 7;
|
||||
const BLACKBERRY = 8;
|
||||
const ANDROID = 9;
|
||||
const LINUX = 10;
|
||||
const TRIDENT = 11;
|
||||
const WEBKIT = 12;
|
||||
const GECKO = 13;
|
||||
const PRESTO = 14;
|
||||
const KHTML = 15;
|
||||
const AMAYA = 16;
|
||||
const IE = 17;
|
||||
const FIREFOX = 18;
|
||||
const CHROME = 19;
|
||||
const SAFARI = 20;
|
||||
const OPERA = 21;
|
||||
const ANDROIDTABLET = 22;
|
||||
|
||||
/**
|
||||
* @var integer The detected platform on which the web client runs.
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $platform;
|
||||
|
||||
/**
|
||||
* @var boolean True if the web client is a mobile device.
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $mobile = false;
|
||||
|
||||
/**
|
||||
* @var integer The detected rendering engine used by the web client.
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $engine;
|
||||
|
||||
/**
|
||||
* @var integer The detected browser used by the web client.
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $browser;
|
||||
|
||||
/**
|
||||
* @var string The detected browser version used by the web client.
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $browserVersion;
|
||||
|
||||
/**
|
||||
* @var array The priority order detected accepted languages for the client.
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $languages = array();
|
||||
|
||||
/**
|
||||
* @var array The priority order detected accepted encodings for the client.
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $encodings = array();
|
||||
|
||||
/**
|
||||
* @var string The web client's user agent string.
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $userAgent;
|
||||
|
||||
/**
|
||||
* @var string The web client's accepted encoding string.
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $acceptEncoding;
|
||||
|
||||
/**
|
||||
* @var string The web client's accepted languages string.
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $acceptLanguage;
|
||||
|
||||
/**
|
||||
* @var boolean True if the web client is a robot.
|
||||
* @since 12.3
|
||||
*/
|
||||
protected $robot = false;
|
||||
|
||||
/**
|
||||
* @var array An array of flags determining whether or not a detection routine has been run.
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $detection = array();
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param string $userAgent The optional user-agent string to parse.
|
||||
* @param string $acceptEncoding The optional client accept encoding string to parse.
|
||||
* @param string $acceptLanguage The optional client accept language string to parse.
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
public function __construct($userAgent = null, $acceptEncoding = null, $acceptLanguage = null)
|
||||
{
|
||||
// If no explicit user agent string was given attempt to use the implicit one from server environment.
|
||||
if (empty($userAgent) && isset($_SERVER['HTTP_USER_AGENT']))
|
||||
{
|
||||
$this->userAgent = $_SERVER['HTTP_USER_AGENT'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->userAgent = $userAgent;
|
||||
}
|
||||
|
||||
// If no explicit acceptable encoding string was given attempt to use the implicit one from server environment.
|
||||
if (empty($acceptEncoding) && isset($_SERVER['HTTP_ACCEPT_ENCODING']))
|
||||
{
|
||||
$this->acceptEncoding = $_SERVER['HTTP_ACCEPT_ENCODING'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->acceptEncoding = $acceptEncoding;
|
||||
}
|
||||
|
||||
// If no explicit acceptable languages string was given attempt to use the implicit one from server environment.
|
||||
if (empty($acceptLanguage) && isset($_SERVER['HTTP_ACCEPT_LANGUAGE']))
|
||||
{
|
||||
$this->acceptLanguage = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->acceptLanguage = $acceptLanguage;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic method to get an object property's value by name.
|
||||
*
|
||||
* @param string $name Name of the property for which to return a value.
|
||||
*
|
||||
* @return mixed The requested value if it exists.
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
switch ($name)
|
||||
{
|
||||
case 'mobile':
|
||||
case 'platform':
|
||||
if (empty($this->detection['platform']))
|
||||
{
|
||||
$this->detectPlatform($this->userAgent);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'engine':
|
||||
if (empty($this->detection['engine']))
|
||||
{
|
||||
$this->detectEngine($this->userAgent);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'browser':
|
||||
case 'browserVersion':
|
||||
if (empty($this->detection['browser']))
|
||||
{
|
||||
$this->detectBrowser($this->userAgent);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'languages':
|
||||
if (empty($this->detection['acceptLanguage']))
|
||||
{
|
||||
$this->detectLanguage($this->acceptLanguage);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'encodings':
|
||||
if (empty($this->detection['acceptEncoding']))
|
||||
{
|
||||
$this->detectEncoding($this->acceptEncoding);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'robot':
|
||||
if (empty($this->detection['robot']))
|
||||
{
|
||||
$this->detectRobot($this->userAgent);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Return the property if it exists.
|
||||
if (isset($this->$name))
|
||||
{
|
||||
return $this->$name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects the client browser and version in a user agent string.
|
||||
*
|
||||
* @param string $userAgent The user-agent string to parse.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
protected function detectBrowser($userAgent)
|
||||
{
|
||||
// Attempt to detect the browser type. Obviously we are only worried about major browsers.
|
||||
if ((stripos($userAgent, 'MSIE') !== false) && (stripos($userAgent, 'Opera') === false))
|
||||
{
|
||||
$this->browser = self::IE;
|
||||
$patternBrowser = 'MSIE';
|
||||
}
|
||||
elseif ((stripos($userAgent, 'Firefox') !== false) && (stripos($userAgent, 'like Firefox') === false))
|
||||
{
|
||||
$this->browser = self::FIREFOX;
|
||||
$patternBrowser = 'Firefox';
|
||||
}
|
||||
elseif (stripos($userAgent, 'Chrome') !== false)
|
||||
{
|
||||
$this->browser = self::CHROME;
|
||||
$patternBrowser = 'Chrome';
|
||||
}
|
||||
elseif (stripos($userAgent, 'Safari') !== false)
|
||||
{
|
||||
$this->browser = self::SAFARI;
|
||||
$patternBrowser = 'Safari';
|
||||
}
|
||||
elseif (stripos($userAgent, 'Opera') !== false)
|
||||
{
|
||||
$this->browser = self::OPERA;
|
||||
$patternBrowser = 'Opera';
|
||||
}
|
||||
|
||||
// If we detected a known browser let's attempt to determine the version.
|
||||
if ($this->browser)
|
||||
{
|
||||
// Build the REGEX pattern to match the browser version string within the user agent string.
|
||||
$pattern = '#(?<browser>Version|' . $patternBrowser . ')[/ ]+(?<version>[0-9.|a-zA-Z.]*)#';
|
||||
|
||||
// Attempt to find version strings in the user agent string.
|
||||
$matches = array();
|
||||
|
||||
if (preg_match_all($pattern, $userAgent, $matches))
|
||||
{
|
||||
// Do we have both a Version and browser match?
|
||||
if (count($matches['browser']) == 2)
|
||||
{
|
||||
// See whether Version or browser came first, and use the number accordingly.
|
||||
if (strripos($userAgent, 'Version') < strripos($userAgent, $patternBrowser))
|
||||
{
|
||||
$this->browserVersion = $matches['version'][0];
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->browserVersion = $matches['version'][1];
|
||||
}
|
||||
}
|
||||
elseif (count($matches['browser']) > 2)
|
||||
{
|
||||
$key = array_search('Version', $matches['browser']);
|
||||
|
||||
if ($key)
|
||||
{
|
||||
$this->browserVersion = $matches['version'][$key];
|
||||
}
|
||||
}
|
||||
// We only have a Version or a browser so use what we have.
|
||||
else
|
||||
{
|
||||
$this->browserVersion = $matches['version'][0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Mark this detection routine as run.
|
||||
$this->detection['browser'] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to detect the accepted response encoding by the client.
|
||||
*
|
||||
* @param string $acceptEncoding The client accept encoding string to parse.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
protected function detectEncoding($acceptEncoding)
|
||||
{
|
||||
// Parse the accepted encodings.
|
||||
$this->encodings = array_map('trim', (array) explode(',', $acceptEncoding));
|
||||
|
||||
// Mark this detection routine as run.
|
||||
$this->detection['acceptEncoding'] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects the client rendering engine in a user agent string.
|
||||
*
|
||||
* @param string $userAgent The user-agent string to parse.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
protected function detectEngine($userAgent)
|
||||
{
|
||||
// Attempt to detect the client engine -- starting with the most popular ... for now.
|
||||
if (stripos($userAgent, 'MSIE') !== false || stripos($userAgent, 'Trident') !== false)
|
||||
{
|
||||
$this->engine = self::TRIDENT;
|
||||
}
|
||||
// Evidently blackberry uses WebKit and doesn't necessarily report it. Bad RIM.
|
||||
elseif (stripos($userAgent, 'AppleWebKit') !== false || stripos($userAgent, 'blackberry') !== false)
|
||||
{
|
||||
$this->engine = self::WEBKIT;
|
||||
}
|
||||
// We have to check for like Gecko because some other browsers spoof Gecko.
|
||||
elseif (stripos($userAgent, 'Gecko') !== false && stripos($userAgent, 'like Gecko') === false)
|
||||
{
|
||||
$this->engine = self::GECKO;
|
||||
}
|
||||
// Sometimes Opera browsers don't say Presto.
|
||||
elseif (stripos($userAgent, 'Opera') !== false || stripos($userAgent, 'Presto') !== false)
|
||||
{
|
||||
$this->engine = self::PRESTO;
|
||||
}
|
||||
// *sigh*
|
||||
elseif (stripos($userAgent, 'KHTML') !== false)
|
||||
{
|
||||
$this->engine = self::KHTML;
|
||||
}
|
||||
// Lesser known engine but it finishes off the major list from Wikipedia :-)
|
||||
elseif (stripos($userAgent, 'Amaya') !== false)
|
||||
{
|
||||
$this->engine = self::AMAYA;
|
||||
}
|
||||
|
||||
// Mark this detection routine as run.
|
||||
$this->detection['engine'] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to detect the accepted languages by the client.
|
||||
*
|
||||
* @param mixed $acceptLanguage The client accept language string to parse.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
protected function detectLanguage($acceptLanguage)
|
||||
{
|
||||
// Parse the accepted encodings.
|
||||
$this->languages = array_map('trim', (array) explode(',', $acceptLanguage));
|
||||
|
||||
// Mark this detection routine as run.
|
||||
$this->detection['acceptLanguage'] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects the client platform in a user agent string.
|
||||
*
|
||||
* @param string $userAgent The user-agent string to parse.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
protected function detectPlatform($userAgent)
|
||||
{
|
||||
// Attempt to detect the client platform.
|
||||
if (stripos($userAgent, 'Windows') !== false)
|
||||
{
|
||||
$this->platform = self::WINDOWS;
|
||||
|
||||
// Let's look at the specific mobile options in the Windows space.
|
||||
if (stripos($userAgent, 'Windows Phone') !== false)
|
||||
{
|
||||
$this->mobile = true;
|
||||
$this->platform = self::WINDOWS_PHONE;
|
||||
}
|
||||
elseif (stripos($userAgent, 'Windows CE') !== false)
|
||||
{
|
||||
$this->mobile = true;
|
||||
$this->platform = self::WINDOWS_CE;
|
||||
}
|
||||
}
|
||||
// Interestingly 'iPhone' is present in all iOS devices so far including iPad and iPods.
|
||||
elseif (stripos($userAgent, 'iPhone') !== false)
|
||||
{
|
||||
$this->mobile = true;
|
||||
$this->platform = self::IPHONE;
|
||||
|
||||
// Let's look at the specific mobile options in the iOS space.
|
||||
if (stripos($userAgent, 'iPad') !== false)
|
||||
{
|
||||
$this->platform = self::IPAD;
|
||||
}
|
||||
elseif (stripos($userAgent, 'iPod') !== false)
|
||||
{
|
||||
$this->platform = self::IPOD;
|
||||
}
|
||||
}
|
||||
// In case where iPhone is not mentioed in iPad user agent string
|
||||
elseif (stripos($userAgent, 'iPad') !== false)
|
||||
{
|
||||
$this->mobile = true;
|
||||
$this->platform = self::IPAD;
|
||||
}
|
||||
// In case where iPhone is not mentioed in iPod user agent string
|
||||
elseif (stripos($userAgent, 'iPod') !== false)
|
||||
{
|
||||
$this->mobile = true;
|
||||
$this->platform = self::IPOD;
|
||||
}
|
||||
// This has to come after the iPhone check because mac strings are also present in iOS devices.
|
||||
elseif (preg_match('/macintosh|mac os x/i', $userAgent))
|
||||
{
|
||||
$this->platform = self::MAC;
|
||||
}
|
||||
elseif (stripos($userAgent, 'Blackberry') !== false)
|
||||
{
|
||||
$this->mobile = true;
|
||||
$this->platform = self::BLACKBERRY;
|
||||
}
|
||||
elseif (stripos($userAgent, 'Android') !== false)
|
||||
{
|
||||
$this->mobile = true;
|
||||
$this->platform = self::ANDROID;
|
||||
/**
|
||||
* Attempt to distinguish between Android phones and tablets
|
||||
* There is no totally foolproof method but certain rules almost always hold
|
||||
* Android 3.x is only used for tablets
|
||||
* Some devices and browsers encourage users to change their UA string to include Tablet.
|
||||
* Google encourages manufacturers to exclude the string Mobile from tablet device UA strings.
|
||||
* In some modes Kindle Android devices include the string Mobile but they include the string Silk.
|
||||
*/
|
||||
if (stripos($userAgent, 'Android 3') !== false || stripos($userAgent, 'Tablet') !== false
|
||||
|| stripos($userAgent, 'Mobile') === false || stripos($userAgent, 'Silk') !== false )
|
||||
{
|
||||
$this->platform = self::ANDROIDTABLET;
|
||||
}
|
||||
}
|
||||
elseif (stripos($userAgent, 'Linux') !== false)
|
||||
{
|
||||
$this->platform = self::LINUX;
|
||||
}
|
||||
|
||||
// Mark this detection routine as run.
|
||||
$this->detection['platform'] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the browser is a robot or not.
|
||||
*
|
||||
* @param string $userAgent The user-agent string to parse.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 12.3
|
||||
*/
|
||||
protected function detectRobot($userAgent)
|
||||
{
|
||||
if (preg_match('/http|bot|robot|spider|crawler|curl|^$/i', $userAgent))
|
||||
{
|
||||
$this->robot = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->robot = false;
|
||||
}
|
||||
|
||||
$this->detection['robot'] = true;
|
||||
}
|
||||
}
|
1
libraries/joomla/application/web/index.html
Normal file
1
libraries/joomla/application/web/index.html
Normal file
@ -0,0 +1 @@
|
||||
<!DOCTYPE html><title></title>
|
153
libraries/joomla/application/web/router.php
Normal file
153
libraries/joomla/application/web/router.php
Normal file
@ -0,0 +1,153 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* Class to define an abstract Web application router.
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Application
|
||||
* @since 12.2
|
||||
*/
|
||||
abstract class JApplicationWebRouter
|
||||
{
|
||||
/**
|
||||
* @var JApplicationWeb The web application on whose behalf we are routing the request.
|
||||
* @since 12.2
|
||||
*/
|
||||
protected $app;
|
||||
|
||||
/**
|
||||
* @var string The default page controller name for an empty route.
|
||||
* @since 12.2
|
||||
*/
|
||||
protected $default;
|
||||
|
||||
/**
|
||||
* @var string Controller class name prefix for creating controller objects by name.
|
||||
* @since 12.2
|
||||
*/
|
||||
protected $controllerPrefix;
|
||||
|
||||
/**
|
||||
* @var JInput An input object from which to derive the route.
|
||||
* @since 12.2
|
||||
*/
|
||||
protected $input;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param JApplicationWeb $app The web application on whose behalf we are routing the request.
|
||||
* @param JInput $input An optional input object from which to derive the route. If none
|
||||
* is given than the input from the application object will be used.
|
||||
*
|
||||
* @since 12.2
|
||||
*/
|
||||
public function __construct(JApplicationWeb $app, JInput $input = null)
|
||||
{
|
||||
$this->app = $app;
|
||||
$this->input = ($input === null) ? $this->app->input : $input;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find and execute the appropriate controller based on a given route.
|
||||
*
|
||||
* @param string $route The route string for which to find and execute a controller.
|
||||
*
|
||||
* @return mixed The return value of the controller executed
|
||||
*
|
||||
* @since 12.2
|
||||
* @throws InvalidArgumentException
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function execute($route)
|
||||
{
|
||||
// Get the controller name based on the route patterns and requested route.
|
||||
$name = $this->parseRoute($route);
|
||||
|
||||
// Get the controller object by name.
|
||||
$controller = $this->fetchController($name);
|
||||
|
||||
// Execute the controller.
|
||||
return $controller->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the controller name prefix.
|
||||
*
|
||||
* @param string $prefix Controller class name prefix for creating controller objects by name.
|
||||
*
|
||||
* @return JApplicationWebRouter This object for method chaining.
|
||||
*
|
||||
* @since 12.2
|
||||
*/
|
||||
public function setControllerPrefix($prefix)
|
||||
{
|
||||
$this->controllerPrefix = (string) $prefix;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default controller name.
|
||||
*
|
||||
* @param string $name The default page controller name for an empty route.
|
||||
*
|
||||
* @return JApplicationWebRouter This object for method chaining.
|
||||
*
|
||||
* @since 12.2
|
||||
*/
|
||||
public function setDefaultController($name)
|
||||
{
|
||||
$this->default = (string) $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given route and return the name of a controller mapped to the given route.
|
||||
*
|
||||
* @param string $route The route string for which to find and execute a controller.
|
||||
*
|
||||
* @return string The controller name for the given route excluding prefix.
|
||||
*
|
||||
* @since 12.2
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
abstract protected function parseRoute($route);
|
||||
|
||||
/**
|
||||
* Get a JController object for a given name.
|
||||
*
|
||||
* @param string $name The controller name (excluding prefix) for which to fetch and instance.
|
||||
*
|
||||
* @return JController
|
||||
*
|
||||
* @since 12.2
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
protected function fetchController($name)
|
||||
{
|
||||
// Derive the controller class name.
|
||||
$class = $this->controllerPrefix . ucfirst($name);
|
||||
|
||||
// If the controller class does not exist panic.
|
||||
if (!class_exists($class) || !is_subclass_of($class, 'JController'))
|
||||
{
|
||||
throw new RuntimeException(sprintf('Unable to locate controller `%s`.', $class), 404);
|
||||
}
|
||||
|
||||
// Instantiate the controller.
|
||||
$controller = new $class($this->input, $this->app);
|
||||
|
||||
return $controller;
|
||||
}
|
||||
}
|
177
libraries/joomla/application/web/router/base.php
Normal file
177
libraries/joomla/application/web/router/base.php
Normal file
@ -0,0 +1,177 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* Basic Web application router class for the Joomla Platform.
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Application
|
||||
* @since 12.2
|
||||
*/
|
||||
class JApplicationWebRouterBase extends JApplicationWebRouter
|
||||
{
|
||||
/**
|
||||
* @var array An array of rules, each rule being an associative array('regex'=> $regex, 'vars' => $vars, 'controller' => $controller)
|
||||
* for routing the request.
|
||||
* @since 12.2
|
||||
*/
|
||||
protected $maps = array();
|
||||
|
||||
/**
|
||||
* Add a route map to the router. If the pattern already exists it will be overwritten.
|
||||
*
|
||||
* @param string $pattern The route pattern to use for matching.
|
||||
* @param string $controller The controller name to map to the given pattern.
|
||||
*
|
||||
* @return JApplicationWebRouter This object for method chaining.
|
||||
*
|
||||
* @since 12.2
|
||||
*/
|
||||
public function addMap($pattern, $controller)
|
||||
{
|
||||
// Sanitize and explode the pattern.
|
||||
$pattern = explode('/', trim(parse_url((string) $pattern, PHP_URL_PATH), ' /'));
|
||||
|
||||
// Prepare the route variables
|
||||
$vars = array();
|
||||
|
||||
// Initialize regular expression
|
||||
$regex = array();
|
||||
|
||||
// Loop on each segment
|
||||
foreach ($pattern as $segment)
|
||||
{
|
||||
// Match a splat with no variable.
|
||||
if ($segment == '*')
|
||||
{
|
||||
$regex[] = '.*';
|
||||
}
|
||||
// Match a splat and capture the data to a named variable.
|
||||
elseif ($segment[0] == '*')
|
||||
{
|
||||
$vars[] = substr($segment, 1);
|
||||
$regex[] = '(.*)';
|
||||
}
|
||||
// Match an escaped splat segment.
|
||||
elseif ($segment[0] == '\\' && $segment[1] == '*')
|
||||
{
|
||||
$regex[] = '\*' . preg_quote(substr($segment, 2));
|
||||
}
|
||||
// Match an unnamed variable without capture.
|
||||
elseif ($segment == ':')
|
||||
{
|
||||
$regex[] = '[^/]*';
|
||||
}
|
||||
// Match a named variable and capture the data.
|
||||
elseif ($segment[0] == ':')
|
||||
{
|
||||
$vars[] = substr($segment, 1);
|
||||
$regex[] = '([^/]*)';
|
||||
}
|
||||
// Match a segment with an escaped variable character prefix.
|
||||
elseif ($segment[0] == '\\' && $segment[1] == ':')
|
||||
{
|
||||
$regex[] = preg_quote(substr($segment, 1));
|
||||
}
|
||||
// Match the standard segment.
|
||||
else
|
||||
{
|
||||
$regex[] = preg_quote($segment);
|
||||
}
|
||||
}
|
||||
|
||||
$this->maps[] = array(
|
||||
'regex' => chr(1) . '^' . implode('/', $regex) . '$' . chr(1),
|
||||
'vars' => $vars,
|
||||
'controller' => (string) $controller
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a route map to the router. If the pattern already exists it will be overwritten.
|
||||
*
|
||||
* @param array $maps A list of route maps to add to the router as $pattern => $controller.
|
||||
*
|
||||
* @return JApplicationWebRouter This object for method chaining.
|
||||
*
|
||||
* @since 12.2
|
||||
*/
|
||||
public function addMaps($maps)
|
||||
{
|
||||
foreach ($maps as $pattern => $controller)
|
||||
{
|
||||
$this->addMap($pattern, $controller);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given route and return the name of a controller mapped to the given route.
|
||||
*
|
||||
* @param string $route The route string for which to find and execute a controller.
|
||||
*
|
||||
* @return string The controller name for the given route excluding prefix.
|
||||
*
|
||||
* @since 12.2
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
protected function parseRoute($route)
|
||||
{
|
||||
$controller = false;
|
||||
|
||||
// Trim the query string off.
|
||||
$route = preg_replace('/([^?]*).*/u', '\1', $route);
|
||||
|
||||
// Sanitize and explode the route.
|
||||
$route = trim(parse_url($route, PHP_URL_PATH), ' /');
|
||||
|
||||
// If the route is empty then simply return the default route. No parsing necessary.
|
||||
if ($route == '')
|
||||
{
|
||||
return $this->default;
|
||||
}
|
||||
|
||||
// Iterate through all of the known route maps looking for a match.
|
||||
foreach ($this->maps as $rule)
|
||||
{
|
||||
if (preg_match($rule['regex'], $route, $matches))
|
||||
{
|
||||
// If we have gotten this far then we have a positive match.
|
||||
$controller = $rule['controller'];
|
||||
|
||||
// Time to set the input variables.
|
||||
// We are only going to set them if they don't already exist to avoid overwriting things.
|
||||
foreach ($rule['vars'] as $i => $var)
|
||||
{
|
||||
$this->input->def($var, $matches[$i + 1]);
|
||||
|
||||
// Don't forget to do an explicit set on the GET superglobal.
|
||||
$this->input->get->def($var, $matches[$i + 1]);
|
||||
}
|
||||
|
||||
$this->input->def('_rawRoute', $route);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// We were unable to find a route match for the request. Panic.
|
||||
if (!$controller)
|
||||
{
|
||||
throw new InvalidArgumentException(sprintf('Unable to handle request for route `%s`.', $route), 404);
|
||||
}
|
||||
|
||||
return $controller;
|
||||
}
|
||||
}
|
1
libraries/joomla/application/web/router/index.html
Normal file
1
libraries/joomla/application/web/router/index.html
Normal file
@ -0,0 +1 @@
|
||||
<!DOCTYPE html><title></title>
|
142
libraries/joomla/application/web/router/rest.php
Normal file
142
libraries/joomla/application/web/router/rest.php
Normal file
@ -0,0 +1,142 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* RESTful Web application router class for the Joomla Platform.
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Application
|
||||
* @since 12.2
|
||||
*/
|
||||
class JApplicationWebRouterRest extends JApplicationWebRouterBase
|
||||
{
|
||||
/**
|
||||
* @var boolean A boolean allowing to pass _method as parameter in POST requests
|
||||
*
|
||||
* @since 12.2
|
||||
*/
|
||||
protected $methodInPostRequest = false;
|
||||
|
||||
/**
|
||||
* @var array An array of HTTP Method => controller suffix pairs for routing the request.
|
||||
* @since 12.2
|
||||
*/
|
||||
protected $suffixMap = array(
|
||||
'GET' => 'Get',
|
||||
'POST' => 'Create',
|
||||
'PUT' => 'Update',
|
||||
'PATCH' => 'Update',
|
||||
'DELETE' => 'Delete',
|
||||
'HEAD' => 'Head',
|
||||
'OPTIONS' => 'Options'
|
||||
);
|
||||
|
||||
/**
|
||||
* Find and execute the appropriate controller based on a given route.
|
||||
*
|
||||
* @param string $route The route string for which to find and execute a controller.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 12.2
|
||||
* @throws InvalidArgumentException
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function execute($route)
|
||||
{
|
||||
// Get the controller name based on the route patterns and requested route.
|
||||
$name = $this->parseRoute($route);
|
||||
|
||||
// Append the HTTP method based suffix.
|
||||
$name .= $this->fetchControllerSuffix();
|
||||
|
||||
// Get the controller object by name.
|
||||
$controller = $this->fetchController($name);
|
||||
|
||||
// Execute the controller.
|
||||
$controller->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a controller class suffix for a given HTTP method.
|
||||
*
|
||||
* @param string $method The HTTP method for which to set the class suffix.
|
||||
* @param string $suffix The class suffix to use when fetching the controller name for a given request.
|
||||
*
|
||||
* @return JApplicationWebRouter This object for method chaining.
|
||||
*
|
||||
* @since 12.2
|
||||
*/
|
||||
public function setHttpMethodSuffix($method, $suffix)
|
||||
{
|
||||
$this->suffixMap[strtoupper((string) $method)] = (string) $suffix;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to allow or not method in POST request
|
||||
*
|
||||
* @param boolean $value A boolean to allow or not method in POST request
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 12.2
|
||||
*/
|
||||
public function setMethodInPostRequest($value)
|
||||
{
|
||||
$this->methodInPostRequest = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the property to allow or not method in POST request
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 12.2
|
||||
*/
|
||||
public function isMethodInPostRequest()
|
||||
{
|
||||
return $this->methodInPostRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the controller class suffix string.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 12.2
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
protected function fetchControllerSuffix()
|
||||
{
|
||||
// Validate that we have a map to handle the given HTTP method.
|
||||
if (!isset($this->suffixMap[$this->input->getMethod()]))
|
||||
{
|
||||
throw new RuntimeException(sprintf('Unable to support the HTTP method `%s`.', $this->input->getMethod()), 404);
|
||||
}
|
||||
|
||||
// Check if request method is POST
|
||||
if ( $this->methodInPostRequest == true && strcmp(strtoupper($this->input->server->getMethod()), 'POST') === 0)
|
||||
{
|
||||
// Get the method from input
|
||||
$postMethod = $this->input->get->getWord('_method');
|
||||
|
||||
// Validate that we have a map to handle the given HTTP method from input
|
||||
if ($postMethod && isset($this->suffixMap[strtoupper($postMethod)]))
|
||||
{
|
||||
return ucfirst($this->suffixMap[strtoupper($postMethod)]);
|
||||
}
|
||||
}
|
||||
|
||||
return ucfirst($this->suffixMap[$this->input->getMethod()]);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user