* (c) 2004-2006 Sean Kerr * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /** * sfAction executes all the logic for the current request. * * @package symfony * @subpackage action * @author Fabien Potencier * @author Sean Kerr * @version SVN: $Id: sfAction.class.php 20048 2009-07-09 09:53:03Z FabianLange $ */ abstract class sfAction extends sfComponent { protected $security = array(); /** * Initializes this action. * * @param sfContext $context The current application context. * @param string $moduleName The module name. * @param string $actionName The action name. * * @return bool true, if initialization completes successfully, otherwise false */ public function initialize($context, $moduleName, $actionName) { parent::initialize($context, $moduleName, $actionName); // include security configuration if ($file = $context->getConfigCache()->checkConfig('modules/'.$this->getModuleName().'/config/security.yml', true)) { require($file); } } /** * Executes an application defined process prior to execution of this sfAction object. * * By default, this method is empty. */ public function preExecute() { } /** * Execute an application defined process immediately after execution of this sfAction object. * * By default, this method is empty. */ public function postExecute() { } /** * Forwards current action to the default 404 error action. * * @param string $message Message of the generated exception * * @throws sfError404Exception * */ public function forward404($message = null) { throw new sfError404Exception($this->get404Message($message)); } /** * Forwards current action to the default 404 error action unless the specified condition is true. * * @param bool $condition A condition that evaluates to true or false * @param string $message Message of the generated exception * * @throws sfError404Exception */ public function forward404Unless($condition, $message = null) { if (!$condition) { throw new sfError404Exception($this->get404Message($message)); } } /** * Forwards current action to the default 404 error action if the specified condition is true. * * @param bool $condition A condition that evaluates to true or false * @param string $message Message of the generated exception * * @throws sfError404Exception */ public function forward404If($condition, $message = null) { if ($condition) { throw new sfError404Exception($this->get404Message($message)); } } /** * Redirects current action to the default 404 error action (with browser redirection). * * This method stops the current code flow. */ public function redirect404() { return $this->redirect('/'.sfConfig::get('sf_error_404_module').'/'.sfConfig::get('sf_error_404_action')); } /** * Forwards current action to a new one (without browser redirection). * * This method stops the action. So, no code is executed after a call to this method. * * @param string $module A module name * @param string $action An action name * * @throws sfStopException */ public function forward($module, $action) { if (sfConfig::get('sf_logging_enabled')) { $this->dispatcher->notify(new sfEvent($this, 'application.log', array(sprintf('Forward to action "%s/%s"', $module, $action)))); } $this->getController()->forward($module, $action); throw new sfStopException(); } /** * If the condition is true, forwards current action to a new one (without browser redirection). * * This method stops the action. So, no code is executed after a call to this method. * * @param bool $condition A condition that evaluates to true or false * @param string $module A module name * @param string $action An action name * * @throws sfStopException */ public function forwardIf($condition, $module, $action) { if ($condition) { $this->forward($module, $action); } } /** * Unless the condition is true, forwards current action to a new one (without browser redirection). * * This method stops the action. So, no code is executed after a call to this method. * * @param bool $condition A condition that evaluates to true or false * @param string $module A module name * @param string $action An action name * * @throws sfStopException */ public function forwardUnless($condition, $module, $action) { if (!$condition) { $this->forward($module, $action); } } /** * Redirects current request to a new URL. * * 2 URL formats are accepted : * - a full URL: http://www.google.com/ * - an internal URL (url_for() format): module/action * * This method stops the action. So, no code is executed after a call to this method. * * @param string $url Url * @param string $statusCode Status code (default to 302) * * @throws sfStopException */ public function redirect($url, $statusCode = 302) { $this->getController()->redirect($url, 0, $statusCode); throw new sfStopException(); } /** * Redirects current request to a new URL, only if specified condition is true. * * This method stops the action. So, no code is executed after a call to this method. * * @param bool $condition A condition that evaluates to true or false * @param string $url Url * @param string $statusCode Status code (default to 302) * * @throws sfStopException * * @see redirect */ public function redirectIf($condition, $url, $statusCode = 302) { if ($condition) { $this->redirect($url, $statusCode); } } /** * Redirects current request to a new URL, unless specified condition is true. * * This method stops the action. So, no code is executed after a call to this method. * * @param bool $condition A condition that evaluates to true or false * @param string $url Url * @param string $statusCode Status code (default to 302) * * @throws sfStopException * * @see redirect */ public function redirectUnless($condition, $url, $statusCode = 302) { if (!$condition) { $this->redirect($url, $statusCode); } } /** * Appends the given text to the response content and bypasses the built-in view system. * * This method must be called as with a return: * * return $this->renderText('some text') * * @param string $text Text to append to the response * * @return sfView::NONE */ public function renderText($text) { $this->getResponse()->setContent($this->getResponse()->getContent().$text); return sfView::NONE; } /** * Returns the partial rendered content. * * If the vars parameter is omitted, the action's internal variables * will be passed, just as it would to a normal template. * * If the vars parameter is set then only those values are * available in the partial. * * @param string $templateName partial name * @param array $vars vars * * @return string The partial content */ public function getPartial($templateName, $vars = null) { $this->getContext()->getConfiguration()->loadHelpers('Partial'); $vars = !is_null($vars) ? $vars : $this->varHolder->getAll(); return get_partial($templateName, $vars); } /** * Appends the result of the given partial execution to the response content. * * This method must be called as with a return: * * return $this->renderPartial('foo/bar') * * @param string $templateName partial name * @param array $vars vars * * @return sfView::NONE * * @see getPartial */ public function renderPartial($templateName, $vars = null) { return $this->renderText($this->getPartial($templateName, $vars)); } /** * Returns the component rendered content. * * If the vars parameter is omitted, the action's internal variables * will be passed, just as it would to a normal template. * * If the vars parameter is set then only those values are * available in the component. * * @param string $moduleName module name * @param string $componentName component name * @param array $vars vars * * @return string The component rendered content */ public function getComponent($moduleName, $componentName, $vars = null) { $this->getContext()->getConfiguration()->loadHelpers('Partial'); $vars = !is_null($vars) ? $vars : $this->varHolder->getAll(); return get_component($moduleName, $componentName, $vars); } /** * Appends the result of the given component execution to the response content. * * This method must be called as with a return: * * return $this->renderComponent('foo', 'bar') * * @param string $moduleName module name * @param string $componentName component name * @param array $vars vars * * @return sfView::NONE * * @see getComponent */ public function renderComponent($moduleName, $componentName, $vars = null) { return $this->renderText($this->getComponent($moduleName, $componentName, $vars)); } /** * Retrieves the default view to be executed when a given request is not served by this action. * * @return string A string containing the view name associated with this action * * @throws sfConfigurationException If compat_10 is not enabled */ public function getDefaultView() { if (!sfConfig::get('sf_compat_10')) { throw new sfConfigurationException('You must set "compat_10" to true if you want to use this method which is deprecated.'); } return sfView::INPUT; } /** * Executes any post-validation error application logic. * * @return string A string containing the view name associated with this action * * @throws sfConfigurationException If compat_10 is not enabled */ public function handleError() { if (!sfConfig::get('sf_compat_10')) { throw new sfConfigurationException('You must set "compat_10" to true if you want to use this method which is deprecated.'); } return sfView::ERROR; } /** * Validates manually files and parameters. * * @return bool true, if validation completes successfully, otherwise false. * * @throws sfConfigurationException If compat_10 is not enabled */ public function validate() { if (!sfConfig::get('sf_compat_10')) { throw new sfConfigurationException('You must set "compat_10" to true if you want to use this method which is deprecated.'); } return true; } /** * Returns the security configuration for this module. * * @return string Current security configuration as an array */ public function getSecurityConfiguration() { return $this->security; } /** * Overrides the current security configuration for this module. * * @param array $security The new security configuration */ public function setSecurityConfiguration($security) { $this->security = $security; } /** * Indicates that this action requires security. * * @return bool true, if this action requires security, otherwise false. */ public function isSecure() { $actionName = strtolower($this->getActionName()); if (isset($this->security[$actionName]['is_secure'])) { return $this->security[$actionName]['is_secure']; } if (isset($this->security['all']['is_secure'])) { return $this->security['all']['is_secure']; } return false; } /** * Gets credentials the user must have to access this action. * * @return mixed An array or a string describing the credentials the user must have to access this action */ public function getCredential() { $actionName = strtolower($this->getActionName()); if (isset($this->security[$actionName]['credentials'])) { $credentials = $this->security[$actionName]['credentials']; } else if (isset($this->security['all']['credentials'])) { $credentials = $this->security['all']['credentials']; } else { $credentials = null; } return $credentials; } /** * Sets an alternate template for this sfAction. * * See 'Naming Conventions' in the 'Symfony View' documentation. * * @param string $name Template name * @param string $module The module (current if null) */ public function setTemplate($name, $module = null) { if (sfConfig::get('sf_logging_enabled')) { $this->dispatcher->notify(new sfEvent($this, 'application.log', array(sprintf('Change template to "%s/%s"', is_null($module) ? 'CURRENT' : $module, $name)))); } if (!is_null($module)) { $name = sfConfig::get('sf_app_dir').'/modules/'.$module.'/templates/'.$name; } sfConfig::set('symfony.view.'.$this->getModuleName().'_'.$this->getActionName().'_template', $name); } /** * Gets the name of the alternate template for this sfAction. * * WARNING: It only returns the template you set with the setTemplate() method, * and does not return the template that you configured in your view.yml. * * See 'Naming Conventions' in the 'Symfony View' documentation. * * @return string Template name. Returns null if no template has been set within the action */ public function getTemplate() { return sfConfig::get('symfony.view.'.$this->getModuleName().'_'.$this->getActionName().'_template'); } /** * Sets an alternate layout for this sfAction. * * To de-activate the layout, set the layout name to false. * * To revert the layout to the one configured in the view.yml, set the template name to null. * * @param mixed $name Layout name or false to de-activate the layout */ public function setLayout($name) { if (sfConfig::get('sf_logging_enabled')) { $this->dispatcher->notify(new sfEvent($this, 'application.log', array(sprintf('Change layout to "%s"', $name)))); } sfConfig::set('symfony.view.'.$this->getModuleName().'_'.$this->getActionName().'_layout', $name); } /** * Gets the name of the alternate layout for this sfAction. * * WARNING: It only returns the layout you set with the setLayout() method, * and does not return the layout that you configured in your view.yml. * * @return mixed Layout name. Returns null if no layout has been set within the action */ public function getLayout() { return sfConfig::get('symfony.view.'.$this->getModuleName().'_'.$this->getActionName().'_layout'); } /** * Changes the default view class used for rendering the template associated with the current action. * * @param string $class View class name */ public function setViewClass($class) { sfConfig::set('mod_'.strtolower($this->getModuleName()).'_view_class', $class); } public function getRoute() { return $this->getRequest()->getAttribute('sf_route'); } /** * Returns a formatted message for a 404 error. * * @param string $message An error message (null by default) * * @return string The error message or a default one if null */ protected function get404Message($message = null) { return is_null($message) ? sprintf('This request has been forwarded to a 404 error page by the action "%s/%s".', $this->getModuleName(), $this->getActionName()) : $message; } }