2010-12-03 22:36:46 +01:00
|
|
|
<?php
|
2015-06-08 16:47:14 +02:00
|
|
|
|
2015-06-08 17:09:25 +02:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2010-12-03 22:36:46 +01:00
|
|
|
namespace Respect\Validation\Exceptions;
|
2011-02-18 04:08:46 +01:00
|
|
|
|
2015-10-23 12:33:37 +02:00
|
|
|
use IteratorAggregate;
|
2011-02-10 21:49:48 +01:00
|
|
|
use RecursiveIteratorIterator;
|
2015-10-22 04:30:30 +02:00
|
|
|
use SplObjectStorage;
|
2010-12-03 22:36:46 +01:00
|
|
|
|
2015-10-23 12:33:37 +02:00
|
|
|
class NestedValidationException extends ValidationException implements IteratorAggregate
|
2010-12-03 22:36:46 +01:00
|
|
|
{
|
2015-10-22 04:30:30 +02:00
|
|
|
/**
|
|
|
|
* @var SplObjectStorage
|
|
|
|
*/
|
|
|
|
private $exceptions = [];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param ValidationException $exception
|
|
|
|
*
|
|
|
|
* @return self
|
|
|
|
*/
|
|
|
|
public function addRelated(ValidationException $exception)
|
2011-02-10 21:49:48 +01:00
|
|
|
{
|
2015-10-22 04:30:30 +02:00
|
|
|
$this->getRelated()->attach($exception);
|
2013-01-14 22:55:03 +01:00
|
|
|
|
2011-02-20 17:59:53 +01:00
|
|
|
return $this;
|
2011-02-10 21:49:48 +01:00
|
|
|
}
|
|
|
|
|
2016-09-17 20:21:05 +02:00
|
|
|
/**
|
2016-10-30 10:39:23 +01:00
|
|
|
* @param string $path
|
2016-09-17 20:21:05 +02:00
|
|
|
* @param ValidationException $exception
|
|
|
|
*
|
|
|
|
* @return ValidationException
|
|
|
|
*/
|
|
|
|
private function getExceptionForPath($path, ValidationException $exception)
|
|
|
|
{
|
|
|
|
if ($path === $exception->guessId()) {
|
|
|
|
return $exception;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!$exception instanceof self) {
|
|
|
|
return $exception;
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach ($exception as $subException) {
|
|
|
|
return $subException;
|
|
|
|
}
|
2016-09-19 18:22:39 +02:00
|
|
|
|
|
|
|
return $exception;
|
2016-09-17 20:21:05 +02:00
|
|
|
}
|
|
|
|
|
2015-10-22 04:30:30 +02:00
|
|
|
/**
|
|
|
|
* @param array $paths
|
|
|
|
*
|
2017-01-23 12:42:47 +01:00
|
|
|
* @return string[]
|
2015-10-22 04:30:30 +02:00
|
|
|
*/
|
2011-04-29 21:00:39 +02:00
|
|
|
public function findMessages(array $paths)
|
2011-03-31 00:06:59 +02:00
|
|
|
{
|
2015-10-18 03:44:47 +02:00
|
|
|
$messages = [];
|
2011-03-31 00:06:59 +02:00
|
|
|
|
2011-04-29 21:00:39 +02:00
|
|
|
foreach ($paths as $key => $value) {
|
|
|
|
$numericKey = is_numeric($key);
|
|
|
|
$path = $numericKey ? $value : $key;
|
|
|
|
|
2016-09-17 20:49:33 +02:00
|
|
|
if (!($exception = $this->getRelatedByName($path))) {
|
|
|
|
$exception = $this->findRelated($path);
|
|
|
|
}
|
2011-04-29 21:00:39 +02:00
|
|
|
|
2016-09-17 20:21:05 +02:00
|
|
|
$path = str_replace('.', '_', $path);
|
|
|
|
|
|
|
|
if (!$exception) {
|
|
|
|
$messages[$path] = '';
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
$exception = $this->getExceptionForPath($path, $exception);
|
|
|
|
if (!$numericKey) {
|
2015-10-22 04:30:30 +02:00
|
|
|
$exception->setTemplate($value);
|
2013-01-14 22:55:03 +01:00
|
|
|
}
|
2011-04-29 21:00:39 +02:00
|
|
|
|
2016-09-17 20:21:05 +02:00
|
|
|
$messages[$path] = $exception->getMainMessage();
|
2011-03-31 00:06:59 +02:00
|
|
|
}
|
2013-01-14 22:55:03 +01:00
|
|
|
|
2011-03-31 00:06:59 +02:00
|
|
|
return $messages;
|
|
|
|
}
|
|
|
|
|
2015-10-22 04:30:30 +02:00
|
|
|
/**
|
|
|
|
* @return Exception
|
|
|
|
*/
|
2011-04-29 21:00:39 +02:00
|
|
|
public function findRelated($path)
|
2011-02-18 04:08:46 +01:00
|
|
|
{
|
2011-02-20 17:59:53 +01:00
|
|
|
$target = $this;
|
2015-10-22 04:30:30 +02:00
|
|
|
$pieces = explode('.', $path);
|
2011-02-18 04:08:46 +01:00
|
|
|
|
2015-10-22 04:30:30 +02:00
|
|
|
while (!empty($pieces) && $target) {
|
|
|
|
$piece = array_shift($pieces);
|
|
|
|
$target = $target->getRelatedByName($piece);
|
2013-01-14 22:55:03 +01:00
|
|
|
}
|
|
|
|
|
2011-02-20 17:59:53 +01:00
|
|
|
return $target;
|
2011-02-10 21:49:48 +01:00
|
|
|
}
|
2011-02-18 04:08:46 +01:00
|
|
|
|
2015-10-22 04:30:30 +02:00
|
|
|
/**
|
|
|
|
* @return RecursiveIteratorIterator
|
|
|
|
*/
|
|
|
|
private function getRecursiveIterator()
|
2011-02-10 21:49:48 +01:00
|
|
|
{
|
2015-10-22 04:30:30 +02:00
|
|
|
$exceptionIterator = new RecursiveExceptionIterator($this);
|
|
|
|
$recursiveIteratorIterator = new RecursiveIteratorIterator(
|
|
|
|
$exceptionIterator,
|
|
|
|
RecursiveIteratorIterator::SELF_FIRST
|
|
|
|
);
|
2011-02-20 17:59:53 +01:00
|
|
|
|
2015-10-22 04:30:30 +02:00
|
|
|
return $recursiveIteratorIterator;
|
2011-02-10 21:49:48 +01:00
|
|
|
}
|
|
|
|
|
2017-03-02 22:04:15 +01:00
|
|
|
/**
|
|
|
|
* 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;
|
|
|
|
}
|
|
|
|
|
2015-10-22 04:30:30 +02:00
|
|
|
/**
|
|
|
|
* @return SplObjectStorage
|
|
|
|
*/
|
|
|
|
public function getIterator()
|
2015-09-11 00:10:18 +02:00
|
|
|
{
|
2015-10-22 04:30:30 +02:00
|
|
|
$childrenExceptions = new SplObjectStorage();
|
|
|
|
|
|
|
|
$recursiveIteratorIterator = $this->getRecursiveIterator();
|
|
|
|
$exceptionIterator = $recursiveIteratorIterator->getInnerIterator();
|
|
|
|
|
|
|
|
$lastDepth = 0;
|
|
|
|
$lastDepthOriginal = 0;
|
|
|
|
$knownDepths = [];
|
|
|
|
foreach ($recursiveIteratorIterator as $childException) {
|
2017-03-02 22:04:15 +01:00
|
|
|
if ($this->isOmissible($childException)) {
|
2015-09-11 00:10:18 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2015-10-22 04:30:30 +02:00
|
|
|
$currentDepth = $lastDepth;
|
|
|
|
$currentDepthOriginal = $recursiveIteratorIterator->getDepth() + 1;
|
|
|
|
|
|
|
|
if (isset($knownDepths[$currentDepthOriginal])) {
|
|
|
|
$currentDepth = $knownDepths[$currentDepthOriginal];
|
|
|
|
} elseif ($currentDepthOriginal > $lastDepthOriginal
|
|
|
|
&& ($this->hasCustomTemplate() || $exceptionIterator->count() != 1)) {
|
|
|
|
++$currentDepth;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isset($knownDepths[$currentDepthOriginal])) {
|
|
|
|
$knownDepths[$currentDepthOriginal] = $currentDepth;
|
|
|
|
}
|
|
|
|
|
|
|
|
$lastDepth = $currentDepth;
|
|
|
|
$lastDepthOriginal = $currentDepthOriginal;
|
|
|
|
|
|
|
|
$childrenExceptions->attach(
|
|
|
|
$childException,
|
|
|
|
[
|
|
|
|
'depth' => $currentDepth,
|
|
|
|
'depth_original' => $currentDepthOriginal,
|
|
|
|
'previous_depth' => $lastDepth,
|
|
|
|
'previous_depth_original' => $lastDepthOriginal,
|
|
|
|
]
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $childrenExceptions;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
public function getMessages()
|
|
|
|
{
|
|
|
|
$messages = [$this->getMessage()];
|
|
|
|
foreach ($this as $exception) {
|
2015-09-11 00:10:18 +02:00
|
|
|
$messages[] = $exception->getMessage();
|
|
|
|
}
|
|
|
|
|
2015-10-22 04:30:30 +02:00
|
|
|
if (count($messages) > 1) {
|
|
|
|
array_shift($messages);
|
|
|
|
}
|
|
|
|
|
2015-09-11 00:10:18 +02:00
|
|
|
return $messages;
|
|
|
|
}
|
|
|
|
|
2015-10-22 04:30:30 +02:00
|
|
|
/**
|
|
|
|
* @return string
|
|
|
|
*/
|
2011-02-20 17:59:53 +01:00
|
|
|
public function getFullMessage()
|
2011-02-10 21:49:48 +01:00
|
|
|
{
|
2015-10-22 04:30:30 +02:00
|
|
|
$marker = '-';
|
|
|
|
$messages = [];
|
|
|
|
$exceptions = $this->getIterator();
|
|
|
|
|
|
|
|
if ($this->hasCustomTemplate() || count($exceptions) != 1) {
|
|
|
|
$messages[] = sprintf('%s %s', $marker, $this->getMessage());
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach ($exceptions as $exception) {
|
|
|
|
$depth = $exceptions[$exception]['depth'];
|
|
|
|
$prefix = str_repeat(' ', $depth * 2);
|
|
|
|
$messages[] = sprintf('%s%s %s', $prefix, $marker, $exception->getMessage());
|
2013-01-14 22:55:03 +01:00
|
|
|
}
|
|
|
|
|
2015-10-22 04:30:30 +02:00
|
|
|
return implode(PHP_EOL, $messages);
|
2011-02-20 17:59:53 +01:00
|
|
|
}
|
|
|
|
|
2015-10-22 04:30:30 +02:00
|
|
|
/**
|
|
|
|
* @return SplObjectStorage
|
|
|
|
*/
|
|
|
|
public function getRelated()
|
2011-02-20 17:59:53 +01:00
|
|
|
{
|
2015-10-22 04:30:30 +02:00
|
|
|
if (!$this->exceptions instanceof SplObjectStorage) {
|
|
|
|
$this->exceptions = new SplObjectStorage();
|
2013-01-14 22:55:03 +01:00
|
|
|
}
|
2015-10-22 04:30:30 +02:00
|
|
|
|
|
|
|
return $this->exceptions;
|
2011-02-10 21:49:48 +01:00
|
|
|
}
|
|
|
|
|
2015-10-22 04:30:30 +02:00
|
|
|
/**
|
|
|
|
* @param string $name
|
|
|
|
* @param mixed $value
|
|
|
|
*
|
|
|
|
* @return self
|
|
|
|
*/
|
2015-10-07 15:13:50 +02:00
|
|
|
public function setParam($name, $value)
|
|
|
|
{
|
|
|
|
if ('translator' === $name) {
|
2015-10-22 04:30:30 +02:00
|
|
|
foreach ($this->getRelated() as $exception) {
|
|
|
|
$exception->setParam($name, $value);
|
2015-10-07 15:13:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-21 08:14:11 +02:00
|
|
|
parent::setParam($name, $value);
|
|
|
|
|
2015-10-07 15:13:50 +02:00
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2015-10-22 04:30:30 +02:00
|
|
|
/**
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
private function isRelated($name, ValidationException $exception)
|
|
|
|
{
|
2016-10-30 10:39:23 +01:00
|
|
|
return $exception->getId() === $name || $exception->getName() === $name;
|
2015-10-22 04:30:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return ValidationException
|
|
|
|
*/
|
2011-02-10 21:49:48 +01:00
|
|
|
public function getRelatedByName($name)
|
2010-12-03 22:36:46 +01:00
|
|
|
{
|
2015-10-22 04:30:30 +02:00
|
|
|
if ($this->isRelated($name, $this)) {
|
|
|
|
return $this;
|
2013-01-14 22:55:03 +01:00
|
|
|
}
|
2011-02-20 17:59:53 +01:00
|
|
|
|
2015-10-22 04:30:30 +02:00
|
|
|
foreach ($this->getRecursiveIterator() as $exception) {
|
|
|
|
if ($this->isRelated($name, $exception)) {
|
|
|
|
return $exception;
|
|
|
|
}
|
|
|
|
}
|
2010-12-03 22:36:46 +01:00
|
|
|
}
|
|
|
|
|
2015-10-22 04:30:30 +02:00
|
|
|
/**
|
|
|
|
* @param array $exceptions
|
|
|
|
*
|
|
|
|
* @return self
|
|
|
|
*/
|
|
|
|
public function setRelated(array $exceptions)
|
2011-02-10 21:49:48 +01:00
|
|
|
{
|
2015-10-22 04:30:30 +02:00
|
|
|
foreach ($exceptions as $exception) {
|
|
|
|
$this->addRelated($exception);
|
2013-01-14 22:55:03 +01:00
|
|
|
}
|
2011-02-19 20:47:34 +01:00
|
|
|
|
2011-02-20 17:59:53 +01:00
|
|
|
return $this;
|
2011-02-02 03:28:02 +01:00
|
|
|
}
|
2011-02-10 21:49:48 +01:00
|
|
|
}
|