[Validator] Fixed value-to-string conversion in constraint violations

This commit is contained in:
Bernhard Schussek 2014-04-10 17:39:39 +02:00
parent 75e8815566
commit 97243bcd02
32 changed files with 202 additions and 128 deletions

View File

@ -32,4 +32,67 @@ abstract class ConstraintValidator implements ConstraintValidatorInterface
{
$this->context = $context;
}
/**
* Returns a string representation of the type of the value.
*
* @param mixed $value
*
* @return string
*/
protected function valueToType($value)
{
return is_object($value) ? get_class($value) : gettype($value);
}
/**
* Returns a string representation of the value.
*
* @param mixed $value
*
* @return string
*/
protected function valueToString($value)
{
if ($value instanceof \DateTime) {
if (class_exists('IntlDateFormatter')) {
$locale = \Locale::getDefault();
$formatter = new \IntlDateFormatter($locale, \IntlDateFormatter::MEDIUM, \IntlDateFormatter::SHORT);
return $formatter->format($value);
}
return $value->format('Y-m-d H:i:s');
}
if (is_object($value)) {
return 'Object('.get_class($value).')';
}
if (is_array($value)) {
return 'Array';
}
if (is_string($value)) {
return '"'.$value.'"';
}
if (is_resource($value)) {
return sprintf('Resource(%s#%d)', get_resource_type($value), $value);
}
if (null === $value) {
return 'null';
}
if (false === $value) {
return 'false';
}
if (true === $value) {
return 'true';
}
return (string) $value;
}
}

View File

