MediaWiki REL1_34
UploadedFile.php
Go to the documentation of this file.
1<?php
2
4
5use Psr\Http\Message\UploadedFileInterface;
6use RuntimeException;
7use Wikimedia\AtEase\AtEase;
8
20class UploadedFile implements UploadedFileInterface {
21
23 private $data;
24
26 private $fromUpload;
27
29 private $stream = null;
30
32 private $moved = false;
33
39 public function __construct( array $data, $fromUpload = true ) {
40 $this->data = $data;
41 $this->fromUpload = $fromUpload;
42 }
43
48 private function checkError() {
49 switch ( $this->data['error'] ) {
50 case UPLOAD_ERR_OK:
51 break;
52
53 case UPLOAD_ERR_INI_SIZE:
54 throw new RuntimeException( 'Upload exceeded maximum size' );
55
56 case UPLOAD_ERR_FORM_SIZE:
57 throw new RuntimeException( 'Upload exceeded form-specified maximum size' );
58
59 case UPLOAD_ERR_PARTIAL:
60 throw new RuntimeException( 'File was only partially uploaded' );
61
62 case UPLOAD_ERR_NO_FILE:
63 throw new RuntimeException( 'No file was uploaded' );
64
65 case UPLOAD_ERR_NO_TMP_DIR:
66 throw new RuntimeException( 'PHP has no temporary folder for storing uploaded files' );
67
68 case UPLOAD_ERR_CANT_WRITE:
69 throw new RuntimeException( 'PHP was unable to save the uploaded file' );
70
71 case UPLOAD_ERR_EXTENSION:
72 throw new RuntimeException( 'A PHP extension stopped the file upload' );
73
74 default:
75 throw new RuntimeException( 'Unknown upload error code ' . $this->data['error'] );
76 }
77
78 if ( $this->moved ) {
79 throw new RuntimeException( 'File has already been moved' );
80 }
81 if ( !isset( $this->data['tmp_name'] ) || !file_exists( $this->data['tmp_name'] ) ) {
82 throw new RuntimeException( 'Uploaded file is missing' );
83 }
84 }
85
86 public function getStream() {
87 if ( $this->stream ) {
88 return $this->stream;
89 }
90
91 $this->checkError();
92 $this->stream = new UploadedFileStream( $this->data['tmp_name'] );
93 return $this->stream;
94 }
95
96 public function moveTo( $targetPath ) {
97 $this->checkError();
98
99 if ( $this->fromUpload && !is_uploaded_file( $this->data['tmp_name'] ) ) {
100 throw new RuntimeException( 'Specified file is not an uploaded file' );
101 }
102
103 // TODO remove the function_exists check once we drop HHVM support
104 if ( function_exists( 'error_clear_last' ) ) {
105 error_clear_last();
106 }
107 $ret = AtEase::quietCall(
108 $this->fromUpload ? 'move_uploaded_file' : 'rename',
109 $this->data['tmp_name'],
110 $targetPath
111 );
112 if ( $ret === false ) {
113 $err = error_get_last();
114 throw new RuntimeException( "Move failed: " . ( $err['message'] ?? 'Unknown error' ) );
115 }
116
117 $this->moved = true;
118 if ( $this->stream ) {
119 $this->stream->close();
120 $this->stream = null;
121 }
122 }
123
124 public function getSize() {
125 return $this->data['size'] ?? null;
126 }
127
128 public function getError() {
129 return $this->data['error'] ?? UPLOAD_ERR_NO_FILE;
130 }
131
132 public function getClientFilename() {
133 $ret = $this->data['name'] ?? null;
134 return $ret === '' ? null : $ret;
135 }
136
137 public function getClientMediaType() {
138 $ret = $this->data['type'] ?? null;
139 return $ret === '' ? null : $ret;
140 }
141
142}
Implementation of StreamInterface for a file in $_FILES.
A simple implementation of UploadedFileInterface.
bool $moved
Whether moveTo() was called.
checkError()
Throw if there was an error.
__construct(array $data, $fromUpload=true)