ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
Stream.php
Go to the documentation of this file.
1<?php
2
4
6
17class Stream implements FileStream
18{
19 const MASK_ACCESS_READ = 01;
22
23 private static $accessMap = [
44 ];
45
49 private $readable;
53 private $writeable;
57 private $seekable;
61 private $stream;
65 private $size;
69 private $uri;
74
75
82 public function __construct($stream, StreamOptions $options = null)
83 {
84 if (!is_resource($stream)) {
85 throw new \InvalidArgumentException('Stream must be a valid resource but "' . gettype($stream) . '" was given.');
86 }
87
88 if ($options !== null) {
89 $this->customMetadata = $options->getMetadata();
90 $this->size = ($options->getSize() !== -1) ? $options->getSize() : null;
91 } else {
92 $this->customMetadata = [];
93 }
94
95 $this->stream = $stream;
96
97 $meta = stream_get_meta_data($this->stream);
98 $mode = $meta['mode'];
99
100 $this->readable = array_key_exists($mode, self::$accessMap) && boolval(self::$accessMap[$mode] & self::MASK_ACCESS_READ);
101 $this->writeable = array_key_exists($mode, self::$accessMap) && boolval(self::$accessMap[$mode] & self::MASK_ACCESS_WRITE);
102 $this->seekable = boolval($meta['seekable']);
103 $this->uri = $this->getMetadata('uri');
104 }
105
106
110 public function close()
111 {
112 if ($this->stream !== null && is_resource($this->stream)) {
113 PHPStreamFunctions::fclose($this->stream);
114 }
115
116 $this->detach();
117 }
118
119
123 public function detach()
124 {
126 $this->stream = $this->size = $this->uri = null;
127
128 return $stream;
129 }
130
131
135 public function getSize()
136 {
137
138 //check if we know the size
139 if ($this->size !== null) {
140 return $this->size;
141 }
142
143 //check if stream is detached
144 if ($this->stream === null) {
145 return null;
146 }
147
148 //clear stat cache if we got a uri (indicates that we have a file resource)
149 if ($this->uri !== null) {
150 clearstatcache(true, $this->uri);
151 }
152
153 $stats = fstat($this->stream);
154 if (array_key_exists('size', $stats)) {
155 $this->size = $stats['size'];
156 return $this->size;
157 }
158
159 //unable to determine stream size
160 return null;
161 }
162
163
167 public function tell()
168 {
169 $this->assertStreamAttached();
170
171 $result = PHPStreamFunctions::ftell($this->stream);
172
173 if ($result === false) {
174 throw new \RuntimeException('Unable to determine stream position');
175 }
176
177 return $result;
178 }
179
180
184 public function eof()
185 {
186 $this->assertStreamAttached();
187
188 return feof($this->stream);
189 }
190
191
195 public function isSeekable()
196 {
197 return $this->seekable;
198 }
199
200
204 public function seek($offset, $whence = SEEK_SET)
205 {
206 $this->assertStreamAttached();
207
208 if (!$this->isSeekable()) {
209 throw new \RuntimeException('Stream is not seekable');
210 }
211
212 if (PHPStreamFunctions::fseek($this->stream, $offset, $whence) === -1) {
213 throw new \RuntimeException("Unable to seek to stream position \"$offset\" with whence \"$whence\"");
214 }
215 }
216
217
221 public function rewind()
222 {
223 $this->seek(0);
224 }
225
226
230 public function isWritable()
231 {
232 return $this->writeable;
233 }
234
235
239 public function write($string)
240 {
241 $this->assertStreamAttached();
242
243 if (!$this->isWritable()) {
244 throw new \RuntimeException('Can not write to a non-writable stream');
245 }
246
247 //we can't know the new size
248 $this->size = null;
249 $result = PHPStreamFunctions::fwrite($this->stream, $string);
250
251 if ($result === false) {
252 throw new \RuntimeException('Unable to write to stream');
253 }
254
255 return $result;
256 }
257
258
262 public function isReadable()
263 {
264 return $this->readable;
265 }
266
267
271 public function read($length)
272 {
273 $this->assertStreamAttached();
274
275 if (!$this->isReadable()) {
276 throw new \RuntimeException('Can not read from non-readable stream');
277 }
278
279 if ($length < 0) {
280 throw new \RuntimeException('Length parameter must not be negative');
281 }
282
283 if ($length === 0) {
284 return '';
285 }
286
287 $junk = PHPStreamFunctions::fread($this->stream, $length);
288 if ($junk === false) {
289 throw new \RuntimeException('Unable to read from stream');
290 }
291
292 return $junk;
293 }
294
295
299 public function getContents()
300 {
301 $this->assertStreamAttached();
302
303 $content = PHPStreamFunctions::stream_get_contents($this->stream);
304
305 if ($content === false) {
306 throw new \RuntimeException('Unable to read stream contents');
307 }
308
309 return $content;
310 }
311
312
316 public function getMetadata($key = null)
317 {
318
319 //return empty array if stream is detached
320 if ($this->stream === null) {
321 return [];
322 }
323
324 //return merged metadata if key is missing
325 if ($key === null) {
326 return array_merge(stream_get_meta_data($this->stream), $this->customMetadata);
327 }
328
329 //return value if key was provided
330
331 //try fetch data from custom metadata
332 if (array_key_exists($key, $this->customMetadata)) {
333 return $this->customMetadata[$key];
334 }
335
336 //try to fetch data from php resource metadata
337 $meta = stream_get_meta_data($this->stream);
338 if (array_key_exists($key, $meta)) {
339 return $meta[$key];
340 }
341
342 //the key was not found in standard and custom metadata.
343 return null;
344 }
345
349 public function __toString()
350 {
351 try {
352 $this->rewind();
353 return strval($this->getContents());
354 } catch (\Exception $ex) {
355 //to string must not throw an error.
356 return '';
357 }
358 }
359
360
364 public function __destruct()
365 {
366
367 //cleanup the resource on object destruction if the stream is not detached.
368 if (!is_null($this->stream)) {
369 $this->close();
370 }
371 }
372
373
380 private function assertStreamAttached()
381 {
382 if ($this->stream === null) {
383 throw new \RuntimeException('Stream is detached');
384 }
385 }
386}
$result
if(!isset( $_REQUEST[ 'ReturnTo'])) if(!isset($_REQUEST['AuthId'])) $options
Definition: as_login.php:20
An exception for terminatinating execution or to throw for unit testing.
getMetadata($key=null)
@inheritDoc
Definition: Stream.php:316
__construct($stream, StreamOptions $options=null)
Stream constructor.
Definition: Stream.php:82
assertStreamAttached()
Checks if the stream is attached to the wrapper.
Definition: Stream.php:380
write($string)
@inheritDoc
Definition: Stream.php:239
read($length)
@inheritDoc
Definition: Stream.php:271
seek($offset, $whence=SEEK_SET)
@inheritDoc
Definition: Stream.php:204
static fwrite($handle, $string, $length=null)
fwrite wrapper
static fread($handle, $length)
fread wrapper
static stream_get_contents($handle, $length=-1)
stream_get_contents wrapper
static fclose($handle)
fclose wrapper
static fseek($stream, $offset, $whence)
fseek wrapper.
$key
Definition: croninfo.php:18
$stats