sfAction.class.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
  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 9477 2008-06-09 09:41:14Z 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. *
  190. * @throws sfStopException
  191. *
  192. * @see redirect
  193. */
  194. public function redirectIf($condition, $url)
  195. {
  196. if ($condition)
  197. {
  198. $this->redirect($url);
  199. }
  200. }
  201. /**
  202. * Redirects current request to a new URL, unless specified condition is true.
  203. *
  204. * This method stops the action. So, no code is executed after a call to this method.
  205. *
  206. * @param bool $condition A condition that evaluates to true or false
  207. * @param string $url Url
  208. *
  209. * @throws sfStopException
  210. *
  211. * @see redirect
  212. */
  213. public function redirectUnless($condition, $url)
  214. {
  215. if (!$condition)
  216. {
  217. $this->redirect($url);
  218. }
  219. }
  220. /**
  221. * Appends the given text to the response content and bypasses the built-in view system.
  222. *
  223. * This method must be called as with a return:
  224. *
  225. * <code>return $this->renderText('some text')</code>
  226. *
  227. * @param string $text Text to append to the response
  228. *
  229. * @return sfView::NONE
  230. */
  231. public function renderText($text)
  232. {
  233. $this->getResponse()->setContent($this->getResponse()->getContent().$text);
  234. return sfView::NONE;
  235. }
  236. /**
  237. * Returns the partial rendered content.
  238. *
  239. * If the vars parameter is omitted, the action's internal variables
  240. * will be passed, just as it would to a normal template.
  241. *
  242. * If the vars parameter is set then only those values are
  243. * available in the partial.
  244. *
  245. * @param string $templateName partial name
  246. * @param array $vars vars
  247. *
  248. * @return string The partial content
  249. */
  250. public function getPartial($templateName, $vars = null)
  251. {
  252. sfLoader::loadHelpers('Partial');
  253. $vars = !is_null($vars) ? $vars : $this->varHolder->getAll();
  254. return get_partial($templateName, $vars);
  255. }
  256. /**
  257. * Appends the result of the given partial execution to the response content.
  258. *
  259. * This method must be called as with a return:
  260. *
  261. * <code>return $this->renderPartial('foo/bar')</code>
  262. *
  263. * @param string $templateName partial name
  264. * @param array $vars vars
  265. *
  266. * @return sfView::NONE
  267. *
  268. * @see getPartial
  269. */
  270. public function renderPartial($templateName, $vars = null)
  271. {
  272. return $this->renderText($this->getPartial($templateName, $vars));
  273. }
  274. /**
  275. * Returns the component rendered content.
  276. *
  277. * If the vars parameter is omitted, the action's internal variables
  278. * will be passed, just as it would to a normal template.
  279. *
  280. * If the vars parameter is set then only those values are
  281. * available in the component.
  282. *
  283. * @param string $moduleName module name
  284. * @param string $componentNae component name
  285. * @param array $vars vars
  286. *
  287. * @return string The component rendered content
  288. */
  289. public function getComponent($moduleName, $componentName, $vars = null)
  290. {
  291. sfLoader::loadHelpers('Partial');
  292. $vars = !is_null($vars) ? $vars : $this->varHolder->getAll();
  293. return get_component($moduleName, $componentName, $vars);
  294. }
  295. /**
  296. * Appends the result of the given component execution to the response content.
  297. *
  298. * This method must be called as with a return:
  299. *
  300. * <code>return $this->renderComponent('foo', 'bar')</code>
  301. *
  302. * @param string $moduleName module name
  303. * @param string $componentNae component name
  304. * @param array $vars vars
  305. *
  306. * @return sfView::NONE
  307. *
  308. * @see getComponent
  309. */
  310. public function renderComponent($moduleName, $componentName, $vars = null)
  311. {
  312. return $this->renderText($this->getComponent($moduleName, $componentName, $vars));
  313. }
  314. /**
  315. * Retrieves the default view to be executed when a given request is not served by this action.
  316. *
  317. * @return string A string containing the view name associated with this action
  318. */
  319. public function getDefaultView()
  320. {
  321. if (!sfConfig::get('sf_compat_10'))
  322. {
  323. throw new sfConfigurationException('You must set "compat_10" to true if you want to use this method which is deprecated.');
  324. }
  325. return sfView::INPUT;
  326. }
  327. /**
  328. * Retrieves the request methods on which this action will process validation and execution.
  329. *
  330. * @return int One of the following values:
  331. *
  332. * - sfRequest::GET
  333. * - sfRequest::POST
  334. * - sfRequest::PUT
  335. * - sfRequest::DELETE
  336. * - sfRequest::HEAD
  337. * - sfRequest::NONE
  338. *
  339. * @see sfRequest
  340. */
  341. public function getRequestMethods()
  342. {
  343. if (!sfConfig::get('sf_compat_10'))
  344. {
  345. throw new sfConfigurationException('You must set "compat_10" to true if you want to use this method which is deprecated.');
  346. }
  347. return sfRequest::GET
  348. | sfRequest::POST
  349. | sfRequest::PUT
  350. | sfRequest::DELETE
  351. | sfRequest::HEAD
  352. | sfRequest::NONE;
  353. }
  354. /**
  355. * Executes any post-validation error application logic.
  356. *
  357. * @return string A string containing the view name associated with this action
  358. */
  359. public function handleError()
  360. {
  361. if (!sfConfig::get('sf_compat_10'))
  362. {
  363. throw new sfConfigurationException('You must set "compat_10" to true if you want to use this method which is deprecated.');
  364. }
  365. return sfView::ERROR;
  366. }
  367. /**
  368. * Validates manually files and parameters.
  369. *
  370. * @return bool true, if validation completes successfully, otherwise false.
  371. */
  372. public function validate()
  373. {
  374. if (!sfConfig::get('sf_compat_10'))
  375. {
  376. throw new sfConfigurationException('You must set "compat_10" to true if you want to use this method which is deprecated.');
  377. }
  378. return true;
  379. }
  380. /**
  381. * Returns the security configuration for this module.
  382. *
  383. * @return string Current security configuration as an array
  384. */
  385. public function getSecurityConfiguration()
  386. {
  387. return $this->security;
  388. }
  389. /**
  390. * Overrides the current security configuration for this module.
  391. *
  392. * @param array $security The new security configuration
  393. */
  394. public function setSecurityConfiguration($security)
  395. {
  396. $this->security = $security;
  397. }
  398. /**
  399. * Indicates that this action requires security.
  400. *
  401. * @return bool true, if this action requires security, otherwise false.
  402. */
  403. public function isSecure()
  404. {
  405. $actionName = strtolower($this->getActionName());
  406. if (isset($this->security[$actionName]['is_secure']))
  407. {
  408. return $this->security[$actionName]['is_secure'];
  409. }
  410. if (isset($this->security['all']['is_secure']))
  411. {
  412. return $this->security['all']['is_secure'];
  413. }
  414. return false;
  415. }
  416. /**
  417. * Gets credentials the user must have to access this action.
  418. *
  419. * @return mixed An array or a string describing the credentials the user must have to access this action
  420. */
  421. public function getCredential()
  422. {
  423. $actionName = strtolower($this->getActionName());
  424. if (isset($this->security[$actionName]['credentials']))
  425. {
  426. $credentials = $this->security[$actionName]['credentials'];
  427. }
  428. else if (isset($this->security['all']['credentials']))
  429. {
  430. $credentials = $this->security['all']['credentials'];
  431. }
  432. else
  433. {
  434. $credentials = null;
  435. }
  436. return $credentials;
  437. }
  438. /**
  439. * Sets an alternate template for this sfAction.
  440. *
  441. * See 'Naming Conventions' in the 'Symfony View' documentation.
  442. *
  443. * @param string $name Template name
  444. * @param string $module The module (current if null)
  445. */
  446. public function setTemplate($name, $module = null)
  447. {
  448. if (sfConfig::get('sf_logging_enabled'))
  449. {
  450. $this->dispatcher->notify(new sfEvent($this, 'application.log', array(sprintf('Change template to "%s/%s"', is_null($module) ? 'CURRENT' : $module, $name))));
  451. }
  452. if (!is_null($module))
  453. {
  454. $name = sfConfig::get('sf_app_dir').'/modules/'.$module.'/templates/'.$name;
  455. }
  456. sfConfig::set('symfony.view.'.$this->getModuleName().'_'.$this->getActionName().'_template', $name);
  457. }
  458. /**
  459. * Gets the name of the alternate template for this sfAction.
  460. *
  461. * WARNING: It only returns the template you set with the setTemplate() method,
  462. * and does not return the template that you configured in your view.yml.
  463. *
  464. * See 'Naming Conventions' in the 'Symfony View' documentation.
  465. *
  466. * @return string Template name. Returns null if no template has been set within the action
  467. */
  468. public function getTemplate()
  469. {
  470. return sfConfig::get('symfony.view.'.$this->getModuleName().'_'.$this->getActionName().'_template');
  471. }
  472. /**
  473. * Sets an alternate layout for this sfAction.
  474. *
  475. * To de-activate the layout, set the layout name to false.
  476. *
  477. * To revert the layout to the one configured in the view.yml, set the template name to null.
  478. *
  479. * @param mixed $name Layout name or false to de-activate the layout
  480. */
  481. public function setLayout($name)
  482. {
  483. if (sfConfig::get('sf_logging_enabled'))
  484. {
  485. $this->dispatcher->notify(new sfEvent($this, 'application.log', array(sprintf('Change layout to "%s"', $name))));
  486. }
  487. sfConfig::set('symfony.view.'.$this->getModuleName().'_'.$this->getActionName().'_layout', $name);
  488. }
  489. /**
  490. * Gets the name of the alternate layout for this sfAction.
  491. *
  492. * WARNING: It only returns the layout you set with the setLayout() method,
  493. * and does not return the layout that you configured in your view.yml.
  494. *
  495. * @return mixed Layout name. Returns null if no layout has been set within the action
  496. */
  497. public function getLayout()
  498. {
  499. return sfConfig::get('symfony.view.'.$this->getModuleName().'_'.$this->getActionName().'_layout');
  500. }
  501. /**
  502. * Changes the default view class used for rendering the template associated with the current action.
  503. *
  504. * @param string $class View class name
  505. */
  506. public function setViewClass($class)
  507. {
  508. sfConfig::set('mod_'.strtolower($this->getModuleName()).'_view_class', $class);
  509. }
  510. /**
  511. * Returns a formatted message for a 404 error.
  512. *
  513. * @param string $message An error message (null by default)
  514. *
  515. * @return string The error message or a default one if null
  516. */
  517. protected function get404Message($message = null)
  518. {
  519. 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;
  520. }
  521. }