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

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

139 lines 4.2 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 * Stream decorator that can cache previously read bytes from a sequentially
8 * read stream.
9 */
10 class CachingStream implements StreamInterface
11 {
12 use StreamDecoratorTrait;
13
14 /** @var StreamInterface Stream being wrapped */
15 private $remoteStream;
16
17 /** @var int Number of bytes to skip reading due to a write on the buffer */
18 private $skipReadBytes = 0;
19
20 /**
21 * We will treat the buffer object as the body of the stream
22 *
23 * @param StreamInterface $stream Stream to cache
24 * @param StreamInterface $target Optionally specify where data is cached
25 */
26 public function __construct(
27 StreamInterface $stream,
28 StreamInterface $target = null
29 ) {
30 $this->remoteStream = $stream;
31 $this->stream = $target ?: new Stream(fopen('php://temp', 'r+'));
32 }
33
34 public function getSize()
35 {
36 return max($this->stream->getSize(), $this->remoteStream->getSize());
37 }
38
39 public function rewind()
40 {
41 $this->seek(0);
42 }
43
44 public function seek($offset, $whence = SEEK_SET)
45 {
46 if ($whence == SEEK_SET) {
47 $byte = $offset;
48 } elseif ($whence == SEEK_CUR) {
49 $byte = $offset + $this->tell();
50 } elseif ($whence == SEEK_END) {
51 $size = $this->remoteStream->getSize();
52 if ($size === null) {
53 $size = $this->cacheEntireStream();
54 }
55 $byte = $size + $offset;
56 } else {
57 throw new \InvalidArgumentException('Invalid whence');
58 }
59
60 $diff = $byte - $this->stream->getSize();
61
62 if ($diff > 0) {
63 // Read the remoteStream until we have read in at least the amount
64 // of bytes requested, or we reach the end of the file.
65 while ($diff > 0 && !$this->remoteStream->eof()) {
66 $this->read($diff);
67 $diff = $byte - $this->stream->getSize();
68 }
69 } else {
70 // We can just do a normal seek since we've already seen this byte.
71 $this->stream->seek($byte);
72 }
73 }
74
75 public function read($length)
76 {
77 // Perform a regular read on any previously read data from the buffer
78 $data = $this->stream->read($length);
79 $remaining = $length - strlen($data);
80
81 // More data was requested so read from the remote stream
82 if ($remaining) {
83 // If data was written to the buffer in a position that would have
84 // been filled from the remote stream, then we must skip bytes on
85 // the remote stream to emulate overwriting bytes from that
86 // position. This mimics the behavior of other PHP stream wrappers.
87 $remoteData = $this->remoteStream->read(
88 $remaining + $this->skipReadBytes
89 );
90
91 if ($this->skipReadBytes) {
92 $len = strlen($remoteData);
93 $remoteData = substr($remoteData, $this->skipReadBytes);
94 $this->skipReadBytes = max(0, $this->skipReadBytes - $len);
95 }
96
97 $data .= $remoteData;
98 $this->stream->write($remoteData);
99 }
100
101 return $data;
102 }
103
104 public function write($string)
105 {
106 // When appending to the end of the currently read stream, you'll want
107 // to skip bytes from being read from the remote stream to emulate
108 // other stream wrappers. Basically replacing bytes of data of a fixed
109 // length.
110 $overflow = (strlen($string) + $this->tell()) - $this->remoteStream->tell();
111 if ($overflow > 0) {
112 $this->skipReadBytes += $overflow;
113 }
114
115 return $this->stream->write($string);
116 }
117
118 public function eof()
119 {
120 return $this->stream->eof() && $this->remoteStream->eof();
121 }
122
123 /**
124 * Close both the remote stream and buffer stream
125 */
126 public function close()
127 {
128 $this->remoteStream->close() && $this->stream->close();
129 }
130
131 private function cacheEntireStream()
132 {
133 $target = new FnStream(['write' => 'strlen']);
134 copy_to_stream($this, $target);
135
136 return $this->tell();
137 }
138 }
139