View source
<?php
if (defined('PHP_VERSION_ID') && constant('PHP_VERSION_ID') >= 50300) {
module_load_include('inc', 'advagg_js_compress', 'advagg_js_compress.php53');
}
function advagg_js_compress_advagg_get_info_on_files_alter(&$return, $cached_data, $bypass_cache) {
$compressor_list = advagg_js_compress_get_enabled_compressors(array(), -1);
$cache_ids = array();
foreach ($return as $filename => &$info) {
if (empty($info['fileext']) || $info['fileext'] !== 'js') {
continue;
}
$cache_id = 'advagg:js_compress:info:' . $info['filename_hash'];
$cache_id .= !empty($info['content_hash']) ? ':' . $info['content_hash'] : '';
$cache_ids[$filename] = $cache_id;
$advagg_js_compress = array();
if (!empty($info['advagg_js_compress'])) {
foreach ($info['advagg_js_compress'] as $values) {
$array_key = array_search($values['name'], $compressor_list);
if ($array_key !== FALSE) {
$cache_hits_data[$array_key] = $values;
}
}
}
ksort($advagg_js_compress);
$info['advagg_js_compress'] = $advagg_js_compress;
}
unset($info);
if (empty($cache_ids)) {
return;
}
$values = array_values($cache_ids);
$cache_hits = cache_get_multiple($values, 'cache_advagg_info');
$compressors = advagg_js_compress_get_enabled_compressors();
$advagg_get_info_on_file_cached_data = drupal_static('advagg_get_info_on_file');
$filenames_info = array();
foreach ($cache_ids as $filename => $cache_id) {
$info =& $return[$filename];
if (!empty($cache_hits[$cache_id]) && isset($cache_hits[$cache_id]->data)) {
$cache_hits_data = array();
foreach ($cache_hits[$cache_id]->data as $values) {
$array_key = array_search($values['name'], $compressor_list);
if ($array_key !== FALSE) {
$cache_hits_data[$array_key] = $values;
}
}
ksort($cache_hits_data);
$info['advagg_js_compress'] = array_replace($info['advagg_js_compress'], $cache_hits_data);
}
foreach ($compressors as $id => $name) {
if (empty($info['advagg_js_compress'][$id])) {
$filenames_info[$filename] = $info;
break;
}
if ($bypass_cache && (empty($advagg_get_info_on_file_cached_data[$info['cache_id']]['content_hash']) || $info['content_hash'] !== $advagg_get_info_on_file_cached_data[$info['cache_id']]['content_hash'])) {
$filenames_info[$filename] = $info;
break;
}
}
}
if (empty($compressors) || variable_get('advagg_cache_level', ADVAGG_CACHE_LEVEL) != 0) {
return;
}
if (!empty($filenames_info)) {
$results = advagg_js_compress_run_mutiple_tests($filenames_info, $compressors);
foreach ($results as $filename => $data) {
$info =& $return[$filename];
if (!empty($info['advagg_js_compress'])) {
$data += $info['advagg_js_compress'];
}
$info['advagg_js_compress'] = $data;
}
}
}
function advagg_js_compress_advagg_get_js_file_contents_alter(&$contents, $filename, $aggregate_settings) {
if (!empty($aggregate_settings['variables']['advagg_js_compressor_file_settings'])) {
$form_api_filename = str_replace(array(
'/',
'.',
), array(
'__',
'--',
), $filename);
if (isset($aggregate_settings['variables']['advagg_js_compressor_file_settings'][$form_api_filename])) {
$aggregate_settings['variables']['advagg_js_compressor'] = $aggregate_settings['variables']['advagg_js_compressor_file_settings'][$form_api_filename];
}
}
if (empty($aggregate_settings['variables']['advagg_js_compressor'])) {
return;
}
$compressor = $aggregate_settings['variables']['advagg_js_compressor'];
module_load_include('inc', 'advagg', 'advagg');
$info = advagg_get_info_on_file($filename);
if (!isset($info['advagg_js_compress'][$compressor]['code'])) {
if (variable_get('advagg_cache_level', ADVAGG_CACHE_LEVEL) == 0 || variable_get('advagg_cache_level', ADVAGG_CACHE_LEVEL) == 1) {
$compressors_to_test = advagg_js_compress_get_enabled_compressors($aggregate_settings);
$info['advagg_js_compress'] = advagg_js_compress_run_test($filename, $info, $compressors_to_test);
}
}
if (!empty($info['advagg_js_compress'][$compressor]['code']) && $info['advagg_js_compress'][$compressor]['code'] == 1) {
advagg_js_compress_prep($contents, $filename, $aggregate_settings);
}
}
function advagg_js_compress_advagg_save_aggregate_alter(&$files_to_save, $aggregate_settings, $other_parameters) {
list($files, $type) = $other_parameters;
if (empty($aggregate_settings['variables']['advagg_gzip']) && empty($aggregate_settings['variables']['advagg_brotli']) || empty($aggregate_settings['variables']['advagg_js_compress_packer']) || $type !== 'js') {
return;
}
$data = reset($files_to_save);
$uri = key($files_to_save);
$compressor = 2;
module_load_include('inc', 'advagg', 'advagg');
foreach ($files as $file => $settings) {
$info = advagg_get_info_on_file($file);
if (!isset($info['advagg_js_compress'][$compressor]['code'])) {
$compressors = advagg_js_compress_get_enabled_compressors(array(), $compressor);
$info['advagg_js_compress'] = advagg_js_compress_run_test($file, $info, $compressors);
}
if (!isset($info['advagg_js_compress'][$compressor]['code']) || $info['advagg_js_compress'][$compressor]['code'] == -1 || $info['advagg_js_compress'][$compressor]['code'] == -3) {
return;
}
}
$aggregate_settings['variables']['advagg_js_compressor'] = $compressor;
advagg_js_compress_prep($data, $uri, $aggregate_settings, FALSE);
$files_to_save[$uri] = $data;
}
function advagg_js_compress_get_enabled_compressors(array $aggregate_settings = array(), $compressor = 0) {
list(, , $compressors) = advagg_js_compress_configuration();
if ($compressor == -1) {
return $compressors;
}
$return_compressors = array();
if (!empty($compressor)) {
$return_compressors = array(
$compressor => $compressors[$compressor],
);
}
else {
if (isset($aggregate_settings['variables']['advagg_js_compressor'])) {
$file = $aggregate_settings['variables']['advagg_js_compressor'];
}
else {
$file = variable_get('advagg_js_compressor', ADVAGG_JS_COMPRESSOR);
}
if (isset($aggregate_settings['variables']['advagg_js_compress_packer'])) {
$packer = $aggregate_settings['variables']['advagg_js_compress_packer'];
}
else {
$packer = variable_get('advagg_js_compress_packer', ADVAGG_JS_COMPRESS_PACKER);
}
if (isset($compressors[$file])) {
$return_compressors[$file] = $compressors[$file];
}
if ($packer) {
$return_compressors[2] = $compressors[2];
}
if ($file == 3) {
if (isset($compressors[3])) {
$return_compressors[3] = $compressors[3];
}
elseif (isset($compressors[5])) {
$return_compressors[5] = $compressors[5];
}
else {
$return_compressors[1] = $compressors[1];
}
}
}
return $return_compressors;
}
function advagg_js_compress_do_it(&$contents, array $info, $compressor, $force_run, array $aggregate_settings, $log_errors) {
$no_errors = TRUE;
$content_hash = !empty($info['content_hash']) ? ":{$info['content_hash']}" : '';
$cache_id = "advagg:js_compress:{$compressor}:{$info['filename_hash']}:{$content_hash}";
$cache = cache_get($cache_id, 'cache_advagg_aggregates');
$force_run = variable_get('advagg_js_compress_force_run', $force_run);
if (!$force_run && !empty($cache->data)) {
$contents = $cache->data;
}
else {
$contents = str_replace(pack("CCC", 0xef, 0xbb, 0xbf), "", $contents);
if ($compressor == 3) {
$contents = str_replace("\t", " ", $contents);
}
$random = dechex(mt_rand());
$end_string = "var advagg_end=\"{$random}\";";
$contents .= "\n{$end_string}";
list(, , , $functions) = advagg_js_compress_configuration();
if (isset($functions[$compressor])) {
$run = $functions[$compressor];
if (function_exists($run)) {
$no_errors = $run($contents, $log_errors, $aggregate_settings);
}
}
else {
return FALSE;
}
$end_string = substr($end_string, 0, -1);
$pos = strrpos($contents, $end_string);
if ($pos === FALSE) {
$end_string = str_replace('"', "'", $end_string);
$pos = strrpos($contents, $end_string);
}
if ($pos !== FALSE) {
$contents = substr($contents, 0, $pos);
}
if ($compressor == 3 || $compressor == 5) {
$a = strrpos($contents, ';');
$b = strrpos($contents, '}');
$c = strrpos($contents, ')');
if ($a !== FALSE || $b !== FALSE || $c !== FALSE) {
$contents = substr($contents, 0, 1 + max($a, $b, $c));
}
}
if (strpbrk(substr(trim($contents), -1), ';}') === FALSE) {
$contents = trim($contents) . ';';
}
if (empty($info['#no_cache'])) {
cache_set($cache_id, $contents, 'cache_advagg_aggregates', REQUEST_TIME + 86400 * 7);
}
else {
cache_set($cache_id, $contents, 'cache_advagg_aggregates', REQUEST_TIME + 3600);
}
}
return $no_errors;
}
function advagg_js_compress_prep(&$contents, $filename, array $aggregate_settings, $add_licensing = TRUE, $log_errors = TRUE, $test_ratios = TRUE, $force_run = FALSE) {
$no_errors = TRUE;
module_load_include('inc', 'advagg', 'advagg');
$compressor = $aggregate_settings['variables']['advagg_js_compressor'];
if ($compressor == 0) {
return FALSE;
}
$url = file_create_url($filename);
$semicolon_count = substr_count($contents, ';');
if ($compressor != 2 && $semicolon_count > 10 && $semicolon_count > substr_count($contents, "\n", strpos($contents, ';')) * 5 && !$force_run) {
$add_license_setting = isset($aggregate_settings['variables']['advagg_js_compress_add_license']) ? $aggregate_settings['variables']['advagg_js_compress_add_license'] : variable_get('advagg_js_compress_add_license', ADVAGG_JS_COMPRESS_ADD_LICENSE);
if ($add_licensing && ($add_license_setting == 1 || $add_license_setting == 3)) {
$contents = "/* Source and licensing information for the line(s) below can be found at {$url}. */\n" . $contents . ";\n/* Source and licensing information for the above line(s) can be found at {$url}. */\n";
return FALSE;
}
}
$contents_before = $contents;
$before = strlen($contents);
if ($compressor == 3 && !function_exists('jsmin')) {
if (defined('PHP_VERSION_ID') && constant('PHP_VERSION_ID') >= 50300) {
$compressor = 5;
watchdog('advagg_js_compress', 'The jsmin function does not exist. Using JSqueeze.');
}
else {
$compressor = 1;
watchdog('advagg_js_compress', 'The jsmin function does not exist. Using JSmin+.');
}
}
if ($compressor == 3 && (version_compare(phpversion('jsmin'), '2.0.0', '<') && advagg_js_compress_string_contains_multibyte_characters($contents))) {
if (defined('PHP_VERSION_ID') && constant('PHP_VERSION_ID') >= 50300) {
$compressor = 5;
watchdog('advagg_js_compress', 'The currently installed jsmin version does not handle multibyte characters, you may consider to upgrade the jsmin extension. Using JSqueeze fallback.');
}
else {
$compressor = 1;
watchdog('advagg_js_compress', 'The currently installed jsmin version does not handle multibyte characters, you may consider to upgrade the jsmin extension. Using JSmin+ fallback.');
}
}
$info = advagg_get_info_on_files(array(
$filename,
), FALSE, FALSE);
$info = $info[$filename];
$no_errors = advagg_js_compress_do_it($contents, $info, $compressor, $force_run, $aggregate_settings, $log_errors, $url);
$after = strlen($contents);
$ratio = 0;
if ($before != 0) {
$ratio = ($before - $after) / $before;
}
$aggregate_settings['variables']['advagg_js_compress_max_ratio'] = isset($aggregate_settings['variables']['advagg_js_compress_max_ratio']) ? $aggregate_settings['variables']['advagg_js_compress_max_ratio'] : variable_get('advagg_js_compress_max_ratio', ADVAGG_JS_COMPRESS_MAX_RATIO);
$aggregate_settings['variables']['advagg_js_compress_ratio'] = isset($aggregate_settings['variables']['advagg_js_compress_ratio']) ? $aggregate_settings['variables']['advagg_js_compress_ratio'] : variable_get('advagg_js_compress_ratio', ADVAGG_JS_COMPRESS_RATIO);
$add_license_setting = isset($aggregate_settings['variables']['advagg_js_compress_add_license']) ? $aggregate_settings['variables']['advagg_js_compress_add_license'] : variable_get('advagg_js_compress_add_license', ADVAGG_JS_COMPRESS_ADD_LICENSE);
if (empty($contents) || empty($ratio) || $ratio < $aggregate_settings['variables']['advagg_js_compress_ratio'] || $ratio > $aggregate_settings['variables']['advagg_js_compress_max_ratio']) {
$contents = $contents_before;
if ($compressor !== 1) {
$no_errors = advagg_js_compress_do_it($contents, $info, 1, $force_run, $aggregate_settings, $log_errors, $url);
$after = strlen($contents);
$ratio = 0;
if ($before != 0) {
$ratio = ($before - $after) / $before;
}
if (empty($contents) || empty($ratio) || $ratio < $aggregate_settings['variables']['advagg_js_compress_ratio'] || $ratio > $aggregate_settings['variables']['advagg_js_compress_max_ratio']) {
$contents = $contents_before;
}
}
}
if ($add_licensing && ($add_license_setting == 1 || $add_license_setting == 3)) {
$contents = "/* Source and licensing information for the line(s) below can be found at {$url}. */\n" . $contents . ";\n/* Source and licensing information for the above line(s) can be found at {$url}. */\n";
}
if (variable_get('advagg_cache_level', ADVAGG_CACHE_LEVEL) < 0 && !$force_run) {
$contents = $contents_before;
}
return $no_errors;
}
function advagg_js_compress_string_contains_multibyte_characters($string) {
if (strlen($string) == drupal_strlen($string)) {
return FALSE;
}
return TRUE;
}
function advagg_js_compress_jsminplus(&$contents, $log_errors = TRUE) {
$no_errors = TRUE;
$contents_before = $contents;
$old_error = error_get_last();
if (!class_exists('JSMinPlus')) {
$nesting_level = ini_get('xdebug.max_nesting_level');
if (!empty($nesting_level) && $nesting_level < 200) {
ini_set('xdebug.max_nesting_level', 200);
}
}
if (is_callable('libraries_load')) {
libraries_load('jsminplus');
}
if (!class_exists('JSMinPlus')) {
include drupal_get_path('module', 'advagg_js_compress') . '/jsminplus.inc';
}
ob_start();
try {
$contents = @JSMinPlus::minify($contents);
$error = trim(ob_get_contents());
if (!empty($error)) {
$no_errors = FALSE;
throw new Exception($error);
}
$recent_error = error_get_last();
if (!empty($recent_error) && serialize($recent_error) !== serialize($old_error)) {
$no_errors = FALSE;
$error = print_r($recent_error, TRUE);
throw new Exception($error);
}
} catch (Exception $e) {
$no_errors = FALSE;
if ($log_errors) {
watchdog('advagg_js_compress', '@message <pre> @contents </pre>', array(
'@message' => $e
->getMessage(),
'@contents' => $contents_before,
), WATCHDOG_WARNING);
}
$contents = $contents_before;
}
ob_end_clean();
return $no_errors;
}
function advagg_js_compress_jspacker(&$contents, $log_errors = TRUE) {
$no_errors = TRUE;
$contents_before = $contents;
if (is_callable('libraries_load')) {
libraries_load('jspacker');
}
if (!class_exists('JavaScriptPacker')) {
include drupal_get_path('module', 'advagg_js_compress') . '/jspacker.inc';
}
$contents = str_replace("}\n", "};\n", $contents);
$contents = str_replace("\nfunction", ";\nfunction", $contents);
try {
$packer = new JavaScriptPacker($contents, 62, TRUE, FALSE);
$contents = $packer
->pack();
} catch (Exception $e) {
$no_errors = FALSE;
if ($log_errors) {
watchdog('advagg_js_compress', '@message <pre> @contents </pre>', array(
'@message' => $e
->getMessage(),
'@contents' => $contents_before,
), WATCHDOG_WARNING);
}
$contents = $contents_before;
}
return $no_errors;
}
function advagg_js_compress_jsmin(&$contents, $log_errors = TRUE) {
$no_errors = TRUE;
$contents_before = $contents;
try {
$contents = jsmin($contents);
} catch (Exception $e) {
$no_errors = FALSE;
if ($log_errors) {
watchdog('advagg_js_compress', '@message <pre> @contents </pre>', array(
'@message' => $e
->getMessage(),
'@contents' => $contents_before,
), WATCHDOG_WARNING);
}
$contents = $contents_before;
}
return $no_errors;
}
function advagg_js_compress_run_test($filename, array $info = array(), array $compressors = array()) {
module_load_include('inc', 'advagg', 'advagg');
if (empty($info)) {
$info = advagg_get_info_on_file($filename, FALSE, FALSE);
}
$cache_id = 'advagg:js_compress:info:' . $info['filename_hash'];
$cache_id .= !empty($info['content_hash']) ? ':' . $info['content_hash'] : '';
$compressor_list = advagg_js_compress_get_enabled_compressors(array(), -1);
if (empty($compressors)) {
$compressors = $compressor_list;
}
if (empty($info['content_hash'])) {
foreach ($compressor_list as $key => $name) {
$results[$key] = array(
'code' => 0,
'ratio' => 0,
'name' => $name,
);
}
}
else {
foreach ($compressor_list as $key => $name) {
$results[$key] = array(
'code' => -1,
'ratio' => 0,
'name' => $name,
);
}
$run_locally = TRUE;
if (module_exists('httprl') && httprl_is_background_callback_capable()) {
$run_locally = FALSE;
$callback_options = array(
array(
'function' => 'advagg_js_compress_test_file',
'return' => &$results,
),
$filename,
$compressors,
$cache_id,
);
httprl_queue_background_callback($callback_options);
httprl_send_request();
foreach ($results as $key => $value) {
if ($value['code'] == -1) {
$sub_result = array();
$sub_result[$key] = $value;
$callback_options = array(
array(
'function' => 'advagg_js_compress_test_file',
'return' => &$sub_result,
),
$filename,
array(
$key => $value['name'],
),
$cache_id,
);
httprl_queue_background_callback($callback_options);
httprl_send_request();
$results[$key] = $sub_result[$key];
}
}
foreach ($results as $key => $value) {
if ($value['code'] != -1) {
$run_locally = TRUE;
break;
}
}
}
if ($run_locally) {
cache_set($cache_id, $results, 'cache_advagg_info', round(REQUEST_TIME + 1209600 + mt_rand(0, 3888000), -3));
$results = advagg_js_compress_test_file($filename, $compressors, $cache_id);
}
}
cache_set($cache_id, $results, 'cache_advagg_info', round(REQUEST_TIME + 1209600 + mt_rand(0, 3888000), -3));
return $results;
}
function advagg_js_compress_run_mutiple_tests(array $filenames_info, array $compressors = array()) {
module_load_include('inc', 'advagg', 'advagg');
$compressor_list = advagg_js_compress_get_enabled_compressors(array(), -1);
if (empty($compressors)) {
$compressors = $compressor_list;
}
if (count($filenames_info) > 5) {
if (drupal_is_cli()) {
drupal_set_time_limit(0);
}
else {
$max_execution_time = ini_get('max_execution_time');
if ($max_execution_time != 0) {
$current_time = 5;
if (is_callable('getrusage')) {
$dat = getrusage();
$current_time = $dat["ru_utime.tv_sec"];
}
$max_time = max(30, ini_get('max_execution_time'));
$time_left = $max_time - $current_time;
drupal_set_time_limit(count($filenames_info) * 3 + $time_left);
}
}
}
$return = array();
foreach ($filenames_info as $filename => $info) {
if (!module_exists('httprl') || !httprl_is_background_callback_capable()) {
$return[$filename] = advagg_js_compress_run_test($filename, $info, $compressors);
continue;
}
$results = array();
if (empty($info)) {
$info = advagg_get_info_on_file($filename, FALSE, FALSE);
}
if (empty($info['content_hash'])) {
foreach ($compressor_list as $key => $name) {
$results[$key] = array(
'code' => 0,
'ratio' => 0,
'name' => $name,
);
}
$return[$filename] = $results;
continue;
}
$results =& $return[$filename];
foreach ($compressor_list as $key => $name) {
$results[$key] = array(
'code' => -1,
'ratio' => 0,
'name' => $name,
);
}
$cache_id = 'advagg:js_compress:info:' . $info['filename_hash'];
$cache_id .= !empty($info['content_hash']) ? ':' . $info['content_hash'] : '';
$callback_options = array(
array(
'function' => 'advagg_js_compress_test_file',
'return' => &$results,
),
$filename,
$compressors,
$cache_id,
);
httprl_queue_background_callback($callback_options);
}
if (module_exists('httprl') && httprl_is_background_callback_capable()) {
httprl_send_request();
foreach ($return as $filename => &$results) {
if (!empty($results)) {
foreach ($results as $key => $value) {
if ($value['code'] == -1) {
unset($results);
$results = array();
break;
}
}
}
if (empty($results)) {
foreach ($compressor_list as $key => $name) {
$info = $filenames_info[$filename];
$cache_id = 'advagg:js_compress:info:' . $info['filename_hash'];
$cache_id .= !empty($info['content_hash']) ? ':' . $info['content_hash'] : '';
$sub_result = array();
$sub_result[$key] = '';
$callback_options = array(
array(
'function' => 'advagg_js_compress_test_file',
'return' => &$sub_result,
),
$filename,
array(
$key => $name,
),
$cache_id,
);
httprl_queue_background_callback($callback_options);
httprl_send_request();
if (!empty($sub_result[$key])) {
$results[$key] = $sub_result[$key];
}
else {
$results[$key] = array(
'code' => -1,
'ratio' => 0,
'name' => $name,
);
}
}
}
}
unset($results);
}
return $return;
}