diff --git a/src/Symfony/Component/Validator/Constraints/File.php b/src/Symfony/Component/Validator/Constraints/File.php index 9144c60472631..ec5af6ce1eff7 100644 --- a/src/Symfony/Component/Validator/Constraints/File.php +++ b/src/Symfony/Component/Validator/Constraints/File.php @@ -23,10 +23,12 @@ class File extends Constraint { public $maxSize = null; + public $minSize = null; public $mimeTypes = array(); public $notFoundMessage = 'The file could not be found.'; public $notReadableMessage = 'The file is not readable.'; public $maxSizeMessage = 'The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.'; + public $minSizeMessage = 'The file is too small ({{ size }} {{ suffix }}). Allowed minimum size is {{ limit }} {{ suffix }}.'; public $mimeTypesMessage = 'The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.'; public $uploadIniSizeErrorMessage = 'The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.'; diff --git a/src/Symfony/Component/Validator/Constraints/FileValidator.php b/src/Symfony/Component/Validator/Constraints/FileValidator.php index 54f0b45d60dae..b3f2cd82fb103 100644 --- a/src/Symfony/Component/Validator/Constraints/FileValidator.php +++ b/src/Symfony/Component/Validator/Constraints/FileValidator.php @@ -112,21 +112,7 @@ public function validate($value, Constraint $constraint) } if ($constraint->maxSize) { - if (ctype_digit((string) $constraint->maxSize)) { - $size = filesize($path); - $limit = (int) $constraint->maxSize; - $suffix = 'bytes'; - } elseif (preg_match('/^\d++k$/', $constraint->maxSize)) { - $size = round(filesize($path) / 1000, 2); - $limit = (int) $constraint->maxSize; - $suffix = 'kB'; - } elseif (preg_match('/^\d++M$/', $constraint->maxSize)) { - $size = round(filesize($path) / 1000000, 2); - $limit = (int) $constraint->maxSize; - $suffix = 'MB'; - } else { - throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum size', $constraint->maxSize)); - } + list($size, $limit, $suffix) = $this->parseSize($constraint->maxSize, $path); if ($size > $limit) { $this->context->addViolation($constraint->maxSizeMessage, array( @@ -140,6 +126,21 @@ public function validate($value, Constraint $constraint) } } + if ($constraint->minSize) { + list($size, $limit, $suffix) = $this->parseSize($constraint->minSize, $path); + + if ($size < $limit) { + $this->context->addViolation($constraint->minSizeMessage, array( + '{{ size }}' => $size, + '{{ limit }}' => $limit, + '{{ suffix }}' => $suffix, + '{{ file }}' => $path, + )); + + return; + } + } + if ($constraint->mimeTypes) { if (!$value instanceof FileObject) { $value = new FileObject($value); @@ -172,4 +173,39 @@ public function validate($value, Constraint $constraint) } } } + + /** + * Parse size, limit and suffix from constraint size. + * + * @param string $constraintSize Constraint size + * @param string $path Path + * + * @return array + * + * @throws ConstraintDefinitionException + */ + private function parseSize($constraintSize, $path) + { + if (ctype_digit((string) $constraintSize)) { + $size = filesize($path); + $limit = (int) $constraintSize; + $suffix = 'bytes'; + } elseif (preg_match('/^\d++k$/', $constraintSize)) { + $size = round(filesize($path) / 1000, 2); + $limit = (int) $constraintSize; + $suffix = 'kB'; + } elseif (preg_match('/^\d++M$/', $constraintSize)) { + $size = round(filesize($path) / 1000000, 2); + $limit = (int) $constraintSize; + $suffix = 'MB'; + } else { + throw new ConstraintDefinitionException(sprintf('"%s" is not a valid size', $constraintSize)); + } + + return array( + $size, + $limit, + $suffix, + ); + } } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/FileValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/FileValidatorTest.php index 0927aedacdd5c..84ff35e2a3f6f 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/FileValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/FileValidatorTest.php @@ -157,6 +157,81 @@ public function testInvalidMaxSize() $this->validator->validate($this->path, $constraint); } + public function testTooSmallBytes() + { + fwrite($this->file, str_repeat('0', 1)); + + $constraint = new File(array( + 'minSize' => 10, + 'minSizeMessage' => 'myMessage', + )); + + $this->context->expects($this->once()) + ->method('addViolation') + ->with('myMessage', array( + '{{ limit }}' => '10', + '{{ size }}' => '1', + '{{ suffix }}' => 'bytes', + '{{ file }}' => $this->path, + )); + + $this->validator->validate($this->getFile($this->path), $constraint); + } + + public function testTooSmallKiloBytes() + { + fwrite($this->file, str_repeat('0', 400)); + + $constraint = new File(array( + 'minSize' => '1k', + 'minSizeMessage' => 'myMessage', + )); + + $this->context->expects($this->once()) + ->method('addViolation') + ->with('myMessage', array( + '{{ limit }}' => '1', + '{{ size }}' => '0.4', + '{{ suffix }}' => 'kB', + '{{ file }}' => $this->path, + )); + + $this->validator->validate($this->getFile($this->path), $constraint); + } + + public function testTooSmallMegaBytes() + { + fwrite($this->file, str_repeat('0', 400000)); + + $constraint = new File(array( + 'minSize' => '1M', + 'minSizeMessage' => 'myMessage', + )); + + $this->context->expects($this->once()) + ->method('addViolation') + ->with('myMessage', array( + '{{ limit }}' => '1', + '{{ size }}' => '0.4', + '{{ suffix }}' => 'MB', + '{{ file }}' => $this->path, + )); + + $this->validator->validate($this->getFile($this->path), $constraint); + } + + /** + * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException + */ + public function testInvalidMinSize() + { + $constraint = new File(array( + 'minSize' => '1abc', + )); + + $this->validator->validate($this->path, $constraint); + } + public function testValidMimeType() { $file = $this