Subversion Repositories php-qbpwcf

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3 liveuser 1
<?php
2
 
3
namespace GuzzleHttp\Psr7;
4
 
5
use InvalidArgumentException;
6
use Psr\Http\Message\StreamInterface;
7
use Psr\Http\Message\UploadedFileInterface;
8
use RuntimeException;
9
 
10
class UploadedFile implements UploadedFileInterface
11
{
12
    /**
13
     * @var int[]
14
     */
15
    private static $errors = [
16
        UPLOAD_ERR_OK,
17
        UPLOAD_ERR_INI_SIZE,
18
        UPLOAD_ERR_FORM_SIZE,
19
        UPLOAD_ERR_PARTIAL,
20
        UPLOAD_ERR_NO_FILE,
21
        UPLOAD_ERR_NO_TMP_DIR,
22
        UPLOAD_ERR_CANT_WRITE,
23
        UPLOAD_ERR_EXTENSION,
24
    ];
25
 
26
    /**
27
     * @var string
28
     */
29
    private $clientFilename;
30
 
31
    /**
32
     * @var string
33
     */
34
    private $clientMediaType;
35
 
36
    /**
37
     * @var int
38
     */
39
    private $error;
40
 
41
    /**
42
     * @var null|string
43
     */
44
    private $file;
45
 
46
    /**
47
     * @var bool
48
     */
49
    private $moved = false;
50
 
51
    /**
52
     * @var int
53
     */
54
    private $size;
55
 
56
    /**
57
     * @var StreamInterface|null
58
     */
59
    private $stream;
60
 
61
    /**
62
     * @param StreamInterface|string|resource $streamOrFile
63
     * @param int $size
64
     * @param int $errorStatus
65
     * @param string|null $clientFilename
66
     * @param string|null $clientMediaType
67
     */
68
    public function __construct(
69
        $streamOrFile,
70
        $size,
71
        $errorStatus,
72
        $clientFilename = null,
73
        $clientMediaType = null
74
    ) {
75
        $this->setError($errorStatus);
76
        $this->setSize($size);
77
        $this->setClientFilename($clientFilename);
78
        $this->setClientMediaType($clientMediaType);
79
 
80
        if ($this->isOk()) {
81
            $this->setStreamOrFile($streamOrFile);
82
        }
83
    }
84
 
85
    /**
86
     * Depending on the value set file or stream variable
87
     *
88
     * @param mixed $streamOrFile
89
     *
90
     * @throws InvalidArgumentException
91
     */
92
    private function setStreamOrFile($streamOrFile)
93
    {
94
        if (is_string($streamOrFile)) {
95
            $this->file = $streamOrFile;
96
        } elseif (is_resource($streamOrFile)) {
97
            $this->stream = new Stream($streamOrFile);
98
        } elseif ($streamOrFile instanceof StreamInterface) {
99
            $this->stream = $streamOrFile;
100
        } else {
101
            throw new InvalidArgumentException(
102
                'Invalid stream or file provided for UploadedFile'
103
            );
104
        }
105
    }
106
 
107
    /**
108
     * @param int $error
109
     *
110
     * @throws InvalidArgumentException
111
     */
112
    private function setError($error)
113
    {
114
        if (false === is_int($error)) {
115
            throw new InvalidArgumentException(
116
                'Upload file error status must be an integer'
117
            );
118
        }
119
 
120
        if (false === in_array($error, UploadedFile::$errors)) {
121
            throw new InvalidArgumentException(
122
                'Invalid error status for UploadedFile'
123
            );
124
        }
125
 
126
        $this->error = $error;
127
    }
128
 
129
    /**
130
     * @param int $size
131
     *
132
     * @throws InvalidArgumentException
133
     */
134
    private function setSize($size)
135
    {
136
        if (false === is_int($size)) {
137
            throw new InvalidArgumentException(
138
                'Upload file size must be an integer'
139
            );
140
        }
141
 
142
        $this->size = $size;
143
    }
144
 
145
    /**
146
     * @param mixed $param
147
     * @return boolean
148
     */
149
    private function isStringOrNull($param)
150
    {
151
        return in_array(gettype($param), ['string', 'NULL']);
152
    }
153
 
154
    /**
155
     * @param mixed $param
156
     * @return boolean
157
     */
158
    private function isStringNotEmpty($param)
159
    {
160
        return is_string($param) && false === empty($param);
161
    }
162
 
163
    /**
164
     * @param string|null $clientFilename
165
     *
166
     * @throws InvalidArgumentException
167
     */
168
    private function setClientFilename($clientFilename)
169
    {
170
        if (false === $this->isStringOrNull($clientFilename)) {
171
            throw new InvalidArgumentException(
172
                'Upload file client filename must be a string or null'
173
            );
174
        }
175
 
176
        $this->clientFilename = $clientFilename;
177
    }
178
 
179
    /**
180
     * @param string|null $clientMediaType
181
     *
182
     * @throws InvalidArgumentException
183
     */
184
    private function setClientMediaType($clientMediaType)
185
    {
186
        if (false === $this->isStringOrNull($clientMediaType)) {
187
            throw new InvalidArgumentException(
188
                'Upload file client media type must be a string or null'
189
            );
190
        }
191
 
192
        $this->clientMediaType = $clientMediaType;
193
    }
194
 
195
    /**
196
     * Return true if there is no upload error
197
     *
198
     * @return boolean
199
     */
200
    private function isOk()
201
    {
202
        return $this->error === UPLOAD_ERR_OK;
203
    }
204
 
205
    /**
206
     * @return boolean
207
     */
208
    public function isMoved()
209
    {
210
        return $this->moved;
211
    }
212
 
213
    /**
214
     * @throws RuntimeException if is moved or not ok
215
     */
216
    private function validateActive()
217
    {
218
        if (false === $this->isOk()) {
219
            throw new RuntimeException('Cannot retrieve stream due to upload error');
220
        }
221
 
222
        if ($this->isMoved()) {
223
            throw new RuntimeException('Cannot retrieve stream after it has already been moved');
224
        }
225
    }
226
 
227
    /**
228
     * {@inheritdoc}
229
     *
230
     * @throws RuntimeException if the upload was not successful.
231
     */
232
    public function getStream()
233
    {
234
        $this->validateActive();
235
 
236
        if ($this->stream instanceof StreamInterface) {
237
            return $this->stream;
238
        }
239
 
240
        return new LazyOpenStream($this->file, 'r+');
241
    }
242
 
243
    /**
244
     * {@inheritdoc}
245
     *
246
     * @see http://php.net/is_uploaded_file
247
     * @see http://php.net/move_uploaded_file
248
     *
249
     * @param string $targetPath Path to which to move the uploaded file.
250
     *
251
     * @throws RuntimeException if the upload was not successful.
252
     * @throws InvalidArgumentException if the $path specified is invalid.
253
     * @throws RuntimeException on any error during the move operation, or on
254
     *     the second or subsequent call to the method.
255
     */
256
    public function moveTo($targetPath)
257
    {
258
        $this->validateActive();
259
 
260
        if (false === $this->isStringNotEmpty($targetPath)) {
261
            throw new InvalidArgumentException(
262
                'Invalid path provided for move operation; must be a non-empty string'
263
            );
264
        }
265
 
266
        if ($this->file) {
267
            $this->moved = php_sapi_name() == 'cli'
268
                ? rename($this->file, $targetPath)
269
                : move_uploaded_file($this->file, $targetPath);
270
        } else {
271
            Utils::copyToStream(
272
                $this->getStream(),
273
                new LazyOpenStream($targetPath, 'w')
274
            );
275
 
276
            $this->moved = true;
277
        }
278
 
279
        if (false === $this->moved) {
280
            throw new RuntimeException(
281
                sprintf('Uploaded file could not be moved to %s', $targetPath)
282
            );
283
        }
284
    }
285
 
286
    /**
287
     * {@inheritdoc}
288
     *
289
     * @return int|null The file size in bytes or null if unknown.
290
     */
291
    public function getSize()
292
    {
293
        return $this->size;
294
    }
295
 
296
    /**
297
     * {@inheritdoc}
298
     *
299
     * @see http://php.net/manual/en/features.file-upload.errors.php
300
     * @return int One of PHP's UPLOAD_ERR_XXX constants.
301
     */
302
    public function getError()
303
    {
304
        return $this->error;
305
    }
306
 
307
    /**
308
     * {@inheritdoc}
309
     *
310
     * @return string|null The filename sent by the client or null if none
311
     *     was provided.
312
     */
313
    public function getClientFilename()
314
    {
315
        return $this->clientFilename;
316
    }
317
 
318
    /**
319
     * {@inheritdoc}
320
     */
321
    public function getClientMediaType()
322
    {
323
        return $this->clientMediaType;
324
    }
325
}