source: vendor/guzzlehttp/psr7/src/ServerRequest.php@ f9c482b

Last change on this file since f9c482b was f9c482b, checked in by Vlado 222039 <vlado.popovski@…>, 7 days ago

Upload new project files

  • Property mode set to 100644
File size: 9.3 KB
RevLine 
[f9c482b]1<?php
2
3declare(strict_types=1);
4
5namespace GuzzleHttp\Psr7;
6
7use InvalidArgumentException;
8use Psr\Http\Message\ServerRequestInterface;
9use Psr\Http\Message\StreamInterface;
10use Psr\Http\Message\UploadedFileInterface;
11use Psr\Http\Message\UriInterface;
12
13/**
14 * Server-side HTTP request
15 *
16 * Extends the Request definition to add methods for accessing incoming data,
17 * specifically server parameters, cookies, matched path parameters, query
18 * string arguments, body parameters, and upload file information.
19 *
20 * "Attributes" are discovered via decomposing the request (and usually
21 * specifically the URI path), and typically will be injected by the application.
22 *
23 * Requests are considered immutable; all methods that might change state are
24 * implemented such that they retain the internal state of the current
25 * message and return a new instance that contains the changed state.
26 */
27class ServerRequest extends Request implements ServerRequestInterface
28{
29 /**
30 * @var array
31 */
32 private $attributes = [];
33
34 /**
35 * @var array
36 */
37 private $cookieParams = [];
38
39 /**
40 * @var array|object|null
41 */
42 private $parsedBody;
43
44 /**
45 * @var array
46 */
47 private $queryParams = [];
48
49 /**
50 * @var array
51 */
52 private $serverParams;
53
54 /**
55 * @var array
56 */
57 private $uploadedFiles = [];
58
59 /**
60 * @param string $method HTTP method
61 * @param string|UriInterface $uri URI
62 * @param (string|string[])[] $headers Request headers
63 * @param string|resource|StreamInterface|null $body Request body
64 * @param string $version Protocol version
65 * @param array $serverParams Typically the $_SERVER superglobal
66 */
67 public function __construct(
68 string $method,
69 $uri,
70 array $headers = [],
71 $body = null,
72 string $version = '1.1',
73 array $serverParams = []
74 ) {
75 $this->serverParams = $serverParams;
76
77 parent::__construct($method, $uri, $headers, $body, $version);
78 }
79
80 /**
81 * Return an UploadedFile instance array.
82 *
83 * @param array $files An array which respect $_FILES structure
84 *
85 * @throws InvalidArgumentException for unrecognized values
86 */
87 public static function normalizeFiles(array $files): array
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 *
115 * @return UploadedFileInterface|UploadedFileInterface[]
116 */
117 private static function createUploadedFileFromSpec(array $value)
118 {
119 if (is_array($value['tmp_name'])) {
120 return self::normalizeNestedFileSpec($value);
121 }
122
123 return new UploadedFile(
124 $value['tmp_name'],
125 (int) $value['size'],
126 (int) $value['error'],
127 $value['name'],
128 $value['type']
129 );
130 }
131
132 /**
133 * Normalize an array of file specifications.
134 *
135 * Loops through all nested files and returns a normalized array of
136 * UploadedFileInterface instances.
137 *
138 * @return UploadedFileInterface[]
139 */
140 private static function normalizeNestedFileSpec(array $files = []): array
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] ?? null,
148 'error' => $files['error'][$key] ?? null,
149 'name' => $files['name'][$key] ?? null,
150 'type' => $files['type'][$key] ?? null,
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 public static function fromGlobals(): ServerRequestInterface
167 {
168 $method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
169 $headers = getallheaders();
170 $uri = self::getUriFromGlobals();
171 $body = new CachingStream(new LazyOpenStream('php://input', 'r+'));
172 $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? str_replace('HTTP/', '', $_SERVER['SERVER_PROTOCOL']) : '1.1';
173
174 $serverRequest = new ServerRequest($method, $uri, $headers, $body, $protocol, $_SERVER);
175
176 return $serverRequest
177 ->withCookieParams($_COOKIE)
178 ->withQueryParams($_GET)
179 ->withParsedBody($_POST)
180 ->withUploadedFiles(self::normalizeFiles($_FILES));
181 }
182
183 private static function extractHostAndPortFromAuthority(string $authority): array
184 {
185 $uri = 'http://'.$authority;
186 $parts = parse_url($uri);
187 if (false === $parts) {
188 return [null, null];
189 }
190
191 $host = $parts['host'] ?? null;
192 $port = $parts['port'] ?? null;
193
194 return [$host, $port];
195 }
196
197 /**
198 * Get a Uri populated with values from $_SERVER.
199 */
200 public static function getUriFromGlobals(): UriInterface
201 {
202 $uri = new Uri('');
203
204 $uri = $uri->withScheme(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http');
205
206 $hasPort = false;
207 if (isset($_SERVER['HTTP_HOST'])) {
208 [$host, $port] = self::extractHostAndPortFromAuthority($_SERVER['HTTP_HOST']);
209 if ($host !== null) {
210 $uri = $uri->withHost($host);
211 }
212
213 if ($port !== null) {
214 $hasPort = true;
215 $uri = $uri->withPort($port);
216 }
217 } elseif (isset($_SERVER['SERVER_NAME'])) {
218 $uri = $uri->withHost($_SERVER['SERVER_NAME']);
219 } elseif (isset($_SERVER['SERVER_ADDR'])) {
220 $uri = $uri->withHost($_SERVER['SERVER_ADDR']);
221 }
222
223 if (!$hasPort && isset($_SERVER['SERVER_PORT'])) {
224 $uri = $uri->withPort($_SERVER['SERVER_PORT']);
225 }
226
227 $hasQuery = false;
228 if (isset($_SERVER['REQUEST_URI'])) {
229 $requestUriParts = explode('?', $_SERVER['REQUEST_URI'], 2);
230 $uri = $uri->withPath($requestUriParts[0]);
231 if (isset($requestUriParts[1])) {
232 $hasQuery = true;
233 $uri = $uri->withQuery($requestUriParts[1]);
234 }
235 }
236
237 if (!$hasQuery && isset($_SERVER['QUERY_STRING'])) {
238 $uri = $uri->withQuery($_SERVER['QUERY_STRING']);
239 }
240
241 return $uri;
242 }
243
244 public function getServerParams(): array
245 {
246 return $this->serverParams;
247 }
248
249 public function getUploadedFiles(): array
250 {
251 return $this->uploadedFiles;
252 }
253
254 public function withUploadedFiles(array $uploadedFiles): ServerRequestInterface
255 {
256 $new = clone $this;
257 $new->uploadedFiles = $uploadedFiles;
258
259 return $new;
260 }
261
262 public function getCookieParams(): array
263 {
264 return $this->cookieParams;
265 }
266
267 public function withCookieParams(array $cookies): ServerRequestInterface
268 {
269 $new = clone $this;
270 $new->cookieParams = $cookies;
271
272 return $new;
273 }
274
275 public function getQueryParams(): array
276 {
277 return $this->queryParams;
278 }
279
280 public function withQueryParams(array $query): ServerRequestInterface
281 {
282 $new = clone $this;
283 $new->queryParams = $query;
284
285 return $new;
286 }
287
288 /**
289 * @return array|object|null
290 */
291 public function getParsedBody()
292 {
293 return $this->parsedBody;
294 }
295
296 public function withParsedBody($data): ServerRequestInterface
297 {
298 $new = clone $this;
299 $new->parsedBody = $data;
300
301 return $new;
302 }
303
304 public function getAttributes(): array
305 {
306 return $this->attributes;
307 }
308
309 /**
310 * @return mixed
311 */
312 public function getAttribute($attribute, $default = null)
313 {
314 if (false === array_key_exists($attribute, $this->attributes)) {
315 return $default;
316 }
317
318 return $this->attributes[$attribute];
319 }
320
321 public function withAttribute($attribute, $value): ServerRequestInterface
322 {
323 $new = clone $this;
324 $new->attributes[$attribute] = $value;
325
326 return $new;
327 }
328
329 public function withoutAttribute($attribute): ServerRequestInterface
330 {
331 if (false === array_key_exists($attribute, $this->attributes)) {
332 return $this;
333 }
334
335 $new = clone $this;
336 unset($new->attributes[$attribute]);
337
338 return $new;
339 }
340}
Note: See TracBrowser for help on using the repository browser.