>bRZ慰'r9B#̙Qu@~~W189@O#Ms=vlCF9 CTcE+֠{'w%*һP40\~_G]KN !1lei;Ze9VLV gg|iu~e{P}kUqWs,Ĭa.`YD@ mu>bM|:; _R P<9KTq6JQ*+j¸5H<07- J}52x<,쫰3uI$eދ"~E nQfoNJCcDJu؂Q `;vmJE@30擜EZtx2+P/fRk? $?Tlݵgev?rPr<?lIm/PU ܧpdl `+UܺL!]QU9d'h/D,_q+L<2+P/fRk?:_ȹR5>ʛ쇊⨵\j9iFԔ1Jp`1kYVj//Ez$x)Y. >]/&Qot^)"^YKQX, Xi aaoAz [T(1SIZ!hkdX^uvOو)nՈjj2yy" O!Q&evޤvwXo^ 4PнLjrdF;A$T8y˗νS-ӖcĉJ} e-rJ@rⶼpK[p{ztԑ})Bo C 7 ԜZ#/S8+\=y nHK2iD )h}g m +?Ah}g,(VdB BDD+⾾N6Z+zO+P6ֱ4 %P㨬;QGfQV Ht΅@D!PN(z#tr`/‘z=xBZ@Cu`%:7i*r.i,𧯺Xh.as$0)}2CK1RVmpuT` 3#/ aI 9(ԢR^Ufa?J션!~߼݄NMHg+ȟ6A_ِ/Muin 6YřX)97wy[nOTٹWiV)v }2[d8_2!.B)p+0/\c3F#h*]0h=aD"3R _)[lh `3̗ ].Ao7Idv,&ߣTK IjT*#$_\o>t)k@q[]@OPA^U񥓈2GOBIU.eu·hUb1ne xub6|&HBfХW n\̤@՞עt/BӴ\q`vZI52]:(3!h/К6eMM8>˹^Yvx5h>Ou8G*7"A/_5sw ooCu_$u%N!2H 4G |G0_rr"Ƃ+(wqHxƿi%D=뵕3re{Iܠ =CJMf"@e K|=³Dd eslwgtBaI ̕>RGJ%5p¨*#sl1K7EdڐSxٮZ{q4ǥ־I%&m5Xc.TCNj\c$'J/%wgFN5K]OcnpH#$b,7Y*&?0bg&Ar2K$qG{xf ?QEސ]cT4!mU5]#~(\T6#Wt-TΕ##.f3JV&ߤ>.qW[jTYhI,VR Gss=IjrOy/y?4\}B8Z%UնgkZ mtC>/AÄ0$T^ 0 Y$iiV?i><x`)ف;Fl8Sd2ʷ 8b(Ǯ/W1spxXy_j-<phr%E.JY0~L4xRJm2f $0)}2C$sde!zR!3#/ aI 9ZiHyw;BAU9ÜA/7-*K4*@pmB^ ~謐L22j梟OЬTHqQOqdsYB1LlrqW}PoE)d鞌7g>믟r#޵M4f@ක0kI6/aB s V6W¸7m R(X۾`1kTL]oluqLPs(P 5} g&e 3~ 5ڹ'-+r?EˏC3i=mN;B[b x jI]*9<|\at֮0gL$m'K&vjoB3b8I#e>"/I?c"/R "iYEPAge s:]--vYH+|Okx8 o3O=[V]:E{my5q.}L-ޑY~lu ڹ"?3V@T"9cT|IŨ699+n&0~WqՍQ֣C$Or9DЇQzb+XNAGCK} return null; } public function isReadable(): bool { return $this->readable; } public function isWritable(): bool { return $this->writable; } public function isSeekable(): bool { return $this->seekable; } public function eof(): bool { if (!isset($this->stream)) { throw new \RuntimeException('Stream is detached'); } return feof($this->stream); } public function tell(): int { if (!isset($this->stream)) { throw new \RuntimeException('Stream is detached'); } $result = ftell($this->stream); if ($result === false) { throw new \RuntimeException('Unable to determine stream position'); } return $result; } public function rewind(): void { $this->seek(0); } public function seek($offset, $whence = SEEK_SET): void { $whence = (int) $whence; if (!isset($this->stream)) { throw new \RuntimeException('Stream is detached'); } if (!$this->seekable) { throw new \RuntimeException('Stream is not seekable'); } if (fseek($this->stream, $offset, $whence) === -1) { throw new \RuntimeException('Unable to seek to stream position ' .$offset.' with whence '.var_export($whence, true)); } } public function read($length): string { if (!isset($this->stream)) { throw new \RuntimeException('Stream is detached'); } if (!$this->readable) { throw new \RuntimeException('Cannot read from non-readable stream'); } if ($length < 0) { throw new \RuntimeException('Length parameter cannot be negative'); } if (0 === $length) { return ''; } try { $string = fread($this->stream, $length); } catch (\Exception $e) { throw new \RuntimeException('Unable to read from stream', 0, $e); } if (false === $string) { throw new \RuntimeException('Unable to read from stream'); } return $string; } public function write($string): int { if (!isset($this->stream)) { throw new \RuntimeException('Stream is detached'); } if (!$this->writable) { throw new \RuntimeException('Cannot write to a non-writable stream'); } // We can't know the size after writing anything $this->size = null; $result = fwrite($this->stream, $string); if ($result === false) { throw new \RuntimeException('Unable to write to stream'); } return $result; } /** * @return mixed */ public function getMetadata($key = null) { if (!isset($this->stream)) { return $key ? null : []; } elseif (!$key) { return $this->customMetadata + stream_get_meta_data($this->stream); } elseif (isset($this->customMetadata[$key])) { return $this->customMetadata[$key]; } $meta = stream_get_meta_data($this->stream); return $meta[$key] ?? null; } }