cake/libs/controller/component.php
| 1 | <?php |
|---|---|
| 2 | /** |
| 3 | * |
| 4 | * PHP versions 4 and 5 |
| 5 | * |
| 6 | * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) |
| 7 | * Copyright 2005-2011, 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-2011, Cake Software Foundation, Inc. (http://cakefoundation.org) |
| 13 | * @link http://cakephp.org CakePHP(tm) Project |
| 14 | * @package cake |
| 15 | * @subpackage cake.cake.libs.controller |
| 16 | * @since CakePHP(tm) v TBD |
| 17 | * @license MIT License (http://www.opensource.org/licenses/mit-license.php) |
| 18 | */ |
| 19 | |
| 20 | /** |
| 21 | * Handler for Controller::$components |
| 22 | * |
| 23 | * @package cake |
| 24 | * @subpackage cake.cake.libs.controller |
| 25 | * @link http://book.cakephp.org/view/993/Components |
| 26 | */ |
| 27 | class Component extends Object { |
| 28 | |
| 29 | /** |
| 30 | * Contains various controller variable information (plugin, name, base). |
| 31 | * |
| 32 | * @var object |
| 33 | * @access private |
| 34 | */ |
| 35 | var $__controllerVars = array('plugin' => null, 'name' => null, 'base' => null); |
| 36 | |
| 37 | /** |
| 38 | * List of loaded components. |
| 39 | * |
| 40 | * @var object |
| 41 | * @access protected |
| 42 | */ |
| 43 | var $_loaded = array(); |
| 44 | |
| 45 | /** |
| 46 | * List of components attached directly to the controller, which callbacks |
| 47 | * should be executed on. |
| 48 | * |
| 49 | * @var object |
| 50 | * @access protected |
| 51 | */ |
| 52 | var $_primary = array(); |
| 53 | |
| 54 | /** |
| 55 | * Settings for loaded components. |
| 56 | * |
| 57 | * @var array |
| 58 | * @access private |
| 59 | */ |
| 60 | var $__settings = array(); |
| 61 | |
| 62 | /** |
| 63 | * Used to initialize the components for current controller. |
| 64 | * |
| 65 | * @param object $controller Controller with components to load |
| 66 | * @return void |
| 67 | * @access public |
| 68 | */ |
| 69 | function init(&$controller) { |
| 70 | if (!is_array($controller->components)) { |
| 71 | return; |
| 72 | } |
| 73 | $this->__controllerVars = array( |
| 74 | 'plugin' => $controller->plugin, 'name' => $controller->name, |
| 75 | 'base' => $controller->base |
| 76 | ); |
| 77 | |
| 78 | $this->_loadComponents($controller); |
| 79 | } |
| 80 | |
| 81 | /** |
| 82 | * Called before the Controller::beforeFilter(). |
| 83 | * |
| 84 | * @param object $controller Controller with components to initialize |
| 85 | * @return void |
| 86 | * @access public |
| 87 | * @link http://book.cakephp.org/view/998/MVC-Class-Access-Within-Components |
| 88 | */ |
| 89 | function initialize(&$controller) { |
| 90 | foreach (array_keys($this->_loaded) as $name) { |
| 91 | $component =& $this->_loaded[$name]; |
| 92 | |
| 93 | if (method_exists($component,'initialize') && $component->enabled === true) { |
| 94 | $settings = array(); |
| 95 | if (isset($this->__settings[$name])) { |
| 96 | $settings = $this->__settings[$name]; |
| 97 | } |
| 98 | $component->initialize($controller, $settings); |
| 99 | } |
| 100 | } |
| 101 | } |
| 102 | |
| 103 | /** |
| 104 | * Called after the Controller::beforeFilter() and before the controller action |
| 105 | * |
| 106 | * @param object $controller Controller with components to startup |
| 107 | * @return void |
| 108 | * @access public |
| 109 | * @link http://book.cakephp.org/view/998/MVC-Class-Access-Within-Components |
| 110 | * @deprecated See Component::triggerCallback() |
| 111 | */ |
| 112 | function startup(&$controller) { |
| 113 | $this->triggerCallback('startup', $controller); |
| 114 | } |
| 115 | |
| 116 | /** |
| 117 | * Called after the Controller::beforeRender(), after the view class is loaded, and before the |
| 118 | * Controller::render() |
| 119 | * |
| 120 | * @param object $controller Controller with components to beforeRender |
| 121 | * @return void |
| 122 | * @access public |
| 123 | * @deprecated See Component::triggerCallback() |
| 124 | */ |
| 125 | function beforeRender(&$controller) { |
| 126 | $this->triggerCallback('beforeRender', $controller); |
| 127 | } |
| 128 | |
| 129 | /** |
| 130 | * Called before Controller::redirect(). |
| 131 | * |
| 132 | * @param object $controller Controller with components to beforeRedirect |
| 133 | * @return void |
| 134 | * @access public |
| 135 | */ |
| 136 | function beforeRedirect(&$controller, $url, $status = null, $exit = true) { |
| 137 | $response = array(); |
| 138 | |
| 139 | foreach ($this->_primary as $name) { |
| 140 | $component =& $this->_loaded[$name]; |
| 141 | |
| 142 | if ($component->enabled === true && method_exists($component, 'beforeRedirect')) { |
| 143 | $resp = $component->beforeRedirect($controller, $url, $status, $exit); |
| 144 | if ($resp === false) { |
| 145 | return false; |
| 146 | } |
| 147 | $response[] = $resp; |
| 148 | } |
| 149 | } |
| 150 | return $response; |
| 151 | } |
| 152 | |
| 153 | /** |
| 154 | * Called after Controller::render() and before the output is printed to the browser. |
| 155 | * |
| 156 | * @param object $controller Controller with components to shutdown |
| 157 | * @return void |
| 158 | * @access public |
| 159 | * @deprecated See Component::triggerCallback() |
| 160 | */ |
| 161 | function shutdown(&$controller) { |
| 162 | $this->triggerCallback('shutdown', $controller); |
| 163 | } |
| 164 | |
| 165 | /** |
| 166 | * Trigger a callback on all primary components. Will fire $callback on all components |
| 167 | * that have such a method. You can implement and fire custom callbacks in addition to the |
| 168 | * standard ones. |
| 169 | * |
| 170 | * example use, from inside a controller: |
| 171 | * |
| 172 | * `$this->Component->triggerCallback('beforeFilter', $this);` |
| 173 | * |
| 174 | * will trigger the beforeFilter callback on all components that have implemented one. You |
| 175 | * can trigger any method in this fashion. |
| 176 | * |
| 177 | * @param Controller $controller Controller instance |
| 178 | * @param string $callback Callback to trigger. |
| 179 | * @return void |
| 180 | * @access public |
| 181 | */ |
| 182 | function triggerCallback($callback, &$controller) { |
| 183 | foreach ($this->_primary as $name) { |
| 184 | $component =& $this->_loaded[$name]; |
| 185 | if (method_exists($component, $callback) && $component->enabled === true) { |
| 186 | $component->{$callback}($controller); |
| 187 | } |
| 188 | } |
| 189 | } |
| 190 | |
| 191 | /** |
| 192 | * Loads components used by this component. |
| 193 | * |
| 194 | * @param object $object Object with a Components array |
| 195 | * @param object $parent the parent of the current object |
| 196 | * @return void |
| 197 | * @access protected |
| 198 | */ |
| 199 | function _loadComponents(&$object, $parent = null) { |
| 200 | $base = $this->__controllerVars['base']; |
| 201 | $normal = Set::normalize($object->components); |
| 202 | foreach ((array)$normal as $component => $config) { |
| 203 | $plugin = isset($this->__controllerVars['plugin']) ? $this->__controllerVars['plugin'] . '.' : null; |
| 204 | list($plugin, $component) = pluginSplit($component, true, $plugin); |
| 205 | $componentCn = $component . 'Component'; |
| 206 | |
| 207 | if (!class_exists($componentCn)) { |
| 208 | if (is_null($plugin) || !App::import('Component', $plugin . $component)) { |
| 209 | if (!App::import('Component', $component)) { |
| 210 | $this->cakeError('missingComponentFile', array(array( |
| 211 | 'className' => $this->__controllerVars['name'], |
| 212 | 'component' => $component, |
| 213 | 'file' => Inflector::underscore($component) . '.php', |
| 214 | 'base' => $base, |
| 215 | 'code' => 500 |
| 216 | ))); |
| 217 | return false; |
| 218 | } |
| 219 | } |
| 220 | |
| 221 | if (!class_exists($componentCn)) { |
| 222 | $this->cakeError('missingComponentClass', array(array( |
| 223 | 'className' => $this->__controllerVars['name'], |
| 224 | 'component' => $component, |
| 225 | 'file' => Inflector::underscore($component) . '.php', |
| 226 | 'base' => $base, |
| 227 | 'code' => 500 |
| 228 | ))); |
| 229 | return false; |
| 230 | } |
| 231 | } |
| 232 | |
| 233 | if ($parent === null) { |
| 234 | $this->_primary[] = $component; |
| 235 | } |
| 236 | |
| 237 | if (isset($this->_loaded[$component])) { |
| 238 | $object->{$component} =& $this->_loaded[$component]; |
| 239 | |
| 240 | if (!empty($config) && isset($this->__settings[$component])) { |
| 241 | $this->__settings[$component] = array_merge($this->__settings[$component], $config); |
| 242 | } elseif (!empty($config)) { |
| 243 | $this->__settings[$component] = $config; |
| 244 | } |
| 245 | } else { |
| 246 | if ($componentCn === 'SessionComponent') { |
| 247 | $object->{$component} =& new $componentCn($base); |
| 248 | } else { |
| 249 | if (PHP5) { |
| 250 | $object->{$component} = new $componentCn(); |
| 251 | } else { |
| 252 | $object->{$component} =& new $componentCn(); |
| 253 | } |
| 254 | } |
| 255 | $object->{$component}->enabled = true; |
| 256 | $this->_loaded[$component] =& $object->{$component}; |
| 257 | if (!empty($config)) { |
| 258 | $this->__settings[$component] = $config; |
| 259 | } |
| 260 | } |
| 261 | |
| 262 | if (isset($object->{$component}->components) && is_array($object->{$component}->components) && (!isset($object->{$component}->{$parent}))) { |
| 263 | $this->_loadComponents($object->{$component}, $component); |
| 264 | } |
| 265 | } |
| 266 | } |
| 267 | } |
| 268 | |
| 269 |