merged branch Herzult/feature/collection_size_validator (PR #4149)
Commits -------3a5e84f
[Validator] Add CollectionSize constraint Discussion ---------- [Validator] Add CollectionSize constraint Bug fix: no Feature addition: yes Backwards compatibility break: no Symfony2 tests pass: yes Fixes the following tickets: - Todo: - I will also send a PR to the documentation as soon as this one is accepted. --------------------------------------------------------------------------- by bschussek at 2012-04-29T08:24:28Z -1 I dislike the rising amount of very specific constraints in the core. Can't we add this to Size? --------------------------------------------------------------------------- by vicb at 2012-04-29T09:01:39Z @bschussek #3918 implements what you propose but then the messages are not valid any more: ```php <?php public $minMessage = 'This value should be {{ limit }} or more'; public $maxMessage = 'This value should be {{ limit }} or less'; public $invalidMessage = 'This value should be a valid number'; ``` I can imagine 2 solutions: - adding some more message, - rename the `Size` constraint to `Range` and create a new `Size` constraint for arrays / countables. What do you think ? --------------------------------------------------------------------------- by bschussek at 2012-04-29T09:27:53Z I'd prefer the second solution and merge `Size` with `SizeLength` as well. --------------------------------------------------------------------------- by vicb at 2012-04-29T09:34:50Z @bschussek It would make sense. @makasim @Herzult any one of you would like to contribute this (i.e. rename the current Size to Range and create a new Size supporting arrays / countables / strings) ? --------------------------------------------------------------------------- by Herzult at 2012-04-29T14:31:12Z Yep, I'm on it. --------------------------------------------------------------------------- by stof at 2012-04-29T15:22:44Z @Herzult could you take the other comment into account and merge SizeLength into you Size ? --------------------------------------------------------------------------- by vicb at 2012-04-29T15:33:05Z The guessers should also be modified (it might also affect the ODM which is in an other repo, if so it would be good to sync the changes). --------------------------------------------------------------------------- by Herzult at 2012-04-29T16:38:19Z @stof the problem merging SizeLength into Size is that they don't have the same required options & messages. --------------------------------------------------------------------------- by Herzult at 2012-04-29T16:47:40Z And what about renaming Range to Interval and SizeLength to IntervalLength? --------------------------------------------------------------------------- by stof at 2012-04-29T16:54:38Z Well, SizeLength is about matching the length of a string currently. Nothing related to intervals --------------------------------------------------------------------------- by Herzult at 2012-04-29T17:29:40Z Here are the current names: * **Size** for collection (countable) size * **Range** for numbers * **SizeLength** for strings Merging **SizeLength** into **Size** is maybe not appropriate because collections and strings are different things. It'll be hard to find messages that fit both collections and strings. Maybe we had better to find a better name for both. What do you think? About the ValidatorTypeGuesser, I'll update it as soon as we know ow to name the constraints. --------------------------------------------------------------------------- by vicb at 2012-04-29T17:43:01Z Size is a good name for both strings and "collections", could we have two sets of strings and select according to the type ? --------------------------------------------------------------------------- by Herzult at 2012-04-29T22:39:55Z I tried to merge them together, what do you think? --------------------------------------------------------------------------- by vicb at 2012-04-30T06:52:37Z I think your changes are great, may be @bschussek has more feedback. The ValidatorTypeGuesser and the translation are yet to be updated. --------------------------------------------------------------------------- by hhamon at 2012-05-01T12:32:28Z Am I missing something or `SizeLength` for strings is a duplicate for `MinLength` and `MaxLength` constraints? --------------------------------------------------------------------------- by Herzult at 2012-05-02T13:29:36Z Yep, that's true. But the only link between this PR and the SizeLength constraint is that I merged it to the one I introduced. --------------------------------------------------------------------------- by Herzult at 2012-05-07T07:48:01Z @bschussek what do you think? --------------------------------------------------------------------------- by vicb at 2012-05-10T19:51:26Z @Herzult this PR looks good to me, could you update the changelog and update guides, try to factorize the code and squash the commits ? Thanks. --------------------------------------------------------------------------- by travisbot at 2012-05-11T15:42:35Z This pull request [passes](http://travis-ci.org/symfony/symfony/builds/1306112) (merged 8d8e6443 into4ac3bddb
). --------------------------------------------------------------------------- by vicb at 2012-05-11T21:42:21Z * could #4259 be helpful ? * please squash the commits. * please create a PR / issue on [symfony-docs](https://github.com/symfony/symfony-docs) thanks for the updates. --------------------------------------------------------------------------- by travisbot at 2012-05-13T18:38:18Z This pull request [fails](http://travis-ci.org/symfony/symfony/builds/1321123) (merged eeda9044 into4ac3bddb
). --------------------------------------------------------------------------- by travisbot at 2012-05-13T18:45:12Z This pull request [passes](http://travis-ci.org/symfony/symfony/builds/1321146) (merged 491ca19a into8b54eb56
). --------------------------------------------------------------------------- by travisbot at 2012-05-14T11:29:39Z This pull request [passes](http://travis-ci.org/symfony/symfony/builds/1326110) (merged 44865024 into8b54eb56
). --------------------------------------------------------------------------- by vicb at 2012-05-14T11:49:37Z @Herzult what about plural translations ? --------------------------------------------------------------------------- by travisbot at 2012-05-14T16:52:37Z This pull request [passes](http://travis-ci.org/symfony/symfony/builds/1328677) (merged 93480f95 into46ffbd52
). --------------------------------------------------------------------------- by travisbot at 2012-05-14T17:03:13Z This pull request [passes](http://travis-ci.org/symfony/symfony/builds/1328705) (merged 326c3b81 into46ffbd52
). --------------------------------------------------------------------------- by vicb at 2012-05-14T20:19:18Z thanks for the updates, this PR looks fine to me. @bschussek ? --------------------------------------------------------------------------- by vicb at 2012-05-16T06:45:51Z @Herzult can you squash your commits ? --------------------------------------------------------------------------- by travisbot at 2012-05-16T11:20:44Z This pull request [passes](http://travis-ci.org/symfony/symfony/builds/1344811) (merged3a5e84f4
into58b6ef23
).
This commit is contained in:
commit
5314836d3c
@ -214,6 +214,18 @@
|
|||||||
<source>A PHP extension caused the upload to fail.</source>
|
<source>A PHP extension caused the upload to fail.</source>
|
||||||
<target>A PHP extension caused the upload to fail.</target>
|
<target>A PHP extension caused the upload to fail.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="54">
|
||||||
|
<source>This collection should contain {{ limit }} elements or more.</source>
|
||||||
|
<target>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</target>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="55">
|
||||||
|
<source>This collection should contain {{ limit }} elements or less.</source>
|
||||||
|
<target>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</target>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="56">
|
||||||
|
<source>This collection should contain exactly {{ limit }} elements.</source>
|
||||||
|
<target>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</target>
|
||||||
|
</trans-unit>
|
||||||
</body>
|
</body>
|
||||||
</file>
|
</file>
|
||||||
</xliff>
|
</xliff>
|
||||||
|
@ -76,7 +76,7 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="19">
|
<trans-unit id="19">
|
||||||
<source>This value is too long. It should have {{ limit }} characters or less.</source>
|
<source>This value is too long. It should have {{ limit }} characters or less.</source>
|
||||||
<target>Cette chaine est trop longue. Elle doit avoir au maximum {{ limit }} caractères.</target>
|
<target>Cette chaine est trop longue. Elle doit avoir au maximum {{ limit }} caractère.|Cette chaine est trop longue. Elle doit avoir au maximum {{ limit }} caractères.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="20">
|
<trans-unit id="20">
|
||||||
<source>This value should be {{ limit }} or more.</source>
|
<source>This value should be {{ limit }} or more.</source>
|
||||||
@ -84,7 +84,7 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="21">
|
<trans-unit id="21">
|
||||||
<source>This value is too short. It should have {{ limit }} characters or more.</source>
|
<source>This value is too short. It should have {{ limit }} characters or more.</source>
|
||||||
<target>Cette chaine est trop courte. Elle doit avoir au minimum {{ limit }} caractères.</target>
|
<target>Cette chaine est trop courte. Elle doit avoir au minimum {{ limit }} caractère.|Cette chaine est trop courte. Elle doit avoir au minimum {{ limit }} caractères.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="22">
|
<trans-unit id="22">
|
||||||
<source>This value should not be blank.</source>
|
<source>This value should not be blank.</source>
|
||||||
@ -192,7 +192,7 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="48">
|
<trans-unit id="48">
|
||||||
<source>This value should have exactly {{ limit }} characters.</source>
|
<source>This value should have exactly {{ limit }} characters.</source>
|
||||||
<target>Cette chaine doit avoir exactement {{ limit }} caractères.</target>
|
<target>Cette chaine doit avoir exactement {{ limit }} caractère.|Cette chaine doit avoir exactement {{ limit }} caractères.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="49">
|
<trans-unit id="49">
|
||||||
<source>The file was only partially uploaded.</source>
|
<source>The file was only partially uploaded.</source>
|
||||||
@ -214,6 +214,18 @@
|
|||||||
<source>A PHP extension caused the upload to fail.</source>
|
<source>A PHP extension caused the upload to fail.</source>
|
||||||
<target>Une extension PHP a empêché le transfert du fichier.</target>
|
<target>Une extension PHP a empêché le transfert du fichier.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="54">
|
||||||
|
<source>This collection should contain {{ limit }} elements or more.</source>
|
||||||
|
<target>Cette collection doit contenir {{ limit }} élément ou plus.|Cette collection doit contenir {{ limit }} éléments ou plus.</target>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="55">
|
||||||
|
<source>This collection should contain {{ limit }} elements or less.</source>
|
||||||
|
<target>Cette collection doit contenir {{ limit }} élément ou moins.|Cette collection doit contenir {{ limit }} éléments ou moins.</target>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="56">
|
||||||
|
<source>This collection should contain exactly {{ limit }} elements.</source>
|
||||||
|
<target>Cette collection doit contenir exactement {{ limit }} élément.|Cette collection doit contenir exactement {{ limit }} éléments.</target>
|
||||||
|
</trans-unit>
|
||||||
</body>
|
</body>
|
||||||
</file>
|
</file>
|
||||||
</xliff>
|
</xliff>
|
||||||
|
@ -155,11 +155,19 @@ class ValidatorTypeGuesser implements FormTypeGuesserInterface
|
|||||||
case 'Symfony\Component\Validator\Constraints\MaxLength':
|
case 'Symfony\Component\Validator\Constraints\MaxLength':
|
||||||
case 'Symfony\Component\Validator\Constraints\MinLength':
|
case 'Symfony\Component\Validator\Constraints\MinLength':
|
||||||
case 'Symfony\Component\Validator\Constraints\Regex':
|
case 'Symfony\Component\Validator\Constraints\Regex':
|
||||||
case 'Symfony\Component\Validator\Constraints\SizeLength':
|
|
||||||
return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE);
|
return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE);
|
||||||
|
|
||||||
case 'Symfony\Component\Validator\Constraints\Min':
|
|
||||||
case 'Symfony\Component\Validator\Constraints\Size':
|
case 'Symfony\Component\Validator\Constraints\Size':
|
||||||
|
switch ($constraint->type) {
|
||||||
|
case 'string':
|
||||||
|
return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE);
|
||||||
|
case 'collection':
|
||||||
|
return new TypeGuess('collection', array(), Guess::MEDIUM_CONFIDENCE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Symfony\Component\Validator\Constraints\Min':
|
||||||
|
case 'Symfony\Component\Validator\Constraints\Range':
|
||||||
case 'Symfony\Component\Validator\Constraints\Max':
|
case 'Symfony\Component\Validator\Constraints\Max':
|
||||||
return new TypeGuess('number', array(), Guess::LOW_CONFIDENCE);
|
return new TypeGuess('number', array(), Guess::LOW_CONFIDENCE);
|
||||||
}
|
}
|
||||||
@ -194,8 +202,11 @@ class ValidatorTypeGuesser implements FormTypeGuesserInterface
|
|||||||
case 'Symfony\Component\Validator\Constraints\MaxLength':
|
case 'Symfony\Component\Validator\Constraints\MaxLength':
|
||||||
return new ValueGuess($constraint->limit, Guess::HIGH_CONFIDENCE);
|
return new ValueGuess($constraint->limit, Guess::HIGH_CONFIDENCE);
|
||||||
|
|
||||||
case 'Symfony\Component\Validator\Constraints\SizeLength':
|
case 'Symfony\Component\Validator\Constraints\Size':
|
||||||
|
if ('string' === $constraint->type && null !== $constraint->max) {
|
||||||
return new ValueGuess($constraint->max, Guess::HIGH_CONFIDENCE);
|
return new ValueGuess($constraint->max, Guess::HIGH_CONFIDENCE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case 'Symfony\Component\Validator\Constraints\Type':
|
case 'Symfony\Component\Validator\Constraints\Type':
|
||||||
if (in_array($constraint->type, array('double', 'float', 'numeric', 'real'))) {
|
if (in_array($constraint->type, array('double', 'float', 'numeric', 'real'))) {
|
||||||
@ -206,7 +217,7 @@ class ValidatorTypeGuesser implements FormTypeGuesserInterface
|
|||||||
case 'Symfony\Component\Validator\Constraints\Max':
|
case 'Symfony\Component\Validator\Constraints\Max':
|
||||||
return new ValueGuess(strlen((string) $constraint->limit), Guess::LOW_CONFIDENCE);
|
return new ValueGuess(strlen((string) $constraint->limit), Guess::LOW_CONFIDENCE);
|
||||||
|
|
||||||
case 'Symfony\Component\Validator\Constraints\Size':
|
case 'Symfony\Component\Validator\Constraints\Range':
|
||||||
return new ValueGuess(strlen((string) $constraint->max), Guess::LOW_CONFIDENCE);
|
return new ValueGuess(strlen((string) $constraint->max), Guess::LOW_CONFIDENCE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -224,7 +235,23 @@ class ValidatorTypeGuesser implements FormTypeGuesserInterface
|
|||||||
case 'Symfony\Component\Validator\Constraints\MinLength':
|
case 'Symfony\Component\Validator\Constraints\MinLength':
|
||||||
return new ValueGuess(sprintf('.{%s,}', (string) $constraint->limit), Guess::LOW_CONFIDENCE);
|
return new ValueGuess(sprintf('.{%s,}', (string) $constraint->limit), Guess::LOW_CONFIDENCE);
|
||||||
|
|
||||||
case 'Symfony\Component\Validator\Constraints\SizeLength':
|
case 'Symfony\Component\Validator\Constraints\Size':
|
||||||
|
if ('string' !== $constraint->type) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($constraint->min === $constraint->max) {
|
||||||
|
return new ValueGuess(sprintf('.{%s}', (string) $constraint->min), Guess::LOW_CONFIDENCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null === $constraint->min) {
|
||||||
|
return new ValueGuess(sprintf('.{0,%s}', (string) $constraint->max), Guess::LOW_CONFIDENCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null === $constraint->max) {
|
||||||
|
return new ValueGuess(sprintf('.{%s,}', (string) $constraint->min), Guess::LOW_CONFIDENCE);
|
||||||
|
}
|
||||||
|
|
||||||
return new ValueGuess(sprintf('.{%s,%s}', (string) $constraint->min, (string) $constraint->max), Guess::LOW_CONFIDENCE);
|
return new ValueGuess(sprintf('.{%s,%s}', (string) $constraint->min, (string) $constraint->max), Guess::LOW_CONFIDENCE);
|
||||||
|
|
||||||
case 'Symfony\Component\Validator\Constraints\Regex':
|
case 'Symfony\Component\Validator\Constraints\Regex':
|
||||||
@ -233,7 +260,7 @@ class ValidatorTypeGuesser implements FormTypeGuesserInterface
|
|||||||
case 'Symfony\Component\Validator\Constraints\Min':
|
case 'Symfony\Component\Validator\Constraints\Min':
|
||||||
return new ValueGuess(sprintf('.{%s,}', strlen((string) $constraint->limit)), Guess::LOW_CONFIDENCE);
|
return new ValueGuess(sprintf('.{%s,}', strlen((string) $constraint->limit)), Guess::LOW_CONFIDENCE);
|
||||||
|
|
||||||
case 'Symfony\Component\Validator\Constraints\Size':
|
case 'Symfony\Component\Validator\Constraints\Range':
|
||||||
return new ValueGuess(sprintf('.{%s,%s}', strlen((string) $constraint->min), strlen((string) $constraint->max)), Guess::LOW_CONFIDENCE);
|
return new ValueGuess(sprintf('.{%s,%s}', strlen((string) $constraint->min), strlen((string) $constraint->max)), Guess::LOW_CONFIDENCE);
|
||||||
|
|
||||||
case 'Symfony\Component\Validator\Constraints\Type':
|
case 'Symfony\Component\Validator\Constraints\Type':
|
||||||
|
@ -5,8 +5,8 @@ CHANGELOG
|
|||||||
-----
|
-----
|
||||||
|
|
||||||
* added support for `ctype_*` assertions in `TypeValidator`
|
* added support for `ctype_*` assertions in `TypeValidator`
|
||||||
* added a Size validator
|
* added a Range validator for numeric values
|
||||||
* added a SizeLength validator
|
* added a Size validator for string & collections
|
||||||
* improved the ImageValidator with min width, max width, min height, and max height constraints
|
* improved the ImageValidator with min width, max width, min height, and max height constraints
|
||||||
* added support for MIME with wildcard in FileValidator
|
* added support for MIME with wildcard in FileValidator
|
||||||
* changed Collection validator to add "missing" and "extra" errors to
|
* changed Collection validator to add "missing" and "extra" errors to
|
||||||
|
@ -18,14 +18,13 @@ use Symfony\Component\Validator\Constraint;
|
|||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
class SizeLength extends Constraint
|
class Range extends Constraint
|
||||||
{
|
{
|
||||||
public $minMessage = 'This value is too short. It should have {{ limit }} characters or more.';
|
public $minMessage = 'This value should be {{ limit }} or more.';
|
||||||
public $maxMessage = 'This value is too long. It should have {{ limit }} characters or less.';
|
public $maxMessage = 'This value should be {{ limit }} or less.';
|
||||||
public $exactMessage = 'This value should have exactly {{ limit }} characters.';
|
public $invalidMessage = 'This value should be a valid number.';
|
||||||
public $min;
|
public $min;
|
||||||
public $max;
|
public $max;
|
||||||
public $charset = 'UTF-8';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
@ -13,12 +13,13 @@ namespace Symfony\Component\Validator\Constraints;
|
|||||||
|
|
||||||
use Symfony\Component\Validator\Constraint;
|
use Symfony\Component\Validator\Constraint;
|
||||||
use Symfony\Component\Validator\ConstraintValidator;
|
use Symfony\Component\Validator\ConstraintValidator;
|
||||||
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
class SizeLengthValidator extends ConstraintValidator
|
class RangeValidator extends ConstraintValidator
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Checks if the passed value is valid.
|
* Checks if the passed value is valid.
|
||||||
@ -26,51 +27,38 @@ class SizeLengthValidator extends ConstraintValidator
|
|||||||
* @param mixed $value The value that should be validated
|
* @param mixed $value The value that should be validated
|
||||||
* @param Constraint $constraint The constraint for the validation
|
* @param Constraint $constraint The constraint for the validation
|
||||||
*
|
*
|
||||||
|
* @return Boolean Whether or not the value is valid
|
||||||
|
*
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
public function validate($value, Constraint $constraint)
|
public function validate($value, Constraint $constraint)
|
||||||
{
|
{
|
||||||
if (null === $value || '' === $value) {
|
if (null === $value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
|
if (!is_numeric($value)) {
|
||||||
throw new UnexpectedTypeException($value, 'string');
|
$this->context->addViolation($constraint->invalidMessage, array(
|
||||||
}
|
|
||||||
|
|
||||||
$value = (string) $value;
|
|
||||||
|
|
||||||
if (function_exists('grapheme_strlen') && 'UTF-8' === $constraint->charset) {
|
|
||||||
$length = grapheme_strlen($value);
|
|
||||||
} elseif (function_exists('mb_strlen')) {
|
|
||||||
$length = mb_strlen($value, $constraint->charset);
|
|
||||||
} else {
|
|
||||||
$length = strlen($value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($constraint->min == $constraint->max && $length != $constraint->max) {
|
|
||||||
$this->context->addViolation($constraint->exactMessage, array(
|
|
||||||
'{{ value }}' => $value,
|
'{{ value }}' => $value,
|
||||||
'{{ limit }}' => $constraint->max,
|
));
|
||||||
), null, (int) $constraint->max);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($length > $constraint->max) {
|
if ($value > $constraint->max) {
|
||||||
$this->context->addViolation($constraint->maxMessage, array(
|
$this->context->addViolation($constraint->maxMessage, array(
|
||||||
'{{ value }}' => $value,
|
'{{ value }}' => $value,
|
||||||
'{{ limit }}' => $constraint->max,
|
'{{ limit }}' => $constraint->max,
|
||||||
), null, (int) $constraint->max);
|
));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($length < $constraint->min) {
|
if ($value < $constraint->min) {
|
||||||
$this->context->addViolation($constraint->minMessage, array(
|
$this->context->addViolation($constraint->minMessage, array(
|
||||||
'{{ value }}' => $value,
|
'{{ value }}' => $value,
|
||||||
'{{ limit }}' => $constraint->min,
|
'{{ limit }}' => $constraint->min,
|
||||||
), null, (int) $constraint->min);
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -20,17 +20,70 @@ use Symfony\Component\Validator\Constraint;
|
|||||||
*/
|
*/
|
||||||
class Size extends Constraint
|
class Size extends Constraint
|
||||||
{
|
{
|
||||||
public $minMessage = 'This value should be {{ limit }} or more.';
|
const TYPE_STRING = 'string';
|
||||||
public $maxMessage = 'This value should be {{ limit }} or less.';
|
const TYPE_COLLECTION = 'collection';
|
||||||
public $invalidMessage = 'This value should be a valid number.';
|
|
||||||
|
public $minMessage;
|
||||||
|
public $maxMessage;
|
||||||
|
public $exactMessage;
|
||||||
|
public $type;
|
||||||
public $min;
|
public $min;
|
||||||
public $max;
|
public $max;
|
||||||
|
public $charset = 'UTF-8';
|
||||||
|
|
||||||
/**
|
private $stringMinMessage = 'This value is too short. It should have {{ limit }} characters or more.';
|
||||||
* {@inheritDoc}
|
private $stringMaxMessage = 'This value is too long. It should have {{ limit }} characters or less.';
|
||||||
*/
|
private $stringExactMessage = 'This value should have exactly {{ limit }} characters.';
|
||||||
public function getRequiredOptions()
|
|
||||||
|
private $collectionMinMessage = 'This collection should contain {{ limit }} elements or more.';
|
||||||
|
private $collectionMaxMessage = 'This collection should contain {{ limit }} elements or less.';
|
||||||
|
private $collectionExactMessage = 'This collection should contain exactly {{ limit }} elements.';
|
||||||
|
|
||||||
|
public function getMinMessage($type)
|
||||||
{
|
{
|
||||||
return array('min', 'max');
|
if (null !== $this->minMessage) {
|
||||||
|
return $this->minMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($type) {
|
||||||
|
case static::TYPE_STRING:
|
||||||
|
return $this->stringMinMessage;
|
||||||
|
case static::TYPE_COLLECTION:
|
||||||
|
return $this->collectionMinMessage;
|
||||||
|
default:
|
||||||
|
throw new \InvalidArgumentException('Invalid type specified.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMaxMessage($type)
|
||||||
|
{
|
||||||
|
if (null !== $this->maxMessage) {
|
||||||
|
return $this->maxMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($type) {
|
||||||
|
case static::TYPE_STRING:
|
||||||
|
return $this->stringMaxMessage;
|
||||||
|
case static::TYPE_COLLECTION:
|
||||||
|
return $this->collectionMaxMessage;
|
||||||
|
default:
|
||||||
|
throw new \InvalidArgumentException('Invalid type specified.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getExactMessage($type)
|
||||||
|
{
|
||||||
|
if (null !== $this->exactMessage) {
|
||||||
|
return $this->exactMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($type) {
|
||||||
|
case static::TYPE_STRING:
|
||||||
|
return $this->stringExactMessage;
|
||||||
|
case static::TYPE_COLLECTION:
|
||||||
|
return $this->collectionExactMessage;
|
||||||
|
default:
|
||||||
|
throw new \InvalidArgumentException('Invalid type specified.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,52 +13,151 @@ namespace Symfony\Component\Validator\Constraints;
|
|||||||
|
|
||||||
use Symfony\Component\Validator\Constraint;
|
use Symfony\Component\Validator\Constraint;
|
||||||
use Symfony\Component\Validator\ConstraintValidator;
|
use Symfony\Component\Validator\ConstraintValidator;
|
||||||
|
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
|
||||||
|
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
|
||||||
*
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
class SizeValidator extends ConstraintValidator
|
class SizeValidator extends ConstraintValidator
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Checks if the passed value is valid.
|
* {@inheritDoc}
|
||||||
*
|
|
||||||
* @param mixed $value The value that should be validated
|
|
||||||
* @param Constraint $constraint The constraint for the validation
|
|
||||||
*
|
|
||||||
* @return Boolean Whether or not the value is valid
|
|
||||||
*
|
|
||||||
* @api
|
|
||||||
*/
|
*/
|
||||||
public function validate($value, Constraint $constraint)
|
public function validate($value, Constraint $constraint)
|
||||||
|
{
|
||||||
|
if (null === $constraint->min && null === $constraint->max) {
|
||||||
|
throw new ConstraintDefinitionException(
|
||||||
|
'Either "min" or "max" must be specified on constraint Size'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null === $constraint->type) {
|
||||||
|
$type = $this->guessType($value);
|
||||||
|
} else {
|
||||||
|
$type = $constraint->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($type) {
|
||||||
|
case Size::TYPE_STRING:
|
||||||
|
return $this->validateString($value, $constraint);
|
||||||
|
case Size::TYPE_COLLECTION:
|
||||||
|
return $this->validateCollection($value, $constraint);
|
||||||
|
default:
|
||||||
|
throw new ConstraintDefinitionException(sprintf(
|
||||||
|
'The "type" on constraint Size must be either "%s" or "%s", "%s" given.',
|
||||||
|
Size::TYPE_STRING,
|
||||||
|
Size::TYPE_COLLECTION,
|
||||||
|
$type
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function validateString($value, Constraint $constraint)
|
||||||
|
{
|
||||||
|
if (null === $value || '' === $value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
|
||||||
|
throw new UnexpectedTypeException($value, 'string, scalar or object with __toString()');
|
||||||
|
}
|
||||||
|
|
||||||
|
$value = (string) $value;
|
||||||
|
|
||||||
|
if (function_exists('grapheme_strlen') && 'UTF-8' === $constraint->charset) {
|
||||||
|
$length = grapheme_strlen($value);
|
||||||
|
} elseif (function_exists('mb_strlen')) {
|
||||||
|
$length = mb_strlen($value, $constraint->charset);
|
||||||
|
} else {
|
||||||
|
$length = strlen($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->validateSize(
|
||||||
|
$constraint,
|
||||||
|
$length,
|
||||||
|
Size::TYPE_STRING,
|
||||||
|
array('{{ value }}' => $value)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function validateCollection($value, Constraint $constraint)
|
||||||
{
|
{
|
||||||
if (null === $value) {
|
if (null === $value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_numeric($value)) {
|
if (!is_array($value) && !$value instanceof \Countable) {
|
||||||
$this->context->addViolation($constraint->invalidMessage, array(
|
throw new UnexpectedTypeException($value, 'array or Countable');
|
||||||
'{{ value }}' => $value,
|
}
|
||||||
));
|
|
||||||
|
$count = count($value);
|
||||||
|
|
||||||
|
$this->validateSize(
|
||||||
|
$constraint,
|
||||||
|
$count,
|
||||||
|
Size::TYPE_COLLECTION,
|
||||||
|
array('{{ count }}' => $count)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function validateSize(Constraint $constraint, $size, $type, array $parameters)
|
||||||
|
{
|
||||||
|
if ($constraint->min == $constraint->max && $size != $constraint->max) {
|
||||||
|
$this->context->addViolation(
|
||||||
|
$constraint->getExactMessage($type),
|
||||||
|
array_merge(array('{{ limit }}' => $constraint->max), $parameters),
|
||||||
|
null,
|
||||||
|
(int) $constraint->max
|
||||||
|
);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($value > $constraint->max) {
|
if (null !== $constraint->max && $size > $constraint->max) {
|
||||||
$this->context->addViolation($constraint->maxMessage, array(
|
$this->context->addViolation(
|
||||||
'{{ value }}' => $value,
|
$constraint->getMaxMessage($type),
|
||||||
'{{ limit }}' => $constraint->max,
|
array_merge(array('{{ limit }}' => $constraint->max), $parameters),
|
||||||
));
|
null,
|
||||||
|
(int) $constraint->max
|
||||||
|
);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($value < $constraint->min) {
|
if (null !== $constraint->min && $size < $constraint->min) {
|
||||||
$this->context->addViolation($constraint->minMessage, array(
|
$this->context->addViolation(
|
||||||
'{{ value }}' => $value,
|
$constraint->getMinMessage($type),
|
||||||
'{{ limit }}' => $constraint->min,
|
array_merge(array('{{ limit }}' => $constraint->min), $parameters),
|
||||||
));
|
null,
|
||||||
|
(int) $constraint->min
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function guessType($value)
|
||||||
|
{
|
||||||
|
if (null === $value || is_scalar($value)) {
|
||||||
|
return Size::TYPE_STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_object($value) && method_exists($value, '__toString')) {
|
||||||
|
if ($value instanceof \Countable) {
|
||||||
|
throw new \RuntimeException(
|
||||||
|
'The "type" must be specified on constraint Size because the '.
|
||||||
|
'validator is not able to guess it since the value is an object '.
|
||||||
|
'implementing both the __toString() method and the Countable '.
|
||||||
|
'interface.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Size::TYPE_STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_array($value) || $value instanceof \Countable) {
|
||||||
|
return Size::TYPE_COLLECTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new UnexpectedTypeException(
|
||||||
|
$value, 'scalar, string, array, Countable or object with __toString()'
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,121 @@
|
|||||||
|
<?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\Tests\Constraints;
|
||||||
|
|
||||||
|
use Symfony\Component\Validator\Constraints\Range;
|
||||||
|
use Symfony\Component\Validator\Constraints\RangeValidator;
|
||||||
|
|
||||||
|
class RangeValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
protected $context;
|
||||||
|
protected $validator;
|
||||||
|
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
$this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
|
||||||
|
$this->validator = new RangeValidator();
|
||||||
|
$this->validator->initialize($this->context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNullIsValid()
|
||||||
|
{
|
||||||
|
$this->context->expects($this->never())
|
||||||
|
->method('addViolation');
|
||||||
|
|
||||||
|
$this->validator->validate(null, new Range(array('min' => 10, 'max' => 20)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider getValidValues
|
||||||
|
*/
|
||||||
|
public function testValidValues($value)
|
||||||
|
{
|
||||||
|
$this->context->expects($this->never())
|
||||||
|
->method('addViolation');
|
||||||
|
|
||||||
|
$constraint = new Range(array('min' => 10, 'max' => 20));
|
||||||
|
$this->validator->validate($value, $constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getValidValues()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array(10.00001),
|
||||||
|
array(19.99999),
|
||||||
|
array('10.00001'),
|
||||||
|
array('19.99999'),
|
||||||
|
array(10),
|
||||||
|
array(20),
|
||||||
|
array(10.0),
|
||||||
|
array(20.0),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider getInvalidValues
|
||||||
|
*/
|
||||||
|
public function testInvalidValues($value)
|
||||||
|
{
|
||||||
|
$this->context->expects($this->once())
|
||||||
|
->method('addViolation');
|
||||||
|
|
||||||
|
$constraint = new Range(array('min' => 10, 'max' => 20));
|
||||||
|
$this->validator->validate($value, $constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getInvalidValues()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array(9.999999),
|
||||||
|
array(20.000001),
|
||||||
|
array('9.999999'),
|
||||||
|
array('20.000001'),
|
||||||
|
array(new \stdClass()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMinMessageIsSet()
|
||||||
|
{
|
||||||
|
$constraint = new Range(array(
|
||||||
|
'min' => 10,
|
||||||
|
'max' => 20,
|
||||||
|
'minMessage' => 'myMessage',
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->context->expects($this->once())
|
||||||
|
->method('addViolation')
|
||||||
|
->with('myMessage', array(
|
||||||
|
'{{ value }}' => 9,
|
||||||
|
'{{ limit }}' => 10,
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->validator->validate(9, $constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMaxMessageIsSet()
|
||||||
|
{
|
||||||
|
$constraint = new Range(array(
|
||||||
|
'min' => 10,
|
||||||
|
'max' => 20,
|
||||||
|
'maxMessage' => 'myMessage',
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->context->expects($this->once())
|
||||||
|
->method('addViolation')
|
||||||
|
->with('myMessage', array(
|
||||||
|
'{{ value }}' => 21,
|
||||||
|
'{{ limit }}' => 20,
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->validator->validate(21, $constraint);
|
||||||
|
}
|
||||||
|
}
|
@ -1,172 +0,0 @@
|
|||||||
<?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\Tests\Constraints;
|
|
||||||
|
|
||||||
use Symfony\Component\Validator\Constraints\SizeLength;
|
|
||||||
use Symfony\Component\Validator\Constraints\SizeLengthValidator;
|
|
||||||
|
|
||||||
class SizeLengthValidatorTest extends \PHPUnit_Framework_TestCase
|
|
||||||
{
|
|
||||||
protected $context;
|
|
||||||
protected $validator;
|
|
||||||
|
|
||||||
protected function setUp()
|
|
||||||
{
|
|
||||||
$this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
|
|
||||||
$this->validator = new SizeLengthValidator();
|
|
||||||
$this->validator->initialize($this->context);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function tearDown()
|
|
||||||
{
|
|
||||||
$this->context = null;
|
|
||||||
$this->validator = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testNullIsValid()
|
|
||||||
{
|
|
||||||
$this->context->expects($this->never())
|
|
||||||
->method('addViolation');
|
|
||||||
|
|
||||||
$this->validator->validate(null, new SizeLength(array('min' => 6, 'max' => 10)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testEmptyStringIsValid()
|
|
||||||
{
|
|
||||||
$this->context->expects($this->never())
|
|
||||||
->method('addViolation');
|
|
||||||
|
|
||||||
$this->validator->validate('', new SizeLength(array('min' => 6, 'max' => 10)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException Symfony\Component\Validator\Exception\UnexpectedTypeException
|
|
||||||
*/
|
|
||||||
public function testExpectsStringCompatibleType()
|
|
||||||
{
|
|
||||||
$this->validator->validate(new \stdClass(), new SizeLength(array('min' => 6, 'max' => 10)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dataProvider getValidValues
|
|
||||||
*/
|
|
||||||
public function testValidValues($value, $mbOnly = false)
|
|
||||||
{
|
|
||||||
if ($mbOnly && !function_exists('mb_strlen')) {
|
|
||||||
return $this->markTestSkipped('mb_strlen does not exist');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->context->expects($this->never())
|
|
||||||
->method('addViolation');
|
|
||||||
|
|
||||||
$constraint = new SizeLength(array('min' => 6, 'max' => 10));
|
|
||||||
$this->validator->validate($value, $constraint);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getValidValues()
|
|
||||||
{
|
|
||||||
return array(
|
|
||||||
array(123456),
|
|
||||||
array(1234567890),
|
|
||||||
array('123456'),
|
|
||||||
array('1234567890'),
|
|
||||||
array('üüüüüü', true),
|
|
||||||
array('üüüüüüüüüü', true),
|
|
||||||
array('éééééé', true),
|
|
||||||
array('éééééééééé', true),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dataProvider getInvalidValues
|
|
||||||
*/
|
|
||||||
public function testInvalidValues($value, $mbOnly = false)
|
|
||||||
{
|
|
||||||
if ($mbOnly && !function_exists('mb_strlen')) {
|
|
||||||
return $this->markTestSkipped('mb_strlen does not exist');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->context->expects($this->once())
|
|
||||||
->method('addViolation');
|
|
||||||
|
|
||||||
$constraint = new SizeLength(array('min' => 6, 'max' => 10));
|
|
||||||
$this->validator->validate($value, $constraint);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getInvalidValues()
|
|
||||||
{
|
|
||||||
return array(
|
|
||||||
array(12345),
|
|
||||||
array(12345678901),
|
|
||||||
array('12345'),
|
|
||||||
array('12345678901'),
|
|
||||||
array('üüüüü', true),
|
|
||||||
array('üüüüüüüüüüü', true),
|
|
||||||
array('ééééé', true),
|
|
||||||
array('ééééééééééé', true),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testMinMessageIsSet()
|
|
||||||
{
|
|
||||||
$constraint = new SizeLength(array(
|
|
||||||
'min' => 5,
|
|
||||||
'max' => 10,
|
|
||||||
'minMessage' => 'myMessage',
|
|
||||||
));
|
|
||||||
|
|
||||||
$this->context->expects($this->once())
|
|
||||||
->method('addViolation')
|
|
||||||
->with('myMessage', array(
|
|
||||||
'{{ value }}' => '1234',
|
|
||||||
'{{ limit }}' => 5,
|
|
||||||
), null, 5);
|
|
||||||
|
|
||||||
$this->validator->validate('1234', $constraint);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testMaxMessageIsSet()
|
|
||||||
{
|
|
||||||
$constraint = new SizeLength(array(
|
|
||||||
'min' => 5,
|
|
||||||
'max' => 10,
|
|
||||||
'maxMessage' => 'myMessage',
|
|
||||||
));
|
|
||||||
|
|
||||||
$this->context->expects($this->once())
|
|
||||||
->method('addViolation')
|
|
||||||
->with('myMessage', array(
|
|
||||||
'{{ value }}' => '12345678901',
|
|
||||||
'{{ limit }}' => 10,
|
|
||||||
), null, 10);
|
|
||||||
|
|
||||||
$this->validator->validate('12345678901', $constraint);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testExactMessageIsSet()
|
|
||||||
{
|
|
||||||
$constraint = new SizeLength(array(
|
|
||||||
'min' => 5,
|
|
||||||
'max' => 5,
|
|
||||||
'exactMessage' => 'myMessage',
|
|
||||||
));
|
|
||||||
|
|
||||||
$this->context->expects($this->once())
|
|
||||||
->method('addViolation')
|
|
||||||
->with('myMessage', array(
|
|
||||||
'{{ value }}' => '1234',
|
|
||||||
'{{ limit }}' => 5,
|
|
||||||
), null, 5);
|
|
||||||
|
|
||||||
$this->validator->validate('1234', $constraint);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,98 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\Validator\Tests\Constraints;
|
||||||
|
|
||||||
|
use Symfony\Component\Validator\Constraints\Size;
|
||||||
|
|
||||||
|
class SizeTest extends \PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @dataProvider getMinMessageData
|
||||||
|
*/
|
||||||
|
public function testGetMinMessage($options, $type, $expected)
|
||||||
|
{
|
||||||
|
$size = new Size($options);
|
||||||
|
$this->assertEquals($expected, $size->getMinMessage($type));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMinMessageData()
|
||||||
|
{
|
||||||
|
$size = new Size();
|
||||||
|
|
||||||
|
return array(
|
||||||
|
array(array(), Size::TYPE_STRING, $this->readAttribute($size, 'stringMinMessage')),
|
||||||
|
array(array(), Size::TYPE_COLLECTION, $this->readAttribute($size, 'collectionMinMessage')),
|
||||||
|
array(array('minMessage' => 'Custom min message'), Size::TYPE_STRING, 'Custom min message'),
|
||||||
|
array(array('minMessage' => 'Custom min message'), Size::TYPE_COLLECTION, 'Custom min message'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function testGetMinMessageWithInvalidType()
|
||||||
|
{
|
||||||
|
$size = new Size();
|
||||||
|
$size->getMinMessage('foo');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider getMaxMessageData
|
||||||
|
*/
|
||||||
|
public function testGetMaxMessage($options, $type, $expected)
|
||||||
|
{
|
||||||
|
$size = new Size($options);
|
||||||
|
$this->assertEquals($expected, $size->getMaxMessage($type));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMaxMessageData()
|
||||||
|
{
|
||||||
|
$size = new Size();
|
||||||
|
|
||||||
|
return array(
|
||||||
|
array(array(), Size::TYPE_STRING, $this->readAttribute($size, 'stringMaxMessage')),
|
||||||
|
array(array(), Size::TYPE_COLLECTION, $this->readAttribute($size, 'collectionMaxMessage')),
|
||||||
|
array(array('maxMessage' => 'Custom max message'), Size::TYPE_STRING, 'Custom max message'),
|
||||||
|
array(array('maxMessage' => 'Custom max message'), Size::TYPE_COLLECTION, 'Custom max message'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function testGetMaxMessageWithInvalidType()
|
||||||
|
{
|
||||||
|
$size = new Size();
|
||||||
|
$size->getMaxMessage('foo');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider getExactMessageData
|
||||||
|
*/
|
||||||
|
public function testGetExactMessage($options, $type, $expected)
|
||||||
|
{
|
||||||
|
$size = new Size($options);
|
||||||
|
$this->assertEquals($expected, $size->getExactMessage($type));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getExactMessageData()
|
||||||
|
{
|
||||||
|
$size = new Size();
|
||||||
|
|
||||||
|
return array(
|
||||||
|
array(array(), Size::TYPE_STRING, $this->readAttribute($size, 'stringExactMessage')),
|
||||||
|
array(array(), Size::TYPE_COLLECTION, $this->readAttribute($size, 'collectionExactMessage')),
|
||||||
|
array(array('exactMessage' => 'Custom exact message'), Size::TYPE_STRING, 'Custom exact message'),
|
||||||
|
array(array('exactMessage' => 'Custom exact message'), Size::TYPE_COLLECTION, 'Custom exact message'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function testGetExactMessageWithInvalidType()
|
||||||
|
{
|
||||||
|
$size = new Size();
|
||||||
|
$size->getExactMessage('foo');
|
||||||
|
}
|
||||||
|
}
|
@ -14,6 +14,19 @@ namespace Symfony\Component\Validator\Tests\Constraints;
|
|||||||
use Symfony\Component\Validator\Constraints\Size;
|
use Symfony\Component\Validator\Constraints\Size;
|
||||||
use Symfony\Component\Validator\Constraints\SizeValidator;
|
use Symfony\Component\Validator\Constraints\SizeValidator;
|
||||||
|
|
||||||
|
class SizeAmbiguous implements \Countable
|
||||||
|
{
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function count()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class SizeValidatorTest extends \PHPUnit_Framework_TestCase
|
class SizeValidatorTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
protected $context;
|
protected $context;
|
||||||
@ -28,94 +41,176 @@ class SizeValidatorTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
public function testNullIsValid()
|
public function testNullIsValid()
|
||||||
{
|
{
|
||||||
$this->context->expects($this->never())
|
$this->context->expects($this->never())->method('addViolation');
|
||||||
->method('addViolation');
|
|
||||||
|
|
||||||
$this->validator->validate(null, new Size(array('min' => 10, 'max' => 20)));
|
$this->validator->validate(null, new Size(array('min' => 10, 'max' => 20)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function testNullIsValidAsAString()
|
||||||
* @dataProvider getValidValues
|
|
||||||
*/
|
|
||||||
public function testValidValues($value)
|
|
||||||
{
|
{
|
||||||
|
$this->context->expects($this->never())->method('addViolation');
|
||||||
|
|
||||||
|
$this->validator->validate(null, new Size(array('type' => 'string', 'min' => 10, 'max' => 20)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNullIsValidAsACollectionCollection()
|
||||||
|
{
|
||||||
|
$this->context->expects($this->never())->method('addViolation');
|
||||||
|
|
||||||
|
$this->validator->validate(null, new Size(array('type' => 'collection', 'min' => 10, 'max' => 20)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testEmptyStringIsValid()
|
||||||
|
{
|
||||||
|
$this->context->expects($this->never())->method('addViolation');
|
||||||
|
|
||||||
|
$this->validator->validate('', new Size(array('min' => 10, 'max' => 20)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testEmptyStringIsValidAsAString()
|
||||||
|
{
|
||||||
|
$this->context->expects($this->never())->method('addViolation');
|
||||||
|
|
||||||
|
$this->validator->validate('', new Size(array('type' => 'string', 'min' => 10, 'max' => 20)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider getValidStringValues
|
||||||
|
*/
|
||||||
|
public function testValidStringValues($value, $mbOnly = false)
|
||||||
|
{
|
||||||
|
if ($mbOnly && !function_exists('mb_strlen')) {
|
||||||
|
return $this->markTestSkipped('mb_strlen does not exist');
|
||||||
|
}
|
||||||
|
|
||||||
$this->context->expects($this->never())
|
$this->context->expects($this->never())
|
||||||
->method('addViolation');
|
->method('addViolation');
|
||||||
|
|
||||||
$constraint = new Size(array('min' => 10, 'max' => 20));
|
$constraint = new Size(array('min' => 6, 'max' => 10));
|
||||||
$this->validator->validate($value, $constraint);
|
$this->validator->validate($value, $constraint);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getValidValues()
|
public function getValidStringValues()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
array(10.00001),
|
array(123456),
|
||||||
array(19.99999),
|
array(1234567890),
|
||||||
array('10.00001'),
|
array('123456'),
|
||||||
array('19.99999'),
|
array('1234567890'),
|
||||||
array(10),
|
array('üüüüüü', true),
|
||||||
array(20),
|
array('üüüüüüüüüü', true),
|
||||||
array(10.0),
|
array('éééééé', true),
|
||||||
array(20.0),
|
array('éééééééééé', true),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider getInvalidValues
|
* @dataProvider getInvalidStringValues
|
||||||
*/
|
*/
|
||||||
public function testInvalidValues($value)
|
public function testInvalidStringValues($value, $mbOnly = false)
|
||||||
{
|
{
|
||||||
$this->context->expects($this->once())
|
if ($mbOnly && !function_exists('mb_strlen')) {
|
||||||
->method('addViolation');
|
return $this->markTestSkipped('mb_strlen does not exist');
|
||||||
|
|
||||||
$constraint = new Size(array('min' => 10, 'max' => 20));
|
|
||||||
$this->validator->validate($value, $constraint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getInvalidValues()
|
$this->context->expects($this->once())->method('addViolation');
|
||||||
|
|
||||||
|
$this->validator->validate($value, new Size(array('min' => 6, 'max' => 10)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getInvalidStringValues()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
array(9.999999),
|
array(12345),
|
||||||
array(20.000001),
|
array(12345678901),
|
||||||
array('9.999999'),
|
array('12345'),
|
||||||
array('20.000001'),
|
array('12345678901'),
|
||||||
array(new \stdClass()),
|
array('üüüüü', true),
|
||||||
|
array('üüüüüüüüüüü', true),
|
||||||
|
array('ééééé', true),
|
||||||
|
array('ééééééééééé', true),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testMinMessageIsSet()
|
/**
|
||||||
|
* @dataProvider getValidCollectionValues
|
||||||
|
*/
|
||||||
|
public function testValidCollectionValue($value)
|
||||||
{
|
{
|
||||||
$constraint = new Size(array(
|
$this->context->expects($this->never())->method('addViolation');
|
||||||
'min' => 10,
|
|
||||||
'max' => 20,
|
|
||||||
'minMessage' => 'myMessage',
|
|
||||||
));
|
|
||||||
|
|
||||||
$this->context->expects($this->once())
|
$this->validator->validate($value, new Size(array('min' => 10, 'max' => 20)));
|
||||||
->method('addViolation')
|
|
||||||
->with('myMessage', array(
|
|
||||||
'{{ value }}' => 9,
|
|
||||||
'{{ limit }}' => 10,
|
|
||||||
));
|
|
||||||
|
|
||||||
$this->validator->validate(9, $constraint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testMaxMessageIsSet()
|
public function getValidCollectionValues()
|
||||||
{
|
{
|
||||||
$constraint = new Size(array(
|
$countable = $this->getMock('Countable');
|
||||||
'min' => 10,
|
$countable->expects($this->any())->method('count')->will($this->returnValue(15));
|
||||||
'max' => 20,
|
|
||||||
'maxMessage' => 'myMessage',
|
|
||||||
));
|
|
||||||
|
|
||||||
$this->context->expects($this->once())
|
return array(
|
||||||
->method('addViolation')
|
array($countable),
|
||||||
->with('myMessage', array(
|
array(range(1, 15)),
|
||||||
'{{ value }}' => 21,
|
);
|
||||||
'{{ limit }}' => 20,
|
}
|
||||||
));
|
|
||||||
|
|
||||||
$this->validator->validate(21, $constraint);
|
/**
|
||||||
|
* @dataProvider getInvalidCollectionValues
|
||||||
|
*/
|
||||||
|
public function testInvalidCollectionValue($value)
|
||||||
|
{
|
||||||
|
$this->context->expects($this->once())->method('addViolation');
|
||||||
|
|
||||||
|
$this->validator->validate($value, new Size(array('min' => 10, 'max' => 20)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getInvalidCollectionValues()
|
||||||
|
{
|
||||||
|
$tooSmallCountable = $this->getMock('Countable');
|
||||||
|
$tooSmallCountable->expects($this->any())->method('count')->will($this->returnValue(5));
|
||||||
|
|
||||||
|
$tooBigCountable = $this->getmock('countable');
|
||||||
|
$tooBigCountable->expects($this->any())->method('count')->will($this->returnValue(25));
|
||||||
|
|
||||||
|
return array(
|
||||||
|
array($tooSmallCountable),
|
||||||
|
array($tooBigCountable),
|
||||||
|
array(array()),
|
||||||
|
array(range(1, 5)),
|
||||||
|
array(range(1, 25)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException RuntimeException
|
||||||
|
*/
|
||||||
|
public function throwsAnExceptionWhenOnAmbiguousValue()
|
||||||
|
{
|
||||||
|
$this->validator->validate(new SizeAmbiguous(), new Size(array('min' => 10, 'max' => 20)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException Symfony\Component\Validator\Exception\UnexpectedTypeException
|
||||||
|
*/
|
||||||
|
public function testExpectsEitherStringOrCollectionCompatible()
|
||||||
|
{
|
||||||
|
$this->validator->validate(new \stdCLass(), new Size(array('min' => 10, 'max' => 20)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException Symfony\Component\Validator\Exception\UnexpectedTypeException
|
||||||
|
*/
|
||||||
|
public function testExpectsStringCompatibleType()
|
||||||
|
{
|
||||||
|
$countable = $this->getMock('Countable');
|
||||||
|
|
||||||
|
$this->validator->validate($countable, new Size(array('type' => 'string', 'min' => 6, 'max' => 10)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException Symfony\Component\Validator\Exception\UnexpectedTypeException
|
||||||
|
*/
|
||||||
|
public function testExpectsCollectionCompatibleType()
|
||||||
|
{
|
||||||
|
$this->validator->validate('string', new Size(array('type' => 'collection', 'min' => 6, 'max' => 10)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user