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