bug #12016 [Validator] Added ConstraintValidator::buildViolation() helper for BC with the 2.4 API (webmozart)

This PR was merged into the 2.5 branch.

Discussion
----------

[Validator] Added ConstraintValidator::buildViolation() helper for BC with the 2.4 API

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | -
| License       | MIT
| Doc PR        | -

This PR adds a `buildViolation()` helper method to the base `ConstraintValidator` to remove the API checks (2.4 vs. 2.5) from the constraint validator implementations. Once the 2.4 API is removed, this helper method will be removed as well.

**Todos**

- [x] Backport changes from #12021

Commits
-------

6b0c24a [Validator] Added ConstraintValidator::buildViolation() helper for BC with 2.4 API
This commit is contained in:
Fabien Potencier 2014-09-25 16:01:10 +02:00
commit d7615e70d2
53 changed files with 902 additions and 631 deletions

View File

@ -262,12 +262,19 @@ class UniqueEntityValidatorTest extends AbstractConstraintValidatorTest
$this->validator->validate($entity1, $constraint);
$this->assertViolation('myMessage', array(), 'property.path.name', 'Foo');
$this->buildViolation('myMessage')
->atPath('property.path.name')
->setInvalidValue('Foo')
->assertRaised();
$this->context->getViolations()->remove(0);
$this->validator->validate($entity2, $constraint);
$this->assertViolation('myMessage', array(), 'property.path.name', 'Foo');
$this->buildViolation('myMessage')
->atPath('property.path.name')
->setInvalidValue('Foo')
->assertRaised();
}
public function testValidateUniquenessUsingCustomRepositoryMethod()

View File

@ -13,7 +13,6 @@ namespace Symfony\Bridge\Doctrine\Validator\Constraints;
use Doctrine\Common\Persistence\ManagerRegistry;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
use Symfony\Component\Validator\ConstraintValidator;
@ -137,14 +136,9 @@ class UniqueEntityValidator extends ConstraintValidator
$errorPath = null !== $constraint->errorPath ? $constraint->errorPath : $fields[0];
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->atPath($errorPath)
->setInvalidValue($criteria[$fields[0]])
->addViolation();
} else {
// 2.4 API
$this->context->addViolationAt($errorPath, $constraint->message, array(), $criteria[$fields[0]]);
}
$this->buildViolation($constraint->message)
->atPath($errorPath)
->setInvalidValue($criteria[$fields[0]])
->addViolation();
}
}

View File

@ -99,40 +99,20 @@ class FormValidator extends ConstraintValidator
? (string) $form->getViewData()
: gettype($form->getViewData());
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($config->getOption('invalid_message'))
->setParameters(array_replace(array('{{ value }}' => $clientDataAsString), $config->getOption('invalid_message_parameters')))
->setInvalidValue($form->getViewData())
->setCode(Form::ERR_INVALID)
->addViolation();
} else {
// 2.4 API
$this->context->addViolation(
$config->getOption('invalid_message'),
array_replace(array('{{ value }}' => $clientDataAsString), $config->getOption('invalid_message_parameters')),
$form->getViewData(),
null,
Form::ERR_INVALID
);
}
$this->buildViolation($config->getOption('invalid_message'))
->setParameters(array_replace(array('{{ value }}' => $clientDataAsString), $config->getOption('invalid_message_parameters')))
->setInvalidValue($form->getViewData())
->setCode(Form::ERR_INVALID)
->addViolation();
}
}
// Mark the form with an error if it contains extra fields
if (count($form->getExtraData()) > 0) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($config->getOption('extra_fields_message'))
->setParameter('{{ extra_fields }}', implode('", "', array_keys($form->getExtraData())))
->setInvalidValue($form->getExtraData())
->addViolation();
} else {
// 2.4 API
$this->context->addViolation(
$config->getOption('extra_fields_message'),
array('{{ extra_fields }}' => implode('", "', array_keys($form->getExtraData()))),
$form->getExtraData()
);
}
$this->buildViolation($config->getOption('extra_fields_message'))
->setParameter('{{ extra_fields }}', implode('", "', array_keys($form->getExtraData())))
->setInvalidValue($form->getExtraData())
->addViolation();
}
}

View File

@ -92,7 +92,8 @@ class UserPasswordValidatorTest extends AbstractConstraintValidatorTest
$this->validator->validate('secret', $constraint);
$this->assertViolation('myMessage');
$this->buildViolation('myMessage')
->assertRaised();
}
/**

View File

@ -11,6 +11,10 @@
namespace Symfony\Component\Validator;
use Symfony\Component\Validator\Context\ExecutionContextInterface as ExecutionContextInterface2Dot5;
use Symfony\Component\Validator\Violation\ConstraintViolationBuilderInterface;
use Symfony\Component\Validator\Violation\LegacyConstraintViolationBuilder;
/**
* Base class for constraint validators
*
@ -24,14 +28,14 @@ abstract class ConstraintValidator implements ConstraintValidatorInterface
* Whether to format {@link \DateTime} objects as RFC-3339 dates
* ("Y-m-d H:i:s").
*
* @var integer
* @var int
*/
const PRETTY_DATE = 1;
/**
* Whether to cast objects with a "__toString()" method to strings.
*
* @var integer
* @var int
*/
const OBJECT_TO_STRING = 2;
@ -48,6 +52,47 @@ abstract class ConstraintValidator implements ConstraintValidatorInterface
$this->context = $context;
}
/**
* Wrapper for {@link ExecutionContextInterface::buildViolation} that
* supports the 2.4 context API.
*
* @param string $message The violation message
* @param array $parameters The message parameters
*
* @return ConstraintViolationBuilderInterface The violation builder
*
* @deprecated This method will be removed in Symfony 3.0.
*/
protected function buildViolation($message, array $parameters = array())
{
if ($this->context instanceof ExecutionContextInterface2Dot5) {
return $this->context->buildViolation($message, $parameters);
}
return new LegacyConstraintViolationBuilder($this->context, $message, $parameters);
}
/**
* Wrapper for {@link ExecutionContextInterface::buildViolation} that
* supports the 2.4 context API.
*
* @param ExecutionContextInterface $context The context to use
* @param string $message The violation message
* @param array $parameters The message parameters
*
* @return ConstraintViolationBuilderInterface The violation builder
*
* @deprecated This method will be removed in Symfony 3.0.
*/
protected function buildViolationInContext(ExecutionContextInterface $context, $message, array $parameters = array())
{
if ($context instanceof ExecutionContextInterface2Dot5) {
return $context->buildViolation($message, $parameters);
}
return new LegacyConstraintViolationBuilder($context, $message, $parameters);
}
/**
* Returns a string representation of the type of the value.
*
@ -82,7 +127,7 @@ abstract class ConstraintValidator implements ConstraintValidatorInterface
* confused by the violation message.
*
* @param mixed $value The value to format as string
* @param integer $format A bitwise combination of the format
* @param int $format A bitwise combination of the format
* constants in this class
*
* @return string The string representation of the passed value
@ -142,7 +187,7 @@ abstract class ConstraintValidator implements ConstraintValidatorInterface
* {@link formatValue()}. The values are then concatenated with commas.
*
* @param array $values A list of values
* @param integer $format A bitwise combination of the format
* @param int $format A bitwise combination of the format
* constants in this class
*
* @return string The string representation of the value list

View File

@ -19,6 +19,7 @@ use Symfony\Component\Validator\Exception\UnexpectedTypeException;
* Provides a base class for the validation of property comparisons.
*
* @author Daniel Holmes <daniel@danielholmes.org>
* @author Bernhard Schussek <bschussek@gmail.com>
*/
abstract class AbstractComparisonValidator extends ConstraintValidator
{
@ -35,12 +36,14 @@ abstract class AbstractComparisonValidator extends ConstraintValidator
return;
}
if (!$this->compareValues($value, $constraint->value)) {
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $this->formatValue($value, self::OBJECT_TO_STRING | self::PRETTY_DATE),
'{{ compared_value }}' => $this->formatValue($constraint->value, self::OBJECT_TO_STRING | self::PRETTY_DATE),
'{{ compared_value_type }}' => $this->formatTypeOf($constraint->value),
));
$comparedValue = $constraint->value;
if (!$this->compareValues($value, $comparedValue)) {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value, self::OBJECT_TO_STRING | self::PRETTY_DATE))
->setParameter('{{ compared_value }}', $this->formatValue($comparedValue, self::OBJECT_TO_STRING | self::PRETTY_DATE))
->setParameter('{{ compared_value_type }}', $this->formatTypeOf($comparedValue))
->addViolation();
}
}

