annotate vendor/guzzlehttp/psr7/src/Stream.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 129ea1e6d783
children
rev   line source
Chris@0 1 <?php
Chris@0 2 namespace GuzzleHttp\Psr7;
Chris@0 3
Chris@0 4 use Psr\Http\Message\StreamInterface;
Chris@0 5
Chris@0 6 /**
Chris@0 7 * PHP stream implementation.
Chris@0 8 *
Chris@0 9 * @var $stream
Chris@0 10 */
Chris@0 11 class Stream implements StreamInterface
Chris@0 12 {
Chris@0 13 private $stream;
Chris@0 14 private $size;
Chris@0 15 private $seekable;
Chris@0 16 private $readable;
Chris@0 17 private $writable;
Chris@0 18 private $uri;
Chris@0 19 private $customMetadata;
Chris@0 20
Chris@0 21 /** @var array Hash of readable and writable stream types */
Chris@0 22 private static $readWriteHash = [
Chris@0 23 'read' => [
Chris@0 24 'r' => true, 'w+' => true, 'r+' => true, 'x+' => true, 'c+' => true,
Chris@0 25 'rb' => true, 'w+b' => true, 'r+b' => true, 'x+b' => true,
Chris@0 26 'c+b' => true, 'rt' => true, 'w+t' => true, 'r+t' => true,
Chris@17 27 'x+t' => true, 'c+t' => true, 'a+' => true, 'rb+' => true,
Chris@0 28 ],
Chris@0 29 'write' => [
Chris@0 30 'w' => true, 'w+' => true, 'rw' => true, 'r+' => true, 'x+' => true,
Chris@17 31 'c+' => true, 'wb' => true, 'w+b' => true, 'r+b' => true, 'rb+' => true,
Chris@0 32 'x+b' => true, 'c+b' => true, 'w+t' => true, 'r+t' => true,
Chris@0 33 'x+t' => true, 'c+t' => true, 'a' => true, 'a+' => true
Chris@0 34 ]
Chris@0 35 ];
Chris@0 36
Chris@0 37 /**
Chris@0 38 * This constructor accepts an associative array of options.
Chris@0 39 *
Chris@0 40 * - size: (int) If a read stream would otherwise have an indeterminate
Chris@0 41 * size, but the size is known due to foreknowledge, then you can
Chris@0 42 * provide that size, in bytes.
Chris@0 43 * - metadata: (array) Any additional metadata to return when the metadata
Chris@0 44 * of the stream is accessed.
Chris@0 45 *
Chris@0 46 * @param resource $stream Stream resource to wrap.
Chris@0 47 * @param array $options Associative array of options.
Chris@0 48 *
Chris@0 49 * @throws \InvalidArgumentException if the stream is not a stream resource
Chris@0 50 */
Chris@0 51 public function __construct($stream, $options = [])
Chris@0 52 {
Chris@0 53 if (!is_resource($stream)) {
Chris@0 54 throw new \InvalidArgumentException('Stream must be a resource');
Chris@0 55 }
Chris@0 56
Chris@0 57 if (isset($options['size'])) {
Chris@0 58 $this->size = $options['size'];
Chris@0 59 }
Chris@0 60
Chris@0 61 $this->customMetadata = isset($options['metadata'])
Chris@0 62 ? $options['metadata']
Chris@0 63 : [];
Chris@0 64
Chris@0 65 $this->stream = $stream;
Chris@0 66 $meta = stream_get_meta_data($this->stream);
Chris@0 67 $this->seekable = $meta['seekable'];
Chris@0 68 $this->readable = isset(self::$readWriteHash['read'][$meta['mode']]);
Chris@0 69 $this->writable = isset(self::$readWriteHash['write'][$meta['mode']]);
Chris@0 70 $this->uri = $this->getMetadata('uri');
Chris@0 71 }
Chris@0 72
Chris@0 73 /**
Chris@0 74 * Closes the stream when the destructed
Chris@0 75 */
Chris@0 76 public function __destruct()
Chris@0 77 {
Chris@0 78 $this->close();
Chris@0 79 }
Chris@0 80
Chris@0 81 public function __toString()
Chris@0 82 {
Chris@0 83 try {
Chris@0 84 $this->seek(0);
Chris@0 85 return (string) stream_get_contents($this->stream);
Chris@0 86 } catch (\Exception $e) {
Chris@0 87 return '';
Chris@0 88 }
Chris@0 89 }
Chris@0 90
Chris@0 91 public function getContents()
Chris@0 92 {
Chris@17 93 if (!isset($this->stream)) {
Chris@17 94 throw new \RuntimeException('Stream is detached');
Chris@17 95 }
Chris@17 96
Chris@0 97 $contents = stream_get_contents($this->stream);
Chris@0 98
Chris@0 99 if ($contents === false) {
Chris@0 100 throw new \RuntimeException('Unable to read stream contents');
Chris@0 101 }
Chris@0 102
Chris@0 103 return $contents;
Chris@0 104 }
Chris@0 105
Chris@0 106 public function close()
Chris@0 107 {
Chris@0 108 if (isset($this->stream)) {
Chris@0 109 if (is_resource($this->stream)) {
Chris@0 110 fclose($this->stream);
Chris@0 111 }
Chris@0 112 $this->detach();
Chris@0 113 }
Chris@0 114 }
Chris@0 115
Chris@0 116 public function detach()
Chris@0 117 {
Chris@0 118 if (!isset($this->stream)) {
Chris@0 119 return null;
Chris@0 120 }
Chris@0 121
Chris@0 122 $result = $this->stream;
Chris@0 123 unset($this->stream);
Chris@0 124 $this->size = $this->uri = null;
Chris@0 125 $this->readable = $this->writable = $this->seekable = false;
Chris@0 126
Chris@0 127 return $result;
Chris@0 128 }
Chris@0 129
Chris@0 130 public function getSize()
Chris@0 131 {
Chris@0 132 if ($this->size !== null) {
Chris@0 133 return $this->size;
Chris@0 134 }
Chris@0 135
Chris@0 136 if (!isset($this->stream)) {
Chris@0 137 return null;
Chris@0 138 }
Chris@0 139
Chris@0 140 // Clear the stat cache if the stream has a URI
Chris@0 141 if ($this->uri) {
Chris@0 142 clearstatcache(true, $this->uri);
Chris@0 143 }
Chris@0 144
Chris@0 145 $stats = fstat($this->stream);
Chris@0 146 if (isset($stats['size'])) {
Chris@0 147 $this->size = $stats['size'];
Chris@0 148 return $this->size;
Chris@0 149 }
Chris@0 150
Chris@0 151 return null;
Chris@0 152 }
Chris@0 153
Chris@0 154 public function isReadable()
Chris@0 155 {
Chris@0 156 return $this->readable;
Chris@0 157 }
Chris@0 158
Chris@0 159 public function isWritable()
Chris@0 160 {
Chris@0 161 return $this->writable;
Chris@0 162 }
Chris@0 163
Chris@0 164 public function isSeekable()
Chris@0 165 {
Chris@0 166 return $this->seekable;
Chris@0 167 }
Chris@0 168
Chris@0 169 public function eof()
Chris@0 170 {
Chris@17 171 if (!isset($this->stream)) {
Chris@17 172 throw new \RuntimeException('Stream is detached');
Chris@17 173 }
Chris@17 174
Chris@17 175 return feof($this->stream);
Chris@0 176 }
Chris@0 177
Chris@0 178 public function tell()
Chris@0 179 {
Chris@17 180 if (!isset($this->stream)) {
Chris@17 181 throw new \RuntimeException('Stream is detached');
Chris@17 182 }
Chris@17 183
Chris@0 184 $result = ftell($this->stream);
Chris@0 185
Chris@0 186 if ($result === false) {
Chris@0 187 throw new \RuntimeException('Unable to determine stream position');
Chris@0 188 }
Chris@0 189
Chris@0 190 return $result;
Chris@0 191 }
Chris@0 192
Chris@0 193 public function rewind()
Chris@0 194 {
Chris@0 195 $this->seek(0);
Chris@0 196 }
Chris@0 197
Chris@0 198 public function seek($offset, $whence = SEEK_SET)
Chris@0 199 {
Chris@17 200 if (!isset($this->stream)) {
Chris@17 201 throw new \RuntimeException('Stream is detached');
Chris@17 202 }
Chris@0 203 if (!$this->seekable) {
Chris@0 204 throw new \RuntimeException('Stream is not seekable');
Chris@17 205 }
Chris@17 206 if (fseek($this->stream, $offset, $whence) === -1) {
Chris@0 207 throw new \RuntimeException('Unable to seek to stream position '
Chris@0 208 . $offset . ' with whence ' . var_export($whence, true));
Chris@0 209 }
Chris@0 210 }
Chris@0 211
Chris@0 212 public function read($length)
Chris@0 213 {
Chris@17 214 if (!isset($this->stream)) {
Chris@17 215 throw new \RuntimeException('Stream is detached');
Chris@17 216 }
Chris@0 217 if (!$this->readable) {
Chris@0 218 throw new \RuntimeException('Cannot read from non-readable stream');
Chris@0 219 }
Chris@0 220 if ($length < 0) {
Chris@0 221 throw new \RuntimeException('Length parameter cannot be negative');
Chris@0 222 }
Chris@0 223
Chris@0 224 if (0 === $length) {
Chris@0 225 return '';
Chris@0 226 }
Chris@0 227
Chris@0 228 $string = fread($this->stream, $length);
Chris@0 229 if (false === $string) {
Chris@0 230 throw new \RuntimeException('Unable to read from stream');
Chris@0 231 }
Chris@0 232
Chris@0 233 return $string;
Chris@0 234 }
Chris@0 235
Chris@0 236 public function write($string)
Chris@0 237 {
Chris@17 238 if (!isset($this->stream)) {
Chris@17 239 throw new \RuntimeException('Stream is detached');
Chris@17 240 }
Chris@0 241 if (!$this->writable) {
Chris@0 242 throw new \RuntimeException('Cannot write to a non-writable stream');
Chris@0 243 }
Chris@0 244
Chris@0 245 // We can't know the size after writing anything
Chris@0 246 $this->size = null;
Chris@0 247 $result = fwrite($this->stream, $string);
Chris@0 248
Chris@0 249 if ($result === false) {
Chris@0 250 throw new \RuntimeException('Unable to write to stream');
Chris@0 251 }
Chris@0 252
Chris@0 253 return $result;
Chris@0 254 }
Chris@0 255
Chris@0 256 public function getMetadata($key = null)
Chris@0 257 {
Chris@0 258 if (!isset($this->stream)) {
Chris@0 259 return $key ? null : [];
Chris@0 260 } elseif (!$key) {
Chris@0 261 return $this->customMetadata + stream_get_meta_data($this->stream);
Chris@0 262 } elseif (isset($this->customMetadata[$key])) {
Chris@0 263 return $this->customMetadata[$key];
Chris@0 264 }
Chris@0 265
Chris@0 266 $meta = stream_get_meta_data($this->stream);
Chris@0 267
Chris@0 268 return isset($meta[$key]) ? $meta[$key] : null;
Chris@0 269 }
Chris@0 270 }