<link type="text/css" rel="stylesheet" media="all" href="/modules/node/node.css?C" />
<link type="text/css" rel="stylesheet" media="all" href="/modules/system/defaults.css?C" />
<link type="text/css" rel="stylesheet" media="all" href="/modules/system/system.css?C" />
<link type="text/css" rel="stylesheet" media="all" href="/modules/system/system-menus.css?C" />

<link type="text/css" rel="stylesheet" media="all" href="/modules/user/user.css?C" />
<link type="text/css" rel="stylesheet" media="all" href="/sites/cs6.com/modules/cck/theme/content.css?C" />
<link type="text/css" rel="stylesheet" media="all" href="/sites/cs6.com/modules/cck/modules/fieldgroup/fieldgroup.css?C" />
<link type="text/css" rel="stylesheet" media="all" href="/sites/cs6.com/modules/date/date.css?C" />
<link type="text/css" rel="stylesheet" media="all" href="/sites/cs6.com/modules/filefield/filefield.css?C" />
<link type="text/css" rel="stylesheet" media="all" href="/sites/cs6.com/modules/filefield_image/filefield_image.css?C" />
<link type="text/css" rel="stylesheet" media="all" href="/sites/cs6.com/themes/zen/zen/html-elements.css?C" />
<link type="text/css" rel="stylesheet" media="all" href="/sites/cs6.com/themes/zen/zen/tabs.css?C" />
<link type="text/css" rel="stylesheet" media="all" href="/sites/cs6.com/themes/cs/layout.css?C" />
<link type="text/css" rel="stylesheet" media="all" href="/sites/cs6.com/themes/zen/zen/block-editing.css?C" />

As you might notice in the above code, each stylesheet url contains a '?' and 'C', sometimes I see only the '?' alone. What does this mean? I'm sure this is not a bug given the amount of flexibility and detail the theme developer has given but what purpose does this serve?

Comments

zeta ζ’s picture

This is a feature of Drupal, not just Zen. It gives you control over the browser’s cache: If one of the files changes, the filename stays the same, so the browser uses it’s own copy and doesn’t see the update. But Drupal changes the ?C to something else, the browser thinks it is a different file (it is different), and uses that – refreshing it’s cache.

The clever bit is that this enables Drupal to change the filename, but still refer to the same file.
___________________
It’s in the detaιls…

demonstration portfolio

lx-88’s picture

Thanks for the description. That's a pretty cool trick.

Thanks,
LX-88

ToshoFreny’s picture

Thank you Zeta. That's very clever. Can you please point me to the function or hook that does this? Just curious to know how this is done.

Loving Life,
Tosho Freny,

zeta ζ’s picture

grep -n \'\?\' includes/*
___________________
It’s in the detaιls…

demonstration portfolio

ToshoFreny’s picture

Zeta, you are too quick and concise! Thanks.

I am posting this incase someone else also wants to know this. The following function drupal_get_css adds the dummy query string to the css files. The same way drupal_get_js adds the dummy query string to js files. Both these function reside in includes/common.php

function drupal_get_css($css = NULL) {
  $output = '';
  if (!isset($css)) {
    $css = drupal_add_css();
  }
  $no_module_preprocess = '';
  $no_theme_preprocess = '';

  $preprocess_css = (variable_get('preprocess_css', FALSE) && (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update'));
  $directory = file_directory_path();
  $is_writable = is_dir($directory) && is_writable($directory) && (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PUBLIC);

  // A dummy query-string is added to filenames, to gain control over
  // browser-caching. The string changes on every update or full cache
  // flush, forcing browsers to load a new copy of the files, as the
  // URL changed.
  $query_string = '?'. substr(variable_get('css_js_query_string', '0'), 0, 1);

  foreach ($css as $media => $types) {
    // If CSS preprocessing is off, we still need to output the styles.
    // Additionally, go through any remaining styles if CSS preprocessing is on and output the non-cached ones.
    foreach ($types as $type => $files) {
      if ($type == 'module') {
        // Setup theme overrides for module styles.
        $theme_styles = array();
        foreach (array_keys($css[$media]['theme']) as $theme_style) {
          $theme_styles[] = basename($theme_style);
        }
      }
      foreach ($types[$type] as $file => $preprocess) {
        // If the theme supplies its own style using the name of the module style, skip its inclusion.
        // This includes any RTL styles associated with its main LTR counterpart.
        if ($type == 'module' && in_array(str_replace('-rtl.css', '.css', basename($file)), $theme_styles)) {
          // Unset the file to prevent its inclusion when CSS aggregation is enabled.
          unset($types[$type][$file]);
          continue;
        }
        // Only include the stylesheet if it exists.
        if (file_exists($file)) {
          if (!$preprocess || !($is_writable && $preprocess_css)) {
            // If a CSS file is not to be preprocessed and it's a module CSS file, it needs to *always* appear at the *top*,
            // regardless of whether preprocessing is on or off.
            if (!$preprocess && $type == 'module') {
              $no_module_preprocess .= '<link type="text/css" rel="stylesheet" media="'. $media .'" href="'. base_path() . $file . $query_string .'" />'."\n";
            }
            // If a CSS file is not to be preprocessed and it's a theme CSS file, it needs to *always* appear at the *bottom*,
            // regardless of whether preprocessing is on or off.
            else if (!$preprocess && $type == 'theme') {
              $no_theme_preprocess .= '<link type="text/css" rel="stylesheet" media="'. $media .'" href="'. base_path() . $file . $query_string .'" />'."\n";
            }
            else {
              $output .= '<link type="text/css" rel="stylesheet" media="'. $media .'" href="'. base_path() . $file . $query_string .'" />'."\n";
            }
          }
        }
      }
    }

    if ($is_writable && $preprocess_css) {
      $filename = md5(serialize($types) . $query_string) .'.css';
      $preprocess_file = drupal_build_css_cache($types, $filename);
      $output .= '<link type="text/css" rel="stylesheet" media="'. $media .'" href="'. base_path() . $preprocess_file .'" />'."\n";
    }
  }

  return $no_module_preprocess . $output . $no_theme_preprocess;
}

Loving Life,
Tosho Freny,