View File

@ -32,9 +32,9 @@ class BlankValidator extends ConstraintValidator
}
if ('' !== $value && null !== $value) {
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $this->formatValue($value),
));
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
}
}

View File

@ -18,6 +18,8 @@ use Symfony\Component\Validator\Constraint;
*
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Tim Nagel <t.nagel@infinite.net.au>
*/
class CardScheme extends Constraint
{

View File

@ -18,9 +18,11 @@ use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* Validates that a card number belongs to a specified scheme.
*
* @author Tim Nagel <t.nagel@infinite.net.au>
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @see http://en.wikipedia.org/wiki/Bank_card_number
* @see http://www.regular-expressions.info/creditcard.html
* @author Tim Nagel <t.nagel@infinite.net.au>
*/
class CardSchemeValidator extends ConstraintValidator
{
@ -113,9 +115,9 @@ class CardSchemeValidator extends ConstraintValidator
}
if (!is_numeric($value)) {
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $this->formatValue($value),
));
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
return;
}
@ -131,8 +133,8 @@ class CardSchemeValidator extends ConstraintValidator
}
}
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $this->formatValue($value),
));
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
}

View File

@ -13,7 +13,6 @@ namespace Symfony\Component\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
@ -64,63 +63,38 @@ class ChoiceValidator extends ConstraintValidator
if ($constraint->multiple) {
foreach ($value as $_value) {
if (!in_array($_value, $choices, $constraint->strict)) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->multipleMessage)
->setParameter('{{ value }}', $this->formatValue($_value))
->addViolation();
} else {
// 2.4 API
$this->context->addViolation($constraint->multipleMessage, array(
'{{ value }}' => $this->formatValue($_value),
));
}
$this->buildViolation($constraint->multipleMessage)
->setParameter('{{ value }}', $this->formatValue($_value))
->setInvalidValue($_value)
->addViolation();
return;
}
}
$count = count($value);
if ($constraint->min !== null && $count < $constraint->min) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->minMessage)
->setParameter('{{ limit }}', $constraint->min)
->setPlural((int) $constraint->min)
->addViolation();
} else {
// 2.4 API
$this->context->addViolation($constraint->minMessage, array(
'{{ limit }}' => $constraint->min,
), $value, (int) $constraint->min);
}
$this->buildViolation($constraint->minMessage)
->setParameter('{{ limit }}', $constraint->min)
->setPlural((int) $constraint->min)
->addViolation();
return;
}
if ($constraint->max !== null && $count > $constraint->max) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->maxMessage)
->setParameter('{{ limit }}', $constraint->max)
->setPlural((int) $constraint->max)
->addViolation();
} else {
// 2.4 API
$this->context->addViolation($constraint->maxMessage, array(
'{{ limit }}' => $constraint->max,
), $value, (int) $constraint->max);
}
$this->buildViolation($constraint->maxMessage)
->setParameter('{{ limit }}', $constraint->max)
->setPlural((int) $constraint->max)
->addViolation();
return;
}
} elseif (!in_array($value, $choices, $constraint->strict)) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
} else {
// 2.4 API
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $this->formatValue($value),
));
}
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
}
}

View File

@ -70,36 +70,22 @@ class CollectionValidator extends ConstraintValidator
}
}
} elseif (!$fieldConstraint instanceof Optional && !$constraint->allowMissingFields) {
if ($context instanceof ExecutionContextInterface) {
$context->buildViolation($constraint->missingFieldsMessage)
->atPath('['.$field.']')
->setParameter('{{ field }}', $this->formatValue($field))
->setInvalidValue(null)
->addViolation();
} else {
// 2.4 API
$context->addViolationAt('['.$field.']', $constraint->missingFieldsMessage, array(
'{{ field }}' => $this->formatValue($field),
), null);
}
$this->buildViolationInContext($context, $constraint->missingFieldsMessage)
->atPath('['.$field.']')
->setParameter('{{ field }}', $this->formatValue($field))
->setInvalidValue(null)
->addViolation();
}
}
if (!$constraint->allowExtraFields) {
foreach ($value as $field => $fieldValue) {
if (!isset($constraint->fields[$field])) {
if ($context instanceof ExecutionContextInterface) {
$context->buildViolation($constraint->extraFieldsMessage)
->atPath('['.$field.']')
->setParameter('{{ field }}', $this->formatValue($field))
->setInvalidValue($fieldValue)
->addViolation();
} else {
// 2.4 API
$context->addViolationAt('['.$field.']', $constraint->extraFieldsMessage, array(
'{{ field }}' => $this->formatValue($field),
), $fieldValue);
}
$this->buildViolationInContext($context, $constraint->extraFieldsMessage)
->atPath('['.$field.']')
->setParameter('{{ field }}', $this->formatValue($field))
->setInvalidValue($fieldValue)
->addViolation();
}
}
}

View File

@ -13,7 +13,6 @@ namespace Symfony\Component\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
@ -36,59 +35,24 @@ class CountValidator extends ConstraintValidator
$count = count($value);
if ($constraint->min == $constraint->max && $count != $constraint->min) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->exactMessage)
->setParameter('{{ count }}', $count)
->setParameter('{{ limit }}', $constraint->min)
->setInvalidValue($value)
->setPlural((int) $constraint->min)
->addViolation();
} else {
// 2.4 API
$this->context->addViolation($constraint->exactMessage, array(
'{{ count }}' => $count,
'{{ limit }}' => $constraint->min,
), $value, (int) $constraint->min);
}
return;
}
if (null !== $constraint->max && $count > $constraint->max) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->maxMessage)
->setParameter('{{ count }}', $count)
->setParameter('{{ limit }}', $constraint->max)
->setInvalidValue($value)
->setPlural((int) $constraint->max)
->addViolation();
} else {
// 2.4 API
$this->context->addViolation($constraint->maxMessage, array(
'{{ count }}' => $count,
'{{ limit }}' => $constraint->max,
), $value, (int) $constraint->max);
}
$this->buildViolation($constraint->min == $constraint->max ? $constraint->exactMessage : $constraint->maxMessage)
->setParameter('{{ count }}', $count)
->setParameter('{{ limit }}', $constraint->max)
->setInvalidValue($value)
->setPlural((int) $constraint->max)
->addViolation();
return;
}
if (null !== $constraint->min && $count < $constraint->min) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->minMessage)
->setParameter('{{ count }}', $count)
->setParameter('{{ limit }}', $constraint->min)
->setInvalidValue($value)
->setPlural((int) $constraint->min)
->addViolation();
} else {
// 2.4 API
$this->context->addViolation($constraint->minMessage, array(
'{{ count }}' => $count,
'{{ limit }}' => $constraint->min,
), $value, (int) $constraint->min);
}
$this->buildViolation($constraint->min == $constraint->max ? $constraint->exactMessage : $constraint->minMessage)
->setParameter('{{ count }}', $count)
->setParameter('{{ limit }}', $constraint->min)
->setInvalidValue($value)
->setPlural((int) $constraint->min)
->addViolation();
}
}
}

View File

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

View File

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

View File

