Validator::rule now accepts any kind of callback

This has been achieved by making sure that the rule is neither
a "native" Validator rule (e.g. there is a validate{$CamleCaseName}
method) nor it has been registered.

If both conditions are met, the rule (even if it is a string)
will be accepted and used.

Tests for this case have also been added.
This commit is contained in:
Matteo Kloiber 2016-11-06 01:40:05 +01:00
parent ebbeca46af
commit a6be7e2dd0
2 changed files with 35 additions and 6 deletions

View File

@ -1066,6 +1066,20 @@ class Validator
return $name;
}
/**
* Returns true if either a valdiator with the given name has been
* registered or there is a default validator by that name.
*
* @param string $name
* @return bool
*/
public function hasValidator($name)
{
$rules = $this->getRules();
return method_exists($this, "validate" . ucfirst($name))
|| isset($rules[$name]);
}
/**
* Convenience method to add a single validation rule
*
@ -1079,12 +1093,8 @@ class Validator
// Get any other arguments passed to function
$params = array_slice(func_get_args(), 2);
// Note: we cannot use is_callable here since max, int, and many
// other string can also be callables but aren't really rule callbacks.
//
// If a closure is used, we can be sure that the user actually
// wants $rule to be a custom rule check.
if (is_object($rule) && ($rule instanceof \Closure))
if (is_callable($rule)
&& !(is_string($rule) && $this->hasValidator($rule)))
{
$name = $this->getUniqueRuleName($fields);
$msg = isset($params[0]) ? $params[0] : null;

View File

@ -1,6 +1,11 @@
<?php
use Valitron\Validator;
function callbackTestFunction($item, $value)
{
return $value === "bar";
}
class ValidateAddInstanceRuleTest extends BaseTestCase
{
protected function assertValid($v)
@ -87,6 +92,20 @@ class ValidateAddInstanceRuleTest extends BaseTestCase
$this->assertEquals("Foo test error message", $errors["foo"][0]);
}
public function testAddRuleWithNamedCallbackOk()
{
$v = new Validator(array("bar" => "foo"));
$v->rule("callbackTestFunction", "bar");
$this->assertFalse($v->validate());
}
public function testAddRuleWithNamedCallbackErr()
{
$v = new Validator(array("foo" => "bar"));
$v->rule("callbackTestFunction", "foo");
$this->assertTrue($v->validate());
}
public function testUniqueRuleName()
{
$v = new Validator(array());