PluginProbe ʕ •ᴥ•ʔ
Check & Log Email – Easy Email Testing & Mail logging / 2.0.15
Check & Log Email – Easy Email Testing & Mail logging v2.0.15
2.0.15 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 2.0 2.0.1 2.0.10 2.0.11 2.0.12 2.0.13 2.0.13.1 2.0.13.2 2.0.14 2.0.2 2.0.3 2.0.4 2.0.5 2.0.5.1 2.0.6 2.0.7 2.0.8 2.0.9 trunk 0.5.7 0.6.0 0.6.1 0.6.2 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.12.1 1.0.13 1.0.13.1 1.0.2 1.0.3
check-email / vendor / guzzlehttp / psr7 / src / Stream.php
check-email / vendor / guzzlehttp / psr7 / src Last commit date
Exception 1 week ago AppendStream.php 1 week ago BufferStream.php 1 week ago CachingStream.php 1 week ago DroppingStream.php 1 week ago FnStream.php 1 week ago Header.php 1 week ago HttpFactory.php 1 week ago InflateStream.php 1 week ago LazyOpenStream.php 1 week ago LimitStream.php 1 week ago Message.php 1 week ago MessageTrait.php 1 week ago MimeType.php 1 week ago MultipartStream.php 1 week ago NoSeekStream.php 1 week ago PumpStream.php 1 week ago Query.php 1 week ago Request.php 1 week ago Response.php 1 week ago Rfc7230.php 1 week ago ServerRequest.php 1 week ago Stream.php 1 week ago StreamDecoratorTrait.php 1 week ago StreamWrapper.php 1 week ago UploadedFile.php 1 week ago Uri.php 1 week ago UriComparator.php 1 week ago UriNormalizer.php 1 week ago UriResolver.php 1 week ago Utils.php 1 week ago
Stream.php
284 lines
1 <?php
2
3 declare(strict_types=1);
4
5 namespace GuzzleHttp\Psr7;
6
7 use Psr\Http\Message\StreamInterface;
8
9 /**
10 * PHP stream implementation.
11 */
12 class Stream implements StreamInterface
13 {
14 /**
15 * @see https://www.php.net/manual/en/function.fopen.php
16 * @see https://www.php.net/manual/en/function.gzopen.php
17 */
18 private const READABLE_MODES = '/r|a\+|ab\+|w\+|wb\+|x\+|xb\+|c\+|cb\+/';
19 private const WRITABLE_MODES = '/a|w|r\+|rb\+|rw|x|c/';
20
21 /** @var resource */
22 private $stream;
23 /** @var int|null */
24 private $size;
25 /** @var bool */
26 private $seekable;
27 /** @var bool */
28 private $readable;
29 /** @var bool */
30 private $writable;
31 /** @var string|null */
32 private $uri;
33 /** @var mixed[] */
34 private $customMetadata;
35
36 /**
37 * This constructor accepts an associative array of options.
38 *
39 * - size: (int) If a read stream would otherwise have an indeterminate
40 * size, but the size is known due to foreknowledge, then you can
41 * provide that size, in bytes.
42 * - metadata: (array) Any additional metadata to return when the metadata
43 * of the stream is accessed.
44 *
45 * @param resource $stream Stream resource to wrap.
46 * @param array{size?: int, metadata?: array} $options Associative array of options.
47 *
48 * @throws \InvalidArgumentException if the stream is not a stream resource
49 */
50 public function __construct($stream, array $options = [])
51 {
52 if (!is_resource($stream)) {
53 throw new \InvalidArgumentException('Stream must be a resource');
54 }
55
56 if (isset($options['size'])) {
57 $this->size = $options['size'];
58 }
59
60 $this->customMetadata = $options['metadata'] ?? [];
61 $this->stream = $stream;
62 $meta = stream_get_meta_data($this->stream);
63 $this->seekable = $meta['seekable'];
64 $this->readable = (bool) preg_match(self::READABLE_MODES, $meta['mode']);
65 $this->writable = (bool) preg_match(self::WRITABLE_MODES, $meta['mode']);
66 $this->uri = $this->getMetadata('uri');
67 }
68
69 /**
70 * Closes the stream when the destructed
71 */
72 public function __destruct()
73 {
74 $this->close();
75 }
76
77 public function __toString(): string
78 {
79 try {
80 if ($this->isSeekable()) {
81 $this->seek(0);
82 }
83
84 return $this->getContents();
85 } catch (\Throwable $e) {
86 if (\PHP_VERSION_ID >= 70400) {
87 throw $e;
88 }
89 trigger_error(sprintf('%s::__toString exception: %s', self::class, (string) $e), E_USER_ERROR);
90
91 return '';
92 }
93 }
94
95 public function getContents(): string
96 {
97 if (!isset($this->stream)) {
98 throw new \RuntimeException('Stream is detached');
99 }
100
101 if (!$this->readable) {
102 throw new \RuntimeException('Cannot read from non-readable stream');
103 }
104
105 return Utils::tryGetContents($this->stream);
106 }
107
108 public function close(): void
109 {
110 if (isset($this->stream)) {
111 if (is_resource($this->stream)) {
112 fclose($this->stream);
113 }
114 $this->detach();
115 }
116 }
117
118 public function detach()
119 {
120 if (!isset($this->stream)) {
121 return null;
122 }
123
124 $result = $this->stream;
125 unset($this->stream);
126 $this->size = $this->uri = null;
127 $this->readable = $this->writable = $this->seekable = false;
128
129 return $result;
130 }
131
132 public function getSize(): ?int
133 {
134 if ($this->size !== null) {
135 return $this->size;
136 }
137
138 if (!isset($this->stream)) {
139 return null;
140 }
141
142 // Clear the stat cache if the stream has a URI
143 if ($this->uri) {
144 clearstatcache(true, $this->uri);
145 }
146
147 $stats = fstat($this->stream);
148 if (is_array($stats) && isset($stats['size'])) {
149 $this->size = $stats['size'];
150
151 return $this->size;
152 }
153
154 return null;
155 }
156
157 public function isReadable(): bool
158 {
159 return $this->readable;
160 }
161
162 public function isWritable(): bool
163 {
164 return $this->writable;
165 }
166
167 public function isSeekable(): bool
168 {
169 return $this->seekable;
170 }
171
172 public function eof(): bool
173 {
174 if (!isset($this->stream)) {
175 throw new \RuntimeException('Stream is detached');
176 }
177
178 return feof($this->stream);
179 }
180
181 public function tell(): int
182 {
183 if (!isset($this->stream)) {
184 throw new \RuntimeException('Stream is detached');
185 }
186
187 $result = ftell($this->stream);
188
189 if ($result === false) {
190 throw new \RuntimeException('Unable to determine stream position');
191 }
192
193 return $result;
194 }
195
196 public function rewind(): void
197 {
198 $this->seek(0);
199 }
200
201 public function seek($offset, $whence = SEEK_SET): void
202 {
203 $whence = (int) $whence;
204
205 if (!isset($this->stream)) {
206 throw new \RuntimeException('Stream is detached');
207 }
208 if (!$this->seekable) {
209 throw new \RuntimeException('Stream is not seekable');
210 }
211 if (fseek($this->stream, $offset, $whence) === -1) {
212 throw new \RuntimeException('Unable to seek to stream position '
213 .$offset.' with whence '.var_export($whence, true));
214 }
215 }
216
217 public function read($length): string
218 {
219 if (!isset($this->stream)) {
220 throw new \RuntimeException('Stream is detached');
221 }
222 if (!$this->readable) {
223 throw new \RuntimeException('Cannot read from non-readable stream');
224 }
225 if ($length < 0) {
226 throw new \RuntimeException('Length parameter cannot be negative');
227 }
228
229 if (0 === $length) {
230 return '';
231 }
232
233 try {
234 $string = fread($this->stream, $length);
235 } catch (\Exception $e) {
236 throw new \RuntimeException('Unable to read from stream', 0, $e);
237 }
238
239 if (false === $string) {
240 throw new \RuntimeException('Unable to read from stream');
241 }
242
243 return $string;
244 }
245
246 public function write($string): int
247 {
248 if (!isset($this->stream)) {
249 throw new \RuntimeException('Stream is detached');
250 }
251 if (!$this->writable) {
252 throw new \RuntimeException('Cannot write to a non-writable stream');
253 }
254
255 // We can't know the size after writing anything
256 $this->size = null;
257 $result = fwrite($this->stream, $string);
258
259 if ($result === false) {
260 throw new \RuntimeException('Unable to write to stream');
261 }
262
263 return $result;
264 }
265
266 /**
267 * @return mixed
268 */
269 public function getMetadata($key = null)
270 {
271 if (!isset($this->stream)) {
272 return $key ? null : [];
273 } elseif (!$key) {
274 return $this->customMetadata + stream_get_meta_data($this->stream);
275 } elseif (isset($this->customMetadata[$key])) {
276 return $this->customMetadata[$key];
277 }
278
279 $meta = stream_get_meta_data($this->stream);
280
281 return $meta[$key] ?? null;
282 }
283 }
284