@ -96,9 +96,9 @@ class ConstraintViolation implements ConstraintViolationInterface
public function __toString()
{
if (is_object($this->root)) {
$class = get_class($this->root);
$class = 'Object('.get_class($this->root).')';
} elseif (is_array($this->root)) {
$class = "Array";
$class = 'Array';
} else {
$class = (string) $this->root;
}

View File

@ -39,34 +39,6 @@ abstract class AbstractComparisonValidator extends ConstraintValidator
}
}
/**
* Returns a string representation of the type of the value.
*
* @param mixed $value
*
* @return string
*/
private function valueToType($value)
{
return is_object($value) ? get_class($value) : gettype($value);
}
/**
* Returns a string representation of the value.
*
* @param mixed $value
*
* @return string
*/
private function valueToString($value)
{
if ($value instanceof \DateTime) {
return $value->format('Y-m-d H:i:s');
}
return var_export($value, true);
}
/**
* Compares the two given values to find if their relationship is valid
*

View File

@ -27,7 +27,9 @@ class BlankValidator extends ConstraintValidator
public function validate($value, Constraint $constraint)
{
if ('' !== $value && null !== $value) {
$this->context->addViolation($constraint->message, array('{{ value }}' => $value));
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $this->valueToString($value)
));
}
}
}

View File

@ -108,7 +108,9 @@ class CardSchemeValidator extends ConstraintValidator
}
if (!is_numeric($value)) {
$this->context->addViolation($constraint->message);
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $this->valueToString($value),
));
return;
}
@ -124,6 +126,8 @@ class CardSchemeValidator extends ConstraintValidator
}
}
$this->context->addViolation($constraint->message);
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $value,
));
}
}

View File

@ -59,25 +59,33 @@ class ChoiceValidator extends ConstraintValidator
if ($constraint->multiple) {
foreach ($value as $_value) {
if (!in_array($_value, $choices, $constraint->strict)) {
$this->context->addViolation($constraint->multipleMessage, array('{{ value }}' => $_value));
$this->context->addViolation($constraint->multipleMessage, array(
'{{ value }}' => $this->valueToString($_value),
));
}
}
$count = count($value);
if ($constraint->min !== null && $count < $constraint->min) {
$this->context->addViolation($constraint->minMessage, array('{{ limit }}' => $constraint->min), null, (int) $constraint->min);
$this->context->addViolation($constraint->minMessage, array(
'{{ limit }}' => $constraint->min
), null, (int) $constraint->min);
return;
}
if ($constraint->max !== null && $count > $constraint->max) {
$this->context->addViolation($constraint->maxMessage, array('{{ limit }}' => $constraint->max), null, (int) $constraint->max);
$this->context->addViolation($constraint->maxMessage, array(
'{{ limit }}' => $constraint->max
), null, (int) $constraint->max);
return;
}
} elseif (!in_array($value, $choices, $constraint->strict)) {
$this->context->addViolation($constraint->message, array('{{ value }}' => $value));
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $this->valueToString($value)
));
}
}
}

View File

@ -42,7 +42,9 @@ class CountryValidator extends ConstraintValidator
$countries = Intl::getRegionBundle()->getCountryNames();
if (!isset($countries[$value])) {
$this->context->addViolation($constraint->message, array('{{ value }}' => $value));
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $value,
));
}
}
}

View File

@ -42,7 +42,9 @@ class CurrencyValidator extends ConstraintValidator
$currencies = Intl::getCurrencyBundle()->getCurrencyNames();
if (!isset($currencies[$value])) {
$this->context->addViolation($constraint->message, array('{{ value }}' => $value));
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $value,
));
}
}
}

View File

@ -40,7 +40,9 @@ class DateValidator extends ConstraintValidator
$value = (string) $value;
if (!preg_match(static::PATTERN, $value, $matches) || !checkdate($matches[2], $matches[3], $matches[1])) {
$this->context->addViolation($constraint->message, array('{{ value }}' => $value));
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $value,
));
}
}
}

View File

@ -50,7 +50,9 @@ class EmailValidator extends ConstraintValidator
}
if (!$valid) {
$this->context->addViolation($constraint->message, array('{{ value }}' => $value));
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $value,
));
}
}

View File

@ -126,10 +126,10 @@ class FileValidator extends ConstraintValidator
if ($size > $limit) {
$this->context->addViolation($constraint->maxSizeMessage, array(
'{{ size }}' => $size,
'{{ limit }}' => $limit,
'{{ suffix }}' => $suffix,
'{{ file }}' => $path,
'{{ size }}' => $size,
'{{ limit }}' => $limit,
'{{ suffix }}' => $suffix,
'{{ file }}' => $path,
));
return;
@ -161,9 +161,9 @@ class FileValidator extends ConstraintValidator
if (false === $valid) {
$this->context->addViolation($constraint->mimeTypesMessage, array(
'{{ type }}' => '"'.$mime.'"',
'{{ types }}' => '"'.implode('", "', $mimeTypes) .'"',
'{{ file }}' => $path,
'{{ type }}' => '"'.$mime.'"',
'{{ types }}' => '"'.implode('", "', $mimeTypes) .'"',
'{{ file }}' => $path,
));
}
}

View File

@ -91,7 +91,9 @@ class IpValidator extends ConstraintValidator
}
if (!filter_var($value, FILTER_VALIDATE_IP, $flag)) {
$this->context->addViolation($constraint->message, array('{{ value }}' => $value));
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $value,
));
}
}
}

View File

@ -42,7 +42,9 @@ class LanguageValidator extends ConstraintValidator
$languages = Intl::getLanguageBundle()->getLanguageNames();
if (!isset($languages[$value])) {
$this->context->addViolation($constraint->message, array('{{ value }}' => $value));
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $value,
));
}
}
}

View File

@ -42,7 +42,9 @@ class LocaleValidator extends ConstraintValidator
$locales = Intl::getLocaleBundle()->getLocaleNames();
if (!isset($locales[$value])) {
$this->context->addViolation($constraint->message, array('{{ value }}' => $value));
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $value,
));
}
}
}

View File

@ -33,7 +33,9 @@ class NullValidator extends ConstraintValidator
$value = 'Array';
}
$this->context->addViolation($constraint->message, array('{{ value }}' => $value));
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $value,
));
}
}
}

View File

@ -30,7 +30,7 @@ class RangeValidator extends ConstraintValidator
if (!is_numeric($value)) {
$this->context->addViolation($constraint->invalidMessage, array(
'{{ value }}' => $value,
'{{ value }}' => $this->valueToString($value),
));
return;

View File

@ -41,7 +41,9 @@ class RegexValidator extends ConstraintValidator
$value = (string) $value;
if ($constraint->match xor preg_match($constraint->pattern, $value)) {
$this->context->addViolation($constraint->message, array('{{ value }}' => $value));
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $value,
));
}
}
}

View File

@ -40,7 +40,9 @@ class TimeValidator extends ConstraintValidator
$value = (string) $value;
if (!preg_match(static::PATTERN, $value)) {
$this->context->addViolation($constraint->message, array('{{ value }}' => $value));
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $value,
));
}
}
}

View File

@ -44,7 +44,7 @@ class TypeValidator extends ConstraintValidator
}
$this->context->addViolation($constraint->message, array(
'{{ value }}' => is_object($value) ? get_class($value) : (is_array($value) ? 'Array' : (string) $value),
'{{ value }}' => $this->valueToString($value),
'{{ type }}' => $constraint->type,
));
}

View File

@ -55,7 +55,9 @@ class UrlValidator extends ConstraintValidator
$pattern = sprintf(static::PATTERN, implode('|', $constraint->protocols));
if (!preg_match($pattern, $value)) {
$this->context->addViolation($constraint->message, array('{{ value }}' => $value));
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $value,
));
}
}
}

View File

@ -29,6 +29,8 @@ abstract class AbstractComparisonValidatorTestCase extends \PHPUnit_Framework_Te
->disableOriginalConstructor()
->getMock();
$this->validator->initialize($this->context);
\Locale::setDefault('en');
}
/**
@ -75,7 +77,7 @@ abstract class AbstractComparisonValidatorTestCase extends \PHPUnit_Framework_Te
* @param mixed $comparedValueString
* @param string $comparedValueType
*/
public function testInvalidComparisonToValue($dirtyValue, $comparedValue, $comparedValueString, $comparedValueType)
public function testInvalidComparisonToValue($dirtyValue, $dirtyValueAsString, $comparedValue, $comparedValueString, $comparedValueType)
{
$constraint = $this->createConstraint(array('value' => $comparedValue));
$constraint->message = 'Constraint Message';
@ -87,7 +89,7 @@ abstract class AbstractComparisonValidatorTestCase extends \PHPUnit_Framework_Te
$this->context->expects($this->once())
->method('addViolation')
->with('Constraint Message', array(
'{{ value }}' => $comparedValueString,
'{{ value }}' => $dirtyValueAsString,
'{{ compared_value }}' => $comparedValueString,
'{{ compared_value_type }}' => $comparedValueType
));

View File

@ -51,7 +51,7 @@ class BlankValidatorTest extends \PHPUnit_Framework_TestCase
/**
* @dataProvider getInvalidValues
*/
public function testInvalidValues($value)
public function testInvalidValues($value, $valueAsString)
{
$constraint = new Blank(array(
'message' => 'myMessage'
@ -60,7 +60,7 @@ class BlankValidatorTest extends \PHPUnit_Framework_TestCase
$this->context->expects($this->once())
->method('addViolation')
->with('myMessage', array(
'{{ value }}' => $value,
'{{ value }}' => $valueAsString,
));
$this->validator->validate($value, $constraint);
@ -69,10 +69,10 @@ class BlankValidatorTest extends \PHPUnit_Framework_TestCase
public function getInvalidValues()
{
return array(
array('foobar'),
array(0),
array(false),
array(1234),
array('foobar', '"foobar"'),
array(0, '0'),
array(false, 'false'),
array(1234, '1234'),
);
}
}

View File

@ -158,7 +158,7 @@ class ChoiceValidatorTest extends \PHPUnit_Framework_TestCase
$this->context->expects($this->once())
->method('addViolation')
->with('myMessage', array(
'{{ value }}' => 'baz',
'{{ value }}' => '"baz"',
), null, null);
$this->validator->validate('baz', $constraint);
@ -175,7 +175,7 @@ class ChoiceValidatorTest extends \PHPUnit_Framework_TestCase
$this->context->expects($this->once())
->method('addViolation')
->with('myMessage', array(
'{{ value }}' => 'baz',
'{{ value }}' => '"baz"',
));
$this->validator->validate(array('foo', 'baz'), $constraint);
@ -255,7 +255,7 @@ class ChoiceValidatorTest extends \PHPUnit_Framework_TestCase
$this->context->expects($this->once())
->method('addViolation')
->with('myMessage', array(
'{{ value }}' => '2',
'{{ value }}' => '"2"',
));
$this->validator->validate('2', $constraint);
@ -287,7 +287,7 @@ class ChoiceValidatorTest extends \PHPUnit_Framework_TestCase
$this->context->expects($this->once())
->method('addViolation')
->with('myMessage', array(
'{{ value }}' => '3',
'{{ value }}' => '"3"',
));
$this->validator->validate(array(2, '3'), $constraint);

View File

@ -49,9 +49,9 @@ class EqualToValidatorTest extends AbstractComparisonValidatorTestCase
public function provideInvalidComparisons()
{
return array(
array(1, 2, '2', 'integer'),
array('22', '333', "'333'", 'string'),
array(new \DateTime('2001-01-01'), new \DateTime('2000-01-01'), '2000-01-01 00:00:00', 'DateTime')
array(1, '1', 2, '2', 'integer'),
array('22', '"22"', '333', '"333"', 'string'),
array(new \DateTime('2001-01-01'), 'Jan 1, 2001 12:00 AM', new \DateTime('2000-01-01'), 'Jan 1, 2000 12:00 AM', 'DateTime')
);
}
}

View File

@ -51,9 +51,9 @@ class GreaterThanOrEqualValidatorTest extends AbstractComparisonValidatorTestCas
public function provideInvalidComparisons()
{
return array(
array(1, 2, '2', 'integer'),
array(new \DateTime('2000/01/01'), new \DateTime('2005/01/01'), '2005-01-01 00:00:00', 'DateTime'),
array('b', 'c', "'c'", 'string')
array(1, '1', 2, '2', 'integer'),
array(new \DateTime('2000/01/01'), 'Jan 1, 2000 12:00 AM', new \DateTime('2005/01/01'), 'Jan 1, 2005 12:00 AM', 'DateTime'),
array('b', '"b"', 'c', '"c"', 'string')
);
}
}

View File

@ -48,12 +48,12 @@ class GreaterThanValidatorTest extends AbstractComparisonValidatorTestCase
public function provideInvalidComparisons()
{
return array(
array(1, 2, '2', 'integer'),
array(2, 2, '2', 'integer'),
array(new \DateTime('2000/01/01'), new \DateTime('2005/01/01'), '2005-01-01 00:00:00', 'DateTime'),
array(new \DateTime('2000/01/01'), new \DateTime('2000/01/01'), '2000-01-01 00:00:00', 'DateTime'),
array('22', '333', "'333'", 'string'),
array('22', '22', "'22'", 'string')
array(1, '1', 2, '2', 'integer'),
array(2, '2', 2, '2', 'integer'),
array(new \DateTime('2000/01/01'), 'Jan 1, 2000 12:00 AM', new \DateTime('2005/01/01'), 'Jan 1, 2005 12:00 AM', 'DateTime'),
array(new \DateTime('2000/01/01'), 'Jan 1, 2000 12:00 AM', new \DateTime('2000/01/01'), 'Jan 1, 2000 12:00 AM', 'DateTime'),
array('22', '"22"', '333', '"333"', 'string'),
array('22', '"22"', '22', '"22"', 'string')
);
}
}

