Skip to content

Commit

Permalink
refactoring Model::validates. adding Record::errors
Browse files Browse the repository at this point in the history
  • Loading branch information
gwoo committed Nov 25, 2009
1 parent 42aef2e commit 4fceb8b
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 51 deletions.
40 changes: 2 additions & 38 deletions libraries/lithium/data/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -400,47 +400,11 @@ public function validates($record, $options = array()) {
$params = compact('record', 'options');
return static::_filter(__METHOD__, $params, function($parent, $params) use ($self) {
extract($params);
$rule = 'isNotEmpty';
$__filter = function($field, $params) use ($record, $rule, &$__filter) {
$data = array();
$errors = array();
if (is_array($params)) {
if (!empty($params[0])) {
$multiple = array();
foreach ($params as $param) {
$multiple[] = $__filter($field, $param);
}
return array_values(array_filter($multiple));
} else if (!empty($params['rule'])) {
if (is_string($params['rule'])) {
$rule = $params['rule'];
} else {
$rule = array_shift((array) $params['rule']);
$data = $params['rule'];
}
}
}
$data = array($record->{$field}) + $data;
if (Validator::invokeMethod($rule, $data) !== true) {
if (is_string($params)) {
return $params;
}
if (!empty($params['message'])) {
return $params['message'];
}
return "{$field} is invalid.";
}
return null;
};
$errors = array();
foreach ($self->validates as $field => $params) {
$errors[$field] = $__filter($field, $params);
}
$errors = array_filter($errors);
$errors = Validator::check($record, $self->validates, $options);
if (empty($errors)) {
return true;
}
$record->set(compact('errors'));
$record->errors($errors);
return false;
});
}
Expand Down
24 changes: 24 additions & 0 deletions libraries/lithium/data/model/Record.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,30 @@ public function data($name = null) {
return empty($name) ? $this->_data : $this->__get($name);
}

/**
* Access the errors of the record.
*
* @param mixed $field if array will overwrite `$this->_errors`, if string and value, sets
* @param string $value
* @return string
*/
public function errors($field = null, $value = null) {
if ($field === null) {
return $this->_errors;
}
if (is_array($field)) {
$this->_errors = $field;
return $this->_errors;
}
if ($value === null && isset($this->_errors[$field])) {
return $this->_errors[$field];
}
if ($value !== null) {
return $this->_errors[$field] = $value;
}
return $value;
}

/**
* Magic method that allows calling of model methods on this record instance, i.e.:
* {{{
Expand Down
18 changes: 11 additions & 7 deletions libraries/lithium/tests/cases/data/ModelTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -181,13 +181,14 @@ public function testValidatesFalse() {

$result = $post->validates();
$this->assertTrue($result === false);
$this->assertFalse(empty($post->errors));
$result = $post->errors();
$this->assertTrue(!empty($result));

$expected = array(
'title' => 'please enter a title',
'email' => array('email is empty', 'email is not valid')
);
$result = $post->errors;
$result = $post->errors();
$this->assertEqual($expected, $result);
}

Expand All @@ -196,12 +197,13 @@ public function testValidatesTitle() {

$result = $post->validates();
$this->assertTrue($result === false);
$this->assertFalse(empty($post->errors));
$result = $post->errors();
$this->assertTrue(!empty($result));

$expected = array(
'email' => array('email is empty', 'email is not valid')
);
$result = $post->errors;
$result = $post->errors();
$this->assertEqual($expected, $result);
}

Expand All @@ -210,12 +212,13 @@ public function testValidatesEmailIsNotEmpty() {

$result = $post->validates();
$this->assertTrue($result === false);
$this->assertFalse(empty($post->errors));
$result = $post->errors();
$this->assertTrue(!empty($result));

$expected = array(
'email' => array('email is not valid')
);
$result = $post->errors;
$result = $post->errors();
$this->assertEqual($expected, $result);
}

Expand All @@ -226,7 +229,8 @@ public function testValidatesEmailIsValid() {

$result = $post->validates();
$this->assertTrue($result === true);
$this->assertTrue(empty($post->errors));
$result = $post->errors();
$this->assertTrue(empty($result));
}
/*
* @todo create proper mock objects for the following test
Expand Down
25 changes: 25 additions & 0 deletions libraries/lithium/tests/cases/data/model/RecordTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,31 @@ public function testRecordFormatExport() {
$result = $this->record->to('foo');
$this->assertEqual($this->record, $result);
}

public function testErrorsPropertyAccess() {
$errors = array(
'title' => 'please enter a title',
'email' => array('email is empty', 'email is not valid')
);

$record = new Record();
$result = $record->errors($errors);
$this->assertEqual($errors, $result);

$result = $record->errors();
$this->assertEqual($errors, $result);

$expected = 'please enter a title';
$result = $record->errors('title');
$this->assertEqual($expected, $result);

$expected = array('email is empty', 'email is not valid');
$result = $record->errors('email');
$this->assertEqual($expected, $result);

$result = $record->errors('not_a_field');
$this->assertNull($result);
}
}

?>
95 changes: 94 additions & 1 deletion libraries/lithium/tests/cases/util/ValidatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ public function testEmailValidation() {

/**
* All ICANN TLDs
*/
*/
$this->assertTrue(Validator::isEmail('abc@example.aero'));
$this->assertTrue(Validator::isEmail('abc@example.asia'));
$this->assertTrue(Validator::isEmail('abc@example.biz'));
Expand Down Expand Up @@ -831,6 +831,99 @@ public function testCreditCardValidation() {
$this->assertFalse(Validator::isLuhn(''));
$this->assertFalse(Validator::isLuhn(true));
}

