diff -u b/includes/bootstrap.inc b/includes/bootstrap.inc
--- b/includes/bootstrap.inc
+++ b/includes/bootstrap.inc
@@ -835,7 +835,7 @@
function drupal_get_filename($type, $name, $filename = NULL) {
// The location of files will not change during the request, so do not use
// drupal_static().
- static $files = array(), $dirs = array();
+ static $files = array(), $dirs = array(), $files_scanned = array();
// Profiles are a special case: they have a fixed location and naming.
if ($type == 'profile') {
@@ -860,8 +860,13 @@
try {
if (function_exists('db_query')) {
$file = db_query("SELECT filename FROM {system} WHERE name = :name AND type = :type", array(':name' => $name, ':type' => $type))->fetchField();
- if ($file !== FALSE && file_exists(DRUPAL_ROOT . '/' . $file)) {
- $files[$type][$name] = $file;
+ if ($file !== FALSE) {
+ if (file_exists(DRUPAL_ROOT . '/' . $file)) {
+ $files[$type][$name] = $file;
+ }
+ else {
+ $database_file_exists = FALSE;
+ }
}
}
}
@@ -894,9 +899,15 @@
$missing = array();
try {
if (function_exists('cache_get')) {
- $cache = cache_get('drupal_get_filename:missing');
+ $cache = cache_get('drupal_get_filename:missing', 'cache_bootstrap');
if (!empty($cache->data)) {
- $missing = $cache->data;
+ // Merge the changes already done in the current request (including
+ // the setting of missing records to NULL) into the values saved
+ // in persistent cache.
+ $missing = $cache->data + $missing;
+ // Set a flag so we know that we've already done a merge with values
+ // in cache_get().
+ $missing['#cache_merge_done'] = TRUE;
}
}
}
@@ -905,6 +916,18 @@
}
}
+ if (isset($missing[$type][$name]) && is_string($missing[$type][$name])) {
+ // This file has moved and the result of a file scan had been cached.
+ if (file_exists($missing[$type][$name])) {
+ $files[$type][$name] = $missing[$type][$name];
+ }
+ else {
+ // File is not available anymore at its new location. Re-do file scan.
+ $missing[$type][$name] = NULL;
+ $missing['#write_cache'] = TRUE;
+ }
+ }
+
if (!isset($dirs[$dir][$extension]) && !isset($missing[$type][$name])) {
$dirs[$dir][$extension] = TRUE;
if (!function_exists('drupal_system_listing')) {
@@ -916,7 +939,18 @@
// called more than once in the same page request.
$matches = drupal_system_listing("/^" . DRUPAL_PHP_FUNCTION_PATTERN . "\.$extension$/", $dir, 'name', 0);
foreach ($matches as $matched_name => $file) {
- $files[$type][$matched_name] = $file->uri;
+ $files_scanned[$type][$matched_name] = $file->uri;
+ }
+ }
+
+ if (isset($files_scanned[$type][$name])) {
+ $files[$type][$name] = $files_scanned[$type][$name];
+ if (isset($database_file_exists) && $database_file_exists === FALSE) {
+ // This file has moved. Cache its new location into the missing files
+ // cache.
+ $missing[$type][$name] = $files_scanned[$type][$name];
+ $missing['#write_cache'] = TRUE;
+ trigger_error(format_string('The following @type has moved on the file system: @name. Clearing caches may help fix this. For more information, see the documentation page.', array('@type' => $type, '@name' => $name, '@documentation' => 'https://www.drupal.org/node/2487215')), E_USER_WARNING);
}
}
}
@@ -933,14 +967,30 @@
- try {
- if (function_exists('cache_set')) {
- cache_set('drupal_get_filename:missing', $missing, 'cache');
- }
- }
- catch (Exception $e) {
- // Hide the error.
- }
+ $missing['#write_cache'] = TRUE;
}
trigger_error(format_string('The following @type is missing from the file system: @name. For more information, see the documentation page.', array('@type' => $type, '@name' => $name, '@documentation' => 'https://www.drupal.org/node/2487215')), E_USER_WARNING);
}
}
/**
+ * Writes the missing and moved files to persistent cache.
+ *
+ * @param array $missing
+ * The array of missing and moved files.
+ */
+function drupal_missing_write_cache() {
+ if (drupal_get_bootstrap_phase() != DRUPAL_BOOTSTRAP_FULL) {
+ return;
+ }
+ $missing = &drupal_static('drupal_get_filename:missing');
+ if (isset($missing['#write_cache'])) {
+ if (!isset($missing['#cache_merge_done'])) {
+ $cache = cache_get('drupal_get_filename:missing', 'cache_bootstrap');
+ if (isset($cache->data)) {
+ $missing = $cache->data + $missing;
+ }
+ }
+ $missing['#write_cache'] = NULL;
+ cache_set('drupal_get_filename:missing', $missing, 'cache_bootstrap');
+ }
+}
+
+/**
diff -u b/modules/simpletest/tests/bootstrap.test b/modules/simpletest/tests/bootstrap.test
--- b/modules/simpletest/tests/bootstrap.test
+++ b/modules/simpletest/tests/bootstrap.test
@@ -382,7 +382,7 @@
}
/**
- * Whether the filename test triggered the right error.
+ * Whether the filename test triggered the right error.
*
* Used by BootstrapGetFilenameTestCase::testDrupalGetFilename().
*
only in patch2:
unchanged:
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -2751,6 +2751,7 @@ function drupal_page_footer() {
_registry_check_code(REGISTRY_WRITE_LOOKUP_CACHE);
drupal_cache_system_paths();
module_implements_write_cache();
+ drupal_missing_write_cache();
system_run_automated_cron();
}