Controller.php 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice.
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  11. * @link http://cakephp.org CakePHP(tm) Project
  12. * @since 0.2.9
  13. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Controller;
  16. use Cake\Error\Exception;
  17. use Cake\Event\Event;
  18. use Cake\Event\EventListener;
  19. use Cake\Event\EventManagerTrait;
  20. use Cake\Log\LogTrait;
  21. use Cake\Model\ModelAwareTrait;
  22. use Cake\Network\Request;
  23. use Cake\Network\Response;
  24. use Cake\ORM\TableRegistry;
  25. use Cake\Routing\RequestActionTrait;
  26. use Cake\Routing\Router;
  27. use Cake\Utility\Inflector;
  28. use Cake\Utility\MergeVariablesTrait;
  29. use Cake\View\ViewVarsTrait;
  30. /**
  31. * Application controller class for organization of business logic.
  32. * Provides basic functionality, such as rendering views inside layouts,
  33. * automatic model availability, redirection, callbacks, and more.
  34. *
  35. * Controllers should provide a number of 'action' methods. These are public methods on the controller
  36. * that are not prefixed with a '_' and not part of Controller. Each action serves as an endpoint for
  37. * performing a specific action on a resource or collection of resources. For example adding or editing a new
  38. * object, or listing a set of objects.
  39. *
  40. * You can access request parameters, using `$this->request`. The request object contains all the POST, GET and FILES
  41. * that were part of the request.
  42. *
  43. * After performing the required actions, controllers are responsible for creating a response. This usually
  44. * takes the form of a generated View, or possibly a redirection to another controller action. In either case
  45. * `$this->response` allows you to manipulate all aspects of the response.
  46. *
  47. * Controllers are created by Dispatcher based on request parameters and routing. By default controllers and actions
  48. * use conventional names. For example `/posts/index` maps to `PostsController::index()`. You can re-map URLs
  49. * using Router::connect().
  50. *
  51. * ### Life cycle callbacks
  52. *
  53. * CakePHP fires a number of life cycle callbacks during each request. By implementing a method
  54. * you can receive the related events. The available callbacks are:
  55. *
  56. * - `beforeFilter(Event $event)` - Called before each action. This is a good place to
  57. * do general logic that applies to all actions.
  58. * - `beforeRender(Event $event)` - Called before the view is rendered.
  59. * - `beforeRedirect(Cake\Event\Event $event $url, Cake\Network\Response $response)` - Called before
  60. * a redirect is done.
  61. * - `afterFilter(Event $event)` - Called after each action is complete and after the view is rendered.
  62. *
  63. * @property \Cake\Controller\Component\AuthComponent $Auth
  64. * @property \Cake\Controller\Component\CookieComponent $Cookie
  65. * @property \Cake\Controller\Component\CsrfComponent $Csrf
  66. * @property \Cake\Controller\Component\PaginatorComponent $Paginator
  67. * @property \Cake\Controller\Component\RequestHandlerComponent $RequestHandler
  68. * @property \Cake\Controller\Component\SecurityComponent $Security
  69. * @property \Cake\Controller\Component\SessionComponent $Session
  70. * @link http://book.cakephp.org/2.0/en/controllers.html
  71. */
  72. class Controller implements EventListener {
  73. use EventManagerTrait;
  74. use LogTrait;
  75. use MergeVariablesTrait;
  76. use ModelAwareTrait;
  77. use RequestActionTrait;
  78. use ViewVarsTrait;
  79. /**
  80. * The name of this controller. Controller names are plural, named after the model they manipulate.
  81. *
  82. * Set automatically using conventions in Controller::__construct().
  83. *
  84. * @var string
  85. * @link http://book.cakephp.org/2.0/en/controllers.html#controller-attributes
  86. */
  87. public $name = null;
  88. /**
  89. * An array containing the names of helpers this controller uses. The array elements should
  90. * not contain the "Helper" part of the class name.
  91. *
  92. * Example: `public $helpers = ['Form', 'Html', 'Time'];`
  93. *
  94. * @var mixed
  95. * @link http://book.cakephp.org/2.0/en/controllers.html#components-helpers-and-uses
  96. */
  97. public $helpers = array();
  98. /**
  99. * An instance of a Cake\Network\Request object that contains information about the current request.
  100. * This object contains all the information about a request and several methods for reading
  101. * additional information about the request.
  102. *
  103. * @var \Cake\Network\Request
  104. * @link http://book.cakephp.org/2.0/en/controllers/request-response.html#Request
  105. */
  106. public $request;
  107. /**
  108. * An instance of a Response object that contains information about the impending response
  109. *
  110. * @var \Cake\Network\Response
  111. * @link http://book.cakephp.org/2.0/en/controllers/request-response.html#cakeresponse
  112. */
  113. public $response;
  114. /**
  115. * The class name to use for creating the response object.
  116. *
  117. * @var string
  118. */
  119. protected $_responseClass = 'Cake\Network\Response';
  120. /**
  121. * Settings for pagination.
  122. *
  123. * Used to pre-configure pagination preferences for the various
  124. * tables your controller will be paginating.
  125. *
  126. * @var array
  127. * @see \Cake\Controller\Component\PaginatorComponent
  128. */
  129. public $paginate = [];
  130. /**
  131. * Set to true to automatically render the view
  132. * after action logic.
  133. *
  134. * @var bool
  135. */
  136. public $autoRender = true;
  137. /**
  138. * Instance of ComponentRegistry used to create Components
  139. *
  140. * @var \Cake\Controller\ComponentRegistry
  141. */
  142. protected $_components = null;
  143. /**
  144. * Array containing the names of components this controller uses. Component names
  145. * should not contain the "Component" portion of the class name.
  146. *
  147. * Example: `public $components = array('Session', 'RequestHandler', 'Acl');`
  148. *
  149. * @var array
  150. * @link http://book.cakephp.org/2.0/en/controllers/components.html
  151. */
  152. public $components = array();
  153. /**
  154. * The name of the View class this controller sends output to.
  155. *
  156. * @var string
  157. */
  158. public $viewClass = 'Cake\View\View';
  159. /**
  160. * Instance of the View created during rendering. Won't be set until after
  161. * Controller::render() is called.
  162. *
  163. * @var \Cake\View\View
  164. */
  165. public $View;
  166. /**
  167. * These properties are settable directly on Controller and passed to the View as options.
  168. *
  169. * @var array
  170. * @see \Cake\View\View
  171. */
  172. protected $_validViewOptions = [
  173. 'viewVars', 'autoLayout', 'helpers', 'view', 'layout', 'name', 'theme', 'layoutPath',
  174. 'viewPath', 'plugin', 'passedArgs'
  175. ];
  176. /**
  177. * Automatically set to the name of a plugin.
  178. *
  179. * @var string
  180. */
  181. public $plugin = null;
  182. /**
  183. * Holds all passed params.
  184. *
  185. * @var mixed
  186. */
  187. public $passedArgs = array();
  188. /**
  189. * Holds current methods of the controller. This is a list of all the methods reachable
  190. * via URL. Modifying this array, will allow you to change which methods can be reached.
  191. *
  192. * @var array
  193. */
  194. public $methods = array();
  195. /**
  196. * The path to this controllers view templates.
  197. * Example `Articles`
  198. *
  199. * Set automatically using conventions in Controller::__construct().
  200. *
  201. * @var string
  202. */
  203. public $viewPath;
  204. /**
  205. * Constructor.
  206. *
  207. * Sets a number of properties based on conventions if they are empty. To override the
  208. * conventions CakePHP uses you can define properties in your class declaration.
  209. *
  210. * @param \Cake\Network\Request $request Request object for this controller. Can be null for testing,
  211. * but expect that features that use the request parameters will not work.
  212. * @param \Cake\Network\Response $response Response object for this controller.
  213. * @param string $name Override the name useful in testing when using mocks.
  214. */
  215. public function __construct($request = null, $response = null, $name = null) {
  216. if ($this->name === null && $name === null) {
  217. list(, $name) = namespaceSplit(get_class($this));
  218. $name = substr($name, 0, -10);
  219. }
  220. if ($name !== null) {
  221. $this->name = $name;
  222. }
  223. if (!$this->viewPath) {
  224. $viewPath = $this->name;
  225. if (isset($request->params['prefix'])) {
  226. $viewPath = Inflector::camelize($request->params['prefix']) . DS . $viewPath;
  227. }
  228. $this->viewPath = $viewPath;
  229. }
  230. $childMethods = get_class_methods($this);
  231. $baseMethods = get_class_methods('Cake\Controller\Controller');
  232. $this->methods = array_diff($childMethods, $baseMethods);
  233. if ($request instanceof Request) {
  234. $this->setRequest($request);
  235. }
  236. if ($response instanceof Response) {
  237. $this->response = $response;
  238. }
  239. $this->modelFactory('Table', ['Cake\ORM\TableRegistry', 'get']);
  240. $modelClass = ($this->plugin ? $this->plugin . '.' : '') . $this->name;
  241. $this->_setModelClass($modelClass);
  242. }
  243. /**
  244. * Get the component registry for this controller.
  245. *
  246. * @return \Cake\Controller\ComponentRegistry
  247. */
  248. public function components() {
  249. if ($this->_components === null) {
  250. $this->_components = new ComponentRegistry($this);
  251. }
  252. return $this->_components;
  253. }
  254. /**
  255. * Add a component to the controller's registry.
  256. *
  257. * This method will also set the component to a property.
  258. * For example:
  259. *
  260. * `$this->addComponent('DebugKit.Toolbar');`
  261. *
  262. * Will result in a `Toolbar` property being set.
  263. *
  264. * @param string $name The name of the component to load.
  265. * @param array $config The config for the component.
  266. * @return \Cake\Controller\Component
  267. */
  268. public function addComponent($name, array $config = []) {
  269. list(, $prop) = pluginSplit($name);
  270. $this->{$prop} = $this->components()->load($name, $config);
  271. return $this->{$prop};
  272. }
  273. /**
  274. * Provides backwards compatibility to avoid problems with empty and isset to alias properties.
  275. *
  276. * @param string $name Property name
  277. * @return bool
  278. */
  279. public function __get($name) {
  280. if (strpos($this->modelClass, $name) !== false) {
  281. list($plugin, $class) = pluginSplit($this->modelClass, true);
  282. $this->loadModel($plugin . $class);
  283. return $this->{$class};
  284. }
  285. return false;
  286. }
  287. /**
  288. * Sets the request objects and configures a number of controller properties
  289. * based on the contents of the request. Controller acts as a proxy for certain View variables
  290. * which must also be updated here. The properties that get set are:
  291. *
  292. * - $this->request - To the $request parameter
  293. * - $this->plugin - To the $request->params['plugin']
  294. * - $this->autoRender - To false if $request->params['return'] == 1
  295. * - $this->passedArgs - The the combined results of params['named'] and params['pass]
  296. * - View::$passedArgs - $this->passedArgs
  297. * - View::$plugin - $this->plugin
  298. * - View::$view - To the $request->params['action']
  299. * - View::$autoLayout - To the false if $request->params['bare']; is set.
  300. *
  301. * @param \Cake\Network\Request $request Request instance.
  302. * @return void
  303. */
  304. public function setRequest(Request $request) {
  305. $this->request = $request;
  306. $this->plugin = isset($request->params['plugin']) ? $request->params['plugin'] : null;
  307. $this->view = isset($request->params['action']) ? $request->params['action'] : null;
  308. if (isset($request->params['pass'])) {
  309. $this->passedArgs = $request->params['pass'];
  310. }
  311. if (!empty($request->params['return']) && $request->params['return'] == 1) {
  312. $this->autoRender = false;
  313. }
  314. if (!empty($request->params['bare'])) {
  315. $this->autoLayout = false;
  316. }
  317. }
  318. /**
  319. * Dispatches the controller action. Checks that the action
  320. * exists and isn't private.
  321. *
  322. * @return mixed The resulting response.
  323. * @throws \Cake\Error\Exception When request is not set.
  324. * @throws \Cake\Controller\Error\PrivateActionException When actions are not public or prefixed by _
  325. * @throws \Cake\Controller\Error\MissingActionException When actions are not defined.
  326. */
  327. public function invokeAction() {
  328. try {
  329. $request = $this->request;
  330. if (!isset($request)) {
  331. throw new Exception('No Request object configured. Cannot invoke action');
  332. }
  333. $method = new \ReflectionMethod($this, $request->params['action']);
  334. if ($this->_isPrivateAction($method, $request)) {
  335. throw new Error\PrivateActionException(array(
  336. 'controller' => $this->name . "Controller",
  337. 'action' => $request->params['action'],
  338. 'prefix' => isset($request->params['prefix']) ? $request->params['prefix'] : '',
  339. 'plugin' => $request->params['plugin'],
  340. ));
  341. }
  342. return $method->invokeArgs($this, $request->params['pass']);
  343. } catch (\ReflectionException $e) {
  344. throw new Error\MissingActionException(array(
  345. 'controller' => $this->name . "Controller",
  346. 'action' => $request->params['action'],
  347. 'prefix' => isset($request->params['prefix']) ? $request->params['prefix'] : '',
  348. 'plugin' => $request->params['plugin'],
  349. ));
  350. }
  351. }
  352. /**
  353. * Check if the request's action is marked as private, with an underscore,
  354. * or if the request is attempting to directly accessing a prefixed action.
  355. *
  356. * @param \ReflectionMethod $method The method to be invoked.
  357. * @param \Cake\Network\Request $request The request to check.
  358. * @return bool
  359. */
  360. protected function _isPrivateAction(\ReflectionMethod $method, Request $request) {
  361. return (
  362. $method->name[0] === '_' ||
  363. !$method->isPublic() ||
  364. !in_array($method->name, $this->methods)
  365. );
  366. }
  367. /**
  368. * Merge components, helpers vars from
  369. * parent classes.
  370. *
  371. * @return void
  372. */
  373. protected function _mergeControllerVars() {
  374. $this->_mergeVars(
  375. ['components', 'helpers'],
  376. ['associative' => ['components', 'helpers']]
  377. );
  378. }
  379. /**
  380. * Returns a list of all events that will fire in the controller during it's lifecycle.
  381. * You can override this function to add you own listener callbacks
  382. *
  383. * @return array
  384. */
  385. public function implementedEvents() {
  386. return array(
  387. 'Controller.initialize' => 'beforeFilter',
  388. 'Controller.beforeRender' => 'beforeRender',
  389. 'Controller.beforeRedirect' => 'beforeRedirect',
  390. 'Controller.shutdown' => 'afterFilter',
  391. );
  392. }
  393. /**
  394. * Loads Model and Component classes.
  395. *
  396. * Using the $components properties, classes are loaded
  397. * and components have their callbacks attached to the EventManager.
  398. * It is also at this time that Controller callbacks are bound.
  399. *
  400. * @return void
  401. * @link http://book.cakephp.org/2.0/en/controllers.html#Controller::constructClasses
  402. */
  403. public function constructClasses() {
  404. $this->_mergeControllerVars();
  405. $this->_loadComponents();
  406. $this->eventManager()->attach($this);
  407. }
  408. /**
  409. * Loads the defined components using the Component factory.
  410. *
  411. * @return void
  412. */
  413. protected function _loadComponents() {
  414. if (empty($this->components)) {
  415. return;
  416. }
  417. $registry = $this->components();
  418. $components = $registry->normalizeArray($this->components);
  419. foreach ($components as $properties) {
  420. list(, $class) = pluginSplit($properties['class']);
  421. $this->{$class} = $registry->load($properties['class'], $properties['config']);
  422. }
  423. }
  424. /**
  425. * Perform the startup process for this controller.
  426. * Fire the Components and Controller callbacks in the correct order.
  427. *
  428. * - Initializes components, which fires their `initialize` callback
  429. * - Calls the controller `beforeFilter`.
  430. * - triggers Component `startup` methods.
  431. *
  432. * @return void|\Cake\Network\Response
  433. */
  434. public function startupProcess() {
  435. $event = $this->eventManager()->dispatch(new Event('Controller.initialize', $this));
  436. if ($event->result instanceof Response) {
  437. return $event->result;
  438. }
  439. $event = $this->eventManager()->dispatch(new Event('Controller.startup', $this));
  440. if ($event->result instanceof Response) {
  441. return $event->result;
  442. }
  443. }
  444. /**
  445. * Perform the various shutdown processes for this controller.
  446. * Fire the Components and Controller callbacks in the correct order.
  447. *
  448. * - triggers the component `shutdown` callback.
  449. * - calls the Controller's `afterFilter` method.
  450. *
  451. * @return void|\Cake\Network\Response
  452. */
  453. public function shutdownProcess() {
  454. $event = $this->eventManager()->dispatch(new Event('Controller.shutdown', $this));
  455. if ($event->result instanceof Response) {
  456. return $event->result;
  457. }
  458. }
  459. /**
  460. * Redirects to given $url, after turning off $this->autoRender.
  461. * Script execution is halted after the redirect.
  462. *
  463. * @param string|array $url A string or array-based URL pointing to another location within the app,
  464. * or an absolute URL
  465. * @param int $status Optional HTTP status code (eg: 404)
  466. * @return void|\Cake\Network\Response
  467. * @link http://book.cakephp.org/3.0/en/controllers.html#Controller::redirect
  468. */
  469. public function redirect($url, $status = null) {
  470. $this->autoRender = false;
  471. $response = $this->response;
  472. if ($status && $response->statusCode() === 200) {
  473. $response->statusCode($status);
  474. }
  475. $event = new Event('Controller.beforeRedirect', $this, [$url, $response]);
  476. $event = $this->eventManager()->dispatch($event);
  477. if ($event->result instanceof Response) {
  478. return $event->result;
  479. }
  480. if ($event->isStopped()) {
  481. return;
  482. }
  483. if ($url !== null && !$response->location()) {
  484. $response->location(Router::url($url, true));
  485. }
  486. return $response;
  487. }
  488. /**
  489. * Internally redirects one action to another. Does not perform another HTTP request unlike Controller::redirect()
  490. *
  491. * Examples:
  492. *
  493. * {{{
  494. * setAction('another_action');
  495. * setAction('action_with_parameters', $parameter1);
  496. * }}}
  497. *
  498. * @param string $action The new action to be 'redirected' to.
  499. * Any other parameters passed to this method will be passed as parameters to the new action.
  500. * @return mixed Returns the return value of the called action
  501. */
  502. public function setAction($action) {
  503. $this->request->params['action'] = $action;
  504. $this->view = $action;
  505. $args = func_get_args();
  506. unset($args[0]);
  507. return call_user_func_array(array(&$this, $action), $args);
  508. }
  509. /**
  510. * Instantiates the correct view class, hands it its data, and uses it to render the view output.
  511. *
  512. * @param string $view View to use for rendering
  513. * @param string $layout Layout to use
  514. * @return \Cake\Network\Response A response object containing the rendered view.
  515. * @link http://book.cakephp.org/2.0/en/controllers.html#Controller::render
  516. */
  517. public function render($view = null, $layout = null) {
  518. $event = new Event('Controller.beforeRender', $this);
  519. $event = $this->eventManager()->dispatch($event);
  520. if ($event->result instanceof Response) {
  521. $this->autoRender = false;
  522. return $event->result;
  523. }
  524. if ($event->isStopped()) {
  525. $this->autoRender = false;
  526. return $this->response;
  527. }
  528. $this->View = $this->createView();
  529. $this->autoRender = false;
  530. $this->response->body($this->View->render($view, $layout));
  531. return $this->response;
  532. }
  533. /**
  534. * Returns the referring URL for this request.
  535. *
  536. * @param string $default Default URL to use if HTTP_REFERER cannot be read from headers
  537. * @param bool $local If true, restrict referring URLs to local server
  538. * @return string Referring URL
  539. * @link http://book.cakephp.org/2.0/en/controllers.html#Controller::referer
  540. */
  541. public function referer($default = null, $local = false) {
  542. if (!$this->request) {
  543. return '/';
  544. }
  545. $referer = $this->request->referer($local);
  546. if ($referer === '/' && $default) {
  547. return Router::url($default, !$local);
  548. }
  549. return $referer;
  550. }
  551. /**
  552. * Handles pagination of records in Table objects.
  553. *
  554. * Will load the referenced Table object, and have the PaginatorComponent
  555. * paginate the query using the request date and settings defined in `$this->paginate`.
  556. *
  557. * This method will also make the PaginatorHelper available in the view.
  558. *
  559. * @param \Cake\ORM\Table|string|\Cake\ORM\Query $object Table to paginate
  560. * (e.g: Table instance, 'TableName' or a Query object)
  561. * @return \Cake\ORM\ResultSet Query results
  562. * @link http://book.cakephp.org/3.0/en/controllers.html#Controller::paginate
  563. * @throws \RuntimeException When no compatible table object can be found.
  564. */
  565. public function paginate($object = null) {
  566. if (is_object($object)) {
  567. $table = $object;
  568. }
  569. if (is_string($object) || $object === null) {
  570. $try = [$object, $this->modelClass];
  571. foreach ($try as $tableName) {
  572. if (empty($tableName)) {
  573. continue;
  574. }
  575. $table = TableRegistry::get($tableName);
  576. break;
  577. }
  578. }
  579. $this->addComponent('Paginator');
  580. if (
  581. !in_array('Paginator', $this->helpers) &&
  582. !array_key_exists('Paginator', $this->helpers)
  583. ) {
  584. $this->helpers[] = 'Paginator';
  585. }
  586. if (empty($table)) {
  587. throw new \RuntimeException('Unable to locate an object compatible with paginate.');
  588. }
  589. return $this->Paginator->paginate($table, $this->paginate);
  590. }
  591. /**
  592. * Called before the controller action. You can use this method to configure and customize components
  593. * or perform logic that needs to happen before each controller action.
  594. *
  595. * @param Event $event An Event instance
  596. * @return void
  597. * @link http://book.cakephp.org/2.0/en/controllers.html#request-life-cycle-callbacks
  598. */
  599. public function beforeFilter(Event $event) {
  600. }
  601. /**
  602. * Called after the controller action is run, but before the view is rendered. You can use this method
  603. * to perform logic or set view variables that are required on every request.
  604. *
  605. * @param Event $event An Event instance
  606. * @return void
  607. * @link http://book.cakephp.org/2.0/en/controllers.html#request-life-cycle-callbacks
  608. */
  609. public function beforeRender(Event $event) {
  610. }
  611. /**
  612. * The beforeRedirect method is invoked when the controller's redirect method is called but before any
  613. * further action.
  614. *
  615. * If the event is stopped the controller will not continue on to redirect the request.
  616. * The $url and $status variables have same meaning as for the controller's method.
  617. * You can set the event result to response instance or modify the redirect location
  618. * using controller's response instance.
  619. *
  620. * @param Event $event An Event instance
  621. * @param string|array $url A string or array-based URL pointing to another location within the app,
  622. * or an absolute URL
  623. * @param \Cake\Network\Response $response The response object.
  624. * @return void
  625. * @link http://book.cakephp.org/2.0/en/controllers.html#request-life-cycle-callbacks
  626. */
  627. public function beforeRedirect(Event $event, $url, Response $response) {
  628. }
  629. /**
  630. * Called after the controller action is run and rendered.
  631. *
  632. * @param Event $event An Event instance
  633. * @return void
  634. * @link http://book.cakephp.org/2.0/en/controllers.html#request-life-cycle-callbacks
  635. */
  636. public function afterFilter(Event $event) {
  637. }
  638. }