Builds a list of bootstrap modules and enabled modules and themes.
@todo There are too many layers/levels of caching involved for system_list() data. Consider to add a config($name, $cache = TRUE) argument to allow callers like system_list() to force-disable a possible configuration storage controller cache or some other way to circumvent it/take it over.
$type: The type of list to return:
An associative array of modules or themes, keyed by name. For $type 'bootstrap' and 'module_enabled', the array values equal the keys. For $type 'theme', the array values are objects representing the respective database row, with the 'info' property already unserialized.
function system_list($type) {
  $lists =& drupal_static(__FUNCTION__);
  // For bootstrap modules, attempt to fetch the list from cache if possible.
  // if not fetch only the required information to fire bootstrap hooks
  // in case we are going to serve the page from cache.
  if ($type == 'bootstrap') {
    if (isset($lists['bootstrap'])) {
      return $lists['bootstrap'];
    }
    if ($cached = cache('bootstrap')
      ->get('bootstrap_modules')) {
      $bootstrap_list = $cached->data;
    }
    else {
      $bootstrap_list = state()
        ->get('system.module.bootstrap') ?: array();
      cache('bootstrap')
        ->set('bootstrap_modules', $bootstrap_list);
    }
    // To avoid a separate database lookup for the filepath, prime the
    // drupal_get_filename() static cache for bootstrap modules only.
    // The rest is stored separately to keep the bootstrap module cache small.
    foreach ($bootstrap_list as $name => $filename) {
      system_register('module', $name, $filename);
    }
    // We only return the module names here since module_list() doesn't need
    // the filename itself.
    $lists['bootstrap'] = array_keys($bootstrap_list);
  }
  elseif (!isset($lists['module_enabled'])) {
    if ($cached = cache('bootstrap')
      ->get('system_list')) {
      $lists = $cached->data;
    }
    else {
      $lists = array(
        'module_enabled' => array(),
        'theme' => array(),
        'filepaths' => array(),
      );
      // The module name (rather than the filename) is used as the fallback
      // weighting in order to guarantee consistent behavior across different
      // Drupal installations, which might have modules installed in different
      // locations in the file system. The ordering here must also be
      // consistent with the one used in module_implements().
      $enabled_modules = (array) config('system.module')
        ->get('enabled');
      $module_files = state()
        ->get('system.module.files');
      foreach ($enabled_modules as $name => $weight) {
        // Build a list of all enabled modules.
        $lists['module_enabled'][$name] = $name;
        // Build a list of filenames so drupal_get_filename can use it.
        $lists['filepaths'][] = array(
          'type' => 'module',
          'name' => $name,
          'filepath' => $module_files[$name],
        );
      }
      // Build a list of themes.
      $enabled_themes = (array) config('system.theme')
        ->get('enabled');
      // @todo Themes include all themes, including disabled/uninstalled. This
      //   system.theme.data state will go away entirely as soon as themes have
      //   a proper installation status.
      // @see http://drupal.org/node/1067408
      $theme_data = state()
        ->get('system.theme.data');
      if (empty($theme_data)) {
        // @todo: system_list() may be called from _drupal_bootstrap_code() and
        // module_load_all(), in which case system.module is not loaded yet.
        // Prevent a filesystem scan in drupal_load() and include it directly.
        // @see http://drupal.org/node/1067408
        require_once DRUPAL_ROOT . '/core/modules/system/system.module';
        $theme_data = system_rebuild_theme_data();
      }
      foreach ($theme_data as $name => $theme) {
        $theme->status = (int) isset($enabled_themes[$name]);
        $lists['theme'][$name] = $theme;
        // Build a list of filenames so drupal_get_filename can use it.
        if (isset($enabled_themes[$name])) {
          $lists['filepaths'][] = array(
            'type' => 'theme',
            'name' => $name,
            'filepath' => $theme->filename,
          );
        }
      }
      // @todo Move into list_themes(). Read info for a particular requested
      //   theme from state instead.
      foreach ($lists['theme'] as $key => $theme) {
        if (!empty($theme->info['base theme'])) {
          // Make a list of the theme's base themes.
          require_once DRUPAL_ROOT . '/core/includes/theme.inc';
          $lists['theme'][$key]->base_themes = drupal_find_base_themes($lists['theme'], $key);
          // Don't proceed if there was a problem with the root base theme.
          if (!current($lists['theme'][$key]->base_themes)) {
            continue;
          }
          // Determine the root base theme.
          $base_key = key($lists['theme'][$key]->base_themes);
          // Add to the list of sub-themes for each of the theme's base themes.
          foreach (array_keys($lists['theme'][$key]->base_themes) as $base_theme) {
            $lists['theme'][$base_theme]->sub_themes[$key] = $lists['theme'][$key]->info['name'];
          }
          // Add the base theme's theme engine info.
          $lists['theme'][$key]->info['engine'] = $lists['theme'][$base_key]->info['engine'];
        }
        else {
          // A plain theme is its own base theme.
          $base_key = $key;
        }
        // Set the theme engine prefix.
        $lists['theme'][$key]->prefix = $lists['theme'][$key]->info['engine'] == 'theme' ? $base_key : $lists['theme'][$key]->info['engine'];
      }
      cache('bootstrap')
        ->set('system_list', $lists);
    }
    // To avoid a separate database lookup for the filepath, prime the
    // drupal_get_filename() static cache with all enabled modules and themes.
    foreach ($lists['filepaths'] as $item) {
      system_register($item['type'], $item['name'], $item['filepath']);
    }
  }
  return $lists[$type];
}