View File

@ -50,11 +50,11 @@ class IdenticalToValidatorTest extends AbstractComparisonValidatorTestCase
public function provideInvalidComparisons()
{
return array(
array(1, 2, '2', 'integer'),
array(2, '2', "'2'", 'string'),
array('22', '333', "'333'", 'string'),
array(new \DateTime('2001-01-01'), new \DateTime('2001-01-01'), '2001-01-01 00:00:00', 'DateTime'),
array(new \DateTime('2001-01-01'), new \DateTime('1999-01-01'), '1999-01-01 00:00:00', 'DateTime')
array(1, '1', 2, '2', 'integer'),
array(2, '2', '2', '"2"', 'string'),
array('22', '"22"', '333', '"333"', 'string'),
array(new \DateTime('2001-01-01'), 'Jan 1, 2001 12:00 AM', new \DateTime('2001-01-01'), 'Jan 1, 2001 12:00 AM', 'DateTime'),
array(new \DateTime('2001-01-01'), 'Jan 1, 2001 12:00 AM', new \DateTime('1999-01-01'), 'Jan 1, 1999 12:00 AM', 'DateTime')
);
}
}

View File

@ -51,9 +51,9 @@ class LessThanOrEqualValidatorTest extends AbstractComparisonValidatorTestCase
public function provideInvalidComparisons()
{
return array(
array(2, 1, '1', 'integer'),
array(new \DateTime('2010-01-01'), new \DateTime('2000-01-01'), '2000-01-01 00:00:00', 'DateTime'),
array('c', 'b', "'b'", 'string')
array(2, '2', 1, '1', 'integer'),
array(new \DateTime('2010-01-01'), 'Jan 1, 2010 12:00 AM', new \DateTime('2000-01-01'), 'Jan 1, 2000 12:00 AM', 'DateTime'),
array('c', '"c"', 'b', '"b"', 'string')
);
}
}

