Skip to content

Commit

Permalink
Merge pull request #176 from henriquemoody/namespace
Browse files Browse the repository at this point in the history
Allow to define custom rule's namespaces/prefixes.
  • Loading branch information
henriquemoody committed Feb 11, 2015
2 parents d311c5e + a4cb208 commit 2914eba
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 11 deletions.
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,23 @@ $errors = $exception->findMessages(array(

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

### Custom Rules

You also can use your own rules:

```php
v::with('My\\Validation\\Rules\\');
v::myRule(); // Try to load "My\Validation\Rules\MyRule" if any
```

By default `with()` appends the given prefix, but you can change this behavior
in order to overwrite default rules:

```php
v::with('My\\Validation\\Rules\\', true);
v::alnum(); // Try to use "My\Validation\Rules\Alnum" if any
```

### Validator Name

On `v::attribute()` and `v::key()`, `{{name}}` is the attribute/key name. For others,
Expand Down
49 changes: 49 additions & 0 deletions library/Factory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace Respect\Validation;

use ReflectionClass;
use Respect\Validation\Exceptions\ComponentException;

class Factory
{
protected $rulePrefixes = array('Respect\\Validation\\Rules\\');

public function getRulePrefixes()
{
return $this->rulePrefixes;
}

public function appendRulePrefix($rulePrefix)
{
array_push($this->rulePrefixes, $rulePrefix);
}

public function prependRulePrefix($rulePrefix)
{
array_unshift($this->rulePrefixes, $rulePrefix);
}

public function rule($ruleName, array $arguments = array())
{
if ($ruleName instanceof Validatable) {
return $ruleName;
}

foreach ($this->getRulePrefixes() as $prefix) {
$className = $prefix.ucfirst($ruleName);
if (! class_exists($className)) {
continue;
}

$reflection = new ReflectionClass($className);
if (! $reflection->isSubclassOf('Respect\\Validation\\Validatable')) {
throw new ComponentException(sprintf('"%s" is not a valid respect rule', $className));
}

return $reflection->newInstanceArgs($arguments);
}

throw new ComponentException(sprintf('"%s" is not a valid rule name', $ruleName));
}
}
53 changes: 42 additions & 11 deletions library/Validator.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,45 @@
*/
class Validator extends AllOf
{
protected static $factory;

/**
* @return Factory
*/
protected static function getFactory()
{
if (! static::$factory instanceof Factory) {
static::$factory = new Factory();
}

return static::$factory;
}

/**
* @param Factory $factory
*
* @return null
*/
public static function setFactory($factory)
{
static::$factory = $factory;
}

/**
* @param string $rulePrefix
* @param bool $prepend
*
* @return null
*/
public static function with($rulePrefix, $prepend = false)
{
if (false === $prepend) {
self::getFactory()->appendRulePrefix($rulePrefix);
} else {
self::getFactory()->prependRulePrefix($rulePrefix);
}
}

/**
* @param string $ruleName
* @param array $arguments
Expand All @@ -131,18 +170,10 @@ public static function __callStatic($ruleName, $arguments)
*/
public static function buildRule($ruleSpec, $arguments = array())
{
if ($ruleSpec instanceof Validatable) {
return $ruleSpec;
}

try {
$validatorFqn = 'Respect\\Validation\\Rules\\'.ucfirst($ruleSpec);
$validatorClass = new ReflectionClass($validatorFqn);
$validatorInstance = $validatorClass->newInstanceArgs($arguments);

return $validatorInstance;
} catch (ReflectionException $e) {
throw new ComponentException($e->getMessage());
return static::getFactory()->rule($ruleSpec, $arguments);
} catch (\Exception $exception) {
throw new ComponentException($exception->getMessage(), $exception->getCode(), $exception);
}
}

Expand Down
72 changes: 72 additions & 0 deletions tests/FactoryTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

namespace Respect\Validation;

/**
* @covers Respect\Validation\Factory
*/
class FactoryTest extends \PHPUnit_Framework_TestCase
{
public function testShouldHaveRulePrefixesByDefault()
{
$factory = new Factory();

$this->assertEquals(array('Respect\\Validation\\Rules\\'), $factory->getRulePrefixes());
}

public function testShouldBeAbleToAppendANewPrefix()
{
$factory = new Factory();
$factory->appendRulePrefix('My\\Validation\\Rules\\');

$this->assertEquals(array('Respect\\Validation\\Rules\\', 'My\\Validation\\Rules\\'), $factory->getRulePrefixes());
}

public function testShouldBeAbleToPrependANewRulePrefix()
{
$factory = new Factory();
$factory->prependRulePrefix('My\\Validation\\Rules\\');

$this->assertEquals(array('My\\Validation\\Rules\\', 'Respect\\Validation\\Rules\\'), $factory->getRulePrefixes());
}

public function testShouldCreateARuleByName()
{
$factory = new Factory();

$this->assertInstanceOf('Respect\\Validation\\Rules\\Uppercase', $factory->rule('uppercase'));
}

public function testShouldDefineConstructorArgumentsWhenCreatingARule()
{
$factory = new Factory();
$rule = $factory->rule('date', array('Y-m-d'));

$this->assertEquals('Y-m-d', $rule->format);
}

/**
* @expectedException Respect\Validation\Exceptions\ComponentException
* @expectedExceptionMessage "uterere" is not a valid rule name
*/
public function testShouldThrowsAnExceptionWhenRuleNameIsNotValid()
{
$factory = new Factory();
$factory->rule('uterere');
}

/**
* @expectedException Respect\Validation\Exceptions\ComponentException
* @expectedExceptionMessage "Respect\Validation\TestNonRule" is not a valid respect rule
*/
public function testShouldThrowsAnExceptionWhenRuleIsNotInstanceOfRuleInterface()
{
$factory = new Factory();
$factory->appendRulePrefix('Respect\\Validation\\Test');
$factory->rule('nonRule');
}
}

class TestNonRule
{
}

0 comments on commit 2914eba

Please sign in to comment.