6 use Psr\Http\Message\StreamInterface;
9 use Wikimedia\AtEase\AtEase;
38 private static function quietCall( callable $func, array
$args, $fail, $msg ) {
40 if ( function_exists(
'error_clear_last' ) ) {
43 $ret = AtEase::quietCall( $func, ...
$args );
44 if ( $ret === $fail ) {
45 $err = error_get_last();
46 throw new RuntimeException(
"$msg: " . ( $err[
'message'] ??
'Unknown error' ) );
55 $this->fp =
self::quietCall(
'fopen', [ $filename,
'r' ],
false,
'Failed to open file' );
64 throw new RuntimeException(
'Stream is not open' );
76 }
catch ( Exception $ex ) {
79 }
catch ( Throwable $ex ) {
88 AtEase::quietCall(
'fclose', $this->fp );
100 if ( $this->size ===
false ) {
105 $stat = AtEase::quietCall(
'fstat', $this->fp );
106 $this->size = $stat[
'size'] ??
null;
115 return self::quietCall(
'ftell', [ $this->fp ], -1,
'Cannot determine stream position' );
120 return !$this->fp || AtEase::quietCall(
'feof', $this->fp );
127 public function seek( $offset, $whence = SEEK_SET ) {
129 self::quietCall(
'fseek', [ $this->fp, $offset, $whence ], -1,
'Seek failed' );
142 throw new RuntimeException(
'Stream is read-only' );
149 public function read( $length ) {
151 return self::quietCall(
'fread', [ $this->fp, $length ],
false,
'Read failed' );
156 return self::quietCall(
'stream_get_contents', [ $this->fp ],
false,
'Read failed' );
161 $ret =
self::quietCall(
'stream_get_meta_data', [ $this->fp ],
false,
'Metadata fetch failed' );
162 if ( $key !==
null ) {
163 $ret = $ret[$key] ??
null;