/standard/tags/release-1.0.2/library/Zend/Controller/Dispatcher/Standard.php
PHP | 418 lines | 191 code | 48 blank | 179 comment | 28 complexity | 0bd49b879e9fc4878e01a490ba8dc014 MD5 | raw file
- <?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-2007 Zend Technologies USA Inc. (http://www.zend.com)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- */
- /** Zend_Loader */
- require_once 'Zend/Loader.php';
- /** Zend_Controller_Dispatcher_Abstract */
- require_once 'Zend/Controller/Dispatcher/Abstract.php';
- /** Zend_Controller_Request_Abstract */
- require_once 'Zend/Controller/Request/Abstract.php';
- /** Zend_Controller_Response_Abstract */
- require_once 'Zend/Controller/Response/Abstract.php';
- /** Zend_Controller_Action */
- require_once 'Zend/Controller/Action.php';
- /**
- * @category Zend
- * @package Zend_Controller
- * @subpackage Dispatcher
- * @copyright Copyright (c) 2005-2007 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;
- /**
- * Constructor: Set current module to default value
- *
- * @param array $params
- * @return void
- */
- public function __construct(array $params = array())
- {
- parent::__construct($params);
- $this->_curModule = $this->getDefaultModule();
- }
- /**
- * Add a single path to the controller directory stack
- *
- * @param string $path
- * @param string $module
- * @return Zend_Controller_Dispatcher_Standard
- */
- public function addControllerDirectory($path, $module = null)
- {
- if (null === $module) {
- $module = $this->_defaultModule;
- }
- $this->getFrontController()->addControllerDirectory($path, $module);
- return $this;
- }
- /**
- * Set controller directory
- *
- * @param array|string $directory
- * @return Zend_Controller_Dispatcher_Standard
- */
- public function setControllerDirectory($directory)
- {
- $this->getFrontController()->setControllerDirectory($directory);
- 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 Returns array of all directories by default, single
- * module directory if module argument provided
- */
- public function getControllerDirectory($module = null)
- {
- $directories = $this->getFrontController()->getControllerDirectory();
- if ((null !== $module) && (isset($directories[$module]))) {
- return $directories[$module];
- }
- return $directories;
- }
- /**
- * Format the module name.
- *
- * @param string $unformatted
- * @return string
- */
- public function formatModuleName($unformatted)
- {
- if ($this->_defaultModule == $unformatted) {
- return $unformatted;
- }
- return ucfirst($this->_formatName($unformatted));
- }
- /**
- * 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;
- }
- $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 boolean
- * @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);
- }
- }
- /**
- * 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 $className($request, $this->getResponse(), $this->getParams());
- if (!$controller instanceof Zend_Controller_Action) {
- require_once 'Zend/Controller/Dispatcher/Exception.php';
- throw new Zend_Controller_Dispatcher_Exception("Controller '$className' is not an instance of Zend_Controller_Action");
- }
- /**
- * 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 (Exception $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)
- {
- $dispatchDir = $this->getDispatchDirectory();
- $loadFile = $dispatchDir . DIRECTORY_SEPARATOR . $this->classToFilename($className);
- $dir = dirname($loadFile);
- $file = basename($loadFile);
- try {
- Zend_Loader::loadFile($file, $dir, true);
- } catch (Zend_Exception $e) {
- require_once 'Zend/Controller/Dispatcher/Exception.php';
- throw new Zend_Controller_Dispatcher_Exception('Cannot load controller class "' . $className . '" from file "' . $file . '" in directory "' . $dir . '"');
- }
- if ($this->_defaultModule != $this->_curModule) {
- $className = $this->formatModuleName($this->_curModule) . '_' . $className;
- }
- if (!class_exists($className)) {
- require_once 'Zend/Controller/Dispatcher/Exception.php';
- throw new Zend_Controller_Dispatcher_Exception('Invalid controller class ("' . $className . '")');
- }
- return $className;
- }
- /**
- * 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();
- $this->_curModule = $this->_defaultModule;
- $this->_curDirectory = $controllerDirs[$this->_defaultModule];
- $module = $request->getModuleName();
- if ($this->isValidModule($module)) {
- $this->_curModule = $module;
- $this->_curDirectory = $controllerDirs[$module];
- } else {
- $request->setModuleName($this->_curModule);
- }
- return $className;
- }
- /**
- * Determine if a given module is valid
- *
- * @param string $module
- * @return bool
- */
- public function isValidModule($module)
- {
- $controllerDir = $this->getControllerDirectory();
- return ((null !== $module) && isset($controllerDir[$module]));
- }
- /**
- * 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)) {
- $moduleDir = $controllerDirs[$module];
- $fileSpec = $moduleDir . DIRECTORY_SEPARATOR . $this->classToFilename($default);
- if (Zend_Loader::isReadable($fileSpec)) {
- $request->setModuleName($module);
- $this->_curModule = $this->formatModuleName($module);
- $this->_curDirectory = $moduleDir;
- }
- } 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);
- }
- }