PluginProbe
DecaLog / 4.4.0
DecaLog v4.4.0
3.0.2 3.1.0 3.10.0 3.2.0 3.3.0 3.4.0 3.4.1 3.5.0 3.5.1 3.6.0 3.6.1 3.6.2 3.6.3 3.7.0 3.7.1 3.8.0 3.9.0 3.9.1 4.0.0 4.1.0 4.2.0 4.3.0 4.3.1 4.4.0 4.5.0 All 75 releases
decalog / includes / libraries / http / discovery / Psr17Factory.php

Psr17Factory.php in DecaLog 4.4.0, at includes/libraries/http/discovery/Psr17Factory.php

304 lines 11.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Http\Discovery;
4
5 use Psr\Http\Message\RequestFactoryInterface;
6 use Psr\Http\Message\RequestInterface;
7 use Psr\Http\Message\ResponseFactoryInterface;
8 use Psr\Http\Message\ResponseInterface;
9 use Psr\Http\Message\ServerRequestFactoryInterface;
10 use Psr\Http\Message\ServerRequestInterface;
11 use Psr\Http\Message\StreamFactoryInterface;
12 use Psr\Http\Message\StreamInterface;
13 use Psr\Http\Message\UploadedFileFactoryInterface;
14 use Psr\Http\Message\UploadedFileInterface;
15 use Psr\Http\Message\UriFactoryInterface;
16 use Psr\Http\Message\UriInterface;
17
18 /**
19 * A generic PSR-17 implementation.
20 *
21 * You can create this class with concrete factory instances or let
22 * it use discovery to find suitable implementations as needed.
23 *
24 * This class also provides two additional methods that are not in PSR17,
25 * to help with creating PSR-7 objects from PHP superglobals:
26 * - createServerRequestFromGlobals()
27 * - createUriFromGlobals()
28 *
29 * The code in this class is inspired by the "nyholm/psr7", "guzzlehttp/psr7"
30 * and "symfony/http-foundation" packages, all licenced under MIT.
31 *
32 * Copyright (c) 2004-2023 Fabien Potencier <fabien@symfony.com>
33 * Copyright (c) 2015 Michael Dowling <mtdowling@gmail.com>
34 * Copyright (c) 2015 Márk Sági-Kazár <mark.sagikazar@gmail.com>
35 * Copyright (c) 2015 Graham Campbell <hello@gjcampbell.co.uk>
36 * Copyright (c) 2016 Tobias Schultze <webmaster@tubo-world.de>
37 * Copyright (c) 2016 George Mponos <gmponos@gmail.com>
38 * Copyright (c) 2016-2018 Tobias Nyholm <tobias.nyholm@gmail.com>
39 *
40 * @author Nicolas Grekas <p@tchwork.com>
41 */
42 class Psr17Factory implements RequestFactoryInterface, ResponseFactoryInterface, ServerRequestFactoryInterface, StreamFactoryInterface, UploadedFileFactoryInterface, UriFactoryInterface
43 {
44 private $requestFactory;
45 private $responseFactory;
46 private $serverRequestFactory;
47 private $streamFactory;
48 private $uploadedFileFactory;
49 private $uriFactory;
50
51 public function __construct(
52 ?RequestFactoryInterface $requestFactory = null,
53 ?ResponseFactoryInterface $responseFactory = null,
54 ?ServerRequestFactoryInterface $serverRequestFactory = null,
55 ?StreamFactoryInterface $streamFactory = null,
56 ?UploadedFileFactoryInterface $uploadedFileFactory = null,
57 ?UriFactoryInterface $uriFactory = null
58 ) {
59 $this->requestFactory = $requestFactory;
60 $this->responseFactory = $responseFactory;
61 $this->serverRequestFactory = $serverRequestFactory;
62 $this->streamFactory = $streamFactory;
63 $this->uploadedFileFactory = $uploadedFileFactory;
64 $this->uriFactory = $uriFactory;
65
66 $this->setFactory($requestFactory);
67 $this->setFactory($responseFactory);
68 $this->setFactory($serverRequestFactory);
69 $this->setFactory($streamFactory);
70 $this->setFactory($uploadedFileFactory);
71 $this->setFactory($uriFactory);
72 }
73
74 /**
75 * @param UriInterface|string $uri
76 */
77 public function createRequest(string $method, $uri): RequestInterface
78 {
79 $factory = $this->requestFactory ?? $this->setFactory(Psr17FactoryDiscovery::findRequestFactory());
80
81 return $factory->createRequest(...\func_get_args());
82 }
83
84 public function createResponse(int $code = 200, string $reasonPhrase = ''): ResponseInterface
85 {
86 $factory = $this->responseFactory ?? $this->setFactory(Psr17FactoryDiscovery::findResponseFactory());
87
88 return $factory->createResponse(...\func_get_args());
89 }
90
91 /**
92 * @param UriInterface|string $uri
93 */
94 public function createServerRequest(string $method, $uri, array $serverParams = []): ServerRequestInterface
95 {
96 $factory = $this->serverRequestFactory ?? $this->setFactory(Psr17FactoryDiscovery::findServerRequestFactory());
97
98 return $factory->createServerRequest(...\func_get_args());
99 }
100
101 public function createServerRequestFromGlobals(?array $server = null, ?array $get = null, ?array $post = null, ?array $cookie = null, ?array $files = null, ?StreamInterface $body = null): ServerRequestInterface
102 {
103 $server = $server ?? $_SERVER;
104 $request = $this->createServerRequest($server['REQUEST_METHOD'] ?? 'GET', $this->createUriFromGlobals($server), $server);
105
106 return $this->buildServerRequestFromGlobals($request, $server, $files ?? $_FILES)
107 ->withQueryParams($get ?? $_GET)
108 ->withParsedBody($post ?? $_POST)
109 ->withCookieParams($cookie ?? $_COOKIE)
110 ->withBody($body ?? $this->createStreamFromFile('php://input', 'r+'));
111 }
112
113 public function createStream(string $content = ''): StreamInterface
114 {
115 $factory = $this->streamFactory ?? $this->setFactory(Psr17FactoryDiscovery::findStreamFactory());
116
117 return $factory->createStream($content);
118 }
119
120 public function createStreamFromFile(string $filename, string $mode = 'r'): StreamInterface
121 {
122 $factory = $this->streamFactory ?? $this->setFactory(Psr17FactoryDiscovery::findStreamFactory());
123
124 return $factory->createStreamFromFile($filename, $mode);
125 }
126
127 /**
128 * @param resource $resource
129 */
130 public function createStreamFromResource($resource): StreamInterface
131 {
132 $factory = $this->streamFactory ?? $this->setFactory(Psr17FactoryDiscovery::findStreamFactory());
133
134 return $factory->createStreamFromResource($resource);
135 }
136
137 public function createUploadedFile(StreamInterface $stream, ?int $size = null, int $error = \UPLOAD_ERR_OK, ?string $clientFilename = null, ?string $clientMediaType = null): UploadedFileInterface
138 {
139 $factory = $this->uploadedFileFactory ?? $this->setFactory(Psr17FactoryDiscovery::findUploadedFileFactory());
140
141 return $factory->createUploadedFile(...\func_get_args());
142 }
143
144 public function createUri(string $uri = ''): UriInterface
145 {
146 $factory = $this->uriFactory ?? $this->setFactory(Psr17FactoryDiscovery::findUriFactory());
147
148 return $factory->createUri(...\func_get_args());
149 }
150
151 public function createUriFromGlobals(?array $server = null): UriInterface
152 {
153 return $this->buildUriFromGlobals($this->createUri(''), $server ?? $_SERVER);
154 }
155
156 private function setFactory($factory)
157 {
158 if (!$this->requestFactory && $factory instanceof RequestFactoryInterface) {
159 $this->requestFactory = $factory;
160 }
161 if (!$this->responseFactory && $factory instanceof ResponseFactoryInterface) {
162 $this->responseFactory = $factory;
163 }
164 if (!$this->serverRequestFactory && $factory instanceof ServerRequestFactoryInterface) {
165 $this->serverRequestFactory = $factory;
166 }
167 if (!$this->streamFactory && $factory instanceof StreamFactoryInterface) {
168 $this->streamFactory = $factory;
169 }
170 if (!$this->uploadedFileFactory && $factory instanceof UploadedFileFactoryInterface) {
171 $this->uploadedFileFactory = $factory;
172 }
173 if (!$this->uriFactory && $factory instanceof UriFactoryInterface) {
174 $this->uriFactory = $factory;
175 }
176
177 return $factory;
178 }
179
180 private function buildServerRequestFromGlobals(ServerRequestInterface $request, array $server, array $files): ServerRequestInterface
181 {
182 $request = $request
183 ->withProtocolVersion(isset($server['SERVER_PROTOCOL']) ? str_replace('HTTP/', '', $server['SERVER_PROTOCOL']) : '1.1')
184 ->withUploadedFiles($this->normalizeFiles($files));
185
186 $headers = [];
187 foreach ($server as $k => $v) {
188 if (0 === strpos($k, 'HTTP_')) {
189 $k = substr($k, 5);
190 } elseif (!\in_array($k, ['CONTENT_TYPE', 'CONTENT_LENGTH', 'CONTENT_MD5'], true)) {
191 continue;
192 }
193 $k = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', $k))));
194
195 $headers[$k] = $v;
196 }
197
198 if (!isset($headers['Authorization'])) {
199 if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) {
200 $headers['Authorization'] = $_SERVER['REDIRECT_HTTP_AUTHORIZATION'];
201 } elseif (isset($_SERVER['PHP_AUTH_USER'])) {
202 $headers['Authorization'] = 'Basic '.base64_encode($_SERVER['PHP_AUTH_USER'].':'.($_SERVER['PHP_AUTH_PW'] ?? ''));
203 } elseif (isset($_SERVER['PHP_AUTH_DIGEST'])) {
204 $headers['Authorization'] = $_SERVER['PHP_AUTH_DIGEST'];
205 }
206 }
207
208 foreach ($headers as $k => $v) {
209 try {
210 $request = $request->withHeader($k, $v);
211 } catch (\InvalidArgumentException $e) {
212 // ignore invalid headers
213 }
214 }
215
216 return $request;
217 }
218
219 private function buildUriFromGlobals(UriInterface $uri, array $server): UriInterface
220 {
221 $uri = $uri->withScheme(!empty($server['HTTPS']) && 'off' !== strtolower($server['HTTPS']) ? 'https' : 'http');
222
223 $hasPort = false;
224 if (isset($server['HTTP_HOST'])) {
225 $parts = parse_url('http://'.$server['HTTP_HOST']);
226
227 $uri = $uri->withHost($parts['host'] ?? 'localhost');
228
229 if ($parts['port'] ?? false) {
230 $hasPort = true;
231 $uri = $uri->withPort($parts['port']);
232 }
233 } else {
234 $uri = $uri->withHost($server['SERVER_NAME'] ?? $server['SERVER_ADDR'] ?? 'localhost');
235 }
236
237 if (!$hasPort && isset($server['SERVER_PORT'])) {
238 $uri = $uri->withPort($server['SERVER_PORT']);
239 }
240
241 $hasQuery = false;
242 if (isset($server['REQUEST_URI'])) {
243 $requestUriParts = explode('?', $server['REQUEST_URI'], 2);
244 $uri = $uri->withPath($requestUriParts[0]);
245 if (isset($requestUriParts[1])) {
246 $hasQuery = true;
247 $uri = $uri->withQuery($requestUriParts[1]);
248 }
249 }
250
251 if (!$hasQuery && isset($server['QUERY_STRING'])) {
252 $uri = $uri->withQuery($server['QUERY_STRING']);
253 }
254
255 return $uri;
256 }
257
258 private function normalizeFiles(array $files): array
259 {
260 foreach ($files as $k => $v) {
261 if ($v instanceof UploadedFileInterface) {
262 continue;
263 }
264 if (!\is_array($v)) {
265 unset($files[$k]);
266 } elseif (!isset($v['tmp_name'])) {
267 $files[$k] = $this->normalizeFiles($v);
268 } else {
269 $files[$k] = $this->createUploadedFileFromSpec($v);
270 }
271 }
272
273 return $files;
274 }
275
276 /**
277 * Create and return an UploadedFile instance from a $_FILES specification.
278 *
279 * @param array $value $_FILES struct
280 *
281 * @return UploadedFileInterface|UploadedFileInterface[]
282 */
283 private function createUploadedFileFromSpec(array $value)
284 {
285 if (!is_array($tmpName = $value['tmp_name'])) {
286 $file = is_file($tmpName) ? $this->createStreamFromFile($tmpName, 'r') : $this->createStream();
287
288 return $this->createUploadedFile($file, $value['size'], $value['error'], $value['name'], $value['type']);
289 }
290
291 foreach ($tmpName as $k => $v) {
292 $tmpName[$k] = $this->createUploadedFileFromSpec([
293 'tmp_name' => $v,
294 'size' => $value['size'][$k] ?? null,
295 'error' => $value['error'][$k] ?? null,
296 'name' => $value['name'][$k] ?? null,
297 'type' => $value['type'][$k] ?? null,
298 ]);
299 }
300
301 return $tmpName;
302 }
303 }
304