array(), 'footer' => array() ); /** Wordpress to_do scripts, used both by mergescripts and admin_bar */ private $to_do; /** Used for save the handles want to deregister both by mmerge_scripts and check_cache method */ private $deregister = array('style' => array(), 'script' => array()); /** Handles that ara not detected by wp_print_scripts, we get it from wp_header and wp_footer we compare the rest_of_handles option with the registered handles generated by wordpress */ private $restOfHandles = array('header' => array(), 'footer' => array()); /** Check whether the method is already executed. This is to prevent the method from executed by other plugins */ private $is_executed = array('merge_styles' => false, 'merge_scripts' => false, 'footer_scripts' => false, 'header_scripts' => false ); public function __construct () { $this->options = get_option(APHMS_OPTION); // echo '
'; print_r($this->options );
}
public function init()
{
add_action('init', array($this, 'run_plugin'));
add_filter('script_loader_src', array($this, 'remove_query_string'));
add_filter('style_loader_src', array($this, 'remove_query_string'));
}
public function remove_query_string( $src )
{
if (strpos($src, $this->options['script_file_name'])
|| strpos($src, $this->options['style_file_name'])) {
$src = remove_query_arg('ver', $src);
}
return $src;
}
public function run_plugin()
{
$admin_bar = is_admin_bar_showing();
if (is_admin()
|| (is_user_logged_in() && !$admin_bar)
|| ($admin_bar && $this->options['manage_scripts']))
{
return;
}
if (isset($this->options['merge_scripts'])) {
add_action( 'wp_print_scripts', array( $this, 'merge_scripts' ), 999 );
add_action( 'wp_head', array( $this, 'deregister_script' ), 7 );
add_action( 'wp_footer', array( $this, 'deregister_script' ) );
}
if (isset($this->options['merge_styles'])) {
add_action( 'wp_print_styles', array( $this, 'merge_styles' ), 10 );
}
}
public function merge_styles()
{
if ($this->is_executed['merge_styles'])
return;
if (!$this->options['merge_styles'])
return;
global $wp_styles;
$queues = $wp_styles->queue;
$wp_styles->all_deps($queues);
$this->to_do = $wp_styles->to_do;
//File Name
$file = Aphms_Helper::merge_file_path('style');
$use_cache = $this->check_cache('style');
// $use_cache = false;
if (!$use_cache)
{
$merged_style = '';
$list_handles = array();
// echo ''; print_r($this->to_do);
foreach( $this->to_do as $handle)
{
if (!key_exists($handle, $wp_styles->registered))
continue;
$file_path = $this->file_path($wp_styles->registered[$handle]->src);
/** We have to save the handle outside the file_exists to make sure all handle are saved,
this is useful for cheching cache
*/
$list_handles[] = $handle;
if (file_exists($file_path))
{
require_once 'minifier/minify/src/Minify.php';
require_once 'minifier/minify/src/CSS.php';
require_once 'minifier/minify/src/Exception.php';
require_once 'minifier/minify/Converter.php';
$this->deregister['style'][] = $handle;
$minifier = new MatthiasMullie\Minify\CSS($file_path);
$minifier->setToPath( $file['file_path'] );
$merged_style .= $minifier->minify();
}
}
if ($merged_style) {
file_put_contents($file['file_path'], '/* APH Merge Scripts v'.APHMS_PLUGIN_VERSION.' */' . "\r\n" . $merged_style);
}
// echo ''; print_r($list_handles);
// update current handles
$this->options['curr_handles']['style']['time'] = time();
$this->options['curr_handles']['style']['handles'] = $list_handles;
update_option(APHMS_OPTION, $this->options);
}
foreach ($this->deregister['style'] as $handle)
{
wp_deregister_style($handle);
}
$time = @$this->options['style_query_string'] ? '?rand=' . time() : '';
wp_enqueue_style('merged-script', $file['file_url'] . $time, '', APHMS_PLUGIN_VERSION);
$this->is_executed['merge_styles'] = true;
}
public function merge_scripts($position)
{
if ($this->is_executed['merge_scripts'])
return;
if ($this->options['merge_scripts'] == 0)
return;
global $wp_scripts;
$wp_scripts->all_deps($wp_scripts->queue);
$this->to_do = $wp_scripts->to_do;
/* Used for either merged path or enqueue url */
$file = Aphms_Helper::merge_file_path('script');
// Check cache
$use_cache = $this->check_cache('script');
// $use_cache = false;
if (!$use_cache)
{
$merged_script = '';
$list_handles = array();
// Loop javascript files and save to $merged_script variable
foreach( $this->to_do as $handle)
{
if ($this->skip_handle($handle) || !key_exists($handle, $wp_scripts->registered))
continue;
$obj = $wp_scripts->registered[$handle];
// wp_localize_script
$localize = '';
if (@key_exists('data', $obj->extra))
$localize = $obj->extra['data'] . ';';
$file_path = $this->file_path($obj->src);
/** We have to save the handle outside the file_exists to make sure all handle are saved,
this is useful for cheching cache
*/
$list_handles[] = $handle;
if (file_exists($file_path))
{
$merged_script .= '/* Handle: ' . $handle . ' */' . "\r\n\r\n" . $localize . file_get_contents($file_path) . ';' . "\r\n\r\n";
$this->deregister['script'][] = $handle;
}
}
// Merge rest of scripts
foreach( $this->options['rest_of_handles']['script'] as $pos => $handles)
{
foreach ($handles as $handle => $arr)
{
if (in_array($handle, $this->to_do) || $this->skip_handle($handle))
continue;
// wp_localize_script
$localize = '';
if (@key_exists('data', $arr['extra']))
$localize = $arr['extra']['data'] . ';';
$file_path = $this->file_path($arr['src']);
if (file_exists($file_path))
{
$list_handles[] = $handle;
$merged_script .= '/* Handle: ' . $handle . ' */' . "\r\n\r\n" . $localize . file_get_contents($file_path) . ';' . "\r\n\r\n";
$this->deregister['script'][] = $handle;
}
}
}
// Save $merged_script into file
if ($merged_script) {
$this->write_js_file($merged_script, $file);
}
// update current handles
$this->options['curr_handles']['script']['time'] = time();
$this->options['curr_handles']['script']['handles'] = $list_handles;
update_option(APHMS_OPTION, $this->options);
}
foreach ($this->deregister['script'] as $handle)
{
wp_deregister_script($handle);
}
$location = $this->options['merge_scripts'] == 2 ? true : false;
$time = $this->options['script_query_string'] ? '?rand=' . time() : '';
wp_enqueue_script('merged-script', $file['file_url'] . $time, '', APHMS_PLUGIN_VERSION, $location);
$this->is_executed['merge_scripts'] = true;
}
private function write_js_file($merged_script, $file)
{
if ($this->options['minify_script']) {
require_once 'minifier/minify/src/Minify.php';
require_once 'minifier/minify/src/JS.php';
require_once 'minifier/minify/src/Exception.php';
$minifier = new MatthiasMullie\Minify\JS($merged_script);
$merged_script = $minifier->minify();
}
$merged_script = '/*! APH Merge Scripts v'.APHMS_PLUGIN_VERSION.' */' . "\r\n" . $merged_script;
file_put_contents($file['file_path'], $merged_script);
if ($this->options['minify_script'] == 2)
{
if (function_exists('exec'))
{
$plugin_dir = 'wp-content' . APHMS_DS . 'plugins' . APHMS_DS . APHMS_PLUGIN_DIR_NAME;
$yui_jar = $plugin_dir . APHMS_DS . 'includes' . APHMS_DS . 'minifier/' . APHMS_DS . 'yuicompressor' . APHMS_DS . 'yuicompressor.jar';
$cmd = 'java -jar ' . $yui_jar . ' ' . $file['file_rel_path'] . ' -o ' . $file['file_rel_path'];
@exec($cmd . ' 2>&1');
}
}
}
/**
Check cache make sure that all handles are processed
*/
private function check_cache($type)
{
if (!$this->options['curr_handles'][$type]['time']
|| !$this->options['curr_handles'][$type]['handles']
)
return false;
// Check whether the merged file exists
$file = Aphms_Helper::merge_file_path($type);
if (!file_exists($file['file_path']))
return false;
// Check whether cache is expired
$date = $this->options['curr_handles'][$type]['time'];
$expired = strtotime('+'.$this->options['cache_age'].' day', $date);
if ($expired < time())
return false;
$list_of_handles = array_merge($this->to_do,
array_keys($this->options['rest_of_handles'][$type]['header']),
array_keys($this->options['rest_of_handles'][$type]['footer'])
);
/* if ($type == 'script')
{
echo ''; print_r($list_of_handles);
echo ''; print_r($this->options['curr_handles'][$type]['handles']);
} */
foreach($list_of_handles as $handle)
{
/**
As we save the handle of merged files into curr_handles, then we need to make sure
that all of list handles (curr handles (to_do) + handles saved by user in the admin bar)
are exists in the curr_handles, if not, don't use the cache
*/
if (!in_array($handle, $this->options['curr_handles'][$type]['handles'])) {
return false;
}
$deregister[] = $handle;
}
// USE CACHE
foreach($list_of_handles as $handle) {
$this->deregister[$type] = $deregister;
}
return true;
}
/**
File path
Find relative path of each style or script
*/
private function file_path($src)
{
$clean_hash = $clean = strtok($src,'?');
$site_url = site_url();
$parse_site_url = parse_url($site_url);
$parse_url = parse_url($clean_hash);
$site_path = '';
if (key_exists('path', $parse_site_url))
{
$site_path = $parse_site_url['path'];
}
if (key_exists('host', $parse_url))
{
// Exclude external script
if ($parse_site_url['host'] != $parse_url['host'])
return false;
$file_path = substr ($parse_url['path'], strlen($site_path));
$file_path = ltrim ($file_path, '/');
}
else
{
$file_path = ltrim($parse_url['path'], '/');
}
return $file_path;
}
private function skip_handle($handle)
{
$excluded_script = $this->options['excluded_handles'];
if (in_array($handle, $excluded_script))
return true;
else
return false;
}
/**
Used in the init method to deregister th scripts earlier
*/
public function deregister_script()
{
if ($this->options['merge_scripts'] == 0)
return;
foreach( $this->options['rest_of_handles']['script'] as $pos => $handles)
{
foreach ($handles as $handle => $arr)
{
if (!in_array($handle, $this->options['excluded_handles'])) {
wp_deregister_script($handle);
}
}
}
}
}