Validator extender (#2102)

Added validator extender, integration tests, and deprecated related Validating event
This commit is contained in:
Alexander Skvortsov 2020-11-01 11:31:16 -05:00 committed by GitHub
parent 10db7aad62
commit 459d4b63b0
4 changed files with 173 additions and 0 deletions

View File

@ -0,0 +1,58 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Extend;
use Flarum\Extension\Extension;
use Illuminate\Contracts\Container\Container;
class Validator implements ExtenderInterface
{
private $configurationCallbacks = [];
private $validator;
/**
* @param string $validatorClass: The ::class attribute of the validator you are modifying.
* The validator should inherit from \Flarum\Foundation\AbstractValidator.
*/
public function __construct($validatorClass)
{
$this->validator = $validatorClass;
}
/**
* Configure the validator. This is often used to adjust validation rules, but can be
* used to make other changes to the validator as well.
*
* @param callable $callable
*
* The callable can be a closure or invokable class, and should accept:
* - \Flarum\Foundation\AbstractValidator $flarumValidator: The Flarum validator wrapper
* - \Illuminate\Validation\Validator $validator: The Laravel validator instance
*/
public function configure($callback)
{
$this->configurationCallbacks[] = $callback;
return $this;
}
public function extend(Container $container, Extension $extension = null)
{
$container->resolving($this->validator, function ($validator, $container) {
foreach ($this->configurationCallbacks as $callback) {
if (is_string($callback)) {
$callback = $container->make($callback);
}
$validator->addConfiguration($callback);
}
});
}
}

View File

@ -18,6 +18,16 @@ use Symfony\Component\Translation\TranslatorInterface;
abstract class AbstractValidator
{
/**
* @var array
*/
protected $configuration = [];
public function addConfiguration($callable)
{
$this->configuration[] = $callable;
}
/**
* @var array
*/
@ -92,10 +102,17 @@ abstract class AbstractValidator
$validator = $this->validator->make($attributes, $rules, $this->getMessages());
/**
* @deprecated in beta 15, removed in beta 16.
*/
$this->events->dispatch(
new Validating($this, $validator)
);
foreach ($this->configuration as $callable) {
$callable($this, $validator);
}
return $validator;
}
}

View File

@ -13,6 +13,7 @@ use Flarum\Foundation\AbstractValidator;
use Illuminate\Validation\Validator;
/**
* @deprecated in Beta 15, remove in beta 16. Use the Validator extender instead.
* The `Validating` event is called when a validator instance for a
* model is being built. This event can be used to add custom rules/extensions
* to the validator for when validation takes place.

View File

@ -0,0 +1,97 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Tests\integration\extenders;
use Flarum\Extend;
use Flarum\Group\GroupValidator;
use Flarum\Tests\integration\TestCase;
use Flarum\User\UserValidator;
use Illuminate\Validation\ValidationException;
class ValidatorTest extends TestCase
{
private function extendToRequireLongPassword()
{
$this->extend((new Extend\Validator(UserValidator::class))->configure(function ($flarumValidator, $validator) {
$validator->setRules([
'password' => [
'required',
'min:20'
]
] + $validator->getRules());
}));
}
private function extendToRequireLongPasswordViaInvokableClass()
{
$this->extend((new Extend\Validator(UserValidator::class))->configure(CustomValidatorClass::class));
}
/**
* @test
*/
public function custom_validation_rule_does_not_exist_by_default()
{
$this->app()->getContainer()->make(UserValidator::class)->assertValid(['password' => 'simplePassword']);
// If we have gotten this far, no validation exception has been thrown, so the test is succesful.
$this->assertTrue(true);
}
/**
* @test
*/
public function custom_validation_rule_exists_if_added()
{
$this->extendToRequireLongPassword();
$this->expectException(ValidationException::class);
$this->app()->getContainer()->make(UserValidator::class)->assertValid(['password' => 'simplePassword']);
}
/**
* @test
*/
public function custom_validation_rule_exists_if_added_via_invokable_class()
{
$this->extendToRequireLongPasswordViaInvokableClass();
$this->expectException(ValidationException::class);
$this->app()->getContainer()->make(UserValidator::class)->assertValid(['password' => 'simplePassword']);
}
/**
* @test
*/
public function custom_validation_rule_doesnt_affect_other_validators()
{
$this->extendToRequireLongPassword();
$this->app()->getContainer()->make(GroupValidator::class)->assertValid(['password' => 'simplePassword']);
// If we have gotten this far, no validation exception has been thrown, so the test is succesful.
$this->assertTrue(true);
}
}
class CustomValidatorClass
{
public function __invoke($flarumValidator, $validator)
{
$validator->setRules([
'password' => [
'required',
'min:20'
]
] + $validator->getRules());
}
}