1 <?php 2 3 declare(strict_types=1); 4 5 namespace GuzzleHttp\Psr7; 6 7 use Psr\Http\Message\StreamInterface; 8 9 /** 10 * Converts Guzzle streams into PHP stream resources. 11 * 12 * @see https://www.php.net/streamwrapper 13 */ 14 final class StreamWrapper 15 { 16 /** @var resource */ 17 public $context; 18 19 /** @var StreamInterface */ 20 private $stream; 21 22 /** @var string r, r+, or w */ 23 private $mode; 24 25 /** 26 * Returns a resource representing the stream. 27 * 28 * @param StreamInterface $stream The stream to get a resource for 29 * 30 * @return resource 31 * 32 * @throws \InvalidArgumentException if stream is not readable or writable 33 */ 34 public static function getResource(StreamInterface $stream) 35 { 36 self::register(); 37 38 if ($stream->isReadable()) { 39 $mode = $stream->isWritable() ? 'r+' : 'r'; 40 } elseif ($stream->isWritable()) { 41 $mode = 'w'; 42 } else { 43 throw new \InvalidArgumentException('The stream must be readable, ' 44 . 'writable, or both.'); 45 } 46 47 return fopen('guzzle://stream', $mode, false, self::createStreamContext($stream)); 48 } 49 50 /** 51 * Creates a stream context that can be used to open a stream as a php stream resource. 52 * 53 * @return resource 54 */ 55 public static function createStreamContext(StreamInterface $stream) 56 { 57 return stream_context_create([ 58 'guzzle' => ['stream' => $stream] 59 ]); 60 } 61 62 /** 63 * Registers the stream wrapper if needed 64 */ 65 public static function register(): void 66 { 67 if (!in_array('guzzle', stream_get_wrappers())) { 68 stream_wrapper_register('guzzle', __CLASS__); 69 } 70 } 71 72 public function stream_open(string $path, string $mode, int $options, string &$opened_path = null): bool 73 { 74 $options = stream_context_get_options($this->context); 75 76 if (!isset($options['guzzle']['stream'])) { 77 return false; 78 } 79 80 $this->mode = $mode; 81 $this->stream = $options['guzzle']['stream']; 82 83 return true; 84 } 85 86 public function stream_read(int $count): string 87 { 88 return $this->stream->read($count); 89 } 90 91 public function stream_write(string $data): int 92 { 93 return $this->stream->write($data); 94 } 95 96 public function stream_tell(): int 97 { 98 return $this->stream->tell(); 99 } 100 101 public function stream_eof(): bool 102 { 103 return $this->stream->eof(); 104 } 105 106 public function stream_seek(int $offset, int $whence): bool 107 { 108 $this->stream->seek($offset, $whence); 109 110 return true; 111 } 112 113 /** 114 * @return resource|false 115 */ 116 public function stream_cast(int $cast_as) 117 { 118 $stream = clone($this->stream); 119 $resource = $stream->detach(); 120 121 return $resource ?? false; 122 } 123 124 /** 125 * @return array<int|string, int> 126 */ 127 public function stream_stat(): array 128 { 129 static $modeMap = [ 130 'r' => 33060, 131 'rb' => 33060, 132 'r+' => 33206, 133 'w' => 33188, 134 'wb' => 33188 135 ]; 136 137 return [ 138 'dev' => 0, 139 'ino' => 0, 140 'mode' => $modeMap[$this->mode], 141 'nlink' => 0, 142 'uid' => 0, 143 'gid' => 0, 144 'rdev' => 0, 145 'size' => $this->stream->getSize() ?: 0, 146 'atime' => 0, 147 'mtime' => 0, 148 'ctime' => 0, 149 'blksize' => 0, 150 'blocks' => 0 151 ]; 152 } 153 154 /** 155 * @return array<int|string, int> 156 */ 157 public function url_stat(string $path, int $flags): array 158 { 159 return [ 160 'dev' => 0, 161 'ino' => 0, 162 'mode' => 0, 163 'nlink' => 0, 164 'uid' => 0, 165 'gid' => 0, 166 'rdev' => 0, 167 'size' => 0, 168 'atime' => 0, 169 'mtime' => 0, 170 'ctime' => 0, 171 'blksize' => 0, 172 'blocks' => 0 173 ]; 174 } 175 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body