Completed
Push — master ( 48ad5f...cbe884 )
by frank
02:18
created

autoptimize.php (11 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/*
3
Plugin Name: Autoptimize
4
Plugin URI: http://autoptimize.com/
5
Description: Optimizes your website, concatenating the CSS and JavaScript code, and compressing it.
6
Version: 2.2.2
7
Author: Frank Goossens (futtta)
8
Author URI: http://blog.futtta.be/
9
Domain Path: localization/
10
Text Domain: autoptimize
11
Released under the GNU General Public License (GPL)
12
http://www.gnu.org/licenses/gpl.txt
13
*/
14
15
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
16
17
define('AUTOPTIMIZE_PLUGIN_DIR',plugin_dir_path(__FILE__));
18
19
// Load config class
20
include(AUTOPTIMIZE_PLUGIN_DIR.'classes/autoptimizeConfig.php');
21
22
// Load toolbar class
23
include( AUTOPTIMIZE_PLUGIN_DIR.'classes/autoptimizeToolbar.php' );
24
25
// Load partners tab if admin
26
if (is_admin()) {
27
    include AUTOPTIMIZE_PLUGIN_DIR.'classlesses/autoptimizePartners.php';
28
}
29
30
// Do we gzip when caching (needed early to load autoptimizeCache.php)
31
define('AUTOPTIMIZE_CACHE_NOGZIP',(bool) get_option('autoptimize_cache_nogzip'));
32
33
// Load cache class
34
include(AUTOPTIMIZE_PLUGIN_DIR.'classes/autoptimizeCache.php');
35
36
// wp-content dir name (automagically set, should not be needed), dirname of AO cache dir and AO-prefix can be overridden in wp-config.php
37
if (!defined('AUTOPTIMIZE_WP_CONTENT_NAME')) { define('AUTOPTIMIZE_WP_CONTENT_NAME','/'.wp_basename( WP_CONTENT_DIR )); }
38
if (!defined('AUTOPTIMIZE_CACHE_CHILD_DIR')) { define('AUTOPTIMIZE_CACHE_CHILD_DIR','/cache/autoptimize/'); }
39
if (!defined('AUTOPTIMIZE_CACHEFILE_PREFIX')) { define('AUTOPTIMIZE_CACHEFILE_PREFIX', 'autoptimize_'); }
40
41
// Plugin dir constants (plugin url's defined later to accomodate domain mapped sites)
42 View Code Duplication
if (is_multisite() && apply_filters( 'autoptimize_separate_blog_caches' , true )) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
43
    $blog_id = get_current_blog_id();
44
    define('AUTOPTIMIZE_CACHE_DIR', WP_CONTENT_DIR.AUTOPTIMIZE_CACHE_CHILD_DIR.$blog_id.'/' );
45
} else {
46
    define('AUTOPTIMIZE_CACHE_DIR', WP_CONTENT_DIR.AUTOPTIMIZE_CACHE_CHILD_DIR);
47
}
48
define('AUTOPTIMIZE_CACHE_DELAY',true);
49
define('WP_ROOT_DIR',str_replace(AUTOPTIMIZE_WP_CONTENT_NAME,'',WP_CONTENT_DIR));
50
51
// Initialize the cache at least once
52
$conf = autoptimizeConfig::instance();
53
54
/* Check if we're updating, in which case we might need to do stuff and flush the cache
55
to avoid old versions of aggregated files lingering around */
56
57
$autoptimize_version="2.2.0";
58
$autoptimize_db_version=get_option('autoptimize_version','none');
59
60
if ($autoptimize_db_version !== $autoptimize_version) {
61
    if ($autoptimize_db_version==="none") {
62
        add_action('admin_notices', 'autoptimize_install_config_notice');
63
    } else {
64
        // updating, include the update-code
65
        include(AUTOPTIMIZE_PLUGIN_DIR.'classlesses/autoptimizeUpdateCode.php');
66
    }
67
68
    update_option('autoptimize_version',$autoptimize_version);
69
    $autoptimize_db_version=$autoptimize_version;
70
}
71
72
// Load translations
73
function autoptimize_load_plugin_textdomain() {
74
    load_plugin_textdomain('autoptimize',false,plugin_basename(dirname( __FILE__ )).'/localization');
75
}
76
add_action( 'init', 'autoptimize_load_plugin_textdomain' );
77
78
function autoptimize_uninstall(){
79
    autoptimizeCache::clearall();
80
81
    $delete_options=array("autoptimize_cache_clean", "autoptimize_cache_nogzip", "autoptimize_css", "autoptimize_css_datauris", "autoptimize_css_justhead", "autoptimize_css_defer", "autoptimize_css_defer_inline", "autoptimize_css_inline", "autoptimize_css_exclude", "autoptimize_html", "autoptimize_html_keepcomments", "autoptimize_js", "autoptimize_js_exclude", "autoptimize_js_forcehead", "autoptimize_js_justhead", "autoptimize_js_trycatch", "autoptimize_version", "autoptimize_show_adv", "autoptimize_cdn_url", "autoptimize_cachesize_notice","autoptimize_css_include_inline","autoptimize_js_include_inline","autoptimize_css_nogooglefont","autoptimize_optimize_logged","autoptimize_optimize_checkout");
82
83
    if ( !is_multisite() ) {
84
        foreach ($delete_options as $del_opt) { delete_option( $del_opt ); }
85
    } else {
86
        global $wpdb;
87
        $blog_ids = $wpdb->get_col( "SELECT blog_id FROM $wpdb->blogs" );
88
        $original_blog_id = get_current_blog_id();
89
        foreach ( $blog_ids as $blog_id ) {
90
            switch_to_blog( $blog_id );
91
            foreach ($delete_options as $del_opt) { delete_option( $del_opt ); }
92
        }
93
        switch_to_blog( $original_blog_id );
94
    }
95
96
    if ( wp_get_schedule( 'ao_cachechecker' ) ) {
97
        wp_clear_scheduled_hook( 'ao_cachechecker' );
98
    }
99
}
100
101
function autoptimize_install_config_notice() {
102
    echo '<div class="updated"><p>';
103
    _e('Thank you for installing and activating Autoptimize. Please configure it under "Settings" -> "Autoptimize" to start improving your site\'s performance.', 'autoptimize' );
104
    echo '</p></div>';
105
}
106
107
function autoptimize_update_config_notice() {
108
    echo '<div class="updated"><p>';
109
    _e('Autoptimize has just been updated. Please <strong>test your site now</strong> and adapt Autoptimize config if needed.', 'autoptimize' );
110
    echo '</p></div>';
111
}
112
113
function autoptimize_cache_unavailable_notice() {
114
    echo '<div class="error"><p>';
115
    printf( __( 'Autoptimize cannot write to the cache directory (%s), please fix to enable CSS/ JS optimization!', 'autoptimize' ), AUTOPTIMIZE_CACHE_DIR );
116
    echo '</p></div>';
117
}
118
119
// Set up the buffering
120
function autoptimize_start_buffering() {
121
    $ao_noptimize = false;
122
123
    // noptimize in qs to get non-optimized page for debugging
124
    if (array_key_exists("ao_noptimize",$_GET) || array_key_exists("ao_noptirocket",$_GET)) {
125
        if ( ( ($_GET["ao_noptimize"]==="1") || ($_GET["ao_noptirocket"]==="1") ) && (apply_filters('autoptimize_filter_honor_qs_noptimize',true)) ) {
126
            $ao_noptimize = true;
127
        }
128
    }
129
130
    // check for DONOTMINIFY constant as used by e.g. WooCommerce POS
131
    if (defined('DONOTMINIFY') && (constant('DONOTMINIFY')===true || constant('DONOTMINIFY')==="true")) {
132
        $ao_noptimize = true;
133
    }
134
135
	// if setting says not to optimize logged in user and user is logged in
136
	if ( get_option('autoptimize_optimize_logged','on') !== 'on' && is_user_logged_in() && current_user_can('edit_posts') ) {
137
		$ao_noptimize = true;
138
	}
139
140
	// if setting says not to optimize cart/ checkout
141
	if ( get_option('autoptimize_optimize_checkout','on') !== 'on' ) {
142
		// checking for woocommerce, easy digital downloads and wp ecommerce
143
		foreach ( array("is_checkout","is_cart","edd_is_checkout","wpsc_is_cart","wpsc_is_checkout") as $shopCond ) {
144
			if ( function_exists($shopCond) && $shopCond() ) {
145
				$ao_noptimize = true;
146
				break;
147
			}
148
		}
149
	}
150
151
    // filter you can use to block autoptimization on your own terms
152
    $ao_noptimize = (bool) apply_filters( 'autoptimize_filter_noptimize', $ao_noptimize );
153
154
    if (!is_feed() && !$ao_noptimize && !is_admin() && ( !function_exists('is_customize_preview') || !is_customize_preview() ) ) {
155
        // load speedupper conditionally (true by default?)
156
        if ( apply_filters('autoptimize_filter_speedupper', true) ) {
157
            include(AUTOPTIMIZE_PLUGIN_DIR.'classlesses/autoptimizeSpeedupper.php');
158
        }
159
160
        // Config element
161
        $conf = autoptimizeConfig::instance();
162
163
        // Load our base class
164
        include(AUTOPTIMIZE_PLUGIN_DIR.'classes/autoptimizeBase.php');
165
166
        // Load extra classes and set some vars
167
        if($conf->get('autoptimize_html')) {
168
            include(AUTOPTIMIZE_PLUGIN_DIR.'classes/autoptimizeHTML.php');
169
            // BUG: new minify-html does not support keeping HTML comments, skipping for now
170
            // if (defined('AUTOPTIMIZE_LEGACY_MINIFIERS')) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
64% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
171
                @include(AUTOPTIMIZE_PLUGIN_DIR.'classes/external/php/minify-html.php');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
172
            // } else {
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
173
            //    @include(AUTOPTIMIZE_PLUGIN_DIR.'classes/external/php/minify-2.1.7-html.php');
174
            // }
175
        }
176
177 View Code Duplication
        if($conf->get('autoptimize_js')) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
178
            include(AUTOPTIMIZE_PLUGIN_DIR.'classes/autoptimizeScripts.php');
179
            if (!class_exists('JSMin')) {
180
                if (defined('AUTOPTIMIZE_LEGACY_MINIFIERS')) {
181
                    @include(AUTOPTIMIZE_PLUGIN_DIR.'classes/external/php/jsmin-1.1.1.php');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
182
                } else {
183
                    @include(AUTOPTIMIZE_PLUGIN_DIR.'classes/external/php/minify-2.3.1-jsmin.php');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
184
                }
185
            }
186
            if ( ! defined( 'CONCATENATE_SCRIPTS' )) {
187
                define('CONCATENATE_SCRIPTS',false);
188
            }
189
            if ( ! defined( 'COMPRESS_SCRIPTS' )) {
190
                define('COMPRESS_SCRIPTS',false);
191
            }
192
        }
193
194 View Code Duplication
        if($conf->get('autoptimize_css')) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
195
            include(AUTOPTIMIZE_PLUGIN_DIR.'classes/autoptimizeStyles.php');
196
            if (defined('AUTOPTIMIZE_LEGACY_MINIFIERS')) {
197
                if (!class_exists('Minify_CSS_Compressor')) {
198
                    @include(AUTOPTIMIZE_PLUGIN_DIR.'classes/external/php/minify-css-compressor.php');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
199
                }
200
            } else {
201
                if (!class_exists('CSSmin')) {
202
                    @include(AUTOPTIMIZE_PLUGIN_DIR.'classes/external/php/yui-php-cssmin-2.4.8-4_fgo.php');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
203
                }
204
            }
205
            if ( ! defined( 'COMPRESS_CSS' )) {
206
                define('COMPRESS_CSS',false);
207
            }
208
        }
