scratch

Subversion Repositories:
Compare Path: Rev
With Path: Rev
?path1? @ 86  →  ?path2? @ 87
/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/Exception/SeekException.php
@@ -0,0 +1,27 @@
<?php
namespace GuzzleHttp\Stream\Exception;
 
use GuzzleHttp\Stream\StreamInterface;
 
/**
* Exception thrown when a seek fails on a stream.
*/
class SeekException extends \RuntimeException
{
private $stream;
 
public function __construct(StreamInterface $stream, $pos = 0, $msg = '')
{
$this->stream = $stream;
$msg = $msg ?: 'Could not seek the stream to position ' . $pos;
parent::__construct($msg);
}
 
/**
* @return StreamInterface
*/
public function getStream()
{
return $this->stream;
}
}
/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/InflateStream.php
@@ -0,0 +1,27 @@
<?php
namespace GuzzleHttp\Stream;
 
/**
* Uses PHP's zlib.inflate filter to inflate deflate or gzipped content.
*
* This stream decorator skips the first 10 bytes of the given stream to remove
* the gzip header, converts the provided stream to a PHP stream resource,
* then appends the zlib.inflate filter. The stream is then converted back
* to a Guzzle stream resource to be used as a Guzzle stream.
*
* @link http://tools.ietf.org/html/rfc1952
* @link http://php.net/manual/en/filters.compression.php
*/
class InflateStream implements MetadataStreamInterface
{
use StreamDecoratorTrait;
 
public function __construct(StreamInterface $stream)
{
// Skip the first 10 bytes
$stream = new LimitStream($stream, -1, 10);
$resource = GuzzleStreamWrapper::getResource($stream);
stream_filter_append($resource, 'zlib.inflate', STREAM_FILTER_READ);
$this->stream = new Stream($resource);
}
}
/vendor/guzzlehttp/streams/src/LazyOpenStream.php
@@ -0,0 +1,37 @@
<?php
namespace GuzzleHttp\Stream;
 
/**
* Lazily reads or writes to a file that is opened only after an IO operation
* take place on the stream.
*/
class LazyOpenStream implements StreamInterface, MetadataStreamInterface
{
use StreamDecoratorTrait;
 
/** @var string File to open */
private $filename;
 
/** @var string $mode */
private $mode;
 
/**
* @param string $filename File to lazily open
* @param string $mode fopen mode to use when opening the stream
*/
public function __construct($filename, $mode)
{
$this->filename = $filename;
$this->mode = $mode;
}
 
/**
* Creates the underlying stream lazily when required.
*
* @return StreamInterface
*/
protected function createStream()
{
return Stream::factory(Utils::open($this->filename, $this->mode));
}
}
/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/MetadataStreamInterface.php
@@ -0,0 +1,24 @@
<?php
namespace GuzzleHttp\Stream;
 
/**
* Represents a stream that contains metadata
*/
interface MetadataStreamInterface extends StreamInterface
{
/**
* 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);
}
/vendor/guzzlehttp/streams/src/NoSeekStream.php
@@ -0,0 +1,20 @@
<?php
namespace GuzzleHttp\Stream;
 
/**
* Stream decorator that prevents a stream from being seeked
*/
class NoSeekStream implements StreamInterface, MetadataStreamInterface
{
use StreamDecoratorTrait;
 
public function seek($offset, $whence = SEEK_SET)
{
return false;
}
 
public function isSeekable()
{
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);
}
}