Allow nested rules (not and optional)

This commit is contained in:
Igor Scheller 2019-07-16 01:39:54 +02:00
parent 6743106d9a
commit b25924e868
2 changed files with 88 additions and 3 deletions

View File

@ -22,6 +22,9 @@ class Validator
'required' => 'NotEmpty', 'required' => 'NotEmpty',
]; ];
/** @var array */
protected $nestedRules = ['optional', 'not'];
/** /**
* @param array $data * @param array $data
* @param array $rules * @param array $rules
@ -37,20 +40,38 @@ class Validator
$v->with('\\Engelsystem\\Http\\Validation\\Rules', true); $v->with('\\Engelsystem\\Http\\Validation\\Rules', true);
$value = isset($data[$key]) ? $data[$key] : null; $value = isset($data[$key]) ? $data[$key] : null;
$values = explode('|', $values);
foreach (explode('|', $values) as $parameters) { $packing = [];
foreach ($this->nestedRules as $rule) {
if (in_array($rule, $values)) {
$packing[] = $rule;
}
}
$values = array_diff($values, $this->nestedRules);
foreach ($values as $parameters) {
$parameters = explode(':', $parameters); $parameters = explode(':', $parameters);
$rule = array_shift($parameters); $rule = array_shift($parameters);
$rule = Str::camel($rule); $rule = Str::camel($rule);
$rule = $this->map($rule); $rule = $this->map($rule);
// To allow rules nesting
$w = $v;
try { try {
call_user_func_array([$v, $rule], $parameters); foreach (array_reverse(array_merge($packing, [$rule])) as $rule) {
if (!in_array($rule, $this->nestedRules)) {
call_user_func_array([$w, $rule], $parameters);
continue;
}
$w = call_user_func_array([new RespectValidator(), $rule], [$w]);
}
} catch (ComponentException $e) { } catch (ComponentException $e) {
throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
} }
if ($v->validate($value)) { if ($w->validate($value)) {
$this->data[$key] = $value; $this->data[$key] = $value;
} else { } else {
$this->errors[$key][] = implode('.', ['validation', $key, $this->mapBack($rule)]); $this->errors[$key][] = implode('.', ['validation', $key, $this->mapBack($rule)]);

View File

@ -16,6 +16,7 @@ class ValidatorTest extends TestCase
public function testValidate() public function testValidate()
{ {
$val = new Validator(); $val = new Validator();
$this->assertTrue($val->validate( $this->assertTrue($val->validate(
['foo' => 'bar', 'lorem' => 'on', 'dolor' => 'bla'], ['foo' => 'bar', 'lorem' => 'on', 'dolor' => 'bla'],
['lorem' => 'accepted'] ['lorem' => 'accepted']
@ -32,12 +33,39 @@ class ValidatorTest extends TestCase
); );
} }
/**
* @covers \Engelsystem\Http\Validation\Validator::validate
*/
public function testValidateChaining()
{
$val = new Validator();
$this->assertTrue($val->validate(
['lorem' => 10],
['lorem' => 'required|min:3|max:10']
));
$this->assertTrue($val->validate(
['lorem' => 3],
['lorem' => 'required|min:3|max:10']
));
$this->assertFalse($val->validate(
['lorem' => 2],
['lorem' => 'required|min:3|max:10']
));
$this->assertFalse($val->validate(
['lorem' => 42],
['lorem' => 'required|min:3|max:10']
));
}
/** /**
* @covers \Engelsystem\Http\Validation\Validator::validate * @covers \Engelsystem\Http\Validation\Validator::validate
*/ */
public function testValidateNotImplemented() public function testValidateNotImplemented()
{ {
$val = new Validator(); $val = new Validator();
$this->expectException(InvalidArgumentException::class); $this->expectException(InvalidArgumentException::class);
$val->validate( $val->validate(
@ -53,6 +81,7 @@ class ValidatorTest extends TestCase
public function testValidateMapping() public function testValidateMapping()
{ {
$val = new Validator(); $val = new Validator();
$this->assertTrue($val->validate( $this->assertTrue($val->validate(
['foo' => 'bar'], ['foo' => 'bar'],
['foo' => 'required'] ['foo' => 'required']
@ -75,4 +104,39 @@ class ValidatorTest extends TestCase
$val->getErrors() $val->getErrors()
); );
} }
/**
* @covers \Engelsystem\Http\Validation\Validator::validate
*/
public function testValidateNesting()
{
$val = new Validator();
$this->assertTrue($val->validate(
[],
['foo' => 'not|required']
));
$this->assertTrue($val->validate(
['foo' => 'foo'],
['foo' => 'not|int']
));
$this->assertFalse($val->validate(
['foo' => 1],
['foo' => 'not|int']
));
$this->assertTrue($val->validate(
[],
['foo' => 'optional|int']
));
$this->assertTrue($val->validate(
['foo' => '33'],
['foo' => 'optional|int']
));
$this->assertFalse($val->validate(
['foo' => 'T'],
['foo' => 'optional|int']
));
}
} }