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 * Provides a read only stream that pumps data from a PHP callable. 0008 * 0009 * When invoking the provided callable, the PumpStream will pass the amount of 0010 * data requested to read to the callable. The callable can choose to ignore 0011 * this value and return fewer or more bytes than requested. Any extra data 0012 * returned by the provided callable is buffered internally until drained using 0013 * the read() function of the PumpStream. The provided callable MUST return 0014 * false when there is no more data to read. 0015 */ 0016 class PumpStream implements StreamInterface 0017 { 0018 /** @var callable */ 0019 private $source; 0020 0021 /** @var int */ 0022 private $size; 0023 0024 /** @var int */ 0025 private $tellPos = 0; 0026 0027 /** @var array */ 0028 private $metadata; 0029 0030 /** @var BufferStream */ 0031 private $buffer; 0032 0033 /** 0034 * @param callable $source Source of the stream data. The callable MAY 0035 * accept an integer argument used to control the 0036 * amount of data to return. The callable MUST 0037 * return a string when called, or false on error 0038 * or EOF. 0039 * @param array $options Stream options: 0040 * - metadata: Hash of metadata to use with stream. 0041 * - size: Size of the stream, if known. 0042 */ 0043 public function __construct(callable $source, array $options = []) 0044 { 0045 $this->source = $source; 0046 $this->size = isset($options['size']) ? $options['size'] : null; 0047 $this->metadata = isset($options['metadata']) ? $options['metadata'] : []; 0048 $this->buffer = new BufferStream(); 0049 } 0050 0051 public function __toString() 0052 { 0053 try { 0054 return copy_to_string($this); 0055 } catch (\Exception $e) { 0056 return ''; 0057 } 0058 } 0059 0060 public function close() 0061 { 0062 $this->detach(); 0063 } 0064 0065 public function detach() 0066 { 0067 $this->tellPos = false; 0068 $this->source = null; 0069 } 0070 0071 public function getSize() 0072 { 0073 return $this->size; 0074 } 0075 0076 public function tell() 0077 { 0078 return $this->tellPos; 0079 } 0080 0081 public function eof() 0082 { 0083 return !$this->source; 0084 } 0085 0086 public function isSeekable() 0087 { 0088 return false; 0089 } 0090 0091 public function rewind() 0092 { 0093 $this->seek(0); 0094 } 0095 0096 public function seek($offset, $whence = SEEK_SET) 0097 { 0098 throw new \RuntimeException('Cannot seek a PumpStream'); 0099 } 0100 0101 public function isWritable() 0102 { 0103 return false; 0104 } 0105 0106 public function write($string) 0107 { 0108 throw new \RuntimeException('Cannot write to a PumpStream'); 0109 } 0110 0111 public function isReadable() 0112 { 0113 return true; 0114 } 0115 0116 public function read($length) 0117 { 0118 $data = $this->buffer->read($length); 0119 $readLen = strlen($data); 0120 $this->tellPos += $readLen; 0121 $remaining = $length - $readLen; 0122 0123 if ($remaining) { 0124 $this->pump($remaining); 0125 $data .= $this->buffer->read($remaining); 0126 $this->tellPos += strlen($data) - $readLen; 0127 } 0128 0129 return $data; 0130 } 0131 0132 public function getContents() 0133 { 0134 $result = ''; 0135 while (!$this->eof()) { 0136 $result .= $this->read(1000000); 0137 } 0138 0139 return $result; 0140 } 0141 0142 public function getMetadata($key = null) 0143 { 0144 if (!$key) { 0145 return $this->metadata; 0146 } 0147 0148 return isset($this->metadata[$key]) ? $this->metadata[$key] : null; 0149 } 0150 0151 private function pump($length) 0152 { 0153 if ($this->source) { 0154 do { 0155 $data = call_user_func($this->source, $length); 0156 if ($data === false || $data === null) { 0157 $this->source = null; 0158 return; 0159 } 0160 $this->buffer->write($data); 0161 $length -= strlen($data); 0162 } while ($length > 0); 0163 } 0164 } 0165 }