dokuwiki-matrixnotifierwas-plugin – Blame information for rev 1

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