You've already forked joomla_test
first commit
This commit is contained in:
151
libraries/joomla/application/base.php
Normal file
151
libraries/joomla/application/base.php
Normal file
@ -0,0 +1,151 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* Joomla Platform Base Application Class
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Application
|
||||
* @since 12.1
|
||||
*/
|
||||
abstract class JApplicationBase
|
||||
{
|
||||
/**
|
||||
* The application dispatcher object.
|
||||
*
|
||||
* @var JEventDispatcher
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $dispatcher;
|
||||
|
||||
/**
|
||||
* The application identity object.
|
||||
*
|
||||
* @var JUser
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $identity;
|
||||
|
||||
/**
|
||||
* The application input object.
|
||||
*
|
||||
* @var JInput
|
||||
* @since 12.1
|
||||
*/
|
||||
public $input = null;
|
||||
|
||||
/**
|
||||
* Method to close the application.
|
||||
*
|
||||
* @param integer $code The exit code (optional; default is 0).
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @since 12.1
|
||||
*/
|
||||
public function close($code = 0)
|
||||
{
|
||||
exit($code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the application identity.
|
||||
*
|
||||
* @return mixed A JUser object or null.
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
public function getIdentity()
|
||||
{
|
||||
return $this->identity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a handler to a particular event group.
|
||||
*
|
||||
* @param string $event The event name.
|
||||
* @param callable $handler The handler, a function or an instance of a event object.
|
||||
*
|
||||
* @return JApplicationBase The application to allow chaining.
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
public function registerEvent($event, $handler)
|
||||
{
|
||||
if ($this->dispatcher instanceof JEventDispatcher)
|
||||
{
|
||||
$this->dispatcher->register($event, $handler);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls all handlers associated with an event group.
|
||||
*
|
||||
* @param string $event The event name.
|
||||
* @param array $args An array of arguments (optional).
|
||||
*
|
||||
* @return array An array of results from each function call, or null if no dispatcher is defined.
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
public function triggerEvent($event, array $args = null)
|
||||
{
|
||||
if ($this->dispatcher instanceof JEventDispatcher)
|
||||
{
|
||||
return $this->dispatcher->trigger($event, $args);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the application to load a custom or default dispatcher.
|
||||
*
|
||||
* The logic and options for creating this object are adequately generic for default cases
|
||||
* but for many applications it will make sense to override this method and create event
|
||||
* dispatchers, if required, based on more specific needs.
|
||||
*
|
||||
* @param JEventDispatcher $dispatcher An optional dispatcher object. If omitted, the factory dispatcher is created.
|
||||
*
|
||||
* @return JApplicationBase This method is chainable.
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
public function loadDispatcher(JEventDispatcher $dispatcher = null)
|
||||
{
|
||||
$this->dispatcher = ($dispatcher === null) ? JEventDispatcher::getInstance() : $dispatcher;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the application to load a custom or default identity.
|
||||
*
|
||||
* The logic and options for creating this object are adequately generic for default cases
|
||||
* but for many applications it will make sense to override this method and create an identity,
|
||||
* if required, based on more specific needs.
|
||||
*
|
||||
* @param JUser $identity An optional identity object. If omitted, the factory user is created.
|
||||
*
|
||||
* @return JApplicationBase This method is chainable.
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
public function loadIdentity(JUser $identity = null)
|
||||
{
|
||||
$this->identity = ($identity === null) ? JFactory::getUser() : $identity;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
294
libraries/joomla/application/cli.php
Normal file
294
libraries/joomla/application/cli.php
Normal file
@ -0,0 +1,294 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* Base class for a Joomla! command line application.
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Application
|
||||
* @since 11.4
|
||||
*/
|
||||
class JApplicationCli extends JApplicationBase
|
||||
{
|
||||
/**
|
||||
* @var JRegistry The application configuration object.
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @var JApplicationCli The application instance.
|
||||
* @since 11.1
|
||||
*/
|
||||
protected static $instance;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param mixed $input An optional argument to provide dependency injection for the application's
|
||||
* input object. If the argument is a JInputCli object that object will become
|
||||
* the application's input object, otherwise a default input object is created.
|
||||
* @param mixed $config An optional argument to provide dependency injection for the application's
|
||||
* config object. If the argument is a JRegistry object that object will become
|
||||
* the application's config object, otherwise a default config object is created.
|
||||
* @param mixed $dispatcher An optional argument to provide dependency injection for the application's
|
||||
* event dispatcher. If the argument is a JEventDispatcher object that object will become
|
||||
* the application's event dispatcher, if it is null then the default event dispatcher
|
||||
* will be created based on the application's loadDispatcher() method.
|
||||
*
|
||||
* @see loadDispatcher()
|
||||
* @since 11.1
|
||||
*/
|
||||
public function __construct(JInputCli $input = null, JRegistry $config = null, JEventDispatcher $dispatcher = null)
|
||||
{
|
||||
// Close the application if we are not executed from the command line.
|
||||
// @codeCoverageIgnoreStart
|
||||
if (!defined('STDOUT') || !defined('STDIN') || !isset($_SERVER['argv']))
|
||||
{
|
||||
$this->close();
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
// If a input object is given use it.
|
||||
if ($input instanceof JInput)
|
||||
{
|
||||
$this->input = $input;
|
||||
}
|
||||
// Create the input based on the application logic.
|
||||
else
|
||||
{
|
||||
if (class_exists('JInput'))
|
||||
{
|
||||
$this->input = new JInputCLI;
|
||||
}
|
||||
}
|
||||
|
||||
// If a config object is given use it.
|
||||
if ($config instanceof JRegistry)
|
||||
{
|
||||
$this->config = $config;
|
||||
}
|
||||
// Instantiate a new configuration object.
|
||||
else
|
||||
{
|
||||
$this->config = new JRegistry;
|
||||
}
|
||||
|
||||
$this->loadDispatcher($dispatcher);
|
||||
|
||||
// Load the configuration object.
|
||||
$this->loadConfiguration($this->fetchConfigurationData());
|
||||
|
||||
// Set the execution datetime and timestamp;
|
||||
$this->set('execution.datetime', gmdate('Y-m-d H:i:s'));
|
||||
$this->set('execution.timestamp', time());
|
||||
|
||||
// Set the current directory.
|
||||
$this->set('cwd', getcwd());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a property of the object or the default value if the property is not set.
|
||||
*
|
||||
* @param string $key The name of the property.
|
||||
* @param mixed $default The default value (optional) if none is set.
|
||||
*
|
||||
* @return mixed The value of the configuration.
|
||||
*
|
||||
* @since 11.3
|
||||
*/
|
||||
public function get($key, $default = null)
|
||||
{
|
||||
return $this->config->get($key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the global JApplicationCli object, only creating it if it doesn't already exist.
|
||||
*
|
||||
* This method must be invoked as: $cli = JApplicationCli::getInstance();
|
||||
*
|
||||
* @param string $name The name (optional) of the JApplicationCli class to instantiate.
|
||||
*
|
||||
* @return JApplicationCli
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public static function getInstance($name = null)
|
||||
{
|
||||
// Only create the object if it doesn't exist.
|
||||
if (empty(self::$instance))
|
||||
{
|
||||
if (class_exists($name) && (is_subclass_of($name, 'JApplicationCli')))
|
||||
{
|
||||
self::$instance = new $name;
|
||||
}
|
||||
else
|
||||
{
|
||||
self::$instance = new JApplicationCli;
|
||||
}
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the application.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
// Trigger the onBeforeExecute event.
|
||||
$this->triggerEvent('onBeforeExecute');
|
||||
|
||||
// Perform application routines.
|
||||
$this->doExecute();
|
||||
|
||||
// Trigger the onAfterExecute event.
|
||||
$this->triggerEvent('onAfterExecute');
|
||||
}
|
||||
|
||||
/**
|
||||
* Load an object or array into the application configuration object.
|
||||
*
|
||||
* @param mixed $data Either an array or object to be loaded into the configuration object.
|
||||
*
|
||||
* @return JApplicationCli Instance of $this to allow chaining.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function loadConfiguration($data)
|
||||
{
|
||||
// Load the data into the configuration object.
|
||||
if (is_array($data))
|
||||
{
|
||||
$this->config->loadArray($data);
|
||||
}
|
||||
elseif (is_object($data))
|
||||
{
|
||||
$this->config->loadObject($data);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a string to standard output.
|
||||
*
|
||||
* @param string $text The text to display.
|
||||
* @param boolean $nl True (default) to append a new line at the end of the output string.
|
||||
*
|
||||
* @return JApplicationCli Instance of $this to allow chaining.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @since 11.1
|
||||
*/
|
||||
public function out($text = '', $nl = true)
|
||||
{
|
||||
fwrite(STDOUT, $text . ($nl ? "\n" : null));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a value from standard input.
|
||||
*
|
||||
* @return string The input string from standard input.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @since 11.1
|
||||
*/
|
||||
public function in()
|
||||
{
|
||||
return rtrim(fread(STDIN, 8192), "\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies a property of the object, creating it if it does not already exist.
|
||||
*
|
||||
* @param string $key The name of the property.
|
||||
* @param mixed $value The value of the property to set (optional).
|
||||
*
|
||||
* @return mixed Previous value of the property
|
||||
*
|
||||
* @since 11.3
|
||||
*/
|
||||
public function set($key, $value = null)
|
||||
{
|
||||
$previous = $this->config->get($key);
|
||||
$this->config->set($key, $value);
|
||||
|
||||
return $previous;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to load a PHP configuration class file based on convention and return the instantiated data object. You
|
||||
* will extend this method in child classes to provide configuration data from whatever data source is relevant
|
||||
* for your specific application.
|
||||
*
|
||||
* @param string $file The path and filename of the configuration file. If not provided, configuration.php
|
||||
* in JPATH_BASE will be used.
|
||||
* @param string $class The class name to instantiate.
|
||||
*
|
||||
* @return mixed Either an array or object to be loaded into the configuration object.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function fetchConfigurationData($file = '', $class = 'JConfig')
|
||||
{
|
||||
// Instantiate variables.
|
||||
$config = array();
|
||||
|
||||
if (empty($file) && defined('JPATH_BASE'))
|
||||
{
|
||||
$file = JPATH_BASE . '/configuration.php';
|
||||
|
||||
// Applications can choose not to have any configuration data
|
||||
// by not implementing this method and not having a config file.
|
||||
if (!file_exists($file))
|
||||
{
|
||||
$file = '';
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($file))
|
||||
{
|
||||
JLoader::register($class, $file);
|
||||
|
||||
if (class_exists($class))
|
||||
{
|
||||
$config = new $class;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new RuntimeException('Configuration class does not exist.');
|
||||
}
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to run the application routines. Most likely you will want to instantiate a controller
|
||||
* and execute it, or perform some sort of task directly.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @since 11.3
|
||||
*/
|
||||
protected function doExecute()
|
||||
{
|
||||
// Your application routines go here.
|
||||
}
|
||||
}
|
915
libraries/joomla/application/daemon.php
Normal file
915
libraries/joomla/application/daemon.php
Normal file
@ -0,0 +1,915 @@
|
||||
<?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;
|
||||
|
||||
jimport('joomla.filesystem.folder');
|
||||
|
||||
/**
|
||||
* Class to turn JCli applications into daemons. It requires CLI and PCNTL support built into PHP.
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Application
|
||||
* @see http://www.php.net/manual/en/book.pcntl.php
|
||||
* @see http://php.net/manual/en/features.commandline.php
|
||||
* @since 11.1
|
||||
*/
|
||||
class JApplicationDaemon extends JApplicationCli
|
||||
{
|
||||
/**
|
||||
* @var array The available POSIX signals to be caught by default.
|
||||
* @see http://php.net/manual/pcntl.constants.php
|
||||
* @since 11.1
|
||||
*/
|
||||
protected static $signals = array(
|
||||
'SIGHUP',
|
||||
'SIGINT',
|
||||
'SIGQUIT',
|
||||
'SIGILL',
|
||||
'SIGTRAP',
|
||||
'SIGABRT',
|
||||
'SIGIOT',
|
||||
'SIGBUS',
|
||||
'SIGFPE',
|
||||
'SIGUSR1',
|
||||
'SIGSEGV',
|
||||
'SIGUSR2',
|
||||
'SIGPIPE',
|
||||
'SIGALRM',
|
||||
'SIGTERM',
|
||||
'SIGSTKFLT',
|
||||
'SIGCLD',
|
||||
'SIGCHLD',
|
||||
'SIGCONT',
|
||||
'SIGTSTP',
|
||||
'SIGTTIN',
|
||||
'SIGTTOU',
|
||||
'SIGURG',
|
||||
'SIGXCPU',
|
||||
'SIGXFSZ',
|
||||
'SIGVTALRM',
|
||||
'SIGPROF',
|
||||
'SIGWINCH',
|
||||
'SIGPOLL',
|
||||
'SIGIO',
|
||||
'SIGPWR',
|
||||
'SIGSYS',
|
||||
'SIGBABY',
|
||||
'SIG_BLOCK',
|
||||
'SIG_UNBLOCK',
|
||||
'SIG_SETMASK'
|
||||
);
|
||||
|
||||
/**
|
||||
* @var boolean True if the daemon is in the process of exiting.
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $exiting = false;
|
||||
|
||||
/**
|
||||
* @var integer The parent process id.
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $parentId = 0;
|
||||
|
||||
/**
|
||||
* @var integer The process id of the daemon.
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $processId = 0;
|
||||
|
||||
/**
|
||||
* @var boolean True if the daemon is currently running.
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $running = false;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param mixed $input An optional argument to provide dependency injection for the application's
|
||||
* input object. If the argument is a JInputCli object that object will become
|
||||
* the application's input object, otherwise a default input object is created.
|
||||
* @param mixed $config An optional argument to provide dependency injection for the application's
|
||||
* config object. If the argument is a JRegistry object that object will become
|
||||
* the application's config object, otherwise a default config object is created.
|
||||
* @param mixed $dispatcher An optional argument to provide dependency injection for the application's
|
||||
* event dispatcher. If the argument is a JEventDispatcher object that object will become
|
||||
* the application's event dispatcher, if it is null then the default event dispatcher
|
||||
* will be created based on the application's loadDispatcher() method.
|
||||
*
|
||||
* @since 11.1
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function __construct(JInputCli $input = null, JRegistry $config = null, JEventDispatcher $dispatcher = null)
|
||||
{
|
||||
// Verify that the process control extension for PHP is available.
|
||||
// @codeCoverageIgnoreStart
|
||||
if (!defined('SIGHUP'))
|
||||
{
|
||||
JLog::add('The PCNTL extension for PHP is not available.', JLog::ERROR);
|
||||
throw new RuntimeException('The PCNTL extension for PHP is not available.');
|
||||
}
|
||||
|
||||
// Verify that POSIX support for PHP is available.
|
||||
if (!function_exists('posix_getpid'))
|
||||
{
|
||||
JLog::add('The POSIX extension for PHP is not available.', JLog::ERROR);
|
||||
throw new RuntimeException('The POSIX extension for PHP is not available.');
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
// Call the parent constructor.
|
||||
parent::__construct($input, $config, $dispatcher);
|
||||
|
||||
// Set some system limits.
|
||||
@set_time_limit($this->config->get('max_execution_time', 0));
|
||||
|
||||
if ($this->config->get('max_memory_limit') !== null)
|
||||
{
|
||||
ini_set('memory_limit', $this->config->get('max_memory_limit', '256M'));
|
||||
}
|
||||
|
||||
// Flush content immediately.
|
||||
ob_implicit_flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to handle POSIX signals.
|
||||
*
|
||||
* @param integer $signal The received POSIX signal.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 11.1
|
||||
* @see pcntl_signal()
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public static function signal($signal)
|
||||
{
|
||||
// Log all signals sent to the daemon.
|
||||
JLog::add('Received signal: ' . $signal, JLog::DEBUG);
|
||||
|
||||
// Let's make sure we have an application instance.
|
||||
if (!is_subclass_of(static::$instance, 'JApplicationDaemon'))
|
||||
{
|
||||
JLog::add('Cannot find the application instance.', JLog::EMERGENCY);
|
||||
throw new RuntimeException('Cannot find the application instance.');
|
||||
}
|
||||
|
||||
// Fire the onReceiveSignal event.
|
||||
static::$instance->triggerEvent('onReceiveSignal', array($signal));
|
||||
|
||||
switch ($signal)
|
||||
{
|
||||
case SIGINT:
|
||||
case SIGTERM:
|
||||
// Handle shutdown tasks
|
||||
if (static::$instance->running && static::$instance->isActive())
|
||||
{
|
||||
static::$instance->shutdown();
|
||||
}
|
||||
else
|
||||
{
|
||||
static::$instance->close();
|
||||
}
|
||||
break;
|
||||
case SIGHUP:
|
||||
// Handle restart tasks
|
||||
if (static::$instance->running && static::$instance->isActive())
|
||||
{
|
||||
static::$instance->shutdown(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
static::$instance->close();
|
||||
}
|
||||
break;
|
||||
case SIGCHLD:
|
||||
// A child process has died
|
||||
while (static::$instance->pcntlWait($signal, WNOHANG || WUNTRACED) > 0)
|
||||
{
|
||||
usleep(1000);
|
||||
}
|
||||
break;
|
||||
case SIGCLD:
|
||||
while (static::$instance->pcntlWait($signal, WNOHANG) > 0)
|
||||
{
|
||||
$signal = static::$instance->pcntlChildExitStatus($signal);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the daemon is active. This does not assume that $this daemon is active, but
|
||||
* only if an instance of the application is active as a daemon.
|
||||
*
|
||||
* @return boolean True if daemon is active.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function isActive()
|
||||
{
|
||||
// Get the process id file location for the application.
|
||||
$pidFile = $this->config->get('application_pid_file');
|
||||
|
||||
// If the process id file doesn't exist then the daemon is obviously not running.
|
||||
if (!is_file($pidFile))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the contents of the process id file as an integer.
|
||||
$fp = fopen($pidFile, 'r');
|
||||
$pid = fread($fp, filesize($pidFile));
|
||||
$pid = (int) $pid;
|
||||
fclose($fp);
|
||||
|
||||
// Check to make sure that the process id exists as a positive integer.
|
||||
if (!$pid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check to make sure the process is active by pinging it and ensure it responds.
|
||||
if (!posix_kill($pid, 0))
|
||||
{
|
||||
// No response so remove the process id file and log the situation.
|
||||
@ unlink($pidFile);
|
||||
JLog::add('The process found based on PID file was unresponsive.', JLog::WARNING);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load an object or array into the application configuration object.
|
||||
*
|
||||
* @param mixed $data Either an array or object to be loaded into the configuration object.
|
||||
*
|
||||
* @return JCli Instance of $this to allow chaining.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function loadConfiguration($data)
|
||||
{
|
||||
// Execute the parent load method.
|
||||
parent::loadConfiguration($data);
|
||||
|
||||
/*
|
||||
* Setup some application metadata options. This is useful if we ever want to write out startup scripts
|
||||
* or just have some sort of information available to share about things.
|
||||
*/
|
||||
|
||||
// The application author name. This string is used in generating startup scripts and has
|
||||
// a maximum of 50 characters.
|
||||
$tmp = (string) $this->config->get('author_name', 'Joomla Platform');
|
||||
$this->config->set('author_name', (strlen($tmp) > 50) ? substr($tmp, 0, 50) : $tmp);
|
||||
|
||||
// The application author email. This string is used in generating startup scripts.
|
||||
$tmp = (string) $this->config->get('author_email', 'admin@joomla.org');
|
||||
$this->config->set('author_email', filter_var($tmp, FILTER_VALIDATE_EMAIL));
|
||||
|
||||
// The application name. This string is used in generating startup scripts.
|
||||
$tmp = (string) $this->config->get('application_name', 'JApplicationDaemon');
|
||||
$this->config->set('application_name', (string) preg_replace('/[^A-Z0-9_-]/i', '', $tmp));
|
||||
|
||||
// The application description. This string is used in generating startup scripts.
|
||||
$tmp = (string) $this->config->get('application_description', 'A generic Joomla Platform application.');
|
||||
$this->config->set('application_description', filter_var($tmp, FILTER_SANITIZE_STRING));
|
||||
|
||||
/*
|
||||
* Setup the application path options. This defines the default executable name, executable directory,
|
||||
* and also the path to the daemon process id file.
|
||||
*/
|
||||
|
||||
// The application executable daemon. This string is used in generating startup scripts.
|
||||
$tmp = (string) $this->config->get('application_executable', basename($this->input->executable));
|
||||
$this->config->set('application_executable', $tmp);
|
||||
|
||||
// The home directory of the daemon.
|
||||
$tmp = (string) $this->config->get('application_directory', dirname($this->input->executable));
|
||||
$this->config->set('application_directory', $tmp);
|
||||
|
||||
// The pid file location. This defaults to a path inside the /tmp directory.
|
||||
$name = $this->config->get('application_name');
|
||||
$tmp = (string) $this->config->get('application_pid_file', strtolower('/tmp/' . $name . '/' . $name . '.pid'));
|
||||
$this->config->set('application_pid_file', $tmp);
|
||||
|
||||
/*
|
||||
* Setup the application identity options. It is important to remember if the default of 0 is set for
|
||||
* either UID or GID then changing that setting will not be attempted as there is no real way to "change"
|
||||
* the identity of a process from some user to root.
|
||||
*/
|
||||
|
||||
// The user id under which to run the daemon.
|
||||
$tmp = (int) $this->config->get('application_uid', 0);
|
||||
$options = array('options' => array('min_range' => 0, 'max_range' => 65000));
|
||||
$this->config->set('application_uid', filter_var($tmp, FILTER_VALIDATE_INT, $options));
|
||||
|
||||
// The group id under which to run the daemon.
|
||||
$tmp = (int) $this->config->get('application_gid', 0);
|
||||
$options = array('options' => array('min_range' => 0, 'max_range' => 65000));
|
||||
$this->config->set('application_gid', filter_var($tmp, FILTER_VALIDATE_INT, $options));
|
||||
|
||||
// Option to kill the daemon if it cannot switch to the chosen identity.
|
||||
$tmp = (bool) $this->config->get('application_require_identity', 1);
|
||||
$this->config->set('application_require_identity', $tmp);
|
||||
|
||||
/*
|
||||
* Setup the application runtime options. By default our execution time limit is infinite obviously
|
||||
* because a daemon should be constantly running unless told otherwise. The default limit for memory
|
||||
* usage is 128M, which admittedly is a little high, but remember it is a "limit" and PHP's memory
|
||||
* management leaves a bit to be desired :-)
|
||||
*/
|
||||
|
||||
// The maximum execution time of the application in seconds. Zero is infinite.
|
||||
$tmp = $this->config->get('max_execution_time');
|
||||
|
||||
if ($tmp !== null)
|
||||
{
|
||||
$this->config->set('max_execution_time', (int) $tmp);
|
||||
}
|
||||
|
||||
// The maximum amount of memory the application can use.
|
||||
$tmp = $this->config->get('max_memory_limit', '256M');
|
||||
|
||||
if ($tmp !== null)
|
||||
{
|
||||
$this->config->set('max_memory_limit', (string) $tmp);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the daemon.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
// Trigger the onBeforeExecute event.
|
||||
$this->triggerEvent('onBeforeExecute');
|
||||
|
||||
// Enable basic garbage collection.
|
||||
gc_enable();
|
||||
|
||||
JLog::add('Starting ' . $this->name, JLog::INFO);
|
||||
|
||||
// Set off the process for becoming a daemon.
|
||||
if ($this->daemonize())
|
||||
{
|
||||
// Declare ticks to start signal monitoring. When you declare ticks, PCNTL will monitor
|
||||
// incoming signals after each tick and call the relevant signal handler automatically.
|
||||
declare (ticks = 1);
|
||||
|
||||
// Start the main execution loop.
|
||||
while (true)
|
||||
{
|
||||
// Perform basic garbage collection.
|
||||
$this->gc();
|
||||
|
||||
// Don't completely overload the CPU.
|
||||
usleep(1000);
|
||||
|
||||
// Execute the main application logic.
|
||||
$this->doExecute();
|
||||
}
|
||||
}
|
||||
// We were not able to daemonize the application so log the failure and die gracefully.
|
||||
else
|
||||
{
|
||||
JLog::add('Starting ' . $this->name . ' failed', JLog::INFO);
|
||||
}
|
||||
|
||||
// Trigger the onAfterExecute event.
|
||||
$this->triggerEvent('onAfterExecute');
|
||||
}
|
||||
|
||||
/**
|
||||
* Restart daemon process.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @since 11.1
|
||||
*/
|
||||
public function restart()
|
||||
{
|
||||
JLog::add('Stopping ' . $this->name, JLog::INFO);
|
||||
$this->shutdown(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop daemon process.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @since 11.1
|
||||
*/
|
||||
public function stop()
|
||||
{
|
||||
JLog::add('Stopping ' . $this->name, JLog::INFO);
|
||||
$this->shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to change the identity of the daemon process and resources.
|
||||
*
|
||||
* @return boolean True if identity successfully changed
|
||||
*
|
||||
* @since 11.1
|
||||
* @see posix_setuid()
|
||||
*/
|
||||
protected function changeIdentity()
|
||||
{
|
||||
// Get the group and user ids to set for the daemon.
|
||||
$uid = (int) $this->config->get('application_uid', 0);
|
||||
$gid = (int) $this->config->get('application_gid', 0);
|
||||
|
||||
// Get the application process id file path.
|
||||
$file = $this->config->get('application_pid_file');
|
||||
|
||||
// Change the user id for the process id file if necessary.
|
||||
if ($uid && (fileowner($file) != $uid) && (!@ chown($file, $uid)))
|
||||
{
|
||||
JLog::add('Unable to change user ownership of the process id file.', JLog::ERROR);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Change the group id for the process id file if necessary.
|
||||
if ($gid && (filegroup($file) != $gid) && (!@ chgrp($file, $gid)))
|
||||
{
|
||||
JLog::add('Unable to change group ownership of the process id file.', JLog::ERROR);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the correct home directory for the process.
|
||||
if ($uid && ($info = posix_getpwuid($uid)) && is_dir($info['dir']))
|
||||
{
|
||||
system('export HOME="' . $info['dir'] . '"');
|
||||
}
|
||||
|
||||
// Change the user id for the process necessary.
|
||||
if ($uid && (posix_getuid($file) != $uid) && (!@ posix_setuid($uid)))
|
||||
{
|
||||
JLog::add('Unable to change user ownership of the proccess.', JLog::ERROR);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Change the group id for the process necessary.
|
||||
if ($gid && (posix_getgid($file) != $gid) && (!@ posix_setgid($gid)))
|
||||
{
|
||||
JLog::add('Unable to change group ownership of the proccess.', JLog::ERROR);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the user and group information based on uid and gid.
|
||||
$user = posix_getpwuid($uid);
|
||||
$group = posix_getgrgid($gid);
|
||||
|
||||
JLog::add('Changed daemon identity to ' . $user['name'] . ':' . $group['name'], JLog::INFO);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to put the application into the background.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 11.1
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
protected function daemonize()
|
||||
{
|
||||
// Is there already an active daemon running?
|
||||
if ($this->isActive())
|
||||
{
|
||||
JLog::add($this->name . ' daemon is still running. Exiting the application.', JLog::EMERGENCY);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reset Process Information
|
||||
$this->safeMode = !!@ ini_get('safe_mode');
|
||||
$this->processId = 0;
|
||||
$this->running = false;
|
||||
|
||||
// Detach process!
|
||||
try
|
||||
{
|
||||
// Check if we should run in the foreground.
|
||||
if (!$this->input->get('f'))
|
||||
{
|
||||
// Detach from the terminal.
|
||||
$this->detach();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Setup running values.
|
||||
$this->exiting = false;
|
||||
$this->running = true;
|
||||
|
||||
// Set the process id.
|
||||
$this->processId = (int) posix_getpid();
|
||||
$this->parentId = $this->processId;
|
||||
}
|
||||
}
|
||||
catch (RuntimeException $e)
|
||||
{
|
||||
JLog::add('Unable to fork.', JLog::EMERGENCY);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verify the process id is valid.
|
||||
if ($this->processId < 1)
|
||||
{
|
||||
JLog::add('The process id is invalid; the fork failed.', JLog::EMERGENCY);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Clear the umask.
|
||||
@ umask(0);
|
||||
|
||||
// Write out the process id file for concurrency management.
|
||||
if (!$this->writeProcessIdFile())
|
||||
{
|
||||
JLog::add('Unable to write the pid file at: ' . $this->config->get('application_pid_file'), JLog::EMERGENCY);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Attempt to change the identity of user running the process.
|
||||
if (!$this->changeIdentity())
|
||||
{
|
||||
|
||||
// If the identity change was required then we need to return false.
|
||||
if ($this->config->get('application_require_identity'))
|
||||
{
|
||||
JLog::add('Unable to change process owner.', JLog::CRITICAL);
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
JLog::add('Unable to change process owner.', JLog::WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
// Setup the signal handlers for the daemon.
|
||||
if (!$this->setupSignalHandlers())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Change the current working directory to the application working directory.
|
||||
@ chdir($this->config->get('application_directory'));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is truly where the magic happens. This is where we fork the process and kill the parent
|
||||
* process, which is essentially what turns the application into a daemon.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 12.1
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
protected function detach()
|
||||
{
|
||||
JLog::add('Detaching the ' . $this->name . ' daemon.', JLog::DEBUG);
|
||||
|
||||
// Attempt to fork the process.
|
||||
$pid = $this->fork();
|
||||
|
||||
// If the pid is positive then we successfully forked, and can close this application.
|
||||
if ($pid)
|
||||
{
|
||||
// Add the log entry for debugging purposes and exit gracefully.
|
||||
JLog::add('Ending ' . $this->name . ' parent process', JLog::DEBUG);
|
||||
$this->close();
|
||||
}
|
||||
// We are in the forked child process.
|
||||
else
|
||||
{
|
||||
// Setup some protected values.
|
||||
$this->exiting = false;
|
||||
$this->running = true;
|
||||
|
||||
// Set the parent to self.
|
||||
$this->parentId = $this->processId;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to fork the process.
|
||||
*
|
||||
* @return integer The child process id to the parent process, zero to the child process.
|
||||
*
|
||||
* @since 11.1
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
protected function fork()
|
||||
{
|
||||
// Attempt to fork the process.
|
||||
$pid = $this->pcntlFork();
|
||||
|
||||
// If the fork failed, throw an exception.
|
||||
if ($pid === -1)
|
||||
{
|
||||
throw new RuntimeException('The process could not be forked.');
|
||||
}
|
||||
// Update the process id for the child.
|
||||
elseif ($pid === 0)
|
||||
{
|
||||
$this->processId = (int) posix_getpid();
|
||||
}
|
||||
// Log the fork in the parent.
|
||||
else
|
||||
{
|
||||
// Log the fork.
|
||||
JLog::add('Process forked ' . $pid, JLog::DEBUG);
|
||||
}
|
||||
|
||||
// Trigger the onFork event.
|
||||
$this->postFork();
|
||||
|
||||
return $pid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to perform basic garbage collection and memory management in the sense of clearing the
|
||||
* stat cache. We will probably call this method pretty regularly in our main loop.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function gc()
|
||||
{
|
||||
// Perform generic garbage collection.
|
||||
gc_collect_cycles();
|
||||
|
||||
// Clear the stat cache so it doesn't blow up memory.
|
||||
clearstatcache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to attach the JApplicationDaemon signal handler to the known signals. Applications
|
||||
* can override these handlers by using the pcntl_signal() function and attaching a different
|
||||
* callback method.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 11.1
|
||||
* @see pcntl_signal()
|
||||
*/
|
||||
protected function setupSignalHandlers()
|
||||
{
|
||||
// We add the error suppression for the loop because on some platforms some constants are not defined.
|
||||
foreach (self::$signals as $signal)
|
||||
{
|
||||
// Ignore signals that are not defined.
|
||||
if (!defined($signal) || !is_int(constant($signal)) || (constant($signal) === 0))
|
||||
{
|
||||
// Define the signal to avoid notices.
|
||||
JLog::add('Signal "' . $signal . '" not defined. Defining it as null.', JLog::DEBUG);
|
||||
define($signal, null);
|
||||
|
||||
// Don't listen for signal.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Attach the signal handler for the signal.
|
||||
if (!$this->pcntlSignal(constant($signal), array('JApplicationDaemon', 'signal')))
|
||||
{
|
||||
JLog::add(sprintf('Unable to reroute signal handler: %s', $signal), JLog::EMERGENCY);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to shut down the daemon and optionally restart it.
|
||||
*
|
||||
* @param boolean $restart True to restart the daemon on exit.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function shutdown($restart = false)
|
||||
{
|
||||
// If we are already exiting, chill.
|
||||
if ($this->exiting)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// If not, now we are.
|
||||
else
|
||||
{
|
||||
$this->exiting = true;
|
||||
}
|
||||
|
||||
// If we aren't already daemonized then just kill the application.
|
||||
if (!$this->running && !$this->isActive())
|
||||
{
|
||||
JLog::add('Process was not daemonized yet, just halting current process', JLog::INFO);
|
||||
$this->close();
|
||||
}
|
||||
|
||||
// Only read the pid for the parent file.
|
||||
if ($this->parentId == $this->processId)
|
||||
{
|
||||
// Read the contents of the process id file as an integer.
|
||||
$fp = fopen($this->config->get('application_pid_file'), 'r');
|
||||
$pid = fread($fp, filesize($this->config->get('application_pid_file')));
|
||||
$pid = (int) $pid;
|
||||
fclose($fp);
|
||||
|
||||
// Remove the process id file.
|
||||
@ unlink($this->config->get('application_pid_file'));
|
||||
|
||||
// If we are supposed to restart the daemon we need to execute the same command.
|
||||
if ($restart)
|
||||
{
|
||||
$this->close(exec(implode(' ', $GLOBALS['argv']) . ' > /dev/null &'));
|
||||
}
|
||||
// If we are not supposed to restart the daemon let's just kill -9.
|
||||
else
|
||||
{
|
||||
passthru('kill -9 ' . $pid);
|
||||
$this->close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to write the process id file out to disk.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function writeProcessIdFile()
|
||||
{
|
||||
// Verify the process id is valid.
|
||||
if ($this->processId < 1)
|
||||
{
|
||||
JLog::add('The process id is invalid.', JLog::EMERGENCY);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the application process id file path.
|
||||
$file = $this->config->get('application_pid_file');
|
||||
|
||||
if (empty($file))
|
||||
{
|
||||
JLog::add('The process id file path is empty.', JLog::ERROR);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure that the folder where we are writing the process id file exists.
|
||||
$folder = dirname($file);
|
||||
|
||||
if (!is_dir($folder) && !JFolder::create($folder))
|
||||
{
|
||||
JLog::add('Unable to create directory: ' . $folder, JLog::ERROR);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write the process id file out to disk.
|
||||
if (!file_put_contents($file, $this->processId))
|
||||
{
|
||||
JLog::add('Unable to write proccess id file: ' . $file, JLog::ERROR);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure the permissions for the proccess id file are accurate.
|
||||
if (!chmod($file, 0644))
|
||||
{
|
||||
JLog::add('Unable to adjust permissions for the proccess id file: ' . $file, JLog::ERROR);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to handle post-fork triggering of the onFork event.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
protected function postFork()
|
||||
{
|
||||
// Trigger the onFork event.
|
||||
$this->triggerEvent('onFork');
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to return the exit code of a terminated child process.
|
||||
*
|
||||
* @param integer $status The status parameter is the status parameter supplied to a successful call to pcntl_waitpid().
|
||||
*
|
||||
* @return integer The child process exit code.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @see pcntl_wexitstatus()
|
||||
* @since 11.3
|
||||
*/
|
||||
protected function pcntlChildExitStatus($status)
|
||||
{
|
||||
return pcntl_wexitstatus($status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to return the exit code of a terminated child process.
|
||||
*
|
||||
* @return integer On success, the PID of the child process is returned in the parent's thread
|
||||
* of execution, and a 0 is returned in the child's thread of execution. On
|
||||
* failure, a -1 will be returned in the parent's context, no child process
|
||||
* will be created, and a PHP error is raised.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @see pcntl_fork()
|
||||
* @since 11.3
|
||||
*/
|
||||
protected function pcntlFork()
|
||||
{
|
||||
return pcntl_fork();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to install a signal handler.
|
||||
*
|
||||
* @param integer $signal The signal number.
|
||||
* @param callable $handler The signal handler which may be the name of a user created function,
|
||||
* or method, or either of the two global constants SIG_IGN or SIG_DFL.
|
||||
* @param boolean $restart Specifies whether system call restarting should be used when this
|
||||
* signal arrives.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @see pcntl_signal()
|
||||
* @since 11.3
|
||||
*/
|
||||
protected function pcntlSignal($signal , $handler, $restart = true)
|
||||
{
|
||||
return pcntl_signal($signal, $handler, $restart);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to wait on or return the status of a forked child.
|
||||
*
|
||||
* @param integer &$status Status information.
|
||||
* @param integer $options If wait3 is available on your system (mostly BSD-style systems),
|
||||
* you can provide the optional options parameter.
|
||||
*
|
||||
* @return integer The process ID of the child which exited, -1 on error or zero if WNOHANG
|
||||
* was provided as an option (on wait3-available systems) and no child was available.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @see pcntl_wait()
|
||||
* @since 11.3
|
||||
*/
|
||||
protected function pcntlWait(&$status, $options = 0)
|
||||
{
|
||||
return pcntl_wait($status, $options);
|
||||
}
|
||||
}
|
1
libraries/joomla/application/index.html
Normal file
1
libraries/joomla/application/index.html
Normal file
@ -0,0 +1 @@
|
||||
<!DOCTYPE html><title></title>
|
107
libraries/joomla/application/route.php
Normal file
107
libraries/joomla/application/route.php
Normal file
@ -0,0 +1,107 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* Route handling class
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Application
|
||||
* @since 11.1
|
||||
*/
|
||||
class JRoute
|
||||
{
|
||||
/**
|
||||
* The route object so we don't have to keep fetching it.
|
||||
*
|
||||
* @var JRouter
|
||||
* @since 12.2
|
||||
*/
|
||||
private static $_router = null;
|
||||
|
||||
/**
|
||||
* Translates an internal Joomla URL to a humanly readible URL.
|
||||
*
|
||||
* @param string $url Absolute or Relative URI to Joomla resource.
|
||||
* @param boolean $xhtml Replace & by & for XML compilance.
|
||||
* @param integer $ssl Secure state for the resolved URI.
|
||||
* 1: Make URI secure using global secure site URI.
|
||||
* 2: Make URI unsecure using the global unsecure site URI.
|
||||
*
|
||||
* @return The translated humanly readible URL.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public static function _($url, $xhtml = true, $ssl = null)
|
||||
{
|
||||
if (!self::$_router)
|
||||
{
|
||||
// Get the router.
|
||||
self::$_router = JFactory::getApplication()->getRouter();
|
||||
|
||||
// Make sure that we have our router
|
||||
if (!self::$_router)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if ((strpos($url, '&') !== 0) && (strpos($url, 'index.php') !== 0))
|
||||
{
|
||||
return $url;
|
||||
}
|
||||
|
||||
// Build route.
|
||||
$uri = self::$_router->build($url);
|
||||
$url = $uri->toString(array('path', 'query', 'fragment'));
|
||||
|
||||
// Replace spaces.
|
||||
$url = preg_replace('/\s/u', '%20', $url);
|
||||
|
||||
/*
|
||||
* Get the secure/unsecure URLs.
|
||||
*
|
||||
* If the first 5 characters of the BASE are 'https', then we are on an ssl connection over
|
||||
* https and need to set our secure URL to the current request URL, if not, and the scheme is
|
||||
* 'http', then we need to do a quick string manipulation to switch schemes.
|
||||
*/
|
||||
if ((int) $ssl)
|
||||
{
|
||||
$uri = JUri::getInstance();
|
||||
|
||||
// Get additional parts.
|
||||
static $prefix;
|
||||
|
||||
if (!$prefix)
|
||||
{
|
||||
$prefix = $uri->toString(array('host', 'port'));
|
||||
}
|
||||
|
||||
// Determine which scheme we want.
|
||||
$scheme = ((int) $ssl === 1) ? 'https' : 'http';
|
||||
|
||||
// Make sure our URL path begins with a slash.
|
||||
if (!preg_match('#^/#', $url))
|
||||
{
|
||||
$url = '/' . $url;
|
||||
}
|
||||
|
||||
// Build the URL.
|
||||
$url = $scheme . '://' . $prefix . $url;
|
||||
}
|
||||
|
||||
if ($xhtml)
|
||||
{
|
||||
$url = htmlspecialchars($url);
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
}
|
521
libraries/joomla/application/router.php
Normal file
521
libraries/joomla/application/router.php
Normal file
@ -0,0 +1,521 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
1184
libraries/joomla/application/web.php
Normal file
1184
libraries/joomla/application/web.php
Normal file
File diff suppressed because it is too large
Load Diff
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