Completed
Push — master ( 821021...ec9c1e )
by frank
02:20
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: https://autoptimize.com/
5
Description: Optimizes your website, concatenating the CSS and JavaScript code, and compressing it.
6
Version: 2.3.2
7
Author: Frank Goossens (futtta)
8
Author URI: https://autoptimize.com/
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 (!defined('AUTOPTIMIZE_CACHE_DIR')) {
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
    if (is_multisite() && apply_filters( 'autoptimize_separate_blog_caches' , true )) {
44
        $blog_id = get_current_blog_id();
45
        define('AUTOPTIMIZE_CACHE_DIR', WP_CONTENT_DIR.AUTOPTIMIZE_CACHE_CHILD_DIR.$blog_id.'/' );
46
    } else {
47
        define('AUTOPTIMIZE_CACHE_DIR', WP_CONTENT_DIR.AUTOPTIMIZE_CACHE_CHILD_DIR );
48
    }
49
}
50
define('AUTOPTIMIZE_CACHE_DELAY',true);
51
define('WP_ROOT_DIR',substr(WP_CONTENT_DIR, 0, strlen(WP_CONTENT_DIR)-strlen(AUTOPTIMIZE_WP_CONTENT_NAME)));
52
53
// WP CLI
54
if ( defined( 'WP_CLI' ) && WP_CLI ) {
55
	require_once AUTOPTIMIZE_PLUGIN_DIR . 'classes/autoptimizeCLI.php';
56
}
57
58
// Initialize the cache at least once
59
$conf = autoptimizeConfig::instance();
60
61
/* Check if we're updating, in which case we might need to do stuff and flush the cache
62
to avoid old versions of aggregated files lingering around */
63
64
$autoptimize_version="2.3.0";
65
$autoptimize_db_version=get_option('autoptimize_version','none');
66
67
if ($autoptimize_db_version !== $autoptimize_version) {
68
    if ($autoptimize_db_version==="none") {
69
        add_action('admin_notices', 'autoptimize_install_config_notice');
70
    } else {
71
        // updating, include the update-code
72
        include(AUTOPTIMIZE_PLUGIN_DIR.'classlesses/autoptimizeUpdateCode.php');
73
    }
74
75
    update_option('autoptimize_version',$autoptimize_version);
76
    $autoptimize_db_version=$autoptimize_version;
77
}
78
79
// Load translations
80
function autoptimize_load_plugin_textdomain() {
81
    load_plugin_textdomain('autoptimize',false,plugin_basename(dirname( __FILE__ )).'/localization');
82
}
83
add_action( 'init', 'autoptimize_load_plugin_textdomain' );
84
85
function autoptimize_uninstall(){
86
    autoptimizeCache::clearall();
87
88
    $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_optimize_logged","autoptimize_optimize_checkout","autoptimize_extra_settings");
89
90
    if ( !is_multisite() ) {
91
        foreach ($delete_options as $del_opt) { delete_option( $del_opt ); }
92
    } else {
93
        global $wpdb;
94
        $blog_ids = $wpdb->get_col( "SELECT blog_id FROM $wpdb->blogs" );
95
        $original_blog_id = get_current_blog_id();
96
        foreach ( $blog_ids as $blog_id ) {
97
            switch_to_blog( $blog_id );
98
            foreach ($delete_options as $del_opt) { delete_option( $del_opt ); }
99
        }
100
        switch_to_blog( $original_blog_id );
101
    }
102
103
    if ( wp_get_schedule( 'ao_cachechecker' ) ) {
104
        wp_clear_scheduled_hook( 'ao_cachechecker' );
105
    }
106
}
107
108
function autoptimize_install_config_notice() {
109
    echo '<div class="updated"><p>';
110
    _e('Thank you for installing and activating Autoptimize. Please configure it under "Settings" -> "Autoptimize" to start improving your site\'s performance.', 'autoptimize' );
111
    echo '</p></div>';
112
}
113
114
function autoptimize_update_config_notice() {
115
    echo '<div class="updated"><p>';
116
    _e('Autoptimize has just been updated. Please <strong>test your site now</strong> and adapt Autoptimize config if needed.', 'autoptimize' );
117
    echo '</p></div>';
118
}
119
120
function autoptimize_cache_unavailable_notice() {
121
    echo '<div class="error"><p>';
122
    printf( __( 'Autoptimize cannot write to the cache directory (%s), please fix to enable CSS/ JS optimization!', 'autoptimize' ), AUTOPTIMIZE_CACHE_DIR );
123
    echo '</p></div>';
124
}
125
126
// Set up the buffering
127
function autoptimize_start_buffering() {
128
    $ao_noptimize = false;
129
130
    // noptimize in qs to get non-optimized page for debugging
131
    if (array_key_exists("ao_noptimize",$_GET) || array_key_exists("ao_noptirocket",$_GET)) {
132
        if ( ( ($_GET["ao_noptimize"]==="1") || ($_GET["ao_noptirocket"]==="1") ) && (apply_filters('autoptimize_filter_honor_qs_noptimize',true)) ) {
133
            $ao_noptimize = true;
134
        }
135
    }
136
137
    // check for DONOTMINIFY constant as used by e.g. WooCommerce POS
138
    if (defined('DONOTMINIFY') && (constant('DONOTMINIFY')===true || constant('DONOTMINIFY')==="true")) {
139
        $ao_noptimize = true;
140
    }
141
142
	// if setting says not to optimize logged in user and user is logged in
143
	if ( get_option('autoptimize_optimize_logged','on') !== 'on' && is_user_logged_in() && current_user_can('edit_posts') ) {
144
		$ao_noptimize = true;
145
	}
146
147
	// if setting says not to optimize cart/ checkout
148
	if ( get_option('autoptimize_optimize_checkout','on') !== 'on' ) {
149
		// checking for woocommerce, easy digital downloads and wp ecommerce
150
		foreach ( array("is_checkout","is_cart","edd_is_checkout","wpsc_is_cart","wpsc_is_checkout") as $shopCond ) {
151
			if ( function_exists($shopCond) && $shopCond() ) {
152
				$ao_noptimize = true;
153
				break;
154
			}
155
		}
156
	}
157
158
    // filter you can use to block autoptimization on your own terms
159
    $ao_noptimize = (bool) apply_filters( 'autoptimize_filter_noptimize', $ao_noptimize );
160
161
    if (!is_feed() && !$ao_noptimize && !is_admin() && ( !function_exists('is_customize_preview') || !is_customize_preview() ) ) {
162
        // load speedupper conditionally (true by default?)
163
        if ( apply_filters('autoptimize_filter_speedupper', true) ) {
164
            include(AUTOPTIMIZE_PLUGIN_DIR.'classlesses/autoptimizeSpeedupper.php');
165
        }
166
167
        // Config element
168
        $conf = autoptimizeConfig::instance();
169
170
        // Load our base class
171
        include(AUTOPTIMIZE_PLUGIN_DIR.'classes/autoptimizeBase.php');
172
173
        // Load extra classes and set some vars
174
        if($conf->get('autoptimize_html')) {
175
            include(AUTOPTIMIZE_PLUGIN_DIR.'classes/autoptimizeHTML.php');
176
            // BUG: new minify-html does not support keeping HTML comments, skipping for now
177
            // 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...
178
                @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...
179
            // } 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...
180
            //    @include(AUTOPTIMIZE_PLUGIN_DIR.'classes/external/php/minify-2.1.7-html.php');
181
            // }
182
        }
183
184 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...
185
            include(AUTOPTIMIZE_PLUGIN_DIR.'classes/autoptimizeScripts.php');
186
            if (!class_exists('JSMin')) {
187
                if (defined('AUTOPTIMIZE_LEGACY_MINIFIERS')) {
188
                    @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...
189
                } else {
190
                    @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...
191
                }
192
            }
193
            if ( ! defined( 'CONCATENATE_SCRIPTS' )) {
194
                define('CONCATENATE_SCRIPTS',false);
195
            }
196
            if ( ! defined( 'COMPRESS_SCRIPTS' )) {
197
                define('COMPRESS_SCRIPTS',false);
198
            }
199
        }
200
201 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...
202
            include(AUTOPTIMIZE_PLUGIN_DIR.'classes/autoptimizeStyles.php');
203
            if (defined('AUTOPTIMIZE_LEGACY_MINIFIERS')) {
204
                if (!class_exists('Minify_CSS_Compressor')) {
205
                    @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...
206
                }
207
            } else {
208
                if (!class_exists('CSSmin')) {
209
                    @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...
210
                }
211
            }
212
            if ( ! defined( 'COMPRESS_CSS' )) {
213
                define('COMPRESS_CSS',false);
214
            }
215
        }
