PluginProbe
Autoptimize / 2.8.2
Autoptimize v2.8.2
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 2.7.8 All 107 releases
autoptimize / classes / autoptimizeMain.php

autoptimizeMain.php in Autoptimize 2.8.2, at classes/autoptimizeMain.php

701 lines 28.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Wraps base plugin logic/hooks and handles activation/deactivation/uninstall.
4 */
5
6 if ( ! defined( 'ABSPATH' ) ) {
7 exit;
8 }
9
10 class autoptimizeMain
11 {
12 const INIT_EARLIER_PRIORITY = -1;
13 const DEFAULT_HOOK_PRIORITY = 2;
14
15 /**
16 * Version string.
17 *
18 * @var string
19 */
20 protected $version = null;
21
22 /**
23 * Main plugin filepath.
24 * Used for activation/deactivation/uninstall hooks.
25 *
26 * @var string
27 */
28 protected $filepath = null;
29
30 /**
31 * Constructor.
32 *
33 * @param string $version Version.
34 * @param string $filepath Filepath. Needed for activation/deactivation/uninstall hooks.
35 */
36 public function __construct( $version, $filepath )
37 {
38 $this->version = $version;
39 $this->filepath = $filepath;
40 }
41
42 public function run()
43 {
44 $this->add_hooks();
45
46 // Runs cache size checker.
47 $checker = new autoptimizeCacheChecker();
48 $checker->run();
49 }
50
51 protected function add_hooks()
52 {
53 if ( ! defined( 'AUTOPTIMIZE_SETUP_INITHOOK' ) ) {
54 define( 'AUTOPTIMIZE_SETUP_INITHOOK', 'plugins_loaded' );
55 }
56
57 add_action( AUTOPTIMIZE_SETUP_INITHOOK, array( $this, 'setup' ) );
58 add_action( AUTOPTIMIZE_SETUP_INITHOOK, array( $this, 'hook_page_cache_purge' ) );
59
60 add_action( 'autoptimize_setup_done', array( $this, 'version_upgrades_check' ) );
61 add_action( 'autoptimize_setup_done', array( $this, 'check_cache_and_run' ) );
62 add_action( 'autoptimize_setup_done', array( $this, 'maybe_run_ao_extra' ), 15 );
63 add_action( 'autoptimize_setup_done', array( $this, 'maybe_run_partners_tab' ), 20 );
64 add_action( 'autoptimize_setup_done', array( $this, 'maybe_run_criticalcss' ), 11 );
65 add_action( 'autoptimize_setup_done', array( $this, 'maybe_run_notfound_fallback' ), 10 );
66
67 add_action( 'init', array( $this, 'load_textdomain' ) );
68
69 if ( is_multisite() && is_admin() ) {
70 // Only if multisite and if in admin we want to check if we need to save options on network level.
71 add_action( 'init', 'autoptimizeOptionWrapper::check_multisite_on_saving_options' );
72 }
73
74 // register uninstall & deactivation hooks.
75 register_uninstall_hook( $this->filepath, 'autoptimizeMain::on_uninstall' );
76 register_deactivation_hook( $this->filepath, 'autoptimizeMain::on_deactivation' );
77 }
78
79 public function load_textdomain()
80 {
81 load_plugin_textdomain( 'autoptimize' );
82 }
83
84 public function setup()
85 {
86 // Do we gzip in php when caching or is the webserver doing it?
87 define( 'AUTOPTIMIZE_CACHE_NOGZIP', (bool) autoptimizeOptionWrapper::get_option( 'autoptimize_cache_nogzip' ) );
88
89 // These can be overridden by specifying them in wp-config.php or such.
90 if ( ! defined( 'AUTOPTIMIZE_WP_CONTENT_NAME' ) ) {
91 define( 'AUTOPTIMIZE_WP_CONTENT_NAME', '/' . wp_basename( WP_CONTENT_DIR ) );
92 }
93 if ( ! defined( 'AUTOPTIMIZE_CACHE_CHILD_DIR' ) ) {
94 define( 'AUTOPTIMIZE_CACHE_CHILD_DIR', '/cache/autoptimize/' );
95 }
96 if ( ! defined( 'AUTOPTIMIZE_CACHEFILE_PREFIX' ) ) {
97 define( 'AUTOPTIMIZE_CACHEFILE_PREFIX', 'autoptimize_' );
98 }
99 // Note: trailing slash is not optional!
100 if ( ! defined( 'AUTOPTIMIZE_CACHE_DIR' ) ) {
101 define( 'AUTOPTIMIZE_CACHE_DIR', autoptimizeCache::get_pathname() );
102 }
103
104 define( 'WP_ROOT_DIR', substr( WP_CONTENT_DIR, 0, strlen( WP_CONTENT_DIR ) - strlen( AUTOPTIMIZE_WP_CONTENT_NAME ) ) );
105
106 if ( ! defined( 'AUTOPTIMIZE_WP_SITE_URL' ) ) {
107 if ( function_exists( 'domain_mapping_siteurl' ) ) {
108 define( 'AUTOPTIMIZE_WP_SITE_URL', domain_mapping_siteurl( get_current_blog_id() ) );
109 } else {
110 define( 'AUTOPTIMIZE_WP_SITE_URL', site_url() );
111 }
112 }
113 if ( ! defined( 'AUTOPTIMIZE_WP_CONTENT_URL' ) ) {
114 if ( function_exists( 'get_original_url' ) ) {
115 define( 'AUTOPTIMIZE_WP_CONTENT_URL', str_replace( get_original_url( AUTOPTIMIZE_WP_SITE_URL ), AUTOPTIMIZE_WP_SITE_URL, content_url() ) );
116 } else {
117 define( 'AUTOPTIMIZE_WP_CONTENT_URL', content_url() );
118 }
119 }
120 if ( ! defined( 'AUTOPTIMIZE_CACHE_URL' ) ) {
121 if ( is_multisite() && apply_filters( 'autoptimize_separate_blog_caches', true ) ) {
122 $blog_id = get_current_blog_id();
123 define( 'AUTOPTIMIZE_CACHE_URL', AUTOPTIMIZE_WP_CONTENT_URL . AUTOPTIMIZE_CACHE_CHILD_DIR . $blog_id . '/' );
124 } else {
125 define( 'AUTOPTIMIZE_CACHE_URL', AUTOPTIMIZE_WP_CONTENT_URL . AUTOPTIMIZE_CACHE_CHILD_DIR );
126 }
127 }
128 if ( ! defined( 'AUTOPTIMIZE_WP_ROOT_URL' ) ) {
129 define( 'AUTOPTIMIZE_WP_ROOT_URL', str_replace( AUTOPTIMIZE_WP_CONTENT_NAME, '', AUTOPTIMIZE_WP_CONTENT_URL ) );
130 }
131 if ( ! defined( 'AUTOPTIMIZE_HASH' ) ) {
132 define( 'AUTOPTIMIZE_HASH', wp_hash( AUTOPTIMIZE_CACHE_URL ) );
133 }
134 if ( ! defined( 'AUTOPTIMIZE_SITE_DOMAIN' ) ) {
135 define( 'AUTOPTIMIZE_SITE_DOMAIN', parse_url( AUTOPTIMIZE_WP_SITE_URL, PHP_URL_HOST ) );
136 }
137
138 // Multibyte-capable string replacements are available with a filter.
139 // Also requires 'mbstring' extension.
140 $with_mbstring = apply_filters( 'autoptimize_filter_main_use_mbstring', false );
141 if ( $with_mbstring ) {
142 autoptimizeUtils::mbstring_available( \extension_loaded( 'mbstring' ) );
143 } else {
144 autoptimizeUtils::mbstring_available( false );
145 }
146
147 do_action( 'autoptimize_setup_done' );
148 }
149
150 /**
151 * Checks if there's a need to upgrade/update options and whatnot,
152 * in which case we might need to do stuff and flush the cache
153 * to avoid old versions of aggregated files lingering around.
154 */
155 public function version_upgrades_check()
156 {
157 autoptimizeVersionUpdatesHandler::check_installed_and_update( $this->version );
158 }
159
160 public function check_cache_and_run()
161 {
162 if ( autoptimizeCache::cacheavail() ) {
163 $conf = autoptimizeConfig::instance();
164 if ( $conf->get( 'autoptimize_html' ) || $conf->get( 'autoptimize_js' ) || $conf->get( 'autoptimize_css' ) || autoptimizeImages::imgopt_active() || autoptimizeImages::should_lazyload_wrapper() ) {
165 if ( ! defined( 'AUTOPTIMIZE_NOBUFFER_OPTIMIZE' ) ) {
166 // Hook into WordPress frontend.
167 if ( defined( 'AUTOPTIMIZE_INIT_EARLIER' ) ) {
168 add_action(
169 'init',
170 array( $this, 'start_buffering' ),
171 self::INIT_EARLIER_PRIORITY
172 );
173 } else {
174 if ( ! defined( 'AUTOPTIMIZE_HOOK_INTO' ) ) {
175 define( 'AUTOPTIMIZE_HOOK_INTO', 'template_redirect' );
176 }
177 add_action(
178 constant( 'AUTOPTIMIZE_HOOK_INTO' ),
179 array( $this, 'start_buffering' ),
180 self::DEFAULT_HOOK_PRIORITY
181 );
182 }
183 }
184
185 // And disable Jetpack's site accelerator if JS or CSS opt. are active.
186 if ( class_exists( 'Jetpack' ) && apply_filters( 'autoptimize_filter_main_disable_jetpack_cdn', true ) && ( $conf->get( 'autoptimize_js' ) || $conf->get( 'autoptimize_css' ) ) ) {
187 add_filter( 'jetpack_force_disable_site_accelerator', '__return_true' );
188 }
189 }
190 } else {
191 add_action( 'admin_notices', 'autoptimizeMain::notice_cache_unavailable' );
192 }
193 }
194
195 public function maybe_run_ao_extra()
196 {
197 if ( apply_filters( 'autoptimize_filter_extra_activate', true ) ) {
198 $ao_imgopt = new autoptimizeImages();
199 $ao_imgopt->run();
200 $ao_extra = new autoptimizeExtra();
201 $ao_extra->run();
202
203 // And show the imgopt notice.
204 add_action( 'admin_notices', 'autoptimizeMain::notice_plug_imgopt' );
205 }
206 }
207
208 public function maybe_run_partners_tab()
209 {
210 // Loads partners tab code if in admin (and not in admin-ajax.php)!
211 if ( autoptimizeConfig::is_admin_and_not_ajax() ) {
212 new autoptimizePartners();
213 }
214 }
215
216 public function maybe_run_criticalcss()
217 {
218 // Loads criticalcss if the power-up is not active and if the filter returns true.
219 if ( apply_filters( 'autoptimize_filter_criticalcss_active', true ) && ! autoptimizeUtils::is_plugin_active( 'autoptimize-criticalcss/ao_criticss_aas.php' ) ) {
220 new autoptimizeCriticalCSSBase();
221 }
222 }
223
224 public function maybe_run_notfound_fallback()
225 {
226 if ( autoptimizeCache::do_fallback() ) {
227 add_action( 'template_redirect', array( 'autoptimizeCache', 'wordpress_notfound_fallback' ) );
228 }
229 }
230
231 public function hook_page_cache_purge()
232 {
233 // hook into a collection of page cache purge actions if filter allows.
234 if ( apply_filters( 'autoptimize_filter_main_hookpagecachepurge', true ) ) {
235 $page_cache_purge_actions = array(
236 'after_rocket_clean_domain', // exists.
237 'hyper_cache_purged', // Stefano confirmed this will be added.
238 'w3tc_flush_posts', // exits.
239 'w3tc_flush_all', // exists.
240 'ce_action_cache_cleared', // Sven confirmed this will be added.
241 'aoce_action_cache_cleared', // Some other cache enabler.
242 'comet_cache_wipe_cache', // still to be confirmed by Raam.
243 'wp_cache_cleared', // cfr. https://github.com/Automattic/wp-super-cache/pull/537.
244 'wpfc_delete_cache', // Emre confirmed this will be added this.
245 'swift_performance_after_clear_all_cache', // swift perf. yeah!
246 'wpo_cache_flush', // wp-optimize.
247 'rt_nginx_helper_after_fastcgi_purge_all', // nginx helper.
248 );
249 $page_cache_purge_actions = apply_filters( 'autoptimize_filter_main_pagecachepurgeactions', $page_cache_purge_actions );
250 foreach ( $page_cache_purge_actions as $purge_action ) {
251 add_action( $purge_action, 'autoptimizeCache::clearall_actionless' );
252 }
253 }
254 }
255
256 /**
257 * Setup output buffering if needed.
258 *
259 * @return void
260 */
261 public function start_buffering()
262 {
263 if ( $this->should_buffer() ) {
264
265 // Load speedupper conditionally (true by default).
266 if ( apply_filters( 'autoptimize_filter_speedupper', true ) ) {
267 $ao_speedupper = new autoptimizeSpeedupper();
268 }
269
270 $conf = autoptimizeConfig::instance();
271
272 if ( $conf->get( 'autoptimize_js' ) ) {
273 if ( ! defined( 'CONCATENATE_SCRIPTS' ) ) {
274 define( 'CONCATENATE_SCRIPTS', false );
275 }
276 if ( ! defined( 'COMPRESS_SCRIPTS' ) ) {
277 define( 'COMPRESS_SCRIPTS', false );
278 }
279 }
280
281 if ( $conf->get( 'autoptimize_css' ) ) {
282 if ( ! defined( 'COMPRESS_CSS' ) ) {
283 define( 'COMPRESS_CSS', false );
284 }
285 }
286
287 if ( apply_filters( 'autoptimize_filter_obkiller', false ) ) {
288 while ( ob_get_level() > 0 ) {
289 ob_end_clean();
290 }
291 }
292
293 // Now, start the real thing!
294 ob_start( array( $this, 'end_buffering' ) );
295 }
296 }
297
298 /**
299 * Returns true if all the conditions to start output buffering are satisfied.
300 *
301 * @param bool $doing_tests Allows overriding the optimization of only
302 * deciding once per request (for use in tests).
303 * @return bool
304 */
305 public static function should_buffer( $doing_tests = false )
306 {
307 static $do_buffering = null;
308
309 // Only check once in case we're called multiple times by others but
310 // still allows multiple calls when doing tests.
311 if ( null === $do_buffering || $doing_tests ) {
312
313 $ao_noptimize = false;
314
315 // Checking for DONOTMINIFY constant as used by e.g. WooCommerce POS.
316 if ( defined( 'DONOTMINIFY' ) && ( constant( 'DONOTMINIFY' ) === true || constant( 'DONOTMINIFY' ) === 'true' ) ) {
317 $ao_noptimize = true;
318 }
319
320 // Skip checking query strings if they're disabled.
321 if ( apply_filters( 'autoptimize_filter_honor_qs_noptimize', true ) ) {
322 // Check for `ao_noptimize` (and other) keys in the query string
323 // to get non-optimized page for debugging.
324 $keys = array(
325 'ao_noptimize',
326 'ao_noptirocket',
327 );
328 foreach ( $keys as $key ) {
329 if ( array_key_exists( $key, $_GET ) && '1' === $_GET[ $key ] ) {
330 $ao_noptimize = true;
331 break;
332 }
333 }
334 }
335
336 // If setting says not to optimize logged in user and user is logged in...
337 if ( false === $ao_noptimize && 'on' !== autoptimizeOptionWrapper::get_option( 'autoptimize_optimize_logged', 'on' ) && is_user_logged_in() && current_user_can( 'edit_posts' ) ) {
338 $ao_noptimize = true;
339 }
340
341 // If setting says not to optimize cart/checkout.
342 if ( false === $ao_noptimize && 'on' !== autoptimizeOptionWrapper::get_option( 'autoptimize_optimize_checkout', 'off' ) ) {
343 // Checking for woocommerce, easy digital downloads and wp ecommerce...
344 foreach ( array( 'is_checkout', 'is_cart', 'is_account_page', 'edd_is_checkout', 'wpsc_is_cart', 'wpsc_is_checkout' ) as $func ) {
345 if ( function_exists( $func ) && $func() ) {
346 $ao_noptimize = true;
347 break;
348 }
349 }
350 }
351
352 // And make sure pagebuilder previews don't get optimized HTML/ JS/ CSS/ ...
353 if ( false === $ao_noptimize ) {
354 $_qs_pagebuilders = array( 'tve', 'elementor-preview', 'fl_builder', 'vc_action', 'et_fb', 'bt-beaverbuildertheme', 'ct_builder', 'fb-edit', 'siteorigin_panels_live_editor' );
355 foreach ( $_qs_pagebuilders as $_pagebuilder ) {
356 if ( array_key_exists( $_pagebuilder, $_GET ) ) {
357 $ao_noptimize = true;
358 break;
359 }
360 }
361 }
362
363 // Also honor PageSpeed=off parameter as used by mod_pagespeed, in use by some pagebuilders,
364 // see https://www.modpagespeed.com/doc/experiment#ModPagespeed for info on that.
365 if ( false === $ao_noptimize && array_key_exists( 'PageSpeed', $_GET ) && 'off' === $_GET['PageSpeed'] ) {
366 $ao_noptimize = true;
367 }
368
369 // And finally allows blocking of autoptimization on your own terms regardless of above decisions.
370 $ao_noptimize = (bool) apply_filters( 'autoptimize_filter_noptimize', $ao_noptimize );
371
372 // Check for site being previewed in the Customizer (available since WP 4.0).
373 $is_customize_preview = false;
374 if ( function_exists( 'is_customize_preview' ) && is_customize_preview() ) {
375 $is_customize_preview = is_customize_preview();
376 }
377
378 /**
379 * We only buffer the frontend requests (and then only if not a feed
380 * and not turned off explicitly and not when being previewed in Customizer)!
381 * NOTE: Tests throw a notice here due to is_feed() being called
382 * while the main query hasn't been ran yet. Thats why we use
383 * AUTOPTIMIZE_INIT_EARLIER in tests.
384 */
385 $do_buffering = ( ! is_admin() && ! is_feed() && ! is_embed() && ! $ao_noptimize && ! $is_customize_preview );
386 }
387
388 return $do_buffering;
389 }
390
391 /**
392 * Returns true if given markup is considered valid/processable/optimizable.
393 *
394 * @param string $content Markup.
395 *
396 * @return bool
397 */
398 public function is_valid_buffer( $content )
399 {
400 // Defaults to true.
401 $valid = true;
402
403 $has_no_html_tag = ( false === stripos( $content, '<html' ) );
404 $has_xsl_stylesheet = ( false !== stripos( $content, '<xsl:stylesheet' ) || false !== stripos( $content, '<?xml-stylesheet' ) );
405 $has_html5_doctype = ( preg_match( '/^<!DOCTYPE.+html>/i', ltrim( $content ) ) > 0 );
406 $has_noptimize_page = ( false !== stripos( $content, '<!-- noptimize-page -->' ) );
407
408 if ( $has_no_html_tag ) {
409 // Can't be valid amp markup without an html tag preceding it.
410 $is_amp_markup = false;
411 } else {
412 $is_amp_markup = self::is_amp_markup( $content );
413 }
414
415 // If it's not html, or if it's amp or contains xsl stylesheets we don't touch it.
416 if ( $has_no_html_tag && ! $has_html5_doctype || $is_amp_markup || $has_xsl_stylesheet || $has_noptimize_page ) {
417 $valid = false;
418 }
419
420 return $valid;
421 }
422
423 /**
424 * Returns true if given $content is considered to be AMP markup.
425 * This is far from actual validation against AMP spec, but it'll do for now.
426 *
427 * @param string $content Markup to check.
428 *
429 * @return bool
430 */
431 public static function is_amp_markup( $content )
432 {
433 // Short-circuit if the page is already AMP from the start.
434 if (
435 preg_match(
436 sprintf(
437 '#^(?:<!.*?>|\s+)*+<html(?=\s)[^>]*?\s(%1$s|%2$s|%3$s)(\s|=|>)#is',
438 'amp',
439 "\xE2\x9A\xA1", // From \AmpProject\Attribute::AMP_EMOJI.
440 "\xE2\x9A\xA1\xEF\xB8\x8F" // From \AmpProject\Attribute::AMP_EMOJI_ALT, per https://github.com/ampproject/amphtml/issues/25990.
441 ),
442 $content
443 )
444 ) {
445 return true;
446 }
447
448 // Or else short-circuit if the AMP plugin will be processing the output to be an AMP page.
449 if ( function_exists( 'amp_is_request' ) ) {
450 return amp_is_request(); // For AMP plugin v2.0+.
451 } elseif ( function_exists( 'is_amp_endpoint' ) ) {
452 return is_amp_endpoint(); // For older/other AMP plugins (still supported in 2.0 as an alias).
453 }
454
455 return false;
456 }
457
458 /**
459 * Processes/optimizes the output-buffered content and returns it.
460 * If the content is not processable, it is returned unmodified.
461 *
462 * @param string $content Buffered content.
463 *
464 * @return string
465 */
466 public function end_buffering( $content )
467 {
468 // Bail early without modifying anything if we can't handle the content.
469 if ( ! $this->is_valid_buffer( $content ) ) {
470 return $content;
471 }
472
473 $conf = autoptimizeConfig::instance();
474
475 // Determine what needs to be ran.
476 $classes = array();
477 if ( $conf->get( 'autoptimize_js' ) ) {
478 $classes[] = 'autoptimizeScripts';
479 }
480 if ( $conf->get( 'autoptimize_css' ) ) {
481 $classes[] = 'autoptimizeStyles';
482 }
483 if ( $conf->get( 'autoptimize_html' ) ) {
484 $classes[] = 'autoptimizeHTML';
485 }
486
487 $classoptions = array(
488 'autoptimizeScripts' => array(
489 'aggregate' => $conf->get( 'autoptimize_js_aggregate' ),
490 'defer_not_aggregate' => $conf->get( 'autoptimize_js_defer_not_aggregate' ),
491 'justhead' => $conf->get( 'autoptimize_js_justhead' ),
492 'forcehead' => $conf->get( 'autoptimize_js_forcehead' ),
493 'trycatch' => $conf->get( 'autoptimize_js_trycatch' ),
494 'js_exclude' => $conf->get( 'autoptimize_js_exclude' ),
495 'cdn_url' => $conf->get( 'autoptimize_cdn_url' ),
496 'include_inline' => $conf->get( 'autoptimize_js_include_inline' ),
497 'minify_excluded' => $conf->get( 'autoptimize_minify_excluded' ),
498 ),
499 'autoptimizeStyles' => array(
500 'aggregate' => $conf->get( 'autoptimize_css_aggregate' ),
501 'justhead' => $conf->get( 'autoptimize_css_justhead' ),
502 'datauris' => $conf->get( 'autoptimize_css_datauris' ),
503 'defer' => $conf->get( 'autoptimize_css_defer' ),
504 'defer_inline' => $conf->get( 'autoptimize_css_defer_inline' ),
505 'inline' => $conf->get( 'autoptimize_css_inline' ),
506 'css_exclude' => $conf->get( 'autoptimize_css_exclude' ),
507 'cdn_url' => $conf->get( 'autoptimize_cdn_url' ),
508 'include_inline' => $conf->get( 'autoptimize_css_include_inline' ),
509 'nogooglefont' => $conf->get( 'autoptimize_css_nogooglefont' ),
510 'minify_excluded' => $conf->get( 'autoptimize_minify_excluded' ),
511 ),
512 'autoptimizeHTML' => array(
513 'keepcomments' => $conf->get( 'autoptimize_html_keepcomments' ),
514 ),
515 );
516
517 $content = apply_filters( 'autoptimize_filter_html_before_minify', $content );
518
519 // Run the classes!
520 foreach ( $classes as $name ) {
521 $instance = new $name( $content );
522 if ( $instance->read( $classoptions[ $name ] ) ) {
523 $instance->minify();
524 $instance->cache();
525 $content = $instance->getcontent();
526 }
527 unset( $instance );
528 }
529
530 $content = apply_filters( 'autoptimize_html_after_minify', $content );
531
532 return $content;
533 }
534
535 public static function autoptimize_nobuffer_optimize( $html_in ) {
536 $html_out = $html_in;
537
538 if ( apply_filters( 'autoptimize_filter_speedupper', true ) ) {
539 $ao_speedupper = new autoptimizeSpeedupper();
540 }
541
542 $self = new self( AUTOPTIMIZE_PLUGIN_VERSION, AUTOPTIMIZE_PLUGIN_FILE );
543 if ( $self->should_buffer() ) {
544 $html_out = $self->end_buffering( $html_in );
545 }
546 return $html_out;
547 }
548
549 public static function on_uninstall()
550 {
551 autoptimizeCache::clearall();
552
553 $delete_options = array(
554 'autoptimize_cache_clean',
555 'autoptimize_cache_nogzip',
556 'autoptimize_css',
557 'autoptimize_css_aggregate',
558 'autoptimize_css_datauris',
559 'autoptimize_css_justhead',
560 'autoptimize_css_defer',
561 'autoptimize_css_defer_inline',
562 'autoptimize_css_inline',
563 'autoptimize_css_exclude',
564 'autoptimize_html',
565 'autoptimize_html_keepcomments',
566 'autoptimize_enable_site_config',
567 'autoptimize_js',
568 'autoptimize_js_aggregate',
569 'autoptimize_js_defer_not_aggregate',
570 'autoptimize_js_exclude',
571 'autoptimize_js_forcehead',
572 'autoptimize_js_justhead',
573 'autoptimize_js_trycatch',
574 'autoptimize_version',
575 'autoptimize_show_adv',
576 'autoptimize_cdn_url',
577 'autoptimize_cachesize_notice',
578 'autoptimize_css_include_inline',
579 'autoptimize_js_include_inline',
580 'autoptimize_optimize_logged',
581 'autoptimize_optimize_checkout',
582 'autoptimize_extra_settings',
583 'autoptimize_service_availablity',
584 'autoptimize_imgopt_provider_stat',
585 'autoptimize_imgopt_launched',
586 'autoptimize_imgopt_settings',
587 'autoptimize_minify_excluded',
588 'autoptimize_cache_fallback',
589 'autoptimize_ccss_rules',
590 'autoptimize_ccss_additional',
591 'autoptimize_ccss_queue',
592 'autoptimize_ccss_viewport',
593 'autoptimize_ccss_finclude',
594 'autoptimize_ccss_rlimit',
595 'autoptimize_ccss_rtimelimit',
596 'autoptimize_ccss_noptimize',
597 'autoptimize_ccss_debug',
598 'autoptimize_ccss_key',
599 'autoptimize_ccss_keyst',
600 'autoptimize_ccss_version',
601 'autoptimize_ccss_loggedin',
602 'autoptimize_ccss_forcepath',
603 'autoptimize_ccss_deferjquery',
604 'autoptimize_ccss_domain',
605 'autoptimize_ccss_unloadccss',
606 );
607
608 if ( ! is_multisite() ) {
609 foreach ( $delete_options as $del_opt ) {
610 delete_option( $del_opt );
611 }
612 autoptimizeMain::remove_cronjobs();
613 } else {
614 global $wpdb;
615 $blog_ids = $wpdb->get_col( "SELECT blog_id FROM $wpdb->blogs" );
616 $original_blog_id = get_current_blog_id();
617 foreach ( $blog_ids as $blog_id ) {
618 switch_to_blog( $blog_id );
619 foreach ( $delete_options as $del_opt ) {
620 delete_option( $del_opt );
621 }
622 autoptimizeMain::remove_cronjobs();
623 }
624 switch_to_blog( $original_blog_id );
625 }
626
627 // Remove AO CCSS cached files and directory.
628 $ao_ccss_dir = WP_CONTENT_DIR . '/uploads/ao_ccss/';
629 if ( file_exists( $ao_ccss_dir ) && is_dir( $ao_ccss_dir ) ) {
630 // fixme: should check for subdirs when in multisite and remove contents of those as well.
631 array_map( 'unlink', glob( $ao_ccss_dir . '*.{css,html,json,log,zip,lock}', GLOB_BRACE ) );
632 rmdir( $ao_ccss_dir );
633 }
634 }
635
636 public static function on_deactivation()
637 {
638 if ( is_multisite() && is_network_admin() ) {
639 global $wpdb;
640 $blog_ids = $wpdb->get_col( "SELECT blog_id FROM $wpdb->blogs" );
641 $original_blog_id = get_current_blog_id();
642 foreach ( $blog_ids as $blog_id ) {
643 switch_to_blog( $blog_id );
644 autoptimizeMain::remove_cronjobs();
645 }
646 switch_to_blog( $original_blog_id );
647 } else {
648 autoptimizeMain::remove_cronjobs();
649 }
650 autoptimizeCache::clearall();
651 }
652
653 public static function remove_cronjobs() {
654 // Remove scheduled events.
655 foreach ( array( 'ao_cachechecker', 'ao_ccss_queue', 'ao_ccss_maintenance' ) as $_event ) {
656 if ( wp_get_schedule( $_event ) ) {
657 wp_clear_scheduled_hook( $_event );
658 }
659 }
660 }
661
662 public static function notice_cache_unavailable()
663 {
664 echo '<div class="error"><p>';
665 // Translators: %s is the cache directory location.
666 printf( __( 'Autoptimize cannot write to the cache directory (%s), please fix to enable CSS/ JS optimization!', 'autoptimize' ), AUTOPTIMIZE_CACHE_DIR );
667 echo '</p></div>';
668 }
669
670 public static function notice_installed()
671 {
672 echo '<div class="updated"><p>';
673 _e( 'Thank you for installing and activating Autoptimize. Please configure it under "Settings" -> "Autoptimize" to start improving your site\'s performance.', 'autoptimize' );
674 echo '</p></div>';
675 }
676
677 public static function notice_updated()
678 {
679 echo '<div class="updated"><p>';
680 _e( 'Autoptimize has just been updated. Please <strong>test your site now</strong> and adapt Autoptimize config if needed.', 'autoptimize' );
681 echo '</p></div>';
682 }
683
684 public static function notice_plug_imgopt()
685 {
686 // Translators: the URL added points to the Autopmize Extra settings.
687 $_ao_imgopt_plug_notice = sprintf( __( 'Did you know Autoptimize includes 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 activate this option.', 'autoptimize' ), '<a href="options-general.php?page=autoptimize_imgopt">', '</a>' );
688 $_ao_imgopt_plug_notice = apply_filters( 'autoptimize_filter_main_imgopt_plug_notice', $_ao_imgopt_plug_notice );
689 $_ao_imgopt_launch_ok = autoptimizeImages::launch_ok_wrapper();
690 $_ao_imgopt_plug_dismissible = 'ao-img-opt-plug-123';
691 $_ao_imgopt_active = autoptimizeImages::imgopt_active();
692 $_is_ao_settings_page = ( str_replace( array( 'autoptimize', 'autoptimize_imgopt', 'ao_critcss', 'autoptimize_extra', 'ao_partners' ), '', $_SERVER['REQUEST_URI'] ) !== $_SERVER['REQUEST_URI'] ? true : false );
693
694 if ( current_user_can( 'manage_options' ) && $_is_ao_settings_page && '' !== $_ao_imgopt_plug_notice && ! $_ao_imgopt_active && $_ao_imgopt_launch_ok && PAnD::is_admin_notice_active( $_ao_imgopt_plug_dismissible ) ) {
695 echo '<div class="notice notice-info is-dismissible" data-dismissible="' . $_ao_imgopt_plug_dismissible . '"><p>';
696 echo $_ao_imgopt_plug_notice;
697 echo '</p></div>';
698 }
699 }
700 }
701