@ -21,7 +21,7 @@ use Symfony\Component\Validator\Exception\UnexpectedTypeException;
*/
class DateTimeValidator extends DateValidator
{
const PATTERN = '/^(\d{4})-(\d{2})-(\d{2}) (0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/';
const PATTERN = '/^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/';
/**
* {@inheritdoc}
@ -42,10 +42,24 @@ class DateTimeValidator extends DateValidator
$value = (string) $value;
if (!preg_match(static::PATTERN, $value, $matches) || !checkdate($matches[2], $matches[3], $matches[1])) {
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $this->formatValue($value),
));
if (!preg_match(static::PATTERN, $value, $matches)) {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
return;
}
if (!DateValidator::checkDate($matches[1], $matches[2], $matches[3])) {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
if (!TimeValidator::checkTime($matches[4], $matches[5], $matches[6])) {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
}
}

View File

@ -24,6 +24,22 @@ class DateValidator extends ConstraintValidator
{
const PATTERN = '/^(\d{4})-(\d{2})-(\d{2})$/';
/**
* Checks whether a date is valid.
*
* @param int $year The year
* @param int $month The month
* @param int $day The day
*
* @return bool Whether the date is valid
*
* @internal
*/
public static function checkDate($year, $month, $day)
{
return checkdate($month, $day, $year);
}
/**
* {@inheritdoc}
*/
@ -43,10 +59,18 @@ 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 }}' => $this->formatValue($value),
));
if (!preg_match(static::PATTERN, $value, $matches)) {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
return;
}
if (!self::checkDate($matches[1], $matches[2], $matches[3])) {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
}
}

View File

@ -13,8 +13,8 @@ namespace Symfony\Component\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\RuntimeException;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Egulias\EmailValidator\EmailValidator as StrictEmailValidator;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
@ -53,34 +53,50 @@ class EmailValidator extends ConstraintValidator
}
$value = (string) $value;
if (null === $constraint->strict) {
$constraint->strict = $this->isStrict;
}
if ($constraint->strict && class_exists('\Egulias\EmailValidator\EmailValidator')) {
$strictValidator = new StrictEmailValidator();
$valid = $strictValidator->isValid($value, false, true);
} elseif ($constraint->strict === true) {
throw new \RuntimeException('Strict email validation requires egulias/email-validator');
} else {
$valid = preg_match('/.+\@.+\..+/', $value);
}
if ($valid) {
$host = substr($value, strpos($value, '@') + 1);
// Check for host DNS resource records
if ($valid && $constraint->checkMX) {
$valid = $this->checkMX($host);
} elseif ($valid && $constraint->checkHost) {
$valid = $this->checkHost($host);
if ($constraint->strict) {
if (!class_exists('\Egulias\EmailValidator\EmailValidator')) {
throw new RuntimeException('Strict email validation requires egulias/email-validator');
}
$strictValidator = new \Egulias\EmailValidator\EmailValidator();
if (!$strictValidator->isValid($value, false, true)) {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
return;
}
} elseif (!preg_match('/.+\@.+\..+/', $value)) {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
return;
}
if (!$valid) {
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $this->formatValue($value),
));
$host = substr($value, strpos($value, '@') + 1);
// Check for host DNS resource records
if ($constraint->checkMX) {
if (!$this->checkMX($host)) {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
return;
}
if ($constraint->checkHost && !$this->checkHost($host)) {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
}

View File

@ -89,7 +89,9 @@ class ExpressionValidator extends ConstraintValidator
}
if (!$this->getExpressionLanguage()->evaluate($constraint->expression, $variables)) {
$this->context->addViolation($constraint->message);
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
}

View File

@ -35,8 +35,8 @@ class FalseValidator extends ConstraintValidator
return;
}
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $this->formatValue($value),
));
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
}

View File

@ -66,38 +66,46 @@ class FileValidator extends ConstraintValidator
$limitInBytes = UploadedFile::getMaxFilesize();
}
$this->context->addViolation($constraint->uploadIniSizeErrorMessage, array(
'{{ limit }}' => $limitInBytes,
'{{ suffix }}' => 'bytes',
));
$this->buildViolation($constraint->uploadIniSizeErrorMessage)
->setParameter('{{ limit }}', $limitInBytes)
->setParameter('{{ suffix }}', 'bytes')
->addViolation();
return;
case UPLOAD_ERR_FORM_SIZE:
$this->context->addViolation($constraint->uploadFormSizeErrorMessage);
$this->buildViolation($constraint->uploadFormSizeErrorMessage)
->addViolation();
return;
case UPLOAD_ERR_PARTIAL:
$this->context->addViolation($constraint->uploadPartialErrorMessage);
$this->buildViolation($constraint->uploadPartialErrorMessage)
->addViolation();
return;
case UPLOAD_ERR_NO_FILE:
$this->context->addViolation($constraint->uploadNoFileErrorMessage);
$this->buildViolation($constraint->uploadNoFileErrorMessage)
->addViolation();
return;
case UPLOAD_ERR_NO_TMP_DIR:
$this->context->addViolation($constraint->uploadNoTmpDirErrorMessage);
$this->buildViolation($constraint->uploadNoTmpDirErrorMessage)
->addViolation();
return;
case UPLOAD_ERR_CANT_WRITE:
$this->context->addViolation($constraint->uploadCantWriteErrorMessage);
$this->buildViolation($constraint->uploadCantWriteErrorMessage)
->addViolation();
return;
case UPLOAD_ERR_EXTENSION:
$this->context->addViolation($constraint->uploadExtensionErrorMessage);
$this->buildViolation($constraint->uploadExtensionErrorMessage)
->addViolation();
return;
default:
$this->context->addViolation($constraint->uploadErrorMessage);
$this->buildViolation($constraint->uploadErrorMessage)
->setCode($value->getError())
->addViolation();
return;
}
@ -110,17 +118,17 @@ class FileValidator extends ConstraintValidator
$path = $value instanceof FileObject ? $value->getPathname() : (string) $value;
if (!is_file($path)) {
$this->context->addViolation($constraint->notFoundMessage, array(
'{{ file }}' => $this->formatValue($path),
));
$this->buildViolation($constraint->notFoundMessage)
->setParameter('{{ file }}', $this->formatValue($path))
->addViolation();
return;
}
if (!is_readable($path)) {
$this->context->addViolation($constraint->notReadableMessage, array(
'{{ file }}' => $this->formatValue($path),
));
$this->buildViolation($constraint->notReadableMessage)
->setParameter('{{ file }}', $this->formatValue($path))
->addViolation();
return;
}
@ -161,12 +169,12 @@ class FileValidator extends ConstraintValidator
$sizeAsString = (string) round($sizeInBytes / $coef, 2);
}
$this->context->addViolation($constraint->maxSizeMessage, array(
'{{ size }}' => $sizeAsString,
'{{ limit }}' => $limitAsString,
'{{ suffix }}' => self::$suffices[$coef],
'{{ file }}' => $this->formatValue($path),
));
$this->buildViolation($constraint->maxSizeMessage)
->setParameter('{{ file }}', $this->formatValue($path))
->setParameter('{{ size }}', $sizeAsString)
->setParameter('{{ limit }}', $limitAsString)
->setParameter('{{ suffix }}', self::$suffices[$coef])
->addViolation();
return;
}
@ -179,29 +187,24 @@ class FileValidator extends ConstraintValidator
$mimeTypes = (array) $constraint->mimeTypes;
$mime = $value->getMimeType();
$valid = false;
foreach ($mimeTypes as $mimeType) {
if ($mimeType === $mime) {
$valid = true;
break;
return;
}
if ($discrete = strstr($mimeType, '/*', true)) {
if (strstr($mime, '/', true) === $discrete) {
$valid = true;
break;
return;
}
}
}
if (false === $valid) {
$this->context->addViolation($constraint->mimeTypesMessage, array(
'{{ type }}' => $this->formatValue($mime),
'{{ types }}' => $this->formatValues($mimeTypes),
'{{ file }}' => $this->formatValue($path),
));
}
$this->buildViolation($constraint->mimeTypesMessage)
->setParameter('{{ file }}', $this->formatValue($path))
->setParameter('{{ type }}', $this->formatValue($mime))
->setParameter('{{ types }}', $this->formatValues($mimeTypes))
->addViolation();
}
}

