Issue #3035312 by kim.pepper, andypost, martin107, yogeshmpawar, naveenvalecha, pguillard, Berdir, dww, claudiu.cristea, jibran, Mile23: Move file_scan_directory() to file_system service
parent
5d68f9fc21
commit
dd907896b1
|
|
@ -992,81 +992,23 @@ function file_unmanaged_save_data($data, $destination = NULL, $replace = FILE_EX
|
|||
* @return
|
||||
* An associative array (keyed on the chosen key) of objects with 'uri',
|
||||
* 'filename', and 'name' properties corresponding to the matched files.
|
||||
*
|
||||
* @deprecated in drupal:8.8.0 and is removed from drupal:9.0.0.
|
||||
* Use \Drupal\Core\File\FileSystemInterface::scanDirectory() instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/3038437
|
||||
*/
|
||||
function file_scan_directory($dir, $mask, $options = [], $depth = 0) {
|
||||
// Merge in defaults.
|
||||
$options += [
|
||||
'callback' => 0,
|
||||
'recurse' => TRUE,
|
||||
'key' => 'uri',
|
||||
'min_depth' => 0,
|
||||
];
|
||||
// Normalize $dir only once.
|
||||
if ($depth == 0) {
|
||||
/** @var \Drupal\Core\StreamWrapper\StreamWrapperManagerInterface $stream_wrapper_manager */
|
||||
$stream_wrapper_manager = \Drupal::service('stream_wrapper_manager');
|
||||
$dir = $stream_wrapper_manager->normalizeUri($dir);
|
||||
$dir_has_slash = (substr($dir, -1) === '/');
|
||||
}
|
||||
|
||||
// Allow directories specified in settings.php to be ignored. You can use this
|
||||
// to not check for files in common special-purpose directories. For example,
|
||||
// node_modules and bower_components. Ignoring irrelevant directories is a
|
||||
// performance boost.
|
||||
if (!isset($options['nomask'])) {
|
||||
$ignore_directories = Settings::get('file_scan_ignore_directories', []);
|
||||
array_walk($ignore_directories, function (&$value) {
|
||||
$value = preg_quote($value, '/');
|
||||
});
|
||||
$default_nomask = '/^' . implode('|', $ignore_directories) . '$/';
|
||||
}
|
||||
|
||||
$options['key'] = in_array($options['key'], ['uri', 'filename', 'name']) ? $options['key'] : 'uri';
|
||||
@trigger_error('file_scan_directory() is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Use \Drupal\Core\File\FileSystemInterface::scanDirectory() instead. See https://www.drupal.org/node/3038437', E_USER_DEPRECATED);
|
||||
$files = [];
|
||||
// Avoid warnings when opendir does not have the permissions to open a
|
||||
// directory.
|
||||
if (is_dir($dir)) {
|
||||
if ($handle = @opendir($dir)) {
|
||||
while (FALSE !== ($filename = readdir($handle))) {
|
||||
// Skip this file if it matches the nomask or starts with a dot.
|
||||
if ($filename[0] != '.'
|
||||
&& !(isset($options['nomask']) && preg_match($options['nomask'], $filename))
|
||||
&& !(!empty($default_nomask) && preg_match($default_nomask, $filename))
|
||||
) {
|
||||
if ($depth == 0 && $dir_has_slash) {
|
||||
$uri = "$dir$filename";
|
||||
}
|
||||
else {
|
||||
$uri = "$dir/$filename";
|
||||
}
|
||||
if ($options['recurse'] && is_dir($uri)) {
|
||||
// Give priority to files in this folder by merging them in after
|
||||
// any subdirectory files.
|
||||
$files = array_merge(file_scan_directory($uri, $mask, $options, $depth + 1), $files);
|
||||
}
|
||||
elseif ($depth >= $options['min_depth'] && preg_match($mask, $filename)) {
|
||||
// Always use this match over anything already set in $files with
|
||||
// the same $options['key'].
|
||||
$file = new stdClass();
|
||||
$file->uri = $uri;
|
||||
$file->filename = $filename;
|
||||
$file->name = pathinfo($filename, PATHINFO_FILENAME);
|
||||
$key = $options['key'];
|
||||
$files[$file->$key] = $file;
|
||||
if ($options['callback']) {
|
||||
$options['callback']($uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
closedir($handle);
|
||||
}
|
||||
else {
|
||||
\Drupal::logger('file')->error('@dir can not be opened', ['@dir' => $dir]);
|
||||
try {
|
||||
if (is_dir($dir)) {
|
||||
$files = \Drupal::service('file_system')->scanDirectory($dir, $mask, $options);
|
||||
}
|
||||
}
|
||||
|
||||
catch (FileException $e) {
|
||||
// Ignore and return empty array for BC.
|
||||
}
|
||||
return $files;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -444,7 +444,9 @@ function install_begin_request($class_loader, &$install_state) {
|
|||
else {
|
||||
$directory = $site_path . '/files/translations';
|
||||
}
|
||||
$container->set('string_translator.file_translation', new FileTranslation($directory));
|
||||
/** @var \Drupal\Core\File\FileSystemInterface $file_system */
|
||||
$file_system = $container->get('file_system');
|
||||
$container->set('string_translator.file_translation', new FileTranslation($directory, $file_system));
|
||||
$container->get('string_translation')
|
||||
->addTranslator($container->get('string_translator.file_translation'));
|
||||
|
||||
|
|
@ -1324,9 +1326,9 @@ function _install_select_profile(&$install_state) {
|
|||
*
|
||||
* @return
|
||||
* An associative array of file URIs keyed by language code. URIs as
|
||||
* returned by file_scan_directory().
|
||||
* returned by FileSystemInterface::scanDirectory().
|
||||
*
|
||||
* @see file_scan_directory()
|
||||
* @see \Drupal\Core\File\FileSystemInterface::scanDirectory()
|
||||
*/
|
||||
function install_find_translations() {
|
||||
$translations = [];
|
||||
|
|
|
|||
|
|
@ -5,15 +5,15 @@
|
|||
* API functions for installing modules and themes.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Extension\Dependency;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Core\File\FileSystemInterface;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Drupal\Component\Utility\Crypt;
|
||||
use Drupal\Component\Utility\OpCodeCache;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Component\Utility\UrlHelper;
|
||||
use Drupal\Core\Extension\Dependency;
|
||||
use Drupal\Core\Extension\ExtensionDiscovery;
|
||||
use Drupal\Core\File\FileSystemInterface;
|
||||
use Drupal\Core\Site\Settings;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
|
||||
/**
|
||||
* Requirement severity -- Informational message only.
|
||||
|
|
@ -166,9 +166,11 @@ function drupal_get_database_types() {
|
|||
|
||||
// The internal database driver name is any valid PHP identifier.
|
||||
$mask = '/^' . DRUPAL_PHP_FUNCTION_PATTERN . '$/';
|
||||
$files = file_scan_directory(DRUPAL_ROOT . '/core/lib/Drupal/Core/Database/Driver', $mask, ['recurse' => FALSE]);
|
||||
/** @var \Drupal\Core\File\FileSystemInterface $file_system */
|
||||
$file_system = \Drupal::service('file_system');
|
||||
$files = $file_system->scanDirectory(DRUPAL_ROOT . '/core/lib/Drupal/Core/Database/Driver', $mask, ['recurse' => FALSE]);
|
||||
if (is_dir(DRUPAL_ROOT . '/drivers/lib/Drupal/Driver/Database')) {
|
||||
$files += file_scan_directory(DRUPAL_ROOT . '/drivers/lib/Drupal/Driver/Database/', $mask, ['recurse' => FALSE]);
|
||||
$files += $file_system->scanDirectory(DRUPAL_ROOT . '/drivers/lib/Drupal/Driver/Database/', $mask, ['recurse' => FALSE]);
|
||||
}
|
||||
foreach ($files as $file) {
|
||||
if (file_exists($file->uri . '/Install/Tasks.php')) {
|
||||
|
|
|
|||
|
|
@ -216,7 +216,10 @@ function drupal_find_theme_templates($cache, $extension, $path) {
|
|||
// Escape the periods in the extension.
|
||||
$regex = '/' . str_replace('.', '\.', $extension) . '$/';
|
||||
// Get a listing of all template files in the path to search.
|
||||
$files = file_scan_directory($path, $regex, ['key' => 'filename']);
|
||||
$files = [];
|
||||
if (is_dir($path)) {
|
||||
$files = \Drupal::service('file_system')->scanDirectory($path, $regex, ['key' => 'filename']);
|
||||
}
|
||||
|
||||
// Find templates that implement registered theme hooks and include that in
|
||||
// what is returned so that the registry knows that the theme has this
|
||||
|
|
|
|||
|
|
@ -196,7 +196,9 @@ class CssCollectionOptimizer implements AssetCollectionOptimizerInterface {
|
|||
$this->fileSystem->delete($uri);
|
||||
}
|
||||
};
|
||||
file_scan_directory('public://css', '/.*/', ['callback' => $delete_stale]);
|
||||
if (is_dir('public://css')) {
|
||||
$this->fileSystem->scanDirectory('public://css', '/.*/', ['callback' => $delete_stale]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -198,7 +198,9 @@ class JsCollectionOptimizer implements AssetCollectionOptimizerInterface {
|
|||
$this->fileSystem->delete($uri);
|
||||
}
|
||||
};
|
||||
file_scan_directory('public://js', '/.*/', ['callback' => $delete_stale]);
|
||||
if (is_dir('public://js')) {
|
||||
$this->fileSystem->scanDirectory('public://js', '/.*/', ['callback' => $delete_stale]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Core\File\Exception;
|
||||
|
||||
/**
|
||||
* Exception thrown when a target is not a regular directory (e.g. a file).
|
||||
*/
|
||||
class NotRegularDirectoryException extends FileException {}
|
||||
|
|
@ -8,6 +8,7 @@ use Drupal\Core\File\Exception\FileException;
|
|||
use Drupal\Core\File\Exception\FileExistsException;
|
||||
use Drupal\Core\File\Exception\FileNotExistsException;
|
||||
use Drupal\Core\File\Exception\FileWriteException;
|
||||
use Drupal\Core\File\Exception\NotRegularDirectoryException;
|
||||
use Drupal\Core\File\Exception\NotRegularFileException;
|
||||
use Drupal\Core\Site\Settings;
|
||||
use Drupal\Core\StreamWrapper\StreamWrapperManager;
|
||||
|
|
@ -625,4 +626,97 @@ class FileSystem implements FileSystemInterface {
|
|||
return $destination;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function scanDirectory($dir, $mask, array $options = []) {
|
||||
// Merge in defaults.
|
||||
$options += [
|
||||
'callback' => 0,
|
||||
'recurse' => TRUE,
|
||||
'key' => 'uri',
|
||||
'min_depth' => 0,
|
||||
];
|
||||
$dir = $this->streamWrapperManager->normalizeUri($dir);
|
||||
if (!is_dir($dir)) {
|
||||
throw new NotRegularDirectoryException("$dir is not a directory.");
|
||||
}
|
||||
// Allow directories specified in settings.php to be ignored. You can use
|
||||
// this to not check for files in common special-purpose directories. For
|
||||
// example, node_modules and bower_components. Ignoring irrelevant
|
||||
// directories is a performance boost.
|
||||
if (!isset($options['nomask'])) {
|
||||
$ignore_directories = $this->settings->get('file_scan_ignore_directories', []);
|
||||
array_walk($ignore_directories, function (&$value) {
|
||||
$value = preg_quote($value, '/');
|
||||
});
|
||||
$options['nomask'] = '/^' . implode('|', $ignore_directories) . '$/';
|
||||
}
|
||||
$options['key'] = in_array($options['key'], ['uri', 'filename', 'name']) ? $options['key'] : 'uri';
|
||||
return $this->doScanDirectory($dir, $mask, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal function to handle directory scanning with recursion.
|
||||
*
|
||||
* @param string $dir
|
||||
* The base directory or URI to scan, without trailing slash.
|
||||
* @param string $mask
|
||||
* The preg_match() regular expression for files to be included.
|
||||
* @param array $options
|
||||
* The options as per ::scanDirectory().
|
||||
* @param int $depth
|
||||
* The current depth of recursion.
|
||||
*
|
||||
* @return array
|
||||
* An associative array as per ::scanDirectory().
|
||||
*
|
||||
* @throws \Drupal\Core\File\Exception\NotRegularDirectoryException
|
||||
* If the directory does not exist.
|
||||
*
|
||||
* @see \Drupal\Core\File\FileSystemInterface::scanDirectory()
|
||||
*/
|
||||
protected function doScanDirectory($dir, $mask, array $options = [], $depth = 0) {
|
||||
$files = [];
|
||||
// Avoid warnings when opendir does not have the permissions to open a
|
||||
// directory.
|
||||
if ($handle = @opendir($dir)) {
|
||||
while (FALSE !== ($filename = readdir($handle))) {
|
||||
// Skip this file if it matches the nomask or starts with a dot.
|
||||
if ($filename[0] != '.' && !(preg_match($options['nomask'], $filename))) {
|
||||
if (substr($dir, -1) == '/') {
|
||||
$uri = "$dir$filename";
|
||||
}
|
||||
else {
|
||||
$uri = "$dir/$filename";
|
||||
}
|
||||
if ($options['recurse'] && is_dir($uri)) {
|
||||
// Give priority to files in this folder by merging them in after
|
||||
// any subdirectory files.
|
||||
$files = array_merge($this->doScanDirectory($uri, $mask, $options, $depth + 1), $files);
|
||||
}
|
||||
elseif ($depth >= $options['min_depth'] && preg_match($mask, $filename)) {
|
||||
// Always use this match over anything already set in $files with
|
||||
// the same $options['key'].
|
||||
$file = new \stdClass();
|
||||
$file->uri = $uri;
|
||||
$file->filename = $filename;
|
||||
$file->name = pathinfo($filename, PATHINFO_FILENAME);
|
||||
$key = $options['key'];
|
||||
$files[$file->$key] = $file;
|
||||
if ($options['callback']) {
|
||||
$options['callback']($uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir($handle);
|
||||
}
|
||||
else {
|
||||
$this->logger->error('@dir can not be opened', ['@dir' => $dir]);
|
||||
}
|
||||
|
||||
return $files;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -472,4 +472,43 @@ interface FileSystemInterface {
|
|||
*/
|
||||
public function getDestinationFilename($destination, $replace);
|
||||
|
||||
/**
|
||||
* Finds all files that match a given mask in a given directory.
|
||||
*
|
||||
* Directories and files beginning with a dot are excluded; this prevents
|
||||
* hidden files and directories (such as SVN working directories) from being
|
||||
* scanned. Use the umask option to skip configuration directories to
|
||||
* eliminate the possibility of accidentally exposing configuration
|
||||
* information. Also, you can use the base directory, recurse, and min_depth
|
||||
* options to improve performance by limiting how much of the filesystem has
|
||||
* to be traversed.
|
||||
*
|
||||
* @param string $dir
|
||||
* The base directory or URI to scan, without trailing slash.
|
||||
* @param string $mask
|
||||
* The preg_match() regular expression for files to be included.
|
||||
* @param array $options
|
||||
* An associative array of additional options, with the following elements:
|
||||
* - 'nomask': The preg_match() regular expression for files to be excluded.
|
||||
* Defaults to the 'file_scan_ignore_directories' setting.
|
||||
* - 'callback': The callback function to call for each match. There is no
|
||||
* default callback.
|
||||
* - 'recurse': When TRUE, the directory scan will recurse the entire tree
|
||||
* starting at the provided directory. Defaults to TRUE.
|
||||
* - 'key': The key to be used for the returned associative array of files.
|
||||
* Possible values are 'uri', for the file's URI; 'filename', for the
|
||||
* basename of the file; and 'name' for the name of the file without the
|
||||
* extension. Defaults to 'uri'.
|
||||
* - 'min_depth': Minimum depth of directories to return files from.
|
||||
* Defaults to 0.
|
||||
*
|
||||
* @return array
|
||||
* An associative array (keyed on the chosen key) of objects with 'uri',
|
||||
* 'filename', and 'name' properties corresponding to the matched files.
|
||||
*
|
||||
* @throws \Drupal\Core\File\Exception\NotRegularDirectoryException
|
||||
* If the directory does not exist.
|
||||
*/
|
||||
public function scanDirectory($dir, $mask, array $options = []);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ namespace Drupal\Core\StringTranslation\Translator;
|
|||
|
||||
use Drupal\Component\Gettext\PoStreamReader;
|
||||
use Drupal\Component\Gettext\PoMemoryWriter;
|
||||
use Drupal\Core\File\FileSystemInterface;
|
||||
|
||||
/**
|
||||
* File based string translation.
|
||||
|
|
@ -22,15 +23,29 @@ class FileTranslation extends StaticTranslation {
|
|||
*/
|
||||
protected $directory;
|
||||
|
||||
/**
|
||||
* The file system.
|
||||
*
|
||||
* @var \Drupal\Core\File\FileSystemInterface
|
||||
*/
|
||||
protected $fileSystem;
|
||||
|
||||
/**
|
||||
* Constructs a StaticTranslation object.
|
||||
*
|
||||
* @param string $directory
|
||||
* The directory to retrieve file translations from.
|
||||
* @param \Drupal\Core\File\FileSystemInterface $file_system
|
||||
* The file system service.
|
||||
*/
|
||||
public function __construct($directory) {
|
||||
public function __construct($directory, FileSystemInterface $file_system = NULL) {
|
||||
parent::__construct();
|
||||
$this->directory = $directory;
|
||||
if (!isset($file_system)) {
|
||||
@trigger_error('Calling FileTranslation::__construct() without the $file_system argument is deprecated in drupal:8.8.0. The $file_system argument will be required in drupal:9.0.0. See https://www.drupal.org/node/3038437', E_USER_DEPRECATED);
|
||||
$file_system = \Drupal::service('file_system');
|
||||
}
|
||||
$this->fileSystem = $file_system;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -65,12 +80,15 @@ class FileTranslation extends StaticTranslation {
|
|||
*
|
||||
* @return array
|
||||
* An associative array of file information objects keyed by file URIs as
|
||||
* returned by file_scan_directory().
|
||||
* returned by FileSystemInterface::scanDirectory().
|
||||
*
|
||||
* @see file_scan_directory()
|
||||
* @see \Drupal\Core\File\FileSystemInterface::scanDirectory()
|
||||
*/
|
||||
public function findTranslationFiles($langcode = NULL) {
|
||||
$files = file_scan_directory($this->directory, $this->getTranslationFilesPattern($langcode), ['recurse' => FALSE]);
|
||||
$files = [];
|
||||
if (is_dir($this->directory)) {
|
||||
$files = $this->fileSystem->scanDirectory($this->directory, $this->getTranslationFilesPattern($langcode), ['recurse' => FALSE]);
|
||||
}
|
||||
return $files;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -106,12 +106,17 @@ class Updater {
|
|||
* Path to the info file.
|
||||
*/
|
||||
public static function findInfoFile($directory) {
|
||||
$info_files = file_scan_directory($directory, '/.*\.info.yml$/');
|
||||
/** @var \Drupal\Core\File\FileSystemInterface $file_system */
|
||||
$file_system = \Drupal::service('file_system');
|
||||
$info_files = [];
|
||||
if (is_dir($directory)) {
|
||||
$info_files = $file_system->scanDirectory($directory, '/.*\.info.yml$/');
|
||||
}
|
||||
if (!$info_files) {
|
||||
return FALSE;
|
||||
}
|
||||
foreach ($info_files as $info_file) {
|
||||
if (mb_substr($info_file->filename, 0, -9) == \Drupal::service('file_system')->basename($directory)) {
|
||||
if (mb_substr($info_file->filename, 0, -9) == $file_system->basename($directory)) {
|
||||
// Info file Has the same name as the directory, return it.
|
||||
return $info_file->uri;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -314,7 +314,7 @@ function file_test_validator(File $file, $errors) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Helper function for testing file_scan_directory().
|
||||
* Helper function for testing FileSystemInterface::scanDirectory().
|
||||
*
|
||||
* Each time the function is called the file is stored in a static variable.
|
||||
* When the function is called with no $filepath parameter, the results are
|
||||
|
|
|
|||
|
|
@ -44,7 +44,11 @@ class ImageAdminStylesTest extends ImageFieldTestBase {
|
|||
* Count the number of images currently create for a style.
|
||||
*/
|
||||
public function getImageCount(ImageStyleInterface $style) {
|
||||
return count(file_scan_directory('public://styles/' . $style->id(), '/.*/'));
|
||||
$count = 0;
|
||||
if (is_dir('public://styles/' . $style->id())) {
|
||||
$count = count(\Drupal::service('file_system')->scanDirectory('public://styles/' . $style->id(), '/.*/'));
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -40,7 +40,11 @@ class ImageFieldValidateTest extends ImageFieldTestBase {
|
|||
$this->drupalPostForm(NULL, [], t('Save'));
|
||||
|
||||
// Get invalid image test files from simpletest.
|
||||
$files = file_scan_directory(drupal_get_path('module', 'simpletest') . '/files', '/invalid-img-.*/');
|
||||
$dir = drupal_get_path('module', 'simpletest') . '/files';
|
||||
$files = [];
|
||||
if (is_dir($dir)) {
|
||||
$files = $file_system->scanDirectory($dir, '/invalid-img-.*/');
|
||||
}
|
||||
$invalid_image_files = [];
|
||||
foreach ($files as $file) {
|
||||
$invalid_image_files[$file->filename] = $file;
|
||||
|
|
|
|||
|
|
@ -42,7 +42,11 @@ class ImageStyleFlushTest extends ImageFieldTestBase {
|
|||
* Count the number of images currently created for a style in a wrapper.
|
||||
*/
|
||||
public function getImageCount($style, $wrapper) {
|
||||
return count(file_scan_directory($wrapper . '://styles/' . $style->id(), '/.*/'));
|
||||
$count = 0;
|
||||
if (is_dir($wrapper . '://styles/' . $style->id())) {
|
||||
$count = count(\Drupal::service('file_system')->scanDirectory($wrapper . '://styles/' . $style->id(), '/.*/'));
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -97,7 +97,10 @@ function locale_translate_get_interface_translation_files(array $projects = [],
|
|||
// {project}-{version}.{langcode}.po.
|
||||
// Only files of known projects and languages will be returned.
|
||||
$directory = \Drupal::config('locale.settings')->get('translation.path');
|
||||
$result = file_scan_directory($directory, '![a-z_]+(\-[0-9a-z\.\-\+]+|)\.[^\./]+\.po$!', ['recurse' => FALSE]);
|
||||
$result = [];
|
||||
if (is_dir($directory)) {
|
||||
$result = \Drupal::service('file_system')->scanDirectory($directory, '![a-z_]+(\-[0-9a-z\.\-\+]+|)\.[^\./]+\.po$!', ['recurse' => FALSE]);
|
||||
}
|
||||
|
||||
foreach ($result as $file) {
|
||||
// Update the file object with project name and version from the file name.
|
||||
|
|
|
|||
|
|
@ -32,10 +32,12 @@ function locale_uninstall() {
|
|||
|
||||
if (is_dir($locale_js_directory)) {
|
||||
$locale_javascripts = \Drupal::state()->get('locale.translation.javascript') ?: [];
|
||||
/** @var \Drupal\Core\File\FileSystemInterface $file_system */
|
||||
$file_system = \Drupal::service('file_system');
|
||||
foreach ($locale_javascripts as $langcode => $file_suffix) {
|
||||
if (!empty($file_suffix)) {
|
||||
try {
|
||||
\Drupal::service('file_system')->delete($locale_js_directory . '/' . $langcode . '_' . $file_suffix . '.js');
|
||||
$file_system->delete($locale_js_directory . '/' . $langcode . '_' . $file_suffix . '.js');
|
||||
}
|
||||
catch (FileException $e) {
|
||||
// Ignore and continue.
|
||||
|
|
@ -43,8 +45,10 @@ function locale_uninstall() {
|
|||
}
|
||||
}
|
||||
// Delete the JavaScript translations directory if empty.
|
||||
if (!file_scan_directory($locale_js_directory, '/.*/')) {
|
||||
\Drupal::service('file_system')->rmdir($locale_js_directory);
|
||||
if (is_dir($locale_js_directory)) {
|
||||
if (!$file_system->scanDirectory($locale_js_directory, '/.*/')) {
|
||||
$file_system->rmdir($locale_js_directory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -175,11 +175,13 @@ function locale_translation_source_check_file($source) {
|
|||
$directory = $source_file->directory;
|
||||
$filename = '/' . preg_quote($source_file->filename) . '$/';
|
||||
|
||||
if ($files = file_scan_directory($directory, $filename, ['key' => 'name', 'recurse' => FALSE])) {
|
||||
$file = current($files);
|
||||
$source_file->uri = $file->uri;
|
||||
$source_file->timestamp = filemtime($file->uri);
|
||||
return $source_file;
|
||||
if (is_dir($directory)) {
|
||||
if ($files = \Drupal::service('file_system')->scanDirectory($directory, $filename, ['key' => 'name', 'recurse' => FALSE])) {
|
||||
$file = current($files);
|
||||
$source_file->uri = $file->uri;
|
||||
$source_file->timestamp = filemtime($file->uri);
|
||||
return $source_file;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ function media_install() {
|
|||
$file_system = \Drupal::service('file_system');
|
||||
$file_system->prepareDirectory($destination, FileSystemInterface::CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS);
|
||||
|
||||
$files = file_scan_directory($source, '/.*\.(svg|png|jpg|jpeg|gif)$/');
|
||||
$files = $file_system->scanDirectory($source, '/.*\.(svg|png|jpg|jpeg|gif)$/');
|
||||
foreach ($files as $file) {
|
||||
// When reinstalling the media module we don't want to copy the icons when
|
||||
// they already exist. The icons could be replaced (by a contrib module or
|
||||
|
|
|
|||
|
|
@ -1,16 +1,21 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\system\Unit\Installer;
|
||||
namespace Drupal\Tests\system\Kernel\Installer;
|
||||
|
||||
use Drupal\Core\StringTranslation\Translator\FileTranslation;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Tests for installer language support.
|
||||
*
|
||||
* @group Installer
|
||||
*/
|
||||
class InstallTranslationFilePatternTest extends UnitTestCase {
|
||||
class InstallTranslationFilePatternTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['system'];
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\StringTranslation\Translator\FileTranslation
|
||||
|
|
@ -27,7 +32,7 @@ class InstallTranslationFilePatternTest extends UnitTestCase {
|
|||
*/
|
||||
protected function setup() {
|
||||
parent::setUp();
|
||||
$this->fileTranslation = new FileTranslation('filename');
|
||||
$this->fileTranslation = new FileTranslation('filename', $this->container->get('file_system'));
|
||||
$method = new \ReflectionMethod('\Drupal\Core\StringTranslation\Translator\FileTranslation', 'getTranslationFilesPattern');
|
||||
$method->setAccessible(TRUE);
|
||||
$this->filePatternMethod = $method;
|
||||
|
|
@ -690,7 +690,9 @@ function update_verify_update_archive($project, $archive_file, $directory) {
|
|||
// functionality).
|
||||
$compatible_project = FALSE;
|
||||
$incompatible = [];
|
||||
$files = file_scan_directory("$directory/$project", '/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.info.yml$/', ['key' => 'name', 'min_depth' => 0]);
|
||||
/** @var \Drupal\Core\File\FileSystemInterface $file_system */
|
||||
$file_system = \Drupal::service('file_system');
|
||||
$files = $file_system->scanDirectory("$directory/$project", '/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.info.yml$/', ['key' => 'name', 'min_depth' => 0]);
|
||||
foreach ($files as $file) {
|
||||
// Get the .info.yml file for the module or theme this file belongs to.
|
||||
$info = \Drupal::service('info_parser')->parse($file->uri);
|
||||
|
|
@ -705,8 +707,6 @@ function update_verify_update_archive($project, $archive_file, $directory) {
|
|||
}
|
||||
}
|
||||
|
||||
/** @var \Drupal\Core\File\FileSystemInterface $file_system */
|
||||
$file_system = \Drupal::service('file_system');
|
||||
if (empty($files)) {
|
||||
$errors[] = t('%archive_file does not contain any .info.yml files.', ['%archive_file' => $file_system->basename($archive_file)]);
|
||||
}
|
||||
|
|
@ -805,7 +805,7 @@ function update_clear_update_disk_cache() {
|
|||
|
||||
// Search for files and directories in base folder only without recursion.
|
||||
foreach ($directories as $directory) {
|
||||
file_scan_directory($directory, '/.*/', ['callback' => 'update_delete_file_if_stale', 'recurse' => FALSE]);
|
||||
\Drupal::service('file_system')->scanDirectory($directory, '/.*/', ['callback' => 'update_delete_file_if_stale', 'recurse' => FALSE]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1084,7 +1084,7 @@ function simpletest_script_get_test_list() {
|
|||
else {
|
||||
$directory = DRUPAL_ROOT . "/" . $args['directory'];
|
||||
}
|
||||
foreach (file_scan_directory($directory, '/\.php$/', $ignore) as $file) {
|
||||
foreach (\Drupal::service('file_system')->scanDirectory($directory, '/\.php$/', $ignore) as $file) {
|
||||
// '/Tests/' can be contained anywhere in the file's path (there can be
|
||||
// sub-directories below /Tests), but must be contained literally.
|
||||
// Case-insensitive to match all Simpletest and PHPUnit tests:
|
||||
|
|
|
|||
|
|
@ -259,4 +259,11 @@ class FileSystemDeprecationTest extends KernelTestBase {
|
|||
$this->assertNotEmpty(drupal_realpath('public://'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedDeprecation file_scan_directory() is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Use \Drupal\Core\File\FileSystemInterface::scanDirectory() instead. See https://www.drupal.org/node/3038437
|
||||
*/
|
||||
public function testDeprecatedScanDirectory() {
|
||||
$this->assertNotNull(file_scan_directory('temporary://', '/^NONEXISTINGFILENAME/'));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,9 @@
|
|||
namespace Drupal\KernelTests\Core\File;
|
||||
|
||||
/**
|
||||
* Tests the file_scan_directory() function.
|
||||
* Tests \Drupal\Core\File\FileSystemInterface::scanDirectory().
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Core\File\FileSystem
|
||||
* @group File
|
||||
*/
|
||||
class RemoteFileScanDirectoryTest extends ScanDirectoryTest {
|
||||
|
|
|
|||
|
|
@ -3,8 +3,9 @@
|
|||
namespace Drupal\KernelTests\Core\File;
|
||||
|
||||
/**
|
||||
* Tests the file_scan_directory() function.
|
||||
* Tests \Drupal\Core\File\FileSystem::scanDirectory.
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Core\File\FileSystem
|
||||
* @group File
|
||||
*/
|
||||
class ScanDirectoryTest extends FileTestBase {
|
||||
|
|
@ -21,6 +22,16 @@ class ScanDirectoryTest extends FileTestBase {
|
|||
*/
|
||||
protected $path;
|
||||
|
||||
/**
|
||||
* The file system.
|
||||
*
|
||||
* @var \Drupal\Core\File\FileSystemInterface
|
||||
*/
|
||||
protected $fileSystem;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
// Hardcode the location of the simpletest files as it is already known
|
||||
|
|
@ -28,15 +39,18 @@ class ScanDirectoryTest extends FileTestBase {
|
|||
// location from drupal_get_filename() in a cached way.
|
||||
// @todo Remove as part of https://www.drupal.org/node/2186491
|
||||
$this->path = 'core/modules/simpletest/files';
|
||||
$this->fileSystem = $this->container->get('file_system');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the format of the returned values.
|
||||
*
|
||||
* @covers ::scanDirectory
|
||||
*/
|
||||
public function testReturn() {
|
||||
// Grab a listing of all the JavaScript files and check that they're
|
||||
// passed to the callback.
|
||||
$all_files = file_scan_directory($this->path, '/^javascript-/');
|
||||
$all_files = $this->fileSystem->scanDirectory($this->path, '/^javascript-/');
|
||||
ksort($all_files);
|
||||
$this->assertEqual(2, count($all_files), 'Found two, expected javascript files.');
|
||||
|
||||
|
|
@ -57,11 +71,13 @@ class ScanDirectoryTest extends FileTestBase {
|
|||
|
||||
/**
|
||||
* Check that the callback function is called correctly.
|
||||
*
|
||||
* @covers ::scanDirectory
|
||||
*/
|
||||
public function testOptionCallback() {
|
||||
|
||||
// When nothing is matched nothing should be passed to the callback.
|
||||
$all_files = file_scan_directory($this->path, '/^NONEXISTINGFILENAME/', ['callback' => 'file_test_file_scan_callback']);
|
||||
$all_files = $this->fileSystem->scanDirectory($this->path, '/^NONEXISTINGFILENAME/', ['callback' => 'file_test_file_scan_callback']);
|
||||
$this->assertEqual(0, count($all_files), 'No files were found.');
|
||||
$results = file_test_file_scan_callback();
|
||||
file_test_file_scan_callback_reset();
|
||||
|
|
@ -69,7 +85,7 @@ class ScanDirectoryTest extends FileTestBase {
|
|||
|
||||
// Grab a listing of all the JavaScript files and check that they're
|
||||
// passed to the callback.
|
||||
$all_files = file_scan_directory($this->path, '/^javascript-/', ['callback' => 'file_test_file_scan_callback']);
|
||||
$all_files = $this->fileSystem->scanDirectory($this->path, '/^javascript-/', ['callback' => 'file_test_file_scan_callback']);
|
||||
$this->assertEqual(2, count($all_files), 'Found two, expected javascript files.');
|
||||
$results = file_test_file_scan_callback();
|
||||
file_test_file_scan_callback_reset();
|
||||
|
|
@ -78,87 +94,97 @@ class ScanDirectoryTest extends FileTestBase {
|
|||
|
||||
/**
|
||||
* Check that the no-mask parameter is honored.
|
||||
*
|
||||
* @covers ::scanDirectory
|
||||
*/
|
||||
public function testOptionNoMask() {
|
||||
// Grab a listing of all the JavaScript files.
|
||||
$all_files = file_scan_directory($this->path, '/^javascript-/');
|
||||
$all_files = $this->fileSystem->scanDirectory($this->path, '/^javascript-/');
|
||||
$this->assertEqual(2, count($all_files), 'Found two, expected javascript files.');
|
||||
|
||||
// Now use the nomask parameter to filter out the .script file.
|
||||
$filtered_files = file_scan_directory($this->path, '/^javascript-/', ['nomask' => '/.script$/']);
|
||||
$filtered_files = $this->fileSystem->scanDirectory($this->path, '/^javascript-/', ['nomask' => '/.script$/']);
|
||||
$this->assertEqual(1, count($filtered_files), 'Filtered correctly.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that key parameter sets the return value's key.
|
||||
*
|
||||
* @covers ::scanDirectory
|
||||
*/
|
||||
public function testOptionKey() {
|
||||
// "filename", for the path starting with $dir.
|
||||
$expected = [$this->path . '/javascript-1.txt', $this->path . '/javascript-2.script'];
|
||||
$actual = array_keys(file_scan_directory($this->path, '/^javascript-/', ['key' => 'filepath']));
|
||||
$actual = array_keys($this->fileSystem->scanDirectory($this->path, '/^javascript-/', ['key' => 'filepath']));
|
||||
sort($actual);
|
||||
$this->assertEqual($expected, $actual, 'Returned the correct values for the filename key.');
|
||||
|
||||
// "basename", for the basename of the file.
|
||||
$expected = ['javascript-1.txt', 'javascript-2.script'];
|
||||
$actual = array_keys(file_scan_directory($this->path, '/^javascript-/', ['key' => 'filename']));
|
||||
$actual = array_keys($this->fileSystem->scanDirectory($this->path, '/^javascript-/', ['key' => 'filename']));
|
||||
sort($actual);
|
||||
$this->assertEqual($expected, $actual, 'Returned the correct values for the basename key.');
|
||||
|
||||
// "name" for the name of the file without an extension.
|
||||
$expected = ['javascript-1', 'javascript-2'];
|
||||
$actual = array_keys(file_scan_directory($this->path, '/^javascript-/', ['key' => 'name']));
|
||||
$actual = array_keys($this->fileSystem->scanDirectory($this->path, '/^javascript-/', ['key' => 'name']));
|
||||
sort($actual);
|
||||
$this->assertEqual($expected, $actual, 'Returned the correct values for the name key.');
|
||||
|
||||
// Invalid option that should default back to "filename".
|
||||
$expected = [$this->path . '/javascript-1.txt', $this->path . '/javascript-2.script'];
|
||||
$actual = array_keys(file_scan_directory($this->path, '/^javascript-/', ['key' => 'INVALID']));
|
||||
$actual = array_keys($this->fileSystem->scanDirectory($this->path, '/^javascript-/', ['key' => 'INVALID']));
|
||||
sort($actual);
|
||||
$this->assertEqual($expected, $actual, 'An invalid key defaulted back to the default.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the recurse option descends into subdirectories.
|
||||
*
|
||||
* @covers ::scanDirectory
|
||||
*/
|
||||
public function testOptionRecurse() {
|
||||
$files = file_scan_directory($this->path . '/..', '/^javascript-/', ['recurse' => FALSE]);
|
||||
$files = $this->fileSystem->scanDirectory($this->path . '/..', '/^javascript-/', ['recurse' => FALSE]);
|
||||
$this->assertTrue(empty($files), "Without recursion couldn't find javascript files.");
|
||||
|
||||
$files = file_scan_directory($this->path . '/..', '/^javascript-/', ['recurse' => TRUE]);
|
||||
$files = $this->fileSystem->scanDirectory($this->path . '/..', '/^javascript-/', ['recurse' => TRUE]);
|
||||
$this->assertEqual(2, count($files), 'With recursion we found the expected javascript files.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the min_depth options lets us ignore files in the starting
|
||||
* directory.
|
||||
*
|
||||
* @covers ::scanDirectory
|
||||
*/
|
||||
public function testOptionMinDepth() {
|
||||
$files = file_scan_directory($this->path, '/^javascript-/', ['min_depth' => 0]);
|
||||
$files = $this->fileSystem->scanDirectory($this->path, '/^javascript-/', ['min_depth' => 0]);
|
||||
$this->assertEqual(2, count($files), 'No minimum-depth gets files in current directory.');
|
||||
|
||||
$files = file_scan_directory($this->path, '/^javascript-/', ['min_depth' => 1]);
|
||||
$files = $this->fileSystem->scanDirectory($this->path, '/^javascript-/', ['min_depth' => 1]);
|
||||
$this->assertTrue(empty($files), 'Minimum-depth of 1 successfully excludes files from current directory.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests file_scan_directory() obeys 'file_scan_ignore_directories' setting.
|
||||
* Tests ::scanDirectory obeys 'file_scan_ignore_directories' setting.
|
||||
*
|
||||
* @covers ::scanDirectory
|
||||
*/
|
||||
public function testIgnoreDirectories() {
|
||||
$files = file_scan_directory('core/modules/system/tests/fixtures/IgnoreDirectories', '/\.txt$/');
|
||||
$files = $this->fileSystem->scanDirectory('core/modules/system/tests/fixtures/IgnoreDirectories', '/\.txt$/');
|
||||
$this->assertCount(2, $files, '2 text files found when not ignoring directories.');
|
||||
|
||||
$this->setSetting('file_scan_ignore_directories', ['frontend_framework']);
|
||||
$files = file_scan_directory('core/modules/system/tests/fixtures/IgnoreDirectories', '/\.txt$/');
|
||||
$files = $this->fileSystem->scanDirectory('core/modules/system/tests/fixtures/IgnoreDirectories', '/\.txt$/');
|
||||
$this->assertCount(1, $files, '1 text files found when ignoring directories called "frontend_framework".');
|
||||
|
||||
// Ensure that the directories in file_scan_ignore_directories are escaped
|
||||
// using preg_quote.
|
||||
$this->setSetting('file_scan_ignore_directories', ['frontend.*']);
|
||||
$files = file_scan_directory('core/modules/system/tests/fixtures/IgnoreDirectories', '/\.txt$/');
|
||||
$files = $this->fileSystem->scanDirectory('core/modules/system/tests/fixtures/IgnoreDirectories', '/\.txt$/');
|
||||
$this->assertCount(2, $files, '2 text files found when ignoring a directory that is not there.');
|
||||
|
||||
$files = file_scan_directory('core/modules/system/tests/fixtures/IgnoreDirectories', '/\.txt$/', ['nomask' => '/^something_thing_else$/']);
|
||||
$files = $this->fileSystem->scanDirectory('core/modules/system/tests/fixtures/IgnoreDirectories', '/\.txt$/', ['nomask' => '/^something_thing_else$/']);
|
||||
$this->assertCount(2, $files, '2 text files found when an "nomask" option is passed in.');
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ class InstallerLanguageTest extends KernelTestBase {
|
|||
|
||||
// Hardcode the simpletest module location as we don't yet know where it is.
|
||||
// @todo Remove as part of https://www.drupal.org/node/2186491
|
||||
$file_translation = new FileTranslation('core/modules/simpletest/files/translations');
|
||||
$file_translation = new FileTranslation('core/modules/simpletest/files/translations', $this->container->get('file_system'));
|
||||
foreach ($expected_translation_files as $langcode => $files_expected) {
|
||||
$files_found = $file_translation->findTranslationFiles($langcode);
|
||||
$this->assertTrue(count($files_found) == count($files_expected), new FormattableMarkup('@count installer languages found.', ['@count' => count($files_expected)]));
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@ trait TestFileCreationTrait {
|
|||
* List of files in public:// that match the filter(s).
|
||||
*/
|
||||
protected function getTestFiles($type, $size = NULL) {
|
||||
/** @var \Drupal\Core\File\FileSystemInterface $file_system */
|
||||
$file_system = \Drupal::service('file_system');
|
||||
if (empty($this->generatedTestFiles)) {
|
||||
// Generate binary test files.
|
||||
$lines = [64, 1024];
|
||||
|
|
@ -69,9 +71,9 @@ trait TestFileCreationTrait {
|
|||
|
||||
// Copy other test files from simpletest.
|
||||
$original = drupal_get_path('module', 'simpletest') . '/files';
|
||||
$files = file_scan_directory($original, '/(html|image|javascript|php|sql)-.*/');
|
||||
$files = $file_system->scanDirectory($original, '/(html|image|javascript|php|sql)-.*/');
|
||||
foreach ($files as $file) {
|
||||
\Drupal::service('file_system')->copy($file->uri, PublicStream::basePath());
|
||||
$file_system->copy($file->uri, PublicStream::basePath());
|
||||
}
|
||||
|
||||
$this->generatedTestFiles = TRUE;
|
||||
|
|
@ -80,7 +82,7 @@ trait TestFileCreationTrait {
|
|||
$files = [];
|
||||
// Make sure type is valid.
|
||||
if (in_array($type, ['binary', 'html', 'image', 'javascript', 'php', 'sql', 'text'])) {
|
||||
$files = file_scan_directory('public://', '/' . $type . '\-.*/');
|
||||
$files = $file_system->scanDirectory('public://', '/' . $type . '\-.*/');
|
||||
|
||||
// If size is set then remove any files that are not of that size.
|
||||
if ($size !== NULL) {
|
||||
|
|
|
|||
|
|
@ -703,7 +703,7 @@ $settings['container_yamls'][] = $app_root . '/' . $site_path . '/services.yml';
|
|||
* with common frontend tools and recursive scanning of directories looking for
|
||||
* extensions.
|
||||
*
|
||||
* @see file_scan_directory()
|
||||
* @see \Drupal\Core\File\FileSystemInterface::scanDirectory()
|
||||
* @see \Drupal\Core\Extension\ExtensionDiscovery::scanDirectory()
|
||||
*/
|
||||
$settings['file_scan_ignore_directories'] = [
|
||||
|
|
|
|||
Loading…
Reference in New Issue