Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 /*
|
Chris@0
|
4 * This file is part of the Symfony package.
|
Chris@0
|
5 *
|
Chris@0
|
6 * (c) Fabien Potencier <fabien@symfony.com>
|
Chris@0
|
7 *
|
Chris@0
|
8 * For the full copyright and license information, please view the LICENSE
|
Chris@0
|
9 * file that was distributed with this source code.
|
Chris@0
|
10 */
|
Chris@0
|
11
|
Chris@0
|
12 namespace Symfony\Component\Validator\Constraints;
|
Chris@0
|
13
|
Chris@0
|
14 use Symfony\Component\Validator\Constraint;
|
Chris@0
|
15 use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
|
Chris@0
|
16 use Symfony\Component\Validator\Exception\RuntimeException;
|
Chris@0
|
17 use Symfony\Component\Validator\Exception\UnexpectedTypeException;
|
Chris@0
|
18
|
Chris@0
|
19 /**
|
Chris@0
|
20 * Validates whether a value is a valid image file and is valid
|
Chris@0
|
21 * against minWidth, maxWidth, minHeight and maxHeight constraints.
|
Chris@0
|
22 *
|
Chris@0
|
23 * @author Benjamin Dulau <benjamin.dulau@gmail.com>
|
Chris@0
|
24 * @author Bernhard Schussek <bschussek@gmail.com>
|
Chris@0
|
25 */
|
Chris@0
|
26 class ImageValidator extends FileValidator
|
Chris@0
|
27 {
|
Chris@0
|
28 /**
|
Chris@0
|
29 * {@inheritdoc}
|
Chris@0
|
30 */
|
Chris@0
|
31 public function validate($value, Constraint $constraint)
|
Chris@0
|
32 {
|
Chris@0
|
33 if (!$constraint instanceof Image) {
|
Chris@0
|
34 throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Image');
|
Chris@0
|
35 }
|
Chris@0
|
36
|
Chris@17
|
37 $violations = \count($this->context->getViolations());
|
Chris@0
|
38
|
Chris@0
|
39 parent::validate($value, $constraint);
|
Chris@0
|
40
|
Chris@17
|
41 $failed = \count($this->context->getViolations()) !== $violations;
|
Chris@0
|
42
|
Chris@0
|
43 if ($failed || null === $value || '' === $value) {
|
Chris@0
|
44 return;
|
Chris@0
|
45 }
|
Chris@0
|
46
|
Chris@0
|
47 if (null === $constraint->minWidth && null === $constraint->maxWidth
|
Chris@0
|
48 && null === $constraint->minHeight && null === $constraint->maxHeight
|
Chris@14
|
49 && null === $constraint->minPixels && null === $constraint->maxPixels
|
Chris@0
|
50 && null === $constraint->minRatio && null === $constraint->maxRatio
|
Chris@0
|
51 && $constraint->allowSquare && $constraint->allowLandscape && $constraint->allowPortrait
|
Chris@0
|
52 && !$constraint->detectCorrupted) {
|
Chris@0
|
53 return;
|
Chris@0
|
54 }
|
Chris@0
|
55
|
Chris@0
|
56 $size = @getimagesize($value);
|
Chris@0
|
57
|
Chris@14
|
58 if (empty($size) || (0 === $size[0]) || (0 === $size[1])) {
|
Chris@0
|
59 $this->context->buildViolation($constraint->sizeNotDetectedMessage)
|
Chris@0
|
60 ->setCode(Image::SIZE_NOT_DETECTED_ERROR)
|
Chris@0
|
61 ->addViolation();
|
Chris@0
|
62
|
Chris@0
|
63 return;
|
Chris@0
|
64 }
|
Chris@0
|
65
|
Chris@0
|
66 $width = $size[0];
|
Chris@0
|
67 $height = $size[1];
|
Chris@0
|
68
|
Chris@0
|
69 if ($constraint->minWidth) {
|
Chris@0
|
70 if (!ctype_digit((string) $constraint->minWidth)) {
|
Chris@14
|
71 throw new ConstraintDefinitionException(sprintf('"%s" is not a valid minimum width.', $constraint->minWidth));
|
Chris@0
|
72 }
|
Chris@0
|
73
|
Chris@0
|
74 if ($width < $constraint->minWidth) {
|
Chris@0
|
75 $this->context->buildViolation($constraint->minWidthMessage)
|
Chris@0
|
76 ->setParameter('{{ width }}', $width)
|
Chris@0
|
77 ->setParameter('{{ min_width }}', $constraint->minWidth)
|
Chris@0
|
78 ->setCode(Image::TOO_NARROW_ERROR)
|
Chris@0
|
79 ->addViolation();
|
Chris@0
|
80
|
Chris@0
|
81 return;
|
Chris@0
|
82 }
|
Chris@0
|
83 }
|
Chris@0
|
84
|
Chris@0
|
85 if ($constraint->maxWidth) {
|
Chris@0
|
86 if (!ctype_digit((string) $constraint->maxWidth)) {
|
Chris@14
|
87 throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum width.', $constraint->maxWidth));
|
Chris@0
|
88 }
|
Chris@0
|
89
|
Chris@0
|
90 if ($width > $constraint->maxWidth) {
|
Chris@0
|
91 $this->context->buildViolation($constraint->maxWidthMessage)
|
Chris@0
|
92 ->setParameter('{{ width }}', $width)
|
Chris@0
|
93 ->setParameter('{{ max_width }}', $constraint->maxWidth)
|
Chris@0
|
94 ->setCode(Image::TOO_WIDE_ERROR)
|
Chris@0
|
95 ->addViolation();
|
Chris@0
|
96
|
Chris@0
|
97 return;
|
Chris@0
|
98 }
|
Chris@0
|
99 }
|
Chris@0
|
100
|
Chris@0
|
101 if ($constraint->minHeight) {
|
Chris@0
|
102 if (!ctype_digit((string) $constraint->minHeight)) {
|
Chris@0
|
103 throw new ConstraintDefinitionException(sprintf('"%s" is not a valid minimum height', $constraint->minHeight));
|
Chris@0
|
104 }
|
Chris@0
|
105
|
Chris@0
|
106 if ($height < $constraint->minHeight) {
|
Chris@0
|
107 $this->context->buildViolation($constraint->minHeightMessage)
|
Chris@0
|
108 ->setParameter('{{ height }}', $height)
|
Chris@0
|
109 ->setParameter('{{ min_height }}', $constraint->minHeight)
|
Chris@0
|
110 ->setCode(Image::TOO_LOW_ERROR)
|
Chris@0
|
111 ->addViolation();
|
Chris@0
|
112
|
Chris@0
|
113 return;
|
Chris@0
|
114 }
|
Chris@0
|
115 }
|
Chris@0
|
116
|
Chris@0
|
117 if ($constraint->maxHeight) {
|
Chris@0
|
118 if (!ctype_digit((string) $constraint->maxHeight)) {
|
Chris@0
|
119 throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum height', $constraint->maxHeight));
|
Chris@0
|
120 }
|
Chris@0
|
121
|
Chris@0
|
122 if ($height > $constraint->maxHeight) {
|
Chris@0
|
123 $this->context->buildViolation($constraint->maxHeightMessage)
|
Chris@0
|
124 ->setParameter('{{ height }}', $height)
|
Chris@0
|
125 ->setParameter('{{ max_height }}', $constraint->maxHeight)
|
Chris@0
|
126 ->setCode(Image::TOO_HIGH_ERROR)
|
Chris@0
|
127 ->addViolation();
|
Chris@0
|
128 }
|
Chris@0
|
129 }
|
Chris@0
|
130
|
Chris@14
|
131 $pixels = $width * $height;
|
Chris@14
|
132
|
Chris@14
|
133 if (null !== $constraint->minPixels) {
|
Chris@14
|
134 if (!ctype_digit((string) $constraint->minPixels)) {
|
Chris@14
|
135 throw new ConstraintDefinitionException(sprintf('"%s" is not a valid minimum amount of pixels', $constraint->minPixels));
|
Chris@14
|
136 }
|
Chris@14
|
137
|
Chris@14
|
138 if ($pixels < $constraint->minPixels) {
|
Chris@14
|
139 $this->context->buildViolation($constraint->minPixelsMessage)
|
Chris@14
|
140 ->setParameter('{{ pixels }}', $pixels)
|
Chris@14
|
141 ->setParameter('{{ min_pixels }}', $constraint->minPixels)
|
Chris@14
|
142 ->setParameter('{{ height }}', $height)
|
Chris@14
|
143 ->setParameter('{{ width }}', $width)
|
Chris@14
|
144 ->setCode(Image::TOO_FEW_PIXEL_ERROR)
|
Chris@14
|
145 ->addViolation();
|
Chris@14
|
146 }
|
Chris@14
|
147 }
|
Chris@14
|
148
|
Chris@14
|
149 if (null !== $constraint->maxPixels) {
|
Chris@14
|
150 if (!ctype_digit((string) $constraint->maxPixels)) {
|
Chris@14
|
151 throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum amount of pixels', $constraint->maxPixels));
|
Chris@14
|
152 }
|
Chris@14
|
153
|
Chris@14
|
154 if ($pixels > $constraint->maxPixels) {
|
Chris@14
|
155 $this->context->buildViolation($constraint->maxPixelsMessage)
|
Chris@14
|
156 ->setParameter('{{ pixels }}', $pixels)
|
Chris@14
|
157 ->setParameter('{{ max_pixels }}', $constraint->maxPixels)
|
Chris@14
|
158 ->setParameter('{{ height }}', $height)
|
Chris@14
|
159 ->setParameter('{{ width }}', $width)
|
Chris@14
|
160 ->setCode(Image::TOO_MANY_PIXEL_ERROR)
|
Chris@14
|
161 ->addViolation();
|
Chris@14
|
162 }
|
Chris@14
|
163 }
|
Chris@14
|
164
|
Chris@0
|
165 $ratio = round($width / $height, 2);
|
Chris@0
|
166
|
Chris@0
|
167 if (null !== $constraint->minRatio) {
|
Chris@0
|
168 if (!is_numeric((string) $constraint->minRatio)) {
|
Chris@0
|
169 throw new ConstraintDefinitionException(sprintf('"%s" is not a valid minimum ratio', $constraint->minRatio));
|
Chris@0
|
170 }
|
Chris@0
|
171
|
Chris@0
|
172 if ($ratio < $constraint->minRatio) {
|
Chris@0
|
173 $this->context->buildViolation($constraint->minRatioMessage)
|
Chris@0
|
174 ->setParameter('{{ ratio }}', $ratio)
|
Chris@0
|
175 ->setParameter('{{ min_ratio }}', $constraint->minRatio)
|
Chris@0
|
176 ->setCode(Image::RATIO_TOO_SMALL_ERROR)
|
Chris@0
|
177 ->addViolation();
|
Chris@0
|
178 }
|
Chris@0
|
179 }
|
Chris@0
|
180
|
Chris@0
|
181 if (null !== $constraint->maxRatio) {
|
Chris@0
|
182 if (!is_numeric((string) $constraint->maxRatio)) {
|
Chris@0
|
183 throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum ratio', $constraint->maxRatio));
|
Chris@0
|
184 }
|
Chris@0
|
185
|
Chris@0
|
186 if ($ratio > $constraint->maxRatio) {
|
Chris@0
|
187 $this->context->buildViolation($constraint->maxRatioMessage)
|
Chris@0
|
188 ->setParameter('{{ ratio }}', $ratio)
|
Chris@0
|
189 ->setParameter('{{ max_ratio }}', $constraint->maxRatio)
|
Chris@0
|
190 ->setCode(Image::RATIO_TOO_BIG_ERROR)
|
Chris@0
|
191 ->addViolation();
|
Chris@0
|
192 }
|
Chris@0
|
193 }
|
Chris@0
|
194
|
Chris@0
|
195 if (!$constraint->allowSquare && $width == $height) {
|
Chris@0
|
196 $this->context->buildViolation($constraint->allowSquareMessage)
|
Chris@0
|
197 ->setParameter('{{ width }}', $width)
|
Chris@0
|
198 ->setParameter('{{ height }}', $height)
|
Chris@0
|
199 ->setCode(Image::SQUARE_NOT_ALLOWED_ERROR)
|
Chris@0
|
200 ->addViolation();
|
Chris@0
|
201 }
|
Chris@0
|
202
|
Chris@0
|
203 if (!$constraint->allowLandscape && $width > $height) {
|
Chris@0
|
204 $this->context->buildViolation($constraint->allowLandscapeMessage)
|
Chris@0
|
205 ->setParameter('{{ width }}', $width)
|
Chris@0
|
206 ->setParameter('{{ height }}', $height)
|
Chris@0
|
207 ->setCode(Image::LANDSCAPE_NOT_ALLOWED_ERROR)
|
Chris@0
|
208 ->addViolation();
|
Chris@0
|
209 }
|
Chris@0
|
210
|
Chris@0
|
211 if (!$constraint->allowPortrait && $width < $height) {
|
Chris@0
|
212 $this->context->buildViolation($constraint->allowPortraitMessage)
|
Chris@0
|
213 ->setParameter('{{ width }}', $width)
|
Chris@0
|
214 ->setParameter('{{ height }}', $height)
|
Chris@0
|
215 ->setCode(Image::PORTRAIT_NOT_ALLOWED_ERROR)
|
Chris@0
|
216 ->addViolation();
|
Chris@0
|
217 }
|
Chris@0
|
218
|
Chris@0
|
219 if ($constraint->detectCorrupted) {
|
Chris@17
|
220 if (!\function_exists('imagecreatefromstring')) {
|
Chris@0
|
221 throw new RuntimeException('Corrupted images detection requires installed and enabled GD extension');
|
Chris@0
|
222 }
|
Chris@0
|
223
|
Chris@0
|
224 $resource = @imagecreatefromstring(file_get_contents($value));
|
Chris@0
|
225
|
Chris@0
|
226 if (false === $resource) {
|
Chris@0
|
227 $this->context->buildViolation($constraint->corruptedMessage)
|
Chris@0
|
228 ->setCode(Image::CORRUPTED_IMAGE_ERROR)
|
Chris@0
|
229 ->addViolation();
|
Chris@0
|
230
|
Chris@0
|
231 return;
|
Chris@0
|
232 }
|
Chris@0
|
233
|
Chris@0
|
234 imagedestroy($resource);
|
Chris@0
|
235 }
|
Chris@0
|
236 }
|
Chris@0
|
237 }
|