File indexing completed on 2024-12-29 05:27:23

0001 <?php
0002 namespace GuzzleHttp\Psr7;
0003 
0004 use Psr\Http\Message\StreamInterface;
0005 
0006 /**
0007  * Compose stream implementations based on a hash of functions.
0008  *
0009  * Allows for easy testing and extension of a provided stream without needing
0010  * to create a concrete class for a simple extension point.
0011  */
0012 class FnStream implements StreamInterface
0013 {
0014     /** @var array */
0015     private $methods;
0016 
0017     /** @var array Methods that must be implemented in the given array */
0018     private static $slots = ['__toString', 'close', 'detach', 'rewind',
0019         'getSize', 'tell', 'eof', 'isSeekable', 'seek', 'isWritable', 'write',
0020         'isReadable', 'read', 'getContents', 'getMetadata'];
0021 
0022     /**
0023      * @param array $methods Hash of method name to a callable.
0024      */
0025     public function __construct(array $methods)
0026     {
0027         $this->methods = $methods;
0028 
0029         // Create the functions on the class
0030         foreach ($methods as $name => $fn) {
0031             $this->{'_fn_' . $name} = $fn;
0032         }
0033     }
0034 
0035     /**
0036      * Lazily determine which methods are not implemented.
0037      * @throws \BadMethodCallException
0038      */
0039     public function __get($name)
0040     {
0041         throw new \BadMethodCallException(str_replace('_fn_', '', $name)
0042             . '() is not implemented in the FnStream');
0043     }
0044 
0045     /**
0046      * The close method is called on the underlying stream only if possible.
0047      */
0048     public function __destruct()
0049     {
0050         if (isset($this->_fn_close)) {
0051             call_user_func($this->_fn_close);
0052         }
0053     }
0054 
0055     /**
0056      * Adds custom functionality to an underlying stream by intercepting
0057      * specific method calls.
0058      *
0059      * @param StreamInterface $stream  Stream to decorate
0060      * @param array           $methods Hash of method name to a closure
0061      *
0062      * @return FnStream
0063      */
0064     public static function decorate(StreamInterface $stream, array $methods)
0065     {
0066         // If any of the required methods were not provided, then simply
0067         // proxy to the decorated stream.
0068         foreach (array_diff(self::$slots, array_keys($methods)) as $diff) {
0069             $methods[$diff] = [$stream, $diff];
0070         }
0071 
0072         return new self($methods);
0073     }
0074 
0075     public function __toString()
0076     {
0077         return call_user_func($this->_fn___toString);
0078     }
0079 
0080     public function close()
0081     {
0082         return call_user_func($this->_fn_close);
0083     }
0084 
0085     public function detach()
0086     {
0087         return call_user_func($this->_fn_detach);
0088     }
0089 
0090     public function getSize()
0091     {
0092         return call_user_func($this->_fn_getSize);
0093     }
0094 
0095     public function tell()
0096     {
0097         return call_user_func($this->_fn_tell);
0098     }
0099 
0100     public function eof()
0101     {
0102         return call_user_func($this->_fn_eof);
0103     }
0104 
0105     public function isSeekable()
0106     {
0107         return call_user_func($this->_fn_isSeekable);
0108     }
0109 
0110     public function rewind()
0111     {
0112         call_user_func($this->_fn_rewind);
0113     }
0114 
0115     public function seek($offset, $whence = SEEK_SET)
0116     {
0117         call_user_func($this->_fn_seek, $offset, $whence);
0118     }
0119 
0120     public function isWritable()
0121     {
0122         return call_user_func($this->_fn_isWritable);
0123     }
0124 
0125     public function write($string)
0126     {
0127         return call_user_func($this->_fn_write, $string);
0128     }
0129 
0130     public function isReadable()
0131     {
0132         return call_user_func($this->_fn_isReadable);
0133     }
0134 
0135     public function read($length)
0136     {
0137         return call_user_func($this->_fn_read, $length);
0138     }
0139 
0140     public function getContents()
0141     {
0142         return call_user_func($this->_fn_getContents);
0143     }
0144 
0145     public function getMetadata($key = null)
0146     {
0147         return call_user_func($this->_fn_getMetadata, $key);
0148     }
0149 }