From b9ba117208d170479ea9c2f7ffbe692c88a8b281 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 29 Sep 2011 15:45:52 +0200 Subject: [PATCH] [Validator] added a SizeLength validator --- CHANGELOG-2.1.md | 1 + .../Validator/Constraints/SizeLength.php | 37 +++++ .../Constraints/SizeLengthValidator.php | 76 ++++++++++ .../Constraints/SizeLengthValidatorTest.php | 136 ++++++++++++++++++ 4 files changed, 250 insertions(+) create mode 100644 src/Symfony/Component/Validator/Constraints/SizeLength.php create mode 100644 src/Symfony/Component/Validator/Constraints/SizeLengthValidator.php create mode 100644 tests/Symfony/Tests/Component/Validator/Constraints/SizeLengthValidatorTest.php diff --git a/CHANGELOG-2.1.md b/CHANGELOG-2.1.md index 0193d3a20b..5edc90ce8e 100644 --- a/CHANGELOG-2.1.md +++ b/CHANGELOG-2.1.md @@ -77,5 +77,6 @@ To get the diff between two versions, go to https://github.com/symfony/symfony/c ### Validator + * added a SizeLength validator * improved the ImageValidator with min width, max width, min height, and max height constraints * added support for MIME with wildcard in FileValidator diff --git a/src/Symfony/Component/Validator/Constraints/SizeLength.php b/src/Symfony/Component/Validator/Constraints/SizeLength.php new file mode 100644 index 0000000000..7d599e6b21 --- /dev/null +++ b/src/Symfony/Component/Validator/Constraints/SizeLength.php @@ -0,0 +1,37 @@ + + * + * 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 SizeLength extends Constraint +{ + public $minMessage = 'This value is too short. It should have {{ limit }} characters or more'; + public $maxMessage = 'This value is too long. It should have {{ limit }} characters or less'; + public $exactMessage = 'This value should have exactly {{ limit }} characters'; + public $min; + public $max; + public $charset = 'UTF-8'; + + /** + * {@inheritDoc} + */ + public function getRequiredOptions() + { + return array('min', 'max'); + } +} diff --git a/src/Symfony/Component/Validator/Constraints/SizeLengthValidator.php b/src/Symfony/Component/Validator/Constraints/SizeLengthValidator.php new file mode 100644 index 0000000000..25258adb70 --- /dev/null +++ b/src/Symfony/Component/Validator/Constraints/SizeLengthValidator.php @@ -0,0 +1,76 @@ + + * + * 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; + +/** + * @api + */ +class SizeLengthValidator 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 + * + * @return Boolean Whether or not the value is valid + * + * @api + */ + public function isValid($value, Constraint $constraint) + { + if (null === $value || '' === $value) { + return true; + } + + if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { + throw new UnexpectedTypeException($value, 'string'); + } + + $value = (string) $value; + + $length = function_exists('mb_strlen') ? mb_strlen($value, $constraint->charset) : strlen($value); + + if ($constraint->min == $constraint->max && $length != $constraint->max) { + $this->setMessage($constraint->exactMessage, array( + '{{ value }}' => $value, + '{{ limit }}' => $constraint->max, + )); + + return false; + } + + if ($length > $constraint->max) { + $this->setMessage($constraint->maxMessage, array( + '{{ value }}' => $value, + '{{ limit }}' => $constraint->max, + )); + + return false; + } + + if ($length < $constraint->min) { + $this->setMessage($constraint->minMessage, array( + '{{ value }}' => $value, + '{{ limit }}' => $constraint->min, + )); + + return false; + } + + return true; + } +} diff --git a/tests/Symfony/Tests/Component/Validator/Constraints/SizeLengthValidatorTest.php b/tests/Symfony/Tests/Component/Validator/Constraints/SizeLengthValidatorTest.php new file mode 100644 index 0000000000..e2a1ee2cab --- /dev/null +++ b/tests/Symfony/Tests/Component/Validator/Constraints/SizeLengthValidatorTest.php @@ -0,0 +1,136 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Tests\Component\Validator\Constraints; + +use Symfony\Component\Validator\Constraints\SizeLength; +use Symfony\Component\Validator\Constraints\SizeLengthValidator; + +class SizeLengthValidatorTest extends \PHPUnit_Framework_TestCase +{ + protected $validator; + + protected function setUp() + { + $this->validator = new SizeLengthValidator(); + } + + protected function tearDown() + { + $this->validator = null; + } + + public function testNullIsValid() + { + $this->assertTrue($this->validator->isValid(null, new SizeLength(array('min' => 6, 'max' => 10)))); + } + + public function testEmptyStringIsValid() + { + $this->assertTrue($this->validator->isValid('', new SizeLength(array('min' => 6, 'max' => 10)))); + } + + public function testExpectsStringCompatibleType() + { + $this->setExpectedException('Symfony\Component\Validator\Exception\UnexpectedTypeException'); + + $this->validator->isValid(new \stdClass(), new SizeLength(array('min' => 6, 'max' => 10))); + } + + /** + * @dataProvider getValidValues + */ + public function testValidValues($value, $skip = false) + { + if (!$skip) { + $constraint = new SizeLength(array('min' => 6, 'max' => 10)); + $this->assertTrue($this->validator->isValid($value, $constraint)); + } + } + + public function getValidValues() + { + return array( + array(123456), + array(1234567890), + array('123456'), + array('1234567890'), + array('üüüüüü', !function_exists('mb_strlen')), + array('üüüüüüüüüü', !function_exists('mb_strlen')), + array('éééééé', !function_exists('mb_strlen')), + array('éééééééééé', !function_exists('mb_strlen')), + ); + } + + /** + * @dataProvider getInvalidValues + */ + public function testInvalidValues($value, $skip = false) + { + if (!$skip) { + $constraint = new SizeLength(array('min' => 6, 'max' => 10)); + $this->assertFalse($this->validator->isValid($value, $constraint)); + } + } + + public function getInvalidValues() + { + return array( + array(12345), + array(12345678901), + array('12345'), + array('12345678901'), + array('üüüüü', !function_exists('mb_strlen')), + array('üüüüüüüüüüü', !function_exists('mb_strlen')), + array('ééééé', !function_exists('mb_strlen')), + array('ééééééééééé', !function_exists('mb_strlen')), + ); + } + + public function testMessageIsSet() + { + $constraint = new SizeLength(array( + 'min' => 5, + 'max' => 10, + 'minMessage' => 'myMinMessage', + 'maxMessage' => 'myMaxMessage', + )); + + $this->assertFalse($this->validator->isValid('1234', $constraint)); + $this->assertEquals('myMinMessage', $this->validator->getMessageTemplate()); + $this->assertEquals(array( + '{{ value }}' => '1234', + '{{ limit }}' => 5, + ), $this->validator->getMessageParameters()); + + $this->assertFalse($this->validator->isValid('12345678901', $constraint)); + $this->assertEquals('myMaxMessage', $this->validator->getMessageTemplate()); + $this->assertEquals(array( + '{{ value }}' => '12345678901', + '{{ limit }}' => 10, + ), $this->validator->getMessageParameters()); + } + + public function testExactErrorMessage() + { + $constraint = new SizeLength(array( + 'min' => 5, + 'max' => 5, + )); + + $this->assertFalse($this->validator->isValid('1234', $constraint)); + $this->assertEquals('This value should have exactly {{ limit }} characters', $this->validator->getMessageTemplate()); + $this->assertEquals(array( + '{{ value }}' => '1234', + '{{ limit }}' => 5, + ), $this->validator->getMessageParameters()); + } +}