123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- <?php
- namespace GuzzleHttp\Psr7;
- use Psr\Http\Message\StreamInterface;
- /**
- * 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 StreamInterface
- {
- /** @var array */
- private $methods;
- /** @var array Methods that must be implemented in the given array */
- private static $slots = ['__toString', 'close', 'detach', 'rewind',
- 'getSize', 'tell', 'eof', 'isSeekable', 'seek', 'isWritable', 'write',
- '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);
- }
- }
- /**
- * An unserialize would allow the __destruct to run when the unserialized value goes out of scope.
- * @throws \LogicException
- */
- public function __wakeup()
- {
- throw new \LogicException('FnStream should never be unserialized');
- }
- /**
- * 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 rewind()
- {
- call_user_func($this->_fn_rewind);
- }
- public function seek($offset, $whence = SEEK_SET)
- {
- 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 isReadable()
- {
- return call_user_func($this->_fn_isReadable);
- }
- public function read($length)
- {
- return call_user_func($this->_fn_read, $length);
- }
- public function getContents()
- {
- return call_user_func($this->_fn_getContents);
- }
- public function getMetadata($key = null)
- {
- return call_user_func($this->_fn_getMetadata, $key);
- }
- }
|