PluginProbe
Autoptimize / 3.1.4
Autoptimize v3.1.4
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/autoptimizeCriticalCSSBase.php +308 -77 2.7.83.1.4 View file →
@@ -15,8 +15,43 @@
15 15 * @var string
16 16 */
17 17 protected $filepath = null;
18 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 +
19 54 public function __construct()
20 55 {
21 56 // define constant, but only once.
22 57 if ( ! defined( 'AO_CCSS_DIR' ) ) {
@@ -34,9 +69,9 @@
34 69
35 70 // Define constants for criticalcss.com base path and API endpoints.
36 71 // fixme: AO_CCSS_URL should be read from the autoptimize availability json stored as option.
37 72 define( 'AO_CCSS_URL', 'https://criticalcss.com' );
38 - define( 'AO_CCSS_API', AO_CCSS_URL . '/api/premium/' );
73 + define( 'AO_CCSS_API', apply_filters( 'autoptimize_filter_ccss_service_url', AO_CCSS_URL . '/api/premium/' ) );
39 74 define( 'AO_CCSS_SLEEP', 10 );
40 75 }
41 76
42 77 // Define support files locations, in case they are not already defined.
@@ -51,119 +86,248 @@
51 86 }
52 87
53 88 $this->filepath = __FILE__;
54 89
55 - $this->setup();
56 - $this->load_requires();
90 + // Add keychecker action for scheduled use.
91 + add_action( 'ao_ccss_keychecker', array( $this, 'ao_ccss_check_key' ) );
57 92 }
58 93
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 - }
94 + public function setup() {
95 + // check if we need to upgrade.
96 + $this->check_upgrade();
66 97
67 - // make sure the 10 minutes cron schedule is added.
68 - add_filter( 'cron_schedules', array( $this, 'ao_ccss_interval' ) );
98 + // add/ remove scheduled jobs.
99 + if ( $this->is_api_active() ) {
100 + // make sure the 10 minutes cron schedule is added.
101 + add_filter( 'cron_schedules', array( $this, 'ao_ccss_interval' ) );
69 102
70 - // check if we need to upgrade.
71 - $this->check_upgrade();
103 + if ( ! wp_next_scheduled( 'ao_ccss_queue' ) ) {
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 + }
72 107
73 - // make sure ao_ccss_queue is scheduled OK if an API key is set.
74 - if ( isset( $ao_ccss_key ) && ! empty( $ao_ccss_key ) && ! wp_next_scheduled( 'ao_ccss_queue' ) ) {
75 - wp_schedule_event( time(), apply_filters( 'ao_ccss_queue_schedule', 'ao_ccss' ), 'ao_ccss_queue' );
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 + }
76 134 }
135 +
136 + // check/ create AO_CCSS_DIR.
137 + if ( ! file_exists( AO_CCSS_DIR ) ) {
138 + $this->create_ao_ccss_dir();
139 + }
77 140 }
78 141
79 142 public function load_requires() {
80 143 // Required libs, core is always needed.
81 - $criticalcss_core = new autoptimizeCriticalCSSCore();
144 + $this->_core = new autoptimizeCriticalCSSCore();
82 145
83 - if ( defined( 'WP_CLI' ) || defined( 'DOING_CRON' ) || is_admin() ) {
84 - // TODO: also include if overridden somehow to force queue processing to be executed?
85 - $criticalcss_cron = new autoptimizeCriticalCSSCron();
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();
86 149 }
87 150
88 151 if ( is_admin() ) {
89 - $criticalcss_settings = new autoptimizeCriticalCSSSettings();
90 - } else {
91 - // enqueuing only done when not wp-admin.
92 - $criticalcss_enqueue = new autoptimizeCriticalCSSEnqueue();
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();
93 156 }
94 157 }
95 158
96 - public static function fetch_options() {
97 - static $autoptimize_ccss_options = null;
159 + /**
160 + * Log a message via CCSS Core object
161 + *
162 + * @param string $msg Message to log.
163 + * @param int $lvl Loglevel.
164 + *
165 + * @return empty
166 + */
167 + public function log( $msg, $lvl ) {
168 + return $this->_core->ao_ccss_log( $msg, $lvl );
169 + }
98 170
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_rlimit'] = get_option( 'autoptimize_ccss_rlimit', '5' );
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'] = 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 );
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 + }
119 179
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 - }
180 + /**
181 + * Check CCSS contents from Core object
182 + *
183 + * @param string $ccss Critical CSS to be checked.
184 + *
185 + * @return bool
186 + */
187 + public function check_contents( $ccss ) {
188 + return $this->_core->ao_ccss_check_contents( $ccss );
189 + }
126 190
127 - // Setup the rules array.
128 - if ( empty( $autoptimize_ccss_options['ao_ccss_rules_raw'] ) ) {
129 - $autoptimize_ccss_options['ao_ccss_rules']['paths'] = array();
130 - $autoptimize_ccss_options['ao_ccss_rules']['types'] = array();
131 - } else {
132 - $autoptimize_ccss_options['ao_ccss_rules'] = json_decode( $autoptimize_ccss_options['ao_ccss_rules_raw'], true );
133 - }
191 + /**
192 + * Get key status from Core object
193 + *
194 + * @param bool $render Indicates if key status is to be rendered.
195 + *
196 + * @return array
197 + */
198 + public function key_status( $render ) {
199 + return $this->_core->ao_ccss_key_status( $render );
200 + }
134 201
135 - // Setup the queue array.
136 - if ( empty( $autoptimize_ccss_options['ao_ccss_queue_raw'] ) ) {
137 - $autoptimize_ccss_options['ao_ccss_queue'] = array();
138 - } else {
139 - $autoptimize_ccss_options['ao_ccss_queue'] = json_decode( $autoptimize_ccss_options['ao_ccss_queue_raw'], true );
140 - }
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 + }
141 210
142 - // Override API key if constant is defined.
143 - if ( defined( 'AUTOPTIMIZE_CRITICALCSS_API_KEY' ) ) {
144 - $autoptimize_ccss_options['ao_ccss_key'] = AUTOPTIMIZE_CRITICALCSS_API_KEY;
145 - }
211 + /**
212 + * Run enqueue in CCSS Enqueue object
213 + *
214 + * @param string $hash Hash (default empty).
215 + * @param string $path Path (default empty).
216 + * @param string $type (default is_page).
217 + */
218 + public function enqueue( $hash = '', $path = '', $type = 'is_page' ) {
219 + // Enqueue is sometimes required on wp-admin requests, load it just-in-time.
220 + if ( is_null( $this->_enqueue ) && $this->is_api_active() ) {
221 + $this->_enqueue = new autoptimizeCriticalCSSEnqueue();
146 222 }
147 223
148 - return $autoptimize_ccss_options;
224 + return $this->_enqueue->ao_ccss_enqueue( $hash, $path, $type );
149 225 }
150 226
227 + /**
228 + * Check auto-rules in CCSS Settings object
229 + */
230 + public function has_autorules() {
231 + return $this->_settings->ao_ccss_has_autorules();
232 + }
233 +
234 + /**
235 + * Get a Critical CSS option
236 + *
237 + * @param string $name The option name.
238 + *
239 + * @return mixed
240 + */
241 + public function get_option( $name ) {
242 + if ( is_null( $this->_options ) ) {
243 + $this->fetch_options();
244 + }
245 +
246 + if ( isset( $this->_options[ $name ] ) ) {
247 + return $this->_options[ $name ];
248 + }
249 +
250 + return null;
251 + }
252 +
253 + public function flush_options() {
254 + $this->_options = null;
255 + }
256 +
257 + protected function fetch_options() {
258 + if ( ! is_null( $this->_options ) ) {
259 + return $this->_options;
260 + }
261 +
262 + $this->_options = array(
263 + 'css_defer' => autoptimizeOptionWrapper::get_option( 'autoptimize_css_defer' ),
264 + 'css_defer_inline' => autoptimizeOptionWrapper::get_option( 'autoptimize_css_defer_inline' ),
265 + 'rules_raw' => get_option( 'autoptimize_ccss_rules', false ),
266 + 'additional' => get_option( 'autoptimize_ccss_additional' ),
267 + 'queue_raw' => get_option( 'autoptimize_ccss_queue', false ),
268 + 'viewport' => get_option( 'autoptimize_ccss_viewport', false ),
269 + 'finclude' => get_option( 'autoptimize_ccss_finclude', false ),
270 + 'rtimelimit' => get_option( 'autoptimize_ccss_rtimelimit', '30' ),
271 + 'noptimize' => get_option( 'autoptimize_ccss_noptimize', false ),
272 + 'debug' => get_option( 'autoptimize_ccss_debug', false ),
273 + 'key' => apply_filters( 'autoptimize_filter_ccss_key', get_option( 'autoptimize_ccss_key' ) ),
274 + 'keyst' => get_option( 'autoptimize_ccss_keyst' ),
275 + 'loggedin' => get_option( 'autoptimize_ccss_loggedin', '1' ),
276 + 'forcepath' => get_option( 'autoptimize_ccss_forcepath', '1' ),
277 + 'servicestatus' => get_option( 'autoptimize_service_availablity' ),
278 + 'deferjquery' => get_option( 'autoptimize_ccss_deferjquery', false ),
279 + 'domain' => get_option( 'autoptimize_ccss_domain' ),
280 + 'unloadccss' => get_option( 'autoptimize_ccss_unloadccss', false ),
281 + );
282 +
283 + if ( strpos( $this->_options['domain'], 'http' ) === false && strpos( $this->_options['domain'], 'uggc' ) === 0 ) {
284 + $this->_options['domain'] = str_rot13( $this->_options['domain'] );
285 + } elseif ( strpos( $this->_options['domain'], 'http' ) !== false ) {
286 + // not rot13'ed yet, do so now (goal; avoid migration plugins change the bound domain).
287 + update_option( 'autoptimize_ccss_domain', str_rot13( $this->_options['domain'] ) );
288 + }
289 +
290 + // Setup the rules array.
291 + if ( empty( $this->_options['rules_raw'] ) ) {
292 + $this->_options['rules'] = array(
293 + 'paths' => array(),
294 + 'types' => array(),
295 + );
296 + } else {
297 + $this->_options['rules'] = json_decode( $this->_options['rules_raw'], true );
298 + }
299 +
300 + // Setup the queue array.
301 + if ( empty( $this->_options['queue_raw'] ) ) {
302 + $this->_options['queue'] = array();
303 + } else {
304 + $this->_options['queue'] = json_decode( $this->_options['queue_raw'], true );
305 + }
306 +
307 + // Override API key if constant is defined.
308 + if ( defined( 'AUTOPTIMIZE_CRITICALCSS_API_KEY' ) ) {
309 + $this->_options['key'] = AUTOPTIMIZE_CRITICALCSS_API_KEY;
310 + }
311 +
312 + return $this->_options;
313 + }
314 +
151 315 public function on_upgrade() {
152 - global $ao_ccss_key;
316 + $key = $this->get_option( 'key' );
153 317
154 318 // Create the cache directory if it doesn't exist already.
155 319 if ( ! file_exists( AO_CCSS_DIR ) ) {
156 - mkdir( AO_CCSS_DIR, 0755, true );
320 + $this->create_ao_ccss_dir();
157 321 }
158 322
159 323 // Create a scheduled event for the queue.
160 - if ( isset( $ao_ccss_key ) && ! empty( $ao_ccss_key ) && ! wp_next_scheduled( 'ao_ccss_queue' ) ) {
324 + if ( $this->is_api_active() && ! wp_next_scheduled( 'ao_ccss_queue' ) ) {
161 325 wp_schedule_event( time(), apply_filters( 'ao_ccss_queue_schedule', 'ao_ccss' ), 'ao_ccss_queue' );
162 326 }
163 327
164 328 // Create a scheduled event for log maintenance.
165 - if ( isset( $ao_ccss_key ) && ! empty( $ao_ccss_key ) && ! wp_next_scheduled( 'ao_ccss_maintenance' ) ) {
329 + if ( $this->is_api_active() && ! wp_next_scheduled( 'ao_ccss_maintenance' ) ) {
166 330 wp_schedule_event( time(), 'twicedaily', 'ao_ccss_maintenance' );
167 331 }
168 332 }
169 333
@@ -180,8 +344,9 @@
180 344 public function ao_ccss_interval( $schedules ) {
181 345 // Let interval be configurable.
182 346 if ( ! defined( 'AO_CCSS_DEBUG_INTERVAL' ) ) {
183 347 $intsec = 600;
348 + $inttxt = '10 minutes';
184 349 } else {
185 350 $intsec = AO_CCSS_DEBUG_INTERVAL;
186 351 if ( $intsec >= 120 ) {
187 352 $inttxt = $intsec / 60 . ' minutes';
@@ -187,15 +352,81 @@
187 352 $inttxt = $intsec / 60 . ' minutes';
188 353 } else {
189 354 $inttxt = $intsec . ' second(s)';
190 355 }
191 - autoptimizeCriticalCSSCore::ao_ccss_log( 'Using custom WP-Cron interval of ' . $inttxt, 3 );
356 + $this->log( 'Using custom WP-Cron interval of ' . $inttxt, 3 );
192 357 }
193 358
194 359 // Attach interval to schedule.
195 360 $schedules['ao_ccss'] = array(
196 361 'interval' => $intsec,
197 - 'display' => __( 'Autoptimize CriticalCSS' ),
362 + 'display' => sprintf( __( 'Every %s (Autoptimize Crit. CSS)', 'autoptimize' ), $inttxt ),
198 363 );
199 364 return $schedules;
365 + }
366 +
367 + public function create_ao_ccss_dir() {
368 + // Make sure dir to write ao_ccss exists and is writable.
369 + if ( ! is_dir( AO_CCSS_DIR ) ) {
370 + // TODO: use wp_mkdir_p() ?
371 + $mkdirresp = @mkdir( AO_CCSS_DIR, 0775, true ); // @codingStandardsIgnoreLine
372 + } else {
373 + $mkdirresp = true;
374 + }
375 +
376 + // Make sure our index.html is there.
377 + if ( ! is_file( AO_CCSS_DIR . 'index.html' ) ) {
378 + $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>' );
379 + } else {
380 + $fileresp = true;
381 + }
382 +
383 + if ( true === $fileresp && true === $mkdirresp ) {
384 + return true;
385 + } else {
386 + return false;
387 + }
388 + }
389 +
390 + /**
391 + * Helper function to determine if there is an active API key.
392 + *
393 + * @return bool
394 + */
395 + public function is_api_active() {
396 + // using options instead of more complex $this->key_status (which gave some dependancy issues ... ;-) ).
397 + $ao_ccss_key = $this->get_option( 'key' );
398 + $ao_ccss_keyst = $this->get_option( 'keyst' );
399 +
400 + if ( ! empty( $ao_ccss_key ) && $ao_ccss_keyst && 2 == $ao_ccss_keyst ) {
401 + return true;
402 + }
403 +
404 + return false;
405 + }
406 +
407 + /**
408 + * Helper function to determine if a rule is MANUAL.
409 + *
410 + * @param array $rule Rule to check.
411 + *
412 + * @return bool
413 + */
414 + public function is_rule_manual( $rule ) {
415 + if ( is_array( $rule ) && false == $rule['hash'] && false != $rule['file'] ) {
416 + return true;
417 + }
418 +
419 + return false;
420 + }
421 +
422 + /**
423 + * Scheduled action to check an inactive key. Not part of autoptimizeCriticalCSSCron.php
424 + * to allow us to only load the main cron logic if we have an active key to begin with.
425 + */
426 + public function ao_ccss_check_key() {
427 + $ao_ccss_key = $this->get_option( 'key' );
428 + $_result = $this->_core->ao_ccss_key_validation( $ao_ccss_key );
429 + $_resmsg = ( true === $_result ) ? 'ok' : 'nok';
430 + $this->log( 'Inactive key checked, result was ' . $_resmsg, 3 );
200 431 }
201 432 }