diff --git a/core/includes/common.inc b/core/includes/common.inc index 52a3a43..247f7ec 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -3469,68 +3469,31 @@ function drupal_pre_render_styles($elements) { * The URI of the CSS cache file, or FALSE if the file could not be saved. */ function drupal_build_css_cache($css) { - $data = ''; - $uri = ''; - $map = variable_get('drupal_css_cache_files', array()); - $key = hash('sha256', serialize($css)); - 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); - - // Build the base URL of this CSS file: start with the full URL. - $css_base_url = file_create_url($stylesheet['data']); - // Move to the parent. - $css_base_url = substr($css_base_url, 0, strrpos($css_base_url, '/')); - // Simplify to a relative URL if the stylesheet URL starts with the - // base URL of the website. - if (substr($css_base_url, 0, strlen($GLOBALS['base_root'])) == $GLOBALS['base_root']) { - $css_base_url = substr($css_base_url, strlen($GLOBALS['base_root'])); - } - - _drupal_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', '_drupal_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; + return drupal_return_css_path($css); +} - // Prefix filename to prevent blocking by firewalls which reject files - // starting with "ad*". - $filename = 'css_' . drupal_hash_base64($data) . '.css'; - // Create the css/ within the files folder. - $csspath = 'public://css'; - $uri = $csspath . '/' . $filename; - // Create the CSS file. - file_prepare_directory($csspath, FILE_CREATE_DIRECTORY); - 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; +/** + * Return a uri for the given css paths. + */ +function drupal_return_css_path($css) { + $css_base_path = 'sites/default/files/css/'; + $directories = array(); + foreach ($css as $stylesheet) { + // Only 'file' stylesheets can be aggregated. + if ($stylesheet['type'] == 'file') { + $directory = str_replace('/', ';', dirname($stylesheet['data'])); + $filename = basename($stylesheet['data']); + if (!isset($directories[$directory])) { + $directories[$directory] = array(); } + $directories[$directory][] = substr($filename, 0, -4); } - // Save the updated map. - $map[$key] = $uri; - variable_set('drupal_css_cache_files', $map); } + $css_paths = array(); + foreach ($directories as $directory => $files) { + $css_paths[] = $directory . '=' . implode('~', $files); + } + $uri = $css_base_path . implode(',', $css_paths) . '.css'; return $uri; } diff --git a/core/modules/system/system.module b/core/modules/system/system.module index 07eacd2..3745dbd 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -546,9 +546,75 @@ function system_element_info() { } /** + * Aggregate and serve css files imagecache style. + */ +function system_aggregate_css($css_paths_string) { + $css = array(); + foreach (explode(',', substr($css_paths_string, 0, -4)) as $directory_string) { + list($directory, $files_string) = explode('=', $directory_string); + foreach (explode('~', $files_string) as $css_file) { + $css[] = str_replace(';', '/', $directory) . '/' . $css_file . '.css'; + } + } + + $data = ''; + $uri = ''; + foreach ($css as $stylesheet) { + $contents = drupal_load_stylesheet($stylesheet, TRUE); + // Build the base URL of this CSS file: start with the full URL. + $css_base_url = file_create_url($stylesheet); + // Move to the parent. + $css_base_url = substr($css_base_url, 0, strrpos($css_base_url, '/')); + // Simplify to a relative URL if the stylesheet URL starts with the + // base URL of the website. + if (substr($css_base_url, 0, strlen($GLOBALS['base_root'])) == $GLOBALS['base_root']) { + $css_base_url = substr($css_base_url, strlen($GLOBALS['base_root'])); + } + + _drupal_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', '_drupal_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; + + $filename = $css_paths_string; + // Create the css/ within the files folder. + $csspath = 'public://css'; + $uri = $csspath . '/' . $filename; + // Create the CSS file. + file_prepare_directory($csspath, FILE_CREATE_DIRECTORY); + if (!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_unmanaged_save_data(gzencode($data, 9, FORCE_GZIP), $uri . '.gz', FILE_EXISTS_REPLACE)) { + return FALSE; + } + } + file_transfer($uri, array('Content-Type' => 'text/css', 'Content-Length' => strlen($data))); +} + +/** * Implements hook_menu(). */ function system_menu() { + $items['sites/default/files/css/%'] = array( + 'title' => 'Download aggregated css', + 'page callback' => 'system_aggregate_css', + 'page arguments' => array(4), + 'access callback' => TRUE, + 'type' => MENU_CALLBACK, + ); $items['system/files'] = array( 'title' => 'File download', 'page callback' => 'file_download',