diff --git a/cake/libs/model/model_behavior.php b/cake/libs/model/model_behavior.php index befd383a983..d584dea37d2 100644 --- a/cake/libs/model/model_behavior.php +++ b/cake/libs/model/model_behavior.php @@ -239,6 +239,7 @@ class BehaviorCollection extends ObjectCollection { /** * Attaches a model object and loads a list of behaviors * + * @todo Make this method a constructor instead.. * @access public * @return void */ @@ -253,13 +254,23 @@ function init($modelName, $behaviors = array()) { } /** - * Attaches a behavior to a model + * Backwards compatible alias for load() + * + * @return void + * @deprecated Replaced with load() + */ + public function attach($behavior, $config = array()) { + return $this->load($behavior, $config); + } + +/** + * Loads a behavior into the collection. * * @param string $behavior CamelCased name of the behavior to load * @param array $config Behavior configuration parameters * @return boolean True on success, false on failure */ - public function attach($behavior, $config = array()) { + public function load($behavior, $config = array()) { list($plugin, $name) = pluginSplit($behavior); $class = $name . 'Behavior'; @@ -343,7 +354,7 @@ public function attach($behavior, $config = array()) { * @param string $name CamelCased name of the behavior to unload * @return void */ - public function detach($name) { + public function unload($name) { list($plugin, $name) = pluginSplit($name); if (isset($this->{$name})) { $this->{$name}->cleanup(ClassRegistry::getObject($this->modelName)); @@ -357,6 +368,17 @@ public function detach($name) { $this->_attached = array_values(array_diff($this->_attached, (array)$name)); } +/** + * Backwards compatible alias for unload() + * + * @param string $name Name of behavior + * @return void + * @deprecated Use unload instead. + */ + public function detach($name) { + return $this->unload($name); + } + /** * Dispatches a behavior method * diff --git a/cake/libs/object_collection.php b/cake/libs/object_collection.php index 8fe93d16858..21bfa690865 100644 --- a/cake/libs/object_collection.php +++ b/cake/libs/object_collection.php @@ -35,6 +35,66 @@ abstract class ObjectCollection { */ protected $_disabled = array(); +/** + * Loads a new object onto the collection. Can throw a variety of exceptions + * + * @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()); + +/** + * Unloads/deletes an object from the collection. + * + * @param string $name Name of the object to delete. + * @return void + */ + abstract public function unload($name); + +/** + * 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. + * + * + * @param string $callback Method to fire on all the objects. Its assumed all the objects implement + * the method you are calling. + * @param array $params Array of parameters for the triggered callback. + * @param array $options Array of options. + * @return mixed Either true or $params[0] if $options['modParams'] is true. + */ + public function trigger($callback, $params = array(), $options = array()) { + if (empty($this->_attached)) { + return true; + } + $options = array_merge( + array('break' => false, 'breakOn' => array(false), 'modParams' => false), + $options + ); + $count = count($this->_attached); + for ($i = 0; $i < $count; $i++) { + $name = $this->_attached[$i]; + if (in_array($name, $this->_disabled)) { + continue; + } + $result = call_user_func_array(array($this->{$name}, $callback), $params); + + if ( + $options['break'] && ($result === $options['breakOn'] || + (is_array($options['breakOn']) && in_array($result, $options['breakOn'], true))) + ) { + return $result; + } elseif ($options['modParams'] && is_array($result)) { + $params[0] = $result; + } + } + if ($options['modParams'] && isset($params[0])) { + return $params[0]; + } + return true; + } + /** * Enables callbacks on a behavior or array of behaviors * diff --git a/cake/libs/view/helper_collection.php b/cake/libs/view/helper_collection.php index 59663eb4447..1659f010aee 100644 --- a/cake/libs/view/helper_collection.php +++ b/cake/libs/view/helper_collection.php @@ -35,6 +35,7 @@ class HelperCollection extends ObjectCollection { public function __construct(View $view) { $this->_View = $view; } + /** * Loads/constructs a helper. Will return the instance in the registry if it already exists. * @@ -65,6 +66,17 @@ public function load($helper, $settings = array()) { return $this->{$name}; } +/** + * Name of the helper to remove from the collection + * + * @param string $name Name of helper to delete. + * @return void + */ + public function unload($name) { + list($plugin, $name) = pluginSplit($name); + unset($this->{$name}); + $this->_attached = array_values(array_diff($this->_attached, (array)$name)); + } } /** diff --git a/cake/tests/cases/libs/view/helper_collection.test.php b/cake/tests/cases/libs/view/helper_collection.test.php index 04ced0d3494..c7fd72835f8 100644 --- a/cake/tests/cases/libs/view/helper_collection.test.php +++ b/cake/tests/cases/libs/view/helper_collection.test.php @@ -53,7 +53,7 @@ function testLoad() { $result = $this->Helpers->attached(); $this->assertEquals(array('Html'), $result, 'attached() results are wrong.'); - + $this->assertTrue($this->Helpers->enabled('Html')); } @@ -82,4 +82,65 @@ function testLoadPluginHelper() { App::build(); } + +/** + * test unload() + * + * @return void + */ + function testUnload() { + $this->Helpers->load('Form'); + $this->Helpers->load('Html'); + + $result = $this->Helpers->attached(); + $this->assertEquals(array('Form', 'Html'), $result, 'loaded helpers is wrong'); + + $this->Helpers->unload('Html'); + $this->assertFalse(isset($this->Helpers->Html)); + $this->assertTrue(isset($this->Helpers->Form)); + + $result = $this->Helpers->attached(); + $this->assertEquals(array('Form'), $result, 'loaded helpers is wrong'); + } + +/** + * test triggering callbacks. + * + * @return void + */ + function testTrigger() { + $this->Helpers->load('Form'); + $this->Helpers->load('Html'); + + $this->Helpers->Html = $this->getMock('HtmlHelper'); + $this->Helpers->Form = $this->getMock('FormHelper'); + + $this->Helpers->Html->expects($this->once())->method('beforeRender') + ->with('one', 'two'); + $this->Helpers->Form->expects($this->once())->method('beforeRender') + ->with('one', 'two'); + + $this->Helpers->trigger('beforeRender', array('one', 'two')); + } + +/** + * test trigger and disabled helpers. + * + * @return void + */ + function testTriggerWithDisabledHelpers() { + $this->Helpers->load('Form'); + $this->Helpers->load('Html'); + + $this->Helpers->Html = $this->getMock('HtmlHelper'); + $this->Helpers->Form = $this->getMock('FormHelper'); + + $this->Helpers->Html->expects($this->once())->method('beforeRender') + ->with('one', 'two'); + $this->Helpers->Form->expects($this->never())->method('beforeRender'); + + $this->Helpers->disable('Form'); + + $this->Helpers->trigger('beforeRender', array('one', 'two')); + } } \ No newline at end of file