You are here

function _cdn_build_css_cache in CDN 7.2

Same name and namespace in other branches
  1. 6.2 cdn.basic.css.inc \_cdn_build_css_cache()

Near-identical to Changes:

See also

drupal_build_css_cache().

2 calls to _cdn_build_css_cache()
CDNCssUrlTestCase::testCssUrl in tests/cdn.test
_cdn_aggregate_css in ./cdn.basic.css.inc
Near-identical to Changes: call _cdn_build_css_cache() instead of drupal_build_css_cache().

File

./cdn.basic.css.inc, line 62
Overrides of Drupal's CSS aggregation system. Ensures that files referenced by CSS files are also served from the CDN, according to the CDN module's CSS aggregation rules.

Code

function _cdn_build_css_cache($css, $suffix = '') {

  // Create different CSS aggregation maps for HTTP and HTTPS.
  $https_mapping = variable_get(CDN_BASIC_MAPPING_HTTPS_VARIABLE, '');
  $css_cache_var = cdn_request_is_https() ? 'cdn_css_cache_files_https' : 'cdn_css_cache_files_http';
  $data = '';
  $uri = '';
  $map = variable_get($css_cache_var, array());

  // Create a new array so that only the file names are used to create the hash.
  // This prevents new aggregates from being created unnecessarily.
  $css_data = array();
  foreach ($css as $css_file) {
    $css_data[] = $css_file['data'];
  }
  $key = hash('sha256', serialize($css_data));
  if (isset($map[$key])) {
    $uri = $map[$key];
  }
  if (empty($uri) || !file_exists($uri)) {

    // Build aggregate CSS file.
    foreach ($css as $stylesheet) {

      // Only 'file' stylesheets can be aggregated.
      if ($stylesheet['type'] == 'file') {
        $contents = drupal_load_stylesheet($stylesheet['data'], TRUE);

        // Get the parent directory of this file, relative to the Drupal root.
        $css_base_url = drupal_substr($stylesheet['data'], 0, strrpos($stylesheet['data'], '/'));
        _cdn_build_css_path(NULL, $css_base_url . '/');

        // Anchor all paths in the CSS with its base URL, ignoring external and absolute paths.
        $data .= preg_replace_callback('/url\\(\\s*[\'"]?(?![a-z]+:|\\/+)([^\'")]+)[\'"]?\\s*\\)/i', '_cdn_build_css_path', $contents);
      }
    }

    // Per the W3C specification at http://www.w3.org/TR/REC-CSS2/cascade.html#at-import,
    // @import rules must proceed any other style, so we move those to the top.
    $regexp = '/@import[^;]+;/i';
    preg_match_all($regexp, $data, $matches);
    $data = preg_replace($regexp, '', $data);
    $data = implode('', $matches[0]) . $data;

    // Prefix filename to prevent blocking by firewalls which reject files
    // starting with "ad*".
    $filename = 'css_' . drupal_hash_base64($data) . $suffix . '.css';

    // Create the css/ within the files folder.
    $csspath = $css_cache_var == 'cdn_css_cache_files_https' ? 'public://cdn/css/https' : 'public://cdn/css/http';
    $uri = $csspath . '/' . $filename;

    // Create the CSS file.
    file_prepare_directory($csspath, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
    if (!file_exists($uri) && !file_unmanaged_save_data($data, $uri, FILE_EXISTS_REPLACE)) {
      return FALSE;
    }

    // If CSS gzip compression is enabled, clean URLs are enabled (which means
    // that rewrite rules are working) and the zlib extension is available then
    // create a gzipped version of this file. This file is served conditionally
    // to browsers that accept gzip using .htaccess rules.
    if (variable_get('css_gzip_compression', TRUE) && variable_get('clean_url', 0) && extension_loaded('zlib')) {
      if (!file_exists($uri . '.gz') && !file_unmanaged_save_data(gzencode($data, 9, FORCE_GZIP), $uri . '.gz', FILE_EXISTS_REPLACE)) {
        return FALSE;
      }
    }

    // Save the updated map.
    $map[$key] = $uri;
    variable_set($css_cache_var, $map);
  }
  return $uri;
}