View File

@ -16,6 +16,9 @@ use Symfony\Component\Validator\Constraint;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Manuel Reinhard <manu@sprain.ch>
* @author Michael Schummel
*/
class Iban extends Constraint
{

View File

@ -45,21 +45,38 @@ class IbanValidator extends ConstraintValidator
// Remove spaces
$canonicalized = str_replace(' ', '', $value);
// The IBAN must have at least 4 characters...
if (strlen($canonicalized) < 4) {
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $this->formatValue($value),
));
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
return;
}
// The IBAN must have at least 4 characters, start with a country
// code and contain only digits and (uppercase) characters
if (strlen($canonicalized) < 4 || !ctype_upper($canonicalized{0})
|| !ctype_upper($canonicalized{1}) || !ctype_alnum($canonicalized)) {
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $this->formatValue($value),
));
// ...start with a country code...
if (!ctype_alpha($canonicalized{0}) || !ctype_alpha($canonicalized{1})) {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
return;
}
// ...contain only digits and characters...
if (!ctype_alnum($canonicalized)) {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
return;
}
// ...and contain uppercase characters only
if ($canonicalized !== strtoupper($canonicalized)) {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
return;
}
@ -76,23 +93,13 @@ class IbanValidator extends ConstraintValidator
// -> 0076 2011 6238 5295 7 121893
$checkSum = $this->toBigInt($canonicalized);
if (false === $checkSum) {
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $this->formatValue($value),
));
return;
}
// Do a modulo-97 operation on the large integer
// We cannot use PHP's modulo operator, so we calculate the
// modulo step-wisely instead
if (1 !== $this->bigModulo97($checkSum)) {
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $this->formatValue($value),
));
return;
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
}
@ -109,11 +116,6 @@ class IbanValidator extends ConstraintValidator
continue;
}
// Disallow lowercase characters
if (ctype_lower($char)) {
return false;
}
// Simply append digits
$bigInt .= $char;
}

View File

@ -15,6 +15,8 @@ namespace Symfony\Component\Validator\Constraints;
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Benjamin Dulau <benjamin.dulau@gmail.com>
*
* @api
*/
class Image extends File
@ -30,6 +32,7 @@ class Image extends File
public $allowLandscape = true;
public $allowPortrait = true;
// The constant for a wrong MIME type is taken from the parent class.
public $mimeTypesMessage = 'This file is not a valid image.';
public $sizeNotDetectedMessage = 'The size of the image could not be detected.';
public $maxWidthMessage = 'The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.';

View File

@ -20,6 +20,7 @@ use Symfony\Component\Validator\Exception\UnexpectedTypeException;
* against minWidth, maxWidth, minHeight and maxHeight constraints
*
* @author Benjamin Dulau <benjamin.dulau@gmail.com>
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class ImageValidator extends FileValidator
{
@ -50,8 +51,10 @@ class ImageValidator extends FileValidator
}
$size = @getimagesize($value);
if (empty($size) || ($size[0] === 0) || ($size[1] === 0)) {
$this->context->addViolation($constraint->sizeNotDetectedMessage);
$this->buildViolation($constraint->sizeNotDetectedMessage)
->addViolation();
return;
}
@ -65,10 +68,10 @@ class ImageValidator extends FileValidator
}
if ($width < $constraint->minWidth) {
$this->context->addViolation($constraint->minWidthMessage, array(
'{{ width }}' => $width,
'{{ min_width }}' => $constraint->minWidth,
));
$this->buildViolation($constraint->minWidthMessage)
->setParameter('{{ width }}', $width)
->setParameter('{{ min_width }}', $constraint->minWidth)
->addViolation();
return;
}
@ -80,10 +83,10 @@ class ImageValidator extends FileValidator
}
if ($width > $constraint->maxWidth) {
$this->context->addViolation($constraint->maxWidthMessage, array(
'{{ width }}' => $width,
'{{ max_width }}' => $constraint->maxWidth,
));
$this->buildViolation($constraint->maxWidthMessage)
->setParameter('{{ width }}', $width)
->setParameter('{{ max_width }}', $constraint->maxWidth)
->addViolation();
return;
}
@ -95,10 +98,10 @@ class ImageValidator extends FileValidator
}
if ($height < $constraint->minHeight) {
$this->context->addViolation($constraint->minHeightMessage, array(
'{{ height }}' => $height,
'{{ min_height }}' => $constraint->minHeight,
));
$this->buildViolation($constraint->minHeightMessage)
->setParameter('{{ height }}', $height)
->setParameter('{{ min_height }}', $constraint->minHeight)
->addViolation();
return;
}
@ -110,10 +113,10 @@ class ImageValidator extends FileValidator
}
if ($height > $constraint->maxHeight) {
$this->context->addViolation($constraint->maxHeightMessage, array(
'{{ height }}' => $height,
'{{ max_height }}' => $constraint->maxHeight,
));
$this->buildViolation($constraint->maxHeightMessage)
->setParameter('{{ height }}', $height)
->setParameter('{{ max_height }}', $constraint->maxHeight)
->addViolation();
}
}
@ -125,10 +128,10 @@ class ImageValidator extends FileValidator
}
if ($ratio < $constraint->minRatio) {
$this->context->addViolation($constraint->minRatioMessage, array(
'{{ ratio }}' => $ratio,
'{{ min_ratio }}' => $constraint->minRatio,
));
$this->buildViolation($constraint->minRatioMessage)
->setParameter('{{ ratio }}', $ratio)
->setParameter('{{ min_ratio }}', $constraint->minRatio)
->addViolation();
}
}
@ -138,32 +141,32 @@ class ImageValidator extends FileValidator
}
if ($ratio > $constraint->maxRatio) {
$this->context->addViolation($constraint->maxRatioMessage, array(
'{{ ratio }}' => $ratio,
'{{ max_ratio }}' => $constraint->maxRatio,
));
$this->buildViolation($constraint->maxRatioMessage)
->setParameter('{{ ratio }}', $ratio)
->setParameter('{{ max_ratio }}', $constraint->maxRatio)
->addViolation();
}
}
if (!$constraint->allowSquare && $width == $height) {
$this->context->addViolation($constraint->allowSquareMessage, array(
'{{ width }}' => $width,
'{{ height }}' => $height,
));
$this->buildViolation($constraint->allowSquareMessage)
->setParameter('{{ width }}', $width)
->setParameter('{{ height }}', $height)
->addViolation();
}
if (!$constraint->allowLandscape && $width > $height) {
$this->context->addViolation($constraint->allowLandscapeMessage, array(
'{{ width }}' => $width,
'{{ height }}' => $height,
));
$this->buildViolation($constraint->allowLandscapeMessage)
->setParameter('{{ width }}', $width)
->setParameter('{{ height }}', $height)
->addViolation();
}
if (!$constraint->allowPortrait && $width < $height) {
$this->context->addViolation($constraint->allowPortraitMessage, array(
'{{ width }}' => $width,
'{{ height }}' => $height,
));
$this->buildViolation($constraint->allowPortraitMessage)
->setParameter('{{ width }}', $width)
->setParameter('{{ height }}', $height)
->addViolation();
}
}
}

View File

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

View File

