2010-12-02 22:04:10 +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-02 22:04:10 +01:00
|
|
|
namespace Respect\Validation\Exceptions;
|
|
|
|
|
2011-02-08 23:10:58 +01:00
|
|
|
use DateTime;
|
2015-08-26 19:30:45 +02:00
|
|
|
use Exception;
|
2011-02-07 11:52:18 +01:00
|
|
|
use InvalidArgumentException;
|
2015-08-26 19:30:45 +02:00
|
|
|
use Traversable;
|
2010-12-02 22:04:10 +01:00
|
|
|
|
2015-10-23 12:46:12 +02:00
|
|
|
class ValidationException extends InvalidArgumentException implements ExceptionInterface
|
2010-12-02 22:04:10 +01:00
|
|
|
{
|
2011-04-10 01:34:21 +02:00
|
|
|
const MODE_DEFAULT = 1;
|
|
|
|
const MODE_NEGATIVE = 2;
|
2011-02-07 02:12:41 +01:00
|
|
|
const STANDARD = 0;
|
2015-10-18 03:44:47 +02:00
|
|
|
public static $defaultTemplates = [
|
|
|
|
self::MODE_DEFAULT => [
|
2015-01-08 03:15:35 +01:00
|
|
|
self::STANDARD => 'Data validation failed for %s',
|
2015-10-18 03:44:47 +02:00
|
|
|
],
|
|
|
|
self::MODE_NEGATIVE => [
|
2015-01-08 03:15:35 +01:00
|
|
|
self::STANDARD => 'Data validation failed for %s',
|
2015-10-18 03:44:47 +02:00
|
|
|
],
|
|
|
|
];
|
2015-08-26 19:30:45 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @var int
|
|
|
|
*/
|
|
|
|
private static $maxDepthStringify = 5;
|
|
|
|
|
2015-08-08 20:36:31 +02:00
|
|
|
/**
|
2015-08-26 19:30:45 +02:00
|
|
|
* @var int
|
2015-08-08 20:36:31 +02:00
|
|
|
*/
|
2015-08-26 19:30:45 +02:00
|
|
|
private static $maxCountStringify = 10;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
private static $maxReplacementStringify = '...';
|
|
|
|
|
2011-02-18 04:08:46 +01:00
|
|
|
protected $id = 'validation';
|
2011-04-10 01:34:21 +02:00
|
|
|
protected $mode = self::MODE_DEFAULT;
|
2011-02-18 04:08:46 +01:00
|
|
|
protected $name = '';
|
2011-02-06 23:21:15 +01:00
|
|
|
protected $template = '';
|
2015-10-18 03:44:47 +02:00
|
|
|
protected $params = [];
|
2015-09-11 07:31:55 +02:00
|
|
|
private $customTemplate = false;
|
2010-12-02 22:04:10 +01:00
|
|
|
|
2015-10-18 03:44:47 +02:00
|
|
|
public static function format($template, array $vars = [])
|
2011-02-06 23:21:15 +01:00
|
|
|
{
|
2011-02-10 21:49:48 +01:00
|
|
|
return preg_replace_callback(
|
|
|
|
'/{{(\w+)}}/',
|
2015-01-08 03:15:35 +01:00
|
|
|
function ($match) use ($vars) {
|
2015-08-26 19:30:45 +02:00
|
|
|
if (!isset($vars[$match[1]])) {
|
|
|
|
return $match[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
$value = $vars[$match[1]];
|
2017-03-14 10:20:36 +01:00
|
|
|
if ('name' == $match[1] && is_string($value)) {
|
2015-08-26 19:30:45 +02:00
|
|
|
return $value;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ValidationException::stringify($value);
|
2013-01-14 22:55:03 +01:00
|
|
|
},
|
|
|
|
$template
|
2011-02-10 21:49:48 +01:00
|
|
|
);
|
2011-02-06 23:21:15 +01:00
|
|
|
}
|
|
|
|
|
2015-08-26 19:30:45 +02:00
|
|
|
/**
|
|
|
|
* @param mixed $value
|
|
|
|
* @param int $depth
|
|
|
|
*
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public static function stringify($value, $depth = 1)
|
2011-02-08 23:10:58 +01:00
|
|
|
{
|
2015-08-26 19:30:45 +02:00
|
|
|
if ($depth >= self::$maxDepthStringify) {
|
|
|
|
return self::$maxReplacementStringify;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_array($value)) {
|
|
|
|
return static::stringifyArray($value, $depth);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_object($value)) {
|
|
|
|
return static::stringifyObject($value, $depth);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_resource($value)) {
|
|
|
|
return sprintf('`[resource] (%s)`', get_resource_type($value));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_float($value)) {
|
|
|
|
if (is_infinite($value)) {
|
|
|
|
return ($value > 0 ? '' : '-').'INF';
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_nan($value)) {
|
|
|
|
return 'NaN';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-30 10:39:23 +01:00
|
|
|
return @json_encode($value, (JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)) ?: $value;
|
2011-02-08 23:10:58 +01:00
|
|
|
}
|
|
|
|
|
2015-08-08 20:36:31 +02:00
|
|
|
/**
|
|
|
|
* @param array $value
|
|
|
|
* @param int $depth
|
|
|
|
*
|
|
|
|
* @return string
|
|
|
|
*/
|
2015-08-26 19:30:45 +02:00
|
|
|
public static function stringifyArray(array $value, $depth = 1)
|
|
|
|
{
|
|
|
|
$nextDepth = ($depth + 1);
|
|
|
|
if ($nextDepth >= self::$maxDepthStringify) {
|
|
|
|
return self::$maxReplacementStringify;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (empty($value)) {
|
|
|
|
return '{ }';
|
|
|
|
}
|
|
|
|
|
|
|
|
$total = count($value);
|
|
|
|
$string = '';
|
|
|
|
$current = 0;
|
|
|
|
foreach ($value as $childKey => $childValue) {
|
|
|
|
if ($current++ >= self::$maxCountStringify) {
|
|
|
|
$string .= self::$maxReplacementStringify;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!is_int($childKey)) {
|
|
|
|
$string .= sprintf('%s: ', static::stringify($childKey, $nextDepth));
|
|
|
|
}
|
|
|
|
|
|
|
|
$string .= static::stringify($childValue, $nextDepth);
|
|
|
|
|
|
|
|
if ($current !== $total) {
|
|
|
|
$string .= ', ';
|
2015-08-08 20:36:31 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-26 19:30:45 +02:00
|
|
|
return sprintf('{ %s }', $string);
|
2015-08-08 20:36:31 +02:00
|
|
|
}
|
|
|
|
|
2015-08-26 19:30:45 +02:00
|
|
|
/**
|
|
|
|
* @param mixed $value
|
|
|
|
* @param int $depth
|
|
|
|
*
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public static function stringifyObject($value, $depth = 2)
|
2011-02-18 04:08:46 +01:00
|
|
|
{
|
2015-08-26 19:30:45 +02:00
|
|
|
$nextDepth = $depth + 1;
|
|
|
|
|
|
|
|
if ($value instanceof DateTime) {
|
|
|
|
return sprintf('"%s"', $value->format('Y-m-d H:i:s'));
|
|
|
|
}
|
|
|
|
|
|
|
|
$class = get_class($value);
|
|
|
|
|
|
|
|
if ($value instanceof Traversable) {
|
|
|
|
return sprintf('`[traversable] (%s: %s)`', $class, static::stringify(iterator_to_array($value), $nextDepth));
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($value instanceof Exception) {
|
2015-10-18 03:44:47 +02:00
|
|
|
$properties = [
|
2015-08-26 19:30:45 +02:00
|
|
|
'message' => $value->getMessage(),
|
|
|
|
'code' => $value->getCode(),
|
|
|
|
'file' => $value->getFile().':'.$value->getLine(),
|
2015-10-18 03:44:47 +02:00
|
|
|
];
|
2015-08-26 19:30:45 +02:00
|
|
|
|
|
|
|
return sprintf('`[exception] (%s: %s)`', $class, static::stringify($properties, $nextDepth));
|
|
|
|
}
|
|
|
|
|
2013-01-14 22:55:03 +01:00
|
|
|
if (method_exists($value, '__toString')) {
|
2015-08-26 19:30:45 +02:00
|
|
|
return static::stringify($value->__toString(), $nextDepth);
|
2013-01-14 22:55:03 +01:00
|
|
|
}
|
2015-08-26 19:30:45 +02:00
|
|
|
|
|
|
|
$properties = static::stringify(get_object_vars($value), $nextDepth);
|
|
|
|
|
|
|
|
return sprintf('`[object] (%s: %s)`', $class, str_replace('`', '', $properties));
|
2011-02-18 04:08:46 +01:00
|
|
|
}
|
|
|
|
|
2011-02-07 11:52:18 +01:00
|
|
|
public function __toString()
|
2010-12-02 22:04:10 +01:00
|
|
|
{
|
2011-02-07 11:52:18 +01:00
|
|
|
return $this->getMainMessage();
|
|
|
|
}
|
|
|
|
|
|
|
|
public function chooseTemplate()
|
2011-02-05 18:32:21 +01:00
|
|
|
{
|
2011-04-10 01:34:21 +02:00
|
|
|
return key(static::$defaultTemplates[$this->mode]);
|
2011-02-05 18:32:21 +01:00
|
|
|
}
|
|
|
|
|
2015-10-18 03:44:47 +02:00
|
|
|
public function configure($name, array $params = [])
|
2011-02-05 18:32:21 +01:00
|
|
|
{
|
2011-02-10 21:49:48 +01:00
|
|
|
$this->setName($name);
|
2011-02-20 17:59:53 +01:00
|
|
|
$this->setId($this->guessId());
|
2015-10-21 08:14:11 +02:00
|
|
|
$this->setParams($params);
|
2013-01-14 22:55:03 +01:00
|
|
|
|
2011-02-07 11:52:18 +01:00
|
|
|
return $this;
|
2011-02-05 18:32:21 +01:00
|
|
|
}
|
|
|
|
|
2011-02-08 23:10:58 +01:00
|
|
|
public function getName()
|
|
|
|
{
|
2011-02-10 21:49:48 +01:00
|
|
|
return $this->name;
|
2011-02-08 23:10:58 +01:00
|
|
|
}
|
|
|
|
|
2011-02-06 23:21:15 +01:00
|
|
|
public function getId()
|
2011-02-02 03:28:02 +01:00
|
|
|
{
|
2011-02-06 23:21:15 +01:00
|
|
|
return $this->id;
|
2011-02-02 03:28:02 +01:00
|
|
|
}
|
2011-02-18 04:08:46 +01:00
|
|
|
|
2011-01-31 01:17:06 +01:00
|
|
|
public function getMainMessage()
|
2010-12-02 22:04:10 +01:00
|
|
|
{
|
2011-02-10 21:49:48 +01:00
|
|
|
$vars = $this->getParams();
|
|
|
|
$vars['name'] = $this->getName();
|
2011-12-27 03:43:22 +01:00
|
|
|
$template = $this->getTemplate();
|
2013-01-14 22:55:03 +01:00
|
|
|
if (isset($vars['translator']) && is_callable($vars['translator'])) {
|
2011-12-27 03:43:22 +01:00
|
|
|
$template = call_user_func($vars['translator'], $template);
|
2013-01-14 22:55:03 +01:00
|
|
|
}
|
|
|
|
|
2011-12-27 03:43:22 +01:00
|
|
|
return static::format($template, $vars);
|
2011-01-31 01:17:06 +01:00
|
|
|
}
|
|
|
|
|
2011-02-10 21:49:48 +01:00
|
|
|
public function getParam($name)
|
2011-01-31 01:17:06 +01:00
|
|
|
{
|
2011-02-10 21:49:48 +01:00
|
|
|
return $this->hasParam($name) ? $this->params[$name] : false;
|
2010-12-02 22:04:10 +01:00
|
|
|
}
|
|
|
|
|
2011-02-10 21:49:48 +01:00
|
|
|
public function getParams()
|
2010-12-02 22:04:10 +01:00
|
|
|
{
|
2011-02-10 21:49:48 +01:00
|
|
|
return $this->params;
|
2010-12-02 22:04:10 +01:00
|
|
|
}
|
|
|
|
|
2011-01-31 01:17:06 +01:00
|
|
|
public function getTemplate()
|
|
|
|
{
|
2013-01-14 22:55:03 +01:00
|
|
|
if (!empty($this->template)) {
|
2011-02-06 23:21:15 +01:00
|
|
|
return $this->template;
|
2013-01-14 22:55:03 +01:00
|
|
|
}
|
2016-10-30 10:39:23 +01:00
|
|
|
|
|
|
|
return $this->template = $this->buildTemplate();
|
2011-02-20 17:59:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public function hasParam($name)
|
|
|
|
{
|
|
|
|
return isset($this->params[$name]);
|
2011-02-07 18:21:58 +01:00
|
|
|
}
|
|
|
|
|
2011-02-07 11:52:18 +01:00
|
|
|
public function setId($id)
|
2010-12-02 22:04:10 +01:00
|
|
|
{
|
2011-02-07 11:52:18 +01:00
|
|
|
$this->id = $id;
|
2013-01-14 22:55:03 +01:00
|
|
|
|
2011-02-07 11:52:18 +01:00
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2011-02-08 23:10:58 +01:00
|
|
|
public function setName($name)
|
|
|
|
{
|
2015-08-26 19:30:45 +02:00
|
|
|
$this->name = $name;
|
2013-01-14 22:55:03 +01:00
|
|
|
|
2011-02-08 23:10:58 +01:00
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2011-04-10 01:34:21 +02:00
|
|
|
public function setMode($mode)
|
|
|
|
{
|
|
|
|
$this->mode = $mode;
|
|
|
|
$this->template = $this->buildTemplate();
|
2013-01-14 22:55:03 +01:00
|
|
|
|
2015-10-21 08:14:11 +02:00
|
|
|
$this->buildMessage();
|
|
|
|
|
2011-04-10 01:34:21 +02:00
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2011-02-20 19:03:09 +01:00
|
|
|
public function setParam($key, $value)
|
|
|
|
{
|
2015-08-26 19:30:45 +02:00
|
|
|
$this->params[$key] = $value;
|
2013-01-14 22:55:03 +01:00
|
|
|
|
2015-10-21 08:14:11 +02:00
|
|
|
$this->buildMessage();
|
|
|
|
|
2011-04-10 01:34:21 +02:00
|
|
|
return $this;
|
2011-02-20 19:03:09 +01:00
|
|
|
}
|
|
|
|
|
2011-02-10 21:49:48 +01:00
|
|
|
public function setParams(array $params)
|
2011-02-07 11:52:18 +01:00
|
|
|
{
|
2013-01-14 22:55:03 +01:00
|
|
|
foreach ($params as $key => $value) {
|
2015-10-21 08:14:11 +02:00
|
|
|
$this->params[$key] = $value;
|
2013-01-14 22:55:03 +01:00
|
|
|
}
|
|
|
|
|
2015-10-21 08:14:11 +02:00
|
|
|
$this->buildMessage();
|
|
|
|
|
2011-04-10 01:34:21 +02:00
|
|
|
return $this;
|
2011-02-07 11:52:18 +01:00
|
|
|
}
|
|
|
|
|
2015-09-11 07:31:55 +02:00
|
|
|
public function hasCustomTemplate()
|
|
|
|
{
|
2016-10-30 10:39:23 +01:00
|
|
|
return true === $this->customTemplate;
|
2015-09-11 07:31:55 +02:00
|
|
|
}
|
|
|
|
|
2011-02-07 11:52:18 +01:00
|
|
|
public function setTemplate($template)
|
|
|
|
{
|
2015-09-11 07:31:55 +02:00
|
|
|
$this->customTemplate = true;
|
2018-01-02 21:24:06 +01:00
|
|
|
if (isset(static::$defaultTemplates[$this->mode][$template])) {
|
|
|
|
$template = static::$defaultTemplates[$this->mode][$template];
|
|
|
|
}
|
2011-02-07 11:52:18 +01:00
|
|
|
$this->template = $template;
|
2013-01-14 22:55:03 +01:00
|
|
|
|
2015-10-22 04:30:30 +02:00
|
|
|
$this->buildMessage();
|
|
|
|
|
2011-04-10 01:34:21 +02:00
|
|
|
return $this;
|
2011-02-07 11:52:18 +01:00
|
|
|
}
|
|
|
|
|
2015-10-21 08:14:11 +02:00
|
|
|
private function buildMessage()
|
|
|
|
{
|
|
|
|
$this->message = $this->getMainMessage();
|
|
|
|
}
|
|
|
|
|
2011-02-20 17:59:53 +01:00
|
|
|
protected function buildTemplate()
|
|
|
|
{
|
|
|
|
$templateKey = $this->chooseTemplate();
|
2013-01-14 22:55:03 +01:00
|
|
|
|
2011-04-10 01:34:21 +02:00
|
|
|
return static::$defaultTemplates[$this->mode][$templateKey];
|
2011-02-20 17:59:53 +01:00
|
|
|
}
|
|
|
|
|
2016-09-17 20:21:05 +02:00
|
|
|
public function guessId()
|
2011-02-07 11:52:18 +01:00
|
|
|
{
|
2015-01-08 03:15:35 +01:00
|
|
|
if (!empty($this->id) && $this->id != 'validation') {
|
2011-04-12 20:26:03 +02:00
|
|
|
return $this->id;
|
2015-01-08 03:15:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
$pieces = explode('\\', get_called_class());
|
|
|
|
$exceptionClassShortName = end($pieces);
|
|
|
|
$ruleClassShortName = str_replace('Exception', '', $exceptionClassShortName);
|
|
|
|
$ruleName = lcfirst($ruleClassShortName);
|
|
|
|
|
|
|
|
return $ruleName;
|
2011-02-07 11:52:18 +01:00
|
|
|
}
|
2011-02-10 21:49:48 +01:00
|
|
|
}
|