stream = $stream; } /** * Return the full size of the buffer. If the underlying stream does * not report it's size, try to fetch the size from the Content-Length * response header. * * @return int The size of the stream. */ public function getSize() : ?int { return $this->stream->getSize() ?: $this->getSizeFromMetadata(); } /** * Attempt to fetch the size from the Content-Length response header. * If we cannot, return 0. * * @return int The Size of the stream */ private function getSizeFromMetadata() : int { foreach ($this->stream->getMetadata('wrapper_data') as $value) { if (\substr($value, 0, 15) == "Content-Length:") { return (int) \substr($value, 16); } } return 0; } /** * Read bytes from the underlying buffer, retrying until we have read * enough bytes or we cannot read any more. We do this because the * internal C code for filling a buffer does not account for when * we try to read large chunks from a user-land stream that does not * return enough bytes. * * @param int $length The number of bytes to read. * @return string Read bytes from the underlying stream. */ public function read($length) : string { $data = ''; do { $moreData = $this->stream->read($length); $data .= $moreData; $readLength = \strlen($moreData); $length -= $readLength; } while ($length > 0 && $readLength > 0); return $data; } }