Simpletest Coverage - includes/stream_wrappers.inc

1 <?php
2 // $Id: stream_wrappers.inc,v 1.1 2009/07/27 19:53:17 dries Exp $
3
4 /**
5 * @file
6 * Drupal stream wrapper interface.
7 *
8 * Provides a Drupal interface and classes to implement PHP stream wrappers for
9 * public, private, and temporary files.
10 *
11 * A stream wrapper is an abstraction of a file system that allows Drupal to
12 * use the same set of methods to access both local files and remote resources.
13 *
14 * Note that PHP 5.2 fopen() only supports URIs of the form "scheme://target"
15 * despite the fact that according to RFC 3986 a URI's scheme component
16 * delimiter is in general just ":", not "://". Becuase of this PHP limitation
17 * and for consistency Drupal will only accept URIs of form "scheme://target".
18 *
19 * @link http://www.faqs.org/rfcs/rfc3986.html
20 * @link http://bugs.php.net/bug.php?id=47070
21 */
22
23 /**
24 * Generic PHP stream wrapper interface.
25 *
26 * @see http://www.php.net/manual/en/class.streamwrapper.php
27 */
28 interface StreamWrapperInterface {
29 public function stream_open($uri, $mode, $options, &$opened_url);
30 public function stream_close();
31 public function stream_lock($operation);
32 public function stream_read($count);
33 public function stream_write($data);
34 public function stream_eof();
35 public function stream_seek($offset, $whence);
36 public function stream_flush();
37 public function stream_tell();
38 public function stream_stat();
39 public function unlink($uri);
40 public function rename($from_uri, $to_uri);
41 public function mkdir($uri, $mode, $options);
42 public function rmdir($uri, $options);
43 public function url_stat($uri, $flags);
44 public function dir_opendir($uri, $options);
45 public function dir_readdir();
46 public function dir_rewinddir();
47 public function dir_closedir();
48 }
49
50 /**
51 * Drupal stream wrapper extension.
52 *
53 * Extend the StreamWrapperInterface with methods expected by Drupal stream
54 * wrapper classes.
55 */
56 interface DrupalStreamWrapperInterface extends StreamWrapperInterface {
57 /**
58 * Set the absolute stream resource URI.
59 *
60 * This allows you to set the URI. Generally is only called by the factory
61 * method.
62 *
63 * @param $uri
64 * A string containing the URI that should be used for this instance.
65 */
66 function setUri($uri);
67
68 /**
69 * Returns the stream resource URI.
70 *
71 * @return
72 * Returns the current URI of the instance.
73 */
74 public function getUri();
75
76 /**
77 * Returns a web accessible URL for the resource.
78 *
79 * This function should return a URL that can be embedded in a web page
80 * and accessed from a browser. For example, the external URL of
81 * "youtube://xIpLd0WQKCY" might be
82 * "http://www.youtube.com/watch?v=xIpLd0WQKCY".
83 *
84 * @return
85 * Returns a string containing a web accessible URL for the resource.
86 */
87 public function getExternalUrl();
88
89 /**
90 * Returns the MIME type of the resource.
91 *
92 * @param $uri
93 * The URI, path, or filename.
94 * @param $mapping
95 * An optional map of extensions to their mimetypes, in the form:
96 * - 'mimetypes': a list of mimetypes, keyed by an identifier,
97 * - 'extensions': the mapping itself, an associative array in which
98 * the key is the extension and the value is the mimetype identifier.
99 * @return
100 * Returns a string containing the MIME type of the resource.
101 */
102 public static function getMimeType($uri, $mapping = NULL);
103
104 /**
105 * Changes permissions of the resource.
106 *
107 * PHP lacks this functionality and it is not part of the official stream
108 * wrapper interface. This is a custom implementation for Drupal.
109 *
110 * @param $mode
111 * Integer value for the permissions. Consult PHP chmod() documentation
112 * for more information.
113 * @return
114 * Returns TRUE on success or FALSE on failure.
115 */
116 public function chmod($mode);
117
118 /**
119 * Returns canonical, absolute path of the resource.
120 *
121 * Implementation placeholder. PHP's realpath() does not support stream
122 * wrappers. We provide this as a default so that individual wrappers may
123 * implement their own solutions.
124 *
125 * @return
126 * Returns a string with absolute pathname on success (implemented
127 * by core wrappers), or FALSE on failure or if the registered
128 * wrapper does not provide an implementation.
129 */
130 public function realpath();
131 }
132
133
134 /**
135 * Drupal stream wrapper base class for local files.
136 *
137 * This class provides a complete stream wrapper implementation. URIs such as
138 * "public://example.txt" are expanded to a normal filesystem path such as
139 * "sites/default/files/example.txt" and then PHP filesystem functions are
140 * invoked.
141 *
142 * DrupalLocalStreamWrapper implementations need to implement at least the
143 * getDirectoryPath() and getExternalUrl() methods.
144 */
145 abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface {
146 /**
147 * Stream context resource.
148 *
149 * @var Resource
150 */
151 public $context;
152
153 /**
154 * A generic resource handle.
155 *
156 * @var Resource
157 */
158 public $handle = NULL;
159
160 /**
161 * Instance URI (stream).
162 *
163 * A stream is referenced as "scheme://target".
164 *
165 * @var String
166 */
167 protected $uri;
168
169 /**
170 * Gets the path that the wrapper is responsible for.
171 *
172 * @return
173 * String specifying the path.
174 */
175 abstract function getDirectoryPath();
176
177 /**
178 * Base implementation of setUri().
179 */
180 function setUri($uri) {
181 $this->uri = $uri;
182 }
183
184 /**
185 * Base implementation of getUri().
186 */
187 function getUri() {
188 return $this->uri;
189 }
190
191 /**
192 * Base implementation of getMimeType().
193 */
194 static function getMimeType($uri, $mapping = NULL) {
195 if (!isset($mapping)) {
196 $mapping = variable_get('mime_extension_mapping', NULL);
197 if (!isset($mapping) && drupal_function_exists('file_default_mimetype_mapping')) {
198 // The default file map, defined in file.mimetypes.inc is quite big.
199 // We only load it when necessary.
200 $mapping = file_default_mimetype_mapping();
201 }
202 }
203
204 $extension = '';
205 $file_parts = explode('.', basename($uri));
206
207 // Remove the first part: a full filename should not match an extension.
208 array_shift($file_parts);
209
210 // Iterate over the file parts, trying to find a match.
211 // For my.awesome.image.jpeg, we try:
212 // - jpeg
213 // - image.jpeg, and
214 // - awesome.image.jpeg
215 while ($additional_part = array_pop($file_parts)) {
216 $extension = strtolower($additional_part . ($extension ? '.' . $extension : ''));
217 if (isset($mapping['extensions'][$extension])) {
218 return $mapping['mimetypes'][$mapping['extensions'][$extension]];
219 }
220 }
221
222 return 'application/octet-stream';
223 }
224
225 /**
226 * Base implementation of chmod().
227 */
228 function chmod($mode) {
229 return @chmod($this->realpath(), $mode);
230 }
231
232 /**
233 * Base implementaiton of realpath().
234 */
235 function realpath() {
236 return @realpath($this->getDirectoryPath() . '/' . file_uri_target($this->uri));
237 }
238
239 /**
240 * Return the local filesystem path.
241 *
242 * @param $uri
243 * Optional URI, supplied when doing a move or rename.
244 */
245 protected function getLocalPath($uri = NULL) {
246 if (!isset($uri)) {
247 $uri = $this->uri;
248 }
249 return $this->getDirectoryPath() . '/' . file_uri_target($uri);
250 }
251
252 /**
253 * Support for fopen(), file_get_contents(), file_put_contents() etc.
254 *
255 * @param $uri
256 * A string containing the path to the file to open.
257 * @param $mode
258 * The file mode ("r", "wb" etc.).
259 * @param $options
260 * A bit mask of STREAM_USE_PATH and STREAM_REPORT_ERRORS.
261 * @param &$opened_path
262 * A string containing the path actually opened.
263 * @return
264 * Returns TRUE if file was opened successfully.
265 * @see http://php.net/manual/en/streamwrapper.stream-open.php
266 */
267 public function stream_open($uri, $mode, $options, &$opened_path) {
268 $this->uri = $uri;
269 $path = $this->getLocalPath();
270 $this->handle = ($options & STREAM_REPORT_ERRORS) ? fopen($path, $mode) : @fopen($path, $mode);
271
272 if ((bool)$this->handle && $options & STREAM_USE_PATH) {
273 $opened_url = $path;
274 }
275
276 return (bool)$this->handle;
277 }
278
279 /**
280 * Support for flock().
281 *
282 * @param $operation
283 * One of the following:
284 * - LOCK_SH to acquire a shared lock (reader).
285 * - LOCK_EX to acquire an exclusive lock (writer).
286 * - LOCK_UN to release a lock (shared or exclusive).
287 * - LOCK_NB if you don't want flock() to block while locking (not
288 * supported on Windows).
289 * @return
290 * Always returns TRUE at the present time.
291 * @see http://php.net/manual/en/streamwrapper.stream-lock.php
292 */
293 public function stream_lock($operation) {
294 if (in_array($operation, array(LOCK_SH, LOCK_EX, LOCK_UN, LOCK_NB))) {
295 return flock($this->handle, $operation);
296 }
297
298 return TRUE;
299 }
300
301 /**
302 * Support for fread(), file_get_contents() etc.
303 *
304 * @param $count
305 * Maximum number of bytes to be read.
306 * @return
307 * The string that was read, or FALSE in case of an error.
308 * @see http://php.net/manual/en/streamwrapper.stream-read.php
309 */
310 public function stream_read($count) {
311 return fread($this->handle, $count);
312 }
313
314 /**
315 * Support for fwrite(), file_put_contents() etc.
316 *
317 * @param $data
318 * The string to be written.
319 * @return
320 * The number of bytes written (integer).
321 * @see http://php.net/manual/en/streamwrapper.stream-write.php
322 */
323 public function stream_write($data) {
324 return fwrite($this->handle, $data);
325 }
326
327 /**
328 * Support for feof().
329 *
330 * @return
331 * TRUE if end-of-file has been reached.
332 * @see http://php.net/manual/en/streamwrapper.stream-eof.php
333 */
334 public function stream_eof() {
335 return feof($this->handle);
336 }
337
338 /**
339 * Support for fseek().
340 *
341 * @param $offset
342 * The byte offset to got to.
343 * @param $whence
344 * SEEK_SET, SEEK_CUR, or SEEK_END.
345 * @return
346 * TRUE on success.
347 * @see http://php.net/manual/en/streamwrapper.stream-seek.php
348 */
349 public function stream_seek($offset, $whence) {
350 return fseek($this->handle, $offset, $whence);
351 }
352
353 /**
354 * Support for fflush().
355 *
356 * @return
357 * TRUE if data was successfully stored (or there was no data to store).
358 * @see http://php.net/manual/en/streamwrapper.stream-flush.php
359 */
360 public function stream_flush() {
361 return fflush($this->handle);
362 }
363
364 /**
365 * Support for ftell().
366 *
367 * @return
368 * The current offset in bytes from the beginning of file.
369 * @see http://php.net/manual/en/streamwrapper.stream-tell.php
370 */
371 public function stream_tell() {
372 return ftell($this->handle);
373 }
374
375 /**
376 * Support for fstat().
377 *
378 * @return
379 * An array with file status, or FALSE in case of an error - see fstat()
380 * for a description of this array.
381 * @see http://php.net/manual/en/streamwrapper.stream-stat.php
382 */
383 public function stream_stat() {
384 return fstat($this->handle);
385 }
386
387 /**
388 * Support for fclose().
389 *
390 * @return
391 * TRUE if stream was successfully closed.
392 * @see http://php.net/manual/en/streamwrapper.stream-close.php
393 */
394 public function stream_close() {
395 return fclose($this->handle);
396 }
397
398 /**
399 * Support for unlink().
400 *
401 * @param $uri
402 * A string containing the uri to the resource to delete.
403 * @return
404 * TRUE if resource was successfully deleted.
405 * @see http://php.net/manual/en/streamwrapper.unlink.php
406 */
407 public function unlink($uri) {
408 $this->uri = $uri;
409 return unlink($this->getLocalPath());
410 }
411
412 /**
413 * Support for rename().
414 *
415 * @param $from_uri,
416 * The uri to the file to rename.
417 * @param $to_uri
418 * The new uri for file.
419 * @return
420 * TRUE if file was successfully renamed.
421 * @see http://php.net/manual/en/streamwrapper.rename.php
422 */
423 public function rename($from_uri, $to_uri) {
424 return rename($this->getLocalPath($from_uri), $this->getLocalPath($to_uri));
425 }
426
427 /**
428 * Support for mkdir().
429 *
430 * @param $uri
431 * A string containing the url to the directory to create.
432 * @param $mode
433 * Permission flags - see mkdir().
434 * @param $options
435 * A bit mask of STREAM_REPORT_ERRORS and STREAM_MKDIR_RECURSIVE.
436 * @return
437 * TRUE if directory was successfully created.
438 * @see http://php.net/manual/en/streamwrapper.mkdir.php
439 */
440 public function mkdir($uri, $mode, $options) {
441 $this->uri = $uri;
442 $recursive = (bool)($options & STREAM_MKDIR_RECURSIVE);
443 if ($options & STREAM_REPORT_ERRORS) {
444 return mkdir($this->getLocalPath(), $mode, $recursive);
445 }
446 else {
447 return @mkdir($this->getLocalPath(), $mode, $recursive);
448 }
449 }
450
451 /**
452 * Support for rmdir().
453 *
454 * @param $uri
455 * A string containing the url to the directory to delete.
456 * @param $options
457 * A bit mask of STREAM_REPORT_ERRORS.
458 * @return
459 * TRUE if directory was successfully removed.
460 * @see http://php.net/manual/en/streamwrapper.rmdir.php
461 */
462 public function rmdir($uri, $options) {
463 $this->uri = $uri;
464 if ($options & STREAM_REPORT_ERRORS) {
465 return rmdir($this->getLocalPath());
466 }
467 else {
468 return @rmdir($this->getLocalPath());
469 }
470 }
471
472 /**
473 * Support for stat().
474 *
475 * @param $uri
476 * A string containing the url to get information about.
477 * @param $flags
478 * A bit mask of STREAM_URL_STAT_LINK and STREAM_URL_STAT_QUIET.
479 * @return
480 * An array with file status, or FALSE in case of an error - see fstat()
481 * for a description of this array.
482 * @see http://php.net/manual/en/streamwrapper.url-stat.php
483 */
484 public function url_stat($uri, $flags) {
485 $this->uri = $uri;
486 if ($flags & STREAM_URL_STAT_QUIET) {
487 return @stat($this->getLocalPath());
488 }
489 else {
490 return stat($this->getLocalPath());
491 }
492 }
493
494 /**
495 * Support for opendir().
496 *
497 * @param $uri
498 * A string containing the url to the directory to open.
499 * @param $options
500 * Unknown (parameter is not documented in PHP Manual).
501 * @return
502 * TRUE on success.
503 * @see http://php.net/manual/en/streamwrapper.dir-opendir.php
504 */
505 public function dir_opendir($uri, $options) {
506 $this->uri = $uri;
507 $this->handle = opendir($this->getLocalPath());
508
509 return (bool)$this->handle;
510 }
511
512 /**
513 * Support for readdir().
514 *
515 * @return
516 * The next filename, or FALSE if there are no more files in the directory.
517 * @see http://php.net/manual/en/streamwrapper.dir-readdir.php
518 */
519 public function dir_readdir() {
520 return readdir($this->handle);
521 }
522
523 /**
524 * Support for rewinddir().
525 *
526 * @return
527 * TRUE on success.
528 * @see http://php.net/manual/en/streamwrapper.dir-rewinddir.php
529 */
530 public function dir_rewinddir() {
531 return rewinddir($this->handle);
532 }
533
534 /**
535 * Support for closedir().
536 *
537 * @return
538 * TRUE on success.
539 * @see http://php.net/manual/en/streamwrapper.dir-closedir.php
540 */
541 public function dir_closedir() {
542 return closedir($this->handle);
543 }
544 }
545
546 /**
547 * Drupal public (public://) stream wrapper class.
548 *
549 * Provides support for storing publicly accessible files with the Drupal file
550 * interface.
551 */
552 class DrupalPublicStreamWrapper extends DrupalLocalStreamWrapper {
553 /**
554 * Implements abstract public function getDirectoryPath()
555 */
556 public function getDirectoryPath() {
557 return variable_get('file_public_path', 'sites/default/files');
558 }
559
560 /**
561 * Overrides getExternalUrl().
562 *
563 * Return the HTML URI of a public file.
564 */
565 function getExternalUrl() {
566 $path = str_replace('\\', '/', file_uri_target($this->uri));
567 return $GLOBALS['base_url'] . '/' . self::getDirectoryPath() . '/' . $path;
568 }
569 }
570
571
572 /**
573 * Drupal private (private://) stream wrapper class.
574 *
575 * Provides support for storing privately accessible files with the Drupal file
576 * interface.
577 *
578 * Extends DrupalPublicStreamWrapper.
579 */
580 class DrupalPrivateStreamWrapper extends DrupalLocalStreamWrapper {
581 /**
582 * Implements abstract public function getDirectoryPath()
583 */
584 public function getDirectoryPath() {
585 return variable_get('file_private_path', 'sites/default/files-private');
586 }
587
588 /**
589 * Overrides getExternalUrl().
590 *
591 * Return the HTML URI of a private file.
592 */
593 function getExternalUrl() {
594 $path = str_replace('\\', '/', file_uri_target($this->uri));
595 return url('system/files/' . $path, array('absolute' => TRUE));
596 }
597 }
598
599 /**
600 * Drupal temporary (temporary://) stream wrapper class.
601 *
602 * Provides support for storing temporarily accessible files with the Drupal
603 * file interface.
604 *
605 * Extends DrupalPublicStreamWrapper.
606 */
607 class DrupalTemporaryStreamWrapper extends DrupalLocalStreamWrapper {
608 /**
609 * Implements abstract public function getDirectoryPath()
610 */
611 public function getDirectoryPath() {
612 return variable_get('file_temporary_path', '/tmp');
613 }
614
615 /**
616 * Overrides getExternalUrl().
617 */
618 public function getExternalUrl() {
619 return '';
620 }
621 }
622

Legend

Missed
lines code that were not excersized during program execution.
Covered
lines code were excersized during program execution.
Comment/non executable
Comment or non-executable line of code.
Dead
lines of code that according to xdebug could not be executed. This is counted as coverage code because in almost all cases it is code that runnable.