1<?php 2namespace GuzzleHttp\Stream; 3 4use GuzzleHttp\Stream\Exception\CannotAttachException; 5 6/** 7 * Stream decorator trait 8 * @property StreamInterface stream 9 */ 10trait StreamDecoratorTrait 11{ 12 /** 13 * @param StreamInterface $stream Stream to decorate 14 */ 15 public function __construct(StreamInterface $stream) 16 { 17 $this->stream = $stream; 18 } 19 20 /** 21 * Magic method used to create a new stream if streams are not added in 22 * the constructor of a decorator (e.g., LazyOpenStream). 23 */ 24 public function __get($name) 25 { 26 if ($name == 'stream') { 27 $this->stream = $this->createStream(); 28 return $this->stream; 29 } 30 31 throw new \UnexpectedValueException("$name not found on class"); 32 } 33 34 public function __toString() 35 { 36 try { 37 $this->seek(0); 38 return $this->getContents(); 39 } catch (\Exception $e) { 40 // Really, PHP? https://bugs.php.net/bug.php?id=53648 41 trigger_error('StreamDecorator::__toString exception: ' 42 . (string) $e, E_USER_ERROR); 43 return ''; 44 } 45 } 46 47 public function getContents() 48 { 49 return Utils::copyToString($this); 50 } 51 52 /** 53 * Allow decorators to implement custom methods 54 * 55 * @param string $method Missing method name 56 * @param array $args Method arguments 57 * 58 * @return mixed 59 */ 60 public function __call($method, array $args) 61 { 62 $result = call_user_func_array(array($this->stream, $method), $args); 63 64 // Always return the wrapped object if the result is a return $this 65 return $result === $this->stream ? $this : $result; 66 } 67 68 public function close() 69 { 70 $this->stream->close(); 71 } 72 73 public function getMetadata($key = null) 74 { 75 return $this->stream->getMetadata($key); 76 } 77 78 public function detach() 79 { 80 return $this->stream->detach(); 81 } 82 83 public function attach($stream) 84 { 85 throw new CannotAttachException(); 86 } 87 88 public function getSize() 89 { 90 return $this->stream->getSize(); 91 } 92 93 public function eof() 94 { 95 return $this->stream->eof(); 96 } 97 98 public function tell() 99 { 100 return $this->stream->tell(); 101 } 102 103 public function isReadable() 104 { 105 return $this->stream->isReadable(); 106 } 107 108 public function isWritable() 109 { 110 return $this->stream->isWritable(); 111 } 112 113 public function isSeekable() 114 { 115 return $this->stream->isSeekable(); 116 } 117 118 public function seek($offset, $whence = SEEK_SET) 119 { 120 return $this->stream->seek($offset, $whence); 121 } 122 123 public function read($length) 124 { 125 return $this->stream->read($length); 126 } 127 128 public function write($string) 129 { 130 return $this->stream->write($string); 131 } 132 133 /** 134 * Implement in subclasses to dynamically create streams when requested. 135 * 136 * @return StreamInterface 137 * @throws \BadMethodCallException 138 */ 139 protected function createStream() 140 { 141 throw new \BadMethodCallException('createStream() not implemented in ' 142 . get_class($this)); 143 } 144} 145