1: <?php
2: 3: 4: 5: 6: 7:
8:
9: namespace Wei;
10:
11: use Wei\Validator\File as FileValidator;
12: use Wei\Validator\Image;
13:
14: 15: 16: 17: 18: 19:
20: class Upload extends Image
21: {
22: 23: 24: 25: 26:
27: protected $postSizeMessage = 'No file uploaded or the total file size is too large, allowed maximum size is %postMaxSize%';
28:
29: 30: 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: 50: 51: 52:
53: protected $name = 'file';
54:
55: 56: 57: 58: 59: 60:
61: protected $field;
62:
63: 64: 65: 66: 67:
68: protected $dir = 'uploads';
69:
70: 71: 72: 73: 74:
75: protected $fileName;
76:
77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87:
88: protected $isImage = false;
89:
90: 91: 92: 93: 94: 95:
96: protected $overwrite = false;
97:
98: 99: 100: 101: 102:
103: protected $unitTest = false;
104:
105: 106: 107: 108: 109:
110: protected $postMaxSize;
111:
112: 113: 114: 115: 116:
117: public function __construct(array $options = array())
118: {
119: parent::__construct($options + array(
120: 'dir' => $this->dir
121: ));
122: }
123:
124: 125: 126: 127: 128: 129: 130:
131: public function __invoke($field = null, $options = array())
132: {
133:
134: if (is_string($field)) {
135: $this->storeOption('field', $field);
136: $options && $this->storeOption($options);
137:
138: } elseif (is_array($field)) {
139: $field && $this->storeOption($field);
140: }
141:
142:
143: parent::reset();
144:
145: $uploadedFiles = $this->request->getParameterReference('file');
146:
147:
148: if (!$this->field) {
149: $this->field = key($uploadedFiles);
150: }
151:
152:
153: if (!isset($uploadedFiles[$this->field])) {
154: $post = $this->request->getParameterReference('post');
155: if (empty($uploadedFiles) && empty($post)) {
156: $error = 'postSize';
157:
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: 170:
171: if ($uploadedFile['error'] !== UPLOAD_ERR_OK) {
172: switch ($uploadedFile['error']) {
173:
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:
181: case UPLOAD_ERR_FORM_SIZE :
182: $this->addError('formLimit');
183: break;
184:
185:
186:
187: case UPLOAD_ERR_PARTIAL :
188: $this->addError('partial');
189: break;
190:
191:
192: case UPLOAD_ERR_NO_TMP_DIR :
193: $this->addError('noTmpDir');
194: break;
195:
196:
197: case UPLOAD_ERR_CANT_WRITE :
198: $this->addError('cantWrite');
199: break;
200:
201:
202: case UPLOAD_ERR_EXTENSION :
203: $this->addError('extension');
204: break;
205:
206:
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:
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: 234: 235: 236: 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: 268: 269: 270:
271: public function getFile()
272: {
273: return $this->file;
274: }
275:
276:
277: 278: 279: 280: 281: 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: 296: 297: 298:
299: public function getDir()
300: {
301: return $this->dir;
302: }
303:
304: 305: 306: 307: 308: 309: 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: 319: 320: 321: 322: 323:
324: protected function isUploadedFile($file)
325: {
326: return $this->unitTest ? is_file($file) : is_uploaded_file($file);
327: }
328:
329: 330: 331: 332: 333: 334: 335: 336:
337: protected function moveUploadedFile($from, $to)
338: {
339: return $this->unitTest ? copy($from, $to) : @move_uploaded_file($from, $to);
340: }
341: }
342: