PluginProbe
Media Cloud Sync / 1.3.11
Media Cloud Sync v1.3.11
1.4.1 1.4.0 1.3.12 1.3.11 1.3.10 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.2.0 1.2.10 1.2.11 1.2.12 1.2.13 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 All 35 releases
media-cloud-sync / includes / sdk / s3 / GuzzleHttp / Psr7 / MultipartStream.php

MultipartStream.php in Media Cloud Sync 1.3.11, at includes/sdk/s3/GuzzleHttp/Psr7/MultipartStream.php

131 lines 4.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare (strict_types=1);
4 namespace Dudlewebs\WPMCS\s3\GuzzleHttp\Psr7;
5
6 use Dudlewebs\WPMCS\s3\Psr\Http\Message\StreamInterface;
7 /**
8 * Stream that when read returns bytes for a streaming multipart or
9 * multipart/form-data stream.
10 */
11 final class MultipartStream implements StreamInterface
12 {
13 use StreamDecoratorTrait;
14 /** @var string */
15 private $boundary;
16 /** @var StreamInterface */
17 private $stream;
18 /**
19 * @param array $elements Array of associative arrays, each containing a
20 * required "name" key mapping to the form field,
21 * name, a required "contents" key mapping to a
22 * StreamInterface/resource/string, an optional
23 * "headers" associative array of custom headers,
24 * and an optional "filename" key mapping to a
25 * string to send as the filename in the part.
26 * @param string $boundary You can optionally provide a specific boundary
27 *
28 * @throws \InvalidArgumentException
29 */
30 public function __construct(array $elements = [], ?string $boundary = null)
31 {
32 $this->boundary = $boundary ?: \bin2hex(\random_bytes(20));
33 $this->stream = $this->createStream($elements);
34 }
35 public function getBoundary() : string
36 {
37 return $this->boundary;
38 }
39 public function isWritable() : bool
40 {
41 return \false;
42 }
43 /**
44 * Get the headers needed before transferring the content of a POST file
45 *
46 * @param string[] $headers
47 */
48 private function getHeaders(array $headers) : string
49 {
50 $str = '';
51 foreach ($headers as $key => $value) {
52 $str .= "{$key}: {$value}\r\n";
53 }
54 return "--{$this->boundary}\r\n" . \trim($str) . "\r\n\r\n";
55 }
56 /**
57 * Create the aggregate stream that will be used to upload the POST data
58 */
59 protected function createStream(array $elements = []) : StreamInterface
60 {
61 $stream = new AppendStream();
62 foreach ($elements as $element) {
63 if (!\is_array($element)) {
64 throw new \UnexpectedValueException('An array is expected');
65 }
66 $this->addElement($stream, $element);
67 }
68 // Add the trailing boundary with CRLF
69 $stream->addStream(Utils::streamFor("--{$this->boundary}--\r\n"));
70 return $stream;
71 }
72 private function addElement(AppendStream $stream, array $element) : void
73 {
74 foreach (['contents', 'name'] as $key) {
75 if (!\array_key_exists($key, $element)) {
76 throw new \InvalidArgumentException("A '{$key}' key is required");
77 }
78 }
79 $element['contents'] = Utils::streamFor($element['contents']);
80 if (empty($element['filename'])) {
81 $uri = $element['contents']->getMetadata('uri');
82 if ($uri && \is_string($uri) && \substr($uri, 0, 6) !== 'php://' && \substr($uri, 0, 7) !== 'data://') {
83 $element['filename'] = $uri;
84 }
85 }
86 [$body, $headers] = $this->createElement($element['name'], $element['contents'], $element['filename'] ?? null, $element['headers'] ?? []);
87 $stream->addStream(Utils::streamFor($this->getHeaders($headers)));
88 $stream->addStream($body);
89 $stream->addStream(Utils::streamFor("\r\n"));
90 }
91 /**
92 * @param string[] $headers
93 *
94 * @return array{0: StreamInterface, 1: string[]}
95 */
96 private function createElement(string $name, StreamInterface $stream, ?string $filename, array $headers) : array
97 {
98 // Set a default content-disposition header if one was no provided
99 $disposition = self::getHeader($headers, 'content-disposition');
100 if (!$disposition) {
101 $headers['Content-Disposition'] = $filename === '0' || $filename ? \sprintf('form-data; name="%s"; filename="%s"', $name, \basename($filename)) : "form-data; name=\"{$name}\"";
102 }
103 // Set a default content-length header if one was no provided
104 $length = self::getHeader($headers, 'content-length');
105 if (!$length) {
106 if ($length = $stream->getSize()) {
107 $headers['Content-Length'] = (string) $length;
108 }
109 }
110 // Set a default Content-Type if one was not supplied
111 $type = self::getHeader($headers, 'content-type');
112 if (!$type && ($filename === '0' || $filename)) {
113 $headers['Content-Type'] = MimeType::fromFilename($filename) ?? 'application/octet-stream';
114 }
115 return [$stream, $headers];
116 }
117 /**
118 * @param string[] $headers
119 */
120 private static function getHeader(array $headers, string $key) : ?string
121 {
122 $lowercaseHeader = \strtolower($key);
123 foreach ($headers as $k => $v) {
124 if (\strtolower((string) $k) === $lowercaseHeader) {
125 return $v;
126 }
127 }
128 return null;
129 }
130 }
131