PluginProbe
Autoptimize / trunk
Autoptimize vtrunk
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 +366 -73 2.4.2 → trunk 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 }
@@ -131,9 +146,9 @@
131 146 // Multibyte-capable string replacements are available with a filter.
132 147 // Also requires 'mbstring' extension.
133 148 $with_mbstring = apply_filters( 'autoptimize_filter_main_use_mbstring', false );
134 149 if ( $with_mbstring ) {
135 - autoptimizeUtils::mbstring_available( \extensions_loaded( 'mbstring' ) );
150 + autoptimizeUtils::mbstring_available( \extension_loaded( 'mbstring' ) );
136 151 } else {
137 152 autoptimizeUtils::mbstring_available( false );
138 153 }
139 154
@@ -153,26 +168,41 @@
153 168 public function check_cache_and_run()
154 169 {
155 170 if ( autoptimizeCache::cacheavail() ) {
156 171 $conf = autoptimizeConfig::instance();
157 - if ( $conf->get( 'autoptimize_html' ) || $conf->get( 'autoptimize_js' ) || $conf->get( 'autoptimize_css' ) ) {
158 - // Hook into WordPress frontend.
159 - if ( defined( 'AUTOPTIMIZE_INIT_EARLIER' ) ) {
160 - add_action(
161 - 'init',
162 - array( $this, 'start_buffering' ),
163 - self::INIT_EARLIER_PRIORITY
164 - );
165 - } else {
166 - if ( ! defined( 'AUTOPTIMIZE_HOOK_INTO' ) ) {
167 - 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 + );
168 190 }
169 - add_action(
170 - constant( 'AUTOPTIMIZE_HOOK_INTO' ),
171 - array( $this, 'start_buffering' ),
172 - self::DEFAULT_HOOK_PRIORITY
173 - );
174 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 );
175 205 }
176 206 } else {
177 207 add_action( 'admin_notices', 'autoptimizeMain::notice_cache_unavailable' );
178 208 }
@@ -180,24 +210,74 @@
180 210
181 211 public function maybe_run_ao_extra()
182 212 {
183 213 if ( apply_filters( 'autoptimize_filter_extra_activate', true ) ) {
214 + $ao_imgopt = new autoptimizeImages();
215 + $ao_imgopt->run();
184 216 $ao_extra = new autoptimizeExtra();
185 217 $ao_extra->run();
186 218
187 219 // And show the imgopt notice.
188 220 add_action( 'admin_notices', 'autoptimizeMain::notice_plug_imgopt' );
221 + add_action( 'admin_notices', 'autoptimizeMain::notice_imgopt_issue' );
189 222 }
190 223 }
191 224
192 - public function maybe_run_partners_tab()
225 + public function maybe_run_admin_only_trinkets()
193 226 {
194 - // 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)!
195 228 if ( autoptimizeConfig::is_admin_and_not_ajax() ) {
196 229 new autoptimizePartners();
230 + new autoptimizeExitSurvey();
231 + new autoptimizeProTab();
197 232 }
198 233 }
199 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 +
200 280 public function hook_page_cache_purge()
201 281 {
202 282 // hook into a collection of page cache purge actions if filter allows.
203 283 if ( apply_filters( 'autoptimize_filter_main_hookpagecachepurge', true ) ) {
@@ -206,12 +286,15 @@
206 286 'hyper_cache_purged', // Stefano confirmed this will be added.
207 287 'w3tc_flush_posts', // exits.
208 288 'w3tc_flush_all', // exists.
209 289 'ce_action_cache_cleared', // Sven confirmed this will be added.
290 + 'aoce_action_cache_cleared', // Some other cache enabler.
210 291 'comet_cache_wipe_cache', // still to be confirmed by Raam.
211 292 'wp_cache_cleared', // cfr. https://github.com/Automattic/wp-super-cache/pull/537.
212 293 'wpfc_delete_cache', // Emre confirmed this will be added this.
213 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.
214 297 );
215 298 $page_cache_purge_actions = apply_filters( 'autoptimize_filter_main_pagecachepurgeactions', $page_cache_purge_actions );
216 299 foreach ( $page_cache_purge_actions as $purge_action ) {
217 300 add_action( $purge_action, 'autoptimizeCache::clearall_actionless' );
@@ -267,9 +350,9 @@
267 350 * @param bool $doing_tests Allows overriding the optimization of only
268 351 * deciding once per request (for use in tests).
269 352 * @return bool
270 353 */
271 - public function should_buffer( $doing_tests = false )
354 + public static function should_buffer( $doing_tests = false )
272 355 {
273 356 static $do_buffering = null;
274 357
275 358 // Only check once in case we're called multiple times by others but
@@ -299,16 +382,16 @@
299 382 }
300 383 }
301 384
302 385 // If setting says not to optimize logged in user and user is logged in...
303 - 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' ) ) {
304 387 $ao_noptimize = true;
305 388 }
306 389
307 390 // If setting says not to optimize cart/checkout.
308 - if ( 'on' !== get_option( 'autoptimize_optimize_checkout', 'on' ) ) {
391 + if ( false === $ao_noptimize && 'on' !== autoptimizeOptionWrapper::get_option( 'autoptimize_optimize_checkout', 'off' ) ) {
309 392 // Checking for woocommerce, easy digital downloads and wp ecommerce...
310 - 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 ) {
311 394 if ( function_exists( $func ) && $func() ) {
312 395 $ao_noptimize = true;
313 396 break;
314 397 }
@@ -314,9 +397,38 @@
314 397 }
315 398 }
316 399 }
317 400
318 - // 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.
319 431 $ao_noptimize = (bool) apply_filters( 'autoptimize_filter_noptimize', $ao_noptimize );
320 432
321 433 // Check for site being previewed in the Customizer (available since WP 4.0).
322 434 $is_customize_preview = false;
@@ -322,8 +434,14 @@
322 434 $is_customize_preview = false;
323 435 if ( function_exists( 'is_customize_preview' ) && is_customize_preview() ) {
324 436 $is_customize_preview = is_customize_preview();
325 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 + }
326 444
327 445 /**
328 446 * We only buffer the frontend requests (and then only if not a feed
329 447 * and not turned off explicitly and not when being previewed in Customizer)!
@@ -330,9 +448,9 @@
330 448 * NOTE: Tests throw a notice here due to is_feed() being called
331 449 * while the main query hasn't been ran yet. Thats why we use
332 450 * AUTOPTIMIZE_INIT_EARLIER in tests.
333 451 */
334 - $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 );
335 453 }
336 454
337 455 return $do_buffering;
338 456 }
@@ -349,10 +467,11 @@
349 467 // Defaults to true.
350 468 $valid = true;
351 469
352 470 $has_no_html_tag = ( false === stripos( $content, '<html' ) );
353 - $has_xsl_stylesheet = ( false !== stripos( $content, '<xsl:stylesheet' ) );
471 + $has_xsl_stylesheet = ( false !== stripos( $content, '<xsl:stylesheet' ) || false !== stripos( $content, '<?xml-stylesheet' ) );
354 472 $has_html5_doctype = ( preg_match( '/^<!DOCTYPE.+html>/i', ltrim( $content ) ) > 0 );
473 + $has_noptimize_page = ( false !== stripos( $content, '<!-- noptimize-page -->' ) );
355 474
356 475 if ( $has_no_html_tag ) {
357 476 // Can't be valid amp markup without an html tag preceding it.
358 477 $is_amp_markup = false;
@@ -360,9 +479,9 @@
360 479 $is_amp_markup = self::is_amp_markup( $content );
361 480 }
362 481
363 482 // If it's not html, or if it's amp or contains xsl stylesheets we don't touch it.
364 - 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 ) {
365 484 $valid = false;
366 485 }
367 486
368 487 return $valid;
@@ -377,11 +496,31 @@
377 496 * @return bool
378 497 */
379 498 public static function is_amp_markup( $content )
380 499 {
381 - $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 + }
382 514
383 - 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;
384 523 }
385 524
386 525 /**
387 526 * Processes/optimizes the output-buffered content and returns it.
@@ -413,30 +552,35 @@
413 552 }
414 553
415 554 $classoptions = array(
416 555 'autoptimizeScripts' => array(
417 - 'aggregate' => $conf->get( 'autoptimize_js_aggregate' ),
418 - 'justhead' => $conf->get( 'autoptimize_js_justhead' ),
419 - 'forcehead' => $conf->get( 'autoptimize_js_forcehead' ),
420 - 'trycatch' => $conf->get( 'autoptimize_js_trycatch' ),
421 - 'js_exclude' => $conf->get( 'autoptimize_js_exclude' ),
422 - 'cdn_url' => $conf->get( 'autoptimize_cdn_url' ),
423 - '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' ),
424 566 ),
425 567 'autoptimizeStyles' => array(
426 - 'aggregate' => $conf->get( 'autoptimize_css_aggregate' ),
427 - 'justhead' => $conf->get( 'autoptimize_css_justhead' ),
428 - 'datauris' => $conf->get( 'autoptimize_css_datauris' ),
429 - 'defer' => $conf->get( 'autoptimize_css_defer' ),
430 - 'defer_inline' => $conf->get( 'autoptimize_css_defer_inline' ),
431 - 'inline' => $conf->get( 'autoptimize_css_inline' ),
432 - 'css_exclude' => $conf->get( 'autoptimize_css_exclude' ),
433 - 'cdn_url' => $conf->get( 'autoptimize_cdn_url' ),
434 - 'include_inline' => $conf->get( 'autoptimize_css_include_inline' ),
435 - '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' ),
436 579 ),
437 580 'autoptimizeHTML' => array(
438 - 'keepcomments' => $conf->get( 'autoptimize_html_keepcomments' ),
581 + 'keepcomments' => $conf->get( 'autoptimize_html_keepcomments' ),
582 + 'minify_inline' => $conf->get( 'autoptimize_html_minify_inline' ),
439 583 ),
440 584 );
441 585
442 586 $content = apply_filters( 'autoptimize_filter_html_before_minify', $content );
@@ -456,12 +600,33 @@
456 600
457 601 return $content;
458 602 }
459 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 +
460 618 public static function on_uninstall()
461 619 {
620 + // clear the cache.
462 621 autoptimizeCache::clearall();
463 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.
464 629 $delete_options = array(
465 630 'autoptimize_cache_clean',
466 631 'autoptimize_cache_nogzip',
467 632 'autoptimize_css',
@@ -473,10 +638,15 @@
473 638 'autoptimize_css_inline',
474 639 'autoptimize_css_exclude',
475 640 'autoptimize_html',
476 641 'autoptimize_html_keepcomments',
642 + 'autoptimize_html_minify_inline',
643 + 'autoptimize_enable_site_config',
644 + 'autoptimize_enable_meta_ao_settings',
477 645 'autoptimize_js',
478 646 'autoptimize_js_aggregate',
647 + 'autoptimize_js_defer_not_aggregate',
648 + 'autoptimize_js_defer_inline',
479 649 'autoptimize_js_exclude',
480 650 'autoptimize_js_forcehead',
481 651 'autoptimize_js_justhead',
482 652 'autoptimize_js_trycatch',
@@ -491,8 +661,29 @@
491 661 'autoptimize_extra_settings',
492 662 'autoptimize_service_availablity',
493 663 'autoptimize_imgopt_provider_stat',
494 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',
495 686 );
496 687
497 688 if ( ! is_multisite() ) {
498 689 foreach ( $delete_options as $del_opt ) {
@@ -497,8 +688,9 @@
497 688 if ( ! is_multisite() ) {
498 689 foreach ( $delete_options as $del_opt ) {
499 690 delete_option( $del_opt );
500 691 }
692 + autoptimizeMain::remove_cronjobs();
501 693 } else {
502 694 global $wpdb;
503 695 $blog_ids = $wpdb->get_col( "SELECT blog_id FROM $wpdb->blogs" );
504 696 $original_blog_id = get_current_blog_id();
@@ -506,22 +698,60 @@
506 698 switch_to_blog( $blog_id );
507 699 foreach ( $delete_options as $del_opt ) {
508 700 delete_option( $del_opt );
509 701 }
702 + autoptimizeMain::remove_cronjobs();
510 703 }
511 704 switch_to_blog( $original_blog_id );
512 705 }
513 706
514 - if ( wp_get_schedule( 'ao_cachechecker' ) ) {
515 - 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 );
516 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 + }
517 721 }
518 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 +
519 749 public static function notice_cache_unavailable()
520 750 {
521 751 echo '<div class="error"><p>';
522 752 // Translators: %s is the cache directory location.
523 - 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 );
524 754 echo '</p></div>';
525 755 }
526 756
527 757 public static function notice_installed()
@@ -526,9 +756,10 @@
526 756
527 757 public static function notice_installed()
528 758 {
529 759 echo '<div class="updated"><p>';
530 - _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>' );
531 762 echo '</p></div>';
532 763 }
533 764
534 765 public static function notice_updated()
@@ -533,9 +764,9 @@
533 764
534 765 public static function notice_updated()
535 766 {
536 767 echo '<div class="updated"><p>';
537 - _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>' );
538 769 echo '</p></div>';
539 770 }
540 771
541 772 public static function notice_plug_imgopt()
@@ -540,23 +771,85 @@
540 771
541 772 public static function notice_plug_imgopt()
542 773 {
543 774 // Translators: the URL added points to the Autopmize Extra settings.
544 - $_ao_imgopt_plug_notice = sprintf( __( 'Did you know Autoptimize includes on-the-fly image optimization and CDN via ShortPixel? Check out the %1$sAutoptimize Extra settings%2$s to activate this option.', 'autoptimize' ), '<a href="options-general.php?page=autoptimize_extra">', '</a>' );
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>' );
545 776 $_ao_imgopt_plug_notice = apply_filters( 'autoptimize_filter_main_imgopt_plug_notice', $_ao_imgopt_plug_notice );
546 - $_ao_imgopt_launch_ok = autoptimizeExtra::imgopt_launch_ok_wrapper();
777 + $_ao_imgopt_launch_ok = autoptimizeImages::launch_ok_wrapper();
547 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();
548 781
549 - // check if AO is optimizing images already.
550 - $_ao_imgopt_active = false;
551 - $_ao_extra_options = get_option( 'autoptimize_extra_settings', '' );
552 - if ( is_array( $_ao_extra_options ) && array_key_exists( 'autoptimize_extra_checkbox_field_5', $_ao_extra_options ) && ! empty( $_ao_extra_options['autoptimize_extra_checkbox_field_5'] ) ) {
553 - $_ao_imgopt_active = true;
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>';
554 786 }
787 + }
555 788
556 - if ( current_user_can( 'manage_options' ) && '' !== $_ao_imgopt_plug_notice && ! $_ao_imgopt_active && $_ao_imgopt_launch_ok && PAnD::is_admin_notice_active( $_ao_imgopt_plug_dismissible ) ) {
557 - echo '<div class="notice notice-info is-dismissible" data-dismissible="' . $_ao_imgopt_plug_dismissible . '"><p>';
558 - echo $_ao_imgopt_plug_notice;
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;
559 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 + }
560 853 }
561 854 }
562 855 }