Current File : /var/www/prestashop/modules/ps_metrics/vendor/php-http/message/src/Stream/BufferedStream.php |
<?php
namespace ps_metrics_module_v4_0_6\Http\Message\Stream;
use Psr\Http\Message\StreamInterface;
/**
* Decorator to make any stream seekable.
*
* Internally it buffers an existing StreamInterface into a php://temp resource (or memory). By default it will use
* 2 megabytes of memory before writing to a temporary disk file.
*
* Due to this, very large stream can suffer performance issue (i/o slowdown).
*/
class BufferedStream implements StreamInterface
{
/** @var resource The buffered resource used to seek previous data */
private $resource;
/** @var int|null size of the stream if available */
private $size;
/** @var StreamInterface The underlying stream decorated by this class */
private $stream;
/** @var int How many bytes were written */
private $written = 0;
/**
* @param StreamInterface $stream Decorated stream
* @param bool $useFileBuffer Whether to use a file buffer (write to a file, if data exceed a certain size)
* by default, set this to false to only use memory
* @param int $memoryBuffer In conjunction with using file buffer, limit (in bytes) from which it begins to buffer
* the data in a file
*/
public function __construct(StreamInterface $stream, $useFileBuffer = \true, $memoryBuffer = 2097152)
{
$this->stream = $stream;
$this->size = $stream->getSize();
if ($useFileBuffer) {
$this->resource = \fopen('php://temp/maxmemory:' . $memoryBuffer, 'rw+');
} else {
$this->resource = \fopen('php://memory', 'rw+');
}
if (\false === $this->resource) {
throw new \RuntimeException('Cannot create a resource over temp or memory implementation');
}
}
public function __toString() : string
{
try {
$this->rewind();
return $this->getContents();
} catch (\Throwable $throwable) {
return '';
}
}
public function close() : void
{
if (null === $this->resource) {
throw new \RuntimeException('Cannot close on a detached stream');
}
$this->stream->close();
\fclose($this->resource);
}
public function detach()
{
if (null === $this->resource) {
return null;
}
// Force reading the remaining data of the stream
$this->getContents();
$resource = $this->resource;
$this->stream->close();
$this->stream = null;
$this->resource = null;
return $resource;
}
public function getSize() : ?int
{
if (null === $this->resource) {
return null;
}
if (null === $this->size && $this->stream->eof()) {
return $this->written;
}
return $this->size;
}
public function tell() : int
{
if (null === $this->resource) {
throw new \RuntimeException('Cannot tell on a detached stream');
}
$tell = \ftell($this->resource);
if (\false === $tell) {
throw new \RuntimeException('ftell failed');
}
return $tell;
}
public function eof() : bool
{
if (null === $this->resource) {
throw new \RuntimeException('Cannot call eof on a detached stream');
}
// We are at the end only when both our resource and underlying stream are at eof
return $this->stream->eof() && \ftell($this->resource) === $this->written;
}
public function isSeekable() : bool
{
return null !== $this->resource;
}
public function seek(int $offset, int $whence = \SEEK_SET) : void
{
if (null === $this->resource) {
throw new \RuntimeException('Cannot seek on a detached stream');
}
\fseek($this->resource, $offset, $whence);
}
public function rewind() : void
{
if (null === $this->resource) {
throw new \RuntimeException('Cannot rewind on a detached stream');
}
\rewind($this->resource);
}
public function isWritable() : bool
{
return \false;
}
public function write(string $string) : int
{
throw new \RuntimeException('Cannot write on this stream');
}
public function isReadable() : bool
{
return null !== $this->resource;
}
public function read(int $length) : string
{
if (null === $this->resource) {
throw new \RuntimeException('Cannot read on a detached stream');
}
if ($length < 0) {
throw new \InvalidArgumentException('Can not read a negative amount of bytes');
}
$read = '';
// First read from the resource
if (\ftell($this->resource) !== $this->written) {
$read = \fread($this->resource, $length);
}
if (\false === $read) {
throw new \RuntimeException('Failed to read from resource');
}
$bytesRead = \strlen($read);
if ($bytesRead < $length) {
$streamRead = $this->stream->read($length - $bytesRead);
// Write on the underlying stream what we read
$this->written += \fwrite($this->resource, $streamRead);
$read .= $streamRead;
}
return $read;
}
public function getContents() : string
{
if (null === $this->resource) {
throw new \RuntimeException('Cannot read on a detached stream');
}
$read = '';
while (!$this->eof()) {
$read .= $this->read(8192);
}
return $read;
}
public function getMetadata(?string $key = null)
{
if (null === $this->resource) {
if (null === $key) {
return [];
}
return null;
}
$metadata = \stream_get_meta_data($this->resource);
if (null === $key) {
return $metadata;
}
if (!\array_key_exists($key, $metadata)) {
return null;
}
return $metadata[$key];
}
}