PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / trunk
Tutor LMS – eLearning and online course solution vtrunk
4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 4.0.2 4.0.1 4.0.0 3.9.15 3.9.14 3.9.13 3.9.12 3.9.11 trunk 1.0.0 1.0.0-alpha 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.2.0 1.2.1 1.2.11 1.2.12 1.2.13 1.2.20 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.1 1.8.10 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.15 1.9.16 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.10 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.1.1 2.1.10 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.3.0 2.4.0 2.5.0 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 3.0.0 3.0.1 3.0.2 3.1.0 3.2.0 3.2.1 3.2.2 3.2.3 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.7.0 3.7.1 3.7.2 3.7.3 3.7.4 3.8.0 3.8.1 3.8.2 3.8.3 3.9.0 3.9.1 3.9.10 3.9.2 3.9.3 3.9.4 3.9.5 3.9.6 3.9.7 3.9.8 3.9.9
tutor / ecommerce / PaymentGateways / Paypal / vendor / guzzlehttp / psr7 / src / CachingStream.php
tutor / ecommerce / PaymentGateways / Paypal / vendor / guzzlehttp / psr7 / src Last commit date
Exception 1 year ago AppendStream.php 2 months ago BufferStream.php 2 months ago CachingStream.php 2 months ago DroppingStream.php 2 months ago FnStream.php 2 months ago Header.php 2 months ago HttpFactory.php 1 year ago InflateStream.php 1 year ago LazyOpenStream.php 1 year ago LimitStream.php 2 months ago Message.php 2 months ago MessageTrait.php 2 months ago MimeType.php 2 months ago MultipartStream.php 2 months ago NoSeekStream.php 2 months ago PumpStream.php 2 months ago Query.php 1 year ago Request.php 2 months ago Response.php 2 months ago Rfc3986.php 2 months ago Rfc7230.php 2 months ago ServerRequest.php 2 months ago Stream.php 2 months ago StreamDecoratorTrait.php 2 months ago StreamWrapper.php 2 months ago UploadedFile.php 2 months ago Uri.php 2 months ago UriComparator.php 2 months ago UriNormalizer.php 2 months ago UriResolver.php 2 months ago Utils.php 2 months ago
CachingStream.php
227 lines
1 <?php
2
3 declare(strict_types=1);
4
5 namespace GuzzleHttp\Psr7;
6
7 use Psr\Http\Message\StreamInterface;
8
9 /**
10 * Stream decorator that can cache previously read bytes from a sequentially
11 * read stream.
12 */
13 final class CachingStream implements StreamInterface
14 {
15 use StreamDecoratorTrait;
16
17 /** @var StreamInterface Stream being wrapped */
18 private $remoteStream;
19
20 /** @var int Number of bytes to skip reading due to a write on the buffer */
21 private $skipReadBytes = 0;
22
23 /**
24 * @var StreamInterface
25 */
26 private $stream;
27
28 /** @var bool */
29 private $detached = false;
30
31 /**
32 * We will treat the buffer object as the body of the stream
33 *
34 * @param StreamInterface $stream Stream to cache. The cursor is assumed to be at the beginning of the stream.
35 * @param StreamInterface $target Optionally specify where data is cached
36 */
37 public function __construct(
38 StreamInterface $stream,
39 ?StreamInterface $target = null
40 ) {
41 $this->remoteStream = $stream;
42 $this->stream = $target ?: new Stream(Utils::tryFopen('php://temp', 'r+'));
43 }
44
45 public function getSize(): ?int
46 {
47 if ($this->detached) {
48 return null;
49 }
50
51 $remoteSize = $this->remoteStream->getSize();
52
53 if (null === $remoteSize) {
54 return null;
55 }
56
57 return max($this->stream->getSize(), $remoteSize);
58 }
59
60 public function rewind(): void
61 {
62 $this->seek(0);
63 }
64
65 public function seek($offset, $whence = SEEK_SET): void
66 {
67 if (!\is_int($offset)) {
68 \trigger_deprecation(
69 'guzzlehttp/psr7',
70 '2.11',
71 'Passing %s to StreamInterface::seek() is deprecated; guzzlehttp/psr7 3.0 requires int for $offset.',
72 \get_debug_type($offset)
73 );
74 }
75
76 if (!\is_int($whence)) {
77 \trigger_deprecation(
78 'guzzlehttp/psr7',
79 '2.11',
80 'Passing %s to StreamInterface::seek() is deprecated; guzzlehttp/psr7 3.0 requires int for $whence.',
81 \get_debug_type($whence)
82 );
83 }
84
85 if ($whence === SEEK_SET) {
86 $byte = $offset;
87 } elseif ($whence === SEEK_CUR) {
88 $byte = $offset + $this->tell();
89 } elseif ($whence === SEEK_END) {
90 $size = $this->remoteStream->getSize();
91 if ($size === null) {
92 $size = $this->cacheEntireStream();
93 }
94 $byte = $size + $offset;
95 } else {
96 throw new \InvalidArgumentException('Invalid whence');
97 }
98
99 $diff = $byte - $this->stream->getSize();
100
101 if ($diff > 0) {
102 // Read the remoteStream until we have read in at least the amount
103 // of bytes requested, or we reach the end of the file.
104 while ($diff > 0 && !$this->remoteStream->eof()) {
105 $previousSize = $this->stream->getSize();
106 $previousSkipReadBytes = $this->skipReadBytes;
107 $data = $this->read($diff);
108 $currentSize = $this->stream->getSize();
109
110 if ($data === '' && $currentSize === $previousSize && $this->skipReadBytes === $previousSkipReadBytes) {
111 break;
112 }
113
114 $diff = $byte - $currentSize;
115 }
116 } else {
117 // We can just do a normal seek since we've already seen this byte.
118 $this->stream->seek($byte);
119 }
120 }
121
122 public function read($length): string
123 {
124 if (!\is_int($length)) {
125 \trigger_deprecation(
126 'guzzlehttp/psr7',
127 '2.11',
128 'Passing %s to StreamInterface::read() is deprecated; guzzlehttp/psr7 3.0 requires int for $length.',
129 \get_debug_type($length)
130 );
131 }
132
133 // Perform a regular read on any previously read data from the buffer
134 $data = $this->stream->read($length);
135 $remaining = $length - strlen($data);
136
137 // More data was requested so read from the remote stream
138 if ($remaining) {
139 // If data was written to the buffer in a position that would have
140 // been filled from the remote stream, then we must skip bytes on
141 // the remote stream to emulate overwriting bytes from that
142 // position. This mimics the behavior of other PHP stream wrappers.
143 $remoteData = $this->remoteStream->read(
144 $remaining + $this->skipReadBytes
145 );
146
147 if ($this->skipReadBytes) {
148 $len = strlen($remoteData);
149 $remoteData = substr($remoteData, $this->skipReadBytes);
150 $this->skipReadBytes = max(0, $this->skipReadBytes - $len);
151 }
152
153 $data .= $remoteData;
154
155 // A short cache write would silently corrupt later replays, so fail loudly.
156 if ($this->stream->write($remoteData) !== strlen($remoteData)) {
157 throw new \RuntimeException('Unable to cache the entire read from the remote stream');
158 }
159 }
160
161 return $data;
162 }
163
164 public function write($string): int
165 {
166 if (!\is_string($string)) {
167 \trigger_deprecation(
168 'guzzlehttp/psr7',
169 '2.11',
170 'Passing %s to StreamInterface::write() is deprecated; guzzlehttp/psr7 3.0 requires string for $string.',
171 \get_debug_type($string)
172 );
173 }
174
175 // When appending to the end of the currently read stream, you'll want
176 // to skip bytes from being read from the remote stream to emulate
177 // other stream wrappers. Basically replacing bytes of data of a fixed
178 // length.
179 $overflow = (strlen($string) + $this->tell()) - $this->remoteStream->tell();
180 if ($overflow > 0) {
181 $this->skipReadBytes += $overflow;
182 }
183
184 return $this->stream->write($string);
185 }
186
187 public function eof(): bool
188 {
189 return $this->stream->eof() && $this->remoteStream->eof();
190 }
191
192 public function detach()
193 {
194 if ($this->detached) {
195 return null;
196 }
197
198 $position = $this->tell();
199
200 $this->cacheEntireStream();
201 $this->stream->seek($position);
202
203 $resource = $this->stream->detach();
204 $this->detached = true;
205
206 return $resource;
207 }
208
209 /**
210 * Close both the remote stream and buffer stream
211 */
212 public function close(): void
213 {
214 $this->remoteStream->close();
215 $this->stream->close();
216 $this->detached = true;
217 }
218
219 private function cacheEntireStream(): int
220 {
221 $target = new FnStream(['write' => 'strlen']);
222 Utils::copyToStream($this, $target);
223
224 return $this->tell();
225 }
226 }
227