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\ServerRequestInterface;
7
use Psr\Http\Message\UriInterface;
8
use Psr\Http\Message\StreamInterface;
9
use Psr\Http\Message\UploadedFileInterface;
10
 
11
/**
12
 * Server-side HTTP request
13
 *
14
 * Extends the Request definition to add methods for accessing incoming data,
15
 * specifically server parameters, cookies, matched path parameters, query
16
 * string arguments, body parameters, and upload file information.
17
 *
18
 * "Attributes" are discovered via decomposing the request (and usually
19
 * specifically the URI path), and typically will be injected by the application.
20
 *
21
 * Requests are considered immutable; all methods that might change state are
22
 * implemented such that they retain the internal state of the current
23
 * message and return a new instance that contains the changed state.
24
 */
25
class ServerRequest extends Request implements ServerRequestInterface
26
{
27
    /**
28
     * @var array
29
     */
30
    private $attributes = [];
31
 
32
    /**
33
     * @var array
34
     */
35
    private $cookieParams = [];
36
 
37
    /**
38
     * @var null|array|object
39
     */
40
    private $parsedBody;
41
 
42
    /**
43
     * @var array
44
     */
45
    private $queryParams = [];
46
 
47
    /**
48
     * @var array
49
     */
50
    private $serverParams;
51
 
52
    /**
53
     * @var array
54
     */
55
    private $uploadedFiles = [];
56
 
57
    /**
58
     * @param string                               $method       HTTP method
59
     * @param string|UriInterface                  $uri          URI
60
     * @param array                                $headers      Request headers
61
     * @param string|null|resource|StreamInterface $body         Request body
62
     * @param string                               $version      Protocol version
63
     * @param array                                $serverParams Typically the $_SERVER superglobal
64
     */
65
    public function __construct(
66
        $method,
67
        $uri,
68
        array $headers = [],
69
        $body = null,
70
        $version = '1.1',
71
        array $serverParams = []
72
    ) {
73
        $this->serverParams = $serverParams;
74
 
75
        parent::__construct($method, $uri, $headers, $body, $version);
76
    }
77
 
78
    /**
79
     * Return an UploadedFile instance array.
80
     *
81
     * @param array $files A array which respect $_FILES structure
82
     *
83
     * @return array
84
     *
85
     * @throws InvalidArgumentException for unrecognized values
86
     */
87
    public static function normalizeFiles(array $files)
88
    {
89
        $normalized = [];
90
 
91
        foreach ($files as $key => $value) {
92
            if ($value instanceof UploadedFileInterface) {
93
                $normalized[$key] = $value;
94
            } elseif (is_array($value) && isset($value['tmp_name'])) {
95
                $normalized[$key] = self::createUploadedFileFromSpec($value);
96
            } elseif (is_array($value)) {
97
                $normalized[$key] = self::normalizeFiles($value);
98
                continue;
99
            } else {
100
                throw new InvalidArgumentException('Invalid value in files specification');
101
            }
102
        }
103
 
104
        return $normalized;
105
    }
106
 
107
    /**
108
     * Create and return an UploadedFile instance from a $_FILES specification.
109
     *
110
     * If the specification represents an array of values, this method will
111
     * delegate to normalizeNestedFileSpec() and return that return value.
112
     *
113
     * @param array $value $_FILES struct
114
     * @return array|UploadedFileInterface
115
     */
116
    private static function createUploadedFileFromSpec(array $value)
117
    {
118
        if (is_array($value['tmp_name'])) {
119
            return self::normalizeNestedFileSpec($value);
120
        }
121
 
122
        return new UploadedFile(
123
            $value['tmp_name'],
124
            (int) $value['size'],
125
            (int) $value['error'],
126
            $value['name'],
127
            $value['type']
128
        );
129
    }
130
 
131
    /**
132
     * Normalize an array of file specifications.
133
     *
134
     * Loops through all nested files and returns a normalized array of
135
     * UploadedFileInterface instances.
136
     *
137
     * @param array $files
138
     * @return UploadedFileInterface[]
139
     */
140
    private static function normalizeNestedFileSpec(array $files = [])
141
    {
142
        $normalizedFiles = [];
143
 
144
        foreach (array_keys($files['tmp_name']) as $key) {
145
            $spec = [
146
                'tmp_name' => $files['tmp_name'][$key],
147
                'size'     => $files['size'][$key],
148
                'error'    => $files['error'][$key],
149
                'name'     => $files['name'][$key],
150
                'type'     => $files['type'][$key],
151
            ];
152
            $normalizedFiles[$key] = self::createUploadedFileFromSpec($spec);
153
        }
154
 
155
        return $normalizedFiles;
156
    }
157
 
158
    /**
159
     * Return a ServerRequest populated with superglobals:
160
     * $_GET
161
     * $_POST
162
     * $_COOKIE
163
     * $_FILES
164
     * $_SERVER
165
     *
166
     * @return ServerRequestInterface
167
     */
168
    public static function fromGlobals()
169
    {
170
        $method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'GET';
171
        $headers = getallheaders();
172
        $uri = self::getUriFromGlobals();
173
        $body = new CachingStream(new LazyOpenStream('php://input', 'r+'));
174
        $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? str_replace('HTTP/', '', $_SERVER['SERVER_PROTOCOL']) : '1.1';
175
 
176
        $serverRequest = new ServerRequest($method, $uri, $headers, $body, $protocol, $_SERVER);
177
 
178
        return $serverRequest
179
            ->withCookieParams($_COOKIE)
180
            ->withQueryParams($_GET)
181
            ->withParsedBody($_POST)
182
            ->withUploadedFiles(self::normalizeFiles($_FILES));
183
    }
184
 
185
    private static function extractHostAndPortFromAuthority($authority)
186
    {
187
        $uri = 'http://'.$authority;
188
        $parts = parse_url($uri);
189
        if (false === $parts) {
190
            return [null, null];
191
        }
192
 
193
        $host = isset($parts['host']) ? $parts['host'] : null;
194
        $port = isset($parts['port']) ? $parts['port'] : null;
195
 
196
        return [$host, $port];
197
    }
198
 
199
    /**
200
     * Get a Uri populated with values from $_SERVER.
201
     *
202
     * @return UriInterface
203
     */
204
    public static function getUriFromGlobals()
205
    {
206
        $uri = new Uri('');
207
 
208
        $uri = $uri->withScheme(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http');
209
 
210
        $hasPort = false;
211
        if (isset($_SERVER['HTTP_HOST'])) {
212
            list($host, $port) = self::extractHostAndPortFromAuthority($_SERVER['HTTP_HOST']);
213
            if ($host !== null) {
214
                $uri = $uri->withHost($host);
215
            }
216
 
217
            if ($port !== null) {
218
                $hasPort = true;
219
                $uri = $uri->withPort($port);
220
            }
221
        } elseif (isset($_SERVER['SERVER_NAME'])) {
222
            $uri = $uri->withHost($_SERVER['SERVER_NAME']);
223
        } elseif (isset($_SERVER['SERVER_ADDR'])) {
224
            $uri = $uri->withHost($_SERVER['SERVER_ADDR']);
225
        }
226
 
227
        if (!$hasPort && isset($_SERVER['SERVER_PORT'])) {
228
            $uri = $uri->withPort($_SERVER['SERVER_PORT']);
229
        }
230
 
231
        $hasQuery = false;
232
        if (isset($_SERVER['REQUEST_URI'])) {
233
            $requestUriParts = explode('?', $_SERVER['REQUEST_URI'], 2);
234
            $uri = $uri->withPath($requestUriParts[0]);
235
            if (isset($requestUriParts[1])) {
236
                $hasQuery = true;
237
                $uri = $uri->withQuery($requestUriParts[1]);
238
            }
239
        }
240
 
241
        if (!$hasQuery && isset($_SERVER['QUERY_STRING'])) {
242
            $uri = $uri->withQuery($_SERVER['QUERY_STRING']);
243
        }
244
 
245
        return $uri;
246
    }
247
 
248
 
249
    /**
250
     * {@inheritdoc}
251
     */
252
    public function getServerParams()
253
    {
254
        return $this->serverParams;
255
    }
256
 
257
    /**
258
     * {@inheritdoc}
259
     */
260
    public function getUploadedFiles()
261
    {
262
        return $this->uploadedFiles;
263
    }
264
 
265
    /**
266
     * {@inheritdoc}
267
     */
268
    public function withUploadedFiles(array $uploadedFiles)
269
    {
270
        $new = clone $this;
271
        $new->uploadedFiles = $uploadedFiles;
272
 
273
        return $new;
274
    }
275
 
276
    /**
277
     * {@inheritdoc}
278
     */
279
    public function getCookieParams()
280
    {
281
        return $this->cookieParams;
282
    }
283
 
284
    /**
285
     * {@inheritdoc}
286
     */
287
    public function withCookieParams(array $cookies)
288
    {
289
        $new = clone $this;
290
        $new->cookieParams = $cookies;
291
 
292
        return $new;
293
    }
294
 
295
    /**
296
     * {@inheritdoc}
297
     */
298
    public function getQueryParams()
299
    {
300
        return $this->queryParams;
301
    }
302
 
303
    /**
304
     * {@inheritdoc}
305
     */
306
    public function withQueryParams(array $query)
307
    {
308
        $new = clone $this;
309
        $new->queryParams = $query;
310
 
311
        return $new;
312
    }
313
 
314
    /**
315
     * {@inheritdoc}
316
     */
317
    public function getParsedBody()
318
    {
319
        return $this->parsedBody;
320
    }
321
 
322
    /**
323
     * {@inheritdoc}
324
     */
325
    public function withParsedBody($data)
326
    {
327
        $new = clone $this;
328
        $new->parsedBody = $data;
329
 
330
        return $new;
331
    }
332
 
333
    /**
334
     * {@inheritdoc}
335
     */
336
    public function getAttributes()
337
    {
338
        return $this->attributes;
339
    }
340
 
341
    /**
342
     * {@inheritdoc}
343
     */
344
    public function getAttribute($attribute, $default = null)
345
    {
346
        if (false === array_key_exists($attribute, $this->attributes)) {
347
            return $default;
348
        }
349
 
350
        return $this->attributes[$attribute];
351
    }
352
 
353
    /**
354
     * {@inheritdoc}
355
     */
356
    public function withAttribute($attribute, $value)
357
    {
358
        $new = clone $this;
359
        $new->attributes[$attribute] = $value;
360
 
361
        return $new;
362
    }
363
 
364
    /**
365
     * {@inheritdoc}
366
     */
367
    public function withoutAttribute($attribute)
368
    {
369
        if (false === array_key_exists($attribute, $this->attributes)) {
370
            return $this;
371
        }
372
 
373
        $new = clone $this;
374
        unset($new->attributes[$attribute]);
375
 
376
        return $new;
377
    }
378
}