From d8c186938ec7a5201ab8a1068ed2c3cc102b788c Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Sun, 4 Oct 2020 20:20:54 +0200 Subject: [PATCH] [Validator] Migrate File and Image constraints to attributes. --- .../Component/Validator/Constraints/File.php | 57 +++- .../Component/Validator/Constraints/Image.php | 104 ++++++ .../Validator/Tests/Constraints/FileTest.php | 36 +++ .../Tests/Constraints/FileValidatorTest.php | 69 +++- .../Validator/Tests/Constraints/ImageTest.php | 60 ++++ .../Tests/Constraints/ImageValidatorTest.php | 297 +++++++++++++----- 6 files changed, 539 insertions(+), 84 deletions(-) create mode 100644 src/Symfony/Component/Validator/Tests/Constraints/ImageTest.php diff --git a/src/Symfony/Component/Validator/Constraints/File.php b/src/Symfony/Component/Validator/Constraints/File.php index 8f3ace89df..65e5bddf2c 100644 --- a/src/Symfony/Component/Validator/Constraints/File.php +++ b/src/Symfony/Component/Validator/Constraints/File.php @@ -22,6 +22,7 @@ use Symfony\Component\Validator\Exception\ConstraintDefinitionException; * * @author Bernhard Schussek */ +#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] class File extends Constraint { // Check the Image constraint for clashes if adding new constants here @@ -61,10 +62,57 @@ class File extends Constraint /** * {@inheritdoc} + * + * @param int|string|null $maxSize + * @param string[]|string|null $mimeTypes */ - public function __construct($options = null) - { - parent::__construct($options); + public function __construct( + array $options = null, + $maxSize = null, + bool $binaryFormat = null, + $mimeTypes = null, + string $notFoundMessage = null, + string $notReadableMessage = null, + string $maxSizeMessage = null, + string $mimeTypesMessage = null, + string $disallowEmptyMessage = null, + + string $uploadIniSizeErrorMessage = null, + string $uploadFormSizeErrorMessage = null, + string $uploadPartialErrorMessage = null, + string $uploadNoFileErrorMessage = null, + string $uploadNoTmpDirErrorMessage = null, + string $uploadCantWriteErrorMessage = null, + string $uploadExtensionErrorMessage = null, + string $uploadErrorMessage = null, + array $groups = null, + $payload = null + ) { + if (null !== $maxSize && !\is_int($maxSize) && !\is_string($maxSize)) { + throw new \TypeError(sprintf('"%s": Expected argument $maxSize to be either null, an integer or a string, got "%s".', __METHOD__, get_debug_type($maxSize))); + } + if (null !== $mimeTypes && !\is_array($mimeTypes) && !\is_string($mimeTypes)) { + throw new \TypeError(sprintf('"%s": Expected argument $mimeTypes to be either null, an array or a string, got "%s".', __METHOD__, get_debug_type($mimeTypes))); + } + + parent::__construct($options, $groups, $payload); + + $this->maxSize = $maxSize ?? $this->maxSize; + $this->binaryFormat = $binaryFormat ?? $this->binaryFormat; + $this->mimeTypes = $mimeTypes ?? $this->mimeTypes; + $this->notFoundMessage = $notFoundMessage ?? $this->notFoundMessage; + $this->notReadableMessage = $notReadableMessage ?? $this->notReadableMessage; + $this->maxSizeMessage = $maxSizeMessage ?? $this->maxSizeMessage; + $this->mimeTypesMessage = $mimeTypesMessage ?? $this->mimeTypesMessage; + $this->disallowEmptyMessage = $disallowEmptyMessage ?? $this->disallowEmptyMessage; + $this->uploadIniSizeErrorMessage = $uploadIniSizeErrorMessage ?? $this->uploadIniSizeErrorMessage; + $this->uploadFormSizeErrorMessage = $uploadFormSizeErrorMessage ?? $this->uploadFormSizeErrorMessage; + $this->uploadPartialErrorMessage = $uploadPartialErrorMessage ?? $this->uploadPartialErrorMessage; + $this->uploadNoFileErrorMessage = $uploadNoFileErrorMessage ?? $this->uploadNoFileErrorMessage; + $this->uploadNoTmpDirErrorMessage = $uploadNoTmpDirErrorMessage ?? $this->uploadNoTmpDirErrorMessage; + $this->uploadCantWriteErrorMessage = $uploadCantWriteErrorMessage ?? $this->uploadCantWriteErrorMessage; + $this->uploadExtensionErrorMessage = $uploadExtensionErrorMessage ?? $this->uploadExtensionErrorMessage; + $this->uploadErrorMessage = $uploadErrorMessage ?? $this->uploadErrorMessage; if (null !== $this->maxSize) { $this->normalizeBinaryFormat($this->maxSize); @@ -100,6 +148,9 @@ class File extends Constraint return parent::__isset($option); } + /** + * @param int|string $maxSize + */ private function normalizeBinaryFormat($maxSize) { $factors = [ diff --git a/src/Symfony/Component/Validator/Constraints/Image.php b/src/Symfony/Component/Validator/Constraints/Image.php index 21005d9ea5..b1480af4c2 100644 --- a/src/Symfony/Component/Validator/Constraints/Image.php +++ b/src/Symfony/Component/Validator/Constraints/Image.php @@ -18,6 +18,7 @@ namespace Symfony\Component\Validator\Constraints; * @author Benjamin Dulau * @author Bernhard Schussek */ +#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] class Image extends File { const SIZE_NOT_DETECTED_ERROR = '6d55c3f4-e58e-4fe3-91ee-74b492199956'; @@ -86,4 +87,107 @@ class Image extends File 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.'; public $corruptedMessage = 'The image file is corrupted.'; + + /** + * {@inheritdoc} + * + * @param int|float $maxRatio + * @param int|float $minRatio + * @param int|float $minPixels + * @param int|float $maxPixels + */ + public function __construct( + array $options = null, + $maxSize = null, + bool $binaryFormat = null, + array $mimeTypes = null, + int $minWidth = null, + int $maxWidth = null, + int $maxHeight = null, + int $minHeight = null, + $maxRatio = null, + $minRatio = null, + $minPixels = null, + $maxPixels = null, + bool $allowSquare = null, + bool $allowLandscape = null, + bool $allowPortrait = null, + bool $detectCorrupted = null, + string $notFoundMessage = null, + string $notReadableMessage = null, + string $maxSizeMessage = null, + string $mimeTypesMessage = null, + string $disallowEmptyMessage = null, + string $uploadIniSizeErrorMessage = null, + string $uploadFormSizeErrorMessage = null, + string $uploadPartialErrorMessage = null, + string $uploadNoFileErrorMessage = null, + string $uploadNoTmpDirErrorMessage = null, + string $uploadCantWriteErrorMessage = null, + string $uploadExtensionErrorMessage = null, + string $uploadErrorMessage = null, + string $sizeNotDetectedMessage = null, + string $maxWidthMessage = null, + string $minWidthMessage = null, + string $maxHeightMessage = null, + string $minHeightMessage = null, + string $minPixelsMessage = null, + string $maxPixelsMessage = null, + string $maxRatioMessage = null, + string $minRatioMessage = null, + string $allowSquareMessage = null, + string $allowLandscapeMessage = null, + string $allowPortraitMessage = null, + string $corruptedMessage = null, + array $groups = null, + $payload = null + ) { + parent::__construct( + $options, + $maxSize, + $binaryFormat, + $mimeTypes, + $notFoundMessage, + $notReadableMessage, + $maxSizeMessage, + $mimeTypesMessage, + $disallowEmptyMessage, + $uploadIniSizeErrorMessage, + $uploadFormSizeErrorMessage, + $uploadPartialErrorMessage, + $uploadNoFileErrorMessage, + $uploadNoTmpDirErrorMessage, + $uploadCantWriteErrorMessage, + $uploadExtensionErrorMessage, + $uploadErrorMessage, + $groups, + $payload + ); + + $this->minWidth = $minWidth ?? $this->minWidth; + $this->maxWidth = $maxWidth ?? $this->maxWidth; + $this->maxHeight = $maxHeight ?? $this->maxHeight; + $this->minHeight = $minHeight ?? $this->minHeight; + $this->maxRatio = $maxRatio ?? $this->maxRatio; + $this->minRatio = $minRatio ?? $this->minRatio; + $this->minPixels = $minPixels ?? $this->minPixels; + $this->maxPixels = $maxPixels ?? $this->maxPixels; + $this->allowSquare = $allowSquare ?? $this->allowSquare; + $this->allowLandscape = $allowLandscape ?? $this->allowLandscape; + $this->allowPortrait = $allowPortrait ?? $this->allowPortrait; + $this->detectCorrupted = $detectCorrupted ?? $this->detectCorrupted; + $this->sizeNotDetectedMessage = $sizeNotDetectedMessage ?? $this->sizeNotDetectedMessage; + $this->maxWidthMessage = $maxWidthMessage ?? $this->maxWidthMessage; + $this->minWidthMessage = $minWidthMessage ?? $this->minWidthMessage; + $this->maxHeightMessage = $maxHeightMessage ?? $this->maxHeightMessage; + $this->minHeightMessage = $minHeightMessage ?? $this->minHeightMessage; + $this->minPixelsMessage = $minPixelsMessage ?? $this->minPixelsMessage; + $this->maxPixelsMessage = $maxPixelsMessage ?? $this->maxPixelsMessage; + $this->maxRatioMessage = $maxRatioMessage ?? $this->maxRatioMessage; + $this->minRatioMessage = $minRatioMessage ?? $this->minRatioMessage; + $this->allowSquareMessage = $allowSquareMessage ?? $this->allowSquareMessage; + $this->allowLandscapeMessage = $allowLandscapeMessage ?? $this->allowLandscapeMessage; + $this->allowPortraitMessage = $allowPortraitMessage ?? $this->allowPortraitMessage; + $this->corruptedMessage = $corruptedMessage ?? $this->corruptedMessage; + } } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/FileTest.php b/src/Symfony/Component/Validator/Tests/Constraints/FileTest.php index dfeeeb774e..1e1b522c24 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/FileTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/FileTest.php @@ -14,6 +14,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\File; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; +use Symfony\Component\Validator\Mapping\ClassMetadata; +use Symfony\Component\Validator\Mapping\Loader\AnnotationLoader; class FileTest extends TestCase { @@ -138,4 +140,38 @@ class FileTest extends TestCase ['100Ki', false, false], ]; } + + /** + * @requires PHP 8 + */ + public function testAttributes() + { + $metadata = new ClassMetadata(FileDummy::class); + self::assertTrue((new AnnotationLoader())->loadClassMetadata($metadata)); + + list($aConstraint) = $metadata->properties['a']->getConstraints(); + self::assertNull($aConstraint->maxSize); + + list($bConstraint) = $metadata->properties['b']->getConstraints(); + self::assertSame(100, $bConstraint->maxSize); + self::assertSame('myMessage', $bConstraint->notFoundMessage); + self::assertSame(['Default', 'FileDummy'], $bConstraint->groups); + + list($cConstraint) = $metadata->properties['c']->getConstraints(); + self::assertSame(100000, $cConstraint->maxSize); + self::assertSame(['my_group'], $cConstraint->groups); + self::assertSame('some attached data', $cConstraint->payload); + } +} + +class FileDummy +{ + #[File] + private $a; + + #[File(maxSize: 100, notFoundMessage: 'myMessage')] + private $b; + + #[File(maxSize: '100K', groups: ['my_group'], payload: 'some attached data')] + private $c; } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/FileValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/FileValidatorTest.php index f517baea87..0dafe98b08 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/FileValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/FileValidatorTest.php @@ -281,6 +281,29 @@ abstract class FileValidatorTest extends ConstraintValidatorTestCase ->assertRaised(); } + /** + * @requires PHP 8 + */ + public function testBinaryFormatNamed() + { + fseek($this->file, 10, \SEEK_SET); + fwrite($this->file, '0'); + fclose($this->file); + + $constraint = eval('return new \Symfony\Component\Validator\Constraints\File(maxSize: 10, binaryFormat: true, maxSizeMessage: "myMessage");'); + + $this->validator->validate($this->getFile($this->path), $constraint); + + $this->buildViolation('myMessage') + ->setParameter('{{ limit }}', '10') + ->setParameter('{{ size }}', '11') + ->setParameter('{{ suffix }}', 'bytes') + ->setParameter('{{ file }}', '"'.$this->path.'"') + ->setParameter('{{ name }}', '"'.basename($this->path).'"') + ->setCode(File::TOO_LARGE_ERROR) + ->assertRaised(); + } + public function testValidMimeType() { $file = $this @@ -329,7 +352,10 @@ abstract class FileValidatorTest extends ConstraintValidatorTestCase $this->assertNoViolation(); } - public function testInvalidMimeType() + /** + * @dataProvider provideMimeTypeConstraints + */ + public function testInvalidMimeType(File $constraint) { $file = $this ->getMockBuilder('Symfony\Component\HttpFoundation\File\File') @@ -344,11 +370,6 @@ abstract class FileValidatorTest extends ConstraintValidatorTestCase ->method('getMimeType') ->willReturn('application/pdf'); - $constraint = new File([ - 'mimeTypes' => ['image/png', 'image/jpg'], - 'mimeTypesMessage' => 'myMessage', - ]); - $this->validator->validate($file, $constraint); $this->buildViolation('myMessage') @@ -360,6 +381,20 @@ abstract class FileValidatorTest extends ConstraintValidatorTestCase ->assertRaised(); } + public function provideMimeTypeConstraints(): iterable + { + yield 'Doctrine style' => [new File([ + 'mimeTypes' => ['image/png', 'image/jpg'], + 'mimeTypesMessage' => 'myMessage', + ])]; + + if (\PHP_VERSION_ID >= 80000) { + yield 'named arguments' => [ + eval('return new \Symfony\Component\Validator\Constraints\File(mimeTypes: ["image/png", "image/jpg"], mimeTypesMessage: "myMessage");'), + ]; + } + } + public function testInvalidWildcardMimeType() { $file = $this @@ -391,14 +426,13 @@ abstract class FileValidatorTest extends ConstraintValidatorTestCase ->assertRaised(); } - public function testDisallowEmpty() + /** + * @dataProvider provideDisallowEmptyConstraints + */ + public function testDisallowEmpty(File $constraint) { ftruncate($this->file, 0); - $constraint = new File([ - 'disallowEmptyMessage' => 'myMessage', - ]); - $this->validator->validate($this->getFile($this->path), $constraint); $this->buildViolation('myMessage') @@ -408,6 +442,19 @@ abstract class FileValidatorTest extends ConstraintValidatorTestCase ->assertRaised(); } + public function provideDisallowEmptyConstraints(): iterable + { + yield 'Doctrine style' => [new File([ + 'disallowEmptyMessage' => 'myMessage', + ])]; + + if (\PHP_VERSION_ID >= 80000) { + yield 'named arguments' => [ + eval('return new \Symfony\Component\Validator\Constraints\File(disallowEmptyMessage: "myMessage");'), + ]; + } + } + /** * @dataProvider uploadedFileErrorProvider */ diff --git a/src/Symfony/Component/Validator/Tests/Constraints/ImageTest.php b/src/Symfony/Component/Validator/Tests/Constraints/ImageTest.php new file mode 100644 index 0000000000..80a6e05055 --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/Constraints/ImageTest.php @@ -0,0 +1,60 @@ + + * + * 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 PHPUnit\Framework\TestCase; +use Symfony\Component\Validator\Constraints\Image; +use Symfony\Component\Validator\Mapping\ClassMetadata; +use Symfony\Component\Validator\Mapping\Loader\AnnotationLoader; + +/** + * @requires PHP 8 + */ +class ImageTest extends TestCase +{ + public function testAttributes() + { + $metadata = new ClassMetadata(ImageDummy::class); + $loader = new AnnotationLoader(); + self::assertTrue($loader->loadClassMetadata($metadata)); + + list($aConstraint) = $metadata->properties['a']->getConstraints(); + self::assertNull($aConstraint->minWidth); + self::assertNull($aConstraint->maxWidth); + self::assertNull($aConstraint->minHeight); + self::assertNull($aConstraint->maxHeight); + + list($bConstraint) = $metadata->properties['b']->getConstraints(); + self::assertSame(50, $bConstraint->minWidth); + self::assertSame(200, $bConstraint->maxWidth); + self::assertSame(50, $bConstraint->minHeight); + self::assertSame(200, $bConstraint->maxHeight); + self::assertSame(['Default', 'ImageDummy'], $bConstraint->groups); + + list($cConstraint) = $metadata->properties['c']->getConstraints(); + self::assertSame(100000, $cConstraint->maxSize); + self::assertSame(['my_group'], $cConstraint->groups); + self::assertSame('some attached data', $cConstraint->payload); + } +} + +class ImageDummy +{ + #[Image] + private $a; + + #[Image(minWidth: 50, maxWidth: 200, minHeight: 50, maxHeight: 200)] + private $b; + + #[Image(maxSize: '100K', groups: ['my_group'], payload: 'some attached data')] + private $c; +} diff --git a/src/Symfony/Component/Validator/Tests/Constraints/ImageValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/ImageValidatorTest.php index 2ad9ceb5d8..96f1a8139c 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/ImageValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/ImageValidatorTest.php @@ -71,13 +71,13 @@ class ImageValidatorTest extends ConstraintValidatorTestCase $this->assertNoViolation(); } - public function testFileNotFound() + /** + * Checks that the logic from FileValidator still works. + * + * @dataProvider provideConstraintsWithNotFoundMessage + */ + public function testFileNotFound(Image $constraint) { - // Check that the logic from FileValidator still works - $constraint = new Image([ - 'notFoundMessage' => 'myMessage', - ]); - $this->validator->validate('foobar', $constraint); $this->buildViolation('myMessage') @@ -86,6 +86,19 @@ class ImageValidatorTest extends ConstraintValidatorTestCase ->assertRaised(); } + public function provideConstraintsWithNotFoundMessage(): iterable + { + yield 'Doctrine style' => [new Image([ + 'notFoundMessage' => 'myMessage', + ])]; + + if (\PHP_VERSION_ID >= 80000) { + yield 'Named arguments' => [ + eval('return new \Symfony\Component\Validator\Constraints\Image(notFoundMessage: "myMessage");'), + ]; + } + } + public function testValidSize() { $constraint = new Image([ @@ -100,13 +113,11 @@ class ImageValidatorTest extends ConstraintValidatorTestCase $this->assertNoViolation(); } - public function testWidthTooSmall() + /** + * @dataProvider provideMinWidthConstraints + */ + public function testWidthTooSmall(Image $constraint) { - $constraint = new Image([ - 'minWidth' => 3, - 'minWidthMessage' => 'myMessage', - ]); - $this->validator->validate($this->image, $constraint); $this->buildViolation('myMessage') @@ -116,13 +127,25 @@ class ImageValidatorTest extends ConstraintValidatorTestCase ->assertRaised(); } - public function testWidthTooBig() + public function provideMinWidthConstraints(): iterable { - $constraint = new Image([ - 'maxWidth' => 1, - 'maxWidthMessage' => 'myMessage', - ]); + yield 'Doctrine style' => [new Image([ + 'minWidth' => 3, + 'minWidthMessage' => 'myMessage', + ])]; + if (\PHP_VERSION_ID >= 80000) { + yield 'Named arguments' => [ + eval('return new \Symfony\Component\Validator\Constraints\Image(minWidth: 3, minWidthMessage: "myMessage");'), + ]; + } + } + + /** + * @dataProvider provideMaxWidthConstraints + */ + public function testWidthTooBig(Image $constraint) + { $this->validator->validate($this->image, $constraint); $this->buildViolation('myMessage') @@ -132,13 +155,25 @@ class ImageValidatorTest extends ConstraintValidatorTestCase ->assertRaised(); } - public function testHeightTooSmall() + public function provideMaxWidthConstraints(): iterable { - $constraint = new Image([ - 'minHeight' => 3, - 'minHeightMessage' => 'myMessage', - ]); + yield 'Doctrine style' => [new Image([ + 'maxWidth' => 1, + 'maxWidthMessage' => 'myMessage', + ])]; + if (\PHP_VERSION_ID >= 80000) { + yield 'Named arguments' => [ + eval('return new \Symfony\Component\Validator\Constraints\Image(maxWidth: 1, maxWidthMessage: "myMessage");'), + ]; + } + } + + /** + * @dataProvider provideMinHeightConstraints + */ + public function testHeightTooSmall(Image $constraint) + { $this->validator->validate($this->image, $constraint); $this->buildViolation('myMessage') @@ -148,13 +183,25 @@ class ImageValidatorTest extends ConstraintValidatorTestCase ->assertRaised(); } - public function testHeightTooBig() + public function provideMinHeightConstraints(): iterable { - $constraint = new Image([ - 'maxHeight' => 1, - 'maxHeightMessage' => 'myMessage', - ]); + yield 'Doctrine style' => [new Image([ + 'minHeight' => 3, + 'minHeightMessage' => 'myMessage', + ])]; + if (\PHP_VERSION_ID >= 80000) { + yield 'Named arguments' => [ + eval('return new \Symfony\Component\Validator\Constraints\Image(minHeight: 3, minHeightMessage: "myMessage");'), + ]; + } + } + + /** + * @dataProvider provideMaxHeightConstraints + */ + public function testHeightTooBig(Image $constraint) + { $this->validator->validate($this->image, $constraint); $this->buildViolation('myMessage') @@ -164,13 +211,25 @@ class ImageValidatorTest extends ConstraintValidatorTestCase ->assertRaised(); } - public function testPixelsTooFew() + public function provideMaxHeightConstraints(): iterable { - $constraint = new Image([ - 'minPixels' => 5, - 'minPixelsMessage' => 'myMessage', - ]); + yield 'Doctrine style' => [new Image([ + 'maxHeight' => 1, + 'maxHeightMessage' => 'myMessage', + ])]; + if (\PHP_VERSION_ID >= 80000) { + yield 'Named arguments' => [ + eval('return new \Symfony\Component\Validator\Constraints\Image(maxHeight: 1, maxHeightMessage: "myMessage");'), + ]; + } + } + + /** + * @dataProvider provideMinPixelsConstraints + */ + public function testPixelsTooFew(Image $constraint) + { $this->validator->validate($this->image, $constraint); $this->buildViolation('myMessage') @@ -182,13 +241,25 @@ class ImageValidatorTest extends ConstraintValidatorTestCase ->assertRaised(); } - public function testPixelsTooMany() + public function provideMinPixelsConstraints(): iterable { - $constraint = new Image([ - 'maxPixels' => 3, - 'maxPixelsMessage' => 'myMessage', - ]); + yield 'Doctrine style' => [new Image([ + 'minPixels' => 5, + 'minPixelsMessage' => 'myMessage', + ])]; + if (\PHP_VERSION_ID >= 80000) { + yield 'Named arguments' => [ + eval('return new \Symfony\Component\Validator\Constraints\Image(minPixels: 5, minPixelsMessage: "myMessage");'), + ]; + } + } + + /** + * @dataProvider provideMaxPixelsConstraints + */ + public function testPixelsTooMany(Image $constraint) + { $this->validator->validate($this->image, $constraint); $this->buildViolation('myMessage') @@ -200,6 +271,20 @@ class ImageValidatorTest extends ConstraintValidatorTestCase ->assertRaised(); } + public function provideMaxPixelsConstraints(): iterable + { + yield 'Doctrine style' => [new Image([ + 'maxPixels' => 3, + 'maxPixelsMessage' => 'myMessage', + ])]; + + if (\PHP_VERSION_ID >= 80000) { + yield 'Named arguments' => [ + eval('return new \Symfony\Component\Validator\Constraints\Image(maxPixels: 3, maxPixelsMessage: "myMessage");'), + ]; + } + } + public function testInvalidMinWidth() { $this->expectException('Symfony\Component\Validator\Exception\ConstraintDefinitionException'); @@ -260,13 +345,11 @@ class ImageValidatorTest extends ConstraintValidatorTestCase $this->validator->validate($this->image, $constraint); } - public function testRatioTooSmall() + /** + * @dataProvider provideMinRatioConstraints + */ + public function testRatioTooSmall(Image $constraint) { - $constraint = new Image([ - 'minRatio' => 2, - 'minRatioMessage' => 'myMessage', - ]); - $this->validator->validate($this->image, $constraint); $this->buildViolation('myMessage') @@ -276,13 +359,25 @@ class ImageValidatorTest extends ConstraintValidatorTestCase ->assertRaised(); } - public function testRatioTooBig() + public function provideMinRatioConstraints(): iterable { - $constraint = new Image([ - 'maxRatio' => 0.5, - 'maxRatioMessage' => 'myMessage', - ]); + yield 'Doctrine style' => [new Image([ + 'minRatio' => 2, + 'minRatioMessage' => 'myMessage', + ])]; + if (\PHP_VERSION_ID >= 80000) { + yield 'Named arguments' => [ + eval('return new \Symfony\Component\Validator\Constraints\Image(minRatio: 2, minRatioMessage: "myMessage");'), + ]; + } + } + + /** + * @dataProvider provideMaxRatioConstraints + */ + public function testRatioTooBig(Image $constraint) + { $this->validator->validate($this->image, $constraint); $this->buildViolation('myMessage') @@ -292,6 +387,20 @@ class ImageValidatorTest extends ConstraintValidatorTestCase ->assertRaised(); } + public function provideMaxRatioConstraints(): iterable + { + yield 'Doctrine style' => [new Image([ + 'maxRatio' => 0.5, + 'maxRatioMessage' => 'myMessage', + ])]; + + if (\PHP_VERSION_ID >= 80000) { + yield 'Named arguments' => [ + eval('return new \Symfony\Component\Validator\Constraints\Image(maxRatio: 0.5, maxRatioMessage: "myMessage");'), + ]; + } + } + public function testMaxRatioUsesTwoDecimalsOnly() { $constraint = new Image([ @@ -323,13 +432,11 @@ class ImageValidatorTest extends ConstraintValidatorTestCase $this->validator->validate($this->image, $constraint); } - public function testSquareNotAllowed() + /** + * @dataProvider provideAllowSquareConstraints + */ + public function testSquareNotAllowed(Image $constraint) { - $constraint = new Image([ - 'allowSquare' => false, - 'allowSquareMessage' => 'myMessage', - ]); - $this->validator->validate($this->image, $constraint); $this->buildViolation('myMessage') @@ -339,13 +446,25 @@ class ImageValidatorTest extends ConstraintValidatorTestCase ->assertRaised(); } - public function testLandscapeNotAllowed() + public function provideAllowSquareConstraints(): iterable { - $constraint = new Image([ - 'allowLandscape' => false, - 'allowLandscapeMessage' => 'myMessage', - ]); + yield 'Doctrine style' => [new Image([ + 'allowSquare' => false, + 'allowSquareMessage' => 'myMessage', + ])]; + if (\PHP_VERSION_ID >= 80000) { + yield 'Named arguments' => [ + eval('return new \Symfony\Component\Validator\Constraints\Image(allowSquare: false, allowSquareMessage: "myMessage");'), + ]; + } + } + + /** + * @dataProvider provideAllowLandscapeConstraints + */ + public function testLandscapeNotAllowed(Image $constraint) + { $this->validator->validate($this->imageLandscape, $constraint); $this->buildViolation('myMessage') @@ -355,13 +474,25 @@ class ImageValidatorTest extends ConstraintValidatorTestCase ->assertRaised(); } - public function testPortraitNotAllowed() + public function provideAllowLandscapeConstraints(): iterable { - $constraint = new Image([ - 'allowPortrait' => false, - 'allowPortraitMessage' => 'myMessage', - ]); + yield 'Doctrine style' => [new Image([ + 'allowLandscape' => false, + 'allowLandscapeMessage' => 'myMessage', + ])]; + if (\PHP_VERSION_ID >= 80000) { + yield 'Named arguments' => [ + eval('return new \Symfony\Component\Validator\Constraints\Image(allowLandscape: false, allowLandscapeMessage: "myMessage");'), + ]; + } + } + + /** + * @dataProvider provideAllowPortraitConstraints + */ + public function testPortraitNotAllowed(Image $constraint) + { $this->validator->validate($this->imagePortrait, $constraint); $this->buildViolation('myMessage') @@ -371,17 +502,29 @@ class ImageValidatorTest extends ConstraintValidatorTestCase ->assertRaised(); } - public function testCorrupted() + public function provideAllowPortraitConstraints(): iterable + { + yield 'Doctrine style' => [new Image([ + 'allowPortrait' => false, + 'allowPortraitMessage' => 'myMessage', + ])]; + + if (\PHP_VERSION_ID >= 80000) { + yield 'Named arguments' => [ + eval('return new \Symfony\Component\Validator\Constraints\Image(allowPortrait: false, allowPortraitMessage: "myMessage");'), + ]; + } + } + + /** + * @dataProvider provideDetectCorruptedConstraints + */ + public function testCorrupted(Image $constraint) { if (!\function_exists('imagecreatefromstring')) { $this->markTestSkipped('This test require GD extension'); } - $constraint = new Image([ - 'detectCorrupted' => true, - 'corruptedMessage' => 'myMessage', - ]); - $this->validator->validate($this->image, $constraint); $this->assertNoViolation(); @@ -392,4 +535,18 @@ class ImageValidatorTest extends ConstraintValidatorTestCase ->setCode(Image::CORRUPTED_IMAGE_ERROR) ->assertRaised(); } + + public function provideDetectCorruptedConstraints(): iterable + { + yield 'Doctrine style' => [new Image([ + 'detectCorrupted' => true, + 'corruptedMessage' => 'myMessage', + ])]; + + if (\PHP_VERSION_ID >= 80000) { + yield 'Named arguments' => [ + eval('return new \Symfony\Component\Validator\Constraints\Image(detectCorrupted: true, corruptedMessage: "myMessage");'), + ]; + } + } }