diff --git a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php index b36c458e4fdfa..cfc56b9b4c88d 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php @@ -262,12 +262,19 @@ public function testValidateUniquenessAfterConsideringMultipleQueryResults() $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() diff --git a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php index 60e11e08c078c..48c35c9eff3a5 100644 --- a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php +++ b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php @@ -13,7 +13,6 @@ 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 @@ public function validate($entity, Constraint $constraint) $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(); } } diff --git a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php index 2a6673cbc5864..ab826f9c979fb 100644 --- a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php +++ b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php @@ -99,40 +99,20 @@ public function validate($form, Constraint $constraint) ? (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(); } } diff --git a/src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php b/src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php index 10f692c6a54d5..ef93e25d2dad5 100644 --- a/src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php @@ -92,7 +92,8 @@ public function testPasswordIsNotValid() $this->validator->validate('secret', $constraint); - $this->assertViolation('myMessage'); + $this->buildViolation('myMessage') + ->assertRaised(); } /** diff --git a/src/Symfony/Component/Validator/ConstraintValidator.php b/src/Symfony/Component/Validator/ConstraintValidator.php index 58c0902e131fa..111c2b4bacec4 100644 --- a/src/Symfony/Component/Validator/ConstraintValidator.php +++ b/src/Symfony/Component/Validator/ConstraintValidator.php @@ -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 @@ public function initialize(ExecutionContextInterface $context) $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 @@ protected function formatTypeOf($value) * 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 @@ protected function formatValue($value, $format = 0) * {@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 diff --git a/src/Symfony/Component/Validator/Constraints/AbstractComparisonValidator.php b/src/Symfony/Component/Validator/Constraints/AbstractComparisonValidator.php index 5fbcd179a6d26..ce7239d98ddf6 100644 --- a/src/Symfony/Component/Validator/Constraints/AbstractComparisonValidator.php +++ b/src/Symfony/Component/Validator/Constraints/AbstractComparisonValidator.php @@ -19,6 +19,7 @@ * Provides a base class for the validation of property comparisons. * * @author Daniel Holmes + * @author Bernhard Schussek */ abstract class AbstractComparisonValidator extends ConstraintValidator { @@ -35,12 +36,14 @@ public function validate($value, Constraint $constraint) 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(); } } diff --git a/src/Symfony/Component/Validator/Constraints/BlankValidator.php b/src/Symfony/Component/Validator/Constraints/BlankValidator.php index e8d444e123ef1..031c7a581cd3a 100644 --- a/src/Symfony/Component/Validator/Constraints/BlankValidator.php +++ b/src/Symfony/Component/Validator/Constraints/BlankValidator.php @@ -32,9 +32,9 @@ public function validate($value, Constraint $constraint) } if ('' !== $value && null !== $value) { - $this->context->addViolation($constraint->message, array( - '{{ value }}' => $this->formatValue($value), - )); + $this->buildViolation($constraint->message) + ->setParameter('{{ value }}', $this->formatValue($value)) + ->addViolation(); } } } diff --git a/src/Symfony/Component/Validator/Constraints/CardScheme.php b/src/Symfony/Component/Validator/Constraints/CardScheme.php index a8f38a982d9fd..26a0e1c2fd466 100644 --- a/src/Symfony/Component/Validator/Constraints/CardScheme.php +++ b/src/Symfony/Component/Validator/Constraints/CardScheme.php @@ -18,6 +18,8 @@ * * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) + * + * @author Tim Nagel */ class CardScheme extends Constraint { diff --git a/src/Symfony/Component/Validator/Constraints/CardSchemeValidator.php b/src/Symfony/Component/Validator/Constraints/CardSchemeValidator.php index 0557f690819cd..7cf7fa4bfe04c 100644 --- a/src/Symfony/Component/Validator/Constraints/CardSchemeValidator.php +++ b/src/Symfony/Component/Validator/Constraints/CardSchemeValidator.php @@ -18,9 +18,11 @@ /** * Validates that a card number belongs to a specified scheme. * + * @author Tim Nagel + * @author Bernhard Schussek + * * @see http://en.wikipedia.org/wiki/Bank_card_number * @see http://www.regular-expressions.info/creditcard.html - * @author Tim Nagel */ class CardSchemeValidator extends ConstraintValidator { @@ -113,9 +115,9 @@ public function validate($value, Constraint $constraint) } 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 @@ public function validate($value, Constraint $constraint) } } - $this->context->addViolation($constraint->message, array( - '{{ value }}' => $this->formatValue($value), - )); + $this->buildViolation($constraint->message) + ->setParameter('{{ value }}', $this->formatValue($value)) + ->addViolation(); } } diff --git a/src/Symfony/Component/Validator/Constraints/ChoiceValidator.php b/src/Symfony/Component/Validator/Constraints/ChoiceValidator.php index f995af6816378..5640c733173a5 100644 --- a/src/Symfony/Component/Validator/Constraints/ChoiceValidator.php +++ b/src/Symfony/Component/Validator/Constraints/ChoiceValidator.php @@ -13,7 +13,6 @@ 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 @@ public function validate($value, Constraint $constraint) 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(); } } } diff --git a/src/Symfony/Component/Validator/Constraints/CollectionValidator.php b/src/Symfony/Component/Validator/Constraints/CollectionValidator.php index 64e8d82526fe7..4289169b1606c 100644 --- a/src/Symfony/Component/Validator/Constraints/CollectionValidator.php +++ b/src/Symfony/Component/Validator/Constraints/CollectionValidator.php @@ -70,36 +70,22 @@ public function validate($value, Constraint $constraint) } } } 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(); } } } diff --git a/src/Symfony/Component/Validator/Constraints/CountValidator.php b/src/Symfony/Component/Validator/Constraints/CountValidator.php index 49d1bfc48f294..0f40a3f1e0deb 100644 --- a/src/Symfony/Component/Validator/Constraints/CountValidator.php +++ b/src/Symfony/Component/Validator/Constraints/CountValidator.php @@ -13,7 +13,6 @@ 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 @@ public function validate($value, Constraint $constraint) $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(); } } } diff --git a/src/Symfony/Component/Validator/Constraints/CountryValidator.php b/src/Symfony/Component/Validator/Constraints/CountryValidator.php index 92049db54d8f1..a3ad1dc83bcaf 100644 --- a/src/Symfony/Component/Validator/Constraints/CountryValidator.php +++ b/src/Symfony/Component/Validator/Constraints/CountryValidator.php @@ -46,9 +46,9 @@ public function validate($value, Constraint $constraint) $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(); } } } diff --git a/src/Symfony/Component/Validator/Constraints/CurrencyValidator.php b/src/Symfony/Component/Validator/Constraints/CurrencyValidator.php index 92989ac99e73c..ae3046f2eb1df 100644 --- a/src/Symfony/Component/Validator/Constraints/CurrencyValidator.php +++ b/src/Symfony/Component/Validator/Constraints/CurrencyValidator.php @@ -46,9 +46,9 @@ public function validate($value, Constraint $constraint) $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(); } } } diff --git a/src/Symfony/Component/Validator/Constraints/DateTimeValidator.php b/src/Symfony/Component/Validator/Constraints/DateTimeValidator.php index 14634b30515e0..88c8e25862294 100644 --- a/src/Symfony/Component/Validator/Constraints/DateTimeValidator.php +++ b/src/Symfony/Component/Validator/Constraints/DateTimeValidator.php @@ -21,7 +21,7 @@ */ 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 @@ public function validate($value, Constraint $constraint) $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(); } } } diff --git a/src/Symfony/Component/Validator/Constraints/DateValidator.php b/src/Symfony/Component/Validator/Constraints/DateValidator.php index 7edc59c5c7e03..e1640b13b3858 100644 --- a/src/Symfony/Component/Validator/Constraints/DateValidator.php +++ b/src/Symfony/Component/Validator/Constraints/DateValidator.php @@ -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 @@ public function validate($value, Constraint $constraint) $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(); } } } diff --git a/src/Symfony/Component/Validator/Constraints/EmailValidator.php b/src/Symfony/Component/Validator/Constraints/EmailValidator.php index 70f3d55c0d3b3..1f487ca1c4a46 100644 --- a/src/Symfony/Component/Validator/Constraints/EmailValidator.php +++ b/src/Symfony/Component/Validator/Constraints/EmailValidator.php @@ -13,8 +13,8 @@ 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 @@ -53,34 +53,50 @@ public function validate($value, Constraint $constraint) } $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 ($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) { - $host = substr($value, strpos($value, '@') + 1); - // Check for host DNS resource records + $host = substr($value, strpos($value, '@') + 1); - if ($valid && $constraint->checkMX) { - $valid = $this->checkMX($host); - } elseif ($valid && $constraint->checkHost) { - $valid = $this->checkHost($host); + // 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 (!$valid) { - $this->context->addViolation($constraint->message, array( - '{{ value }}' => $this->formatValue($value), - )); + if ($constraint->checkHost && !$this->checkHost($host)) { + $this->buildViolation($constraint->message) + ->setParameter('{{ value }}', $this->formatValue($value)) + ->addViolation(); } } diff --git a/src/Symfony/Component/Validator/Constraints/ExpressionValidator.php b/src/Symfony/Component/Validator/Constraints/ExpressionValidator.php index 3df23d4342792..a20d1ac2518f4 100644 --- a/src/Symfony/Component/Validator/Constraints/ExpressionValidator.php +++ b/src/Symfony/Component/Validator/Constraints/ExpressionValidator.php @@ -89,7 +89,9 @@ public function validate($value, Constraint $constraint) } if (!$this->getExpressionLanguage()->evaluate($constraint->expression, $variables)) { - $this->context->addViolation($constraint->message); + $this->buildViolation($constraint->message) + ->setParameter('{{ value }}', $this->formatValue($value)) + ->addViolation(); } } diff --git a/src/Symfony/Component/Validator/Constraints/FalseValidator.php b/src/Symfony/Component/Validator/Constraints/FalseValidator.php index d798ebfbb98ac..206780cefc73c 100644 --- a/src/Symfony/Component/Validator/Constraints/FalseValidator.php +++ b/src/Symfony/Component/Validator/Constraints/FalseValidator.php @@ -35,8 +35,8 @@ public function validate($value, Constraint $constraint) return; } - $this->context->addViolation($constraint->message, array( - '{{ value }}' => $this->formatValue($value), - )); + $this->buildViolation($constraint->message) + ->setParameter('{{ value }}', $this->formatValue($value)) + ->addViolation(); } } diff --git a/src/Symfony/Component/Validator/Constraints/FileValidator.php b/src/Symfony/Component/Validator/Constraints/FileValidator.php index 3916ef54931df..acc80c9b07943 100644 --- a/src/Symfony/Component/Validator/Constraints/FileValidator.php +++ b/src/Symfony/Component/Validator/Constraints/FileValidator.php @@ -66,38 +66,46 @@ public function validate($value, Constraint $constraint) $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 @@ public function validate($value, Constraint $constraint) $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 @@ public function validate($value, Constraint $constraint) $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 @@ public function validate($value, Constraint $constraint) $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(); } } diff --git a/src/Symfony/Component/Validator/Constraints/Iban.php b/src/Symfony/Component/Validator/Constraints/Iban.php index 628d21cacecd3..895a93cd5860e 100644 --- a/src/Symfony/Component/Validator/Constraints/Iban.php +++ b/src/Symfony/Component/Validator/Constraints/Iban.php @@ -16,6 +16,9 @@ /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) + * + * @author Manuel Reinhard + * @author Michael Schummel */ class Iban extends Constraint { diff --git a/src/Symfony/Component/Validator/Constraints/IbanValidator.php b/src/Symfony/Component/Validator/Constraints/IbanValidator.php index 2276789c319a1..b66561dc2ade1 100644 --- a/src/Symfony/Component/Validator/Constraints/IbanValidator.php +++ b/src/Symfony/Component/Validator/Constraints/IbanValidator.php @@ -45,21 +45,38 @@ public function validate($value, Constraint $constraint) // 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 @@ public function validate($value, Constraint $constraint) // -> 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 @@ private function toBigInt($string) continue; } - // Disallow lowercase characters - if (ctype_lower($char)) { - return false; - } - // Simply append digits $bigInt .= $char; } diff --git a/src/Symfony/Component/Validator/Constraints/Image.php b/src/Symfony/Component/Validator/Constraints/Image.php index 6401603a752e7..707e2af312e01 100644 --- a/src/Symfony/Component/Validator/Constraints/Image.php +++ b/src/Symfony/Component/Validator/Constraints/Image.php @@ -15,6 +15,8 @@ * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * + * @author Benjamin Dulau + * * @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.'; diff --git a/src/Symfony/Component/Validator/Constraints/ImageValidator.php b/src/Symfony/Component/Validator/Constraints/ImageValidator.php index 43bea3d7c2122..4eaed687dc985 100644 --- a/src/Symfony/Component/Validator/Constraints/ImageValidator.php +++ b/src/Symfony/Component/Validator/Constraints/ImageValidator.php @@ -20,6 +20,7 @@ * against minWidth, maxWidth, minHeight and maxHeight constraints * * @author Benjamin Dulau + * @author Bernhard Schussek */ class ImageValidator extends FileValidator { @@ -50,8 +51,10 @@ public function validate($value, Constraint $constraint) } $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 @@ public function validate($value, Constraint $constraint) } 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 @@ public function validate($value, Constraint $constraint) } 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 @@ public function validate($value, Constraint $constraint) } 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 @@ public function validate($value, Constraint $constraint) } 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 @@ public function validate($value, Constraint $constraint) } 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 @@ public function validate($value, Constraint $constraint) } 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(); } } } diff --git a/src/Symfony/Component/Validator/Constraints/IpValidator.php b/src/Symfony/Component/Validator/Constraints/IpValidator.php index 69286e90f99ae..8db2ddb062b03 100644 --- a/src/Symfony/Component/Validator/Constraints/IpValidator.php +++ b/src/Symfony/Component/Validator/Constraints/IpValidator.php @@ -95,9 +95,9 @@ public function validate($value, Constraint $constraint) } 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(); } } } diff --git a/src/Symfony/Component/Validator/Constraints/IsbnValidator.php b/src/Symfony/Component/Validator/Constraints/IsbnValidator.php index 67b1fc44e72bc..8972b91610406 100644 --- a/src/Symfony/Component/Validator/Constraints/IsbnValidator.php +++ b/src/Symfony/Component/Validator/Constraints/IsbnValidator.php @@ -54,30 +54,45 @@ public function validate($value, Constraint $constraint) } } - 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 @@ protected function validateIsbn10($isbn) $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 @@ protected function getMessage($constraint, $type = null) { 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; } diff --git a/src/Symfony/Component/Validator/Constraints/IssnValidator.php b/src/Symfony/Component/Validator/Constraints/IssnValidator.php index ed9a6fb9f8126..2ee8a53dfd7e5 100644 --- a/src/Symfony/Component/Validator/Constraints/IssnValidator.php +++ b/src/Symfony/Component/Validator/Constraints/IssnValidator.php @@ -19,6 +19,7 @@ * Validates whether the value is a valid ISSN. * * @author Antonio J. GarcĂ­a Lagar + * @author Bernhard Schussek * * @see https://en.wikipedia.org/wiki/Issn */ @@ -42,25 +43,73 @@ public function validate($value, Constraint $constraint) } $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."$/"; + // 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(); - if (!preg_match($pattern, $value)) { - $this->context->addViolation($constraint->message, array( - '{{ value }}' => $this->formatValue($value), - )); + return; + } + + $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; } - $canonical = strtoupper(str_replace('-', '', $value)); + // 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 @@ public function validate($value, Constraint $constraint) } if (0 !== $checkSum % 11) { - $this->context->addViolation($constraint->message, array( - '{{ value }}' => $this->formatValue($value), - )); + $this->buildViolation($constraint->message) + ->setParameter('{{ value }}', $this->formatValue($value)) + ->addViolation(); } } } diff --git a/src/Symfony/Component/Validator/Constraints/LanguageValidator.php b/src/Symfony/Component/Validator/Constraints/LanguageValidator.php index 3286f26b86bf3..1cc2a438197b2 100644 --- a/src/Symfony/Component/Validator/Constraints/LanguageValidator.php +++ b/src/Symfony/Component/Validator/Constraints/LanguageValidator.php @@ -46,9 +46,9 @@ public function validate($value, Constraint $constraint) $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(); } } } diff --git a/src/Symfony/Component/Validator/Constraints/LengthValidator.php b/src/Symfony/Component/Validator/Constraints/LengthValidator.php index eeb9d3a5d1b3d..cdc5bea985df3 100644 --- a/src/Symfony/Component/Validator/Constraints/LengthValidator.php +++ b/src/Symfony/Component/Validator/Constraints/LengthValidator.php @@ -13,7 +13,6 @@ 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 @@ public function validate($value, Constraint $constraint) $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(); } } } diff --git a/src/Symfony/Component/Validator/Constraints/LocaleValidator.php b/src/Symfony/Component/Validator/Constraints/LocaleValidator.php index 08f1d1d0a52e6..dadbebaf4297d 100644 --- a/src/Symfony/Component/Validator/Constraints/LocaleValidator.php +++ b/src/Symfony/Component/Validator/Constraints/LocaleValidator.php @@ -46,9 +46,9 @@ public function validate($value, Constraint $constraint) $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(); } } } diff --git a/src/Symfony/Component/Validator/Constraints/Luhn.php b/src/Symfony/Component/Validator/Constraints/Luhn.php index 1feafe3e5b16b..e9b406adede15 100644 --- a/src/Symfony/Component/Validator/Constraints/Luhn.php +++ b/src/Symfony/Component/Validator/Constraints/Luhn.php @@ -18,6 +18,9 @@ * * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) + * + * @author Tim Nagel + * @author Greg Knapp http://gregk.me/2011/php-implementation-of-bank-card-luhn-algorithm/ */ class Luhn extends Constraint { diff --git a/src/Symfony/Component/Validator/Constraints/LuhnValidator.php b/src/Symfony/Component/Validator/Constraints/LuhnValidator.php index a149aa9a8117e..c82d6d8917a07 100644 --- a/src/Symfony/Component/Validator/Constraints/LuhnValidator.php +++ b/src/Symfony/Component/Validator/Constraints/LuhnValidator.php @@ -55,9 +55,9 @@ public function validate($value, Constraint $constraint) $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 @@ public function validate($value, Constraint $constraint) } 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(); } } } diff --git a/src/Symfony/Component/Validator/Constraints/NotBlankValidator.php b/src/Symfony/Component/Validator/Constraints/NotBlankValidator.php index e76135623a232..9deab1503b026 100644 --- a/src/Symfony/Component/Validator/Constraints/NotBlankValidator.php +++ b/src/Symfony/Component/Validator/Constraints/NotBlankValidator.php @@ -32,9 +32,9 @@ public function validate($value, Constraint $constraint) } 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(); } } } diff --git a/src/Symfony/Component/Validator/Constraints/NullValidator.php b/src/Symfony/Component/Validator/Constraints/NullValidator.php index 645ffc034b11a..1e6c3a53897ab 100644 --- a/src/Symfony/Component/Validator/Constraints/NullValidator.php +++ b/src/Symfony/Component/Validator/Constraints/NullValidator.php @@ -32,9 +32,9 @@ public function validate($value, Constraint $constraint) } if (null !== $value) { - $this->context->addViolation($constraint->message, array( - '{{ value }}' => $this->formatValue($value), - )); + $this->buildViolation($constraint->message) + ->setParameter('{{ value }}', $this->formatValue($value)) + ->addViolation(); } } } diff --git a/src/Symfony/Component/Validator/Constraints/RangeValidator.php b/src/Symfony/Component/Validator/Constraints/RangeValidator.php index c7bf7a93bcb37..0abd0cb449972 100644 --- a/src/Symfony/Component/Validator/Constraints/RangeValidator.php +++ b/src/Symfony/Component/Validator/Constraints/RangeValidator.php @@ -34,27 +34,27 @@ public function validate($value, Constraint $constraint) } 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(); } } } diff --git a/src/Symfony/Component/Validator/Constraints/RegexValidator.php b/src/Symfony/Component/Validator/Constraints/RegexValidator.php index 88b19d023dbb9..b18234454f095 100644 --- a/src/Symfony/Component/Validator/Constraints/RegexValidator.php +++ b/src/Symfony/Component/Validator/Constraints/RegexValidator.php @@ -45,9 +45,9 @@ public function validate($value, Constraint $constraint) $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(); } } } diff --git a/src/Symfony/Component/Validator/Constraints/TimeValidator.php b/src/Symfony/Component/Validator/Constraints/TimeValidator.php index cf252b1d28dd6..3d52fbe43585c 100644 --- a/src/Symfony/Component/Validator/Constraints/TimeValidator.php +++ b/src/Symfony/Component/Validator/Constraints/TimeValidator.php @@ -22,7 +22,23 @@ */ 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 @@ public function validate($value, Constraint $constraint) $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(); } } } diff --git a/src/Symfony/Component/Validator/Constraints/TrueValidator.php b/src/Symfony/Component/Validator/Constraints/TrueValidator.php index ef0e2608ef8e6..a01f5bb37deda 100644 --- a/src/Symfony/Component/Validator/Constraints/TrueValidator.php +++ b/src/Symfony/Component/Validator/Constraints/TrueValidator.php @@ -36,9 +36,9 @@ public function validate($value, Constraint $constraint) } 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(); } } } diff --git a/src/Symfony/Component/Validator/Constraints/TypeValidator.php b/src/Symfony/Component/Validator/Constraints/TypeValidator.php index 002c1bd2aa565..ca6e5aa7ca0f4 100644 --- a/src/Symfony/Component/Validator/Constraints/TypeValidator.php +++ b/src/Symfony/Component/Validator/Constraints/TypeValidator.php @@ -48,9 +48,9 @@ public function validate($value, Constraint $constraint) 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(); } } diff --git a/src/Symfony/Component/Validator/Constraints/UrlValidator.php b/src/Symfony/Component/Validator/Constraints/UrlValidator.php index 70469592f8e41..3d184775acd5d 100644 --- a/src/Symfony/Component/Validator/Constraints/UrlValidator.php +++ b/src/Symfony/Component/Validator/Constraints/UrlValidator.php @@ -59,9 +59,9 @@ public function validate($value, Constraint $constraint) $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(); } } } diff --git a/src/Symfony/Component/Validator/Constraints/UuidValidator.php b/src/Symfony/Component/Validator/Constraints/UuidValidator.php index 9f1e1abb84e83..5361f12de0f0a 100644 --- a/src/Symfony/Component/Validator/Constraints/UuidValidator.php +++ b/src/Symfony/Component/Validator/Constraints/UuidValidator.php @@ -19,6 +19,7 @@ * Validates whether the value is a valid UUID per RFC 4122. * * @author Colin O'Dell + * @author Bernhard Schussek * * @see http://tools.ietf.org/html/rfc4122 * @see https://en.wikipedia.org/wiki/Universally_unique_identifier @@ -64,19 +65,43 @@ public function validate($value, Constraint $constraint) $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(); } } } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/CallbackValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/CallbackValidatorTest.php index f92f23ec6288f..9bb12a25361b6 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/CallbackValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/CallbackValidatorTest.php @@ -82,9 +82,9 @@ public function testSingleMethodExplicitName() $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 @@ public function testSingleStaticMethod() $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 @@ public function testClosure() $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 @@ public function testClosureNullObject() $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 @@ public function testClosureExplicitName() $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 @@ public function testArrayCallable() $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 @@ public function testArrayCallableNullObject() $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 @@ public function testArrayCallableExplicitName() $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 @@ public function testSingleMethodBc() $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 diff --git a/src/Symfony/Component/Validator/Tests/Constraints/ChoiceValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/ChoiceValidatorTest.php index a299dfc8718d8..84b5bc3b0d63b 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/ChoiceValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/ChoiceValidatorTest.php @@ -161,6 +161,7 @@ public function testInvalidChoiceMultiple() $this->buildViolation('myMessage') ->setParameter('{{ value }}', '"baz"') + ->setInvalidValue('baz') ->assertRaised(); } @@ -274,6 +275,7 @@ public function testStrictWithMultipleChoices() $this->buildViolation('myMessage') ->setParameter('{{ value }}', '"3"') + ->setInvalidValue('3') ->assertRaised(); } } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/CountValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/CountValidatorTest.php index f8ce076011547..31c7c7856288c 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/CountValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/CountValidatorTest.php @@ -65,14 +65,6 @@ public function getFourElements() ); } - public function getNotFourElements() - { - return array_merge( - $this->getThreeOrLessElements(), - $this->getFiveOrMoreElements() - ); - } - public function getFiveOrMoreElements() { return array( @@ -118,7 +110,7 @@ public function testValidValuesExact($value) /** * @dataProvider getFiveOrMoreElements */ - public function testInvalidValuesMax($value) + public function testTooManyValues($value) { $constraint = new Count(array( 'max' => 4, @@ -138,7 +130,7 @@ public function testInvalidValuesMax($value) /** * @dataProvider getThreeOrLessElements */ - public function testInvalidValuesMin($value) + public function testTooFewValues($value) { $constraint = new Count(array( 'min' => 4, @@ -156,9 +148,30 @@ public function testInvalidValuesMin($value) } /** - * @dataProvider getNotFourElements + * @dataProvider getFiveOrMoreElements + */ + 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 testInvalidValuesExact($value) + public function testTooFewValuesExact($value) { $constraint = new Count(array( 'min' => 4, diff --git a/src/Symfony/Component/Validator/Tests/Constraints/ExpressionValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/ExpressionValidatorTest.php index 1e90c09e31c3b..378f531936373 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/ExpressionValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/ExpressionValidatorTest.php @@ -71,7 +71,9 @@ public function testFailingExpressionAtObjectLevel() $this->validator->validate($object, $constraint); - $this->assertViolation('myMessage'); + $this->buildViolation('myMessage') + ->setParameter('{{ value }}', 'object') + ->assertRaised(); } public function testSucceedingExpressionAtPropertyLevel() @@ -106,7 +108,10 @@ public function testFailingExpressionAtPropertyLevel() $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 @@ public function testFailingExpressionAtNestedPropertyLevel() $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 @@ public function testFailingExpressionAtPropertyLevelWithoutRoot() $this->validator->validate('2', $constraint); - $this->assertViolation('myMessage', array(), ''); + $this->buildViolation('myMessage') + ->setParameter('{{ value }}', '"2"') + ->atPath('') + ->assertRaised(); } } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/ImageValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/ImageValidatorTest.php index dffbae3967875..5d6c9a91ff4dc 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/ImageValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/ImageValidatorTest.php @@ -202,10 +202,10 @@ public function testRatioTooSmall() $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 @@ public function testRatioTooBig() $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 @@ public function testSquareNotAllowed() $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 @@ public function testLandscapeNotAllowed() $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 @@ public function testPortraitNotAllowed() $this->validator->validate($this->imagePortrait, $constraint); - $this->assertViolation('myMessage', array( - '{{ width }}' => 1, - '{{ height }}' => 2, - )); + $this->buildViolation('myMessage') + ->setParameter('{{ width }}', 1) + ->setParameter('{{ height }}', 2) + ->assertRaised(); } } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/IsbnValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/IsbnValidatorTest.php index 6f80e66a45dd0..296ab7c94a3ab 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/IsbnValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/IsbnValidatorTest.php @@ -52,10 +52,11 @@ public function getValidIsbn10() 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 @@ public function getValidIsbn13() 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 @@ public function testInvalidIsbn13($isbn) /** * @dataProvider getValidIsbn */ - public function testValidIsbn($isbn) + public function testValidIsbnAny($isbn) { $constraint = new Isbn(); @@ -223,9 +224,25 @@ public function testValidIsbn($isbn) } /** - * @dataProvider getInvalidIsbn + * @dataProvider getInvalidIsbn10 + */ + 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 testInvalidIsbn($isbn) + public function testInvalidIsbnAnyIsbn13($isbn) { $constraint = new Isbn(array( 'bothIsbnMessage' => 'myMessage', diff --git a/src/Symfony/Component/Validator/Tests/Constraints/IssnValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/IssnValidatorTest.php index 4d353cd2b8198..cb7ae3d8925dc 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/IssnValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/IssnValidatorTest.php @@ -79,18 +79,12 @@ public function getValidIssn() ); } - 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 @@ public function getInvalidValueIssn() ); } - public function getInvalidIssn() - { - return array_merge( - $this->getInvalidFormatedIssn(), - $this->getInvalidValueIssn() - ); - } - public function testNullIsValid() { $constraint = new Issn(); @@ -180,38 +166,6 @@ public function testValidIssn($issn) $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 */ diff --git a/src/Symfony/Component/Validator/Tests/Constraints/LengthValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/LengthValidatorTest.php index ab0d0ff9c9b72..7674ae24272e3 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/LengthValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/LengthValidatorTest.php @@ -73,14 +73,6 @@ public function getFourCharacters() ); } - public function getNotFourCharacters() - { - return array_merge( - $this->getThreeOrLessCharacters(), - $this->getFiveOrMoreCharacters() - ); - } - public function getFiveOrMoreCharacters() { return array( @@ -189,9 +181,34 @@ public function testInvalidValuesMax($value, $mbOnly = false) } /** - * @dataProvider getNotFourCharacters + * @dataProvider getThreeOrLessCharacters + */ + 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 testInvalidValuesExact($value, $mbOnly = false) + public function testInvalidValuesExactMoreThanFour($value, $mbOnly = false) { if ($mbOnly && !function_exists('mb_strlen')) { $this->markTestSkipped('mb_strlen does not exist'); diff --git a/src/Symfony/Component/Validator/Tests/Constraints/LuhnValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/LuhnValidatorTest.php index d395056f00067..4ad3c736eb09d 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/LuhnValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/LuhnValidatorTest.php @@ -97,6 +97,8 @@ public function getInvalidNumbers() array('1234567812345678'), array('4222222222222222'), array('0000000000000000'), + array('000000!000000000'), + array('42-22222222222222'), ); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/RangeValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/RangeValidatorTest.php index 9ed2b094b2770..81f3ce624dfb2 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/RangeValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/RangeValidatorTest.php @@ -188,38 +188,6 @@ public function getInvalidValues() ); } - 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( diff --git a/src/Symfony/Component/Validator/Tests/Constraints/UuidValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/UuidValidatorTest.php index 296464ae379e4..b34ce8138b707 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/UuidValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/UuidValidatorTest.php @@ -83,9 +83,9 @@ public function testInvalidStrictUuids($uuid) $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 @@ public function testVersionConstraintIsInvalid($uuid) $this->validator->validate($uuid, $constraint); - $this->assertViolation('myMessage', array( - '{{ value }}' => $uuid, - )); + $this->buildViolation('myMessage') + ->setParameter('{{ value }}', '"'.$uuid.'"') + ->assertRaised(); } /** @@ -177,9 +177,9 @@ public function testInvalidNonStrictUuids($uuid) $this->validator->validate($uuid, $constraint); - $this->assertViolation('myMessage', array( - '{{ value }}' => $uuid, - )); + $this->buildViolation('myMessage') + ->setParameter('{{ value }}', '"'.$uuid.'"') + ->assertRaised(); } public function getInvalidNonStrictUuids() diff --git a/src/Symfony/Component/Validator/Violation/LegacyConstraintViolationBuilder.php b/src/Symfony/Component/Validator/Violation/LegacyConstraintViolationBuilder.php new file mode 100644 index 0000000000000..06cfdb60fbd5b --- /dev/null +++ b/src/Symfony/Component/Validator/Violation/LegacyConstraintViolationBuilder.php @@ -0,0 +1,165 @@ + + * + * 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 + * + * @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); + } +} pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy