1. sfAction.class.php
  2. /** * 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 24279 2009-11-23 15:21:18Z fabien $ */
  3. abstract class sfAction extends sfComponent
  4. {
  5. protected
  6. $security = array();
  7. /**
  8. * Initializes this action.
  9. *
  10. * @param sfContext $context The current application context.
  11. * @param string $moduleName The module name.
  12. * @param string $actionName The action name.
  13. *
  14. * @return bool true, if initialization completes successfully, otherwise false
  15. */
  16. public function initialize($context, $moduleName, $actionName)
  17. {
  18. parent::initialize($context, $moduleName, $actionName);
  19. // include security configuration
  20. if ($file = $context->getConfigCache()->checkConfig('modules/'.$this->getModuleName().'/config/security.yml', true))
  21. {
  22. require($file);
  23. }
  24. }
  25. /**
  26. * Executes an application defined process prior to execution of this sfAction object.
  27. *
  28. * By default, this method is empty.
  29. */
  30. public function preExecute()
  31. {
  32. }
  33. /**
  34. * Execute an application defined process immediately after execution of this sfAction object.
  35. *
  36. * By default, this method is empty.
  37. */
  38. public function postExecute()
  39. {
  40. }
  41. /**
  42. * Forwards current action to the default 404 error action.
  43. *
  44. * @param string $message Message of the generated exception
  45. *
  46. * @throws sfError404Exception
  47. *
  48. */
  49. public function forward404($message = null)
  50. {
  51. throw new sfError404Exception($this->get404Message($message));
  52. }
  53. /**
  54. * Forwards current action to the default 404 error action unless the specified condition is true.
  55. *
  56. * @param bool $condition A condition that evaluates to true or false
  57. * @param string $message Message of the generated exception
  58. *
  59. * @throws sfError404Exception
  60. */
  61. public function forward404Unless($condition, $message = null)
  62. {
  63. if (!$condition)
  64. {
  65. throw new sfError404Exception($this->get404Message($message));
  66. }
  67. }
  68. /**
  69. * Forwards current action to the default 404 error action if the specified condition is true.
  70. *
  71. * @param bool $condition A condition that evaluates to true or false
  72. * @param string $message Message of the generated exception
  73. *
  74. * @throws sfError404Exception
  75. */
  76. public function forward404If($condition, $message = null)
  77. {
  78. if ($condition)
  79. {
  80. throw new sfError404Exception($this->get404Message($message));
  81. }
  82. }
  83. /**
  84. * Redirects current action to the default 404 error action (with browser redirection).
  85. *
  86. * This method stops the current code flow.
  87. */
  88. public function redirect404()
  89. {
  90. return $this->redirect('/'.sfConfig::get('sf_error_404_module').'/'.sfConfig::get('sf_error_404_action'));
  91. }
  92. /**
  93. * Forwards current action to a new one (without browser redirection).
  94. *
  95. * This method stops the action. So, no code is executed after a call to this method.
  96. *
  97. * @param string $module A module name
  98. * @param string $action An action name
  99. *
  100. * @throws sfStopException
  101. */
  102. public function forward($module, $action)
  103. {
  104. if (sfConfig::get('sf_logging_enabled'))
  105. {
  106. $this->dispatcher->notify(new sfEvent($this, 'application.log', array(sprintf('Forward to action "%s/%s"', $module, $action))));
  107. }
  108. $this->getController()->forward($module, $action);
  109. throw new sfStopException();
  110. }
  111. /**
  112. * If the condition is true, forwards current action to a new one (without browser redirection).
  113. *
  114. * This method stops the action. So, no code is executed after a call to this method.
  115. *
  116. * @param bool $condition A condition that evaluates to true or false
  117. * @param string $module A module name
  118. * @param string $action An action name
  119. *
  120. * @throws sfStopException
  121. */
  122. public function forwardIf($condition, $module, $action)
  123. {
  124. if ($condition)
  125. {
  126. $this->forward($module, $action);
  127. }
  128. }
  129. /**
  130. * Unless the condition is true, forwards current action to a new one (without browser redirection).
  131. *
  132. * This method stops the action. So, no code is executed after a call to this method.
  133. *
  134. * @param bool $condition A condition that evaluates to true or false
  135. * @param string $module A module name
  136. * @param string $action An action name
  137. *
  138. * @throws sfStopException
  139. */
  140. public function forwardUnless($condition, $module, $action)
  141. {
  142. if (!$condition)
  143. {
  144. $this->forward($module, $action);
  145. }
  146. }
  147. /**
  148. * Redirects current request to a new URL.
  149. *
  150. * 2 URL formats are accepted :
  151. * - a full URL: http://www.google.com/
  152. * - an internal URL (url_for() format): module/action
  153. *
  154. * This method stops the action. So, no code is executed after a call to this method.
  155. *
  156. * @param string $url Url
  157. * @param string $statusCode Status code (default to 302)
  158. *
  159. * @throws sfStopException
  160. */
  161. public function redirect($url, $statusCode = 302)
  162. {
  163. // compatibility with url_for2() style signature
  164. if (is_object($statusCode) || is_array($statusCode))
  165. {
  166. $url = array_merge(array('sf_route' => $url), is_object($statusCode) ? array('sf_subject' => $statusCode) : $statusCode);
  167. $statusCode = func_num_args() >= 3 ? func_get_arg(2) : 302;
  168. }
  169. $this->getController()->redirect($url, 0, $statusCode);
  170. throw new sfStopException();
  171. }
  172. /**
  173. * Redirects current request to a new URL, only if specified condition is true.
  174. *
  175. * This method stops the action. So, no code is executed after a call to this method.
  176. *
  177. * @param bool $condition A condition that evaluates to true or false
  178. * @param string $url Url
  179. * @param string $statusCode Status code (default to 302)
  180. *
  181. * @throws sfStopException
  182. *
  183. * @see redirect
  184. */
  185. public function redirectIf($condition, $url, $statusCode = 302)
  186. {
  187. if ($condition)
  188. {
  189. // compatibility with url_for2() style signature
  190. $arguments = func_get_args();
  191. call_user_func_array(array($this, 'redirect'), array_slice($arguments, 1));
  192. }
  193. }
  194. /**
  195. * Redirects current request to a new URL, unless specified condition is true.
  196. *
  197. * This method stops the action. So, no code is executed after a call to this method.
  198. *
  199. * @param bool $condition A condition that evaluates to true or false
  200. * @param string $url Url
  201. * @param string $statusCode Status code (default to 302)
  202. *
  203. * @throws sfStopException
  204. *
  205. * @see redirect
  206. */
  207. public function redirectUnless($condition, $url, $statusCode = 302)
  208. {
  209. if (!$condition)
  210. {
  211. // compatibility with url_for2() style signature
  212. $arguments = func_get_args();
  213. call_user_func_array(array($this, 'redirect'), array_slice($arguments, 1));
  214. }
  215. }
  216. /**
  217. * Appends the given text to the response content and bypasses the built-in view system.
  218. *
  219. * This method must be called as with a return:
  220. *
  221. * <code>return $this->renderText('some text')</code>
  222. *
  223. * @param string $text Text to append to the response
  224. *
  225. * @return sfView::NONE
  226. */
  227. public function renderText($text)
  228. {
  229. $this->getResponse()->setContent($this->getResponse()->getContent().$text);
  230. return sfView::NONE;
  231. }
  232. /**
  233. * Returns the partial rendered content.
  234. *
  235. * If the vars parameter is omitted, the action's internal variables
  236. * will be passed, just as it would to a normal template.
  237. *
  238. * If the vars parameter is set then only those values are
  239. * available in the partial.
  240. *
  241. * @param string $templateName partial name
  242. * @param array $vars vars
  243. *
  244. * @return string The partial content
  245. */
  246. public function getPartial($templateName, $vars = null)
  247. {
  248. $this->getContext()->getConfiguration()->loadHelpers('Partial');
  249. $vars = null !== $vars ? $vars : $this->varHolder->getAll();
  250. return get_partial($templateName, $vars);
  251. }
  252. /**
  253. * Appends the result of the given partial execution to the response content.
  254. *
  255. * This method must be called as with a return:
  256. *
  257. * <code>return $this->renderPartial('foo/bar')</code>
  258. *
  259. * @param string $templateName partial name
  260. * @param array $vars vars
  261. *
  262. * @return sfView::NONE
  263. *
  264. * @see getPartial
  265. */
  266. public function renderPartial($templateName, $vars = null)
  267. {
  268. return $this->renderText($this->getPartial($templateName, $vars));
  269. }
  270. /**
  271. * Returns the component rendered content.
  272. *
  273. * If the vars parameter is omitted, the action's internal variables
  274. * will be passed, just as it would to a normal template.
  275. *
  276. * If the vars parameter is set then only those values are
  277. * available in the component.
  278. *
  279. * @param string $moduleName module name
  280. * @param string $componentName component name
  281. * @param array $vars vars
  282. *
  283. * @return string The component rendered content
  284. */
  285. public function getComponent($moduleName, $componentName, $vars = null)
  286. {
  287. $this->getContext()->getConfiguration()->loadHelpers('Partial');
  288. $vars = null !== $vars ? $vars : $this->varHolder->getAll();
  289. return get_component($moduleName, $componentName, $vars);
  290. }
  291. /**
  292. * Appends the result of the given component execution to the response content.
  293. *
  294. * This method must be called as with a return:
  295. *
  296. * <code>return $this->renderComponent('foo', 'bar')</code>
  297. *
  298. * @param string $moduleName module name
  299. * @param string $componentName component name
  300. * @param array $vars vars
  301. *
  302. * @return sfView::NONE
  303. *
  304. * @see getComponent
  305. */
  306. public function renderComponent($moduleName, $componentName, $vars = null)
  307. {
  308. return $this->renderText($this->getComponent($moduleName, $componentName, $vars));
  309. }
  310. /**
  311. * Returns the security configuration for this module.
  312. *
  313. * @return string Current security configuration as an array
  314. */
  315. public function getSecurityConfiguration()
  316. {
  317. return $this->security;
  318. }
  319. /**
  320. * Overrides the current security configuration for this module.
  321. *
  322. * @param array $security The new security configuration
  323. */
  324. public function setSecurityConfiguration($security)
  325. {
  326. $this->security = $security;
  327. }
  328. /**
  329. * Returns a value from security.yml.
  330. *
  331. * @param string $name The name of the value to pull from security.yml
  332. * @param mixed $default The default value to return if none is found in security.yml
  333. *
  334. * @return mixed
  335. */
  336. public function getSecurityValue($name, $default = null)
  337. {
  338. $actionName = strtolower($this->getActionName());
  339. if (isset($this->security[$actionName][$name]))
  340. {
  341. return $this->security[$actionName][$name];
  342. }
  343. if (isset($this->security['all'][$name]))
  344. {
  345. return $this->security['all'][$name];
  346. }
  347. return $default;
  348. }
  349. /**
  350. * Indicates that this action requires security.
  351. *
  352. * @return bool true, if this action requires security, otherwise false.
  353. */
  354. public function isSecure()
  355. {
  356. return $this->getSecurityValue('is_secure', false);
  357. }
  358. /**
  359. * Gets credentials the user must have to access this action.
  360. *
  361. * @return mixed An array or a string describing the credentials the user must have to access this action
  362. */
  363. public function getCredential()
  364. {
  365. return $this->getSecurityValue('credentials');
  366. }
  367. /**
  368. * Sets an alternate template for this sfAction.
  369. *
  370. * See 'Naming Conventions' in the 'Symfony View' documentation.
  371. *
  372. * @param string $name Template name
  373. * @param string $module The module (current if null)
  374. */
  375. public function setTemplate($name, $module = null)
  376. {
  377. if (sfConfig::get('sf_logging_enabled'))
  378. {
  379. $this->dispatcher->notify(new sfEvent($this, 'application.log', array(sprintf('Change template to "%s/%s"', null === $module ? 'CURRENT' : $module, $name))));
  380. }
  381. if (null !== $module)
  382. {
  383. $name = sfConfig::get('sf_app_dir').'/modules/'.$module.'/templates/'.$name;
  384. }
  385. sfConfig::set('symfony.view.'.$this->getModuleName().'_'.$this->getActionName().'_template', $name);
  386. }
  387. /**
  388. * Gets the name of the alternate template for this sfAction.
  389. *
  390. * WARNING: It only returns the template you set with the setTemplate() method,
  391. * and does not return the template that you configured in your view.yml.
  392. *
  393. * See 'Naming Conventions' in the 'Symfony View' documentation.
  394. *
  395. * @return string Template name. Returns null if no template has been set within the action
  396. */
  397. public function getTemplate()
  398. {
  399. return sfConfig::get('symfony.view.'.$this->getModuleName().'_'.$this->getActionName().'_template');
  400. }
  401. /**
  402. * Sets an alternate layout for this sfAction.
  403. *
  404. * To de-activate the layout, set the layout name to false.
  405. *
  406. * To revert the layout to the one configured in the view.yml, set the template name to null.
  407. *
  408. * @param mixed $name Layout name or false to de-activate the layout
  409. */
  410. public function setLayout($name)
  411. {
  412. if (sfConfig::get('sf_logging_enabled'))
  413. {
  414. $this->dispatcher->notify(new sfEvent($this, 'application.log', array(sprintf('Change layout to "%s"', $name))));
  415. }
  416. sfConfig::set('symfony.view.'.$this->getModuleName().'_'.$this->getActionName().'_layout', $name);
  417. }
  418. /**
  419. * Gets the name of the alternate layout for this sfAction.
  420. *
  421. * WARNING: It only returns the layout you set with the setLayout() method,
  422. * and does not return the layout that you configured in your view.yml.
  423. *
  424. * @return mixed Layout name. Returns null if no layout has been set within the action
  425. */
  426. public function getLayout()
  427. {
  428. return sfConfig::get('symfony.view.'.$this->getModuleName().'_'.$this->getActionName().'_layout');
  429. }
  430. /**
  431. * Changes the default view class used for rendering the template associated with the current action.
  432. *
  433. * @param string $class View class name
  434. */
  435. public function setViewClass($class)
  436. {
  437. sfConfig::set('mod_'.strtolower($this->getModuleName()).'_view_class', $class);
  438. }
  439. /**
  440. * Returns the current route for this request
  441. *
  442. * @return sfRoute The route for the request
  443. */
  444. public function getRoute()
  445. {
  446. return $this->getRequest()->getAttribute('sf_route');
  447. }
  448. /**
  449. * Returns a formatted message for a 404 error.
  450. *
  451. * @param string $message An error message (null by default)
  452. *
  453. * @return string The error message or a default one if null
  454. */
  455. protected function get404Message($message = null)
  456. {
  457. return null === $message ? sprintf('This request has been forwarded to a 404 error page by the action "%s/%s".', $this->getModuleName(), $this->getActionName()) : $message;
  458. }
  459. }

Debug toolbar