216
217
        // filter to be used with care, kills all output buffers when true. use with extreme caution. you have been warned!
218
        if (apply_filters('autoptimize_filter_obkiller',false)) {
219
            while (ob_get_level() > 0) {
220
                ob_end_clean();
221
            }
222
        }
223
        // Now, start the real thing!
224
        ob_start('autoptimize_end_buffering');
225
    }
226
}
227
228
// Action on end, this is where the magic happens
229
function autoptimize_end_buffering($content) {
230
    if ( ((stripos($content,"<html") === false) && (stripos($content,"<!DOCTYPE html") === false)) || preg_match('/<html[^>]*(?:amp|⚡)/',$content) === 1 || stripos($content,"<xsl:stylesheet") !== false ) { return $content; }
231
232
    // load URL constants as late as possible to allow domain mapper to kick in
233
    if (function_exists("domain_mapping_siteurl")) {
234
        define('AUTOPTIMIZE_WP_SITE_URL',domain_mapping_siteurl(get_current_blog_id()));
235
        define('AUTOPTIMIZE_WP_CONTENT_URL',str_replace(get_original_url(AUTOPTIMIZE_WP_SITE_URL),AUTOPTIMIZE_WP_SITE_URL,content_url()));
236
    } else {
237
        define('AUTOPTIMIZE_WP_SITE_URL',site_url());
238
        define('AUTOPTIMIZE_WP_CONTENT_URL',content_url());
239
    }
240
241 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...
242
        $blog_id = get_current_blog_id();
243
        define('AUTOPTIMIZE_CACHE_URL',AUTOPTIMIZE_WP_CONTENT_URL.AUTOPTIMIZE_CACHE_CHILD_DIR.$blog_id.'/' );
244
    } else {
245
        define('AUTOPTIMIZE_CACHE_URL',AUTOPTIMIZE_WP_CONTENT_URL.AUTOPTIMIZE_CACHE_CHILD_DIR);
246
    }
