Mon Aug 7 02:54:40 PHT 2006 Nimrod A. Abing * Delegate controller actions to an Action class. This modification allows the client code to implement actions in separate classes. It is comprised of two parts: 1. A custom dispatcher capable of loading an Action class if action is not found to be in the controller's methods. 2. An Action base class. Rationale: Implementing actions as methods of the controller class can become unwieldy especially with very large applications. Most of the time, only one of those action methods is invoked. The PHP engine still has to parse through the whole controller class file. By moving out the actions into separate class files that are loaded on demand the overhead of parsing through a large file consisting mainly of dead code is avoided. Because an action class is self-contained, it is now safe to implement a more structured approach in implementing methods through the use of small helper methods in the action class. Full Description: First and foremost, the goal of this modification is to be backwards compatible with existing code. This will help in migration towards using action classes. Secondly, missing action classes must not disrupt the normal dispatching of the request. Missing action classes will not trigger a special error. Instead, the usual "Missing Method in Controller..." errors will be generated. Finally, plugins should be able to use action classes as well. How to implement an action class-based CakePHP app: 1. Edit app/config/core.php and set CUSTOM_DISPATCHER to 'acDispatcher'. 2. For each controller create a folder in app/controllers/ with the same name as the controller following the usual CakePHP naming conventions. 3. Override app_action.php if desired. Place your custom app_action.php in app/app_action.php. 4. Create an action class file inside app/controllers/controller_name. We also follow the CakePHP naming conventions here. 5. Implement the method perform() in your action class. This is the same as creating an action as a method in your controller. If your action accepts parameters, specify them as such in the parameter list for perform(). For example: http://example.com/ctrl/index/ Create the directory app/controllers/ctrl Create the file app/controllers/ctrl/index_action.php Define IndexAction in index_action.php defining the perform() method. Notes: - You get a reference to the controller in $this->controller. - All the properties of the controller can also be referenced in the context of the action itself. For instance, the $uses property is also available as a reference using $this->uses. For plugins, simply follow the usual conventions as above in addition to the CakePHP plugin conventions. diff -rN -u old-cake/app/ac_dispatcher.php new-cake/app/ac_dispatcher.php --- old-cake/app/ac_dispatcher.php 1970-01-01 08:00:00.000000000 +0800 +++ new-cake/app/ac_dispatcher.php 2006-08-07 03:26:42.000000000 +0800 @@ -0,0 +1,368 @@ + + * Copyright (c) 2006, Cake Software Foundation, Inc. + * 1785 E. Sahara Avenue, Suite 490-204 + * Las Vegas, Nevada 89104 + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @filesource + * @copyright Copyright (c) 2006, Cake Software Foundation, Inc. + * @link http://abing.gotdns.com/cake/diffs/ CakePHP-Diffs Project + * @package cake + * @subpackage cake.app + * @since CakePHP v 1.1.6.3346-diffs + * @version $Revision$ + * @modifiedby $LastChangedBy$ + * @lastmodified $Date$ + * @license http://www.opensource.org/licenses/mit-license.php The MIT License + */ +/** + * List of helpers to include + */ + uses(DS.'controller'.DS.'action'); + +/** + * Dispatcher translates URLs to controller-action-paramter triads. + * + * Dispatches the request, creating appropriate models and controllers. + * + * @package cake + * @subpackage cake.app + */ +class acDispatcher extends Dispatcher { + var $useActionClass; + + function __construct() { + parent::__construct(); + } +/** + * Dispatches and invokes given URL, handing over control to the involved controllers, and then renders the results (if autoRender is set). + * + * If no controller of given name can be found, invoke() shows error messages in + * the form of Missing Controllers information. It does the same with Actions (methods of Controllers are called + * Actions). + * + * @param string $url URL information to work on. + * @param array $additionalParams Settings array ("bare", "return"), + * which is melded with the GET and POST params. + * @return boolean Success + */ + function dispatch($url, $additionalParams=array()) { + $params = array_merge($this->parseParams($url), $additionalParams); + $missingController = false; + $missingAction = false; + $missingView = false; + $privateAction = false; + $this->base = $this->baseUrl(); + $this->useActionClass = false; + + if (empty($params['controller'])) { + $missingController = true; + } else { + $ctrlName = Inflector::camelize($params['controller']); + $ctrlClass = $ctrlName.'Controller'; + + if(!class_exists($ctrlClass)) { + if (!loadController($ctrlName)) { + $pluginName = Inflector::camelize($params['action']); + if (!loadPluginController(Inflector::underscore($ctrlName), $pluginName)) { + if(preg_match('/([\\.]+)/', $ctrlName)) { + return $this->cakeError('error404', array( + array('url' => strtolower($ctrlName), + 'message' => 'Was not found on this server', + 'base' => $this->base))); + exit(); + } else { + $missingController = true; + } + } else { + $params['plugin'] = Inflector::underscore($ctrlName); + } + } else { + $params['plugin'] = null; + $this->plugin = null; + } + } + } + + if(isset($params['plugin'])){ + $plugin = $params['plugin']; + $pluginName = Inflector::camelize($params['action']); + $pluginClass = $pluginName.'Controller'; + $ctrlClass = $pluginClass; + $oldAction = $params['action']; + $params = $this->_restructureParams($params); + $this->plugin = $plugin; + loadPluginModels($plugin); + $this->base = $this->base.'/'.Inflector::underscore($ctrlName); + + if(empty($params['controller']) || !class_exists($pluginClass)) { + $params['controller'] = Inflector::underscore($ctrlName); + $ctrlClass = $ctrlName.'Controller'; + if (!is_null($params['action'])) { + array_unshift($params['pass'], $params['action']); + } + $params['action'] = $oldAction; + } + } + + if(defined('CAKE_ADMIN')) { + if(isset($params[CAKE_ADMIN])) { + $this->admin = '/'.CAKE_ADMIN ; + $url = preg_replace('/'.CAKE_ADMIN.'\//', '', $url); + + if (empty($params['action'])) { + $params['action'] = CAKE_ADMIN.'_'.'index'; + } else { + $params['action'] = CAKE_ADMIN.'_'.$params['action']; + } + } else { + $__access = strpos($params['action'], CAKE_ADMIN); + if ($__access !== false) { + $privateAction = true; + } + } + } + + if ($missingController) { + return $this->cakeError('missingController', array( + array('className' => Inflector::camelize($params['controller']."Controller"), + 'webroot' => $this->webroot, + 'url' => $url, + 'base' => $this->base))); + } else { + $controller =& new $ctrlClass(); + } + + $classMethods = get_class_methods($controller); + $classVars = get_object_vars($controller); + + if (empty($params['action'])) { + $params['action'] = 'index'; + } + + if((in_array($params['action'], $classMethods) || in_array(strtolower($params['action']), $classMethods)) && (in_array(strtolower($params['action']), $controller->hiddenMethods) || strpos($params['action'], '_', 0) === 0)) { + $privateAction = true; + } + + if(!in_array($params['action'], $classMethods) && !in_array(strtolower($params['action']), $classMethods)) { + $missingAction = true; + } + + if (in_array(strtolower($params['action']), array('beforefilter', 'beforerender', 'afterfilter'))) { + $missingAction = true; + } + elseif ($missingAction) { + if (isset($params['plugin'])) { + $missingAction = (false === loadPluginControllerAction($params['plugin'], $params['controller'], $params['action'])); + } + else { + $missingAction = (false === loadControllerAction($params['controller'], $params['action'])); + } + if (!$missingAction) { + $this->useActionClass = true; + } + } + + if(in_array('return', array_keys($params)) && $params['return'] == 1) { + $controller->autoRender = false; + } + + $controller->base = $this->base; + $base = strip_plugin($this->base, $this->plugin); + if(defined("BASE_URL")){ + $controller->here = $base . $this->admin . $url; + } else { + $controller->here = $base . $this->admin . '/' . $url; + } + $controller->webroot = $this->webroot; + $controller->params = $params; + $controller->action = $params['action']; + + if (!empty($controller->params['data'])) { + $controller->data =& $controller->params['data']; + } else { + $controller->data = null; + } + + if (!empty($controller->params['pass'])) { + $controller->passed_args =& $controller->params['pass']; + $controller->passedArgs =& $controller->params['pass']; + } else { + $controller->passed_args = null; + $controller->passedArgs = null; + } + + if (!empty($params['bare'])) { + $controller->autoLayout = !$params['bare']; + } else { + $controller->autoLayout = $controller->autoLayout; + } + + $controller->webservices = $params['webservices']; + $controller->plugin = $this->plugin; + + if(!is_null($controller->webservices)) { + array_push($controller->components, $controller->webservices); + array_push($controller->helpers, $controller->webservices); + $component =& new Component($controller); + } + $controller->_initComponents(); + $controller->constructClasses(); + + if ($missingAction && !in_array('scaffold', array_keys($classVars))){ + return $this->cakeError('missingAction', array( + array('className' => Inflector::camelize($params['controller']."Controller"), + 'action' => $params['action'], + 'webroot' => $this->webroot, + 'url' => $url, + 'base' => $this->base))); + } + + if (defined('CUSTOM_DISPATCHER_ERROR') && CUSTOM_DISPATCHER_ERROR === true) { + return $this->cakeError('missingDispatcher', array( + array('className' => CUSTOM_DISPATCHER, + 'dispatcher' => CUSTOM_DISPATCHER, + 'webroot' => $this->webroot, + 'url' => $url, + 'base' => $this->base))); + } + + if ($privateAction){ + return $this->cakeError('privateAction', array( + array('className' => Inflector::camelize($params['controller']."Controller"), + 'action' => $params['action'], + 'webroot' => $this->webroot, + 'url' => $url, + 'base' => $this->base))); + } + return $this->_invoke($controller, $params, $missingAction); + } +/** + * Invokes given controller's render action if autoRender option is set. Otherwise the contents of the operation are returned as a string. + * + * @param object $controller + * @param array $params + * @param boolean $missingAction + * @return string + */ + function _invoke (&$controller, $params, $missingAction = false) { + $this->start($controller); + $classVars = get_object_vars($controller); + + if ($missingAction && in_array('scaffold', array_keys($classVars))) { + uses(DS.'controller'.DS.'scaffold'); + return new Scaffold($controller, $params); + } else { + if ($this->useActionClass) { + $actionClass = Inflector::camelize($params['action']).'Action'; + $action =& new $actionClass(); + $action->setController($controller); + $output = call_user_func_array(array(&$action, 'perform'), empty($params['pass'])? null: $params['pass']); + } else { + $output = call_user_func_array(array(&$controller, $params['action']), empty($params['pass'])? null: $params['pass']); + } + } + if ($controller->autoRender) { + $output = $controller->render(); + } + $controller->output =& $output; + $controller->afterFilter(); + return $controller->output; + } +} + +/* + * Functions used by acdispatcher + */ + +/** + * Loads an action class for a controller. + * + * @param string $controller Name of controller + * @param string $name Name of action + * @return boolean Success + */ + function loadControllerAction($controller, $name) { + $paths = Configure::getInstance(); + if (!class_exists('AppAction')) { + if (file_exists(APP . 'app_action.php')) { + require(APP . 'app_action.php'); + } else { + require(CAKE . 'app_action.php'); + } + } + + if (!class_exists($name . 'Action')) { + $controller = Inflector::underscore($controller); + $name = Inflector::underscore($name); + + foreach($paths->controllerPaths as $path) { + if (file_exists($path . $controller . DS .$name . '_action.php')) { + require($path . $controller . DS .$name . '_action.php'); + return validActionClass(Inflector::camelize($name).'Action'); + } + } + return false; + } else { + return true; + } + } +/** + * Loads an action class for a plugin controller. + * + * @param string $plugin Name of plugin + * @param string $controller Name of controller + * @param string $action Name of action class to load + * @return boolean Success + */ + function loadPluginControllerAction($plugin, $controller, $action) { + $pluginAppAction = Inflector::camelize($plugin . '_app_action'); + $pluginAppActionFile = APP . 'plugins' . DS . $plugin . DS . $plugin . '_app_action.php'; + if (!class_exists($pluginAppAction)) { + if (file_exists($pluginAppActionFile)) { + require($pluginAppActionFile); + } else { + return false; + } + } + + if (!class_exists($action . 'Action')) { + $controller = Inflector::underscore($controller); + $action = Inflector::underscore($action); + + $file = APP . 'plugins' . DS . $plugin . DS . 'controllers' . DS . $controller . DS . $action .'_action.php'; + + if (file_exists($file)) { + require($file); + return validActionClass(Inflector::camelize($action).'Action'); + } else { + return false; + } + } else { + return true; + } + } + + function validActionClass($actionClass) { + if (class_exists($actionClass)) { + if (in_array('perform', get_class_methods($actionClass))) { + return true; + } + } + return false; + } + +// FILE ENDS HERE \ No newline at end of file diff -rN -u old-cake/cake/app_action.php new-cake/cake/app_action.php --- old-cake/cake/app_action.php 1970-01-01 08:00:00.000000000 +0800 +++ new-cake/cake/app_action.php 2006-08-07 03:26:42.000000000 +0800 @@ -0,0 +1,43 @@ + + * Copyright (c) 2006, Cake Software Foundation, Inc. + * 1785 E. Sahara Avenue, Suite 490-204 + * Las Vegas, Nevada 89104 + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @filesource + * @copyright Copyright (c) 2006, Cake Software Foundation, Inc. + * @link http://abing.gotdns.com/cake/diffs/ CakePHP-Diffs Project + * @package cake + * @subpackage cake.cake + * @since CakePHP v 1.1.6.3346-diffs + * @version $Revision$ + * @modifiedby $LastChangedBy$ + * @lastmodified $Date$ + * @license http://www.opensource.org/licenses/mit-license.php The MIT License + */ +/** + * This is a placeholder class. + * Create the same file in app/app_action.php + * + * Add your application-wide methods in the class below, your actions + * will inherit them. + * + * @package cake + * @subpackage cake.cake + */ +class AppAction extends Action { +} + +// FILE ENDS HERE \ No newline at end of file diff -rN -u old-cake/cake/libs/controller/action.php new-cake/cake/libs/controller/action.php --- old-cake/cake/libs/controller/action.php 1970-01-01 08:00:00.000000000 +0800 +++ new-cake/cake/libs/controller/action.php 2006-08-07 03:26:42.000000000 +0800 @@ -0,0 +1,82 @@ + + * Copyright (c) 2006, Cake Software Foundation, Inc. + * 1785 E. Sahara Avenue, Suite 490-204 + * Las Vegas, Nevada 89104 + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @filesource + * @copyright Copyright (c) 2006, Cake Software Foundation, Inc. + * @link http://abing.gotdns.com/cake/diffs/ CakePHP-Diffs Project + * @package cake + * @subpackage cake.cake.libs.controller + * @since CakePHP v 1.1.6.3346-diffs + * @version $Revision$ + * @modifiedby $LastChangedBy$ + * @lastmodified $Date$ + * @license http://www.opensource.org/licenses/mit-license.php The MIT License + */ +/** + * Action + * + * A controller action is where you place all the code necessary to perform a + * requested action. The main entry point for the action is the perform() + * method. It is invoked by the acdispatcher, a custom dispatcher class that + * knows how to use action classes. + * + * @package cake + * @subpackage cake.cake.libs.controller + * + */ +class Action extends Object{ +/** + * Name of the action. + * + * @var unknown_type + */ + var $name; +/** + * Reference to the controller object that invoked this action. + * + * @var unknown_type + */ + var $controller; + +/** + * Constructor + * + * @param objref $controller Reference to the controller object that invoked the action + */ + function __construct() { + if ($this->name === null) { + $r = null; + + if (!preg_match('/(.*)Action/i', get_class($this), $r)) { + die ("Action::__construct() : Can't get or parse my own class name, exiting."); + } + $this->name = $r[1]; + } + + parent::__construct(); + } + + function setController(&$controller) { + $this->controller =& $controller; + + foreach (array_keys(get_object_vars($controller)) as $cvar) { + if ('name' != $cvar) { + $this->{$cvar} =& $controller->{$cvar}; + } + } + } +} + +// FILE ENDS HERE \ No newline at end of file diff -rN -u old-cake/cake/scripts/templates/skel/ac_dispatcher.php new-cake/cake/scripts/templates/skel/ac_dispatcher.php --- old-cake/cake/scripts/templates/skel/ac_dispatcher.php 1970-01-01 08:00:00.000000000 +0800 +++ new-cake/cake/scripts/templates/skel/ac_dispatcher.php 2006-08-07 03:26:42.000000000 +0800 @@ -0,0 +1,368 @@ + + * Copyright (c) 2006, Cake Software Foundation, Inc. + * 1785 E. Sahara Avenue, Suite 490-204 + * Las Vegas, Nevada 89104 + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @filesource + * @copyright Copyright (c) 2006, Cake Software Foundation, Inc. + * @link http://abing.gotdns.com/cake/diffs/ CakePHP-Diffs Project + * @package cake + * @subpackage cake.app + * @since CakePHP v 1.1.6.3346-diffs + * @version $Revision$ + * @modifiedby $LastChangedBy$ + * @lastmodified $Date$ + * @license http://www.opensource.org/licenses/mit-license.php The MIT License + */ +/** + * List of helpers to include + */ + uses(DS.'controller'.DS.'action'); + +/** + * Dispatcher translates URLs to controller-action-paramter triads. + * + * Dispatches the request, creating appropriate models and controllers. + * + * @package cake + * @subpackage cake.app + */ +class acDispatcher extends Dispatcher { + var $useActionClass; + + function __construct() { + parent::__construct(); + } +/** + * Dispatches and invokes given URL, handing over control to the involved controllers, and then renders the results (if autoRender is set). + * + * If no controller of given name can be found, invoke() shows error messages in + * the form of Missing Controllers information. It does the same with Actions (methods of Controllers are called + * Actions). + * + * @param string $url URL information to work on. + * @param array $additionalParams Settings array ("bare", "return"), + * which is melded with the GET and POST params. + * @return boolean Success + */ + function dispatch($url, $additionalParams=array()) { + $params = array_merge($this->parseParams($url), $additionalParams); + $missingController = false; + $missingAction = false; + $missingView = false; + $privateAction = false; + $this->base = $this->baseUrl(); + $this->useActionClass = false; + + if (empty($params['controller'])) { + $missingController = true; + } else { + $ctrlName = Inflector::camelize($params['controller']); + $ctrlClass = $ctrlName.'Controller'; + + if(!class_exists($ctrlClass)) { + if (!loadController($ctrlName)) { + $pluginName = Inflector::camelize($params['action']); + if (!loadPluginController(Inflector::underscore($ctrlName), $pluginName)) { + if(preg_match('/([\\.]+)/', $ctrlName)) { + return $this->cakeError('error404', array( + array('url' => strtolower($ctrlName), + 'message' => 'Was not found on this server', + 'base' => $this->base))); + exit(); + } else { + $missingController = true; + } + } else { + $params['plugin'] = Inflector::underscore($ctrlName); + } + } else { + $params['plugin'] = null; + $this->plugin = null; + } + } + } + + if(isset($params['plugin'])){ + $plugin = $params['plugin']; + $pluginName = Inflector::camelize($params['action']); + $pluginClass = $pluginName.'Controller'; + $ctrlClass = $pluginClass; + $oldAction = $params['action']; + $params = $this->_restructureParams($params); + $this->plugin = $plugin; + loadPluginModels($plugin); + $this->base = $this->base.'/'.Inflector::underscore($ctrlName); + + if(empty($params['controller']) || !class_exists($pluginClass)) { + $params['controller'] = Inflector::underscore($ctrlName); + $ctrlClass = $ctrlName.'Controller'; + if (!is_null($params['action'])) { + array_unshift($params['pass'], $params['action']); + } + $params['action'] = $oldAction; + } + } + + if(defined('CAKE_ADMIN')) { + if(isset($params[CAKE_ADMIN])) { + $this->admin = '/'.CAKE_ADMIN ; + $url = preg_replace('/'.CAKE_ADMIN.'\//', '', $url); + + if (empty($params['action'])) { + $params['action'] = CAKE_ADMIN.'_'.'index'; + } else { + $params['action'] = CAKE_ADMIN.'_'.$params['action']; + } + } else { + $__access = strpos($params['action'], CAKE_ADMIN); + if ($__access !== false) { + $privateAction = true; + } + } + } + + if ($missingController) { + return $this->cakeError('missingController', array( + array('className' => Inflector::camelize($params['controller']."Controller"), + 'webroot' => $this->webroot, + 'url' => $url, + 'base' => $this->base))); + } else { + $controller =& new $ctrlClass(); + } + + $classMethods = get_class_methods($controller); + $classVars = get_object_vars($controller); + + if (empty($params['action'])) { + $params['action'] = 'index'; + } + + if((in_array($params['action'], $classMethods) || in_array(strtolower($params['action']), $classMethods)) && (in_array(strtolower($params['action']), $controller->hiddenMethods) || strpos($params['action'], '_', 0) === 0)) { + $privateAction = true; + } + + if(!in_array($params['action'], $classMethods) && !in_array(strtolower($params['action']), $classMethods)) { + $missingAction = true; + } + + if (in_array(strtolower($params['action']), array('beforefilter', 'beforerender', 'afterfilter'))) { + $missingAction = true; + } + elseif ($missingAction) { + if (isset($params['plugin'])) { + $missingAction = (false === loadPluginControllerAction($params['plugin'], $params['controller'], $params['action'])); + } + else { + $missingAction = (false === loadControllerAction($params['controller'], $params['action'])); + } + if (!$missingAction) { + $this->useActionClass = true; + } + } + + if(in_array('return', array_keys($params)) && $params['return'] == 1) { + $controller->autoRender = false; + } + + $controller->base = $this->base; + $base = strip_plugin($this->base, $this->plugin); + if(defined("BASE_URL")){ + $controller->here = $base . $this->admin . $url; + } else { + $controller->here = $base . $this->admin . '/' . $url; + } + $controller->webroot = $this->webroot; + $controller->params = $params; + $controller->action = $params['action']; + + if (!empty($controller->params['data'])) { + $controller->data =& $controller->params['data']; + } else { + $controller->data = null; + } + + if (!empty($controller->params['pass'])) { + $controller->passed_args =& $controller->params['pass']; + $controller->passedArgs =& $controller->params['pass']; + } else { + $controller->passed_args = null; + $controller->passedArgs = null; + } + + if (!empty($params['bare'])) { + $controller->autoLayout = !$params['bare']; + } else { + $controller->autoLayout = $controller->autoLayout; + } + + $controller->webservices = $params['webservices']; + $controller->plugin = $this->plugin; + + if(!is_null($controller->webservices)) { + array_push($controller->components, $controller->webservices); + array_push($controller->helpers, $controller->webservices); + $component =& new Component($controller); + } + $controller->_initComponents(); + $controller->constructClasses(); + + if ($missingAction && !in_array('scaffold', array_keys($classVars))){ + return $this->cakeError('missingAction', array( + array('className' => Inflector::camelize($params['controller']."Controller"), + 'action' => $params['action'], + 'webroot' => $this->webroot, + 'url' => $url, + 'base' => $this->base))); + } + + if (defined('CUSTOM_DISPATCHER_ERROR') && CUSTOM_DISPATCHER_ERROR === true) { + return $this->cakeError('missingDispatcher', array( + array('className' => CUSTOM_DISPATCHER, + 'dispatcher' => CUSTOM_DISPATCHER, + 'webroot' => $this->webroot, + 'url' => $url, + 'base' => $this->base))); + } + + if ($privateAction){ + return $this->cakeError('privateAction', array( + array('className' => Inflector::camelize($params['controller']."Controller"), + 'action' => $params['action'], + 'webroot' => $this->webroot, + 'url' => $url, + 'base' => $this->base))); + } + return $this->_invoke($controller, $params, $missingAction); + } +/** + * Invokes given controller's render action if autoRender option is set. Otherwise the contents of the operation are returned as a string. + * + * @param object $controller + * @param array $params + * @param boolean $missingAction + * @return string + */ + function _invoke (&$controller, $params, $missingAction = false) { + $this->start($controller); + $classVars = get_object_vars($controller); + + if ($missingAction && in_array('scaffold', array_keys($classVars))) { + uses(DS.'controller'.DS.'scaffold'); + return new Scaffold($controller, $params); + } else { + if ($this->useActionClass) { + $actionClass = Inflector::camelize($params['action']).'Action'; + $action =& new $actionClass(); + $action->setController($controller); + $output = call_user_func_array(array(&$action, 'perform'), empty($params['pass'])? null: $params['pass']); + } else { + $output = call_user_func_array(array(&$controller, $params['action']), empty($params['pass'])? null: $params['pass']); + } + } + if ($controller->autoRender) { + $output = $controller->render(); + } + $controller->output =& $output; + $controller->afterFilter(); + return $controller->output; + } +} + +/* + * Functions used by acdispatcher + */ + +/** + * Loads an action class for a controller. + * + * @param string $controller Name of controller + * @param string $name Name of action + * @return boolean Success + */ + function loadControllerAction($controller, $name) { + $paths = Configure::getInstance(); + if (!class_exists('AppAction')) { + if (file_exists(APP . 'app_action.php')) { + require(APP . 'app_action.php'); + } else { + require(CAKE . 'app_action.php'); + } + } + + if (!class_exists($name . 'Action')) { + $controller = Inflector::underscore($controller); + $name = Inflector::underscore($name); + + foreach($paths->controllerPaths as $path) { + if (file_exists($path . $controller . DS .$name . '_action.php')) { + require($path . $controller . DS .$name . '_action.php'); + return validActionClass(Inflector::camelize($name).'Action'); + } + } + return false; + } else { + return true; + } + } +/** + * Loads an action class for a plugin controller. + * + * @param string $plugin Name of plugin + * @param string $controller Name of controller + * @param string $action Name of action class to load + * @return boolean Success + */ + function loadPluginControllerAction($plugin, $controller, $action) { + $pluginAppAction = Inflector::camelize($plugin . '_app_action'); + $pluginAppActionFile = APP . 'plugins' . DS . $plugin . DS . $plugin . '_app_action.php'; + if (!class_exists($pluginAppAction)) { + if (file_exists($pluginAppActionFile)) { + require($pluginAppActionFile); + } else { + return false; + } + } + + if (!class_exists($action . 'Action')) { + $controller = Inflector::underscore($controller); + $action = Inflector::underscore($action); + + $file = APP . 'plugins' . DS . $plugin . DS . 'controllers' . DS . $controller . DS . $action .'_action.php'; + + if (file_exists($file)) { + require($file); + return validActionClass(Inflector::camelize($action).'Action'); + } else { + return false; + } + } else { + return true; + } + } + + function validActionClass($actionClass) { + if (class_exists($actionClass)) { + if (in_array('perform', get_class_methods($actionClass))) { + return true; + } + } + return false; + } + +// FILE ENDS HERE \ No newline at end of file diff -rN -u old-cake/cake/scripts/templates/skel/app_action.php new-cake/cake/scripts/templates/skel/app_action.php --- old-cake/cake/scripts/templates/skel/app_action.php 1970-01-01 08:00:00.000000000 +0800 +++ new-cake/cake/scripts/templates/skel/app_action.php 2006-08-07 03:26:42.000000000 +0800 @@ -0,0 +1,43 @@ + + * Copyright (c) 2006, Cake Software Foundation, Inc. + * 1785 E. Sahara Avenue, Suite 490-204 + * Las Vegas, Nevada 89104 + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @filesource + * @copyright Copyright (c) 2006, Cake Software Foundation, Inc. + * @link http://abing.gotdns.com/cake/diffs/ CakePHP-Diffs Project + * @package cake + * @subpackage cake.cake + * @since CakePHP v 1.1.6.3346-diffs + * @version $Revision$ + * @modifiedby $LastChangedBy$ + * @lastmodified $Date$ + * @license http://www.opensource.org/licenses/mit-license.php The MIT License + */ +/** + * This is a placeholder class. + * Create the same file in app/app_action.php + * + * Add your application-wide methods in the class below, your actions + * will inherit them. + * + * @package cake + * @subpackage cake.cake + */ +class AppAction extends Action { +} + +// FILE ENDS HERE \ No newline at end of file