scratch – Blame information for rev 87

Subversion Repositories:
Rev:
Rev Author Line No. Line
87 office 1 <?php
2 namespace GuzzleHttp\Stream;
3  
4 /**
5 * PHP stream implementation
6 */
7 class Stream implements MetadataStreamInterface
8 {
9 private $stream;
10 private $size;
11 private $seekable;
12 private $readable;
13 private $writable;
14 private $uri;
15  
16 /** @var array Hash of readable and writable stream types */
17 private static $readWriteHash = [
18 'read' => [
19 'r' => true, 'w+' => true, 'r+' => true, 'x+' => true, 'c+' => true,
20 'rb' => true, 'w+b' => true, 'r+b' => true, 'x+b' => true,
21 'c+b' => true, 'rt' => true, 'w+t' => true, 'r+t' => true,
22 'x+t' => true, 'c+t' => true, 'a+' => true
23 ],
24 'write' => [
25 'w' => true, 'w+' => true, 'rw' => true, 'r+' => true, 'x+' => true,
26 'c+' => true, 'wb' => true, 'w+b' => true, 'r+b' => true,
27 'x+b' => true, 'c+b' => true, 'w+t' => true, 'r+t' => true,
28 'x+t' => true, 'c+t' => true, 'a' => true, 'a+' => true
29 ]
30 ];
31  
32 /**
33 * Create a new stream based on the input type
34 *
35 * @param resource|string|StreamInterface $resource Entity body data
36 * @param int $size Size of the data contained in the resource
37 *
38 * @return Stream
39 * @throws \InvalidArgumentException if the $resource arg is not valid.
40 */
41 public static function factory($resource = '', $size = null)
42 {
43 $type = gettype($resource);
44  
45 if ($type == 'string') {
46 $stream = fopen('php://temp', 'r+');
47 if ($resource !== '') {
48 fwrite($stream, $resource);
49 fseek($stream, 0);
50 }
51 return new self($stream);
52 }
53  
54 if ($type == 'resource') {
55 return new self($resource, $size);
56 }
57  
58 if ($resource instanceof StreamInterface) {
59 return $resource;
60 }
61  
62 if ($type == 'object' && method_exists($resource, '__toString')) {
63 return self::factory((string) $resource, $size);
64 }
65  
66 throw new \InvalidArgumentException('Invalid resource type: ' . $type);
67 }
68  
69 /**
70 * @param resource $stream Stream resource to wrap
71 * @param int $size Size of the stream in bytes. Only pass if the
72 * size cannot be obtained from the stream.
73 *
74 * @throws \InvalidArgumentException if the stream is not a stream resource
75 */
76 public function __construct($stream, $size = null)
77 {
78 if (!is_resource($stream)) {
79 throw new \InvalidArgumentException('Stream must be a resource');
80 }
81  
82 $this->size = $size;
83 $this->stream = $stream;
84 $meta = stream_get_meta_data($this->stream);
85 $this->seekable = $meta['seekable'];
86 $this->readable = isset(self::$readWriteHash['read'][$meta['mode']]);
87 $this->writable = isset(self::$readWriteHash['write'][$meta['mode']]);
88 $this->uri = isset($meta['uri']) ? $meta['uri'] : null;
89 }
90  
91 /**
92 * Closes the stream when the destructed
93 */
94 public function __destruct()
95 {
96 $this->close();
97 }
98  
99 public function __toString()
100 {
101 if (!$this->stream) {
102 return '';
103 }
104  
105 $this->seek(0);
106  
107 return (string) stream_get_contents($this->stream);
108 }
109  
110 public function getContents($maxLength = -1)
111 {
112 return $this->stream
113 ? stream_get_contents($this->stream, $maxLength)
114 : '';
115 }
116  
117 public function close()
118 {
119 if (is_resource($this->stream)) {
120 fclose($this->stream);
121 }
122  
123 $this->detach();
124 }
125  
126 public function detach()
127 {
128 $result = $this->stream;
129 $this->stream = $this->size = $this->uri = null;
130 $this->readable = $this->writable = $this->seekable = false;
131  
132 return $result;
133 }
134  
135 public function getSize()
136 {
137 if ($this->size !== null) {
138 return $this->size;
139 }
140  
141 if (!$this->stream) {
142 return null;
143 }
144  
145 // Clear the stat cache if the stream has a URI
146 if ($this->uri) {
147 clearstatcache(true, $this->uri);
148 }
149  
150 $stats = fstat($this->stream);
151 if (isset($stats['size'])) {
152 $this->size = $stats['size'];
153 return $this->size;
154 }
155  
156 return null;
157 }
158  
159 public function isReadable()
160 {
161 return $this->readable;
162 }
163  
164 public function isWritable()
165 {
166 return $this->writable;
167 }
168  
169 public function isSeekable()
170 {
171 return $this->seekable;
172 }
173  
174 public function eof()
175 {
176 return $this->stream && feof($this->stream);
177 }
178  
179 public function tell()
180 {
181 return $this->stream ? ftell($this->stream) : false;
182 }
183  
184 public function setSize($size)
185 {
186 $this->size = $size;
187  
188 return $this;
189 }
190  
191 public function seek($offset, $whence = SEEK_SET)
192 {
193 return $this->seekable
194 ? fseek($this->stream, $offset, $whence) === 0
195 : false;
196 }
197  
198 public function read($length)
199 {
200 return $this->readable ? fread($this->stream, $length) : '';
201 }
202  
203 public function write($string)
204 {
205 // We can't know the size after writing anything
206 $this->size = null;
207  
208 return $this->writable ? fwrite($this->stream, $string) : false;
209 }
210  
211 public function flush()
212 {
213 return $this->stream ? fflush($this->stream) : false;
214 }
215  
216 /**
217 * Get stream metadata as an associative array or retrieve a specific key.
218 *
219 * The keys returned are identical to the keys returned from PHP's
220 * stream_get_meta_data() function.
221 *
222 * @param string $key Specific metadata to retrieve.
223 *
224 * @return array|mixed|null Returns an associative array if no key is
225 * no key is provided. Returns a specific key
226 * value if a key is provided and the value is
227 * found, or null if the key is not found.
228 * @see http://php.net/manual/en/function.stream-get-meta-data.php
229 */
230 public function getMetadata($key = null)
231 {
232 $meta = $this->stream ? stream_get_meta_data($this->stream) : [];
233  
234 return !$key ? $meta : (isset($meta[$key]) ? $meta[$key] : null);
235 }
236 }