171 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			171 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| 
 | |
| namespace GuzzleHttp\Psr7;
 | |
| 
 | |
| use Psr\Http\Message\StreamInterface;
 | |
| 
 | |
| /**
 | |
|  * Provides a read only stream that pumps data from a PHP callable.
 | |
|  *
 | |
|  * When invoking the provided callable, the PumpStream will pass the amount of
 | |
|  * data requested to read to the callable. The callable can choose to ignore
 | |
|  * this value and return fewer or more bytes than requested. Any extra data
 | |
|  * returned by the provided callable is buffered internally until drained using
 | |
|  * the read() function of the PumpStream. The provided callable MUST return
 | |
|  * false when there is no more data to read.
 | |
|  *
 | |
|  * @final
 | |
|  */
 | |
| class PumpStream implements StreamInterface
 | |
| {
 | |
|     /** @var callable */
 | |
|     private $source;
 | |
| 
 | |
|     /** @var int */
 | |
|     private $size;
 | |
| 
 | |
|     /** @var int */
 | |
|     private $tellPos = 0;
 | |
| 
 | |
|     /** @var array */
 | |
|     private $metadata;
 | |
| 
 | |
|     /** @var BufferStream */
 | |
|     private $buffer;
 | |
| 
 | |
|     /**
 | |
|      * @param callable $source  Source of the stream data. The callable MAY
 | |
|      *                          accept an integer argument used to control the
 | |
|      *                          amount of data to return. The callable MUST
 | |
|      *                          return a string when called, or false on error
 | |
|      *                          or EOF.
 | |
|      * @param array    $options Stream options:
 | |
|      *                          - metadata: Hash of metadata to use with stream.
 | |
|      *                          - size: Size of the stream, if known.
 | |
|      */
 | |
|     public function __construct(callable $source, array $options = [])
 | |
|     {
 | |
|         $this->source = $source;
 | |
|         $this->size = isset($options['size']) ? $options['size'] : null;
 | |
|         $this->metadata = isset($options['metadata']) ? $options['metadata'] : [];
 | |
|         $this->buffer = new BufferStream();
 | |
|     }
 | |
| 
 | |
|     public function __toString()
 | |
|     {
 | |
|         try {
 | |
|             return Utils::copyToString($this);
 | |
|         } catch (\Exception $e) {
 | |
|             return '';
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     public function close()
 | |
|     {
 | |
|         $this->detach();
 | |
|     }
 | |
| 
 | |
|     public function detach()
 | |
|     {
 | |
|         $this->tellPos = false;
 | |
|         $this->source = null;
 | |
| 
 | |
|         return null;
 | |
|     }
 | |
| 
 | |
|     public function getSize()
 | |
|     {
 | |
|         return $this->size;
 | |
|     }
 | |
| 
 | |
|     public function tell()
 | |
|     {
 | |
|         return $this->tellPos;
 | |
|     }
 | |
| 
 | |
|     public function eof()
 | |
|     {
 | |
|         return !$this->source;
 | |
|     }
 | |
| 
 | |
|     public function isSeekable()
 | |
|     {
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     public function rewind()
 | |
|     {
 | |
|         $this->seek(0);
 | |
|     }
 | |
| 
 | |
|     public function seek($offset, $whence = SEEK_SET)
 | |
|     {
 | |
|         throw new \RuntimeException('Cannot seek a PumpStream');
 | |
|     }
 | |
| 
 | |
|     public function isWritable()
 | |
|     {
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     public function write($string)
 | |
|     {
 | |
|         throw new \RuntimeException('Cannot write to a PumpStream');
 | |
|     }
 | |
| 
 | |
|     public function isReadable()
 | |
|     {
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     public function read($length)
 | |
|     {
 | |
|         $data = $this->buffer->read($length);
 | |
|         $readLen = strlen($data);
 | |
|         $this->tellPos += $readLen;
 | |
|         $remaining = $length - $readLen;
 | |
| 
 | |
|         if ($remaining) {
 | |
|             $this->pump($remaining);
 | |
|             $data .= $this->buffer->read($remaining);
 | |
|             $this->tellPos += strlen($data) - $readLen;
 | |
|         }
 | |
| 
 | |
|         return $data;
 | |
|     }
 | |
| 
 | |
|     public function getContents()
 | |
|     {
 | |
|         $result = '';
 | |
|         while (!$this->eof()) {
 | |
|             $result .= $this->read(1000000);
 | |
|         }
 | |
| 
 | |
|         return $result;
 | |
|     }
 | |
| 
 | |
|     public function getMetadata($key = null)
 | |
|     {
 | |
|         if (!$key) {
 | |
|             return $this->metadata;
 | |
|         }
 | |
| 
 | |
|         return isset($this->metadata[$key]) ? $this->metadata[$key] : null;
 | |
|     }
 | |
| 
 | |
|     private function pump($length)
 | |
|     {
 | |
|         if ($this->source) {
 | |
|             do {
 | |
|                 $data = call_user_func($this->source, $length);
 | |
|                 if ($data === false || $data === null) {
 | |
|                     $this->source = null;
 | |
|                     return;
 | |
|                 }
 | |
|                 $this->buffer->write($data);
 | |
|                 $length -= strlen($data);
 | |
|             } while ($length > 0);
 | |
|         }
 | |
|     }
 | |
| }
 | 
