Refactoring behavior method dispatch handling to work on PHP4, fixes #4296, refactoring schema test

git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@6532 3807eeeb-6ff5-0310-8944-8be069107fe0
This commit is contained in:
nate 2008-03-09 06:24:40 +00:00
parent 199a098cf1
commit e87d4e80dd
5 changed files with 71 additions and 22 deletions

View file

@ -145,6 +145,35 @@ class ModelBehavior extends Object {
* @access public
*/
function onError(&$model, $error) { }
/**
* Overrides Object::dispatchMethod to account for PHP4's broken reference support
*
* @see Object::dispatchMethod
* @access public
*/
function dispatchMethod(&$model, $method, $params = array()) {
if (empty($params)) {
return $this->{$method}(&$model);
}
$params = array_values($params);
switch (count($params)) {
case 1:
return $this->{$method}($model, $params[0]);
case 2:
return $this->{$method}($model, $params[0], $params[1]);
case 3:
return $this->{$method}($model, $params[0], $params[1], $params[2]);
case 4:
return $this->{$method}($model, $params[0], $params[1], $params[2], $params[3]);
case 5:
return $this->{$method}($model, $params[0], $params[1], $params[2], $params[3], $params[4]);
default:
array_unshift($params, &$model);
return call_user_func_array(array(&$this, $method), $params);
break;
}
}
/**
* If $model's whitelist property is non-empty, $field will be added to it.
* Note: this method should *only* be used in beforeValidate or beforeSave to ensure
@ -216,7 +245,7 @@ class BehaviorCollection extends Object {
*
* @access public
*/
function __construct(&$model, $behaviors = array()) {
function init(&$model, $behaviors = array()) {
$this->model =& $model;
if (!empty($behaviors)) {
@ -358,7 +387,7 @@ class BehaviorCollection extends Object {
* @return array All methods for all behaviors attached to this object
* @access public
*/
function dispatchMethod($method, $params = array(), $strict = false) {
function dispatchMethod(&$model, $method, $params = array(), $strict = false) {
$methods = array_map('strtolower', array_keys($this->__methods));
$found = (in_array(strtolower($method), $methods));
$call = null;
@ -381,22 +410,22 @@ class BehaviorCollection extends Object {
}
}
}
if (!empty($call)) {
return $this->{$call[1]}->dispatchMethod($call[0], array_merge(array(&$this->model), $params));
return $this->{$call[1]}->dispatchMethod($model, $call[0], $params);
}
return array('unhandled');
}
/**
* Dispatches a behavior callback on all attached behavior objects
*
* @param model $model
* @param string $callback
* @param array $params
* @param array $options
* @return mixed
* @access public
*/
function trigger($callback, $params = array(), $options = array()) {
function trigger(&$model, $callback, $params = array(), $options = array()) {
if (empty($this->_attached)) {
return true;
}
@ -409,7 +438,7 @@ class BehaviorCollection extends Object {
if (in_array($name, $this->_disabled)) {
continue;
}
$result = $this->{$name}->dispatchMethod($callback, array_merge(array(&$this->model), (array)$params));
$result = $this->{$name}->dispatchMethod(&$model, $callback, $params);
if ($options['break'] && ($result === $options['breakOn'] || is_array($options['breakOn'] && in_array($result, $options['breakOn'], true)))) {
return $result;

View file

@ -388,7 +388,8 @@ class Model extends Overloadable {
}
}
}
$this->Behaviors = new BehaviorCollection($this, $this->actsAs);
$this->Behaviors = new BehaviorCollection();
$this->Behaviors->init($this, $this->actsAs);
}
/**
* Handles custom method calls, like findBy<field> for DB models,
@ -400,7 +401,7 @@ class Model extends Overloadable {
* @access protected
*/
function call__($method, $params) {
$result = $this->Behaviors->dispatchMethod($method, $params);
$result = $this->Behaviors->dispatchMethod($this, $method, $params);
if ($result !== array('unhandled')) {
return $result;
@ -1094,7 +1095,7 @@ class Model extends Overloadable {
}
if ($options['callbacks'] === true || $options['callbacks'] == 'before') {
if (!$this->Behaviors->trigger('beforeSave', array(), array('break' => true, 'breakOn' => false)) || !$this->beforeSave()) {
if (!$this->Behaviors->trigger($this, 'beforeSave', array(), array('break' => true, 'breakOn' => false)) || !$this->beforeSave()) {
$this->whitelist = $_whitelist;
return false;
}
@ -1171,7 +1172,7 @@ class Model extends Overloadable {
$success = $this->data;
}
if ($options['callbacks'] === true || $options['callbacks'] == 'after') {
$this->Behaviors->trigger('afterSave', array($created));
$this->Behaviors->trigger($this, 'afterSave', array($created));
$this->afterSave($created);
}
if (!empty($this->data)) {
@ -1462,7 +1463,7 @@ class Model extends Overloadable {
if ($this->exists() && $this->beforeDelete($cascade)) {
$db =& ConnectionManager::getDataSource($this->useDbConfig);
if (!$this->Behaviors->trigger('beforeDelete', array($cascade), array('break' => true, 'breakOn' => false))) {
if (!$this->Behaviors->trigger($this, 'beforeDelete', array($cascade), array('break' => true, 'breakOn' => false))) {
return false;
}
$this->_deleteDependent($id, $cascade);
@ -1477,7 +1478,7 @@ class Model extends Overloadable {
if (!empty($this->belongsTo)) {
$this->updateCounterCache($keys[$this->alias]);
}
$this->Behaviors->trigger('afterDelete');
$this->Behaviors->trigger($this, 'afterDelete');
$this->afterDelete();
$this->_clearCache();
$this->id = false;
@ -1718,7 +1719,7 @@ class Model extends Overloadable {
}
$query['order'] = array($query['order']);
$return = $this->Behaviors->trigger('beforeFind', array($query), array('break' => true, 'breakOn' => false, 'modParams' => true));
$return = $this->Behaviors->trigger($this, 'beforeFind', array($query), array('break' => true, 'breakOn' => false, 'modParams' => true));
$query = ife(is_array($return), $return, $query);
if ($return === false) {
@ -1855,7 +1856,7 @@ class Model extends Overloadable {
* @access private
*/
function __filterResults($results, $primary = true) {
$return = $this->Behaviors->trigger('afterFind', array($results, $primary), array('modParams' => true));
$return = $this->Behaviors->trigger($this, 'afterFind', array($results, $primary), array('modParams' => true));
if ($return !== true) {
$results = $return;
}
@ -2062,7 +2063,7 @@ class Model extends Overloadable {
* @access public
*/
function invalidFields() {
if (!$this->Behaviors->trigger('beforeValidate', array(), array('break' => true, 'breakOn' => false)) || $this->beforeValidate() === false) {
if (!$this->Behaviors->trigger($this, 'beforeValidate', array(), array('break' => true, 'breakOn' => false)) || $this->beforeValidate() === false) {
return $this->validationErrors;
}
@ -2126,7 +2127,7 @@ class Model extends Overloadable {
} elseif (in_array($rule, $behaviorMethods) || in_array(strtolower($rule), $behaviorMethods)) {
$ruleParams[] = array_diff_key($validator, $default);
$ruleParams[0] = array($fieldName => $ruleParams[0]);
$valid = $this->Behaviors->dispatchMethod($rule, $ruleParams);
$valid = $this->Behaviors->dispatchMethod($this, $rule, $ruleParams);
} elseif (method_exists($Validation, $rule)) {
$valid = $Validation->dispatchMethod($rule, $ruleParams);
} elseif (!is_array($validator['rule'])) {

View file

@ -87,6 +87,14 @@ class TestBehavior extends ModelBehavior {
}
}
function testData(&$model) {
if (!isset($model->data['Apple']['field'])) {
return false;
}
$model->data['Apple']['field_2'] = true;
return true;
}
function validateField(&$model, $field) {
return current($field) === 'Orange';
}
@ -202,7 +210,8 @@ class BehaviorTest extends CakeTestCase {
}
function testBehaviorValidateCallback() {
$this->model = new Apple();
$this->model =& new Apple();
$this->model->Behaviors->attach('Test');
$this->assertIdentical($this->model->validates(), true);
@ -230,9 +239,9 @@ class BehaviorTest extends CakeTestCase {
$expected = 'working';
$this->assertEqual($this->model->testMethod(), $expected);
$this->assertEqual($this->model->Behaviors->dispatchMethod('testMethod'), $expected);
$this->assertEqual($this->model->Behaviors->dispatchMethod($this->model, 'testMethod'), $expected);
$result = $this->model->Behaviors->dispatchMethod('wtf');
$result = $this->model->Behaviors->dispatchMethod($this->model, 'wtf');
$this->assertEqual($result, array('unhandled'));
$result = $this->model->{'look for the remote'}('in the couch');
@ -240,6 +249,15 @@ class BehaviorTest extends CakeTestCase {
$this->assertEqual($result, $expected);
}
function testBehaviorMethodDispatchingWithData() {
$this->model = new Apple();
$this->model->Behaviors->attach('Test');
$this->model->set('field', 'value');
$this->assertTrue($this->model->testData());
$this->assertTrue($this->model->data['Apple']['field_2']);
}
function tearDown() {
unset($this->model);
ClassRegistry::flush();

View file

@ -3237,7 +3237,7 @@ class ModelTest extends CakeTestCase {
$this->assertEqual($this->model->Comment->find('all'), $expected);
foreach (array('User', 'Comment') as $class) {
$fixture =& $this->_fixtures[$this->_fixtureClassMap[$class]]->drop($db2);
$this->_fixtures[$this->_fixtureClassMap[$class]]->drop($db2);
}
}

View file

@ -25,7 +25,8 @@
* @lastmodified $Date$
* @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License
*/
uses('model' . DS .'schema');
App::import('Core', 'Schema');
/**
* Test for Schema database management
*
@ -170,7 +171,7 @@ class CakeSchemaTest extends CakeTestCase {
function testSchemaName() {
$Schema = new CakeSchema();
$this->assertEqual($Schema->name, 'App');
$this->assertEqual(strtolower($Schema->name), strtolower(APP_DIR));
Configure::write('App.dir', 'Some.name.with.dots');
$Schema = new CakeSchema();