<?php namespace GuzzleHttp\Psr7; use Psr\Http\Message\StreamInterface; /** * Reads from multiple streams, one after the other. * * This is a read-only stream decorator. */ class AppendStream implements StreamInterface { /** @var StreamInterface[] Streams being decorated */ private $streams = []; private $seekable = true; private $current = 0; private $pos = 0; private $detached = false; /** * @param StreamInterface[] $streams Streams to decorate. Each stream must * be readable. */ public function __construct(array $streams = []) { foreach ($streams as $stream) { $this->addStream($stream); } } public function __toString() { try { $this->rewind(); return $this->getContents(); } catch (\Exception $e) { return ''; } } /** * Add a stream to the AppendStream * * @param StreamInterface $stream Stream to append. Must be readable. * * @throws \InvalidArgumentException if the stream is not readable */ public function addStream(StreamInterface $stream) { if (!$stream->isReadable()) { throw new \InvalidArgumentException('Each stream must be readable'); } // The stream is only seekable if all streams are seekable if (!$stream->isSeekable()) { $this->seekable = false; } $this->streams[] = $stream; } public function getContents() { return copy_to_string($this); } /** * Closes each attached stream. * * {@inheritdoc} */ public function close() { $this->pos = $this->current = 0; foreach ($this->streams as $stream) { $stream->close(); } $this->streams = []; } /** * Detaches each attached stream * * {@inheritdoc} */ public function detach() { $this->close(); $this->detached = true; } public function tell() { return $this->pos; } /** * Tries to calculate the size by adding the size of each stream. * * If any of the streams do not return a valid number, then the size of the * append stream cannot be determined and null is returned. * * {@inheritdoc} */ public function getSize() { $size = 0; foreach ($this->streams as $stream) { $s = $stream->getSize(); if ($s === null) { return null; } $size += $s; } return $size; } public function eof() { return !$this->streams || ($this->current >= count($this->streams) - 1 && $this->streams[$this->current]->eof()); } public function rewind() { $this->seek(0); } /** * Attempts to seek to the given position. Only supports SEEK_SET. * * {@inheritdoc} */ public function seek($offset, $whence = SEEK_SET) { if (!$this->seekable) { throw new \RuntimeException('This AppendStream is not seekable'); } elseif ($whence !== SEEK_SET) { throw new \RuntimeException('The AppendStream can only seek with SEEK_SET'); } $this->pos = $this->current = 0; // Rewind each stream foreach ($this->streams as $i => $stream) { try { $stream->rewind(); } catch (\Exception $e) { throw new \RuntimeException('Unable to seek stream ' . $i . ' of the AppendStream', 0, $e); } } // Seek to the actual position by reading from each stream while ($this->pos < $offset && !$this->eof()) { $result = $this->read(min(8096, $offset - $this->pos)); if ($result === '') { break; } } } /** * Reads from all of the appended streams until the length is met or EOF. * * {@inheritdoc} */ public function read($length) { $buffer = ''; $total = count($this->streams) - 1; $remaining = $length; $progressToNext = false; while ($remaining > 0) { // Progress to the next stream if needed. if ($progressToNext || $this->streams[$this->current]->eof()) { $progressToNext = false; if ($this->current === $total) { break; } $this->current++; } $result = $this->streams[$this->current]->read($remaining); // Using a loose comparison here to match on '', false, and null if ($result == null) { $progressToNext = true; continue; } $buffer .= $result; $remaining = $length - strlen($buffer); } $this->pos += strlen($buffer); return $buffer; } public function isReadable() { return true; } public function isWritable() { return false; } public function isSeekable() { return $this->seekable; } public function write($string) { throw new \RuntimeException('Cannot write to an AppendStream'); } public function getMetadata($key = null) { return $key ? null : []; } }
Name | Type | Size | Permission | Actions |
---|---|---|---|---|
AppendStream.php | File | 5.37 KB | 0644 |
|
BufferStream.php | File | 2.97 KB | 0644 |
|
CachingStream.php | File | 4.15 KB | 0644 |
|
DroppingStream.php | File | 1.05 KB | 0644 |
|
FnStream.php | File | 3.57 KB | 0644 |
|
InflateStream.php | File | 1.72 KB | 0644 |
|
LazyOpenStream.php | File | 880 B | 0644 |
|
LimitStream.php | File | 4.11 KB | 0644 |
|
MessageTrait.php | File | 4.47 KB | 0644 |
|
MultipartStream.php | File | 4.58 KB | 0644 |
|
NoSeekStream.php | File | 424 B | 0644 |
|
PumpStream.php | File | 3.94 KB | 0644 |
|
Request.php | File | 3.3 KB | 0644 |
|
Response.php | File | 3.97 KB | 0644 |
|
ServerRequest.php | File | 9.19 KB | 0644 |
|
Stream.php | File | 6.59 KB | 0644 |
|
StreamDecoratorTrait.php | File | 3.2 KB | 0644 |
|
StreamWrapper.php | File | 2.74 KB | 0644 |
|
UploadedFile.php | File | 7.37 KB | 0644 |
|
Uri.php | File | 19.35 KB | 0644 |
|
UriNormalizer.php | File | 8.12 KB | 0644 |
|
UriResolver.php | File | 8.57 KB | 0644 |
|
functions.php | File | 23.88 KB | 0644 |
|
functions_include.php | File | 156 B | 0644 |
|