Component.php 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  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 CakePHP(tm) v 1.2
  13. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Controller;
  16. use Cake\Core\Object;
  17. use Cake\Event\Event;
  18. use Cake\Event\EventListener;
  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. * ## Life cycle callbacks
  25. *
  26. * Components can provide several callbacks that are fired at various stages of the request
  27. * cycle. The available callbacks are:
  28. *
  29. * - `initialize()` - Called before the controller's beforeFilter method.
  30. * - `startup()` - Called after the controller's beforeFilter method,
  31. * and before the controller action is called.
  32. * - `beforeRender()` - Called before the Controller beforeRender, and
  33. * before the view class is loaded.
  34. * - `shutdown()` - Called after the action is complete and the view has been rendered.
  35. * but before Controller::afterFilter().
  36. * - `beforeRedirect()` - Called before Controller::redirect(), and
  37. * before a redirect() is done. Allows you to replace the URL that will
  38. * be redirected to with a new URL. The return of this method can either be an
  39. * array or a string. If the return is an array and contains a 'url' key.
  40. * You may also supply the following:
  41. *
  42. * - `status` The status code for the redirect
  43. * - `exit` Whether or not the redirect should exit.
  44. *
  45. * If your response is a string or an array that does not contain a 'url' key it will
  46. * be used as the new URL to redirect to.
  47. *
  48. * Each callback has a slightly different signature:
  49. *
  50. * - `intitalize(Event $event)`
  51. * - `startup(Event $event)`
  52. * - `beforeRender(Event $event)`
  53. * - `beforeRedirect(Event $event $url, Response $response)`
  54. * - `shutdown(Event $event)`
  55. *
  56. * While the controller is not an explicit argument it is the subject of each event
  57. * and can be fetched using Event::subject().
  58. *
  59. * @link http://book.cakephp.org/2.0/en/controllers/components.html
  60. * @see Controller::$components
  61. */
  62. class Component extends Object implements EventListener {
  63. /**
  64. * Component registry class used to lazy load components.
  65. *
  66. * @var ComponentRegistry
  67. */
  68. protected $_registry;
  69. /**
  70. * Settings for this Component
  71. *
  72. * @var array
  73. */
  74. public $settings = array();
  75. /**
  76. * Other Components this component uses.
  77. *
  78. * @var array
  79. */
  80. public $components = array();
  81. /**
  82. * A component lookup table used to lazy load component objects.
  83. *
  84. * @var array
  85. */
  86. protected $_componentMap = array();
  87. /**
  88. * Constructor
  89. *
  90. * @param ComponentRegistry $registry A ComponentRegistry this component can use to lazy load its components
  91. * @param array $settings Array of configuration settings.
  92. */
  93. public function __construct(ComponentRegistry $registry, $settings = []) {
  94. $this->_registry = $registry;
  95. $this->settings = $settings;
  96. $this->_set($settings);
  97. if (!empty($this->components)) {
  98. $this->_componentMap = $registry->normalizeArray($this->components);
  99. }
  100. }
  101. /**
  102. * Magic method for lazy loading $components.
  103. *
  104. * @param string $name Name of component to get.
  105. * @return mixed A Component object or null.
  106. */
  107. public function __get($name) {
  108. if (isset($this->_componentMap[$name]) && !isset($this->{$name})) {
  109. $settings = array_merge((array)$this->_componentMap[$name]['settings'], array('enabled' => false));
  110. $this->{$name} = $this->_registry->load($this->_componentMap[$name]['class'], $settings);
  111. }
  112. if (isset($this->{$name})) {
  113. return $this->{$name};
  114. }
  115. }
  116. /**
  117. * Get the Controller callbacks this Component is interested in.
  118. *
  119. * Uses Conventions to map controller events to standard component
  120. * callback method names. By defining one of the callback methods a
  121. * component is assumed to be interested in the related event.
  122. *
  123. * Override this method if you need to add non-conventional event listeners.
  124. * Or if you want components to listen to non-standard events.
  125. *
  126. * @return array
  127. */
  128. public function implementedEvents() {
  129. $eventMap = [
  130. 'Controller.initialize' => 'initialize',
  131. 'Controller.startup' => 'startup',
  132. 'Controller.beforeRender' => 'beforeRender',
  133. 'Controller.beforeRedirect' => 'beforeRedirect',
  134. 'Controller.shutdown' => 'shutdown',
  135. ];
  136. $events = [];
  137. foreach ($eventMap as $event => $method) {
  138. if (method_exists($this, $method)) {
  139. $events[$event] = $method;
  140. }
  141. }
  142. return $events;
  143. }
  144. }