Controller.php 26 KB

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