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 * @access public
*/ */
function onError(&$model, $error) { } 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. * 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 * Note: this method should *only* be used in beforeValidate or beforeSave to ensure
@ -216,7 +245,7 @@ class BehaviorCollection extends Object {
* *
* @access public * @access public
*/ */
function __construct(&$model, $behaviors = array()) { function init(&$model, $behaviors = array()) {
$this->model =& $model; $this->model =& $model;
if (!empty($behaviors)) { if (!empty($behaviors)) {
@ -358,7 +387,7 @@ class BehaviorCollection extends Object {
* @return array All methods for all behaviors attached to this object * @return array All methods for all behaviors attached to this object
* @access public * @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)); $methods = array_map('strtolower', array_keys($this->__methods));
$found = (in_array(strtolower($method), $methods)); $found = (in_array(strtolower($method), $methods));
$call = null; $call = null;
@ -381,22 +410,22 @@ class BehaviorCollection extends Object {
} }
} }
} }
if (!empty($call)) { 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'); return array('unhandled');
} }
/** /**
* Dispatches a behavior callback on all attached behavior objects * Dispatches a behavior callback on all attached behavior objects
* *
* @param model $model
* @param string $callback * @param string $callback
* @param array $params * @param array $params
* @param array $options * @param array $options
* @return mixed * @return mixed
* @access public * @access public
*/ */
function trigger($callback, $params = array(), $options = array()) { function trigger(&$model, $callback, $params = array(), $options = array()) {
if (empty($this->_attached)) { if (empty($this->_attached)) {
return true; return true;
} }
@ -409,7 +438,7 @@ class BehaviorCollection extends Object {
if (in_array($name, $this->_disabled)) { if (in_array($name, $this->_disabled)) {
continue; 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)))) { if ($options['break'] && ($result === $options['breakOn'] || is_array($options['breakOn'] && in_array($result, $options['breakOn'], true)))) {
return $result; 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, * Handles custom method calls, like findBy<field> for DB models,
@ -400,7 +401,7 @@ class Model extends Overloadable {
* @access protected * @access protected
*/ */
function call__($method, $params) { function call__($method, $params) {
$result = $this->Behaviors->dispatchMethod($method, $params); $result = $this->Behaviors->dispatchMethod($this, $method, $params);
if ($result !== array('unhandled')) { if ($result !== array('unhandled')) {
return $result; return $result;
@ -1094,7 +1095,7 @@ class Model extends Overloadable {
} }
if ($options['callbacks'] === true || $options['callbacks'] == 'before') { 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; $this->whitelist = $_whitelist;
return false; return false;
} }
@ -1171,7 +1172,7 @@ class Model extends Overloadable {
$success = $this->data; $success = $this->data;
} }
if ($options['callbacks'] === true || $options['callbacks'] == 'after') { if ($options['callbacks'] === true || $options['callbacks'] == 'after') {
$this->Behaviors->trigger('afterSave', array($created)); $this->Behaviors->trigger($this, 'afterSave', array($created));
$this->afterSave($created); $this->afterSave($created);
} }
if (!empty($this->data)) { if (!empty($this->data)) {
@ -1462,7 +1463,7 @@ class Model extends Overloadable {
if ($this->exists() && $this->beforeDelete($cascade)) { if ($this->exists() && $this->beforeDelete($cascade)) {
$db =& ConnectionManager::getDataSource($this->useDbConfig); $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; return false;
} }
$this->_deleteDependent($id, $cascade); $this->_deleteDependent($id, $cascade);
@ -1477,7 +1478,7 @@ class Model extends Overloadable {
if (!empty($this->belongsTo)) { if (!empty($this->belongsTo)) {
$this->updateCounterCache($keys[$this->alias]); $this->updateCounterCache($keys[$this->alias]);
} }
$this->Behaviors->trigger('afterDelete'); $this->Behaviors->trigger($this, 'afterDelete');
$this->afterDelete(); $this->afterDelete();
$this->_clearCache(); $this->_clearCache();
$this->id = false; $this->id = false;
@ -1718,7 +1719,7 @@ class Model extends Overloadable {
} }
$query['order'] = array($query['order']); $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); $query = ife(is_array($return), $return, $query);
if ($return === false) { if ($return === false) {
@ -1855,7 +1856,7 @@ class Model extends Overloadable {
* @access private * @access private
*/ */
function __filterResults($results, $primary = true) { 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) { if ($return !== true) {
$results = $return; $results = $return;
} }
@ -2062,7 +2063,7 @@ class Model extends Overloadable {
* @access public * @access public
*/ */
function invalidFields() { 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; return $this->validationErrors;
} }
@ -2126,7 +2127,7 @@ class Model extends Overloadable {
} elseif (in_array($rule, $behaviorMethods) || in_array(strtolower($rule), $behaviorMethods)) { } elseif (in_array($rule, $behaviorMethods) || in_array(strtolower($rule), $behaviorMethods)) {
$ruleParams[] = array_diff_key($validator, $default); $ruleParams[] = array_diff_key($validator, $default);
$ruleParams[0] = array($fieldName => $ruleParams[0]); $ruleParams[0] = array($fieldName => $ruleParams[0]);
$valid = $this->Behaviors->dispatchMethod($rule, $ruleParams); $valid = $this->Behaviors->dispatchMethod($this, $rule, $ruleParams);
} elseif (method_exists($Validation, $rule)) { } elseif (method_exists($Validation, $rule)) {
$valid = $Validation->dispatchMethod($rule, $ruleParams); $valid = $Validation->dispatchMethod($rule, $ruleParams);
} elseif (!is_array($validator['rule'])) { } 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) { function validateField(&$model, $field) {
return current($field) === 'Orange'; return current($field) === 'Orange';
} }
@ -202,7 +210,8 @@ class BehaviorTest extends CakeTestCase {
} }
function testBehaviorValidateCallback() { function testBehaviorValidateCallback() {
$this->model = new Apple(); $this->model =& new Apple();
$this->model->Behaviors->attach('Test'); $this->model->Behaviors->attach('Test');
$this->assertIdentical($this->model->validates(), true); $this->assertIdentical($this->model->validates(), true);
@ -230,9 +239,9 @@ class BehaviorTest extends CakeTestCase {
$expected = 'working'; $expected = 'working';
$this->assertEqual($this->model->testMethod(), $expected); $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')); $this->assertEqual($result, array('unhandled'));
$result = $this->model->{'look for the remote'}('in the couch'); $result = $this->model->{'look for the remote'}('in the couch');
@ -240,6 +249,15 @@ class BehaviorTest extends CakeTestCase {
$this->assertEqual($result, $expected); $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() { function tearDown() {
unset($this->model); unset($this->model);
ClassRegistry::flush(); ClassRegistry::flush();

View file

@ -3237,7 +3237,7 @@ class ModelTest extends CakeTestCase {
$this->assertEqual($this->model->Comment->find('all'), $expected); $this->assertEqual($this->model->Comment->find('all'), $expected);
foreach (array('User', 'Comment') as $class) { 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$ * @lastmodified $Date$
* @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License * @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 * Test for Schema database management
* *
@ -170,7 +171,7 @@ class CakeSchemaTest extends CakeTestCase {
function testSchemaName() { function testSchemaName() {
$Schema = new CakeSchema(); $Schema = new CakeSchema();
$this->assertEqual($Schema->name, 'App'); $this->assertEqual(strtolower($Schema->name), strtolower(APP_DIR));
Configure::write('App.dir', 'Some.name.with.dots'); Configure::write('App.dir', 'Some.name.with.dots');
$Schema = new CakeSchema(); $Schema = new CakeSchema();