public function testCheckHasErrors() {
$rules = array(
'title' => 'please enter a title',
);
$result = Validator::check(null, $rules);
$this->assertFalse(empty($result));

$expected = array(
'title' => 'please enter a title',
);
$this->assertEqual($expected, $result);
}

public function testCheckPasses() {
$rules = array(
'title' => 'please enter a title',
);
$data = (object) array('title' => 'new title');
$result = Validator::check($data, $rules);
$this->assertTrue(empty($result));
}

public function testCheckMultipleHasErrors() {
$rules = array(
'title' => 'please enter a title',
'email' => array(
array('rule' => 'isNotEmpty', 'message' => 'email is empty'),
array('rule' => 'isEmail', 'message' => 'email is not valid'),
)
);
$result = Validator::check(null, $rules);
$this->assertFalse(empty($result));

$expected = array(
'title' => 'please enter a title',
'email' => array('email is empty', 'email is not valid')
);
$this->assertEqual($expected, $result);
}

public function testCheckMultipleHasFirstError() {
$rules = array(
'title' => 'please enter a title',
'email' => array(
array('rule' => 'isNotEmpty', 'message' => 'email is empty'),
array('rule' => 'isEmail', 'message' => 'email is not valid'),
)
);
$data = (object) array('email' => 'something');
$result = Validator::check($data, $rules);
$this->assertFalse(empty($result));

$expected = array(
'title' => 'please enter a title',
'email' => array('email is not valid')
);
$this->assertEqual($expected, $result);
}

public function testCheckMultipleHasOneError() {
$rules = array(
'title' => 'please enter a title',
'email' => array(
array('rule' => 'isNotEmpty', 'message' => 'email is empty'),
array('rule' => 'isEmail', 'message' => 'email is not valid'),
)
);
$data = (object) array('title' => 'new title', 'email' => 'something');
$result = Validator::check($data, $rules);
$this->assertFalse(empty($result));

$expected = array(
'email' => array('email is not valid')
);
$this->assertEqual($expected, $result);
}

public function testCheckMultiplePasses() {
$rules = array(
'title' => 'please enter a title',
'email' => array(
array('rule' => 'isNotEmpty', 'message' => 'email is empty'),
array('rule' => 'isEmail', 'message' => 'email is not valid'),
)
);
$data = (object) array('title' => 'new title', 'email' => 'something@test.com');
$result = Validator::check($data, $rules);
$this->assertTrue(empty($result));

$expected = array();
$this->assertEqual($expected, $result);
}
}

?>
45 changes: 40 additions & 5 deletions libraries/lithium/util/Validator.php
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,6 @@ public static function __callStatic($method, $args = array()) {
$args += array(1 => 'any', 2 => array());
$rule = preg_replace("/^is([A-Z][A-Za-z0-9]+)$/", '$1', $method);
$rule[0] = strtolower($rule[0]);

return static::rule($rule, $args[0], $args[1], $args[2]);
}

Expand All @@ -273,12 +272,49 @@ public static function __callStatic($method, $args = array()) {
* This method may be used to validate any arbitrary array data against a set of validation
* rules.
*
* @param string $values An array of key/value pairs, where the values are to be checked.
* @param string $rules
* @param object $data An object of with property values to check.
* @param string $rules array of rules to check against object properties
* @return mixed When all validation rules pass
* @todo Bring over validation loop from Model, determine formats/options, implement.
*/
public static function check($values, $rules, $options = array()) {
public static function check($record, $rules, $options = array()) {
$rule = 'isNotEmpty';
$__filter = function($field, $rules) use ($record, $rule, &$__filter) {
$data = isset($record->{$field}) ? array($record->{$field}) : array();
$errors = array();
if (is_array($rules)) {
if (!empty($rules[0])) {
$multiple = array();
foreach ($rules as $rule) {
$multiple[] = $__filter($field, $rule);
}
return array_values(array_filter($multiple));
} else if (!empty($rules['rule'])) {
if (is_string($rules['rule'])) {
$rule = $rules['rule'];
} else {
$rule = array_shift((array) $rules['rule']);
$data += $rules['rule'];
}
}
}

if (Validator::invokeMethod($rule, $data) !== true) {
if (is_string($rules)) {
return $rules;
}
if (!empty($rules['message'])) {
return $rules['message'];
}
return "{$field} is invalid.";
}
return null;
};
$errors = array();
foreach ($rules as $field => $rules) {
$errors[$field] = $__filter($field, $rules);
}
return array_filter($errors);
}

/**
Expand Down Expand Up @@ -406,7 +442,6 @@ public static function rule($rule, $value, $format = 'any', $options = array())
$formats = (array)$format;
$all = true;
}

if (static::_checkFormats($ruleCheck, $formats, $value, $all, $options)) {
return (bool)static::_filters('after', $rule, compact('value', 'format', 'options'));
}
Expand Down

0 comments on commit 4fceb8b

Please sign in to comment.