PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 27.9
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v27.9
28.5 28.4 28.3 28.2 28.1 28.0 27.9 27.8 27.7 27.6 27.5 trunk 18.0 18.1 18.2 18.3 18.4 18.4.1 18.5 18.5.1 18.6 18.7 18.8 18.9 19.0 All 129 releases
wordpress-seo / vendor_prefixed / guzzlehttp / psr7 / src / CachingStream.php

CachingStream.php in Yoast SEO – Advanced SEO with real-time guidance and built-in AI 27.9, at vendor_prefixed/guzzlehttp/psr7/src/CachingStream.php

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