30     private $customMetadata;
 
   48         if (!is_resource($stream)) {
 
   49             throw new \InvalidArgumentException(
'Stream must be a resource');
 
   52         if (isset($options[
'size'])) {
 
   53             $this->size = $options[
'size'];
 
   56         $this->customMetadata = isset($options[
'metadata'])
 
   57             ? $options[
'metadata']
 
   60         $this->stream = $stream;
 
   61         $meta = stream_get_meta_data($this->stream);
 
   62         $this->seekable = $meta[
'seekable'];
 
   63         $this->readable = (bool)preg_match(self::READABLE_MODES, $meta[
'mode']);
 
   64         $this->writable = (bool)preg_match(self::WRITABLE_MODES, $meta[
'mode']);
 
   80             return (
string) stream_get_contents($this->stream);
 
   81         } 
catch (\Exception $e) {
 
   88         if (!isset($this->stream)) {
 
   89             throw new \RuntimeException(
'Stream is detached');
 
   92         $contents = stream_get_contents($this->stream);
 
   94         if ($contents === 
false) {
 
   95             throw new \RuntimeException(
'Unable to read stream contents');
 
  103         if (isset($this->stream)) {
 
  104             if (is_resource($this->stream)) {
 
  105                 fclose($this->stream);
 
  113         if (!isset($this->stream)) {
 
  117         $result = $this->stream;
 
  118         unset($this->stream);
 
  119         $this->size = $this->uri = 
null;
 
  120         $this->readable = $this->writable = $this->seekable = 
false;
 
  127         if ($this->size !== 
null) {
 
  131         if (!isset($this->stream)) {
 
  137             clearstatcache(
true, $this->uri);
 
  140         $stats = fstat($this->stream);
 
  141         if (isset($stats[
'size'])) {
 
  142             $this->size = $stats[
'size'];
 
  151         return $this->readable;
 
  156         return $this->writable;
 
  161         return $this->seekable;
 
  166         if (!isset($this->stream)) {
 
  167             throw new \RuntimeException(
'Stream is detached');
 
  170         return feof($this->stream);
 
  175         if (!isset($this->stream)) {
 
  176             throw new \RuntimeException(
'Stream is detached');
 
  179         $result = ftell($this->stream);
 
  181         if ($result === 
false) {
 
  182             throw new \RuntimeException(
'Unable to determine stream position');
 
  193     public function seek($offset, $whence = SEEK_SET)
 
  195         $whence = (int) $whence;
 
  197         if (!isset($this->stream)) {
 
  198             throw new \RuntimeException(
'Stream is detached');
 
  200         if (!$this->seekable) {
 
  201             throw new \RuntimeException(
'Stream is not seekable');
 
  203         if (fseek($this->stream, $offset, $whence) === -1) {
 
  204             throw new \RuntimeException(
'Unable to seek to stream position ' 
  205                 . $offset . 
' with whence ' . var_export($whence, 
true));
 
  211         if (!isset($this->stream)) {
 
  212             throw new \RuntimeException(
'Stream is detached');
 
  214         if (!$this->readable) {
 
  215             throw new \RuntimeException(
'Cannot read from non-readable stream');
 
  218             throw new \RuntimeException(
'Length parameter cannot be negative');
 
  225         $string = fread($this->stream, $length);
 
  226         if (
false === $string) {
 
  227             throw new \RuntimeException(
'Unable to read from stream');
 
  235         if (!isset($this->stream)) {
 
  236             throw new \RuntimeException(
'Stream is detached');
 
  238         if (!$this->writable) {
 
  239             throw new \RuntimeException(
'Cannot write to a non-writable stream');
 
  244         $result = fwrite($this->stream, $string);
 
  246         if ($result === 
false) {
 
  247             throw new \RuntimeException(
'Unable to write to stream');
 
  255         if (!isset($this->stream)) {
 
  256             return $key ? null : [];
 
  258             return $this->customMetadata + stream_get_meta_data($this->stream);
 
  259         } elseif (isset($this->customMetadata[$key])) {
 
  260             return $this->customMetadata[$key];
 
  263         $meta = stream_get_meta_data($this->stream);
 
  265         return isset($meta[$key]) ? $meta[$key] : 
null;