Always display message for AbstractRelated rule

`NestedValidationException` should include all `AbstractRelated` rule
exceptions.

`AbstractRelated` rule failures always indicate an interesting nested
context, which should not be omitted from the final result.

`NonOmissibleExceptionInterface` is a marker interface for
exceptions thrown by instances of `AbstractRelated`, which
facilitates identification of those rules' exceptions with
`instanceof`.
This commit is contained in:
Jonathan Stewmon 2017-03-02 15:04:15 -06:00 committed by Henrique Moody
parent 88e60b6a3a
commit 8851fb5abc
No known key found for this signature in database
GPG key ID: 221E9281655813A6
9 changed files with 146 additions and 8 deletions

View file

@ -11,7 +11,7 @@
namespace Respect\Validation\Exceptions;
class AttributeException extends NestedValidationException
class AttributeException extends NestedValidationException implements NonOmissibleExceptionInterface
{
const NOT_PRESENT = 0;
const INVALID = 1;

View file

@ -11,6 +11,6 @@
namespace Respect\Validation\Exceptions;
class CallException extends GroupedValidationException
class CallException extends GroupedValidationException implements NonOmissibleExceptionInterface
{
}

View file

@ -11,7 +11,7 @@
namespace Respect\Validation\Exceptions;
class KeyException extends AttributeException
class KeyException extends AttributeException implements NonOmissibleExceptionInterface
{
public static $defaultTemplates = [
self::MODE_DEFAULT => [

View file

@ -11,7 +11,7 @@
namespace Respect\Validation\Exceptions;
class KeyNestedException extends AttributeException
class KeyNestedException extends AttributeException implements NonOmissibleExceptionInterface
{
public static $defaultTemplates = [
self::MODE_DEFAULT => [

View file

@ -11,7 +11,7 @@
namespace Respect\Validation\Exceptions;
class KeySetException extends GroupedValidationException
class KeySetException extends GroupedValidationException implements NonOmissibleExceptionInterface
{
const STRUCTURE = 2;

View file

@ -122,6 +122,26 @@ class NestedValidationException extends ValidationException implements IteratorA
return $recursiveIteratorIterator;
}
/**
* Returns weather an exception should be omitted or not.
*
* @param ExceptionInterface $exception
*
* @return bool
*/
private function isOmissible(ExceptionInterface $exception)
{
if (!$exception instanceof self) {
return false;
}
$relatedExceptions = $exception->getRelated();
$relatedExceptions->rewind();
$childException = $relatedExceptions->current();
return $relatedExceptions->count() === 1 && !$childException instanceof NonOmissibleExceptionInterface;
}
/**
* @return SplObjectStorage
*/
@ -136,9 +156,7 @@ class NestedValidationException extends ValidationException implements IteratorA
$lastDepthOriginal = 0;
$knownDepths = [];
foreach ($recursiveIteratorIterator as $childException) {
if ($childException instanceof self
&& $childException->getRelated()->count() > 0
&& $childException->getRelated()->count() < 2) {
if ($this->isOmissible($childException)) {
continue;
}

View file

@ -0,0 +1,16 @@
<?php
/*
* This file is part of Respect/Validation.
*
* (c) Alexandre Gomes Gaigalas <alexandre@gaigalas.net>
*
* For the full copyright and license information, please view the "LICENSE.md"
* file that was distributed with this source code.
*/
namespace Respect\Validation\Exceptions;
interface NonOmissibleExceptionInterface extends ExceptionInterface
{
}

View file

@ -0,0 +1,53 @@
--FILE--
<?php
require 'vendor/autoload.php';
use Respect\Validation\Exceptions\NestedValidationException;
use Respect\Validation\Validator as v;
try {
$array = [
'mysql' => [
'host' => 42,
'user' => 'user',
'password' => 'password',
'schema' => 'schema',
],
'postgresql' => [
'host' => 'host',
'user' => 42,
'password' => 'password',
'schema' => 'schema',
],
];
$object = json_decode(json_encode($array));
v::create()
->attribute(
'mysql',
v::create()
->attribute('host', v::stringType(), true)
->attribute('user', v::stringType(), true)
->attribute('password', v::stringType(), true)
->attribute('schema', v::stringType(), true),
true
)
->attribute(
'postgresql',
v::create()
->attribute('host', v::stringType(), true)
->attribute('user', v::stringType(), true)
->attribute('password', v::stringType(), true)
->attribute('schema', v::stringType(), true),
true
)
->setName('the given data')
->assert($object);
} catch (NestedValidationException $exception) {
echo $exception->getFullMessage().PHP_EOL;
}
?>
--EXPECTF--
- All of the required rules must pass for the given data
- These rules must pass for mysql
- host must be a string
- These rules must pass for postgresql
- user must be a string

View file

@ -0,0 +1,51 @@
--FILE--
<?php
require 'vendor/autoload.php';
use Respect\Validation\Exceptions\NestedValidationException;
use Respect\Validation\Validator as v;
try {
v::create()
->key(
'mysql',
v::create()
->key('host', v::stringType(), true)
->key('user', v::stringType(), true)
->key('password', v::stringType(), true)
->key('schema', v::stringType(), true),
true
)
->key(
'postgresql',
v::create()
->key('host', v::stringType(), true)
->key('user', v::stringType(), true)
->key('password', v::stringType(), true)
->key('schema', v::stringType(), true),
true
)
->setName('the given data')
->assert([
'mysql' => [
'host' => 42,
'user' => 'user',
'password' => 'password',
'schema' => 'schema',
],
'postgresql' => [
'host' => 'host',
'user' => 42,
'password' => 'password',
'schema' => 'schema',
],
]);
} catch (NestedValidationException $exception) {
echo $exception->getFullMessage().PHP_EOL;
}
?>
--EXPECTF--
- All of the required rules must pass for the given data
- These rules must pass for mysql
- host must be a string
- These rules must pass for postgresql
- user must be a string