annotate vendor/guzzlehttp/psr7/src/Stream.php @ 0:4c8ae668cc8c

Initial import (non-working)
author Chris Cannam
date Wed, 29 Nov 2017 16:09:58 +0000
parents
children 129ea1e6d783
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@0 27 'x+t' => true, 'c+t' => true, 'a+' => true
Chris@0 28 ],
Chris@0 29 'write' => [
Chris@0 30 'w' => true, 'w+' => true, 'rw' => true, 'r+' => true, 'x+' => true,
Chris@0 31 'c+' => true, 'wb' => true, 'w+b' => true, 'r+b' => 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 public function __get($name)
Chris@0 74 {
Chris@0 75 if ($name == 'stream') {
Chris@0 76 throw new \RuntimeException('The stream is detached');
Chris@0 77 }
Chris@0 78
Chris@0 79 throw new \BadMethodCallException('No value for ' . $name);
Chris@0 80 }
Chris@0 81
Chris@0 82 /**
Chris@0 83 * Closes the stream when the destructed
Chris@0 84 */
Chris@0 85 public function __destruct()
Chris@0 86 {
Chris@0 87 $this->close();
Chris@0 88 }
Chris@0 89
Chris@0 90 public function __toString()
Chris@0 91 {
Chris@0 92 try {
Chris@0 93 $this->seek(0);
Chris@0 94 return (string) stream_get_contents($this->stream);
Chris@0 95 } catch (\Exception $e) {
Chris@0 96 return '';
Chris@0 97 }
Chris@0 98 }
Chris@0 99
Chris@0 100 public function getContents()
Chris@0 101 {
Chris@0 102 $contents = stream_get_contents($this->stream);
Chris@0 103
Chris@0 104 if ($contents === false) {
Chris@0 105 throw new \RuntimeException('Unable to read stream contents');
Chris@0 106 }
Chris@0 107
Chris@0 108 return $contents;
Chris@0 109 }
Chris@0 110
Chris@0 111 public function close()
Chris@0 112 {
Chris@0 113 if (isset($this->stream)) {
Chris@0 114 if (is_resource($this->stream)) {
Chris@0 115 fclose($this->stream);
Chris@0 116 }
Chris@0 117 $this->detach();
Chris@0 118 }
Chris@0 119 }
Chris@0 120
Chris@0 121 public function detach()
Chris@0 122 {
Chris@0 123 if (!isset($this->stream)) {
Chris@0 124 return null;
Chris@0 125 }
Chris@0 126
Chris@0 127 $result = $this->stream;
Chris@0 128 unset($this->stream);
Chris@0 129 $this->size = $this->uri = null;
Chris@0 130 $this->readable = $this->writable = $this->seekable = false;
Chris@0 131
Chris@0 132 return $result;
Chris@0 133 }
Chris@0 134
Chris@0 135 public function getSize()
Chris@0 136 {
Chris@0 137 if ($this->size !== null) {
Chris@0 138 return $this->size;
Chris@0 139 }
Chris@0 140
Chris@0 141 if (!isset($this->stream)) {
Chris@0 142 return null;
Chris@0 143 }
Chris@0 144
Chris@0 145 // Clear the stat cache if the stream has a URI
Chris@0 146 if ($this->uri) {
Chris@0 147 clearstatcache(true, $this->uri);
Chris@0 148 }
Chris@0 149
Chris@0 150 $stats = fstat($this->stream);
Chris@0 151 if (isset($stats['size'])) {
Chris@0 152 $this->size = $stats['size'];
Chris@0 153 return $this->size;
Chris@0 154 }
Chris@0 155
Chris@0 156 return null;
Chris@0 157 }
Chris@0 158
Chris@0 159 public function isReadable()
Chris@0 160 {
Chris@0 161 return $this->readable;
Chris@0 162 }
Chris@0 163
Chris@0 164 public function isWritable()
Chris@0 165 {
Chris@0 166 return $this->writable;
Chris@0 167 }
Chris@0 168
Chris@0 169 public function isSeekable()
Chris@0 170 {
Chris@0 171 return $this->seekable;
Chris@0 172 }
Chris@0 173
Chris@0 174 public function eof()
Chris@0 175 {
Chris@0 176 return !$this->stream || feof($this->stream);
Chris@0 177 }
Chris@0 178
Chris@0 179 public function tell()
Chris@0 180 {
Chris@0 181 $result = ftell($this->stream);
Chris@0 182
Chris@0 183 if ($result === false) {
Chris@0 184 throw new \RuntimeException('Unable to determine stream position');
Chris@0 185 }
Chris@0 186
Chris@0 187 return $result;
Chris@0 188 }
Chris@0 189
Chris@0 190 public function rewind()
Chris@0 191 {
Chris@0 192 $this->seek(0);
Chris@0 193 }
Chris@0 194
Chris@0 195 public function seek($offset, $whence = SEEK_SET)
Chris@0 196 {
Chris@0 197 if (!$this->seekable) {
Chris@0 198 throw new \RuntimeException('Stream is not seekable');
Chris@0 199 } elseif (fseek($this->stream, $offset, $whence) === -1) {
Chris@0 200 throw new \RuntimeException('Unable to seek to stream position '
Chris@0 201 . $offset . ' with whence ' . var_export($whence, true));
Chris@0 202 }
Chris@0 203 }
Chris@0 204
Chris@0 205 public function read($length)
Chris@0 206 {
Chris@0 207 if (!$this->readable) {
Chris@0 208 throw new \RuntimeException('Cannot read from non-readable stream');
Chris@0 209 }
Chris@0 210 if ($length < 0) {
Chris@0 211 throw new \RuntimeException('Length parameter cannot be negative');
Chris@0 212 }
Chris@0 213
Chris@0 214 if (0 === $length) {
Chris@0 215 return '';
Chris@0 216 }
Chris@0 217
Chris@0 218 $string = fread($this->stream, $length);
Chris@0 219 if (false === $string) {
Chris@0 220 throw new \RuntimeException('Unable to read from stream');
Chris@0 221 }
Chris@0 222
Chris@0 223 return $string;
Chris@0 224 }
Chris@0 225
Chris@0 226 public function write($string)
Chris@0 227 {
Chris@0 228 if (!$this->writable) {
Chris@0 229 throw new \RuntimeException('Cannot write to a non-writable stream');
Chris@0 230 }
Chris@0 231
Chris@0 232 // We can't know the size after writing anything
Chris@0 233 $this->size = null;
Chris@0 234 $result = fwrite($this->stream, $string);
Chris@0 235
Chris@0 236 if ($result === false) {
Chris@0 237 throw new \RuntimeException('Unable to write to stream');
Chris@0 238 }
Chris@0 239
Chris@0 240 return $result;
Chris@0 241 }
Chris@0 242
Chris@0 243 public function getMetadata($key = null)
Chris@0 244 {
Chris@0 245 if (!isset($this->stream)) {
Chris@0 246 return $key ? null : [];
Chris@0 247 } elseif (!$key) {
Chris@0 248 return $this->customMetadata + stream_get_meta_data($this->stream);
Chris@0 249 } elseif (isset($this->customMetadata[$key])) {
Chris@0 250 return $this->customMetadata[$key];
Chris@0 251 }
Chris@0 252
Chris@0 253 $meta = stream_get_meta_data($this->stream);
Chris@0 254
Chris@0 255 return isset($meta[$key]) ? $meta[$key] : null;
Chris@0 256 }
Chris@0 257 }