diff -u b/includes/bootstrap.inc b/includes/bootstrap.inc
--- b/includes/bootstrap.inc
+++ b/includes/bootstrap.inc
@@ -845,4 +845,8 @@
static $files = array();
+ // This flag may hold a string that indicates where the filename was retrieved
+ // from.
+ $filename_retrieved_from = '';
+
// Profiles are a special case: they have a fixed location and naming.
if ($type == 'profile') {
@@ -856,6 +860,7 @@
if (!empty($filename) && file_exists($filename)) {
// Prime the static cache with the provided filename.
$files[$type][$name] = $filename;
+ $filename_retrieved_from = 'priming';
}
elseif (isset($files[$type][$name])) {
// This item had already been found earlier in the request, either through
@@ -864,34 +869,40 @@
// Do nothing.
}
else {
- $system_filepaths = &drupal_static('system_filepaths');
- if (!isset($system_filepaths[$type][$name])) {
- // Look for the filename listed in the {system} table.
- // Verify that we have an active database connection, before querying
- // the database. This is required because this function is called both
- // before we have a database connection (i.e. during installation) and
- // when a database connection fails.
- 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) {
- $system_filepaths[$type][$name] = $file;
- if (file_exists(DRUPAL_ROOT . '/' . $file)) {
- $files[$type][$name] = $file;
- }
+ // Look for the filename listed in the {system} table.
+ // Verify that we have an active database connection, before querying
+ // the database. This is required because this function is called both
+ // before we have a database connection (i.e. during installation) and
+ // when a database connection fails.
+ try {
+ $system_query_success = FALSE;
+ 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) {
+ if (file_exists(DRUPAL_ROOT . '/' . $file)) {
+ $files[$type][$name] = $file;
+ $filename_retrieved_from = 'system_table';
}
}
+ $system_query_success = TRUE;
}
- catch (Exception $e) {
- // The database table may not exist because Drupal is not yet installed,
- // the database might be down, or we may have done a non-database cache
- // flush while $conf['page_cache_without_database'] = TRUE and
- // $conf['page_cache_invoke_hooks'] = TRUE. We have a fallback for these
- // cases so we hide the error completely.
- }
+ }
+ catch (Exception $e) {
+ // The database table may not exist because Drupal is not yet installed,
+ // the database might be down, or we may have done a non-database cache
+ // flush while $conf['page_cache_without_database'] = TRUE and
+ // $conf['page_cache_invoke_hooks'] = TRUE. We have a fallback for these
+ // cases so we hide the error completely.
+ // We also hide the trigger_error() "moved or newly introduced" warning
+ // in this case as we can't be sure if it's correct.
+ }
+ if (!$system_query_success) {
+ // We can't tell if the error message will be valid if the query to the
+ // {system} table failed, so skip triggering of errors.
+ $trigger_error = FALSE;
}
// Fall back to searching the filesystem if the database could not find the
// file or the file does not exist at the path returned by the database.
@@ -902,10 +913,19 @@
if (isset($files[$type][$name])) {
// We found a file.
+ // Get the static file scan list. This list may be incomplete as there
+ // may be further files listed in persistent cache, but we skip loading that
+ // as a performance optimization, as the persistent cache record will
+ // be cleared on every system_rebuild_module_data() anyway.
$file_scans = &drupal_static('_drupal_get_filename_fallback');
// If this file had previously been marked as missing, clean up the entry
// from the file scan cache.
- if (isset($file_scans[$type][$name]) && $file_scans[$type][$name] === FALSE) {
+ $missing_reappeared = isset($file_scans[$type][$name]) && $file_scans[$type][$name] === FALSE;
+ // If this file had previously been marked as moved, and reappeared
+ // at the location listed in the system table or in the primed static,
+ // clean up the entry from the file scan cache.
+ $moved_reappeared = isset($file_scans[$type][$name]) && is_string($file_scans[$type][$name]) && ($filename_retrieved_from == 'system_table' || $filename_retrieved_from == 'priming');
+ if ($missing_reappeared || $moved_reappeared) {
$file_scans[$type][$name] = NULL;
$file_scans['#write_cache'] = TRUE;
}
@@ -937,7 +957,7 @@
// keys the type and name of the item, and as value:
// - the boolean FALSE if the item is missing
// - a string with location found in a file scan if the module/theme has moved
- // from the location listed in the {system} table.
+ // from the location listed in the {system} table.
$file_scans = &drupal_static('_drupal_get_filename_fallback');
if (!isset($file_scans)) {
$file_scans = array();
@@ -964,8 +984,8 @@
}
}
- // Check whether this file had previously moved from the path listed in the
- // {system} table.
+ // Check whether this file had moved from the path listed in the {system}
+ // table during a previous file scan.
if (isset($file_scans[$type][$name]) && is_string($file_scans[$type][$name]) && file_exists($file_scans[$type][$name])) {
// The file exists at the location cached in a previous file scan.
$filename_from_file_scan = $file_scans[$type][$name];
@@ -976,22 +996,22 @@
}
if (isset($filename_from_file_scan)) {
- // Check whether the file we found was listed as being in another
- // location in the {system} table.
- $system_filepaths = &drupal_static('system_filepaths');
- if (isset($system_filepaths[$type][$name]) && $system_filepaths[$type][$name] != $filename_from_file_scan) {
- // Make sure our change to the file scan cache will be written to
- // the persistent cache.
- if (!isset($file_scans[$type][$name]) || isset($file_scans[$type][$name]) && $file_scans[$type][$name] != $filename_from_file_scan) {
- $file_scans['#write_cache'] = TRUE;
- }
- // This file has moved. Store its new location in the file scan cache.
+ // The file has either moved from the location in the {system} table
+ // or is not yet listed in the {system} table.
+ // Make sure our change to the file scan cache will be written to the
+ // persistent cache.
+ if (!isset($file_scans[$type][$name]) || isset($file_scans[$type][$name]) && $file_scans[$type][$name] != $filename_from_file_scan) {
$file_scans[$type][$name] = $filename_from_file_scan;
- // Create a user-level warning about the moved file.
- if ($trigger_error) {
- _drupal_get_filename_fallback_trigger_error($type, $name, 'moved');
+ if (!$trigger_error) {
+ // If we skip error triggering, do not write the found file location to
+ // persistent cache.
+ $file_scans['#write_cache'] = TRUE;
}
}
+ // Create a user-level warning about the moved / recently introduced file.
+ if ($trigger_error) {
+ _drupal_get_filename_fallback_trigger_error($type, $name, 'moved');
+ }
return $filename_from_file_scan;
}
else {
@@ -1023,14 +1043,15 @@
* The type of the error ('missing' or 'moved').
*/
function _drupal_get_filename_fallback_trigger_error($type, $name, $error_type) {
- // Make sure we only show any missing/moved file error only once per request.
+ // Make sure we only show any missing / moved file error only once per
+ // request.
static $errors_triggered = array();
if (empty($errors_triggered[$type][$name][$error_type])) {
if ($error_type == 'missing') {
- trigger_error(format_string('The following %type is missing from the file system: %name. In order to fix this, put the file back in its original location or uninstall the module. For more information, see the documentation page.', array('%type' => $type, '%name' => $name, '@documentation' => 'https://www.drupal.org/node/2487215')), E_USER_WARNING);
+ trigger_error(format_string('The following @type is missing from the file system: %name. In order to fix this, put the file back in its original location or uninstall the module. For more information, see the documentation page.', array('@type' => $type, '%name' => $name, '@documentation' => 'https://www.drupal.org/node/2487215')), E_USER_WARNING);
}
elseif ($error_type == 'moved') {
- trigger_error(format_string('The following %type has moved within the file system: %name. In order to fix this, clear caches or put the file back in its original location. For more information, see the documentation page.', array('%type' => $type, '%name' => $name, '@documentation' => 'https://www.drupal.org/node/2487215')), E_USER_WARNING);
+ trigger_error(format_string('The following @type has moved or has recently appeared within the file system: %name. In order to fix this, clear caches or put the file back in its original location. For more information, see the documentation page.', array('@type' => $type, '%name' => $name, '@documentation' => 'https://www.drupal.org/node/2487215')), E_USER_WARNING);
}
$errors_triggered[$type][$name][$error_type] = TRUE;
}
@@ -1105,8 +1126,8 @@
}
$file_scans = &drupal_static('_drupal_get_filename_fallback');
if (isset($file_scans['#write_cache'])) {
- // Merge the newly found out missing and moved file data with
- // the previously existing data, if we had not done so yet.
+ // Merge the newly found out missing and moved file data with the previously
+ // existing data, if we had not done so yet.
if (!isset($file_scans['#cache_merge_done'])) {
$cache = cache_get('_drupal_get_filename_fallback', 'cache_bootstrap');
if (isset($cache->data)) {
diff -u b/includes/module.inc b/includes/module.inc
--- b/includes/module.inc
+++ b/includes/module.inc
@@ -121,7 +121,6 @@
*/
function system_list($type) {
$lists = &drupal_static(__FUNCTION__);
- $system_filepaths = &drupal_static('system_filepaths');
// For bootstrap modules, attempt to fetch the list from cache if possible.
// if not fetch only the required information to fire bootstrap hooks
@@ -210,10 +209,7 @@
cache_set('system_list', $lists, 'cache_bootstrap');
}
foreach ($lists['filepaths'] as $item) {
- // Save the file paths from the database into a static variable so we
- // can determine later if the files have moved.
- $system_filepaths[$item['type']][$item['name']] = $item['filepath'];
- // To avoid a separate database lookup for the filepath, prime the
+ // To avoid a separate database lookup for the file path, prime the
// drupal_get_filename() static cache with all enabled modules and all
// themes.
drupal_get_filename($item['type'], $item['name'], $item['filepath']);
diff -u b/includes/update.inc b/includes/update.inc
--- b/includes/update.inc
+++ b/includes/update.inc
@@ -797,7 +797,7 @@
// 'Default' profile has been renamed to 'Standard' in D7.
// We change the profile here to prevent a broken record in the system table.
- // @see system_update_7049()
+ // See system_update_7049()
if ($profile == 'default') {
$profile = 'standard';
variable_set('install_profile', $profile);