sfAction.class.php 15 KB

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