Autoptimize - Version 2.0.2

Version Description

  • bugfix: disallow moving non-aggregated JS by default (can be re-enabled by passing false to the autoptimize_filter_js_unmovable)
  • bugfix: hook autoptimize_action_cachepurged into init to avoid ugly error-message for ZenCache (Comet Cache) users
  • bugfix to allow for Autoptimize to work with PHP 5.2, although you really should upgrade
Download this release

Release Info

Developer futtta
Plugin Icon 128x128 Autoptimize
Version 2.0.2
Comparing to
See all releases

Code changes from version 2.0.0 to 2.0.2

README.md CHANGED
@@ -47,7 +47,7 @@ add_filter('autoptimize_filter_js_defer','my_ao_override_defer',10,1);
47
  */
48
  function my_ao_override_defer($defer) {
49
  return $defer."async ";
50
- }
51
  ```
52
 
53
  ### Filter: autoptimize_filter_noptimize
@@ -216,3 +216,12 @@ function my_ao_css_defer_inline($inlined) {
216
  return $inlined."h2,h1{color:red !important;}";
217
  }
218
  ```
 
 
 
 
 
 
 
 
 
47
  */
48
  function my_ao_override_defer($defer) {
49
  return $defer."async ";
50
+ }
51
  ```
52
 
53
  ### Filter: autoptimize_filter_noptimize
216
  return $inlined."h2,h1{color:red !important;}";
217
  }
218
  ```
219
+
220
+ ### Filter: `autoptimize_separate_blog_caches`
221
+
222
+ ```php
223
+ add_filter('autoptimize_separate_blog_caches','__return_false',10,1);
224
+ /**
225
+ * Do not separate cache folders in multisite setup.
226
+ */
227
+ ```
autoptimize.php CHANGED
@@ -3,7 +3,7 @@
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.0.0
7
  Author: Frank Goossens (futtta)
8
  Author URI: http://blog.futtta.be/
9
  Domain Path: localization/
@@ -25,17 +25,17 @@ define('AUTOPTIMIZE_CACHE_NOGZIP',(bool) get_option('autoptimize_cache_nogzip'))
25
  // Load cache class
26
  include(AUTOPTIMIZE_PLUGIN_DIR.'/classes/autoptimizeCache.php');
27
 
28
- // wp-content dir, dirname of AO cache dir and AO-prefix can be overridden in wp-config.php
 
29
  if (!defined('AUTOPTIMIZE_CACHE_CHILD_DIR')) { define('AUTOPTIMIZE_CACHE_CHILD_DIR','/cache/autoptimize/'); }
30
- if (!defined('AUTOPTIMIZE_WP_CONTENT_NAME')) { define('AUTOPTIMIZE_WP_CONTENT_NAME','/wp-content'); }
31
  if (!defined('AUTOPTIMIZE_CACHEFILE_PREFIX')) { define('AUTOPTIMIZE_CACHEFILE_PREFIX', 'autoptimize_'); }
32
 
33
  // Plugin dir constants (plugin url's defined later to accomodate domain mapped sites)
34
- if (is_multisite()) {
35
  $blog_id = get_current_blog_id();
36
- define('AUTOPTIMIZE_CACHE_DIR' , WP_CONTENT_DIR.AUTOPTIMIZE_CACHE_CHILD_DIR.$blog_id.'/' );
37
  } else {
38
- define('AUTOPTIMIZE_CACHE_DIR',WP_CONTENT_DIR.AUTOPTIMIZE_CACHE_CHILD_DIR);
39
  }
40
  define('AUTOPTIMIZE_CACHE_DELAY',true);
41
  define('WP_ROOT_DIR',str_replace(AUTOPTIMIZE_WP_CONTENT_NAME,'',WP_CONTENT_DIR));
@@ -51,12 +51,12 @@ $autoptimize_db_version=get_option('autoptimize_version','none');
51
 
52
  if ($autoptimize_db_version !== $autoptimize_version) {
53
  if ($autoptimize_db_version==="none") {
54
- add_action('admin_notices', 'autoptimize_install_config_notice');
55
  } else {
56
  // updating, include the update-code
57
  include(AUTOPTIMIZE_PLUGIN_DIR.'/classlesses/autoptimizeUpdateCode.php');
58
  }
59
-
60
  update_option('autoptimize_version',$autoptimize_version);
61
  $autoptimize_db_version=$autoptimize_version;
62
  }
