[Validator] improved image validator

This commit is contained in:
Luciano Mammino 2013-07-14 19:03:22 +02:00 committed by Fabien Potencier
parent 63e6368dc0
commit b0306242cc
6 changed files with 209 additions and 1 deletions

View File

@ -1,6 +1,11 @@
CHANGELOG
=========
2.4.0
-----
* added `minRatio`, `maxRatio`, `allowSquare`, `allowLandscape`, and `allowPortrait` to Image validator
2.3.0
-----

View File

@ -23,6 +23,11 @@ class Image extends File
public $maxWidth = null;
public $maxHeight = null;
public $minHeight = null;
public $maxRatio = null;
public $minRatio = null;
public $allowSquare = true;
public $allowLandscape = true;
public $allowPortrait = true;
public $mimeTypesMessage = 'This file is not a valid image.';
public $sizeNotDetectedMessage = 'The size of the image could not be detected.';
@ -30,4 +35,9 @@ class Image extends File
public $minWidthMessage = 'The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.';
public $maxHeightMessage = 'The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.';
public $minHeightMessage = 'The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.';
public $maxRatioMessage = 'The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.';
public $minRatioMessage = 'The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.';
public $allowSquareMessage = 'The image is square ({{ width }}x{{ height }}px). Square images are not allowed.';
public $allowLandscapeMessage = 'The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.';
public $allowPortraitMessage = 'The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.';
}

View File

@ -38,7 +38,9 @@ class ImageValidator extends FileValidator
}
if (null === $constraint->minWidth && null === $constraint->maxWidth
&& null === $constraint->minHeight && null === $constraint->maxHeight) {
&& null === $constraint->minHeight && null === $constraint->maxHeight
&& null === $constraint->minRatio && null === $constraint->maxRatio
&& $constraint->allowSquare && $constraint->allowLandscape && $constraint->allowPortrait) {
return;
}
@ -109,5 +111,55 @@ class ImageValidator extends FileValidator
));
}
}
$ratio = $width / $height;
if (null !== $constraint->minRatio) {
if (!is_numeric((string) $constraint->minRatio)) {
throw new ConstraintDefinitionException(sprintf('"%s" is not a valid minimum ratio', $constraint->minRatio));
}
if ($ratio < $constraint->minRatio) {
$this->context->addViolation($constraint->minRatioMessage, array(
'{{ ratio }}' => $ratio,
'{{ min_ratio }}' => $constraint->minRatio
));
}
}
if (null !== $constraint->maxRatio) {
if (!is_numeric((string) $constraint->maxRatio)) {
throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum ratio', $constraint->maxRatio));
}
if ($ratio > $constraint->maxRatio) {
$this->context->addViolation($constraint->maxRatioMessage, array(
'{{ ratio }}' => $ratio,
'{{ max_ratio }}' => $constraint->maxRatio
));
}
}
if (!$constraint->allowSquare && $width == $height) {
$this->context->addViolation($constraint->allowSquareMessage, array(
'{{ width }}' => $width,
'{{ height }}' => $height
));
}
if (!$constraint->allowLandscape && $width > $height) {
$this->context->addViolation($constraint->allowLandscapeMessage, array(
'{{ width }}' => $width,
'{{ height }}' => $height
));
}
if (!$constraint->allowPortrait && $width < $height) {
$this->context->addViolation($constraint->allowPortraitMessage, array(
'{{ width }}' => $width,
'{{ height }}' => $height
));
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 B

View File

@ -20,6 +20,8 @@ class ImageValidatorTest extends \PHPUnit_Framework_TestCase
protected $validator;
protected $path;
protected $image;
protected $imageLandscape;
protected $imagePortrait;
protected function setUp()
{
@ -27,6 +29,8 @@ class ImageValidatorTest extends \PHPUnit_Framework_TestCase
$this->validator = new ImageValidator();
$this->validator->initialize($this->context);
$this->image = __DIR__.'/Fixtures/test.gif';
$this->imageLandscape = __DIR__.'/Fixtures/test_landscape.gif';
$this->imagePortrait = __DIR__.'/Fixtures/test_portrait.gif';
}
public function testNullIsValid()
@ -223,4 +227,141 @@ class ImageValidatorTest extends \PHPUnit_Framework_TestCase
$this->validator->validate($this->image, $constraint);
}
public function testRatioTooSmall()
{
if (!class_exists('Symfony\Component\HttpFoundation\File\File')) {
$this->markTestSkipped('The "HttpFoundation" component is not available');
}
$constraint = new Image(array(
'minRatio' => 2,
'minRatioMessage' => 'myMessage',
));
$this->context->expects($this->once())
->method('addViolation')
->with('myMessage', array(
'{{ ratio }}' => 1,
'{{ min_ratio }}' => 2,
));
$this->validator->validate($this->image, $constraint);
}
public function testRatioTooBig()
{
if (!class_exists('Symfony\Component\HttpFoundation\File\File')) {
$this->markTestSkipped('The "HttpFoundation" component is not available');
}
$constraint = new Image(array(
'maxRatio' => 0.5,
'maxRatioMessage' => 'myMessage',
));
$this->context->expects($this->once())
->method('addViolation')
->with('myMessage', array(
'{{ ratio }}' => 1,
'{{ max_ratio }}' => 0.5,
));
$this->validator->validate($this->image, $constraint);
}
/**
* @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
*/
public function testInvalidMinRatio()
{
if (!class_exists('Symfony\Component\HttpFoundation\File\File')) {
$this->markTestSkipped('The "HttpFoundation" component is not available');
}
$constraint = new Image(array(
'minRatio' => '1abc',
));
$this->validator->validate($this->image, $constraint);
}
/**
* @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
*/
public function testInvalidMaxRatio()
{
if (!class_exists('Symfony\Component\HttpFoundation\File\File')) {
$this->markTestSkipped('The "HttpFoundation" component is not available');
}
$constraint = new Image(array(
'maxRatio' => '1abc',
));
$this->validator->validate($this->image, $constraint);
}
public function testSquareNotAllowed()
{
if (!class_exists('Symfony\Component\HttpFoundation\File\File')) {
$this->markTestSkipped('The "HttpFoundation" component is not available');
}
$constraint = new Image(array(
'allowSquare' => false,
'allowSquareMessage' => 'myMessage',
));
$this->context->expects($this->once())
->method('addViolation')
->with('myMessage', array(
'{{ width }}' => 2,
'{{ height }}' => 2,
));
$this->validator->validate($this->image, $constraint);
}
public function testLandscapeNotAllowed()
{
if (!class_exists('Symfony\Component\HttpFoundation\File\File')) {
$this->markTestSkipped('The "HttpFoundation" component is not available');
}
$constraint = new Image(array(
'allowLandscape' => false,
'allowLandscapeMessage' => 'myMessage',
));
$this->context->expects($this->once())
->method('addViolation')
->with('myMessage', array(
'{{ width }}' => 2,
'{{ height }}' => 1,
));
$this->validator->validate($this->imageLandscape, $constraint);
}
public function testPortraitNotAllowed()
{
if (!class_exists('Symfony\Component\HttpFoundation\File\File')) {
$this->markTestSkipped('The "HttpFoundation" component is not available');
}
$constraint = new Image(array(
'allowPortrait' => false,
'allowPortraitMessage' => 'myMessage',
));
$this->context->expects($this->once())
->method('addViolation')
->with('myMessage', array(
'{{ width }}' => 1,
'{{ height }}' => 2,
));
$this->validator->validate($this->imagePortrait, $constraint);
}
}