Skip to content
This repository
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 324 lines (306 sloc) 10.361 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
<?php
/**
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/

/**
* Deals with Collections of objects. Keeping registries of those objects,
* loading and constructing new objects and triggering callbacks. Each subclass needs
* to implement its own load() functionality.
*
* All core subclasses of ObjectCollection by convention loaded objects are stored
* in `$this->_loaded`. Enabled objects are stored in `$this->_enabled`. In addition
* the all support an `enabled` option that controls the enabled/disabled state of the object
* when loaded.
*
* @package Cake.Utility
* @since CakePHP(tm) v 2.0
*/
abstract class ObjectCollection {

/**
* List of the currently-enabled objects
*
* @var array
*/
protected $_enabled = array();

/**
* A hash of loaded objects, indexed by name
*
* @var array
*/
protected $_loaded = array();

/**
* Default object priority. A non zero integer.
*
* @var int
*/
public $defaultPriority = 10;

/**
* Loads a new object onto the collection. Can throw a variety of exceptions
*
* Implementations of this class support a `$options['enabled']` flag which enables/disables
* a loaded object.
*
* @param string $name Name of object to load.
* @param array $options Array of configuration options for the object to be constructed.
* @return object the constructed object
*/
abstract public function load($name, $options = array());

/**
* Trigger a callback method on every object in the collection.
* Used to trigger methods on objects in the collection. Will fire the methods in the
* order they were attached.
*
* ### Options
*
* - `breakOn` Set to the value or values you want the callback propagation to stop on.
* Can either be a scalar value, or an array of values to break on. Defaults to `false`.
*
* - `break` Set to true to enabled breaking. When a trigger is broken, the last returned value
* will be returned. If used in combination with `collectReturn` the collected results will be returned.
* Defaults to `false`.
*
* - `collectReturn` Set to true to collect the return of each object into an array.
* This array of return values will be returned from the trigger() call. Defaults to `false`.
*
* - `modParams` Allows each object the callback gets called on to modify the parameters to the next object.
* Setting modParams to an integer value will allow you to modify the parameter with that index.
* Any non-null value will modify the parameter index indicated.
* Defaults to false.
*
*
* @param string $callback|CakeEvent Method to fire on all the objects. Its assumed all the objects implement
* the method you are calling. If an instance of CakeEvent is provided, then then Event name will parsed to
* get the callback name. This is done by getting the last word after any dot in the event name
* (eg. `Model.afterSave` event will trigger the `afterSave` callback)
* @param array $params Array of parameters for the triggered callback.
* @param array $options Array of options.
* @return mixed Either the last result or all results if collectReturn is on.
* @throws CakeException when modParams is used with an index that does not exist.
*/
public function trigger($callback, $params = array(), $options = array()) {
if (empty($this->_enabled)) {
return true;
}
if ($callback instanceof CakeEvent) {
$event = $callback;
if (is_array($event->data)) {
$params =& $event->data;
} else {
$params = array($event->subject());
}
//TODO: Temporary BC check, while we move all the triggers system into the CakeEventManager
foreach (array('breakOn', 'collectReturn', 'modParams') as $opt) {
if (isset($event->{$opt})) {
$options[$opt] = $event->{$opt};
}
}
$callback = array_pop(explode('.', $event->name()));
}
$options = array_merge(
array(
'break' => false,
'breakOn' => false,
'collectReturn' => false,
'modParams' => false
),
$options
);
$collected = array();
$list = array_keys($this->_enabled);
if ($options['modParams'] !== false && !isset($params[$options['modParams']])) {
throw new CakeException(__d('cake_dev', 'Cannot use modParams with indexes that do not exist.'));
}
foreach ($list as $name) {
$result = call_user_func_array(array($this->_loaded[$name], $callback), $params);
if ($options['collectReturn'] === true) {
$collected[] = $result;
}
if (
$options['break'] && ($result === $options['breakOn'] ||
(is_array($options['breakOn']) && in_array($result, $options['breakOn'], true)))
) {
return $result;
} elseif ($options['modParams'] !== false && !in_array($result, array(true, false, null), true)) {
$params[$options['modParams']] = $result;
}
}
if ($options['modParams'] !== false) {
return $params[$options['modParams']];
}
return $options['collectReturn'] ? $collected : $result;
}

/**
* Provide public read access to the loaded objects
*
* @param string $name Name of property to read
* @return mixed
*/
public function __get($name) {
if (isset($this->_loaded[$name])) {
return $this->_loaded[$name];
}
return null;
}

/**
* Provide isset access to _loaded
*
* @param string $name Name of object being checked.
* @return boolean
*/
public function __isset($name) {
return isset($this->_loaded[$name]);
}

/**
* Enables callbacks on an object or array of objects
*
* @param string|array $name CamelCased name of the object(s) to enable (string or array)
* @param boolean Prioritize enabled list after enabling object(s)
* @return void
*/
public function enable($name, $prioritize = true) {
$enabled = false;
foreach ((array)$name as $object) {
if (isset($this->_loaded[$object]) && !isset($this->_enabled[$object])) {
$priority = isset($this->_loaded[$object]->settings['priority']) ? $this->_loaded[$object]->settings['priority'] : $this->defaultPriority;
$this->_enabled[$object] = array($priority);
$enabled = true;
}
}
if ($prioritize && $enabled) {
$this->prioritize();
}
}

/**
* Prioritize list of enabled object
*
* @return array Prioritized list of object
*/
public function prioritize() {
$i = 1;
foreach ($this->_enabled as $name => $priority) {
$priority[1] = $i++;
$this->_enabled[$name] = $priority;
}
asort($this->_enabled);
return $this->_enabled;
}

/**
* Set priority for an object or array of objects
*
* @param string|array $name CamelCased name of the object(s) to enable (string or array)
* If string the second param $priority is used else it should be an associative array
* with keys as object names and values as priorities to set.
* @param int|null Integer priority to set or null for default
* @return void
*/
public function setPriority($name, $priority = null) {
if (is_string($name)) {
$name = array($name => $priority);
}
foreach ($name as $obj => $prio) {
if (isset($this->_loaded[$obj])) {
if (is_null($prio)) {
$prio = $this->defaultPriority;
}
$this->_loaded[$obj]->settings['priority'] = $prio;
if (isset($this->_enabled[$obj])) {
$this->_enabled[$obj] = array($prio);
}
}
}
$this->prioritize();
}

/**
* Disables callbacks on a object or array of objects. Public object methods are still
* callable as normal.
*
* @param string|array $name CamelCased name of the objects(s) to disable (string or array)
* @return void
*/
public function disable($name) {
foreach ((array)$name as $object) {
unset($this->_enabled[$object]);
}
}

/**
* Gets the list of currently-enabled objects, or, the current status of a single objects
*
* @param string $name Optional. The name of the object to check the status of. If omitted,
* returns an array of currently-enabled object
* @return mixed If $name is specified, returns the boolean status of the corresponding object.
* Otherwise, returns an array of all enabled objects.
*/
public function enabled($name = null) {
if (!empty($name)) {
return isset($this->_enabled[$name]);
}
return array_keys($this->_enabled);
}

/**
* Gets the list of attached behaviors, or, whether the given behavior is attached
*
* @param string $name Optional. The name of the behavior to check the status of. If omitted,
* returns an array of currently-attached behaviors
* @return mixed If $name is specified, returns the boolean status of the corresponding behavior.
* Otherwise, returns an array of all attached behaviors.
*/
public function attached($name = null) {
if (!empty($name)) {
return isset($this->_loaded[$name]);
}
return array_keys($this->_loaded);
}

/**
* Name of the object to remove from the collection
*
* @param string $name Name of the object to delete.
* @return void
*/
public function unload($name) {
list($plugin, $name) = pluginSplit($name);
unset($this->_loaded[$name]);
unset($this->_enabled[$name]);
}

/**
* Adds or overwrites an instantiated object to the collection
*
* @param string $name Name of the object
* @param Object $object The object to use
* @return array Loaded objects
*/
public function set($name = null, $object = null) {
if (!empty($name) && !empty($object)) {
list($plugin, $name) = pluginSplit($name);
$this->_loaded[$name] = $object;
}
return $this->_loaded;
}

/**
* Normalizes an object array, creates an array that makes lazy loading
* easier
*
* @param array $objects Array of child objects to normalize.
* @return array Array of normalized objects.
*/
public static function normalizeObjectArray($objects) {
$normal = array();
foreach ($objects as $i => $objectName) {
$options = array();
if (!is_int($i)) {
$options = (array)$objectName;
$objectName = $i;
}
list($plugin, $name) = pluginSplit($objectName);
$normal[$name] = array('class' => $objectName, 'settings' => $options);
}
return $normal;
}
}
Something went wrong with that request. Please try again.