2015-08-17 17:00:26 -07:00
< ? php
2015-08-27 12:03:05 -07:00
namespace GuzzleHttp\Psr7 ;
use Psr\Http\Message\StreamInterface ;
2015-08-17 17:00:26 -07:00
/**
* 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 */
2015-08-27 12:03:05 -07:00
private static $slots = [ '__toString' , 'close' , 'detach' , 'rewind' ,
2015-08-17 17:00:26 -07:00
'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 );
}
}
/**
* 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 );
}
2015-08-27 12:03:05 -07:00
public function rewind ()
{
call_user_func ( $this -> _fn_rewind );
}
2015-08-17 17:00:26 -07:00
public function seek ( $offset , $whence = SEEK_SET )
{
2015-08-27 12:03:05 -07:00
call_user_func ( $this -> _fn_seek , $offset , $whence );
2015-08-17 17:00:26 -07:00
}
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 );
}
}