Overview

Namespaces

  • None
  • PHP
  • Wei
    • Validator

Classes

  • All
  • AllOf
  • Alnum
  • Alpha
  • BaseValidator
  • Between
  • Blank
  • Callback
  • CharLength
  • Chinese
  • Color
  • Contains
  • CreditCard
  • Date
  • DateTime
  • Decimal
  • Digit
  • Dir
  • DivisibleBy
  • DoubleByte
  • Email
  • EndsWith
  • EqualTo
  • Exists
  • FieldExists
  • File
  • GreaterThan
  • GreaterThanOrEqual
  • IdCardCn
  • IdCardHk
  • IdCardMo
  • IdCardTw
  • IdenticalTo
  • Image
  • In
  • Ip
  • Length
  • LessThan
  • LessThanOrEqual
  • Lowercase
  • Luhn
  • MaxLength
  • MinLength
  • MobileCn
  • NaturalNumber
  • NoneOf
  • Null
  • Number
  • OneOf
  • Password
  • Phone
  • PhoneCn
  • PlateNumberCn
  • PositiveInteger
  • PostcodeCn
  • Present
  • QQ
  • RecordExists
  • Regex
  • Required
  • SomeOf
  • StartsWith
  • Time
  • Tld
  • Type
  • Uppercase
  • Url
  • Uuid
  • Overview
  • Namespace
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * Wei Framework
  4:  *
  5:  * @copyright   Copyright (c) 2008-2013 Twin Huang
  6:  * @license     http://opensource.org/licenses/mit-license.php MIT License
  7:  */
  8: 
  9: namespace Wei\Validator;
 10: 
 11: /**
 12:  * Check if the input is valid file
 13:  *
 14:  * @author      Twin Huang <twinhuang@qq.com>
 15:  */
 16: class File extends BaseValidator
 17: {
 18:     protected $notFoundMessage = '%name% is not found or not readable';
 19: 
 20:     protected $maxSizeMessage = '%name% is too large(%sizeString%), allowed maximum size is %maxSizeString%';
 21: 
 22:     protected $minSizeMessage = '%name% is too small(%sizeString%), expected minimum size is %minSizeString%';
 23: 
 24:     protected $extsMessage = '%name% extension(%ext%) is not allowed, allowed extension: %exts%';
 25: 
 26:     protected $excludeExtsMessage = '%name% extension(%ext%) is not allowed, not allowed extension: %excludeExts%';
 27: 
 28:     protected $mimeTypeNotDetectedMessage = '%name% mime type could not be detected';
 29: 
 30:     protected $mimeTypesMessage = '%name% mime type "%mimeType%" is not allowed';
 31: 
 32:     protected $excludeMimeTypesMessage = '%name% mime type "%mimeType%" is not allowed';
 33: 
 34:     protected $negativeMessage = '%name% must be a non-existing file';
 35: 
 36:     /**
 37:      * The absolute file path, or false when file not found or not readable
 38:      *
 39:      * @var string|false
 40:      */
 41:     protected $file;
 42: 
 43:     /**
 44:      * The origin name of uploaded file, if the input is not uploaded file
 45:      * array, the origin name is equals to $this->file
 46:      *
 47:      * @var string
 48:      */
 49:     protected $originFile;
 50: 
 51:     /**
 52:      * The detected byte size of file
 53:      *
 54:      * @var int
 55:      */
 56:     protected $size;
 57: 
 58:     /**
 59:      * The formatted file size, e.g. 1.2MB, 10KB
 60:      *
 61:      * @var string
 62:      */
 63:     protected $sizeString;
 64: 
 65:     /**
 66:      * The maximum file size limit
 67:      *
 68:      * @var int
 69:      */
 70:     protected $maxSize = 0;
 71: 
 72:     /**
 73:      * The formatted maximum file size, e.g. 1.2MB, 10KB
 74:      *
 75:      * @var string
 76:      */
 77:     protected $maxSizeString;
 78: 
 79:     /**
 80:      * The minimum file size limit
 81:      *
 82:      * @var int
 83:      */
 84:     protected $minSize = 0;
 85: 
 86:     /**
 87:      * The formatted minimum file size, e.g. 1.2MB, 10KB
 88:      *
 89:      * @var string
 90:      */
 91:     protected $minSizeString;
 92: 
 93:     /**
 94:      * The detected file extension
 95:      *
 96:      * @var string
 97:      */
 98:     protected $ext;
 99: 
100:     /**
101:      * The allowed file extensions
102:      *
103:      * @var array
104:      */
105:     protected $exts = array();
106: 
107:     /**
108:      * The excluding file extensions
109:      *
110:      * @var array
111:      */
112:     protected $excludeExts = array();
113: 
114:     /**
115:      * The detected file mime type
116:      *
117:      * @var string
118:      */
119:     protected $mimeType;
120: 
121:     /**
122:      * The allowed file mime types
123:      *
124:      * @var array
125:      */
126:     protected $mimeTypes = array();
127: 
128:     /**
129:      * The excluding file mime types
130:      *
131:      * @var array
132:      */
133:     protected $excludeMimeTypes = array();
134: 
135:     /**
136:      * The file size unit
137:      *
138:      * @var string
139:      */
140:     protected $units = array('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
141: 
142:     /**
143:      * The magic database file to detect file mime type
144:      *
145:      * @link http://www.php.net/manual/en/function.finfo-open.php
146:      * @var string|null
147:      */
148:     protected $magicFile;
149: 
150:     /**
151:      * {@inheritdoc}
152:      */
153:     public function __invoke($input, $options = array())
154:     {
155:         $options && $this->storeOption($options);
156: 
157:         return $this->isValid($input);
158:     }
159: 
160:     /**
161:      * {@inheritdoc}
162:      */
163:     protected function doValidate($input)
164:     {
165:         switch ( true ) {
166:             case is_string($input) :
167:                 $file = $originFile = $input;
168:                 break;
169: 
170:             // File array from $_FILES
171:             case is_array($input) :
172:                 if (!isset($input['tmp_name']) || !isset($input['name'])) {
173:                     $this->addError('notFound');
174:                     return false;
175:                 }
176: 
177:                 $file = $input['tmp_name'];
178:                 $originFile = $input['name'];
179:                 break;
180: 
181:             case $input instanceof \SplFileInfo:
182:                 $file = $originFile = $input->getPathname();
183:                 break;
184: 
185:             default:
186:                 $this->addError('notString');
187:                 return false;
188:         }
189: 
190:         $this->originFile = $originFile;
191:         $this->file = $file = stream_resolve_include_path($file);
192:         if (!$file || !is_file($file)) {
193:             $this->addError('notFound');
194:             return false;
195:         }
196: 
197:         // Validate file extension
198:         if ($this->exts || $this->excludeExts) {
199:             $ext = $this->getExt();
200:         }
201: 
202:         if ($this->excludeExts && in_array($ext, $this->excludeExts)) {
203:             $this->addError('excludeExts');
204:         }
205: 
206:         if ($this->exts && !in_array($ext, $this->exts)) {
207:             $this->addError('exts');
208:         }
209: 
210:         // Validate file size
211:         if ($this->maxSize || $this->minSize) {
212:             $this->size = filesize($file);
213:             $this->sizeString = $this->fromBytes($this->size);
214:         }
215: 
216:         if ($this->maxSize && $this->maxSize <= $this->size) {
217:             $this->addError('maxSize');
218:         }
219: 
220:         if ($this->minSize && $this->minSize > $this->size) {
221:             $this->addError('minSize');
222:         }
223: 
224:         // Validate file mime type
225:         if ($this->mimeTypes || $this->excludeMimeTypes) {
226:             $mimeType = $this->getMimeType();
227:             if (!$mimeType) {
228:                 $this->addError('mimeTypeNotDetected');
229:                 return false;
230:             }
231:         }
232: 
233:         if ($this->mimeTypes && !$this->inMimeType($mimeType, $this->mimeTypes)) {
234:             $this->addError('mimeTypes');
235:         }
236: 
237:         if ($this->excludeMimeTypes && $this->inMimeType($mimeType, $this->excludeMimeTypes)) {
238:             $this->addError('excludeMimeTypes');
239:         }
240: 
241:         return !$this->errors;
242:     }
243: 
244:     /**
245:      * Checks if a mime type exists in a mime type array
246:      *
247:      * @param string $findMe    The mime type to be searched
248:      * @param array $mimeTypes  The mime type array, allow element likes
249:      *                          "image/*" to match all image mime type, such as
250:      *                          "image/gif", "image/jpeg", etc
251:      * @return boolean
252:      */
253:     public function inMimeType($findMe, $mimeTypes)
254:     {
255:         foreach ($mimeTypes as $mimeType) {
256:             if ($mimeType == $findMe) {
257:                 return true;
258:             }
259: 
260:             $type = strstr($mimeType, '/*', true);
261:             if ($type && $type === strstr($findMe, '/', true)) {
262:                 return true;
263:             }
264:         }
265:         return false;
266:     }
267: 
268:     /**
269:      * Set allowed file extensions
270:      *
271:      * @param string|array $exts String format likes 'php,js' or array format likes [php, js]
272:      * @return File
273:      */
274:     public function setExts($exts)
275:     {
276:         $this->exts = $this->convertToArray($exts);
277:         return $this;
278:     }
279: 
280:      /**
281:      * Set exclude file extensions
282:      *
283:      * @param string|array $exts String format likes 'php,js' or array format likes [php, js]
284:      * @return File
285:      */
286:     public function setExcludeExts($exts)
287:     {
288:         $this->excludeExts = $this->convertToArray($exts);
289:         return $this;
290:     }
291: 
292:     /**
293:      * Set maximum file size
294:      *
295:      * @param string|int $maxSize
296:      * @return File
297:      */
298:     protected function setMaxSize($maxSize)
299:     {
300:         $this->maxSize = $this->toBytes($maxSize);
301:         $this->maxSizeString = $this->fromBytes($this->maxSize);
302:         return $this;
303:     }
304: 
305:     /**
306:      * Set the minimum file size
307:      *
308:      * @param string|int $minSize
309:      * @return File
310:      */
311:     protected function setMinSize($minSize)
312:     {
313:         $this->minSize = $this->toBytes($minSize);
314:         $this->minSizeString = $this->fromBytes($this->minSize);
315:         return $this;
316:     }
317: 
318:     /**
319:      * Converts human readable file size (e.g. 1.2MB, 10KB) into bytes
320:      *
321:      * @param string|int $size
322:      * @return int
323:      */
324:     public function toBytes($size)
325:     {
326:         if (is_numeric($size)) {
327:             return (int) $size;
328:         }
329: 
330:         $unit = strtoupper(substr($size, -2));
331: 
332:         $value = substr($size, 0, -1);
333:         if (!is_numeric($value)) {
334:             $value = substr($value, 0, -1);
335:         }
336: 
337:         $exponent = array_search($unit, $this->units);
338:         return (int)($value * pow(1024, $exponent));
339:     }
340: 
341:     /**
342:      * Formats bytes to human readable file size (e.g. 1.2MB, 10KB)
343:      *
344:      * @param int $bytes
345:      * @return string
346:      */
347:     public function fromBytes($bytes)
348:     {
349:         for ($i=0; $bytes >= 1024 && $i < 8; $i++) {
350:             $bytes /= 1024;
351:         }
352:         return round($bytes, 2) . $this->units[$i];
353:     }
354: 
355:     /**
356:      * Set the file mime types
357:      *
358:      * @param string|array $mimeTypes
359:      * @return File
360:      */
361:     public function setMimeTypes($mimeTypes)
362:     {
363:         $this->mimeTypes = $this->convertToArray($mimeTypes);
364:         return $this;
365:     }
366: 
367:     /**
368:      * Set the file exclude mime types
369:      *
370:      * @param string|array $excludeMimeTypes
371:      * @return File
372:      */
373:     public function setExcludeMimeTypes($excludeMimeTypes)
374:     {
375:         $this->excludeMimeTypes = $this->convertToArray($excludeMimeTypes);
376:         return $this;
377:     }
378: 
379:     /**
380:      * Converts parameter to array
381:      *
382:      * @param mixed $var
383:      * @return array
384:      * @throws \InvalidArgumentException When parameter is not a string or array
385:      */
386:     protected function convertToArray($var)
387:     {
388:         if (is_string($var)) {
389:             return explode(',', $var);
390:         } elseif (is_array($var)) {
391:             return $var;
392:         } else {
393:             throw new \InvalidArgumentException(sprintf(
394:                 'Expected argument of type string or array, "%s" given',
395:                 is_object($var) ? get_class($var) : gettype($var)
396:             ));
397:         }
398:     }
399: 
400:     /**
401:      * Returns the file mime type on success
402:      *
403:      * @return string|false
404:      * @throws \UnexpectedValueException When failed to open fileinfo database
405:      */
406:     public function getMimeType()
407:     {
408:         if (!$this->mimeType) {
409:             $finfo = finfo_open(FILEINFO_MIME_TYPE, $this->magicFile);
410:             if (!$finfo) {
411:                 throw new \UnexpectedValueException('Failed to open fileinfo database');
412:             }
413:             $this->mimeType = finfo_file($finfo, $this->file);
414:         }
415:         return $this->mimeType;
416:     }
417: 
418:     /**
419:      * Returns the file extension, if file is not exists, return null instead
420:      *
421:      * @return string
422:      */
423:     public function getExt()
424:     {
425:         if (is_null($this->ext) && $this->originFile) {
426:             $file = basename($this->originFile);
427:             // Use substr instead of pathinfo, because pathinfo may return error value in unicode
428:             if (false !== $pos = strrpos($file, '.')) {
429:                 $this->ext = strtolower(substr($file, $pos + 1));
430:             } else {
431:                 $this->ext = '';
432:             }
433:         }
434:         return $this->ext;
435:     }
436: }
437: 
Wei Framework API documentation generated by ApiGen