PluginProbe
Autoptimize / 3.0.3
Autoptimize v3.0.3
2.2.2 2.3.0 2.3.1 2.3.2 2.3.3 2.3.4 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.5.0 2.5.1 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 2.7.8 All 107 releases
← All changes | classes/autoptimizeCriticalCSSCore.php +199 -164 2.7.13.0.3 View file →
@@ -8,81 +8,93 @@
8 8 exit;
9 9 }
10 10
11 11 class autoptimizeCriticalCSSCore {
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 - }
12 + protected $_types = null;
20 13
14 + public function __construct() {
15 + $this->criticalcss = autoptimize()->criticalcss();
21 16 $this->run();
22 17 }
23 18
24 19 public function run() {
25 - global $ao_css_defer;
26 - global $ao_ccss_deferjquery;
27 - global $ao_ccss_key;
20 + $css_defer = $this->criticalcss->get_option( 'css_defer' );
21 + $deferjquery = $this->criticalcss->get_option( 'deferjquery' );
22 + $unloadccss = $this->criticalcss->get_option( 'unloadccss' );
28 23
29 - // add all filters to do CCSS if key present.
30 - if ( $ao_css_defer && isset( $ao_ccss_key ) && ! empty( $ao_ccss_key ) ) {
31 - // Set AO behavior: disable minification to avoid double minifying and caching.
32 - add_filter( 'autoptimize_filter_css_critcss_minify', '__return_false' );
33 - add_filter( 'autoptimize_filter_css_defer_inline', array( $this, 'ao_ccss_frontend' ), 10, 1 );
24 + if ( ! $css_defer ) {
25 + return;
26 + }
34 27
35 - // Add the action to enqueue jobs for CriticalCSS cron.
36 - add_action( 'autoptimize_action_css_hash', array( 'autoptimizeCriticalCSSEnqueue', 'ao_ccss_enqueue' ), 10, 1 );
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 );
37 32
38 - // conditionally add the filter to defer jquery and others.
39 - if ( $ao_ccss_deferjquery ) {
40 - add_filter( 'autoptimize_html_after_minify', array( $this, 'ao_ccss_defer_jquery' ), 11, 1 );
41 - }
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 + }
42 37
43 - // Order paths by length, as longest ones have greater priority in the rules.
44 - if ( ! empty( $ao_ccss_rules['paths'] ) ) {
45 - $keys = array_map( 'strlen', array_keys( $ao_ccss_rules['paths'] ) );
46 - array_multisort( $keys, SORT_DESC, $ao_ccss_rules['paths'] );
47 - }
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 + }
48 46
49 - // Add an array with default WordPress's conditional tags
50 - // NOTE: these tags are sorted.
51 - global $ao_ccss_types;
52 - $ao_ccss_types = $this->get_ao_ccss_core_types();
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 + }
53 51
54 - // Extend conditional tags on plugin initalization.
55 - add_action( apply_filters( 'autoptimize_filter_ccss_extend_types_hook', 'init' ), array( $this, 'ao_ccss_extend_types' ) );
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.
56 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 );
57 70 }
58 71
59 72 public function ao_ccss_frontend( $inlined ) {
60 73 // Apply CriticalCSS to frontend pages
61 74 // Attach types and settings arrays.
62 - global $ao_ccss_types;
63 - global $ao_ccss_rules;
64 - global $ao_ccss_additional;
65 - global $ao_ccss_loggedin;
66 - global $ao_ccss_debug;
67 - global $ao_ccss_keyst;
68 - $no_ccss = '';
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 );
69 81
70 82 // Only if keystatus is OK and option to add CCSS for logged on users is on or user is not logged in.
71 - if ( ( $ao_ccss_keyst && 2 == $ao_ccss_keyst ) && ( $ao_ccss_loggedin || ! is_user_logged_in() ) ) {
83 + if ( $loggedin || ! is_user_logged_in() ) {
72 84 // Check for a valid CriticalCSS based on path to return its contents.
73 - $req_path = strtok( urldecode( $_SERVER['REQUEST_URI'] ), '?' );
74 - if ( ! empty( $ao_ccss_rules['paths'] ) ) {
75 - foreach ( $ao_ccss_rules['paths'] as $path => $rule ) {
85 + $req_path = strtok( $_SERVER['REQUEST_URI'], '?' );
86 + if ( ! empty( $rules['paths'] ) ) {
87 + foreach ( $rules['paths'] as $path => $rule ) {
76 88 // explicit match OR partial match if MANUAL rule.
77 - if ( $req_path == $path || ( false == $rule['hash'] && false != $rule['file'] && strpos( $req_path, str_replace( site_url(), '', $path ) ) !== false ) ) {
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 ) ) ) {
78 90 if ( file_exists( AO_CCSS_DIR . $rule['file'] ) ) {
79 91 $_ccss_contents = file_get_contents( AO_CCSS_DIR . $rule['file'] );
80 92 if ( 'none' != $_ccss_contents ) {
81 - if ( $ao_ccss_debug ) {
93 + if ( $debug ) {
82 94 $_ccss_contents = '/* PATH: ' . $path . ' hash: ' . $rule['hash'] . ' file: ' . $rule['file'] . ' */ ' . $_ccss_contents;
83 95 }
84 - return apply_filters( 'autoptimize_filter_ccss_core_ccss', $_ccss_contents . $ao_ccss_additional );
96 + return apply_filters( 'autoptimize_filter_ccss_core_ccss', $_ccss_contents . $additional );
85 97 } else {
86 98 $no_ccss = 'none';
87 99 }
88 100 }
@@ -90,57 +102,57 @@
90 102 }
91 103 }
92 104
93 105 // Check for a valid CriticalCSS based on conditional tags to return its contents.
94 - if ( ! empty( $ao_ccss_rules['types'] ) && 'none' !== $no_ccss ) {
106 + if ( ! empty( $rules['types'] ) && 'none' !== $no_ccss ) {
95 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.
96 - $ao_ccss_rules['types'] = array_replace( array_intersect_key( array_flip( $ao_ccss_types ), $ao_ccss_rules['types'] ), $ao_ccss_rules['types'] );
97 - $is_front_page = is_front_page();
108 + $rules['types'] = array_replace( array_intersect_key( array_flip( $this->_types ), $rules['types'] ), $rules['types'] );
109 + $is_front_page = is_front_page();
98 110
99 - foreach ( $ao_ccss_rules['types'] as $type => $rule ) {
100 - if ( in_array( $type, $ao_ccss_types ) && file_exists( AO_CCSS_DIR . $rule['file'] ) ) {
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'] ) ) {
101 113 $_ccss_contents = file_get_contents( AO_CCSS_DIR . $rule['file'] );
102 114 if ( $is_front_page && 'is_front_page' == $type ) {
103 115 if ( 'none' != $_ccss_contents ) {
104 - if ( $ao_ccss_debug ) {
116 + if ( $debug ) {
105 117 $_ccss_contents = '/* TYPES: ' . $type . ' hash: ' . $rule['hash'] . ' file: ' . $rule['file'] . ' */ ' . $_ccss_contents;
106 118 }
107 - return apply_filters( 'autoptimize_filter_ccss_core_ccss', $_ccss_contents . $ao_ccss_additional );
119 + return apply_filters( 'autoptimize_filter_ccss_core_ccss', $_ccss_contents . $additional );
108 120 } else {
109 121 $no_ccss = 'none';
110 122 }
111 - } elseif ( strpos( $type, 'custom_post_' ) === 0 && ! $is_front_page ) {
123 + } elseif ( ( $this->criticalcss->is_api_active() || $this->criticalcss->is_rule_manual( $rule ) ) && strpos( $type, 'custom_post_' ) === 0 && ! $is_front_page ) {
112 124 if ( get_post_type( get_the_ID() ) === substr( $type, 12 ) ) {
113 125 if ( 'none' != $_ccss_contents ) {
114 - if ( $ao_ccss_debug ) {
126 + if ( $debug ) {
115 127 $_ccss_contents = '/* TYPES: ' . $type . ' hash: ' . $rule['hash'] . ' file: ' . $rule['file'] . ' */ ' . $_ccss_contents;
116 128 }
117 - return apply_filters( 'autoptimize_filter_ccss_core_ccss', $_ccss_contents . $ao_ccss_additional );
129 + return apply_filters( 'autoptimize_filter_ccss_core_ccss', $_ccss_contents . $additional );
118 130 } else {
119 131 $no_ccss = 'none';
120 132 }
121 133 }
122 - } elseif ( 0 === strpos( $type, 'template_' ) && ! $is_front_page ) {
134 + } elseif ( ( $this->criticalcss->is_api_active() || $this->criticalcss->is_rule_manual( $rule ) ) && 0 === strpos( $type, 'template_' ) && ! $is_front_page ) {
123 135 if ( is_page_template( substr( $type, 9 ) ) ) {
124 136 if ( 'none' != $_ccss_contents ) {
125 - if ( $ao_ccss_debug ) {
137 + if ( $debug ) {
126 138 $_ccss_contents = '/* TYPES: ' . $type . ' hash: ' . $rule['hash'] . ' file: ' . $rule['file'] . ' */ ' . $_ccss_contents;
127 139 }
128 - return apply_filters( 'autoptimize_filter_ccss_core_ccss', $_ccss_contents . $ao_ccss_additional );
140 + return apply_filters( 'autoptimize_filter_ccss_core_ccss', $_ccss_contents . $additional );
129 141 } else {
130 142 $no_ccss = 'none';
131 143 }
132 144 }
133 - } elseif ( ! $is_front_page ) {
145 + } elseif ( ( $this->criticalcss->is_api_active() || $this->criticalcss->is_rule_manual( $rule ) ) && ! $is_front_page ) {
134 146 // all "normal" conditional tags, core + woo + buddypress + edd + bbpress
135 147 // but we have to remove the prefix for the non-core ones for them to function.
136 148 $type = str_replace( array( 'woo_', 'bp_', 'bbp_', 'edd_' ), '', $type );
137 149 if ( function_exists( $type ) && call_user_func( $type ) ) {
138 150 if ( 'none' != $_ccss_contents ) {
139 - if ( $ao_ccss_debug ) {
151 + if ( $debug ) {
140 152 $_ccss_contents = '/* TYPES: ' . $type . ' hash: ' . $rule['hash'] . ' file: ' . $rule['file'] . ' */ ' . $_ccss_contents;
141 153 }
142 - return apply_filters( 'autoptimize_filter_ccss_core_ccss', $_ccss_contents . $ao_ccss_additional );
154 + return apply_filters( 'autoptimize_filter_ccss_core_ccss', $_ccss_contents . $additional );
143 155 } else {
144 156 $no_ccss = 'none';
145 157 }
146 158 }
@@ -152,9 +164,9 @@
152 164
153 165 // Finally, inline the default CriticalCSS if any or else the entire CSS for the page
154 166 // This also applies to logged in users if the option to add CCSS for logged in users has been disabled.
155 167 if ( ! empty( $inlined ) && 'none' !== $no_ccss ) {
156 - return apply_filters( 'autoptimize_filter_ccss_core_ccss', $inlined . $ao_ccss_additional );
168 + return apply_filters( 'autoptimize_filter_ccss_core_ccss', $inlined . $additional );
157 169 } else {
158 170 add_filter( 'autoptimize_filter_css_inline', '__return_true' );
159 171 return;
160 172 }
@@ -160,17 +172,22 @@
160 172 }
161 173 }
162 174
163 175 public function ao_ccss_defer_jquery( $in ) {
164 - // try to defer all JS (main goal being jquery.js as AO by default does not aggregate that).
165 - if ( ( ! is_user_logged_in() || $ao_ccss_loggedin ) && preg_match_all( '#<script.*>(.*)</script>#Usmi', $in, $matches, PREG_SET_ORDER ) ) {
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 ) ) {
166 180 foreach ( $matches as $match ) {
167 - if ( ( ! preg_match( '/<script.* type\s?=.*>/', $match[0] ) || preg_match( '/type\s*=\s*[\'"]?(?:text|application)\/(?:javascript|ecmascript)[\'"]?/i', $match[0] ) ) && '' !== $match[1] && ( false !== strpos( $match[1], 'jQuery' ) || false !== strpos( $match[1], '$' ) ) ) {
168 - // inline js that requires jquery, wrap deferring JS around it to defer it.
169 - $new_match = 'var aoDeferInlineJQuery=function(){' . $match[1] . '}; if (document.readyState === "loading") {document.addEventListener("DOMContentLoaded", aoDeferInlineJQuery);} else {aoDeferInlineJQuery();}';
170 - $in = str_replace( $match[1], $new_match, $in );
171 - } elseif ( '' === $match[1] && false !== strpos( $match[0], 'src=' ) && false === strpos( $match[0], 'defer' ) ) {
172 - // linked non-aggregated JS, defer it.
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.
183 + continue;
184 + } elseif ( '' !== $match[1] && ( ! preg_match( '/<script.* type\s?=.*>/', $match[0] ) || preg_match( '/type\s*=\s*[\'"]?(?:text|application)\/(?:javascript|ecmascript)[\'"]?/i', $match[0] ) ) ) {
185 + // base64-encode and defer all inline JS.
186 + $base64_js = '<script defer src="data:text/javascript;base64,' . base64_encode( $match[1] ) . '"></script>';
187 + $in = str_replace( $match[0], $base64_js, $in );
188 + } elseif ( str_replace( array( ' defer', ' async' ), '', $match[0] ) === $match[0] ) {
189 + // and defer linked JS unless already deferred or asynced.
173 190 $new_match = str_replace( '<script ', '<script defer ', $match[0] );
174 191 $in = str_replace( $match[0], $new_match, $in );
175 192 }
176 193 }
@@ -177,17 +194,36 @@
177 194 }
178 195 return $in;
179 196 }
180 197
198 + public function ao_ccss_unloadccss( $html_in ) {
199 + // set media attrib of inline CCSS to none at onLoad to avoid it impacting full CSS (rarely needed).
200 + $_unloadccss_js = apply_filters( 'autoptimize_filter_ccss_core_unloadccss_js', '<script>window.addEventListener("load", function(event) {var el = document.getElementById("aoatfcss"); if(el) el.media = "none";})</script>' );
201 +
202 + if ( false !== strpos( $html_in, $_unloadccss_js . '</body>' ) ) {
203 + return $html_in;
204 + }
205 +
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 +
181 218 public function ao_ccss_extend_types() {
182 219 // Extend contidional tags
183 220 // Attach the conditional tags array.
184 - global $ao_ccss_types;
185 221
186 222 // in some cases $ao_ccss_types is empty and/or not an array, this should work around that problem.
187 - if ( empty( $ao_ccss_types ) || ! is_array( $ao_ccss_types ) ) {
188 - $ao_ccss_types = get_ao_ccss_core_types();
189 - autoptimizeCriticalCSSCore::ao_ccss_log( 'Empty types array in extend, refetching array with core conditionals.', 3 );
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 );
190 226 }
191 227
192 228 // Custom Post Types.
193 229 $cpts = get_post_types(
@@ -198,20 +234,25 @@
198 234 'names',
199 235 'and'
200 236 );
201 237 foreach ( $cpts as $cpt ) {
202 - array_unshift( $ao_ccss_types, 'custom_post_' . $cpt );
238 + array_unshift( $this->_types, 'custom_post_' . $cpt );
203 239 }
204 240
205 241 // Templates.
206 - $templates = wp_get_theme()->get_page_templates();
242 + // Transient cache to avoid frequent disk reads.
243 + $templates = get_transient( 'autoptimize_ccss_page_templates' );
244 + if ( ! $templates ) {
245 + $templates = wp_get_theme()->get_page_templates();
246 + set_transient( 'autoptimize_ccss_page_templates', $templates, HOUR_IN_SECONDS );
247 + }
207 248 foreach ( $templates as $tplfile => $tplname ) {
208 - array_unshift( $ao_ccss_types, 'template_' . $tplfile );
249 + array_unshift( $this->_types, 'template_' . $tplfile );
209 250 }
210 251
211 252 // bbPress tags.
212 253 if ( function_exists( 'is_bbpress' ) ) {
213 - $ao_ccss_types = array_merge(
254 + $this->_types = array_merge(
214 255 array(
215 256 'bbp_is_bbpress',
216 257 'bbp_is_favorites',
217 258 'bbp_is_forum_archive',
@@ -235,15 +276,15 @@
235 276 'bbp_is_topic_tag_edit',
236 277 'bbp_is_topics_created',
237 278 'bbp_is_user_home',
238 279 'bbp_is_user_home_edit',
239 - ), $ao_ccss_types
280 + ), $this->_types
240 281 );
241 282 }
242 283
243 284 // BuddyPress tags.
244 285 if ( function_exists( 'is_buddypress' ) ) {
245 - $ao_ccss_types = array_merge(
286 + $this->_types = array_merge(
246 287 array(
247 288 'bp_is_activation_page',
248 289 'bp_is_activity',
249 290 'bp_is_blogs',
@@ -277,27 +318,27 @@
277 318 'bp_is_settings_component',
278 319 'bp_is_user',
279 320 'bp_is_user_profile',
280 321 'bp_is_wire',
281 - ), $ao_ccss_types
322 + ), $this->_types
282 323 );
283 324 }
284 325
285 326 // Easy Digital Downloads (EDD) tags.
286 327 if ( function_exists( 'edd_is_checkout' ) ) {
287 - $ao_ccss_types = array_merge(
328 + $this->_types = array_merge(
288 329 array(
289 330 'edd_is_checkout',
290 331 'edd_is_failed_transaction_page',
291 332 'edd_is_purchase_history_page',
292 333 'edd_is_success_page',
293 - ), $ao_ccss_types
334 + ), $this->_types
294 335 );
295 336 }
296 337
297 338 // WooCommerce tags.
298 339 if ( class_exists( 'WooCommerce' ) ) {
299 - $ao_ccss_types = array_merge(
340 + $this->_types = array_merge(
300 341 array(
301 342 'woo_is_account_page',
302 343 'woo_is_cart',
303 344 'woo_is_checkout',
@@ -306,44 +347,35 @@
306 347 'woo_is_product_tag',
307 348 'woo_is_shop',
308 349 'woo_is_wc_endpoint_url',
309 350 'woo_is_woocommerce',
310 - ), $ao_ccss_types
351 + ), $this->_types
311 352 );
312 353 }
313 354 }
314 355
315 356 public function get_ao_ccss_core_types() {
316 - global $ao_ccss_types;
317 - if ( empty( $ao_ccss_types ) || ! is_array( $ao_ccss_types ) ) {
318 - return array(
319 - 'is_404',
320 - 'is_archive',
321 - 'is_author',
322 - 'is_category',
323 - 'is_front_page',
324 - 'is_home',
325 - 'is_page',
326 - 'is_post',
327 - 'is_search',
328 - 'is_attachment',
329 - 'is_single',
330 - 'is_sticky',
331 - 'is_paged',
332 - );
333 - } else {
334 - return $ao_ccss_types;
335 - }
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 + );
336 371 }
337 372
338 - public static function ao_ccss_key_status( $render ) {
373 + public function ao_ccss_key_status( $render ) {
339 374 // Provide key status
340 375 // Get key and key status.
341 - global $ao_ccss_key;
342 - global $ao_ccss_keyst;
343 - $self = new self();
344 - $key = $ao_ccss_key;
345 - $key_status = $ao_ccss_keyst;
376 + $key = $this->criticalcss->get_option( 'key' );
377 + $key_status = $this->criticalcss->get_option( 'keyst' );
346 378
347 379 // Prepare returned variables.
348 380 $key_return = array();
349 381 $status = false;
@@ -364,9 +396,9 @@
364 396 $message = __( 'Your API key is invalid. Please enter a valid <a href="https://criticalcss.com/?aff=1" target="_blank">criticalcss.com</a> key.', 'autoptimize' );
365 397 } elseif ( $key && ! $key_status ) {
366 398 // Key exists but it has no valid status yet
367 399 // Perform key validation.
368 - $key_check = $self->ao_ccss_key_validation( $key );
400 + $key_check = $this->ao_ccss_key_validation( $key );
369 401
370 402 // Key is valid, set valid status.
371 403 if ( $key_check ) {
372 404 $status = 'valid';
@@ -406,28 +438,40 @@
406 438 return $key_return;
407 439 }
408 440
409 441 public function ao_ccss_key_validation( $key ) {
442 + $noptimize = $this->criticalcss->get_option( 'noptimize' );
443 +
410 444 // POST a dummy job to criticalcss.com to check for key validation
411 445 // Prepare home URL for the request.
412 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';
453 + }
454 +
413 455 $src_url = apply_filters( 'autoptimize_filter_ccss_cron_srcurl', $src_url );
414 456
415 457 // Prepare the request.
416 458 $url = esc_url_raw( AO_CCSS_API . 'generate' );
417 459 $args = array(
418 - 'headers' => array(
419 - 'User-Agent' => 'Autoptimize CriticalCSS Power-Up v' . AO_CCSS_VER,
460 + 'headers' => apply_filters( 'autoptimize_ccss_cron_api_generate_headers', array(
461 + 'User-Agent' => 'Autoptimize v' . AO_CCSS_VER,
420 462 'Content-type' => 'application/json; charset=utf-8',
421 463 'Authorization' => 'JWT ' . $key,
422 464 'Connection' => 'close',
423 - ),
465 + ) ),
424 466 // Body must be JSON.
425 467 'body' => json_encode(
426 - array(
427 - 'url' => $src_url,
428 - 'aff' => 1,
429 - 'aocssv' => AO_CCSS_VER,
468 + apply_filters( 'autoptimize_ccss_cron_api_generate_body',
469 + array(
470 + 'url' => $src_url,
471 + 'aff' => 1,
472 + 'aocssv' => AO_CCSS_VER,
473 + )
430 474 )
431 475 ),
432 476 );
433 477
@@ -439,16 +483,16 @@
439 483 if ( 200 == $code ) {
440 484 // Response is OK.
441 485 // Set key status as valid and log key check.
442 486 update_option( 'autoptimize_ccss_keyst', 2 );
443 - autoptimizeCriticalCSSCore::ao_ccss_log( 'criticalcss.com: API key is valid, updating key status', 3 );
487 + $this->ao_ccss_log( 'criticalcss.com: API key is valid, updating key status', 3 );
444 488
445 489 // extract job-id from $body and put it in the queue as a P job
446 490 // but only if no jobs and no rules!
447 - global $ao_ccss_queue;
448 - global $ao_ccss_rules;
491 + $queue = $this->criticalcss->get_option( 'queue' );
492 + $rules = $this->criticalcss->get_option( 'rules' );
449 493
450 - if ( 0 == count( $ao_ccss_queue ) && 0 == count( $ao_ccss_rules['types'] ) && 0 == count( $ao_ccss_rules['paths'] ) ) {
494 + if ( 0 == count( $queue ) && 0 == count( $rules['types'] ) && 0 == count( $rules['paths'] ) ) {
451 495 if ( 'JOB_QUEUED' == $body['job']['status'] || 'JOB_ONGOING' == $body['job']['status'] ) {
452 496 $jprops['ljid'] = 'firstrun';
453 497 $jprops['rtarget'] = 'types|is_front_page';
454 498 $jprops['ptype'] = 'is_front_page';
@@ -460,12 +504,12 @@
460 504 $jprops['jrstat'] = null;
461 505 $jprops['jvstat'] = null;
462 506 $jprops['jctime'] = microtime( true );
463 507 $jprops['jftime'] = null;
464 - $ao_ccss_queue['/'] = $jprops;
465 - $ao_ccss_queue_raw = json_encode( $ao_ccss_queue );
466 - update_option( 'autoptimize_ccss_queue', $ao_ccss_queue_raw, false );
467 - autoptimizeCriticalCSSCore::ao_ccss_log( 'Created P job for is_front_page based on API key check response.', 3 );
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 );
468 512 }
469 513 }
470 514 return true;
471 515 } elseif ( 401 == $code ) {
@@ -471,66 +515,52 @@
471 515 } elseif ( 401 == $code ) {
472 516 // Response is unauthorized
473 517 // Set key status as invalid and log key check.
474 518 update_option( 'autoptimize_ccss_keyst', 1 );
475 - autoptimizeCriticalCSSCore::ao_ccss_log( 'criticalcss.com: API key is invalid, updating key status', 3 );
519 + $this->ao_ccss_log( 'criticalcss.com: API key is invalid, updating key status', 3 );
476 520 return false;
477 521 } else {
478 522 // Response unkown
479 523 // Log key check attempt.
480 - autoptimizeCriticalCSSCore::ao_ccss_log( 'criticalcss.com: could not check API key status, this is a service error, body follows if any...', 2 );
524 + $this->ao_ccss_log( 'criticalcss.com: could not check API key status, this is a service error, body follows if any...', 2 );
481 525 if ( ! empty( $body ) ) {
482 - autoptimizeCriticalCSSCore::ao_ccss_log( print_r( $body, true ), 2 );
526 + $this->ao_ccss_log( print_r( $body, true ), 2 );
483 527 }
484 528 if ( is_wp_error( $req ) ) {
485 - autoptimizeCriticalCSSCore::ao_ccss_log( $req->get_error_message(), 2 );
529 + $this->ao_ccss_log( $req->get_error_message(), 2 );
486 530 }
487 531 return false;
488 532 }
489 533 }
490 534
491 - public static function ao_ccss_viewport() {
535 + public function ao_ccss_viewport() {
492 536 // Get viewport size
493 537 // Attach viewport option.
494 - global $ao_ccss_viewport;
538 + $viewport = $this->criticalcss->get_option( 'viewport' );
495 539
496 - // Prepare viewport array.
497 - $viewport = array();
498 -
499 - // Viewport Width.
500 - if ( ! empty( $ao_ccss_viewport['w'] ) ) {
501 - $viewport['w'] = $ao_ccss_viewport['w'];
502 - } else {
503 - $viewport['w'] = '';
504 - }
505 -
506 - // Viewport Height.
507 - if ( ! empty( $ao_ccss_viewport['h'] ) ) {
508 - $viewport['h'] = $ao_ccss_viewport['h'];
509 - } else {
510 - $viewport['h'] = '';
511 - }
512 -
513 - return $viewport;
540 + return array(
541 + 'w' => ! empty( $viewport['w'] ) ? $viewport['w'] : '',
542 + 'h' => ! empty( $viewport['h'] ) ? $viewport['h'] : '',
543 + );
514 544 }
515 545
516 - public static function ao_ccss_check_contents( $ccss ) {
546 + public function ao_ccss_check_contents( $ccss ) {
517 547 // Perform basic exploit avoidance and CSS validation.
518 548 if ( ! empty( $ccss ) ) {
519 549 // Try to avoid code injection.
520 - $blacklist = array( '#!/', 'function(', '<script', '<?php' );
521 - foreach ( $blacklist as $blacklisted ) {
522 - if ( strpos( $ccss, $blacklisted ) !== false ) {
523 - autoptimizeCriticalCSSCore::ao_ccss_log( 'Critical CSS received contained blacklisted content.', 2 );
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 );
524 554 return false;
525 555 }
526 556 }
527 557
528 558 // Check for most basics CSS structures.
529 - $pinklist = array( '{', '}', ':' );
530 - foreach ( $pinklist as $needed ) {
559 + $needlist = array( '{', '}', ':' );
560 + foreach ( $needlist as $needed ) {
531 561 if ( false === strpos( $ccss, $needed ) && 'none' !== $ccss ) {
532 - autoptimizeCriticalCSSCore::ao_ccss_log( 'Critical CSS received did not seem to contain real CSS.', 2 );
562 + $this->ao_ccss_log( 'Critical CSS received did not seem to contain real CSS.', 2 );
533 563 return false;
534 564 }
535 565 }
536 566 }
@@ -538,12 +568,12 @@
538 568 // Return true if file critical CSS is sane.
539 569 return true;
540 570 }
541 571
542 - public static function ao_ccss_log( $msg, $lvl ) {
572 + public function ao_ccss_log( $msg, $lvl ) {
543 573 // Commom logging facility
544 574 // Attach debug option.
545 - global $ao_ccss_debug;
575 + $debug = $this->criticalcss->get_option( 'debug' );
546 576
547 577 // Prepare log levels, where accepted $lvl are:
548 578 // 1: II (for info)
549 579 // 2: EE (for error)
@@ -558,9 +588,9 @@
558 588 $level = 'EE';
559 589 break;
560 590 case 3:
561 591 // Output debug messages only if debug mode is enabled.
562 - if ( $ao_ccss_debug ) {
592 + if ( $debug ) {
563 593 $level = 'DD';
564 594 }
565 595 break;
566 596 default:
@@ -575,6 +605,11 @@
575 605
576 606 // Write message to log file.
577 607 error_log( $message, 3, AO_CCSS_LOG );
578 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' );
579 614 }
580 615 }