<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Controller
* @subpackage Dispatcher
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/** Zend_Loader */
require_once 'Zend/Loader.php';
/** Zend_Controller_Dispatcher_Abstract */
require_once 'Zend/Controller/Dispatcher/Abstract.php';
/**
* @category Zend
* @package Zend_Controller
* @subpackage Dispatcher
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Controller_Dispatcher_Standard extends Zend_Controller_Dispatcher_Abstract
{
/**
* Current dispatchable directory
* @var string
*/
protected $_curDirectory;
/**
* Current module (formatted)
* @var string
*/
protected $_curModule;
/**
* Controller directory(ies)
* @var array
*/
protected $_controllerDirectory = [];
/**
* Constructor: Set current module to default value
*
* @param array $params
* @return void
*/
public function __construct(array $params = [])
{
parent::__construct($params);
$this->_curModule = $this->getDefaultModule();
}
/**
* Add a single path to the controller directory stack
*
* @param string $path
* @param string $module
* @return $this
*/
public function addControllerDirectory($path, $module = null)
{
if (null === $module) {
$module = $this->_defaultModule;
}
$module = (string) $module;
$path = rtrim((string) $path, '/\\');
$this->_controllerDirectory[$module] = $path;
return $this;
}
/**
* Set controller directory
*
* @param array|string $directory
* @return $this
*/
public function setControllerDirectory($directory, $module = null)
{
$this->_controllerDirectory = [];
if (is_string($directory)) {
$this->addControllerDirectory($directory, $module);
} elseif (is_array($directory)) {
foreach ((array) $directory as $module => $path) {
$this->addControllerDirectory($path, $module);
}
} else {
require_once 'Zend/Controller/Exception.php';
throw new Zend_Controller_Exception('Controller directory spec must be either a string or an array');
}
return $this;
}
/**
* Return the currently set directories for Zend_Controller_Action class
* lookup
*
* If a module is specified, returns just that directory.
*
* @param string $module Module name
* @return array|string|null Returns array of all directories by default, single
* module directory if module argument provided
*/
public function getControllerDirectory($module = null)
{
if (null === $module) {
return $this->_controllerDirectory;
}
$module = (string) $module;
if (array_key_exists($module, $this->_controllerDirectory)) {
return $this->_controllerDirectory[$module];
}
return null;
}
/**
* Remove a controller directory by module name
*
* @param string $module
* @return bool
*/
public function removeControllerDirectory($module)
{
$module = (string) $module;
if (array_key_exists($module, $this->_controllerDirectory)) {
unset($this->_controllerDirectory[$module]);
return true;
}
return false;
}
/**
* Format the module name.
*
* @param string $unformatted
* @return string
*/
public function formatModuleName($unformatted)
{
if (($this->_defaultModule == $unformatted) && !$this->getParam('prefixDefaultModule')) {
return $unformatted;
}
return ucfirst($this->_formatName($unformatted));
}
/**
* Format action class name
*
* @param string $moduleName Name of the current module
* @param string $className Name of the action class
* @return string Formatted class name
*/
public function formatClassName($moduleName, $className)
{
return $this->formatModuleName($moduleName) . '_' . $className;
}
/**
* Convert a class name to a filename
*
* @param string $class
* @return string
*/
public function classToFilename($class)
{
return str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php';
}
/**
* Returns TRUE if the Zend_Controller_Request_Abstract object can be
* dispatched to a controller.
*
* Use this method wisely. By default, the dispatcher will fall back to the
* default controller (either in the module specified or the global default)
* if a given controller does not exist. This method returning false does
* not necessarily indicate the dispatcher will not still dispatch the call.
*
* @param Zend_Controller_Request_Abstract $action
* @return boolean
*/
public function isDispatchable(Zend_Controller_Request_Abstract $request)
{
$className = $this->getControllerClass($request);
if (!$className) {
return false;
}
$finalClass = $className;
if (($this->_defaultModule != $this->_curModule)
|| $this->getParam('prefixDefaultModule'))
{
$finalClass = $this->formatClassName($this->_curModule, $className);
}
if (class_exists($finalClass, false)) {
return true;
}
$fileSpec = $this->classToFilename($className);
$dispatchDir = $this->getDispatchDirectory();
$test = $dispatchDir . DIRECTORY_SEPARATOR . $fileSpec;
return Zend_Loader::isReadable($test);
}
/**
* Dispatch to a controller/action
*
* By default, if a controller is not dispatchable, dispatch() will throw
* an exception. If you wish to use the default controller instead, set the
* param 'useDefaultControllerAlways' via {@link setParam()}.
*
* @param Zend_Controller_Request_Abstract $request
* @param Zend_Controller_Response_Abstract $response
* @return void
* @throws Zend_Controller_Dispatcher_Exception
*/
public function dispatch(Zend_Controller_Request_Abstract $request, Zend_Controller_Response_Abstract $response)
{
$this->setResponse($response);
/**
* Get controller class
*/
if (!$this->isDispatchable($request)) {
$controller = $request->getControllerName();
if (!$this->getParam('useDefaultControllerAlways') && !empty($controller)) {
require_once 'Zend/Controller/Dispatcher/Exception.php';
throw new Zend_Controller_Dispatcher_Exception('Invalid controller specified (' . $request->getControllerName() . ')');
}
$className = $this->getDefaultControllerClass($request);
} else {
$className = $this->getControllerClass($request);
if (!$className) {
$className = $this->getDefaultControllerClass($request);
}
}
/**
* If we're in a module or prefixDefaultModule is on, we must add the module name
* prefix to the contents of $className, as getControllerClass does not do that automatically.
* We must keep a separate variable because modules are not strictly PSR-0: We need the no-module-prefix
* class name to do the class->file mapping, but the full class name to insantiate the controller
*/
$moduleClassName = $className;
if (($this->_defaultModule != $this->_curModule)
|| $this->getParam('prefixDefaultModule'))
{
$moduleClassName = $this->formatClassName($this->_curModule, $className);
}
/**
* Load the controller class file
*/
$className = $this->loadClass($className);
/**
* Instantiate controller with request, response, and invocation
* arguments; throw exception if it's not an action controller
*/
$controller = new $moduleClassName($request, $this->getResponse(), $this->getParams());
if (!($controller instanceof Zend_Controller_Action_Interface) &&
!($controller instanceof Zend_Controller_Action)) {
require_once 'Zend/Controller/Dispatcher/Exception.php';
throw new Zend_Controller_Dispatcher_Exception(
'Controller "' . $moduleClassName . '" is not an instance of Zend_Controller_Action_Interface'
);
}
/**
* Retrieve the action name
*/
$action = $this->getActionMethod($request);
/**
* Dispatch the method call
*/
$request->setDispatched(true);
// by default, buffer output
$disableOb = $this->getParam('disableOutputBuffering');
$obLevel = ob_get_level();
if (empty($disableOb)) {
ob_start();
}
try {
$controller->dispatch($action);
} catch (\Throwable $e) {
// Clean output buffer on error
$curObLevel = ob_get_level();
if ($curObLevel > $obLevel) {
do {
ob_get_clean();
$curObLevel = ob_get_level();
} while ($curObLevel > $obLevel);
}
throw $e;
}
if (empty($disableOb)) {
$content = ob_get_clean();
$response->appendBody($content);
}
// Destroy the page controller instance and reflection objects
$controller = null;
}
/**
* Load a controller class
*
* Attempts to load the controller class file from
* {@link getControllerDirectory()}. If the controller belongs to a
* module, looks for the module prefix to the controller class.
*
* @param string $className
* @return string Class name loaded
* @throws Zend_Controller_Dispatcher_Exception if class not loaded
*/
public function loadClass($className)
{
$finalClass = $className;
if (($this->_defaultModule != $this->_curModule)
|| $this->getParam('prefixDefaultModule'))
{
$finalClass = $this->formatClassName($this->_curModule, $className);
}
if (class_exists($finalClass, false)) {
return $finalClass;
}
$dispatchDir = $this->getDispatchDirectory();
$loadFile = $dispatchDir . DIRECTORY_SEPARATOR . $this->classToFilename($className);
if (Zend_Loader::isReadable($loadFile)) {
include_once $loadFile;
} else {
require_once 'Zend/Controller/Dispatcher/Exception.php';
throw new Zend_Controller_Dispatcher_Exception('Cannot load controller class "' . $className . '" from file "' . $loadFile . "'");
}
if (!class_exists($finalClass, false)) {
require_once 'Zend/Controller/Dispatcher/Exception.php';
throw new Zend_Controller_Dispatcher_Exception('Invalid controller class ("' . $finalClass . '")');
}
return $finalClass;
}
/**
* Get controller class name
*
* Try request first; if not found, try pulling from request parameter;
* if still not found, fallback to default
*
* @param Zend_Controller_Request_Abstract $request
* @return string|false Returns class name on success
*/
public function getControllerClass(Zend_Controller_Request_Abstract $request)
{
$controllerName = $request->getControllerName();
if (empty($controllerName)) {
if (!$this->getParam('useDefaultControllerAlways')) {
return false;
}
$controllerName = $this->getDefaultControllerName();
$request->setControllerName($controllerName);
}
$className = $this->formatControllerName($controllerName);
$controllerDirs = $this->getControllerDirectory();
$module = $request->getModuleName();
if ($this->isValidModule($module)) {
$this->_curModule = $module;
$this->_curDirectory = $controllerDirs[$module];
} elseif ($this->isValidModule($this->_defaultModule)) {
$request->setModuleName($this->_defaultModule);
$this->_curModule = $this->_defaultModule;
$this->_curDirectory = $controllerDirs[$this->_defaultModule];
} else {
require_once 'Zend/Controller/Exception.php';
throw new Zend_Controller_Exception('No default module defined for this application');
}
return $className;
}
/**
* Determine if a given module is valid
*
* @param string $module
* @return bool
*/
public function isValidModule($module)
{
if (!is_string($module)) {
return false;
}
$module = strtolower($module);
$controllerDir = $this->getControllerDirectory();
foreach (array_keys($controllerDir) as $moduleName) {
if ($module == strtolower($moduleName)) {
return true;
}
}
return false;
}
/**
* Retrieve default controller class
*
* Determines whether the default controller to use lies within the
* requested module, or if the global default should be used.
*
* By default, will only use the module default unless that controller does
* not exist; if this is the case, it falls back to the default controller
* in the default module.
*
* @param Zend_Controller_Request_Abstract $request
* @return string
*/
public function getDefaultControllerClass(Zend_Controller_Request_Abstract $request)
{
$controller = $this->getDefaultControllerName();
$default = $this->formatControllerName($controller);
$request->setControllerName($controller)
->setActionName(null);
$module = $request->getModuleName();
$controllerDirs = $this->getControllerDirectory();
$this->_curModule = $this->_defaultModule;
$this->_curDirectory = $controllerDirs[$this->_defaultModule];
if ($this->isValidModule($module)) {
$found = false;
if (class_exists($default, false)) {
$found = true;
} else {
$moduleDir = $controllerDirs[$module];
$fileSpec = $moduleDir . DIRECTORY_SEPARATOR . $this->classToFilename($default);
if (Zend_Loader::isReadable($fileSpec)) {
$found = true;
$this->_curDirectory = $moduleDir;
}
}
if ($found) {
$request->setModuleName($module);
$this->_curModule = $this->formatModuleName($module);
}
} else {
$request->setModuleName($this->_defaultModule);
}
return $default;
}
/**
* Return the value of the currently selected dispatch directory (as set by
* {@link getController()})
*
* @return string
*/
public function getDispatchDirectory()
{
return $this->_curDirectory;
}
/**
* Determine the action name
*
* First attempt to retrieve from request; then from request params
* using action key; default to default action
*
* Returns formatted action name
*
* @param Zend_Controller_Request_Abstract $request
* @return string
*/
public function getActionMethod(Zend_Controller_Request_Abstract $request)
{
$action = $request->getActionName();
if (empty($action)) {
$action = $this->getDefaultAction();
$request->setActionName($action);
}
return $this->formatActionName($action);
}
}
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Controller
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/** Zend_Loader */
require_once 'Zend/Loader.php';
/** Zend_Controller_Action_HelperBroker */
require_once 'Zend/Controller/Action/HelperBroker.php';
/** Zend_Controller_Plugin_Broker */
require_once 'Zend/Controller/Plugin/Broker.php';
/**
* @category Zend
* @package Zend_Controller
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Controller_Front
{
/**
* Base URL
* @var string
*/
protected $_baseUrl = null;
/**
* Directory|ies where controllers are stored
*
* @var string|array
*/
protected $_controllerDir = null;
/**
* Instance of Zend_Controller_Dispatcher_Interface
* @var Zend_Controller_Dispatcher_Interface
*/
protected $_dispatcher = null;
/**
* Singleton instance
*
* Marked only as protected to allow extension of the class. To extend,
* simply override {@link getInstance()}.
*
* @var Zend_Controller_Front
*/
protected static $_instance = null;
/**
* Array of invocation parameters to use when instantiating action
* controllers
* @var array
*/
protected $_invokeParams = [];
/**
* Subdirectory within a module containing controllers; defaults to 'controllers'
* @var string
*/
protected $_moduleControllerDirectoryName = 'controllers';
/**
* Instance of Zend_Controller_Plugin_Broker
* @var Zend_Controller_Plugin_Broker
*/
protected $_plugins = null;
/**
* Instance of Zend_Controller_Request_Abstract
* @var Zend_Controller_Request_Abstract
*/
protected $_request = null;
/**
* Instance of Zend_Controller_Response_Abstract
* @var Zend_Controller_Response_Abstract
*/
protected $_response = null;
/**
* Whether or not to return the response prior to rendering output while in
* {@link dispatch()}; default is to send headers and render output.
* @var boolean
*/
protected $_returnResponse = false;
/**
* Instance of Zend_Controller_Router_Interface
* @var Zend_Controller_Router_Interface
*/
protected $_router = null;
/**
* Whether or not exceptions encountered in {@link dispatch()} should be
* thrown or trapped in the response object
* @var boolean
*/
protected $_throwExceptions = false;
/**
* Constructor
*
* Instantiate using {@link getInstance()}; front controller is a singleton
* object.
*
* Instantiates the plugin broker.
*
* @return void
*/
protected function __construct()
{
$this->_plugins = new Zend_Controller_Plugin_Broker();
}
/**
* Enforce singleton; disallow cloning
*
* @return void
*/
private function __clone()
{
}
/**
* Singleton instance
*
* @return Zend_Controller_Front
*/
public static function getInstance()
{
if (null === self::$_instance) {
self::$_instance = new self();
}
return self::$_instance;
}
/**
* Resets all object properties of the singleton instance
*
* Primarily used for testing; could be used to chain front controllers.
*
* Also resets action helper broker, clearing all registered helpers.
*
* @return void
*/
public function resetInstance()
{
$reflection = new ReflectionObject($this);
foreach ($reflection->getProperties() as $property) {
$name = $property->getName();
switch ($name) {
case '_instance':
break;
case '_controllerDir':
case '_invokeParams':
$this->{$name} = [];
break;
case '_plugins':
$this->{$name} = new Zend_Controller_Plugin_Broker();
break;
case '_throwExceptions':
case '_returnResponse':
$this->{$name} = false;
break;
case '_moduleControllerDirectoryName':
$this->{$name} = 'controllers';
break;
default:
$this->{$name} = null;
break;
}
}
Zend_Controller_Action_HelperBroker::resetHelpers();
}
/**
* Convenience feature, calls setControllerDirectory()->setRouter()->dispatch()
*
* In PHP 5.1.x, a call to a static method never populates $this -- so run()
* may actually be called after setting up your front controller.
*
* @param string|array $controllerDirectory Path to Zend_Controller_Action
* controller classes or array of such paths
* @return void
* @throws Zend_Controller_Exception if called from an object instance
*/
public static function run($controllerDirectory)
{
self::getInstance()
->setControllerDirectory($controllerDirectory)
->dispatch();
}
/**
* Add a controller directory to the controller directory stack
*
* If $args is presented and is a string, uses it for the array key mapping
* to the directory specified.
*
* @param string $directory
* @param string $module Optional argument; module with which to associate directory. If none provided, assumes 'default'
* @return $this
* @throws Zend_Controller_Exception if directory not found or readable
*/
public function addControllerDirectory($directory, $module = null)
{
$this->getDispatcher()->addControllerDirectory($directory, $module);
return $this;
}
/**
* Set controller directory
*
* Stores controller directory(ies) in dispatcher. May be an array of
* directories or a string containing a single directory.
*
* @param string|array $directory Path to Zend_Controller_Action controller
* classes or array of such paths
* @param string $module Optional module name to use with string $directory
* @return $this
*/
public function setControllerDirectory($directory, $module = null)
{
$this->getDispatcher()->setControllerDirectory($directory, $module);
return $this;
}
/**
* Retrieve controller directory
*
* Retrieves:
* - Array of all controller directories if no $name passed
* - String path if $name passed and exists as a key in controller directory array
* - null if $name passed but does not exist in controller directory keys
*
* @param string $name Default null
* @return array|string|null
*/
public function getControllerDirectory($name = null)
{
return $this->getDispatcher()->getControllerDirectory($name);
}
/**
* Remove a controller directory by module name
*
* @param string $module
* @return bool
*/
public function removeControllerDirectory($module)
{
return $this->getDispatcher()->removeControllerDirectory($module);
}
/**
* Specify a directory as containing modules
*
* Iterates through the directory, adding any subdirectories as modules;
* the subdirectory within each module named after {@link $_moduleControllerDirectoryName}
* will be used as the controller directory path.
*
* @param string $path
* @return $this
*/
public function addModuleDirectory($path)
{
try{
$dir = new DirectoryIterator($path);
} catch(Throwable $e) {
require_once 'Zend/Controller/Exception.php';
throw new Zend_Controller_Exception("Directory $path not readable", 0, $e);
}
foreach ($dir as $file) {
if ($file->isDot() || !$file->isDir()) {
continue;
}
$module = $file->getFilename();
// Don't use SCCS directories as modules
if (preg_match('/^[^a-z]/i', $module) || ('CVS' == $module)) {
continue;
}
$moduleDir = $file->getPathname() . DIRECTORY_SEPARATOR . $this->getModuleControllerDirectoryName();
$this->addControllerDirectory($moduleDir, $module);
}
return $this;
}
/**
* Return the path to a module directory (but not the controllers directory within)
*
* @param string $module
* @return string|null
*/
public function getModuleDirectory($module = null)
{
if (null === $module) {
$request = $this->getRequest();
if (null !== $request) {
$module = $this->getRequest()->getModuleName();
}
if (empty($module)) {
$module = $this->getDispatcher()->getDefaultModule();
}
}
$controllerDir = $this->getControllerDirectory($module);
if ((null === $controllerDir) || !is_string($controllerDir)) {
return null;
}
return dirname($controllerDir);
}
/**
* Set the directory name within a module containing controllers
*
* @param string $name
* @return $this
*/
public function setModuleControllerDirectoryName($name = 'controllers')
{
$this->_moduleControllerDirectoryName = (string) $name;
return $this;
}
/**
* Return the directory name within a module containing controllers
*
* @return string
*/
public function getModuleControllerDirectoryName()
{
return $this->_moduleControllerDirectoryName;
}
/**
* Set the default controller (unformatted string)
*
* @param string $controller
* @return $this
*/
public function setDefaultControllerName($controller)
{
$dispatcher = $this->getDispatcher();
$dispatcher->setDefaultControllerName($controller);
return $this;
}
/**
* Retrieve the default controller (unformatted string)
*
* @return string
*/
public function getDefaultControllerName()
{
return $this->getDispatcher()->getDefaultControllerName();
}
/**
* Set the default action (unformatted string)
*
* @param string $action
* @return $this
*/
public function setDefaultAction($action)
{
$dispatcher = $this->getDispatcher();
$dispatcher->setDefaultAction($action);
return $this;
}
/**
* Retrieve the default action (unformatted string)
*
* @return string
*/
public function getDefaultAction()
{
return $this->getDispatcher()->getDefaultAction();
}
/**
* Set the default module name
*
* @param string $module
* @return $this
*/
public function setDefaultModule($module)
{
$dispatcher = $this->getDispatcher();
$dispatcher->setDefaultModule($module);
return $this;
}
/**
* Retrieve the default module
*
* @return string
*/
public function getDefaultModule()
{
return $this->getDispatcher()->getDefaultModule();
}
/**
* Set request class/object
*
* Set the request object. The request holds the request environment.
*
* If a class name is provided, it will instantiate it
*
* @param string|Zend_Controller_Request_Abstract $request
* @throws Zend_Controller_Exception if invalid request class
* @return $this
*/
public function setRequest($request)
{
if (is_string($request)) {
if (!class_exists($request)) {
require_once 'Zend/Loader.php';
Zend_Loader::loadClass($request);
}
$request = new $request();
}
if (!$request instanceof Zend_Controller_Request_Abstract) {
require_once 'Zend/Controller/Exception.php';
throw new Zend_Controller_Exception('Invalid request class');
}
$this->_request = $request;
return $this;
}
/**
* Return the request object.
*
* @return null|Zend_Controller_Request_Abstract
*/
public function getRequest()
{
return $this->_request;
}
/**
* Set router class/object
*
* Set the router object. The router is responsible for mapping
* the request to a controller and action.
*
* If a class name is provided, instantiates router with any parameters
* registered via {@link setParam()} or {@link setParams()}.
*
* @param string|Zend_Controller_Router_Interface $router
* @throws Zend_Controller_Exception if invalid router class
* @return $this
*/
public function setRouter($router)
{
if (is_string($router)) {
if (!class_exists($router)) {
require_once 'Zend/Loader.php';
Zend_Loader::loadClass($router);
}
$router = new $router();
}
if (!$router instanceof Zend_Controller_Router_Interface) {
require_once 'Zend/Controller/Exception.php';
throw new Zend_Controller_Exception('Invalid router class');
}
$router->setFrontController($this);
$this->_router = $router;
return $this;
}
/**
* Return the router object.
*
* Instantiates a Zend_Controller_Router_Rewrite object if no router currently set.
*
* @return Zend_Controller_Router_Interface
*/
public function getRouter()
{
if (null == $this->_router) {
require_once 'Zend/Controller/Router/Rewrite.php';
$this->setRouter(new Zend_Controller_Router_Rewrite());
}
return $this->_router;
}
/**
* Set the base URL used for requests
*
* Use to set the base URL segment of the REQUEST_URI to use when
* determining PATH_INFO, etc. Examples:
* - /admin
* - /myapp
* - /subdir/index.php
*
* Note that the URL should not include the full URI. Do not use:
* - http://example.com/admin
* - http://example.com/myapp
* - http://example.com/subdir/index.php
*
* If a null value is passed, this can be used as well for autodiscovery (default).
*
* @param string $base
* @return $this
* @throws Zend_Controller_Exception for non-string $base
*/
public function setBaseUrl($base = null)
{
if (!is_string($base) && (null !== $base)) {
require_once 'Zend/Controller/Exception.php';
throw new Zend_Controller_Exception('Rewrite base must be a string');
}
$this->_baseUrl = $base;
if ((null !== ($request = $this->getRequest())) && (method_exists($request, 'setBaseUrl'))) {
$request->setBaseUrl($base);
}
return $this;
}
/**
* Retrieve the currently set base URL
*
* @return string|null
*/
public function getBaseUrl()
{
$request = $this->getRequest();
if ((null !== $request) && method_exists($request, 'getBaseUrl')) {
return $request->getBaseUrl();
}
return $this->_baseUrl;
}
/**
* Set the dispatcher object. The dispatcher is responsible for
* taking a Zend_Controller_Dispatcher_Token object, instantiating the controller, and
* call the action method of the controller.
*
* @param Zend_Controller_Dispatcher_Interface $dispatcher
* @return $this
*/
public function setDispatcher(Zend_Controller_Dispatcher_Interface $dispatcher)
{
$this->_dispatcher = $dispatcher;
return $this;
}
/**
* Return the dispatcher object.
*
* @return Zend_Controller_Dispatcher_Interface
*/
public function getDispatcher()
{
/**
* Instantiate the default dispatcher if one was not set.
*/
if (!$this->_dispatcher instanceof Zend_Controller_Dispatcher_Interface) {
require_once 'Zend/Controller/Dispatcher/Standard.php';
$this->_dispatcher = new Zend_Controller_Dispatcher_Standard();
}
return $this->_dispatcher;
}
/**
* Set response class/object
*
* Set the response object. The response is a container for action
* responses and headers. Usage is optional.
*
* If a class name is provided, instantiates a response object.
*
* @param string|Zend_Controller_Response_Abstract $response
* @throws Zend_Controller_Exception if invalid response class
* @return $this
*/
public function setResponse($response)
{
if (is_string($response)) {
if (!class_exists($response)) {
require_once 'Zend/Loader.php';
Zend_Loader::loadClass($response);
}
$response = new $response();
}
if (!$response instanceof Zend_Controller_Response_Abstract) {
require_once 'Zend/Controller/Exception.php';
throw new Zend_Controller_Exception('Invalid response class');
}
$this->_response = $response;
return $this;
}
/**
* Return the response object.
*
* @return null|Zend_Controller_Response_Abstract
*/
public function getResponse()
{
return $this->_response;
}
/**
* Add or modify a parameter to use when instantiating an action controller
*
* @param string $name
* @param mixed $value
* @return $this
*/
public function setParam($name, $value)
{
$name = (string) $name;
$this->_invokeParams[$name] = $value;
return $this;
}
/**
* Set parameters to pass to action controller constructors
*
* @param array $params
* @return $this
*/
public function setParams(array $params)
{
$this->_invokeParams = array_merge($this->_invokeParams, $params);
return $this;
}
/**
* Retrieve a single parameter from the controller parameter stack
*
* @param string $name
* @return mixed
*/
public function getParam($name)
{
if(isset($this->_invokeParams[$name])) {
return $this->_invokeParams[$name];
}
return null;
}
/**
* Retrieve action controller instantiation parameters
*
* @return array
*/
public function getParams()
{
return $this->_invokeParams;
}
/**
* Clear the controller parameter stack
*
* By default, clears all parameters. If a parameter name is given, clears
* only that parameter; if an array of parameter names is provided, clears
* each.
*
* @param null|string|array $name single key or array of keys for params to clear
* @return $this
*/
public function clearParams($name = null)
{
if (null === $name) {
$this->_invokeParams = [];
} elseif (is_string($name) && isset($this->_invokeParams[$name])) {
unset($this->_invokeParams[$name]);
} elseif (is_array($name)) {
foreach ($name as $key) {
if (is_string($key) && isset($this->_invokeParams[$key])) {
unset($this->_invokeParams[$key]);
}
}
}
return $this;
}
/**
* Register a plugin.
*
* @param Zend_Controller_Plugin_Abstract $plugin
* @param int $stackIndex Optional; stack index for plugin
* @return $this
*/
public function registerPlugin(Zend_Controller_Plugin_Abstract $plugin, $stackIndex = null)
{
$this->_plugins->registerPlugin($plugin, $stackIndex);
return $this;
}
/**
* Unregister a plugin.
*
* @param string|Zend_Controller_Plugin_Abstract $plugin Plugin class or object to unregister
* @return $this
*/
public function unregisterPlugin($plugin)
{
$this->_plugins->unregisterPlugin($plugin);
return $this;
}
/**
* Is a particular plugin registered?
*
* @param string $class
* @return bool
*/
public function hasPlugin($class)
{
return $this->_plugins->hasPlugin($class);
}
/**
* Retrieve a plugin or plugins by class
*
* @param string $class
* @return false|Zend_Controller_Plugin_Abstract|array
*/
public function getPlugin($class)
{
return $this->_plugins->getPlugin($class);
}
/**
* Retrieve all plugins
*
* @return array
*/
public function getPlugins()
{
return $this->_plugins->getPlugins();
}
/**
* Set the throwExceptions flag and retrieve current status
*
* Set whether exceptions encounted in the dispatch loop should be thrown
* or caught and trapped in the response object.
*
* Default behaviour is to trap them in the response object; call this
* method to have them thrown.
*
* Passing no value will return the current value of the flag; passing a
* boolean true or false value will set the flag and return the current
* object instance.
*
* @param boolean $flag Defaults to null (return flag state)
* @return boolean|Zend_Controller_Front Used as a setter, returns object; as a getter, returns boolean
*/
public function throwExceptions($flag = null)
{
if ($flag !== null) {
$this->_throwExceptions = (bool) $flag;
return $this;
}
return $this->_throwExceptions;
}
/**
* Set whether {@link dispatch()} should return the response without first
* rendering output. By default, output is rendered and dispatch() returns
* nothing.
*
* @param boolean $flag
* @return boolean|Zend_Controller_Front Used as a setter, returns object; as a getter, returns boolean
*/
public function returnResponse($flag = null)
{
if (true === $flag) {
$this->_returnResponse = true;
return $this;
} elseif (false === $flag) {
$this->_returnResponse = false;
return $this;
}
return $this->_returnResponse;
}
/**
* Dispatch an HTTP request to a controller/action.
*
* @param Zend_Controller_Request_Abstract|null $request
* @param Zend_Controller_Response_Abstract|null $response
* @return void|Zend_Controller_Response_Abstract Returns response object if returnResponse() is true
*/
public function dispatch(?Zend_Controller_Request_Abstract $request = null, ?Zend_Controller_Response_Abstract $response = null)
{
if (!$this->getParam('noErrorHandler') && !$this->_plugins->hasPlugin('Zend_Controller_Plugin_ErrorHandler')) {
// Register with stack index of 100
require_once 'Zend/Controller/Plugin/ErrorHandler.php';
$this->_plugins->registerPlugin(new Zend_Controller_Plugin_ErrorHandler(), 100);
}
if (!$this->getParam('noViewRenderer') && !Zend_Controller_Action_HelperBroker::hasHelper('viewRenderer')) {
require_once 'Zend/Controller/Action/Helper/ViewRenderer.php';
Zend_Controller_Action_HelperBroker::getStack()->offsetSet(-80, new Zend_Controller_Action_Helper_ViewRenderer());
}
/**
* Instantiate default request object (HTTP version) if none provided
*/
if ($request !== null) {
$this->setRequest($request);
} elseif ((null === $request) && (null === ($request = $this->getRequest()))) {
require_once 'Zend/Controller/Request/Http.php';
$request = new Zend_Controller_Request_Http();
$this->setRequest($request);
}
/**
* Set base URL of request object, if available
*/
if (is_callable([$this->_request, 'setBaseUrl'])) {
if (null !== $this->_baseUrl) {
$this->_request->setBaseUrl($this->_baseUrl);
}
}
/**
* Instantiate default response object (HTTP version) if none provided
*/
if ($response !== null) {
$this->setResponse($response);
} elseif ((null === $this->_response) && (null === ($this->_response = $this->getResponse()))) {
require_once 'Zend/Controller/Response/Http.php';
$response = new Zend_Controller_Response_Http();
$this->setResponse($response);
}
/**
* Register request and response objects with plugin broker
*/
$this->_plugins
->setRequest($this->_request)
->setResponse($this->_response);
/**
* Initialize router
*/
$router = $this->getRouter();
$router->setParams($this->getParams());
/**
* Initialize dispatcher
*/
$dispatcher = $this->getDispatcher();
$dispatcher->setParams($this->getParams())
->setResponse($this->_response);
// Begin dispatch
try {
/**
* Route request to controller/action, if a router is provided
*/
/**
* Notify plugins of router startup
*/
$this->_plugins->routeStartup($this->_request);
try {
$router->route($this->_request);
} catch (Throwable $e) {
if ($this->throwExceptions()) {
throw $e;
}
$this->_response->setException($e);
}
/**
* Notify plugins of router completion
*/
$this->_plugins->routeShutdown($this->_request);
/**
* Notify plugins of dispatch loop startup
*/
$this->_plugins->dispatchLoopStartup($this->_request);
/**
* Attempt to dispatch the controller/action. If the $this->_request
* indicates that it needs to be dispatched, move to the next
* action in the request.
*/
do {
$this->_request->setDispatched(true);
/**
* Notify plugins of dispatch startup
*/
$this->_plugins->preDispatch($this->_request);
/**
* Skip requested action if preDispatch() has reset it
*/
if (!$this->_request->isDispatched()) {
continue;
}
/**
* Dispatch request
*/
try {
$dispatcher->dispatch($this->_request, $this->_response);
} catch (Throwable $e) {
if ($this->throwExceptions()) {
throw $e;
}
$this->_response->setException($e);
}
/**
* Notify plugins of dispatch completion
*/
$this->_plugins->postDispatch($this->_request);
} while (!$this->_request->isDispatched());
} catch (Throwable $e) {
if ($this->throwExceptions()) {
throw $e;
}
$this->_response->setException($e);
}
/**
* Notify plugins of dispatch loop completion
*/
try {
$this->_plugins->dispatchLoopShutdown();
} catch (Throwable $e) {
if ($this->throwExceptions()) {
throw $e;
}
$this->_response->setException($e);
}
if ($this->returnResponse()) {
return $this->_response;
}
$this->_response->sendResponse();
}
}
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Application
* @subpackage Bootstrap
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Application_Bootstrap_BootstrapAbstract
*/
require_once 'Zend/Application/Bootstrap/BootstrapAbstract.php';
/**
* Concrete base class for bootstrap classes
*
* Registers and utilizes Zend_Controller_Front by default.
*
* @uses Zend_Application_Bootstrap_Bootstrap
* @category Zend
* @package Zend_Application
* @subpackage Bootstrap
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
#[AllowDynamicProperties]
class Zend_Application_Bootstrap_Bootstrap
extends Zend_Application_Bootstrap_BootstrapAbstract
{
/**
* Application resource namespace
* @var false|string
*/
protected $_appNamespace = false;
/**
* Application resource autoloader
* @var Zend_Loader_Autoloader_Resource
*/
protected $_resourceLoader;
/**
* Constructor
*
* Ensure FrontController resource is registered
*
* @param Zend_Application|Zend_Application_Bootstrap_Bootstrapper $application
*/
public function __construct($application)
{
parent::__construct($application);
if ($application->hasOption('resourceloader')) {
$this->setOptions(
[
'resourceloader' => $application->getOption(
'resourceloader'
)
]
);
}
$this->getResourceLoader();
if (!$this->hasPluginResource('FrontController')) {
$this->registerPluginResource('FrontController');
}
}
/**
* Run the application
*
* Checks to see that we have a default controller directory. If not, an
* exception is thrown.
*
* If so, it registers the bootstrap with the 'bootstrap' parameter of
* the front controller, and dispatches the front controller.
*
* @return mixed
* @throws Zend_Application_Bootstrap_Exception
*/
public function run()
{
$front = $this->getResource('FrontController');
$default = $front->getDefaultModule();
if (null === $front->getControllerDirectory($default)) {
throw new Zend_Application_Bootstrap_Exception(
'No default controller directory registered with front controller'
);
}
$front->setParam('bootstrap', $this);
$response = $front->dispatch();
if ($front->returnResponse()) {
return $response;
}
}
/**
* Set module resource loader
*
* @param Zend_Loader_Autoloader_Resource $loader
* @return Zend_Application_Bootstrap_Bootstrap
*/
public function setResourceLoader(Zend_Loader_Autoloader_Resource $loader)
{
$this->_resourceLoader = $loader;
return $this;
}
/**
* Retrieve module resource loader
*
* @return Zend_Loader_Autoloader_Resource
*/
public function getResourceLoader()
{
if ((null === $this->_resourceLoader)
&& (false !== ($namespace = $this->getAppNamespace()))
) {
$r = new ReflectionClass($this);
$path = $r->getFileName();
$this->setResourceLoader(
new Zend_Application_Module_Autoloader(
[
'namespace' => $namespace,
'basePath' => dirname($path),
]
)
);
}
return $this->_resourceLoader;
}
/**
* Get application namespace (used for module autoloading)
*
* @return string
*/
public function getAppNamespace()
{
return $this->_appNamespace;
}
/**
* Set application namespace (for module autoloading)
*
* @param string $value
* @return Zend_Application_Bootstrap_Bootstrap
*/
public function setAppNamespace($value)
{
$this->_appNamespace = (string) $value;
return $this;
}
}
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Application
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @category Zend
* @package Zend_Application
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Application
{
/**
* Autoloader to use
*
* @var Zend_Loader_Autoloader
*/
protected $_autoloader;
/**
* Bootstrap
*
* @var Zend_Application_Bootstrap_BootstrapAbstract
*/
protected $_bootstrap;
/**
* Application environment
*
* @var string
*/
protected $_environment;
/**
* Flattened (lowercase) option keys
*
* @var array
*/
protected $_optionKeys = [];
/**
* Options for Zend_Application
*
* @var array
*/
protected $_options = [];
/**
* For bootstrapping the config we probably need to pass configuration to the config parsers.
* Since options are not set up yet, we use this static array to pass configurations to the config parsers.
*
* @var array|null
*/
protected static $configParserOptions = null;
/**
* Sets a configuration array to be used for the config parsers on loading the configuration from files
* @param array $configParserOptions
*/
public static function setConfigParserOptions(array $configParserOptions) {
self::$configParserOptions = $configParserOptions;
}
/**
* Constructor
*
* Initialize application. Potentially initializes include_paths, PHP
* settings, and bootstrap class.
*
* @param string $environment
* @param string|array|Zend_Config $options String path to configuration file, or array/Zend_Config of configuration options
* @param bool $suppressNotFoundWarnings Should warnings be suppressed when a file is not found during autoloading?
* @throws Zend_Application_Exception When invalid options are provided
* @return void
*/
public function __construct($environment, $options = null, $suppressNotFoundWarnings = null)
{
$this->_environment = (string) $environment;
require_once 'Zend/Loader/Autoloader.php';
$this->_autoloader = Zend_Loader_Autoloader::getInstance();
$this->_autoloader->suppressNotFoundWarnings($suppressNotFoundWarnings);
if (null !== $options) {
if (is_string($options)) {
$options = $this->_loadConfig($options);
} elseif ($options instanceof Zend_Config) {
$options = $options->toArray();
} elseif (!is_array($options)) {
throw new Zend_Application_Exception(
'Invalid options provided; must be location of config file,'
. ' a config object, or an array'
);
}
$this->setOptions($options);
}
}
/**
* Retrieve current environment
*
* @return string
*/
public function getEnvironment()
{
return $this->_environment;
}
/**
* Retrieve autoloader instance
*
* @return Zend_Loader_Autoloader
*/
public function getAutoloader()
{
return $this->_autoloader;
}
/**
* Set application options
*
* @param array $options
* @throws Zend_Application_Exception When no bootstrap path is provided
* @throws Zend_Application_Exception When invalid bootstrap information are provided
* @return Zend_Application
*/
public function setOptions(array $options)
{
if (!empty($options['config'])) {
if (is_array($options['config'])) {
$_options = [];
foreach ($options['config'] as $tmp) {
$_options = $this->mergeOptions(
$_options, $this->_loadConfig($tmp)
);
}
$options = $this->mergeOptions($_options, $options);
} else {
$options = $this->mergeOptions(
$this->_loadConfig($options['config']), $options
);
}
}
$this->_options = $options;
$options = array_change_key_case($options, CASE_LOWER);
$this->_optionKeys = array_keys($options);
if (!empty($options['phpsettings'])) {
$this->setPhpSettings($options['phpsettings']);
}
if (!empty($options['includepaths'])) {
$this->setIncludePaths($options['includepaths']);
}
if (!empty($options['autoloadernamespaces'])) {
$this->setAutoloaderNamespaces($options['autoloadernamespaces']);
}
if (!empty($options['autoloaderzfpath'])) {
$autoloader = $this->getAutoloader();
if (method_exists($autoloader, 'setZfPath')) {
$zfPath = $options['autoloaderzfpath'];
$zfVersion = !empty($options['autoloaderzfversion'])
? $options['autoloaderzfversion']
: 'latest';
$autoloader->setZfPath($zfPath, $zfVersion);
}
}
if (!empty($options['bootstrap'])) {
$bootstrap = $options['bootstrap'];
if (is_string($bootstrap)) {
$this->setBootstrap($bootstrap);
} elseif (is_array($bootstrap)) {
if (empty($bootstrap['path'])) {
throw new Zend_Application_Exception(
'No bootstrap path provided'
);
}
$path = $bootstrap['path'];
$class = null;
if (!empty($bootstrap['class'])) {
$class = $bootstrap['class'];
}
$this->setBootstrap($path, $class);
} else {
throw new Zend_Application_Exception(
'Invalid bootstrap information provided'
);
}
}
return $this;
}
/**
* Retrieve application options (for caching)
*
* @return array
*/
public function getOptions()
{
return $this->_options;
}
/**
* Is an option present?
*
* @param string $key
* @return bool
*/
public function hasOption($key)
{
return in_array(strtolower($key), $this->_optionKeys);
}
/**
* Retrieve a single option
*
* @param string $key
* @return mixed
*/
public function getOption($key)
{
if ($this->hasOption($key)) {
$options = $this->getOptions();
$options = array_change_key_case($options, CASE_LOWER);
return $options[strtolower($key)];
}
return null;
}
/**
* Merge options recursively
*
* @param array $array1
* @param mixed $array2
* @return array
*/
public function mergeOptions(array $array1, $array2 = null)
{
if (is_array($array2)) {
foreach ($array2 as $key => $val) {
if (is_array($val)) {
$array1[$key] = (array_key_exists($key, $array1) && is_array($array1[$key]))
? $this->mergeOptions($array1[$key], $val)
: $val;
} else {
$array1[$key] = $val;
}
}
}
return $array1;
}
/**
* Set PHP configuration settings
*
* @param array $settings
* @param string $prefix Key prefix to prepend to array values (used to map . separated INI values)
* @return Zend_Application
*/
public function setPhpSettings(array $settings, $prefix = '')
{
foreach ($settings as $key => $value) {
$key = empty($prefix) ? $key : $prefix . $key;
if (is_scalar($value)) {
ini_set($key, $value);
} elseif (is_array($value)) {
$this->setPhpSettings($value, $key . '.');
}
}
return $this;
}
/**
* Set include path
*
* @param array $paths
* @return Zend_Application
*/
public function setIncludePaths(array $paths)
{
$path = implode(PATH_SEPARATOR, $paths);
set_include_path($path . PATH_SEPARATOR . get_include_path());
return $this;
}
/**
* Set autoloader namespaces
*
* @param array $namespaces
* @return Zend_Application
*/
public function setAutoloaderNamespaces(array $namespaces)
{
$autoloader = $this->getAutoloader();
foreach ($namespaces as $namespace) {
$autoloader->registerNamespace($namespace);
}
return $this;
}
/**
* Set bootstrap path/class
*
* @param string $path
* @param string $class
* @return Zend_Application
*/
public function setBootstrap($path, $class = null)
{
// setOptions() can potentially send a null value; specify default
// here
if (null === $class) {
$class = 'Bootstrap';
}
if (!class_exists($class, false)) {
require_once $path;
if (!class_exists($class, false)) {
throw new Zend_Application_Exception(
'Bootstrap class not found'
);
}
}
$this->_bootstrap = new $class($this);
if (!$this->_bootstrap instanceof Zend_Application_Bootstrap_Bootstrapper) {
throw new Zend_Application_Exception(
'Bootstrap class does not implement'
. ' Zend_Application_Bootstrap_Bootstrapper'
);
}
return $this;
}
/**
* Get bootstrap object
*
* @return Zend_Application_Bootstrap_BootstrapAbstract
*/
public function getBootstrap()
{
if (null === $this->_bootstrap) {
$this->_bootstrap = new Zend_Application_Bootstrap_Bootstrap($this);
}
return $this->_bootstrap;
}
/**
* Bootstrap application
*
* @param null|string|array $resource
* @return Zend_Application
*/
public function bootstrap($resource = null)
{
$this->getBootstrap()->bootstrap($resource);
return $this;
}
/**
* Run the application
*
* @return void
*/
public function run()
{
$this->getBootstrap()->run();
}
/**
* Load configuration file of options
*
* @param string $file
* @throws Zend_Application_Exception When invalid configuration file is provided
* @return array
*/
protected function _loadConfig($file)
{
$environment = $this->getEnvironment();
$suffix = pathinfo($file, PATHINFO_EXTENSION);
$suffix = ($suffix === 'dist')
? pathinfo(basename($file, ".$suffix"), PATHINFO_EXTENSION)
: $suffix;
$configParserOptions = self::$configParserOptions ?? false;
switch (strtolower($suffix)) {
case 'ini':
$config = new Zend_Config_Ini($file, $environment, $configParserOptions);
break;
case 'xml':
$config = new Zend_Config_Xml($file, $environment, $configParserOptions);
break;
case 'json':
$config = new Zend_Config_Json($file, $environment, $configParserOptions);
break;
case 'yaml':
case 'yml':
$config = new Zend_Config_Yaml($file, $environment, $configParserOptions);
break;
case 'php':
case 'inc':
$config = include $file;
if (!is_array($config)) {
throw new Zend_Application_Exception(
'Invalid configuration file provided; PHP file does not'
. ' return array value'
);
}
return $config;
break;
default:
throw new Zend_Application_Exception(
'Invalid configuration file provided; unknown config type'
);
}
return $config->toArray();
}
}
<?php
// Define path to application directory
defined('APPLICATION_PATH')
|| define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));
// Define application environment
defined('APPLICATION_ENV')
|| define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production'));
// Ensure library/ is on include_path
set_include_path(implode(PATH_SEPARATOR, array(
realpath(APPLICATION_PATH . '/../library'),
realpath(APPLICATION_PATH . '/../vendor/shardj/zf1-future/library'),
realpath(APPLICATION_PATH . '/models'),
realpath(APPLICATION_PATH . '/validate'),
get_include_path(),
)));
require_once APPLICATION_PATH . '/../vendor/autoload.php';
/** Zend_Application */
require_once 'Zend/Application.php';
require_once 'version.php';
require_once 'Contextly/Sentry.php';
Contextly_Sentry::init();
// Create application, bootstrap, and run
$application = new Zend_Application(
APPLICATION_ENV,
array('config' => array(
APPLICATION_PATH . '/configs/application.ini',
APPLICATION_PATH . '/configs/application.secrets.ini',
))
);
$application->bootstrap()
->run();
// Some global function here
function getmicrotime() {
list($usec, $sec) = explode(" ",microtime());
return ((float)$usec + (float)$sec);
}