Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
15.38% |
2 / 13 |
CRAP | |
26.19% |
22 / 84 |
FileSystem | |
0.00% |
0 / 1 |
|
15.38% |
2 / 13 |
786.49 | |
26.19% |
22 / 84 |
__construct | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 4 |
|||
moveUploadedFile | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 6 |
|||
chmod | |
100.00% |
1 / 1 |
4 | |
100.00% |
8 / 8 |
|||
unlink | |
0.00% |
0 / 1 |
4.59 | |
66.67% |
4 / 6 |
|||
realpath | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 3 |
|||
dirname | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 4 |
|||
basename | |
0.00% |
0 / 1 |
4.03 | |
87.50% |
7 / 8 |
|||
mkdir | |
0.00% |
0 / 1 |
110 | |
0.00% |
0 / 23 |
|||
mkdirCall | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 3 |
|||
rmdir | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 6 |
|||
tempnam | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 7 |
|||
uriScheme | |
100.00% |
1 / 1 |
2 | |
100.00% |
3 / 3 |
|||
validScheme | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 3 |
<?php | |
/** | |
* @file | |
* Contains \Drupal\Core\File\FileSystem. | |
*/ | |
namespace Drupal\Core\File; | |
use Drupal\Core\Site\Settings; | |
use Drupal\Core\StreamWrapper\StreamWrapperManagerInterface; | |
use Psr\Log\LoggerInterface; | |
/** | |
* Provides helpers to operate on files and stream wrappers. | |
*/ | |
class FileSystem implements FileSystemInterface { | |
/** | |
* Default mode for new directories. See self::chmod(). | |
*/ | |
const CHMOD_DIRECTORY = 0775; | |
/** | |
* Default mode for new files. See self::chmod(). | |
*/ | |
const CHMOD_FILE = 0664; | |
/** | |
* The site settings. | |
* | |
* @var \Drupal\Core\Site\Settings | |
*/ | |
protected $settings; | |
/** | |
* The file logger channel. | |
* | |
* @var \Psr\Log\LoggerInterface | |
*/ | |
protected $logger; | |
/** | |
* The stream wrapper manager. | |
* | |
* @var \Drupal\Core\StreamWrapper\StreamWrapperManagerInterface | |
*/ | |
protected $streamWrapperManager; | |
/** | |
* Constructs a new FileSystem. | |
* | |
* @param \Drupal\Core\StreamWrapper\StreamWrapperManagerInterface $stream_wrapper_manager | |
* The stream wrapper manager. | |
* @param \Drupal\Core\Site\Settings $settings | |
* The site settings. | |
* @param \Psr\Log\LoggerInterface $logger | |
* The file logger channel. | |
*/ | |
public function __construct(StreamWrapperManagerInterface $stream_wrapper_manager, Settings $settings, LoggerInterface $logger) { | |
$this->streamWrapperManager = $stream_wrapper_manager; | |
$this->settings = $settings; | |
$this->logger = $logger; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function moveUploadedFile($filename, $uri) { | |
$result = @move_uploaded_file($filename, $uri); | |
// PHP's move_uploaded_file() does not properly support streams if | |
// open_basedir is enabled so if the move failed, try finding a real path | |
// and retry the move operation. | |
if (!$result) { | |
if ($realpath = $this->realpath($uri)) { | |
$result = move_uploaded_file($filename, $realpath); | |
} | |
else { | |
$result = move_uploaded_file($filename, $uri); | |
} | |
} | |
return $result; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function chmod($uri, $mode = NULL) { | |
if (!isset($mode)) { | |
if (is_dir($uri)) { | |
$mode = $this->settings->get('file_chmod_directory', static::CHMOD_DIRECTORY); | |
} | |
else { | |
$mode = $this->settings->get('file_chmod_file', static::CHMOD_FILE); | |
} | |
} | |
if (@chmod($uri, $mode)) { | |
return TRUE; | |
} | |
$this->logger->error('The file permissions could not be set on %uri.', array('%uri' => $uri)); | |
return FALSE; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function unlink($uri, $context = NULL) { | |
$scheme = $this->uriScheme($uri); | |
if (!$this->validScheme($scheme) && (substr(PHP_OS, 0, 3) == 'WIN')) { | |
chmod($uri, 0600); | |
} | |
if ($context) { | |
return unlink($uri, $context); | |
} | |
else { | |
return unlink($uri); | |
} | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function realpath($uri) { | |
// If this URI is a stream, pass it off to the appropriate stream wrapper. | |
// Otherwise, attempt PHP's realpath. This allows use of this method even | |
// for unmanaged files outside of the stream wrapper interface. | |
if ($wrapper = $this->streamWrapperManager->getViaUri($uri)) { | |
return $wrapper->realpath(); | |
} | |
return realpath($uri); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function dirname($uri) { | |
$scheme = $this->uriScheme($uri); | |
if ($this->validScheme($scheme)) { | |
return $this->streamWrapperManager->getViaScheme($scheme)->dirname($uri); | |
} | |
else { | |
return dirname($uri); | |
} | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function basename($uri, $suffix = NULL) { | |
$separators = '/'; | |
if (DIRECTORY_SEPARATOR != '/') { | |
// For Windows OS add special separator. | |
$separators .= DIRECTORY_SEPARATOR; | |
} | |
// Remove right-most slashes when $uri points to directory. | |
$uri = rtrim($uri, $separators); | |
// Returns the trailing part of the $uri starting after one of the directory | |
// separators. | |
$filename = preg_match('@[^' . preg_quote($separators, '@') . ']+$@', $uri, $matches) ? $matches[0] : ''; | |
// Cuts off a suffix from the filename. | |
if ($suffix) { | |
$filename = preg_replace('@' . preg_quote($suffix, '@') . '$@', '', $filename); | |
} | |
return $filename; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function mkdir($uri, $mode = NULL, $recursive = FALSE, $context = NULL) { | |
if (!isset($mode)) { | |
$mode = $this->settings->get('file_chmod_directory', static::CHMOD_DIRECTORY); | |
} | |
// If the URI has a scheme, don't override the umask - schemes can handle | |
// this issue in their own implementation. | |
if ($this->uriScheme($uri)) { | |
return $this->mkdirCall($uri, $mode, $recursive, $context); | |
} | |
// If recursive, create each missing component of the parent directory | |
// individually and set the mode explicitly to override the umask. | |
if ($recursive) { | |
// Ensure the path is using DIRECTORY_SEPARATOR. | |
$uri = str_replace('/', DIRECTORY_SEPARATOR, $uri); | |
// Determine the components of the path. | |
$components = explode(DIRECTORY_SEPARATOR, $uri); | |
// If the filepath is absolute the first component will be empty as there | |
// will be nothing before the first slash. | |
if ($components[0] == '') { | |
$recursive_path = DIRECTORY_SEPARATOR; | |
// Get rid of the empty first component. | |
array_shift($components); | |
} | |
else { | |
$recursive_path = ''; | |
} | |
// Don't handle the top-level directory in this loop. | |
array_pop($components); | |
// Create each component if necessary. | |
foreach ($components as $component) { | |
$recursive_path .= $component; | |
if (!file_exists($recursive_path)) { | |
if (!$this->mkdirCall($recursive_path, $mode, FALSE, $context)) { | |
return FALSE; | |
} | |
// Not necessary to use self::chmod() as there is no scheme. | |
if (!chmod($recursive_path, $mode)) { | |
return FALSE; | |
} | |
} | |
$recursive_path .= DIRECTORY_SEPARATOR; | |
} | |
} | |
// Do not check if the top-level directory already exists, as this condition | |
// must cause this function to fail. | |
if (!$this->mkdirCall($uri, $mode, FALSE, $context)) { | |
return FALSE; | |
} | |
// Not necessary to use self::chmod() as there is no scheme. | |
return chmod($uri, $mode); | |
} | |
/** | |
* Helper function. Ensures we don't pass a NULL as a context resource to | |
* mkdir(). | |
* | |
* @see self::mkdir() | |
*/ | |
protected function mkdirCall($uri, $mode, $recursive, $context) { | |
if (is_null($context)) { | |
return mkdir($uri, $mode, $recursive); | |
} | |
else { | |
return mkdir($uri, $mode, $recursive, $context); | |
} | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function rmdir($uri, $context = NULL) { | |
$scheme = $this->uriScheme($uri); | |
if (!$this->validScheme($scheme) && (substr(PHP_OS, 0, 3) == 'WIN')) { | |
chmod($uri, 0700); | |
} | |
if ($context) { | |
return rmdir($uri, $context); | |
} | |
else { | |
return rmdir($uri); | |
} | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function tempnam($directory, $prefix) { | |
$scheme = $this->uriScheme($directory); | |
if ($this->validScheme($scheme)) { | |
$wrapper = $this->streamWrapperManager->getViaScheme($scheme); | |
if ($filename = tempnam($wrapper->getDirectoryPath(), $prefix)) { | |
return $scheme . '://' . static::basename($filename); | |
} | |
else { | |
return FALSE; | |
} | |
} | |
else { | |
// Handle as a normal tempnam() call. | |
return tempnam($directory, $prefix); | |
} | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function uriScheme($uri) { | |
if (preg_match('/^([\w\-]+):\/\/|^(data):/', $uri, $matches)) { | |
// The scheme will always be the last element in the matches array. | |
return array_pop($matches); | |
} | |
return FALSE; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function validScheme($scheme) { | |
if (!$scheme) { | |
return FALSE; | |
} | |
return class_exists($this->streamWrapperManager->getClass($scheme)); | |
} | |
} |