View File

@ -48,11 +48,11 @@ class LessThanValidatorTest extends AbstractComparisonValidatorTestCase
public function provideInvalidComparisons()
{
return array(
array(3, 2, '2', 'integer'),
array(2, 2, '2', 'integer'),
array(new \DateTime('2010-01-01'), new \DateTime('2000-01-01'), '2000-01-01 00:00:00', 'DateTime'),
array(new \DateTime('2000-01-01'), new \DateTime('2000-01-01'), '2000-01-01 00:00:00', 'DateTime'),
array('333', '22', "'22'", 'string'),
array(3, '3', 2, '2', 'integer'),
array(2, '2', 2, '2', 'integer'),
array(new \DateTime('2010-01-01'), 'Jan 1, 2010 12:00 AM', new \DateTime('2000-01-01'), 'Jan 1, 2000 12:00 AM', 'DateTime'),
array(new \DateTime('2000-01-01'), 'Jan 1, 2000 12:00 AM', new \DateTime('2000-01-01'), 'Jan 1, 2000 12:00 AM', 'DateTime'),
array('333', '"333"', '22', '"22"', 'string'),
);
}
}

View File

@ -48,10 +48,10 @@ class NotEqualToValidatorTest extends AbstractComparisonValidatorTestCase
public function provideInvalidComparisons()
{
return array(
array(3, 3, '3', 'integer'),
array('2', 2, '2', 'integer'),
array('a', 'a', "'a'", 'string'),
array(new \DateTime('2000-01-01'), new \DateTime('2000-01-01'), '2000-01-01 00:00:00', 'DateTime')
array(3, '3', 3, '3', 'integer'),
array('2', '"2"', 2, '2', 'integer'),
array('a', '"a"', 'a', '"a"', 'string'),
array(new \DateTime('2000-01-01'), 'Jan 1, 2000 12:00 AM', new \DateTime('2000-01-01'), 'Jan 1, 2000 12:00 AM', 'DateTime')
);
}
}

