Mercurial > hg > isophonics-drupal-site
comparison vendor/guzzlehttp/psr7/src/MultipartStream.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
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 } |