diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index e26cb36..7347ef6 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -845,7 +845,7 @@ function drupal_settings_initialize() { 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(); $bad = array(); // Profiles are converted into modules in system_rebuild_module_data(). // @todo Remove false-exposure of profiles as modules. @@ -863,58 +863,86 @@ function drupal_get_filename($type, $name, $filename = NULL) { elseif (isset($files[$type][$name])) { // nothing } - // 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. else { - 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 && file_exists(DRUPAL_ROOT . '/' . $file)) { - $files[$type][$name] = $file; - } - } + // Check the bootstrap cache for the existing files data. + // If we have an entry in the cache then use it and save a call to the db. + // This is install safe as the default cache backend will return false. + $cache = cache('bootstrap')->get('drupal_get_filename'); + + // Check if we got something from the cache that matches the type and name. + if (isset($cache->data) && isset($cache->data[$type][$name])) { + $files[$type][$name] = $cache->data[$type][$name]; } - catch (Exception $e) { - // The database table may not exist because Drupal is not yet installed, - // or the database might be down. We have a fallback for this case so we - // hide the error completely. - } - // Fallback to searching the filesystem if the database could not find the - // file or the file returned by the database is not found. - if (!isset($files[$type][$name])) { - // We have a consistent directory naming: modules, themes... - $dir = $type . 's'; - if ($type == 'theme_engine') { - $dir = 'themes/engines'; - $extension = 'engine'; - } - elseif ($type == 'theme') { - $extension = 'info'; - } - // Profiles are converted into modules in system_rebuild_module_data(). - // @todo Remove false-exposure of profiles as modules. - elseif ($original_type == 'profile') { - $dir = 'profiles'; - $extension = 'profile'; - } - else { - $extension = $type; + else { + // 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 && file_exists(DRUPAL_ROOT . '/' . $file)) { + $files[$type][$name] = $file; + + cache('bootstrap')->set('drupal_get_filename', $files); + } + } } + catch (Exception $e) { + // The database table may not exist because Drupal is not yet installed, + // or the database might be down. We have a fallback for this case so we + // hide the error completely. + } + + // Fallback to searching the filesystem if the database could not find the + // file or the file returned by the database is not found. + if (!isset($files[$type][$name])) { + // We have a consistent directory naming: modules, themes... + $dir = $type . 's'; + if ($type == 'theme_engine') { + $dir = 'themes/engines'; + $extension = 'engine'; + } + elseif ($type == 'theme') { + $extension = 'info'; + } + // Profiles are converted into modules in system_rebuild_module_data(). + // @todo Remove false-exposure of profiles as modules. + elseif ($original_type == 'profile') { + $dir = 'profiles'; + $extension = 'profile'; + } + else { + $extension = $type; + } - if (!isset($dirs[$dir][$extension])) { - $dirs[$dir][$extension] = TRUE; - if (!function_exists('drupal_system_listing')) { - require_once DRUPAL_ROOT . '/core/includes/common.inc'; + // See if we have a cached list of files missing from the file system. + if (empty($bad)) { + $cache = cache('bootstrap')->get('drupal_get_filename_missing'); + if (!empty($cache->data)) { + $bad = $cache->data; + } } - // Scan the appropriate directories for all files with the requested - // extension, not just the file we are currently looking for. This - // prevents unnecessary scans from being repeated when this function is - // 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; + + if (!isset($dirs[$dir][$extension]) && !isset($bad[$type][$name])) { + $dirs[$dir][$extension] = TRUE; + if (!function_exists('drupal_system_listing')) { + require_once DRUPAL_ROOT . '/core/includes/common.inc'; + } + // Scan the appropriate directories for all files with the requested + // extension, not just the file we are currently looking for. This + // prevents unnecessary scans from being repeated when this function is + // called more than once in the same page request. + $matches = drupal_system_listing("/^" . DRUPAL_PHP_FUNCTION_PATTERN . "\.$extension$/", $dir, 'name', 0); + + if (count($matches) > 0) { + foreach ($matches as $matched_name => $file) { + $files[$type][$matched_name] = $file->uri; + } + + // Update the cache entry if we found files locally + cache('bootstrap')->set('drupal_get_filename', $variables); + } } } } @@ -923,6 +951,12 @@ function drupal_get_filename($type, $name, $filename = NULL) { if (isset($files[$type][$name])) { return $files[$type][$name]; } + elseif (!isset($bad[$type][$name])) { + // Add the missing file to a temporary cache and throw a watchdog alert. + $bad[$type][$name] = TRUE; + $cache = cache('bootstrap')->set('drupal_get_filename_missing', $bad, -1); + watchdog('system', 'The following @type is missing from the file system: @name.', array('@type' => $type, '@name' => $name), WATCHDOG_ALERT); + } } /**