Version Description
- fundamental change for new installations: by default Autoptimize will not aggregate JS/ CSS any more (HTTP/2 is ubiquitous and there are other advantages to not aggregating esp. re. inline JS/ CSS and dependancies)
- new: no API needed any more to create manual critical CSS rules.
- new: "Remove WordPress blocks CSS" option on the "Extra" tab to remove block- and global styles (and SVG).
- new: compatibility logic for "edit with elementor", "revolution slider", for non-aggregated inline JS requiring jQuery even if not excluded (
Download this release
Release Info
Developer | futtta |
Plugin | Autoptimize |
Version | 3.0.0 |
Comparing to | |
See all releases |
Code changes from version 2.9.5.1 to 3.0.0
- autoptimize.php +2 -2
- classes/autoptimizeBase.php +5 -1
- classes/autoptimizeCache.php +14 -0
- classes/autoptimizeCompatibility.php +117 -0
- classes/autoptimizeConfig.php +90 -37
- classes/autoptimizeCriticalCSSBase.php +311 -83
- classes/autoptimizeCriticalCSSCore.php +148 -166
- classes/autoptimizeCriticalCSSCron.php +164 -162
- classes/autoptimizeCriticalCSSEnqueue.php +159 -163
- classes/autoptimizeCriticalCSSSettings.php +49 -36
- classes/autoptimizeCriticalCSSSettingsAjax.php +114 -34
- classes/autoptimizeExtra.php +46 -3
- classes/autoptimizeHTML.php +8 -4
- classes/autoptimizeImages.php +77 -5
- classes/autoptimizeMain.php +43 -3
- classes/autoptimizeMetabox.php +28 -20
- classes/autoptimizeScripts.php +14 -3
- classes/autoptimizeStyles.php +4 -2
- classes/autoptimizeVersionUpdatesHandler.php +18 -2
- classes/critcss-inc/admin_settings_adv.php +14 -11
- classes/critcss-inc/admin_settings_explain.php +11 -3
- classes/critcss-inc/admin_settings_queue.js.php +5 -0
- classes/critcss-inc/admin_settings_queue.php +3 -2
- classes/critcss-inc/admin_settings_rules.js.php +17 -2
- classes/critcss-inc/admin_settings_rules.php +7 -2
- classes/external/php/jsmin.php +1 -1
- config/autoptimize_404_handler.php +2 -2
- readme.txt +15 -2
autoptimize.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
* Plugin Name: Autoptimize
|
4 |
* Plugin URI: https://autoptimize.com/
|
5 |
* Description: Makes your site faster by optimizing CSS, JS, Images, Google fonts and more.
|
6 |
-
* Version:
|
7 |
* Author: Frank Goossens (futtta)
|
8 |
* Author URI: https://autoptimize.com/
|
9 |
* Text Domain: autoptimize
|
@@ -21,7 +21,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
21 |
exit;
|
22 |
}
|
23 |
|
24 |
-
define( 'AUTOPTIMIZE_PLUGIN_VERSION', '
|
25 |
|
26 |
// plugin_dir_path() returns the trailing slash!
|
27 |
define( 'AUTOPTIMIZE_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
|
3 |
* Plugin Name: Autoptimize
|
4 |
* Plugin URI: https://autoptimize.com/
|
5 |
* Description: Makes your site faster by optimizing CSS, JS, Images, Google fonts and more.
|
6 |
+
* Version: 3.0.0
|
7 |
* Author: Frank Goossens (futtta)
|
8 |
* Author URI: https://autoptimize.com/
|
9 |
* Text Domain: autoptimize
|
21 |
exit;
|
22 |
}
|
23 |
|
24 |
+
define( 'AUTOPTIMIZE_PLUGIN_VERSION', '3.0.0' );
|
25 |
|
26 |
// plugin_dir_path() returns the trailing slash!
|
27 |
define( 'AUTOPTIMIZE_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
|
classes/autoptimizeBase.php
CHANGED
@@ -77,6 +77,10 @@ abstract class autoptimizeBase
|
|
77 |
{
|
78 |
$url = apply_filters( 'autoptimize_filter_cssjs_alter_url', $url );
|
79 |
|
|
|
|
|
|
|
|
|
80 |
if ( false !== strpos( $url, '%' ) ) {
|
81 |
$url = urldecode( $url );
|
82 |
}
|
@@ -669,7 +673,7 @@ abstract class autoptimizeBase
|
|
669 |
'js/jquery/jquery.js',
|
670 |
);
|
671 |
foreach ( $minified_variants as $ending ) {
|
672 |
-
if ( autoptimizeUtils::str_ends_in( $filepath, $ending ) ) {
|
673 |
return false;
|
674 |
}
|
675 |
}
|
77 |
{
|
78 |
$url = apply_filters( 'autoptimize_filter_cssjs_alter_url', $url );
|
79 |
|
80 |
+
if ( is_null( $url ) ) {
|
81 |
+
return false;
|
82 |
+
}
|
83 |
+
|
84 |
if ( false !== strpos( $url, '%' ) ) {
|
85 |
$url = urldecode( $url );
|
86 |
}
|
673 |
'js/jquery/jquery.js',
|
674 |
);
|
675 |
foreach ( $minified_variants as $ending ) {
|
676 |
+
if ( autoptimizeUtils::str_ends_in( $filepath, $ending ) && true === apply_filters( 'autoptimize_filter_base_prepare_exclude_minified', true ) ) {
|
677 |
return false;
|
678 |
}
|
679 |
}
|
classes/autoptimizeCache.php
CHANGED
@@ -382,6 +382,16 @@ class autoptimizeCache
|
|
382 |
*/
|
383 |
public static function clearall( $propagate = true )
|
384 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
385 |
if ( ! self::cacheavail() ) {
|
386 |
return false;
|
387 |
}
|
@@ -636,6 +646,7 @@ class autoptimizeCache
|
|
636 |
$_fallback_php_contents = file_get_contents( AUTOPTIMIZE_PLUGIN_DIR . 'config/' . $_fallback_filename );
|
637 |
$_fallback_php_contents = str_replace( '<?php exit;', '<?php', $_fallback_php_contents );
|
638 |
$_fallback_php_contents = str_replace( '<!--ao-cache-dir-->', AUTOPTIMIZE_CACHE_DIR, $_fallback_php_contents );
|
|
|
639 |
if ( is_multisite() ) {
|
640 |
$_fallback_php_contents = str_replace( '$multisite = false;', '$multisite = true;', $_fallback_php_contents );
|
641 |
}
|
@@ -817,6 +828,9 @@ class autoptimizeCache
|
|
817 |
'timeout' => 5,
|
818 |
)
|
819 |
);
|
|
|
|
|
|
|
820 |
} elseif ( defined('NGINX_HELPER_BASENAME') ) {
|
821 |
do_action( 'rt_nginx_helper_purge_all' );
|
822 |
} elseif ( file_exists( WP_CONTENT_DIR . '/wp-cache-config.php' ) && function_exists( 'prune_super_cache' ) ) {
|
382 |
*/
|
383 |
public static function clearall( $propagate = true )
|
384 |
{
|
385 |
+
if ( defined( 'ET_CORE_VERSION' ) && 'Divi' === get_template() ) {
|
386 |
+
// see https://blog.futtta.be/2018/11/17/warning-divi-purging-autoptimizes-cache/ .
|
387 |
+
$dbt = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 2 );
|
388 |
+
$caller = isset( $dbt[1]['function'] ) ? $dbt[1]['function'] : null;
|
389 |
+
if ( $caller === 'et_core_clear_wp_cache' ) {
|
390 |
+
_doing_it_wrong( 'autoptimizeCache::clearall', 'Divi devs: please don\'t clear Autoptimize\'s cache, it is unneeded and can break sites. You can contact me at futtta@gmail.com to discuss.', 'Autoptimize 2.9.6' );
|
391 |
+
return false;
|
392 |
+
}
|
393 |
+
}
|
394 |
+
|
395 |
if ( ! self::cacheavail() ) {
|
396 |
return false;
|
397 |
}
|
646 |
$_fallback_php_contents = file_get_contents( AUTOPTIMIZE_PLUGIN_DIR . 'config/' . $_fallback_filename );
|
647 |
$_fallback_php_contents = str_replace( '<?php exit;', '<?php', $_fallback_php_contents );
|
648 |
$_fallback_php_contents = str_replace( '<!--ao-cache-dir-->', AUTOPTIMIZE_CACHE_DIR, $_fallback_php_contents );
|
649 |
+
$_fallback_php_contents = str_replace( '<!--ao-cachefile-prefix-->', AUTOPTIMIZE_CACHEFILE_PREFIX, $_fallback_php_contents );
|
650 |
if ( is_multisite() ) {
|
651 |
$_fallback_php_contents = str_replace( '$multisite = false;', '$multisite = true;', $_fallback_php_contents );
|
652 |
}
|
828 |
'timeout' => 5,
|
829 |
)
|
830 |
);
|
831 |
+
} elseif ( class_exists( 'RaidboxesNginxCacheFunctions' ) ) {
|
832 |
+
$rb_cache_helper = new RaidboxesNginxCacheFunctions();
|
833 |
+
$rb_cache_helper->purge_cache();
|
834 |
} elseif ( defined('NGINX_HELPER_BASENAME') ) {
|
835 |
do_action( 'rt_nginx_helper_purge_all' );
|
836 |
} elseif ( file_exists( WP_CONTENT_DIR . '/wp-cache-config.php' ) && function_exists( 'prune_super_cache' ) ) {
|
classes/autoptimizeCompatibility.php
ADDED
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Multiple compatibility snippets to ensure important/ stubborn plugins work out of the box.
|
4 |
+
*
|
5 |
+
*/
|
6 |
+
|
7 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
8 |
+
exit;
|
9 |
+
}
|
10 |
+
|
11 |
+
class autoptimizeCompatibility
|
12 |
+
{
|
13 |
+
/**
|
14 |
+
* Constructor.
|
15 |
+
*
|
16 |
+
*/
|
17 |
+
public function __construct()
|
18 |
+
{
|
19 |
+
if ( ! is_admin() && ! defined( 'DOING_CRON' ) ) {
|
20 |
+
$this->conf = autoptimizeConfig::instance();
|
21 |
+
$this->run();
|
22 |
+
}
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Runs multiple compatibility snippets to ensure important plugins work out of the box.
|
27 |
+
*
|
28 |
+
*/
|
29 |
+
public function run()
|
30 |
+
{
|
31 |
+
// Edit with Elementor in frontend admin menu (so for editors/ administrators) needs JS opt. disabled to appear & function.
|
32 |
+
if ( defined( 'ELEMENTOR_VERSION' ) && is_user_logged_in() && current_user_can( 'edit_posts' ) && apply_filters( 'autoptimize_filter_compatibility_editelementor_active', true ) ) {
|
33 |
+
add_filter( 'autoptimize_filter_js_noptimize', '__return_true' );
|
34 |
+
}
|
35 |
+
|
36 |
+
// Revslider; jQuery should not be deferred + exclude all revslider JS.
|
37 |
+
if ( defined( 'RS_REVISION' ) && $this->conf->get( 'autoptimize_js' ) && true == $this->inline_js_config_checker() && apply_filters( 'autoptimize_filter_compatibility_revslider_active', true ) ) {
|
38 |
+
add_filter( 'autoptimize_filter_js_exclude', function( $js_excl = '', $html = '' ) {
|
39 |
+
$revslider_excl = 'revslider, setREVStartSize, window.RSIW, window.RS_MODULES, jquery.min.js';
|
40 |
+
if ( ! empty( $html ) && false !== strpos( $html, '<rs-slides>' ) ) {
|
41 |
+
if ( is_array( $js_excl ) ) {
|
42 |
+
$js_excl = implode( ',', $js_excl );
|
43 |
+
}
|
44 |
+
|
45 |
+
$js_excl .= ',' . $revslider_excl;
|
46 |
+
}
|
47 |
+
return $js_excl;
|
48 |
+
}, 11, 2 );
|
49 |
+
}
|
50 |
+
|
51 |
+
// Revslider; remove revslider JS if no slides in HTML for non-logged in users.
|
52 |
+
if ( defined( 'RS_REVISION' ) && $this->conf->get( 'autoptimize_js' ) && false === is_user_logged_in() && apply_filters( 'autoptimize_filter_compatibility_revslider_remover_active', true ) ) {
|
53 |
+
add_filter( 'autoptimize_filter_js_removables', function( $to_remove = '', $html = '' ) {
|
54 |
+
if ( ! empty( $html ) && false === strpos( $html, '<rs-slides>') ) {
|
55 |
+
$to_remove .= 'plugins/revslider, setREVStartSize, window.RSIW, window.RS_MODULES';
|
56 |
+
}
|
57 |
+
|
58 |
+
return $to_remove;
|
59 |
+
}, 11, 2 );
|
60 |
+
}
|
61 |
+
|
62 |
+
// Exclude jQuery if inline JS is found that requires jQuery.
|
63 |
+
if ( $this->inline_js_config_checker() && false === strpos( $this->conf->get( 'autoptimize_js_exclude' ), 'jquery.min.js' ) && apply_filters( 'autoptimize_filter_compatibility_inline_jquery', true ) ) {
|
64 |
+
add_filter( 'autoptimize_filter_js_exclude', function( $js_excl = '', $html = '' ) {
|
65 |
+
if ( ! empty( $html ) && preg_match( '/<script[^>]*>[^<]*(jQuery|\$)\([^<]*<\/script>/Usm', $html ) ) {
|
66 |
+
if ( is_array( $js_excl ) ) {
|
67 |
+
$js_excl = implode( ',', $js_excl );
|
68 |
+
}
|
69 |
+
|
70 |
+
if ( false === strpos( $js_excl, 'jquery.min.js' ) ) {
|
71 |
+
$js_excl .= ', jquery.min.js';
|
72 |
+
}
|
73 |
+
}
|
74 |
+
return $js_excl;
|
75 |
+
}, 12, 2 );
|
76 |
+
}
|
77 |
+
|
78 |
+
// Make JS-based Gutenberg blocks work OOTB.
|
79 |
+
if ( $this->inline_js_config_checker() && apply_filters( 'autoptimize_filter_compatibility_gutenberg_js', true ) ) {
|
80 |
+
add_filter( 'autoptimize_filter_js_exclude', function( $js_excl = '', $html = '' ) {
|
81 |
+
if ( ! empty( $html ) && false !== strpos( $html, 'wp.i18n' ) || false !== strpos( $html, 'wp.apiFetch' ) || false !== strpos( $html, 'window.lodash' ) ) {
|
82 |
+
if ( is_array( $js_excl ) ) {
|
83 |
+
$js_excl = implode( ',', $js_excl );
|
84 |
+
}
|
85 |
+
|
86 |
+
if ( false === strpos( $js_excl, 'jquery.min.js' ) ) {
|
87 |
+
$js_excl .= ', jquery.min.js';
|
88 |
+
}
|
89 |
+
|
90 |
+
if ( false === strpos( $js_excl, 'wp-includes/js/dist' ) ) {
|
91 |
+
$js_excl .= ', wp-includes/js/dist';
|
92 |
+
}
|
93 |
+
}
|
94 |
+
return $js_excl;
|
95 |
+
}, 13, 2 );
|
96 |
+
}
|
97 |
+
}
|
98 |
+
|
99 |
+
public function inline_js_config_checker() {
|
100 |
+
static $inline_js_flagged = null;
|
101 |
+
|
102 |
+
if ( null === $inline_js_flagged ) {
|
103 |
+
if ( ( $this->conf->get( 'autoptimize_js_aggregate' ) || apply_filters( 'autoptimize_filter_js_dontaggregate', false ) ) && apply_filters( 'autoptimize_js_include_inline', $this->conf->get( 'autoptimize_js_include_inline' ) ) ) {
|
104 |
+
// if all files and also inline JS are aggregated we don't have to worry about inline JS.
|
105 |
+
$inline_js_flagged = false;
|
106 |
+
} else if ( apply_filters( 'autoptimize_filter_js_defer_not_aggregate', $this->conf->get( 'autoptimize_js_defer_not_aggregate' ) ) && apply_filters( 'autoptimize_js_filter_defer_inline', $this->conf->get( 'autoptimize_js_defer_inline' ) ) ) {
|
107 |
+
// and when not aggregating but deferring all including inline JS, then all is OK too.
|
108 |
+
$inline_js_flagged = false;
|
109 |
+
}
|
110 |
+
|
111 |
+
// in all other cases we need to pay attention to inline JS requiring src'ed JS to be available.
|
112 |
+
$inline_js_flagged = true;
|
113 |
+
}
|
114 |
+
|
115 |
+
return $inline_js_flagged;
|
116 |
+
}
|
117 |
+
}
|
classes/autoptimizeConfig.php
CHANGED
@@ -226,7 +226,7 @@ if ( is_network_admin() && autoptimizeOptionWrapper::is_ao_active_for_network()
|
|
226 |
<table class="form-table">
|
227 |
<tr valign="top">
|
228 |
<th scope="row"><?php _e( 'Optimize JavaScript Code?', 'autoptimize' ); ?></th>
|
229 |
-
<td><input type="checkbox" id="autoptimize_js" name="autoptimize_js" <?php echo
|
230 |
</tr>
|
231 |
<tr valign="top" class="js_sub js_aggregate_master">
|
232 |
<th scope="row"><?php _e( 'Aggregate JS-files?', 'autoptimize' ); ?></th>
|
@@ -235,17 +235,17 @@ if ( is_network_admin() && autoptimizeOptionWrapper::is_ao_active_for_network()
|
|
235 |
</tr>
|
236 |
<tr valign="top" class="js_sub js_aggregate hidden">
|
237 |
<th scope="row"> <?php _e( 'Also aggregate inline JS?', 'autoptimize' ); ?></th>
|
238 |
-
<td><label class="cb_label"><input type="checkbox" name="autoptimize_js_include_inline" <?php echo
|
239 |
<?php _e( 'Let Autoptimize also extract JS from the HTML (discouraged as it can make Autoptimize\'s cache size grow quickly)', 'autoptimize' ); ?></label></td>
|
240 |
</tr>
|
241 |
<tr valign="top" class="js_sub js_aggregate hidden">
|
242 |
<th scope="row"> <?php _e( 'Force JavaScript in <head>?', 'autoptimize' ); ?></th>
|
243 |
-
<td><label class="cb_label"><input type="checkbox" name="autoptimize_js_forcehead" <?php echo
|
244 |
<?php _e( 'Load JavaScript early (discouraged as it makes the JS render blocking)', 'autoptimize' ); ?></label></td>
|
245 |
</tr>
|
246 |
<tr valign="top" class="js_sub js_aggregate hidden">
|
247 |
<th scope="row"> <?php _e( 'Add try-catch wrapping?', 'autoptimize' ); ?></th>
|
248 |
-
<td><label class="cb_label"><input type="checkbox" name="autoptimize_js_trycatch" <?php echo
|
249 |
<?php _e( 'If your aggregated scripts break because of a JS-error, you might want to try this, but generally discouraged.', 'autoptimize' ); ?></label></td>
|
250 |
</tr>
|
251 |
<tr valign="top" class="js_sub js_not_aggregate_master">
|
@@ -255,7 +255,7 @@ if ( is_network_admin() && autoptimizeOptionWrapper::is_ao_active_for_network()
|
|
255 |
</tr>
|
256 |
<tr valign="top" id="js_defer_inline" class="js_sub js_not_aggregate hidden">
|
257 |
<th scope="row"> <?php _e( 'Also defer inline JS?', 'autoptimize' ); ?></th>
|
258 |
-
<td><label class="cb_label"><input type="checkbox" name="autoptimize_js_defer_inline" <?php echo
|
259 |
<?php _e( 'Also defer inline JS. Generally this will allow all JS to be deferred, so you should remove default exclusions, test and only exclude specific items if still needed.', 'autoptimize' ); ?></label></td>
|
260 |
</tr>
|
261 |
<?php if ( autoptimizeOptionWrapper::get_option( 'autoptimize_js_justhead' ) ) { ?>
|
@@ -266,13 +266,13 @@ if ( is_network_admin() && autoptimizeOptionWrapper::is_ao_active_for_network()
|
|
266 |
echo ' <i>' . __( '(deprecated)', 'autoptimize' ) . '</i>';
|
267 |
?>
|
268 |
</th>
|
269 |
-
<td><label class="cb_label"><input type="checkbox" name="autoptimize_js_justhead" <?php echo
|
270 |
<?php _e( 'Mostly useful in combination with previous option when using jQuery-based templates, but might help keeping cache size under control.', 'autoptimize' ); ?></label></td>
|
271 |
</tr>
|
272 |
<?php } ?>
|
273 |
<tr valign="top" class="js_sub">
|
274 |
<th scope="row"><?php _e( 'Exclude scripts from Autoptimize:', 'autoptimize' ); ?></th>
|
275 |
-
<td><label><input type="text" style="width:100%;" name="autoptimize_js_exclude" value="<?php echo esc_attr( autoptimizeOptionWrapper::get_option( 'autoptimize_js_exclude', '
|
276 |
<?php
|
277 |
echo __( 'A comma-separated list of scripts you do not want optimized, for example \'whatever.js, my_var\' (without the quotes).', 'autoptimize' ) . ' ' . __( 'Important: when "aggregate JS-files" is on, excluded non-minified files are still minified by Autoptimize unless that option under "misc" is disabled.', 'autoptimize' );
|
278 |
?>
|
@@ -290,7 +290,7 @@ echo __( 'A comma-separated list of scripts you do not want optimized, for examp
|
|
290 |
<table class="form-table">
|
291 |
<tr valign="top">
|
292 |
<th scope="row"><?php _e( 'Optimize CSS Code?', 'autoptimize' ); ?></th>
|
293 |
-
<td><input type="checkbox" id="autoptimize_css" name="autoptimize_css" <?php echo
|
294 |
</tr>
|
295 |
<tr class="css_sub" valign="top">
|
296 |
<th scope="row"><?php _e( 'Aggregate CSS-files?', 'autoptimize' ); ?></th>
|
@@ -299,12 +299,12 @@ echo __( 'A comma-separated list of scripts you do not want optimized, for examp
|
|
299 |
</tr>
|
300 |
<tr valign="top" class="css_sub css_aggregate">
|
301 |
<th scope="row"><?php _e( 'Also aggregate inline CSS?', 'autoptimize' ); ?></th>
|
302 |
-
<td><label class="cb_label"><input type="checkbox" name="autoptimize_css_include_inline" <?php echo
|
303 |
<?php _e( 'Check this option for Autoptimize to also aggregate CSS in the HTML.', 'autoptimize' ); ?></label></td>
|
304 |
</tr>
|
305 |
<tr class="css_sub css_aggregate" valign="top">
|
306 |
<th scope="row"><?php _e( 'Generate data: URIs for images?', 'autoptimize' ); ?></th>
|
307 |
-
<td><label class="cb_label"><input type="checkbox" name="autoptimize_css_datauris" <?php echo
|
308 |
<?php _e( 'Enable this to include small background-images in the CSS itself instead of as separate downloads.', 'autoptimize' ); ?></label></td>
|
309 |
</tr>
|
310 |
<?php if ( autoptimizeOptionWrapper::get_option( 'autoptimize_css_justhead' ) ) { ?>
|
@@ -315,19 +315,19 @@ _e( 'Look for styles only in <head>?', 'autoptimize' );
|
|
315 |
echo ' <i>' . __( '(deprecated)', 'autoptimize' ) . '</i>';
|
316 |
?>
|
317 |
</th>
|
318 |
-
<td><label class="cb_label"><input type="checkbox" name="autoptimize_css_justhead" <?php echo
|
319 |
<?php _e( 'Don\'t autoptimize CSS outside the head-section. If the cache gets big, you might want to enable this.', 'autoptimize' ); ?></label></td>
|
320 |
</tr>
|
321 |
<?php } ?>
|
322 |
<tr valign="top" class="css_sub">
|
323 |
<th scope="row"><?php _e( 'Eliminate render-blocking CSS?', 'autoptimize' ); ?></th>
|
324 |
-
<td><label class="cb_label"><input type="checkbox" name="autoptimize_css_defer" id="autoptimize_css_defer" <?php echo
|
325 |
<?php
|
326 |
_e( 'Inline "above the fold CSS" while loading the main autoptimized CSS only after page load. <a href="https://wordpress.org/plugins/autoptimize/faq/" target="_blank">Check the FAQ</a> for more info.', 'autoptimize' );
|
327 |
echo ' ';
|
328 |
$critcss_settings_url = get_admin_url( null, 'options-general.php?page=ao_critcss' );
|
329 |
// translators: links "autoptimize critical CSS" tab.
|
330 |
-
echo sprintf( __( '
|
331 |
?>
|
332 |
</label></td>
|
333 |
</tr>
|
@@ -337,12 +337,12 @@ echo sprintf( __( 'This can be fully automated for different types of pages on t
|
|
337 |
</tr>
|
338 |
<tr valign="top" class="css_sub css_aggregate">
|
339 |
<th scope="row"><?php _e( 'Inline all CSS?', 'autoptimize' ); ?></th>
|
340 |
-
<td><label class="cb_label"><input type="checkbox" id="autoptimize_css_inline" name="autoptimize_css_inline" <?php echo
|
341 |
<?php _e( 'Inlining all CSS is an easy way to stop the CSS from being render-blocking, but is generally not recommended because the size of the HTML increases significantly. Additionally it might push meta-tags down to a position where e.g. Facebook and Whatsapp will not find them any more, breaking thumbnails when sharing.', 'autoptimize' ); ?></label></td>
|
342 |
</tr>
|
343 |
<tr valign="top" class="css_sub">
|
344 |
<th scope="row"><?php _e( 'Exclude CSS from Autoptimize:', 'autoptimize' ); ?></th>
|
345 |
-
<td><label><input type="text" style="width:100%;" name="autoptimize_css_exclude" value="<?php echo esc_attr(
|
346 |
<?php
|
347 |
echo __( 'A comma-separated list of CSS you want to exclude from being optimized.', 'autoptimize' ) . ' ' . __( 'Important: excluded non-minified files are still minified by Autoptimize unless that option under "misc" is disabled.', 'autoptimize' );
|
348 |
?>
|
@@ -365,12 +365,12 @@ $_rapidload_link = 'https://misc.optimizingmatters.com/partners/?from=csssetting
|
|
365 |
<table class="form-table">
|
366 |
<tr valign="top">
|
367 |
<th scope="row"><?php _e( 'Optimize HTML Code?', 'autoptimize' ); ?></th>
|
368 |
-
<td><input type="checkbox" id="autoptimize_html" name="autoptimize_html" <?php echo
|
369 |
</tr>
|
370 |
<tr class="html_sub" valign="top">
|
371 |
<th scope="row"><?php _e( 'Keep HTML comments?', 'autoptimize' ); ?></th>
|
372 |
-
<td><label class="cb_label"><input type="checkbox" name="autoptimize_html_keepcomments" <?php echo
|
373 |
-
<?php _e( 'Enable this if you want HTML comments to remain in the page.', 'autoptimize' ); ?></label></td>
|
374 |
</tr>
|
375 |
</table>
|
376 |
</li>
|
@@ -435,7 +435,7 @@ if ( true === autoptimizeImages::imgopt_active() && true === apply_filters( 'aut
|
|
435 |
<table class="form-table">
|
436 |
<tr valign="top" >
|
437 |
<th scope="row"><?php _e( 'Save aggregated script/css as static files?', 'autoptimize' ); ?></th>
|
438 |
-
<td><label class="cb_label"><input type="checkbox" name="autoptimize_cache_nogzip" <?php echo
|
439 |
<?php _e( 'By default files saved are static css/js, uncheck this option if your webserver doesn\'t properly handle the compression and expiry.', 'autoptimize' ); ?></label></td>
|
440 |
</tr>
|
441 |
<?php
|
@@ -446,17 +446,17 @@ if ( true === autoptimizeImages::imgopt_active() && true === apply_filters( 'aut
|
|
446 |
?>
|
447 |
<tr valign="top" id="min_excl_row" class="<?php echo $_min_excl_class; ?>">
|
448 |
<th scope="row"><?php _e( 'Minify excluded CSS and JS files?', 'autoptimize' ); ?></th>
|
449 |
-
<td><label class="cb_label"><input type="checkbox" name="autoptimize_minify_excluded" <?php echo
|
450 |
<?php _e( 'When aggregating JS or CSS, excluded files that are not minified (based on filename) are by default minified by Autoptimize despite being excluded. Uncheck this option if anything breaks despite excluding.', 'autoptimize' ); ?></label></td>
|
451 |
</tr>
|
452 |
<tr valign="top">
|
453 |
<th scope="row"><?php _e( 'Enable 404 fallbacks?', 'autoptimize' ); ?></th>
|
454 |
-
<td><label class="cb_label"><input type="checkbox" name="autoptimize_cache_fallback" <?php echo
|
455 |
<?php _e( 'Sometimes Autoptimized JS/ CSS is referenced in cached HTML but is already removed, resulting in broken sites. With this option on, Autoptimize will try to redirect those not-found files to "fallback"-versions, keeping the page/ site somewhat intact. In some cases this will require extra web-server level configuration to ensure <code>wp-content/autoptimize_404_handler.php</code> is set to handle 404\'s in <code>wp-content/cache/autoptimize</code>.', 'autoptimize' ); ?></label></td>
|
456 |
</tr>
|
457 |
<tr valign="top">
|
458 |
<th scope="row"><?php _e( 'Also optimize for logged in editors/ administrators?', 'autoptimize' ); ?></th>
|
459 |
-
<td><label class="cb_label"><input type="checkbox" name="autoptimize_optimize_logged" <?php echo
|
460 |
<?php _e( 'By default Autoptimize is also active for logged on editors/ administrators, uncheck this option if you don\'t want Autoptimize to optimize when logged in e.g. to use a pagebuilder.', 'autoptimize' ); ?></label></td>
|
461 |
</tr>
|
462 |
<?php
|
@@ -464,7 +464,7 @@ if ( true === autoptimizeImages::imgopt_active() && true === apply_filters( 'aut
|
|
464 |
?>
|
465 |
<tr valign="top" >
|
466 |
<th scope="row"><?php _e( 'Also optimize shop cart/ checkout?', 'autoptimize' ); ?></th>
|
467 |
-
<td><label class="cb_label"><input type="checkbox" name="autoptimize_optimize_checkout" <?php echo
|
468 |
<?php _e( 'By default Autoptimize is also active on your shop\'s cart/ checkout, uncheck not to optimize those.', 'autoptimize' ); ?></label>
|
469 |
</td>
|
470 |
</tr>
|
@@ -474,7 +474,7 @@ if ( true === autoptimizeImages::imgopt_active() && true === apply_filters( 'aut
|
|
474 |
?>
|
475 |
<tr valign="top">
|
476 |
<th scope="row"><?php _e( 'Enable configuration per post/ page?', 'autoptimize' ); ?></th>
|
477 |
-
<td><label class="cb_label"><input type="checkbox" name="autoptimize_enable_meta_ao_settings" <?php echo
|
478 |
<?php _e( 'Add a "metabox" to the post/ page edit screen allowing different optimizations to be turned off on a per post/ page level?', 'autoptimize' ); ?></label></td>
|
479 |
</tr>
|
480 |
<?php } ?>
|
@@ -558,12 +558,14 @@ if ( true === autoptimizeImages::imgopt_active() && true === apply_filters( 'aut
|
|
558 |
jQuery( ".js_not_aggregate_master:visible" ).fadeTo( 'slow', .33 ); // grey out "not aggregate"
|
559 |
jQuery( ".js_not_aggregate" ).hide( 'slow' ); // hide not aggregate sub-items
|
560 |
jQuery( "#min_excl_row" ).show(); // make sure "minify excluded" is visible
|
|
|
561 |
} else {
|
562 |
jQuery( ".js_aggregate" ).hide( 'slow' ); // hide sub-itmes
|
563 |
jQuery( ".js_not_aggregate_master:visible" ).fadeTo( 'slow', 1 ); // un-grey-out "not aggregate"
|
564 |
if ( jQuery( "#autoptimize_css_aggregate" ).prop( 'checked' ) == false ) { // hide "minify excluded"
|
565 |
jQuery( "#min_excl_row" ).hide();
|
566 |
}
|
|
|
567 |
}
|
568 |
});
|
569 |
|
@@ -574,6 +576,7 @@ if ( true === autoptimizeImages::imgopt_active() && true === apply_filters( 'aut
|
|
574 |
jQuery( ".js_not_aggregate" ).show( 'slow'); // show sub-items
|
575 |
jQuery( ".js_aggregate_master:visible" ).fadeTo( 'slow', .33 ); // grey out "aggregate"
|
576 |
jQuery( ".js_aggregate" ).hide( 'slow' ); // hide aggregate sub-items
|
|
|
577 |
} else {
|
578 |
jQuery( ".js_not_aggregate" ).hide( 'slow' ); // hide sub-items
|
579 |
jQuery( ".js_aggregate_master:visible" ).fadeTo( 'slow', 1 ); // un-grey-out "aggregate"
|
@@ -592,11 +595,13 @@ if ( true === autoptimizeImages::imgopt_active() && true === apply_filters( 'aut
|
|
592 |
if (this.checked && jQuery("#autoptimize_css").prop('checked')) {
|
593 |
jQuery(".css_aggregate:visible").fadeTo("fast",1);
|
594 |
jQuery( "#min_excl_row" ).show();
|
|
|
595 |
} else {
|
596 |
jQuery(".css_aggregate:visible").fadeTo("fast",.33);
|
597 |
if ( jQuery( "#autoptimize_js_aggregate" ).prop('checked') == false ) {
|
598 |
jQuery( "#min_excl_row" ).hide();
|
599 |
}
|
|
|
600 |
}
|
601 |
});
|
602 |
|
@@ -650,9 +655,6 @@ if ( true === autoptimizeImages::imgopt_active() && true === apply_filters( 'aut
|
|
650 |
if (!jQuery("#autoptimize_css_aggregate").prop('checked')) {
|
651 |
jQuery(".css_aggregate:visible").fadeTo('fast',.33);
|
652 |
}
|
653 |
-
if (!jQuery("#autoptimize_js").prop('checked')) {
|
654 |
-
jQuery(".js_sub:visible").fadeTo('fast',.33);
|
655 |
-
}
|
656 |
if (jQuery("#autoptimize_js_aggregate").prop('checked')) {
|
657 |
jQuery( ".js_aggregate" ).show( 'fast' );
|
658 |
jQuery( ".js_not_aggregate_master:visible" ).fadeTo( 'fast', .33 );
|
@@ -664,6 +666,31 @@ if ( true === autoptimizeImages::imgopt_active() && true === apply_filters( 'aut
|
|
664 |
if (jQuery("#autoptimize_enable_site_config").prop('checked')) {
|
665 |
jQuery("li.itemDetail:not(.multiSite)").fadeTo('fast',.33);
|
666 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
667 |
}
|
668 |
</script>
|
669 |
</div>
|
@@ -769,19 +796,19 @@ if ( true === autoptimizeImages::imgopt_active() && true === apply_filters( 'aut
|
|
769 |
'autoptimize_html_keepcomments' => 0,
|
770 |
'autoptimize_enable_site_config' => 1,
|
771 |
'autoptimize_js' => 0,
|
772 |
-
'autoptimize_js_aggregate' =>
|
773 |
-
'autoptimize_js_defer_not_aggregate' =>
|
774 |
-
'autoptimize_js_defer_inline' =>
|
775 |
-
'autoptimize_js_exclude' => 'wp-includes/js/dist/, wp-includes/js/tinymce/, js/jquery/jquery.
|
776 |
'autoptimize_js_trycatch' => 0,
|
777 |
'autoptimize_js_justhead' => 0,
|
778 |
'autoptimize_js_include_inline' => 0,
|
779 |
'autoptimize_js_forcehead' => 0,
|
780 |
'autoptimize_css' => 0,
|
781 |
-
'autoptimize_css_aggregate' =>
|
782 |
-
'autoptimize_css_exclude' => 'admin-bar.min.css, dashicons.min.css, wp-content/cache/, wp-content/uploads/',
|
783 |
'autoptimize_css_justhead' => 0,
|
784 |
-
'autoptimize_css_include_inline' =>
|
785 |
'autoptimize_css_defer' => 0,
|
786 |
'autoptimize_css_defer_inline' => '',
|
787 |
'autoptimize_css_inline' => 0,
|
@@ -812,6 +839,7 @@ if ( true === autoptimizeImages::imgopt_active() && true === apply_filters( 'aut
|
|
812 |
'autoptimize_extra_text_field_2' => '',
|
813 |
'autoptimize_extra_text_field_3' => '',
|
814 |
'autoptimize_extra_text_field_7' => '',
|
|
|
815 |
);
|
816 |
|
817 |
return $defaults;
|
@@ -985,15 +1013,40 @@ if ( true === autoptimizeImages::imgopt_active() && true === apply_filters( 'aut
|
|
985 |
global $wp_query;
|
986 |
if ( isset( $wp_query ) && ( is_page() || is_single() ) ) {
|
987 |
$_meta_value = get_post_meta( get_the_ID(), 'ao_post_optimize', true );
|
988 |
-
} else {
|
989 |
$_meta_value = false;
|
990 |
}
|
991 |
}
|
992 |
|
993 |
-
// If autoptimize_post_optimize !== 'on' then always return false as all is off.
|
994 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
995 |
return false;
|
996 |
} else {
|
|
|
|
|
|
|
|
|
997 |
return true;
|
998 |
}
|
999 |
}
|
226 |
<table class="form-table">
|
227 |
<tr valign="top">
|
228 |
<th scope="row"><?php _e( 'Optimize JavaScript Code?', 'autoptimize' ); ?></th>
|
229 |
+
<td><input type="checkbox" id="autoptimize_js" name="autoptimize_js" <?php echo $conf->get( 'autoptimize_js' ) ? 'checked="checked" ' : ''; ?>/></td>
|
230 |
</tr>
|
231 |
<tr valign="top" class="js_sub js_aggregate_master">
|
232 |
<th scope="row"><?php _e( 'Aggregate JS-files?', 'autoptimize' ); ?></th>
|
235 |
</tr>
|
236 |
<tr valign="top" class="js_sub js_aggregate hidden">
|
237 |
<th scope="row"> <?php _e( 'Also aggregate inline JS?', 'autoptimize' ); ?></th>
|
238 |
+
<td><label class="cb_label"><input type="checkbox" name="autoptimize_js_include_inline" <?php echo $conf->get( 'autoptimize_js_include_inline' ) ? 'checked="checked" ' : ''; ?>/>
|
239 |
<?php _e( 'Let Autoptimize also extract JS from the HTML (discouraged as it can make Autoptimize\'s cache size grow quickly)', 'autoptimize' ); ?></label></td>
|
240 |
</tr>
|
241 |
<tr valign="top" class="js_sub js_aggregate hidden">
|
242 |
<th scope="row"> <?php _e( 'Force JavaScript in <head>?', 'autoptimize' ); ?></th>
|
243 |
+
<td><label class="cb_label"><input type="checkbox" name="autoptimize_js_forcehead" <?php echo $conf->get( 'autoptimize_js_forcehead' ) ? 'checked="checked" ' : ''; ?>/>
|
244 |
<?php _e( 'Load JavaScript early (discouraged as it makes the JS render blocking)', 'autoptimize' ); ?></label></td>
|
245 |
</tr>
|
246 |
<tr valign="top" class="js_sub js_aggregate hidden">
|
247 |
<th scope="row"> <?php _e( 'Add try-catch wrapping?', 'autoptimize' ); ?></th>
|
248 |
+
<td><label class="cb_label"><input type="checkbox" name="autoptimize_js_trycatch" <?php echo $conf->get( 'autoptimize_js_trycatch' ) ? 'checked="checked" ' : ''; ?>/>
|
249 |
<?php _e( 'If your aggregated scripts break because of a JS-error, you might want to try this, but generally discouraged.', 'autoptimize' ); ?></label></td>
|
250 |
</tr>
|
251 |
<tr valign="top" class="js_sub js_not_aggregate_master">
|
255 |
</tr>
|
256 |
<tr valign="top" id="js_defer_inline" class="js_sub js_not_aggregate hidden">
|
257 |
<th scope="row"> <?php _e( 'Also defer inline JS?', 'autoptimize' ); ?></th>
|
258 |
+
<td><label class="cb_label"><input type="checkbox" name="autoptimize_js_defer_inline" <?php echo $conf->get( 'autoptimize_js_defer_inline' ) ? 'checked="checked" ' : ''; ?>/>
|
259 |
<?php _e( 'Also defer inline JS. Generally this will allow all JS to be deferred, so you should remove default exclusions, test and only exclude specific items if still needed.', 'autoptimize' ); ?></label></td>
|
260 |
</tr>
|
261 |
<?php if ( autoptimizeOptionWrapper::get_option( 'autoptimize_js_justhead' ) ) { ?>
|
266 |
echo ' <i>' . __( '(deprecated)', 'autoptimize' ) . '</i>';
|
267 |
?>
|
268 |
</th>
|
269 |
+
<td><label class="cb_label"><input type="checkbox" name="autoptimize_js_justhead" <?php echo $conf->get( 'autoptimize_js_justhead' ) ? 'checked="checked" ' : ''; ?>/>
|
270 |
<?php _e( 'Mostly useful in combination with previous option when using jQuery-based templates, but might help keeping cache size under control.', 'autoptimize' ); ?></label></td>
|
271 |
</tr>
|
272 |
<?php } ?>
|
273 |
<tr valign="top" class="js_sub">
|
274 |
<th scope="row"><?php _e( 'Exclude scripts from Autoptimize:', 'autoptimize' ); ?></th>
|
275 |
+
<td><label><input type="text" style="width:100%;" name="autoptimize_js_exclude" value="<?php echo esc_attr( autoptimizeOptionWrapper::get_option( 'autoptimize_js_exclude', '' ) ); ?>"/><br />
|
276 |
<?php
|
277 |
echo __( 'A comma-separated list of scripts you do not want optimized, for example \'whatever.js, my_var\' (without the quotes).', 'autoptimize' ) . ' ' . __( 'Important: when "aggregate JS-files" is on, excluded non-minified files are still minified by Autoptimize unless that option under "misc" is disabled.', 'autoptimize' );
|
278 |
?>
|
290 |
<table class="form-table">
|
291 |
<tr valign="top">
|
292 |
<th scope="row"><?php _e( 'Optimize CSS Code?', 'autoptimize' ); ?></th>
|
293 |
+
<td><input type="checkbox" id="autoptimize_css" name="autoptimize_css" <?php echo $conf->get( 'autoptimize_css' ) ? 'checked="checked" ' : ''; ?>/></td>
|
294 |
</tr>
|
295 |
<tr class="css_sub" valign="top">
|
296 |
<th scope="row"><?php _e( 'Aggregate CSS-files?', 'autoptimize' ); ?></th>
|
299 |
</tr>
|
300 |
<tr valign="top" class="css_sub css_aggregate">
|
301 |
<th scope="row"><?php _e( 'Also aggregate inline CSS?', 'autoptimize' ); ?></th>
|
302 |
+
<td><label class="cb_label"><input type="checkbox" name="autoptimize_css_include_inline" <?php echo $conf->get( 'autoptimize_css_include_inline', '1' ) ? 'checked="checked" ' : ''; ?>/>
|
303 |
<?php _e( 'Check this option for Autoptimize to also aggregate CSS in the HTML.', 'autoptimize' ); ?></label></td>
|
304 |
</tr>
|
305 |
<tr class="css_sub css_aggregate" valign="top">
|
306 |
<th scope="row"><?php _e( 'Generate data: URIs for images?', 'autoptimize' ); ?></th>
|
307 |
+
<td><label class="cb_label"><input type="checkbox" name="autoptimize_css_datauris" <?php echo $conf->get( 'autoptimize_css_datauris' ) ? 'checked="checked" ' : ''; ?>/>
|
308 |
<?php _e( 'Enable this to include small background-images in the CSS itself instead of as separate downloads.', 'autoptimize' ); ?></label></td>
|
309 |
</tr>
|
310 |
<?php if ( autoptimizeOptionWrapper::get_option( 'autoptimize_css_justhead' ) ) { ?>
|
315 |
echo ' <i>' . __( '(deprecated)', 'autoptimize' ) . '</i>';
|
316 |
?>
|
317 |
</th>
|
318 |
+
<td><label class="cb_label"><input type="checkbox" name="autoptimize_css_justhead" <?php echo $conf->get( 'autoptimize_css_justhead' ) ? 'checked="checked" ' : ''; ?>/>
|
319 |
<?php _e( 'Don\'t autoptimize CSS outside the head-section. If the cache gets big, you might want to enable this.', 'autoptimize' ); ?></label></td>
|
320 |
</tr>
|
321 |
<?php } ?>
|
322 |
<tr valign="top" class="css_sub">
|
323 |
<th scope="row"><?php _e( 'Eliminate render-blocking CSS?', 'autoptimize' ); ?></th>
|
324 |
+
<td><label class="cb_label"><input type="checkbox" name="autoptimize_css_defer" id="autoptimize_css_defer" <?php echo $conf->get( 'autoptimize_css_defer' ) ? 'checked="checked" ' : ''; ?>/>
|
325 |
<?php
|
326 |
_e( 'Inline "above the fold CSS" while loading the main autoptimized CSS only after page load. <a href="https://wordpress.org/plugins/autoptimize/faq/" target="_blank">Check the FAQ</a> for more info.', 'autoptimize' );
|
327 |
echo ' ';
|
328 |
$critcss_settings_url = get_admin_url( null, 'options-general.php?page=ao_critcss' );
|
329 |
// translators: links "autoptimize critical CSS" tab.
|
330 |
+
echo sprintf( __( 'You can manually create rules for different types of pages or have this done fully automated on the %s tab.', 'autoptimize' ), '<a href="' . $critcss_settings_url . '">CriticalCSS</a>' );
|
331 |
?>
|
332 |
</label></td>
|
333 |
</tr>
|
337 |
</tr>
|
338 |
<tr valign="top" class="css_sub css_aggregate">
|
339 |
<th scope="row"><?php _e( 'Inline all CSS?', 'autoptimize' ); ?></th>
|
340 |
+
<td><label class="cb_label"><input type="checkbox" id="autoptimize_css_inline" name="autoptimize_css_inline" <?php echo $conf->get( 'autoptimize_css_inline' ) ? 'checked="checked" ' : ''; ?>/>
|
341 |
<?php _e( 'Inlining all CSS is an easy way to stop the CSS from being render-blocking, but is generally not recommended because the size of the HTML increases significantly. Additionally it might push meta-tags down to a position where e.g. Facebook and Whatsapp will not find them any more, breaking thumbnails when sharing.', 'autoptimize' ); ?></label></td>
|
342 |
</tr>
|
343 |
<tr valign="top" class="css_sub">
|
344 |
<th scope="row"><?php _e( 'Exclude CSS from Autoptimize:', 'autoptimize' ); ?></th>
|
345 |
+
<td><label><input type="text" style="width:100%;" name="autoptimize_css_exclude" value="<?php echo esc_attr( $conf->get( 'autoptimize_css_exclude', '' ) ); ?>"/><br />
|
346 |
<?php
|
347 |
echo __( 'A comma-separated list of CSS you want to exclude from being optimized.', 'autoptimize' ) . ' ' . __( 'Important: excluded non-minified files are still minified by Autoptimize unless that option under "misc" is disabled.', 'autoptimize' );
|
348 |
?>
|
365 |
<table class="form-table">
|
366 |
<tr valign="top">
|
367 |
<th scope="row"><?php _e( 'Optimize HTML Code?', 'autoptimize' ); ?></th>
|
368 |
+
<td><input type="checkbox" id="autoptimize_html" name="autoptimize_html" <?php echo $conf->get( 'autoptimize_html' ) ? 'checked="checked" ' : ''; ?>/></td>
|
369 |
</tr>
|
370 |
<tr class="html_sub" valign="top">
|
371 |
<th scope="row"><?php _e( 'Keep HTML comments?', 'autoptimize' ); ?></th>
|
372 |
+
<td><label class="cb_label"><input type="checkbox" name="autoptimize_html_keepcomments" <?php echo $conf->get( 'autoptimize_html_keepcomments' ) ? 'checked="checked" ' : ''; ?>/>
|
373 |
+
<?php _e( 'Enable this if you want HTML comments to remain in the page or if you want the inline CSS/ JS not to be minified.', 'autoptimize' ); ?></label></td>
|
374 |
</tr>
|
375 |
</table>
|
376 |
</li>
|
435 |
<table class="form-table">
|
436 |
<tr valign="top" >
|
437 |
<th scope="row"><?php _e( 'Save aggregated script/css as static files?', 'autoptimize' ); ?></th>
|
438 |
+
<td><label class="cb_label"><input type="checkbox" name="autoptimize_cache_nogzip" <?php echo $conf->get( 'autoptimize_cache_nogzip') ? 'checked="checked" ' : ''; ?>/>
|
439 |
<?php _e( 'By default files saved are static css/js, uncheck this option if your webserver doesn\'t properly handle the compression and expiry.', 'autoptimize' ); ?></label></td>
|
440 |
</tr>
|
441 |
<?php
|
446 |
?>
|
447 |
<tr valign="top" id="min_excl_row" class="<?php echo $_min_excl_class; ?>">
|
448 |
<th scope="row"><?php _e( 'Minify excluded CSS and JS files?', 'autoptimize' ); ?></th>
|
449 |
+
<td><label class="cb_label"><input type="checkbox" name="autoptimize_minify_excluded" <?php echo $conf->get( 'autoptimize_minify_excluded' ) ? 'checked="checked" ' : ''; ?>/>
|
450 |
<?php _e( 'When aggregating JS or CSS, excluded files that are not minified (based on filename) are by default minified by Autoptimize despite being excluded. Uncheck this option if anything breaks despite excluding.', 'autoptimize' ); ?></label></td>
|
451 |
</tr>
|
452 |
<tr valign="top">
|
453 |
<th scope="row"><?php _e( 'Enable 404 fallbacks?', 'autoptimize' ); ?></th>
|
454 |
+
<td><label class="cb_label"><input type="checkbox" name="autoptimize_cache_fallback" <?php echo $conf->get( 'autoptimize_cache_fallback' ) ? 'checked="checked" ' : ''; ?>/>
|
455 |
<?php _e( 'Sometimes Autoptimized JS/ CSS is referenced in cached HTML but is already removed, resulting in broken sites. With this option on, Autoptimize will try to redirect those not-found files to "fallback"-versions, keeping the page/ site somewhat intact. In some cases this will require extra web-server level configuration to ensure <code>wp-content/autoptimize_404_handler.php</code> is set to handle 404\'s in <code>wp-content/cache/autoptimize</code>.', 'autoptimize' ); ?></label></td>
|
456 |
</tr>
|
457 |
<tr valign="top">
|
458 |
<th scope="row"><?php _e( 'Also optimize for logged in editors/ administrators?', 'autoptimize' ); ?></th>
|
459 |
+
<td><label class="cb_label"><input type="checkbox" name="autoptimize_optimize_logged" <?php echo $conf->get( 'autoptimize_optimize_logged' ) ? 'checked="checked" ' : ''; ?>/>
|
460 |
<?php _e( 'By default Autoptimize is also active for logged on editors/ administrators, uncheck this option if you don\'t want Autoptimize to optimize when logged in e.g. to use a pagebuilder.', 'autoptimize' ); ?></label></td>
|
461 |
</tr>
|
462 |
<?php
|
464 |
?>
|
465 |
<tr valign="top" >
|
466 |
<th scope="row"><?php _e( 'Also optimize shop cart/ checkout?', 'autoptimize' ); ?></th>
|
467 |
+
<td><label class="cb_label"><input type="checkbox" name="autoptimize_optimize_checkout" <?php echo $conf->get( 'autoptimize_optimize_checkout' ) ? 'checked="checked" ' : ''; ?>/>
|
468 |
<?php _e( 'By default Autoptimize is also active on your shop\'s cart/ checkout, uncheck not to optimize those.', 'autoptimize' ); ?></label>
|
469 |
</td>
|
470 |
</tr>
|
474 |
?>
|
475 |
<tr valign="top">
|
476 |
<th scope="row"><?php _e( 'Enable configuration per post/ page?', 'autoptimize' ); ?></th>
|
477 |
+
<td><label class="cb_label"><input type="checkbox" name="autoptimize_enable_meta_ao_settings" <?php echo $conf->get( 'autoptimize_enable_meta_ao_settings' ) ? 'checked="checked" ' : ''; ?>/>
|
478 |
<?php _e( 'Add a "metabox" to the post/ page edit screen allowing different optimizations to be turned off on a per post/ page level?', 'autoptimize' ); ?></label></td>
|
479 |
</tr>
|
480 |
<?php } ?>
|
558 |
jQuery( ".js_not_aggregate_master:visible" ).fadeTo( 'slow', .33 ); // grey out "not aggregate"
|
559 |
jQuery( ".js_not_aggregate" ).hide( 'slow' ); // hide not aggregate sub-items
|
560 |
jQuery( "#min_excl_row" ).show(); // make sure "minify excluded" is visible
|
561 |
+
check_exclusions( "js", "on" );
|
562 |
} else {
|
563 |
jQuery( ".js_aggregate" ).hide( 'slow' ); // hide sub-itmes
|
564 |
jQuery( ".js_not_aggregate_master:visible" ).fadeTo( 'slow', 1 ); // un-grey-out "not aggregate"
|
565 |
if ( jQuery( "#autoptimize_css_aggregate" ).prop( 'checked' ) == false ) { // hide "minify excluded"
|
566 |
jQuery( "#min_excl_row" ).hide();
|
567 |
}
|
568 |
+
check_exclusions( "js", "off" );
|
569 |
}
|
570 |
});
|
571 |
|
576 |
jQuery( ".js_not_aggregate" ).show( 'slow'); // show sub-items
|
577 |
jQuery( ".js_aggregate_master:visible" ).fadeTo( 'slow', .33 ); // grey out "aggregate"
|
578 |
jQuery( ".js_aggregate" ).hide( 'slow' ); // hide aggregate sub-items
|
579 |
+
check_exclusions( "js", "off" );
|
580 |
} else {
|
581 |
jQuery( ".js_not_aggregate" ).hide( 'slow' ); // hide sub-items
|
582 |
jQuery( ".js_aggregate_master:visible" ).fadeTo( 'slow', 1 ); // un-grey-out "aggregate"
|
595 |
if (this.checked && jQuery("#autoptimize_css").prop('checked')) {
|
596 |
jQuery(".css_aggregate:visible").fadeTo("fast",1);
|
597 |
jQuery( "#min_excl_row" ).show();
|
598 |
+
check_exclusions( "css", "on" );
|
599 |
} else {
|
600 |
jQuery(".css_aggregate:visible").fadeTo("fast",.33);
|
601 |
if ( jQuery( "#autoptimize_js_aggregate" ).prop('checked') == false ) {
|
602 |
jQuery( "#min_excl_row" ).hide();
|
603 |
}
|
604 |
+
check_exclusions( "css", "off" );
|
605 |
}
|
606 |
});
|
607 |
|
655 |
if (!jQuery("#autoptimize_css_aggregate").prop('checked')) {
|
656 |
jQuery(".css_aggregate:visible").fadeTo('fast',.33);
|
657 |
}
|
|
|
|
|
|
|
658 |
if (jQuery("#autoptimize_js_aggregate").prop('checked')) {
|
659 |
jQuery( ".js_aggregate" ).show( 'fast' );
|
660 |
jQuery( ".js_not_aggregate_master:visible" ).fadeTo( 'fast', .33 );
|
666 |
if (jQuery("#autoptimize_enable_site_config").prop('checked')) {
|
667 |
jQuery("li.itemDetail:not(.multiSite)").fadeTo('fast',.33);
|
668 |
}
|
669 |
+
if (!jQuery("#autoptimize_js").prop('checked')) {
|
670 |
+
jQuery(".js_sub:visible").fadeTo('fast',.33);
|
671 |
+
}
|
672 |
+
}
|
673 |
+
|
674 |
+
function check_exclusions( what, state ) {
|
675 |
+
exclusion_node = 'input[name="autoptimize_' + what + '_exclude"]';
|
676 |
+
current_exclusion = jQuery( exclusion_node ).val();
|
677 |
+
|
678 |
+
if ( what == "js" ) {
|
679 |
+
default_exclusion = ", wp-includes/js/dist/, wp-includes/js/tinymce/, js/jquery/jquery.min.js";
|
680 |
+
} else if ( what == "css") {
|
681 |
+
default_exclusion = ", admin-bar.min.css, dashicons.min.css, wp-content/cache/, wp-content/uploads/";
|
682 |
+
}
|
683 |
+
|
684 |
+
default_in_current = current_exclusion.indexOf(default_exclusion);
|
685 |
+
|
686 |
+
if ( state == "on" && default_in_current == -1 ) {
|
687 |
+
jQuery( exclusion_node ).val( current_exclusion + default_exclusion );
|
688 |
+
} else if ( state = "off" && current_exclusion == default_exclusion ) {
|
689 |
+
jQuery( exclusion_node ).val( "" );
|
690 |
+
} else if ( state = "off" && default_in_current != -1 ) {
|
691 |
+
new_exclusion = current_exclusion.substring( 0, default_in_current) + current_exclusion.substring( default_in_current + default_exclusion.length, current_exclusion.length );
|
692 |
+
jQuery( exclusion_node ).val( new_exclusion );
|
693 |
+
}
|
694 |
}
|
695 |
</script>
|
696 |
</div>
|
796 |
'autoptimize_html_keepcomments' => 0,
|
797 |
'autoptimize_enable_site_config' => 1,
|
798 |
'autoptimize_js' => 0,
|
799 |
+
'autoptimize_js_aggregate' => 0,
|
800 |
+
'autoptimize_js_defer_not_aggregate' => 1,
|
801 |
+
'autoptimize_js_defer_inline' => 1,
|
802 |
+
'autoptimize_js_exclude' => '', // 'wp-includes/js/dist/, wp-includes/js/tinymce/, js/jquery/jquery.min.js',
|
803 |
'autoptimize_js_trycatch' => 0,
|
804 |
'autoptimize_js_justhead' => 0,
|
805 |
'autoptimize_js_include_inline' => 0,
|
806 |
'autoptimize_js_forcehead' => 0,
|
807 |
'autoptimize_css' => 0,
|
808 |
+
'autoptimize_css_aggregate' => 0,
|
809 |
+
'autoptimize_css_exclude' => '', // admin-bar.min.css, dashicons.min.css, wp-content/cache/, wp-content/uploads/',
|
810 |
'autoptimize_css_justhead' => 0,
|
811 |
+
'autoptimize_css_include_inline' => 0,
|
812 |
'autoptimize_css_defer' => 0,
|
813 |
'autoptimize_css_defer_inline' => '',
|
814 |
'autoptimize_css_inline' => 0,
|
839 |
'autoptimize_extra_text_field_2' => '',
|
840 |
'autoptimize_extra_text_field_3' => '',
|
841 |
'autoptimize_extra_text_field_7' => '',
|
842 |
+
'autoptimize_extra_checkbox_field_8' => '0',
|
843 |
);
|
844 |
|
845 |
return $defaults;
|
1013 |
global $wp_query;
|
1014 |
if ( isset( $wp_query ) && ( is_page() || is_single() ) ) {
|
1015 |
$_meta_value = get_post_meta( get_the_ID(), 'ao_post_optimize', true );
|
1016 |
+
} else if ( isset( $wp_query ) ) {
|
1017 |
$_meta_value = false;
|
1018 |
}
|
1019 |
}
|
1020 |
|
1021 |
+
// If autoptimize_post_optimize !== 'on' (except for ao_post_preload, which can have other values) then always return false as all is off.
|
1022 |
+
// fixme: need unit tests to ensure below logic is sane!
|
1023 |
+
if ( empty( $_meta_value ) || ! is_array( $_meta_value ) ) {
|
1024 |
+
// no metabox values so all optimizations are a go.
|
1025 |
+
if ( in_array( $optim, array( 'ao_post_preload' ) ) ) {
|
1026 |
+
// but make sure to return false for text input.
|
1027 |
+
return false;
|
1028 |
+
}
|
1029 |
+
return true;
|
1030 |
+
} else if ( array_key_exists( 'ao_post_optimize', $_meta_value ) && 'on' !== $_meta_value['ao_post_optimize'] ) {
|
1031 |
+
// ao entirely off for this page.
|
1032 |
+
return false;
|
1033 |
+
} else if ( array_key_exists( $optim, $_meta_value ) && empty( $_meta_value[$optim] ) ) {
|
1034 |
+
// sub-optimization off for this page.
|
1035 |
+
return false;
|
1036 |
+
} else if ( array_key_exists( $optim, $_meta_value ) && 'on' === $_meta_value[$optim] ) {
|
1037 |
+
// sub-optimization is explictly on.
|
1038 |
+
return true;
|
1039 |
+
} else if ( array_key_exists( $optim, $_meta_value ) && in_array( $optim, array( 'ao_post_preload' ) ) && ! empty( $_meta_value[$optim] ) ) {
|
1040 |
+
// a non-bool metabox optimization (currently only preload field), return value instead of bool.
|
1041 |
+
return $_meta_value[$optim];
|
1042 |
+
} else if ( in_array( $optim, array( 'ao_post_preload' ) ) && ( ! array_key_exists( $optim, $_meta_value ) || empty( $_meta_value[$optim] ) ) ) {
|
1043 |
+
// a non-bool metabox optimization not found or empty, so returning false.
|
1044 |
return false;
|
1045 |
} else {
|
1046 |
+
// when in doubt "go" for optimization, but this should never happen?
|
1047 |
+
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
|
1048 |
+
error_log( 'AO metabox logic fallback; well, how did I get here? Maybe this helps: looking for ' . $optim . ' in ' . json_encode( $_meta_value ) );
|
1049 |
+
}
|
1050 |
return true;
|
1051 |
}
|
1052 |
}
|
classes/autoptimizeCriticalCSSBase.php
CHANGED
@@ -16,6 +16,41 @@ class autoptimizeCriticalCSSBase {
|
|
16 |
*/
|
17 |
protected $filepath = null;
|
18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
public function __construct()
|
20 |
{
|
21 |
// define constant, but only once.
|
@@ -35,7 +70,7 @@ class autoptimizeCriticalCSSBase {
|
|
35 |
// Define constants for criticalcss.com base path and API endpoints.
|
36 |
// fixme: AO_CCSS_URL should be read from the autoptimize availability json stored as option.
|
37 |
define( 'AO_CCSS_URL', 'https://criticalcss.com' );
|
38 |
-
define( 'AO_CCSS_API', AO_CCSS_URL . '/api/premium/' );
|
39 |
define( 'AO_CCSS_SLEEP', 10 );
|
40 |
}
|
41 |
|
@@ -51,118 +86,243 @@ class autoptimizeCriticalCSSBase {
|
|
51 |
}
|
52 |
|
53 |
$this->filepath = __FILE__;
|
54 |
-
|
55 |
-
|
56 |
-
$this
|
57 |
}
|
58 |
|
59 |
-
public function setup()
|
60 |
-
{
|
61 |
-
// get all options.
|
62 |
-
$all_options = $this->fetch_options();
|
63 |
-
foreach ( $all_options as $option => $value ) {
|
64 |
-
${$option} = $value;
|
65 |
-
}
|
66 |
-
|
67 |
-
// make sure the 10 minutes cron schedule is added.
|
68 |
-
add_filter( 'cron_schedules', array( $this, 'ao_ccss_interval' ) );
|
69 |
-
|
70 |
// check if we need to upgrade.
|
71 |
$this->check_upgrade();
|
72 |
|
73 |
-
//
|
74 |
-
if (
|
75 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
76 |
}
|
77 |
}
|
78 |
|
79 |
public function load_requires() {
|
80 |
// Required libs, core is always needed.
|
81 |
-
$
|
82 |
|
83 |
-
if ( defined( 'WP_CLI' ) || defined( 'DOING_CRON' ) || is_admin() ) {
|
84 |
-
//
|
85 |
-
$
|
86 |
}
|
87 |
|
88 |
if ( is_admin() ) {
|
89 |
-
$
|
90 |
-
} else {
|
91 |
-
// enqueuing only done when not wp-admin.
|
92 |
-
$
|
93 |
-
}
|
94 |
-
}
|
95 |
-
|
96 |
-
public static function fetch_options() {
|
97 |
-
static $autoptimize_ccss_options = null;
|
98 |
-
|
99 |
-
if ( null === $autoptimize_ccss_options ) {
|
100 |
-
// not cached yet, fetching from WordPress options.
|
101 |
-
$autoptimize_ccss_options['ao_css_defer'] = autoptimizeOptionWrapper::get_option( 'autoptimize_css_defer' );
|
102 |
-
$autoptimize_ccss_options['ao_css_defer_inline'] = autoptimizeOptionWrapper::get_option( 'autoptimize_css_defer_inline' );
|
103 |
-
$autoptimize_ccss_options['ao_ccss_rules_raw'] = get_option( 'autoptimize_ccss_rules', false );
|
104 |
-
$autoptimize_ccss_options['ao_ccss_additional'] = get_option( 'autoptimize_ccss_additional' );
|
105 |
-
$autoptimize_ccss_options['ao_ccss_queue_raw'] = get_option( 'autoptimize_ccss_queue', false );
|
106 |
-
$autoptimize_ccss_options['ao_ccss_viewport'] = get_option( 'autoptimize_ccss_viewport', false );
|
107 |
-
$autoptimize_ccss_options['ao_ccss_finclude'] = get_option( 'autoptimize_ccss_finclude', false );
|
108 |
-
$autoptimize_ccss_options['ao_ccss_rtimelimit'] = get_option( 'autoptimize_ccss_rtimelimit', '30' );
|
109 |
-
$autoptimize_ccss_options['ao_ccss_noptimize'] = get_option( 'autoptimize_ccss_noptimize', false );
|
110 |
-
$autoptimize_ccss_options['ao_ccss_debug'] = get_option( 'autoptimize_ccss_debug', false );
|
111 |
-
$autoptimize_ccss_options['ao_ccss_key'] = apply_filters( 'autoptimize_filter_ccss_key', get_option( 'autoptimize_ccss_key' ) );
|
112 |
-
$autoptimize_ccss_options['ao_ccss_keyst'] = get_option( 'autoptimize_ccss_keyst' );
|
113 |
-
$autoptimize_ccss_options['ao_ccss_loggedin'] = get_option( 'autoptimize_ccss_loggedin', '1' );
|
114 |
-
$autoptimize_ccss_options['ao_ccss_forcepath'] = get_option( 'autoptimize_ccss_forcepath', '1' );
|
115 |
-
$autoptimize_ccss_options['ao_ccss_servicestatus'] = get_option( 'autoptimize_service_availablity' );
|
116 |
-
$autoptimize_ccss_options['ao_ccss_deferjquery'] = get_option( 'autoptimize_ccss_deferjquery', false );
|
117 |
-
$autoptimize_ccss_options['ao_ccss_domain'] = get_option( 'autoptimize_ccss_domain' );
|
118 |
-
$autoptimize_ccss_options['ao_ccss_unloadccss'] = get_option( 'autoptimize_ccss_unloadccss', false );
|
119 |
-
|
120 |
-
if ( strpos( $autoptimize_ccss_options['ao_ccss_domain'], 'http' ) === false && strpos( $autoptimize_ccss_options['ao_ccss_domain'], 'uggc' ) === 0 ) {
|
121 |
-
$autoptimize_ccss_options['ao_ccss_domain'] = str_rot13( $autoptimize_ccss_options['ao_ccss_domain'] );
|
122 |
-
} elseif ( strpos( $autoptimize_ccss_options['ao_ccss_domain'], 'http' ) !== false ) {
|
123 |
-
// not rot13'ed yet, do so now (goal; avoid migration plugins change the bound domain).
|
124 |
-
update_option( 'autoptimize_ccss_domain', str_rot13( $autoptimize_ccss_options['ao_ccss_domain'] ) );
|
125 |
-
}
|
126 |
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
|
|
|
|
|
|
|
|
134 |
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
|
|
|
|
141 |
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
146 |
}
|
147 |
|
148 |
-
return $
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
149 |
}
|
150 |
|
151 |
public function on_upgrade() {
|
152 |
-
|
153 |
|
154 |
// Create the cache directory if it doesn't exist already.
|
155 |
if ( ! file_exists( AO_CCSS_DIR ) ) {
|
156 |
-
|
157 |
}
|
158 |
|
159 |
// Create a scheduled event for the queue.
|
160 |
-
if (
|
161 |
wp_schedule_event( time(), apply_filters( 'ao_ccss_queue_schedule', 'ao_ccss' ), 'ao_ccss_queue' );
|
162 |
}
|
163 |
|
164 |
// Create a scheduled event for log maintenance.
|
165 |
-
if (
|
166 |
wp_schedule_event( time(), 'twicedaily', 'ao_ccss_maintenance' );
|
167 |
}
|
168 |
}
|
@@ -181,6 +341,7 @@ class autoptimizeCriticalCSSBase {
|
|
181 |
// Let interval be configurable.
|
182 |
if ( ! defined( 'AO_CCSS_DEBUG_INTERVAL' ) ) {
|
183 |
$intsec = 600;
|
|
|
184 |
} else {
|
185 |
$intsec = AO_CCSS_DEBUG_INTERVAL;
|
186 |
if ( $intsec >= 120 ) {
|
@@ -188,14 +349,81 @@ class autoptimizeCriticalCSSBase {
|
|
188 |
} else {
|
189 |
$inttxt = $intsec . ' second(s)';
|
190 |
}
|
191 |
-
|
192 |
}
|
193 |
|
194 |
// Attach interval to schedule.
|
195 |
$schedules['ao_ccss'] = array(
|
196 |
'interval' => $intsec,
|
197 |
-
'display' => __( 'Autoptimize
|
198 |
);
|
199 |
return $schedules;
|
200 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
201 |
}
|
16 |
*/
|
17 |
protected $filepath = null;
|
18 |
|
19 |
+
/**
|
20 |
+
* Critical CSS options
|
21 |
+
*
|
22 |
+
* @var array
|
23 |
+
*/
|
24 |
+
protected $_options = null;
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Core object
|
28 |
+
*
|
29 |
+
* @var object
|
30 |
+
*/
|
31 |
+
protected $_core = null;
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Cron object
|
35 |
+
*
|
36 |
+
* @var object
|
37 |
+
*/
|
38 |
+
protected $_cron = null;
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Settings object
|
42 |
+
*
|
43 |
+
* @var object
|
44 |
+
*/
|
45 |
+
protected $_settings = null;
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Enqueue object
|
49 |
+
*
|
50 |
+
* @var object
|
51 |
+
*/
|
52 |
+
protected $_enqueue = null;
|
53 |
+
|
54 |
public function __construct()
|
55 |
{
|
56 |
// define constant, but only once.
|
70 |
// Define constants for criticalcss.com base path and API endpoints.
|
71 |
// fixme: AO_CCSS_URL should be read from the autoptimize availability json stored as option.
|
72 |
define( 'AO_CCSS_URL', 'https://criticalcss.com' );
|
73 |
+
define( 'AO_CCSS_API', apply_filters( 'autoptimize_filter_ccss_service_url', AO_CCSS_URL . '/api/premium/' ) );
|
74 |
define( 'AO_CCSS_SLEEP', 10 );
|
75 |
}
|
76 |
|
86 |
}
|
87 |
|
88 |
$this->filepath = __FILE__;
|
89 |
+
|
90 |
+
// Add keychecker action for scheduled use.
|
91 |
+
add_action( 'ao_ccss_keychecker', array( $this, 'ao_ccss_check_key' ) );
|
92 |
}
|
93 |
|
94 |
+
public function setup() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
95 |
// check if we need to upgrade.
|
96 |
$this->check_upgrade();
|
97 |
|
98 |
+
// add/ remove scheduled jobs.
|
99 |
+
if ( $this->is_api_active() ) {
|
100 |
+
if ( ! wp_next_scheduled( 'ao_ccss_queue' ) ) {
|
101 |
+
// make sure the 10 minutes cron schedule is added.
|
102 |
+
add_filter( 'cron_schedules', array( $this, 'ao_ccss_interval' ) );
|
103 |
+
|
104 |
+
// make sure ao_ccss_queue is scheduled OK if an API key is active.
|
105 |
+
wp_schedule_event( time(), apply_filters( 'ao_ccss_queue_schedule', 'ao_ccss' ), 'ao_ccss_queue' );
|
106 |
+
}
|
107 |
+
|
108 |
+
if ( ! wp_next_scheduled( 'ao_ccss_maintenance' ) ) {
|
109 |
+
// and schedule maintenance job.
|
110 |
+
wp_schedule_event( time(), 'twicedaily', 'ao_ccss_maintenance' );
|
111 |
+
}
|
112 |
+
|
113 |
+
if ( wp_next_scheduled( 'ao_ccss_keychecker' ) ) {
|
114 |
+
// api is active now, no need to check key as it is checked by using the API.
|
115 |
+
wp_clear_scheduled_hook( 'ao_ccss_keychecker' );
|
116 |
+
}
|
117 |
+
} else {
|
118 |
+
if ( wp_next_scheduled( 'ao_ccss_queue' ) ) {
|
119 |
+
wp_clear_scheduled_hook( 'ao_ccss_queue' );
|
120 |
+
}
|
121 |
+
|
122 |
+
if ( wp_next_scheduled( 'ao_ccss_maintenance' ) ) {
|
123 |
+
wp_clear_scheduled_hook( 'ao_ccss_maintenance' );
|
124 |
+
}
|
125 |
+
|
126 |
+
// add keychecker logic if api is not active but we have a key so maybe this is a temporary issue, check if key is OK daily.
|
127 |
+
$ao_ccss_key = $this->get_option( 'key' );
|
128 |
+
if ( ! empty( $ao_ccss_key ) && ! wp_next_scheduled( 'ao_ccss_keychecker' ) ) {
|
129 |
+
wp_schedule_event( time(), 'twicedaily', 'ao_ccss_keychecker' );
|
130 |
+
} else if ( empty( $ao_ccss_key ) && wp_next_scheduled( 'ao_ccss_keychecker' ) ) {
|
131 |
+
// edge case: we had a inactive key that was checked daily, but it is now removed, so remove keychecker from schedule.
|
132 |
+
wp_clear_scheduled_hook( 'ao_ccss_keychecker' );
|
133 |
+
}
|
134 |
+
}
|
135 |
+
|
136 |
+
// check/ create AO_CCSS_DIR.
|
137 |
+
if ( ! file_exists( AO_CCSS_DIR ) ) {
|
138 |
+
$this->create_ao_ccss_dir();
|
139 |
}
|
140 |
}
|
141 |
|
142 |
public function load_requires() {
|
143 |
// Required libs, core is always needed.
|
144 |
+
$this->_core = new autoptimizeCriticalCSSCore();
|
145 |
|
146 |
+
if ( ( defined( 'WP_CLI' ) || defined( 'DOING_CRON' ) || is_admin() ) && $this->is_api_active() ) {
|
147 |
+
// cron only initiated when doing cron (or wp_cli or is_amdin) and when we have an active API key.
|
148 |
+
$this->_cron = new autoptimizeCriticalCSSCron();
|
149 |
}
|
150 |
|
151 |
if ( is_admin() ) {
|
152 |
+
$this->_settings = new autoptimizeCriticalCSSSettings();
|
153 |
+
} else if ( $this->is_api_active() ) {
|
154 |
+
// enqueuing only done when not wp-admin and when API is active.
|
155 |
+
$this->_enqueue = new autoptimizeCriticalCSSEnqueue();
|
156 |
+
}
|
157 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
158 |
|
159 |
+
/**
|
160 |
+
* Log a message via CCSS Core object
|
161 |
+
*
|
162 |
+
* @param string $msg
|
163 |
+
* @param int $lvl
|
164 |
+
*
|
165 |
+
* @return void
|
166 |
+
*/
|
167 |
+
public function log( $msg, $lvl ) {
|
168 |
+
return $this->_core->ao_ccss_log( $msg, $lvl );
|
169 |
+
}
|
170 |
|
171 |
+
/**
|
172 |
+
* Get viewport from CCSS Core object
|
173 |
+
*
|
174 |
+
* @return array
|
175 |
+
*/
|
176 |
+
public function viewport() {
|
177 |
+
return $this->_core->ao_ccss_viewport();
|
178 |
+
}
|
179 |
|
180 |
+
/**
|
181 |
+
* Check CCSS contents from Core object
|
182 |
+
*
|
183 |
+
* @param string $ccss
|
184 |
+
*
|
185 |
+
* @return bool
|
186 |
+
*/
|
187 |
+
public function check_contents( $ccss ) {
|
188 |
+
return $this->_core->ao_ccss_check_contents( $ccss );
|
189 |
+
}
|
190 |
+
|
191 |
+
/**
|
192 |
+
* Get key status from Core object
|
193 |
+
*
|
194 |
+
* @param bool $render
|
195 |
+
*
|
196 |
+
* @return array
|
197 |
+
*/
|
198 |
+
public function key_status( $render ) {
|
199 |
+
return $this->_core->ao_ccss_key_status( $render );
|
200 |
+
}
|
201 |
+
|
202 |
+
/**
|
203 |
+
* Return valid types from core object
|
204 |
+
*
|
205 |
+
* @return array
|
206 |
+
*/
|
207 |
+
public function get_types() {
|
208 |
+
return $this->_core->get_types();
|
209 |
+
}
|
210 |
+
|
211 |
+
/**
|
212 |
+
* Run enqueue in CCSS Enqueue object
|
213 |
+
*/
|
214 |
+
public function enqueue( $hash = '', $path = '', $type = 'is_page' ) {
|
215 |
+
// Enqueue is sometimes required on wp-admin requests, load it just-in-time.
|
216 |
+
if ( is_null( $this->_enqueue ) && $this->is_api_active() ) {
|
217 |
+
$this->_enqueue = new autoptimizeCriticalCSSEnqueue();
|
218 |
}
|
219 |
|
220 |
+
return $this->_enqueue->ao_ccss_enqueue( $hash, $path, $type );
|
221 |
+
}
|
222 |
+
|
223 |
+
/**
|
224 |
+
* Check auto-rules in CCSS Settings object
|
225 |
+
*/
|
226 |
+
public function has_autorules() {
|
227 |
+
return $this->_settings->ao_ccss_has_autorules();
|
228 |
+
}
|
229 |
+
|
230 |
+
/**
|
231 |
+
* Get a Critical CSS option
|
232 |
+
*
|
233 |
+
* @param string $name The option name
|
234 |
+
*
|
235 |
+
* @return mixed
|
236 |
+
*/
|
237 |
+
public function get_option( $name ) {
|
238 |
+
if ( is_null( $this->_options ) ) {
|
239 |
+
$this->fetch_options();
|
240 |
+
}
|
241 |
+
|
242 |
+
if ( isset( $this->_options[ $name ] ) ) {
|
243 |
+
return $this->_options[ $name ];
|
244 |
+
}
|
245 |
+
|
246 |
+
return null;
|
247 |
+
}
|
248 |
+
|
249 |
+
public function flush_options() {
|
250 |
+
$this->_options = null;
|
251 |
+
}
|
252 |
+
|
253 |
+
protected function fetch_options() {
|
254 |
+
if ( ! is_null( $this->_options ) ) {
|
255 |
+
return $this->_options;
|
256 |
+
}
|
257 |
+
|
258 |
+
$this->_options = array(
|
259 |
+
'css_defer' => autoptimizeOptionWrapper::get_option( 'autoptimize_css_defer' ),
|
260 |
+
'css_defer_inline' => autoptimizeOptionWrapper::get_option( 'autoptimize_css_defer_inline' ),
|
261 |
+
'rules_raw' => get_option( 'autoptimize_ccss_rules', false ),
|
262 |
+
'additional' => get_option( 'autoptimize_ccss_additional' ),
|
263 |
+
'queue_raw' => get_option( 'autoptimize_ccss_queue', false ),
|
264 |
+
'viewport' => get_option( 'autoptimize_ccss_viewport', false ),
|
265 |
+
'finclude' => get_option( 'autoptimize_ccss_finclude', false ),
|
266 |
+
'rtimelimit' => get_option( 'autoptimize_ccss_rtimelimit', '30' ),
|
267 |
+
'noptimize' => get_option( 'autoptimize_ccss_noptimize', false ),
|
268 |
+
'debug' => get_option( 'autoptimize_ccss_debug', false ),
|
269 |
+
'key' => apply_filters( 'autoptimize_filter_ccss_key', get_option( 'autoptimize_ccss_key' ) ),
|
270 |
+
'keyst' => get_option( 'autoptimize_ccss_keyst' ),
|
271 |
+
'loggedin' => get_option( 'autoptimize_ccss_loggedin', '1' ),
|
272 |
+
'forcepath' => get_option( 'autoptimize_ccss_forcepath', '1' ),
|
273 |
+
'servicestatus' => get_option( 'autoptimize_service_availablity' ),
|
274 |
+
'deferjquery' => get_option( 'autoptimize_ccss_deferjquery', false ),
|
275 |
+
'domain' => get_option( 'autoptimize_ccss_domain' ),
|
276 |
+
'unloadccss' => get_option( 'autoptimize_ccss_unloadccss', false ),
|
277 |
+
);
|
278 |
+
|
279 |
+
if ( strpos( $this->_options['domain'], 'http' ) === false && strpos( $this->_options['domain'], 'uggc' ) === 0 ) {
|
280 |
+
$this->_options['domain'] = str_rot13( $this->_options['domain'] );
|
281 |
+
} elseif ( strpos( $this->_options['domain'], 'http' ) !== false ) {
|
282 |
+
// not rot13'ed yet, do so now (goal; avoid migration plugins change the bound domain).
|
283 |
+
update_option( 'autoptimize_ccss_domain', str_rot13( $this->_options['domain'] ) );
|
284 |
+
}
|
285 |
+
|
286 |
+
// Setup the rules array.
|
287 |
+
if ( empty( $this->_options['rules_raw'] ) ) {
|
288 |
+
$this->_options['rules'] = array(
|
289 |
+
'paths' => array(),
|
290 |
+
'types' => array(),
|
291 |
+
);
|
292 |
+
} else {
|
293 |
+
$this->_options['rules'] = json_decode( $this->_options['rules_raw'], true );
|
294 |
+
}
|
295 |
+
|
296 |
+
// Setup the queue array.
|
297 |
+
if ( empty( $this->_options['queue_raw'] ) ) {
|
298 |
+
$this->_options['queue'] = array();
|
299 |
+
} else {
|
300 |
+
$this->_options['queue'] = json_decode( $this->_options['queue_raw'], true );
|
301 |
+
}
|
302 |
+
|
303 |
+
// Override API key if constant is defined.
|
304 |
+
if ( defined( 'AUTOPTIMIZE_CRITICALCSS_API_KEY' ) ) {
|
305 |
+
$this->_options['key'] = AUTOPTIMIZE_CRITICALCSS_API_KEY;
|
306 |
+
}
|
307 |
+
|
308 |
+
return $this->_options;
|
309 |
}
|
310 |
|
311 |
public function on_upgrade() {
|
312 |
+
$key = $this->get_option( 'key' );
|
313 |
|
314 |
// Create the cache directory if it doesn't exist already.
|
315 |
if ( ! file_exists( AO_CCSS_DIR ) ) {
|
316 |
+
$this->create_ao_ccss_dir();
|
317 |
}
|
318 |
|
319 |
// Create a scheduled event for the queue.
|
320 |
+
if ( $this->is_api_active() && ! wp_next_scheduled( 'ao_ccss_queue' ) ) {
|
321 |
wp_schedule_event( time(), apply_filters( 'ao_ccss_queue_schedule', 'ao_ccss' ), 'ao_ccss_queue' );
|
322 |
}
|
323 |
|
324 |
// Create a scheduled event for log maintenance.
|
325 |
+
if ( $this->is_api_active() && ! wp_next_scheduled( 'ao_ccss_maintenance' ) ) {
|
326 |
wp_schedule_event( time(), 'twicedaily', 'ao_ccss_maintenance' );
|
327 |
}
|
328 |
}
|
341 |
// Let interval be configurable.
|
342 |
if ( ! defined( 'AO_CCSS_DEBUG_INTERVAL' ) ) {
|
343 |
$intsec = 600;
|
344 |
+
$inttxt = '10 minutes';
|
345 |
} else {
|
346 |
$intsec = AO_CCSS_DEBUG_INTERVAL;
|
347 |
if ( $intsec >= 120 ) {
|
349 |
} else {
|
350 |
$inttxt = $intsec . ' second(s)';
|
351 |
}
|
352 |
+
$this->log( 'Using custom WP-Cron interval of ' . $inttxt, 3 );
|
353 |
}
|
354 |
|
355 |
// Attach interval to schedule.
|
356 |
$schedules['ao_ccss'] = array(
|
357 |
'interval' => $intsec,
|
358 |
+
'display' => __( 'Every ' . $inttxt . ' (Autoptimize Crit. CSS)' ),
|
359 |
);
|
360 |
return $schedules;
|
361 |
}
|
362 |
+
|
363 |
+
public function create_ao_ccss_dir() {
|
364 |
+
// Make sure dir to write ao_ccss exists and is writable.
|
365 |
+
if ( ! is_dir( AO_CCSS_DIR ) ) {
|
366 |
+
// TODO: use wp_mkdir_p()
|
367 |
+
$mkdirresp = @mkdir( AO_CCSS_DIR, 0775, true ); // @codingStandardsIgnoreLine
|
368 |
+
} else {
|
369 |
+
$mkdirresp = true;
|
370 |
+
}
|
371 |
+
|
372 |
+
// Make sure our index.html is there.
|
373 |
+
if ( ! is_file( AO_CCSS_DIR . 'index.html' ) ) {
|
374 |
+
$fileresp = file_put_contents( AO_CCSS_DIR . 'index.html', '<html><head><meta name="robots" content="noindex, nofollow"></head><body>Generated by <a href="http://wordpress.org/extend/plugins/autoptimize/" rel="nofollow">Autoptimize</a></body></html>' );
|
375 |
+
} else {
|
376 |
+
$fileresp = true;
|
377 |
+
}
|
378 |
+
|
379 |
+
if ( true === $fileresp && true === $mkdirresp ) {
|
380 |
+
return true;
|
381 |
+
} else {
|
382 |
+
return false;
|
383 |
+
}
|
384 |
+
}
|
385 |
+
|
386 |
+
/**
|
387 |
+
* Helper function to determine if there is an active API key.
|
388 |
+
*
|
389 |
+
* @return bool
|
390 |
+
*/
|
391 |
+
public function is_api_active() {
|
392 |
+
// using options instead of more complex $this->key_status (which gave some dependancy issues ... ;-) ).
|
393 |
+
$ao_ccss_key = $this->get_option( 'key' );
|
394 |
+
$ao_ccss_keyst = $this->get_option( 'keyst' );
|
395 |
+
|
396 |
+
if ( ! empty( $ao_ccss_key ) && $ao_ccss_keyst && 2 == $ao_ccss_keyst ) {
|
397 |
+
return true;
|
398 |
+
}
|
399 |
+
|
400 |
+
return false;
|
401 |
+
}
|
402 |
+
|
403 |
+
/**
|
404 |
+
* Helper function to determine if a rule is MANUAL.
|
405 |
+
*
|
406 |
+
* @param array $rule
|
407 |
+
*
|
408 |
+
* @return bool
|
409 |
+
*/
|
410 |
+
public function is_rule_manual( $rule ) {
|
411 |
+
if ( is_array( $rule ) && false == $rule['hash'] && false != $rule['file'] ) {
|
412 |
+
return true;
|
413 |
+
}
|
414 |
+
|
415 |
+
return false;
|
416 |
+
}
|
417 |
+
|
418 |
+
/**
|
419 |
+
* Scheduled action to check an inactive key. Not part of autoptimizeCriticalCSSCron.php
|
420 |
+
* to allow us to only load the main cron logic if we have an active key to begin with.
|
421 |
+
*
|
422 |
+
*/
|
423 |
+
public function ao_ccss_check_key() {
|
424 |
+
$ao_ccss_key = $this->get_option( 'key' );
|
425 |
+
$_result = $this->_core->ao_ccss_key_validation( $ao_ccss_key );
|
426 |
+
$_resmsg = ( true === $_result) ? 'ok' : 'nok';
|
427 |
+
$this->log( 'Inactive key checked, result was ' . $_resmsg, 3 );
|
428 |
+
}
|
429 |
}
|
classes/autoptimizeCriticalCSSCore.php
CHANGED
@@ -9,94 +9,91 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
9 |
}
|
10 |
|
11 |
class autoptimizeCriticalCSSCore {
|
12 |
-
|
13 |
-
{
|
14 |
-
// fetch all options at once and populate them individually explicitely as globals.
|
15 |
-
$all_options = autoptimizeCriticalCSSBase::fetch_options();
|
16 |
-
foreach ( $all_options as $_option => $_value ) {
|
17 |
-
global ${$_option};
|
18 |
-
${$_option} = $_value;
|
19 |
-
}
|
20 |
|
|
|
|
|
21 |
$this->run();
|
22 |
}
|
23 |
|
24 |
public function run() {
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
global $ao_ccss_unloadccss;
|
29 |
-
|
30 |
-
// add all filters to do CCSS if key present.
|
31 |
-
if ( $ao_css_defer && isset( $ao_ccss_key ) && ! empty( $ao_ccss_key ) ) {
|
32 |
-
// Set AO behavior: disable minification to avoid double minifying and caching.
|
33 |
-
add_filter( 'autoptimize_filter_css_critcss_minify', '__return_false' );
|
34 |
-
add_filter( 'autoptimize_filter_css_defer_inline', array( $this, 'ao_ccss_frontend' ), 10, 1 );
|
35 |
-
|
36 |
-
// Add the action to enqueue jobs for CriticalCSS cron.
|
37 |
-
add_action( 'autoptimize_action_css_hash', array( 'autoptimizeCriticalCSSEnqueue', 'ao_ccss_enqueue' ), 10, 1 );
|
38 |
-
|
39 |
-
// conditionally add the filter to defer jquery and others but only if not done so in autoptimizeScripts.
|
40 |
-
$_native_defer = false;
|
41 |
-
if ( 'on' === autoptimizeOptionWrapper::get_option( 'autoptimize_js_defer_not_aggregate' ) && 'on' === autoptimizeOptionWrapper::get_option( 'autoptimize_js_defer_inline' ) ) {
|
42 |
-
$_native_defer = true;
|
43 |
-
}
|
44 |
-
if ( $ao_ccss_deferjquery && ! $_native_defer ) {
|
45 |
-
add_filter( 'autoptimize_html_after_minify', array( $this, 'ao_ccss_defer_jquery' ), 11, 1 );
|
46 |
-
}
|
47 |
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
}
|
52 |
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
}
|
58 |
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
|
64 |
-
|
65 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
66 |
|
67 |
-
|
68 |
-
|
|
|
|
|
|
|
|
|
|
|
69 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
}
|
71 |
|
72 |
public function ao_ccss_frontend( $inlined ) {
|
73 |
// Apply CriticalCSS to frontend pages
|
74 |
// Attach types and settings arrays.
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
$no_ccss = '';
|
83 |
-
$ao_ccss_additional = autoptimizeStyles::sanitize_css( $ao_ccss_additional );
|
84 |
|
85 |
// Only if keystatus is OK and option to add CCSS for logged on users is on or user is not logged in.
|
86 |
-
if (
|
87 |
// Check for a valid CriticalCSS based on path to return its contents.
|
88 |
$req_path = strtok( $_SERVER['REQUEST_URI'], '?' );
|
89 |
-
if ( ! empty( $
|
90 |
-
foreach ( $
|
91 |
// explicit match OR partial match if MANUAL rule.
|
92 |
-
if ( $req_path == $path || urldecode( $req_path ) == $path || ( apply_filters( 'autoptimize_filter_ccss_core_path_partial_match', true ) && false == $rule['hash'] && false != $rule['file'] && strpos( $req_path, str_replace( site_url(), '', $path ) ) !== false ) ) {
|
93 |
if ( file_exists( AO_CCSS_DIR . $rule['file'] ) ) {
|
94 |
$_ccss_contents = file_get_contents( AO_CCSS_DIR . $rule['file'] );
|
95 |
if ( 'none' != $_ccss_contents ) {
|
96 |
-
if ( $
|
97 |
$_ccss_contents = '/* PATH: ' . $path . ' hash: ' . $rule['hash'] . ' file: ' . $rule['file'] . ' */ ' . $_ccss_contents;
|
98 |
}
|
99 |
-
return apply_filters( 'autoptimize_filter_ccss_core_ccss', $_ccss_contents . $
|
100 |
} else {
|
101 |
$no_ccss = 'none';
|
102 |
}
|
@@ -106,55 +103,55 @@ class autoptimizeCriticalCSSCore {
|
|
106 |
}
|
107 |
|
108 |
// Check for a valid CriticalCSS based on conditional tags to return its contents.
|
109 |
-
if ( ! empty( $
|
110 |
// order types-rules by the order of the original $ao_ccss_types array so as not to depend on the order in which rules were added.
|
111 |
-
$
|
112 |
-
$is_front_page
|
113 |
|
114 |
-
foreach ( $
|
115 |
-
if ( in_array( $type, $
|
116 |
$_ccss_contents = file_get_contents( AO_CCSS_DIR . $rule['file'] );
|
117 |
if ( $is_front_page && 'is_front_page' == $type ) {
|
118 |
if ( 'none' != $_ccss_contents ) {
|
119 |
-
if ( $
|
120 |
$_ccss_contents = '/* TYPES: ' . $type . ' hash: ' . $rule['hash'] . ' file: ' . $rule['file'] . ' */ ' . $_ccss_contents;
|
121 |
}
|
122 |
-
return apply_filters( 'autoptimize_filter_ccss_core_ccss', $_ccss_contents . $
|
123 |
} else {
|
124 |
$no_ccss = 'none';
|
125 |
}
|
126 |
-
} elseif ( strpos( $type, 'custom_post_' ) === 0 && ! $is_front_page ) {
|
127 |
if ( get_post_type( get_the_ID() ) === substr( $type, 12 ) ) {
|
128 |
if ( 'none' != $_ccss_contents ) {
|
129 |
-
if ( $
|
130 |
$_ccss_contents = '/* TYPES: ' . $type . ' hash: ' . $rule['hash'] . ' file: ' . $rule['file'] . ' */ ' . $_ccss_contents;
|
131 |
}
|
132 |
-
return apply_filters( 'autoptimize_filter_ccss_core_ccss', $_ccss_contents . $
|
133 |
} else {
|
134 |
$no_ccss = 'none';
|
135 |
}
|
136 |
}
|
137 |
-
} elseif ( 0 === strpos( $type, 'template_' ) && ! $is_front_page ) {
|
138 |
if ( is_page_template( substr( $type, 9 ) ) ) {
|
139 |
if ( 'none' != $_ccss_contents ) {
|
140 |
-
if ( $
|
141 |
$_ccss_contents = '/* TYPES: ' . $type . ' hash: ' . $rule['hash'] . ' file: ' . $rule['file'] . ' */ ' . $_ccss_contents;
|
142 |
}
|
143 |
-
return apply_filters( 'autoptimize_filter_ccss_core_ccss', $_ccss_contents . $
|
144 |
} else {
|
145 |
$no_ccss = 'none';
|
146 |
}
|
147 |
}
|
148 |
-
} elseif ( ! $is_front_page ) {
|
149 |
// all "normal" conditional tags, core + woo + buddypress + edd + bbpress
|
150 |
// but we have to remove the prefix for the non-core ones for them to function.
|
151 |
$type = str_replace( array( 'woo_', 'bp_', 'bbp_', 'edd_' ), '', $type );
|
152 |
if ( function_exists( $type ) && call_user_func( $type ) ) {
|
153 |
if ( 'none' != $_ccss_contents ) {
|
154 |
-
if ( $
|
155 |
$_ccss_contents = '/* TYPES: ' . $type . ' hash: ' . $rule['hash'] . ' file: ' . $rule['file'] . ' */ ' . $_ccss_contents;
|
156 |
}
|
157 |
-
return apply_filters( 'autoptimize_filter_ccss_core_ccss', $_ccss_contents . $
|
158 |
} else {
|
159 |
$no_ccss = 'none';
|
160 |
}
|
@@ -168,7 +165,7 @@ class autoptimizeCriticalCSSCore {
|
|
168 |
// Finally, inline the default CriticalCSS if any or else the entire CSS for the page
|
169 |
// This also applies to logged in users if the option to add CCSS for logged in users has been disabled.
|
170 |
if ( ! empty( $inlined ) && 'none' !== $no_ccss ) {
|
171 |
-
return apply_filters( 'autoptimize_filter_ccss_core_ccss', $inlined . $
|
172 |
} else {
|
173 |
add_filter( 'autoptimize_filter_css_inline', '__return_true' );
|
174 |
return;
|
@@ -176,9 +173,10 @@ class autoptimizeCriticalCSSCore {
|
|
176 |
}
|
177 |
|
178 |
public function ao_ccss_defer_jquery( $in ) {
|
179 |
-
|
|
|
180 |
// defer all linked and inline JS.
|
181 |
-
if ( ( ! is_user_logged_in() || $
|
182 |
foreach ( $matches as $match ) {
|
183 |
if ( str_replace( apply_filters( 'autoptimize_filter_ccss_core_defer_exclude', array( 'data-noptimize="1"', 'data-cfasync="false"', 'data-pagespeed-no-defer' ) ), '', $match[0] ) !== $match[0] ) {
|
184 |
// do not touch JS with noptimize/ cfasync/ pagespeed-no-defer flags.
|
@@ -208,15 +206,23 @@ class autoptimizeCriticalCSSCore {
|
|
208 |
return str_replace( '</body>', $_unloadccss_js . '</body>', $html_in );
|
209 |
}
|
210 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
211 |
public function ao_ccss_extend_types() {
|
212 |
// Extend contidional tags
|
213 |
// Attach the conditional tags array.
|
214 |
-
global $ao_ccss_types;
|
215 |
|
216 |
// in some cases $ao_ccss_types is empty and/or not an array, this should work around that problem.
|
217 |
-
if ( empty( $
|
218 |
-
$
|
219 |
-
|
220 |
}
|
221 |
|
222 |
// Custom Post Types.
|
@@ -229,7 +235,7 @@ class autoptimizeCriticalCSSCore {
|
|
229 |
'and'
|
230 |
);
|
231 |
foreach ( $cpts as $cpt ) {
|
232 |
-
array_unshift( $
|
233 |
}
|
234 |
|
235 |
// Templates.
|
@@ -240,12 +246,12 @@ class autoptimizeCriticalCSSCore {
|
|
240 |
set_transient( 'autoptimize_ccss_page_templates', $templates, HOUR_IN_SECONDS );
|
241 |
}
|
242 |
foreach ( $templates as $tplfile => $tplname ) {
|
243 |
-
array_unshift( $
|
244 |
}
|
245 |
|
246 |
// bbPress tags.
|
247 |
if ( function_exists( 'is_bbpress' ) ) {
|
248 |
-
$
|
249 |
array(
|
250 |
'bbp_is_bbpress',
|
251 |
'bbp_is_favorites',
|
@@ -271,13 +277,13 @@ class autoptimizeCriticalCSSCore {
|
|
271 |
'bbp_is_topics_created',
|
272 |
'bbp_is_user_home',
|
273 |
'bbp_is_user_home_edit',
|
274 |
-
), $
|
275 |
);
|
276 |
}
|
277 |
|
278 |
// BuddyPress tags.
|
279 |
if ( function_exists( 'is_buddypress' ) ) {
|
280 |
-
$
|
281 |
array(
|
282 |
'bp_is_activation_page',
|
283 |
'bp_is_activity',
|
@@ -313,25 +319,25 @@ class autoptimizeCriticalCSSCore {
|
|
313 |
'bp_is_user',
|
314 |
'bp_is_user_profile',
|
315 |
'bp_is_wire',
|
316 |
-
), $
|
317 |
);
|
318 |
}
|
319 |
|
320 |
// Easy Digital Downloads (EDD) tags.
|
321 |
if ( function_exists( 'edd_is_checkout' ) ) {
|
322 |
-
$
|
323 |
array(
|
324 |
'edd_is_checkout',
|
325 |
'edd_is_failed_transaction_page',
|
326 |
'edd_is_purchase_history_page',
|
327 |
'edd_is_success_page',
|
328 |
-
), $
|
329 |
);
|
330 |
}
|
331 |
|
332 |
// WooCommerce tags.
|
333 |
if ( class_exists( 'WooCommerce' ) ) {
|
334 |
-
$
|
335 |
array(
|
336 |
'woo_is_account_page',
|
337 |
'woo_is_cart',
|
@@ -342,42 +348,33 @@ class autoptimizeCriticalCSSCore {
|
|
342 |
'woo_is_shop',
|
343 |
'woo_is_wc_endpoint_url',
|
344 |
'woo_is_woocommerce',
|
345 |
-
), $
|
346 |
);
|
347 |
}
|
348 |
}
|
349 |
|
350 |
public function get_ao_ccss_core_types() {
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
'is_sticky',
|
366 |
-
'is_paged',
|
367 |
-
);
|
368 |
-
} else {
|
369 |
-
return $ao_ccss_types;
|
370 |
-
}
|
371 |
}
|
372 |
|
373 |
-
public
|
374 |
// Provide key status
|
375 |
// Get key and key status.
|
376 |
-
|
377 |
-
|
378 |
-
$self = new self();
|
379 |
-
$key = $ao_ccss_key;
|
380 |
-
$key_status = $ao_ccss_keyst;
|
381 |
|
382 |
// Prepare returned variables.
|
383 |
$key_return = array();
|
@@ -400,7 +397,7 @@ class autoptimizeCriticalCSSCore {
|
|
400 |
} elseif ( $key && ! $key_status ) {
|
401 |
// Key exists but it has no valid status yet
|
402 |
// Perform key validation.
|
403 |
-
$key_check = $
|
404 |
|
405 |
// Key is valid, set valid status.
|
406 |
if ( $key_check ) {
|
@@ -442,14 +439,14 @@ class autoptimizeCriticalCSSCore {
|
|
442 |
}
|
443 |
|
444 |
public function ao_ccss_key_validation( $key ) {
|
445 |
-
|
446 |
|
447 |
// POST a dummy job to criticalcss.com to check for key validation
|
448 |
// Prepare home URL for the request.
|
449 |
$src_url = get_home_url();
|
450 |
|
451 |
// Avoid AO optimizations if required by config or avoid lazyload if lazyload is active in AO.
|
452 |
-
if ( ! empty( $
|
453 |
$src_url .= '?ao_noptirocket=1';
|
454 |
} elseif ( class_exists( 'autoptimizeImages', false ) && autoptimizeImages::should_lazyload_wrapper() ) {
|
455 |
$src_url .= '?ao_nolazy=1';
|
@@ -460,12 +457,12 @@ class autoptimizeCriticalCSSCore {
|
|
460 |
// Prepare the request.
|
461 |
$url = esc_url_raw( AO_CCSS_API . 'generate' );
|
462 |
$args = array(
|
463 |
-
'headers' => array(
|
464 |
'User-Agent' => 'Autoptimize v' . AO_CCSS_VER,
|
465 |
'Content-type' => 'application/json; charset=utf-8',
|
466 |
'Authorization' => 'JWT ' . $key,
|
467 |
'Connection' => 'close',
|
468 |
-
),
|
469 |
// Body must be JSON.
|
470 |
'body' => json_encode(
|
471 |
apply_filters( 'autoptimize_ccss_cron_api_generate_body',
|
@@ -487,14 +484,14 @@ class autoptimizeCriticalCSSCore {
|
|
487 |
// Response is OK.
|
488 |
// Set key status as valid and log key check.
|
489 |
update_option( 'autoptimize_ccss_keyst', 2 );
|
490 |
-
|
491 |
|
492 |
// extract job-id from $body and put it in the queue as a P job
|
493 |
// but only if no jobs and no rules!
|
494 |
-
|
495 |
-
|
496 |
|
497 |
-
if ( 0 == count( $
|
498 |
if ( 'JOB_QUEUED' == $body['job']['status'] || 'JOB_ONGOING' == $body['job']['status'] ) {
|
499 |
$jprops['ljid'] = 'firstrun';
|
500 |
$jprops['rtarget'] = 'types|is_front_page';
|
@@ -508,10 +505,10 @@ class autoptimizeCriticalCSSCore {
|
|
508 |
$jprops['jvstat'] = null;
|
509 |
$jprops['jctime'] = microtime( true );
|
510 |
$jprops['jftime'] = null;
|
511 |
-
$
|
512 |
-
$
|
513 |
-
update_option( 'autoptimize_ccss_queue', $
|
514 |
-
|
515 |
}
|
516 |
}
|
517 |
return true;
|
@@ -519,55 +516,41 @@ class autoptimizeCriticalCSSCore {
|
|
519 |
// Response is unauthorized
|
520 |
// Set key status as invalid and log key check.
|
521 |
update_option( 'autoptimize_ccss_keyst', 1 );
|
522 |
-
|
523 |
return false;
|
524 |
} else {
|
525 |
// Response unkown
|
526 |
// Log key check attempt.
|
527 |
-
|
528 |
if ( ! empty( $body ) ) {
|
529 |
-
|
530 |
}
|
531 |
if ( is_wp_error( $req ) ) {
|
532 |
-
|
533 |
}
|
534 |
return false;
|
535 |
}
|
536 |
}
|
537 |
|
538 |
-
public
|
539 |
// Get viewport size
|
540 |
// Attach viewport option.
|
541 |
-
|
542 |
-
|
543 |
-
// Prepare viewport array.
|
544 |
-
$viewport = array();
|
545 |
|
546 |
-
|
547 |
-
|
548 |
-
$viewport['
|
549 |
-
|
550 |
-
$viewport['w'] = '';
|
551 |
-
}
|
552 |
-
|
553 |
-
// Viewport Height.
|
554 |
-
if ( ! empty( $ao_ccss_viewport['h'] ) ) {
|
555 |
-
$viewport['h'] = $ao_ccss_viewport['h'];
|
556 |
-
} else {
|
557 |
-
$viewport['h'] = '';
|
558 |
-
}
|
559 |
-
|
560 |
-
return $viewport;
|
561 |
}
|
562 |
|
563 |
-
public
|
564 |
// Perform basic exploit avoidance and CSS validation.
|
565 |
if ( ! empty( $ccss ) ) {
|
566 |
// Try to avoid code injection.
|
567 |
$blocklist = array( '#!/', 'function(', '<script', '<?php' );
|
568 |
foreach ( $blocklist as $blocklisted ) {
|
569 |
if ( strpos( $ccss, $blocklisted ) !== false ) {
|
570 |
-
|
571 |
return false;
|
572 |
}
|
573 |
}
|
@@ -576,7 +559,7 @@ class autoptimizeCriticalCSSCore {
|
|
576 |
$needlist = array( '{', '}', ':' );
|
577 |
foreach ( $needlist as $needed ) {
|
578 |
if ( false === strpos( $ccss, $needed ) && 'none' !== $ccss ) {
|
579 |
-
|
580 |
return false;
|
581 |
}
|
582 |
}
|
@@ -586,10 +569,10 @@ class autoptimizeCriticalCSSCore {
|
|
586 |
return true;
|
587 |
}
|
588 |
|
589 |
-
public
|
590 |
// Commom logging facility
|
591 |
// Attach debug option.
|
592 |
-
|
593 |
|
594 |
// Prepare log levels, where accepted $lvl are:
|
595 |
// 1: II (for info)
|
@@ -606,7 +589,7 @@ class autoptimizeCriticalCSSCore {
|
|
606 |
break;
|
607 |
case 3:
|
608 |
// Output debug messages only if debug mode is enabled.
|
609 |
-
if ( $
|
610 |
$level = 'DD';
|
611 |
}
|
612 |
break;
|
@@ -625,9 +608,8 @@ class autoptimizeCriticalCSSCore {
|
|
625 |
}
|
626 |
}
|
627 |
|
628 |
-
public
|
629 |
// Clears transient cache for page templates.
|
630 |
delete_transient( 'autoptimize_ccss_page_templates' );
|
631 |
}
|
632 |
-
|
633 |
}
|
9 |
}
|
10 |
|
11 |
class autoptimizeCriticalCSSCore {
|
12 |
+
protected $_types = null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
|
14 |
+
public function __construct() {
|
15 |
+
$this->criticalcss = autoptimize()->criticalcss();
|
16 |
$this->run();
|
17 |
}
|
18 |
|
19 |
public function run() {
|
20 |
+
$css_defer = $this->criticalcss->get_option( 'css_defer' );
|
21 |
+
$deferjquery = $this->criticalcss->get_option( 'deferjquery' );
|
22 |
+
$unloadccss = $this->criticalcss->get_option( 'unloadccss' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
|
24 |
+
if ( ! $css_defer ) {
|
25 |
+
return;
|
26 |
+
}
|
|
|
27 |
|
28 |
+
// add all filters to do CCSS
|
29 |
+
// Set AO behavior: disable minification to avoid double minifying and caching.
|
30 |
+
add_filter( 'autoptimize_filter_css_critcss_minify', '__return_false' );
|
31 |
+
add_filter( 'autoptimize_filter_css_defer_inline', array( $this, 'ao_ccss_frontend' ), 10, 1 );
|
|
|
32 |
|
33 |
+
// Add the action to enqueue jobs for CriticalCSS cron.
|
34 |
+
if ( $this->criticalcss->is_api_active() ) {
|
35 |
+
add_action( 'autoptimize_action_css_hash', array( $this->criticalcss, 'enqueue' ), 10, 1 );
|
36 |
+
}
|
37 |
|
38 |
+
// conditionally add the filter to defer jquery and others but only if not done so in autoptimizeScripts.
|
39 |
+
$_native_defer = false;
|
40 |
+
if ( 'on' === autoptimizeOptionWrapper::get_option( 'autoptimize_js_defer_not_aggregate' ) && 'on' === autoptimizeOptionWrapper::get_option( 'autoptimize_js_defer_inline' ) ) {
|
41 |
+
$_native_defer = true;
|
42 |
+
}
|
43 |
+
if ( $deferjquery && ! $_native_defer ) {
|
44 |
+
add_filter( 'autoptimize_html_after_minify', array( $this, 'ao_ccss_defer_jquery' ), 11, 1 );
|
45 |
+
}
|
46 |
+
|
47 |
+
// conditionally add filter to unload the CCSS.
|
48 |
+
if ( $unloadccss ) {
|
49 |
+
add_filter( 'autoptimize_html_after_minify', array( $this, 'ao_ccss_unloadccss' ), 12, 1 );
|
50 |
+
}
|
51 |
|
52 |
+
// Order paths by length, as longest ones have greater priority in the rules.
|
53 |
+
$rules = $this->criticalcss->get_option( 'rules' );
|
54 |
+
if ( ! empty( $rules['paths'] ) ) {
|
55 |
+
$keys = array_map( 'strlen', array_keys( $rules['paths'] ) );
|
56 |
+
array_multisort( $keys, SORT_DESC, $rules['paths'] );
|
57 |
+
// TODO: Not sure what we're doing here. Sorted the $keys,
|
58 |
+
// but they don't seem to be used anywhere.
|
59 |
}
|
60 |
+
|
61 |
+
// Add an array with default WordPress's conditional tags
|
62 |
+
// NOTE: these tags are sorted.
|
63 |
+
$this->_types = $this->get_ao_ccss_core_types();
|
64 |
+
|
65 |
+
// Extend conditional tags on plugin initalization.
|
66 |
+
add_action( apply_filters( 'autoptimize_filter_ccss_extend_types_hook', 'init' ), array( $this, 'ao_ccss_extend_types' ) );
|
67 |
+
|
68 |
+
// When autoptimize cache is cleared, also clear transient cache for page templates.
|
69 |
+
add_action( 'autoptimize_action_cachepurged', array( $this, 'ao_ccss_clear_page_tpl_cache' ), 10, 0 );
|
70 |
}
|
71 |
|
72 |
public function ao_ccss_frontend( $inlined ) {
|
73 |
// Apply CriticalCSS to frontend pages
|
74 |
// Attach types and settings arrays.
|
75 |
+
$rules = $this->criticalcss->get_option( 'rules' );
|
76 |
+
$additional = $this->criticalcss->get_option( 'additional' );
|
77 |
+
$loggedin = $this->criticalcss->get_option( 'loggedin' );
|
78 |
+
$debug = $this->criticalcss->get_option( 'debug' );
|
79 |
+
$no_ccss = '';
|
80 |
+
$additional = autoptimizeStyles::sanitize_css( $additional );
|
|
|
|
|
|
|
81 |
|
82 |
// Only if keystatus is OK and option to add CCSS for logged on users is on or user is not logged in.
|
83 |
+
if ( $loggedin || ! is_user_logged_in() ) {
|
84 |
// Check for a valid CriticalCSS based on path to return its contents.
|
85 |
$req_path = strtok( $_SERVER['REQUEST_URI'], '?' );
|
86 |
+
if ( ! empty( $rules['paths'] ) ) {
|
87 |
+
foreach ( $rules['paths'] as $path => $rule ) {
|
88 |
// explicit match OR partial match if MANUAL rule.
|
89 |
+
if ( ( $this->criticalcss->is_api_active() || $this->criticalcss->is_rule_manual( $rule ) ) && ( $req_path == $path || urldecode( $req_path ) == $path || ( apply_filters( 'autoptimize_filter_ccss_core_path_partial_match', true ) && false == $rule['hash'] && false != $rule['file'] && strpos( $req_path, str_replace( site_url(), '', $path ) ) !== false ) ) ) {
|
90 |
if ( file_exists( AO_CCSS_DIR . $rule['file'] ) ) {
|
91 |
$_ccss_contents = file_get_contents( AO_CCSS_DIR . $rule['file'] );
|
92 |
if ( 'none' != $_ccss_contents ) {
|
93 |
+
if ( $debug ) {
|
94 |
$_ccss_contents = '/* PATH: ' . $path . ' hash: ' . $rule['hash'] . ' file: ' . $rule['file'] . ' */ ' . $_ccss_contents;
|
95 |
}
|
96 |
+
return apply_filters( 'autoptimize_filter_ccss_core_ccss', $_ccss_contents . $additional );
|
97 |
} else {
|
98 |
$no_ccss = 'none';
|
99 |
}
|
103 |
}
|
104 |
|
105 |
// Check for a valid CriticalCSS based on conditional tags to return its contents.
|
106 |
+
if ( ! empty( $rules['types'] ) && 'none' !== $no_ccss ) {
|
107 |
// order types-rules by the order of the original $ao_ccss_types array so as not to depend on the order in which rules were added.
|
108 |
+
$rules['types'] = array_replace( array_intersect_key( array_flip( $this->_types ), $rules['types'] ), $rules['types'] );
|
109 |
+
$is_front_page = is_front_page();
|
110 |
|
111 |
+
foreach ( $rules['types'] as $type => $rule ) {
|
112 |
+
if ( ( $this->criticalcss->is_api_active() || $this->criticalcss->is_rule_manual( $rule ) ) && in_array( $type, $this->_types ) && file_exists( AO_CCSS_DIR . $rule['file'] ) ) {
|
113 |
$_ccss_contents = file_get_contents( AO_CCSS_DIR . $rule['file'] );
|
114 |
if ( $is_front_page && 'is_front_page' == $type ) {
|
115 |
if ( 'none' != $_ccss_contents ) {
|
116 |
+
if ( $debug ) {
|
117 |
$_ccss_contents = '/* TYPES: ' . $type . ' hash: ' . $rule['hash'] . ' file: ' . $rule['file'] . ' */ ' . $_ccss_contents;
|
118 |
}
|
119 |
+
return apply_filters( 'autoptimize_filter_ccss_core_ccss', $_ccss_contents . $additional );
|
120 |
} else {
|
121 |
$no_ccss = 'none';
|
122 |
}
|
123 |
+
} elseif ( ( $this->criticalcss->is_api_active() || $this->criticalcss->is_rule_manual( $rule ) ) && strpos( $type, 'custom_post_' ) === 0 && ! $is_front_page ) {
|
124 |
if ( get_post_type( get_the_ID() ) === substr( $type, 12 ) ) {
|
125 |
if ( 'none' != $_ccss_contents ) {
|
126 |
+
if ( $debug ) {
|
127 |
$_ccss_contents = '/* TYPES: ' . $type . ' hash: ' . $rule['hash'] . ' file: ' . $rule['file'] . ' */ ' . $_ccss_contents;
|
128 |
}
|
129 |
+
return apply_filters( 'autoptimize_filter_ccss_core_ccss', $_ccss_contents . $additional );
|
130 |
} else {
|
131 |
$no_ccss = 'none';
|
132 |
}
|
133 |
}
|
134 |
+
} elseif ( ( $this->criticalcss->is_api_active() || $this->criticalcss->is_rule_manual( $rule ) ) && 0 === strpos( $type, 'template_' ) && ! $is_front_page ) {
|
135 |
if ( is_page_template( substr( $type, 9 ) ) ) {
|
136 |
if ( 'none' != $_ccss_contents ) {
|
137 |
+
if ( $debug ) {
|
138 |
$_ccss_contents = '/* TYPES: ' . $type . ' hash: ' . $rule['hash'] . ' file: ' . $rule['file'] . ' */ ' . $_ccss_contents;
|
139 |
}
|
140 |
+
return apply_filters( 'autoptimize_filter_ccss_core_ccss', $_ccss_contents . $additional );
|
141 |
} else {
|
142 |
$no_ccss = 'none';
|
143 |
}
|
144 |
}
|
145 |
+
} elseif ( ( $this->criticalcss->is_api_active() || $this->criticalcss->is_rule_manual( $rule ) ) && ! $is_front_page ) {
|
146 |
// all "normal" conditional tags, core + woo + buddypress + edd + bbpress
|
147 |
// but we have to remove the prefix for the non-core ones for them to function.
|
148 |
$type = str_replace( array( 'woo_', 'bp_', 'bbp_', 'edd_' ), '', $type );
|
149 |
if ( function_exists( $type ) && call_user_func( $type ) ) {
|
150 |
if ( 'none' != $_ccss_contents ) {
|
151 |
+
if ( $debug ) {
|
152 |
$_ccss_contents = '/* TYPES: ' . $type . ' hash: ' . $rule['hash'] . ' file: ' . $rule['file'] . ' */ ' . $_ccss_contents;
|
153 |
}
|
154 |
+
return apply_filters( 'autoptimize_filter_ccss_core_ccss', $_ccss_contents . $additional );
|
155 |
} else {
|
156 |
$no_ccss = 'none';
|
157 |
}
|
165 |
// Finally, inline the default CriticalCSS if any or else the entire CSS for the page
|
166 |
// This also applies to logged in users if the option to add CCSS for logged in users has been disabled.
|
167 |
if ( ! empty( $inlined ) && 'none' !== $no_ccss ) {
|
168 |
+
return apply_filters( 'autoptimize_filter_ccss_core_ccss', $inlined . $additional );
|
169 |
} else {
|
170 |
add_filter( 'autoptimize_filter_css_inline', '__return_true' );
|
171 |
return;
|
173 |
}
|
174 |
|
175 |
public function ao_ccss_defer_jquery( $in ) {
|
176 |
+
$loggedin = $this->criticalcss->get_option( 'loggedin' );
|
177 |
+
|
178 |
// defer all linked and inline JS.
|
179 |
+
if ( ( ! is_user_logged_in() || $loggedin ) && preg_match_all( '#<script.*>(.*)</script>#Usmi', $in, $matches, PREG_SET_ORDER ) ) {
|
180 |
foreach ( $matches as $match ) {
|
181 |
if ( str_replace( apply_filters( 'autoptimize_filter_ccss_core_defer_exclude', array( 'data-noptimize="1"', 'data-cfasync="false"', 'data-pagespeed-no-defer' ) ), '', $match[0] ) !== $match[0] ) {
|
182 |
// do not touch JS with noptimize/ cfasync/ pagespeed-no-defer flags.
|
206 |
return str_replace( '</body>', $_unloadccss_js . '</body>', $html_in );
|
207 |
}
|
208 |
|
209 |
+
/**
|
210 |
+
* Get the types array.
|
211 |
+
*
|
212 |
+
* @return array|null
|
213 |
+
*/
|
214 |
+
public function get_types() {
|
215 |
+
return $this->_types;
|
216 |
+
}
|
217 |
+
|
218 |
public function ao_ccss_extend_types() {
|
219 |
// Extend contidional tags
|
220 |
// Attach the conditional tags array.
|
|
|
221 |
|
222 |
// in some cases $ao_ccss_types is empty and/or not an array, this should work around that problem.
|
223 |
+
if ( empty( $this->_types ) || ! is_array( $this->_types ) ) {
|
224 |
+
$this->_types = $this->get_ao_ccss_core_types();
|
225 |
+
$this->ao_ccss_log( 'Empty types array in extend, refetching array with core conditionals.', 3 );
|
226 |
}
|
227 |
|
228 |
// Custom Post Types.
|
235 |
'and'
|
236 |
);
|
237 |
foreach ( $cpts as $cpt ) {
|
238 |
+
array_unshift( $this->_types, 'custom_post_' . $cpt );
|
239 |
}
|
240 |
|
241 |
// Templates.
|
246 |
set_transient( 'autoptimize_ccss_page_templates', $templates, HOUR_IN_SECONDS );
|
247 |
}
|
248 |
foreach ( $templates as $tplfile => $tplname ) {
|
249 |
+
array_unshift( $this->_types, 'template_' . $tplfile );
|
250 |
}
|
251 |
|
252 |
// bbPress tags.
|
253 |
if ( function_exists( 'is_bbpress' ) ) {
|
254 |
+
$this->_types = array_merge(
|
255 |
array(
|
256 |
'bbp_is_bbpress',
|
257 |
'bbp_is_favorites',
|
277 |
'bbp_is_topics_created',
|
278 |
'bbp_is_user_home',
|
279 |
'bbp_is_user_home_edit',
|
280 |
+
), $this->_types
|
281 |
);
|
282 |
}
|
283 |
|
284 |
// BuddyPress tags.
|
285 |
if ( function_exists( 'is_buddypress' ) ) {
|
286 |
+
$this->_types = array_merge(
|
287 |
array(
|
288 |
'bp_is_activation_page',
|
289 |
'bp_is_activity',
|
319 |
'bp_is_user',
|
320 |
'bp_is_user_profile',
|
321 |
'bp_is_wire',
|
322 |
+
), $this->_types
|
323 |
);
|
324 |
}
|
325 |
|
326 |
// Easy Digital Downloads (EDD) tags.
|
327 |
if ( function_exists( 'edd_is_checkout' ) ) {
|
328 |
+
$this->_types = array_merge(
|
329 |
array(
|
330 |
'edd_is_checkout',
|
331 |
'edd_is_failed_transaction_page',
|
332 |
'edd_is_purchase_history_page',
|
333 |
'edd_is_success_page',
|
334 |
+
), $this->_types
|
335 |
);
|
336 |
}
|
337 |
|
338 |
// WooCommerce tags.
|
339 |
if ( class_exists( 'WooCommerce' ) ) {
|
340 |
+
$this->_types = array_merge(
|
341 |
array(
|
342 |
'woo_is_account_page',
|
343 |
'woo_is_cart',
|
348 |
'woo_is_shop',
|
349 |
'woo_is_wc_endpoint_url',
|
350 |
'woo_is_woocommerce',
|
351 |
+
), $this->_types
|
352 |
);
|
353 |
}
|
354 |
}
|
355 |
|
356 |
public function get_ao_ccss_core_types() {
|
357 |
+
return array(
|
358 |
+
'is_404',
|
359 |
+
'is_front_page',
|
360 |
+
'is_home',
|
361 |
+
'is_page',
|
362 |
+
'is_single',
|
363 |
+
'is_category',
|
364 |
+
'is_author',
|
365 |
+
'is_archive',
|
366 |
+
'is_search',
|
367 |
+
'is_attachment',
|
368 |
+
'is_sticky',
|
369 |
+
'is_paged',
|
370 |
+
);
|
|
|
|
|
|
|
|
|
|
|
|
|
371 |
}
|
372 |
|
373 |
+
public function ao_ccss_key_status( $render ) {
|
374 |
// Provide key status
|
375 |
// Get key and key status.
|
376 |
+
$key = $this->criticalcss->get_option( 'key' );
|
377 |
+
$key_status = $this->criticalcss->get_option( 'keyst' );
|
|
|
|
|
|
|
378 |
|
379 |
// Prepare returned variables.
|
380 |
$key_return = array();
|
397 |
} elseif ( $key && ! $key_status ) {
|
398 |
// Key exists but it has no valid status yet
|
399 |
// Perform key validation.
|
400 |
+
$key_check = $this->ao_ccss_key_validation( $key );
|
401 |
|
402 |
// Key is valid, set valid status.
|
403 |
if ( $key_check ) {
|
439 |
}
|
440 |
|
441 |
public function ao_ccss_key_validation( $key ) {
|
442 |
+
$noptimize = $this->criticalcss->get_option( 'noptimize' );
|
443 |
|
444 |
// POST a dummy job to criticalcss.com to check for key validation
|
445 |
// Prepare home URL for the request.
|
446 |
$src_url = get_home_url();
|
447 |
|
448 |
// Avoid AO optimizations if required by config or avoid lazyload if lazyload is active in AO.
|
449 |
+
if ( ! empty( $noptimize ) ) {
|
450 |
$src_url .= '?ao_noptirocket=1';
|
451 |
} elseif ( class_exists( 'autoptimizeImages', false ) && autoptimizeImages::should_lazyload_wrapper() ) {
|
452 |
$src_url .= '?ao_nolazy=1';
|
457 |
// Prepare the request.
|
458 |
$url = esc_url_raw( AO_CCSS_API . 'generate' );
|
459 |
$args = array(
|
460 |
+
'headers' => apply_filters( 'autoptimize_ccss_cron_api_generate_headers', array(
|
461 |
'User-Agent' => 'Autoptimize v' . AO_CCSS_VER,
|
462 |
'Content-type' => 'application/json; charset=utf-8',
|
463 |
'Authorization' => 'JWT ' . $key,
|
464 |
'Connection' => 'close',
|
465 |
+
) ),
|
466 |
// Body must be JSON.
|
467 |
'body' => json_encode(
|
468 |
apply_filters( 'autoptimize_ccss_cron_api_generate_body',
|
484 |
// Response is OK.
|
485 |
// Set key status as valid and log key check.
|
486 |
update_option( 'autoptimize_ccss_keyst', 2 );
|
487 |
+
$this->ao_ccss_log( 'criticalcss.com: API key is valid, updating key status', 3 );
|
488 |
|
489 |
// extract job-id from $body and put it in the queue as a P job
|
490 |
// but only if no jobs and no rules!
|
491 |
+
$queue = $this->criticalcss->get_option( 'queue' );
|
492 |
+
$rules = $this->criticalcss->get_option( 'rules' );
|
493 |
|
494 |
+
if ( 0 == count( $queue ) && 0 == count( $rules['types'] ) && 0 == count( $rules['paths'] ) ) {
|
495 |
if ( 'JOB_QUEUED' == $body['job']['status'] || 'JOB_ONGOING' == $body['job']['status'] ) {
|
496 |
$jprops['ljid'] = 'firstrun';
|
497 |
$jprops['rtarget'] = 'types|is_front_page';
|
505 |
$jprops['jvstat'] = null;
|
506 |
$jprops['jctime'] = microtime( true );
|
507 |
$jprops['jftime'] = null;
|
508 |
+
$queue['/'] = $jprops;
|
509 |
+
$queue_raw = json_encode( $queue );
|
510 |
+
update_option( 'autoptimize_ccss_queue', $queue_raw, false );
|
511 |
+
$this->ao_ccss_log( 'Created P job for is_front_page based on API key check response.', 3 );
|
512 |
}
|
513 |
}
|
514 |
return true;
|
516 |
// Response is unauthorized
|
517 |
// Set key status as invalid and log key check.
|
518 |
update_option( 'autoptimize_ccss_keyst', 1 );
|
519 |
+
$this->ao_ccss_log( 'criticalcss.com: API key is invalid, updating key status', 3 );
|
520 |
return false;
|
521 |
} else {
|
522 |
// Response unkown
|
523 |
// Log key check attempt.
|
524 |
+
$this->ao_ccss_log( 'criticalcss.com: could not check API key status, this is a service error, body follows if any...', 2 );
|
525 |
if ( ! empty( $body ) ) {
|
526 |
+
$this->ao_ccss_log( print_r( $body, true ), 2 );
|
527 |
}
|
528 |
if ( is_wp_error( $req ) ) {
|
529 |
+
$this->ao_ccss_log( $req->get_error_message(), 2 );
|
530 |
}
|
531 |
return false;
|
532 |
}
|
533 |
}
|
534 |
|
535 |
+
public function ao_ccss_viewport() {
|
536 |
// Get viewport size
|
537 |
// Attach viewport option.
|
538 |
+
$viewport = $this->criticalcss->get_option( 'viewport' );
|
|
|
|
|
|
|
539 |
|
540 |
+
return array(
|
541 |
+
'w' => ! empty( $viewport['w'] ) ? $viewport['w'] : '',
|
542 |
+
'h' => ! empty( $viewport['h'] ) ? $viewport['h'] : '',
|
543 |
+
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
544 |
}
|
545 |
|
546 |
+
public function ao_ccss_check_contents( $ccss ) {
|
547 |
// Perform basic exploit avoidance and CSS validation.
|
548 |
if ( ! empty( $ccss ) ) {
|
549 |
// Try to avoid code injection.
|
550 |
$blocklist = array( '#!/', 'function(', '<script', '<?php' );
|
551 |
foreach ( $blocklist as $blocklisted ) {
|
552 |
if ( strpos( $ccss, $blocklisted ) !== false ) {
|
553 |
+
$this->ao_ccss_log( 'Critical CSS received contained blocklisted content.', 2 );
|
554 |
return false;
|
555 |
}
|
556 |
}
|
559 |
$needlist = array( '{', '}', ':' );
|
560 |
foreach ( $needlist as $needed ) {
|
561 |
if ( false === strpos( $ccss, $needed ) && 'none' !== $ccss ) {
|
562 |
+
$this->ao_ccss_log( 'Critical CSS received did not seem to contain real CSS.', 2 );
|
563 |
return false;
|
564 |
}
|
565 |
}
|
569 |
return true;
|
570 |
}
|
571 |
|
572 |
+
public function ao_ccss_log( $msg, $lvl ) {
|
573 |
// Commom logging facility
|
574 |
// Attach debug option.
|
575 |
+
$debug = $this->criticalcss->get_option( 'debug' );
|
576 |
|
577 |
// Prepare log levels, where accepted $lvl are:
|
578 |
// 1: II (for info)
|
589 |
break;
|
590 |
case 3:
|
591 |
// Output debug messages only if debug mode is enabled.
|
592 |
+
if ( $debug ) {
|
593 |
$level = 'DD';
|
594 |
}
|
595 |
break;
|
608 |
}
|
609 |
}
|
610 |
|
611 |
+
public function ao_ccss_clear_page_tpl_cache() {
|
612 |
// Clears transient cache for page templates.
|
613 |
delete_transient( 'autoptimize_ccss_page_templates' );
|
614 |
}
|
|
|
615 |
}
|
classes/autoptimizeCriticalCSSCron.php
CHANGED
@@ -9,14 +9,8 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
9 |
}
|
10 |
|
11 |
class autoptimizeCriticalCSSCron {
|
12 |
-
public function __construct()
|
13 |
-
|
14 |
-
// fetch all options at once and populate them individually explicitely as globals.
|
15 |
-
$all_options = autoptimizeCriticalCSSBase::fetch_options();
|
16 |
-
foreach ( $all_options as $_option => $_value ) {
|
17 |
-
global ${$_option};
|
18 |
-
${$_option} = $_value;
|
19 |
-
}
|
20 |
|
21 |
// Add queue control to a registered event.
|
22 |
add_action( 'ao_ccss_queue', array( $this, 'ao_ccss_queue_control' ) );
|
@@ -26,10 +20,11 @@ class autoptimizeCriticalCSSCron {
|
|
26 |
|
27 |
public function ao_ccss_queue_control() {
|
28 |
// The queue execution backend.
|
29 |
-
|
30 |
-
|
|
|
31 |
// no key set, not processing the queue!
|
32 |
-
|
33 |
return;
|
34 |
}
|
35 |
|
@@ -56,7 +51,7 @@ class autoptimizeCriticalCSSCron {
|
|
56 |
if ( $qdobj ) {
|
57 |
if ( 1 === $qdobj['enable'] ) {
|
58 |
$queue_debug = true;
|
59 |
-
|
60 |
}
|
61 |
}
|
62 |
}
|
@@ -76,30 +71,30 @@ class autoptimizeCriticalCSSCron {
|
|
76 |
if ( ! $queue_lock ) {
|
77 |
|
78 |
// Log queue start and create the lock file.
|
79 |
-
|
80 |
if ( touch( AO_CCSS_LOCK ) ) {
|
81 |
-
|
82 |
}
|
83 |
|
84 |
// Attach required variables.
|
85 |
-
|
86 |
-
|
87 |
|
88 |
// Initialize counters.
|
89 |
-
if ( $
|
90 |
// no time limit set, let's go with 1000 seconds.
|
91 |
-
$
|
92 |
}
|
93 |
-
$mt = time() + $
|
94 |
$jc = 1; // job count number.
|
95 |
$jr = 1; // jobs requests number.
|
96 |
-
$jt = count( $
|
97 |
|
98 |
// Sort queue by ascending job status (e.g. ERROR, JOB_ONGOING, JOB_QUEUED, NEW...).
|
99 |
-
array_multisort( array_column( $
|
100 |
|
101 |
// Iterates over the entire queue.
|
102 |
-
foreach ( $
|
103 |
// Prepare flags and target rule.
|
104 |
$update = false;
|
105 |
$deljob = false;
|
@@ -108,13 +103,13 @@ class autoptimizeCriticalCSSCron {
|
|
108 |
$trule = explode( '|', $jprops['rtarget'] );
|
109 |
|
110 |
// Log job count.
|
111 |
-
|
112 |
|
113 |
// Process NEW jobs.
|
114 |
if ( 'NEW' == $jprops['jqstat'] ) {
|
115 |
|
116 |
// Log the new job.
|
117 |
-
|
118 |
|
119 |
// Compare job and rule hashes (if any).
|
120 |
$hash = $this->ao_ccss_diff_hashes( $jprops['ljid'], $jprops['hash'], $jprops['hashes'], $jprops['rtarget'] );
|
@@ -124,7 +119,7 @@ class autoptimizeCriticalCSSCron {
|
|
124 |
if ( $jr > 2 ) {
|
125 |
// we already posted 2 jobs to criticalcss.com, don't post more this run
|
126 |
// but we can keep on processing the queue to keep it tidy.
|
127 |
-
|
128 |
continue;
|
129 |
}
|
130 |
|
@@ -136,12 +131,28 @@ class autoptimizeCriticalCSSCron {
|
|
136 |
$jr++;
|
137 |
|
138 |
// NOTE: All the following conditions maps to the ones in admin_settings_queue.js.php.
|
139 |
-
if (
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
140 |
// SUCCESS: request has a valid result.
|
141 |
// Update job properties.
|
142 |
$jprops['jid'] = $apireq['job']['id'];
|
143 |
$jprops['jqstat'] = $apireq['job']['status'];
|
144 |
-
|
145 |
} elseif ( 'STATUS_JOB_BAD' == $apireq['job']['status'] ) {
|
146 |
// ERROR: concurrent requests
|
147 |
// Update job properties.
|
@@ -154,23 +165,7 @@ class autoptimizeCriticalCSSCron {
|
|
154 |
}
|
155 |
$jprops['jvstat'] = 'NONE';
|
156 |
$jprops['jftime'] = microtime( true );
|
157 |
-
|
158 |
-
} elseif ( 'INVALID_JWT_TOKEN' == $apireq['errorCode'] ) {
|
159 |
-
// ERROR: key validation
|
160 |
-
// Update job properties.
|
161 |
-
$jprops['jqstat'] = $apireq['errorCode'];
|
162 |
-
$jprops['jrstat'] = $apireq['error'];
|
163 |
-
$jprops['jvstat'] = 'NONE';
|
164 |
-
$jprops['jftime'] = microtime( true );
|
165 |
-
autoptimizeCriticalCSSCore::ao_ccss_log( 'API key validation error when processing job id <' . $jprops['ljid'] . '>, job status is now <' . $jprops['jqstat'] . '>', 3 );
|
166 |
-
} elseif ( empty( $apireq ) ) {
|
167 |
-
// ERROR: no response
|
168 |
-
// Update job properties.
|
169 |
-
$jprops['jqstat'] = 'NO_RESPONSE';
|
170 |
-
$jprops['jrstat'] = 'NONE';
|
171 |
-
$jprops['jvstat'] = 'NONE';
|
172 |
-
$jprops['jftime'] = microtime( true );
|
173 |
-
autoptimizeCriticalCSSCore::ao_ccss_log( 'Job id <' . $jprops['ljid'] . '> request has no response, status now is <' . $jprops['jqstat'] . '>', 3 );
|
174 |
} else {
|
175 |
// UNKNOWN: unhandled generate exception
|
176 |
// Update job properties.
|
@@ -178,15 +173,15 @@ class autoptimizeCriticalCSSCron {
|
|
178 |
$jprops['jrstat'] = 'NONE';
|
179 |
$jprops['jvstat'] = 'NONE';
|
180 |
$jprops['jftime'] = microtime( true );
|
181 |
-
|
182 |
-
|
183 |
}
|
184 |
} else {
|
185 |
// SUCCESS: Job hash is equal to a previous one, so it's done
|
186 |
// Update job status and finish time.
|
187 |
$jprops['jqstat'] = 'JOB_DONE';
|
188 |
$jprops['jftime'] = microtime( true );
|
189 |
-
|
190 |
}
|
191 |
|
192 |
// Set queue update flag.
|
@@ -195,7 +190,7 @@ class autoptimizeCriticalCSSCron {
|
|
195 |
} elseif ( 'JOB_QUEUED' == $jprops['jqstat'] || 'JOB_ONGOING' == $jprops['jqstat'] ) {
|
196 |
// Process QUEUED and ONGOING jobs
|
197 |
// Log the pending job.
|
198 |
-
|
199 |
|
200 |
// Dispatch the job result request and increment request count.
|
201 |
$apireq = $this->ao_ccss_api_results( $jprops['jid'], $queue_debug, $qdobj['htcode'] );
|
@@ -219,7 +214,7 @@ class autoptimizeCriticalCSSCron {
|
|
219 |
// Process a PENDING job
|
220 |
// Update job properties.
|
221 |
$jprops['jqstat'] = $apireq['status'];
|
222 |
-
|
223 |
} elseif ( 'JOB_DONE' == $apireq['status'] ) {
|
224 |
// Process a DONE job
|
225 |
// New resultStatus from ccss.com "HTML_404", consider as "GOOD" for now.
|
@@ -236,7 +231,7 @@ class autoptimizeCriticalCSSCron {
|
|
236 |
$jprops['jvstat'] = $apireq['validationStatus'];
|
237 |
$jprops['jftime'] = microtime( true );
|
238 |
$rule_update = true;
|
239 |
-
|
240 |
} elseif ( 'GOOD' == $apireq['resultStatus'] && ( 'BAD' == $apireq['validationStatus'] || 'SCREENSHOT_WARN_BLANK' == $apireq['validationStatus'] ) ) {
|
241 |
// SUCCESS: GOOD job with BAD or SCREENSHOT_WARN_BLANK validation
|
242 |
// Update job properties.
|
@@ -247,9 +242,9 @@ class autoptimizeCriticalCSSCron {
|
|
247 |
if ( apply_filters( 'autoptimize_filter_ccss_save_review_rules', true ) ) {
|
248 |
$jprops['file'] = $this->ao_ccss_save_file( $apireq['css'], $trule, true );
|
249 |
$rule_update = true;
|
250 |
-
|
251 |
} else {
|
252 |
-
|
253 |
}
|
254 |
} elseif ( 'GOOD' != $apireq['resultStatus'] && ( 'GOOD' != $apireq['validationStatus'] || 'WARN' != $apireq['validationStatus'] || 'BAD' != $apireq['validationStatus'] || 'SCREENSHOT_WARN_BLANK' != $apireq['validationStatus'] ) ) {
|
255 |
// ERROR: no GOOD, WARN or BAD results
|
@@ -258,9 +253,9 @@ class autoptimizeCriticalCSSCron {
|
|
258 |
$jprops['jrstat'] = $apireq['resultStatus'];
|
259 |
$jprops['jvstat'] = $apireq['validationStatus'];
|
260 |
$jprops['jftime'] = microtime( true );
|
261 |
-
|
262 |
$apireq['css'] = '/* critical css removed for DEBUG logging purposes */';
|
263 |
-
|
264 |
} else {
|
265 |
// UNKNOWN: unhandled JOB_DONE exception
|
266 |
// Update job properties.
|
@@ -268,9 +263,9 @@ class autoptimizeCriticalCSSCron {
|
|
268 |
$jprops['jrstat'] = $apireq['resultStatus'];
|
269 |
$jprops['jvstat'] = $apireq['validationStatus'];
|
270 |
$jprops['jftime'] = microtime( true );
|
271 |
-
|
272 |
$apireq['css'] = '/* critical css removed for DEBUG logging purposes */';
|
273 |
-
|
274 |
}
|
275 |
} elseif ( 'JOB_FAILED' == $apireq['job']['status'] || 'STATUS_JOB_BAD' == $apireq['job']['status'] ) {
|
276 |
// ERROR: failed job
|
@@ -283,7 +278,7 @@ class autoptimizeCriticalCSSCron {
|
|
283 |
}
|
284 |
$jprops['jvstat'] = 'NONE';
|
285 |
$jprops['jftime'] = microtime( true );
|
286 |
-
|
287 |
} elseif ( 'This css no longer exists. Please re-generate it.' == $apireq['error'] ) {
|
288 |
// ERROR: CSS doesn't exist
|
289 |
// Update job properties.
|
@@ -291,7 +286,7 @@ class autoptimizeCriticalCSSCron {
|
|
291 |
$jprops['jrstat'] = $apireq['error'];
|
292 |
$jprops['jvstat'] = 'NONE';
|
293 |
$jprops['jftime'] = microtime( true );
|
294 |
-
|
295 |
} elseif ( empty( $apireq ) ) {
|
296 |
// ERROR: no response
|
297 |
// Update job properties.
|
@@ -299,7 +294,7 @@ class autoptimizeCriticalCSSCron {
|
|
299 |
$jprops['jrstat'] = 'NONE';
|
300 |
$jprops['jvstat'] = 'NONE';
|
301 |
$jprops['jftime'] = microtime( true );
|
302 |
-
|
303 |
} else {
|
304 |
// UNKNOWN: unhandled results exception
|
305 |
// Update job properties.
|
@@ -307,7 +302,7 @@ class autoptimizeCriticalCSSCron {
|
|
307 |
$jprops['jrstat'] = 'NONE';
|
308 |
$jprops['jvstat'] = 'NONE';
|
309 |
$jprops['jftime'] = microtime( true );
|
310 |
-
|
311 |
}
|
312 |
|
313 |
// Set queue update flag.
|
@@ -324,31 +319,31 @@ class autoptimizeCriticalCSSCron {
|
|
324 |
if ( $update ) {
|
325 |
if ( ! $deljob ) {
|
326 |
// Update properties of a NEW or PENDING job...
|
327 |
-
$
|
328 |
} else {
|
329 |
// ...or remove the DONE job.
|
330 |
-
unset( $
|
331 |
-
|
332 |
}
|
333 |
|
334 |
// Update queue object.
|
335 |
-
$
|
336 |
-
update_option( 'autoptimize_ccss_queue', $
|
337 |
-
|
338 |
|
339 |
// Update target rule.
|
340 |
if ( $rule_update ) {
|
341 |
$this->ao_ccss_rule_update( $jprops['ljid'], $jprops['rtarget'], $jprops['file'], $jprops['hash'] );
|
342 |
-
|
343 |
}
|
344 |
} else {
|
345 |
// Or log no queue action.
|
346 |
-
|
347 |
}
|
348 |
|
349 |
// Break the loop if request time limit is (almost exceeded).
|
350 |
if ( time() > $mt ) {
|
351 |
-
|
352 |
break;
|
353 |
}
|
354 |
|
@@ -359,13 +354,13 @@ class autoptimizeCriticalCSSCron {
|
|
359 |
// Remove the lock file and log the queue end.
|
360 |
if ( file_exists( AO_CCSS_LOCK ) ) {
|
361 |
unlink( AO_CCSS_LOCK );
|
362 |
-
|
363 |
}
|
364 |
-
|
365 |
|
366 |
// Log that queue is locked.
|
367 |
} else {
|
368 |
-
|
369 |
}
|
370 |
}
|
371 |
|
@@ -376,7 +371,7 @@ class autoptimizeCriticalCSSCron {
|
|
376 |
// Job with a single hash
|
377 |
// Set job hash.
|
378 |
$hash = $hashes[0];
|
379 |
-
|
380 |
} else {
|
381 |
// Job with multiple hashes
|
382 |
// Loop through hashes to concatenate them.
|
@@ -387,52 +382,56 @@ class autoptimizeCriticalCSSCron {
|
|
387 |
|
388 |
// Set job hash.
|
389 |
$hash = md5( $nhash );
|
390 |
-
|
391 |
}
|
392 |
|
393 |
// STEP 2: compare job to existing jobs to prevent double submission for same type+hash.
|
394 |
-
|
395 |
|
396 |
-
foreach ( $
|
397 |
-
|
398 |
if ( $queue_item['hash'] == $hash && $queue_item['rtarget'] == $rule && in_array( $queue_item['jqstat'], array( 'JOB_QUEUED', 'JOB_ONGOING', 'JOB_DONE' ) ) ) {
|
399 |
-
|
400 |
return false;
|
401 |
}
|
402 |
}
|
403 |
|
404 |
// STEP 3: compare job and existing rule (if any) hashes
|
405 |
// Attach required arrays.
|
406 |
-
|
407 |
|
408 |
// Prepare rule variables.
|
409 |
$trule = explode( '|', $rule );
|
410 |
-
$
|
411 |
-
|
|
|
|
|
|
|
|
|
412 |
// If hash is empty, set it to now for a "forced job".
|
413 |
-
if ( empty( $hash
|
414 |
$hash = 'new';
|
415 |
-
|
416 |
}
|
417 |
|
418 |
// Check if a MANUAL rule exist and return false.
|
419 |
if ( ! empty( $srule ) && ( 0 == $srule['hash'] && 0 != $srule['file'] ) ) {
|
420 |
-
|
421 |
return false;
|
422 |
} elseif ( ! empty( $srule ) ) {
|
423 |
// Check if an AUTO rule exist.
|
424 |
if ( $hash === $srule['hash'] && is_file( AO_CCSS_DIR . $srule['file'] ) && 0 != filesize( AO_CCSS_DIR . $srule['file'] ) ) {
|
425 |
// Check if job hash matches rule, if the CCSS file exists said file is not empty and return FALSE is so.
|
426 |
-
|
427 |
return false;
|
428 |
} else {
|
429 |
// Or return the new hash if they differ.
|
430 |
-
|
431 |
return $hash;
|
432 |
}
|
433 |
} else {
|
434 |
// Return the hash for a job that has no rule yet.
|
435 |
-
|
436 |
return $hash;
|
437 |
}
|
438 |
}
|
@@ -440,14 +439,11 @@ class autoptimizeCriticalCSSCron {
|
|
440 |
public function ao_ccss_api_generate( $path, $debug, $dcode ) {
|
441 |
// POST jobs to criticalcss.com and return responses
|
442 |
// Get key and key status.
|
443 |
-
|
444 |
-
|
445 |
-
$
|
446 |
-
$key_status = $ao_ccss_keyst;
|
447 |
|
448 |
// Prepare full URL to request.
|
449 |
-
global $ao_ccss_noptimize;
|
450 |
-
|
451 |
$site_host = get_site_url();
|
452 |
$site_path = parse_url( $site_host, PHP_URL_PATH );
|
453 |
|
@@ -458,20 +454,20 @@ class autoptimizeCriticalCSSCron {
|
|
458 |
// Logic to bind to one domain to avoid site clones of sites would
|
459 |
// automatically begin spawning requests to criticalcss.com which has
|
460 |
// a per domain cost.
|
461 |
-
|
462 |
-
if ( empty( $
|
463 |
// first request being done, update option to allow future requests are only allowed if from same domain.
|
464 |
update_option( 'autoptimize_ccss_domain', str_rot13( $site_host ) );
|
465 |
-
} elseif ( trim( $
|
466 |
// not the same domain, log as error and return without posting to criticalcss.com.
|
467 |
-
|
468 |
return false;
|
469 |
}
|
470 |
|
471 |
$src_url = $site_host . $path;
|
472 |
|
473 |
// Avoid AO optimizations if required by config or avoid lazyload if lazyload is active in AO.
|
474 |
-
if ( ! empty( $
|
475 |
$src_url .= '?ao_noptirocket=1';
|
476 |
} elseif ( ( class_exists( 'autoptimizeImages', false ) && autoptimizeImages::should_lazyload_wrapper() ) || apply_filters( 'autoptimize_filter_ccss_enforce_nolazy', false ) ) {
|
477 |
$src_url .= '?ao_nolazy=1';
|
@@ -486,15 +482,15 @@ class autoptimizeCriticalCSSCron {
|
|
486 |
$body['aocssv'] = AO_CCSS_VER;
|
487 |
|
488 |
// Prepare and add viewport size to the body if available.
|
489 |
-
$viewport =
|
490 |
if ( ! empty( $viewport['w'] ) && ! empty( $viewport['h'] ) ) {
|
491 |
$body['width'] = $viewport['w'];
|
492 |
$body['height'] = $viewport['h'];
|
493 |
}
|
494 |
|
495 |
// Prepare and add forceInclude to the body if available.
|
496 |
-
|
497 |
-
$finclude = $this->ao_ccss_finclude( $
|
498 |
if ( ! empty( $finclude ) ) {
|
499 |
$body['forceInclude'] = $finclude;
|
500 |
}
|
@@ -504,17 +500,17 @@ class autoptimizeCriticalCSSCron {
|
|
504 |
|
505 |
// Body must be json and log it.
|
506 |
$body = json_encode( $body );
|
507 |
-
|
508 |
|
509 |
// Prepare the request.
|
510 |
$url = esc_url_raw( AO_CCSS_API . 'generate?aover=' . AO_CCSS_VER );
|
511 |
$args = array(
|
512 |
-
'headers' => array(
|
513 |
'User-Agent' => 'Autoptimize v' . AO_CCSS_VER,
|
514 |
'Content-type' => 'application/json; charset=utf-8',
|
515 |
'Authorization' => 'JWT ' . $key,
|
516 |
'Connection' => 'close',
|
517 |
-
),
|
518 |
'body' => $body,
|
519 |
);
|
520 |
|
@@ -533,42 +529,42 @@ class autoptimizeCriticalCSSCron {
|
|
533 |
// Workaround criticalcss.com non-RESTful reponses.
|
534 |
if ( 'JOB_QUEUED' == $body['job']['status'] || 'JOB_ONGOING' == $body['job']['status'] || 'STATUS_JOB_BAD' == $body['job']['status'] ) {
|
535 |
// Log successful and return encoded request body.
|
536 |
-
|
537 |
|
538 |
// This code also means the key is valid, so cache key status for 24h if not already cached.
|
539 |
if ( ( ! $key_status || 2 != $key_status ) && $key ) {
|
540 |
update_option( 'autoptimize_ccss_keyst', 2 );
|
541 |
-
|
542 |
}
|
543 |
|
544 |
// Return the request body.
|
545 |
return $body;
|
546 |
} else {
|
547 |
// Log successful requests with invalid reponses.
|
548 |
-
|
549 |
-
|
550 |
return $body;
|
551 |
}
|
552 |
} else {
|
553 |
// Response code is anything else.
|
554 |
// Log failed request with a valid response code and return body.
|
555 |
if ( $code ) {
|
556 |
-
|
557 |
-
|
558 |
|
559 |
if ( 401 == $code ) {
|
560 |
// If request is unauthorized, also clear key status.
|
561 |
update_option( 'autoptimize_ccss_keyst', 1 );
|
562 |
-
|
563 |
}
|
564 |
|
565 |
// Return the request body.
|
566 |
return $body;
|
567 |
} else {
|
568 |
// Log failed request with no response and return false.
|
569 |
-
|
570 |
if ( is_wp_error( $req ) ) {
|
571 |
-
|
572 |
}
|
573 |
|
574 |
return false;
|
@@ -579,17 +575,16 @@ class autoptimizeCriticalCSSCron {
|
|
579 |
public function ao_ccss_api_results( $jobid, $debug, $dcode ) {
|
580 |
// GET jobs from criticalcss.com and return responses
|
581 |
// Get key.
|
582 |
-
|
583 |
-
$key = $ao_ccss_key;
|
584 |
|
585 |
// Prepare the request.
|
586 |
$url = AO_CCSS_API . 'results?resultId=' . $jobid;
|
587 |
$args = array(
|
588 |
-
'headers' => array(
|
589 |
'User-Agent' => 'Autoptimize CriticalCSS Power-Up v' . AO_CCSS_VER,
|
590 |
'Authorization' => 'JWT ' . $key,
|
591 |
'Connection' => 'close',
|
592 |
-
),
|
593 |
);
|
594 |
|
595 |
// Dispatch the request and store its response code.
|
@@ -607,36 +602,36 @@ class autoptimizeCriticalCSSCron {
|
|
607 |
if ( is_array( $body ) && ( array_key_exists( 'status', $body ) || array_key_exists( 'job', $body ) ) && ( 'JOB_QUEUED' == $body['status'] || 'JOB_ONGOING' == $body['status'] || 'JOB_DONE' == $body['status'] || 'JOB_FAILED' == $body['status'] || 'JOB_UNKNOWN' == $body['status'] || 'STATUS_JOB_BAD' == $body['job']['status'] ) ) {
|
608 |
// Workaround criticalcss.com non-RESTful reponses
|
609 |
// Log successful and return encoded request body.
|
610 |
-
|
611 |
return $body;
|
612 |
} elseif ( is_array( $body ) && ( array_key_exists( 'error', $body ) && 'This css no longer exists. Please re-generate it.' == $body['error'] ) ) {
|
613 |
// Handle no CSS reply
|
614 |
// Log no CSS error and return encoded request body.
|
615 |
-
|
616 |
return $body;
|
617 |
} else {
|
618 |
// Log failed request and return false.
|
619 |
-
|
620 |
-
|
621 |
return false;
|
622 |
}
|
623 |
} else {
|
624 |
// Response code is anything else
|
625 |
// Log failed request with a valid response code and return body.
|
626 |
if ( $code ) {
|
627 |
-
|
628 |
-
|
629 |
if ( 401 == $code ) {
|
630 |
// If request is unauthorized, also clear key status.
|
631 |
update_option( 'autoptimize_ccss_keyst', 1 );
|
632 |
-
|
633 |
}
|
634 |
|
635 |
// Return the request body.
|
636 |
return $body;
|
637 |
} else {
|
638 |
// Log failed request with no response and return false.
|
639 |
-
|
640 |
return false;
|
641 |
}
|
642 |
}
|
@@ -655,39 +650,40 @@ class autoptimizeCriticalCSSCron {
|
|
655 |
$filename = false;
|
656 |
$content = $ccss;
|
657 |
|
658 |
-
if (
|
659 |
// Sanitize content, set filename and try to save file.
|
660 |
$file = AO_CCSS_DIR . 'ccss_' . md5( $ccss . $target[1] ) . $rmark . '.css';
|
661 |
$status = file_put_contents( $file, $content, LOCK_EX );
|
662 |
$filename = pathinfo( $file, PATHINFO_BASENAME );
|
663 |
-
|
664 |
|
665 |
if ( ! $status ) {
|
666 |
// If file has not been saved, reset filename.
|
667 |
-
|
668 |
$filename = false;
|
669 |
return $filename;
|
670 |
}
|
671 |
} else {
|
672 |
-
|
673 |
return $filename;
|
674 |
}
|
675 |
|
676 |
// Remove old critical CSS if a previous one existed in the rule and if that file exists in filesystem
|
677 |
-
// NOTE: out of scope critical CSS file removal (issue #5)
|
678 |
// Attach required arrays.
|
679 |
-
|
680 |
-
|
681 |
-
//
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
$
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
|
|
|
|
691 |
}
|
692 |
}
|
693 |
}
|
@@ -699,26 +695,30 @@ class autoptimizeCriticalCSSCron {
|
|
699 |
public function ao_ccss_rule_update( $ljid, $srule, $file, $hash ) {
|
700 |
// Update or create a rule
|
701 |
// Attach required arrays.
|
702 |
-
|
703 |
|
704 |
// Prepare rule variables.
|
705 |
$trule = explode( '|', $srule );
|
706 |
-
|
|
|
|
|
|
|
|
|
707 |
$action = false;
|
708 |
$rtype = '';
|
709 |
|
710 |
-
if ( 0 === $rule['hash'] && 0 !== $rule['file'] ) {
|
711 |
// manual rule, don't ever overwrite.
|
712 |
$action = 'NOT UPDATED';
|
713 |
$rtype = 'MANUAL';
|
714 |
-
} elseif ( 0 === $rule['hash'] && 0 === $rule['file'] ) {
|
715 |
// If this is an user created AUTO rule with no hash and file yet, update its hash and filename
|
716 |
// Set rule hash, file and action flag.
|
717 |
$rule['hash'] = $hash;
|
718 |
$rule['file'] = $file;
|
719 |
$action = 'UPDATED';
|
720 |
$rtype = 'AUTO';
|
721 |
-
} elseif ( 0 !== $rule['hash'] && ctype_alnum( $rule['hash'] ) ) {
|
722 |
// If this is an genuine AUTO rule, update its hash and filename
|
723 |
// Set rule hash, file and action flag.
|
724 |
$rule['hash'] = $hash;
|
@@ -736,18 +736,19 @@ class autoptimizeCriticalCSSCron {
|
|
736 |
$rtype = 'AUTO';
|
737 |
} else {
|
738 |
// Log that no rule was created.
|
739 |
-
|
740 |
}
|
741 |
}
|
742 |
|
743 |
if ( $action ) {
|
744 |
// If a rule creation/update is required, persist updated rules object.
|
745 |
-
$
|
746 |
-
$
|
747 |
-
update_option( 'autoptimize_ccss_rules', $
|
748 |
-
|
|
|
749 |
} else {
|
750 |
-
|
751 |
}
|
752 |
}
|
753 |
|
@@ -811,10 +812,11 @@ class autoptimizeCriticalCSSCron {
|
|
811 |
}
|
812 |
|
813 |
// Queue cleaning.
|
814 |
-
|
|
|
815 |
$queue_purge_threshold = 100;
|
816 |
$queue_purge_age = 24 * 60 * 60;
|
817 |
-
$queue_length = count( $
|
818 |
$timestamp_yesterday = microtime( true ) - $queue_purge_age;
|
819 |
$remove_old_new = false;
|
820 |
$queue_altered = false;
|
@@ -823,23 +825,23 @@ class autoptimizeCriticalCSSCron {
|
|
823 |
$remove_old_new = true;
|
824 |
}
|
825 |
|
826 |
-
foreach ( $
|
827 |
if ( ( $remove_old_new && 'NEW' == $job['jqstat'] && $job['jctime'] < $timestamp_yesterday ) || in_array( $job['jqstat'], array( 'JOB_FAILED', 'STATUS_JOB_BAD', 'NO_CSS', 'NO_RESPONSE' ) ) ) {
|
828 |
-
unset( $
|
829 |
$queue_altered = true;
|
830 |
}
|
831 |
}
|
832 |
|
833 |
// save queue to options!
|
834 |
if ( $queue_altered ) {
|
835 |
-
$
|
836 |
-
update_option( 'autoptimize_ccss_queue', $
|
837 |
-
|
838 |
}
|
839 |
|
840 |
// re-check key if invalid.
|
841 |
-
|
842 |
-
if ( 1 == $
|
843 |
$this->ao_ccss_api_generate( '', '', '' );
|
844 |
}
|
845 |
}
|
9 |
}
|
10 |
|
11 |
class autoptimizeCriticalCSSCron {
|
12 |
+
public function __construct() {
|
13 |
+
$this->criticalcss = autoptimize()->criticalcss();
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
|
15 |
// Add queue control to a registered event.
|
16 |
add_action( 'ao_ccss_queue', array( $this, 'ao_ccss_queue_control' ) );
|
20 |
|
21 |
public function ao_ccss_queue_control() {
|
22 |
// The queue execution backend.
|
23 |
+
$key = $this->criticalcss->get_option( 'key' );
|
24 |
+
|
25 |
+
if ( empty( $key ) ) {
|
26 |
// no key set, not processing the queue!
|
27 |
+
$this->criticalcss->log( 'No key set, so not processing queue.', 3 );
|
28 |
return;
|
29 |
}
|
30 |
|
51 |
if ( $qdobj ) {
|
52 |
if ( 1 === $qdobj['enable'] ) {
|
53 |
$queue_debug = true;
|
54 |
+
$this->criticalcss->log( 'Queue operating in debug mode with the following settings: <' . $qdobj_raw . '>', 3 );
|
55 |
}
|
56 |
}
|
57 |
}
|
71 |
if ( ! $queue_lock ) {
|
72 |
|
73 |
// Log queue start and create the lock file.
|
74 |
+
$this->criticalcss->log( 'Queue control started', 3 );
|
75 |
if ( touch( AO_CCSS_LOCK ) ) {
|
76 |
+
$this->criticalcss->log( 'Queue control locked', 3 );
|
77 |
}
|
78 |
|
79 |
// Attach required variables.
|
80 |
+
$queue = $this->criticalcss->get_option( 'queue' );
|
81 |
+
$rtimelimit = $this->criticalcss->get_option( 'rtimelimit' );
|
82 |
|
83 |
// Initialize counters.
|
84 |
+
if ( $rtimelimit == 0 ) {
|
85 |
// no time limit set, let's go with 1000 seconds.
|
86 |
+
$rtimelimit = 1000;
|
87 |
}
|
88 |
+
$mt = time() + $rtimelimit; // maxtime queue processing can run.
|
89 |
$jc = 1; // job count number.
|
90 |
$jr = 1; // jobs requests number.
|
91 |
+
$jt = count( $queue ); // number of jobs in queue.
|
92 |
|
93 |
// Sort queue by ascending job status (e.g. ERROR, JOB_ONGOING, JOB_QUEUED, NEW...).
|
94 |
+
array_multisort( array_column( $queue, 'jqstat' ), $queue ); // @codingStandardsIgnoreLine
|
95 |
|
96 |
// Iterates over the entire queue.
|
97 |
+
foreach ( $queue as $path => $jprops ) {
|
98 |
// Prepare flags and target rule.
|
99 |
$update = false;
|
100 |
$deljob = false;
|
103 |
$trule = explode( '|', $jprops['rtarget'] );
|
104 |
|
105 |
// Log job count.
|
106 |
+
$this->criticalcss->log( 'Processing job ' . $jc . ' of ' . $jt . ' with id <' . $jprops['ljid'] . '> and status <' . $jprops['jqstat'] . '>', 3 );
|
107 |
|
108 |
// Process NEW jobs.
|
109 |
if ( 'NEW' == $jprops['jqstat'] ) {
|
110 |
|
111 |
// Log the new job.
|
112 |
+
$this->criticalcss->log( 'Found NEW job with local ID <' . $jprops['ljid'] . '>, starting its queue processing', 3 );
|
113 |
|
114 |
// Compare job and rule hashes (if any).
|
115 |
$hash = $this->ao_ccss_diff_hashes( $jprops['ljid'], $jprops['hash'], $jprops['hashes'], $jprops['rtarget'] );
|
119 |
if ( $jr > 2 ) {
|
120 |
// we already posted 2 jobs to criticalcss.com, don't post more this run
|
121 |
// but we can keep on processing the queue to keep it tidy.
|
122 |
+
$this->criticalcss->log( 'Holding off on generating request for job with local ID <' . $jprops['ljid'] . '>, maximum number of POSTS reached.', 3 );
|
123 |
continue;
|
124 |
}
|
125 |
|
131 |
$jr++;
|
132 |
|
133 |
// NOTE: All the following conditions maps to the ones in admin_settings_queue.js.php.
|
134 |
+
if ( empty( $apireq ) ) {
|
135 |
+
// ERROR: no response
|
136 |
+
// Update job properties.
|
137 |
+
$jprops['jqstat'] = 'NO_RESPONSE';
|
138 |
+
$jprops['jrstat'] = 'NONE';
|
139 |
+
$jprops['jvstat'] = 'NONE';
|
140 |
+
$jprops['jftime'] = microtime( true );
|
141 |
+
$this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> request has no response, status now is <' . $jprops['jqstat'] . '>', 3 );
|
142 |
+
} elseif ( array_key_exists( 'errorCode', $apireq ) && 'INVALID_JWT_TOKEN' == $apireq['errorCode'] ) {
|
143 |
+
// ERROR: key validation
|
144 |
+
// Update job properties.
|
145 |
+
$jprops['jqstat'] = $apireq['errorCode'];
|
146 |
+
$jprops['jrstat'] = $apireq['error'];
|
147 |
+
$jprops['jvstat'] = 'NONE';
|
148 |
+
$jprops['jftime'] = microtime( true );
|
149 |
+
$this->criticalcss->log( 'API key validation error when processing job id <' . $jprops['ljid'] . '>, job status is now <' . $jprops['jqstat'] . '>', 3 );
|
150 |
+
} elseif ( array_key_exists( 'job', $apireq ) && 'JOB_QUEUED' == $apireq['job']['status'] || 'JOB_ONGOING' == $apireq['job']['status'] ) {
|
151 |
// SUCCESS: request has a valid result.
|
152 |
// Update job properties.
|
153 |
$jprops['jid'] = $apireq['job']['id'];
|
154 |
$jprops['jqstat'] = $apireq['job']['status'];
|
155 |
+
$this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> generate request successful, remote id <' . $jprops['jid'] . '>, status now is <' . $jprops['jqstat'] . '>', 3 );
|
156 |
} elseif ( 'STATUS_JOB_BAD' == $apireq['job']['status'] ) {
|
157 |
// ERROR: concurrent requests
|
158 |
// Update job properties.
|
165 |
}
|
166 |
$jprops['jvstat'] = 'NONE';
|
167 |
$jprops['jftime'] = microtime( true );
|
168 |
+
$this->criticalcss->log( 'Concurrent requests when processing job id <' . $jprops['ljid'] . '>, job status is now <' . $jprops['jqstat'] . '>', 3 );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
169 |
} else {
|
170 |
// UNKNOWN: unhandled generate exception
|
171 |
// Update job properties.
|
173 |
$jprops['jrstat'] = 'NONE';
|
174 |
$jprops['jvstat'] = 'NONE';
|
175 |
$jprops['jftime'] = microtime( true );
|
176 |
+
$this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> generate request has an UNKNOWN condition, status now is <' . $jprops['jqstat'] . '>, check log messages above for more information', 2 );
|
177 |
+
$this->criticalcss->log( 'Job response was: ' . json_encode( $apireq ), 3 );
|
178 |
}
|
179 |
} else {
|
180 |
// SUCCESS: Job hash is equal to a previous one, so it's done
|
181 |
// Update job status and finish time.
|
182 |
$jprops['jqstat'] = 'JOB_DONE';
|
183 |
$jprops['jftime'] = microtime( true );
|
184 |
+
$this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> requires no further processing, status now is <' . $jprops['jqstat'] . '>', 3 );
|
185 |
}
|
186 |
|
187 |
// Set queue update flag.
|
190 |
} elseif ( 'JOB_QUEUED' == $jprops['jqstat'] || 'JOB_ONGOING' == $jprops['jqstat'] ) {
|
191 |
// Process QUEUED and ONGOING jobs
|
192 |
// Log the pending job.
|
193 |
+
$this->criticalcss->log( 'Found PENDING job with local ID <' . $jprops['ljid'] . '>, continuing its queue processing', 3 );
|
194 |
|
195 |
// Dispatch the job result request and increment request count.
|
196 |
$apireq = $this->ao_ccss_api_results( $jprops['jid'], $queue_debug, $qdobj['htcode'] );
|
214 |
// Process a PENDING job
|
215 |
// Update job properties.
|
216 |
$jprops['jqstat'] = $apireq['status'];
|
217 |
+
$this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> result request successful, remote id <' . $jprops['jid'] . '>, status <' . $jprops['jqstat'] . '> unchanged', 3 );
|
218 |
} elseif ( 'JOB_DONE' == $apireq['status'] ) {
|
219 |
// Process a DONE job
|
220 |
// New resultStatus from ccss.com "HTML_404", consider as "GOOD" for now.
|
231 |
$jprops['jvstat'] = $apireq['validationStatus'];
|
232 |
$jprops['jftime'] = microtime( true );
|
233 |
$rule_update = true;
|
234 |
+
$this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> result request successful, remote id <' . $jprops['jid'] . '>, status <' . $jprops['jqstat'] . '>, file saved <' . $jprops['file'] . '>', 3 );
|
235 |
} elseif ( 'GOOD' == $apireq['resultStatus'] && ( 'BAD' == $apireq['validationStatus'] || 'SCREENSHOT_WARN_BLANK' == $apireq['validationStatus'] ) ) {
|
236 |
// SUCCESS: GOOD job with BAD or SCREENSHOT_WARN_BLANK validation
|
237 |
// Update job properties.
|
242 |
if ( apply_filters( 'autoptimize_filter_ccss_save_review_rules', true ) ) {
|
243 |
$jprops['file'] = $this->ao_ccss_save_file( $apireq['css'], $trule, true );
|
244 |
$rule_update = true;
|
245 |
+
$this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> result request successful, remote id <' . $jprops['jid'] . '>, status <' . $jprops['jqstat'] . ', file saved <' . $jprops['file'] . '> but requires REVIEW', 3 );
|
246 |
} else {
|
247 |
+
$this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> result request successful, remote id <' . $jprops['jid'] . '>, status <' . $jprops['jqstat'] . ', file not saved because it required REVIEW.', 3 );
|
248 |
}
|
249 |
} elseif ( 'GOOD' != $apireq['resultStatus'] && ( 'GOOD' != $apireq['validationStatus'] || 'WARN' != $apireq['validationStatus'] || 'BAD' != $apireq['validationStatus'] || 'SCREENSHOT_WARN_BLANK' != $apireq['validationStatus'] ) ) {
|
250 |
// ERROR: no GOOD, WARN or BAD results
|
253 |
$jprops['jrstat'] = $apireq['resultStatus'];
|
254 |
$jprops['jvstat'] = $apireq['validationStatus'];
|
255 |
$jprops['jftime'] = microtime( true );
|
256 |
+
$this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> result request successful but job FAILED, status now is <' . $jprops['jqstat'] . '>', 3 );
|
257 |
$apireq['css'] = '/* critical css removed for DEBUG logging purposes */';
|
258 |
+
$this->criticalcss->log( 'Job response was: ' . json_encode( $apireq ), 3 );
|
259 |
} else {
|
260 |
// UNKNOWN: unhandled JOB_DONE exception
|
261 |
// Update job properties.
|
263 |
$jprops['jrstat'] = $apireq['resultStatus'];
|
264 |
$jprops['jvstat'] = $apireq['validationStatus'];
|
265 |
$jprops['jftime'] = microtime( true );
|
266 |
+
$this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> result request successful but job is UNKNOWN, status now is <' . $jprops['jqstat'] . '>', 2 );
|
267 |
$apireq['css'] = '/* critical css removed for DEBUG logging purposes */';
|
268 |
+
$this->criticalcss->log( 'Job response was: ' . json_encode( $apireq ), 3 );
|
269 |
}
|
270 |
} elseif ( 'JOB_FAILED' == $apireq['job']['status'] || 'STATUS_JOB_BAD' == $apireq['job']['status'] ) {
|
271 |
// ERROR: failed job
|
278 |
}
|
279 |
$jprops['jvstat'] = 'NONE';
|
280 |
$jprops['jftime'] = microtime( true );
|
281 |
+
$this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> result request successful but job FAILED, status now is <' . $jprops['jqstat'] . '>', 3 );
|
282 |
} elseif ( 'This css no longer exists. Please re-generate it.' == $apireq['error'] ) {
|
283 |
// ERROR: CSS doesn't exist
|
284 |
// Update job properties.
|
286 |
$jprops['jrstat'] = $apireq['error'];
|
287 |
$jprops['jvstat'] = 'NONE';
|
288 |
$jprops['jftime'] = microtime( true );
|
289 |
+
$this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> result request successful but job FAILED, status now is <' . $jprops['jqstat'] . '>', 3 );
|
290 |
} elseif ( empty( $apireq ) ) {
|
291 |
// ERROR: no response
|
292 |
// Update job properties.
|
294 |
$jprops['jrstat'] = 'NONE';
|
295 |
$jprops['jvstat'] = 'NONE';
|
296 |
$jprops['jftime'] = microtime( true );
|
297 |
+
$this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> request has no response, status now is <' . $jprops['jqstat'] . '>', 3 );
|
298 |
} else {
|
299 |
// UNKNOWN: unhandled results exception
|
300 |
// Update job properties.
|
302 |
$jprops['jrstat'] = 'NONE';
|
303 |
$jprops['jvstat'] = 'NONE';
|
304 |
$jprops['jftime'] = microtime( true );
|
305 |
+
$this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> result request has an UNKNOWN condition, status now is <' . $jprops['jqstat'] . '>, check log messages above for more information', 2 );
|
306 |
}
|
307 |
|
308 |
// Set queue update flag.
|
319 |
if ( $update ) {
|
320 |
if ( ! $deljob ) {
|
321 |
// Update properties of a NEW or PENDING job...
|
322 |
+
$queue[ $path ] = $jprops;
|
323 |
} else {
|
324 |
// ...or remove the DONE job.
|
325 |
+
unset( $queue[ $path ] );
|
326 |
+
$this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> is DONE and was removed from the queue', 3 );
|
327 |
}
|
328 |
|
329 |
// Update queue object.
|
330 |
+
$queue_raw = json_encode( $queue );
|
331 |
+
update_option( 'autoptimize_ccss_queue', $queue_raw, false );
|
332 |
+
$this->criticalcss->log( 'Queue updated by job id <' . $jprops['ljid'] . '>', 3 );
|
333 |
|
334 |
// Update target rule.
|
335 |
if ( $rule_update ) {
|
336 |
$this->ao_ccss_rule_update( $jprops['ljid'], $jprops['rtarget'], $jprops['file'], $jprops['hash'] );
|
337 |
+
$this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> updated the target rule <' . $jprops['rtarget'] . '>', 3 );
|
338 |
}
|
339 |
} else {
|
340 |
// Or log no queue action.
|
341 |
+
$this->criticalcss->log( 'Nothing to do on this job', 3 );
|
342 |
}
|
343 |
|
344 |
// Break the loop if request time limit is (almost exceeded).
|
345 |
if ( time() > $mt ) {
|
346 |
+
$this->criticalcss->log( 'The time limit of ' . $rtimelimit . ' seconds was exceeded, queue control must finish now', 3 );
|
347 |
break;
|
348 |
}
|
349 |
|
354 |
// Remove the lock file and log the queue end.
|
355 |
if ( file_exists( AO_CCSS_LOCK ) ) {
|
356 |
unlink( AO_CCSS_LOCK );
|
357 |
+
$this->criticalcss->log( 'Queue control unlocked', 3 );
|
358 |
}
|
359 |
+
$this->criticalcss->log( 'Queue control finished', 3 );
|
360 |
|
361 |
// Log that queue is locked.
|
362 |
} else {
|
363 |
+
$this->criticalcss->log( 'Queue is already running, skipping the attempt to run it again', 3 );
|
364 |
}
|
365 |
}
|
366 |
|
371 |
// Job with a single hash
|
372 |
// Set job hash.
|
373 |
$hash = $hashes[0];
|
374 |
+
$this->criticalcss->log( 'Job id <' . $ljid . '> updated with SINGLE hash <' . $hash . '>', 3 );
|
375 |
} else {
|
376 |
// Job with multiple hashes
|
377 |
// Loop through hashes to concatenate them.
|
382 |
|
383 |
// Set job hash.
|
384 |
$hash = md5( $nhash );
|
385 |
+
$this->criticalcss->log( 'Job id <' . $ljid . '> updated with a COMPOSITE hash <' . $hash . '>', 3 );
|
386 |
}
|
387 |
|
388 |
// STEP 2: compare job to existing jobs to prevent double submission for same type+hash.
|
389 |
+
$queue = $this->criticalcss->get_option( 'queue' );
|
390 |
|
391 |
+
foreach ( $queue as $queue_item ) {
|
392 |
+
$this->criticalcss->log( 'Comparing <' . $rule . $hash . '> with <' . $queue_item['rtarget'] . $queue_item['hash'] . '>', 3 );
|
393 |
if ( $queue_item['hash'] == $hash && $queue_item['rtarget'] == $rule && in_array( $queue_item['jqstat'], array( 'JOB_QUEUED', 'JOB_ONGOING', 'JOB_DONE' ) ) ) {
|
394 |
+
$this->criticalcss->log( 'Job id <' . $ljid . '> matches the already pending job <' . $queue_item['ljid'] . '>', 3 );
|
395 |
return false;
|
396 |
}
|
397 |
}
|
398 |
|
399 |
// STEP 3: compare job and existing rule (if any) hashes
|
400 |
// Attach required arrays.
|
401 |
+
$rules = $this->criticalcss->get_option( 'rules' );
|
402 |
|
403 |
// Prepare rule variables.
|
404 |
$trule = explode( '|', $rule );
|
405 |
+
if ( is_array( $trule ) && ! empty( $trule ) && array_key_exists( $trule[1], $rules[ $trule[0] ] ) ) {
|
406 |
+
$srule = $rules[ $trule[0] ][ $trule[1] ];
|
407 |
+
} else {
|
408 |
+
$srule = '';
|
409 |
+
}
|
410 |
+
|
411 |
// If hash is empty, set it to now for a "forced job".
|
412 |
+
if ( empty( $hash ) ) {
|
413 |
$hash = 'new';
|
414 |
+
$this->criticalcss->log( 'Job id <' . $ljid . '> had no hash, assuming forced job so setting hash to new', 3 );
|
415 |
}
|
416 |
|
417 |
// Check if a MANUAL rule exist and return false.
|
418 |
if ( ! empty( $srule ) && ( 0 == $srule['hash'] && 0 != $srule['file'] ) ) {
|
419 |
+
$this->criticalcss->log( 'Job id <' . $ljid . '> matches the MANUAL rule <' . $trule[0] . '|' . $trule[1] . '>', 3 );
|
420 |
return false;
|
421 |
} elseif ( ! empty( $srule ) ) {
|
422 |
// Check if an AUTO rule exist.
|
423 |
if ( $hash === $srule['hash'] && is_file( AO_CCSS_DIR . $srule['file'] ) && 0 != filesize( AO_CCSS_DIR . $srule['file'] ) ) {
|
424 |
// Check if job hash matches rule, if the CCSS file exists said file is not empty and return FALSE is so.
|
425 |
+
$this->criticalcss->log( 'Job id <' . $ljid . '> with hash <' . $hash . '> MATCH the one in rule <' . $trule[0] . '|' . $trule[1] . '>', 3 );
|
426 |
return false;
|
427 |
} else {
|
428 |
// Or return the new hash if they differ.
|
429 |
+
$this->criticalcss->log( 'Job id <' . $ljid . '> with hash <' . $hash . '> DOES NOT MATCH the one in rule <' . $trule[0] . '|' . $trule[1] . '> or rule\'s CCSS file was invalid.', 3 );
|
430 |
return $hash;
|
431 |
}
|
432 |
} else {
|
433 |
// Return the hash for a job that has no rule yet.
|
434 |
+
$this->criticalcss->log( 'Job id <' . $ljid . '> with hash <' . $hash . '> has no rule yet', 3 );
|
435 |
return $hash;
|
436 |
}
|
437 |
}
|
439 |
public function ao_ccss_api_generate( $path, $debug, $dcode ) {
|
440 |
// POST jobs to criticalcss.com and return responses
|
441 |
// Get key and key status.
|
442 |
+
$key = $this->criticalcss->get_option( 'key' );
|
443 |
+
$key_status = $this->criticalcss->get_option( 'keyst' );
|
444 |
+
$noptimize = $this->criticalcss->get_option( 'noptimize' );
|
|
|
445 |
|
446 |
// Prepare full URL to request.
|
|
|
|
|
447 |
$site_host = get_site_url();
|
448 |
$site_path = parse_url( $site_host, PHP_URL_PATH );
|
449 |
|
454 |
// Logic to bind to one domain to avoid site clones of sites would
|
455 |
// automatically begin spawning requests to criticalcss.com which has
|
456 |
// a per domain cost.
|
457 |
+
$domain = $this->criticalcss->get_option( 'domain' );
|
458 |
+
if ( empty( $domain ) ) {
|
459 |
// first request being done, update option to allow future requests are only allowed if from same domain.
|
460 |
update_option( 'autoptimize_ccss_domain', str_rot13( $site_host ) );
|
461 |
+
} elseif ( trim( $domain, '\'"' ) !== 'none' && parse_url( $site_host, PHP_URL_HOST ) !== parse_url( $domain, PHP_URL_HOST ) && apply_filters( 'autoptimize_filter_ccss_bind_domain', true ) ) {
|
462 |
// not the same domain, log as error and return without posting to criticalcss.com.
|
463 |
+
$this->criticalcss->log( 'Request for domain ' . $site_host . ' does not match bound domain ' . $domain . ' so not proceeding.', 2 );
|
464 |
return false;
|
465 |
}
|
466 |
|
467 |
$src_url = $site_host . $path;
|
468 |
|
469 |
// Avoid AO optimizations if required by config or avoid lazyload if lazyload is active in AO.
|
470 |
+
if ( ! empty( $noptimize ) ) {
|
471 |
$src_url .= '?ao_noptirocket=1';
|
472 |
} elseif ( ( class_exists( 'autoptimizeImages', false ) && autoptimizeImages::should_lazyload_wrapper() ) || apply_filters( 'autoptimize_filter_ccss_enforce_nolazy', false ) ) {
|
473 |
$src_url .= '?ao_nolazy=1';
|
482 |
$body['aocssv'] = AO_CCSS_VER;
|
483 |
|
484 |
// Prepare and add viewport size to the body if available.
|
485 |
+
$viewport = $this->criticalcss->viewport();
|
486 |
if ( ! empty( $viewport['w'] ) && ! empty( $viewport['h'] ) ) {
|
487 |
$body['width'] = $viewport['w'];
|
488 |
$body['height'] = $viewport['h'];
|
489 |
}
|
490 |
|
491 |
// Prepare and add forceInclude to the body if available.
|
492 |
+
$finclude = $this->criticalcss->get_option( 'finclude' );
|
493 |
+
$finclude = $this->ao_ccss_finclude( $finclude );
|
494 |
if ( ! empty( $finclude ) ) {
|
495 |
$body['forceInclude'] = $finclude;
|
496 |
}
|
500 |
|
501 |
// Body must be json and log it.
|
502 |
$body = json_encode( $body );
|
503 |
+
$this->criticalcss->log( 'criticalcss.com: POST generate request body is ' . $body, 3 );
|
504 |
|
505 |
// Prepare the request.
|
506 |
$url = esc_url_raw( AO_CCSS_API . 'generate?aover=' . AO_CCSS_VER );
|
507 |
$args = array(
|
508 |
+
'headers' => apply_filters( 'autoptimize_ccss_cron_api_generate_headers', array(
|
509 |
'User-Agent' => 'Autoptimize v' . AO_CCSS_VER,
|
510 |
'Content-type' => 'application/json; charset=utf-8',
|
511 |
'Authorization' => 'JWT ' . $key,
|
512 |
'Connection' => 'close',
|
513 |
+
) ),
|
514 |
'body' => $body,
|
515 |
);
|
516 |
|
529 |
// Workaround criticalcss.com non-RESTful reponses.
|
530 |
if ( 'JOB_QUEUED' == $body['job']['status'] || 'JOB_ONGOING' == $body['job']['status'] || 'STATUS_JOB_BAD' == $body['job']['status'] ) {
|
531 |
// Log successful and return encoded request body.
|
532 |
+
$this->criticalcss->log( 'criticalcss.com: POST generate request for path <' . $src_url . '> replied successfully', 3 );
|
533 |
|
534 |
// This code also means the key is valid, so cache key status for 24h if not already cached.
|
535 |
if ( ( ! $key_status || 2 != $key_status ) && $key ) {
|
536 |
update_option( 'autoptimize_ccss_keyst', 2 );
|
537 |
+
$this->criticalcss->log( 'criticalcss.com: API key is valid, updating key status', 3 );
|
538 |
}
|
539 |
|
540 |
// Return the request body.
|
541 |
return $body;
|
542 |
} else {
|
543 |
// Log successful requests with invalid reponses.
|
544 |
+
$this->criticalcss->log( 'criticalcss.com: POST generate request for path <' . $src_url . '> replied with code <' . $code . '> and an UNKNOWN error condition, body follows...', 2 );
|
545 |
+
$this->criticalcss->log( print_r( $body, true ), 2 );
|
546 |
return $body;
|
547 |
}
|
548 |
} else {
|
549 |
// Response code is anything else.
|
550 |
// Log failed request with a valid response code and return body.
|
551 |
if ( $code ) {
|
552 |
+
$this->criticalcss->log( 'criticalcss.com: POST generate request for path <' . $src_url . '> replied with error code <' . $code . '>, body follows...', 2 );
|
553 |
+
$this->criticalcss->log( print_r( $body, true ), 2 );
|
554 |
|
555 |
if ( 401 == $code ) {
|
556 |
// If request is unauthorized, also clear key status.
|
557 |
update_option( 'autoptimize_ccss_keyst', 1 );
|
558 |
+
$this->criticalcss->log( 'criticalcss.com: API key is invalid, updating key status', 3 );
|
559 |
}
|
560 |
|
561 |
// Return the request body.
|
562 |
return $body;
|
563 |
} else {
|
564 |
// Log failed request with no response and return false.
|
565 |
+
$this->criticalcss->log( 'criticalcss.com: POST generate request for path <' . $src_url . '> has no response, this could be a service timeout', 2 );
|
566 |
if ( is_wp_error( $req ) ) {
|
567 |
+
$this->criticalcss->log( $req->get_error_message(), 2 );
|
568 |
}
|
569 |
|
570 |
return false;
|
575 |
public function ao_ccss_api_results( $jobid, $debug, $dcode ) {
|
576 |
// GET jobs from criticalcss.com and return responses
|
577 |
// Get key.
|
578 |
+
$key = $this->criticalcss->get_option( 'key' );
|
|
|
579 |
|
580 |
// Prepare the request.
|
581 |
$url = AO_CCSS_API . 'results?resultId=' . $jobid;
|
582 |
$args = array(
|
583 |
+
'headers' => apply_filters( 'autoptimize_ccss_cron_api_generate_headers', array(
|
584 |
'User-Agent' => 'Autoptimize CriticalCSS Power-Up v' . AO_CCSS_VER,
|
585 |
'Authorization' => 'JWT ' . $key,
|
586 |
'Connection' => 'close',
|
587 |
+
) ),
|
588 |
);
|
589 |
|
590 |
// Dispatch the request and store its response code.
|
602 |
if ( is_array( $body ) && ( array_key_exists( 'status', $body ) || array_key_exists( 'job', $body ) ) && ( 'JOB_QUEUED' == $body['status'] || 'JOB_ONGOING' == $body['status'] || 'JOB_DONE' == $body['status'] || 'JOB_FAILED' == $body['status'] || 'JOB_UNKNOWN' == $body['status'] || 'STATUS_JOB_BAD' == $body['job']['status'] ) ) {
|
603 |
// Workaround criticalcss.com non-RESTful reponses
|
604 |
// Log successful and return encoded request body.
|
605 |
+
$this->criticalcss->log( 'criticalcss.com: GET results request for remote job id <' . $jobid . '> replied successfully', 3 );
|
606 |
return $body;
|
607 |
} elseif ( is_array( $body ) && ( array_key_exists( 'error', $body ) && 'This css no longer exists. Please re-generate it.' == $body['error'] ) ) {
|
608 |
// Handle no CSS reply
|
609 |
// Log no CSS error and return encoded request body.
|
610 |
+
$this->criticalcss->log( 'criticalcss.com: GET results request for remote job id <' . $jobid . '> replied successfully but the CSS for it does not exist anymore', 3 );
|
611 |
return $body;
|
612 |
} else {
|
613 |
// Log failed request and return false.
|
614 |
+
$this->criticalcss->log( 'criticalcss.com: GET results request for remote job id <' . $jobid . '> replied with code <' . $code . '> and an UNKNOWN error condition, body follows...', 2 );
|
615 |
+
$this->criticalcss->log( print_r( $body, true ), 2 );
|
616 |
return false;
|
617 |
}
|
618 |
} else {
|
619 |
// Response code is anything else
|
620 |
// Log failed request with a valid response code and return body.
|
621 |
if ( $code ) {
|
622 |
+
$this->criticalcss->log( 'criticalcss.com: GET results request for remote job id <' . $jobid . '> replied with error code <' . $code . '>, body follows...', 2 );
|
623 |
+
$this->criticalcss->log( print_r( $body, true ), 2 );
|
624 |
if ( 401 == $code ) {
|
625 |
// If request is unauthorized, also clear key status.
|
626 |
update_option( 'autoptimize_ccss_keyst', 1 );
|
627 |
+
$this->criticalcss->log( 'criticalcss.com: API key is invalid, updating key status', 3 );
|
628 |
}
|
629 |
|
630 |
// Return the request body.
|
631 |
return $body;
|
632 |
} else {
|
633 |
// Log failed request with no response and return false.
|
634 |
+
$this->criticalcss->log( 'criticalcss.com: GET results request for remote job id <' . $jobid . '> has no response, this could be a service timeout', 2 );
|
635 |
return false;
|
636 |
}
|
637 |
}
|
650 |
$filename = false;
|
651 |
$content = $ccss;
|
652 |
|
653 |
+
if ( $this->criticalcss->check_contents( $content ) ) {
|
654 |
// Sanitize content, set filename and try to save file.
|
655 |
$file = AO_CCSS_DIR . 'ccss_' . md5( $ccss . $target[1] ) . $rmark . '.css';
|
656 |
$status = file_put_contents( $file, $content, LOCK_EX );
|
657 |
$filename = pathinfo( $file, PATHINFO_BASENAME );
|
658 |
+
$this->criticalcss->log( 'Critical CSS file for the rule <' . $target[0] . '|' . $target[1] . '> was saved as <' . $filename . '>, size in bytes is <' . $status . '>', 3 );
|
659 |
|
660 |
if ( ! $status ) {
|
661 |
// If file has not been saved, reset filename.
|
662 |
+
$this->criticalcss->log( 'Critical CSS file <' . $filename . '> could not be not saved', 2 );
|
663 |
$filename = false;
|
664 |
return $filename;
|
665 |
}
|
666 |
} else {
|
667 |
+
$this->criticalcss->log( 'Critical CSS received did not pass content check', 2 );
|
668 |
return $filename;
|
669 |
}
|
670 |
|
671 |
// Remove old critical CSS if a previous one existed in the rule and if that file exists in filesystem
|
|
|
672 |
// Attach required arrays.
|
673 |
+
$rules = $this->criticalcss->get_option( 'rules' );
|
674 |
+
|
675 |
+
// Only proceed if the rule already existed.
|
676 |
+
if ( array_key_exists( $target[1], $rules[ $target[0] ] ) ) {
|
677 |
+
$srule = $rules[ $target[0] ][ $target[1] ];
|
678 |
+
$oldfile = $srule['file'];
|
679 |
+
|
680 |
+
if ( $oldfile && $oldfile !== $filename ) {
|
681 |
+
$delfile = AO_CCSS_DIR . $oldfile;
|
682 |
+
if ( file_exists( $delfile ) ) {
|
683 |
+
$unlinkst = unlink( $delfile );
|
684 |
+
if ( $unlinkst ) {
|
685 |
+
$this->criticalcss->log( 'A previous critical CSS file <' . $oldfile . '> was removed for the rule <' . $target[0] . '|' . $target[1] . '>', 3 );
|
686 |
+
}
|
687 |
}
|
688 |
}
|
689 |
}
|
695 |
public function ao_ccss_rule_update( $ljid, $srule, $file, $hash ) {
|
696 |
// Update or create a rule
|
697 |
// Attach required arrays.
|
698 |
+
$rules = $this->criticalcss->get_option( 'rules' );
|
699 |
|
700 |
// Prepare rule variables.
|
701 |
$trule = explode( '|', $srule );
|
702 |
+
if ( array_key_exists( $trule[1], $rules[$trule[0]] ) ) {
|
703 |
+
$rule = $rules[ $trule[0] ][ $trule[1] ];
|
704 |
+
} else {
|
705 |
+
$rule = array();
|
706 |
+
}
|
707 |
$action = false;
|
708 |
$rtype = '';
|
709 |
|
710 |
+
if ( is_array( $rule ) && 0 === $rule['hash'] && 0 !== $rule['file'] ) {
|
711 |
// manual rule, don't ever overwrite.
|
712 |
$action = 'NOT UPDATED';
|
713 |
$rtype = 'MANUAL';
|
714 |
+
} elseif ( is_array( $rule ) && 0 === $rule['hash'] && 0 === $rule['file'] ) {
|
715 |
// If this is an user created AUTO rule with no hash and file yet, update its hash and filename
|
716 |
// Set rule hash, file and action flag.
|
717 |
$rule['hash'] = $hash;
|
718 |
$rule['file'] = $file;
|
719 |
$action = 'UPDATED';
|
720 |
$rtype = 'AUTO';
|
721 |
+
} elseif ( is_array( $rule ) && 0 !== $rule['hash'] && ctype_alnum( $rule['hash'] ) ) {
|
722 |
// If this is an genuine AUTO rule, update its hash and filename
|
723 |
// Set rule hash, file and action flag.
|
724 |
$rule['hash'] = $hash;
|
736 |
$rtype = 'AUTO';
|
737 |
} else {
|
738 |
// Log that no rule was created.
|
739 |
+
$this->criticalcss->log( 'Exception, no AUTO rule created', 3 );
|
740 |
}
|
741 |
}
|
742 |
|
743 |
if ( $action ) {
|
744 |
// If a rule creation/update is required, persist updated rules object.
|
745 |
+
$rules[ $trule[0] ][ $trule[1] ] = $rule;
|
746 |
+
$rules_raw = json_encode( $rules );
|
747 |
+
update_option( 'autoptimize_ccss_rules', $rules_raw );
|
748 |
+
$this->criticalcss->flush_options();
|
749 |
+
$this->criticalcss->log( 'Target rule <' . $srule . '> of type <' . $rtype . '> was ' . $action . ' for job id <' . $ljid . '>', 3 );
|
750 |
} else {
|
751 |
+
$this->criticalcss->log( 'No rule action required', 3 );
|
752 |
}
|
753 |
}
|
754 |
|
812 |
}
|
813 |
|
814 |
// Queue cleaning.
|
815 |
+
$queue = $this->criticalcss->get_option( 'queue' );
|
816 |
+
|
817 |
$queue_purge_threshold = 100;
|
818 |
$queue_purge_age = 24 * 60 * 60;
|
819 |
+
$queue_length = count( $queue );
|
820 |
$timestamp_yesterday = microtime( true ) - $queue_purge_age;
|
821 |
$remove_old_new = false;
|
822 |
$queue_altered = false;
|
825 |
$remove_old_new = true;
|
826 |
}
|
827 |
|
828 |
+
foreach ( $queue as $path => $job ) {
|
829 |
if ( ( $remove_old_new && 'NEW' == $job['jqstat'] && $job['jctime'] < $timestamp_yesterday ) || in_array( $job['jqstat'], array( 'JOB_FAILED', 'STATUS_JOB_BAD', 'NO_CSS', 'NO_RESPONSE' ) ) ) {
|
830 |
+
unset( $queue[ $path ] );
|
831 |
$queue_altered = true;
|
832 |
}
|
833 |
}
|
834 |
|
835 |
// save queue to options!
|
836 |
if ( $queue_altered ) {
|
837 |
+
$queue_raw = json_encode( $queue );
|
838 |
+
update_option( 'autoptimize_ccss_queue', $queue_raw, false );
|
839 |
+
$this->criticalcss->log( 'Queue cleaning done.', 3 );
|
840 |
}
|
841 |
|
842 |
// re-check key if invalid.
|
843 |
+
$keyst = $this->criticalcss->get_option( 'keyst' );
|
844 |
+
if ( 1 == $keyst ) {
|
845 |
$this->ao_ccss_api_generate( '', '', '' );
|
846 |
}
|
847 |
}
|
classes/autoptimizeCriticalCSSEnqueue.php
CHANGED
@@ -8,20 +8,13 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
8 |
}
|
9 |
|
10 |
class autoptimizeCriticalCSSEnqueue {
|
11 |
-
public function __construct()
|
12 |
-
|
13 |
-
// fetch all options at once and populate them individually explicitely as globals.
|
14 |
-
$all_options = autoptimizeCriticalCSSBase::fetch_options();
|
15 |
-
foreach ( $all_options as $_option => $_value ) {
|
16 |
-
global ${$_option};
|
17 |
-
${$_option} = $_value;
|
18 |
-
}
|
19 |
}
|
20 |
|
21 |
-
public
|
22 |
-
$self = new self();
|
23 |
// Get key status.
|
24 |
-
$key =
|
25 |
|
26 |
// Queue is available to anyone...
|
27 |
$enqueue = true;
|
@@ -29,187 +22,190 @@ class autoptimizeCriticalCSSEnqueue {
|
|
29 |
// ... which are not the ones below.
|
30 |
if ( 'nokey' == $key['status'] || 'invalid' == $key['status'] ) {
|
31 |
$enqueue = false;
|
32 |
-
|
33 |
-
} elseif ( ! empty( $hash ) && ( is_user_logged_in() || is_feed() || is_404() || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) || $
|
34 |
$enqueue = false;
|
35 |
-
|
36 |
} elseif ( empty( $hash ) && empty( $path ) || ( ( 'is_single' !== $type ) && ( 'is_page' !== $type ) ) ) {
|
37 |
$enqueue = false;
|
38 |
-
|
39 |
}
|
40 |
|
41 |
-
if ( $enqueue ) {
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
|
|
|
|
60 |
}
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
}
|
|
|
74 |
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
|
80 |
-
|
81 |
-
|
82 |
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
|
97 |
-
|
98 |
-
|
99 |
-
}
|
100 |
}
|
|
|
101 |
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
|
117 |
-
|
118 |
-
|
119 |
-
}
|
120 |
}
|
121 |
}
|
|
|
122 |
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
} else {
|
139 |
-
// Exception; we don't want a path-based rule for "/" as that messes things up, hard-switch this to a type-based is_front_page rule.
|
140 |
-
$target_rule = 'types|' . 'is_front_page';
|
141 |
-
}
|
142 |
} else {
|
143 |
-
|
|
|
144 |
}
|
145 |
-
autoptimizeCriticalCSSCore::ao_ccss_log( 'Job submission QUALIFIED by MISSING rule for page type <' . $req_type . '> on path <' . $req_path . '>, new rule target is <' . $target_rule . '>', 3 );
|
146 |
} else {
|
147 |
-
|
148 |
-
autoptimizeCriticalCSSCore::ao_ccss_log( 'Job submission QUALIFIED by AUTO rule <' . $target_rule . '> with hash <' . $rule_properties['hash'] . '> and file <' . $rule_properties['file'] . '>', 3 );
|
149 |
}
|
|
|
|
|
|
|
|
|
|
|
150 |
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
157 |
$req_path,
|
158 |
$target_rule,
|
159 |
$req_type,
|
160 |
$hash,
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
);
|
167 |
// Set update flag.
|
168 |
$queue_update = true;
|
169 |
-
} else {
|
170 |
-
// This is an existing job
|
171 |
-
// The job is still NEW, most likely this is extra CSS file for the same page that needs a hash.
|
172 |
-
if ( 'NEW' == $ao_ccss_queue[ $req_path ]['jqstat'] ) {
|
173 |
-
// Add hash if it's not already in the job.
|
174 |
-
if ( ! in_array( $hash, $ao_ccss_queue[ $req_path ]['hashes'] ) ) {
|
175 |
-
// Push new hash to its array and update flag.
|
176 |
-
$queue_update = array_push( $ao_ccss_queue[ $req_path ]['hashes'], $hash );
|
177 |
-
|
178 |
-
// Log job update.
|
179 |
-
autoptimizeCriticalCSSCore::ao_ccss_log( 'Hashes UPDATED on local job id <' . $ao_ccss_queue[ $req_path ]['ljid'] . '>, job status NEW, target rule <' . $ao_ccss_queue[ $req_path ]['rtarget'] . '>, hash added: ' . $hash, 3 );
|
180 |
-
|
181 |
-
// Return from here as the hash array is already updated.
|
182 |
-
return true;
|
183 |
-
}
|
184 |
-
} elseif ( 'NEW' != $ao_ccss_queue[ $req_path ]['jqstat'] && 'JOB_QUEUED' != $ao_ccss_queue[ $req_path ]['jqstat'] && 'JOB_ONGOING' != $ao_ccss_queue[ $req_path ]['jqstat'] ) {
|
185 |
-
// Allow requeuing jobs that are not NEW, JOB_QUEUED or JOB_ONGOING
|
186 |
-
// Merge new job keeping some previous job values.
|
187 |
-
$ao_ccss_queue[ $req_path ] = $self->ao_ccss_define_job(
|
188 |
-
$req_path,
|
189 |
-
$target_rule,
|
190 |
-
$req_type,
|
191 |
-
$hash,
|
192 |
-
$ao_ccss_queue[ $req_path ]['file'],
|
193 |
-
$ao_ccss_queue[ $req_path ]['jid'],
|
194 |
-
$ao_ccss_queue[ $req_path ]['jrstat'],
|
195 |
-
$ao_ccss_queue[ $req_path ]['jvstat'],
|
196 |
-
false
|
197 |
-
);
|
198 |
-
// Set update flag.
|
199 |
-
$queue_update = true;
|
200 |
-
}
|
201 |
}
|
|
|
202 |
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
}
|
214 |
}
|
215 |
}
|
@@ -217,14 +213,14 @@ class autoptimizeCriticalCSSEnqueue {
|
|
217 |
public function ao_ccss_get_type() {
|
218 |
// Get the type of a page
|
219 |
// Attach the conditional tags array.
|
220 |
-
|
221 |
-
|
222 |
|
223 |
// By default, a page type is false.
|
224 |
$page_type = false;
|
225 |
|
226 |
// Iterates over the array to match a type.
|
227 |
-
foreach ( $
|
228 |
if ( is_404() ) {
|
229 |
$page_type = 'is_404';
|
230 |
break;
|
@@ -232,13 +228,13 @@ class autoptimizeCriticalCSSEnqueue {
|
|
232 |
// identify frontpage immediately to avoid it also matching a CPT or template.
|
233 |
$page_type = 'is_front_page';
|
234 |
break;
|
235 |
-
} elseif ( strpos( $type, 'custom_post_' ) !== false && ( ! $
|
236 |
// Match custom post types and not page or page not forced to path-based.
|
237 |
if ( get_post_type( get_the_ID() ) === substr( $type, 12 ) ) {
|
238 |
$page_type = $type;
|
239 |
break;
|
240 |
}
|
241 |
-
} elseif ( strpos( $type, 'template_' ) !== false && ( ! $
|
242 |
// Match templates if not page or if page is not forced to path-based.
|
243 |
if ( is_page_template( substr( $type, 9 ) ) ) {
|
244 |
$page_type = $type;
|
@@ -287,7 +283,7 @@ class autoptimizeCriticalCSSEnqueue {
|
|
287 |
}
|
288 |
|
289 |
// Log job creation.
|
290 |
-
|
291 |
|
292 |
return $path;
|
293 |
}
|
8 |
}
|
9 |
|
10 |
class autoptimizeCriticalCSSEnqueue {
|
11 |
+
public function __construct() {
|
12 |
+
$this->criticalcss = autoptimize()->criticalcss();
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
}
|
14 |
|
15 |
+
public function ao_ccss_enqueue( $hash = '', $path = '', $type = 'is_page' ) {
|
|
|
16 |
// Get key status.
|
17 |
+
$key = $this->criticalcss->key_status( false );
|
18 |
|
19 |
// Queue is available to anyone...
|
20 |
$enqueue = true;
|
22 |
// ... which are not the ones below.
|
23 |
if ( 'nokey' == $key['status'] || 'invalid' == $key['status'] ) {
|
24 |
$enqueue = false;
|
25 |
+
$this->criticalcss->log( "Job queuing is not available: no valid API key found.", 3 );
|
26 |
+
} elseif ( ! empty( $hash ) && ( is_user_logged_in() || is_feed() || is_404() || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) || $this->ao_ccss_ua() || false === apply_filters( 'autoptimize_filter_ccss_enqueue_should_enqueue', true ) ) ) {
|
27 |
$enqueue = false;
|
28 |
+
$this->criticalcss->log( "Job queuing is not available for WordPress's logged in users, feeds, error pages, ajax calls or calls from criticalcss.com itself.", 3 );
|
29 |
} elseif ( empty( $hash ) && empty( $path ) || ( ( 'is_single' !== $type ) && ( 'is_page' !== $type ) ) ) {
|
30 |
$enqueue = false;
|
31 |
+
$this->criticalcss->log( "Forced job queuing failed, no path or not right type", 3 );
|
32 |
}
|
33 |
|
34 |
+
if ( ! $enqueue ) {
|
35 |
+
return;
|
36 |
+
}
|
37 |
+
|
38 |
+
// Continue if queue is available
|
39 |
+
// Attach required arrays/ vars.
|
40 |
+
$rules = $this->criticalcss->get_option( 'rules' );
|
41 |
+
$queue_raw = $this->criticalcss->get_option( 'queue_raw' );
|
42 |
+
$queue = $this->criticalcss->get_option( 'queue' );
|
43 |
+
$forcepath = $this->criticalcss->get_option( 'forcepath' );
|
44 |
+
|
45 |
+
// Get request path and page type, and initialize the queue update flag.
|
46 |
+
if ( ! empty( $hash ) ) {
|
47 |
+
$req_orig = $_SERVER['REQUEST_URI'];
|
48 |
+
$req_type = $this->ao_ccss_get_type();
|
49 |
+
} elseif ( ! empty( $path ) ) {
|
50 |
+
$req_orig = $path;
|
51 |
+
if ( $path === '/' ) {
|
52 |
+
$req_type = 'is_front_page';
|
53 |
+
} else {
|
54 |
+
$req_type = $type;
|
55 |
}
|
56 |
+
}
|
57 |
+
$req_path = strtok( $req_orig, '?' );
|
58 |
+
|
59 |
+
// Check if we have a lang param. we need to keep as WPML can switch languages based on that
|
60 |
+
// and that includes RTL -> LTR so diff. structure, so rules would be RTL vs LTR
|
61 |
+
// but this needs changes in the structur of the rule object so off by default for now
|
62 |
+
// as now this will simply result in conditional rules being overwritten.
|
63 |
+
if ( apply_filters( 'autoptimize_filter_ccss_coreenqueue_honor_lang', false ) && strpos( $req_orig, 'lang=' ) !== false ) {
|
64 |
+
$req_params = strtok( '?' );
|
65 |
+
parse_str( $req_params, $req_params_arr );
|
66 |
+
if ( array_key_exists( 'lang', $req_params_arr ) && !empty( $req_params_arr['lang'] ) ) {
|
67 |
+
$req_path .= '?lang=' . $req_params_arr['lang'];
|
68 |
}
|
69 |
+
}
|
70 |
|
71 |
+
$job_qualify = false;
|
72 |
+
$target_rule = false;
|
73 |
+
$rule_properties = false;
|
74 |
+
$queue_update = false;
|
75 |
|
76 |
+
// Match for paths in rules.
|
77 |
+
foreach ( $rules['paths'] as $path => $props ) {
|
78 |
|
79 |
+
// Prepare rule target and log.
|
80 |
+
$target_rule = 'paths|' . $path;
|
81 |
+
$this->criticalcss->log( 'Qualifying path <' . $req_path . '> for job submission by rule <' . $target_rule . '>', 3 );
|
82 |
|
83 |
+
// Path match
|
84 |
+
// -> exact match needed for AUTO rules
|
85 |
+
// -> partial match OK for MANUAL rules (which have empty hash and a file with CCSS).
|
86 |
+
if ( $path === $req_path || ( false == $props['hash'] && false != $props['file'] && preg_match( '|' . $path . '|', $req_path ) ) ) {
|
87 |
|
88 |
+
// There's a path match in the rule, so job QUALIFIES with a path rule match.
|
89 |
+
$job_qualify = true;
|
90 |
+
$rule_properties = $props;
|
91 |
+
$this->criticalcss->log( 'Path <' . $req_path . '> QUALIFIED for job submission by rule <' . $target_rule . '>', 3 );
|
92 |
|
93 |
+
// Stop processing other path rules.
|
94 |
+
break;
|
|
|
95 |
}
|
96 |
+
}
|
97 |
|
98 |
+
// Match for types in rules if no path rule matches and if we're not enforcing paths.
|
99 |
+
if ( '' !== $hash && ! $job_qualify && ( ! $forcepath || ! in_array( $req_type, apply_filters( 'autoptimize_filter_ccss_coreenqueue_forcepathfortype', array( 'is_page' ) ) ) || ! apply_filters( 'autoptimize_filter_ccss_coreenqueue_ignorealltypes', false ) ) ) {
|
100 |
+
foreach ( $rules['types'] as $type => $props ) {
|
101 |
|
102 |
+
// Prepare rule target and log.
|
103 |
+
$target_rule = 'types|' . $type;
|
104 |
+
$this->criticalcss->log( 'Qualifying page type <' . $req_type . '> on path <' . $req_path . '> for job submission by rule <' . $target_rule . '>', 3 );
|
105 |
|
106 |
+
if ( $req_type == $type ) {
|
107 |
+
// Type match.
|
108 |
+
// There's a type match in the rule, so job QUALIFIES with a type rule match.
|
109 |
+
$job_qualify = true;
|
110 |
+
$rule_properties = $props;
|
111 |
+
$this->criticalcss->log( 'Page type <' . $req_type . '> on path <' . $req_path . '> QUALIFIED for job submission by rule <' . $target_rule . '>', 3 );
|
112 |
|
113 |
+
// Stop processing other type rules.
|
114 |
+
break;
|
|
|
115 |
}
|
116 |
}
|
117 |
+
}
|
118 |
|
119 |
+
if ( $job_qualify && ( ( false == $rule_properties['hash'] && false != $rule_properties['file'] ) || strpos( $req_type, 'template_' ) !== false ) ) {
|
120 |
+
// If job qualifies but rule hash is false and file isn't false (MANUAL rule) or if template, job does not qualify despite what previous evaluations says.
|
121 |
+
$job_qualify = false;
|
122 |
+
$this->criticalcss->log( 'Job submission DISQUALIFIED by MANUAL rule <' . $target_rule . '> with hash <' . $rule_properties['hash'] . '> and file <' . $rule_properties['file'] . '>', 3 );
|
123 |
+
} elseif ( ! $job_qualify && empty( $rule_properties ) ) {
|
124 |
+
// But if job does not qualify and rule properties are set, job qualifies as there is no matching rule for it yet
|
125 |
+
// Fill-in the new target rule.
|
126 |
+
$job_qualify = true;
|
127 |
+
|
128 |
+
// Should we switch to path-base AUTO-rules? Conditions:
|
129 |
+
// 1. forcepath option has to be enabled (off by default)
|
130 |
+
// 2. request type should be (by default, but filterable) one of is_page (removed for now: woo_is_product or woo_is_product_category).
|
131 |
+
if ( ( $forcepath && in_array( $req_type, apply_filters( 'autoptimize_filter_ccss_coreenqueue_forcepathfortype', array( 'is_page' ) ) ) ) || apply_filters( 'autoptimize_filter_ccss_coreenqueue_ignorealltypes', false ) || empty( $hash )) {
|
132 |
+
if ( '/' !== $req_path ) {
|
133 |
+
$target_rule = 'paths|' . $req_path;
|
|
|
|
|
|
|
|
|
134 |
} else {
|
135 |
+
// Exception; we don't want a path-based rule for "/" as that messes things up, hard-switch this to a type-based is_front_page rule.
|
136 |
+
$target_rule = 'types|' . 'is_front_page';
|
137 |
}
|
|
|
138 |
} else {
|
139 |
+
$target_rule = 'types|' . $req_type;
|
|
|
140 |
}
|
141 |
+
$this->criticalcss->log( 'Job submission QUALIFIED by MISSING rule for page type <' . $req_type . '> on path <' . $req_path . '>, new rule target is <' . $target_rule . '>', 3 );
|
142 |
+
} else {
|
143 |
+
// Or just log a job qualified by a matching rule.
|
144 |
+
$this->criticalcss->log( 'Job submission QUALIFIED by AUTO rule <' . $target_rule . '> with hash <' . $rule_properties['hash'] . '> and file <' . $rule_properties['file'] . '>', 3 );
|
145 |
+
}
|
146 |
|
147 |
+
// Submit job.
|
148 |
+
if ( $job_qualify ) {
|
149 |
+
if ( ! array_key_exists( $req_path, $queue ) ) {
|
150 |
+
// This is a NEW job
|
151 |
+
// Merge job into the queue.
|
152 |
+
$queue[ $req_path ] = $this->ao_ccss_define_job(
|
153 |
+
$req_path,
|
154 |
+
$target_rule,
|
155 |
+
$req_type,
|
156 |
+
$hash,
|
157 |
+
null,
|
158 |
+
null,
|
159 |
+
null,
|
160 |
+
null,
|
161 |
+
true
|
162 |
+
);
|
163 |
+
// Set update flag.
|
164 |
+
$queue_update = true;
|
165 |
+
} else {
|
166 |
+
// This is an existing job
|
167 |
+
// The job is still NEW, most likely this is extra CSS file for the same page that needs a hash.
|
168 |
+
if ( 'NEW' == $queue[ $req_path ]['jqstat'] ) {
|
169 |
+
// Add hash if it's not already in the job.
|
170 |
+
if ( ! in_array( $hash, $queue[ $req_path ]['hashes'] ) ) {
|
171 |
+
// Push new hash to its array and update flag.
|
172 |
+
$queue_update = array_push( $queue[ $req_path ]['hashes'], $hash );
|
173 |
+
|
174 |
+
// Log job update.
|
175 |
+
$this->criticalcss->log( 'Hashes UPDATED on local job id <' . $queue[ $req_path ]['ljid'] . '>, job status NEW, target rule <' . $queue[ $req_path ]['rtarget'] . '>, hash added: ' . $hash, 3 );
|
176 |
+
|
177 |
+
// Return from here as the hash array is already updated.
|
178 |
+
return true;
|
179 |
+
}
|
180 |
+
} elseif ( 'NEW' != $queue[ $req_path ]['jqstat'] && 'JOB_QUEUED' != $queue[ $req_path ]['jqstat'] && 'JOB_ONGOING' != $queue[ $req_path ]['jqstat'] ) {
|
181 |
+
// Allow requeuing jobs that are not NEW, JOB_QUEUED or JOB_ONGOING
|
182 |
+
// Merge new job keeping some previous job values.
|
183 |
+
$queue[ $req_path ] = $this->ao_ccss_define_job(
|
184 |
$req_path,
|
185 |
$target_rule,
|
186 |
$req_type,
|
187 |
$hash,
|
188 |
+
$queue[ $req_path ]['file'],
|
189 |
+
$queue[ $req_path ]['jid'],
|
190 |
+
$queue[ $req_path ]['jrstat'],
|
191 |
+
$queue[ $req_path ]['jvstat'],
|
192 |
+
false
|
193 |
);
|
194 |
// Set update flag.
|
195 |
$queue_update = true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
196 |
}
|
197 |
+
}
|
198 |
|
199 |
+
if ( $queue_update ) {
|
200 |
+
// Persist the job to the queue and return.
|
201 |
+
$queue_raw = json_encode( $queue );
|
202 |
+
update_option( 'autoptimize_ccss_queue', $queue_raw, false );
|
203 |
+
$this->criticalcss->flush_options();
|
204 |
+
return true;
|
205 |
+
} else {
|
206 |
+
// Or just return false if no job was added.
|
207 |
+
$this->criticalcss->log( 'A job for path <' . $req_path . '> already exist with NEW or PENDING status, skipping job creation', 3 );
|
208 |
+
return false;
|
209 |
}
|
210 |
}
|
211 |
}
|
213 |
public function ao_ccss_get_type() {
|
214 |
// Get the type of a page
|
215 |
// Attach the conditional tags array.
|
216 |
+
$types = $this->criticalcss->get_types();
|
217 |
+
$forcepath = $this->criticalcss->get_option( 'forcepath' );
|
218 |
|
219 |
// By default, a page type is false.
|
220 |
$page_type = false;
|
221 |
|
222 |
// Iterates over the array to match a type.
|
223 |
+
foreach ( $types as $type ) {
|
224 |
if ( is_404() ) {
|
225 |
$page_type = 'is_404';
|
226 |
break;
|
228 |
// identify frontpage immediately to avoid it also matching a CPT or template.
|
229 |
$page_type = 'is_front_page';
|
230 |
break;
|
231 |
+
} elseif ( strpos( $type, 'custom_post_' ) !== false && ( ! $forcepath || ! is_page() ) ) {
|
232 |
// Match custom post types and not page or page not forced to path-based.
|
233 |
if ( get_post_type( get_the_ID() ) === substr( $type, 12 ) ) {
|
234 |
$page_type = $type;
|
235 |
break;
|
236 |
}
|
237 |
+
} elseif ( strpos( $type, 'template_' ) !== false && ( ! $forcepath || ! is_page() ) ) {
|
238 |
// Match templates if not page or if page is not forced to path-based.
|
239 |
if ( is_page_template( substr( $type, 9 ) ) ) {
|
240 |
$page_type = $type;
|
283 |
}
|
284 |
|
285 |
// Log job creation.
|
286 |
+
$this->criticalcss->log( 'Job ' . $operation . ' with local job id <' . $path['ljid'] . '> for target rule <' . $target . '>', 3 );
|
287 |
|
288 |
return $path;
|
289 |
}
|
classes/autoptimizeCriticalCSSSettings.php
CHANGED
@@ -15,8 +15,8 @@ class autoptimizeCriticalCSSSettings {
|
|
15 |
*/
|
16 |
private $settings_screen_do_remote_http = true;
|
17 |
|
18 |
-
public function __construct()
|
19 |
-
|
20 |
$this->settings_screen_do_remote_http = apply_filters( 'autoptimize_settingsscreen_remotehttp', $this->settings_screen_do_remote_http );
|
21 |
$this->run();
|
22 |
}
|
@@ -100,12 +100,20 @@ class autoptimizeCriticalCSSSettings {
|
|
100 |
require_once( 'critcss-inc/admin_settings_adv.php' );
|
101 |
require_once( 'critcss-inc/admin_settings_explain.php' );
|
102 |
|
103 |
-
|
104 |
-
$
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
109 |
?>
|
110 |
<script>document.title = "Autoptimize: <?php _e( 'Critical CSS', 'autoptimize' ); ?> " + document.title;</script>
|
111 |
<div class="wrap">
|
@@ -118,26 +126,25 @@ class autoptimizeCriticalCSSSettings {
|
|
118 |
// Print AO settings tabs.
|
119 |
echo autoptimizeConfig::ao_admin_tabs();
|
120 |
|
121 |
-
|
122 |
-
if ( ! is_dir( AO_CCSS_DIR ) ) {
|
123 |
-
$mkdirresp = @mkdir( AO_CCSS_DIR, 0775, true ); // @codingStandardsIgnoreLine
|
124 |
-
} else {
|
125 |
-
$mkdirresp = true;
|
126 |
-
}
|
127 |
-
|
128 |
-
// Make sure our index.html is there.
|
129 |
-
if ( ! is_file( AO_CCSS_DIR . 'index.html' ) ) {
|
130 |
-
$fileresp = file_put_contents( AO_CCSS_DIR . 'index.html', '<html><head><meta name="robots" content="noindex, nofollow"></head><body>Generated by <a href="http://wordpress.org/extend/plugins/autoptimize/" rel="nofollow">Autoptimize</a></body></html>' );
|
131 |
-
} else {
|
132 |
-
$fileresp = true;
|
133 |
-
}
|
134 |
|
135 |
// Warn if we could not create those files.
|
136 |
-
if ( (
|
137 |
?>
|
138 |
<div class="notice-error notice"><p>
|
139 |
<?php
|
140 |
-
_e( 'Could not create the required directory. Make sure the webserver can write to the wp-content directory.', 'autoptimize' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
141 |
?>
|
142 |
</p></div>
|
143 |
<?php
|
@@ -283,7 +290,7 @@ class autoptimizeCriticalCSSSettings {
|
|
283 |
settings_fields( 'ao_ccss_options_group' );
|
284 |
|
285 |
// Get API key status.
|
286 |
-
$key =
|
287 |
|
288 |
if ( $this->is_multisite_network_admin() ) {
|
289 |
?>
|
@@ -306,25 +313,31 @@ class autoptimizeCriticalCSSSettings {
|
|
306 |
// Render advanced panel.
|
307 |
ao_ccss_render_adv();
|
308 |
} else {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
309 |
// But if key is other than valid, add hidden fields to persist settings when submitting form
|
310 |
// Show explanation of why and how to get a API key.
|
311 |
ao_ccss_render_explain();
|
312 |
|
313 |
// Get viewport size.
|
314 |
-
$viewport =
|
315 |
|
316 |
// Add hidden fields.
|
317 |
-
echo "<input class='hidden' name='
|
318 |
-
echo
|
319 |
-
echo '<input class="hidden" name="autoptimize_ccss_viewport[
|
320 |
-
echo '<input class="hidden" name="autoptimize_ccss_viewport[h]" value="' . $viewport['h'] . '">';
|
321 |
echo '<input class="hidden" name="autoptimize_ccss_finclude" value="' . esc_attr( $ao_ccss_finclude ) . '">';
|
322 |
-
echo '<input class="hidden" name="autoptimize_ccss_rtimelimit" value="' . $ao_ccss_rtimelimit . '">';
|
323 |
-
echo '<input class="hidden" name="autoptimize_ccss_debug" value="' . $ao_ccss_debug . '">';
|
324 |
-
echo '<input class="hidden" name="autoptimize_ccss_noptimize" value="' . $ao_ccss_noptimize . '">';
|
325 |
echo '<input class="hidden" name="autoptimize_css_defer_inline" value="' . esc_attr( $ao_css_defer_inline ) . '">';
|
326 |
-
echo '<input class="hidden" name="autoptimize_ccss_loggedin" value="' . $ao_ccss_loggedin . '">';
|
327 |
-
echo '<input class="hidden" name="autoptimize_ccss_forcepath" value="' . $ao_ccss_forcepath . '">';
|
328 |
}
|
329 |
// Render key panel unconditionally.
|
330 |
ao_ccss_render_key( $ao_ccss_key, $key['status'], $key['stmsg'], $key['msg'], $key['color'] );
|
@@ -377,11 +390,11 @@ class autoptimizeCriticalCSSSettings {
|
|
377 |
}
|
378 |
}
|
379 |
|
380 |
-
public
|
381 |
static $_has_auto_rules = null;
|
382 |
|
383 |
if ( null === $_has_auto_rules ) {
|
384 |
-
|
385 |
$_has_auto_rules = false;
|
386 |
if ( ! empty( $ao_ccss_rules ) ) {
|
387 |
foreach ( array( 'types', 'paths' ) as $_typat ) {
|
15 |
*/
|
16 |
private $settings_screen_do_remote_http = true;
|
17 |
|
18 |
+
public function __construct() {
|
19 |
+
$this->criticalcss = autoptimize()->criticalcss();
|
20 |
$this->settings_screen_do_remote_http = apply_filters( 'autoptimize_settingsscreen_remotehttp', $this->settings_screen_do_remote_http );
|
21 |
$this->run();
|
22 |
}
|
100 |
require_once( 'critcss-inc/admin_settings_adv.php' );
|
101 |
require_once( 'critcss-inc/admin_settings_explain.php' );
|
102 |
|
103 |
+
$ao_ccss_key = $this->criticalcss->get_option( 'key' );
|
104 |
+
$ao_ccss_keyst = $this->criticalcss->get_option( 'keyst' );
|
105 |
+
$ao_css_defer = $this->criticalcss->get_option( 'css_defer' );
|
106 |
+
$ao_ccss_deferjquery = $this->criticalcss->get_option( 'deferjquery' );
|
107 |
+
$ao_ccss_queue = $this->criticalcss->get_option( 'queue' );
|
108 |
+
$ao_ccss_rules = $this->criticalcss->get_option( 'rules' );
|
109 |
+
$ao_ccss_servicestatus = $this->criticalcss->get_option( 'servicestatus' );
|
110 |
+
$ao_ccss_finclude = $this->criticalcss->get_option( 'finclude' );
|
111 |
+
$ao_ccss_rtimelimit = $this->criticalcss->get_option( 'rtimelimit' );
|
112 |
+
$ao_ccss_debug = $this->criticalcss->get_option( 'debug' );
|
113 |
+
$ao_ccss_noptimize = $this->criticalcss->get_option( 'noptimize' );
|
114 |
+
$ao_css_defer_inline = $this->criticalcss->get_option( 'css_defer_inline' );
|
115 |
+
$ao_ccss_loggedin = $this->criticalcss->get_option( 'loggedin' );
|
116 |
+
$ao_ccss_forcepath = $this->criticalcss->get_option( 'forcepath' );
|
117 |
?>
|
118 |
<script>document.title = "Autoptimize: <?php _e( 'Critical CSS', 'autoptimize' ); ?> " + document.title;</script>
|
119 |
<div class="wrap">
|
126 |
// Print AO settings tabs.
|
127 |
echo autoptimizeConfig::ao_admin_tabs();
|
128 |
|
129 |
+
$mkdirresult = $this->criticalcss->create_ao_ccss_dir();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
130 |
|
131 |
// Warn if we could not create those files.
|
132 |
+
if ( ( true !== $mkdirresult ) ) {
|
133 |
?>
|
134 |
<div class="notice-error notice"><p>
|
135 |
<?php
|
136 |
+
_e( 'Could not create the required directory. Make sure the webserver can write to the wp-content/uploads directory.', 'autoptimize' );
|
137 |
+
?>
|
138 |
+
</p></div>
|
139 |
+
<?php
|
140 |
+
}
|
141 |
+
|
142 |
+
// Check if CSS optimization is on.
|
143 |
+
if ( 'on' !== autoptimizeOptionWrapper::get_option( 'autoptimize_css' ) || 'on' !== autoptimizeOptionWrapper::get_option( 'autoptimize_css_defer' ) ) {
|
144 |
+
?>
|
145 |
+
<div class="notice-info notice"><p>
|
146 |
+
<?php
|
147 |
+
_e( 'To be able to use Critical CSS you will have to enable CSS optimization and make sure "eliminate render-blocking CSS" is active on the main Autoptimize settings page.', 'autoptimize' );
|
148 |
?>
|
149 |
</p></div>
|
150 |
<?php
|
290 |
settings_fields( 'ao_ccss_options_group' );
|
291 |
|
292 |
// Get API key status.
|
293 |
+
$key = $this->criticalcss->key_status( true );
|
294 |
|
295 |
if ( $this->is_multisite_network_admin() ) {
|
296 |
?>
|
313 |
// Render advanced panel.
|
314 |
ao_ccss_render_adv();
|
315 |
} else {
|
316 |
+
if ( apply_filters( 'autoptimize_filter_ccss_rules_without_api', true ) ) {
|
317 |
+
// Render rules section for manual rules.
|
318 |
+
ao_ccss_render_rules();
|
319 |
+
} else {
|
320 |
+
echo "<input class='hidden' name='autoptimize_ccss_queue' value='" . json_encode( $ao_ccss_rules, JSON_FORCE_OBJECT ) . "'>";
|
321 |
+
}
|
322 |
+
|
323 |
// But if key is other than valid, add hidden fields to persist settings when submitting form
|
324 |
// Show explanation of why and how to get a API key.
|
325 |
ao_ccss_render_explain();
|
326 |
|
327 |
// Get viewport size.
|
328 |
+
$viewport = $this->criticalcss->viewport();
|
329 |
|
330 |
// Add hidden fields.
|
331 |
+
echo "<input class='hidden' name='autoptimize_ccss_queue' value='" . json_encode( $ao_ccss_queue, JSON_FORCE_OBJECT ) . "'>";
|
332 |
+
echo '<input class="hidden" name="autoptimize_ccss_viewport[w]" value="' . esc_attr( $viewport['w'] ) . '">';
|
333 |
+
echo '<input class="hidden" name="autoptimize_ccss_viewport[h]" value="' . esc_attr( $viewport['h'] ) . '">';
|
|
|
334 |
echo '<input class="hidden" name="autoptimize_ccss_finclude" value="' . esc_attr( $ao_ccss_finclude ) . '">';
|
335 |
+
echo '<input class="hidden" name="autoptimize_ccss_rtimelimit" value="' . esc_attr( $ao_ccss_rtimelimit ) . '">';
|
336 |
+
echo '<input class="hidden" name="autoptimize_ccss_debug" value="' . esc_attr( $ao_ccss_debug ) . '">';
|
337 |
+
echo '<input class="hidden" name="autoptimize_ccss_noptimize" value="' . esc_attr( $ao_ccss_noptimize ) . '">';
|
338 |
echo '<input class="hidden" name="autoptimize_css_defer_inline" value="' . esc_attr( $ao_css_defer_inline ) . '">';
|
339 |
+
echo '<input class="hidden" name="autoptimize_ccss_loggedin" value="' . esc_attr( $ao_ccss_loggedin ). '">';
|
340 |
+
echo '<input class="hidden" name="autoptimize_ccss_forcepath" value="' . esc_attr( $ao_ccss_forcepath ) . '">';
|
341 |
}
|
342 |
// Render key panel unconditionally.
|
343 |
ao_ccss_render_key( $ao_ccss_key, $key['status'], $key['stmsg'], $key['msg'], $key['color'] );
|
390 |
}
|
391 |
}
|
392 |
|
393 |
+
public function ao_ccss_has_autorules() {
|
394 |
static $_has_auto_rules = null;
|
395 |
|
396 |
if ( null === $_has_auto_rules ) {
|
397 |
+
$ao_ccss_rules = $this->criticalcss->get_option( 'rules' );
|
398 |
$_has_auto_rules = false;
|
399 |
if ( ! empty( $ao_ccss_rules ) ) {
|
400 |
foreach ( array( 'types', 'paths' ) as $_typat ) {
|
classes/autoptimizeCriticalCSSSettingsAjax.php
CHANGED
@@ -8,14 +8,8 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
8 |
}
|
9 |
|
10 |
class autoptimizeCriticalCSSSettingsAjax {
|
11 |
-
public function __construct()
|
12 |
-
|
13 |
-
// fetch all options at once and populate them individually explicitely as globals.
|
14 |
-
$all_options = autoptimizeCriticalCSSBase::fetch_options();
|
15 |
-
foreach ( $all_options as $_option => $_value ) {
|
16 |
-
global ${$_option};
|
17 |
-
${$_option} = $_value;
|
18 |
-
}
|
19 |
$this->run();
|
20 |
}
|
21 |
|
@@ -88,7 +82,7 @@ class autoptimizeCriticalCSSSettingsAjax {
|
|
88 |
$critcsscontents = stripslashes( $_POST['critcsscontents'] );
|
89 |
|
90 |
// If there is content and it's valid, write the file.
|
91 |
-
if ( $critcsscontents &&
|
92 |
// Set file path and status.
|
93 |
$critcssfile = AO_CCSS_DIR . strip_tags( $_POST['critcssfile'] );
|
94 |
$status = file_put_contents( $critcssfile, $critcsscontents, LOCK_EX );
|
@@ -215,15 +209,64 @@ class autoptimizeCriticalCSSSettingsAjax {
|
|
215 |
}
|
216 |
|
217 |
// Init array, get options and prepare the raw object.
|
218 |
-
$settings
|
219 |
-
|
220 |
-
|
221 |
-
$settings['
|
222 |
-
$settings['
|
223 |
-
$settings['
|
224 |
-
$settings['
|
225 |
-
$settings['
|
226 |
-
$settings['
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
227 |
|
228 |
// Initialize error flag.
|
229 |
$error = true;
|
@@ -238,7 +281,7 @@ class autoptimizeCriticalCSSSettingsAjax {
|
|
238 |
}
|
239 |
|
240 |
// Prepare archive.
|
241 |
-
$zipfile = AO_CCSS_DIR . date( 'Ymd-H\hi' ) . '_ao_ccss_settings.zip';
|
242 |
$file = pathinfo( $zipfile, PATHINFO_BASENAME );
|
243 |
$zip = new ZipArchive();
|
244 |
$ret = $zip->open( $zipfile, ZipArchive::CREATE );
|
@@ -287,7 +330,7 @@ class autoptimizeCriticalCSSSettingsAjax {
|
|
287 |
// create tmp dir with hard guess name in AO_CCSS_DIR.
|
288 |
$_secret_dir = wp_hash( uniqid( md5( AUTOPTIMIZE_CACHE_URL ), true ) );
|
289 |
$_import_tmp_dir = trailingslashit( AO_CCSS_DIR . $_secret_dir );
|
290 |
-
mkdir( $_import_tmp_dir );
|
291 |
|
292 |
// Save file to that tmp directory but give it our own name to prevent directory traversal risks when using original name.
|
293 |
$zipfile = $_import_tmp_dir . uniqid( 'import_settings-', true ) . '.zip';
|
@@ -299,7 +342,7 @@ class autoptimizeCriticalCSSSettingsAjax {
|
|
299 |
// loop through all files in the zipfile.
|
300 |
for ($i = 0; $i < $zip->numFiles; $i++) {
|
301 |
// but only extract known good files.
|
302 |
-
if ( preg_match('/^settings\.json
|
303 |
$zip->extractTo( AO_CCSS_DIR, $zip->getNameIndex( $i ) );
|
304 |
}
|
305 |
}
|
@@ -307,7 +350,7 @@ class autoptimizeCriticalCSSSettingsAjax {
|
|
307 |
} else {
|
308 |
$error = 'could not extract';
|
309 |
}
|
310 |
-
|
311 |
// and remove temp. dir with all contents (the import-zipfile).
|
312 |
$this->rrmdir( $_import_tmp_dir );
|
313 |
|
@@ -320,15 +363,52 @@ class autoptimizeCriticalCSSSettingsAjax {
|
|
320 |
// Get settings and turn them into an object.
|
321 |
$settings = json_decode( file_get_contents( $importfile ), true );
|
322 |
|
323 |
-
// Update options.
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
332 |
} else {
|
333 |
// Settings file doesn't exist, update error flag.
|
334 |
$error = 'settings file does not exist';
|
@@ -353,7 +433,7 @@ class autoptimizeCriticalCSSSettingsAjax {
|
|
353 |
// Close ajax request.
|
354 |
wp_die();
|
355 |
}
|
356 |
-
|
357 |
public function ao_ccss_queuerunner_callback() {
|
358 |
check_ajax_referer( 'ao_ccss_queuerunner_nonce', 'ao_ccss_queuerunner_nonce' );
|
359 |
|
@@ -370,7 +450,7 @@ class autoptimizeCriticalCSSSettingsAjax {
|
|
370 |
}
|
371 |
} else {
|
372 |
$response['code'] = '500';
|
373 |
-
$response['msg'] = 'Not allowed';
|
374 |
}
|
375 |
|
376 |
// Dispatch respose.
|
@@ -443,7 +523,7 @@ class autoptimizeCriticalCSSSettingsAjax {
|
|
443 |
return true;
|
444 |
}
|
445 |
}
|
446 |
-
|
447 |
public function rrmdir( $path ) {
|
448 |
// recursively remove a directory as found on
|
449 |
// https://andy-carter.com/blog/recursively-remove-a-directory-in-php.
|
8 |
}
|
9 |
|
10 |
class autoptimizeCriticalCSSSettingsAjax {
|
11 |
+
public function __construct() {
|
12 |
+
$this->criticalcss = autoptimize()->criticalcss();
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
$this->run();
|
14 |
}
|
15 |
|
82 |
$critcsscontents = stripslashes( $_POST['critcsscontents'] );
|
83 |
|
84 |
// If there is content and it's valid, write the file.
|
85 |
+
if ( $critcsscontents && $this->criticalcss->check_contents( $critcsscontents ) ) {
|
86 |
// Set file path and status.
|
87 |
$critcssfile = AO_CCSS_DIR . strip_tags( $_POST['critcssfile'] );
|
88 |
$status = file_put_contents( $critcssfile, $critcsscontents, LOCK_EX );
|
209 |
}
|
210 |
|
211 |
// Init array, get options and prepare the raw object.
|
212 |
+
$settings = array();
|
213 |
+
|
214 |
+
// CCSS settings.
|
215 |
+
$settings['ccss']['rules'] = get_option( 'autoptimize_ccss_rules' );
|
216 |
+
$settings['ccss']['additional'] = get_option( 'autoptimize_ccss_additional' );
|
217 |
+
$settings['ccss']['viewport'] = get_option( 'autoptimize_ccss_viewport' );
|
218 |
+
$settings['ccss']['finclude'] = get_option( 'autoptimize_ccss_finclude' );
|
219 |
+
$settings['ccss']['rtimelimit'] = get_option( 'autoptimize_ccss_rtimelimit' );
|
220 |
+
$settings['ccss']['noptimize'] = get_option( 'autoptimize_ccss_noptimize' );
|
221 |
+
$settings['ccss']['debug'] = get_option( 'autoptimize_ccss_debug' );
|
222 |
+
$settings['ccss']['key'] = get_option( 'autoptimize_ccss_key' );
|
223 |
+
$settings['ccss']['deferjquery'] = get_option( 'autoptimize_ccss_deferjquery' );
|
224 |
+
$settings['ccss']['domain'] = get_option( 'autoptimize_ccss_domain' );
|
225 |
+
$settings['ccss']['forcepath'] = get_option( 'autoptimize_ccss_forcepath' );
|
226 |
+
$settings['ccss']['loggedin'] = get_option( 'autoptimize_ccss_loggedin' );
|
227 |
+
$settings['ccss']['rlimit'] = get_option( 'autoptimize_ccss_rlimit' );
|
228 |
+
$settings['ccss']['unloadccss'] = get_option( 'autoptimize_ccss_unloadccss' );
|
229 |
+
|
230 |
+
// JS settings.
|
231 |
+
$settings['js']['root'] = get_option( 'autoptimize_js' );
|
232 |
+
$settings['js']['aggregate'] = get_option( 'autoptimize_js_aggregate' );
|
233 |
+
$settings['js']['defer_not_aggregate'] = get_option( 'autoptimize_js_defer_not_aggregate' );
|
234 |
+
$settings['js']['defer_inline'] = get_option( 'autoptimize_js_defer_inline' );
|
235 |
+
$settings['js']['exclude'] = get_option( 'autoptimize_js_exclude' );
|
236 |
+
$settings['js']['forcehead'] = get_option( 'autoptimize_js_forcehead' );
|
237 |
+
$settings['js']['justhead'] = get_option( 'autoptimize_js_justhead' );
|
238 |
+
$settings['js']['trycatch'] = get_option( 'autoptimize_js_trycatch' );
|
239 |
+
$settings['js']['include_inline'] = get_option( 'autoptimize_js_include_inline');
|
240 |
+
|
241 |
+
// CSS settings.
|
242 |
+
$settings['css']['root'] = get_option( 'autoptimize_css' );
|
243 |
+
$settings['css']['aggregate'] = get_option( 'autoptimize_css_aggregate' );
|
244 |
+
$settings['css']['datauris'] = get_option( 'autoptimize_css_datauris' );
|
245 |
+
$settings['css']['justhead'] = get_option( 'autoptimize_css_justhead' );
|
246 |
+
$settings['css']['defer'] = get_option( 'autoptimize_css_defer' );
|
247 |
+
$settings['css']['defer_inline'] = get_option( 'autoptimize_css_defer_inline' );
|
248 |
+
$settings['css']['inline'] = get_option( 'autoptimize_css_inline' );
|
249 |
+
$settings['css']['exclude'] = get_option( 'autoptimize_css_exclude' );
|
250 |
+
$settings['css']['include_inline'] = get_option( 'autoptimize_css_include_inline' );
|
251 |
+
|
252 |
+
// Others.
|
253 |
+
$settings['other']['autoptimize_imgopt_settings'] = get_option( 'autoptimize_imgopt_settings' );
|
254 |
+
$settings['other']['autoptimize_extra_settings'] = get_option( 'autoptimize_extra_settings' );
|
255 |
+
$settings['other']['autoptimize_cache_fallback'] = get_option( 'autoptimize_cache_fallback' );
|
256 |
+
$settings['other']['autoptimize_cache_nogzip'] = get_option( 'autoptimize_cache_nogzip' );
|
257 |
+
$settings['other']['autoptimize_cdn_url'] = get_option( 'autoptimize_cdn_url' );
|
258 |
+
$settings['other']['autoptimize_enable_meta_ao_settings'] = get_option( 'autoptimize_enable_meta_ao_settings' );
|
259 |
+
$settings['other']['autoptimize_enable_site_config'] = get_option( 'autoptimize_enable_site_config' );
|
260 |
+
$settings['other']['autoptimize_html'] = get_option( 'autoptimize_html' );
|
261 |
+
$settings['other']['autoptimize_html_keepcomments'] = get_option( 'autoptimize_html_keepcomments' );
|
262 |
+
$settings['other']['autoptimize_minify_excluded'] = get_option( 'autoptimize_minify_excluded' );
|
263 |
+
$settings['other']['autoptimize_optimize_checkout'] = get_option( 'autoptimize_optimize_checkout' );
|
264 |
+
$settings['other']['autoptimize_optimize_logged'] = get_option( 'autoptimize_optimize_logged' );
|
265 |
+
|
266 |
+
if ( defined( 'AO_PRO_VERSION' ) ) {
|
267 |
+
$settings['pro']['boosters'] = get_option( 'autoptimize_pro_boosters' );
|
268 |
+
$settings['pro']['pagecache'] = get_option( 'autoptimize_pro_pagecache' );
|
269 |
+
}
|
270 |
|
271 |
// Initialize error flag.
|
272 |
$error = true;
|
281 |
}
|
282 |
|
283 |
// Prepare archive.
|
284 |
+
$zipfile = AO_CCSS_DIR . str_replace( array('.', '/'), '_', parse_url( AUTOPTIMIZE_WP_SITE_URL, PHP_URL_HOST ) ) . '_' . date( 'Ymd-H\hi' ) . '_ao_ccss_settings.zip';
|
285 |
$file = pathinfo( $zipfile, PATHINFO_BASENAME );
|
286 |
$zip = new ZipArchive();
|
287 |
$ret = $zip->open( $zipfile, ZipArchive::CREATE );
|
330 |
// create tmp dir with hard guess name in AO_CCSS_DIR.
|
331 |
$_secret_dir = wp_hash( uniqid( md5( AUTOPTIMIZE_CACHE_URL ), true ) );
|
332 |
$_import_tmp_dir = trailingslashit( AO_CCSS_DIR . $_secret_dir );
|
333 |
+
mkdir( $_import_tmp_dir, 0774, true );
|
334 |
|
335 |
// Save file to that tmp directory but give it our own name to prevent directory traversal risks when using original name.
|
336 |
$zipfile = $_import_tmp_dir . uniqid( 'import_settings-', true ) . '.zip';
|
342 |
// loop through all files in the zipfile.
|
343 |
for ($i = 0; $i < $zip->numFiles; $i++) {
|
344 |
// but only extract known good files.
|
345 |
+
if ( preg_match('/^settings\.json$|^\.\/ccss_[a-z0-9]{32}\.css$/', $zip->getNameIndex( $i ) ) > 0 ) {
|
346 |
$zip->extractTo( AO_CCSS_DIR, $zip->getNameIndex( $i ) );
|
347 |
}
|
348 |
}
|
350 |
} else {
|
351 |
$error = 'could not extract';
|
352 |
}
|
353 |
+
|
354 |
// and remove temp. dir with all contents (the import-zipfile).
|
355 |
$this->rrmdir( $_import_tmp_dir );
|
356 |
|
363 |
// Get settings and turn them into an object.
|
364 |
$settings = json_decode( file_get_contents( $importfile ), true );
|
365 |
|
366 |
+
// Update options from settings, but only for known options.
|
367 |
+
// CCSS.
|
368 |
+
foreach ( array( 'rules', 'additional', 'viewport', 'finclude', 'rtimelimit', 'noptimize', 'debug', 'key', 'deferjquery', 'domain', 'forcepath', 'loggedin', 'rlimit', 'unloadccss' ) as $ccss_setting ) {
|
369 |
+
if ( false === array_key_exists( 'ccss', $settings ) || false === array_key_exists( $ccss_setting, $settings['ccss'] ) ) {
|
370 |
+
continue;
|
371 |
+
} else {
|
372 |
+
update_option( 'autoptimize_ccss_' . $ccss_setting, $settings['ccss'][$ccss_setting] );
|
373 |
+
}
|
374 |
+
}
|
375 |
+
|
376 |
+
// JS.
|
377 |
+
foreach ( array( 'root', 'aggregate', 'defer_not_aggregate', 'defer_inline', 'exclude', 'forcehead', 'trycatch', 'include_inline' ) as $js_setting ) {
|
378 |
+
if ( false === array_key_exists( 'js', $settings ) || false === array_key_exists( $js_setting, $settings['js'] ) ) {
|
379 |
+
continue;
|
380 |
+
} else if ( 'root' === $js_setting ) {
|
381 |
+
update_option( 'autoptimize_js', $settings['js']['root'] );
|
382 |
+
} else {
|
383 |
+
update_option( 'autoptimize_js_' . $js_setting, $settings['js'][$js_setting] );
|
384 |
+
}
|
385 |
+
}
|
386 |
+
|
387 |
+
// CSS.
|
388 |
+
foreach ( array( 'root', 'aggregate', 'datauris', 'justhead', 'defer', 'defer_inline', 'inline', 'exclude', 'include_inline' ) as $css_setting ) {
|
389 |
+
if ( false === array_key_exists( 'css', $settings ) || false === array_key_exists( $css_setting, $settings['css'] ) ) {
|
390 |
+
continue;
|
391 |
+
} else if ( 'root' === $css_setting ) {
|
392 |
+
update_option( 'autoptimize_css', $settings['css']['root'] );
|
393 |
+
} else {
|
394 |
+
update_option( 'autoptimize_css_' . $css_setting, $settings['css'][$css_setting] );
|
395 |
+
}
|
396 |
+
}
|
397 |
+
|
398 |
+
// Other.
|
399 |
+
foreach ( array( 'autoptimize_imgopt_settings', 'autoptimize_extra_settings', 'autoptimize_cache_fallback', 'autoptimize_cache_nogzip', 'autoptimize_cdn_url', 'autoptimize_enable_meta_ao_settings', 'autoptimize_enable_site_config', 'autoptimize_html', 'autoptimize_html_keepcomments', 'autoptimize_minify_excluded', 'autoptimize_optimize_checkout', 'autoptimize_optimize_logged' ) as $other_setting ) {
|
400 |
+
if ( false === array_key_exists( 'other', $settings ) || false === array_key_exists( $other_setting, $settings['other'] ) ) {
|
401 |
+
continue;
|
402 |
+
} else {
|
403 |
+
update_option( $other_setting, $settings['other'][$other_setting] );
|
404 |
+
}
|
405 |
+
}
|
406 |
+
|
407 |
+
// AO Pro.
|
408 |
+
if ( defined( 'AO_PRO_VERSION' ) && array_key_exists( 'pro', $settings ) ) {
|
409 |
+
update_option( 'autoptimize_pro_boosters', $settings['pro']['boosters'] );
|
410 |
+
update_option( 'autoptimize_pro_pagecache', $settings['pro']['pagecache'] );
|
411 |
+
}
|
412 |
} else {
|
413 |
// Settings file doesn't exist, update error flag.
|
414 |
$error = 'settings file does not exist';
|
433 |
// Close ajax request.
|
434 |
wp_die();
|
435 |
}
|
436 |
+
|
437 |
public function ao_ccss_queuerunner_callback() {
|
438 |
check_ajax_referer( 'ao_ccss_queuerunner_nonce', 'ao_ccss_queuerunner_nonce' );
|
439 |
|
450 |
}
|
451 |
} else {
|
452 |
$response['code'] = '500';
|
453 |
+
$response['msg'] = 'Not allowed';
|
454 |
}
|
455 |
|
456 |
// Dispatch respose.
|
523 |
return true;
|
524 |
}
|
525 |
}
|
526 |
+
|
527 |
public function rrmdir( $path ) {
|
528 |
// recursively remove a directory as found on
|
529 |
// https://andy-carter.com/blog/recursively-remove-a-directory-in-php.
|
classes/autoptimizeExtra.php
CHANGED
@@ -117,6 +117,8 @@ class autoptimizeExtra
|
|
117 |
{
|
118 |
if ( strpos( $src, '?ver=' ) ) {
|
119 |
$src = remove_query_arg( 'ver', $src );
|
|
|
|
|
120 |
}
|
121 |
|
122 |
return $src;
|
@@ -184,9 +186,14 @@ class autoptimizeExtra
|
|
184 |
}
|
185 |
|
186 |
// Preload!
|
187 |
-
if ( ! empty( $options['autoptimize_extra_text_field_7'] ) || has_filter( 'autoptimize_filter_extra_tobepreloaded' ) ) {
|
188 |
add_filter( 'autoptimize_html_after_minify', array( $this, 'filter_preload' ), 10, 2 );
|
189 |
}
|
|
|
|
|
|
|
|
|
|
|
190 |
}
|
191 |
|
192 |
public function filter_remove_emoji_dns_prefetch( $urls, $relation_type )
|
@@ -402,6 +409,15 @@ class autoptimizeExtra
|
|
402 |
if ( array_key_exists( 'autoptimize_extra_text_field_7', $options ) ) {
|
403 |
$preloads = array_filter( array_map( 'trim', explode( ',', wp_strip_all_tags( $options['autoptimize_extra_text_field_7'] ) ) ) );
|
404 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
405 |
$preloads = apply_filters( 'autoptimize_filter_extra_tobepreloaded', $preloads );
|
406 |
|
407 |
// immediately return if nothing to be preloaded.
|
@@ -412,6 +428,9 @@ class autoptimizeExtra
|
|
412 |
// iterate through array and add preload link to tmp string.
|
413 |
$preload_output = '';
|
414 |
foreach ( $preloads as $preload ) {
|
|
|
|
|
|
|
415 |
$preload = esc_url_raw( $preload );
|
416 |
$crossorigin = '';
|
417 |
$preload_as = '';
|
@@ -439,11 +458,29 @@ class autoptimizeExtra
|
|
439 |
}
|
440 |
$preload_output = apply_filters( 'autoptimize_filter_extra_preload_output', $preload_output );
|
441 |
|
|
|
|
|
|
|
|
|
442 |
// add string to head (before first link node by default).
|
443 |
$preload_inject = apply_filters( 'autoptimize_filter_extra_preload_inject', '<link' );
|
444 |
-
$position = autoptimizeUtils::strpos( $
|
445 |
|
446 |
-
return autoptimizeUtils::substr_replace( $
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
447 |
}
|
448 |
|
449 |
public function admin_menu()
|
@@ -524,6 +561,12 @@ class autoptimizeExtra
|
|
524 |
<label><input type='checkbox' name='autoptimize_extra_settings[autoptimize_extra_checkbox_field_0]' <?php if ( ! empty( $options['autoptimize_extra_checkbox_field_0'] ) && '1' === $options['autoptimize_extra_checkbox_field_0'] ) { echo 'checked="checked"'; } ?> value='1'><?php _e( 'Removing query strings (or more specifically the <code>ver</code> parameter) will not improve load time, but might improve performance scores.', 'autoptimize' ); ?></label>
|
525 |
</td>
|
526 |
</tr>
|
|
|
|
|
|
|
|
|
|
|
|
|
527 |
<tr>
|
528 |
<th scope="row"><?php _e( 'Preconnect to 3rd party domains <em>(advanced users)</em>', 'autoptimize' ); ?></th>
|
529 |
<td>
|
117 |
{
|
118 |
if ( strpos( $src, '?ver=' ) ) {
|
119 |
$src = remove_query_arg( 'ver', $src );
|
120 |
+
} else if ( strpos( $src, '?v=' ) ) {
|
121 |
+
$src = remove_query_arg( 'v', $src );
|
122 |
}
|
123 |
|
124 |
return $src;
|
186 |
}
|
187 |
|
188 |
// Preload!
|
189 |
+
if ( ! empty( $options['autoptimize_extra_text_field_7'] ) || has_filter( 'autoptimize_filter_extra_tobepreloaded' ) || ! empty( autoptimizeConfig::get_post_meta_ao_settings( 'ao_post_preload' ) ) ) {
|
190 |
add_filter( 'autoptimize_html_after_minify', array( $this, 'filter_preload' ), 10, 2 );
|
191 |
}
|
192 |
+
|
193 |
+
// Remove global styles.
|
194 |
+
if ( ! empty( $options['autoptimize_extra_checkbox_field_8'] ) ) {
|
195 |
+
$this->disable_global_styles();
|
196 |
+
}
|
197 |
}
|
198 |
|
199 |
public function filter_remove_emoji_dns_prefetch( $urls, $relation_type )
|
409 |
if ( array_key_exists( 'autoptimize_extra_text_field_7', $options ) ) {
|
410 |
$preloads = array_filter( array_map( 'trim', explode( ',', wp_strip_all_tags( $options['autoptimize_extra_text_field_7'] ) ) ) );
|
411 |
}
|
412 |
+
|
413 |
+
if ( false === autoptimizeImages::imgopt_active() && false === autoptimizeImages::should_lazyload_wrapper() ) {
|
414 |
+
// only do this here if imgopt/ lazyload are not active?
|
415 |
+
$metabox_preloads = array_filter( array_map( 'trim', explode( ',', wp_strip_all_tags( autoptimizeConfig::get_post_meta_ao_settings( 'ao_post_preload' ) ) ) ) );
|
416 |
+
if ( ! empty( $metabox_preloads ) ) {
|
417 |
+
$preloads = array_merge( $preloads, $metabox_preloads );
|
418 |
+
}
|
419 |
+
}
|
420 |
+
|
421 |
$preloads = apply_filters( 'autoptimize_filter_extra_tobepreloaded', $preloads );
|
422 |
|
423 |
// immediately return if nothing to be preloaded.
|
428 |
// iterate through array and add preload link to tmp string.
|
429 |
$preload_output = '';
|
430 |
foreach ( $preloads as $preload ) {
|
431 |
+
if ( $preload !== filter_var( $preload, FILTER_VALIDATE_URL ) ) {
|
432 |
+
continue;
|
433 |
+
}
|
434 |
$preload = esc_url_raw( $preload );
|
435 |
$crossorigin = '';
|
436 |
$preload_as = '';
|
458 |
}
|
459 |
$preload_output = apply_filters( 'autoptimize_filter_extra_preload_output', $preload_output );
|
460 |
|
461 |
+
return $this->inject_preloads( $preload_output, $in );
|
462 |
+
}
|
463 |
+
|
464 |
+
public static function inject_preloads( $preloads, $html ) {
|
465 |
// add string to head (before first link node by default).
|
466 |
$preload_inject = apply_filters( 'autoptimize_filter_extra_preload_inject', '<link' );
|
467 |
+
$position = autoptimizeUtils::strpos( $html, $preload_inject );
|
468 |
|
469 |
+
return autoptimizeUtils::substr_replace( $html, $preloads . $preload_inject, $position, strlen( $preload_inject ) );
|
470 |
+
}
|
471 |
+
|
472 |
+
public function disable_global_styles()
|
473 |
+
{
|
474 |
+
remove_action( 'wp_enqueue_scripts', 'wp_enqueue_global_styles' );
|
475 |
+
remove_action( 'wp_footer', 'wp_enqueue_global_styles', 1 );
|
476 |
+
remove_action( 'wp_body_open', 'wp_global_styles_render_svg_filters' );
|
477 |
+
|
478 |
+
if ( true === apply_filters( 'autoptimize_filter_extra_global_styles_and_block_css', true ) ) {
|
479 |
+
add_action( 'wp_enqueue_scripts', function(){
|
480 |
+
wp_dequeue_style( 'wp-block-library' );
|
481 |
+
wp_dequeue_style( 'wp-block-library-theme' );
|
482 |
+
});
|
483 |
+
}
|
484 |
}
|
485 |
|
486 |
public function admin_menu()
|
561 |
<label><input type='checkbox' name='autoptimize_extra_settings[autoptimize_extra_checkbox_field_0]' <?php if ( ! empty( $options['autoptimize_extra_checkbox_field_0'] ) && '1' === $options['autoptimize_extra_checkbox_field_0'] ) { echo 'checked="checked"'; } ?> value='1'><?php _e( 'Removing query strings (or more specifically the <code>ver</code> parameter) will not improve load time, but might improve performance scores.', 'autoptimize' ); ?></label>
|
562 |
</td>
|
563 |
</tr>
|
564 |
+
<tr>
|
565 |
+
<th scope="row"><?php _e( 'Remove WordPress block CSS', 'autoptimize' ); ?></th>
|
566 |
+
<td>
|
567 |
+
<label><input type='checkbox' name='autoptimize_extra_settings[autoptimize_extra_checkbox_field_8]' <?php if ( ! empty( $options['autoptimize_extra_checkbox_field_8'] ) && '1' === $options['autoptimize_extra_checkbox_field_8'] ) { echo 'checked="checked"'; } ?> value='1'><?php _e( 'WordPress adds block CSS and global styles to improve easy styling of block-based sites, but which can add a significant amount of CSS and SVG. If you are sure your site can do without the block CSS and "global styles", you can disable them here.', 'autoptimize' ); ?></label>
|
568 |
+
</td>
|
569 |
+
</tr>
|
570 |
<tr>
|
571 |
<th scope="row"><?php _e( 'Preconnect to 3rd party domains <em>(advanced users)</em>', 'autoptimize' ); ?></th>
|
572 |
<td>
|
classes/autoptimizeHTML.php
CHANGED
@@ -82,10 +82,14 @@ class autoptimizeHTML extends autoptimizeBase
|
|
82 |
$options['xhtml'] = true;
|
83 |
}
|
84 |
|
85 |
-
// Optionally
|
86 |
-
if ( apply_filters( 'autoptimize_html_minify_inline_js_css',
|
87 |
-
|
88 |
-
|
|
|
|
|
|
|
|
|
89 |
}
|
90 |
|
91 |
$tmp_content = AO_Minify_HTML::minify( $this->content, $options );
|
82 |
$options['xhtml'] = true;
|
83 |
}
|
84 |
|
85 |
+
// Optionally minify inline JS & CSS.
|
86 |
+
if ( apply_filters( 'autoptimize_html_minify_inline_js_css', true ) && false === $this->keepcomments ) {
|
87 |
+
if ( false != autoptimizeOptionWrapper::get_option( 'autoptimize_js' ) && false != autoptimizeConfig::get_post_meta_ao_settings( 'ao_post_js_optimize' ) && true !== apply_filters( 'autoptimize_filter_js_noptimize', false, $this->content ) ) {
|
88 |
+
$options['jsMinifier'] = 'JSMin::minify';
|
89 |
+
}
|
90 |
+
if ( false != autoptimizeOptionWrapper::get_option( 'autoptimize_css' ) && false != autoptimizeConfig::get_post_meta_ao_settings( 'ao_post_css_optimize' ) && true !== apply_filters( 'autoptimize_filter_css_noptimize', false, $this->content ) ) {
|
91 |
+
$options['cssMinifier'] = 'autoptimizeCSSmin::minify';
|
92 |
+
}
|
93 |
}
|
94 |
|
95 |
$tmp_content = AO_Minify_HTML::minify( $this->content, $options );
|
classes/autoptimizeImages.php
CHANGED
@@ -562,6 +562,7 @@ class autoptimizeImages
|
|
562 |
* filter for critical CSS.
|
563 |
*/
|
564 |
$to_replace = array();
|
|
|
565 |
|
566 |
// hide noscript tags to avoid nesting noscript tags (as lazyloaded images add noscript).
|
567 |
if ( $this->should_lazyload() ) {
|
@@ -573,6 +574,9 @@ class autoptimizeImages
|
|
573 |
);
|
574 |
}
|
575 |
|
|
|
|
|
|
|
576 |
// extract img tags.
|
577 |
if ( preg_match_all( '#<img[^>]*src[^>]*>#Usmi', $in, $matches ) ) {
|
578 |
foreach ( $matches[0] as $tag ) {
|
@@ -649,6 +653,11 @@ class autoptimizeImages
|
|
649 |
// then call add_lazyload-function with lpiq placeholder if set.
|
650 |
$tag = $this->add_lazyload( $tag, $placeholder );
|
651 |
}
|
|
|
|
|
|
|
|
|
|
|
652 |
|
653 |
$tag = apply_filters( 'autoptimize_filter_imgopt_tag_postopt' , $tag );
|
654 |
|
@@ -656,6 +665,11 @@ class autoptimizeImages
|
|
656 |
if ( $tag !== $orig_tag ) {
|
657 |
$to_replace[ $orig_tag ] = $tag;
|
658 |
}
|
|
|
|
|
|
|
|
|
|
|
659 |
}
|
660 |
}
|
661 |
|
@@ -702,6 +716,17 @@ class autoptimizeImages
|
|
702 |
$out = $this->process_picture_tag( $out, true, false );
|
703 |
}
|
704 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
705 |
return $out;
|
706 |
}
|
707 |
|
@@ -726,13 +751,17 @@ class autoptimizeImages
|
|
726 |
$_max_width = apply_filters( 'autoptimize_filter_imgopt_max_width', 4999 );
|
727 |
if ( $width > $_max_width ) {
|
728 |
$_width = $_max_width;
|
729 |
-
$height
|
|
|
|
|
730 |
$width = $_width;
|
731 |
}
|
732 |
$_max_height = apply_filters( 'autoptimize_filter_imgopt_max_height', 4999 );
|
733 |
if ( $height > $_max_height ) {
|
734 |
$_height = $_max_height;
|
735 |
-
$width
|
|
|
|
|
736 |
$height = $_height;
|
737 |
}
|
738 |
|
@@ -780,6 +809,7 @@ class autoptimizeImages
|
|
780 |
{
|
781 |
// only used is image optimization is NOT active but lazyload is.
|
782 |
$to_replace = array();
|
|
|
783 |
|
784 |
// hide (no)script tags to avoid nesting noscript tags (as lazyloaded images add noscript).
|
785 |
$out = autoptimizeBase::replace_contents_with_marker_if_exists(
|
@@ -789,12 +819,20 @@ class autoptimizeImages
|
|
789 |
$in
|
790 |
);
|
791 |
|
792 |
-
//
|
|
|
|
|
|
|
793 |
if ( preg_match_all( '#<img[^>]*src[^>]*>#Usmi', $out, $matches ) ) {
|
794 |
foreach ( $matches[0] as $tag ) {
|
795 |
if ( $this->should_lazyload( $out ) ) {
|
796 |
$to_replace[ $tag ] = $this->add_lazyload( $tag );
|
797 |
}
|
|
|
|
|
|
|
|
|
|
|
798 |
}
|
799 |
$out = str_replace( array_keys( $to_replace ), array_values( $to_replace ), $out );
|
800 |
}
|
@@ -811,6 +849,17 @@ class autoptimizeImages
|
|
811 |
$out
|
812 |
);
|
813 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
814 |
return $out;
|
815 |
}
|
816 |
|
@@ -879,7 +928,14 @@ class autoptimizeImages
|
|
879 |
$noptimize_flag = ' data-noptimize="1"';
|
880 |
}
|
881 |
|
882 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
883 |
$cdn_url = $this->get_cdn_url();
|
884 |
if ( ! empty( $cdn_url ) ) {
|
885 |
$cdn_url = rtrim( $cdn_url, '/' );
|
@@ -896,6 +952,22 @@ class autoptimizeImages
|
|
896 |
echo apply_filters( 'autoptimize_filter_imgopt_lazyload_jsconfig', '<script' . $type_js . $noptimize_flag . '>window.lazySizesConfig=window.lazySizesConfig||{};window.lazySizesConfig.loadMode=1;</script>' );
|
897 |
echo apply_filters( 'autoptimize_filter_imgopt_lazyload_js', '<script async' . $type_js . $noptimize_flag . ' src=\'' . $lazysizes_js . '\'></script>' );
|
898 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
899 |
|
900 |
public static function get_cdn_url() {
|
901 |
// getting CDN url here to avoid having to make bigger changes to autoptimizeBase.
|
@@ -1204,7 +1276,7 @@ class autoptimizeImages
|
|
1204 |
<tr id='autoptimize_imgopt_ngimg' <?php if ( ! array_key_exists( 'autoptimize_imgopt_checkbox_field_1', $options ) || ( isset( $options['autoptimize_imgopt_checkbox_field_1'] ) && '1' !== $options['autoptimize_imgopt_checkbox_field_1'] ) ) { echo 'class="hidden"'; } ?>>
|
1205 |
<th scope="row"><?php _e( 'Load AVIF in supported browsers?', 'autoptimize' ); ?></th>
|
1206 |
<td>
|
1207 |
-
<label><input type='checkbox' id='autoptimize_imgopt_ngimg_checkbox' name='autoptimize_imgopt_settings[autoptimize_imgopt_checkbox_field_4]' <?php if ( ! empty( $options['autoptimize_imgopt_checkbox_field_4'] ) && '1' === $options['
|
1208 |
</td>
|
1209 |
</tr>
|
1210 |
<tr>
|
562 |
* filter for critical CSS.
|
563 |
*/
|
564 |
$to_replace = array();
|
565 |
+
$to_preload = '';
|
566 |
|
567 |
// hide noscript tags to avoid nesting noscript tags (as lazyloaded images add noscript).
|
568 |
if ( $this->should_lazyload() ) {
|
574 |
);
|
575 |
}
|
576 |
|
577 |
+
// get img preloads as set in post metabox.
|
578 |
+
$metabox_preloads = array_filter( array_map( 'trim', explode( ',', wp_strip_all_tags( autoptimizeConfig::get_post_meta_ao_settings( 'ao_post_preload' ) ) ) ) );
|
579 |
+
|
580 |
// extract img tags.
|
581 |
if ( preg_match_all( '#<img[^>]*src[^>]*>#Usmi', $in, $matches ) ) {
|
582 |
foreach ( $matches[0] as $tag ) {
|
653 |
// then call add_lazyload-function with lpiq placeholder if set.
|
654 |
$tag = $this->add_lazyload( $tag, $placeholder );
|
655 |
}
|
656 |
+
|
657 |
+
// add decoding="async" behind filter, not sure if I'll make it default true yet.
|
658 |
+
if ( true === apply_filters( 'autoptimize_filter_imgopt_add_decoding', true ) && false === strpos( $tag, ' decoding=' ) ) {
|
659 |
+
$tag = str_replace( '<img ', '<img decoding="async" ', $tag );
|
660 |
+
}
|
661 |
|
662 |
$tag = apply_filters( 'autoptimize_filter_imgopt_tag_postopt' , $tag );
|
663 |
|
665 |
if ( $tag !== $orig_tag ) {
|
666 |
$to_replace[ $orig_tag ] = $tag;
|
667 |
}
|
668 |
+
|
669 |
+
// and check if image needs to be prelaoded.
|
670 |
+
if ( ! empty( $metabox_preloads ) && str_replace( $metabox_preloads, '', $tag ) !== $tag ) {
|
671 |
+
$to_preload .= $this->create_img_preload_tag( $tag );
|
672 |
+
}
|
673 |
}
|
674 |
}
|
675 |
|
716 |
$out = $this->process_picture_tag( $out, true, false );
|
717 |
}
|
718 |
|
719 |
+
if ( ! empty( $metabox_preloads ) && empty( $to_preload ) ) {
|
720 |
+
// the preload was not in an img tag, so adding a non-responsive preload instead.
|
721 |
+
foreach( $metabox_preloads as $img_preload ) {
|
722 |
+
$to_preload .= '<link rel="preload" href="' . $img_preload . '" as="image">' ;
|
723 |
+
}
|
724 |
+
}
|
725 |
+
|
726 |
+
if ( ! empty( $to_preload ) ) {
|
727 |
+
$out = autoptimizeExtra::inject_preloads( $to_preload, $out );
|
728 |
+
}
|
729 |
+
|
730 |
return $out;
|
731 |
}
|
732 |
|
751 |
$_max_width = apply_filters( 'autoptimize_filter_imgopt_max_width', 4999 );
|
752 |
if ( $width > $_max_width ) {
|
753 |
$_width = $_max_width;
|
754 |
+
if ( ! empty( $height ) && is_int( $height ) ) {
|
755 |
+
$height = $_width / $width * $height;
|
756 |
+
}
|
757 |
$width = $_width;
|
758 |
}
|
759 |
$_max_height = apply_filters( 'autoptimize_filter_imgopt_max_height', 4999 );
|
760 |
if ( $height > $_max_height ) {
|
761 |
$_height = $_max_height;
|
762 |
+
if ( ! empty( $width ) && is_int( $width ) ) {
|
763 |
+
$width = $_height / $height * $width;
|
764 |
+
}
|
765 |
$height = $_height;
|
766 |
}
|
767 |
|
809 |
{
|
810 |
// only used is image optimization is NOT active but lazyload is.
|
811 |
$to_replace = array();
|
812 |
+
$to_preload = '';
|
813 |
|
814 |
// hide (no)script tags to avoid nesting noscript tags (as lazyloaded images add noscript).
|
815 |
$out = autoptimizeBase::replace_contents_with_marker_if_exists(
|
819 |
$in
|
820 |
);
|
821 |
|
822 |
+
// get img preloads as set in post metabox.
|
823 |
+
$metabox_preloads = array_filter( array_map( 'trim', explode( ',', wp_strip_all_tags( autoptimizeConfig::get_post_meta_ao_settings( 'ao_post_preload' ) ) ) ) );
|
824 |
+
|
825 |
+
// extract img tags and add lazyload attribs/ add preloads.
|
826 |
if ( preg_match_all( '#<img[^>]*src[^>]*>#Usmi', $out, $matches ) ) {
|
827 |
foreach ( $matches[0] as $tag ) {
|
828 |
if ( $this->should_lazyload( $out ) ) {
|
829 |
$to_replace[ $tag ] = $this->add_lazyload( $tag );
|
830 |
}
|
831 |
+
|
832 |
+
// and check if image needs to be prelaoded.
|
833 |
+
if ( ! empty( $metabox_preloads ) && str_replace( $metabox_preloads, '', $tag ) !== $tag ) {
|
834 |
+
$to_preload .= $this->create_img_preload_tag( $tag );
|
835 |
+
}
|
836 |
}
|
837 |
$out = str_replace( array_keys( $to_replace ), array_values( $to_replace ), $out );
|
838 |
}
|
849 |
$out
|
850 |
);
|
851 |
|
852 |
+
if ( ! empty( $metabox_preloads ) && empty( $to_preload ) ) {
|
853 |
+
// the preload was not in an img tag, so adding a non-responsive preload instead.
|
854 |
+
foreach( $metabox_preloads as $img_preload ) {
|
855 |
+
$to_preload .= '<link rel="preload" href="' . $img_preload . '" as="image">' ;
|
856 |
+
}
|
857 |
+
}
|
858 |
+
|
859 |
+
if ( ! empty( $to_preload ) ) {
|
860 |
+
$out = autoptimizeExtra::inject_preloads( $to_preload, $out );
|
861 |
+
}
|
862 |
+
|
863 |
return $out;
|
864 |
}
|
865 |
|
928 |
$noptimize_flag = ' data-noptimize="1"';
|
929 |
}
|
930 |
|
931 |
+
$_extra = autoptimizeOptionWrapper::get_option( 'autoptimize_extra_settings', '' );
|
932 |
+
if ( is_array( $_extra ) && array_key_exists( 'autoptimize_extra_checkbox_field_0', $_extra ) && ! empty( $_extra['autoptimize_extra_checkbox_field_0'] ) ) {
|
933 |
+
// if "remove query strings" is active in "extra", then let's be consistant and not add one ourselves? :)
|
934 |
+
$lazysizes_js = plugins_url( 'external/js/lazysizes.min.js', __FILE__ );
|
935 |
+
} else {
|
936 |
+
$lazysizes_js = plugins_url( 'external/js/lazysizes.min.js?ao_version=' . AUTOPTIMIZE_PLUGIN_VERSION, __FILE__ );
|
937 |
+
}
|
938 |
+
|
939 |
$cdn_url = $this->get_cdn_url();
|
940 |
if ( ! empty( $cdn_url ) ) {
|
941 |
$cdn_url = rtrim( $cdn_url, '/' );
|
952 |
echo apply_filters( 'autoptimize_filter_imgopt_lazyload_jsconfig', '<script' . $type_js . $noptimize_flag . '>window.lazySizesConfig=window.lazySizesConfig||{};window.lazySizesConfig.loadMode=1;</script>' );
|
953 |
echo apply_filters( 'autoptimize_filter_imgopt_lazyload_js', '<script async' . $type_js . $noptimize_flag . ' src=\'' . $lazysizes_js . '\'></script>' );
|
954 |
}
|
955 |
+
|
956 |
+
public static function create_img_preload_tag( $tag ) {
|
957 |
+
// rewrite img tag to link preload img.
|
958 |
+
$_from = array( '<img ', ' src=', ' sizes=', ' srcset=' );
|
959 |
+
$_to = array( '<link rel="preload" as="image" ', ' href=', ' imagesizes=', ' imagesrcset=' );
|
960 |
+
$tag = str_replace( $_from, $_to, $tag );
|
961 |
+
|
962 |
+
// and remove title, alt, class and id.
|
963 |
+
$tag = preg_replace( '/ ((?:title|alt|class|id|loading)=".*")/Um', '', $tag );
|
964 |
+
if ( $tag !== str_replace( array(' title=', ' class=', ' alt=', ' id=' ), '', $tag ) ) {
|
965 |
+
// 2nd regex pass if still title/ class/ alt in case single quotes were used iso doubles.
|
966 |
+
$tag = preg_replace( '/ ((?:title|alt|class|id|loading)=\'.*\')/Um', '', $tag );
|
967 |
+
}
|
968 |
+
|
969 |
+
return $tag;
|
970 |
+
}
|
971 |
|
972 |
public static function get_cdn_url() {
|
973 |
// getting CDN url here to avoid having to make bigger changes to autoptimizeBase.
|
1276 |
<tr id='autoptimize_imgopt_ngimg' <?php if ( ! array_key_exists( 'autoptimize_imgopt_checkbox_field_1', $options ) || ( isset( $options['autoptimize_imgopt_checkbox_field_1'] ) && '1' !== $options['autoptimize_imgopt_checkbox_field_1'] ) ) { echo 'class="hidden"'; } ?>>
|
1277 |
<th scope="row"><?php _e( 'Load AVIF in supported browsers?', 'autoptimize' ); ?></th>
|
1278 |
<td>
|
1279 |
+
<label><input type='checkbox' id='autoptimize_imgopt_ngimg_checkbox' name='autoptimize_imgopt_settings[autoptimize_imgopt_checkbox_field_4]' <?php if ( ! empty( $options['autoptimize_imgopt_checkbox_field_4'] ) && '1' === $options['autoptimize_imgopt_checkbox_field_4'] ) { echo 'checked="checked"'; } ?> value='1'><?php _e( 'Automatically serve AVIF image format to any browser that supports it.', 'autoptimize' ); ?></label>
|
1280 |
</td>
|
1281 |
</tr>
|
1282 |
<tr>
|
classes/autoptimizeMain.php
CHANGED
@@ -27,6 +27,13 @@ class autoptimizeMain
|
|
27 |
*/
|
28 |
protected $filepath = null;
|
29 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
/**
|
31 |
* Constructor.
|
32 |
*
|
@@ -59,6 +66,7 @@ class autoptimizeMain
|
|
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_admin_only_trinkets' ), 20 );
|
64 |
add_action( 'autoptimize_setup_done', array( $this, 'maybe_run_criticalcss' ), 11 );
|
@@ -218,11 +226,18 @@ class autoptimizeMain
|
|
218 |
}
|
219 |
}
|
220 |
|
|
|
|
|
|
|
|
|
|
|
221 |
public function maybe_run_criticalcss()
|
222 |
{
|
223 |
// Loads criticalcss if the power-up is not active and if the filter returns true.
|
224 |
if ( apply_filters( 'autoptimize_filter_criticalcss_active', true ) && ! autoptimizeUtils::is_plugin_active( 'autoptimize-criticalcss/ao_criticss_aas.php' ) ) {
|
225 |
-
new autoptimizeCriticalCSSBase();
|
|
|
|
|
226 |
}
|
227 |
}
|
228 |
|
@@ -233,6 +248,23 @@ class autoptimizeMain
|
|
233 |
}
|
234 |
}
|
235 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
236 |
public function hook_page_cache_purge()
|
237 |
{
|
238 |
// hook into a collection of page cache purge actions if filter allows.
|
@@ -356,7 +388,7 @@ class autoptimizeMain
|
|
356 |
|
357 |
// And make sure pagebuilder previews don't get optimized HTML/ JS/ CSS/ ...
|
358 |
if ( false === $ao_noptimize ) {
|
359 |
-
$_qs_pagebuilders = array( 'tve', 'elementor-preview', 'fl_builder', 'vc_action', 'et_fb', 'bt-beaverbuildertheme', 'ct_builder', 'fb-edit', 'siteorigin_panels_live_editor' );
|
360 |
foreach ( $_qs_pagebuilders as $_pagebuilder ) {
|
361 |
if ( array_key_exists( $_pagebuilder, $_GET ) ) {
|
362 |
$ao_noptimize = true;
|
@@ -559,8 +591,15 @@ class autoptimizeMain
|
|
559 |
|
560 |
public static function on_uninstall()
|
561 |
{
|
|
|
562 |
autoptimizeCache::clearall();
|
563 |
|
|
|
|
|
|
|
|
|
|
|
|
|
564 |
$delete_options = array(
|
565 |
'autoptimize_cache_clean',
|
566 |
'autoptimize_cache_nogzip',
|
@@ -616,6 +655,7 @@ class autoptimizeMain
|
|
616 |
'autoptimize_ccss_deferjquery',
|
617 |
'autoptimize_ccss_domain',
|
618 |
'autoptimize_ccss_unloadccss',
|
|
|
619 |
);
|
620 |
|
621 |
if ( ! is_multisite() ) {
|
@@ -671,7 +711,7 @@ class autoptimizeMain
|
|
671 |
|
672 |
public static function remove_cronjobs() {
|
673 |
// Remove scheduled events.
|
674 |
-
foreach ( array( 'ao_cachechecker', 'ao_ccss_queue', 'ao_ccss_maintenance' ) as $_event ) {
|
675 |
if ( wp_get_schedule( $_event ) ) {
|
676 |
wp_clear_scheduled_hook( $_event );
|
677 |
}
|
27 |
*/
|
28 |
protected $filepath = null;
|
29 |
|
30 |
+
/**
|
31 |
+
* Critical CSS base object
|
32 |
+
*
|
33 |
+
* @var object
|
34 |
+
*/
|
35 |
+
protected $_criticalcss = null;
|
36 |
+
|
37 |
/**
|
38 |
* Constructor.
|
39 |
*
|
66 |
|
67 |
add_action( 'autoptimize_setup_done', array( $this, 'version_upgrades_check' ) );
|
68 |
add_action( 'autoptimize_setup_done', array( $this, 'check_cache_and_run' ) );
|
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 );
|
226 |
}
|
227 |
}
|
228 |
|
229 |
+
public function criticalcss()
|
230 |
+
{
|
231 |
+
return $this->_criticalcss;
|
232 |
+
}
|
233 |
+
|
234 |
public function maybe_run_criticalcss()
|
235 |
{
|
236 |
// Loads criticalcss if the power-up is not active and if the filter returns true.
|
237 |
if ( apply_filters( 'autoptimize_filter_criticalcss_active', true ) && ! autoptimizeUtils::is_plugin_active( 'autoptimize-criticalcss/ao_criticss_aas.php' ) ) {
|
238 |
+
$this->_criticalcss = new autoptimizeCriticalCSSBase();
|
239 |
+
$this->_criticalcss->setup();
|
240 |
+
$this->_criticalcss->load_requires();
|
241 |
}
|
242 |
}
|
243 |
|
248 |
}
|
249 |
}
|
250 |
|
251 |
+
public function maybe_run_ao_compat()
|
252 |
+
{
|
253 |
+
// Condtionally loads the compatibility-class to ensure more out-of-the-box compatibility with big players.
|
254 |
+
$_run_compat = true;
|
255 |
+
|
256 |
+
if ( autoptimizeOptionWrapper::get_option( 'autoptimize_installed_before_compatibility', false ) ) {
|
257 |
+
// If AO was already running before Compatibility logic was added, don't run compat by default
|
258 |
+
// because it can be assumed everything works and we want to avoid (perf) regressions that
|
259 |
+
// could occur due to compatibility code.
|
260 |
+
$_run_compat = false;
|
261 |
+
}
|
262 |
+
|
263 |
+
if ( apply_filters( 'autoptimize_filter_init_compatibility', $_run_compat ) ) {
|
264 |
+
new autoptimizeCompatibility();
|
265 |
+
}
|
266 |
+
}
|
267 |
+
|
268 |
public function hook_page_cache_purge()
|
269 |
{
|
270 |
// hook into a collection of page cache purge actions if filter allows.
|
388 |
|
389 |
// And make sure pagebuilder previews don't get optimized HTML/ JS/ CSS/ ...
|
390 |
if ( false === $ao_noptimize ) {
|
391 |
+
$_qs_pagebuilders = array( 'tve', 'elementor-preview', 'fl_builder', 'vc_action', 'et_fb', 'bt-beaverbuildertheme', 'ct_builder', 'fb-edit', 'siteorigin_panels_live_editor', 'preview' );
|
392 |
foreach ( $_qs_pagebuilders as $_pagebuilder ) {
|
393 |
if ( array_key_exists( $_pagebuilder, $_GET ) ) {
|
394 |
$ao_noptimize = true;
|
591 |
|
592 |
public static function on_uninstall()
|
593 |
{
|
594 |
+
// clear the cache.
|
595 |
autoptimizeCache::clearall();
|
596 |
|
597 |
+
// remove postmeta if active.
|
598 |
+
if ( autoptimizeConfig::is_ao_meta_settings_active() ) {
|
599 |
+
delete_post_meta_by_key( 'ao_post_optimize' );
|
600 |
+
}
|
601 |
+
|
602 |
+
// remove all options.
|
603 |
$delete_options = array(
|
604 |
'autoptimize_cache_clean',
|
605 |
'autoptimize_cache_nogzip',
|
655 |
'autoptimize_ccss_deferjquery',
|
656 |
'autoptimize_ccss_domain',
|
657 |
'autoptimize_ccss_unloadccss',
|
658 |
+
'autoptimize_installed_before_compatibility',
|
659 |
);
|
660 |
|
661 |
if ( ! is_multisite() ) {
|
711 |
|
712 |
public static function remove_cronjobs() {
|
713 |
// Remove scheduled events.
|
714 |
+
foreach ( array( 'ao_cachechecker', 'ao_ccss_queue', 'ao_ccss_maintenance', 'ao_ccss_keychecker' ) as $_event ) {
|
715 |
if ( wp_get_schedule( $_event ) ) {
|
716 |
wp_clear_scheduled_hook( $_event );
|
717 |
}
|
classes/autoptimizeMetabox.php
CHANGED
@@ -23,7 +23,7 @@ class autoptimizeMetabox
|
|
23 |
|
24 |
public function ao_metabox_add_box()
|
25 |
{
|
26 |
-
$screens = array(
|
27 |
'post',
|
28 |
'page',
|
29 |
// add extra types e.g. product or ... ?
|
@@ -42,7 +42,7 @@ class autoptimizeMetabox
|
|
42 |
|
43 |
/**
|
44 |
* Prints the box content.
|
45 |
-
*
|
46 |
* @param WP_Post $post The object for the current post/page.
|
47 |
*/
|
48 |
function ao_metabox_content( $post )
|
@@ -50,7 +50,7 @@ class autoptimizeMetabox
|
|
50 |
wp_nonce_field( 'ao_metabox', 'ao_metabox_nonce' );
|
51 |
|
52 |
$ao_opt_value = $this->check_ao_opt_sanity( get_post_meta( $post->ID, 'ao_post_optimize', true ) );
|
53 |
-
|
54 |
$_ao_meta_sub_opacity = '';
|
55 |
if ( 'on' !== $ao_opt_value['ao_post_optimize'] ) {
|
56 |
$_ao_meta_sub_opacity = 'opacity:.33;';
|
@@ -62,9 +62,9 @@ class autoptimizeMetabox
|
|
62 |
<?php _e( 'Optimize this page?', 'autoptimize' ); ?>
|
63 |
</label>
|
64 |
</p>
|
65 |
-
<?php
|
66 |
$_ao_meta_js_style = '';
|
67 |
-
if ( 'on' !== get_option( 'autoptimize_js', false ) ) {
|
68 |
$_ao_meta_js_style = 'display:none;';
|
69 |
}
|
70 |
echo '<p class="ao_meta_sub" style="' . $_ao_meta_sub_opacity . $_ao_meta_js_style . '">';
|
@@ -74,9 +74,9 @@ class autoptimizeMetabox
|
|
74 |
<?php _e( 'Optimize JS?', 'autoptimize' ); ?>
|
75 |
</label>
|
76 |
</p>
|
77 |
-
<?php
|
78 |
$_ao_meta_css_style = '';
|
79 |
-
if ( 'on' !== get_option( 'autoptimize_css', false ) ) {
|
80 |
$_ao_meta_css_style = 'display:none;';
|
81 |
}
|
82 |
echo '<p class="ao_meta_sub" style="' . $_ao_meta_sub_opacity . $_ao_meta_css_style . '">';
|
@@ -86,9 +86,9 @@ class autoptimizeMetabox
|
|
86 |
<?php _e( 'Optimize CSS?', 'autoptimize' ); ?>
|
87 |
</label>
|
88 |
</p>
|
89 |
-
<?php
|
90 |
$_ao_meta_ccss_style = '';
|
91 |
-
if ( 'on' !== get_option( 'autoptimize_css_defer', false ) ) {
|
92 |
$_ao_meta_ccss_style = 'display:none;';
|
93 |
}
|
94 |
if ( 'on' !== $ao_opt_value['ao_post_css_optimize'] ) {
|
@@ -101,7 +101,7 @@ class autoptimizeMetabox
|
|
101 |
<?php _e( 'Inline critical CSS?', 'autoptimize' ); ?>
|
102 |
</label>
|
103 |
</p>
|
104 |
-
<?php
|
105 |
$_ao_meta_lazyload_style = '';
|
106 |
if ( false === autoptimizeImages::should_lazyload_wrapper() ) {
|
107 |
$_ao_meta_lazyload_style = 'display:none;';
|
@@ -113,6 +113,13 @@ class autoptimizeMetabox
|
|
113 |
<?php _e( 'Lazyload images?', 'autoptimize' ); ?>
|
114 |
</label>
|
115 |
</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
116 |
<p>
|
117 |
<?php
|
118 |
// Get path + check if button should be enabled or disabled.
|
@@ -132,7 +139,7 @@ class autoptimizeMetabox
|
|
132 |
}
|
133 |
|
134 |
// if CSS opt and inline & defer are on and if we have a slug, the button can be active.
|
135 |
-
if ( false !== $_slug && 'on' === get_option( 'autoptimize_css', false ) && 'on' === get_option( 'autoptimize_css_defer', false ) && ! empty( apply_filters( 'autoptimize_filter_ccss_key', get_option( 'autoptimize_ccss_key', false ) ) ) && '2' === get_option( 'autoptimize_ccss_keyst', false ) ) {
|
136 |
$_generate_disabled = false;
|
137 |
}
|
138 |
?>
|
@@ -229,11 +236,13 @@ class autoptimizeMetabox
|
|
229 |
|
230 |
// OK, we can have a look at the actual data now.
|
231 |
// Sanitize user input.
|
232 |
-
foreach ( array( 'ao_post_optimize', 'ao_post_js_optimize', 'ao_post_css_optimize', 'ao_post_ccss', 'ao_post_lazyload' ) as $opti_type ) {
|
233 |
-
if ( isset( $_POST[$opti_type] ) ) {
|
234 |
-
$ao_meta_result[$opti_type] = 'on';
|
235 |
-
} else {
|
236 |
$ao_meta_result[$opti_type] = '';
|
|
|
|
|
|
|
|
|
237 |
}
|
238 |
}
|
239 |
|
@@ -252,11 +261,9 @@ class autoptimizeMetabox
|
|
252 |
$type = 'is_single';
|
253 |
}
|
254 |
|
255 |
-
$path
|
256 |
-
$
|
257 |
-
$
|
258 |
-
$criticalcss_enqueue = new autoptimizeCriticalCSSEnqueue();
|
259 |
-
$_result = $criticalcss_enqueue->ao_ccss_enqueue( '', $path, $type );
|
260 |
|
261 |
if ( $_result ) {
|
262 |
$response['code'] = '200';
|
@@ -285,6 +292,7 @@ class autoptimizeMetabox
|
|
285 |
'ao_post_css_optimize' => 'on',
|
286 |
'ao_post_ccss' => 'on',
|
287 |
'ao_post_lazyload' => 'on',
|
|
|
288 |
);
|
289 |
return $ao_metabox_defaults;
|
290 |
}
|
23 |
|
24 |
public function ao_metabox_add_box()
|
25 |
{
|
26 |
+
$screens = array(
|
27 |
'post',
|
28 |
'page',
|
29 |
// add extra types e.g. product or ... ?
|
42 |
|
43 |
/**
|
44 |
* Prints the box content.
|
45 |
+
*
|
46 |
* @param WP_Post $post The object for the current post/page.
|
47 |
*/
|
48 |
function ao_metabox_content( $post )
|
50 |
wp_nonce_field( 'ao_metabox', 'ao_metabox_nonce' );
|
51 |
|
52 |
$ao_opt_value = $this->check_ao_opt_sanity( get_post_meta( $post->ID, 'ao_post_optimize', true ) );
|
53 |
+
|
54 |
$_ao_meta_sub_opacity = '';
|
55 |
if ( 'on' !== $ao_opt_value['ao_post_optimize'] ) {
|
56 |
$_ao_meta_sub_opacity = 'opacity:.33;';
|
62 |
<?php _e( 'Optimize this page?', 'autoptimize' ); ?>
|
63 |
</label>
|
64 |
</p>
|
65 |
+
<?php
|
66 |
$_ao_meta_js_style = '';
|
67 |
+
if ( 'on' !== autoptimizeOptionWrapper::get_option( 'autoptimize_js', false ) ) {
|
68 |
$_ao_meta_js_style = 'display:none;';
|
69 |
}
|
70 |
echo '<p class="ao_meta_sub" style="' . $_ao_meta_sub_opacity . $_ao_meta_js_style . '">';
|
74 |
<?php _e( 'Optimize JS?', 'autoptimize' ); ?>
|
75 |
</label>
|
76 |
</p>
|
77 |
+
<?php
|
78 |
$_ao_meta_css_style = '';
|
79 |
+
if ( 'on' !== autoptimizeOptionWrapper::get_option( 'autoptimize_css', false ) ) {
|
80 |
$_ao_meta_css_style = 'display:none;';
|
81 |
}
|
82 |
echo '<p class="ao_meta_sub" style="' . $_ao_meta_sub_opacity . $_ao_meta_css_style . '">';
|
86 |
<?php _e( 'Optimize CSS?', 'autoptimize' ); ?>
|
87 |
</label>
|
88 |
</p>
|
89 |
+
<?php
|
90 |
$_ao_meta_ccss_style = '';
|
91 |
+
if ( 'on' !== autoptimizeOptionWrapper::get_option( 'autoptimize_css_defer', false ) || 'on' !== autoptimizeOptionWrapper::get_option( 'autoptimize_css', false ) ) {
|
92 |
$_ao_meta_ccss_style = 'display:none;';
|
93 |
}
|
94 |
if ( 'on' !== $ao_opt_value['ao_post_css_optimize'] ) {
|
101 |
<?php _e( 'Inline critical CSS?', 'autoptimize' ); ?>
|
102 |
</label>
|
103 |
</p>
|
104 |
+
<?php
|
105 |
$_ao_meta_lazyload_style = '';
|
106 |
if ( false === autoptimizeImages::should_lazyload_wrapper() ) {
|
107 |
$_ao_meta_lazyload_style = 'display:none;';
|
113 |
<?php _e( 'Lazyload images?', 'autoptimize' ); ?>
|
114 |
</label>
|
115 |
</p>
|
116 |
+
<p class="ao_meta_sub" style="<?php echo $_ao_meta_sub_opacity ?>">
|
117 |
+
<label for="autoptimize_post_preload">
|
118 |
+
<?php _e( 'LCP Image to preload', 'autoptimize' ); ?>
|
119 |
+
</label>
|
120 |
+
<input type="text" id="autoptimize_post_preload" name="ao_post_preload" value="<?php echo esc_attr( $ao_opt_value['ao_post_preload'] ) ?>">
|
121 |
+
</p>
|
122 |
+
<p> </p>
|
123 |
<p>
|
124 |
<?php
|
125 |
// Get path + check if button should be enabled or disabled.
|
139 |
}
|
140 |
|
141 |
// if CSS opt and inline & defer are on and if we have a slug, the button can be active.
|
142 |
+
if ( false !== $_slug && 'on' === autoptimizeOptionWrapper::get_option( 'autoptimize_css', false ) && 'on' === autoptimizeOptionWrapper::get_option( 'autoptimize_css_defer', false ) && ! empty( apply_filters( 'autoptimize_filter_ccss_key', autoptimizeOptionWrapper::get_option( 'autoptimize_ccss_key', false ) ) ) && '2' === autoptimizeOptionWrapper::get_option( 'autoptimize_ccss_keyst', false ) ) {
|
143 |
$_generate_disabled = false;
|
144 |
}
|
145 |
?>
|
236 |
|
237 |
// OK, we can have a look at the actual data now.
|
238 |
// Sanitize user input.
|
239 |
+
foreach ( array( 'ao_post_optimize', 'ao_post_js_optimize', 'ao_post_css_optimize', 'ao_post_ccss', 'ao_post_lazyload', 'ao_post_preload' ) as $opti_type ) {
|
240 |
+
if ( ! isset( $_POST[$opti_type] ) ) {
|
|
|
|
|
241 |
$ao_meta_result[$opti_type] = '';
|
242 |
+
} else if ( 'on' === $_POST[$opti_type] ) {
|
243 |
+
$ao_meta_result[$opti_type] = 'on';
|
244 |
+
} else if ( in_array( $opti_type, array( 'ao_post_preload' ) ) ) {
|
245 |
+
$ao_meta_result[$opti_type] = $_POST[$opti_type];
|
246 |
}
|
247 |
}
|
248 |
|
261 |
$type = 'is_single';
|
262 |
}
|
263 |
|
264 |
+
$path = wp_strip_all_tags( $_POST['path'] );
|
265 |
+
$criticalcss = autoptimize()->criticalcss();
|
266 |
+
$_result = $criticalcss->enqueue( '', $path, $type );
|
|
|
|
|
267 |
|
268 |
if ( $_result ) {
|
269 |
$response['code'] = '200';
|
292 |
'ao_post_css_optimize' => 'on',
|
293 |
'ao_post_ccss' => 'on',
|
294 |
'ao_post_lazyload' => 'on',
|
295 |
+
'ao_post_preload' => '',
|
296 |
);
|
297 |
return $ao_metabox_defaults;
|
298 |
}
|
classes/autoptimizeScripts.php
CHANGED
@@ -261,6 +261,8 @@ class autoptimizeScripts extends autoptimizeBase
|
|
261 |
if ( $this->aggregate && apply_filters( 'autoptimize_filter_js_dontaggregate', false ) ) {
|
262 |
$this->aggregate = false;
|
263 |
}
|
|
|
|
|
264 |
|
265 |
// Defer when not aggregating.
|
266 |
if ( false === $this->aggregate && apply_filters( 'autoptimize_filter_js_defer_not_aggregate', $options['defer_not_aggregate'] ) ) {
|
@@ -434,6 +436,8 @@ class autoptimizeScripts extends autoptimizeBase
|
|
434 |
$code = preg_replace( '/(?:^\\s*<!--\\s*|\\s*(?:\\/\\/)?\\s*-->\\s*$)/', '', $code );
|
435 |
$this->scripts[] = 'INLINE;' . $code;
|
436 |
} else {
|
|
|
|
|
437 |
if ( false === $this->defer_inline ) {
|
438 |
// Can we move this?
|
439 |
$autoptimize_js_moveable = apply_filters( 'autoptimize_js_moveable', '', $tag );
|
@@ -446,10 +450,17 @@ class autoptimizeScripts extends autoptimizeBase
|
|
446 |
} else {
|
447 |
$tag = '';
|
448 |
}
|
449 |
-
}
|
450 |
// defer inline JS by base64 encoding it.
|
451 |
-
preg_match( '#<script.*>(.*)</script>#Usmi', $tag, $match );
|
452 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
453 |
$this->content = str_replace( $tag, $new_tag, $this->content );
|
454 |
$tag = '';
|
455 |
} else {
|
261 |
if ( $this->aggregate && apply_filters( 'autoptimize_filter_js_dontaggregate', false ) ) {
|
262 |
$this->aggregate = false;
|
263 |
}
|
264 |
+
// and the filter that should have been there to begin with.
|
265 |
+
$this->aggregate = apply_filters( 'autoptimize_filter_js_aggregate', $this->aggregate );
|
266 |
|
267 |
// Defer when not aggregating.
|
268 |
if ( false === $this->aggregate && apply_filters( 'autoptimize_filter_js_defer_not_aggregate', $options['defer_not_aggregate'] ) ) {
|
436 |
$code = preg_replace( '/(?:^\\s*<!--\\s*|\\s*(?:\\/\\/)?\\s*-->\\s*$)/', '', $code );
|
437 |
$this->scripts[] = 'INLINE;' . $code;
|
438 |
} else {
|
439 |
+
$_inline_deferable = apply_filters( 'autoptimize_filters_js_inline_deferable', array( 'nonce', 'post_id', 'syntaxhighlighter' ) );
|
440 |
+
$_inline_dontmove = array_values( array_diff( $this->dontmove, $_inline_deferable ) );
|
441 |
if ( false === $this->defer_inline ) {
|
442 |
// Can we move this?
|
443 |
$autoptimize_js_moveable = apply_filters( 'autoptimize_js_moveable', '', $tag );
|
450 |
} else {
|
451 |
$tag = '';
|
452 |
}
|
453 |
+
} else if ( str_replace( $_inline_dontmove, '', $tag ) === $tag ) {
|
454 |
// defer inline JS by base64 encoding it.
|
455 |
+
// preg_match( '#<script.*>(.*)</script>#Usmi', $tag, $match );
|
456 |
+
preg_match( '#<script(?:[^>](?!id=))*\s*(?:id=(["\'])([^"\']+)\1)*+[^>]*+>(.*?)<\/script>#is', $tag, $match );
|
457 |
+
if ( $match[2] ) {
|
458 |
+
$_id = 'id="' . $match[2] . '" ';
|
459 |
+
} else {
|
460 |
+
$_id = '';
|
461 |
+
}
|
462 |
+
|
463 |
+
$new_tag = '<script defer ' . $_id . 'src="data:text/javascript;base64,' . base64_encode( $match[3] ) . '"></script>';
|
464 |
$this->content = str_replace( $tag, $new_tag, $this->content );
|
465 |
$tag = '';
|
466 |
} else {
|
classes/autoptimizeStyles.php
CHANGED
@@ -198,6 +198,8 @@ class autoptimizeStyles extends autoptimizeBase
|
|
198 |
if ( $this->aggregate && apply_filters( 'autoptimize_filter_css_dontaggregate', false ) ) {
|
199 |
$this->aggregate = false;
|
200 |
}
|
|
|
|
|
201 |
|
202 |
// include inline?
|
203 |
if ( apply_filters( 'autoptimize_css_include_inline', $options['include_inline'] ) ) {
|
@@ -489,7 +491,7 @@ class autoptimizeStyles extends autoptimizeBase
|
|
489 |
private function check_datauri_exclude_list( $url )
|
490 |
{
|
491 |
static $exclude_list = null;
|
492 |
-
$no_datauris
|
493 |
|
494 |
// Again, skip doing certain stuff repeatedly when loop-called.
|
495 |
if ( null === $exclude_list ) {
|
@@ -871,7 +873,7 @@ class autoptimizeStyles extends autoptimizeBase
|
|
871 |
}
|
872 |
|
873 |
if ( ! empty( $code ) ) {
|
874 |
-
$tmp_thiscss =
|
875 |
if ( ! empty( $tmp_thiscss ) ) {
|
876 |
$thiscss = $tmp_thiscss;
|
877 |
$import_ok = true;
|
198 |
if ( $this->aggregate && apply_filters( 'autoptimize_filter_css_dontaggregate', false ) ) {
|
199 |
$this->aggregate = false;
|
200 |
}
|
201 |
+
// and the filter that should have been there to begin with.
|
202 |
+
$this->aggregate = apply_filters( 'autoptimize_filter_css_aggregate', $this->aggregate );
|
203 |
|
204 |
// include inline?
|
205 |
if ( apply_filters( 'autoptimize_css_include_inline', $options['include_inline'] ) ) {
|
491 |
private function check_datauri_exclude_list( $url )
|
492 |
{
|
493 |
static $exclude_list = null;
|
494 |
+
static $no_datauris = array();
|
495 |
|
496 |
// Again, skip doing certain stuff repeatedly when loop-called.
|
497 |
if ( null === $exclude_list ) {
|
873 |
}
|
874 |
|
875 |
if ( ! empty( $code ) ) {
|
876 |
+
$tmp_thiscss = str_replace( $import, $code, $thiscss );
|
877 |
if ( ! empty( $tmp_thiscss ) ) {
|
878 |
$thiscss = $tmp_thiscss;
|
879 |
$import_ok = true;
|
classes/autoptimizeVersionUpdatesHandler.php
CHANGED
@@ -57,6 +57,13 @@ class autoptimizeVersionUpdatesHandler
|
|
57 |
$this->upgrade_from_2_7();
|
58 |
$major_update = true;
|
59 |
// No break, intentionally, so all upgrades are ran during a single request...
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
60 |
}
|
61 |
|
62 |
if ( true === $major_update ) {
|
@@ -258,11 +265,20 @@ class autoptimizeVersionUpdatesHandler
|
|
258 |
* remove CCSS request limit option + update jquery exclusion to include WordPress 5.6 jquery.min.js.
|
259 |
*/
|
260 |
private function upgrade_from_2_7() {
|
261 |
-
delete_option( 'autoptimize_ccss_rlimit' );
|
262 |
$js_exclusions = get_option( 'autoptimize_js_exclude', '' );
|
263 |
if ( strpos( $js_exclusions, 'js/jquery/jquery.js' ) !== false && strpos( $js_exclusions, 'js/jquery/jquery.min.js' ) === false ) {
|
264 |
$js_exclusions .= ', js/jquery/jquery.min.js';
|
265 |
-
update_option( 'autoptimize_js_exclude', $js_exclusions );
|
266 |
}
|
267 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
268 |
}
|
57 |
$this->upgrade_from_2_7();
|
58 |
$major_update = true;
|
59 |
// No break, intentionally, so all upgrades are ran during a single request...
|
60 |
+
case '2.8':
|
61 |
+
// nothing
|
62 |
+
case '2.9':
|
63 |
+
if ( version_compare( autoptimizeOptionWrapper::get_option( 'autoptimize_version', 'none' ), '2.9.999', 'lt' ) ) {
|
64 |
+
$this->upgrade_from_2_9_before_compatibility();
|
65 |
+
}
|
66 |
+
$major_update = false;
|
67 |
}
|
68 |
|
69 |
if ( true === $major_update ) {
|
265 |
* remove CCSS request limit option + update jquery exclusion to include WordPress 5.6 jquery.min.js.
|
266 |
*/
|
267 |
private function upgrade_from_2_7() {
|
268 |
+
autoptimizeOptionWrapper::delete_option( 'autoptimize_ccss_rlimit' );
|
269 |
$js_exclusions = get_option( 'autoptimize_js_exclude', '' );
|
270 |
if ( strpos( $js_exclusions, 'js/jquery/jquery.js' ) !== false && strpos( $js_exclusions, 'js/jquery/jquery.min.js' ) === false ) {
|
271 |
$js_exclusions .= ', js/jquery/jquery.min.js';
|
272 |
+
autoptimizeOptionWrapper::update_option( 'autoptimize_js_exclude', $js_exclusions );
|
273 |
}
|
274 |
}
|
275 |
+
|
276 |
+
/**
|
277 |
+
* set an option to indicate the AO installation predates the compatibility logic, this way we
|
278 |
+
* can avoid adding compatibility code that is likely not needed and maybe not wanted as it
|
279 |
+
* can introduce performance regressions.
|
280 |
+
*/
|
281 |
+
private function upgrade_from_2_9_before_compatibility() {
|
282 |
+
autoptimizeOptionWrapper::update_option( 'autoptimize_installed_before_compatibility', true );
|
283 |
+
}
|
284 |
}
|
classes/critcss-inc/admin_settings_adv.php
CHANGED
@@ -7,16 +7,17 @@
|
|
7 |
* Function to render the advanced panel.
|
8 |
*/
|
9 |
function ao_ccss_render_adv() {
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
|
|
20 |
|
21 |
// In case domain is not set yet (done in cron.php).
|
22 |
if ( empty( $ao_ccss_domain ) ) {
|
@@ -24,7 +25,7 @@ function ao_ccss_render_adv() {
|
|
24 |
}
|
25 |
|
26 |
// Get viewport size.
|
27 |
-
$viewport =
|
28 |
?>
|
29 |
<ul id="adv-panel">
|
30 |
<li class="itemDetail">
|
@@ -101,6 +102,7 @@ function ao_ccss_render_adv() {
|
|
101 |
</p>
|
102 |
</td>
|
103 |
</tr>
|
|
|
104 |
<tr>
|
105 |
<th scope="row">
|
106 |
<?php _e( 'Defer jQuery and other non-aggregated JS-files? (deprecated)', 'autoptimize' ); ?>
|
@@ -113,6 +115,7 @@ function ao_ccss_render_adv() {
|
|
113 |
</p>
|
114 |
</td>
|
115 |
</tr>
|
|
|
116 |
<tr>
|
117 |
<th scope="row">
|
118 |
<?php _e( 'Unload critical CSS after page load?', 'autoptimize' ); ?>
|
7 |
* Function to render the advanced panel.
|
8 |
*/
|
9 |
function ao_ccss_render_adv() {
|
10 |
+
$criticalcss = autoptimize()->criticalcss();
|
11 |
+
|
12 |
+
$ao_ccss_debug = esc_attr( $criticalcss->get_option( 'debug' ) );
|
13 |
+
$ao_ccss_finclude = esc_textarea( $criticalcss->get_option( 'finclude' ) );
|
14 |
+
$ao_ccss_rtimelimit = esc_attr( $criticalcss->get_option( 'rtimelimit' ) );
|
15 |
+
$ao_ccss_noptimize = esc_attr( $criticalcss->get_option( 'noptimize' ) );
|
16 |
+
$ao_ccss_loggedin = esc_attr( $criticalcss->get_option( 'loggedin' ) );
|
17 |
+
$ao_ccss_forcepath = esc_attr( $criticalcss->get_option( 'forcepath' ) );
|
18 |
+
$ao_ccss_deferjquery = esc_attr( $criticalcss->get_option( 'deferjquery' ) );
|
19 |
+
$ao_ccss_domain = esc_attr( $criticalcss->get_option( 'domain' ) );
|
20 |
+
$ao_ccss_unloadccss = esc_attr( $criticalcss->get_option( 'unloadccss' ) );
|
21 |
|
22 |
// In case domain is not set yet (done in cron.php).
|
23 |
if ( empty( $ao_ccss_domain ) ) {
|
25 |
}
|
26 |
|
27 |
// Get viewport size.
|
28 |
+
$viewport = $criticalcss->viewport();
|
29 |
?>
|
30 |
<ul id="adv-panel">
|
31 |
<li class="itemDetail">
|
102 |
</p>
|
103 |
</td>
|
104 |
</tr>
|
105 |
+
<?php if ( 1 == $ao_ccss_deferjquery ) { ?>
|
106 |
<tr>
|
107 |
<th scope="row">
|
108 |
<?php _e( 'Defer jQuery and other non-aggregated JS-files? (deprecated)', 'autoptimize' ); ?>
|
115 |
</p>
|
116 |
</td>
|
117 |
</tr>
|
118 |
+
<?php } ?>
|
119 |
<tr>
|
120 |
<th scope="row">
|
121 |
<?php _e( 'Unload critical CSS after page load?', 'autoptimize' ); ?>
|
classes/critcss-inc/admin_settings_explain.php
CHANGED
@@ -18,15 +18,23 @@ function ao_ccss_render_explain() {
|
|
18 |
<?php
|
19 |
$ccss_explanation = '';
|
20 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
// get the HTML with the explanation of what critical CSS is.
|
22 |
if ( apply_filters( 'autoptimize_settingsscreen_remotehttp', true ) ) {
|
23 |
-
$ccss_explanation = get_transient(
|
24 |
if ( empty( $ccss_explanation ) ) {
|
25 |
-
$ccss_expl_resp = wp_remote_get(
|
26 |
if ( ! is_wp_error( $ccss_expl_resp ) ) {
|
27 |
if ( '200' == wp_remote_retrieve_response_code( $ccss_expl_resp ) ) {
|
28 |
$ccss_explanation = wp_kses_post( wp_remote_retrieve_body( $ccss_expl_resp ) );
|
29 |
-
set_transient( '
|
30 |
}
|
31 |
}
|
32 |
}
|
18 |
<?php
|
19 |
$ccss_explanation = '';
|
20 |
|
21 |
+
if ( apply_filters( 'autoptimize_filter_ccss_rules_without_api', true ) ) {
|
22 |
+
$_transient = 'ao3_ccss_explain';
|
23 |
+
$_explain_html = 'https://misc.optimizingmatters.com/autoptimize_ccss_explain_ao30_i18n.html?ao_ver=';
|
24 |
+
} else {
|
25 |
+
$_transient = 'ao_ccss_explain';
|
26 |
+
$_explain_html = 'https://misc.optimizingmatters.com/autoptimize_ccss_explain_i18n.html?ao_ver=';
|
27 |
+
}
|
28 |
+
|
29 |
// get the HTML with the explanation of what critical CSS is.
|
30 |
if ( apply_filters( 'autoptimize_settingsscreen_remotehttp', true ) ) {
|
31 |
+
$ccss_explanation = get_transient( $_transient );
|
32 |
if ( empty( $ccss_explanation ) ) {
|
33 |
+
$ccss_expl_resp = wp_remote_get( $_explain_html . AUTOPTIMIZE_PLUGIN_VERSION );
|
34 |
if ( ! is_wp_error( $ccss_expl_resp ) ) {
|
35 |
if ( '200' == wp_remote_retrieve_response_code( $ccss_expl_resp ) ) {
|
36 |
$ccss_explanation = wp_kses_post( wp_remote_retrieve_body( $ccss_expl_resp ) );
|
37 |
+
set_transient( 'ao3_ccss_explain', $ccss_explanation, WEEK_IN_SECONDS );
|
38 |
}
|
39 |
}
|
40 |
}
|
classes/critcss-inc/admin_settings_queue.js.php
CHANGED
@@ -63,6 +63,11 @@ function drawQueueTable(queue) {
|
|
63 |
dbtn = false;
|
64 |
hbtn = false;
|
65 |
|
|
|
|
|
|
|
|
|
|
|
66 |
// Prepare job statuses
|
67 |
if (keys.jqstat === 'NEW') {
|
68 |
// Status: NEW (N, sort order 1)
|
63 |
dbtn = false;
|
64 |
hbtn = false;
|
65 |
|
66 |
+
// don't list jobs that don't have a type, they are irrelevant and this also avoids "type.replace is not a function".
|
67 |
+
if ( type == false ) {
|
68 |
+
return;
|
69 |
+
}
|
70 |
+
|
71 |
// Prepare job statuses
|
72 |
if (keys.jqstat === 'NEW') {
|
73 |
// Status: NEW (N, sort order 1)
|
classes/critcss-inc/admin_settings_queue.php
CHANGED
@@ -8,7 +8,8 @@
|
|
8 |
*/
|
9 |
function ao_ccss_render_queue() {
|
10 |
// Attach required arrays.
|
11 |
-
|
|
|
12 |
|
13 |
// Prepare the queue object.
|
14 |
if ( empty( $ao_ccss_queue ) ) {
|
@@ -25,7 +26,7 @@ function ao_ccss_render_queue() {
|
|
25 |
<span class="toggle-indicator dashicons dashicons-arrow-up dashicons-arrow-down"></span>
|
26 |
</button>
|
27 |
<?php
|
28 |
-
if (
|
29 |
$_queue_visibility = 'hidden';
|
30 |
} else {
|
31 |
$_queue_visibility = 'visible';
|
8 |
*/
|
9 |
function ao_ccss_render_queue() {
|
10 |
// Attach required arrays.
|
11 |
+
$criticalcss = autoptimize()->criticalcss();
|
12 |
+
$ao_ccss_queue = $criticalcss->get_option( 'queue' );
|
13 |
|
14 |
// Prepare the queue object.
|
15 |
if ( empty( $ao_ccss_queue ) ) {
|
26 |
<span class="toggle-indicator dashicons dashicons-arrow-up dashicons-arrow-down"></span>
|
27 |
</button>
|
28 |
<?php
|
29 |
+
if ( $criticalcss->has_autorules() ) {
|
30 |
$_queue_visibility = 'hidden';
|
31 |
} else {
|
32 |
$_queue_visibility = 'visible';
|
classes/critcss-inc/admin_settings_rules.js.php
CHANGED
@@ -55,6 +55,15 @@ function drawTable(critCssArray) {
|
|
55 |
hash=nv.hash;
|
56 |
file=nv.file;
|
57 |
filest=nv.file;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
58 |
if (file == 0) {
|
59 |
file='<?php _e( 'To be fetched from criticalcss.com in the next queue run...', 'autoptimize' ); ?>';
|
60 |
}
|
@@ -64,6 +73,9 @@ function drawTable(critCssArray) {
|
|
64 |
} else {
|
65 |
type='<?php _e( 'AUTO', 'autoptimize' ); ?>';
|
66 |
typeClass = 'auto';
|
|
|
|
|
|
|
67 |
}
|
68 |
if (file && typeof file == 'string') {
|
69 |
rmark_find=file.split('_');
|
@@ -76,8 +88,11 @@ function drawTable(critCssArray) {
|
|
76 |
} else {
|
77 |
target = i.replace(/(woo_|template_|custom_post_|edd_|bp_|bbp_)/,'');
|
78 |
}
|
79 |
-
|
80 |
-
jQuery("#" + nodeId + "_edit"
|
|
|
|
|
|
|
81 |
jQuery("#" + nodeId + "_remove").click(function(){confirmRemove(this.id);});
|
82 |
})
|
83 |
});
|
55 |
hash=nv.hash;
|
56 |
file=nv.file;
|
57 |
filest=nv.file;
|
58 |
+
auto_style = '';
|
59 |
+
<?php
|
60 |
+
$criticalcss = new autoptimizeCriticalCSSBase();
|
61 |
+
if ( $criticalcss->is_api_active() ){
|
62 |
+
?>api_active = 1;<?php
|
63 |
+
} else {
|
64 |
+
?>api_active = 0;<?php
|
65 |
+
}
|
66 |
+
?>
|
67 |
if (file == 0) {
|
68 |
file='<?php _e( 'To be fetched from criticalcss.com in the next queue run...', 'autoptimize' ); ?>';
|
69 |
}
|
73 |
} else {
|
74 |
type='<?php _e( 'AUTO', 'autoptimize' ); ?>';
|
75 |
typeClass = 'auto';
|
76 |
+
if ( api_active != 1 ) {
|
77 |
+
auto_style = ' style="opacity:.5;" '
|
78 |
+
}
|
79 |
}
|
80 |
if (file && typeof file == 'string') {
|
81 |
rmark_find=file.split('_');
|
88 |
} else {
|
89 |
target = i.replace(/(woo_|template_|custom_post_|edd_|bp_|bbp_)/,'');
|
90 |
}
|
91 |
+
|
92 |
+
jQuery("#rules-list").append("<tr " + auto_style + "class='rule "+k+"Rule'><td class='type'><span class='badge " + typeClass + "'>" + type + "</span></td><td class='target'>" + target + "</td><td class='file'>" + file + "</td><td class='btn edit'><span class=\"button-secondary\" id=\"" + nodeId + "_edit\"><?php _e( 'Edit', 'autoptimize' ); ?></span></td><td class='btn delete'><span class=\"button-secondary\" id=\"" + nodeId + "_remove\"><?php _e( 'Remove', 'autoptimize' ); ?></span></td></tr>");
|
93 |
+
if ( typeClass == 'manual' || api_active == 1 ) {
|
94 |
+
jQuery("#" + nodeId + "_edit").click(function(){addEditRow(this.id);});
|
95 |
+
}
|
96 |
jQuery("#" + nodeId + "_remove").click(function(){confirmRemove(this.id);});
|
97 |
})
|
98 |
});
|
classes/critcss-inc/admin_settings_rules.php
CHANGED
@@ -8,8 +8,13 @@
|
|
8 |
*/
|
9 |
function ao_ccss_render_rules() {
|
10 |
// Attach required arrays.
|
11 |
-
|
12 |
-
|
|
|
|
|
|
|
|
|
|
|
13 |
?>
|
14 |
<ul id="rules-panel">
|
15 |
<li class="itemDetail">
|
8 |
*/
|
9 |
function ao_ccss_render_rules() {
|
10 |
// Attach required arrays.
|
11 |
+
$criticalcss = autoptimize()->criticalcss();
|
12 |
+
$ao_ccss_rules = $criticalcss->get_option( 'rules' );
|
13 |
+
$ao_ccss_types = $criticalcss->get_types();
|
14 |
+
|
15 |
+
if ( empty( $ao_ccss_types ) || ! is_array( $ao_ccss_types ) ) {
|
16 |
+
$ao_ccss_types = array( 'No conditionals, check CSS optimization settings.' );
|
17 |
+
}
|
18 |
?>
|
19 |
<ul id="rules-panel">
|
20 |
<li class="itemDetail">
|
classes/external/php/jsmin.php
CHANGED
@@ -332,7 +332,7 @@ class JSMin {
|
|
332 |
$c = $this->input[$this->inputIndex];
|
333 |
$this->inputIndex += 1;
|
334 |
} else {
|
335 |
-
$c
|
336 |
}
|
337 |
}
|
338 |
if (ord($c) >= self::ORD_SPACE || $c === "\n" || $c === null) {
|
332 |
$c = $this->input[$this->inputIndex];
|
333 |
$this->inputIndex += 1;
|
334 |
} else {
|
335 |
+
return $c;
|
336 |
}
|
337 |
}
|
338 |
if (ord($c) >= self::ORD_SPACE || $c === "\n" || $c === null) {
|
config/autoptimize_404_handler.php
CHANGED
@@ -33,12 +33,12 @@ $js_or_css = pathinfo( $original_request, PATHINFO_EXTENSION );
|
|
33 |
// add multisite logic.
|
34 |
$multisite = false;
|
35 |
if ( true === $multisite ) {
|
36 |
-
preg_match( '#\/([0-9]{1,
|
37 |
$ao_root_cache_dir = preg_replace( '#[0-9]*\/$#', '', $ao_cache_dir );
|
38 |
$ao_cache_dir = $ao_root_cache_dir . $child_site_id[1] . '/';
|
39 |
}
|
40 |
|
41 |
-
$fallback_path = $ao_cache_dir . $js_or_css . '
|
42 |
|
43 |
if ( $original_request !== $fallback_target && file_exists( $fallback_path ) ) {
|
44 |
// error_log( 'Autoptimize file ' . $original_request . ' not found, using fallback instead.' );
|
33 |
// add multisite logic.
|
34 |
$multisite = false;
|
35 |
if ( true === $multisite ) {
|
36 |
+
preg_match( '#\/([0-9]{1,5})\/(?:js|css)\/[a-z0-9]*_fallback\.(?:js|css)$#', $fallback_target, $child_site_id );
|
37 |
$ao_root_cache_dir = preg_replace( '#[0-9]*\/$#', '', $ao_cache_dir );
|
38 |
$ao_cache_dir = $ao_root_cache_dir . $child_site_id[1] . '/';
|
39 |
}
|
40 |
|
41 |
+
$fallback_path = $ao_cache_dir . $js_or_css . '/<!--ao-cachefile-prefix-->_fallback.' . $js_or_css;
|
42 |
|
43 |
if ( $original_request !== $fallback_target && file_exists( $fallback_path ) ) {
|
44 |
// error_log( 'Autoptimize file ' . $original_request . ' not found, using fallback instead.' );
|
readme.txt
CHANGED
@@ -5,7 +5,7 @@ Donate link: http://blog.futtta.be/2013/10/21/do-not-donate-to-me/
|
|
5 |
Requires at least: 4.9
|
6 |
Tested up to: 5.9
|
7 |
Requires PHP: 5.6
|
8 |
-
Stable tag:
|
9 |
|
10 |
Autoptimize speeds up your website by optimizing JS, CSS, images (incl. lazy-load), HTML and Google Fonts, asyncing JS, removing emoji cruft and more.
|
11 |
|
@@ -15,7 +15,7 @@ Autoptimize makes optimizing your site really easy. It can aggregate, minify and
|
|
15 |
If you consider performance important, you really should use one of the many caching plugins to do page caching. Some good candidates to complement Autoptimize that way are e.g. [Speed Booster pack](https://wordpress.org/plugins/speed-booster-pack/), [KeyCDN's Cache Enabler](https://wordpress.org/plugins/cache-enabler), [WP Super Cache](http://wordpress.org/plugins/wp-super-cache/) or if you use Cloudflare [WP Cloudflare Super Page Cache](https://wordpress.org/plugins/wp-cloudflare-page-cache/).
|
16 |
|
17 |
> <strong>Premium Support</strong><br>
|
18 |
-
> We provide great [Autoptimize Pro Support and Web Performance Optimization services](https://misc.optimizingmatters.com/partners/?from=
|
19 |
|
20 |
(Speed-surfing image under creative commons [by LL Twistiti](https://www.flickr.com/photos/twistiti/818552808/))
|
21 |
|
@@ -324,6 +324,19 @@ Just [fork Autoptimize on Github](https://github.com/futtta/autoptimize) and cod
|
|
324 |
|
325 |
== Changelog ==
|
326 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
327 |
= 2.9.5.1 =
|
328 |
* fix for CSS cache growing too fast when inline CSS with variable selectors from WordPress 5.9 comment blocks is aggregated.
|
329 |
|
5 |
Requires at least: 4.9
|
6 |
Tested up to: 5.9
|
7 |
Requires PHP: 5.6
|
8 |
+
Stable tag: 3.0.0
|
9 |
|
10 |
Autoptimize speeds up your website by optimizing JS, CSS, images (incl. lazy-load), HTML and Google Fonts, asyncing JS, removing emoji cruft and more.
|
11 |
|
15 |
If you consider performance important, you really should use one of the many caching plugins to do page caching. Some good candidates to complement Autoptimize that way are e.g. [Speed Booster pack](https://wordpress.org/plugins/speed-booster-pack/), [KeyCDN's Cache Enabler](https://wordpress.org/plugins/cache-enabler), [WP Super Cache](http://wordpress.org/plugins/wp-super-cache/) or if you use Cloudflare [WP Cloudflare Super Page Cache](https://wordpress.org/plugins/wp-cloudflare-page-cache/).
|
16 |
|
17 |
> <strong>Premium Support</strong><br>
|
18 |
+
> We provide great [Autoptimize Pro Support and Web Performance Optimization services](https://misc.optimizingmatters.com/partners/?from=partnertab&partner=autoptimizepro), check out our offering on [https://accelera.autoptimize.com/](https://misc.optimizingmatters.com/partners/?from=partnertab&partner=autoptimizepro)!
|
19 |
|
20 |
(Speed-surfing image under creative commons [by LL Twistiti](https://www.flickr.com/photos/twistiti/818552808/))
|
21 |
|
324 |
|
325 |
== Changelog ==
|
326 |
|
327 |
+
= 3.0.0 =
|
328 |
+
* fundamental change for new installations: by default Autoptimize will not aggregate JS/ CSS any more (HTTP/2 is ubiquitous and there are other advantages to not aggregating esp. re. inline JS/ CSS and dependancies)
|
329 |
+
* new: no API needed any more to create manual critical CSS rules.
|
330 |
+
* new: "Remove WordPress blocks CSS" option on the "Extra" tab to remove block- and global styles (and SVG).
|
331 |
+
* new: compatibility logic for "edit with elementor", "revolution slider", for non-aggregated inline JS requiring jQuery even if not excluded (= auto-exclude of jQuery) and JS-heavy WordPress blocks (Gutenberg)
|
332 |
+
* new: configure an image to be preloaded on a per page/ post basis for better LCP.
|
333 |
+
* improvement: defer inline now also allowed if inline JS contains nonce or post_id.
|
334 |
+
* improvement: settings export/ import on critical CSS tab now takes into account all Autoptimize settings, not just the critical CSS ones.
|
335 |
+
* technical improvement: all criticalCSS classes were refactored, removing use of global variables.
|
336 |
+
* technical improvement: automated unit tests on Travis-CI for PHP versions 7.2 to 8.1.
|
337 |
+
* fix: stop Divi from clearing Autoptimize's cache [which is pretty counter-productive](https://blog.futtta.be/2018/11/17/warning-divi-purging-autoptimizes-cache/).
|
338 |
+
* misc smaller fixes/ improvements, see the [GitHub commit log](https://github.com/futtta/autoptimize/commits/beta)
|
339 |
+
|
340 |
= 2.9.5.1 =
|
341 |
* fix for CSS cache growing too fast when inline CSS with variable selectors from WordPress 5.9 comment blocks is aggregated.
|
342 |
|