PluginProbe
Depicter — Popup & Slider Builder / 1.3.2
Depicter — Popup & Slider Builder v1.3.2
4.8.1 trunk 1.0.0 1.1.0 1.1.2 1.1.4 1.1.6 1.1.7 1.1.8 1.1.9 1.2.0 1.3.0 1.3.1 1.3.2 1.3.3 1.3.5 1.3.8 1.5.0 1.5.1 1.5.2 1.5.5 1.6.0 1.6.1 1.6.2 1.7.0 All 76 releases
depicter / modules / GuzzleHttp / Psr7 / CachingStream.php

CachingStream.php in Depicter — Popup & Slider Builder 1.3.2, at modules/GuzzleHttp/Psr7/CachingStream.php

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