247
    define('AUTOPTIMIZE_WP_ROOT_URL',str_replace(AUTOPTIMIZE_WP_CONTENT_NAME,'',AUTOPTIMIZE_WP_CONTENT_URL));
248
    define('AUTOPTIMIZE_HASH',wp_hash(AUTOPTIMIZE_CACHE_DIR));
249
250
    // Config element
251
    $conf = autoptimizeConfig::instance();
252
253
    // Choose the classes
254
    $classes = array();
255
    if($conf->get('autoptimize_js'))
256
        $classes[] = 'autoptimizeScripts';
257
    if($conf->get('autoptimize_css'))
258
        $classes[] = 'autoptimizeStyles';
259
    if($conf->get('autoptimize_html'))
260
        $classes[] = 'autoptimizeHTML';
261
262
    // Set some options
263
    $classoptions = array(
264
        'autoptimizeScripts' => array(
265
            'justhead' => $conf->get('autoptimize_js_justhead'),
266
            'forcehead' => $conf->get('autoptimize_js_forcehead'),
267
            'trycatch' => $conf->get('autoptimize_js_trycatch'),
268
            'js_exclude' => $conf->get('autoptimize_js_exclude'),
269
            'cdn_url' => $conf->get('autoptimize_cdn_url'),
270
            'include_inline' => $conf->get('autoptimize_js_include_inline')
271
        ),
272
        'autoptimizeStyles' => array(
273
            'justhead' => $conf->get('autoptimize_css_justhead'),
274
            'datauris' => $conf->get('autoptimize_css_datauris'),
275
            'defer' => $conf->get('autoptimize_css_defer'),
276
            'defer_inline' => $conf->get('autoptimize_css_defer_inline'),
277
            'inline' => $conf->get('autoptimize_css_inline'),
278
            'css_exclude' => $conf->get('autoptimize_css_exclude'),
279
            'cdn_url' => $conf->get('autoptimize_cdn_url'),
280
            'include_inline' => $conf->get('autoptimize_css_include_inline'),
281
            'nogooglefont' => $conf->get('autoptimize_css_nogooglefont')
282
        ),
283
        'autoptimizeHTML' => array(
284
            'keepcomments' => $conf->get('autoptimize_html_keepcomments')
285
        )
286
    );
287
288
    $content = apply_filters( 'autoptimize_filter_html_before_minify', $content );
289
290
    // Run the classes
291
    foreach($classes as $name) {
292
        $instance = new $name($content);
293
        if($instance->read($classoptions[$name])) {
294
            $instance->minify();
295
            $instance->cache();
296
            $content = $instance->getcontent();
297
        }
298
        unset($instance);
299
    }
300
    
301
    $content = apply_filters( 'autoptimize_html_after_minify', $content );
302
    return $content;
303
}
304
305
if ( autoptimizeCache::cacheavail() ) {
306
    $conf = autoptimizeConfig::instance();
307
    if( $conf->get('autoptimize_html') || $conf->get('autoptimize_js') || $conf->get('autoptimize_css') ) {
308
        // Hook to wordpress
309
        if (defined('AUTOPTIMIZE_INIT_EARLIER')) {
310
            add_action('init','autoptimize_start_buffering',-1);
311
        } else {
312
            if (!defined('AUTOPTIMIZE_HOOK_INTO')) { define('AUTOPTIMIZE_HOOK_INTO', 'template_redirect'); }
313
            add_action(constant("AUTOPTIMIZE_HOOK_INTO"),'autoptimize_start_buffering',2);
314
        }
315
    }
316
} else {
317
    add_action('admin_notices', 'autoptimize_cache_unavailable_notice');
318
}
319
320
function autoptimize_activate() {
321
    register_uninstall_hook( __FILE__, 'autoptimize_uninstall' );
322
}
323
register_activation_hook( __FILE__, 'autoptimize_activate' );
324
325
include_once('classlesses/autoptimizeCacheChecker.php');
326
327
add_action('plugins_loaded','includeAutoptimizeExtra');
328
function includeAutoptimizeExtra() {
329
    if ( apply_filters('autoptimize_filter_extra_activate',true) ) {
330
        include_once('classlesses/autoptimizeExtra.php');
331
    }
332
}
333
334
// Do not pollute other plugins
335
unset($conf);
336