.
*/
if (!class_exists('WPMinify')) {
class WPMinify {
var $author_homepage = 'http://omninoggin.com/';
var $homepage = 'http://omninoggin.com/wordpress-plugins/wp-minify-wordpress-plugin/';
var $name = 'wp_minify';
var $name_dashed = 'wp-minify';
var $name_proper = 'WP Minify';
var $required_wp_version = '2.7';
var $version = '0.6.5';
var $c = null;
var $debug = false;
var $cache_location = 'wp-content/plugins/wp-minify/cache/';
var $url_len_limit = 2000;
var $minify_limit = 50;
var $buffer_started = false;
var $default_exclude = array('https://');
function WPMinify() {
// initialize common functions
$this->c = new WPMinifyCommon($this);
// load translation
$this->c->load_text_domain();
// register admin scripts
add_action('admin_init', array($this->c, 'a_register_scripts'));
add_action('admin_init', array($this->c, 'a_register_styles'));
// check wp version
add_action('admin_head', array($this->c, 'a_check_version'));
// load admin menu
add_action('admin_menu', array($this, 'a_menu'));
if (!is_admin()) {
// No need to minify admin stuff
add_action('init', array($this, 'pre_content'), 99999);
add_action('wp_footer', array($this, 'post_content'));
// advertise hook
add_action('wp_footer', array($this, 'advertise'));
}
}
// admin functions
function a_default_options() {
return array(
'cache_interval' => 900,
'enable_css' => true,
'css_exclude' => array(),
'css_include' => array(),
'debug' => false,
'enable_js' => true,
'js_exclude' => array(),
'js_include' => array(),
'show_link' => true,
'version' => $this->version,
'wp_path' => ''
);
}
function a_update_options() {
// new options
$wpm_new_options = stripslashes_deep($_POST['wpm_options_update']);
// current options
$wpm_current_options = get_option($this->name);
// convert "on" to true and "off" to false for checkbox fields
// and set defaults for fields that are left blank
if ( isset($wpm_new_options['show_link']) && $wpm_new_options['show_link'] == "on")
$wpm_new_options['show_link'] = true;
else
$wpm_new_options['show_link'] = false;
if ( isset($wpm_new_options['enable_js']) )
$wpm_new_options['enable_js'] = true;
else
$wpm_new_options['enable_js'] = false;
if ( isset($wpm_new_options['enable_css']) )
$wpm_new_options['enable_css'] = true;
else
$wpm_new_options['enable_css'] = false;
if ( isset($wpm_new_options['debug']) )
$wpm_new_options['debug'] = true;
else
$wpm_new_options['debug'] = false;
if ( strlen(trim($wpm_new_options['js_include'])) > 0 )
$wpm_new_options['js_include'] = $this->array_trim(split(chr(10), str_replace(chr(13), '', $wpm_new_options['js_include'])));
else
$wpm_new_options['js_include'] = array();
if ( strlen(trim($wpm_new_options['js_exclude'])) > 0 )
$wpm_new_options['js_exclude'] = $this->array_trim(split(chr(10), str_replace(chr(13), '', $wpm_new_options['js_exclude'])));
else
$wpm_new_options['js_exclude'] = array();
if ( strlen(trim($wpm_new_options['css_include'])) > 0 )
$wpm_new_options['css_include'] = $this->array_trim(split(chr(10), str_replace(chr(13), '', $wpm_new_options['css_include'])));
else
$wpm_new_options['css_include'] = array();
if ( strlen(trim($wpm_new_options['css_exclude'])) > 0 )
$wpm_new_options['css_exclude'] = $this->array_trim(split(chr(10), str_replace(chr(13), '', $wpm_new_options['css_exclude'])));
else
$wpm_new_options['css_exclude'] = array();
// Update options
foreach($wpm_new_options as $key => $value) {
$wpm_current_options[$key] = $value;
}
update_option($this->name, $wpm_current_options);
}
function a_request_handler() {
if (isset($_POST['wpm_options_update_submit'])) {
check_admin_referer($this->name);
$this->a_update_options();
add_action('admin_notices', array($this->c, 'a_notify_updated'));
}
elseif (isset($_POST['wpm_options_clear_cache_submit'])) {
// if user wants to regenerate nonce
check_admin_referer($this->name);
$this->c->a_clear_cache();
add_action('admin_notices', array($this->c, 'a_notify_cache_cleared'));
}
elseif (isset($_POST['wpm_options_upgrade_submit'])) {
// if user wants to upgrade options (for new options on version upgrades)
check_admin_referer($this->name);
$this->c->a_upgrade_options();
add_action('admin_notices', array($this->c, 'a_notify_upgraded'));
}
elseif (isset($_POST['wpm_options_reset_submit'])) {
// if user wants to reset all options
check_admin_referer($this->name);
$this->c->a_reset_options();
add_action('admin_notices', array($this->c, 'a_notify_reset'));
}
// only check these on plugin settings page
$this->c->a_check_dir_writable($this->c->get_plugin_dir().'cache/', array($this, 'a_notify_cache_not_writable'));
$this->c->a_check_orphan_options(array($this, 'a_notify_orphan_options'));
if ($this->c->a_check_dir_writable($this->c->get_plugin_dir().'min/config.php', array($this, 'a_notify_config_not_writable'))) {
$this->a_check_minify_config();
}
}
function a_check_minify_config() {
$fname = $this->c->get_plugin_dir().'min/config.php';
$fhandle = fopen($fname,'r');
$content = fread($fhandle,filesize($fname));
preg_match('/\/\/###WPM-CACHE-PATH-BEFORE###(.*)\/\/###WPM-CACHE-PATH-AFTER###/s', $content, $matches);
$cache_path_code = $matches[1];
if (!preg_match('/\$min_cachePath.*?/', $cache_path_code)) {
$content = preg_replace(
'/\/\/###WPM-CACHE-PATH-BEFORE###(.*)\/\/###WPM-CACHE-PATH-AFTER###/s',
"//###WPM-CACHE-PATH-BEFORE###\n".'$min_cachePath = \''.$this->c->get_plugin_dir()."cache/';\n//###WPM-CACHE-PATH-AFTER###",
$content);
$this->a_notify_modified_minify_config();
}
$fhandle = fopen($fname,"w");
fwrite($fhandle,$content);
fclose($fhandle);
}
function a_notify_cache_not_writable() {
$this->c->a_notify(
sprintf('%s: %s',
__('Cache directory is not writable. Please grant your server write permissions to the directory', $this->name),
$this->c->get_plugin_dir().'cache/'),
true);
}
function a_notify_config_not_writable() {
$this->c->a_notify(
sprintf('%s: %s',
__('Minify Engine config.php is not writable. Please grant your server write permissions to file', $this->name),
$this->c->get_plugin_dir().'min/config.php'));
}
function a_notify_orphan_options() {
$this->c->a_notify(
sprintf('%s ',
__('Some option settings are missing (possibly from plugin upgrade). Please reactivate.', $this->name),
__('Reactivate', $this->name)));
}
function a_notify_modified_minify_config() {
$this->c->a_notify( __('Minify Engine config.php was configured automatically.', $this->name));
}
function a_menu() {
$options_page = add_options_page($this->name_proper, $this->name_proper, 'manage_options', 'wp-minify', array($this, 'a_page'));
add_action('admin_head-'.$options_page, array($this, 'a_request_handler'));
add_action('admin_print_scripts-'.$options_page, array($this->c, 'a_enqueue_scripts'));
add_action('admin_print_styles-'.$options_page, array($this->c, 'a_enqueue_styles'));
}
function a_page() {
$wpm_options = get_option($this->name);
printf('
%s
',
__('WP Minify Options', $this->name),
__('General Configuration', $this->name),
__('Documentation', $this->name)
);
printf('
');
if ( isset($_GET['wpm-page']) ) {
if ( $_GET['wpm-page'] || !$_GET['wpm-page'] ) {
require_once('options-generic.php');
}
}
else {
require_once('options-generic.php');
}
printf('
'); // omni_admin_main
require_once('options-sidebar.php');
printf('
'); // wrap
} // admin_page()
// other functions
function fetch_and_cache($url, $cache_file) {
$ch = curl_init();
$timeout = 5; // set to zero for no timeout
curl_setopt ($ch, CURLOPT_URL, $url);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
$content = curl_exec($ch);
curl_close($ch);
if ( $content ) {
if ( is_array($content) ) {
$content = implode($content);
}
// save cache file
$fh = fopen($cache_file, 'w');
if ( $fh ) {
fwrite($fh, $content);
fclose($fh);
}
else {
// cannot open for write. no error b/c something else is probably writing to the file.
}
return $content;
}
else {
printf(
'%s: '.$url.'. %s',
__('Error: Could not fetch and cache URL'),
__('You might need to exclude this file in WP Minify options.')
);
return '';
}
}
function refetch_cache_if_expired($url, $cache_file) {
$wpm_options = get_option($this->name);
$cache_file_mtime = filemtime($cache_file);
if ( (time() - $cache_file_mtime) > $wpm_options['cache_interval'] ) {
$this->fetch_and_cache($url, $cache_file);
}
}
function tiny_filename($str) {
$f = __FILE__;
// no fancy shortening for Windows
return ('/' === $f[0]) ? strtr(base64_encode(md5($str, true)), '+/=', '-_(') : md5($str);
}
function array_trim($arr, $charlist=null){
foreach($arr as $key => $value){
if (is_array($value)) $result[$key] = array_trim($value, $charlist);
else $result[$key] = trim($value, $charlist);
}
return $result;
}
function check_and_split_url($url) {
$wpm_options = get_option($this->name);
// append &debug if we need to
if ( $wpm_options['debug'] ) {
$debug_url = '&debug=true';
}
else {
$debug_url = '';
}
$url_chunk = explode('?f=', $url);
$base_url = array_shift($url_chunk);
$files = explode(',', array_shift($url_chunk));
$num_files = sizeof($files);
if ( $url > $this->url_len_limit or $num_files > $this->minify_limit ) {
$first_half = $this->check_and_split_url($base_url . '?f=' . implode(',', array_slice($files, 0, $num_files/2)));
$second_half = $this->check_and_split_url($base_url . '?f=' . implode(',', array_slice($files, $num_files/2)));
return $first_half + $second_half;
}
else {
return array($base_url . '?f=' . implode(',', $files) . $debug_url);
}
}
function fetch_content($url, $type) {
$wpm_options = get_option($this->name);
$cache_file = $this->c->get_plugin_dir().'cache/'.md5($url).$type;
$content = '';
if ( file_exists($cache_file) ) {
// check cache expiration
$this->refetch_cache_if_expired($url, $cache_file);
$fh = fopen($cache_file, 'r');
if ( $fh && filesize($cache_file) > 0 ) {
$content = fread($fh, filesize($cache_file));
fclose($fh);
}
else {
// cannot open cache file so fetch it
$content = $this->fetch_and_cache($url, $cache_file);
}
}
else {
// no cache file. fetch from internet and save to local cache
$content = $this->fetch_and_cache($url, $cache_file);
}
return $content;
}
function get_script_src_from_handle($handle) {
global $wp_scripts;
$ver = $wp_scripts->registered[$handle]->ver ? $wp_scripts->registered[$handle]->ver : $wp_scripts->default_version;
if ( isset($wp_scripts->args[$handle]) )
$ver .= '&' . $wp_scripts->args[$handle];
$src = $wp_scripts->registered[$handle]->src;
if ( !preg_match('|^https?://|', $src) && !preg_match('|^' . preg_quote(WP_CONTENT_URL) . '|', $src) ) {
$src = $wp_scripts->base_url . $src;
}
$src = add_query_arg('ver', $ver, $src);
$src = clean_url(apply_filters( 'script_loader_src', $src, $handle ));
$wp_scripts->print_scripts_l10n( $handle );
return $src;
}
function get_js_location($src) {
if ( $this->debug )
echo 'Script URL:'.$src."
\n";
$wpm_options = get_option($this->name);
$site_url = trailingslashit(get_option('siteurl'));
$num_matches = preg_match('/^https?:\/\/.*?\//', $site_url, $matches);
$domain = $num_matches>0? $matches[0] : $site_url; // domain if found; the "slashed" site url otherwise
$script_path = str_replace($domain, '', $src); // relative paths only for local urls
$script_path = preg_replace('/^\//', '', $script_path); // strip front / if any
$script_path = preg_replace('/\?.*/i', '', $script_path); // throws away parameters, if any
if ( substr($script_path, 0, 4) != 'http' && substr($script_path, -3, 3) == '.js' ) {
// if script is local to server
if ( $this->debug )
echo 'Local script detected:'.$script_path."
\n";
$location = $script_path;
}
else {
// fetch scripts if necessary
$this->fetch_content($src, '.js');
$location = $this->cache_location . md5($src) . '.js';
}
return trailingslashit($wpm_options['wp_path']) . $location;
}
function get_css_location($src) {
if ( $this->debug )
echo 'Style URL:'.$src."
\n";
$wpm_options = get_option($this->name);
$site_url = trailingslashit(get_option('siteurl'));
$num_matches = preg_match('/^https?:\/\/.*?\//', $site_url, $matches);
$domain = $num_matches>0? $matches[0] : $site_url; // domain if found; the "slashed" site url otherwise
$css_path = str_replace($domain, '', $src); // relative paths only for local urls
$css_path = preg_replace('/^\//', '', $css_path); // strip front / if any
$css_path = preg_replace('/\?.*/i', '', $css_path); // throws away parameters, if any
if ( substr($css_path, 0, 4) != 'http' && substr($css_path, -4, 4) == '.css' ) {
// if css is local to server
if ( $this->debug )
echo 'Local css detected:'.$css_path."
\n";
$location = $css_path;
}
else {
// fetch css if necessary
$this->fetch_content($src, '.css');
$location = $this->cache_location . md5($src) . '.css';
}
return trailingslashit($wpm_options['wp_path']) . $location;
}
function build_minify_urls($locations) {
$minify_url = $this->c->get_plugin_url().'min/?f=';
$minify_url .= implode(',', $locations);
return $this->check_and_split_url($minify_url);
}
function extract_css($content) {
$wpm_options = get_option($this->name);
$css_locations = array();
preg_match_all('/]*?)>/i', $content, $link_tags_match);
foreach ($link_tags_match[0] as $link_tag) {
if ( strpos(strtolower($link_tag), 'stylesheet') ) {
// check CSS media type
if ( !strpos(strtolower($link_tag), 'media=' )
|| preg_match('/media=["\'](?:["\']|[^"\']*?(all|screen)[^"\']*?["\'])/', $link_tag )
) {
preg_match('/href=[\'"]([^\'"]+)/', $link_tag, $href_match);
if ( $href_match[1] ) {
// do not include anything in excluded list
$skip = false;
$exclusions = array_merge($this->default_exclude, $wpm_options['css_exclude']);
foreach ($exclusions as $exclude_pat) {
$exclude_pat = trim($exclude_pat);
if ( strlen($exclude_pat) > 0 && strpos($href_match[1], $exclude_pat) !== false ) {
$skip = true;
break;
}
}
if ( $skip ) continue;
$content = str_replace($link_tag . '', '', $content);
$content = str_replace($link_tag, '', $content);
$css_locations[] = $this->get_css_location($href_match[1]);
}
}
}
}
foreach ($wpm_options['css_include'] as $src) {
$css_locations[] = $this->get_css_location($src);
}
return array($content, $css_locations);
}
function inject_css($content, $css_locations) {
if ( count($css_locations) > 0 ) {
// build minify URLS
$css_tags = '';
$minify_urls = $this->build_minify_urls($css_locations);
foreach ($minify_urls as $minify_url) {
if ( $this->debug )
echo 'Minify URL:'.$minify_url;
$css_tags .= "";
}
// HTML5 has