209
210
        // filter to be used with care, kills all output buffers when true. use with extreme caution. you have been warned!
211
        if (apply_filters('autoptimize_filter_obkiller',false)) {
212
            while (ob_get_level() > 0) {
213
                ob_end_clean();
214
            }
215
        }
216
        // Now, start the real thing!
217
        ob_start('autoptimize_end_buffering');
218
    }
219
}
220
221
// Action on end, this is where the magic happens
222
function autoptimize_end_buffering($content) {
223
    if ( ((stripos($content,"<html") === false) && (stripos($content,"<!DOCTYPE html") === false)) || preg_match('/<html[^>]*(?:amp|⚡)/',$content) === 1 || stripos($content,"<xsl:stylesheet") !== false ) { return $content; }
224
225
    // load URL constants as late as possible to allow domain mapper to kick in
226
    if (function_exists("domain_mapping_siteurl")) {
227
        define('AUTOPTIMIZE_WP_SITE_URL',domain_mapping_siteurl(get_current_blog_id()));
228
        define('AUTOPTIMIZE_WP_CONTENT_URL',str_replace(get_original_url(AUTOPTIMIZE_WP_SITE_URL),AUTOPTIMIZE_WP_SITE_URL,content_url()));
229
    } else {
230
        define('AUTOPTIMIZE_WP_SITE_URL',site_url());
231
        define('AUTOPTIMIZE_WP_CONTENT_URL',content_url());
232
    }
233
234 View Code Duplication
    if ( is_multisite() && apply_filters( 'autoptimize_separate_blog_caches' , true ) ) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
235
        $blog_id = get_current_blog_id();
236
        define('AUTOPTIMIZE_CACHE_URL',AUTOPTIMIZE_WP_CONTENT_URL.AUTOPTIMIZE_CACHE_CHILD_DIR.$blog_id.'/' );
237
    } else {
238
        define('AUTOPTIMIZE_CACHE_URL',AUTOPTIMIZE_WP_CONTENT_URL.AUTOPTIMIZE_CACHE_CHILD_DIR);
239
    }
