mirror of
https://github.com/Respect/Validation.git
synced 2024-06-08 08:42:15 +02:00
Fluent interface for Valitation\Validator, draft string validator, better tests, composite validation improvements
This commit is contained in:
parent
5850afdad5
commit
d25f7220dc
|
@ -18,7 +18,9 @@ abstract class AbstractCompositeValidator extends AbstractNode
|
|||
|
||||
public function addValidator($validator, $arguments=array())
|
||||
{
|
||||
$this->appendValidator(Validator::buildValidator($validator, $arguments));
|
||||
$this->appendValidator(
|
||||
Validator::buildValidator($validator, $arguments)
|
||||
);
|
||||
}
|
||||
|
||||
public function hasValidator($validator)
|
||||
|
@ -72,7 +74,7 @@ abstract class AbstractCompositeValidator extends AbstractNode
|
|||
$exceptions = array();
|
||||
foreach ($validators as $v)
|
||||
try {
|
||||
$v->validate($input);
|
||||
$v->assert($input);
|
||||
} catch (InvalidException $e) {
|
||||
$exceptions[] = $e;
|
||||
}
|
||||
|
|
|
@ -8,18 +8,18 @@ use Respect\Validation\InvalidException;
|
|||
class All extends AbstractCompositeValidator
|
||||
{
|
||||
|
||||
public function isValid($input)
|
||||
public function is($input)
|
||||
{
|
||||
$validators = $this->getValidators();
|
||||
return count($validators) === count(array_filter(
|
||||
$validators,
|
||||
function($v) use($input) {
|
||||
return $v->isValid($input);
|
||||
return $v->is($input);
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
public function validate($input)
|
||||
public function assert($input)
|
||||
{
|
||||
$exceptions = $this->iterateValidation($input);
|
||||
if (!empty($exceptions))
|
||||
|
@ -27,5 +27,4 @@ class All extends AbstractCompositeValidator
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -8,7 +8,7 @@ use Respect\Validation\InvalidException;
|
|||
class One extends AbstractCompositeValidator
|
||||
{
|
||||
|
||||
public function validate($input)
|
||||
public function assert($input)
|
||||
{
|
||||
$validators = $this->getValidators();
|
||||
$exceptions = $this->iterateValidation($input);
|
||||
|
@ -17,12 +17,12 @@ class One extends AbstractCompositeValidator
|
|||
return true;
|
||||
}
|
||||
|
||||
public function isValid($input)
|
||||
public function is($input)
|
||||
{
|
||||
return (boolean) array_filter(
|
||||
$this->getValidators(),
|
||||
function($v) use($input) {
|
||||
return $v->isValid($input);
|
||||
return $v->is($input);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -15,8 +15,6 @@ class Between extends AbstractDateValidator implements Validatable
|
|||
self::MSG_OUT_OF_BOUNDS => '%s is not between %s and %s.'
|
||||
);
|
||||
|
||||
|
||||
|
||||
public function __construct($min, $max, $format=null)
|
||||
{
|
||||
|
||||
|
@ -31,10 +29,10 @@ class Between extends AbstractDateValidator implements Validatable
|
|||
$this->setFormat($format);
|
||||
}
|
||||
|
||||
public function validate($input)
|
||||
public function assert($input)
|
||||
{
|
||||
$target = $this->getDateObject($input);
|
||||
if (!$this->isValid($target))
|
||||
if (!$this->is($target))
|
||||
throw new OutOfBoundsException(
|
||||
sprintf(
|
||||
$this->getMessage(self::MSG_OUT_OF_BOUNDS),
|
||||
|
@ -45,7 +43,7 @@ class Between extends AbstractDateValidator implements Validatable
|
|||
return true;
|
||||
}
|
||||
|
||||
public function isValid($input)
|
||||
public function is($input)
|
||||
{
|
||||
$target = $this->getDateObject($input);
|
||||
return $target >= $this->min and $target <= $this->max;
|
||||
|
|
23
library/Respect/Validation/String/NotEmpty.php
Normal file
23
library/Respect/Validation/String/NotEmpty.php
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
namespace Respect\Validation\String;
|
||||
|
||||
use Respect\Validation\Validatable;
|
||||
use Respect\Validation\AbstractNode;
|
||||
|
||||
class NotEmpty extends AbstractNode implements Validatable
|
||||
{
|
||||
|
||||
public function is($input)
|
||||
{
|
||||
$trimmed = trim($input);
|
||||
return!empty($trimmed);
|
||||
}
|
||||
|
||||
public function assert($input)
|
||||
{
|
||||
if (!$this->is($input))
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
}
|
|
@ -5,9 +5,9 @@ namespace Respect\Validation;
|
|||
interface Validatable
|
||||
{
|
||||
|
||||
public function validate($input);
|
||||
public function assert($input);
|
||||
|
||||
public function isValid($input);
|
||||
public function is($input);
|
||||
|
||||
public function getMessages();
|
||||
|
||||
|
|
|
@ -4,41 +4,148 @@ namespace Respect\Validation;
|
|||
|
||||
use ReflectionClass;
|
||||
|
||||
abstract class Validator
|
||||
class Validator
|
||||
{
|
||||
|
||||
public static function validate($input, $validatorName)
|
||||
protected $input;
|
||||
protected $subject;
|
||||
protected $validator;
|
||||
protected $arguments;
|
||||
protected $operation;
|
||||
|
||||
public function getOperation()
|
||||
{
|
||||
$arguments = func_get_args();
|
||||
$arguments = array_slice($arguments, 2);
|
||||
return static::buildValidator($validatorName, $arguments)->validate($input);
|
||||
return $this->operation;
|
||||
}
|
||||
|
||||
public static function is($input, $validatorName)
|
||||
public function getInput()
|
||||
{
|
||||
$arguments = func_get_args();
|
||||
$arguments = array_slice($arguments, 2);
|
||||
return static::buildValidator($validatorName, $arguments)->isValid($input);
|
||||
return $this->input;
|
||||
}
|
||||
|
||||
public function getSubject()
|
||||
{
|
||||
return $this->subject;
|
||||
}
|
||||
|
||||
public function getValidator()
|
||||
{
|
||||
return $this->validator;
|
||||
}
|
||||
|
||||
public function getArguments()
|
||||
{
|
||||
return $this->arguments;
|
||||
}
|
||||
|
||||
public function setInput($input)
|
||||
{
|
||||
$this->input = $input;
|
||||
}
|
||||
|
||||
public function setSubject($subject)
|
||||
{
|
||||
$this->subject = $subject;
|
||||
}
|
||||
|
||||
public function setValidator($validator)
|
||||
{
|
||||
$this->validator = $validator;
|
||||
}
|
||||
|
||||
public function setArguments(array $arguments)
|
||||
{
|
||||
$this->arguments = $arguments;
|
||||
}
|
||||
|
||||
public function addArgument($argument)
|
||||
{
|
||||
$this->arguments[] = $argument;
|
||||
}
|
||||
|
||||
public function setOperation($operation)
|
||||
{
|
||||
$this->operation = $operation;
|
||||
}
|
||||
|
||||
public function isComplete()
|
||||
{
|
||||
return isset($this->operation, $this->input, $this->subject,
|
||||
$this->validator);
|
||||
}
|
||||
|
||||
protected function applySteps(array $stepData)
|
||||
{
|
||||
foreach ($stepData as $p) {
|
||||
if (!isset($this->operation)) {
|
||||
$this->setOperation($p);
|
||||
continue;
|
||||
}
|
||||
if (!isset($this->input)) {
|
||||
$this->setInput($p);
|
||||
continue;
|
||||
}
|
||||
if (!isset($this->subject)) {
|
||||
$this->setSubject($p);
|
||||
continue;
|
||||
}
|
||||
if (!isset($this->validator)) {
|
||||
$this->setValidator($p);
|
||||
continue;
|
||||
}
|
||||
$this->addArgument($p);
|
||||
}
|
||||
if ($this->isComplete())
|
||||
return $this->execute();
|
||||
else
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function __call($method, $arguments)
|
||||
{
|
||||
array_unshift($arguments, $method);
|
||||
return $this->applySteps($arguments);
|
||||
}
|
||||
|
||||
public function __get($property)
|
||||
{
|
||||
return $this->applySteps(array($property));
|
||||
}
|
||||
|
||||
public function execute()
|
||||
{
|
||||
if (!$this->isComplete())
|
||||
throw new ComponentException('Validator not complete');
|
||||
$validatorSpec = array($this->subject, $this->validator);
|
||||
$validatorInstance = static::buildValidator($validatorSpec,
|
||||
$this->arguments);
|
||||
$operationSpec = array($validatorInstance, $this->operation);
|
||||
return call_user_func($operationSpec, $this->input);
|
||||
}
|
||||
|
||||
public function __construct($operation=null, $input=null, $subject=null,
|
||||
$validator=null, $arguments=array())
|
||||
{
|
||||
$this->operation = $operation;
|
||||
$this->input = $input;
|
||||
$this->subject = $subject;
|
||||
$this->validator = $validator;
|
||||
$this->arguments = $arguments;
|
||||
}
|
||||
|
||||
public static function __callStatic($method, $arguments)
|
||||
{
|
||||
if (2 > count($arguments))
|
||||
return false;
|
||||
if (0 === strpos($method, 'valid')) {
|
||||
$arguments[1] = substr($method, 5) . '\\' . $arguments[1];
|
||||
$arguments[1] = trim($arguments[1], '\\');
|
||||
return call_user_func_array(
|
||||
array(get_called_class(), 'validate'), $arguments
|
||||
);
|
||||
} elseif (0 === strpos($method, 'is')) {
|
||||
$arguments[1] = substr($method, 2) . '\\' . $arguments[1];
|
||||
$arguments[1] = trim($arguments[1], '\\');
|
||||
return call_user_func_array(
|
||||
array(get_called_class(), 'is'), $arguments
|
||||
);
|
||||
}
|
||||
return false;
|
||||
preg_match('#^(is|assert)([[:alnum:]]+)?$#', $method, $matches);
|
||||
array_shift($matches);
|
||||
$input = array_shift($arguments);
|
||||
$operation = array_shift($matches);
|
||||
$subject = array_shift($matches) ? : array_shift($arguments);
|
||||
$validator = array_shift($arguments);
|
||||
$v = new static($operation, $input, $subject, $validator, $arguments);
|
||||
if ($v->isComplete())
|
||||
return $v->execute();
|
||||
else
|
||||
return $v;
|
||||
}
|
||||
|
||||
public static function buildValidator($validator, $arguments=array())
|
||||
|
@ -53,7 +160,9 @@ abstract class Validator
|
|||
);
|
||||
$validatorFqn = explode('\\', get_called_class());
|
||||
array_pop($validatorFqn);
|
||||
$validatorFqn = array_merge($validatorFqn, explode('\\', $validator));
|
||||
if (!is_array($validator))
|
||||
$validator = explode('\\', $validator);
|
||||
$validatorFqn = array_merge($validatorFqn, $validator);
|
||||
$validatorFqn = array_map('ucfirst', $validatorFqn);
|
||||
$validatorFqn = implode('\\', $validatorFqn);
|
||||
$validatorClass = new ReflectionClass($validatorFqn);
|
||||
|
|
|
@ -20,7 +20,7 @@ class AllTest extends ValidatorTestCase
|
|||
public function testValidateManyValid($a, $b, $c)
|
||||
{
|
||||
$this->object->addValidators(func_get_args());
|
||||
$this->assertTrue($this->object->validate('any'));
|
||||
$this->assertTrue($this->object->assert('any'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -29,7 +29,7 @@ class AllTest extends ValidatorTestCase
|
|||
public function testManyIsValid($a, $b, $c)
|
||||
{
|
||||
$this->object->addValidators(func_get_args());
|
||||
$this->assertTrue($this->object->isValid('any'));
|
||||
$this->assertTrue($this->object->is('any'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -38,7 +38,7 @@ class AllTest extends ValidatorTestCase
|
|||
public function testManyIsInvalid($a, $b, $c)
|
||||
{
|
||||
$this->object->addValidators(func_get_args());
|
||||
$this->assertFalse($this->object->isValid('any'));
|
||||
$this->assertFalse($this->object->is('any'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -50,7 +50,7 @@ class AllTest extends ValidatorTestCase
|
|||
$this->object->addValidator(
|
||||
$this->buildMockValidator('Aids', array('Aids_1' => 'aesfg'))
|
||||
);
|
||||
$this->assertFalse($this->object->isValid('any'));
|
||||
$this->assertFalse($this->object->is('any'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -60,7 +60,7 @@ class AllTest extends ValidatorTestCase
|
|||
{
|
||||
$this->object->addValidators(func_get_args());
|
||||
try {
|
||||
$this->object->validate('any');
|
||||
$this->object->assert('any');
|
||||
} catch (InvalidException $e) {
|
||||
$this->assertEquals(3, count($e->getExceptions()));
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ class OneTest extends ValidatorTestCase
|
|||
$valid = $this->buildMockValidator('Darth', array('Darth_1' => 'o54n'));
|
||||
$this->object->addValidators(func_get_args());
|
||||
$this->object->addValidator($valid);
|
||||
$this->assertTrue($this->object->validate('any'));
|
||||
$this->assertTrue($this->object->assert('any'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -33,7 +33,7 @@ class OneTest extends ValidatorTestCase
|
|||
{
|
||||
$this->object->addValidators(func_get_args());
|
||||
try {
|
||||
$this->object->validate('any');
|
||||
$this->object->assert('any');
|
||||
} catch (InvalidException $e) {
|
||||
$this->assertEquals(3, count($e->getExceptions()));
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ class OneTest extends ValidatorTestCase
|
|||
$valid = $this->buildMockValidator('Darth', array('Darth_1' => 'o54n'));
|
||||
$this->object->addValidators(func_get_args());
|
||||
$this->object->addValidator($valid);
|
||||
$this->assertTrue($this->object->isValid('any'));
|
||||
$this->assertTrue($this->object->is('any'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -56,7 +56,7 @@ class OneTest extends ValidatorTestCase
|
|||
public function testIsValidOneAllRotten($invalidA, $invalidB, $invalidC)
|
||||
{
|
||||
$this->object->addValidators(func_get_args());
|
||||
$this->assertFalse($this->object->isValid('any'));
|
||||
$this->assertFalse($this->object->is('any'));
|
||||
}
|
||||
|
||||
}
|
|
@ -13,8 +13,8 @@ class BetweenTest extends \PHPUnit_Framework_TestCase
|
|||
public function testBetweenValid($input, $min, $max)
|
||||
{
|
||||
$between = new Between($min, $max);
|
||||
$this->assertTrue($between->isValid($input));
|
||||
$this->assertTrue($between->validate($input));
|
||||
$this->assertTrue($between->is($input));
|
||||
$this->assertTrue($between->assert($input));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -25,8 +25,8 @@ class BetweenTest extends \PHPUnit_Framework_TestCase
|
|||
{
|
||||
|
||||
$between = new Between($min, $max);
|
||||
$this->assertFalse($between->isValid($input));
|
||||
$this->assertFalse($between->validate($input));
|
||||
$this->assertFalse($between->is($input));
|
||||
$this->assertFalse($between->assert($input));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -5,40 +5,76 @@ namespace Respect\Validation;
|
|||
class ValidatorTest extends ValidatorTestCase
|
||||
{
|
||||
|
||||
public function testSimpleValidateCall()
|
||||
public function testPartialEmpty()
|
||||
{
|
||||
$valid = Validator::valid('now', 'Date\Between', 'yesterday', 'tomorrow');
|
||||
$this->assertTrue($valid);
|
||||
$v = Validator::is();
|
||||
$this->assertType('Respect\Validation\Validator', $v);
|
||||
$this->assertSame('is', $v->getOperation());
|
||||
}
|
||||
|
||||
public function testDynamicValidateCall()
|
||||
public function testPartialInputOnly()
|
||||
{
|
||||
$valid = Validator::validDate('now', 'Between', 'yesterday', 'tomorrow');
|
||||
$this->assertTrue($valid);
|
||||
$v = Validator::is('something');
|
||||
$this->assertType('Respect\Validation\Validator', $v);
|
||||
$this->assertSame('is', $v->getOperation());
|
||||
$this->assertSame('something', $v->getInput());
|
||||
}
|
||||
|
||||
public function testSimpleIsValidCall()
|
||||
public function testPartialInputSubject()
|
||||
{
|
||||
$valid = Validator::is('now', 'Date\Between', 'yesterday', 'tomorrow');
|
||||
$this->assertTrue($valid);
|
||||
$v = Validator::is('now', 'date');
|
||||
$this->assertType('Respect\Validation\Validator', $v);
|
||||
$this->assertSame('is', $v->getOperation());
|
||||
$this->assertSame('now', $v->getInput());
|
||||
$this->assertSame('date', $v->getSubject());
|
||||
}
|
||||
|
||||
public function testDynamicIsValidCall()
|
||||
public function testValidateSimple()
|
||||
{
|
||||
$valid = Validator::isDate('now', 'Between', 'yesterday', 'tomorrow');
|
||||
$this->assertTrue($valid);
|
||||
$v = Validator::is('foo', 'string', 'notEmpty');
|
||||
$this->assertTrue($v);
|
||||
}
|
||||
|
||||
public function testNodeName()
|
||||
public function testValidateArguments()
|
||||
{
|
||||
$valid = Validator::isDate('now', 'between', 'yesterday', 'tomorrow');
|
||||
$this->assertTrue($valid);
|
||||
$v = Validator::is('now', 'date', 'between', 'yesterday', 'tomorrow');
|
||||
$this->assertTrue($v);
|
||||
}
|
||||
|
||||
public function testNodeName2()
|
||||
public function testFluentSubjectGetter()
|
||||
{
|
||||
$valid = Validator::is('now', 'date\between', 'yesterday', 'tomorrow');
|
||||
$this->assertTrue($valid);
|
||||
$v = Validator::is('now')->date;
|
||||
$this->assertType('Respect\Validation\Validator', $v);
|
||||
$this->assertSame('is', $v->getOperation());
|
||||
$this->assertSame('now', $v->getInput());
|
||||
$this->assertSame('date', $v->getSubject());
|
||||
}
|
||||
|
||||
public function testFluentSubjectCall()
|
||||
{
|
||||
$v = Validator::is('now')->date();
|
||||
$this->assertType('Respect\Validation\Validator', $v);
|
||||
$this->assertSame('is', $v->getOperation());
|
||||
$this->assertSame('now', $v->getInput());
|
||||
$this->assertSame('date', $v->getSubject());
|
||||
}
|
||||
|
||||
public function testFluentSubjectGetterMixed()
|
||||
{
|
||||
$v = Validator::is('now')->date->between('yesterday', 'tomorrow');
|
||||
$this->assertTrue($v);
|
||||
}
|
||||
|
||||
public function testFluentSubjectCallMixed()
|
||||
{
|
||||
$v = Validator::is('now', 'date')->between('yesterday', 'tomorrow');
|
||||
$this->assertTrue($v);
|
||||
}
|
||||
|
||||
public function testFluentSubjectCallMixed2()
|
||||
{
|
||||
$v = Validator::is('now')->date('between', 'yesterday', 'tomorrow');
|
||||
$this->assertTrue($v);
|
||||
}
|
||||
|
||||
}
|
|
@ -22,13 +22,13 @@ abstract class ValidatorTestCase extends \PHPUnit_Framework_TestCase
|
|||
{
|
||||
$validator = Mockery::mock('Respect\Validation\Validatable');
|
||||
if ($invalid) {
|
||||
$validator->shouldReceive('validate')->andThrow(
|
||||
$validator->shouldReceive('assert')->andThrow(
|
||||
new InvalidException('Always invalid, man.')
|
||||
);
|
||||
$validator->shouldReceive('isValid')->andReturn(false);
|
||||
$validator->shouldReceive('is')->andReturn(false);
|
||||
} else {
|
||||
$validator->shouldReceive('isValid')->andReturn(true);
|
||||
$validator->shouldReceive('validate')->andReturn(true);
|
||||
$validator->shouldReceive('is')->andReturn(true);
|
||||
$validator->shouldReceive('assert')->andReturn(true);
|
||||
}
|
||||
$validator->shouldReceive('getMessages')->andReturn(
|
||||
$messages
|
||||
|
@ -38,8 +38,8 @@ abstract class ValidatorTestCase extends \PHPUnit_Framework_TestCase
|
|||
eval("
|
||||
namespace Respect\Validation\Foo;
|
||||
class $name implements \Respect\Validation\Validatable {
|
||||
public function validate(\$input) {}
|
||||
public function isValid(\$input) {}
|
||||
public function assert(\$input) {}
|
||||
public function is(\$input) {}
|
||||
public function setMessages(array \$messages) {}
|
||||
public function getMessages() {
|
||||
return " . var_export($messages,
|
||||
|
|
Loading…
Reference in a new issue