PluginProbe
StockPack – Stock photos and AI images from Unsplash, Adobe Stock, Freepik and more / 2.4.3
StockPack – Stock photos and AI images from Unsplash, Adobe Stock, Freepik and more v2.4.3
3.7.2 3.7.1 3.7.0 3.6.0 3.6.1 3.5.2 trunk 2.0 2.1 2.2 2.3 2.4 2.4.1 2.4.2 2.4.3 2.5.0 2.5.1 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.7 2.6.0 2.6.1 All 73 releases
stockpack / vendor / guzzlehttp / psr7 / src / MultipartStream.php

MultipartStream.php in StockPack – Stock photos and AI images from Unsplash, Adobe Stock, Freepik and more 2.4.3, at vendor/guzzlehttp/psr7/src/MultipartStream.php

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