240
    define('AUTOPTIMIZE_WP_ROOT_URL',str_replace(AUTOPTIMIZE_WP_CONTENT_NAME,'',AUTOPTIMIZE_WP_CONTENT_URL));
241
    define('AUTOPTIMIZE_HASH',wp_hash(AUTOPTIMIZE_CACHE_DIR));
242
243
    // Config element
244
    $conf = autoptimizeConfig::instance();
245
246
    // Choose the classes
247
    $classes = array();
248
    if($conf->get('autoptimize_js'))
249
        $classes[] = 'autoptimizeScripts';
250
    if($conf->get('autoptimize_css'))
251
        $classes[] = 'autoptimizeStyles';
252
    if($conf->get('autoptimize_html'))
253
        $classes[] = 'autoptimizeHTML';
254
255
    // Set some options
256
    $classoptions = array(
257
        'autoptimizeScripts' => array(
258
            'justhead' => $conf->get('autoptimize_js_justhead'),
259
            'forcehead' => $conf->get('autoptimize_js_forcehead'),
260
            'trycatch' => $conf->get('autoptimize_js_trycatch'),
261
            'js_exclude' => $conf->get('autoptimize_js_exclude'),
262
            'cdn_url' => $conf->get('autoptimize_cdn_url'),
263
            'include_inline' => $conf->get('autoptimize_js_include_inline')
264
        ),
265
        'autoptimizeStyles' => array(
266
            'justhead' => $conf->get('autoptimize_css_justhead'),
267
            'datauris' => $conf->get('autoptimize_css_datauris'),
268
            'defer' => $conf->get('autoptimize_css_defer'),
269
            'defer_inline' => $conf->get('autoptimize_css_defer_inline'),
270
            'inline' => $conf->get('autoptimize_css_inline'),
271
            'css_exclude' => $conf->get('autoptimize_css_exclude'),
272
            'cdn_url' => $conf->get('autoptimize_cdn_url'),
273
            'include_inline' => $conf->get('autoptimize_css_include_inline'),
274
            'nogooglefont' => $conf->get('autoptimize_css_nogooglefont')
275
        ),
276
        'autoptimizeHTML' => array(
277
            'keepcomments' => $conf->get('autoptimize_html_keepcomments')
278
        )
279
    );
