1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
namespace Nyholm\Psr7\Factory; |
6
|
|
|
|
7
|
|
|
use InvalidArgumentException; |
8
|
|
|
use Psr\Http\Message\ServerRequestInterface; |
9
|
|
|
use Psr\Http\Message\UploadedFileInterface; |
10
|
|
|
use Interop\Http\Factory\ServerRequestFactoryInterface; |
11
|
|
|
use Nyholm\Psr7\ServerRequest; |
12
|
|
|
use Nyholm\Psr7\UploadedFile; |
13
|
|
|
|
14
|
|
|
/** |
15
|
|
|
* @author Tobias Nyholm <[email protected]> |
16
|
|
|
* @author Martijn van der Ven <[email protected]> |
17
|
|
|
*/ |
18
|
|
|
final class ServerRequestFactory implements ServerRequestFactoryInterface |
19
|
|
|
{ |
20
|
23 |
|
public function createServerRequest(string $method, $uri, array $serverParams = []): ServerRequestInterface |
21
|
|
|
{ |
22
|
23 |
|
return new ServerRequest($method, $uri, [], null, '1.1', $serverParams); |
23
|
|
|
} |
24
|
|
|
|
25
|
15 |
|
public function createServerRequestFromArray(array $server): ServerRequestInterface |
26
|
|
|
{ |
27
|
15 |
|
return new ServerRequest($this->getMethodFromEnv($server), $this->getUriFromEnvWithHTTP($server), [], null, '1.1', $server); |
28
|
|
|
} |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* Create a new server request from a set of arrays. |
32
|
|
|
* |
33
|
|
|
* @param array $server Typically $_SERVER or similar structure. |
34
|
|
|
* @param array $headers Typically the output of getallheaders() or similar structure. |
35
|
|
|
* @param array $cookie Typically $_COOKIE or similar structure. |
36
|
|
|
* @param array $get Typically $_GET or similar structure. |
37
|
|
|
* @param array $post Typically $_POST or similar structure. |
38
|
|
|
* @param array $files Typically $_FILES or similar structure. |
39
|
|
|
* |
40
|
|
|
* @throws InvalidArgumentException If no valid method or URI can be determined. |
41
|
|
|
*/ |
42
|
|
|
public function createServerRequestFromArrays(array $server, array $headers, array $cookie, array $get, array $post, array $files): ServerRequestInterface |
43
|
|
|
{ |
44
|
|
|
$method = $this->getMethodFromEnv($server); |
45
|
|
|
$uri = $this->getUriFromEnvWithHTTP($server); |
46
|
|
|
|
47
|
|
|
$protocol = isset($server['SERVER_PROTOCOL']) ? str_replace('HTTP/', '', $server['SERVER_PROTOCOL']) : '1.1'; |
48
|
|
|
|
49
|
|
|
$serverRequest = new ServerRequest($method, $uri, $headers, null, $protocol, $server); |
50
|
|
|
|
51
|
|
|
return $serverRequest |
52
|
|
|
->withCookieParams($cookie) |
53
|
|
|
->withQueryParams($get) |
54
|
|
|
->withParsedBody($post) |
55
|
|
|
->withUploadedFiles(self::normalizeFiles($files)); |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* Create a new server request from the current environment variables. |
60
|
|
|
* Defaults to a GET request to minimise the risk of an InvalidArgumentException. |
61
|
|
|
* Includes the current request headers as supplied by the server through `getallheaders()`. |
62
|
|
|
* |
63
|
|
|
* @throws InvalidArgumentException If no valid method or URI can be determined. |
64
|
|
|
*/ |
65
|
|
|
public function createServerRequestFromGlobals(): ServerRequestInterface |
66
|
|
|
{ |
67
|
|
|
$server = $_SERVER; |
68
|
|
|
if (false === isset($server['REQUEST_METHOD'])) { |
69
|
|
|
$server['REQUEST_METHOD'] = 'GET'; |
70
|
|
|
} |
71
|
|
|
$headers = function_exists('getallheaders') ? getallheaders() : []; |
72
|
|
|
|
73
|
|
|
return $this->createServerRequestFromArrays($server, $headers, $_COOKIE, $_GET, $_POST, $_FILES); |
74
|
|
|
} |
75
|
|
|
|
76
|
15 |
|
private function getMethodFromEnv(array $environment): string |
77
|
|
|
{ |
78
|
15 |
|
if (false === isset($environment['REQUEST_METHOD'])) { |
79
|
|
|
throw new InvalidArgumentException('Cannot determine HTTP method'); |
80
|
|
|
} |
81
|
|
|
|
82
|
15 |
|
return $environment['REQUEST_METHOD']; |
83
|
|
|
} |
84
|
|
|
|
85
|
15 |
|
private function getUriFromEnvWithHTTP(array $environment): \Psr\Http\Message\UriInterface |
86
|
|
|
{ |
87
|
15 |
|
$uri = (new UriFactory())->createUriFromArray($environment); |
|
|
|
|
88
|
15 |
|
if ('' === $uri->getScheme()) { |
89
|
15 |
|
$uri = $uri->withScheme('http'); |
90
|
|
|
} |
91
|
|
|
|
92
|
15 |
|
return $uri; |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
/** |
96
|
|
|
* Return an UploadedFile instance array. |
97
|
|
|
* |
98
|
|
|
* @param array $files A array which respect $_FILES structure |
99
|
|
|
* |
100
|
|
|
* @throws InvalidArgumentException for unrecognized values |
101
|
|
|
*/ |
102
|
|
|
private static function normalizeFiles(array $files): array |
103
|
|
|
{ |
104
|
|
|
$normalized = []; |
105
|
|
|
|
106
|
|
|
foreach ($files as $key => $value) { |
107
|
|
|
if ($value instanceof UploadedFileInterface) { |
108
|
|
|
$normalized[$key] = $value; |
109
|
|
|
} elseif (is_array($value) && isset($value['tmp_name'])) { |
110
|
|
|
$normalized[$key] = self::createUploadedFileFromSpec($value); |
111
|
|
|
} elseif (is_array($value)) { |
112
|
|
|
$normalized[$key] = self::normalizeFiles($value); |
113
|
|
|
|
114
|
|
|
continue; |
115
|
|
|
} else { |
116
|
|
|
throw new InvalidArgumentException('Invalid value in files specification'); |
117
|
|
|
} |
118
|
|
|
} |
119
|
|
|
|
120
|
|
|
return $normalized; |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* Create and return an UploadedFile instance from a $_FILES specification. |
125
|
|
|
* |
126
|
|
|
* If the specification represents an array of values, this method will |
127
|
|
|
* delegate to normalizeNestedFileSpec() and return that return value. |
128
|
|
|
* |
129
|
|
|
* @param array $value $_FILES struct |
130
|
|
|
* |
131
|
|
|
* @return array|UploadedFileInterface |
132
|
|
|
*/ |
133
|
|
|
private static function createUploadedFileFromSpec(array $value) |
134
|
|
|
{ |
135
|
|
|
if (is_array($value['tmp_name'])) { |
136
|
|
|
return self::normalizeNestedFileSpec($value); |
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
return new UploadedFile( |
140
|
|
|
$value['tmp_name'], |
141
|
|
|
(int) $value['size'], |
142
|
|
|
(int) $value['error'], |
143
|
|
|
$value['name'], |
144
|
|
|
$value['type'] |
145
|
|
|
); |
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
/** |
149
|
|
|
* Normalize an array of file specifications. |
150
|
|
|
* |
151
|
|
|
* Loops through all nested files and returns a normalized array of |
152
|
|
|
* UploadedFileInterface instances. |
153
|
|
|
* |
154
|
|
|
* @param array $files |
155
|
|
|
* |
156
|
|
|
* @return UploadedFileInterface[] |
157
|
|
|
*/ |
158
|
|
|
private static function normalizeNestedFileSpec(array $files = []): array |
159
|
|
|
{ |
160
|
|
|
$normalizedFiles = []; |
161
|
|
|
|
162
|
|
|
foreach (array_keys($files['tmp_name']) as $key) { |
163
|
|
|
$spec = [ |
164
|
|
|
'tmp_name' => $files['tmp_name'][$key], |
165
|
|
|
'size' => $files['size'][$key], |
166
|
|
|
'error' => $files['error'][$key], |
167
|
|
|
'name' => $files['name'][$key], |
168
|
|
|
'type' => $files['type'][$key], |
169
|
|
|
]; |
170
|
|
|
$normalizedFiles[$key] = self::createUploadedFileFromSpec($spec); |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
return $normalizedFiles; |
174
|
|
|
} |
175
|
|
|
} |
176
|
|
|
|
This method has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.