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 / MultipartStream.php

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

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