New version 6.x-1.11 for Advanced CSS/JS Aggregation module

This commit is contained in:
Manuel Cillero 2017-08-05 00:43:16 +02:00
parent e72db62736
commit 329321644a
17 changed files with 734 additions and 414 deletions

View file

@ -101,6 +101,11 @@ define('ADVAGG_CLOSURE', TRUE);
*/
define('ADVAGG_STRICT_JS_BUNDLES', TRUE);
/**
* Default value for how long the request can go before php times out.
*/
define('ADVAGG_SET_TIME_LIMIT', 240);
/**
* Default mode for aggregate creation.
*
@ -359,6 +364,10 @@ function advagg_init() {
$conf['advagg_use_full_cache'] = FALSE;
}
// Include the ctools_ajax_run_page_preprocess() function.
if (function_exists('ctools_include')) {
ctools_include('ajax');
}
// Disable ctools_ajax_page_preprocess() if this functionality is available.
if (variable_get('advagg_enabled', ADVAGG_ENABLED) && function_exists('ctools_ajax_run_page_preprocess')) {
ctools_ajax_run_page_preprocess(FALSE);
@ -438,8 +447,9 @@ function advagg_get_root_files_dir($reset = FALSE) {
$custom_path = variable_get('advagg_custom_files_dir', ADVAGG_CUSTOM_FILES_DIR);
}
if (empty($custom_path)) {
$css_path = file_create_path('advagg_css');
$js_path = file_create_path('advagg_js');
$file_path = file_directory_path();
$css_path = file_create_path($file_path . '/advagg_css');
$js_path = file_create_path($file_path . '/advagg_js');
return array($css_path, $js_path);
}
file_check_directory($custom_path, FILE_CREATE_DIRECTORY);
@ -967,7 +977,7 @@ function advagg_get_filename($files, $filetype, $counter = FALSE, $bundle_md5 =
$counters[$key] = $values['bundle_md5'];
}
}
$result = advagg_db_multi_select_in('advagg_bundles', 'bundle_md5', "'%s'", $counters, array('counter', 'bundle_md5'), 'GROUP BY bundle_md5');
$result = advagg_db_multi_select_in('advagg_bundles', 'bundle_md5', "'%s'", $counters, array('counter', 'bundle_md5'), 'GROUP BY bundle_md5, counter');
while ($row = db_fetch_array($result)) {
$key = array_search($row['bundle_md5'], $counters);
if (empty($filenames[$key]['counter']) && $filenames[$key]['counter'] !== 0) {
@ -1414,7 +1424,34 @@ function advagg_file_copy(&$source, $dest = 0, $replace = FILE_EXISTS_RENAME) {
return FALSE;
}
if (!@copy($source, $dest)) {
// Perform the replace operation. Since there could be multiple processes
// writing to the same file, the best option is to create a temporary file in
// the same directory and then rename it to the destination. A temporary file
// is needed if the directory is mounted on a separate machine; thus ensuring
// the rename command stays local.
$result = FALSE;
if ($replace == FILE_EXISTS_REPLACE) {
// Get a temporary filename in the destination directory.
$temporary_file = tempnam(dirname($dest), 'file');
// Place contents in the temporary file.
if ($temporary_file && @copy($source, $temporary_file)) {
if (!$result = @rename($temporary_file, $dest)) {
// Unlink and try again for windows. Rename on windows does not replace
// the file if it already exists.
@unlink($dest);
$result = @rename($temporary_file, $dest);
}
// Remove temporary_file if rename failed.
if (!$result) {
@unlink($temporary_file);
}
}
}
// Perform the copy operation.
else {
$result = @copy($source, $dest);
}
if ($result === FALSE) {
drupal_set_message(t('The selected file %file could not be copied. ' . $dest, array('%file' => $source)), 'error');
return 0;
}
@ -1462,7 +1499,7 @@ function advagg_checksum($filename) {
}
}
}
elseif ($mode = 'md5') {
elseif ($mode == 'md5') {
$checksum = md5(file_get_contents($filename));
}
}
@ -1560,7 +1597,7 @@ function advagg_get_bundle_from_filename($filename) {
function advagg_flush_caches() {
// Try to allocate enough time to flush the cache
if (function_exists('set_time_limit')) {
@set_time_limit(240);
@set_time_limit(variable_get('advagg_set_time_limit', ADVAGG_SET_TIME_LIMIT));
}
global $_advagg;
@ -1779,7 +1816,7 @@ function advagg_build_uri($path) {
}
// Use the patched version of file_create_url().
else {
$path = file_create_url($path);
$path = advagg_file_create_url($path);
}
// Return here if the path was changed above.
if (strcmp($original_path, $path) != 0) {
@ -1793,7 +1830,7 @@ function advagg_build_uri($path) {
$hook_file_url_alter = module_implements('file_url_alter');
}
if (!empty($hook_file_url_alter)) {
$path = file_create_url($path);
$path = advagg_file_create_url($path);
// Return here if the path was changed above.
if (strcmp($original_path, $path) != 0) {
return $path;
@ -1804,6 +1841,63 @@ function advagg_build_uri($path) {
return base_path() . $path;
}
/**
* Create the download path to a file.
*
* There are two kinds of local files:
* - "created files", i.e. those in the files directory (which is stored in
* the file_directory_path variable and can be retrieved using
* file_directory_path()). These are files that have either been uploaded by
* users or were generated automatically (for example through CSS
* aggregation).
* - "shipped files", i.e. those outside of the files directory, which ship as
* part of Drupal core or contributed modules or themes.
*
* @param $path
* A string containing the Drupal path (i.e. path relative to the Drupal
* root directory) of the file to generate the URL for.
* @return
* A string containing a URL that can be used to download the file.
*/
function advagg_file_create_url($path) {
// Clean up Windows paths.
$old_path = $path = str_replace('\\', '/', $path);
drupal_alter('file_url', $path);
// If any module has altered the path, then return the alteration.
if ($path != $old_path) {
return $path;
}
// Otherwise serve the file from Drupal's web server. This point will only
// be reached when either no custom_file_url_rewrite() function has been
// defined, or when that function returned FALSE, thereby indicating that it
// cannot (or doesn't wish to) rewrite the URL. This is typically because
// the file doesn't match some conditions to be served from a CDN or static
// file server, or because the file has not yet been synced to the CDN or
// static file server.
// Shipped files.
if (strpos($path, file_directory_path() . '/') !== 0) {
return base_path() . $path;
}
// Created files.
else {
switch (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC)) {
case FILE_DOWNLOADS_PUBLIC:
return $GLOBALS['base_url'] . '/' . $path;
case FILE_DOWNLOADS_PRIVATE:
// Strip file_directory_path from $path. Private downloads' URLs are
// rewritten to be served relatively to system/files (which is a menu
// callback that streams the file) instead of relatively to the file
// directory path.
$path = file_directory_strip($path);
return url('system/files/' . $path, array('absolute' => TRUE));
}
}
}
/**
* ***MODIFIED CORE FUNCTIONS BELOW***
*
@ -2066,7 +2160,7 @@ function advagg_process_css($css = NULL, $noagg = FALSE) {
$files = array();
foreach ($types as $type) {
foreach ($type as $file => $cache) {
if ($cache) {
if ($cache && advagg_file_exists($file)) {
$files[] = $file;
$files_included[$media][$file] = TRUE;
unset($files_aggregates_included[$file]);
@ -2664,9 +2758,9 @@ function advagg_css_js_file_builder($type, $files, $query_string = '', $counter
// Only generate once.
$lock_name = 'advagg_' . $filename;
if (!lock_acquire($lock_name)) {
if (!lock_acquire($lock_name) && !$force) {
if (variable_get('advagg_aggregate_mode', ADVAGG_AGGREGATE_MODE) == 0 ) {
$locks[] = array($lock_name => $filepath);
$locks[$lock_name] = $filepath;
$output[$filepath] = array(
'prefix' => $prefix,
'suffix' => $suffix,
@ -2771,15 +2865,32 @@ function advagg_css_js_file_builder($type, $files, $query_string = '', $counter
* string containing all the files.
*/
function advagg_build_css_bundle($files) {
$data = '';
// Check if CSS compression is enabled.
if (module_exists('advagg_css') && (variable_get('advagg_css_compress_agg_files', ADVAGG_CSS_COMPRESS_AGG_FILES) || variable_get('advagg_css_compress_inline', ADVAGG_CSS_COMPRESS_INLINE))) {
$optimize = FALSE;
}
else {
$optimize = TRUE;
}
// Build aggregate CSS file.
$data = '';
foreach ($files as $file) {
$contents = drupal_load_stylesheet($file, TRUE);
// Return the path to where this CSS file originated from.
$base = base_path() . dirname($file) . '/';
_drupal_build_css_path(NULL, $base);
// Prefix all paths within this CSS file, ignoring external and absolute paths.
$data .= preg_replace_callback('/url\([\'"]?(?![a-z]+:|\/+)([^\'")]+)[\'"]?\)/i', '_drupal_build_css_path', $contents);
$contents = advagg_drupal_load_stylesheet($file, $optimize);
// Build the base URL of this CSS file: start with the full URL.
$css_base_url = advagg_file_create_url($file);
// 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,
@ -2806,9 +2917,10 @@ function advagg_build_js_bundle($files) {
$data = '';
// Build aggregate JS file.
foreach ($files as $file) {
// Append a ';' and a newline after each JS file to prevent them from running together.
// Append a ';', '/**/', and a newline after each JS file to prevent them
// from running together.
if (advagg_file_exists($file)) {
$data .= file_get_contents($file) . ";\n";
$data .= @file_get_contents($file) . ";/**/\n";
}
}
return $data;
@ -3013,14 +3125,26 @@ function advagg_add_css_inline($data = NULL, $media = 'all', $prefix = NULL, $su
* We use HTML-safe strings, i.e. with <, > and & escaped.
*/
function advagg_drupal_to_js($var) {
// Different versions of PHP handle json_encode() differently.
static $php550;
static $php530;
if (!isset($php550)) {
$php550 = version_compare(PHP_VERSION, '5.5.0', '>=');
}
if (!isset($php530)) {
$php530 = version_compare(PHP_VERSION, '5.3.0', '>=');
}
// json_encode on PHP prior to PHP 5.3.0 doesn't support options.
if ($php530) {
return json_encode($var, JSON_HEX_QUOT | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS);
// Default json encode options.
$options = JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT;
if ($php550) {
// Output partial json if PHP >= 5.5.0.
$options |= JSON_PARTIAL_OUTPUT_ON_ERROR;
}
// Encode to JSON.
return @json_encode($var, $options);
}
// if json_encode exists, use it.
@ -3197,6 +3321,54 @@ function _advagg_drupal_load_stylesheet($matches) {
return preg_replace('/url\(\s*([\'"]?)(?![a-z]+:|\/+)/i', 'url(\1' . $directory, $file);
}
/**
* Loads the stylesheet and resolves all @import commands.
*
* Loads a stylesheet and replaces @import commands with the contents of the
* imported file. Use this instead of file_get_contents when processing
* stylesheets.
*
* The returned contents are compressed removing white space and comments only
* when CSS aggregation is enabled. This optimization will not apply for
* color.module enabled themes with CSS aggregation turned off.
*
* @param $file
* Name of the stylesheet to be processed.
* @param $optimize
* Defines if CSS contents should be compressed or not.
* @param $reset_basepath
* Used internally to facilitate recursive resolution of @import commands.
*
* @return
* Contents of the stylesheet, including any resolved @import commands.
*/
function advagg_drupal_load_stylesheet($file, $optimize = NULL, $reset_basepath = TRUE) {
// These statics are not cache variables, so we don't use drupal_static().
static $_optimize, $basepath;
if ($reset_basepath) {
$basepath = '';
}
// Store the value of $optimize for preg_replace_callback with nested
// @import loops.
if (isset($optimize)) {
$_optimize = $optimize;
}
// Stylesheets are relative one to each other. Start by adding a base path
// prefix provided by the parent stylesheet (if necessary).
if ($basepath && !file_uri_scheme($file)) {
$file = $basepath . '/' . $file;
}
$basepath = dirname($file);
// Load the CSS stylesheet. We suppress errors because themes may specify
// stylesheets in their .info file that don't exist in the theme's path,
// but are merely there to disable certain module CSS files.
if ($contents = @file_get_contents($file)) {
// Return the processed stylesheet.
return advagg_drupal_load_stylesheet_content($contents, $_optimize);
}
return '';
}
/**
* Perform an HTTP request; does not wait for reply & you will never get it
* back.