View File

@ -52,9 +52,9 @@ class NotIdenticalToValidatorTest extends AbstractComparisonValidatorTestCase
$date = new \DateTime('2000-01-01');
return array(
array(3, 3, '3', 'integer'),
array('a', 'a', "'a'", 'string'),
array($date, $date, '2000-01-01 00:00:00', 'DateTime')
array(3, '3', 3, '3', 'integer'),
array('a', '"a"', 'a', '"a"', 'string'),
array($date, 'Jan 1, 2000 12:00 AM', $date, 'Jan 1, 2000 12:00 AM', 'DateTime')
);
}
}

View File

@ -132,36 +132,37 @@ class TypeValidatorTest extends \PHPUnit_Framework_TestCase
{
$object = new \stdClass();
$file = $this->createFile();
$fileAsString = 'Resource(stream#'.intval($file).')';
return array(
array('foobar', 'numeric', 'foobar'),
array('foobar', 'boolean', 'foobar'),
array('0', 'integer', '0'),
array('1.5', 'float', '1.5'),
array('foobar', 'numeric', '"foobar"'),
array('foobar', 'boolean', '"foobar"'),
array('0', 'integer', '"0"'),
array('1.5', 'float', '"1.5"'),
array(12345, 'string', '12345'),
array($object, 'boolean', 'stdClass'),
array($object, 'numeric', 'stdClass'),
array($object, 'integer', 'stdClass'),
array($object, 'float', 'stdClass'),
array($object, 'string', 'stdClass'),
array($object, 'resource', 'stdClass'),
array($file, 'boolean', (string) $file),
array($file, 'numeric', (string) $file),
array($file, 'integer', (string) $file),
array($file, 'float', (string) $file),
array($file, 'string', (string) $file),
array($file, 'object', (string) $file),
array('12a34', 'digit', '12a34'),
array('1a#23', 'alnum', '1a#23'),
array('abcd1', 'alpha', 'abcd1'),
array("\nabc", 'cntrl', "\nabc"),
array("abc\n", 'graph', "abc\n"),
array('abCDE', 'lower', 'abCDE'),
array('ABcde', 'upper', 'ABcde'),
array("\nabc", 'print', "\nabc"),
array('abc&$!', 'punct', 'abc&$!'),
array("\nabc", 'space', "\nabc"),
array('AR1012', 'xdigit', 'AR1012'),
array($object, 'boolean', 'Object(stdClass)'),
array($object, 'numeric', 'Object(stdClass)'),
array($object, 'integer', 'Object(stdClass)'),
array($object, 'float', 'Object(stdClass)'),
array($object, 'string', 'Object(stdClass)'),
array($object, 'resource', 'Object(stdClass)'),
array($file, 'boolean', $fileAsString),
array($file, 'numeric', $fileAsString),
array($file, 'integer', $fileAsString),
array($file, 'float', $fileAsString),
array($file, 'string', $fileAsString),
array($file, 'object', $fileAsString),
array('12a34', 'digit', '"12a34"'),
array('1a#23', 'alnum', '"1a#23"'),
array('abcd1', 'alpha', '"abcd1"'),
array("\nabc", 'cntrl', "\"\nabc\""),
array("abc\n", 'graph', "\"abc\n\""),
array('abCDE', 'lower', '"abCDE"'),
array('ABcde', 'upper', '"ABcde"'),
array("\nabc", 'print', "\"\nabc\""),
array('abc&$!', 'punct', '"abc&$!"'),
array("\nabc", 'space', "\"\nabc\""),
array('AR1012', 'xdigit', '"AR1012"'),
);
}