Skip to content

Commit a4cb208

Browse files
committed
Create a Factory to create rules
It also provide a way to define namespaces/prefixes to use the custom rules on Respect\Validation.
1 parent 3e46726 commit a4cb208

File tree

4 files changed

+180
-11
lines changed

4 files changed

+180
-11
lines changed

README.md

+17
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,23 @@ $errors = $exception->findMessages(array(
174174

175175
For all messages, the `{{name}}` and `{{input}}` variable is available for templates.
176176

177+
### Custom Rules
178+
179+
You also can use your own rules:
180+
181+
```php
182+
v::with('My\\Validation\\Rules\\');
183+
v::myRule(); // Try to load "My\Validation\Rules\MyRule" if any
184+
```
185+
186+
By default `with()` appends the given prefix, but you can change this behavior
187+
in order to overwrite default rules:
188+
189+
```php
190+
v::with('My\\Validation\\Rules\\', true);
191+
v::alnum(); // Try to use "My\Validation\Rules\Alnum" if any
192+
```
193+
177194
### Validator Name
178195

179196
On `v::attribute()` and `v::key()`, `{{name}}` is the attribute/key name. For others,

library/Factory.php

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
namespace Respect\Validation;
4+
5+
use ReflectionClass;
6+
use Respect\Validation\Exceptions\ComponentException;
7+
8+
class Factory
9+
{
10+
protected $rulePrefixes = array('Respect\\Validation\\Rules\\');
11+
12+
public function getRulePrefixes()
13+
{
14+
return $this->rulePrefixes;
15+
}
16+
17+
public function appendRulePrefix($rulePrefix)
18+
{
19+
array_push($this->rulePrefixes, $rulePrefix);
20+
}
21+
22+
public function prependRulePrefix($rulePrefix)
23+
{
24+
array_unshift($this->rulePrefixes, $rulePrefix);
25+
}
26+
27+
public function rule($ruleName, array $arguments = array())
28+
{
29+
if ($ruleName instanceof Validatable) {
30+
return $ruleName;
31+
}
32+
33+
foreach ($this->getRulePrefixes() as $prefix) {
34+
$className = $prefix.ucfirst($ruleName);
35+
if (! class_exists($className)) {
36+
continue;
37+
}
38+
39+
$reflection = new ReflectionClass($className);
40+
if (! $reflection->isSubclassOf('Respect\\Validation\\Validatable')) {
41+
throw new ComponentException(sprintf('"%s" is not a valid respect rule', $className));
42+
}
43+
44+
return $reflection->newInstanceArgs($arguments);
45+
}
46+
47+
throw new ComponentException(sprintf('"%s" is not a valid rule name', $ruleName));
48+
}
49+
}

library/Validator.php

+42-11
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,45 @@
106106
*/
107107
class Validator extends AllOf
108108
{
109+
protected static $factory;
110+
111+
/**
112+
* @return Factory
113+
*/
114+
protected static function getFactory()
115+
{
116+
if (! static::$factory instanceof Factory) {
117+
static::$factory = new Factory();
118+
}
119+
120+
return static::$factory;
121+
}
122+
123+
/**
124+
* @param Factory $factory
125+
*
126+
* @return null
127+
*/
128+
public static function setFactory($factory)
129+
{
130+
static::$factory = $factory;
131+
}
132+
133+
/**
134+
* @param string $rulePrefix
135+
* @param bool $prepend
136+
*
137+
* @return null
138+
*/
139+
public static function with($rulePrefix, $prepend = false)
140+
{
141+
if (false === $prepend) {
142+
self::getFactory()->appendRulePrefix($rulePrefix);
143+
} else {
144+
self::getFactory()->prependRulePrefix($rulePrefix);
145+
}
146+
}
147+
109148
/**
110149
* @param string $ruleName
111150
* @param array $arguments
@@ -131,18 +170,10 @@ public static function __callStatic($ruleName, $arguments)
131170
*/
132171
public static function buildRule($ruleSpec, $arguments = array())
133172
{
134-
if ($ruleSpec instanceof Validatable) {
135-
return $ruleSpec;
136-
}
137-
138173
try {
139-
$validatorFqn = 'Respect\\Validation\\Rules\\'.ucfirst($ruleSpec);
140-
$validatorClass = new ReflectionClass($validatorFqn);
141-
$validatorInstance = $validatorClass->newInstanceArgs($arguments);
142-
143-
return $validatorInstance;
144-
} catch (ReflectionException $e) {
145-
throw new ComponentException($e->getMessage());
174+
return static::getFactory()->rule($ruleSpec, $arguments);
175+
} catch (\Exception $exception) {
176+
throw new ComponentException($exception->getMessage(), $exception->getCode(), $exception);
146177
}
147178
}
148179

tests/FactoryTest.php

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
3+
namespace Respect\Validation;
4+
5+
/**
6+
* @covers Respect\Validation\Factory
7+
*/
8+
class FactoryTest extends \PHPUnit_Framework_TestCase
9+
{
10+
public function testShouldHaveRulePrefixesByDefault()
11+
{
12+
$factory = new Factory();
13+
14+
$this->assertEquals(array('Respect\\Validation\\Rules\\'), $factory->getRulePrefixes());
15+
}
16+
17+
public function testShouldBeAbleToAppendANewPrefix()
18+
{
19+
$factory = new Factory();
20+
$factory->appendRulePrefix('My\\Validation\\Rules\\');
21+
22+
$this->assertEquals(array('Respect\\Validation\\Rules\\', 'My\\Validation\\Rules\\'), $factory->getRulePrefixes());
23+
}
24+
25+
public function testShouldBeAbleToPrependANewRulePrefix()
26+
{
27+
$factory = new Factory();
28+
$factory->prependRulePrefix('My\\Validation\\Rules\\');
29+
30+
$this->assertEquals(array('My\\Validation\\Rules\\', 'Respect\\Validation\\Rules\\'), $factory->getRulePrefixes());
31+
}
32+
33+
public function testShouldCreateARuleByName()
34+
{
35+
$factory = new Factory();
36+
37+
$this->assertInstanceOf('Respect\\Validation\\Rules\\Uppercase', $factory->rule('uppercase'));
38+
}
39+
40+
public function testShouldDefineConstructorArgumentsWhenCreatingARule()
41+
{
42+
$factory = new Factory();
43+
$rule = $factory->rule('date', array('Y-m-d'));
44+
45+
$this->assertEquals('Y-m-d', $rule->format);
46+
}
47+
48+
/**
49+
* @expectedException Respect\Validation\Exceptions\ComponentException
50+
* @expectedExceptionMessage "uterere" is not a valid rule name
51+
*/
52+
public function testShouldThrowsAnExceptionWhenRuleNameIsNotValid()
53+
{
54+
$factory = new Factory();
55+
$factory->rule('uterere');
56+
}
57+
58+
/**
59+
* @expectedException Respect\Validation\Exceptions\ComponentException
60+
* @expectedExceptionMessage "Respect\Validation\TestNonRule" is not a valid respect rule
61+
*/
62+
public function testShouldThrowsAnExceptionWhenRuleIsNotInstanceOfRuleInterface()
63+
{
64+
$factory = new Factory();
65+
$factory->appendRulePrefix('Respect\\Validation\\Test');
66+
$factory->rule('nonRule');
67+
}
68+
}
69+
70+
class TestNonRule
71+
{
72+
}

0 commit comments

Comments
 (0)