Mercurial > hg > cmmr2012-drupal-site
comparison vendor/symfony/validator/Constraints/FileValidator.php @ 0:c75dbcec494b
Initial commit from drush-created site
author | Chris Cannam |
---|---|
date | Thu, 05 Jul 2018 14:24:15 +0000 |
parents | |
children | a9cd425dd02b |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:c75dbcec494b |
---|---|
1 <?php | |
2 | |
3 /* | |
4 * This file is part of the Symfony package. | |
5 * | |
6 * (c) Fabien Potencier <fabien@symfony.com> | |
7 * | |
8 * For the full copyright and license information, please view the LICENSE | |
9 * file that was distributed with this source code. | |
10 */ | |
11 | |
12 namespace Symfony\Component\Validator\Constraints; | |
13 | |
14 use Symfony\Component\HttpFoundation\File\File as FileObject; | |
15 use Symfony\Component\HttpFoundation\File\UploadedFile; | |
16 use Symfony\Component\Validator\Constraint; | |
17 use Symfony\Component\Validator\ConstraintValidator; | |
18 use Symfony\Component\Validator\Exception\UnexpectedTypeException; | |
19 | |
20 /** | |
21 * @author Bernhard Schussek <bschussek@gmail.com> | |
22 */ | |
23 class FileValidator extends ConstraintValidator | |
24 { | |
25 const KB_BYTES = 1000; | |
26 const MB_BYTES = 1000000; | |
27 const KIB_BYTES = 1024; | |
28 const MIB_BYTES = 1048576; | |
29 | |
30 private static $suffices = array( | |
31 1 => 'bytes', | |
32 self::KB_BYTES => 'kB', | |
33 self::MB_BYTES => 'MB', | |
34 self::KIB_BYTES => 'KiB', | |
35 self::MIB_BYTES => 'MiB', | |
36 ); | |
37 | |
38 /** | |
39 * {@inheritdoc} | |
40 */ | |
41 public function validate($value, Constraint $constraint) | |
42 { | |
43 if (!$constraint instanceof File) { | |
44 throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\File'); | |
45 } | |
46 | |
47 if (null === $value || '' === $value) { | |
48 return; | |
49 } | |
50 | |
51 if ($value instanceof UploadedFile && !$value->isValid()) { | |
52 switch ($value->getError()) { | |
53 case UPLOAD_ERR_INI_SIZE: | |
54 $iniLimitSize = UploadedFile::getMaxFilesize(); | |
55 if ($constraint->maxSize && $constraint->maxSize < $iniLimitSize) { | |
56 $limitInBytes = $constraint->maxSize; | |
57 $binaryFormat = $constraint->binaryFormat; | |
58 } else { | |
59 $limitInBytes = $iniLimitSize; | |
60 $binaryFormat = true; | |
61 } | |
62 | |
63 list($sizeAsString, $limitAsString, $suffix) = $this->factorizeSizes(0, $limitInBytes, $binaryFormat); | |
64 $this->context->buildViolation($constraint->uploadIniSizeErrorMessage) | |
65 ->setParameter('{{ limit }}', $limitAsString) | |
66 ->setParameter('{{ suffix }}', $suffix) | |
67 ->setCode(UPLOAD_ERR_INI_SIZE) | |
68 ->addViolation(); | |
69 | |
70 return; | |
71 case UPLOAD_ERR_FORM_SIZE: | |
72 $this->context->buildViolation($constraint->uploadFormSizeErrorMessage) | |
73 ->setCode(UPLOAD_ERR_FORM_SIZE) | |
74 ->addViolation(); | |
75 | |
76 return; | |
77 case UPLOAD_ERR_PARTIAL: | |
78 $this->context->buildViolation($constraint->uploadPartialErrorMessage) | |
79 ->setCode(UPLOAD_ERR_PARTIAL) | |
80 ->addViolation(); | |
81 | |
82 return; | |
83 case UPLOAD_ERR_NO_FILE: | |
84 $this->context->buildViolation($constraint->uploadNoFileErrorMessage) | |
85 ->setCode(UPLOAD_ERR_NO_FILE) | |
86 ->addViolation(); | |
87 | |
88 return; | |
89 case UPLOAD_ERR_NO_TMP_DIR: | |
90 $this->context->buildViolation($constraint->uploadNoTmpDirErrorMessage) | |
91 ->setCode(UPLOAD_ERR_NO_TMP_DIR) | |
92 ->addViolation(); | |
93 | |
94 return; | |
95 case UPLOAD_ERR_CANT_WRITE: | |
96 $this->context->buildViolation($constraint->uploadCantWriteErrorMessage) | |
97 ->setCode(UPLOAD_ERR_CANT_WRITE) | |
98 ->addViolation(); | |
99 | |
100 return; | |
101 case UPLOAD_ERR_EXTENSION: | |
102 $this->context->buildViolation($constraint->uploadExtensionErrorMessage) | |
103 ->setCode(UPLOAD_ERR_EXTENSION) | |
104 ->addViolation(); | |
105 | |
106 return; | |
107 default: | |
108 $this->context->buildViolation($constraint->uploadErrorMessage) | |
109 ->setCode($value->getError()) | |
110 ->addViolation(); | |
111 | |
112 return; | |
113 } | |
114 } | |
115 | |
116 if (!is_scalar($value) && !$value instanceof FileObject && !(is_object($value) && method_exists($value, '__toString'))) { | |
117 throw new UnexpectedTypeException($value, 'string'); | |
118 } | |
119 | |
120 $path = $value instanceof FileObject ? $value->getPathname() : (string) $value; | |
121 | |
122 if (!is_file($path)) { | |
123 $this->context->buildViolation($constraint->notFoundMessage) | |
124 ->setParameter('{{ file }}', $this->formatValue($path)) | |
125 ->setCode(File::NOT_FOUND_ERROR) | |
126 ->addViolation(); | |
127 | |
128 return; | |
129 } | |
130 | |
131 if (!is_readable($path)) { | |
132 $this->context->buildViolation($constraint->notReadableMessage) | |
133 ->setParameter('{{ file }}', $this->formatValue($path)) | |
134 ->setCode(File::NOT_READABLE_ERROR) | |
135 ->addViolation(); | |
136 | |
137 return; | |
138 } | |
139 | |
140 $sizeInBytes = filesize($path); | |
141 | |
142 if (0 === $sizeInBytes) { | |
143 $this->context->buildViolation($constraint->disallowEmptyMessage) | |
144 ->setParameter('{{ file }}', $this->formatValue($path)) | |
145 ->setCode(File::EMPTY_ERROR) | |
146 ->addViolation(); | |
147 | |
148 return; | |
149 } | |
150 | |
151 if ($constraint->maxSize) { | |
152 $limitInBytes = $constraint->maxSize; | |
153 | |
154 if ($sizeInBytes > $limitInBytes) { | |
155 list($sizeAsString, $limitAsString, $suffix) = $this->factorizeSizes($sizeInBytes, $limitInBytes, $constraint->binaryFormat); | |
156 $this->context->buildViolation($constraint->maxSizeMessage) | |
157 ->setParameter('{{ file }}', $this->formatValue($path)) | |
158 ->setParameter('{{ size }}', $sizeAsString) | |
159 ->setParameter('{{ limit }}', $limitAsString) | |
160 ->setParameter('{{ suffix }}', $suffix) | |
161 ->setCode(File::TOO_LARGE_ERROR) | |
162 ->addViolation(); | |
163 | |
164 return; | |
165 } | |
166 } | |
167 | |
168 if ($constraint->mimeTypes) { | |
169 if (!$value instanceof FileObject) { | |
170 $value = new FileObject($value); | |
171 } | |
172 | |
173 $mimeTypes = (array) $constraint->mimeTypes; | |
174 $mime = $value->getMimeType(); | |
175 | |
176 foreach ($mimeTypes as $mimeType) { | |
177 if ($mimeType === $mime) { | |
178 return; | |
179 } | |
180 | |
181 if ($discrete = strstr($mimeType, '/*', true)) { | |
182 if (strstr($mime, '/', true) === $discrete) { | |
183 return; | |
184 } | |
185 } | |
186 } | |
187 | |
188 $this->context->buildViolation($constraint->mimeTypesMessage) | |
189 ->setParameter('{{ file }}', $this->formatValue($path)) | |
190 ->setParameter('{{ type }}', $this->formatValue($mime)) | |
191 ->setParameter('{{ types }}', $this->formatValues($mimeTypes)) | |
192 ->setCode(File::INVALID_MIME_TYPE_ERROR) | |
193 ->addViolation(); | |
194 } | |
195 } | |
196 | |
197 private static function moreDecimalsThan($double, $numberOfDecimals) | |
198 { | |
199 return strlen((string) $double) > strlen(round($double, $numberOfDecimals)); | |
200 } | |
201 | |
202 /** | |
203 * Convert the limit to the smallest possible number | |
204 * (i.e. try "MB", then "kB", then "bytes"). | |
205 */ | |
206 private function factorizeSizes($size, $limit, $binaryFormat) | |
207 { | |
208 if ($binaryFormat) { | |
209 $coef = self::MIB_BYTES; | |
210 $coefFactor = self::KIB_BYTES; | |
211 } else { | |
212 $coef = self::MB_BYTES; | |
213 $coefFactor = self::KB_BYTES; | |
214 } | |
215 | |
216 $limitAsString = (string) ($limit / $coef); | |
217 | |
218 // Restrict the limit to 2 decimals (without rounding! we | |
219 // need the precise value) | |
220 while (self::moreDecimalsThan($limitAsString, 2)) { | |
221 $coef /= $coefFactor; | |
222 $limitAsString = (string) ($limit / $coef); | |
223 } | |
224 | |
225 // Convert size to the same measure, but round to 2 decimals | |
226 $sizeAsString = (string) round($size / $coef, 2); | |
227 | |
228 // If the size and limit produce the same string output | |
229 // (due to rounding), reduce the coefficient | |
230 while ($sizeAsString === $limitAsString) { | |
231 $coef /= $coefFactor; | |
232 $limitAsString = (string) ($limit / $coef); | |
233 $sizeAsString = (string) round($size / $coef, 2); | |
234 } | |
235 | |
236 return array($sizeAsString, $limitAsString, self::$suffices[$coef]); | |
237 } | |
238 } |