abstract class LocalStream in Drupal 8
Same name and namespace in other branches
- 9 core/lib/Drupal/Core/StreamWrapper/LocalStream.php \Drupal\Core\StreamWrapper\LocalStream
- 10 core/lib/Drupal/Core/StreamWrapper/LocalStream.php \Drupal\Core\StreamWrapper\LocalStream
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.
Hierarchy
- class \Drupal\Core\StreamWrapper\LocalStream implements StreamWrapperInterface
Expanded class hierarchy of LocalStream
3 files declare their use of LocalStream
- DummyStreamWrapper.php in core/
modules/ file/ tests/ file_test/ src/ StreamWrapper/ DummyStreamWrapper.php - FileCopy.php in core/
modules/ migrate/ src/ Plugin/ migrate/ process/ FileCopy.php - TranslationsStream.php in core/
modules/ locale/ src/ StreamWrapper/ TranslationsStream.php
File
- core/
lib/ Drupal/ Core/ StreamWrapper/ LocalStream.php, line 16
Namespace
Drupal\Core\StreamWrapperView source
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.
*/
public abstract function getDirectoryPath();
/**
* {@inheritdoc}
*/
public function setUri($uri) {
$this->uri = $uri;
}
/**
* {@inheritdoc}
*/
public 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}
*/
public 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::service('file_system')
->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, [
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 $this
->getFileSystem()
->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\Core\File\FileSystemInterface::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\Core\File\FileSystemInterface::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);
}
/** @var \Drupal\Core\File\FileSystemInterface $file_system */
$file_system = \Drupal::service('file_system');
if ($options & STREAM_REPORT_ERRORS) {
return $file_system
->mkdir($localpath, $mode, $recursive);
}
else {
return @$file_system
->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;
/** @var \Drupal\Core\File\FileSystemInterface $file_system */
$file_system = \Drupal::service('file_system');
if ($options & STREAM_REPORT_ERRORS) {
return $file_system
->rmdir($this
->getLocalPath());
}
else {
return @$file_system
->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;
}
/**
* Returns file system service.
*
* @return \Drupal\Core\File\FileSystemInterface
* The file system service.
*/
private function getFileSystem() {
return \Drupal::service('file_system');
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
LocalStream:: |
public | property | Stream context resource. | |
LocalStream:: |
public | property | A generic resource handle. | |
LocalStream:: |
protected | property | Instance URI (stream). | |
LocalStream:: |
public | function |
Gets the name of the directory from a given path. Overrides StreamWrapperInterface:: |
|
LocalStream:: |
public | function |
Support for closedir(). Overrides PhpStreamWrapperInterface:: |
|
LocalStream:: |
public | function |
Support for opendir(). Overrides PhpStreamWrapperInterface:: |
|
LocalStream:: |
public | function |
Support for readdir(). Overrides PhpStreamWrapperInterface:: |
|
LocalStream:: |
public | function |
Support for rewinddir(). Overrides PhpStreamWrapperInterface:: |
|
LocalStream:: |
abstract public | function | Gets the path that the wrapper is responsible for. | 6 |
LocalStream:: |
private | function | Returns file system service. | |
LocalStream:: |
protected | function | Returns the canonical absolute path of the URI, if possible. | |
LocalStream:: |
protected | function | Returns the local writable target of the resource within the stream. | |
LocalStream:: |
public static | function |
Returns the type of stream wrapper. Overrides StreamWrapperInterface:: |
5 |
LocalStream:: |
public | function |
Returns the stream resource URI. Overrides StreamWrapperInterface:: |
|
LocalStream:: |
public | function |
Support for mkdir(). Overrides PhpStreamWrapperInterface:: |
1 |
LocalStream:: |
public | function |
Returns canonical, absolute path of the resource. Overrides StreamWrapperInterface:: |
1 |
LocalStream:: |
public | function |
Support for rename(). Overrides PhpStreamWrapperInterface:: |
1 |
LocalStream:: |
public | function |
Support for rmdir(). Overrides PhpStreamWrapperInterface:: |
1 |
LocalStream:: |
public | function |
Sets the absolute stream resource URI. Overrides StreamWrapperInterface:: |
|
LocalStream:: |
public | function |
Retrieve the underlying stream resource. Overrides PhpStreamWrapperInterface:: |
|
LocalStream:: |
public | function |
Support for fclose(). Overrides PhpStreamWrapperInterface:: |
|
LocalStream:: |
public | function |
Support for feof(). Overrides PhpStreamWrapperInterface:: |
|
LocalStream:: |
public | function |
Support for fflush(). Overrides PhpStreamWrapperInterface:: |
1 |
LocalStream:: |
public | function |
Support for flock(). Overrides PhpStreamWrapperInterface:: |
1 |
LocalStream:: |
public | function |
Sets metadata on the stream. Overrides PhpStreamWrapperInterface:: |
1 |
LocalStream:: |
public | function |
Support for fopen(), file_get_contents(), file_put_contents() etc. Overrides PhpStreamWrapperInterface:: |
1 |
LocalStream:: |
public | function |
Support for fread(), file_get_contents() etc. Overrides PhpStreamWrapperInterface:: |
|
LocalStream:: |
public | function |
Seeks to specific location in a stream. Overrides PhpStreamWrapperInterface:: |
|
LocalStream:: |
public | function |
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… Overrides PhpStreamWrapperInterface:: |
|
LocalStream:: |
public | function |
Support for fstat(). Overrides PhpStreamWrapperInterface:: |
|
LocalStream:: |
public | function |
Support for ftell(). Overrides PhpStreamWrapperInterface:: |
|
LocalStream:: |
public | function |
Truncate stream. Overrides PhpStreamWrapperInterface:: |
1 |
LocalStream:: |
public | function |
Support for fwrite(), file_put_contents() etc. Overrides PhpStreamWrapperInterface:: |
1 |
LocalStream:: |
public | function |
Support for unlink(). Overrides PhpStreamWrapperInterface:: |
1 |
LocalStream:: |
public | function |
Support for stat(). Overrides PhpStreamWrapperInterface:: |
|
StreamWrapperInterface:: |
constant | A filter that matches all wrappers. | ||
StreamWrapperInterface:: |
public | function | Returns the description of the stream wrapper for use in the UI. | 6 |
StreamWrapperInterface:: |
public | function | Returns a web accessible URL for the resource. | 6 |
StreamWrapperInterface:: |
public | function | Returns the name of the stream wrapper for use in the UI. | 6 |
StreamWrapperInterface:: |
constant | Defines the stream wrapper bit flag for a hidden file. | ||
StreamWrapperInterface:: |
constant | Refers to a local file system location. | ||
StreamWrapperInterface:: |
constant | Hidden, readable and writable using local files. | ||
StreamWrapperInterface:: |
constant | Visible, readable and writable using local files. | ||
StreamWrapperInterface:: |
constant | This is the default 'type' flag. This does not include StreamWrapperInterface::LOCAL, because PHP grants a greater trust level to local files (for example, they can be used in an "include" statement, regardless of the… | ||
StreamWrapperInterface:: |
constant | Wrapper is readable (almost always true). | ||
StreamWrapperInterface:: |
constant | Visible and read-only. | ||
StreamWrapperInterface:: |
constant | Exposed in the UI and potentially web accessible. | ||
StreamWrapperInterface:: |
constant | Wrapper is writable. | ||
StreamWrapperInterface:: |
constant | Visible, readable and writable. |