Component.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  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 1.2.0
  13. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Controller;
  16. use Cake\Core\InstanceConfigTrait;
  17. use Cake\Event\EventListenerInterface;
  18. use Cake\Log\LogTrait;
  19. /**
  20. * Base class for an individual Component. Components provide reusable bits of
  21. * controller logic that can be composed into a controller. Components also
  22. * provide request life-cycle callbacks for injecting logic at specific points.
  23. *
  24. * ### Initialize hook
  25. *
  26. * Like Controller and Table, this class has an initialize() hook that you can use
  27. * to add custom 'constructor' logic. It is important to remember that each request
  28. * (and sub-request) will only make one instance of any given component.
  29. *
  30. * ### Life cycle callbacks
  31. *
  32. * Components can provide several callbacks that are fired at various stages of the request
  33. * cycle. The available callbacks are:
  34. *
  35. * - `beforeFilter(Event $event)`
  36. * Called before the controller's beforeFilter method by default.
  37. * - `startup(Event $event)`
  38. * Called after the controller's beforeFilter method, and before the
  39. * controller action is called.
  40. * - `beforeRender(Event $event)`
  41. * Called before the Controller beforeRender, and before the view class is loaded.
  42. * - `shutdown(Event $event)`
  43. * Called after the action is complete and the view has been rendered but
  44. * before Controller::afterFilter().
  45. * - `beforeRedirect(Event $event $url, Response $response)`
  46. * Called before a redirect is done. Allows you to change the URL that will
  47. * be redirected to by returning a Response instance with new URL set using
  48. * Response::location(). Redirection can be prevented by stopping the event
  49. * propagation.
  50. *
  51. * While the controller is not an explicit argument for the callback methods it
  52. * is the subject of each event and can be fetched using Event::subject().
  53. *
  54. * @link http://book.cakephp.org/3.0/en/controllers/components.html
  55. * @see Controller::$components
  56. */
  57. class Component implements EventListenerInterface
  58. {
  59. use InstanceConfigTrait;
  60. use LogTrait;
  61. /**
  62. * Request object
  63. *
  64. * @var \Cake\Network\Request
  65. */
  66. public $request;
  67. /**
  68. * Component registry class used to lazy load components.
  69. *
  70. * @var \Cake\Controller\ComponentRegistry
  71. */
  72. protected $_registry;
  73. /**
  74. * Other Components this component uses.
  75. *
  76. * @var array
  77. */
  78. public $components = [];
  79. /**
  80. * Default config
  81. *
  82. * These are merged with user-provided config when the component is used.
  83. *
  84. * @var array
  85. */
  86. protected $_defaultConfig = [];
  87. /**
  88. * A component lookup table used to lazy load component objects.
  89. *
  90. * @var array
  91. */
  92. protected $_componentMap = [];
  93. /**
  94. * Constructor
  95. *
  96. * @param ComponentRegistry $registry A ComponentRegistry this component can use to lazy load its components
  97. * @param array $config Array of configuration settings.
  98. */
  99. public function __construct(ComponentRegistry $registry, array $config = [])
  100. {
  101. $this->_registry = $registry;
  102. $controller = $registry->getController();
  103. if ($controller) {
  104. $this->request =& $controller->request;
  105. }
  106. $this->config($config);
  107. if (!empty($this->components)) {
  108. $this->_componentMap = $registry->normalizeArray($this->components);
  109. }
  110. $this->initialize($config);
  111. }
  112. /**
  113. * Constructor hook method.
  114. *
  115. * Implement this method to avoid having to overwrite
  116. * the constructor and call parent.
  117. *
  118. * @param array $config The configuration settings provided to this component.
  119. * @return void
  120. */
  121. public function initialize(array $config)
  122. {
  123. }
  124. /**
  125. * Magic method for lazy loading $components.
  126. *
  127. * @param string $name Name of component to get.
  128. * @return mixed A Component object or null.
  129. */
  130. public function __get($name)
  131. {
  132. if (isset($this->_componentMap[$name]) && !isset($this->{$name})) {
  133. $config = ['enabled' => false] + (array)$this->_componentMap[$name]['config'];
  134. $this->{$name} = $this->_registry->load($this->_componentMap[$name]['class'], $config);
  135. }
  136. if (isset($this->{$name})) {
  137. return $this->{$name};
  138. }
  139. }
  140. /**
  141. * Get the Controller callbacks this Component is interested in.
  142. *
  143. * Uses Conventions to map controller events to standard component
  144. * callback method names. By defining one of the callback methods a
  145. * component is assumed to be interested in the related event.
  146. *
  147. * Override this method if you need to add non-conventional event listeners.
  148. * Or if you want components to listen to non-standard events.
  149. *
  150. * @return array
  151. */
  152. public function implementedEvents()
  153. {
  154. $eventMap = [
  155. 'Controller.initialize' => 'beforeFilter',
  156. 'Controller.startup' => 'startup',
  157. 'Controller.beforeRender' => 'beforeRender',
  158. 'Controller.beforeRedirect' => 'beforeRedirect',
  159. 'Controller.shutdown' => 'shutdown',
  160. ];
  161. $events = [];
  162. foreach ($eventMap as $event => $method) {
  163. if (method_exists($this, $method)) {
  164. $events[$event] = $method;
  165. }
  166. }
  167. return $events;
  168. }
  169. }