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