function agrcache_generate_aggregate in Aggregate cache 7
Menu callback to generate a css aggregate.
1 string reference to 'agrcache_generate_aggregate'
- agrcache_menu in ./
agrcache.module - Implements hook_menu().
File
- ./
agrcache.module, line 390 - Provides imagecache style generation of css/js aggregates.
Code
function agrcache_generate_aggregate($filename, $type) {
// Recreate the full uri from the filename.
$path = "public://{$type}";
$uri = $path . '/' . $filename;
$map = agrcache_get_file_list($type);
$compression = variable_get($type . '_gzip_compression', TRUE) && variable_get('clean_url', 0) && extension_loaded('zlib');
// This callback should only be called if the file does not already exist on
// disk since the webserver will serve the file directly, bypassing PHP when it does.
// However it is possible that the file was created during bootstrap by another request.
if (file_exists($uri)) {
$data = file_get_contents($uri);
}
elseif (isset($map['callbacks'][$uri])) {
// There is a possible race condition in the following deployment case with
// multiple web heads.
// - server A has updated code, and gets a page request - i.e. builds a
// filename.
// - server B (this server) is not updated yet, and gets a request for an
// aggregate with that filename.
// In this case, server 2 cannot assume that the filename matches the
// actual contents of the files on disk, since the files on disk are in
// fact different, given the filename was generated on a different server,
// with different files. Based on the information in the map, build the
// filename again, and ensure they match. Since the filename depends on
// the contents of the files, if the filenames don't match we know we've
// hit this race condition. When that happens, log an error, don't write
// the aggregate, but still serve the contents of the old file, which is
// the best we can do.
$write = TRUE;
$function = 'agrcache_collect_' . $type . '_group';
$files = $map['callbacks'][$uri];
$this_data = $function($files);
$this_filename = $type . '_' . drupal_hash_base64(agrcache_serialize_files($files) . $this_data) . ".{$type}";
$path = "public://{$type}";
$this_uri = $path . '/' . $this_filename;
if ($this_uri !== $uri) {
watchdog('agrcache', 'Attempted to create an aggregate based on a set of files that does not match the filename provided.');
$write = FALSE;
}
// @todo: consider adding locking here.
// @see drupal.org/node/886488
$function = 'agrcache_process_' . $type . '_group';
$data = $function($map['callbacks'][$uri]);
// Check file_exists() again, in case the file was built during processing.
if (!file_exists($uri) && $write) {
_agrcache_file_unmanaged_save_data($data, $path, $uri);
// If 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 ($compression) {
$compressed = gzencode($data, 9, FORCE_GZIP);
if (!file_exists($uri . '.gz')) {
_agrcache_file_unmanaged_save_data($compressed, $path, $uri . '.gz');
}
}
}
}
else {
$data = '';
watchdog('agrcache', 'Received request for a non-existent css aggregate @uri', array(
'@uri' => $uri,
));
}
$content_type = $type == 'css' ? 'text/css' : 'application/javascript';
$headers = array();
$headers['Content-Type'] = $content_type;
// Ensure that only the request that is hitting PHP sees this file,
// otherwise we want to use the file on disk for consistency.
$headers['Cache-Control'] = 'private, no-cache, no-store';
$headers['Edge-Control'] = 'bypass-cache';
foreach ($headers as $key => $value) {
drupal_add_http_header($key, $value);
}
print $data;
drupal_exit();
}