Chris@0: stream = $stream; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Magic method used to create a new stream if streams are not added in Chris@0: * the constructor of a decorator (e.g., LazyOpenStream). Chris@0: * Chris@0: * @param string $name Name of the property (allows "stream" only). Chris@0: * Chris@0: * @return StreamInterface Chris@0: */ Chris@0: public function __get($name) Chris@0: { Chris@0: if ($name == 'stream') { Chris@0: $this->stream = $this->createStream(); Chris@0: return $this->stream; Chris@0: } Chris@0: Chris@0: throw new \UnexpectedValueException("$name not found on class"); Chris@0: } Chris@0: Chris@0: public function __toString() Chris@0: { Chris@0: try { Chris@0: if ($this->isSeekable()) { Chris@0: $this->seek(0); Chris@0: } Chris@0: return $this->getContents(); Chris@0: } catch (\Exception $e) { Chris@0: // Really, PHP? https://bugs.php.net/bug.php?id=53648 Chris@0: trigger_error('StreamDecorator::__toString exception: ' Chris@0: . (string) $e, E_USER_ERROR); Chris@0: return ''; Chris@0: } Chris@0: } Chris@0: Chris@0: public function getContents() Chris@0: { Chris@0: return copy_to_string($this); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Allow decorators to implement custom methods Chris@0: * Chris@0: * @param string $method Missing method name Chris@0: * @param array $args Method arguments Chris@0: * Chris@0: * @return mixed Chris@0: */ Chris@0: public function __call($method, array $args) Chris@0: { Chris@0: $result = call_user_func_array([$this->stream, $method], $args); Chris@0: Chris@0: // Always return the wrapped object if the result is a return $this Chris@0: return $result === $this->stream ? $this : $result; Chris@0: } Chris@0: Chris@0: public function close() Chris@0: { Chris@0: $this->stream->close(); Chris@0: } Chris@0: Chris@0: public function getMetadata($key = null) Chris@0: { Chris@0: return $this->stream->getMetadata($key); Chris@0: } Chris@0: Chris@0: public function detach() Chris@0: { Chris@0: return $this->stream->detach(); Chris@0: } Chris@0: Chris@0: public function getSize() Chris@0: { Chris@0: return $this->stream->getSize(); Chris@0: } Chris@0: Chris@0: public function eof() Chris@0: { Chris@0: return $this->stream->eof(); Chris@0: } Chris@0: Chris@0: public function tell() Chris@0: { Chris@0: return $this->stream->tell(); Chris@0: } Chris@0: Chris@0: public function isReadable() Chris@0: { Chris@0: return $this->stream->isReadable(); Chris@0: } Chris@0: Chris@0: public function isWritable() Chris@0: { Chris@0: return $this->stream->isWritable(); Chris@0: } Chris@0: Chris@0: public function isSeekable() Chris@0: { Chris@0: return $this->stream->isSeekable(); Chris@0: } Chris@0: Chris@0: public function rewind() Chris@0: { Chris@0: $this->seek(0); Chris@0: } Chris@0: Chris@0: public function seek($offset, $whence = SEEK_SET) Chris@0: { Chris@0: $this->stream->seek($offset, $whence); Chris@0: } Chris@0: Chris@0: public function read($length) Chris@0: { Chris@0: return $this->stream->read($length); Chris@0: } Chris@0: Chris@0: public function write($string) Chris@0: { Chris@0: return $this->stream->write($string); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Implement in subclasses to dynamically create streams when requested. Chris@0: * Chris@0: * @return StreamInterface Chris@0: * @throws \BadMethodCallException Chris@0: */ Chris@0: protected function createStream() Chris@0: { Chris@0: throw new \BadMethodCallException('Not implemented'); Chris@0: } Chris@0: }