UploadedFile::getClientMediaType()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
/**
4
 * This file is part of slick/http
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
namespace Slick\Http\Message\Server;
11
12
use Psr\Http\Message\StreamInterface;
13
use Psr\Http\Message\UploadedFileInterface;
14
use Slick\Http\Message\Exception\InvalidArgumentException;
15
use Slick\Http\Message\Exception\RuntimeException;
16
use Slick\Http\Message\Stream\FileStream;
17
18
/**
19
 * UploadedFile
20
 *
21
 * @package Slick\Http\Message\Server
22
*/
23
final class UploadedFile implements UploadedFileInterface
24
{
25
    /**
26
     * @var StreamInterface
27
     */
28
    private $stream;
29
30
    /**
31
     * @var int
32
     */
33
    private $size;
34
35
    /**
36
     * @var int
37
     */
38
    private $error;
39
40
    /**
41
     * @var string
42
     */
43
    private $clientName;
44
45
    /**
46
     * @var string
47
     */
48
    private $mediaType;
49
50
    /**
51
     * @var string
52
     */
53
    private $tmpFile;
54
55
    /**
56
     * @var bool
57
     */
58
    private $moved = false;
59
60
    /**
61
     * Creates an UploadedFile
62
     *
63
     * @param StreamInterface $stream
64
     */
65
    private function __construct(StreamInterface $stream)
66
    {
67
        $this->stream = $stream;
68
    }
69
70
    /**
71
     * Creates an uploaded file from PHP's $_FILE upload data
72
     *
73
     * @param array $fileUploadData
74
     *
75
     * @return UploadedFile
76
     */
77
    public static function create(array $fileUploadData)
78
    {
79
        $uploadedFile = new UploadedFile(new FileStream($fileUploadData['tmp_name']));
80
        $uploadedFile->size = $fileUploadData['size'];
81
        $uploadedFile->error = $fileUploadData['error'];
82
        $uploadedFile->clientName = $fileUploadData['name'];
83
        $uploadedFile->mediaType = $fileUploadData['type'];
84
        $uploadedFile->tmpFile = $fileUploadData['tmp_name'];
85
86
        return $uploadedFile;
87
    }
88
89
    /**
90
     * Retrieve a stream representing the uploaded file.
91
     *
92
     * @return StreamInterface Stream representation of the uploaded file.
93
     *
94
     * @throws RuntimeException in cases when no stream is available
95
     */
96
    public function getStream()
97
    {
98
        if (!$this->stream) {
99
            throw new RuntimeException(
100
                "The uploaded file stream is no longer available."
101
            );
102
        }
103
        return $this->stream;
104
    }
105
106
    /**
107
     * Retrieve the file size.
108
     *
109
     * @return int|null The file size in bytes or null if unknown.
110
     */
111
    public function getSize()
112
    {
113
        return $this->size;
114
    }
115
116
    /**
117
     * Retrieve the error associated with the uploaded file.
118
     *
119
     * If the file was uploaded successfully, this method will return
120
     * UPLOAD_ERR_OK.
121
     *
122
     * @see http://php.net/manual/en/features.file-upload.errors.php
123
     *
124
     * @return int One of PHP's UPLOAD_ERR_XXX constants.
125
     */
126
    public function getError()
127
    {
128
        return $this->error;
129
    }
130
131
    /**
132
     * Retrieve the filename sent by the client.
133
     *
134
     * Do not trust the value returned by this method. A client could send
135
     * a malicious filename with the intention to corrupt or hack your
136
     * application.
137
     *
138
     * @return string|null The filename sent by the client or null if none
139
     *     was provided.
140
     */
141
    public function getClientFilename()
142
    {
143
        return $this->clientName;
144
    }
145
146
    /**
147
     * Retrieve the media type sent by the client.
148
     *
149
     * Do not trust the value returned by this method. A client could send
150
     * a malicious media type with the intention to corrupt or hack your
151
     * application.
152
     *
153
     * @return string|null The media type sent by the client or null if none
154
     *     was provided.
155
     */
156
    public function getClientMediaType()
157
    {
158
        return $this->mediaType;
159
    }
160
161
    /**
162
     * Move the uploaded file to a new location.
163
     *
164
     * $targetPath may be an absolute path, or a relative path. If it is a
165
     * relative path, resolution should be the same as used by PHP's rename()
166
     * function.
167
     *
168
     * The original file or stream will be removed on completion.
169
     *
170
     * If this method is called more than once, any subsequent calls will raise
171
     * an exception.
172
     *
173
     * @see http://php.net/is_uploaded_file
174
     * @see http://php.net/move_uploaded_file
175
     *
176
     * @param string $targetPath Path to which to move the uploaded file.
177
     *
178
     * @throws InvalidArgumentException if the $targetPath specified is invalid.
179
     * @throws RuntimeException on any error during the move operation, or on
180
     *     the second or subsequent call to the method.
181
     */
182
    public function moveTo($targetPath)
183
    {
184
        $this->checkMoved();
185
        $this->checkTargetDirExists($targetPath);
186
        $this->checkUpload();
187
188
        $exception = null;
189
        set_error_handler(function ($number, $error) use (&$exception) {
190
            $exception = new RuntimeException(
191
                "Cannot move uploaded file: ($number) {$error}"
192
            );
193
        });
194
195
        move_uploaded_file($this->tmpFile, $targetPath);
196
        restore_error_handler();
197
198
        if ($exception instanceof RuntimeException) {
199
            throw $exception;
200
        }
201
202
        $this->stream = null;
203
        $this->moved = true;
204
    }
205
206
    /**
207
     * Check if current file is already moved
208
     */
209
    private function checkMoved()
210
    {
211
        if ($this->moved) {
212
            throw new RuntimeException(
213
                "Uploaded file has already been move."
214
            );
215
        }
216
    }
217
218
    /**
219
     * Check if target directory exists
220
     *
221
     * @param $targetPath
222
     */
223
    private function checkTargetDirExists($targetPath)
224
    {
225
        if (!is_dir(dirname($targetPath))) {
226
            throw new InvalidArgumentException(
227
                "Cannot move uploaded file: target directory dos not exists."
228
            );
229
        }
230
    }
231
232
    /**
233
     * Checks if upload was successful
234
     */
235
    private function checkUpload()
236
    {
237
        if (!is_uploaded_file($this->tmpFile)) {
238
            throw new RuntimeException(
239
                "Cannot move uploaded file: the client file was not uploaded."
240
            );
241
        }
242
    }
243
}
244