<?php
namespace SpeedyCache;
if(!defined('ABSPATH')){
die('HACKING ATTEMPT');
}
use \SpeedyCache\Util;
class JS{
// Depericated since 1.2.0
// do not use it just to prevent site from breaking.
static function init(){
}
static function minify(&$content){
global $speedycache;
if(!class_exists('\SpeedyCache\Enhanced')){
return;
}
preg_match_all('/<script\s+([^>]+[\s"\'])?src\s*=\s*[\'"]\s*?(?<url>[^\'"]+\.js(?:\?[^\'"]*)?)\s*?[\'"]([^>]+)?\/?><\/script>/is', $content, $tags, PREG_SET_ORDER);
if(empty($tags)){
return;
}
if(empty($_SERVER['HTTP_HOST'])){
return;
}
$site_host = str_replace('www.', '', sanitize_text_field(wp_unslash($_SERVER['HTTP_HOST'])));
$site_url = site_url();
foreach($tags as $tag){
if(empty($tag['url'])){
continue;
}
$url = $tag['url'];
if(self::is_excluded($url)) continue;
// We don't want to minify already minified js
if(strpos($url, '.min.js') !== FALSE){
continue;
}
// We wont process any css that is not present on this WordPress install
if(strpos($url, $site_host) === FALSE){
continue;
}
$file_path = Util::url_to_path($url);
if(!file_exists($file_path)){
continue;
}
$file_name = self::file_name($file_path);
if(empty($speedycache->enhanced)){
\SpeedyCache\Enhanced::init();
}
$js = file_get_contents($file_path);
$js = \SpeedyCache\Enhanced::minify_js($js);
$asset_path = Util::cache_path('assets');
if(!is_dir($asset_path)){
mkdir($asset_path, 0755, true);
touch($asset_path . 'index.html');
}
$minified_path = $asset_path.$file_name;
file_put_contents($minified_path, $js);
$minified_url = Util::path_to_url($minified_path);
$content = str_replace($tag['url'], $minified_url, $content);
// TODO: check if there is a preload.
}
}
static function combine_head(&$content){
global $speedycache;
if (preg_match('/<head.*?>(.*?)<\/head>/is', $content, $head_section)) {
$head = preg_replace( '/<!--(.*)-->/Uis', '', $head_section[1]);
// Regex pattern to match script tags with src attribute in the head section
preg_match_all('/<script\s+([^>]+[\s"\'])?src\s*=\s*[\'"]\s*?(?<url>[^\'"]+\.js(?:\?[^\'"]*)?)\s*?[\'"]([^>]+)?\/?><\/script>/is', $head, $tags, PREG_SET_ORDER);
if(empty($tags)){
return;
}
if(empty($_SERVER['HTTP_HOST'])){
return;
}
$site_host = str_replace('www.', '', sanitize_text_field(wp_unslash($_SERVER['HTTP_HOST'])));
$site_url = site_url();
$tags = array_reverse($tags);
// There is no sense in combinining just 2 files.
if(count($tags) < 2){
return;
}
$combined_js = '';
$prev_tag = '';
foreach($tags as $tag){
if(empty($tag['url'])){
continue;
}
// We wont combine modules.
if(!empty($tag[1]) && strpos($tag[1], 'module')){
continue;
}
$url = $tag['url'];
if(self::is_excluded($url)) continue;
// We wont process any js that is not present on this WordPress install
if(strpos($url, $site_host) === FALSE){
continue;
}
$file_path = Util::url_to_path($url);
if(!file_exists($file_path) || !is_readable($file_path)){
continue;
}
$combined_js = file_get_contents($file_path) . "\n" . $combined_js;
// Removing the JS which has already been combined, as we will add the combined file at the top after title.
if(!empty($prev_tag)){
$content = str_replace($prev_tag, '', $content);
}
// We remove the previous tag, in current iteration, so at last we have a tag to replace wirh the combined script.
$prev_tag = $tag[0];
}
if(empty($combined_js)){
return;
}
if(class_exists('\SpeedyCache\Enhanced') && !empty($speedycache->options['minify_js'])){
if(empty($speedycache->enhanced)){
\SpeedyCache\Enhanced::init();
}
$combined_js = \SpeedyCache\Enhanced::minify_js($combined_js);
}
// Creating Combined file name
$file_name = md5($combined_js);
$file_name = substr($file_name, 0, 16) . '-combined.js';
$asset_path = Util::cache_path('assets');
if(!is_dir($asset_path)){
mkdir($asset_path, 0755, true);
touch($asset_path . 'index.html');
}
$combined_path = $asset_path.$file_name;
file_put_contents($combined_path, $combined_js);
$final_url = Util::path_to_url($combined_path);
// Injecting the Combined JS
if(!empty($prev_tag)){
$content = str_replace($prev_tag, '<script src="'.esc_url($final_url).'" />', $content);
return;
}
$content = str_replace('</title>', "</title>\n".'<script src="'.esc_url($final_url).'"/>', $content);
}
}
static function file_name($path){
$file_hash = md5_file($path);
$file_name = substr($file_hash, 0, 16) . '-' . basename($path);
return $file_name;
}
static function combine_body(&$content){
global $speedycache;
\SpeedyCache\Enhanced::init();
\SpeedyCache\Enhanced::set_html($content);
if(!empty($speedycache->options['minify_js'])){
$content = \SpeedyCache\Enhanced::combine_js_in_footer(true);
}else{
$content = \SpeedyCache\Enhanced::combine_js_in_footer();
}
}
static function is_excluded($url){
$excludes = get_option('speedycache_exclude', []);
// Combining JQUERY will mess up the site.
if(strpos($url, 'jquery')){
return true;
}
if(empty($excludes)){
return false;
}
foreach($excludes as $exclude){
if(empty($exclude['type'])){
continue;
}
if($exclude['type'] !== 'js'){
continue;
}
if(empty($exclude['content'])){
continue;
}
if(preg_match('/'.preg_quote($exclude['content'], '/').'/', $url)){
return true;
}
}
return false;
}
}