@@ -66,23 +66,23 @@ load_plugin_textdomain('autoptimize',false,plugin_basename(dirname( __FILE__ )).
66
 
67
  function autoptimize_uninstall(){
68
  autoptimizeCache::clearall();
69
-
70
  $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");
71
-
72
  if ( !is_multisite() ) {
73
  foreach ($delete_options as $del_opt) { delete_option( $del_opt ); }
74
  } else {
75
  global $wpdb;
76
  $blog_ids = $wpdb->get_col( "SELECT blog_id FROM $wpdb->blogs" );
77
  $original_blog_id = get_current_blog_id();
78
- foreach ( $blog_ids as $blog_id )
79
  {
80
  switch_to_blog( $blog_id );
81
  foreach ($delete_options as $del_opt) { delete_option( $del_opt ); }
82
  }
83
  switch_to_blog( $original_blog_id );
84
  }
85
-
86
  if ( wp_get_schedule( 'ao_cachechecker' ) ) {
87
  wp_clear_scheduled_hook( 'ao_cachechecker' );
88
  }
@@ -106,22 +106,22 @@ function autoptimize_cache_unavailable_notice() {
106
  echo '</p></div>';
107
  }
108
 
109
-
110
  // Set up the buffering
111
  function autoptimize_start_buffering() {
112
  $ao_noptimize = false;
113
 
114
  // noptimize in qs to get non-optimized page for debugging
115
  if (array_key_exists("ao_noptimize",$_GET)) {
116
- if ($_GET["ao_noptimize"]==="1") {
117
  $ao_noptimize = true;
118
  }
119
  }
120
 
121
  // check for DONOTMINIFY constant as used by e.g. WooCommerce POS
122
- if (defined('DONOTMINIFY') && (constant('DONOTMINIFY')===true || constant('DONOTMINIFY')==="true")) {
123
- $ao_noptimize = true;
124
- }
125
 
126
  // filter you can use to block autoptimization on your own terms
127
  $ao_noptimize = (bool) apply_filters( 'autoptimize_filter_noptimize', $ao_noptimize );
@@ -129,10 +129,10 @@ function autoptimize_start_buffering() {
129
  if (!is_feed() && !$ao_noptimize && !is_admin()) {
130
  // Config element
131
  $conf = autoptimizeConfig::instance();
132
-
133
  // Load our base class
134
  include(AUTOPTIMIZE_PLUGIN_DIR.'classes/autoptimizeBase.php');
135
-
136
  // Load extra classes and set some vars
137
  if($conf->get('autoptimize_html')) {
138
  include(AUTOPTIMIZE_PLUGIN_DIR.'classes/autoptimizeHTML.php');
@@ -143,7 +143,7 @@ function autoptimize_start_buffering() {
143
  // @include(AUTOPTIMIZE_PLUGIN_DIR.'classes/external/php/minify-2.1.7-html.php');
144
  // }
145
  }
146
-
147
  if($conf->get('autoptimize_js')) {
148
  include(AUTOPTIMIZE_PLUGIN_DIR.'classes/autoptimizeScripts.php');
149
  if (!class_exists('JSMin')) {
@@ -160,7 +160,7 @@ function autoptimize_start_buffering() {
160
  define('COMPRESS_SCRIPTS',false);
161
  }
162
  }
163
-
164
  if($conf->get('autoptimize_css')) {
165
  include(AUTOPTIMIZE_PLUGIN_DIR.'classes/autoptimizeStyles.php');
166
  if (defined('AUTOPTIMIZE_LEGACY_MINIFIERS')) {
@@ -176,7 +176,7 @@ function autoptimize_start_buffering() {
176
  define('COMPRESS_CSS',false);
177
  }
178
  }
179
-
180
  // Now, start the real thing!
181
  ob_start('autoptimize_end_buffering');
182
  }
@@ -184,7 +184,7 @@ function autoptimize_start_buffering() {
184
 
185
  // Action on end, this is where the magic happens
186
  function autoptimize_end_buffering($content) {
187
- if ( stripos($content,"<html") === false || stripos($content,"<xsl:stylesheet") !== false ) { return $content;}
188
 
189
  // load URL constants as late as possible to allow domain mapper to kick in
190
  if (function_exists("domain_mapping_siteurl")) {
@@ -194,10 +194,10 @@ function autoptimize_end_buffering($content) {
194
  define('AUTOPTIMIZE_WP_SITE_URL',site_url());
195
  define('AUTOPTIMIZE_WP_CONTENT_URL',content_url());
196
  }
197
-
198
- if ( is_multisite() ) {
199
- $blog_id = get_current_blog_id();
200
- define('AUTOPTIMIZE_CACHE_URL',AUTOPTIMIZE_WP_CONTENT_URL.AUTOPTIMIZE_CACHE_CHILD_DIR.$blog_id.'/' );
201
  } else {
202
  define('AUTOPTIMIZE_CACHE_URL',AUTOPTIMIZE_WP_CONTENT_URL.AUTOPTIMIZE_CACHE_CHILD_DIR);
203
  }
@@ -205,7 +205,7 @@ function autoptimize_end_buffering($content) {
205
 
206
  // Config element
207
  $conf = autoptimizeConfig::instance();
208
-
209
  // Choose the classes
210
  $classes = array();
211
  if($conf->get('autoptimize_js'))
@@ -214,7 +214,7 @@ function autoptimize_end_buffering($content) {
214
  $classes[] = 'autoptimizeStyles';
215
  if($conf->get('autoptimize_html'))
216
  $classes[] = 'autoptimizeHTML';
217
-
218
  // Set some options
219
  $classoptions = array(
220
  'autoptimizeScripts' => array(
@@ -240,8 +240,8 @@ function autoptimize_end_buffering($content) {
240
  'keepcomments' => $conf->get('autoptimize_html_keepcomments')
241
  )
242
  );
243
-
244
- $content = apply_filters( 'autoptimize_filter_html_before_minify', $content );
245
  // Run the classes
246
  foreach($classes as $name) {
247
  $instance = new $name($content);
@@ -257,53 +257,15 @@ function autoptimize_end_buffering($content) {
257
  return $content;
258
  }
259
 
260
- function autoptimize_flush_pagecache($nothing) {
261
- if(function_exists('wp_cache_clear_cache')) {
262
- if (is_multisite()) {
263
- $blog_id = get_current_blog_id();
264
- wp_cache_clear_cache($blog_id);
265
- } else {
266
- wp_cache_clear_cache();
267
- }
268
- } else if ( has_action('cachify_flush_cache') ) {
269
- do_action('cachify_flush_cache');
270
- } else if ( function_exists('w3tc_pgcache_flush') ) {
271
- w3tc_pgcache_flush(); // w3 total cache
272
- } else if ( function_exists('hyper_cache_invalidate') ) {
273
- hyper_cache_invalidate(); // hypercache
274
- } else if ( function_exists('wp_fast_cache_bulk_delete_all') ) {
275
- wp_fast_cache_bulk_delete_all(); // wp fast cache
276
- } else if (class_exists("WpFastestCache")) {
277
- $wpfc = new WpFastestCache(); // wp fastest cache
278
- $wpfc -> deleteCache();
279
- } else if ( class_exists("c_ws_plugin__qcache_purging_routines") ) {
280
- c_ws_plugin__qcache_purging_routines::purge_cache_dir(); // quick cache
281
- } else if ( class_exists("zencache")) {
282
- zencache::clear(); // zen cache
283
- } else if(file_exists(WP_CONTENT_DIR.'/wp-cache-config.php') && function_exists('prune_super_cache')){
284
- // fallback for WP-Super-Cache
285
- global $cache_path;
286
- if (is_multisite()) {
287
- $blog_id = get_current_blog_id();
288
- prune_super_cache( get_supercache_dir( $blog_id ), true );
289
- prune_super_cache( $cache_path . 'blogs/', true );
290
- } else {
291
- prune_super_cache($cache_path.'supercache/',true);
292
- prune_super_cache($cache_path,true);
293
- }
294
- }
295
- }
296
- add_action('ao_flush_pagecache','autoptimize_flush_pagecache',10,1);
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
  add_action('template_redirect','autoptimize_start_buffering',2);
306
- }
307
  }
308
  } else {
309
  add_action('admin_notices', 'autoptimize_cache_unavailable_notice');
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.0.2
7
  Author: Frank Goossens (futtta)
8
  Author URI: http://blog.futtta.be/
9
  Domain Path: localization/
25
  // Load cache class
26
  include(AUTOPTIMIZE_PLUGIN_DIR.'/classes/autoptimizeCache.php');
27
 
28
+ // 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
29
+ if (!defined('AUTOPTIMIZE_WP_CONTENT_NAME')) { define('AUTOPTIMIZE_WP_CONTENT_NAME','/'.wp_basename( WP_CONTENT_DIR )); }
30
  if (!defined('AUTOPTIMIZE_CACHE_CHILD_DIR')) { define('AUTOPTIMIZE_CACHE_CHILD_DIR','/cache/autoptimize/'); }
 
31
  if (!defined('AUTOPTIMIZE_CACHEFILE_PREFIX')) { define('AUTOPTIMIZE_CACHEFILE_PREFIX', 'autoptimize_'); }
32
 
33
  // Plugin dir constants (plugin url's defined later to accomodate domain mapped sites)
34
+ if (is_multisite() && apply_filters( 'autoptimize_separate_blog_caches' , true )) {
35
  $blog_id = get_current_blog_id();
36
+ define('AUTOPTIMIZE_CACHE_DIR', WP_CONTENT_DIR.AUTOPTIMIZE_CACHE_CHILD_DIR.$blog_id.'/' );
37
  } else {
38
+ define('AUTOPTIMIZE_CACHE_DIR', WP_CONTENT_DIR.AUTOPTIMIZE_CACHE_CHILD_DIR);
39
  }
40
  define('AUTOPTIMIZE_CACHE_DELAY',true);
41
  define('WP_ROOT_DIR',str_replace(AUTOPTIMIZE_WP_CONTENT_NAME,'',WP_CONTENT_DIR));
51
 
52
  if ($autoptimize_db_version !== $autoptimize_version) {
53
  if ($autoptimize_db_version==="none") {
54
+ add_action('admin_notices', 'autoptimize_install_config_notice');
55
  } else {
56
  // updating, include the update-code
57
  include(AUTOPTIMIZE_PLUGIN_DIR.'/classlesses/autoptimizeUpdateCode.php');
58
  }
59
+
60
  update_option('autoptimize_version',$autoptimize_version);
61
  $autoptimize_db_version=$autoptimize_version;
62
  }
66
 
67
  function autoptimize_uninstall(){
68
  autoptimizeCache::clearall();
69
+
70
  $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");
71
+
72
  if ( !is_multisite() ) {
73
  foreach ($delete_options as $del_opt) { delete_option( $del_opt ); }
74
  } else {
75
  global $wpdb;
76
  $blog_ids = $wpdb->get_col( "SELECT blog_id FROM $wpdb->blogs" );
77
  $original_blog_id = get_current_blog_id();
78
+ foreach ( $blog_ids as $blog_id )
79
  {
80
  switch_to_blog( $blog_id );
81
  foreach ($delete_options as $del_opt) { delete_option( $del_opt ); }
82
  }
83
  switch_to_blog( $original_blog_id );
84
  }
85
+
86
  if ( wp_get_schedule( 'ao_cachechecker' ) ) {
87
  wp_clear_scheduled_hook( 'ao_cachechecker' );
88
  }
106
  echo '</p></div>';
107
  }
108
 
109
+
110
  // Set up the buffering
111
  function autoptimize_start_buffering() {
112
  $ao_noptimize = false;
113
 
114
  // noptimize in qs to get non-optimized page for debugging
115
  if (array_key_exists("ao_noptimize",$_GET)) {
116
+ if ( ($_GET["ao_noptimize"]==="1") && (apply_filters('autoptimize_filter_honor_qs_noptimize',true)) ) {
117
  $ao_noptimize = true;
118
  }
119
  }
120
 
121
  // check for DONOTMINIFY constant as used by e.g. WooCommerce POS
122
+ if (defined('DONOTMINIFY') && (constant('DONOTMINIFY')===true || constant('DONOTMINIFY')==="true")) {
123
+ $ao_noptimize = true;
124
+ }
125
 
126
  // filter you can use to block autoptimization on your own terms
127
  $ao_noptimize = (bool) apply_filters( 'autoptimize_filter_noptimize', $ao_noptimize );
129
  if (!is_feed() && !$ao_noptimize && !is_admin()) {
130
  // Config element
131
  $conf = autoptimizeConfig::instance();
132
+
133
  // Load our base class
134
  include(AUTOPTIMIZE_PLUGIN_DIR.'classes/autoptimizeBase.php');
135
+
136
  // Load extra classes and set some vars
137
  if($conf->get('autoptimize_html')) {
138
  include(AUTOPTIMIZE_PLUGIN_DIR.'classes/autoptimizeHTML.php');
143
  // @include(AUTOPTIMIZE_PLUGIN_DIR.'classes/external/php/minify-2.1.7-html.php');
144
  // }
145
  }
146
+
147
  if($conf->get('autoptimize_js')) {
148
  include(AUTOPTIMIZE_PLUGIN_DIR.'classes/autoptimizeScripts.php');
149
  if (!class_exists('JSMin')) {
160
  define('COMPRESS_SCRIPTS',false);
161
  }
162
  }
163
+
164
  if($conf->get('autoptimize_css')) {
165
  include(AUTOPTIMIZE_PLUGIN_DIR.'classes/autoptimizeStyles.php');
166
  if (defined('AUTOPTIMIZE_LEGACY_MINIFIERS')) {
176
  define('COMPRESS_CSS',false);
177
  }
178
  }
179
+
180
  // Now, start the real thing!
181
  ob_start('autoptimize_end_buffering');
182
  }
184
 
185
  // Action on end, this is where the magic happens
186
  function autoptimize_end_buffering($content) {
187
+ if ( stripos($content,"<html") === false || stripos($content,"<html amp") !== false || stripos($content,"<html ⚡") !== false ||stripos($content,"<xsl:stylesheet") !== false ) { return $content;}
188
 
189
  // load URL constants as late as possible to allow domain mapper to kick in
190
  if (function_exists("domain_mapping_siteurl")) {
194
  define('AUTOPTIMIZE_WP_SITE_URL',site_url());
195
  define('AUTOPTIMIZE_WP_CONTENT_URL',content_url());
196
  }
197
+
198
+ if ( is_multisite() && apply_filters( 'autoptimize_separate_blog_caches' , true ) ) {
199
+ $blog_id = get_current_blog_id();
200
+ define('AUTOPTIMIZE_CACHE_URL',AUTOPTIMIZE_WP_CONTENT_URL.AUTOPTIMIZE_CACHE_CHILD_DIR.$blog_id.'/' );
201
  } else {
202
  define('AUTOPTIMIZE_CACHE_URL',AUTOPTIMIZE_WP_CONTENT_URL.AUTOPTIMIZE_CACHE_CHILD_DIR);
203
  }
205
 
206
  // Config element
207
  $conf = autoptimizeConfig::instance();
208
+
209
  // Choose the classes
210
  $classes = array();
211
  if($conf->get('autoptimize_js'))
214
  $classes[] = 'autoptimizeStyles';
215
  if($conf->get('autoptimize_html'))
216
  $classes[] = 'autoptimizeHTML';
217
+
218
  // Set some options
219
  $classoptions = array(
220
  'autoptimizeScripts' => array(
240
  'keepcomments' => $conf->get('autoptimize_html_keepcomments')
241
  )
242
  );
243
+
244
+ $content = apply_filters( 'autoptimize_filter_html_before_minify', $content );
245
  // Run the classes
246
  foreach($classes as $name) {
247
  $instance = new $name($content);
257
  return $content;
258
  }
259
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
260
  if ( autoptimizeCache::cacheavail() ) {
261
  $conf = autoptimizeConfig::instance();
262
  if( $conf->get('autoptimize_html') || $conf->get('autoptimize_js') || $conf->get('autoptimize_css') ) {
263
  // Hook to wordpress
264
+ if (defined('AUTOPTIMIZE_INIT_EARLIER')) {
265
+ add_action('init','autoptimize_start_buffering',-1);
266
+ } else {
267
  add_action('template_redirect','autoptimize_start_buffering',2);
268
+ }
269
  }
270
  } else {
271
  add_action('admin_notices', 'autoptimize_cache_unavailable_notice');
classes/autoptimizeBase.php CHANGED
@@ -76,7 +76,7 @@ abstract class autoptimizeBase {
76
  // try to remove "wp root url" from url while not minding http<>https
77
  $tmp_ao_root = preg_replace('/https?/','',AUTOPTIMIZE_WP_ROOT_URL);
78
  $tmp_url = preg_replace('/https?/','',$url);
79
- $path = str_replace($tmp_ao_root,'',$tmp_url);
80
 
81
  // final check; if path starts with :// or //, this is not a URL in the WP context and we have to assume we can't aggregate
82
  if (preg_match('#^:?//#',$path)) {
@@ -90,7 +90,18 @@ abstract class autoptimizeBase {
90
 
91
  // needed for WPML-filter
92
  protected function ao_getDomain($in) {
93
- return(parse_url($in,PHP_URL_HOST));
 
 
 
 
 
 
 
 
 
 
 
94
  }
95
 
96
 
@@ -100,9 +111,7 @@ abstract class autoptimizeBase {
100
  $logmsg="<!--noptimize--><!-- ".$logmsg." --><!--/noptimize-->";
101
  $this->content.=$logmsg;
102
  } else {
103
- $logfile=WP_CONTENT_DIR.'/ao_log.txt';
104
- $logmsg.="\n--\n";
105
- file_put_contents($logfile,$logmsg,FILE_APPEND);
106
  }
107
  }
108
 
@@ -205,10 +214,11 @@ abstract class autoptimizeBase {
205
  }
206
 
207
  protected function url_replace_cdn( $url ) {
208
- if ( ! empty( $this->cdn_url ) ) {
 
209
  // secondly prepend domain-less absolute URL's
210
  if ( ( substr( $url, 0, 1 ) === '/' ) && ( substr( $url, 1, 1 ) !== '/' ) ) {
211
- $url = rtrim( $this->cdn_url, '/' ) . $url;
212
  } else {
213
  // get wordpress base URL
214
  $WPSiteBreakdown = parse_url( AUTOPTIMIZE_WP_SITE_URL );
@@ -217,17 +227,17 @@ abstract class autoptimizeBase {
217
  $WPBaseUrl .= ":" . $WPSiteBreakdown['port'];
218
  }
219
  // three: replace full url's with scheme
220
- $tmp_url = str_replace( $WPBaseUrl, rtrim( $this->cdn_url, '/' ), $url );
221
  if ( $tmp_url === $url ) {
222
  // last attempt; replace scheme-less URL's
223
- $url = str_replace( preg_replace( '/https?:/', '', $WPBaseUrl ), rtrim( $this->cdn_url, '/' ), $url );
224
  } else {
225
  $url = $tmp_url;
226
  }
227
  }
228
  }
229
 
230
- // allow API filter to take care of CDN replacement
231
  $url = apply_filters( 'autoptimize_filter_base_replace_cdn', $url );
232
  return $url;
233
  }
@@ -260,44 +270,48 @@ abstract class autoptimizeBase {
260
  return false;
261
  }
262
 
263
- // inject already minified code in optimized JS/CSS
264
- protected function inject_minified($in) {
265
- if ( strpos( $in, '%%INJECTLATER%%' ) !== false ) {
266
- $out = preg_replace_callback(
267
- '#%%INJECTLATER%%(.*?)%%INJECTLATER%%#is',
268
- create_function(
269
- '$matches',
270
- '$filepath=base64_decode($matches[1]);
271
- $filecontent=file_get_contents($filepath);
272
-
273
- // remove comments and blank lines
274
- if (substr($filepath,-3,3)===".js") {
275
- $filecontent=preg_replace("#^\s*\/\/.*$#Um","",$filecontent);
276
- }
277
- $filecontent=preg_replace("#^\s*\/\*[^!].*\*\/\s?#Us","",$filecontent);
278
- $filecontent=preg_replace("#(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+#", "\n", $filecontent);
279
 
280
- // specific stuff for JS-files
281
- if (substr($filepath,-3,3)===".js") {
282
- if ((substr($filecontent,-1,1)!==";")&&(substr($filecontent,-1,1)!=="}")) {
283
- $filecontent.=";";
284
- }
285
-
286
- if (get_option("autoptimize_js_trycatch")==="on") {
287
- $filecontent="try{".$filecontent."}catch(e){}";
288
- }
289
- } else if ((substr($filepath,-4,4)===".css")) {
290
- $filecontent=autoptimizeStyles::fixurls($filepath,$filecontent);
291
- }
292
-
293
- // return
294
- return "\n".$filecontent;'
295
- ),
296
- $in
297
- );
298
- } else {
299
- $out = $in;
300
- }
301
- return $out;
 
 
 
 
 
 
 
 
 
302
  }
 
 
303
  }
76
  // try to remove "wp root url" from url while not minding http<>https
77
  $tmp_ao_root = preg_replace('/https?/','',AUTOPTIMIZE_WP_ROOT_URL);
78
  $tmp_url = preg_replace('/https?/','',$url);
79
+ $path = str_replace($tmp_ao_root,'',$tmp_url);
80
 
81
  // final check; if path starts with :// or //, this is not a URL in the WP context and we have to assume we can't aggregate
82
  if (preg_match('#^:?//#',$path)) {
90
 
91
  // needed for WPML-filter
92
  protected function ao_getDomain($in) {
93
+ // make sure the url starts with something vaguely resembling a protocol
94
+ if ((strpos($in,"http")!==0) && (strpos($in,"//")!==0)) {
95
+ $in="http://".$in;
96
+ }
97
+
98
+ // do the actual parse_url
99
+ $out = parse_url($in,PHP_URL_HOST);
100
+
101
+ // fallback if parse_url does not understand the url is in fact a url
102
+ if (empty($out)) $out=$in;
103
+
104
+ return $out;
105
  }
106
 
107
 
111
  $logmsg="<!--noptimize--><!-- ".$logmsg." --><!--/noptimize-->";
112
  $this->content.=$logmsg;
113
  } else {
114
+ error_log("Autoptimize: ".$logmsg);
 
 
115
  }
116
  }
117
 
214
  }
215
 
216
  protected function url_replace_cdn( $url ) {
217
+ $cdn_url = apply_filters( 'autoptimize_filter_base_cdnurl', $this->cdn_url );
218
+ if ( !empty($cdn_url) ) {
219
  // secondly prepend domain-less absolute URL's
220
  if ( ( substr( $url, 0, 1 ) === '/' ) && ( substr( $url, 1, 1 ) !== '/' ) ) {
221
+ $url = rtrim( $cdn_url, '/' ) . $url;
222
  } else {
223
  // get wordpress base URL
224
  $WPSiteBreakdown = parse_url( AUTOPTIMIZE_WP_SITE_URL );
227
  $WPBaseUrl .= ":" . $WPSiteBreakdown['port'];
228
  }
229
  // three: replace full url's with scheme
230
+ $tmp_url = str_replace( $WPBaseUrl, rtrim( $cdn_url, '/' ), $url );
231
  if ( $tmp_url === $url ) {
232
  // last attempt; replace scheme-less URL's
233
+ $url = str_replace( preg_replace( '/https?:/', '', $WPBaseUrl ), rtrim( $cdn_url, '/' ), $url );
234
  } else {
235
  $url = $tmp_url;
236
  }
237
  }
238
  }
239
 
240
+ // allow API filter to take alter after CDN replacement
241
  $url = apply_filters( 'autoptimize_filter_base_replace_cdn', $url );
242
  return $url;
243
  }
270
  return false;
271
  }
272
 
273
+ // inject already minified code in optimized JS/CSS
274
+ protected function inject_minified($in) {
275
+ if ( strpos( $in, '%%INJECTLATER%%' ) !== false ) {
276
+ $out = preg_replace_callback(
277
+ '#%%INJECTLATER%%(.*?)%%INJECTLATER%%#is',
278
+ create_function(
279
+ '$matches',
280
+ '$filepath=base64_decode(strtok($matches[1],"|"));
281
+ $filecontent=file_get_contents($filepath);
 
 
 
 
 
 
 
282
 
283
+ // remove BOM
284
+ $filecontent = preg_replace("#\x{EF}\x{BB}\x{BF}#","",$filecontent);
285
+
286
+ // remove comments and blank lines
287
+ if (substr($filepath,-3,3)===".js") {
288
+ $filecontent=preg_replace("#^\s*\/\/.*$#Um","",$filecontent);
289
+ }
290
+
291
+ $filecontent=preg_replace("#^\s*\/\*[^!].*\*\/\s?#Us","",$filecontent);
292
+ $filecontent=preg_replace("#(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+#", "\n", $filecontent);
293
+
294
+ // specific stuff for JS-files
295
+ if (substr($filepath,-3,3)===".js") {
296
+ if ((substr($filecontent,-1,1)!==";")&&(substr($filecontent,-1,1)!=="}")) {
297
+ $filecontent.=";";
298
+ }
299
+
300
+ if (get_option("autoptimize_js_trycatch")==="on") {
301
+ $filecontent="try{".$filecontent."}catch(e){}";
302
+ }
303
+ } else if ((substr($filepath,-4,4)===".css")) {
304
+ $filecontent=autoptimizeStyles::fixurls($filepath,$filecontent);
305
+ }
306
+
307
+ // return
308
+ return "\n".$filecontent;'
309
+ ),
310
+ $in
311
+ );
312
+ } else {
313
+ $out = $in;
314
  }
315
+ return $out;
316
+ }
317
  }
classes/autoptimizeCache.php CHANGED
@@ -61,6 +61,7 @@ class autoptimizeCache {
61
  }
62
 
63
  public function getname() {
 
64
  return $this->filename;
65
  }
66
 
@@ -86,50 +87,18 @@ class autoptimizeCache {
86
 
87
  @unlink(AUTOPTIMIZE_CACHE_DIR."/.htaccess");
88
  delete_transient("autoptimize_stats");
89
-
90
- // Do we need to clean any caching plugins cache-files?
91
- if(function_exists('wp_cache_clear_cache')) {
92
- if (is_multisite()) {
93
- $blog_id = get_current_blog_id();
94
- wp_cache_clear_cache($blog_id);
95
- } else {
96
- wp_cache_clear_cache();
97
- }
98
- } else if ( function_exists('w3tc_pgcache_flush') ) {
99
- w3tc_pgcache_flush(); // w3 total cache
100
- } else if ( function_exists('hyper_cache_invalidate') ) {
101
- hyper_cache_invalidate(); // hypercache
102
- } else if ( function_exists('wp_fast_cache_bulk_delete_all') ) {
103
- wp_fast_cache_bulk_delete_all(); // wp fast cache
104
- } else if (class_exists("WpFastestCache")) {
105
- $wpfc = new WpFastestCache(); // wp fastest cache
106
- $wpfc -> deleteCache();
107
- } else if ( class_exists("c_ws_plugin__qcache_purging_routines") ) {
108
- c_ws_plugin__qcache_purging_routines::purge_cache_dir(); // quick cache
109
- } else if ( class_exists("zencache") ) {
110
- zencache::clear(); // zen cache, tbc
111
- } else if(file_exists(WP_CONTENT_DIR.'/wp-cache-config.php') && function_exists('prune_super_cache')){
112
- // fallback for WP-Super-Cache
113
- global $cache_path;
114
- if (is_multisite()) {
115
- $blog_id = get_current_blog_id();
116
- prune_super_cache( get_supercache_dir( $blog_id ), true );
117
- prune_super_cache( $cache_path . 'blogs/', true );
118
- } else {
119
- prune_super_cache($cache_path.'supercache/',true);
120
- prune_super_cache($cache_path,true);
121
- }
122
- } else {
123
- // fallback; schedule event and try to clear there
124
- wp_schedule_single_event( time() + 1, 'ao_flush_pagecache' , array(time()));
125
- }
126
 
 
127
  if (!function_exists('autoptimize_do_cachepurged_action')) {
128
  function autoptimize_do_cachepurged_action() {
129
  do_action("autoptimize_action_cachepurged");
130
  }
131
  }
132
- add_action("after_setup_theme","autoptimize_do_cachepurged_action");
 
 
 
 
133
 
134
  return true;
135
  }
@@ -191,7 +160,7 @@ class autoptimizeCache {
191
  /** write index.html here to avoid prying eyes */
192
  $indexFile=AUTOPTIMIZE_CACHE_DIR.'/index.html';
193
  if(!is_file($indexFile)) {
194
- @file_put_contents($indexFile,'<html><body>Generated by <a href="http://wordpress.org/extend/plugins/autoptimize/">Autoptimize</a></body></html>');
195
  }
196
 
197
  /** write .htaccess here to overrule wp_super_cache */
@@ -283,7 +252,7 @@ class autoptimizeCache {
283
  // and write index.html here to avoid prying eyes
284
  $indexFile=$dir.'/index.html';
285
  if(!is_file($indexFile)) {
286
- @file_put_contents($indexFile,'<html><body>Generated by <a href="http://wordpress.org/extend/plugins/autoptimize/">Autoptimize</a></body></html>');
287
  }
288
 
289
  return true;
61
  }
62
 
63
  public function getname() {
64
+ apply_filters('autoptimize_filter_cache_getname',AUTOPTIMIZE_CACHE_URL.$this->filename);
65
  return $this->filename;
66
  }
67
 
87
 
88
  @unlink(AUTOPTIMIZE_CACHE_DIR."/.htaccess");
89
  delete_transient("autoptimize_stats");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
 
91
+ // add cachepurged action
92
  if (!function_exists('autoptimize_do_cachepurged_action')) {
93
  function autoptimize_do_cachepurged_action() {
94
  do_action("autoptimize_action_cachepurged");
95
  }
96
  }
97
+ add_action("init","autoptimize_do_cachepurged_action",11);
98
+
99
+ // try to purge caching plugins cache-files?
100
+ include_once(AUTOPTIMIZE_PLUGIN_DIR.'classlesses/autoptimizePageCacheFlush.php');
101
+ add_action("autoptimize_action_cachepurged","autoptimize_flush_pagecache",10,0);
102
 
103
  return true;
104
  }
160
  /** write index.html here to avoid prying eyes */
161
  $indexFile=AUTOPTIMIZE_CACHE_DIR.'/index.html';
162
  if(!is_file($indexFile)) {
163
+ @file_put_contents($indexFile,'<html><head><meta name="robots" content="noindex, nofollow"></head><body>Generated by <a href="http://wordpress.org/extend/plugins/autoptimize/" rel="nofollow">Autoptimize</a></body></html>');
164
  }
165
 
166
  /** write .htaccess here to overrule wp_super_cache */
252
  // and write index.html here to avoid prying eyes
253
  $indexFile=$dir.'/index.html';
254
  if(!is_file($indexFile)) {
255
+ @file_put_contents($indexFile,'<html><head><meta name="robots" content="noindex, nofollow"></head><body>Generated by <a href="http://wordpress.org/extend/plugins/autoptimize/" rel="nofollow">Autoptimize</a></body></html>');
256
  }
257
 
258
  return true;
classes/autoptimizeConfig.php CHANGED
@@ -4,7 +4,7 @@ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
4
  class autoptimizeConfig {
5
  private $config = null;
6
  static private $instance = null;
7
-
8
  //Singleton: private construct
9
  private function __construct() {
10
  if( is_admin() ) {
@@ -41,13 +41,20 @@ class autoptimizeConfig {
41
 
42
  public function show() {
43
  ?>
44
- <style>input[type=url]:invalid {color: red; border-color:red;} .form-table th{font-weight:100;} #futtta_feed ul{list-style:outside;} #futtta_feed {font-size:medium; margin:0px 20px;}</style>
45
 
46
  <div class="wrap">
47
 
48
  <h1><?php _e('Autoptimize Settings','autoptimize'); ?></h1>
49
 
 
 
 
 
50
  <div style="float:left;width:70%;">
 
 
 
51
  <?php
52
  if (get_option('autoptimize_show_adv','0')=='1') {
53
  ?>
@@ -75,7 +82,7 @@ if (get_option('autoptimize_show_adv','0')=='1') {
75
  <tr class="html_sub" valign="top">
76
  <th scope="row"><?php _e('Keep HTML comments?','autoptimize'); ?></th>
77
  <td><label for="autoptimize_html_keepcomments"><input type="checkbox" name="autoptimize_html_keepcomments" <?php echo get_option('autoptimize_html_keepcomments')?'checked="checked" ':''; ?>/>
78
- <?php _e('Enable this if you want HTML comments to remain in the page, needed for e.g. AdSense to function properly.','autoptimize'); ?></label></td>
79
  </tr>
80
  </table>
81
 
@@ -187,7 +194,7 @@ if (get_option('autoptimize_show_adv','0')=='1') {
187
  <td><?php
188
  $AOstatArr=autoptimizeCache::stats();
189
  $AOcacheSize=round($AOstatArr[1]/1024);
190
- echo $AOstatArr[0]." files, totalling ".$AOcacheSize." Kbytes (calculated at ".date("H:i e", $AOstatArr[2]).")";
191
  ?></td>
192
  </tr>
193
  <tr valign="top" class="hidden ao_adv">
@@ -208,21 +215,23 @@ if (get_option('autoptimize_show_adv','0')=='1') {
208
  <style>.autoptimize_banner ul li {font-size:medium;text-align:center;} .unslider-arrow {left:unset;}</style>
209
  <div class="autoptimize_banner">
210
  <ul>
211
- <?php
212
- $AO_banner=get_transient("autoptimize_banner");
213
- if (empty($AO_banner)) {
214
- $banner_resp = wp_remote_get("http://optimizingmatters.com/autoptimize_news.html");
215
- if (!is_wp_error($banner_resp)) {
216
- if (wp_remote_retrieve_response_code($banner_resp)=="200") {
217
- $AO_banner = wp_kses_post(wp_remote_retrieve_body($banner_resp));
218
- set_transient("autoptimize_banner",$AO_banner,DAY_IN_SECONDS);
219
- }
220
- }
221
- }
222
- echo $AO_banner;
223
- ?>
224
- <li><?php _e("Need help? <a href='https://wordpress.org/plugins/autoptimize/faq/'>Check out the FAQ</a> or post your question on <a href='http://wordpress.org/support/plugin/autoptimize'>the support-forum</a>."); ?></li>
225
- <li><?php _e("Happy with Autoptimize?","autoptimize"); ?><br /><a href="<?php echo network_admin_url(); ?>plugin-install.php?tab=search&type=author&s=futtta"><?php _e("Try my other plugins!"); ?></a></li>
 
 
226
  </ul>
227
  </div>
228
  <div style="float:right;width:30%" id="autoptimize_admin_feed">
@@ -475,28 +484,59 @@ if (get_option('autoptimize_show_adv','0')=='1') {
475
  }
476
 
477
  private function getFutttaFeeds($url) {
478
- $rss = fetch_feed( $url );
479
- $maxitems = 0;
480
-
481
- if ( ! is_wp_error( $rss ) ) {
482
- $maxitems = $rss->get_item_quantity( 7 );
483
- $rss_items = $rss->get_items( 0, $maxitems );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
484
  }
485
- ?>
486
- <ul>
487
- <?php if ( $maxitems == 0 ) : ?>
488
- <li><?php _e( 'No items', 'autoptimize' ); ?></li>
489
- <?php else : ?>
490
- <?php foreach ( $rss_items as $item ) : ?>
491
- <li>
492
- <a href="<?php echo esc_url( $item->get_permalink() ); ?>"
493
- title="<?php printf( __( 'Posted %s', 'autoptimize' ), $item->get_date('j F Y | g:i a') ); ?>">
494
- <?php echo esc_html( $item->get_title() ); ?>
495
- </a>
496
- </li>
497
- <?php endforeach; ?>
498
- <?php endif; ?>
499
- </ul>
500
- <?php
501
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
502
  }
4
  class autoptimizeConfig {
5
  private $config = null;
6
  static private $instance = null;
7
+
8
  //Singleton: private construct
9
  private function __construct() {
10
  if( is_admin() ) {
41
 
42
  public function show() {
43
  ?>
44
+ <style>input[type=url]:invalid {color: red; border-color:red;} .form-table th{font-weight:100;} #futtta_feed ul{list-style:outside;} #futtta_feed {font-size:medium; margin:0px 20px;} #ao_hide_adv,#ao_show_adv{float:right;margin-top:10px;margin-right:10px;}</style>
45
 
46
  <div class="wrap">
47
 
48
  <h1><?php _e('Autoptimize Settings','autoptimize'); ?></h1>
49
 
50
+ <?php if (version_compare(PHP_VERSION, '5.3.0') < 0) { ?>
51
+ <div class="notice-error notice"><?php _e('<p><strong>You are using a very old version of PHP</strong> (5.2.x or older) which has <a href="http://blog.futtta.be/2016/03/15/why-would-you-still-be-on-php-5-2/" target="_blank">serious security and performance issues</a>. Please ask your hoster to provide you with an upgrade path to 5.6 or 7.0</p>','autoptimize'); ?></div>
52
+ <?php } ?>
53
+
54
  <div style="float:left;width:70%;">
55
+
56
+ <?php echo $this->ao_admin_tabs(); ?>
57
+
58
  <?php
59
  if (get_option('autoptimize_show_adv','0')=='1') {
60
  ?>
82
  <tr class="html_sub" valign="top">
83
  <th scope="row"><?php _e('Keep HTML comments?','autoptimize'); ?></th>
84
  <td><label for="autoptimize_html_keepcomments"><input type="checkbox" name="autoptimize_html_keepcomments" <?php echo get_option('autoptimize_html_keepcomments')?'checked="checked" ':''; ?>/>
85
+ <?php _e('Enable this if you want HTML comments to remain in the page.','autoptimize'); ?></label></td>
86
  </tr>
87
  </table>
88
 
194
  <td><?php
195
  $AOstatArr=autoptimizeCache::stats();
196
  $AOcacheSize=round($AOstatArr[1]/1024);
197
+ echo $AOstatArr[0].__(' files, totalling ','autoptimize').$AOcacheSize.__(' Kbytes (calculated at ','autoptimize').date("H:i e", $AOstatArr[2]).')';
198
  ?></td>
199
  </tr>
200
  <tr valign="top" class="hidden ao_adv">
215
  <style>.autoptimize_banner ul li {font-size:medium;text-align:center;} .unslider-arrow {left:unset;}</style>
216
  <div class="autoptimize_banner">
217
  <ul>
218
+ <?php
219
+ if (apply_filters('autoptimize_settingsscreen_remotehttp',true)) {
220
+ $AO_banner=get_transient("autoptimize_banner");
221
+ if (empty($AO_banner)) {
222
+ $banner_resp = wp_remote_get("http://optimizingmatters.com/autoptimize_news.html");
223
+ if (!is_wp_error($banner_resp)) {
224
+ if (wp_remote_retrieve_response_code($banner_resp)=="200") {
225
+ $AO_banner = wp_kses_post(wp_remote_retrieve_body($banner_resp));
226
+ set_transient("autoptimize_banner",$AO_banner,DAY_IN_SECONDS);
227
+ }
228
+ }
229
+ }
230
+ echo $AO_banner;
231
+ }
232
+ ?>
233
+ <li><?php _e("Need help? <a href='https://wordpress.org/plugins/autoptimize/faq/'>Check out the FAQ</a> or post your question on <a href='http://wordpress.org/support/plugin/autoptimize'>the support-forum</a>.","autoptimize"); ?></li>
234
+ <li><?php _e("Happy with Autoptimize?","autoptimize"); ?><br /><a href="<?php echo network_admin_url(); ?>plugin-install.php?tab=search&type=author&s=optimizingmatters"><?php _e("Try my other plugins!","autoptimize"); ?></a></li>
235
  </ul>
236
  </div>
237
  <div style="float:right;width:30%" id="autoptimize_admin_feed">
484
  }
485
 
486
  private function getFutttaFeeds($url) {
487
+ if (apply_filters('autoptimize_settingsscreen_remotehttp',true)) {
488
+ $rss = fetch_feed( $url );
489
+ $maxitems = 0;
490
+
491
+ if ( ! is_wp_error( $rss ) ) {
492
+ $maxitems = $rss->get_item_quantity( 7 );
493
+ $rss_items = $rss->get_items( 0, $maxitems );
494
+ }
495
+ ?>
496
+ <ul>
497
+ <?php if ( $maxitems == 0 ) : ?>
498
+ <li><?php _e( 'No items', 'autoptimize' ); ?></li>
499
+ <?php else : ?>
500
+ <?php foreach ( $rss_items as $item ) : ?>
501
+ <li>
502
+ <a href="<?php echo esc_url( $item->get_permalink() ); ?>"
503
+ title="<?php printf( __( 'Posted %s', 'autoptimize' ), $item->get_date('j F Y | g:i a') ); ?>">
504
+ <?php echo esc_html( $item->get_title() ); ?>
505
+ </a>
506
+ </li>
507
+ <?php endforeach; ?>
508
+ <?php endif; ?>
509
+ </ul>
510
+ <?php
511
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
512
  }
513
+
514
+ // based on http://wordpress.stackexchange.com/a/58826
515
+ static function ao_admin_tabs(){
516
+ $tabs = apply_filters('autoptimize_filter_settingsscreen_tabs',array('autoptimize' => __('Main','autoptimize')));
517
+ $tabContent="";
518
+
519
+ if (count($tabs)>1) {
520
+ if(isset($_GET['page'])){
521
+ $currentId = $_GET['page'];
522
+ } else {
523
+ $currentId = "autoptimize";
524
+ }
525
+
526
+ $tabContent .= "<h2 class=\"nav-tab-wrapper\">";
527
+ foreach($tabs as $tabId => $tabName){
528
+ if($currentId == $tabId){
529
+ $class = " nav-tab-active";
530
+ } else{
531
+ $class = "";
532
+ }
533
+ $tabContent .= '<a class="nav-tab'.$class.'" href="?page='.$tabId.'">'.$tabName.'</a>';
534
+ }
535
+ $tabContent .= "</h2>";
536
+ } else {
537
+ $tabContent = "<hr/>";
538
+ }
539
+
540
+ return $tabContent;
541
+ }
542
  }
classes/autoptimizeScripts.php CHANGED
@@ -3,7 +3,7 @@ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
3
 
4
  class autoptimizeScripts extends autoptimizeBase {
5
  private $scripts = array();
6
- private $dontmove = array('document.write','html5.js','show_ads.js','google_ad','blogcatalog.com/w','tweetmeme.com/i','mybloglog.com/','histats.com/js','ads.smowtion.com/ad.js','statcounter.com/counter/counter.js','widgets.amung.us','ws.amazon.com/widgets','media.fastclick.net','/ads/','comment-form-quicktags/quicktags.php','edToolbar','intensedebate.com','scripts.chitika.net/','_gaq.push','jotform.com/','admin-bar.min.js','GoogleAnalyticsObject','plupload.full.min.js','syntaxhighlighter','adsbygoogle','gist.github.com','_stq','nonce','post_id');
7
  private $domove = array('gaJsHost','load_cmc','jd.gallery.transitions.js','swfobject.embedSWF(','tiny_mce.js','tinyMCEPreInit.go');
8
  private $domovelast = array('addthis.com','/afsonline/show_afs_search.js','disqus.js','networkedblogs.com/getnetworkwidget','infolinks.com/js/','jd.gallery.js.php','jd.gallery.transitions.js','swfobject.embedSWF(','linkwithin.com/widget.js','tiny_mce.js','tinyMCEPreInit.go');
9
  private $trycatch = false;
@@ -74,6 +74,7 @@ class autoptimizeScripts extends autoptimizeBase {
74
  } else {
75
  $this->forcehead = false;
76
  }
 
77
 
78
  // get cdn url
79
  $this->cdn_url = $options['cdn_url'];
@@ -90,8 +91,8 @@ class autoptimizeScripts extends autoptimizeBase {
90
  //Get script files
91
  if(preg_match_all('#<script.*</script>#Usmi',$this->content,$matches)) {
92
  foreach($matches[0] as $tag) {
93
- // only consider aggregation if no js type is specified or if type is text/javascript
94
- if((strpos($tag,"type=")!==strpos($tag,"type=\"text/javascript\""))&&(strpos($tag,"type=")!==strpos($tag,"type='text/javascript'"))){
95
  $tag='';
96
  continue;
97
  }
@@ -211,7 +212,7 @@ class autoptimizeScripts extends autoptimizeBase {
211
  $scriptsrc=$tmpscriptsrc;
212
  $this->alreadyminified=true;
213
  } else if ((strpos($script,"min.js")!==false) && ($this->inject_min_late===true)) {
214
- $scriptsrc="%%INJECTLATER%%".base64_encode($script)."%%INJECTLATER%%";
215
  }
216
  $this->jscode .= "\n".$scriptsrc;
217
  }/*else{
@@ -345,7 +346,10 @@ class autoptimizeScripts extends autoptimizeBase {
345
 
346
  //Checks agains the blacklist
347
  private function ismovable($tag) {
348
- return false;
 
 
 
349
  foreach($this->domove as $match) {
350
  if(strpos($tag,$match)!==false) {
351
  //Matched something
@@ -379,4 +383,29 @@ class autoptimizeScripts extends autoptimizeBase {
379
  //Should be in 'first'
380
  return false;
381
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
382
  }
3
 
4
  class autoptimizeScripts extends autoptimizeBase {
5
  private $scripts = array();
6
+ private $dontmove = array('document.write','html5.js','show_ads.js','google_ad','blogcatalog.com/w','tweetmeme.com/i','mybloglog.com/','histats.com/js','ads.smowtion.com/ad.js','statcounter.com/counter/counter.js','widgets.amung.us','ws.amazon.com/widgets','media.fastclick.net','/ads/','comment-form-quicktags/quicktags.php','edToolbar','intensedebate.com','scripts.chitika.net/','_gaq.push','jotform.com/','admin-bar.min.js','GoogleAnalyticsObject','plupload.full.min.js','syntaxhighlighter','adsbygoogle','gist.github.com','_stq','nonce','post_id','data-noptimize');
7
  private $domove = array('gaJsHost','load_cmc','jd.gallery.transitions.js','swfobject.embedSWF(','tiny_mce.js','tinyMCEPreInit.go');
8
  private $domovelast = array('addthis.com','/afsonline/show_afs_search.js','disqus.js','networkedblogs.com/getnetworkwidget','infolinks.com/js/','jd.gallery.js.php','jd.gallery.transitions.js','swfobject.embedSWF(','linkwithin.com/widget.js','tiny_mce.js','tinyMCEPreInit.go');
9
  private $trycatch = false;
74
  } else {
75
  $this->forcehead = false;
76
  }
77
+ $this->forcehead = apply_filters( 'autoptimize_filter_js_forcehead', $this->forcehead );
78
 
79
  // get cdn url
80
  $this->cdn_url = $options['cdn_url'];
91
  //Get script files
92
  if(preg_match_all('#<script.*</script>#Usmi',$this->content,$matches)) {
93
  foreach($matches[0] as $tag) {
94
+ // only consider aggregation whitelisted in should_aggregate-function
95
+ if( !$this->should_aggregate($tag) ) {
96
  $tag='';
97
  continue;
98
  }
212
  $scriptsrc=$tmpscriptsrc;
213
  $this->alreadyminified=true;
214
  } else if ((strpos($script,"min.js")!==false) && ($this->inject_min_late===true)) {
215
+ $scriptsrc="%%INJECTLATER%%".base64_encode($script)."|".md5($scriptsrc)."%%INJECTLATER%%";
216
  }
217
  $this->jscode .= "\n".$scriptsrc;
218
  }/*else{
346
 
347
  //Checks agains the blacklist
348
  private function ismovable($tag) {
349
+ if ($this->include_inline !== true || apply_filters('autoptimize_filter_js_unmovable',true)) {
350
+ return false;
351
+ }
352
+
353
  foreach($this->domove as $match) {
354
  if(strpos($tag,$match)!==false) {
355
  //Matched something
383
  //Should be in 'first'
384
  return false;
385
  }
386
+ /**
387
+ * Determines wheter a <script> $tag should be aggregated or not.
388
+ *
389
+ * We consider these as "aggregation-safe" currently:
390
+ * - script tags without a `type` attribute
391
+ * - script tags with an explicit `type` of `text/javascript`, 'text/ecmascript',
392
+ * 'application/javascript' or 'application/ecmascript'
393
+ *
394
+ * Everything else should return false.
395
+ *
396
+ * @param string $tag
397
+ * @return bool
398
+ *
399
+ * original function by https://github.com/zytzagoo/ on his AO fork, thanks Tomas!
400
+ */
401
+ public function should_aggregate($tag) {
402
+ preg_match('#<(script[^>]*)>#i',$tag,$scripttag);
403
+ if ( strpos($scripttag[1], 'type=')===false ) {
404
+ return true;
405
+ } else if ( preg_match('/type=["\']?(?:text|application)\/(?:javascript|ecmascript)["\']?/i', $scripttag[1]) ) {
406
+ return true;
407
+ } else {
408
+ return false;
409
+ }
410
+ }
411
  }
classes/autoptimizeStyles.php CHANGED
@@ -188,9 +188,8 @@ class autoptimizeStyles extends autoptimizeBase {
188
  if (has_filter('autoptimize_css_individual_style') && !empty($tmpstyle)) {
189
  $css=$tmpstyle;
190
  $this->alreadyminified=true;
191
- } else if ((strpos($cssPath,"min.css")!==false) && (strpos($css,"@import")===false) && ($this->inject_min_late===true)) {
192
- // only if filter is true?
193
- $css="%%INJECTLATER%%".base64_encode($cssPath)."%%INJECTLATER%%";
194
  }
195
  } else {
196
  // Couldn't read CSS. Maybe getpath isn't working?
@@ -248,8 +247,8 @@ class autoptimizeStyles extends autoptimizeBase {
248
  if ( has_filter('autoptimize_css_individual_style') && !empty($tmpstyle)) {
249
  $code=$tmpstyle;
250
  $this->alreadyminified=true;
251
- } else if ((strpos($path,"min.css")!==false) && (strpos($css,"@import")===false) && ($this->inject_min_late===true)) {
252
- $code="%%INJECTLATER%%".base64_encode($path)."%%INJECTLATER%%";
253
  }
254
 
255
  if(!empty($code)) {
@@ -392,11 +391,9 @@ class autoptimizeStyles extends autoptimizeBase {
392
  }
393
 
394
  // CDN the fonts!
395
- if ((!empty($this->cdn_url))&&apply_filters("autoptimize_filter_css_fonts_cdn",false)) {
396
  $fontreplace = array();
397
- $fonturl_regex = <<<LOD
398
- ~(?(DEFINE)(?<quoted_content>(["']) (?>[^"'\\]++ | \\{2} | \\. | (?!\g{-1})["'] )*+ \g{-1})(?<comment> /\* .*? \*/ ) (?<url_skip>(?: data: ) [^"'\s)}]*+ ) (?<other_content>(?> [^u}/"']++ | \g<quoted_content> | \g<comment> | \Bu | u(?!rl\s*+\() | /(?!\*) | \g<url_start> \g<url_skip> ["']?+ )++ ) (?<anchor> \G(?<!^) ["']?+ | @font-face \s*+ { ) (?<url_start> url\( \s*+ ["']?+ ) ) \g<comment> (*SKIP)(*FAIL) | \g<anchor> \g<other_content>?+ \g<url_start> \K ((?:(?:https?:)?(?://[[:alnum:]\-\.]+)(?::[0-9]+)?)?\/[^"'\s)}]*+) ~xs
399
- LOD;
400
 
401
  preg_match_all($fonturl_regex,$code,$matches);
402
  if (is_array($matches)) {
@@ -514,7 +511,7 @@ LOD;
514
  }
515
  } else {
516
  if ($this->defer == true) {
517
- $deferredCssBlock = "<script>function lCss(url,media) {var d=document;var l=d.createElement('link');l.rel='stylesheet';l.type='text/css';l.href=url;l.media=media;aoin=d.getElementsByTagName('noscript')[0];aoin.parentNode.insertBefore(l,aoin.nextSibling);}function deferredCSS() {";
518
  $noScriptCssBlock = "<noscript>";
519
  $defer_inline_code=$this->defer_inline;
520
  $defer_inline_code=apply_filters( 'autoptimize_filter_css_defer_inline', $defer_inline_code );
@@ -539,7 +536,7 @@ LOD;
539
  unset($tmp_code);
540
  }
541
  }
542
- $code_out='<style type="text/css" media="all">'.$defer_inline_code.'</style>';
543
  $this->inject_in_html($code_out,$replaceTag);
544
  }
545
  }
@@ -637,4 +634,23 @@ LOD;
637
  return true;
638
  }
639
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
640
  }
188
  if (has_filter('autoptimize_css_individual_style') && !empty($tmpstyle)) {
189
  $css=$tmpstyle;
190
  $this->alreadyminified=true;
191
+ } else if ($this->can_inject_late($cssPath,$css)) {
192
+ $css="%%INJECTLATER%%".base64_encode($cssPath)."|".md5($css)."%%INJECTLATER%%";
 
193
  }
194
  } else {
195
  // Couldn't read CSS. Maybe getpath isn't working?
247
  if ( has_filter('autoptimize_css_individual_style') && !empty($tmpstyle)) {
248
  $code=$tmpstyle;
249
  $this->alreadyminified=true;
250
+ } else if ($this->can_inject_late($path,$code)) {
251
+ $code="%%INJECTLATER%%".base64_encode($path)."|".md5($code)."%%INJECTLATER%%";
252
  }
253
 
254
  if(!empty($code)) {
391
  }
392
 
393
  // CDN the fonts!
394
+ if ( (!empty($this->cdn_url)) && (apply_filters('autoptimize_filter_css_fonts_cdn',false)) && (version_compare(PHP_VERSION, '5.3.0') >= 0) ) {
395
  $fontreplace = array();
396
+ include_once(AUTOPTIMIZE_PLUGIN_DIR.'classlesses/autoptimizeFontRegex.php');
 
 
397
 
398
  preg_match_all($fonturl_regex,$code,$matches);
399
  if (is_array($matches)) {
511
  }
512
  } else {
513
  if ($this->defer == true) {
514
+ $deferredCssBlock = "<script data-cfasync='false'>function lCss(url,media) {var d=document;var l=d.createElement('link');l.rel='stylesheet';l.type='text/css';l.href=url;l.media=media;aoin=d.getElementsByTagName('noscript')[0];aoin.parentNode.insertBefore(l,aoin.nextSibling);}function deferredCSS() {";
515
  $noScriptCssBlock = "<noscript>";
516
  $defer_inline_code=$this->defer_inline;
517
  $defer_inline_code=apply_filters( 'autoptimize_filter_css_defer_inline', $defer_inline_code );
536
  unset($tmp_code);
537
  }
538
  }
539
+ $code_out='<style type="text/css" id="aoatfcss" media="all">'.$defer_inline_code.'</style>';
540
  $this->inject_in_html($code_out,$replaceTag);
541
  }
542
  }
634
  return true;
635
  }
636
  }
637
+
638
+ private function can_inject_late($cssPath,$css) {
639
+ if ((strpos($cssPath,"min.css")===false) || ($this->inject_min_late!==true)) {
640
+ // late-inject turned off or file not minified based on filename
641
+ return false;
642
+ } else if (strpos($css,"@import")!==false) {
643
+ // can't late-inject files with imports as those need to be aggregated
644
+ return false;
645
+ } else if ( (strpos($css,"@font-face")!==false ) && ( apply_filters("autoptimize_filter_css_fonts_cdn",false)===true) && (!empty($this->cdn_url)) ) {
646
+ // don't late-inject CSS with font-src's if fonts are set to be CDN'ed
647
+ return false;
648
+ } else if ( (($this->datauris == true) || (!empty($this->cdn_url))) && preg_match("#background[^;}]*url\(#Ui",$css) ) {
649
+ // don't late-inject CSS with images if CDN is set OR is image inlining is on
650
+ return false;
651
+ } else {
652
+ // phew, all is safe, we can late-inject
653
+ return true;
654
+ }
655
+ }
656
  }
classes/external/index.html CHANGED
@@ -1 +1 @@
1
- <html><body><p>Generated by <a href="http://wordpress.org/extend/plugins/autoptimize/">Autoptimize</a>, a WordPress plugin that speeds up your website and helps you save bandwidth by aggregating and minimizing JS and CSS.</p><p>Up to date info on Autoptimize <a href="http://blog.futtta.be/category/autoptimize/" title="more about atoptimize on my blog">can be found on blog.futtta.be</a>, where you can also find <a href="http://blog.futtta.be/category/wordpress" title="blog.futtta.be about WordPress">posts about WordPress</a> and <a href="http://blog.futtta.be/category/internet/" title="about browsers, development and mobile web on blog.futtta.be">Web Technology in general</a>.</p></body></html>
1
+ <html><head><meta name="robots" content="noindex, nofollow"></head><body>Generated by <a href="http://wordpress.org/extend/plugins/autoptimize/" rel="nofollow">Autoptimize</a></body></html>
classes/external/js/index.html CHANGED
@@ -1 +1 @@
1
- <html><body><p>Generated by <a href="http://wordpress.org/extend/plugins/autoptimize/">Autoptimize</a>, a WordPress plugin that speeds up your website and helps you save bandwidth by aggregating and minimizing JS and CSS.</p><p>Up to date info on Autoptimize <a href="http://blog.futtta.be/category/autoptimize/" title="more about atoptimize on my blog">can be found on blog.futtta.be</a>, where you can also find <a href="http://blog.futtta.be/category/wordpress" title="blog.futtta.be about WordPress">posts about WordPress</a> and <a href="http://blog.futtta.be/category/internet/" title="about browsers, development and mobile web on blog.futtta.be">Web Technology in general</a>.</p></body></html>
1
+ <html><head><meta name="robots" content="noindex, nofollow"></head><body>Generated by <a href="http://wordpress.org/extend/plugins/autoptimize/" rel="nofollow">Autoptimize</a></body></html>
classes/external/php/index.html CHANGED
@@ -1 +1 @@
1
- <html><body><p>Generated by <a href="http://wordpress.org/extend/plugins/autoptimize/">Autoptimize</a>, a WordPress plugin that speeds up your website and helps you save bandwidth by aggregating and minimizing JS and CSS.</p><p>Up to date info on Autoptimize <a href="http://blog.futtta.be/category/autoptimize/" title="more about atoptimize on my blog">can be found on blog.futtta.be</a>, where you can also find <a href="http://blog.futtta.be/category/wordpress" title="blog.futtta.be about WordPress">posts about WordPress</a> and <a href="http://blog.futtta.be/category/internet/" title="about browsers, development and mobile web on blog.futtta.be">Web Technology in general</a>.</p></body></html>
1
+ <html><head><meta name="robots" content="noindex, nofollow"></head><body>Generated by <a href="http://wordpress.org/extend/plugins/autoptimize/" rel="nofollow">Autoptimize</a></body></html>
classes/external/php/yui-php-cssmin-2.4.8-4_fgo.php CHANGED
@@ -265,7 +265,7 @@ class CSSmin
265
  $css = preg_replace('/\s+/', ' ', $css);
266
 
267
  // preserve flex, keeping percentage even if 0
268
- $css = preg_replace_callback('/flex\s?:\s?([0-9 %]*(?:auto)?)/i',array($this, 'replace_flex'),$css);
269
 
270
  // Fix IE7 issue on matrix filters which browser accept whitespaces between Matrix parameters
271
  $css = preg_replace_callback('/\s*filter\:\s*progid:DXImageTransform\.Microsoft\.Matrix\(([^\)]+)\)/', array($this, 'preserve_old_IE_specific_matrix_definition'), $css);
@@ -469,7 +469,7 @@ class CSSmin
469
 
470
  if ($found_terminator) {
471
  $token = $this->str_slice($css, $start_index, $end_index);
472
- if (strpos($token,"<svg")===false) {
473
  $token = preg_replace('/\s+/', '', $token);
474
  }
475
  $this->preserved_tokens[] = $token;
265
  $css = preg_replace('/\s+/', ' ', $css);
266
 
267
  // preserve flex, keeping percentage even if 0
268
+ $css = preg_replace_callback('/flex\s?:\s?((?:[0-9 ]*)\s?(?:px|em|auto|%)?(?:calc\(.*\))?)/i',array($this, 'replace_flex'),$css);
269
 
270
  // Fix IE7 issue on matrix filters which browser accept whitespaces between Matrix parameters
271
  $css = preg_replace_callback('/\s*filter\:\s*progid:DXImageTransform\.Microsoft\.Matrix\(([^\)]+)\)/', array($this, 'preserve_old_IE_specific_matrix_definition'), $css);
469
 
470
  if ($found_terminator) {
471
  $token = $this->str_slice($css, $start_index, $end_index);
472
+ if (strpos($token,"<svg")===false && strpos($token,'svg+xml')===false) {
473
  $token = preg_replace('/\s+/', '', $token);
474
  }
475
  $this->preserved_tokens[] = $token;
classlesses/autoptimizeFontRegex.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // regex to find fonts, externalised to avoid nasty errors for php<5.3
3
+
4
+ $fonturl_regex = <<<'LOD'
5
+ ~(?(DEFINE)(?<quoted_content>(["']) (?>[^"'\\]++ | \\{2} | \\. | (?!\g{-1})["'] )*+ \g{-1})(?<comment> /\* .*? \*/ ) (?<url_skip>(?: data: ) [^"'\s)}]*+ ) (?<other_content>(?> [^u}/"']++ | \g<quoted_content> | \g<comment> | \Bu | u(?!rl\s*+\() | /(?!\*) | \g<url_start> \g<url_skip> ["']?+ )++ ) (?<anchor> \G(?<!^) ["']?+ | @font-face \s*+ { ) (?<url_start> url\( \s*+ ["']?+ ) ) \g<comment> (*SKIP)(*FAIL) | \g<anchor> \g<other_content>?+ \g<url_start> \K ((?:(?:https?:)?(?://[[:alnum:]\-\.]+)(?::[0-9]+)?)?\/[^"'\s)}]*+) ~xs
6
+ LOD;
7
+
8
+ ?>
classlesses/autoptimizePageCacheFlush.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // flush as many page cache plugin's caches as possible
3
+ // hyper cache and gator cache hook into AO, so we don't need to :-)
4
+
5
+ function autoptimize_flush_pagecache() {
6
+ if(function_exists('wp_cache_clear_cache')) {
7
+ if (is_multisite()) {
8
+ $blog_id = get_current_blog_id();
9
+ wp_cache_clear_cache($blog_id);
10
+ } else {
11
+ wp_cache_clear_cache();
12
+ }
13
+ } else if ( has_action('cachify_flush_cache') ) {
14
+ do_action('cachify_flush_cache');
15
+ } else if ( function_exists('w3tc_pgcache_flush') ) {
16
+ w3tc_pgcache_flush();
17
+ } else if ( function_exists('wp_fast_cache_bulk_delete_all') ) {
18
+ wp_fast_cache_bulk_delete_all(); // still to retest
19
+ } else if (class_exists("WpFastestCache")) {
20
+ $wpfc = new WpFastestCache();
21
+ $wpfc -> deleteCache();
22
+ } else if ( class_exists("c_ws_plugin__qcache_purging_routines") ) {
23
+ c_ws_plugin__qcache_purging_routines::purge_cache_dir(); // quick cache, still to retest
24
+ } else if ( class_exists("zencache") ) {
25
+ zencache::clear();
26
+ } else if ( class_exists("comet_cache") ) {
27
+ comet_cache::clear();
28
+ } else if ( class_exists("WpeCommon") ) {
29
+ if ( apply_filters('autoptimize_flush_wpengine_aggressive', false) ) {
30
+ if ( method_exists( "WpeCommon", "purge_memcached" ) ) {
31
+ WpeCommon::purge_memcached();
32
+ }
33
+ if ( method_exists( "WpeCommon", "clear_maxcdn_cache" ) ) {
34
+ WpeCommon::clear_maxcdn_cache();
35
+ }
36
+ }
37
+ if ( method_exists( "WpeCommon", "purge_varnish_cache" ) ) {
38
+ WpeCommon::purge_varnish_cache();
39
+ }
40
+ } else if(file_exists(WP_CONTENT_DIR.'/wp-cache-config.php') && function_exists('prune_super_cache')){
41
+ // fallback for WP-Super-Cache
42
+ global $cache_path;
43
+ if (is_multisite()) {
44
+ $blog_id = get_current_blog_id();
45
+ prune_super_cache( get_supercache_dir( $blog_id ), true );
46
+ prune_super_cache( $cache_path . 'blogs/', true );
47
+ } else {
48
+ prune_super_cache($cache_path.'supercache/',true);
49
+ prune_super_cache($cache_path,true);
50
+ }
51
+ }
52
+ }
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: futtta, turl, optimizingmatters
3
  Tags: css, html, javascript, js, optimize, speed, cache, aggregate, minimize, minification, performance, pagespeed
4
  Donate link: http://blog.futtta.be/2013/10/21/do-not-donate-to-me/
5
  Requires at least: 2.7
6
- Tested up to: 4.4
7
- Stable tag: 2.0.0
8
 
9
  Autoptimize speeds up your website and helps you save bandwidth by aggregating and minimizing JS, CSS and HTML.
10
 
@@ -15,7 +15,7 @@ Autoptimize makes optimizing your site really easy. It concatenates all scripts
15
  If you consider performance important, you really should use a caching-plugin such as e.g. [WP Super Cache](http://wordpress.org/extend/plugins/wp-super-cache/) or
16
  [HyperCache](http://wordpress.org/extend/plugins/hyper-cache/) to complement Autoptimize.
17
 
18
- (Image under creative commons [by LL Twistiti](https://www.flickr.com/photos/twistiti/818552808/))
19
 
20
  == Installation ==
21
 
@@ -41,7 +41,7 @@ CSS in general should go in the head of the document. Recently a.o. Google start
41
 
42
  = But how can one find out what the "above the fold CSS" is? =
43
 
44
- There's no easy solution for that as "above the fold" depends on where the fold is, which in turn depends on screensize. There are some tools available however, which try to identify just what is "above the fold". [This list of tools](https://github.com/addyosmani/above-the-fold-css-tools) is a great starting point and esp. [http://jonassebastianohlsson.com/criticalpathcssgenerator/](http://jonassebastianohlsson.com/criticalpathcssgenerator/) is an easy solution if you're not into node.js yourself. Alternatively [this bookmarklet](https://gist.github.com/PaulKinlan/6284142) (Chrome-only) can be helpful as well.
45
 
46
  = Or should you inline all CSS? =
47
 
@@ -57,28 +57,28 @@ You can find more information on this topic [in this blog post](http://blog.futt
57
 
58
  = My cache is getting huge, doesn't Autoptimize purge the cache? =
59
 
60
- Autoptimize does not have its proper cache purging mechanism, as this could remove optimized CSS/JS which is still referred to in other caches, which would break your site.
61
 
62
- You can however keep the cache size at an acceptable level by either:
63
 
64
  * disactivating the "aggregate inline JS" and/ or "aggregate inline CSS" options
65
  * excluding JS-variables (or sometimes CSS-selectors) that change on a per page (or per pageload) basis. You can read how you can do that [in this blogpost](http://blog.futtta.be/2014/03/19/how-to-keep-autoptimizes-cache-size-under-control-and-improve-visitor-experience/).
66
 
67
  = Where is the "look only in head" option? =
68
 
69
- While "look only in head" still works, it is now (since Autoptimize 2.0 no longer visible on the settings-page if it is not active. As long as the option is active (for JS or CSS), it will however remain visible until you deactivate it. If you're comfortable with PHP, there however still are filters available to keep on using "look only in head".
70
 
71
  = So should I aggregate inline CSS/ JS? =
72
 
73
- Before Autoptimize 2.0, inline code was always optimized with all CSS pushed in the head-section and all JS at the end with a defer-flag. This often caused 2 problems; the priority of inline CSS got lost and inline JS could contain page- or request-specific code which broke Autoptimize's caching mechanism leading to too many cached files and the minification running over and over. This is why as from 2.0 by default inline code is not optimized (except for those upgrading from previous versions). Additionally, to avoid inline JS breaking because the optimized JS is not available, JS is forced in head by default. If you want to squeeze out as much performance as possible, you should indeed tick the "aggregate inline"-options and disable "force JS into head", while off course keeping an eye out for the disadvantages listed above.
74
 
75
  = What can I do with the API? =
76
 
77
- A whole lot; there are filters you can use to conditionally disable Autoptimize per request, to change the CSS- and JS-excludes, to change the limit for CSS background-images to be inlined in the CSS, to define what JS-files are moved behing the aggregated on, to change the defer-attribute on the aggregated JS script-tag, ... There are examples for many filters in autoptimize_helper.php_example.
78
 
79
- = How can I use/ activate autoptimize_helper.php_example? =
80
 
81
- Copy it to /wp-content/plugins/autoptimize_helper.php and activate it in WordPress' plugin page. After that you can simple remove the one of the comment-sequences (double-slash) to activate one (or more) of the functions in there.
82
 
83
  = How does CDN work? =
84
 
@@ -90,10 +90,7 @@ If you want your uploaded images to be on the CDN as well, you can change the up
90
 
91
  Autoptimize supports this, but it is not enabled by default because [non-local fonts might require some extra configuration](http://davidwalsh.name/cdn-fonts). But if you have your cross-origin request policy in order, you can tell Autoptimize to put your fonts on the CDN by hooking into the API, setting `autoptimize_filter_css_fonts_cdn` to `true` this way;
92
 
93
- `add_filter('autoptimize_filter_css_fonts_cdn','cdn_fonts');
94
- function cdn_fonts() {
95
- return true;
96
- }`
97
 
98
  = How can I force the aggregated files to be static CSS or JS instead of PHP? =
99
 
@@ -105,7 +102,7 @@ Both CSS and JS optimization can skip code from being aggregated and minimized b
105
 
106
  * if you want to exclude a specific file, e.g. wp-content/plugins/funkyplugin/css/style.css, you could simply exclude "funkyplugin/css/style.css"
107
  * if you want to exclude all files of a specific plugin, e.g. wp-content/plugins/funkyplugin/js/*, you can exclude for example "funkyplugin/js/" or "plugins/funkyplugin"
108
- * if you want to exclude inline code, you'll have to find a specific, unique string in that block of code and add that to the exclusion list. Example: to exclude "<script>funky_data='Won\'t you take me to, Funky Town'</script>", the identifier is "funky_data".
109
 
110
  = Configuring & Troubleshooting Autoptimize =
111
 
@@ -115,14 +112,14 @@ If your blog doesn't function normally after having turned on Autoptimize, here
115
 
116
  * If all works but you notice your blog is slower, ensure you have a page caching plugin installed (WP Super Cache or similar) and check the info on cache size (the solution for that problem also impacts performance for uncached pages) in this FAQ as well.
117
  * In case your blog looks weird, i.e. when the layout gets messed up, there is problem with CSS optimization. In this case you can turn on the option "Look for styles on just head?" and see if that solves the problem. You can also force CSS not to be aggregated by wrapping it in noptimize-tags in your theme or widget or by adding filename (for external stylesheets) or string (for inline styles) to the exclude-list.
118
- * In case some functionality on your site stops working (a carroussel, a menu, the search input, ...) you're likely hitting JavaScript optimization trouble. Disable the option "Aggregate inline JS" and activate "Force JavaScript in <head>?" (and optionally "[Add try/catch wrapping](http://blog.futtta.be/2014/08/18/when-should-you-trycatch-javascript/)") and try again. Alternatively -for the technically savvy- you can exclude specific scripts from being treated (moved and/ or aggregated) by Autoptimize by adding a string that will match the offending Javascript or excluding it from within your template files or widgets by wrapping the code between noptimize-tags. Identifying the offending JavaScript and choosing the correct exclusion-string can be trial and error, but in the majority of cases JavaScript optimization issues can be solved this way. When debugging JavaScript issues, your browsers error console is the most important tool to help you understand what is going on.
119
- * If your theme uses jQuery, you can try either forcing all in head or excluding jquery(-min).js (and jQuery-plugins if needed).
120
  * If you can't get either CSS or JS optimization working, you can off course always continue using the other two optimization-techniques.
121
  * If you tried the troubleshooting tips above and you still can't get CSS and JS working at all, you can ask for support on the [WordPress Autoptimize support forum](http://wordpress.org/support/plugin/autoptimize). See below for a description of what information you should provide in your "trouble ticket"
122
 
123
  = Help, I have a blank page or an internal server error after enabling Autoptimize!! =
124
 
125
- First of all make sure you're not running other HTML, CSS or JS minification plugins simultaneously with Autoptimize.
126
 
127
  In some rare cases the [CSS minification component](https://github.com/tubalmartin/YUI-CSS-compressor-PHP-port/) currently used by Autoptimize crashes due to a lack of resources (see [detailed technical explanation here](http://blog.futtta.be/2014/01/14/irregular-expressions-have-your-stack-for-lunch/)). You can in that case either disable CSS optimization, try to exclude specific CSS from being aggregated or activate the legacy minifiers which don't have that problem. The latter can be accomplished by adding this to your wp-config.php:
128
 
@@ -134,18 +131,41 @@ The "legacy minifiers" will remain in Autoptimize "for ever" and changes to wp-c
134
 
135
  If you are running Apache, the htaccess file written by Autoptimize can in some cases conflict with the AllowOverrides settings of your Apache configuration (as is the case with the default configuration of some Ubuntu installations), which results in "internal server errors" on the autoptimize CSS- and JS-files. This can be solved by [setting AllowOverrides to All](http://httpd.apache.org/docs/2.4/mod/core.html#allowoverride).
136
 
137
- = My Autoptimized CSS/ JS is broken after upgrading from 1.9.4 to 2.0! =
138
 
139
- One of the bigger changes in Autoptimize 2.0 is that files that have "min.js" or "min.css" in their name are considered already minified and are only injected into the aggregated code after the actual minification, because this has an important performance-benefit. Although this has been tested rather thoroughly, it is possible that this approach does not always work. You can turn this behavior off by hooking into Autoptimize's API, like this;
 
 
 
 
 
 
 
 
 
 
 
140
 
141
  `
142
- add_filter('autoptimize_filter_js_inject_min_late','no_late_inject');
143
- add_filter('autoptimize_filter_css_inject_min_late','no_late_inject');
144
- function no_late_inject() {
 
 
145
  return false;
 
146
  }
147
  `
148
 
 
 
 
 
 
 
 
 
 
149
  Obviously you can choose to do this for only CSS, JS or both (as in example).
150
 
151
  = I use NextGen Galleries and a lot of JS is not aggregated/ minified? =
@@ -168,14 +188,9 @@ define('AUTOPTIMIZE_CACHE_CHILD_DIR','/resources/');
168
  define('AUTOPTIMIZE_CACHEFILE_PREFIX','aggregated_');
169
  `
170
 
171
- If you changed your wp-content-folder as per [the WordPress guidelines](http://codex.wordpress.org/Editing_wp-config.php#Moving_wp-content_folder), you can tell Autoptimize about that with;
172
- `
173
- define( 'AUTOPTIMIZE_WP_CONTENT_NAME','/content' );
174
- `
175
-
176
  = Where can I report an error? =
177
 
178
- You can report problems on the [wordpress.org support forum](http://wordpress.org/support/plugin/autoptimize), or [contact the maintainer using this contact form](http://blog.futtta.be/contact/).
179
 
180
  = What information should I include when requesting support =
181
 
@@ -197,6 +212,22 @@ Just [fork Autoptimize on Github](https://github.com/futtta/autoptimize) and cod
197
 
198
  == Changelog ==
199
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200
  = 2.0.0 =
201
  * On average 30% faster minification (more info [in this blogpost](http://blog.futtta.be/2015/12/22/making-autoptimize-faster/))!
202
  * New: Option to (de-)activate aggregation of inline JS and CSS.
3
  Tags: css, html, javascript, js, optimize, speed, cache, aggregate, minimize, minification, performance, pagespeed
4
  Donate link: http://blog.futtta.be/2013/10/21/do-not-donate-to-me/
5
  Requires at least: 2.7
6
+ Tested up to: 4.6
7
+ Stable tag: 2.0.2
8
 
9
  Autoptimize speeds up your website and helps you save bandwidth by aggregating and minimizing JS, CSS and HTML.
10
 
15
  If you consider performance important, you really should use a caching-plugin such as e.g. [WP Super Cache](http://wordpress.org/extend/plugins/wp-super-cache/) or
16
  [HyperCache](http://wordpress.org/extend/plugins/hyper-cache/) to complement Autoptimize.
17
 
18
+ (Speed-surfing image under creative commons [by LL Twistiti](https://www.flickr.com/photos/twistiti/818552808/))
19
 
20
  == Installation ==
21
 
41
 
42
  = But how can one find out what the "above the fold CSS" is? =
43
 
44
+ There's no easy solution for that as "above the fold" depends on where the fold is, which in turn depends on screensize. There are some tools available however, which try to identify just what is "above the fold". [This list of tools](https://github.com/addyosmani/above-the-fold-css-tools) is a great starting point. [http://jonassebastianohlsson.com/criticalpathcssgenerator/](http://jonassebastianohlsson.com/criticalpathcssgenerator/) is a nice basic solution and [http://criticalcss.com/](http://misc.optimizingmatters.com/partners/?from=faq&amp;partner=critcss) is a premium solution by the same developer. Alternatively [this bookmarklet](https://gist.github.com/PaulKinlan/6284142) (Chrome-only) can be helpful as well.
45
 
46
  = Or should you inline all CSS? =
47
 
57
 
58
  = My cache is getting huge, doesn't Autoptimize purge the cache? =
59
 
60
+ Autoptimize does not have its proper cache purging mechanism, as this could remove optimized CSS/JS which is still referred to in other caches, which would break your site. As from version 2.0.0 Autoptimize will display a notice on the administration pages if the cache size surpasses the half a Gigabyte mark.
61
 
62
+ You can keep the cache size at an acceptable level by either:
63
 
64
  * disactivating the "aggregate inline JS" and/ or "aggregate inline CSS" options
65
  * excluding JS-variables (or sometimes CSS-selectors) that change on a per page (or per pageload) basis. You can read how you can do that [in this blogpost](http://blog.futtta.be/2014/03/19/how-to-keep-autoptimizes-cache-size-under-control-and-improve-visitor-experience/).
66
 
67
  = Where is the "look only in head" option? =
68
 
69
+ While "look only in head" still works, it is now (since Autoptimize 2.0.0) no longer visible on the settings-page if it is not active. As long as the option is active (for JS or CSS), it will however remain visible until you deactivate it. If you're comfortable with PHP, there however still are filters available to keep on using "look only in head".
70
 
71
  = So should I aggregate inline CSS/ JS? =
72
 
73
+ Before Autoptimize 2.0.0, inline code was always optimized with all CSS pushed in the head-section and all JS at the end with a defer-flag. This often caused 2 problems; the priority of inline CSS got lost and inline JS could contain page- or request-specific code which broke Autoptimize's caching mechanism leading to too many cached files and the minification running over and over. This is why as from 2.0.0 by default inline code is not optimized (except for those upgrading from previous versions). Additionally, to avoid inline JS breaking because the optimized JS is not available, JS is forced in head by default. If you want to squeeze out as much performance as possible, you should indeed tick the "aggregate inline"-options and disable "force JS into head", while off course keeping an eye out for the disadvantages listed above.
74
 
75
  = What can I do with the API? =
76
 
77
+ A whole lot; there are filters you can use to conditionally disable Autoptimize per request, to change the CSS- and JS-excludes, to change the limit for CSS background-images to be inlined in the CSS, to define what JS-files are moved behind the aggregated one, to change the defer-attribute on the aggregated JS script-tag, ... There are examples for many filters in autoptimize_helper.php_example and in this FAQ.
78
 
79
+ = How can I use the code in autoptimize_helper.php_example? =
80
 
81
+ Although you could add the code to your theme's functions.php, it would get overwritten with your next theme update. Therefor it is better to either create a helper plugin of your own or to simply use [the Code Snippets plugin](https://wordpress.org/plugins/code-snippets/) to manage any custom code.
82
 
83
  = How does CDN work? =
84
 
90
 
91
  Autoptimize supports this, but it is not enabled by default because [non-local fonts might require some extra configuration](http://davidwalsh.name/cdn-fonts). But if you have your cross-origin request policy in order, you can tell Autoptimize to put your fonts on the CDN by hooking into the API, setting `autoptimize_filter_css_fonts_cdn` to `true` this way;
92
 
93
+ `add_filter('autoptimize_filter_css_fonts_cdn',__return_true);`
 
 
 
94
 
95
  = How can I force the aggregated files to be static CSS or JS instead of PHP? =
96
 
102
 
103
  * if you want to exclude a specific file, e.g. wp-content/plugins/funkyplugin/css/style.css, you could simply exclude "funkyplugin/css/style.css"
104
  * if you want to exclude all files of a specific plugin, e.g. wp-content/plugins/funkyplugin/js/*, you can exclude for example "funkyplugin/js/" or "plugins/funkyplugin"
105
+ * if you want to exclude inline code, you'll have to find a specific, unique string in that block of code and add that to the exclusion list. Example: to exclude ´<script>funky_data='Won\'t you take me to, Funky Town'</script>`, the identifier is "funky_data".
106
 
107
  = Configuring & Troubleshooting Autoptimize =
108
 
112
 
113
  * If all works but you notice your blog is slower, ensure you have a page caching plugin installed (WP Super Cache or similar) and check the info on cache size (the solution for that problem also impacts performance for uncached pages) in this FAQ as well.
114
  * In case your blog looks weird, i.e. when the layout gets messed up, there is problem with CSS optimization. In this case you can turn on the option "Look for styles on just head?" and see if that solves the problem. You can also force CSS not to be aggregated by wrapping it in noptimize-tags in your theme or widget or by adding filename (for external stylesheets) or string (for inline styles) to the exclude-list.
115
+ * In case some functionality on your site stops working (a carroussel, a menu, the search input, ...) you're likely hitting JavaScript optimization trouble. Disable the option "Aggregate inline JS" and activate "Force JavaScript in head?" and try again. Excluding ´jquery.js´ from optimization (see below) and optionally activating "[Add try/catch wrapping](http://blog.futtta.be/2014/08/18/when-should-you-trycatch-javascript/)") can also help. Alternatively -for the technically savvy- you can exclude specific scripts from being treated (moved and/ or aggregated) by Autoptimize by adding a string that will match the offending Javascript or excluding it from within your template files or widgets by wrapping the code between noptimize-tags. Identifying the offending JavaScript and choosing the correct exclusion-string can be trial and error, but in the majority of cases JavaScript optimization issues can be solved this way. When debugging JavaScript issues, your browsers error console is the most important tool to help you understand what is going on.
116
+ * If your theme or plugin require jQuery, you can try either forcing all in head and/ or excluding jquery.js (and jQuery-plugins if needed).
117
  * If you can't get either CSS or JS optimization working, you can off course always continue using the other two optimization-techniques.
118
  * If you tried the troubleshooting tips above and you still can't get CSS and JS working at all, you can ask for support on the [WordPress Autoptimize support forum](http://wordpress.org/support/plugin/autoptimize). See below for a description of what information you should provide in your "trouble ticket"
119
 
120
  = Help, I have a blank page or an internal server error after enabling Autoptimize!! =
121
 
122
+ First of all make sure you're not running other HTML, CSS or JS minification plugins (BWP minify, WP minify, ...) simultaneously with Autoptimize or disable that functionality your page caching plugin (W3 Total Cache, WP Fastest Cache, ...).
123
 
124
  In some rare cases the [CSS minification component](https://github.com/tubalmartin/YUI-CSS-compressor-PHP-port/) currently used by Autoptimize crashes due to a lack of resources (see [detailed technical explanation here](http://blog.futtta.be/2014/01/14/irregular-expressions-have-your-stack-for-lunch/)). You can in that case either disable CSS optimization, try to exclude specific CSS from being aggregated or activate the legacy minifiers which don't have that problem. The latter can be accomplished by adding this to your wp-config.php:
125
 
131
 
132
  If you are running Apache, the htaccess file written by Autoptimize can in some cases conflict with the AllowOverrides settings of your Apache configuration (as is the case with the default configuration of some Ubuntu installations), which results in "internal server errors" on the autoptimize CSS- and JS-files. This can be solved by [setting AllowOverrides to All](http://httpd.apache.org/docs/2.4/mod/core.html#allowoverride).
133
 
134
+ = I get no error, but my pages are not optimized at all? =
135
 
136
+ Autoptimize does a number of checks before actually optimizing. When one of the following is true, your pages won't be optimized:
137
+ * if there is no opening `<html` tag
138
+ * if there is `<xsl:stylesheet` in the response (indicating the output is not HTML but XML)
139
+ * if there is `<html amp` in the response (as AMP-pages are optimized already)
140
+ * if the output is an RSS-feed (is_feed() function)
141
+ * if the output is a WordPress administration page (is_admin() function)
142
+ * if the page is requested with ?ao_noptimize=1 appended to the URL
143
+ * if code hooks into Autoptimize to disable optimization (see topic on Visual Composer)
144
+
145
+ = Visual Composer, Beaver Builder and similar page builder solutions are broken!! =
146
+
147
+ These page builder plugins run on the frontend for logged in users and are very JavaScript intensive and should not be optimized. You can tell Autoptimize not to act on these page-builder powered pages for logged in users with this code:
148
 
149
  `
150
+ add_filter('autoptimize_filter_noptimize','pagebuilder_noptimize',10,0);
151
+ function pagebuilder_noptimize() {
152
+ if (is_user_logged_in()) {
153
+ return true;
154
+ } else {
155
  return false;
156
+ }
157
  }
158
  `
159
 
160
+ = My Autoptimized CSS/ JS is broken after upgrading from 1.9.4 to 2.0! =
161
+
162
+ One of the bigger changes in Autoptimize 2.0 is that files that have "min.js" or "min.css" in their name are considered already minified and are only injected into the aggregated code after the actual minification, because this has an important performance-benefit. Although this has been tested rather thoroughly, it is possible that this approach does not always work. You can turn this behavior off by hooking into Autoptimize's API, like this;
163
+
164
+ `
165
+ add_filter('autoptimize_filter_js_inject_min_late',__return_false);
166
+ add_filter('autoptimize_filter_css_inject_min_late',__return_false);
167
+ `
168
+
169
  Obviously you can choose to do this for only CSS, JS or both (as in example).
170
 
171
  = I use NextGen Galleries and a lot of JS is not aggregated/ minified? =
188
  define('AUTOPTIMIZE_CACHEFILE_PREFIX','aggregated_');
189
  `
190
 
 
 
 
 
 
191
  = Where can I report an error? =
192
 
193
+ You can report problems on the [wordpress.org support forum](http://wordpress.org/support/plugin/autoptimize). If you are 100% sure this your problem cannot be solved using Autoptimize configuration and that you in fact discovered a bug in the code, you can [create an issue on GitHub](https://github.com/futtta/autoptimize/issues).
194
 
195
  = What information should I include when requesting support =
196
 
212
 
213
  == Changelog ==
214
 
215
+ = 2.0.2 =
216
+ * bugfix: disallow moving non-aggregated JS by default (can be re-enabled by passing false to the `autoptimize_filter_js_unmovable`)
217
+ * bugfix: hook autoptimize_action_cachepurged into init to avoid ugly error-message for ZenCache (Comet Cache) users
218
+ * bugfix to allow for Autoptimize to work with PHP 5.2, although [you really should upgrade](http://blog.futtta.be/2016/03/15/why-would-you-still-be-on-php-5-2/)
219
+
220
+ = 2.0.1 =
221
+ * Improvement: Autoptimize now also tries to purge WP Engine cache when AO’s cache is cleared
222
+ * Improvement: for AMP pages (which are pretty optimized anyway) Autoptimize will not optimize to avoid issues with e.g. "inline & defer" and with AO adding attributes to link-tags that are not allowed in the subset of HTML that AMP is
223
+ * Improvement: refactored the page cache purging mechanism (removing duplicate code, now nicely hooking into AO's own `autoptimize_action_cachepurged` action)
224
+ * Improvement: Re-enable functionality to move non-aggregated JS if “also aggregate inline JS” is active (can be disabled with `autoptimize_filter_js_unmovable` filter)
225
+ * Improvement: script tags with `data-noptimize` attribute will be excluded from optimization
226
+ * Bugfix: Better support for renamed wp-content directories
227
+ * Bugfix: Multiple fixes for late-injected CSS/ JS (changes in those files were not always picked up, fonts or background images were not being CDN’ed, ...)
228
+ * Misc. other fixes & improvements, go read [the commit-log on GitHub](https://github.com/futtta/autoptimize/commits/master) if you’re that curious
229
+ * Tested & confirmed working with WordPress 4.5 (beta 3)
230
+
231
  = 2.0.0 =
232
  * On average 30% faster minification (more info [in this blogpost](http://blog.futtta.be/2015/12/22/making-autoptimize-faster/))!
233
  * New: Option to (de-)activate aggregation of inline JS and CSS.