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@0
|
37 $violations = count($this->context->getViolations());
|
Chris@0
|
38
|
Chris@0
|
39 parent::validate($value, $constraint);
|
Chris@0
|
40
|
Chris@0
|
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@0
|
49 && null === $constraint->minRatio && null === $constraint->maxRatio
|
Chris@0
|
50 && $constraint->allowSquare && $constraint->allowLandscape && $constraint->allowPortrait
|
Chris@0
|
51 && !$constraint->detectCorrupted) {
|
Chris@0
|
52 return;
|
Chris@0
|
53 }
|
Chris@0
|
54
|
Chris@0
|
55 $size = @getimagesize($value);
|
Chris@0
|
56
|
Chris@0
|
57 if (empty($size) || ($size[0] === 0) || ($size[1] === 0)) {
|
Chris@0
|
58 $this->context->buildViolation($constraint->sizeNotDetectedMessage)
|
Chris@0
|
59 ->setCode(Image::SIZE_NOT_DETECTED_ERROR)
|
Chris@0
|
60 ->addViolation();
|
Chris@0
|
61
|
Chris@0
|
62 return;
|
Chris@0
|
63 }
|
Chris@0
|
64
|
Chris@0
|
65 $width = $size[0];
|
Chris@0
|
66 $height = $size[1];
|
Chris@0
|
67
|
Chris@0
|
68 if ($constraint->minWidth) {
|
Chris@0
|
69 if (!ctype_digit((string) $constraint->minWidth)) {
|
Chris@0
|
70 throw new ConstraintDefinitionException(sprintf('"%s" is not a valid minimum width', $constraint->minWidth));
|
Chris@0
|
71 }
|
Chris@0
|
72
|
Chris@0
|
73 if ($width < $constraint->minWidth) {
|
Chris@0
|
74 $this->context->buildViolation($constraint->minWidthMessage)
|
Chris@0
|
75 ->setParameter('{{ width }}', $width)
|
Chris@0
|
76 ->setParameter('{{ min_width }}', $constraint->minWidth)
|
Chris@0
|
77 ->setCode(Image::TOO_NARROW_ERROR)
|
Chris@0
|
78 ->addViolation();
|
Chris@0
|
79
|
Chris@0
|
80 return;
|
Chris@0
|
81 }
|
Chris@0
|
82 }
|
Chris@0
|
83
|
Chris@0
|
84 if ($constraint->maxWidth) {
|
Chris@0
|
85 if (!ctype_digit((string) $constraint->maxWidth)) {
|
Chris@0
|
86 throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum width', $constraint->maxWidth));
|
Chris@0
|
87 }
|
Chris@0
|
88
|
Chris@0
|
89 if ($width > $constraint->maxWidth) {
|
Chris@0
|
90 $this->context->buildViolation($constraint->maxWidthMessage)
|
Chris@0
|
91 ->setParameter('{{ width }}', $width)
|
Chris@0
|
92 ->setParameter('{{ max_width }}', $constraint->maxWidth)
|
Chris@0
|
93 ->setCode(Image::TOO_WIDE_ERROR)
|
Chris@0
|
94 ->addViolation();
|
Chris@0
|
95
|
Chris@0
|
96 return;
|
Chris@0
|
97 }
|
Chris@0
|
98 }
|
Chris@0
|
99
|
Chris@0
|
100 if ($constraint->minHeight) {
|
Chris@0
|
101 if (!ctype_digit((string) $constraint->minHeight)) {
|
Chris@0
|
102 throw new ConstraintDefinitionException(sprintf('"%s" is not a valid minimum height', $constraint->minHeight));
|
Chris@0
|
103 }
|
Chris@0
|
104
|
Chris@0
|
105 if ($height < $constraint->minHeight) {
|
Chris@0
|
106 $this->context->buildViolation($constraint->minHeightMessage)
|
Chris@0
|
107 ->setParameter('{{ height }}', $height)
|
Chris@0
|
108 ->setParameter('{{ min_height }}', $constraint->minHeight)
|
Chris@0
|
109 ->setCode(Image::TOO_LOW_ERROR)
|
Chris@0
|
110 ->addViolation();
|
Chris@0
|
111
|
Chris@0
|
112 return;
|
Chris@0
|
113 }
|
Chris@0
|
114 }
|
Chris@0
|
115
|
Chris@0
|
116 if ($constraint->maxHeight) {
|
Chris@0
|
117 if (!ctype_digit((string) $constraint->maxHeight)) {
|
Chris@0
|
118 throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum height', $constraint->maxHeight));
|
Chris@0
|
119 }
|
Chris@0
|
120
|
Chris@0
|
121 if ($height > $constraint->maxHeight) {
|
Chris@0
|
122 $this->context->buildViolation($constraint->maxHeightMessage)
|
Chris@0
|
123 ->setParameter('{{ height }}', $height)
|
Chris@0
|
124 ->setParameter('{{ max_height }}', $constraint->maxHeight)
|
Chris@0
|
125 ->setCode(Image::TOO_HIGH_ERROR)
|
Chris@0
|
126 ->addViolation();
|
Chris@0
|
127 }
|
Chris@0
|
128 }
|
Chris@0
|
129
|
Chris@0
|
130 $ratio = round($width / $height, 2);
|
Chris@0
|
131
|
Chris@0
|
132 if (null !== $constraint->minRatio) {
|
Chris@0
|
133 if (!is_numeric((string) $constraint->minRatio)) {
|
Chris@0
|
134 throw new ConstraintDefinitionException(sprintf('"%s" is not a valid minimum ratio', $constraint->minRatio));
|
Chris@0
|
135 }
|
Chris@0
|
136
|
Chris@0
|
137 if ($ratio < $constraint->minRatio) {
|
Chris@0
|
138 $this->context->buildViolation($constraint->minRatioMessage)
|
Chris@0
|
139 ->setParameter('{{ ratio }}', $ratio)
|
Chris@0
|
140 ->setParameter('{{ min_ratio }}', $constraint->minRatio)
|
Chris@0
|
141 ->setCode(Image::RATIO_TOO_SMALL_ERROR)
|
Chris@0
|
142 ->addViolation();
|
Chris@0
|
143 }
|
Chris@0
|
144 }
|
Chris@0
|
145
|
Chris@0
|
146 if (null !== $constraint->maxRatio) {
|
Chris@0
|
147 if (!is_numeric((string) $constraint->maxRatio)) {
|
Chris@0
|
148 throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum ratio', $constraint->maxRatio));
|
Chris@0
|
149 }
|
Chris@0
|
150
|
Chris@0
|
151 if ($ratio > $constraint->maxRatio) {
|
Chris@0
|
152 $this->context->buildViolation($constraint->maxRatioMessage)
|
Chris@0
|
153 ->setParameter('{{ ratio }}', $ratio)
|
Chris@0
|
154 ->setParameter('{{ max_ratio }}', $constraint->maxRatio)
|
Chris@0
|
155 ->setCode(Image::RATIO_TOO_BIG_ERROR)
|
Chris@0
|
156 ->addViolation();
|
Chris@0
|
157 }
|
Chris@0
|
158 }
|
Chris@0
|
159
|
Chris@0
|
160 if (!$constraint->allowSquare && $width == $height) {
|
Chris@0
|
161 $this->context->buildViolation($constraint->allowSquareMessage)
|
Chris@0
|
162 ->setParameter('{{ width }}', $width)
|
Chris@0
|
163 ->setParameter('{{ height }}', $height)
|
Chris@0
|
164 ->setCode(Image::SQUARE_NOT_ALLOWED_ERROR)
|
Chris@0
|
165 ->addViolation();
|
Chris@0
|
166 }
|
Chris@0
|
167
|
Chris@0
|
168 if (!$constraint->allowLandscape && $width > $height) {
|
Chris@0
|
169 $this->context->buildViolation($constraint->allowLandscapeMessage)
|
Chris@0
|
170 ->setParameter('{{ width }}', $width)
|
Chris@0
|
171 ->setParameter('{{ height }}', $height)
|
Chris@0
|
172 ->setCode(Image::LANDSCAPE_NOT_ALLOWED_ERROR)
|
Chris@0
|
173 ->addViolation();
|
Chris@0
|
174 }
|
Chris@0
|
175
|
Chris@0
|
176 if (!$constraint->allowPortrait && $width < $height) {
|
Chris@0
|
177 $this->context->buildViolation($constraint->allowPortraitMessage)
|
Chris@0
|
178 ->setParameter('{{ width }}', $width)
|
Chris@0
|
179 ->setParameter('{{ height }}', $height)
|
Chris@0
|
180 ->setCode(Image::PORTRAIT_NOT_ALLOWED_ERROR)
|
Chris@0
|
181 ->addViolation();
|
Chris@0
|
182 }
|
Chris@0
|
183
|
Chris@0
|
184 if ($constraint->detectCorrupted) {
|
Chris@0
|
185 if (!function_exists('imagecreatefromstring')) {
|
Chris@0
|
186 throw new RuntimeException('Corrupted images detection requires installed and enabled GD extension');
|
Chris@0
|
187 }
|
Chris@0
|
188
|
Chris@0
|
189 $resource = @imagecreatefromstring(file_get_contents($value));
|
Chris@0
|
190
|
Chris@0
|
191 if (false === $resource) {
|
Chris@0
|
192 $this->context->buildViolation($constraint->corruptedMessage)
|
Chris@0
|
193 ->setCode(Image::CORRUPTED_IMAGE_ERROR)
|
Chris@0
|
194 ->addViolation();
|
Chris@0
|
195
|
Chris@0
|
196 return;
|
Chris@0
|
197 }
|
Chris@0
|
198
|
Chris@0
|
199 imagedestroy($resource);
|
Chris@0
|
200 }
|
Chris@0
|
201 }
|
Chris@0
|
202 }
|