Open Monograph Press  3.3.0
BufferedStream.php
1 <?php
2 
4 
6 
16 {
18  private $resource;
19 
21  private $size;
22 
24  private $stream;
25 
27  private $written = 0;
28 
36  public function __construct(StreamInterface $stream, $useFileBuffer = true, $memoryBuffer = 2097152)
37  {
38  $this->stream = $stream;
39  $this->size = $stream->getSize();
40 
41  if ($useFileBuffer) {
42  $this->resource = fopen('php://temp/maxmemory:'.$memoryBuffer, 'rw+');
43  } else {
44  $this->resource = fopen('php://memory', 'rw+');
45  }
46 
47  if (false === $this->resource) {
48  throw new \RuntimeException('Cannot create a resource over temp or memory implementation');
49  }
50  }
51 
55  public function __toString()
56  {
57  try {
58  $this->rewind();
59 
60  return $this->getContents();
61  } catch (\Throwable $throwable) {
62  return '';
63  } catch (\Exception $exception) { // Layer to be BC with PHP 5, remove this when we only support PHP 7+
64  return '';
65  }
66  }
67 
71  public function close()
72  {
73  if (null === $this->resource) {
74  throw new \RuntimeException('Cannot close on a detached stream');
75  }
76 
77  $this->stream->close();
78  fclose($this->resource);
79  }
80 
84  public function detach()
85  {
86  if (null === $this->resource) {
87  return;
88  }
89 
90  // Force reading the remaining data of the stream
91  $this->getContents();
92 
93  $resource = $this->resource;
94  $this->stream->close();
95  $this->stream = null;
96  $this->resource = null;
97 
98  return $resource;
99  }
100 
104  public function getSize()
105  {
106  if (null === $this->resource) {
107  return;
108  }
109 
110  if (null === $this->size && $this->stream->eof()) {
111  return $this->written;
112  }
113 
114  return $this->size;
115  }
116 
120  public function tell()
121  {
122  if (null === $this->resource) {
123  throw new \RuntimeException('Cannot tell on a detached stream');
124  }
125 
126  return ftell($this->resource);
127  }
128 
132  public function eof()
133  {
134  if (null === $this->resource) {
135  throw new \RuntimeException('Cannot call eof on a detached stream');
136  }
137 
138  // We are at the end only when both our resource and underlying stream are at eof
139  return $this->stream->eof() && (ftell($this->resource) === $this->written);
140  }
141 
145  public function isSeekable()
146  {
147  return null !== $this->resource;
148  }
149 
153  public function seek($offset, $whence = SEEK_SET)
154  {
155  if (null === $this->resource) {
156  throw new \RuntimeException('Cannot seek on a detached stream');
157  }
158 
159  fseek($this->resource, $offset, $whence);
160  }
161 
165  public function rewind()
166  {
167  if (null === $this->resource) {
168  throw new \RuntimeException('Cannot rewind on a detached stream');
169  }
170 
171  rewind($this->resource);
172  }
173 
177  public function isWritable()
178  {
179  return false;
180  }
181 
185  public function write($string)
186  {
187  throw new \RuntimeException('Cannot write on this stream');
188  }
189 
193  public function isReadable()
194  {
195  return null !== $this->resource;
196  }
197 
201  public function read($length)
202  {
203  if (null === $this->resource) {
204  throw new \RuntimeException('Cannot read on a detached stream');
205  }
206 
207  $read = '';
208 
209  // First read from the resource
210  if (ftell($this->resource) !== $this->written) {
211  $read = fread($this->resource, $length);
212  }
213 
214  $bytesRead = strlen($read);
215 
216  if ($bytesRead < $length) {
217  $streamRead = $this->stream->read($length - $bytesRead);
218 
219  // Write on the underlying stream what we read
220  $this->written += fwrite($this->resource, $streamRead);
221  $read .= $streamRead;
222  }
223 
224  return $read;
225  }
226 
230  public function getContents()
231  {
232  if (null === $this->resource) {
233  throw new \RuntimeException('Cannot read on a detached stream');
234  }
235 
236  $read = '';
237 
238  while (!$this->eof()) {
239  $read .= $this->read(8192);
240  }
241 
242  return $read;
243  }
244 
248  public function getMetadata($key = null)
249  {
250  if (null === $this->resource) {
251  if (null === $key) {
252  return [];
253  }
254 
255  return;
256  }
257 
258  $metadata = stream_get_meta_data($this->resource);
259 
260  if (null === $key) {
261  return $metadata;
262  }
263 
264  if (!array_key_exists($key, $metadata)) {
265  return;
266  }
267 
268  return $metadata[$key];
269  }
270 }
Http\Message\Stream\BufferedStream
Definition: BufferedStream.php:15
Http\Message\Stream\BufferedStream\seek
seek($offset, $whence=SEEK_SET)
Definition: BufferedStream.php:165
Psr\Http\Message\StreamInterface
Definition: vendor/psr/http-message/src/StreamInterface.php:12
Http\Message\Stream\BufferedStream\getMetadata
getMetadata($key=null)
Definition: BufferedStream.php:260
Http\Message\Stream\BufferedStream\eof
eof()
Definition: BufferedStream.php:144
Http\Message\Stream\BufferedStream\__toString
__toString()
Definition: BufferedStream.php:67
Http\Message\Stream\BufferedStream\rewind
rewind()
Definition: BufferedStream.php:177
Http\Message\Stream\BufferedStream\isSeekable
isSeekable()
Definition: BufferedStream.php:157
Http\Message\Stream\BufferedStream\isReadable
isReadable()
Definition: BufferedStream.php:205
Http\Message\Stream\BufferedStream\__construct
__construct(StreamInterface $stream, $useFileBuffer=true, $memoryBuffer=2097152)
Definition: BufferedStream.php:48
Http\Message\Stream\BufferedStream\read
read($length)
Definition: BufferedStream.php:213
Http\Message\Stream\BufferedStream\getSize
getSize()
Definition: BufferedStream.php:116
Http\Message\Stream\BufferedStream\isWritable
isWritable()
Definition: BufferedStream.php:189
Http\Message\Stream\BufferedStream\getContents
getContents()
Definition: BufferedStream.php:242
Http\Message\Stream\BufferedStream\tell
tell()
Definition: BufferedStream.php:132
Http\Message\Stream\BufferedStream\write
write($string)
Definition: BufferedStream.php:197
Http\Message\Stream\BufferedStream\detach
detach()
Definition: BufferedStream.php:96
Http\Message\Stream\BufferedStream\close
close()
Definition: BufferedStream.php:83
Http\Message\Stream
Definition: BufferedStream.php:3
Http\Message\Exception
Definition: php-http/message/src/Exception.php:8