/vendor/guzzlehttp/streams/src/AppendStream.php |
@@ -0,0 +1,211 @@ |
<?php |
namespace GuzzleHttp\Stream; |
|
/** |
* Reads from multiple streams, one after the other. |
* |
* This is a read-only stream decorator. |
*/ |
class AppendStream implements StreamInterface |
{ |
/** @var StreamInterface[] Streams being decorated */ |
private $streams = []; |
|
private $seekable = true; |
private $current = 0; |
private $pos = 0; |
|
/** |
* @param StreamInterface[] $streams Streams to decorate. Each stream must |
* be readable. |
*/ |
public function __construct(array $streams = []) |
{ |
foreach ($streams as $stream) { |
$this->addStream($stream); |
} |
} |
|
public function __toString() |
{ |
try { |
$this->seek(0); |
return $this->getContents(); |
} catch (\Exception $e) { |
return ''; |
} |
} |
|
/** |
* Add a stream to the AppendStream |
* |
* @param StreamInterface $stream Stream to append. Must be readable. |
* |
* @throws \InvalidArgumentException if the stream is not readable |
*/ |
public function addStream(StreamInterface $stream) |
{ |
if (!$stream->isReadable()) { |
throw new \InvalidArgumentException('Each stream must be readable'); |
} |
|
// The stream is only seekable if all streams are seekable |
if (!$stream->isSeekable()) { |
$this->seekable = false; |
} |
|
$this->streams[] = $stream; |
} |
|
public function getContents($maxLength = -1) |
{ |
return Utils::copyToString($this, $maxLength); |
} |
|
/** |
* Closes each attached stream. |
* |
* {@inheritdoc} |
*/ |
public function close() |
{ |
$this->pos = $this->current = 0; |
|
foreach ($this->streams as $stream) { |
$stream->close(); |
} |
|
$this->streams = []; |
} |
|
/** |
* Detaches each attached stream |
* |
* {@inheritdoc} |
*/ |
public function detach() |
{ |
$this->close(); |
} |
|
public function tell() |
{ |
return $this->pos; |
} |
|
/** |
* Tries to calculate the size by adding the size of each stream. |
* |
* If any of the streams do not return a valid number, then the size of the |
* append stream cannot be determined and null is returned. |
* |
* {@inheritdoc} |
*/ |
public function getSize() |
{ |
$size = 0; |
|
foreach ($this->streams as $stream) { |
$s = $stream->getSize(); |
if ($s === null) { |
return null; |
} |
$size += $s; |
} |
|
return $size; |
} |
|
public function eof() |
{ |
return !$this->streams || |
($this->current >= count($this->streams) - 1 && |
$this->streams[$this->current]->eof()); |
} |
|
/** |
* Attempts to seek to the given position. Only supports SEEK_SET. |
* |
* {@inheritdoc} |
*/ |
public function seek($offset, $whence = SEEK_SET) |
{ |
if (!$this->seekable || $whence !== SEEK_SET) { |
return false; |
} |
|
$success = true; |
$this->pos = $this->current = 0; |
|
// Rewind each stream |
foreach ($this->streams as $stream) { |
if (!$stream->seek(0)) { |
$success = false; |
} |
} |
|
if (!$success) { |
return false; |
} |
|
// Seek to the actual position by reading from each stream |
while ($this->pos < $offset && !$this->eof()) { |
$this->read(min(8096, $offset - $this->pos)); |
} |
|
return $this->pos == $offset; |
} |
|
/** |
* Reads from all of the appended streams until the length is met or EOF. |
* |
* {@inheritdoc} |
*/ |
public function read($length) |
{ |
$buffer = ''; |
$total = count($this->streams) - 1; |
$remaining = $length; |
|
while ($remaining > 0) { |
// Progress to the next stream if needed. |
if ($this->streams[$this->current]->eof()) { |
if ($this->current == $total) { |
break; |
} |
$this->current++; |
} |
$buffer .= $this->streams[$this->current]->read($remaining); |
$remaining = $length - strlen($buffer); |
} |
|
$this->pos += strlen($buffer); |
|
return $buffer; |
} |
|
public function isReadable() |
{ |
return true; |
} |
|
public function isWritable() |
{ |
return false; |
} |
|
public function isSeekable() |
{ |
return $this->seekable; |
} |
|
public function write($string) |
{ |
return false; |
} |
|
public function flush() |
{ |
return false; |
} |
} |
/vendor/guzzlehttp/streams/src/CachingStream.php |
@@ -0,0 +1,121 @@ |
<?php |
namespace GuzzleHttp\Stream; |
use GuzzleHttp\Stream\Exception\SeekException; |
|
/** |
* Stream decorator that can cache previously read bytes from a sequentially |
* read stream. |
*/ |
class CachingStream implements StreamInterface, MetadataStreamInterface |
{ |
use StreamDecoratorTrait; |
|
/** @var StreamInterface Stream being wrapped */ |
private $remoteStream; |
|
/** @var int Number of bytes to skip reading due to a write on the buffer */ |
private $skipReadBytes = 0; |
|
/** |
* We will treat the buffer object as the body of the stream |
* |
* @param StreamInterface $stream Stream to cache |
* @param StreamInterface $target Optionally specify where data is cached |
*/ |
public function __construct( |
StreamInterface $stream, |
StreamInterface $target = null |
) { |
$this->remoteStream = $stream; |
$this->stream = $target ?: new Stream(fopen('php://temp', 'r+')); |
} |
|
public function getSize() |
{ |
return max($this->stream->getSize(), $this->remoteStream->getSize()); |
} |
|
/** |
* {@inheritdoc} |
* @throws SeekException When seeking with SEEK_END or when seeking |
* past the total size of the buffer stream |
*/ |
public function seek($offset, $whence = SEEK_SET) |
{ |
if ($whence == SEEK_SET) { |
$byte = $offset; |
} elseif ($whence == SEEK_CUR) { |
$byte = $offset + $this->tell(); |
} else { |
return false; |
} |
|
// You cannot skip ahead past where you've read from the remote stream |
if ($byte > $this->stream->getSize()) { |
throw new SeekException( |
$this, |
$byte, |
sprintf('Cannot seek to byte %d when the buffered stream only' |
. ' contains %d bytes', $byte, $this->stream->getSize()) |
); |
} |
|
return $this->stream->seek($byte); |
} |
|
public function read($length) |
{ |
// Perform a regular read on any previously read data from the buffer |
$data = $this->stream->read($length); |
$remaining = $length - strlen($data); |
|
// More data was requested so read from the remote stream |
if ($remaining) { |
// If data was written to the buffer in a position that would have |
// been filled from the remote stream, then we must skip bytes on |
// the remote stream to emulate overwriting bytes from that |
// position. This mimics the behavior of other PHP stream wrappers. |
$remoteData = $this->remoteStream->read( |
$remaining + $this->skipReadBytes |
); |
|
if ($this->skipReadBytes) { |
$len = strlen($remoteData); |
$remoteData = substr($remoteData, $this->skipReadBytes); |
$this->skipReadBytes = max(0, $this->skipReadBytes - $len); |
} |
|
$data .= $remoteData; |
$this->stream->write($remoteData); |
} |
|
return $data; |
} |
|
public function write($string) |
{ |
// When appending to the end of the currently read stream, you'll want |
// to skip bytes from being read from the remote stream to emulate |
// other stream wrappers. Basically replacing bytes of data of a fixed |
// length. |
$overflow = (strlen($string) + $this->tell()) - $this->remoteStream->tell(); |
if ($overflow > 0) { |
$this->skipReadBytes += $overflow; |
} |
|
return $this->stream->write($string); |
} |
|
public function eof() |
{ |
return $this->stream->eof() && $this->remoteStream->eof(); |
} |
|
/** |
* Close both the remote stream and buffer stream |
*/ |
public function close() |
{ |
$this->remoteStream->close() && $this->stream->close(); |
} |
} |
/vendor/guzzlehttp/streams/src/FnStream.php |
@@ -0,0 +1,147 @@ |
<?php |
namespace GuzzleHttp\Stream; |
|
/** |
* Compose stream implementations based on a hash of functions. |
* |
* Allows for easy testing and extension of a provided stream without needing |
* to create a concrete class for a simple extension point. |
*/ |
class FnStream implements MetadataStreamInterface |
{ |
/** @var array */ |
private $methods; |
|
/** @var array Methods that must be implemented in the given array */ |
private static $slots = ['__toString', 'close', 'detach', 'getSize', |
'tell', 'eof', 'isSeekable', 'seek', 'isWritable', 'write', 'flush', |
'isReadable', 'read', 'getContents', 'getMetadata']; |
|
/** |
* @param array $methods Hash of method name to a callable. |
*/ |
public function __construct(array $methods) |
{ |
$this->methods = $methods; |
|
// Create the functions on the class |
foreach ($methods as $name => $fn) { |
$this->{'_fn_' . $name} = $fn; |
} |
} |
|
/** |
* Lazily determine which methods are not implemented. |
* @throws \BadMethodCallException |
*/ |
public function __get($name) |
{ |
throw new \BadMethodCallException(str_replace('_fn_', '', $name) |
. '() is not implemented in the FnStream'); |
} |
|
/** |
* The close method is called on the underlying stream only if possible. |
*/ |
public function __destruct() |
{ |
if (isset($this->_fn_close)) { |
call_user_func($this->_fn_close); |
} |
} |
|
/** |
* Adds custom functionality to an underlying stream by intercepting |
* specific method calls. |
* |
* @param StreamInterface $stream Stream to decorate |
* @param array $methods Hash of method name to a closure |
* |
* @return FnStream |
*/ |
public static function decorate(StreamInterface $stream, array $methods) |
{ |
// If any of the required methods were not provided, then simply |
// proxy to the decorated stream. |
foreach (array_diff(self::$slots, array_keys($methods)) as $diff) { |
$methods[$diff] = [$stream, $diff]; |
} |
|
return new self($methods); |
} |
|
public function __toString() |
{ |
return call_user_func($this->_fn___toString); |
} |
|
public function close() |
{ |
return call_user_func($this->_fn_close); |
} |
|
public function detach() |
{ |
return call_user_func($this->_fn_detach); |
} |
|
public function getSize() |
{ |
return call_user_func($this->_fn_getSize); |
} |
|
public function tell() |
{ |
return call_user_func($this->_fn_tell); |
} |
|
public function eof() |
{ |
return call_user_func($this->_fn_eof); |
} |
|
public function isSeekable() |
{ |
return call_user_func($this->_fn_isSeekable); |
} |
|
public function seek($offset, $whence = SEEK_SET) |
{ |
return call_user_func($this->_fn_seek, $offset, $whence); |
} |
|
public function isWritable() |
{ |
return call_user_func($this->_fn_isWritable); |
} |
|
public function write($string) |
{ |
return call_user_func($this->_fn_write, $string); |
} |
|
public function flush() |
{ |
return call_user_func($this->_fn_flush); |
} |
|
public function isReadable() |
{ |
return call_user_func($this->_fn_isReadable); |
} |
|
public function read($length) |
{ |
return call_user_func($this->_fn_read, $length); |
} |
|
public function getContents($maxLength = -1) |
{ |
return call_user_func($this->_fn_getContents, $maxLength); |
} |
|
public function getMetadata($key = null) |
{ |
return call_user_func($this->_fn_getMetadata, $key); |
} |
} |
/vendor/guzzlehttp/streams/src/GuzzleStreamWrapper.php |
@@ -0,0 +1,122 @@ |
<?php |
namespace GuzzleHttp\Stream; |
|
/** |
* Converts Guzzle streams into PHP stream resources. |
*/ |
class GuzzleStreamWrapper |
{ |
/** @var resource */ |
public $context; |
|
/** @var StreamInterface */ |
private $stream; |
|
/** @var string r, r+, or w */ |
private $mode; |
|
/** |
* Returns a resource representing the stream. |
* |
* @param StreamInterface $stream The stream to get a resource for |
* |
* @return resource |
* @throws \InvalidArgumentException if stream is not readable or writable |
*/ |
public static function getResource(StreamInterface $stream) |
{ |
self::register(); |
|
if ($stream->isReadable()) { |
$mode = $stream->isWritable() ? 'r+' : 'r'; |
} elseif ($stream->isWritable()) { |
$mode = 'w'; |
} else { |
throw new \InvalidArgumentException('The stream must be readable, ' |
. 'writable, or both.'); |
} |
|
return fopen('guzzle://stream', $mode, null, stream_context_create([ |
'guzzle' => ['stream' => $stream] |
])); |
} |
|
/** |
* Registers the stream wrapper if needed |
*/ |
public static function register() |
{ |
if (!in_array('guzzle', stream_get_wrappers())) { |
stream_wrapper_register('guzzle', __CLASS__); |
} |
} |
|
public function stream_open($path, $mode, $options, &$opened_path) |
{ |
$options = stream_context_get_options($this->context); |
|
if (!isset($options['guzzle']['stream'])) { |
return false; |
} |
|
$this->mode = $mode; |
$this->stream = $options['guzzle']['stream']; |
|
return true; |
} |
|
public function stream_read($count) |
{ |
return $this->stream->read($count); |
} |
|
public function stream_write($data) |
{ |
return (int) $this->stream->write($data); |
} |
|
public function stream_tell() |
{ |
return $this->stream->tell(); |
} |
|
public function stream_eof() |
{ |
return $this->stream->eof(); |
} |
|
public function stream_flush() |
{ |
return $this->stream->flush(); |
} |
|
public function stream_seek($offset, $whence) |
{ |
return $this->stream->seek($offset, $whence); |
} |
|
public function stream_stat() |
{ |
static $modeMap = [ |
'r' => 33060, |
'r+' => 33206, |
'w' => 33188 |
]; |
|
return [ |
'dev' => 0, |
'ino' => 0, |
'mode' => $modeMap[$this->mode], |
'nlink' => 0, |
'uid' => 0, |
'gid' => 0, |
'rdev' => 0, |
'size' => $this->stream->getSize() ?: 0, |
'atime' => 0, |
'mtime' => 0, |
'ctime' => 0, |
'blksize' => 0, |
'blocks' => 0 |
]; |
} |
} |
/vendor/guzzlehttp/streams/src/LimitStream.php |
@@ -0,0 +1,153 @@ |
<?php |
namespace GuzzleHttp\Stream; |
use GuzzleHttp\Stream\Exception\SeekException; |
|
/** |
* Decorator used to return only a subset of a stream |
*/ |
class LimitStream implements StreamInterface, MetadataStreamInterface |
{ |
use StreamDecoratorTrait; |
|
/** @var int Offset to start reading from */ |
private $offset; |
|
/** @var int Limit the number of bytes that can be read */ |
private $limit; |
|
/** |
* @param StreamInterface $stream Stream to wrap |
* @param int $limit Total number of bytes to allow to be read |
* from the stream. Pass -1 for no limit. |
* @param int|null $offset Position to seek to before reading (only |
* works on seekable streams). |
*/ |
public function __construct( |
StreamInterface $stream, |
$limit = -1, |
$offset = 0 |
) { |
$this->stream = $stream; |
$this->setLimit($limit); |
$this->setOffset($offset); |
} |
|
public function eof() |
{ |
if ($this->limit == -1) { |
return $this->stream->eof(); |
} |
|
$tell = $this->stream->tell(); |
|
return $tell === false || |
($tell >= $this->offset + $this->limit) || |
$this->stream->eof(); |
} |
|
/** |
* Returns the size of the limited subset of data |
* {@inheritdoc} |
*/ |
public function getSize() |
{ |
if (null === ($length = $this->stream->getSize())) { |
return null; |
} elseif ($this->limit == -1) { |
return $length - $this->offset; |
} else { |
return min($this->limit, $length - $this->offset); |
} |
} |
|
/** |
* Allow for a bounded seek on the read limited stream |
* {@inheritdoc} |
*/ |
public function seek($offset, $whence = SEEK_SET) |
{ |
if ($whence != SEEK_SET) { |
return false; |
} |
|
if ($offset < $this->offset) { |
$offset = $this->offset; |
} |
|
if ($this->limit !== -1 && $offset > ($this->offset + $this->limit)) { |
$offset = $this->offset + $this->limit; |
} |
|
return $this->stream->seek($offset); |
} |
|
/** |
* Give a relative tell() |
* {@inheritdoc} |
*/ |
public function tell() |
{ |
return $this->stream->tell() - $this->offset; |
} |
|
/** |
* Set the offset to start limiting from |
* |
* @param int $offset Offset to seek to and begin byte limiting from |
* |
* @return self |
* @throws SeekException |
*/ |
public function setOffset($offset) |
{ |
$current = $this->stream->tell(); |
|
if ($current !== $offset) { |
// If the stream cannot seek to the offset position, then read to it |
if (!$this->stream->seek($offset)) { |
if ($current > $offset) { |
throw new SeekException($this, $offset); |
} else { |
$this->stream->read($offset - $current); |
} |
} |
} |
|
$this->offset = $offset; |
|
return $this; |
} |
|
/** |
* Set the limit of bytes that the decorator allows to be read from the |
* stream. |
* |
* @param int $limit Number of bytes to allow to be read from the stream. |
* Use -1 for no limit. |
* @return self |
*/ |
public function setLimit($limit) |
{ |
$this->limit = $limit; |
|
return $this; |
} |
|
public function read($length) |
{ |
if ($this->limit == -1) { |
return $this->stream->read($length); |
} |
|
// Check if the current position is less than the total allowed |
// bytes + original offset |
$remaining = ($this->offset + $this->limit) - $this->stream->tell(); |
if ($remaining > 0) { |
// Only return the amount of requested data, ensuring that the byte |
// limit is not exceeded |
return $this->stream->read(min($remaining, $length)); |
} else { |
return false; |
} |
} |
} |
/vendor/guzzlehttp/streams/src/Stream.php |
@@ -0,0 +1,236 @@ |
<?php |
namespace GuzzleHttp\Stream; |
|
/** |
* PHP stream implementation |
*/ |
class Stream implements MetadataStreamInterface |
{ |
private $stream; |
private $size; |
private $seekable; |
private $readable; |
private $writable; |
private $uri; |
|
/** @var array Hash of readable and writable stream types */ |
private static $readWriteHash = [ |
'read' => [ |
'r' => true, 'w+' => true, 'r+' => true, 'x+' => true, 'c+' => true, |
'rb' => true, 'w+b' => true, 'r+b' => true, 'x+b' => true, |
'c+b' => true, 'rt' => true, 'w+t' => true, 'r+t' => true, |
'x+t' => true, 'c+t' => true, 'a+' => true |
], |
'write' => [ |
'w' => true, 'w+' => true, 'rw' => true, 'r+' => true, 'x+' => true, |
'c+' => true, 'wb' => true, 'w+b' => true, 'r+b' => true, |
'x+b' => true, 'c+b' => true, 'w+t' => true, 'r+t' => true, |
'x+t' => true, 'c+t' => true, 'a' => true, 'a+' => true |
] |
]; |
|
/** |
* Create a new stream based on the input type |
* |
* @param resource|string|StreamInterface $resource Entity body data |
* @param int $size Size of the data contained in the resource |
* |
* @return Stream |
* @throws \InvalidArgumentException if the $resource arg is not valid. |
*/ |
public static function factory($resource = '', $size = null) |
{ |
$type = gettype($resource); |
|
if ($type == 'string') { |
$stream = fopen('php://temp', 'r+'); |
if ($resource !== '') { |
fwrite($stream, $resource); |
fseek($stream, 0); |
} |
return new self($stream); |
} |
|
if ($type == 'resource') { |
return new self($resource, $size); |
} |
|
if ($resource instanceof StreamInterface) { |
return $resource; |
} |
|
if ($type == 'object' && method_exists($resource, '__toString')) { |
return self::factory((string) $resource, $size); |
} |
|
throw new \InvalidArgumentException('Invalid resource type: ' . $type); |
} |
|
/** |
* @param resource $stream Stream resource to wrap |
* @param int $size Size of the stream in bytes. Only pass if the |
* size cannot be obtained from the stream. |
* |
* @throws \InvalidArgumentException if the stream is not a stream resource |
*/ |
public function __construct($stream, $size = null) |
{ |
if (!is_resource($stream)) { |
throw new \InvalidArgumentException('Stream must be a resource'); |
} |
|
$this->size = $size; |
$this->stream = $stream; |
$meta = stream_get_meta_data($this->stream); |
$this->seekable = $meta['seekable']; |
$this->readable = isset(self::$readWriteHash['read'][$meta['mode']]); |
$this->writable = isset(self::$readWriteHash['write'][$meta['mode']]); |
$this->uri = isset($meta['uri']) ? $meta['uri'] : null; |
} |
|
/** |
* Closes the stream when the destructed |
*/ |
public function __destruct() |
{ |
$this->close(); |
} |
|
public function __toString() |
{ |
if (!$this->stream) { |
return ''; |
} |
|
$this->seek(0); |
|
return (string) stream_get_contents($this->stream); |
} |
|
public function getContents($maxLength = -1) |
{ |
return $this->stream |
? stream_get_contents($this->stream, $maxLength) |
: ''; |
} |
|
public function close() |
{ |
if (is_resource($this->stream)) { |
fclose($this->stream); |
} |
|
$this->detach(); |
} |
|
public function detach() |
{ |
$result = $this->stream; |
$this->stream = $this->size = $this->uri = null; |
$this->readable = $this->writable = $this->seekable = false; |
|
return $result; |
} |
|
public function getSize() |
{ |
if ($this->size !== null) { |
return $this->size; |
} |
|
if (!$this->stream) { |
return null; |
} |
|
// Clear the stat cache if the stream has a URI |
if ($this->uri) { |
clearstatcache(true, $this->uri); |
} |
|
$stats = fstat($this->stream); |
if (isset($stats['size'])) { |
$this->size = $stats['size']; |
return $this->size; |
} |
|
return null; |
} |
|
public function isReadable() |
{ |
return $this->readable; |
} |
|
public function isWritable() |
{ |
return $this->writable; |
} |
|
public function isSeekable() |
{ |
return $this->seekable; |
} |
|
public function eof() |
{ |
return $this->stream && feof($this->stream); |
} |
|
public function tell() |
{ |
return $this->stream ? ftell($this->stream) : false; |
} |
|
public function setSize($size) |
{ |
$this->size = $size; |
|
return $this; |
} |
|
public function seek($offset, $whence = SEEK_SET) |
{ |
return $this->seekable |
? fseek($this->stream, $offset, $whence) === 0 |
: false; |
} |
|
public function read($length) |
{ |
return $this->readable ? fread($this->stream, $length) : ''; |
} |
|
public function write($string) |
{ |
// We can't know the size after writing anything |
$this->size = null; |
|
return $this->writable ? fwrite($this->stream, $string) : false; |
} |
|
public function flush() |
{ |
return $this->stream ? fflush($this->stream) : false; |
} |
|
/** |
* Get stream metadata as an associative array or retrieve a specific key. |
* |
* The keys returned are identical to the keys returned from PHP's |
* stream_get_meta_data() function. |
* |
* @param string $key Specific metadata to retrieve. |
* |
* @return array|mixed|null Returns an associative array if no key is |
* no key is provided. Returns a specific key |
* value if a key is provided and the value is |
* found, or null if the key is not found. |
* @see http://php.net/manual/en/function.stream-get-meta-data.php |
*/ |
public function getMetadata($key = null) |
{ |
$meta = $this->stream ? stream_get_meta_data($this->stream) : []; |
|
return !$key ? $meta : (isset($meta[$key]) ? $meta[$key] : null); |
} |
} |
/vendor/guzzlehttp/streams/src/StreamDecoratorTrait.php |
@@ -0,0 +1,144 @@ |
<?php |
namespace GuzzleHttp\Stream; |
|
/** |
* Stream decorator trait |
* @property StreamInterface stream |
*/ |
trait StreamDecoratorTrait |
{ |
/** |
* @param StreamInterface $stream Stream to decorate |
*/ |
public function __construct(StreamInterface $stream) |
{ |
$this->stream = $stream; |
} |
|
/** |
* Magic method used to create a new stream if streams are not added in |
* the constructor of a decorator (e.g., LazyOpenStream). |
*/ |
public function __get($name) |
{ |
if ($name == 'stream') { |
$this->stream = $this->createStream(); |
return $this->stream; |
} |
|
throw new \UnexpectedValueException("$name not found on class"); |
} |
|
public function __toString() |
{ |
try { |
$this->seek(0); |
return $this->getContents(); |
} catch (\Exception $e) { |
// Really, PHP? https://bugs.php.net/bug.php?id=53648 |
trigger_error('StreamDecorator::__toString exception: ' |
. (string) $e, E_USER_ERROR); |
return ''; |
} |
} |
|
public function getContents($maxLength = -1) |
{ |
return Utils::copyToString($this, $maxLength); |
} |
|
/** |
* Allow decorators to implement custom methods |
* |
* @param string $method Missing method name |
* @param array $args Method arguments |
* |
* @return mixed |
*/ |
public function __call($method, array $args) |
{ |
$result = call_user_func_array(array($this->stream, $method), $args); |
|
// Always return the wrapped object if the result is a return $this |
return $result === $this->stream ? $this : $result; |
} |
|
public function close() |
{ |
$this->stream->close(); |
} |
|
public function getMetadata($key = null) |
{ |
return $this->stream instanceof MetadataStreamInterface |
? $this->stream->getMetadata($key) |
: null; |
} |
|
public function detach() |
{ |
return $this->stream->detach(); |
} |
|
public function getSize() |
{ |
return $this->stream->getSize(); |
} |
|
public function eof() |
{ |
return $this->stream->eof(); |
} |
|
public function tell() |
{ |
return $this->stream->tell(); |
} |
|
public function isReadable() |
{ |
return $this->stream->isReadable(); |
} |
|
public function isWritable() |
{ |
return $this->stream->isWritable(); |
} |
|
public function isSeekable() |
{ |
return $this->stream->isSeekable(); |
} |
|
public function seek($offset, $whence = SEEK_SET) |
{ |
return $this->stream->seek($offset, $whence); |
} |
|
public function read($length) |
{ |
return $this->stream->read($length); |
} |
|
public function write($string) |
{ |
return $this->stream->write($string); |
} |
|
public function flush() |
{ |
return $this->stream->flush(); |
} |
|
/** |
* Implement in subclasses to dynamically create streams when requested. |
* |
* @return StreamInterface |
* @throws \BadMethodCallException |
*/ |
protected function createStream() |
{ |
throw new \BadMethodCallException('createStream() not implemented in ' |
. get_class($this)); |
} |
} |
/vendor/guzzlehttp/streams/src/StreamInterface.php |
@@ -0,0 +1,132 @@ |
<?php |
namespace GuzzleHttp\Stream; |
|
/** |
* Describes a stream instance. |
*/ |
interface StreamInterface |
{ |
/** |
* Attempts to seek to the beginning of the stream and reads all data into |
* a string until the end of the stream is reached. |
* |
* Warning: This could attempt to load a large amount of data into memory. |
* |
* @return string |
*/ |
public function __toString(); |
|
/** |
* Closes the stream and any underlying resources. |
*/ |
public function close(); |
|
/** |
* Separates any underlying resources from the stream. |
* |
* After the underlying resource has been detached, the stream object is in |
* an unusable state. If you wish to use a Stream object as a PHP stream |
* but keep the Stream object in a consistent state, use |
* {@see GuzzleHttp\Stream\GuzzleStreamWrapper::getResource}. |
* |
* @return resource|null Returns the underlying PHP stream resource or null |
* if the Stream object did not utilize an underlying |
* stream resource. |
*/ |
public function detach(); |
|
/** |
* Get the size of the stream if known |
* |
* @return int|null Returns the size in bytes if known, or null if unknown |
*/ |
public function getSize(); |
|
/** |
* Returns the current position of the file read/write pointer |
* |
* @return int|bool Returns the position of the file pointer or false on error |
*/ |
public function tell(); |
|
/** |
* Returns true if the stream is at the end of the stream. |
* |
* @return bool |
*/ |
public function eof(); |
|
/** |
* Returns whether or not the stream is seekable |
* |
* @return bool |
*/ |
public function isSeekable(); |
|
/** |
* Seek to a position in the stream |
* |
* @param int $offset Stream offset |
* @param int $whence Specifies how the cursor position will be calculated |
* based on the seek offset. Valid values are identical |
* to the built-in PHP $whence values for `fseek()`. |
* SEEK_SET: Set position equal to offset bytes |
* SEEK_CUR: Set position to current location plus offset |
* SEEK_END: Set position to end-of-stream plus offset |
* |
* @return bool Returns true on success or false on failure |
* @link http://www.php.net/manual/en/function.fseek.php |
*/ |
public function seek($offset, $whence = SEEK_SET); |
|
/** |
* Returns whether or not the stream is writable |
* |
* @return bool |
*/ |
public function isWritable(); |
|
/** |
* Write data to the stream |
* |
* @param string $string The string that is to be written. |
* |
* @return int|bool Returns the number of bytes written to the stream on |
* success or false on failure. |
*/ |
public function write($string); |
|
/** |
* Flush the write buffers of the stream. |
* |
* @return bool Returns true on success and false on failure |
*/ |
public function flush(); |
|
/** |
* Returns whether or not the stream is readable |
* |
* @return bool |
*/ |
public function isReadable(); |
|
/** |
* Read data from the stream |
* |
* @param int $length Read up to $length bytes from the object and return |
* them. Fewer than $length bytes may be returned if |
* underlying stream call returns fewer bytes. |
* |
* @return string Returns the data read from the stream. |
*/ |
public function read($length); |
|
/** |
* Returns the remaining contents in a string, up to maxlength bytes. |
* |
* @param int $maxLength The maximum bytes to read. Defaults to -1 (read |
* all the remaining buffer). |
* @return string |
*/ |
public function getContents($maxLength = -1); |
} |
/vendor/guzzlehttp/streams/src/Utils.php |
@@ -0,0 +1,194 @@ |
<?php |
namespace GuzzleHttp\Stream; |
|
use GuzzleHttp\Stream\Exception\SeekException; |
|
/** |
* Static utility class because PHP's autoloaders don't support the concept |
* of namespaced function autoloading. |
*/ |
class Utils |
{ |
/** |
* Safely opens a PHP stream resource using a filename. |
* |
* When fopen fails, PHP normally raises a warning. This function adds an |
* error handler that checks for errors and throws an exception instead. |
* |
* @param string $filename File to open |
* @param string $mode Mode used to open the file |
* |
* @return resource |
* @throws \RuntimeException if the file cannot be opened |
*/ |
public static function open($filename, $mode) |
{ |
$ex = null; |
set_error_handler(function () use ($filename, $mode, &$ex) { |
$ex = new \RuntimeException(sprintf( |
'Unable to open %s using mode %s: %s', |
$filename, |
$mode, |
func_get_args()[1] |
)); |
}); |
|
$handle = fopen($filename, $mode); |
restore_error_handler(); |
|
if ($ex) { |
/** @var $ex \RuntimeException */ |
throw $ex; |
} |
|
return $handle; |
} |
|
/** |
* Copy the contents of a stream into a string until the given number of |
* bytes have been read. |
* |
* @param StreamInterface $stream Stream to read |
* @param int $maxLen Maximum number of bytes to read. Pass -1 |
* to read the entire stream. |
* @return string |
*/ |
public static function copyToString(StreamInterface $stream, $maxLen = -1) |
{ |
$buffer = ''; |
|
if ($maxLen === -1) { |
while (!$stream->eof()) { |
$buf = $stream->read(1048576); |
if ($buf === '' || $buf === false) { |
break; |
} |
$buffer .= $buf; |
} |
return $buffer; |
} |
|
$len = 0; |
while (!$stream->eof() && $len < $maxLen) { |
$buf = $stream->read($maxLen - $len); |
if ($buf === '' || $buf === false) { |
break; |
} |
$buffer .= $buf; |
$len = strlen($buffer); |
} |
|
return $buffer; |
} |
|
/** |
* Copy the contents of a stream into another stream until the given number |
* of bytes have been read. |
* |
* @param StreamInterface $source Stream to read from |
* @param StreamInterface $dest Stream to write to |
* @param int $maxLen Maximum number of bytes to read. Pass -1 |
* to read the entire stream. |
*/ |
public static function copyToStream( |
StreamInterface $source, |
StreamInterface $dest, |
$maxLen = -1 |
) { |
if ($maxLen === -1) { |
while (!$source->eof()) { |
if (!$dest->write($source->read(1048576))) { |
break; |
} |
} |
return; |
} |
|
$bytes = 0; |
while (!$source->eof()) { |
$buf = $source->read($maxLen - $bytes); |
if (!($len = strlen($buf))) { |
break; |
} |
$bytes += $len; |
$dest->write($buf); |
if ($bytes == $maxLen) { |
break; |
} |
} |
} |
|
/** |
* Calculate a hash of a Stream |
* |
* @param StreamInterface $stream Stream to calculate the hash for |
* @param string $algo Hash algorithm (e.g. md5, crc32, etc) |
* @param bool $rawOutput Whether or not to use raw output |
* |
* @return string Returns the hash of the stream |
* @throws SeekException |
*/ |
public static function hash( |
StreamInterface $stream, |
$algo, |
$rawOutput = false |
) { |
$pos = $stream->tell(); |
|
if ($pos > 0 && !$stream->seek(0)) { |
throw new SeekException($stream); |
} |
|
$ctx = hash_init($algo); |
while (!$stream->eof()) { |
hash_update($ctx, $stream->read(1048576)); |
} |
|
$out = hash_final($ctx, (bool) $rawOutput); |
$stream->seek($pos); |
|
return $out; |
} |
|
/** |
* Read a line from the stream up to the maximum allowed buffer length |
* |
* @param StreamInterface $stream Stream to read from |
* @param int $maxLength Maximum buffer length |
* |
* @return string|bool |
*/ |
public static function readline(StreamInterface $stream, $maxLength = null) |
{ |
$buffer = ''; |
$size = 0; |
|
while (!$stream->eof()) { |
if (false === ($byte = $stream->read(1))) { |
return $buffer; |
} |
$buffer .= $byte; |
// Break when a new line is found or the max length - 1 is reached |
if ($byte == PHP_EOL || ++$size == $maxLength - 1) { |
break; |
} |
} |
|
return $buffer; |
} |
|
/** |
* Alias of GuzzleHttp\Stream\Stream::factory. |
* |
* @param mixed $resource Resource to create |
* @param int $size Size if known up front |
* |
* @return MetadataStreamInterface |
* |
* @see GuzzleHttp\Stream\Stream::factory |
*/ |
public static function create($resource, $size = null) |
{ |
return Stream::factory($resource, $size); |
} |
} |
/vendor/guzzlehttp/streams/src/functions.php |
@@ -0,0 +1,68 @@ |
<?php |
/* |
* This file is deprecated and only included so that backwards compatibility |
* is maintained for downstream packages. |
* |
* Use the functions available in the Utils class instead of the the below |
* namespaced functions. |
*/ |
namespace GuzzleHttp\Stream; |
|
if (!defined('GUZZLE_STREAMS_FUNCTIONS')) { |
|
define('GUZZLE_STREAMS_FUNCTIONS', true); |
|
/** |
* @deprecated Moved to Stream::factory |
*/ |
function create($resource = '', $size = null) |
{ |
return Stream::factory($resource, $size); |
} |
|
/** |
* @deprecated Moved to Utils::copyToString |
*/ |
function copy_to_string(StreamInterface $stream, $maxLen = -1) |
{ |
return Utils::copyToString($stream, $maxLen); |
} |
|
/** |
* @deprecated Moved to Utils::copyToStream |
*/ |
function copy_to_stream( |
StreamInterface $source, |
StreamInterface $dest, |
$maxLen = -1 |
) { |
Utils::copyToStream($source, $dest, $maxLen); |
} |
|
/** |
* @deprecated Moved to Utils::hash |
*/ |
function hash( |
StreamInterface $stream, |
$algo, |
$rawOutput = false |
) { |
return Utils::hash($stream, $algo, $rawOutput); |
} |
|
/** |
* @deprecated Moced to Utils::readline |
*/ |
function read_line(StreamInterface $stream, $maxLength = null) |
{ |
return Utils::readline($stream, $maxLength); |
} |
|
/** |
* @deprecated Moved to Utils::open() |
*/ |
function safe_open($filename, $mode) |
{ |
return Utils::open($filename, $mode); |
} |
} |