Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
0.00% |
0 / 30 |
CRAP | |
0.00% |
0 / 152 |
LocalStream | |
0.00% |
0 / 1 |
|
3.23% |
1 / 31 |
3306 | |
0.00% |
0 / 152 |
getType | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
getDirectoryPath | |
100.00% |
1 / 1 |
1 | |
100.00% |
0 / 0 |
|||
setUri | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
getUri | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
getTarget | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 6 |
|||
realpath | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
getLocalPath | |
0.00% |
0 / 1 |
56 | |
0.00% |
0 / 17 |
|||
stream_open | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 8 |
|||
stream_lock | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 5 |
|||
stream_read | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
stream_write | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
stream_eof | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
stream_seek | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
stream_flush | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
stream_tell | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
stream_stat | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
stream_close | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
stream_cast | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 2 |
|||
stream_metadata | |
0.00% |
0 / 1 |
90 | |
0.00% |
0 / 28 |
|||
stream_set_option | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 3 |
|||
stream_truncate | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
unlink | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 3 |
|||
rename | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
dirname | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 8 |
|||
mkdir | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 15 |
|||
rmdir | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 8 |
|||
url_stat | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 9 |
|||
dir_opendir | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 4 |
|||
dir_readdir | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
dir_rewinddir | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 3 |
|||
dir_closedir | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 3 |
<?php | |
/** | |
* @file | |
* Contains \Drupal\Core\StreamWrapper\LocalStream. | |
*/ | |
namespace Drupal\Core\StreamWrapper; | |
/** | |
* Defines a Drupal stream wrapper base class for local files. | |
* | |
* This class provides a complete stream wrapper implementation. URIs such as | |
* "public://example.txt" are expanded to a normal filesystem path such as | |
* "sites/default/files/example.txt" and then PHP filesystem functions are | |
* invoked. | |
* | |
* Drupal\Core\StreamWrapper\LocalStream implementations need to implement at least the | |
* getDirectoryPath() and getExternalUrl() methods. | |
*/ | |
abstract class LocalStream implements StreamWrapperInterface { | |
/** | |
* Stream context resource. | |
* | |
* @var resource | |
*/ | |
public $context; | |
/** | |
* A generic resource handle. | |
* | |
* @var resource | |
*/ | |
public $handle = NULL; | |
/** | |
* Instance URI (stream). | |
* | |
* A stream is referenced as "scheme://target". | |
* | |
* @var string | |
*/ | |
protected $uri; | |
/** | |
* {@inheritdoc} | |
*/ | |
public static function getType() { | |
return StreamWrapperInterface::NORMAL; | |
} | |
/** | |
* Gets the path that the wrapper is responsible for. | |
* | |
* @todo Review this method name in D8 per https://www.drupal.org/node/701358. | |
* | |
* @return string | |
* String specifying the path. | |
*/ | |
abstract function getDirectoryPath(); | |
/** | |
* {@inheritdoc} | |
*/ | |
function setUri($uri) { | |
$this->uri = $uri; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
function getUri() { | |
return $this->uri; | |
} | |
/** | |
* Returns the local writable target of the resource within the stream. | |
* | |
* This function should be used in place of calls to realpath() or similar | |
* functions when attempting to determine the location of a file. While | |
* functions like realpath() may return the location of a read-only file, this | |
* method may return a URI or path suitable for writing that is completely | |
* separate from the URI used for reading. | |
* | |
* @param string $uri | |
* Optional URI. | |
* | |
* @return string|bool | |
* Returns a string representing a location suitable for writing of a file, | |
* or FALSE if unable to write to the file such as with read-only streams. | |
*/ | |
protected function getTarget($uri = NULL) { | |
if (!isset($uri)) { | |
$uri = $this->uri; | |
} | |
list(, $target) = explode('://', $uri, 2); | |
// Remove erroneous leading or trailing, forward-slashes and backslashes. | |
return trim($target, '\/'); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
function realpath() { | |
return $this->getLocalPath(); | |
} | |
/** | |
* Returns the canonical absolute path of the URI, if possible. | |
* | |
* @param string $uri | |
* (optional) The stream wrapper URI to be converted to a canonical | |
* absolute path. This may point to a directory or another type of file. | |
* | |
* @return string|bool | |
* If $uri is not set, returns the canonical absolute path of the URI | |
* previously set by the | |
* Drupal\Core\StreamWrapper\StreamWrapperInterface::setUri() function. | |
* If $uri is set and valid for this class, returns its canonical absolute | |
* path, as determined by the realpath() function. If $uri is set but not | |
* valid, returns FALSE. | |
*/ | |
protected function getLocalPath($uri = NULL) { | |
if (!isset($uri)) { | |
$uri = $this->uri; | |
} | |
$path = $this->getDirectoryPath() . '/' . $this->getTarget($uri); | |
// In PHPUnit tests, the base path for local streams may be a virtual | |
// filesystem stream wrapper URI, in which case this local stream acts like | |
// a proxy. realpath() is not supported by vfsStream, because a virtual | |
// file system does not have a real filepath. | |
if (strpos($path, 'vfs://') === 0) { | |
return $path; | |
} | |
$realpath = realpath($path); | |
if (!$realpath) { | |
// This file does not yet exist. | |
$realpath = realpath(dirname($path)) . '/' . drupal_basename($path); | |
} | |
$directory = realpath($this->getDirectoryPath()); | |
if (!$realpath || !$directory || strpos($realpath, $directory) !== 0) { | |
return FALSE; | |
} | |
return $realpath; | |
} | |
/** | |
* Support for fopen(), file_get_contents(), file_put_contents() etc. | |
* | |
* @param string $uri | |
* A string containing the URI to the file to open. | |
* @param int $mode | |
* The file mode ("r", "wb" etc.). | |
* @param int $options | |
* A bit mask of STREAM_USE_PATH and STREAM_REPORT_ERRORS. | |
* @param string $opened_path | |
* A string containing the path actually opened. | |
* | |
* @return bool | |
* Returns TRUE if file was opened successfully. | |
* | |
* @see http://php.net/manual/streamwrapper.stream-open.php | |
*/ | |
public function stream_open($uri, $mode, $options, &$opened_path) { | |
$this->uri = $uri; | |
$path = $this->getLocalPath(); | |
$this->handle = ($options & STREAM_REPORT_ERRORS) ? fopen($path, $mode) : @fopen($path, $mode); | |
if ((bool) $this->handle && $options & STREAM_USE_PATH) { | |
$opened_path = $path; | |
} | |
return (bool) $this->handle; | |
} | |
/** | |
* Support for flock(). | |
* | |
* @param int $operation | |
* One of the following: | |
* - LOCK_SH to acquire a shared lock (reader). | |
* - LOCK_EX to acquire an exclusive lock (writer). | |
* - LOCK_UN to release a lock (shared or exclusive). | |
* - LOCK_NB if you don't want flock() to block while locking (not | |
* supported on Windows). | |
* | |
* @return bool | |
* Always returns TRUE at the present time. | |
* | |
* @see http://php.net/manual/streamwrapper.stream-lock.php | |
*/ | |
public function stream_lock($operation) { | |
if (in_array($operation, array(LOCK_SH, LOCK_EX, LOCK_UN, LOCK_NB))) { | |
return flock($this->handle, $operation); | |
} | |
return TRUE; | |
} | |
/** | |
* Support for fread(), file_get_contents() etc. | |
* | |
* @param int $count | |
* Maximum number of bytes to be read. | |
* | |
* @return string|bool | |
* The string that was read, or FALSE in case of an error. | |
* | |
* @see http://php.net/manual/streamwrapper.stream-read.php | |
*/ | |
public function stream_read($count) { | |
return fread($this->handle, $count); | |
} | |
/** | |
* Support for fwrite(), file_put_contents() etc. | |
* | |
* @param string $data | |
* The string to be written. | |
* | |
* @return int | |
* The number of bytes written. | |
* | |
* @see http://php.net/manual/streamwrapper.stream-write.php | |
*/ | |
public function stream_write($data) { | |
return fwrite($this->handle, $data); | |
} | |
/** | |
* Support for feof(). | |
* | |
* @return bool | |
* TRUE if end-of-file has been reached. | |
* | |
* @see http://php.net/manual/streamwrapper.stream-eof.php | |
*/ | |
public function stream_eof() { | |
return feof($this->handle); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function stream_seek($offset, $whence = SEEK_SET) { | |
// fseek returns 0 on success and -1 on a failure. | |
// stream_seek 1 on success and 0 on a failure. | |
return !fseek($this->handle, $offset, $whence); | |
} | |
/** | |
* Support for fflush(). | |
* | |
* @return bool | |
* TRUE if data was successfully stored (or there was no data to store). | |
* | |
* @see http://php.net/manual/streamwrapper.stream-flush.php | |
*/ | |
public function stream_flush() { | |
return fflush($this->handle); | |
} | |
/** | |
* Support for ftell(). | |
* | |
* @return bool | |
* The current offset in bytes from the beginning of file. | |
* | |
* @see http://php.net/manual/streamwrapper.stream-tell.php | |
*/ | |
public function stream_tell() { | |
return ftell($this->handle); | |
} | |
/** | |
* Support for fstat(). | |
* | |
* @return bool | |
* An array with file status, or FALSE in case of an error - see fstat() | |
* for a description of this array. | |
* | |
* @see http://php.net/manual/streamwrapper.stream-stat.php | |
*/ | |
public function stream_stat() { | |
return fstat($this->handle); | |
} | |
/** | |
* Support for fclose(). | |
* | |
* @return bool | |
* TRUE if stream was successfully closed. | |
* | |
* @see http://php.net/manual/streamwrapper.stream-close.php | |
*/ | |
public function stream_close() { | |
return fclose($this->handle); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function stream_cast($cast_as) { | |
return $this->handle ? $this->handle : FALSE; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function stream_metadata($uri, $option, $value) { | |
$target = $this->getLocalPath($uri); | |
$return = FALSE; | |
switch ($option) { | |
case STREAM_META_TOUCH: | |
if (!empty($value)) { | |
$return = touch($target, $value[0], $value[1]); | |
} | |
else { | |
$return = touch($target); | |
} | |
break; | |
case STREAM_META_OWNER_NAME: | |
case STREAM_META_OWNER: | |
$return = chown($target, $value); | |
break; | |
case STREAM_META_GROUP_NAME: | |
case STREAM_META_GROUP: | |
$return = chgrp($target, $value); | |
break; | |
case STREAM_META_ACCESS: | |
$return = chmod($target, $value); | |
break; | |
} | |
if ($return) { | |
// For convenience clear the file status cache of the underlying file, | |
// since metadata operations are often followed by file status checks. | |
clearstatcache(TRUE, $target); | |
} | |
return $return; | |
} | |
/** | |
* {@inheritdoc} | |
* | |
* Since Windows systems do not allow it and it is not needed for most use | |
* cases anyway, this method is not supported on local files and will trigger | |
* an error and return false. If needed, custom subclasses can provide | |
* OS-specific implementations for advanced use cases. | |
*/ | |
public function stream_set_option($option, $arg1, $arg2) { | |
trigger_error('stream_set_option() not supported for local file based stream wrappers', E_USER_WARNING); | |
return FALSE; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function stream_truncate($new_size) { | |
return ftruncate($this->handle, $new_size); | |
} | |
/** | |
* Support for unlink(). | |
* | |
* @param string $uri | |
* A string containing the URI to the resource to delete. | |
* | |
* @return bool | |
* TRUE if resource was successfully deleted. | |
* | |
* @see http://php.net/manual/streamwrapper.unlink.php | |
*/ | |
public function unlink($uri) { | |
$this->uri = $uri; | |
return drupal_unlink($this->getLocalPath()); | |
} | |
/** | |
* Support for rename(). | |
* | |
* @param string $from_uri, | |
* The URI to the file to rename. | |
* @param string $to_uri | |
* The new URI for file. | |
* | |
* @return bool | |
* TRUE if file was successfully renamed. | |
* | |
* @see http://php.net/manual/streamwrapper.rename.php | |
*/ | |
public function rename($from_uri, $to_uri) { | |
return rename($this->getLocalPath($from_uri), $this->getLocalPath($to_uri)); | |
} | |
/** | |
* Gets the name of the directory from a given path. | |
* | |
* This method is usually accessed through drupal_dirname(), which wraps | |
* around the PHP dirname() function because it does not support stream | |
* wrappers. | |
* | |
* @param string $uri | |
* A URI or path. | |
* | |
* @return string | |
* A string containing the directory name. | |
* | |
* @see drupal_dirname() | |
*/ | |
public function dirname($uri = NULL) { | |
list($scheme) = explode('://', $uri, 2); | |
$target = $this->getTarget($uri); | |
$dirname = dirname($target); | |
if ($dirname == '.') { | |
$dirname = ''; | |
} | |
return $scheme . '://' . $dirname; | |
} | |
/** | |
* Support for mkdir(). | |
* | |
* @param string $uri | |
* A string containing the URI to the directory to create. | |
* @param int $mode | |
* Permission flags - see mkdir(). | |
* @param int $options | |
* A bit mask of STREAM_REPORT_ERRORS and STREAM_MKDIR_RECURSIVE. | |
* | |
* @return bool | |
* TRUE if directory was successfully created. | |
* | |
* @see http://php.net/manual/streamwrapper.mkdir.php | |
*/ | |
public function mkdir($uri, $mode, $options) { | |
$this->uri = $uri; | |
$recursive = (bool) ($options & STREAM_MKDIR_RECURSIVE); | |
if ($recursive) { | |
// $this->getLocalPath() fails if $uri has multiple levels of directories | |
// that do not yet exist. | |
$localpath = $this->getDirectoryPath() . '/' . $this->getTarget($uri); | |
} | |
else { | |
$localpath = $this->getLocalPath($uri); | |
} | |
if ($options & STREAM_REPORT_ERRORS) { | |
return drupal_mkdir($localpath, $mode, $recursive); | |
} | |
else { | |
return @drupal_mkdir($localpath, $mode, $recursive); | |
} | |
} | |
/** | |
* Support for rmdir(). | |
* | |
* @param string $uri | |
* A string containing the URI to the directory to delete. | |
* @param int $options | |
* A bit mask of STREAM_REPORT_ERRORS. | |
* | |
* @return bool | |
* TRUE if directory was successfully removed. | |
* | |
* @see http://php.net/manual/streamwrapper.rmdir.php | |
*/ | |
public function rmdir($uri, $options) { | |
$this->uri = $uri; | |
if ($options & STREAM_REPORT_ERRORS) { | |
return drupal_rmdir($this->getLocalPath()); | |
} | |
else { | |
return @drupal_rmdir($this->getLocalPath()); | |
} | |
} | |
/** | |
* Support for stat(). | |
* | |
* @param string $uri | |
* A string containing the URI to get information about. | |
* @param int $flags | |
* A bit mask of STREAM_URL_STAT_LINK and STREAM_URL_STAT_QUIET. | |
* | |
* @return array | |
* An array with file status, or FALSE in case of an error - see fstat() | |
* for a description of this array. | |
* | |
* @see http://php.net/manual/streamwrapper.url-stat.php | |
*/ | |
public function url_stat($uri, $flags) { | |
$this->uri = $uri; | |
$path = $this->getLocalPath(); | |
// Suppress warnings if requested or if the file or directory does not | |
// exist. This is consistent with PHP's plain filesystem stream wrapper. | |
if ($flags & STREAM_URL_STAT_QUIET || !file_exists($path)) { | |
return @stat($path); | |
} | |
else { | |
return stat($path); | |
} | |
} | |
/** | |
* Support for opendir(). | |
* | |
* @param string $uri | |
* A string containing the URI to the directory to open. | |
* @param int $options | |
* Unknown (parameter is not documented in PHP Manual). | |
* | |
* @return bool | |
* TRUE on success. | |
* | |
* @see http://php.net/manual/streamwrapper.dir-opendir.php | |
*/ | |
public function dir_opendir($uri, $options) { | |
$this->uri = $uri; | |
$this->handle = opendir($this->getLocalPath()); | |
return (bool) $this->handle; | |
} | |
/** | |
* Support for readdir(). | |
* | |
* @return string | |
* The next filename, or FALSE if there are no more files in the directory. | |
* | |
* @see http://php.net/manual/streamwrapper.dir-readdir.php | |
*/ | |
public function dir_readdir() { | |
return readdir($this->handle); | |
} | |
/** | |
* Support for rewinddir(). | |
* | |
* @return bool | |
* TRUE on success. | |
* | |
* @see http://php.net/manual/streamwrapper.dir-rewinddir.php | |
*/ | |
public function dir_rewinddir() { | |
rewinddir($this->handle); | |
// We do not really have a way to signal a failure as rewinddir() does not | |
// have a return value and there is no way to read a directory handler | |
// without advancing to the next file. | |
return TRUE; | |
} | |
/** | |
* Support for closedir(). | |
* | |
* @return bool | |
* TRUE on success. | |
* | |
* @see http://php.net/manual/streamwrapper.dir-closedir.php | |
*/ | |
public function dir_closedir() { | |
closedir($this->handle); | |
// We do not really have a way to signal a failure as closedir() does not | |
// have a return value. | |
return TRUE; | |
} | |
} |