Overview

Namespaces

  • None
  • Wei
    • Validator

Classes

  • Wei\Validator\All
  • Wei\Validator\AllOf
  • Wei\Validator\Alnum
  • Wei\Validator\Alpha
  • Wei\Validator\BaseValidator
  • Wei\Validator\Between
  • Wei\Validator\Blank
  • Wei\Validator\Callback
  • Wei\Validator\CharLength
  • Wei\Validator\Chinese
  • Wei\Validator\Color
  • Wei\Validator\Contains
  • Wei\Validator\CreditCard
  • Wei\Validator\Date
  • Wei\Validator\DateTime
  • Wei\Validator\Decimal
  • Wei\Validator\Digit
  • Wei\Validator\Dir
  • Wei\Validator\DivisibleBy
  • Wei\Validator\DoubleByte
  • Wei\Validator\Email
  • Wei\Validator\EndsWith
  • Wei\Validator\EqualTo
  • Wei\Validator\Exists
  • Wei\Validator\FieldExists
  • Wei\Validator\File
  • Wei\Validator\GreaterThan
  • Wei\Validator\GreaterThanOrEqual
  • Wei\Validator\IdCardCn
  • Wei\Validator\IdCardHk
  • Wei\Validator\IdCardMo
  • Wei\Validator\IdCardTw
  • Wei\Validator\IdenticalTo
  • Wei\Validator\Image
  • Wei\Validator\In
  • Wei\Validator\Ip
  • Wei\Validator\Length
  • Wei\Validator\LessThan
  • Wei\Validator\LessThanOrEqual
  • Wei\Validator\Lowercase
  • Wei\Validator\Luhn
  • Wei\Validator\MaxLength
  • Wei\Validator\MinLength
  • Wei\Validator\MobileCn
  • Wei\Validator\NaturalNumber
  • Wei\Validator\NoneOf
  • Wei\Validator\Null
  • Wei\Validator\Number
  • Wei\Validator\OneOf
  • Wei\Validator\Password
  • Wei\Validator\Phone
  • Wei\Validator\PhoneCn
  • Wei\Validator\PlateNumberCn
  • Wei\Validator\PositiveInteger
  • Wei\Validator\PostcodeCn
  • Wei\Validator\Present
  • Wei\Validator\QQ
  • Wei\Validator\RecordExists
  • Wei\Validator\Regex
  • Wei\Validator\Required
  • Wei\Validator\SomeOf
  • Wei\Validator\StartsWith
  • Wei\Validator\Time
  • Wei\Validator\Tld
  • Wei\Validator\Type
  • Wei\Validator\Uppercase
  • Wei\Validator\Url
  • Wei\Validator\Uuid
  • Overview
  • Namespace
  • Function
  1: <?php
  2: /**
  3:  * Wei Framework
  4:  *
  5:  * @copyright   Copyright (c) 2008-2015 Twin Huang
  6:  * @license     http://opensource.org/licenses/mit-license.php MIT License
  7:  */
  8: 
  9: namespace Wei;
 10: 
 11: use Wei\Validator\File as FileValidator;
 12: use Wei\Validator\Image;
 13: 
 14: /**
 15:  * A service that handles the uploaded files
 16:  *
 17:  * @author      Twin Huang <twinhuang@qq.com>
 18:  * @property    Request $request The HTTP request wei
 19:  */
 20: class Upload extends Image
 21: {
 22:     /**
 23:      * Seems that the total post data size is too large
 24:      *
 25:      * @link http://php.net/manual/en/ini.core.php#ini.post-max-size
 26:      */
 27:     protected $postSizeMessage = 'No file uploaded or the total file size is too large, allowed maximum size is %postMaxSize%';
 28: 
 29:     /**
 30:      * The uploaded file array do not contain the key "$this->field", or error code not available
 31:      */
 32:     protected $noFileMessage = 'No file uploaded, please select a file to upload';
 33: 
 34:     protected $formLimitMessage = '%name% is larger than the MAX_FILE_SIZE value in the HTML form';
 35: 
 36:     protected $partialMessage = '%name% was partial uploaded, please try again';
 37: 
 38:     protected $noTmpDirMessage = 'The temporary upload directory is missing';
 39: 
 40:     protected $cantWriteMessage = 'Cannot write %name% to disk';
 41: 
 42:     protected $extensionMessage = 'File upload stopped by extension';
 43: 
 44:     protected $notUploadedFileMessage = 'No file uploaded';
 45: 
 46:     protected $cantMoveMessage = 'Cannot move uploaded file';
 47: 
 48:     /**
 49:      * The name for error message
 50:      *
 51:      * @var string
 52:      */
 53:     protected $name = 'file';
 54: 
 55:     /**
 56:      * The name defined in the file input, if it's not specified, use the first
 57:      * key in upload files array (equals to $_FILES on default)
 58:      *
 59:      * @var string
 60:      */
 61:     protected $field;
 62: 
 63:     /**
 64:      * The directory to save file, automatic create it if not exist
 65:      *
 66:      * @var string
 67:      */
 68:     protected $dir = 'uploads';
 69: 
 70:     /**
 71:      * The custom file name (without extension) as upload file name to save
 72:      *
 73:      * @var string
 74:      */
 75:     protected $fileName;
 76: 
 77:     /**
 78:      * Whether check if the upload file is valid image or not
 79:      *
 80:      * You can specify any one of the following options to enable image detect
 81:      * * maxWidth
 82:      * * maxHeight
 83:      * * minWidth
 84:      * * minHeight
 85:      *
 86:      * @var bool
 87:      */
 88:     protected $isImage = false;
 89: 
 90:     /**
 91:      * Whether overwrite existing file, if set to false, the uploader will add
 92:      * a number between file name and extension, like file-1.jpg, file-2.jpg
 93:      *
 94:      * @var bool
 95:      */
 96:     protected $overwrite = false;
 97: 
 98:     /**
 99:      * Whether in unit test mode
100:      *
101:      * @var bool
102:      */
103:     protected $unitTest = false;
104: 
105:     /**
106:      * The max size of post data, for $this->postMaxSize
107:      *
108:      * @var string
109:      */
110:     protected $postMaxSize;
111: 
112:     /**
113:      * Constructor
114:      *
115:      * @param array $options
116:      */
117:     public function __construct(array $options = array())
118:     {
119:         parent::__construct($options + array(
120:             'dir' => $this->dir
121:         ));
122:     }
123: 
124:     /**
125:      * Upload a file
126:      *
127:      * @param string|array $field The name of file input or options of wei
128:      * @param array $options The options of wei
129:      * @return bool
130:      */
131:     public function __invoke($field = null, $options = array())
132:     {
133:         // ($field, $options)
134:         if (is_string($field)) {
135:             $this->storeOption('field', $field);
136:             $options && $this->storeOption($options);
137:         // ($options)
138:         } elseif (is_array($field)) {
139:             $field && $this->storeOption($field);
140:         }
141: 
142:         // Clean previous status
143:         parent::reset();
144: 
145:         $uploadedFiles = $this->request->getParameterReference('file');
146: 
147:         // Set default name
148:         if (!$this->field) {
149:             $this->field = key($uploadedFiles);
150:         }
151: 
152:         // Check if has file uploaded or file too large
153:         if (!isset($uploadedFiles[$this->field])) {
154:             $post = $this->request->getParameterReference('post');
155:             if (empty($uploadedFiles) && empty($post)) {
156:                 $error = 'postSize';
157:                 // Prepare postMaxSize variable for $this->postSizeMessage
158:                 $this->postMaxSize = $this->getIniSize('post_max_size');
159:             } else {
160:                 $error = 'noFile';
161:             }
162:             $this->addError($error);
163:             return false;
164:         }
165: 
166:         $uploadedFile = $uploadedFiles[$this->field];
167: 
168:         /**
169:          * @link http://php.net/manual/en/features.file-upload.errors.php
170:          */
171:         if ($uploadedFile['error'] !== UPLOAD_ERR_OK) {
172:             switch ($uploadedFile['error']) {
173:                 // The uploaded file exceeds the upload_max_filesize directive in php.ini
174:                 case UPLOAD_ERR_INI_SIZE :
175:                     $this->sizeString = $this->fromBytes($uploadedFile['size']);
176:                     $this->maxSizeString = $this->getIniSize('upload_max_filesize');
177:                     $this->addError('maxSize');
178:                     break;
179: 
180:                 // The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form
181:                 case UPLOAD_ERR_FORM_SIZE :
182:                     $this->addError('formLimit');
183:                     break;
184: 
185:                 // The uploaded file was only partially uploaded
186:                 // http://stackoverflow.com/questions/2937466/why-might-a-file-only-be-partially-uploaded
187:                 case UPLOAD_ERR_PARTIAL :
188:                     $this->addError('partial');
189:                     break;
190: 
191:                 // Missing a temporary folder
192:                 case UPLOAD_ERR_NO_TMP_DIR :
193:                     $this->addError('noTmpDir');
194:                     break;
195: 
196:                 // Failed to write file to disk
197:                 case UPLOAD_ERR_CANT_WRITE :
198:                     $this->addError('cantWrite');
199:                     break;
200: 
201:                 // A PHP extension stopped the file upload
202:                 case UPLOAD_ERR_EXTENSION :
203:                     $this->addError('extension');
204:                     break;
205: 
206:                 // No file was uploaded
207:                 case UPLOAD_ERR_NO_FILE :
208:                 default :
209:                     $this->addError('noFile');
210:             }
211:             return false;
212:         }
213: 
214:         if (!$this->isUploadedFile($uploadedFile['tmp_name'])) {
215:             $this->addError('notUploadedFile');
216:             return false;
217:         }
218: 
219:         // Validate file extension, size, mime type by parent class
220:         if ($this->isImage || $this->maxWidth || $this->maxHeight || $this->minWidth || $this->minHeight) {
221:             $result = parent::doValidate($uploadedFile);
222:         } else {
223:             $result = FileValidator::doValidate($uploadedFile);
224:         }
225:         if (false === $result) {
226:             return false;
227:         }
228: 
229:         return $this->saveFile($uploadedFile);
230:     }
231: 
232:     /**
233:      * Save uploaded file to upload directory
234:      *
235:      * @param array $uploadedFile
236:      * @return boolean
237:      */
238:     protected function saveFile($uploadedFile)
239:     {
240:         $ext = $this->getExt();
241:         $fullExt = $ext ? '.' . $ext : '';
242: 
243:         if ($this->fileName) {
244:             $fileName = $this->fileName;
245:         } else {
246:             $fileName = substr($uploadedFile['name'], 0, strlen($uploadedFile['name']) - strlen($fullExt));
247:         }
248: 
249:         $this->file = $this->dir . '/' . $fileName . $fullExt;
250:         if (!$this->overwrite) {
251:             $i = 1;
252:             while(is_file($this->file)) {
253:                 $this->file = $this->dir . '/' . $fileName . '-' . $i . $fullExt;
254:                 $i++;
255:             }
256:         }
257: 
258:         if (!$this->moveUploadedFile($uploadedFile['tmp_name'], $this->file)) {
259:             $this->addError('cantMove');
260:             return false;
261:         }
262: 
263:         return true;
264:     }
265: 
266:     /**
267:      * Returns the uploaded file path
268:      *
269:      * @return string
270:      */
271:     public function getFile()
272:     {
273:         return $this->file;
274:     }
275: 
276: 
277:     /**
278:      * Set upload directory
279:      *
280:      * @param string $dir
281:      * @return $this
282:      */
283:     public function setDir($dir)
284:     {
285:         $dir = rtrim($dir, '/');
286:         if (!is_dir($dir)) {
287:             mkdir($dir, 0700, true);
288:         }
289:         $this->dir = $dir;
290: 
291:         return $this;
292:     }
293: 
294:     /**
295:      * Returns upload directory
296:      *
297:      * @return string
298:      */
299:     public function getDir()
300:     {
301:         return $this->dir;
302:     }
303: 
304:     /**
305:      * Returns a human readable file size (e.g. 1.2MB, 10KB), which recive from
306:      * the ini configuration
307:      *
308:      * @param string $name The name of ini configuration
309:      * @return string
310:      */
311:     protected function getIniSize($name)
312:     {
313:         $size = ini_get($name);
314:         return is_numeric($size) ? $this->fromBytes($size) : $size;
315:     }
316: 
317:     /**
318:      * Check if the file was uploaded via HTTP POST, if $this->unitTest is
319:      * enable, it will always return true
320:      *
321:      * @param string $file
322:      * @return bool
323:      */
324:     protected function isUploadedFile($file)
325:     {
326:         return $this->unitTest ? is_file($file) : is_uploaded_file($file);
327:     }
328: 
329:     /**
330:      * Moves an uploaded file to a new location, if $this->unitTest is enable,
331:      * it will use `copy` function instead
332:      *
333:      * @param string $from The uploaded file name
334:      * @param string $to The destination of the moved file.
335:      * @return bool
336:      */
337:     protected function moveUploadedFile($from, $to)
338:     {
339:         return $this->unitTest ? copy($from, $to) : @move_uploaded_file($from, $to);
340:     }
341: }
342: 
Wei Framework API documentation generated by ApiGen