@ -54,30 +54,45 @@ class IsbnValidator extends ConstraintValidator
}
}
if ('isbn10' === $constraint->type && !$this->validateIsbn10($canonical)) {
$this->context->addViolation($this->getMessage($constraint, 'isbn10'), array(
'{{ value }}' => $this->formatValue($value),
));
} elseif ('isbn13' === $constraint->type && !$this->validateIsbn13($canonical)) {
$this->context->addViolation($this->getMessage($constraint, 'isbn13'), array(
'{{ value }}' => $this->formatValue($value),
));
} elseif (!$this->validateIsbn10($canonical) && !$this->validateIsbn13($canonical)) {
$this->context->addViolation($this->getMessage($constraint), array(
'{{ value }}' => $this->formatValue($value),
));
// Explicitly validate against ISBN-10
if ('isbn10' === $constraint->type) {
if (!$this->validateIsbn10($canonical)) {
$this->buildViolation($this->getMessage($constraint, $constraint->type))
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
return;
}
// Explicitly validate against ISBN-13
if ('isbn13' === $constraint->type) {
if (!$this->validateIsbn13($canonical)) {
$this->buildViolation($this->getMessage($constraint, $constraint->type))
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
return;
}
// Try both ISBNs
if (!$this->validateIsbn10($canonical) && !$this->validateIsbn13($canonical)) {
$this->buildViolation($this->getMessage($constraint))
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
}
protected function validateIsbn10($isbn)
{
if (10 !== strlen($isbn)) {
return false;
}
$checkSum = 0;
for ($i = 0; $i < 10; ++$i) {
if (!isset($isbn{$i})) {
return false;
}
if ('X' === $isbn{$i}) {
$digit = 10;
} elseif (ctype_digit($isbn{$i})) {
@ -89,12 +104,26 @@ class IsbnValidator extends ConstraintValidator
$checkSum += $digit * intval(10 - $i);
}
if (isset($isbn{$i})) {
return false;
}
return 0 === $checkSum % 11;
}
protected function validateIsbn13($isbn)
{
if (13 !== strlen($isbn) || !ctype_digit($isbn)) {
if (!ctype_digit($isbn)) {
return false;
}
$length = strlen($isbn);
if ($length < 13) {
return false;
}
if ($length > 13) {
return false;
}
@ -116,9 +145,9 @@ class IsbnValidator extends ConstraintValidator
{
if (null !== $constraint->message) {
return $constraint->message;
} elseif ($type == 'isbn10') {
} elseif ('isbn10' === $type) {
return $constraint->isbn10Message;
} elseif ($type == 'isbn13') {
} elseif ('isbn13' === $type) {
return $constraint->isbn13Message;
}

View File

@ -19,6 +19,7 @@ use Symfony\Component\Validator\Exception\UnexpectedTypeException;
* Validates whether the value is a valid ISSN.
*
* @author Antonio J. García Lagar <aj@garcialagar.es>
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @see https://en.wikipedia.org/wiki/Issn
*/
@ -42,25 +43,73 @@ class IssnValidator extends ConstraintValidator
}
$value = (string) $value;
$canonical = $value;
// Compose regex pattern
$digitsPattern = $constraint->requireHyphen ? '\d{4}-\d{3}' : '\d{4}-?\d{3}';
$checkSumPattern = $constraint->caseSensitive ? '[\d|X]' : '[\d|X|x]';
$pattern = "/^".$digitsPattern.$checkSumPattern."$/";
if (!preg_match($pattern, $value)) {
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $this->formatValue($value),
));
// 1234-567X
// ^
if (isset($canonical{4}) && '-' === $canonical{4}) {
// remove hyphen
$canonical = substr($canonical, 0, 4).substr($canonical, 5);
} elseif ($constraint->requireHyphen) {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
return;
}
$canonical = strtoupper(str_replace('-', '', $value));
$length = strlen($canonical);
if ($length < 8) {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
return;
}
if ($length > 8) {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
return;
}
// 1234567X
// ^^^^^^^ digits only
if (!ctype_digit(substr($canonical, 0, 7))) {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
return;
}
// 1234567X
// ^ digit, x or X
if (!ctype_digit($canonical{7}) && 'x' !== $canonical{7} && 'X' !== $canonical{7}) {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
return;
}
// 1234567X
// ^ case-sensitive?
if ($constraint->caseSensitive && 'x' === $canonical{7}) {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
return;
}
// Calculate a checksum. "X" equals 10.
$checkSum = 'X' === $canonical{7}
? 10 : $canonical{7};
$checkSum = 'X' === $canonical{7} || 'x' === $canonical{7}
? 10
: $canonical{7};
for ($i = 0; $i < 7; ++$i) {
// Multiply the first digit by 8, the second by 7, etc.
@ -68,9 +117,9 @@ class IssnValidator extends ConstraintValidator
}
if (0 !== $checkSum % 11) {
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $this->formatValue($value),
));
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
}
}

View File

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

View File

@ -13,7 +13,6 @@ namespace Symfony\Component\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
@ -48,59 +47,24 @@ class LengthValidator extends ConstraintValidator
$length = strlen($stringValue);
}
if ($constraint->min == $constraint->max && $length != $constraint->min) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->exactMessage)
->setParameter('{{ value }}', $this->formatValue($stringValue))
->setParameter('{{ limit }}', $constraint->min)
->setInvalidValue($value)
->setPlural((int) $constraint->min)
->addViolation();
} else {
// 2.4 API
$this->context->addViolation($constraint->exactMessage, array(
'{{ value }}' => $this->formatValue($stringValue),
'{{ limit }}' => $constraint->min,
), $value, (int) $constraint->min);
}
return;
}
if (null !== $constraint->max && $length > $constraint->max) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->maxMessage)
->setParameter('{{ value }}', $this->formatValue($stringValue))
->setParameter('{{ limit }}', $constraint->max)
->setInvalidValue($value)
->setPlural((int) $constraint->max)
->addViolation();
} else {
// 2.4 API
$this->context->addViolation($constraint->maxMessage, array(
'{{ value }}' => $this->formatValue($stringValue),
'{{ limit }}' => $constraint->max,
), $value, (int) $constraint->max);
}
$this->buildViolation($constraint->min == $constraint->max ? $constraint->exactMessage : $constraint->maxMessage)
->setParameter('{{ value }}', $this->formatValue($stringValue))
->setParameter('{{ limit }}', $constraint->max)
->setInvalidValue($value)
->setPlural((int) $constraint->max)
->addViolation();
return;
}
if (null !== $constraint->min && $length < $constraint->min) {
if ($this->context instanceof ExecutionContextInterface) {
$this->context->buildViolation($constraint->minMessage)
->setParameter('{{ value }}', $this->formatValue($stringValue))
->setParameter('{{ limit }}', $constraint->min)
->setInvalidValue($value)
->setPlural((int) $constraint->min)
->addViolation();
} else {
// 2.4 API
$this->context->addViolation($constraint->minMessage, array(
'{{ value }}' => $this->formatValue($stringValue),
'{{ limit }}' => $constraint->min,
), $value, (int) $constraint->min);
}
$this->buildViolation($constraint->min == $constraint->max ? $constraint->exactMessage : $constraint->minMessage)
->setParameter('{{ value }}', $this->formatValue($stringValue))
->setParameter('{{ limit }}', $constraint->min)
->setInvalidValue($value)
->setPlural((int) $constraint->min)
->addViolation();
}
}
}

View File

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

View File

@ -18,6 +18,9 @@ use Symfony\Component\Validator\Constraint;
*
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Tim Nagel <t.nagel@infinite.net.au>
* @author Greg Knapp http://gregk.me/2011/php-implementation-of-bank-card-luhn-algorithm/
*/
class Luhn extends Constraint
{

View File

@ -55,9 +55,9 @@ class LuhnValidator extends ConstraintValidator
$value = (string) $value;
if (!ctype_digit($value)) {
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $this->formatValue($value),
));
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
return;
}
@ -85,9 +85,9 @@ class LuhnValidator extends ConstraintValidator
}
if (0 === $checkSum || 0 !== $checkSum % 10) {
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $this->formatValue($value),
));
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
}
}

View File

@ -32,9 +32,9 @@ class NotBlankValidator extends ConstraintValidator
}
if (false === $value || (empty($value) && '0' != $value)) {
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $this->formatValue($value),
));
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
}
}

View File

