PluginProbe
Autoptimize / 3.1.16
Autoptimize v3.1.16
3.1.16 2.2.2 2.3.0 2.3.1 2.3.2 2.3.3 2.3.4 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.5.0 2.5.1 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 All 108 releases
← All changes | classes/autoptimizeMain.php +390 -63 2.4.0 → 3.1.16 View file →
@@ -27,8 +27,15 @@
27 27 */
28 28 protected $filepath = null;
29 29
30 30 /**
31 + * Critical CSS base object
32 + *
33 + * @var object
34 + */
35 + protected $_criticalcss = null;
36 +
37 + /**
31 38 * Constructor.
32 39 *
33 40 * @param string $version Version.
34 41 * @param string $filepath Filepath. Needed for activation/deactivation/uninstall hooks.
@@ -49,25 +56,33 @@
49 56 }
50 57
51 58 protected function add_hooks()
52 59 {
53 - add_action( 'plugins_loaded', array( $this, 'setup' ) );
60 + if ( ! defined( 'AUTOPTIMIZE_SETUP_INITHOOK' ) ) {
61 + define( 'AUTOPTIMIZE_SETUP_INITHOOK', 'plugins_loaded' );
62 + }
54 63
64 + add_action( AUTOPTIMIZE_SETUP_INITHOOK, array( $this, 'setup' ) );
65 + add_action( AUTOPTIMIZE_SETUP_INITHOOK, array( $this, 'hook_page_cache_purge' ) );
66 +
55 67 add_action( 'autoptimize_setup_done', array( $this, 'version_upgrades_check' ) );
56 68 add_action( 'autoptimize_setup_done', array( $this, 'check_cache_and_run' ) );
57 - add_action( 'autoptimize_setup_done', array( $this, 'maybe_run_ao_extra' ) );
58 - add_action( 'autoptimize_setup_done', array( $this, 'maybe_run_partners_tab' ) );
69 + add_action( 'autoptimize_setup_done', array( $this, 'maybe_run_ao_compat' ), 10 );
70 + add_action( 'autoptimize_setup_done', array( $this, 'maybe_run_ao_extra' ), 15 );
71 + add_action( 'autoptimize_setup_done', array( $this, 'maybe_run_admin_only_trinkets' ), 20 );
72 + add_action( 'autoptimize_setup_done', array( $this, 'maybe_run_criticalcss' ), 11 );
73 + add_action( 'autoptimize_setup_done', array( $this, 'maybe_run_notfound_fallback' ), 10 );
59 74
60 75 add_action( 'init', array( $this, 'load_textdomain' ) );
61 - add_action( 'plugins_loaded', array( $this, 'hook_page_cache_purge' ) );
62 - add_action( 'admin_init', array( 'PAnD', 'init' ) );
63 76
64 - register_activation_hook( $this->filepath, array( $this, 'on_activate' ) );
65 - }
77 + if ( is_multisite() && is_admin() ) {
78 + // Only if multisite and if in admin we want to check if we need to save options on network level.
79 + add_action( 'init', 'autoptimizeOptionWrapper::check_multisite_on_saving_options' );
80 + }
66 81
67 - public function on_activate()
68 - {
82 + // register uninstall & deactivation hooks.
69 83 register_uninstall_hook( $this->filepath, 'autoptimizeMain::on_uninstall' );
84 + register_deactivation_hook( $this->filepath, 'autoptimizeMain::on_deactivation' );
70 85 }
71 86
72 87 public function load_textdomain()
73 88 {
@@ -76,9 +91,9 @@
76 91
77 92 public function setup()
78 93 {
79 94 // Do we gzip in php when caching or is the webserver doing it?
80 - define( 'AUTOPTIMIZE_CACHE_NOGZIP', (bool) get_option( 'autoptimize_cache_nogzip' ) );
95 + define( 'AUTOPTIMIZE_CACHE_NOGZIP', (bool) autoptimizeOptionWrapper::get_option( 'autoptimize_cache_nogzip' ) );
81 96
82 97 // These can be overridden by specifying them in wp-config.php or such.
83 98 if ( ! defined( 'AUTOPTIMIZE_WP_CONTENT_NAME' ) ) {
84 99 define( 'AUTOPTIMIZE_WP_CONTENT_NAME', '/' . wp_basename( WP_CONTENT_DIR ) );
@@ -103,9 +118,9 @@
103 118 define( 'AUTOPTIMIZE_WP_SITE_URL', site_url() );
104 119 }
105 120 }
106 121 if ( ! defined( 'AUTOPTIMIZE_WP_CONTENT_URL' ) ) {
107 - if ( function_exists( 'domain_mapping_siteurl' ) ) {
122 + if ( function_exists( 'get_original_url' ) ) {
108 123 define( 'AUTOPTIMIZE_WP_CONTENT_URL', str_replace( get_original_url( AUTOPTIMIZE_WP_SITE_URL ), AUTOPTIMIZE_WP_SITE_URL, content_url() ) );
109 124 } else {
110 125 define( 'AUTOPTIMIZE_WP_CONTENT_URL', content_url() );
111 126 }
@@ -126,8 +141,18 @@
126 141 }
127 142 if ( ! defined( 'AUTOPTIMIZE_SITE_DOMAIN' ) ) {
128 143 define( 'AUTOPTIMIZE_SITE_DOMAIN', parse_url( AUTOPTIMIZE_WP_SITE_URL, PHP_URL_HOST ) );
129 144 }
145 +
146 + // Multibyte-capable string replacements are available with a filter.
147 + // Also requires 'mbstring' extension.
148 + $with_mbstring = apply_filters( 'autoptimize_filter_main_use_mbstring', false );
149 + if ( $with_mbstring ) {
150 + autoptimizeUtils::mbstring_available( \extension_loaded( 'mbstring' ) );
151 + } else {
152 + autoptimizeUtils::mbstring_available( false );
153 + }
154 +
130 155 do_action( 'autoptimize_setup_done' );
131 156 }
132 157
133 158 /**
@@ -143,26 +168,41 @@
143 168 public function check_cache_and_run()
144 169 {
145 170 if ( autoptimizeCache::cacheavail() ) {
146 171 $conf = autoptimizeConfig::instance();
147 - if ( $conf->get( 'autoptimize_html' ) || $conf->get( 'autoptimize_js' ) || $conf->get( 'autoptimize_css' ) ) {
148 - // Hook into WordPress frontend.
149 - if ( defined( 'AUTOPTIMIZE_INIT_EARLIER' ) ) {
150 - add_action(
151 - 'init',
152 - array( $this, 'start_buffering' ),
153 - self::INIT_EARLIER_PRIORITY
154 - );
155 - } else {
156 - if ( ! defined( 'AUTOPTIMIZE_HOOK_INTO' ) ) {
157 - define( 'AUTOPTIMIZE_HOOK_INTO', 'template_redirect' );
172 + if ( $conf->get( 'autoptimize_html' ) || $conf->get( 'autoptimize_js' ) || $conf->get( 'autoptimize_css' ) || autoptimizeImages::imgopt_active() || autoptimizeImages::should_lazyload_wrapper() ) {
173 + if ( ! defined( 'AUTOPTIMIZE_NOBUFFER_OPTIMIZE' ) ) {
174 + // Hook into WordPress frontend.
175 + if ( defined( 'AUTOPTIMIZE_INIT_EARLIER' ) ) {
176 + add_action(
177 + 'init',
178 + array( $this, 'start_buffering' ),
179 + self::INIT_EARLIER_PRIORITY
180 + );
181 + } else {
182 + if ( ! defined( 'AUTOPTIMIZE_HOOK_INTO' ) ) {
183 + define( 'AUTOPTIMIZE_HOOK_INTO', 'template_redirect' );
184 + }
185 + add_action(
186 + constant( 'AUTOPTIMIZE_HOOK_INTO' ),
187 + array( $this, 'start_buffering' ),
188 + self::DEFAULT_HOOK_PRIORITY
189 + );
158 190 }
159 - add_action(
160 - constant( 'AUTOPTIMIZE_HOOK_INTO' ),
161 - array( $this, 'start_buffering' ),
162 - self::DEFAULT_HOOK_PRIORITY
163 - );
164 191 }
192 +
193 + // And disable Jetpack's site accelerator if JS or CSS opt. are active.
194 + if ( class_exists( 'Jetpack' ) && apply_filters( 'autoptimize_filter_main_disable_jetpack_cdn', true ) && ( $conf->get( 'autoptimize_js' ) || $conf->get( 'autoptimize_css' ) || autoptimizeImages::imgopt_active() ) ) {
195 + add_filter( 'jetpack_force_disable_site_accelerator', '__return_true' ); // this does not seemt to work any more?
196 + if ( true === autoptimizeImages::imgopt_active() ) {
197 + // only disable photon if AO is optimizing images.
198 + add_filter( 'jetpack_photon_skip_for_url', '__return_true' );
199 + }
200 + }
201 +
202 + // Add "no cache found" notice.
203 + add_action( 'admin_notices', 'autoptimizeMain::notice_nopagecache', 99 );
204 + add_action( 'admin_notices', 'autoptimizeMain::notice_potential_conflict', 99 );
165 205 }
166 206 } else {
167 207 add_action( 'admin_notices', 'autoptimizeMain::notice_cache_unavailable' );
168 208 }
@@ -170,21 +210,74 @@
170 210
171 211 public function maybe_run_ao_extra()
172 212 {
173 213 if ( apply_filters( 'autoptimize_filter_extra_activate', true ) ) {
214 + $ao_imgopt = new autoptimizeImages();
215 + $ao_imgopt->run();
174 216 $ao_extra = new autoptimizeExtra();
175 217 $ao_extra->run();
218 +
219 + // And show the imgopt notice.
220 + add_action( 'admin_notices', 'autoptimizeMain::notice_plug_imgopt' );
221 + add_action( 'admin_notices', 'autoptimizeMain::notice_imgopt_issue' );
176 222 }
177 223 }
178 224
179 - public function maybe_run_partners_tab()
225 + public function maybe_run_admin_only_trinkets()
180 226 {
181 - // Loads partners tab code if in admin (and not in admin-ajax.php)!
227 + // Loads partners tab and exit survey code if in admin (and not in admin-ajax.php)!
182 228 if ( autoptimizeConfig::is_admin_and_not_ajax() ) {
183 229 new autoptimizePartners();
230 + new autoptimizeExitSurvey();
231 + new autoptimizeProTab();
184 232 }
185 233 }
186 234
235 + public function criticalcss()
236 + {
237 + if ( apply_filters( 'autoptimize_filter_criticalcss_active', true ) && ! autoptimizeUtils::is_plugin_active( 'autoptimize-criticalcss/ao_criticss_aas.php' ) ) {
238 + return $this->_criticalcss;
239 + } else {
240 + return false;
241 + }
242 + }
243 +
244 + public function maybe_run_criticalcss()
245 + {
246 + // Loads criticalcss if the filter returns true & old power-up is not active.
247 + if ( apply_filters( 'autoptimize_filter_criticalcss_active', true ) && ! autoptimizeUtils::is_plugin_active( 'autoptimize-criticalcss/ao_criticss_aas.php' ) ) {
248 + $this->_criticalcss = new autoptimizeCriticalCSSBase();
249 + $this->_criticalcss->setup();
250 + $this->_criticalcss->load_requires();
251 + }
252 + }
253 +
254 + public function maybe_run_notfound_fallback()
255 + {
256 + if ( autoptimizeCache::do_fallback() ) {
257 + add_action( 'template_redirect', array( 'autoptimizeCache', 'wordpress_notfound_fallback' ) );
258 + }
259 + }
260 +
261 + public function maybe_run_ao_compat()
262 + {
263 + $conf = autoptimizeConfig::instance();
264 +
265 + // Condtionally loads the compatibility-class to ensure more out-of-the-box compatibility with big players.
266 + $_run_compat = true;
267 +
268 + if ( 'on' === $conf->get( 'autoptimize_installed_before_compatibility' ) ) {
269 + // If AO was already running before Compatibility logic was added, don't run compat by default
270 + // because it can be assumed everything works and we want to avoid (perf) regressions that
271 + // could occur due to compatibility code.
272 + $_run_compat = false;
273 + }
274 +
275 + if ( apply_filters( 'autoptimize_filter_init_compatibility', $_run_compat ) ) {
276 + new autoptimizeCompatibility();
277 + }
278 + }
279 +
187 280 public function hook_page_cache_purge()
188 281 {
189 282 // hook into a collection of page cache purge actions if filter allows.
190 283 if ( apply_filters( 'autoptimize_filter_main_hookpagecachepurge', true ) ) {
@@ -193,12 +286,15 @@
193 286 'hyper_cache_purged', // Stefano confirmed this will be added.
194 287 'w3tc_flush_posts', // exits.
195 288 'w3tc_flush_all', // exists.
196 289 'ce_action_cache_cleared', // Sven confirmed this will be added.
290 + 'aoce_action_cache_cleared', // Some other cache enabler.
197 291 'comet_cache_wipe_cache', // still to be confirmed by Raam.
198 292 'wp_cache_cleared', // cfr. https://github.com/Automattic/wp-super-cache/pull/537.
199 293 'wpfc_delete_cache', // Emre confirmed this will be added this.
200 294 'swift_performance_after_clear_all_cache', // swift perf. yeah!
295 + 'wpo_cache_flush', // wp-optimize.
296 + 'rt_nginx_helper_after_fastcgi_purge_all', // nginx helper.
201 297 );
202 298 $page_cache_purge_actions = apply_filters( 'autoptimize_filter_main_pagecachepurgeactions', $page_cache_purge_actions );
203 299 foreach ( $page_cache_purge_actions as $purge_action ) {
204 300 add_action( $purge_action, 'autoptimizeCache::clearall_actionless' );
@@ -254,9 +350,9 @@
254 350 * @param bool $doing_tests Allows overriding the optimization of only
255 351 * deciding once per request (for use in tests).
256 352 * @return bool
257 353 */
258 - public function should_buffer( $doing_tests = false )
354 + public static function should_buffer( $doing_tests = false )
259 355 {
260 356 static $do_buffering = null;
261 357
262 358 // Only check once in case we're called multiple times by others but
@@ -286,16 +382,16 @@
286 382 }
287 383 }
288 384
289 385 // If setting says not to optimize logged in user and user is logged in...
290 - if ( 'on' !== get_option( 'autoptimize_optimize_logged', 'on' ) && is_user_logged_in() && current_user_can( 'edit_posts' ) ) {
386 + if ( false === $ao_noptimize && 'on' !== autoptimizeOptionWrapper::get_option( 'autoptimize_optimize_logged', 'on' ) && is_user_logged_in() && current_user_can( 'edit_posts' ) ) {
291 387 $ao_noptimize = true;
292 388 }
293 389
294 390 // If setting says not to optimize cart/checkout.
295 - if ( 'on' !== get_option( 'autoptimize_optimize_checkout', 'on' ) ) {
391 + if ( false === $ao_noptimize && 'on' !== autoptimizeOptionWrapper::get_option( 'autoptimize_optimize_checkout', 'off' ) ) {
296 392 // Checking for woocommerce, easy digital downloads and wp ecommerce...
297 - foreach ( array( 'is_checkout', 'is_cart', 'edd_is_checkout', 'wpsc_is_cart', 'wpsc_is_checkout' ) as $func ) {
393 + foreach ( array( 'is_checkout', 'is_cart', 'is_account_page', 'edd_is_checkout', 'wpsc_is_cart', 'wpsc_is_checkout' ) as $func ) {
298 394 if ( function_exists( $func ) && $func() ) {
299 395 $ao_noptimize = true;
300 396 break;
301 397 }
@@ -301,9 +397,38 @@
301 397 }
302 398 }
303 399 }
304 400
305 - // Allows blocking of autoptimization on your own terms regardless of above decisions.
401 + // Misc. querystring paramaters that will stop AO from doing optimizations (pagebuilders +
402 + // 2 generic parameters that could/ should become standard between optimization plugins?).
403 + if ( false === $ao_noptimize ) {
404 + $_qs_showstoppers = array( 'no_cache', 'no_optimize', 'tve', 'elementor-preview', 'fl_builder', 'vc_action', 'et_fb', 'bt-beaverbuildertheme', 'ct_builder', 'fb-edit', 'siteorigin_panels_live_editor', 'preview', 'td_action' );
405 +
406 + // doing Jonathan a quick favor to allow correct unused CSS generation ;-) .
407 + if ( apply_filters( 'autoptimize_filter_main_showstoppers_do_wp_rocket_a_favor', true ) ) {
408 + $_qs_showstoppers[] = 'nowprocket';
409 + }
410 +
411 + foreach ( $_qs_showstoppers as $_showstopper ) {
412 + if ( array_key_exists( $_showstopper, $_GET ) ) {
413 + $ao_noptimize = true;
414 + break;
415 + }
416 + }
417 + }
418 +
419 + // Also honor PageSpeed=off parameter as used by mod_pagespeed, in use by some pagebuilders,
420 + // see https://www.modpagespeed.com/doc/experiment#ModPagespeed for info on that.
421 + if ( false === $ao_noptimize && array_key_exists( 'PageSpeed', $_GET ) && 'off' === $_GET['PageSpeed'] ) {
422 + $ao_noptimize = true;
423 + }
424 +
425 + // If page/ post check post_meta to see if optimize is off.
426 + if ( false === autoptimizeConfig::get_post_meta_ao_settings( 'ao_post_optimize' ) ) {
427 + $ao_noptimize = true;
428 + }
429 +
430 + // And finally allows blocking of autoptimization on your own terms regardless of above decisions.
306 431 $ao_noptimize = (bool) apply_filters( 'autoptimize_filter_noptimize', $ao_noptimize );
307 432
308 433 // Check for site being previewed in the Customizer (available since WP 4.0).
309 434 $is_customize_preview = false;
@@ -309,8 +434,14 @@
309 434 $is_customize_preview = false;
310 435 if ( function_exists( 'is_customize_preview' ) && is_customize_preview() ) {
311 436 $is_customize_preview = is_customize_preview();
312 437 }
438 +
439 + // explicitly disable when is_login exists and is true but don't use it direclty because older versions of WordPress don't have that yet.
440 + $is_login = false;
441 + if ( function_exists( 'is_login' ) && true === is_login() ) {
442 + $is_login = true;
443 + }
313 444
314 445 /**
315 446 * We only buffer the frontend requests (and then only if not a feed
316 447 * and not turned off explicitly and not when being previewed in Customizer)!
@@ -317,9 +448,9 @@
317 448 * NOTE: Tests throw a notice here due to is_feed() being called
318 449 * while the main query hasn't been ran yet. Thats why we use
319 450 * AUTOPTIMIZE_INIT_EARLIER in tests.
320 451 */
321 - $do_buffering = ( ! is_admin() && ! is_feed() && ! $ao_noptimize && ! $is_customize_preview );
452 + $do_buffering = ( ! is_admin() && ! is_feed() && ! is_embed() && ! $is_login && ! $is_customize_preview && ! $ao_noptimize );
322 453 }
323 454
324 455 return $do_buffering;
325 456 }
@@ -336,10 +467,11 @@
336 467 // Defaults to true.
337 468 $valid = true;
338 469
339 470 $has_no_html_tag = ( false === stripos( $content, '<html' ) );
340 - $has_xsl_stylesheet = ( false !== stripos( $content, '<xsl:stylesheet' ) );
341 - $has_html5_doctype = ( preg_match( '/^<!DOCTYPE.+html>/i', $content ) > 0 );
471 + $has_xsl_stylesheet = ( false !== stripos( $content, '<xsl:stylesheet' ) || false !== stripos( $content, '<?xml-stylesheet' ) );
472 + $has_html5_doctype = ( preg_match( '/^<!DOCTYPE.+html>/i', ltrim( $content ) ) > 0 );
473 + $has_noptimize_page = ( false !== stripos( $content, '<!-- noptimize-page -->' ) );
342 474
343 475 if ( $has_no_html_tag ) {
344 476 // Can't be valid amp markup without an html tag preceding it.
345 477 $is_amp_markup = false;
@@ -347,9 +479,9 @@
347 479 $is_amp_markup = self::is_amp_markup( $content );
348 480 }
349 481
350 482 // If it's not html, or if it's amp or contains xsl stylesheets we don't touch it.
351 - if ( $has_no_html_tag && ! $has_html5_doctype || $is_amp_markup || $has_xsl_stylesheet ) {
483 + if ( $has_no_html_tag && ! $has_html5_doctype || $is_amp_markup || $has_xsl_stylesheet || $has_noptimize_page ) {
352 484 $valid = false;
353 485 }
354 486
355 487 return $valid;
@@ -364,11 +496,31 @@
364 496 * @return bool
365 497 */
366 498 public static function is_amp_markup( $content )
367 499 {
368 - $is_amp_markup = preg_match( '/<html[^>]*(?:amp|âš¡)/i', $content );
500 + // Short-circuit if the page is already AMP from the start.
501 + if (
502 + preg_match(
503 + sprintf(
504 + '#^(?:<!.*?>|\s+)*+<html(?=\s)[^>]*?\s(%1$s|%2$s|%3$s)(\s|=|>)#is',
505 + 'amp',
506 + "\xE2\x9A\xA1", // From \AmpProject\Attribute::AMP_EMOJI.
507 + "\xE2\x9A\xA1\xEF\xB8\x8F" // From \AmpProject\Attribute::AMP_EMOJI_ALT, per https://github.com/ampproject/amphtml/issues/25990.
508 + ),
509 + $content
510 + )
511 + ) {
512 + return true;
513 + }
369 514
370 - return (bool) $is_amp_markup;
515 + // Or else short-circuit if the AMP plugin will be processing the output to be an AMP page.
516 + if ( function_exists( 'amp_is_request' ) ) {
517 + return amp_is_request(); // For AMP plugin v2.0+.
518 + } elseif ( function_exists( 'is_amp_endpoint' ) ) {
519 + return is_amp_endpoint(); // For older/other AMP plugins (still supported in 2.0 as an alias).
520 + }
521 +
522 + return false;
371 523 }
372 524
373 525 /**
374 526 * Processes/optimizes the output-buffered content and returns it.
@@ -400,30 +552,35 @@
400 552 }
401 553
402 554 $classoptions = array(
403 555 'autoptimizeScripts' => array(
404 - 'aggregate' => $conf->get( 'autoptimize_js_aggregate' ),
405 - 'justhead' => $conf->get( 'autoptimize_js_justhead' ),
406 - 'forcehead' => $conf->get( 'autoptimize_js_forcehead' ),
407 - 'trycatch' => $conf->get( 'autoptimize_js_trycatch' ),
408 - 'js_exclude' => $conf->get( 'autoptimize_js_exclude' ),
409 - 'cdn_url' => $conf->get( 'autoptimize_cdn_url' ),
410 - 'include_inline' => $conf->get( 'autoptimize_js_include_inline' ),
556 + 'aggregate' => $conf->get( 'autoptimize_js_aggregate' ),
557 + 'defer_not_aggregate' => $conf->get( 'autoptimize_js_defer_not_aggregate' ),
558 + 'defer_inline' => $conf->get( 'autoptimize_js_defer_inline' ),
559 + 'justhead' => $conf->get( 'autoptimize_js_justhead' ),
560 + 'forcehead' => $conf->get( 'autoptimize_js_forcehead' ),
561 + 'trycatch' => $conf->get( 'autoptimize_js_trycatch' ),
562 + 'js_exclude' => $conf->get( 'autoptimize_js_exclude' ),
563 + 'cdn_url' => $conf->get( 'autoptimize_cdn_url' ),
564 + 'include_inline' => $conf->get( 'autoptimize_js_include_inline' ),
565 + 'minify_excluded' => $conf->get( 'autoptimize_minify_excluded' ),
411 566 ),
412 567 'autoptimizeStyles' => array(
413 - 'aggregate' => $conf->get( 'autoptimize_css_aggregate' ),
414 - 'justhead' => $conf->get( 'autoptimize_css_justhead' ),
415 - 'datauris' => $conf->get( 'autoptimize_css_datauris' ),
416 - 'defer' => $conf->get( 'autoptimize_css_defer' ),
417 - 'defer_inline' => $conf->get( 'autoptimize_css_defer_inline' ),
418 - 'inline' => $conf->get( 'autoptimize_css_inline' ),
419 - 'css_exclude' => $conf->get( 'autoptimize_css_exclude' ),
420 - 'cdn_url' => $conf->get( 'autoptimize_cdn_url' ),
421 - 'include_inline' => $conf->get( 'autoptimize_css_include_inline' ),
422 - 'nogooglefont' => $conf->get( 'autoptimize_css_nogooglefont' ),
568 + 'aggregate' => $conf->get( 'autoptimize_css_aggregate' ),
569 + 'justhead' => $conf->get( 'autoptimize_css_justhead' ),
570 + 'datauris' => $conf->get( 'autoptimize_css_datauris' ),
571 + 'defer' => $conf->get( 'autoptimize_css_defer' ),
572 + 'defer_inline' => $conf->get( 'autoptimize_css_defer_inline' ),
573 + 'inline' => $conf->get( 'autoptimize_css_inline' ),
574 + 'css_exclude' => $conf->get( 'autoptimize_css_exclude' ),
575 + 'cdn_url' => $conf->get( 'autoptimize_cdn_url' ),
576 + 'include_inline' => $conf->get( 'autoptimize_css_include_inline' ),
577 + 'nogooglefont' => $conf->get( 'autoptimize_css_nogooglefont' ),
578 + 'minify_excluded' => $conf->get( 'autoptimize_minify_excluded' ),
423 579 ),
424 580 'autoptimizeHTML' => array(
425 - 'keepcomments' => $conf->get( 'autoptimize_html_keepcomments' ),
581 + 'keepcomments' => $conf->get( 'autoptimize_html_keepcomments' ),
582 + 'minify_inline' => $conf->get( 'autoptimize_html_minify_inline' ),
426 583 ),
427 584 );
428 585
429 586 $content = apply_filters( 'autoptimize_filter_html_before_minify', $content );
@@ -443,12 +600,33 @@
443 600
444 601 return $content;
445 602 }
446 603
604 + public static function autoptimize_nobuffer_optimize( $html_in ) {
605 + $html_out = $html_in;
606 +
607 + if ( apply_filters( 'autoptimize_filter_speedupper', true ) ) {
608 + $ao_speedupper = new autoptimizeSpeedupper();
609 + }
610 +
611 + $self = new self( AUTOPTIMIZE_PLUGIN_VERSION, AUTOPTIMIZE_PLUGIN_FILE );
612 + if ( $self->should_buffer() ) {
613 + $html_out = $self->end_buffering( $html_in );
614 + }
615 + return $html_out;
616 + }
617 +
447 618 public static function on_uninstall()
448 619 {
620 + // clear the cache.
449 621 autoptimizeCache::clearall();
450 622
623 + // remove postmeta if active.
624 + if ( autoptimizeConfig::is_ao_meta_settings_active() ) {
625 + delete_post_meta_by_key( 'ao_post_optimize' );
626 + }
627 +
628 + // remove all options.
451 629 $delete_options = array(
452 630 'autoptimize_cache_clean',
453 631 'autoptimize_cache_nogzip',
454 632 'autoptimize_css',
@@ -460,10 +638,15 @@
460 638 'autoptimize_css_inline',
461 639 'autoptimize_css_exclude',
462 640 'autoptimize_html',
463 641 'autoptimize_html_keepcomments',
642 + 'autoptimize_html_minify_inline',
643 + 'autoptimize_enable_site_config',
644 + 'autoptimize_enable_meta_ao_settings',
464 645 'autoptimize_js',
465 646 'autoptimize_js_aggregate',
647 + 'autoptimize_js_defer_not_aggregate',
648 + 'autoptimize_js_defer_inline',
466 649 'autoptimize_js_exclude',
467 650 'autoptimize_js_forcehead',
468 651 'autoptimize_js_justhead',
469 652 'autoptimize_js_trycatch',
@@ -478,8 +661,29 @@
478 661 'autoptimize_extra_settings',
479 662 'autoptimize_service_availablity',
480 663 'autoptimize_imgopt_provider_stat',
481 664 'autoptimize_imgopt_launched',
665 + 'autoptimize_imgopt_settings',
666 + 'autoptimize_minify_excluded',
667 + 'autoptimize_cache_fallback',
668 + 'autoptimize_ccss_rules',
669 + 'autoptimize_ccss_additional',
670 + 'autoptimize_ccss_queue',
671 + 'autoptimize_ccss_viewport',
672 + 'autoptimize_ccss_finclude',
673 + 'autoptimize_ccss_rlimit',
674 + 'autoptimize_ccss_rtimelimit',
675 + 'autoptimize_ccss_noptimize',
676 + 'autoptimize_ccss_debug',
677 + 'autoptimize_ccss_key',
678 + 'autoptimize_ccss_keyst',
679 + 'autoptimize_ccss_version',
680 + 'autoptimize_ccss_loggedin',
681 + 'autoptimize_ccss_forcepath',
682 + 'autoptimize_ccss_deferjquery',
683 + 'autoptimize_ccss_domain',
684 + 'autoptimize_ccss_unloadccss',
685 + 'autoptimize_installed_before_compatibility',
482 686 );
483 687
484 688 if ( ! is_multisite() ) {
485 689 foreach ( $delete_options as $del_opt ) {
@@ -484,8 +688,9 @@
484 688 if ( ! is_multisite() ) {
485 689 foreach ( $delete_options as $del_opt ) {
486 690 delete_option( $del_opt );
487 691 }
692 + autoptimizeMain::remove_cronjobs();
488 693 } else {
489 694 global $wpdb;
490 695 $blog_ids = $wpdb->get_col( "SELECT blog_id FROM $wpdb->blogs" );
491 696 $original_blog_id = get_current_blog_id();
@@ -493,22 +698,60 @@
493 698 switch_to_blog( $blog_id );
494 699 foreach ( $delete_options as $del_opt ) {
495 700 delete_option( $del_opt );
496 701 }
702 + autoptimizeMain::remove_cronjobs();
497 703 }
498 704 switch_to_blog( $original_blog_id );
499 705 }
500 706
501 - if ( wp_get_schedule( 'ao_cachechecker' ) ) {
502 - wp_clear_scheduled_hook( 'ao_cachechecker' );
707 + // Remove AO CCSS cached files and directory.
708 + $ao_ccss_dir = WP_CONTENT_DIR . '/uploads/ao_ccss/';
709 + if ( file_exists( $ao_ccss_dir ) && is_dir( $ao_ccss_dir ) && defined( 'GLOB_BRACE' ) ) {
710 + // fixme: should check for subdirs when in multisite and remove contents of those as well.
711 + // fixme: if GLOB_BRACE is not avaible we need to remove AO_CCSS_DIR differently?
712 + array_map( 'unlink', glob( $ao_ccss_dir . '*.{css,html,json,log,zip,lock}', GLOB_BRACE ) );
713 + rmdir( $ao_ccss_dir );
503 714 }
715 +
716 + // Remove 404-handler (although that should have been removed in clearall already).
717 + $_fallback_php = trailingslashit( WP_CONTENT_DIR ) . 'autoptimize_404_handler.php';
718 + if ( file_exists( $_fallback_php ) ) {
719 + unlink( $_fallback_php );
720 + }
504 721 }
505 722
723 + public static function on_deactivation()
724 + {
725 + if ( is_multisite() && is_network_admin() ) {
726 + global $wpdb;
727 + $blog_ids = $wpdb->get_col( "SELECT blog_id FROM $wpdb->blogs" );
728 + $original_blog_id = get_current_blog_id();
729 + foreach ( $blog_ids as $blog_id ) {
730 + switch_to_blog( $blog_id );
731 + autoptimizeMain::remove_cronjobs();
732 + }
733 + switch_to_blog( $original_blog_id );
734 + } else {
735 + autoptimizeMain::remove_cronjobs();
736 + }
737 + autoptimizeCache::clearall();
738 + }
739 +
740 + public static function remove_cronjobs() {
741 + // Remove scheduled events.
742 + foreach ( array( 'ao_cachechecker', 'ao_ccss_queue', 'ao_ccss_maintenance', 'ao_ccss_keychecker' ) as $_event ) {
743 + if ( wp_get_schedule( $_event ) ) {
744 + wp_clear_scheduled_hook( $_event );
745 + }
746 + }
747 + }
748 +
506 749 public static function notice_cache_unavailable()
507 750 {
508 751 echo '<div class="error"><p>';
509 752 // Translators: %s is the cache directory location.
510 - printf( __( 'Autoptimize cannot write to the cache directory (%s), please fix to enable CSS/ JS optimization!', 'autoptimize' ), AUTOPTIMIZE_CACHE_DIR );
753 + printf( esc_html__( 'Autoptimize cannot write to the cache directory (%s), please fix to enable CSS/ JS optimization!', 'autoptimize' ), AUTOPTIMIZE_CACHE_DIR );
511 754 echo '</p></div>';
512 755 }
513 756
514 757 public static function notice_installed()
@@ -513,9 +756,10 @@
513 756
514 757 public static function notice_installed()
515 758 {
516 759 echo '<div class="updated"><p>';
517 - _e( 'Thank you for installing and activating Autoptimize. Please configure it under "Settings" -> "Autoptimize" to start improving your site\'s performance.', 'autoptimize' );
760 + // translators: the variables contain opening and closing <a> tags to link to the settings page.
761 + printf( esc_html__( 'Thank you for installing and activating Autoptimize. Your site is being optimized immediately, please test the frontend to ensure everything still works as expected. If needed you can change JavaScript or CSS optimization settings under %1$sSettings -> Autoptimize%2$s .', 'autoptimize' ), '<a href="options-general.php?page=autoptimize">', '</a>' );
518 762 echo '</p></div>';
519 763 }
520 764
521 765 public static function notice_updated()
@@ -520,9 +764,92 @@
520 764
521 765 public static function notice_updated()
522 766 {
523 767 echo '<div class="updated"><p>';
524 - _e( 'Autoptimize has just been updated. Please <strong>test your site now</strong> and adapt Autoptimize config if needed.', 'autoptimize' );
768 + printf( esc_html__( 'Autoptimize has just been updated. Please %1$stest your site now%2$s and adapt Autoptimize config if needed.', 'autoptimize' ), '<strong>', '</strong>' );
525 769 echo '</p></div>';
526 770 }
527 771
772 + public static function notice_plug_imgopt()
773 + {
774 + // Translators: the URL added points to the Autopmize Extra settings.
775 + $_ao_imgopt_plug_notice = sprintf( esc_html__( 'Did you know that Autoptimize offers on-the-fly image optimization (with support for WebP and AVIF) and CDN via ShortPixel? Check out the %1$sAutoptimize Image settings%2$s to enable this option.', 'autoptimize' ), '<a href="options-general.php?page=autoptimize_imgopt">', '</a>' );
776 + $_ao_imgopt_plug_notice = apply_filters( 'autoptimize_filter_main_imgopt_plug_notice', $_ao_imgopt_plug_notice );
777 + $_ao_imgopt_launch_ok = autoptimizeImages::launch_ok_wrapper();
778 + $_ao_imgopt_plug_dismissible = 'ao-img-opt-plug-123';
779 + $_ao_imgopt_active = autoptimizeImages::imgopt_active();
780 + $_is_ao_settings_page = autoptimizeUtils::is_ao_settings();
781 +
782 + if ( current_user_can( 'manage_options' ) && ! defined( 'AO_PRO_VERSION' ) && $_is_ao_settings_page && '' !== $_ao_imgopt_plug_notice && ! $_ao_imgopt_active && $_ao_imgopt_launch_ok && PAnD::is_admin_notice_active( $_ao_imgopt_plug_dismissible ) ) {
783 + echo '<div class="notice notice-info is-dismissible" data-dismissible="' . $_ao_imgopt_plug_dismissible . '"><p>';
784 + echo $_ao_imgopt_plug_notice;
785 + echo '</p></div>';
786 + }
787 + }
788 +
789 + public static function notice_imgopt_issue()
790 + {
791 + // Translators: the URL added points to the Autopmize Extra settings.
792 + $_ao_imgopt_issue_notice = sprintf( esc_html__( 'Shortpixel reports it cannot always reach your site, which might mean some images are not optimized. You can %1$sread more about why this happens and how you can fix that problem here%2$s.', 'autoptimize' ), '<a href="https://shortpixel.com/knowledge-base/article/469-i-received-an-e-mail-that-says-some-of-my-images-are-not-accessible-what-should-i-do#fullarticle" target="_blank">', '</a>' );
793 + $_ao_imgopt_issue_notice = apply_filters( 'autoptimize_filter_main_imgopt_issue_notice', $_ao_imgopt_issue_notice );
794 + $_ao_imgopt_issue_dismissible = 'ao-img-opt-issue-14';
795 + $_ao_imgopt_active = autoptimizeImages::imgopt_active();
796 + $_ao_imgopt_status = autoptimizeOptionWrapper::get_option( 'autoptimize_imgopt_provider_stat', '' );
797 +
798 + if ( is_array( $_ao_imgopt_status ) && array_key_exists( 'TemporaryRedirectOrigin', $_ao_imgopt_status ) && ( $_ao_imgopt_status['TemporaryRedirectOrigin'] === "true" || $_ao_imgopt_status['TemporaryRedirectOrigin'] === true ) ) {
799 + $_ao_imgopt_status_redirect_warning = true;
800 + } else {
801 + $_ao_imgopt_status_redirect_warning = false;
802 + }
803 +
804 + if ( current_user_can( 'manage_options' ) && $_ao_imgopt_active && $_ao_imgopt_status_redirect_warning && '' !== $_ao_imgopt_issue_notice && PAnD::is_admin_notice_active( $_ao_imgopt_issue_dismissible ) ) {
805 + echo '<div class="notice notice-info is-dismissible" data-dismissible="' . $_ao_imgopt_issue_dismissible . '"><p>';
806 + echo $_ao_imgopt_issue_notice;
807 + echo '</p></div>';
808 + }
809 + }
810 +
811 +
812 + public static function notice_nopagecache()
813 + {
814 + /*
815 + * Autoptimize does not do page caching (yet) but not everyone knows, so below logic tries to find out if page caching is available and if not show a notice on the AO Settings pages.
816 + *
817 + * uses helper function in autoptimizeUtils.php
818 + */
819 + // translators: strong tags and a break.
820 + $_ao_nopagecache_notice = sprintf( esc_html__( 'It looks like your site might not have %1$spage caching%2$s which is a %1$smust-have for performance%2$s. If you are sure you have a page cache, you can close this notice.%3$sWhen in doubt check with your host if they offer this or install a free page caching plugin like for example KeyCDN Cache Enabler', 'autoptimize' ), '<strong>', '</strong>', '<br />' );
821 + // translators: strong tags.
822 + $_ao_nopagecache_notice .= ' ' . esc_html__('or consider ', 'autoptimize') . '<strong><a href="https://autoptimize.com/pro/">Autoptimize Pro</a></strong>' . sprintf( esc_html__( ' which not only has page caching but also image optimization, critical CSS and advanced booster options %1$sto make your site significantly faster%2$s!', 'autoptimize' ), '<strong>', '</strong>' );
823 + $_ao_nopagecache_dismissible = 'ao-nopagecache-forever'; // the notice is only shown once and will not re-appear when dismissed.
824 + $_is_ao_settings_page = autoptimizeUtils::is_ao_settings();
825 +
826 + if ( current_user_can( 'manage_options' ) && $_is_ao_settings_page && PAnD::is_admin_notice_active( $_ao_nopagecache_dismissible ) && true === apply_filters( 'autoptimize_filter_main_show_pagecache_notice', true ) ) {
827 + if ( false === autoptimizeUtils::find_pagecache() ) {
828 + echo '<div class="notice notice-info is-dismissible" data-dismissible="' . $_ao_nopagecache_dismissible . '"><p>';
829 + echo $_ao_nopagecache_notice;
830 + echo '</p></div>';
831 + }
832 + }
833 + }
834 +
835 + public static function notice_potential_conflict()
836 + {
837 + /*
838 + * Using other plugins to do CSS/ JS optimization can cause unexpected and hard to troubleshoot issues, warn users who seem to be in that situation.
839 + */
840 + // Translators: some strong tags + the sentence will be finished with the name of the offending plugin and a final stop.
841 + $_ao_potential_conflict_notice = sprintf( esc_html__( 'It looks like you have %1$sanother plugin also doing CSS and/ or JS optimization%2$s, which can result in hard to troubleshoot %1$sconflicts%2$s. For this reason it is recommended to disable this functionality in', 'autoptimize' ), '<strong>', '</strong>' ) . ' ';
842 + $_ao_potential_conflict_dismissible = 'ao-potential-conflict-forever'; // the notice is only shown once and will not re-appear when dismissed.
843 + $_is_ao_settings_page = autoptimizeUtils::is_ao_settings();
844 +
845 + if ( current_user_can( 'manage_options' ) && $_is_ao_settings_page && PAnD::is_admin_notice_active( $_ao_potential_conflict_dismissible ) && true === apply_filters( 'autoptimize_filter_main_show_potential_conclict_notice', true ) ) {
846 + $_potential_conflicts = autoptimizeUtils::find_potential_conflicts();
847 + if ( false !== $_potential_conflicts ) {
848 + $_ao_potential_conflict_notice .= '<strong>' . $_potential_conflicts . '</strong>.';
849 + echo '<div class="notice notice-info is-dismissible" data-dismissible="' . $_ao_potential_conflict_dismissible . '"><p>';
850 + echo $_ao_potential_conflict_notice;
851 + echo '</p></div>';
852 + }
853 + }
854 + }
528 855 }