1: <?php
2:
3: namespace PHPixie\HTTP\Messages\Stream;
4:
5: use Psr\Http\Message\StreamInterface;
6: use RuntimeException;
7:
8: 9: 10:
11: class Implementation implements StreamInterface
12: {
13: 14: 15:
16: protected $uri;
17:
18: 19: 20:
21: protected $mode;
22:
23: 24: 25:
26: protected $resource;
27:
28: 29: 30:
31: protected $processed = false;
32:
33: 34: 35:
36: protected $isReadable;
37:
38: 39: 40:
41: protected $isWritable;
42:
43: 44: 45:
46: protected $isSeekable;
47:
48: 49: 50: 51: 52:
53: public function __construct($uri, $mode = 'r')
54: {
55: $this->uri = $uri;
56: $this->mode = $mode;
57: }
58:
59: 60: 61: 62: 63: 64:
65: public function resource($throwIfDetached = false)
66: {
67: if(!$this->processed) {
68:
69: if($this->resource !== false) {
70: $this->resource = fopen($this->uri, $this->mode);
71: }
72:
73: $this->processed = true;
74: }
75:
76: if($throwIfDetached && $this->resource === null) {
77: throw new RuntimeException("The resource has been detached");
78: }
79:
80: return $this->resource;
81: }
82:
83: 84: 85:
86: public function __toString()
87: {
88: if(($resource = $this->resource()) === null) {
89: return '';
90: }
91:
92: return stream_get_contents($resource, -1, 0);
93: }
94:
95: 96: 97:
98: public function close()
99: {
100: $resource = $this->detach();
101:
102: if ($resource !== null) {
103: fclose($resource);
104: }
105: }
106:
107: 108: 109:
110: public function detach()
111: {
112: $resource = $this->resource();
113: $this->resource = null;
114: return $resource;
115: }
116:
117: 118: 119:
120: public function getSize()
121: {
122: if(($resource = $this->resource()) === null) {
123: return null;
124: }
125:
126: $stats = fstat($resource);
127: return $stats['size'];
128: }
129:
130: 131: 132:
133: public function tell()
134: {
135: return ftell($this->resource(true));
136: }
137:
138: 139: 140:
141: public function eof()
142: {
143: if(($resource = $this->resource()) === null) {
144: return true;
145: }
146:
147: return feof($resource);
148: }
149:
150: 151: 152:
153: public function isSeekable()
154: {
155: if(($resource = $this->resource()) === null) {
156: return false;
157: }
158:
159: if($this->isSeekable === null) {
160: $meta = stream_get_meta_data($resource);
161: $this->isSeekable = $meta['seekable'];
162: }
163:
164: return $this->isSeekable;
165: }
166:
167: 168: 169:
170: public function isWritable()
171: {
172: if(($resource = $this->resource()) === null) {
173: return false;
174: }
175:
176: if($this->isWritable === null) {
177: $meta = stream_get_meta_data($resource);
178: $this->isWritable = is_writable($meta['uri']);
179: }
180:
181: return $this->isWritable;
182: }
183:
184: 185: 186:
187: public function isReadable()
188: {
189: if(($resource = $this->resource()) === null) {
190: return false;
191: }
192:
193: if($this->isReadable === null) {
194: $meta = stream_get_meta_data($resource);
195: $mode = $meta['mode'];
196: $this->isReadable = strstr($mode, 'r') || strstr($mode, '+');
197: }
198:
199: return $this->isReadable;
200: }
201:
202: 203: 204:
205: public function seek($offset, $whence = SEEK_SET)
206: {
207: if(!$this->isSeekable()) {
208: throw new RuntimeException("The stream is not seakable");
209: }
210:
211: fseek($this->resource(), $offset, $whence);
212: }
213:
214: 215: 216:
217: public function rewind()
218: {
219: $this->seek(0);
220: }
221:
222: 223: 224:
225: public function write($string)
226: {
227: if(!$this->isWritable()) {
228: throw new RuntimeException("The stream is not writable");
229: }
230:
231: return fwrite($this->resource(), $string);
232: }
233:
234: 235: 236:
237: public function read($length)
238: {
239: if(!$this->isReadable()) {
240: throw new RuntimeException("The stream is not readable");
241: }
242:
243: return fread($this->resource(), $length);
244: }
245:
246: 247: 248:
249: public function getContents()
250: {
251: return stream_get_contents($this->resource(true));
252: }
253:
254: 255: 256:
257: public function getMetadata($key = null)
258: {
259: if(($resource = $this->resource()) === null) {
260: $metadata = array();
261:
262: }else{
263: $metadata = stream_get_meta_data($resource);
264: }
265:
266: if ($key === null) {
267: return $metadata;
268: }
269:
270: if (!array_key_exists($key, $metadata)) {
271: return null;
272: }
273:
274: return $metadata[$key];
275: }
276:
277:
278: }