| [ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 <?php 2 3 declare (strict_types=1); 4 namespace WordPress\AiClientDependencies\Nyholm\Psr7; 5 6 use WordPress\AiClientDependencies\Psr\Http\Message\StreamInterface; 7 /** 8 * @author Michael Dowling and contributors to guzzlehttp/psr7 9 * @author Tobias Nyholm <tobias.nyholm@gmail.com> 10 * @author Martijn van der Ven <martijn@vanderven.se> 11 * 12 * @final This class should never be extended. See https://github.com/Nyholm/psr7/blob/master/doc/final.md 13 */ 14 class Stream implements StreamInterface 15 { 16 use StreamTrait; 17 /** @var resource|null A resource reference */ 18 private $stream; 19 /** @var bool */ 20 private $seekable; 21 /** @var bool */ 22 private $readable; 23 /** @var bool */ 24 private $writable; 25 /** @var array|mixed|void|bool|null */ 26 private $uri; 27 /** @var int|null */ 28 private $size; 29 /** @var array Hash of readable and writable stream types */ 30 private const READ_WRITE_HASH = ['read' => ['r' => \true, 'w+' => \true, 'r+' => \true, 'x+' => \true, 'c+' => \true, 'rb' => \true, 'w+b' => \true, 'r+b' => \true, 'x+b' => \true, 'c+b' => \true, 'rt' => \true, 'w+t' => \true, 'r+t' => \true, 'x+t' => \true, 'c+t' => \true, 'a+' => \true], 'write' => ['w' => \true, 'w+' => \true, 'rw' => \true, 'r+' => \true, 'x+' => \true, 'c+' => \true, 'wb' => \true, 'w+b' => \true, 'r+b' => \true, 'x+b' => \true, 'c+b' => \true, 'w+t' => \true, 'r+t' => \true, 'x+t' => \true, 'c+t' => \true, 'a' => \true, 'a+' => \true]]; 31 /** 32 * @param resource $body 33 */ 34 public function __construct($body) 35 { 36 if (!\is_resource($body)) { 37 throw new \InvalidArgumentException('First argument to Stream::__construct() must be resource'); 38 } 39 $this->stream = $body; 40 $meta = \stream_get_meta_data($this->stream); 41 $this->seekable = $meta['seekable'] && 0 === \fseek($this->stream, 0, \SEEK_CUR); 42 $this->readable = isset(self::READ_WRITE_HASH['read'][$meta['mode']]); 43 $this->writable = isset(self::READ_WRITE_HASH['write'][$meta['mode']]); 44 } 45 /** 46 * Creates a new PSR-7 stream. 47 * 48 * @param string|resource|StreamInterface $body 49 * 50 * @throws \InvalidArgumentException 51 */ 52 public static function create($body = ''): StreamInterface 53 { 54 if ($body instanceof StreamInterface) { 55 return $body; 56 } 57 if (\is_string($body)) { 58 if (200000 <= \strlen($body)) { 59 $body = self::openZvalStream($body); 60 } else { 61 $resource = \fopen('php://memory', 'r+'); 62 \fwrite($resource, $body); 63 \fseek($resource, 0); 64 $body = $resource; 65 } 66 } 67 if (!\is_resource($body)) { 68 throw new \InvalidArgumentException('First argument to Stream::create() must be a string, resource or StreamInterface'); 69 } 70 return new self($body); 71 } 72 /** 73 * Closes the stream when the destructed. 74 */ 75 public function __destruct() 76 { 77 $this->close(); 78 } 79 public function close(): void 80 { 81 if (isset($this->stream)) { 82 if (\is_resource($this->stream)) { 83 \fclose($this->stream); 84 } 85 $this->detach(); 86 } 87 } 88 public function detach() 89 { 90 if (!isset($this->stream)) { 91 return null; 92 } 93 $result = $this->stream; 94 unset($this->stream); 95 $this->size = $this->uri = null; 96 $this->readable = $this->writable = $this->seekable = \false; 97 return $result; 98 } 99 private function getUri() 100 { 101 if (\false !== $this->uri) { 102 $this->uri = $this->getMetadata('uri') ?? \false; 103 } 104 return $this->uri; 105 } 106 public function getSize(): ?int 107 { 108 if (null !== $this->size) { 109 return $this->size; 110 } 111 if (!isset($this->stream)) { 112 return null; 113 } 114 // Clear the stat cache if the stream has a URI 115 if ($uri = $this->getUri()) { 116 \clearstatcache(\true, $uri); 117 } 118 $stats = \fstat($this->stream); 119 if (isset($stats['size'])) { 120 $this->size = $stats['size']; 121 return $this->size; 122 } 123 return null; 124 } 125 public function tell(): int 126 { 127 if (!isset($this->stream)) { 128 throw new \RuntimeException('Stream is detached'); 129 } 130 if (\false === $result = @\ftell($this->stream)) { 131 throw new \RuntimeException('Unable to determine stream position: ' . (\error_get_last()['message'] ?? '')); 132 } 133 return $result; 134 } 135 public function eof(): bool 136 { 137 return !isset($this->stream) || \feof($this->stream); 138 } 139 public function isSeekable(): bool 140 { 141 return $this->seekable; 142 } 143 public function seek($offset, $whence = \SEEK_SET): void 144 { 145 if (!isset($this->stream)) { 146 throw new \RuntimeException('Stream is detached'); 147 } 148 if (!$this->seekable) { 149 throw new \RuntimeException('Stream is not seekable'); 150 } 151 if (-1 === \fseek($this->stream, $offset, $whence)) { 152 throw new \RuntimeException('Unable to seek to stream position "' . $offset . '" with whence ' . \var_export($whence, \true)); 153 } 154 } 155 public function rewind(): void 156 { 157 $this->seek(0); 158 } 159 public function isWritable(): bool 160 { 161 return $this->writable; 162 } 163 public function write($string): int 164 { 165 if (!isset($this->stream)) { 166 throw new \RuntimeException('Stream is detached'); 167 } 168 if (!$this->writable) { 169 throw new \RuntimeException('Cannot write to a non-writable stream'); 170 } 171 // We can't know the size after writing anything 172 $this->size = null; 173 if (\false === $result = @\fwrite($this->stream, $string)) { 174 throw new \RuntimeException('Unable to write to stream: ' . (\error_get_last()['message'] ?? '')); 175 } 176 return $result; 177 } 178 public function isReadable(): bool 179 { 180 return $this->readable; 181 } 182 public function read($length): string 183 { 184 if (!isset($this->stream)) { 185 throw new \RuntimeException('Stream is detached'); 186 } 187 if (!$this->readable) { 188 throw new \RuntimeException('Cannot read from non-readable stream'); 189 } 190 if (\false === $result = @\fread($this->stream, $length)) { 191 throw new \RuntimeException('Unable to read from stream: ' . (\error_get_last()['message'] ?? '')); 192 } 193 return $result; 194 } 195 public function getContents(): string 196 { 197 if (!isset($this->stream)) { 198 throw new \RuntimeException('Stream is detached'); 199 } 200 $exception = null; 201 \set_error_handler(static function ($type, $message) use (&$exception) { 202 throw $exception = new \RuntimeException('Unable to read stream contents: ' . $message); 203 }); 204 try { 205 return \stream_get_contents($this->stream); 206 } catch (\Throwable $e) { 207 throw $e === $exception ? $e : new \RuntimeException('Unable to read stream contents: ' . $e->getMessage(), 0, $e); 208 } finally { 209 \restore_error_handler(); 210 } 211 } 212 /** 213 * @return mixed 214 */ 215 public function getMetadata($key = null) 216 { 217 if (null !== $key && !\is_string($key)) { 218 throw new \InvalidArgumentException('Metadata key must be a string'); 219 } 220 if (!isset($this->stream)) { 221 return $key ? null : []; 222 } 223 $meta = \stream_get_meta_data($this->stream); 224 if (null === $key) { 225 return $meta; 226 } 227 return $meta[$key] ?? null; 228 } 229 private static function openZvalStream(string $body) 230 { 231 static $wrapper; 232 $wrapper ?? \stream_wrapper_register('Nyholm-Psr7-Zval', $wrapper = \get_class(new class 233 { 234 public $context; 235 private $data; 236 private $position = 0; 237 public function stream_open(): bool 238 { 239 $this->data = \stream_context_get_options($this->context)['Nyholm-Psr7-Zval']['data']; 240 \stream_context_set_option($this->context, 'Nyholm-Psr7-Zval', 'data', null); 241 return \true; 242 } 243 public function stream_read(int $count): string 244 { 245 $result = \substr($this->data, $this->position, $count); 246 $this->position += \strlen($result); 247 return $result; 248 } 249 public function stream_write(string $data): int 250 { 251 $this->data = \substr_replace($this->data, $data, $this->position, \strlen($data)); 252 $this->position += \strlen($data); 253 return \strlen($data); 254 } 255 public function stream_tell(): int 256 { 257 return $this->position; 258 } 259 public function stream_eof(): bool 260 { 261 return \strlen($this->data) <= $this->position; 262 } 263 public function stream_stat(): array 264 { 265 return [ 266 'mode' => 33206, 267 // POSIX_S_IFREG | 0666 268 'nlink' => 1, 269 'rdev' => -1, 270 'size' => \strlen($this->data), 271 'blksize' => -1, 272 'blocks' => -1, 273 ]; 274 } 275 public function stream_seek(int $offset, int $whence): bool 276 { 277 if (\SEEK_SET === $whence && (0 <= $offset && \strlen($this->data) >= $offset)) { 278 $this->position = $offset; 279 } elseif (\SEEK_CUR === $whence && 0 <= $offset) { 280 $this->position += $offset; 281 } elseif (\SEEK_END === $whence && (0 > $offset && 0 <= $offset = \strlen($this->data) + $offset)) { 282 $this->position = $offset; 283 } else { 284 return \false; 285 } 286 return \true; 287 } 288 public function stream_set_option(): bool 289 { 290 return \true; 291 } 292 public function stream_truncate(int $new_size): bool 293 { 294 if ($new_size) { 295 $this->data = \substr($this->data, 0, $new_size); 296 $this->position = \min($this->position, $new_size); 297 } else { 298 $this->data = ''; 299 $this->position = 0; 300 } 301 return \true; 302 } 303 })); 304 $context = \stream_context_create(['Nyholm-Psr7-Zval' => ['data' => $body]]); 305 if (!$stream = @\fopen('Nyholm-Psr7-Zval://', 'r+', \false, $context)) { 306 \stream_wrapper_register('Nyholm-Psr7-Zval', $wrapper); 307 $stream = \fopen('Nyholm-Psr7-Zval://', 'r+', \false, $context); 308 } 309 return $stream; 310 } 311 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated : Sat Jun 13 09:38:55 2026 | Cross-referenced by PHPXref |