280
281
    $content = apply_filters( 'autoptimize_filter_html_before_minify', $content );
282
283
    // Run the classes
284
    foreach($classes as $name) {
285
        $instance = new $name($content);
286
        if($instance->read($classoptions[$name])) {
287
            $instance->minify();
288
            $instance->cache();
289
            $content = $instance->getcontent();
290
        }
291
        unset($instance);
292
    }
293
    
294
    $content = apply_filters( 'autoptimize_html_after_minify', $content );
295
    return $content;
296
}
297
298
if ( autoptimizeCache::cacheavail() ) {
299
    $conf = autoptimizeConfig::instance();
300
    if( $conf->get('autoptimize_html') || $conf->get('autoptimize_js') || $conf->get('autoptimize_css') ) {
301
        // Hook to wordpress
302
        if (defined('AUTOPTIMIZE_INIT_EARLIER')) {
303
            add_action('init','autoptimize_start_buffering',-1);
304
        } else {
305
            if (!defined('AUTOPTIMIZE_HOOK_INTO')) { define('AUTOPTIMIZE_HOOK_INTO', 'template_redirect'); }
306
            add_action(constant("AUTOPTIMIZE_HOOK_INTO"),'autoptimize_start_buffering',2);
307
        }
308
    }
309
} else {
310
    add_action('admin_notices', 'autoptimize_cache_unavailable_notice');
311
}
312
313
function autoptimize_activate() {
314
    register_uninstall_hook( __FILE__, 'autoptimize_uninstall' );
315
}
316
register_activation_hook( __FILE__, 'autoptimize_activate' );
317
318
include_once('classlesses/autoptimizeCacheChecker.php');
319
320
// Do not pollute other plugins
321
unset($conf);
322