PluginProbe
Depicter — Popup & Slider Builder / 1.3.2
Depicter — Popup & Slider Builder v1.3.2
4.8.1 trunk 1.0.0 1.1.0 1.1.2 1.1.4 1.1.6 1.1.7 1.1.8 1.1.9 1.2.0 1.3.0 1.3.1 1.3.2 1.3.3 1.3.5 1.3.8 1.5.0 1.5.1 1.5.2 1.5.5 1.6.0 1.6.1 1.6.2 1.7.0 All 76 releases
depicter / modules / GuzzleHttp / Psr7 / Utils.php

Utils.php in Depicter — Popup & Slider Builder 1.3.2, at modules/GuzzleHttp/Psr7/Utils.php

429 lines 14.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Depicter\GuzzleHttp\Psr7;
4
5 use Depicter\Psr\Http\Message\RequestInterface;
6 use Depicter\Psr\Http\Message\ServerRequestInterface;
7 use Depicter\Psr\Http\Message\StreamInterface;
8 use Depicter\Psr\Http\Message\UriInterface;
9
10 final class Utils
11 {
12 /**
13 * Remove the items given by the keys, case insensitively from the data.
14 *
15 * @param iterable<string> $keys
16 *
17 * @return array
18 */
19 public static function caselessRemove($keys, array $data)
20 {
21 $result = [];
22
23 foreach ($keys as &$key) {
24 $key = strtolower($key);
25 }
26
27 foreach ($data as $k => $v) {
28 if (!in_array(strtolower($k), $keys)) {
29 $result[$k] = $v;
30 }
31 }
32
33 return $result;
34 }
35
36 /**
37 * Copy the contents of a stream into another stream until the given number
38 * of bytes have been read.
39 *
40 * @param StreamInterface $source Stream to read from
41 * @param StreamInterface $dest Stream to write to
42 * @param int $maxLen Maximum number of bytes to read. Pass -1
43 * to read the entire stream.
44 *
45 * @throws \RuntimeException on error.
46 */
47 public static function copyToStream(StreamInterface $source, StreamInterface $dest, $maxLen = -1)
48 {
49 $bufferSize = 8192;
50
51 if ($maxLen === -1) {
52 while (!$source->eof()) {
53 if (!$dest->write($source->read($bufferSize))) {
54 break;
55 }
56 }
57 } else {
58 $remaining = $maxLen;
59 while ($remaining > 0 && !$source->eof()) {
60 $buf = $source->read(min($bufferSize, $remaining));
61 $len = strlen($buf);
62 if (!$len) {
63 break;
64 }
65 $remaining -= $len;
66 $dest->write($buf);
67 }
68 }
69 }
70
71 /**
72 * Copy the contents of a stream into a string until the given number of
73 * bytes have been read.
74 *
75 * @param StreamInterface $stream Stream to read
76 * @param int $maxLen Maximum number of bytes to read. Pass -1
77 * to read the entire stream.
78 *
79 * @return string
80 *
81 * @throws \RuntimeException on error.
82 */
83 public static function copyToString(StreamInterface $stream, $maxLen = -1)
84 {
85 $buffer = '';
86
87 if ($maxLen === -1) {
88 while (!$stream->eof()) {
89 $buf = $stream->read(1048576);
90 // Using a loose equality here to match on '' and false.
91 if ($buf == null) {
92 break;
93 }
94 $buffer .= $buf;
95 }
96 return $buffer;
97 }
98
99 $len = 0;
100 while (!$stream->eof() && $len < $maxLen) {
101 $buf = $stream->read($maxLen - $len);
102 // Using a loose equality here to match on '' and false.
103 if ($buf == null) {
104 break;
105 }
106 $buffer .= $buf;
107 $len = strlen($buffer);
108 }
109
110 return $buffer;
111 }
112
113 /**
114 * Calculate a hash of a stream.
115 *
116 * This method reads the entire stream to calculate a rolling hash, based
117 * on PHP's `hash_init` functions.
118 *
119 * @param StreamInterface $stream Stream to calculate the hash for
120 * @param string $algo Hash algorithm (e.g. md5, crc32, etc)
121 * @param bool $rawOutput Whether or not to use raw output
122 *
123 * @return string Returns the hash of the stream
124 *
125 * @throws \RuntimeException on error.
126 */
127 public static function hash(StreamInterface $stream, $algo, $rawOutput = false)
128 {
129 $pos = $stream->tell();
130
131 if ($pos > 0) {
132 $stream->rewind();
133 }
134
135 $ctx = hash_init($algo);
136 while (!$stream->eof()) {
137 hash_update($ctx, $stream->read(1048576));
138 }
139
140 $out = hash_final($ctx, (bool) $rawOutput);
141 $stream->seek($pos);
142
143 return $out;
144 }
145
146 /**
147 * Clone and modify a request with the given changes.
148 *
149 * This method is useful for reducing the number of clones needed to mutate
150 * a message.
151 *
152 * The changes can be one of:
153 * - method: (string) Changes the HTTP method.
154 * - set_headers: (array) Sets the given headers.
155 * - remove_headers: (array) Remove the given headers.
156 * - body: (mixed) Sets the given body.
157 * - uri: (UriInterface) Set the URI.
158 * - query: (string) Set the query string value of the URI.
159 * - version: (string) Set the protocol version.
160 *
161 * @param RequestInterface $request Request to clone and modify.
162 * @param array $changes Changes to apply.
163 *
164 * @return RequestInterface
165 */
166 public static function modifyRequest(RequestInterface $request, array $changes)
167 {
168 if (!$changes) {
169 return $request;
170 }
171
172 $headers = $request->getHeaders();
173
174 if (!isset($changes['uri'])) {
175 $uri = $request->getUri();
176 } else {
177 // Remove the host header if one is on the URI
178 if ($host = $changes['uri']->getHost()) {
179 $changes['set_headers']['Host'] = $host;
180
181 if ($port = $changes['uri']->getPort()) {
182 $standardPorts = ['http' => 80, 'https' => 443];
183 $scheme = $changes['uri']->getScheme();
184 if (isset($standardPorts[$scheme]) && $port != $standardPorts[$scheme]) {
185 $changes['set_headers']['Host'] .= ':' . $port;
186 }
187 }
188 }
189 $uri = $changes['uri'];
190 }
191
192 if (!empty($changes['remove_headers'])) {
193 $headers = self::caselessRemove($changes['remove_headers'], $headers);
194 }
195
196 if (!empty($changes['set_headers'])) {
197 $headers = self::caselessRemove(array_keys($changes['set_headers']), $headers);
198 $headers = $changes['set_headers'] + $headers;
199 }
200
201 if (isset($changes['query'])) {
202 $uri = $uri->withQuery($changes['query']);
203 }
204
205 if ($request instanceof ServerRequestInterface) {
206 $new = (new ServerRequest(
207 isset($changes['method']) ? $changes['method'] : $request->getMethod(),
208 $uri,
209 $headers,
210 isset($changes['body']) ? $changes['body'] : $request->getBody(),
211 isset($changes['version'])
212 ? $changes['version']
213 : $request->getProtocolVersion(),
214 $request->getServerParams()
215 ))
216 ->withParsedBody($request->getParsedBody())
217 ->withQueryParams($request->getQueryParams())
218 ->withCookieParams($request->getCookieParams())
219 ->withUploadedFiles($request->getUploadedFiles());
220
221 foreach ($request->getAttributes() as $key => $value) {
222 $new = $new->withAttribute($key, $value);
223 }
224
225 return $new;
226 }
227
228 return new Request(
229 isset($changes['method']) ? $changes['method'] : $request->getMethod(),
230 $uri,
231 $headers,
232 isset($changes['body']) ? $changes['body'] : $request->getBody(),
233 isset($changes['version'])
234 ? $changes['version']
235 : $request->getProtocolVersion()
236 );
237 }
238
239 /**
240 * Read a line from the stream up to the maximum allowed buffer length.
241 *
242 * @param StreamInterface $stream Stream to read from
243 * @param int|null $maxLength Maximum buffer length
244 *
245 * @return string
246 */
247 public static function readLine(StreamInterface $stream, $maxLength = null)
248 {
249 $buffer = '';
250 $size = 0;
251
252 while (!$stream->eof()) {
253 // Using a loose equality here to match on '' and false.
254 if (null == ($byte = $stream->read(1))) {
255 return $buffer;
256 }
257 $buffer .= $byte;
258 // Break when a new line is found or the max length - 1 is reached
259 if ($byte === "\n" || ++$size === $maxLength - 1) {
260 break;
261 }
262 }
263
264 return $buffer;
265 }
266
267 /**
268 * Create a new stream based on the input type.
269 *
270 * Options is an associative array that can contain the following keys:
271 * - metadata: Array of custom metadata.
272 * - size: Size of the stream.
273 *
274 * This method accepts the following `$resource` types:
275 * - `Depicter\Psr\Http\Message\StreamInterface`: Returns the value as-is.
276 * - `string`: Creates a stream object that uses the given string as the contents.
277 * - `resource`: Creates a stream object that wraps the given PHP stream resource.
278 * - `Iterator`: If the provided value implements `Iterator`, then a read-only
279 * stream object will be created that wraps the given iterable. Each time the
280 * stream is read from, data from the iterator will fill a buffer and will be
281 * continuously called until the buffer is equal to the requested read size.
282 * Subsequent read calls will first read from the buffer and then call `next`
283 * on the underlying iterator until it is exhausted.
284 * - `object` with `__toString()`: If the object has the `__toString()` method,
285 * the object will be cast to a string and then a stream will be returned that
286 * uses the string value.
287 * - `NULL`: When `null` is passed, an empty stream object is returned.
288 * - `callable` When a callable is passed, a read-only stream object will be
289 * created that invokes the given callable. The callable is invoked with the
290 * number of suggested bytes to read. The callable can return any number of
291 * bytes, but MUST return `false` when there is no more data to return. The
292 * stream object that wraps the callable will invoke the callable until the
293 * number of requested bytes are available. Any additional bytes will be
294 * buffered and used in subsequent reads.
295 *
296 * @param resource|string|int|float|bool|StreamInterface|callable|\Iterator|null $resource Entity body data
297 * @param array $options Additional options
298 *
299 * @return StreamInterface
300 *
301 * @throws \InvalidArgumentException if the $resource arg is not valid.
302 */
303 public static function streamFor($resource = '', array $options = [])
304 {
305 if (is_scalar($resource)) {
306 $stream = self::tryFopen('php://temp', 'r+');
307 if ($resource !== '') {
308 fwrite($stream, $resource);
309 fseek($stream, 0);
310 }
311 return new Stream($stream, $options);
312 }
313
314 switch (gettype($resource)) {
315 case 'resource':
316 /*
317 * The 'php://input' is a special stream with quirks and inconsistencies.
318 * We avoid using that stream by reading it into php://temp
319 */
320 $metaData = \stream_get_meta_data($resource);
321 if (isset($metaData['uri']) && $metaData['uri'] === 'php://input') {
322 $stream = self::tryFopen('php://temp', 'w+');
323 fwrite($stream, stream_get_contents($resource));
324 fseek($stream, 0);
325 $resource = $stream;
326 }
327 return new Stream($resource, $options);
328 case 'object':
329 if ($resource instanceof StreamInterface) {
330 return $resource;
331 } elseif ($resource instanceof \Iterator) {
332 return new PumpStream(function () use ($resource) {
333 if (!$resource->valid()) {
334 return false;
335 }
336 $result = $resource->current();
337 $resource->next();
338 return $result;
339 }, $options);
340 } elseif (method_exists($resource, '__toString')) {
341 return Utils::streamFor((string) $resource, $options);
342 }
343 break;
344 case 'NULL':
345 return new Stream(self::tryFopen('php://temp', 'r+'), $options);
346 }
347
348 if (is_callable($resource)) {
349 return new PumpStream($resource, $options);
350 }
351
352 throw new \InvalidArgumentException('Invalid resource type: ' . gettype($resource));
353 }
354
355 /**
356 * Safely opens a PHP stream resource using a filename.
357 *
358 * When fopen fails, PHP normally raises a warning. This function adds an
359 * error handler that checks for errors and throws an exception instead.
360 *
361 * @param string $filename File to open
362 * @param string $mode Mode used to open the file
363 *
364 * @return resource
365 *
366 * @throws \RuntimeException if the file cannot be opened
367 */
368 public static function tryFopen($filename, $mode)
369 {
370 $ex = null;
371 set_error_handler(function () use ($filename, $mode, &$ex) {
372 $ex = new \RuntimeException(sprintf(
373 'Unable to open "%s" using mode "%s": %s',
374 $filename,
375 $mode,
376 func_get_args()[1]
377 ));
378
379 return true;
380 });
381
382 try {
383 $handle = fopen($filename, $mode);
384 } catch (\Throwable $e) {
385 $ex = new \RuntimeException(sprintf(
386 'Unable to open "%s" using mode "%s": %s',
387 $filename,
388 $mode,
389 $e->getMessage()
390 ), 0, $e);
391 }
392
393 restore_error_handler();
394
395 if ($ex) {
396 /** @var $ex \RuntimeException */
397 throw $ex;
398 }
399
400 return $handle;
401 }
402
403 /**
404 * Returns a UriInterface for the given value.
405 *
406 * This function accepts a string or UriInterface and returns a
407 * UriInterface for the given value. If the value is already a
408 * UriInterface, it is returned as-is.
409 *
410 * @param string|UriInterface $uri
411 *
412 * @return UriInterface
413 *
414 * @throws \InvalidArgumentException
415 */
416 public static function uriFor($uri)
417 {
418 if ($uri instanceof UriInterface) {
419 return $uri;
420 }
421
422 if (is_string($uri)) {
423 return new Uri($uri);
424 }
425
426 throw new \InvalidArgumentException('URI must be a string or UriInterface');
427 }
428 }
429