@ -32,9 +32,9 @@ class NullValidator extends ConstraintValidator
}
if (null !== $value) {
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $this->formatValue($value),
));
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
}
}

View File

@ -34,27 +34,27 @@ class RangeValidator extends ConstraintValidator
}
if (!is_numeric($value)) {
$this->context->addViolation($constraint->invalidMessage, array(
'{{ value }}' => $this->formatValue($value),
));
$this->buildViolation($constraint->invalidMessage)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
return;
}
if (null !== $constraint->max && $value > $constraint->max) {
$this->context->addViolation($constraint->maxMessage, array(
'{{ value }}' => $value,
'{{ limit }}' => $constraint->max,
));
$this->buildViolation($constraint->maxMessage)
->setParameter('{{ value }}', $value)
->setParameter('{{ limit }}', $constraint->max)
->addViolation();
return;
}
if (null !== $constraint->min && $value < $constraint->min) {
$this->context->addViolation($constraint->minMessage, array(
'{{ value }}' => $value,
'{{ limit }}' => $constraint->min,
));
$this->buildViolation($constraint->minMessage)
->setParameter('{{ value }}', $value)
->setParameter('{{ limit }}', $constraint->min)
->addViolation();
}
}
}

View File

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

View File

@ -22,7 +22,23 @@ use Symfony\Component\Validator\Exception\UnexpectedTypeException;
*/
class TimeValidator extends ConstraintValidator
{
const PATTERN = '/^(0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/';
const PATTERN = '/^(\d{2}):(\d{2}):(\d{2})$/';
/**
* Checks whether a time is valid.
*
* @param int $hour The hour
* @param int $minute The minute
* @param int $second The second
*
* @return bool Whether the time is valid
*
* @internal
*/
public static function checkTime($hour, $minute, $second)
{
return $hour >= 0 && $hour < 24 && $minute >= 0 && $minute < 60 && $second >= 0 && $second < 60;
}
/**
* {@inheritdoc}
@ -43,10 +59,18 @@ class TimeValidator extends ConstraintValidator
$value = (string) $value;
if (!preg_match(static::PATTERN, $value)) {
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $this->formatValue($value),
));
if (!preg_match(static::PATTERN, $value, $matches)) {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
return;
}
if (!self::checkTime($matches[1], $matches[2], $matches[3])) {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
}
}

View File

@ -36,9 +36,9 @@ class TrueValidator extends ConstraintValidator
}
if (true !== $value && 1 !== $value && '1' !== $value) {
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $this->formatValue($value),
));
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
}
}

View File

@ -48,9 +48,9 @@ class TypeValidator extends ConstraintValidator
return;
}
$this->context->addViolation($constraint->message, array(
'{{ value }}' => $this->formatValue($value),
'{{ type }}' => $constraint->type,
));
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->setParameter('{{ type }}', $constraint->type)
->addViolation();
}
}

View File

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

View File

@ -19,6 +19,7 @@ use Symfony\Component\Validator\Exception\UnexpectedTypeException;
* Validates whether the value is a valid UUID per RFC 4122.
*
* @author Colin O'Dell <colinodell@gmail.com>
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @see http://tools.ietf.org/html/rfc4122
* @see https://en.wikipedia.org/wiki/Universally_unique_identifier
@ -64,19 +65,43 @@ class UuidValidator extends ConstraintValidator
$value = (string) $value;
if ($constraint->strict) {
$length = strlen($value);
if ($length < static::STRICT_UUID_LENGTH) {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
return;
}
if ($length > static::STRICT_UUID_LENGTH) {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
return;
}
// Insert the allowed versions into the regular expression
$pattern = sprintf(static::STRICT_PATTERN, implode('', $constraint->versions));
if (strlen($value) !== static::STRICT_UUID_LENGTH || !preg_match($pattern, $value)) {
$this->context->addViolation($constraint->message, array('{{ value }}' => $value));
if (!preg_match($pattern, $value)) {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
} else {
// Trim any wrapping characters like [] or {} used by some legacy systems
$value = trim($value, '[]{}');
if (!preg_match(static::LOOSE_PATTERN, $value)) {
$this->context->addViolation($constraint->message, array('{{ value }}' => $value));
}
return;
}
// Trim any wrapping characters like [] or {} used by some legacy systems
$value = trim($value, '[]{}');
if (!preg_match(static::LOOSE_PATTERN, $value)) {
$this->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
->addViolation();
}
}
}

View File

@ -82,9 +82,9 @@ class CallbackValidatorTest extends AbstractConstraintValidatorTest
$this->validator->validate($object, $constraint);
$this->assertViolation('My message', array(
'{{ value }}' => 'foobar',
));
$this->buildViolation('My message')
->setParameter('{{ value }}', 'foobar')
->assertRaised();
}
public function testSingleStaticMethod()
@ -94,9 +94,9 @@ class CallbackValidatorTest extends AbstractConstraintValidatorTest
$this->validator->validate($object, $constraint);
$this->assertViolation('Static message', array(
'{{ value }}' => 'baz',
));
$this->buildViolation('Static message')
->setParameter('{{ value }}', 'baz')
->assertRaised();
}
public function testClosure()
@ -110,9 +110,9 @@ class CallbackValidatorTest extends AbstractConstraintValidatorTest
$this->validator->validate($object, $constraint);
$this->assertViolation('My message', array(
'{{ value }}' => 'foobar',
));
$this->buildViolation('My message')
->setParameter('{{ value }}', 'foobar')
->assertRaised();
}
public function testClosureNullObject()
@ -125,9 +125,9 @@ class CallbackValidatorTest extends AbstractConstraintValidatorTest
$this->validator->validate(null, $constraint);
$this->assertViolation('My message', array(
'{{ value }}' => 'foobar',
));
$this->buildViolation('My message')
->setParameter('{{ value }}', 'foobar')
->assertRaised();
}
public function testClosureExplicitName()
@ -143,9 +143,9 @@ class CallbackValidatorTest extends AbstractConstraintValidatorTest
$this->validator->validate($object, $constraint);
$this->assertViolation('My message', array(
'{{ value }}' => 'foobar',
));
$this->buildViolation('My message')
->setParameter('{{ value }}', 'foobar')
->assertRaised();
}
public function testArrayCallable()
@ -155,9 +155,9 @@ class CallbackValidatorTest extends AbstractConstraintValidatorTest
$this->validator->validate($object, $constraint);
$this->assertViolation('Callback message', array(
'{{ value }}' => 'foobar',
));
$this->buildViolation('Callback message')
->setParameter('{{ value }}', 'foobar')
->assertRaised();
}
public function testArrayCallableNullObject()
@ -166,9 +166,9 @@ class CallbackValidatorTest extends AbstractConstraintValidatorTest
$this->validator->validate(null, $constraint);
$this->assertViolation('Callback message', array(
'{{ value }}' => 'foobar',
));
$this->buildViolation('Callback message')
->setParameter('{{ value }}', 'foobar')
->assertRaised();
}
public function testArrayCallableExplicitName()
@ -180,9 +180,9 @@ class CallbackValidatorTest extends AbstractConstraintValidatorTest
$this->validator->validate($object, $constraint);
$this->assertViolation('Callback message', array(
'{{ value }}' => 'foobar',
));
$this->buildViolation('Callback message')
->setParameter('{{ value }}', 'foobar')
->assertRaised();
}
// BC with Symfony < 2.4
@ -193,9 +193,9 @@ class CallbackValidatorTest extends AbstractConstraintValidatorTest
$this->validator->validate($object, $constraint);
$this->assertViolation('My message', array(
'{{ value }}' => 'foobar',
));
$this->buildViolation('My message')
->setParameter('{{ value }}', 'foobar')
->assertRaised();
}
// BC with Symfony < 2.4

View File

@ -161,6 +161,7 @@ class ChoiceValidatorTest extends AbstractConstraintValidatorTest
$this->buildViolation('myMessage')
->setParameter('{{ value }}', '"baz"')
->setInvalidValue('baz')
->assertRaised();
}
@ -274,6 +275,7 @@ class ChoiceValidatorTest extends AbstractConstraintValidatorTest
$this->buildViolation('myMessage')
->setParameter('{{ value }}', '"3"')
->setInvalidValue('3')
->assertRaised();
}
}

View File

@ -65,14 +65,6 @@ abstract class CountValidatorTest extends AbstractConstraintValidatorTest
);
}
public function getNotFourElements()
{
return array_merge(
$this->getThreeOrLessElements(),
$this->getFiveOrMoreElements()
);
}
public function getFiveOrMoreElements()
{
return array(
@ -118,7 +110,7 @@ abstract class CountValidatorTest extends AbstractConstraintValidatorTest
/**
* @dataProvider getFiveOrMoreElements
*/
public function testInvalidValuesMax($value)
public function testTooManyValues($value)
{
$constraint = new Count(array(
'max' => 4,
@ -138,7 +130,7 @@ abstract class CountValidatorTest extends AbstractConstraintValidatorTest
/**
* @dataProvider getThreeOrLessElements
*/
public function testInvalidValuesMin($value)
public function testTooFewValues($value)
{
$constraint = new Count(array(
'min' => 4,
@ -156,9 +148,30 @@ abstract class CountValidatorTest extends AbstractConstraintValidatorTest
}
/**
* @dataProvider getNotFourElements
* @dataProvider getFiveOrMoreElements
*/
public function testInvalidValuesExact($value)
public function testTooManyValuesExact($value)
{
$constraint = new Count(array(
'min' => 4,
'max' => 4,
'exactMessage' => 'myMessage',
));
$this->validator->validate($value, $constraint);
$this->buildViolation('myMessage')
->setParameter('{{ count }}', count($value))
->setParameter('{{ limit }}', 4)
->setInvalidValue($value)
->setPlural(4)
->assertRaised();
}
/**
* @dataProvider getThreeOrLessElements
*/
public function testTooFewValuesExact($value)
{
$constraint = new Count(array(
'min' => 4,

View File

@ -71,7 +71,9 @@ class ExpressionValidatorTest extends AbstractConstraintValidatorTest
$this->validator->validate($object, $constraint);
$this->assertViolation('myMessage');
$this->buildViolation('myMessage')
->setParameter('{{ value }}', 'object')
->assertRaised();
}
public function testSucceedingExpressionAtPropertyLevel()
@ -106,7 +108,10 @@ class ExpressionValidatorTest extends AbstractConstraintValidatorTest
$this->validator->validate('2', $constraint);
$this->assertViolation('myMessage', array(), 'data');
$this->buildViolation('myMessage')
->setParameter('{{ value }}', '"2"')
->atPath('data')
->assertRaised();
}
public function testSucceedingExpressionAtNestedPropertyLevel()
@ -147,7 +152,10 @@ class ExpressionValidatorTest extends AbstractConstraintValidatorTest
$this->validator->validate('2', $constraint);
$this->assertViolation('myMessage', array(), 'reference.data');
$this->buildViolation('myMessage')
->setParameter('{{ value }}', '"2"')
->atPath('reference.data')
->assertRaised();
}
/**
@ -184,6 +192,9 @@ class ExpressionValidatorTest extends AbstractConstraintValidatorTest
$this->validator->validate('2', $constraint);
$this->assertViolation('myMessage', array(), '');
$this->buildViolation('myMessage')
->setParameter('{{ value }}', '"2"')
->atPath('')
->assertRaised();
}
}

View File

@ -202,10 +202,10 @@ class ImageValidatorTest extends AbstractConstraintValidatorTest
$this->validator->validate($this->image, $constraint);
$this->assertViolation('myMessage', array(
'{{ ratio }}' => 1,
'{{ min_ratio }}' => 2,
));
$this->buildViolation('myMessage')
->setParameter('{{ ratio }}', 1)
->setParameter('{{ min_ratio }}', 2)
->assertRaised();
}
public function testRatioTooBig()
@ -217,10 +217,10 @@ class ImageValidatorTest extends AbstractConstraintValidatorTest
$this->validator->validate($this->image, $constraint);
$this->assertViolation('myMessage', array(
'{{ ratio }}' => 1,
'{{ max_ratio }}' => 0.5,
));
$this->buildViolation('myMessage')
->setParameter('{{ ratio }}', 1)
->setParameter('{{ max_ratio }}', 0.5)
->assertRaised();
}
public function testMaxRatioUsesTwoDecimalsOnly()
@ -267,10 +267,10 @@ class ImageValidatorTest extends AbstractConstraintValidatorTest
$this->validator->validate($this->image, $constraint);
$this->assertViolation('myMessage', array(
'{{ width }}' => 2,
'{{ height }}' => 2,
));
$this->buildViolation('myMessage')
->setParameter('{{ width }}', 2)
->setParameter('{{ height }}', 2)
->assertRaised();
}
public function testLandscapeNotAllowed()
@ -282,10 +282,10 @@ class ImageValidatorTest extends AbstractConstraintValidatorTest
$this->validator->validate($this->imageLandscape, $constraint);
$this->assertViolation('myMessage', array(
'{{ width }}' => 2,
'{{ height }}' => 1,
));
$this->buildViolation('myMessage')
->setParameter('{{ width }}', 2)
->setParameter('{{ height }}', 1)
->assertRaised();
}
public function testPortraitNotAllowed()
@ -297,9 +297,9 @@ class ImageValidatorTest extends AbstractConstraintValidatorTest
$this->validator->validate($this->imagePortrait, $constraint);
$this->assertViolation('myMessage', array(
'{{ width }}' => 1,
'{{ height }}' => 2,
));
$this->buildViolation('myMessage')
->setParameter('{{ width }}', 1)
->setParameter('{{ height }}', 2)
->assertRaised();
}
}

View File

@ -52,10 +52,11 @@ class IsbnValidatorTest extends AbstractConstraintValidatorTest
public function getInvalidIsbn10()
{
return array(
array('27234422841'),
array('272344228'),
array('0-4712-9231'),
array('1234567890'),
array('987'),
array('0987656789'),
array(0),
array('7-35622-5444'),
array('0-4X19-92611'),
array('0_45122_5244'),
@ -89,16 +90,16 @@ class IsbnValidatorTest extends AbstractConstraintValidatorTest
public function getInvalidIsbn13()
{
return array(
array('1234567890'),
array('987'),
array('0987656789'),
array(0),
array('0-4X19-9261981'),
array('978-27234422821'),
array('978-272344228'),
array('978-2723442-82'),
array('978-2723442281'),
array('978-0321513774'),
array('979-0431225385'),
array('980-0474292319'),
array('978_0451225245'),
array('978#0471292319'),
array('0-4X19-92619812'),
array('978_2723442282'),
array('978#2723442282'),
array('978-272C442282'),
// chr(1) evaluates to 0
// 978-2070546817 is valid
@ -213,7 +214,7 @@ class IsbnValidatorTest extends AbstractConstraintValidatorTest
/**
* @dataProvider getValidIsbn
*/
public function testValidIsbn($isbn)
public function testValidIsbnAny($isbn)
{
$constraint = new Isbn();
@ -223,9 +224,25 @@ class IsbnValidatorTest extends AbstractConstraintValidatorTest
}
/**
* @dataProvider getInvalidIsbn
* @dataProvider getInvalidIsbn10
*/
public function testInvalidIsbn($isbn)
public function testInvalidIsbnAnyIsbn10($isbn)
{
$constraint = new Isbn(array(
'bothIsbnMessage' => 'myMessage',
));
$this->validator->validate($isbn, $constraint);
$this->buildViolation('myMessage')
->setParameter('{{ value }}', '"'.$isbn.'"')
->assertRaised();
}
/**
* @dataProvider getInvalidIsbn13
*/
public function testInvalidIsbnAnyIsbn13($isbn)
{
$constraint = new Isbn(array(
'bothIsbnMessage' => 'myMessage',

View File

@ -79,18 +79,12 @@ class IssnValidatorTest extends AbstractConstraintValidatorTest
);
}
public function getInvalidFormatedIssn()
public function getInvalidIssn()
{
return array(
array(0),
array('1539'),
array('2156-537A'),
);
}
public function getInvalidValueIssn()
{
return array(
array('1119-0231'),
array('1684-5312'),
array('1996-0783'),
@ -99,14 +93,6 @@ class IssnValidatorTest extends AbstractConstraintValidatorTest
);
}
public function getInvalidIssn()
{
return array_merge(
$this->getInvalidFormatedIssn(),
$this->getInvalidValueIssn()
);
}
public function testNullIsValid()
{
$constraint = new Issn();
@ -180,38 +166,6 @@ class IssnValidatorTest extends AbstractConstraintValidatorTest
$this->assertNoViolation();
}
/**
* @dataProvider getInvalidFormatedIssn
*/
public function testInvalidFormatIssn($issn)
{
$constraint = new Issn(array(
'message' => 'myMessage',
));
$this->validator->validate($issn, $constraint);
$this->buildViolation('myMessage')
->setParameter('{{ value }}', '"'.$issn.'"')
->assertRaised();
}
/**
* @dataProvider getInvalidValueIssn
*/
public function testInvalidValueIssn($issn)
{
$constraint = new Issn(array(
'message' => 'myMessage',
));
$this->validator->validate($issn, $constraint);
$this->buildViolation('myMessage')
->setParameter('{{ value }}', '"'.$issn.'"')
->assertRaised();
}
/**
* @dataProvider getInvalidIssn
*/

View File

@ -73,14 +73,6 @@ class LengthValidatorTest extends AbstractConstraintValidatorTest
);
}
public function getNotFourCharacters()
{
return array_merge(
$this->getThreeOrLessCharacters(),
$this->getFiveOrMoreCharacters()
);
}
public function getFiveOrMoreCharacters()
{
return array(
@ -189,9 +181,34 @@ class LengthValidatorTest extends AbstractConstraintValidatorTest
}
/**
* @dataProvider getNotFourCharacters
* @dataProvider getThreeOrLessCharacters
*/
public function testInvalidValuesExact($value, $mbOnly = false)
public function testInvalidValuesExactLessThanFour($value, $mbOnly = false)
{
if ($mbOnly && !function_exists('mb_strlen')) {
$this->markTestSkipped('mb_strlen does not exist');
}
$constraint = new Length(array(
'min' => 4,
'max' => 4,
'exactMessage' => 'myMessage',
));
$this->validator->validate($value, $constraint);
$this->buildViolation('myMessage')
->setParameter('{{ value }}', '"'.$value.'"')
->setParameter('{{ limit }}', 4)
->setInvalidValue($value)
->setPlural(4)
->assertRaised();
}
/**
* @dataProvider getFiveOrMoreCharacters
*/
public function testInvalidValuesExactMoreThanFour($value, $mbOnly = false)
{
if ($mbOnly && !function_exists('mb_strlen')) {
$this->markTestSkipped('mb_strlen does not exist');

View File

@ -97,6 +97,8 @@ class LuhnValidatorTest extends AbstractConstraintValidatorTest
array('1234567812345678'),
array('4222222222222222'),
array('0000000000000000'),
array('000000!000000000'),
array('42-22222222222222'),
);
}

View File

@ -188,38 +188,6 @@ class RangeValidatorTest extends AbstractConstraintValidatorTest
);
}
public function testMinMessageIsSet()
{
$constraint = new Range(array(
'min' => 10,
'max' => 20,
'minMessage' => 'myMessage',
));
$this->validator->validate(9, $constraint);
$this->buildViolation('myMessage')
->setParameter('{{ value }}', 9)
->setParameter('{{ limit }}', 10)
->assertRaised();
}
public function testMaxMessageIsSet()
{
$constraint = new Range(array(
'min' => 10,
'max' => 20,
'maxMessage' => 'myMessage',
));
$this->validator->validate(21, $constraint);
$this->buildViolation('myMessage')
->setParameter('{{ value }}', 21)
->setParameter('{{ limit }}', 20)
->assertRaised();
}
public function testNonNumeric()
{
$this->validator->validate('abcd', new Range(array(

View File

@ -83,9 +83,9 @@ class UuidValidatorTest extends AbstractConstraintValidatorTest
$this->validator->validate($uuid, $constraint);
$this->assertViolation('testMessage', array(
'{{ value }}' => $uuid,
));
$this->buildViolation('testMessage')
->setParameter('{{ value }}', '"'.$uuid.'"')
->assertRaised();
}
public function getInvalidStrictUuids()
@ -130,9 +130,9 @@ class UuidValidatorTest extends AbstractConstraintValidatorTest
$this->validator->validate($uuid, $constraint);
$this->assertViolation('myMessage', array(
'{{ value }}' => $uuid,
));
$this->buildViolation('myMessage')
->setParameter('{{ value }}', '"'.$uuid.'"')
->assertRaised();
}
/**
@ -177,9 +177,9 @@ class UuidValidatorTest extends AbstractConstraintValidatorTest
$this->validator->validate($uuid, $constraint);
$this->assertViolation('myMessage', array(
'{{ value }}' => $uuid,
));
$this->buildViolation('myMessage')
->setParameter('{{ value }}', '"'.$uuid.'"')
->assertRaised();
}
public function getInvalidNonStrictUuids()

View File

@ -0,0 +1,165 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Validator\Violation;
use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;
use Symfony\Component\Validator\ExecutionContextInterface;
use Symfony\Component\Validator\Util\PropertyPath;
/**
* Backwards-compatible implementation of {@link ConstraintViolationBuilderInterface}.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @internal You should not instantiate or use this class. Code against
* {@link ConstraintViolationBuilderInterface} instead.
*
* @deprecated This class will be removed in Symfony 3.0.
*/
class LegacyConstraintViolationBuilder implements ConstraintViolationBuilderInterface
{
/**
* @var ExecutionContextInterface
*/
private $context;
/**
* @var string
*/
private $message;
/**
* @var array
*/
private $parameters;
/**
* @var mixed
*/
private $root;
/**
* @var mixed
*/
private $invalidValue;
/**
* @var string
*/
private $propertyPath;
/**
* @var int|null
*/
private $plural;
/**
* @var mixed
*/
private $code;
public function __construct(ExecutionContextInterface $context, $message, array $parameters)
{
$this->context = $context;
$this->message = $message;
$this->parameters = $parameters;
$this->root = $context->getRoot();
$this->invalidValue = $context->getValue();
}
/**
* {@inheritdoc}
*/
public function atPath($path)
{
$this->propertyPath = $path;
return $this;
}
/**
* {@inheritdoc}
*/
public function setParameter($key, $value)
{
$this->parameters[$key] = $value;
return $this;
}
/**
* {@inheritdoc}
*/
public function setParameters(array $parameters)
{
$this->parameters = $parameters;
return $this;
}
/**
* {@inheritdoc}
*/
public function setTranslationDomain($translationDomain)
{
// can't be set in the old API
return $this;
}
/**
* {@inheritdoc}
*/
public function setInvalidValue($invalidValue)
{
$this->invalidValue = $invalidValue;
return $this;
}
/**
* {@inheritdoc}
*/
public function setPlural($number)
{
$this->plural = $number;
return $this;
}
/**
* {@inheritdoc}
*/
public function setCode($code)
{
$this->code = $code;
return $this;
}
/**
* {@inheritdoc}
*/
public function addViolation()
{
if ($this->propertyPath) {
$this->context->addViolationAt($this->propertyPath, $this->message, $this->parameters, $this->invalidValue, $this->plural, $this->code);
return;
}
$this->context->addViolation($this->message, $this->parameters, $this->invalidValue, $this->plural, $this->code);
}
}