mirror of
https://github.com/vlucas/valitron.git
synced 2025-12-31 07:01:54 +00:00
Merge pull request #166 from Matt3o12/addTmpRule
Add anonymous and instance rules
This commit is contained in:
commit
633c9ff57f
23
README.md
23
README.md
@ -188,6 +188,29 @@ Valitron\Validator::addRule('alwaysFail', function($field, $value, array $params
|
|||||||
}, 'Everything you do is wrong. You fail.');
|
}, 'Everything you do is wrong. You fail.');
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You can also use one-off rules that are only valid for the specified
|
||||||
|
fields.
|
||||||
|
|
||||||
|
```php
|
||||||
|
$v = new Valitron\Validator(array("foo" => "bar"));
|
||||||
|
$v->rule(function($field, $value, $params, $fields) {
|
||||||
|
return true;
|
||||||
|
}, "foo")->message("{field} failed...");
|
||||||
|
```
|
||||||
|
|
||||||
|
This is useful because such rules can have access to variables
|
||||||
|
defined in the scope where the `Validator` lives. The Closure's
|
||||||
|
signature is identical to `Validator::addRule` callback's
|
||||||
|
signature.
|
||||||
|
|
||||||
|
If you wish to add your own rules that are not static (i.e.,
|
||||||
|
your rule is not static and available to call `Validator`
|
||||||
|
instances), you need to use `Validator::addInstanceRule`.
|
||||||
|
This rule will take the same parameters as
|
||||||
|
`Validator::addRule` but it has to be called on a `Validator`
|
||||||
|
instance.
|
||||||
|
|
||||||
|
|
||||||
## Alternate syntax for adding rules
|
## Alternate syntax for adding rules
|
||||||
|
|
||||||
As the number of rules grows, you may prefer the alternate syntax
|
As the number of rules grows, you may prefer the alternate syntax
|
||||||
|
|||||||
@ -37,6 +37,21 @@ class Validator
|
|||||||
*/
|
*/
|
||||||
protected $_labels = array();
|
protected $_labels = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains all rules that are available to the current valitron instance.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $_instanceRules = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains all rule messages that are available to the current valitron
|
||||||
|
* instance
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $_instanceRuleMessage = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
@ -921,8 +936,9 @@ class Validator
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Callback is user-specified or assumed method on class
|
// Callback is user-specified or assumed method on class
|
||||||
if (isset(static::$_rules[$v['rule']])) {
|
$errors = $this->getRules();
|
||||||
$callback = static::$_rules[$v['rule']];
|
if (isset($errors[$v['rule']])) {
|
||||||
|
$callback = $errors[$v['rule']];
|
||||||
} else {
|
} else {
|
||||||
$callback = array($this, 'validate' . ucfirst($v['rule']));
|
$callback = array($this, 'validate' . ucfirst($v['rule']));
|
||||||
}
|
}
|
||||||
@ -945,6 +961,26 @@ class Validator
|
|||||||
return count($this->errors()) === 0;
|
return count($this->errors()) === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all rule callbacks, the static and instance ones.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function getRules()
|
||||||
|
{
|
||||||
|
return array_merge($this->_instanceRules, static::$_rules);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all rule message, the static and instance ones.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function getRuleMessages()
|
||||||
|
{
|
||||||
|
return array_merge($this->_instanceRuleMessage, static::$_ruleMessages);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine whether a field is being validated by the given rule.
|
* Determine whether a field is being validated by the given rule.
|
||||||
*
|
*
|
||||||
@ -952,6 +988,7 @@ class Validator
|
|||||||
* @param string $field The name of the field
|
* @param string $field The name of the field
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
|
|
||||||
protected function hasRule($name, $field)
|
protected function hasRule($name, $field)
|
||||||
{
|
{
|
||||||
foreach ($this->_validations as $validation) {
|
foreach ($this->_validations as $validation) {
|
||||||
@ -965,6 +1002,31 @@ class Validator
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static function assertRuleCallback($callback)
|
||||||
|
{
|
||||||
|
if (!is_callable($callback)) {
|
||||||
|
throw new \InvalidArgumentException('Second argument must be a valid callback. Given argument was not callable.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new validation rule callback that is tied to the current
|
||||||
|
* instance only.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param mixed $callback
|
||||||
|
* @param string $message
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function addInstanceRule($name, $callback, $message = null)
|
||||||
|
{
|
||||||
|
static::assertRuleCallback($callback);
|
||||||
|
|
||||||
|
$this->_instanceRules[$name] = $callback;
|
||||||
|
$this->_instanceRuleMessage[$name] = $message;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register new validation rule callback
|
* Register new validation rule callback
|
||||||
*
|
*
|
||||||
@ -973,27 +1035,75 @@ class Validator
|
|||||||
* @param string $message
|
* @param string $message
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public static function addRule($name, $callback, $message = self::ERROR_DEFAULT)
|
public static function addRule($name, $callback, $message = null)
|
||||||
{
|
{
|
||||||
if (!is_callable($callback)) {
|
if ($message === null)
|
||||||
throw new \InvalidArgumentException('Second argument must be a valid callback. Given argument was not callable.');
|
{
|
||||||
|
$message = static::ERROR_DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static::assertRuleCallback($callback);
|
||||||
|
|
||||||
static::$_rules[$name] = $callback;
|
static::$_rules[$name] = $callback;
|
||||||
static::$_ruleMessages[$name] = $message;
|
static::$_ruleMessages[$name] = $message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getUniqueRuleName($fields)
|
||||||
|
{
|
||||||
|
if (is_array($fields))
|
||||||
|
{
|
||||||
|
$fields = implode("_", $fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
$orgName = "{$fields}_rule";
|
||||||
|
$name = $orgName;
|
||||||
|
$rules = $this->getRules();
|
||||||
|
while (isset($rules[$name]))
|
||||||
|
{
|
||||||
|
$name = $orgName . "_" . rand(0, 10000);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
* Convenience method to add a single validation rule
|
||||||
*
|
*
|
||||||
* @param string $rule
|
* @param string|callback $rule
|
||||||
* @param array $fields
|
* @param array $fields
|
||||||
* @return $this
|
* @return $this
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function rule($rule, $fields)
|
public function rule($rule, $fields)
|
||||||
{
|
{
|
||||||
if (!isset(static::$_rules[$rule])) {
|
// Get any other arguments passed to function
|
||||||
|
$params = array_slice(func_get_args(), 2);
|
||||||
|
|
||||||
|
if (is_callable($rule)
|
||||||
|
&& !(is_string($rule) && $this->hasValidator($rule)))
|
||||||
|
{
|
||||||
|
$name = $this->getUniqueRuleName($fields);
|
||||||
|
$msg = isset($params[0]) ? $params[0] : null;
|
||||||
|
$this->addInstanceRule($name, $rule, $msg);
|
||||||
|
$rule = $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
$errors = $this->getRules();
|
||||||
|
if (!isset($errors[$rule])) {
|
||||||
$ruleMethod = 'validate' . ucfirst($rule);
|
$ruleMethod = 'validate' . ucfirst($rule);
|
||||||
if (!method_exists($this, $ruleMethod)) {
|
if (!method_exists($this, $ruleMethod)) {
|
||||||
throw new \InvalidArgumentException("Rule '" . $rule . "' has not been registered with " . __CLASS__ . "::addRule().");
|
throw new \InvalidArgumentException("Rule '" . $rule . "' has not been registered with " . __CLASS__ . "::addRule().");
|
||||||
@ -1001,10 +1111,8 @@ class Validator
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure rule has an accompanying message
|
// Ensure rule has an accompanying message
|
||||||
$message = isset(static::$_ruleMessages[$rule]) ? static::$_ruleMessages[$rule] : self::ERROR_DEFAULT;
|
$msgs = $this->getRuleMessages();
|
||||||
|
$message = isset($msgs[$rule]) ? $msgs[$rule] : self::ERROR_DEFAULT;
|
||||||
// Get any other arguments passed to function
|
|
||||||
$params = array_slice(func_get_args(), 2);
|
|
||||||
|
|
||||||
$this->_validations[] = array(
|
$this->_validations[] = array(
|
||||||
'rule' => $rule,
|
'rule' => $rule,
|
||||||
|
|||||||
120
tests/Valitron/ValidateAddInstanceRuleTest.php
Normal file
120
tests/Valitron/ValidateAddInstanceRuleTest.php
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
<?php
|
||||||
|
use Valitron\Validator;
|
||||||
|
|
||||||
|
function callbackTestFunction($item, $value)
|
||||||
|
{
|
||||||
|
return $value === "bar";
|
||||||
|
}
|
||||||
|
|
||||||
|
class ValidateAddInstanceRuleTest extends BaseTestCase
|
||||||
|
{
|
||||||
|
protected function assertValid($v)
|
||||||
|
{
|
||||||
|
$msg = "\tErrors:\n";
|
||||||
|
$status = $v->validate();
|
||||||
|
foreach ($v->errors() as $label => $messages)
|
||||||
|
{
|
||||||
|
foreach ($messages as $theMessage)
|
||||||
|
{
|
||||||
|
$msg .= "\n\t{$label}: {$theMessage}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertTrue($v->validate(), $msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAddInstanceRule()
|
||||||
|
{
|
||||||
|
$v = new Validator(array(
|
||||||
|
"foo" => "bar",
|
||||||
|
"fuzz" => "bazz",
|
||||||
|
));
|
||||||
|
|
||||||
|
$v->addInstanceRule("fooRule", function($field, $value)
|
||||||
|
{
|
||||||
|
return $field !== "foo" || $value !== "barz";
|
||||||
|
});
|
||||||
|
|
||||||
|
Validator::addRule("fuzzerRule", function($field, $value)
|
||||||
|
{
|
||||||
|
return $field !== "fuzz" || $value === "bazz";
|
||||||
|
});
|
||||||
|
|
||||||
|
$v->rule("required", array("foo", "fuzz"));
|
||||||
|
$v->rule("fuzzerRule", "fuzz");
|
||||||
|
$v->rule("fooRule", "foo");
|
||||||
|
|
||||||
|
$this->assertValid($v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAddInstanceRuleFail()
|
||||||
|
{
|
||||||
|
$v = new Validator(array("foo" => "bar"));
|
||||||
|
$v->addInstanceRule("fooRule", function($field)
|
||||||
|
{
|
||||||
|
return $field === "for";
|
||||||
|
});
|
||||||
|
$v->rule("fooRule", "foo");
|
||||||
|
$this->assertFalse($v->validate());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAddAddRuleWithCallback()
|
||||||
|
{
|
||||||
|
$v = new Validator(array("foo" => "bar"));
|
||||||
|
$v->rule(function($field, $value) {
|
||||||
|
return $field === "foo" && $value === "bar";
|
||||||
|
}, "foo");
|
||||||
|
|
||||||
|
$this->assertValid($v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAddAddRuleWithCallbackFail()
|
||||||
|
{
|
||||||
|
$v = new Validator(array("foo" => "baz"));
|
||||||
|
$v->rule(function($field, $value) {
|
||||||
|
return $field === "foo" && $value === "bar";
|
||||||
|
}, "foo");
|
||||||
|
|
||||||
|
$this->assertFalse($v->validate());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAddAddRuleWithCallbackFailMessage()
|
||||||
|
{
|
||||||
|
$v = new Validator(array("foo" => "baz"));
|
||||||
|
$v->rule(function($field, $value) {
|
||||||
|
return $field === "foo" && $value === "bar";
|
||||||
|
}, "foo", "test error message");
|
||||||
|
|
||||||
|
$this->assertFalse($v->validate());
|
||||||
|
$errors = $v->errors();
|
||||||
|
$this->assertArrayHasKey("foo", $errors);
|
||||||
|
$this->assertCount(1, $errors["foo"]);
|
||||||
|
$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());
|
||||||
|
$args = array("foo", "bar");
|
||||||
|
$this->assertEquals("foo_bar_rule", $v->getUniqueRuleName($args));
|
||||||
|
$this->assertEquals("foo_rule", $v->getUniqueRuleName("foo"));
|
||||||
|
|
||||||
|
$v->addInstanceRule("foo_rule", function() {});
|
||||||
|
$u = $v->getUniqueRuleName("foo");
|
||||||
|
$this->assertRegExp("/^foo_rule_[0-9]{1,5}$/", $u);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user