PluginProbe
StockPack – Stock photos and AI images from Unsplash, Adobe Stock, Freepik and more / 2.5.7
StockPack – Stock photos and AI images from Unsplash, Adobe Stock, Freepik and more v2.5.7
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 / AppendStream.php

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

242 lines 5.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 * Reads from multiple streams, one after the other.
8 *
9 * This is a read-only stream decorator.
10 */
11 class AppendStream implements StreamInterface
12 {
13 /** @var StreamInterface[] Streams being decorated */
14 private $streams = [];
15
16 private $seekable = true;
17 private $current = 0;
18 private $pos = 0;
19
20 /**
21 * @param StreamInterface[] $streams Streams to decorate. Each stream must
22 * be readable.
23 */
24 public function __construct(array $streams = [])
25 {
26 foreach ($streams as $stream) {
27 $this->addStream($stream);
28 }
29 }
30
31 public function __toString()
32 {
33 try {
34 $this->rewind();
35 return $this->getContents();
36 } catch (\Exception $e) {
37 return '';
38 }
39 }
40
41 /**
42 * Add a stream to the AppendStream
43 *
44 * @param StreamInterface $stream Stream to append. Must be readable.
45 *
46 * @throws \InvalidArgumentException if the stream is not readable
47 */
48 public function addStream(StreamInterface $stream)
49 {
50 if (!$stream->isReadable()) {
51 throw new \InvalidArgumentException('Each stream must be readable');
52 }
53
54 // The stream is only seekable if all streams are seekable
55 if (!$stream->isSeekable()) {
56 $this->seekable = false;
57 }
58
59 $this->streams[] = $stream;
60 }
61
62 public function getContents()
63 {
64 return copy_to_string($this);
65 }
66
67 /**
68 * Closes each attached stream.
69 *
70 * {@inheritdoc}
71 */
72 public function close()
73 {
74 $this->pos = $this->current = 0;
75 $this->seekable = true;
76
77 foreach ($this->streams as $stream) {
78 $stream->close();
79 }
80
81 $this->streams = [];
82 }
83
84 /**
85 * Detaches each attached stream.
86 *
87 * Returns null as it's not clear which underlying stream resource to return.
88 *
89 * {@inheritdoc}
90 */
91 public function detach()
92 {
93 $this->pos = $this->current = 0;
94 $this->seekable = true;
95
96 foreach ($this->streams as $stream) {
97 $stream->detach();
98 }
99
100 $this->streams = [];
101 }
102
103 public function tell()
104 {
105 return $this->pos;
106 }
107
108 /**
109 * Tries to calculate the size by adding the size of each stream.
110 *
111 * If any of the streams do not return a valid number, then the size of the
112 * append stream cannot be determined and null is returned.
113 *
114 * {@inheritdoc}
115 */
116 public function getSize()
117 {
118 $size = 0;
119
120 foreach ($this->streams as $stream) {
121 $s = $stream->getSize();
122 if ($s === null) {
123 return null;
124 }
125 $size += $s;
126 }
127
128 return $size;
129 }
130
131 public function eof()
132 {
133 return !$this->streams ||
134 ($this->current >= count($this->streams) - 1 &&
135 $this->streams[$this->current]->eof());
136 }
137
138 public function rewind()
139 {
140 $this->seek(0);
141 }
142
143 /**
144 * Attempts to seek to the given position. Only supports SEEK_SET.
145 *
146 * {@inheritdoc}
147 */
148 public function seek($offset, $whence = SEEK_SET)
149 {
150 if (!$this->seekable) {
151 throw new \RuntimeException('This AppendStream is not seekable');
152 } elseif ($whence !== SEEK_SET) {
153 throw new \RuntimeException('The AppendStream can only seek with SEEK_SET');
154 }
155
156 $this->pos = $this->current = 0;
157
158 // Rewind each stream
159 foreach ($this->streams as $i => $stream) {
160 try {
161 $stream->rewind();
162 } catch (\Exception $e) {
163 throw new \RuntimeException('Unable to seek stream '
164 . $i . ' of the AppendStream', 0, $e);
165 }
166 }
167
168 // Seek to the actual position by reading from each stream
169 while ($this->pos < $offset && !$this->eof()) {
170 $result = $this->read(min(8096, $offset - $this->pos));
171 if ($result === '') {
172 break;
173 }
174 }
175 }
176
177 /**
178 * Reads from all of the appended streams until the length is met or EOF.
179 *
180 * {@inheritdoc}
181 */
182 public function read($length)
183 {
184 $buffer = '';
185 $total = count($this->streams) - 1;
186 $remaining = $length;
187 $progressToNext = false;
188
189 while ($remaining > 0) {
190
191 // Progress to the next stream if needed.
192 if ($progressToNext || $this->streams[$this->current]->eof()) {
193 $progressToNext = false;
194 if ($this->current === $total) {
195 break;
196 }
197 $this->current++;
198 }
199
200 $result = $this->streams[$this->current]->read($remaining);
201
202 // Using a loose comparison here to match on '', false, and null
203 if ($result == null) {
204 $progressToNext = true;
205 continue;
206 }
207
208 $buffer .= $result;
209 $remaining = $length - strlen($buffer);
210 }
211
212 $this->pos += strlen($buffer);
213
214 return $buffer;
215 }
216
217 public function isReadable()
218 {
219 return true;
220 }
221
222 public function isWritable()
223 {
224 return false;
225 }
226
227 public function isSeekable()
228 {
229 return $this->seekable;
230 }
231
232 public function write($string)
233 {
234 throw new \RuntimeException('Cannot write to an AppendStream');
235 }
236
237 public function getMetadata($key = null)
238 {
239 return $key ? null : [];
240 }
241 }
242