Adding ability for BehaviorCollection::hasMethod() to return the callback.

Re-factored BehaviorCollection::dispatchMethod to be simpler and faster.
Changing now BehaviorCollection stores callbacks so they look like normal php callback arrays.
This commit is contained in:
mark_story 2010-12-26 17:09:20 -05:00
parent 769da1a7c8
commit 0c4b665ad0
2 changed files with 54 additions and 36 deletions

View file

@ -128,7 +128,7 @@ class BehaviorCollection extends ObjectCollection {
$this->_loaded[$name]->setup(ClassRegistry::getObject($this->modelName), $config);
foreach ($this->_loaded[$name]->mapMethods as $method => $alias) {
$this->__mappedMethods[$method] = array($alias, $name);
$this->__mappedMethods[$method] = array($name, $alias);
}
$methods = get_class_methods($this->_loaded[$name]);
$parentMethods = array_flip(get_class_methods('ModelBehavior'));
@ -144,7 +144,7 @@ class BehaviorCollection extends ObjectCollection {
!in_array($m, $callbacks)
);
if ($methodAllowed) {
$this->__methods[$m] = array($m, $name);
$this->__methods[$m] = array($name, $m);
}
}
}
@ -171,7 +171,7 @@ class BehaviorCollection extends ObjectCollection {
unset($this->_loaded[$name]);
}
foreach ($this->__methods as $m => $callback) {
if (is_array($callback) && $callback[1] == $name) {
if (is_array($callback) && $callback[0] == $name) {
unset($this->__methods[$m]);
}
}
@ -194,42 +194,29 @@ class BehaviorCollection extends ObjectCollection {
*
* @return array All methods for all behaviors attached to this object
*/
public function dispatchMethod(&$model, $method, $params = array(), $strict = false) {
$methods = array_keys($this->__methods);
$check = array_flip($methods);
$found = isset($check[$method]);
$call = null;
if ($strict && !$found) {
public function dispatchMethod($model, $method, $params = array(), $strict = false) {
$method = $this->hasMethod($method, true);
if ($strict && empty($method)) {
trigger_error(__("BehaviorCollection::dispatchMethod() - Method %s not found in any attached behavior", $method), E_USER_WARNING);
return null;
} elseif ($found) {
$methods = array_combine($methods, array_values($this->__methods));
$call = $methods[$method];
} else {
$count = count($this->__mappedMethods);
$mapped = array_keys($this->__mappedMethods);
for ($i = 0; $i < $count; $i++) {
if (preg_match($mapped[$i] . 'i', $method)) {
$call = $this->__mappedMethods[$mapped[$i]];
array_unshift($params, $method);
break;
}
}
}
if (!empty($call)) {
return call_user_func_array(
array(&$this->_loaded[$call[1]], $call[0]),
array_merge(array(&$model), $params)
);
if (empty($method)) {
return array('unhandled');
}
return array('unhandled');
if (count($method) === 3) {
array_unshift($params, $method[2]);
unset($method[2]);
}
return call_user_func_array(
array($this->_loaded[$method[0]], $method[1]),
array_merge(array(&$model), $params)
);
}
/**
* Gets the method list for attached behaviors, i.e. all public, non-callback methods
* Gets the method list for attached behaviors, i.e. all public, non-callback methods.
* This does not include mappedMethods.
*
* @return array All public methods for all behaviors attached to this collection
*/
@ -242,14 +229,20 @@ class BehaviorCollection extends ObjectCollection {
* also check mappedMethods.
*
* @param string $method The method to find.
* @return boolean Method was found.
* @param boolean $callback Return the callback for the method.
* @return mixed If $callback is false, a boolean will be returnned, if its true, an array
* containing callback information will be returnned. For mapped methods the array will have 3 elements.
*/
public function hasMethod($method) {
public function hasMethod($method, $callback = false) {
if (isset($this->__methods[$method])) {
return true;
return $callback ? $this->__methods[$method] : true;
}
foreach ($this->__mappedMethods as $pattern => $target) {
if (preg_match($pattern . 'i', $method)) {
if ($callback) {
$target[] = $method;
return $target;
}
return true;
}
}

View file

@ -1151,8 +1151,33 @@ class BehaviorCollectionTest extends CakeTestCase {
$Sample = new Sample();
$Collection = new BehaviorCollection();
$Collection->init('Sample', array('Test', 'Test2'));
$this->assertTrue($Collection->hasMethod('look for the remote in the couch'));
$this->assertTrue($Collection->hasMethod('mappingRobotOnTheRoof'));
}
/**
* test hasMethod returrning a 'callback'
*
* @return void
*/
function testHasMethodAsCallback() {
$Sample = new Sample();
$Collection = new BehaviorCollection();
$Collection->init('Sample', array('Test', 'Test2'));
$result = $Collection->hasMethod('testMethod', true);
$expected = array('Test', 'testMethod');
$this->assertEquals($expected, $result);
$result = $Collection->hasMethod('resolveMethod', true);
$expected = array('Test2', 'resolveMethod');
$this->assertEquals($expected, $result);
$result = $Collection->hasMethod('mappingRobotOnTheRoof', true);
$expected = array('Test2', 'mapped', 'mappingRobotOnTheRoof');
$this->assertEquals($expected, $result);
}
}