1: <?php
2: /**
3: * Components collection is used as a registry for loaded components and handles loading
4: * and constructing component class objects.
5: *
6: * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
7: * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
8: *
9: * Licensed under The MIT License
10: * For full copyright and license information, please see the LICENSE.txt
11: * Redistributions of files must retain the above copyright notice.
12: *
13: * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
14: * @link https://cakephp.org CakePHP(tm) Project
15: * @package Cake.Controller
16: * @since CakePHP(tm) v 2.0
17: * @license https://opensource.org/licenses/mit-license.php MIT License
18: */
19:
20: App::uses('ObjectCollection', 'Utility');
21: App::uses('Component', 'Controller');
22: App::uses('CakeEventListener', 'Event');
23:
24: /**
25: * Components collection is used as a registry for loaded components and handles loading
26: * and constructing component class objects.
27: *
28: * @package Cake.Controller
29: */
30: class ComponentCollection extends ObjectCollection implements CakeEventListener {
31:
32: /**
33: * The controller that this collection was initialized with.
34: *
35: * @var Controller
36: */
37: protected $_Controller = null;
38:
39: /**
40: * Initializes all the Components for a controller.
41: * Attaches a reference of each component to the Controller.
42: *
43: * @param Controller $Controller Controller to initialize components for.
44: * @return void
45: */
46: public function init(Controller $Controller) {
47: if (empty($Controller->components)) {
48: return;
49: }
50: $this->_Controller = $Controller;
51: $components = ComponentCollection::normalizeObjectArray($Controller->components);
52: foreach ($components as $name => $properties) {
53: $Controller->{$name} = $this->load($properties['class'], $properties['settings']);
54: }
55: }
56:
57: /**
58: * Set the controller associated with the collection.
59: *
60: * @param Controller $Controller Controller to set
61: * @return void
62: */
63: public function setController(Controller $Controller) {
64: $this->_Controller = $Controller;
65: }
66:
67: /**
68: * Get the controller associated with the collection.
69: *
70: * @return Controller Controller instance
71: */
72: public function getController() {
73: return $this->_Controller;
74: }
75:
76: /**
77: * Loads/constructs a component. Will return the instance in the registry if it already exists.
78: * You can use `$settings['enabled'] = false` to disable callbacks on a component when loading it.
79: * Callbacks default to on. Disabled component methods work as normal, only callbacks are disabled.
80: *
81: * You can alias your component as an existing component by setting the 'className' key, i.e.,
82: * ```
83: * public $components = array(
84: * 'Email' => array(
85: * 'className' => 'AliasedEmail'
86: * );
87: * );
88: * ```
89: * All calls to the `Email` component would use `AliasedEmail` instead.
90: *
91: * @param string $component Component name to load
92: * @param array $settings Settings for the component.
93: * @return Component A component object, Either the existing loaded component or a new one.
94: * @throws MissingComponentException when the component could not be found
95: */
96: public function load($component, $settings = array()) {
97: if (isset($settings['className'])) {
98: $alias = $component;
99: $component = $settings['className'];
100: }
101: list($plugin, $name) = pluginSplit($component, true);
102: if (!isset($alias)) {
103: $alias = $name;
104: }
105: if (isset($this->_loaded[$alias])) {
106: return $this->_loaded[$alias];
107: }
108: $componentClass = $name . 'Component';
109: App::uses($componentClass, $plugin . 'Controller/Component');
110: if (!class_exists($componentClass)) {
111: throw new MissingComponentException(array(
112: 'class' => $componentClass,
113: 'plugin' => substr($plugin, 0, -1)
114: ));
115: }
116: $this->_loaded[$alias] = new $componentClass($this, $settings);
117: $enable = isset($settings['enabled']) ? $settings['enabled'] : true;
118: if ($enable) {
119: $this->enable($alias);
120: }
121: return $this->_loaded[$alias];
122: }
123:
124: /**
125: * Returns the implemented events that will get routed to the trigger function
126: * in order to dispatch them separately on each component
127: *
128: * @return array
129: */
130: public function implementedEvents() {
131: return array(
132: 'Controller.initialize' => array('callable' => 'trigger'),
133: 'Controller.startup' => array('callable' => 'trigger'),
134: 'Controller.beforeRender' => array('callable' => 'trigger'),
135: 'Controller.beforeRedirect' => array('callable' => 'trigger'),
136: 'Controller.shutdown' => array('callable' => 'trigger'),
137: );
138: }
139:
140: }
141: