merged branch bschussek/size_deprecation (PR #4851)

Commits
-------

0be602d [Validator] Deprecated the Size constraint
d661837 [Validator] Reverted the changes done to the Size constraint in 3a5e84f4a7
d84b689 [Validator] Added the constraints MinCount and MaxCount
1a732e4 [Validator] Removed the Range constraint as it duplicates functionality given in Min and Max

Discussion
----------

[Validator] Deprecated the Size constraint in favor of MinCount and MaxCount

Bug fix: no
Feature addition: yes
Backwards compatibility break: no
Symfony2 tests pass: yes
Fixes the following tickets: -
Todo: -

This PR cleans up with the current ambiguity between

* Min
* Max
* MinLength
* MaxLength
* Range
* Size

in the following ways:

* The Range constraint was removed again as it can be completely replaced by Min and Max.
* The Size constraint was reverted to it's 2.0 feature set and deprecated.
* The constraints MinCount and MaxCount were added to make up for the functionality that was added to Size.
This commit is contained in:
Fabien Potencier 2012-07-11 15:50:35 +02:00
commit c3b79f1f15
28 changed files with 586 additions and 667 deletions

View File

@ -1136,6 +1136,26 @@
private $recursiveCollection;
```
* The `Size` constraint was deprecated and will be removed in Symfony 2.3. You should
use the constraints `Min` and `Max` instead.
Before:
```
/** @Assert\Size(min = 2, max = 16) */
private $numberOfCpus;
```
After:
```
/**
* @Assert\Min(2)
* @Assert\Max(16)
*/
private $numberOfCpus;
```
### Session
* Flash messages now return an array based on their type. The old method is

View File

@ -158,19 +158,14 @@ class ValidatorTypeGuesser implements FormTypeGuesserInterface
return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE);
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':
return new TypeGuess('number', array(), Guess::LOW_CONFIDENCE);
case 'Symfony\Component\Validator\Constraints\MinCount':
case 'Symfony\Component\Validator\Constraints\MaxCount':
return new TypeGuess('collection', array(), Guess::LOW_CONFIDENCE);
case 'Symfony\Component\Validator\Constraints\Time':
return new TypeGuess('time', array('input'=>'string'), Guess::HIGH_CONFIDENCE);
@ -208,12 +203,6 @@ class ValidatorTypeGuesser implements FormTypeGuesserInterface
case 'Symfony\Component\Validator\Constraints\MaxLength':
return new ValueGuess($constraint->limit, Guess::HIGH_CONFIDENCE);
case 'Symfony\Component\Validator\Constraints\Size':
if ('string' === $constraint->type && null !== $constraint->max) {
return new ValueGuess($constraint->max, Guess::HIGH_CONFIDENCE);
}
break;
case 'Symfony\Component\Validator\Constraints\Type':
if (in_array($constraint->type, array('double', 'float', 'numeric', 'real'))) {
return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE);
@ -223,7 +212,7 @@ class ValidatorTypeGuesser implements FormTypeGuesserInterface
case 'Symfony\Component\Validator\Constraints\Max':
return new ValueGuess(strlen((string) $constraint->limit), Guess::LOW_CONFIDENCE);
case 'Symfony\Component\Validator\Constraints\Range':
case 'Symfony\Component\Validator\Constraints\Size':
return new ValueGuess(strlen((string) $constraint->max), Guess::LOW_CONFIDENCE);
}
}
@ -241,25 +230,6 @@ class ValidatorTypeGuesser implements FormTypeGuesserInterface
case 'Symfony\Component\Validator\Constraints\MinLength':
return new ValueGuess(sprintf('.{%s,}', (string) $constraint->limit), Guess::LOW_CONFIDENCE);
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);
case 'Symfony\Component\Validator\Constraints\Regex':
$htmlPattern = $constraint->getHtmlPattern();
@ -271,7 +241,7 @@ class ValidatorTypeGuesser implements FormTypeGuesserInterface
case 'Symfony\Component\Validator\Constraints\Min':
return new ValueGuess(sprintf('.{%s,}', strlen((string) $constraint->limit)), Guess::LOW_CONFIDENCE);
case 'Symfony\Component\Validator\Constraints\Range':
case 'Symfony\Component\Validator\Constraints\Size':
return new ValueGuess(sprintf('.{%s,%s}', strlen((string) $constraint->min), strlen((string) $constraint->max)), Guess::LOW_CONFIDENCE);
case 'Symfony\Component\Validator\Constraints\Type':

View File

@ -5,8 +5,6 @@ CHANGELOG
-----
* added support for `ctype_*` assertions in `TypeValidator`
* added a Range validator for numeric values
* added a Size validator for string & collections
* improved the ImageValidator with min width, max width, min height, and max height constraints
* added support for MIME with wildcard in FileValidator
* changed Collection validator to add "missing" and "extra" errors to
@ -23,3 +21,5 @@ CHANGELOG
* [BC BREAK] collections in fields annotated with `Valid` are not traversed
recursively anymore by default. `Valid` contains a new property `deep`
which enables the BC behavior.
* added MinCount and MaxCount constraint
* deprecated the Size constraint

View File

@ -18,19 +18,24 @@ use Symfony\Component\Validator\Constraint;
*
* @api
*/
class Range extends Constraint
class MaxCount extends Constraint
{
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.';
public $min;
public $max;
public $message = 'This collection should contain {{ limit }} elements or less.';
public $limit;
/**
* {@inheritDoc}
*/
public function getDefaultOption()
{
return 'limit';
}
/**
* {@inheritDoc}
*/
public function getRequiredOptions()
{
return array('min', 'max');
return array('limit');
}
}

View File

@ -13,13 +13,12 @@ namespace Symfony\Component\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*/
class RangeValidator extends ConstraintValidator
class MaxCountValidator extends ConstraintValidator
{
/**
* Checks if the passed value is valid.
@ -27,8 +26,6 @@ class RangeValidator extends ConstraintValidator
* @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)
@ -37,28 +34,17 @@ class RangeValidator extends ConstraintValidator
return;
}
if (!is_numeric($value)) {
$this->context->addViolation($constraint->invalidMessage, array(
'{{ value }}' => $value,
));
return;
if (!is_array($value) && !$value instanceof \Countable) {
throw new UnexpectedTypeException($value, 'array or \Countable');
}
if ($value > $constraint->max) {
$this->context->addViolation($constraint->maxMessage, array(
'{{ value }}' => $value,
'{{ limit }}' => $constraint->max,
));
$count = count($value);
return;
}
if ($value < $constraint->min) {
$this->context->addViolation($constraint->minMessage, array(
'{{ value }}' => $value,
'{{ limit }}' => $constraint->min,
));
if ($count > $constraint->limit) {
$this->context->addViolation($constraint->message, array(
'{{ count }}' => $count,
'{{ limit }}' => $constraint->limit,
), $value, (int) $constraint->limit);
}
}
}

View File

@ -0,0 +1,41 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
*
* @api
*/
class MinCount extends Constraint
{
public $message = 'This collection should contain {{ limit }} elements or more.';
public $limit;
/**
* {@inheritDoc}
*/
public function getDefaultOption()
{
return 'limit';
}
/**
* {@inheritDoc}
*/
public function getRequiredOptions()
{
return array('limit');
}
}

View File

@ -0,0 +1,50 @@
<?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\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class MinCountValidator extends ConstraintValidator
{
/**
* Checks if the passed value is valid.
*
* @param mixed $value The value that should be validated
* @param Constraint $constraint The constraint for the validation
*
* @throws UnexpectedTypeException If the given value is no array or \Countable.
*/
public function validate($value, Constraint $constraint)
{
if (null === $value) {
return;
}
if (!is_array($value) && !$value instanceof \Countable) {
throw new UnexpectedTypeException($value, 'array or \Countable');
}
$count = count($value);
if ($count < $constraint->limit) {
$this->context->addViolation($constraint->message, array(
'{{ count }}' => $count,
'{{ limit }}' => $constraint->limit,
), $value, (int) $constraint->limit);
}
}
}

View File

@ -17,73 +17,22 @@ use Symfony\Component\Validator\Constraint;
* @Annotation
*
* @api
*
* @deprecated Deprecated since version 2.1, to be removed in 2.3.
*/
class Size extends Constraint
{
const TYPE_STRING = 'string';
const TYPE_COLLECTION = 'collection';
public $minMessage;
public $maxMessage;
public $exactMessage;
public $type;
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';
public $min;
public $max;
public $charset = 'UTF-8';
private $stringMinMessage = 'This value is too short. It should have {{ limit }} characters or more.';
private $stringMaxMessage = 'This value is too long. It should have {{ limit }} characters or less.';
private $stringExactMessage = 'This value should have exactly {{ limit }} characters.';
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)
/**
* {@inheritDoc}
*/
public function getRequiredOptions()
{
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.');
}
return array('min', 'max');
}
}

View File

@ -13,151 +13,54 @@ namespace Symfony\Component\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @api
*
* @deprecated Deprecated since version 2.1, to be removed in 2.3.
*/
class SizeValidator extends ConstraintValidator
{
/**
* {@inheritDoc}
* Checks if the passed value is valid.
*
* @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)
{
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) {
return;
}
if (!is_array($value) && !$value instanceof \Countable) {
throw new UnexpectedTypeException($value, 'array or Countable');
}
$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
);
if (!is_numeric($value)) {
$this->context->addViolation($constraint->invalidMessage, array(
'{{ value }}' => $value,
));
return;
}
if (null !== $constraint->max && $size > $constraint->max) {
$this->context->addViolation(
$constraint->getMaxMessage($type),
array_merge(array('{{ limit }}' => $constraint->max), $parameters),
null,
(int) $constraint->max
);
if ($value > $constraint->max) {
$this->context->addViolation($constraint->maxMessage, array(
'{{ value }}' => $value,
'{{ limit }}' => $constraint->max,
));
return;
}
if (null !== $constraint->min && $size < $constraint->min) {
$this->context->addViolation(
$constraint->getMinMessage($type),
array_merge(array('{{ limit }}' => $constraint->min), $parameters),
null,
(int) $constraint->min
);
if ($value < $constraint->min) {
$this->context->addViolation($constraint->minMessage, array(
'{{ value }}' => $value,
'{{ limit }}' => $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()'
);
}
}

View File

@ -210,10 +210,6 @@
<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>
</file>
</xliff>

View File

@ -210,10 +210,6 @@
<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>
</file>
</xliff>

View File

@ -210,10 +210,6 @@
<source>This collection should contain {{ limit }} elements or less.</source>
<target>Questa collezione dovrebbe contenere massimo {{ limit }} elemento.|Questa collezione dovrebbe contenere massimo {{ limit }} elementi.</target>
</trans-unit>
<trans-unit id="56">
<source>This collection should contain exactly {{ limit }} elements.</source>
<target>Questa collezione dovrebbe contenere esattamente {{ limit }} elemento.|Questa collezione dovrebbe contenere esattamente {{ limit }} elementi.</target>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -210,10 +210,6 @@
<source>This collection should contain {{ limit }} elements or less.</source>
<target>Deze collectie moet {{ limit }} element of minder bevatten.|Deze collectie moet {{ limit }} elementen of minder bevatten.</target>
</trans-unit>
<trans-unit id="56">
<source>This collection should contain exactly {{ limit }} elements.</source>
<target>Deze collectie moet exact {{ limit }} element bevatten.|Deze collectie moet exact {{ limit }} elementen bevatten.</target>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -210,10 +210,6 @@
<source>This collection should contain {{ limit }} elements or less.</source>
<target>Esta coleção deve conter {{ limit }} elemento ou menos.|Esta coleção deve conter {{ limit }} elementos ou menos.</target>
</trans-unit>
<trans-unit id="56">
<source>This collection should contain exactly {{ limit }} elements.</source>
<target>Esta coleção deve conter exatamente {{ limit }} elemento.|Esta coleção deve conter exatamente {{ limit }} elementos.</target>
</trans-unit>
</body>
</file>
</xliff>
</xliff>

View File

@ -210,10 +210,6 @@
<source>This collection should contain {{ limit }} elements or less.</source>
<target>Esta coleção deve conter {{ limit }} elemento ou menos.|Esta coleção deve conter {{ limit }} elementos ou menos.</target>
</trans-unit>
<trans-unit id="56">
<source>This collection should contain exactly {{ limit }} elements.</source>
<target>Esta coleção deve conter exatamente {{ limit }} elemento.|Esta coleção deve conter exatamente {{ limit }} elementos.</target>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -210,10 +210,6 @@
<source>This collection should contain {{ limit }} elements or less.</source>
<target>Эта коллекция должна содержать {{ limit }} элемент или меньше.|Эта коллекция должна содержать {{ limit }} элемента или меньше.|Эта коллекция должна содержать {{ limit }} элементов или меньше.</target>
</trans-unit>
<trans-unit id="56">
<source>This collection should contain exactly {{ limit }} elements.</source>
<target>Эта коллекция должна содержать ровно {{ limit }} элемент.|Эта коллекция должна содержать ровно {{ limit }} элемента.|Эта коллекция должна содержать ровно {{ limit }} элементов.</target>
</trans-unit>
</body>
</file>
</xliff>
</xliff>

View File

@ -210,10 +210,6 @@
<source>This collection should contain {{ limit }} elements or less.</source>
<target>Ta zbirka bi morala vsebovati {{ limit }} ali manj elementov.</target>
</trans-unit>
<trans-unit id="56">
<source>This collection should contain exactly {{ limit }} elements.</source>
<target>Ta zbirka bi morala vsebovati točno {{ limit }} element.|Ta zbirka bi morala vsebovati točno {{ limit }} elementa.|Ta zbirka bi morala vsebovati točno {{ limit }} elemente.|Ta zbirka bi morala vsebovati točno {{ limit }} elementov.</target>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -210,10 +210,6 @@
<source>This collection should contain {{ limit }} elements or less.</source>
<target>Ова колекција треба да садржи {{ limit }} или мање елемената.|Ова колекција треба да садржи {{ limit }} или мање елемената.|Ова колекција треба да садржи {{ limit }} или мање елемената.</target>
</trans-unit>
<trans-unit id="56">
<source>This collection should contain exactly {{ limit }} elements.</source>
<target>Ова колекција треба да садржи тачно {{ limit }} елемент.|Ова колекција треба да садржи тачно {{ limit }} елемента.|Ова колекција треба да садржи тачно {{ limit }} елемената.</target>
</trans-unit>
</body>
</file>
</xliff>
</xliff>

View File

@ -210,10 +210,6 @@
<source>This collection should contain {{ limit }} elements or less.</source>
<target>Ova kolekcija treba da sadrži {{ limit }} ili manje elemenata.|Ova kolekcija treba da sadrži {{ limit }} ili manje elemenata.|Ova kolekcija treba da sadrži {{ limit }} ili manje elemenata.</target>
</trans-unit>
<trans-unit id="56">
<source>This collection should contain exactly {{ limit }} elements.</source>
<target>Ova kolekcija treba da sadrži tačno {{ limit }} element.|Ova kolekcija treba da sadrži tačno {{ limit }} elementa.|Ova kolekcija treba da sadrži tačno {{ limit }} elemenata.</target>
</trans-unit>
</body>
</file>
</xliff>
</xliff>

View File

@ -0,0 +1,23 @@
<?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;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class MaxCountValidatorArrayTest extends MaxCountValidatorTest
{
protected function createCollection(array $content)
{
return $content;
}
}

View File

@ -0,0 +1,38 @@
<?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;
class MaxCountValidatorCountableTest_Countable implements \Countable
{
private $content;
public function __construct(array $content)
{
$this->content = $content;
}
public function count()
{
return count($this->content);
}
}
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class MaxCountValidatorCountableTest extends MaxCountValidatorTest
{
protected function createCollection(array $content)
{
return new MaxCountValidatorCountableTest_Countable($content);
}
}

View File

@ -0,0 +1,113 @@
<?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\MaxCount;
use Symfony\Component\Validator\Constraints\MaxCountValidator;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
abstract class MaxCountValidatorTest 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 MaxCountValidator();
$this->validator->initialize($this->context);
}
protected function tearDown()
{
$this->context = null;
$this->validator = null;
}
abstract protected function createCollection(array $content);
public function testNullIsValid()
{
$this->context->expects($this->never())
->method('addViolation');
$this->validator->validate(null, new MaxCount(6));
}
/**
* @expectedException Symfony\Component\Validator\Exception\UnexpectedTypeException
*/
public function testExpectsCountableType()
{
$this->validator->validate(new \stdClass(), new MaxCount(5));
}
/**
* @dataProvider getValidValues
*/
public function testValidValues($value)
{
$this->context->expects($this->never())
->method('addViolation');
$constraint = new MaxCount(3);
$this->validator->validate($value, $constraint);
}
public function getValidValues()
{
return array(
array($this->createCollection(array(1))),
array($this->createCollection(array(1, 2))),
array($this->createCollection(array(1, 2, 3))),
array($this->createCollection(array('a' => 1, 'b' => 2, 'c' => 3))),
);
}
/**
* @dataProvider getInvalidValues
*/
public function testInvalidValues($value)
{
$constraint = new MaxCount(array(
'limit' => 3,
'message' => 'myMessage'
));
$this->context->expects($this->once())
->method('addViolation')
->with('myMessage', $this->identicalTo(array(
'{{ count }}' => count($value),
'{{ limit }}' => 3,
)), $value, 3);
$this->validator->validate($value, $constraint);
}
public function getInvalidValues()
{
return array(
array($this->createCollection(array(1, 2, 3, 4))),
array($this->createCollection(array(1, 2, 3, 4, 5))),
array($this->createCollection(array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4))),
);
}
public function testDefaultOption()
{
$constraint = new MaxCount(5);
$this->assertEquals(5, $constraint->limit);
}
}

View File

@ -0,0 +1,23 @@
<?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;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class MinCountValidatorArrayTest extends MinCountValidatorTest
{
protected function createCollection(array $content)
{
return $content;
}
}

View File

@ -0,0 +1,38 @@
<?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;
class MinCountValidatorCountableTest_Countable implements \Countable
{
private $content;
public function __construct(array $content)
{
$this->content = $content;
}
public function count()
{
return count($this->content);
}
}
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class MinCountValidatorCountableTest extends MinCountValidatorTest
{
protected function createCollection(array $content)
{
return new MinCountValidatorCountableTest_Countable($content);
}
}

View File

@ -0,0 +1,114 @@
<?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\MinCount;
use Symfony\Component\Validator\Constraints\MinCountValidator;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
abstract class MinCountValidatorTest 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 MinCountValidator();
$this->validator->initialize($this->context);
}
protected function tearDown()
{
$this->context = null;
$this->validator = null;
}
abstract protected function createCollection(array $content);
public function testNullIsValid()
{
$this->context->expects($this->never())
->method('addViolation');
$this->validator->validate(null, new MinCount(6));
}
/**
* @expectedException Symfony\Component\Validator\Exception\UnexpectedTypeException
*/
public function testExpectsCountableType()
{
$this->validator->validate(new \stdClass(), new MinCount(5));
}
/**
* @dataProvider getValidValues
*/
public function testValidValues($value)
{
$this->context->expects($this->never())
->method('addViolation');
$constraint = new MinCount(3);
$this->validator->validate($value, $constraint);
}
public function getValidValues()
{
return array(
array($this->createCollection(array(1, 2, 3))),
array($this->createCollection(array(1, 2, 3, 4))),
array($this->createCollection(array(1, 2, 3, 4, 5))),
array($this->createCollection(array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4))),
);
}
/**
* @dataProvider getInvalidValues
*/
public function testInvalidValues($value)
{
$constraint = new MinCount(array(
'limit' => 4,
'message' => 'myMessage'
));
$this->context->expects($this->once())
->method('addViolation')
->with('myMessage', $this->identicalTo(array(
'{{ count }}' => count($value),
'{{ limit }}' => 4,
)), $value, 4);
$this->validator->validate($value, $constraint);
}
public function getInvalidValues()
{
return array(
array($this->createCollection(array(1))),
array($this->createCollection(array(1, 2))),
array($this->createCollection(array(1, 2, 3))),
array($this->createCollection(array('a' => 1, 'b' => 2, 'c' => 3))),
);
}
public function testDefaultOption()
{
$constraint = new MinCount(5);
$this->assertEquals(5, $constraint->limit);
}
}

View File

@ -1,121 +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\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);
}
}

View File

@ -1,98 +0,0 @@
<?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');
}
}

View File

@ -14,19 +14,6 @@ namespace Symfony\Component\Validator\Tests\Constraints;
use Symfony\Component\Validator\Constraints\Size;
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
{
protected $context;
@ -41,176 +28,94 @@ class SizeValidatorTest extends \PHPUnit_Framework_TestCase
public function testNullIsValid()
{
$this->context->expects($this->never())->method('addViolation');
$this->context->expects($this->never())
->method('addViolation');
$this->validator->validate(null, new Size(array('min' => 10, 'max' => 20)));
}
public function testNullIsValidAsAString()
{
$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
* @dataProvider getValidValues
*/
public function testValidStringValues($value, $mbOnly = false)
public function testValidValues($value)
{
if ($mbOnly && !function_exists('mb_strlen')) {
return $this->markTestSkipped('mb_strlen does not exist');
}
$this->context->expects($this->never())
->method('addViolation');
$constraint = new Size(array('min' => 6, 'max' => 10));
$constraint = new Size(array('min' => 10, 'max' => 20));
$this->validator->validate($value, $constraint);
}
public function getValidStringValues()
public function getValidValues()
{
return array(
array(123456),
array(1234567890),
array('123456'),
array('1234567890'),
array('üüüüüü', true),
array('üüüüüüüüüü', true),
array('éééééé', true),
array('éééééééééé', true),
array(10.00001),
array(19.99999),
array('10.00001'),
array('19.99999'),
array(10),
array(20),
array(10.0),
array(20.0),
);
}
/**
* @dataProvider getInvalidStringValues
* @dataProvider getInvalidValues
*/
public function testInvalidStringValues($value, $mbOnly = false)
public function testInvalidValues($value)
{
if ($mbOnly && !function_exists('mb_strlen')) {
return $this->markTestSkipped('mb_strlen does not exist');
}
$this->context->expects($this->once())
->method('addViolation');
$this->context->expects($this->once())->method('addViolation');
$this->validator->validate($value, new Size(array('min' => 6, 'max' => 10)));
$constraint = new Size(array('min' => 10, 'max' => 20));
$this->validator->validate($value, $constraint);
}
public function getInvalidStringValues()
public function getInvalidValues()
{
return array(
array(12345),
array(12345678901),
array('12345'),
array('12345678901'),
array('üüüüü', true),
array('üüüüüüüüüüü', true),
array('ééééé', true),
array('ééééééééééé', true),
array(9.999999),
array(20.000001),
array('9.999999'),
array('20.000001'),
array(new \stdClass()),
);
}
/**
* @dataProvider getValidCollectionValues
*/
public function testValidCollectionValue($value)
public function testMinMessageIsSet()
{
$this->context->expects($this->never())->method('addViolation');
$constraint = new Size(array(
'min' => 10,
'max' => 20,
'minMessage' => 'myMessage',
));
$this->validator->validate($value, new Size(array('min' => 10, 'max' => 20)));
$this->context->expects($this->once())
->method('addViolation')
->with('myMessage', array(
'{{ value }}' => 9,
'{{ limit }}' => 10,
));
$this->validator->validate(9, $constraint);
}
public function getValidCollectionValues()
public function testMaxMessageIsSet()
{
$countable = $this->getMock('Countable');
$countable->expects($this->any())->method('count')->will($this->returnValue(15));
$constraint = new Size(array(
'min' => 10,
'max' => 20,
'maxMessage' => 'myMessage',
));
return array(
array($countable),
array(range(1, 15)),
);
}
$this->context->expects($this->once())
->method('addViolation')
->with('myMessage', array(
'{{ value }}' => 21,
'{{ limit }}' => 20,
));
/**
* @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)));
$this->validator->validate(21, $constraint);
}
}