123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248 |
- <?php
- declare(strict_types=1);
- namespace GuzzleHttp\Psr7;
- use Psr\Http\Message\StreamInterface;
- final class AppendStream implements StreamInterface
- {
-
- private $streams = [];
-
- private $seekable = true;
-
- private $current = 0;
-
- private $pos = 0;
-
- public function __construct(array $streams = [])
- {
- foreach ($streams as $stream) {
- $this->addStream($stream);
- }
- }
- public function __toString(): string
- {
- try {
- $this->rewind();
- return $this->getContents();
- } catch (\Throwable $e) {
- if (\PHP_VERSION_ID >= 70400) {
- throw $e;
- }
- trigger_error(sprintf('%s::__toString exception: %s', self::class, (string) $e), E_USER_ERROR);
- return '';
- }
- }
-
- public function addStream(StreamInterface $stream): void
- {
- if (!$stream->isReadable()) {
- throw new \InvalidArgumentException('Each stream must be readable');
- }
-
- if (!$stream->isSeekable()) {
- $this->seekable = false;
- }
- $this->streams[] = $stream;
- }
- public function getContents(): string
- {
- return Utils::copyToString($this);
- }
-
- public function close(): void
- {
- $this->pos = $this->current = 0;
- $this->seekable = true;
- foreach ($this->streams as $stream) {
- $stream->close();
- }
- $this->streams = [];
- }
-
- public function detach()
- {
- $this->pos = $this->current = 0;
- $this->seekable = true;
- foreach ($this->streams as $stream) {
- $stream->detach();
- }
- $this->streams = [];
- return null;
- }
- public function tell(): int
- {
- return $this->pos;
- }
-
- public function getSize(): ?int
- {
- $size = 0;
- foreach ($this->streams as $stream) {
- $s = $stream->getSize();
- if ($s === null) {
- return null;
- }
- $size += $s;
- }
- return $size;
- }
- public function eof(): bool
- {
- return !$this->streams
- || ($this->current >= count($this->streams) - 1
- && $this->streams[$this->current]->eof());
- }
- public function rewind(): void
- {
- $this->seek(0);
- }
-
- public function seek($offset, $whence = SEEK_SET): void
- {
- 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;
-
- 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);
- }
- }
-
- while ($this->pos < $offset && !$this->eof()) {
- $result = $this->read(min(8096, $offset - $this->pos));
- if ($result === '') {
- break;
- }
- }
- }
-
- public function read($length): string
- {
- $buffer = '';
- $total = count($this->streams) - 1;
- $remaining = $length;
- $progressToNext = false;
- while ($remaining > 0) {
-
- if ($progressToNext || $this->streams[$this->current]->eof()) {
- $progressToNext = false;
- if ($this->current === $total) {
- break;
- }
- ++$this->current;
- }
- $result = $this->streams[$this->current]->read($remaining);
- if ($result === '') {
- $progressToNext = true;
- continue;
- }
- $buffer .= $result;
- $remaining = $length - strlen($buffer);
- }
- $this->pos += strlen($buffer);
- return $buffer;
- }
- public function isReadable(): bool
- {
- return true;
- }
- public function isWritable(): bool
- {
- return false;
- }
- public function isSeekable(): bool
- {
- return $this->seekable;
- }
- public function write($string): int
- {
- throw new \RuntimeException('Cannot write to an AppendStream');
- }
-
- public function getMetadata($key = null)
- {
- return $key ? null : [];
- }
- }
|