resource = $resource; } public static function fromString(string $content): self { $r = fopen('php://temp', 'r+'); fwrite($r, $content); rewind($r); return new self($r); } public function __toString(): string { if (!$this->resource) { return ''; } $pos = ftell($this->resource); rewind($this->resource); $contents = stream_get_contents($this->resource); fseek($this->resource, $pos); return $contents ?: ''; } public function close(): void { fclose($this->resource); } public function detach() { $r = $this->resource; $this->resource = null; return $r; } public function getSize(): ?int { return null; } public function tell(): int { return ftell($this->resource); } public function eof(): bool { return feof($this->resource); } public function isSeekable(): bool { return true; } public function seek($offset, $whence = SEEK_SET): void { fseek($this->resource, $offset, $whence); } public function rewind(): void { rewind($this->resource); } public function isWritable(): bool { return true; } public function write($string): int { return fwrite($this->resource, $string); } public function isReadable(): bool { return true; } public function read($length): string { return fread($this->resource, $length); } public function getContents(): string { return stream_get_contents($this->resource); } public function getMetadata($key = null) { return null; } }