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 +315 -71 2.7.23.1.4 View file →
@@ -15,15 +15,47 @@
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' ) ) {
23 - // Define plugin version.
24 - define( 'AO_CCSS_VER', 'AO_' . AUTOPTIMIZE_PLUGIN_VERSION );
25 -
26 58 // Define a constant with the directory to store critical CSS in.
27 59 if ( is_multisite() ) {
28 60 $blog_id = get_current_blog_id();
29 61 define( 'AO_CCSS_DIR', WP_CONTENT_DIR . '/uploads/ao_ccss/' . $blog_id . '/' );
@@ -29,128 +61,273 @@
29 61 define( 'AO_CCSS_DIR', WP_CONTENT_DIR . '/uploads/ao_ccss/' . $blog_id . '/' );
30 62 } else {
31 63 define( 'AO_CCSS_DIR', WP_CONTENT_DIR . '/uploads/ao_ccss/' );
32 64 }
65 + }
66 + if ( ! defined( 'AO_CCSS_VER' ) ) {
67 + // Define plugin version.
68 + define( 'AO_CCSS_VER', 'AO_' . AUTOPTIMIZE_PLUGIN_VERSION );
33 69
34 - // Define support files locations.
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 +
77 + // Define support files locations, in case they are not already defined.
78 + if ( ! defined( 'AO_CCSS_LOCK' ) ) {
35 79 define( 'AO_CCSS_LOCK', AO_CCSS_DIR . 'queue.lock' );
80 + }
81 + if ( ! defined( 'AO_CCSS_LOG' ) ) {
36 82 define( 'AO_CCSS_LOG', AO_CCSS_DIR . 'queuelog.html' );
83 + }
84 + if ( ! defined( 'AO_CCSS_DEBUG' ) ) {
37 85 define( 'AO_CCSS_DEBUG', AO_CCSS_DIR . 'queue.json' );
38 -
39 - // Define constants for criticalcss.com base path and API endpoints.
40 - // fixme: AO_CCSS_URL should be read from the autoptimize availability json stored as option.
41 - define( 'AO_CCSS_URL', 'https://criticalcss.com' );
42 - define( 'AO_CCSS_API', AO_CCSS_URL . '/api/premium/' );
43 86 }
44 87
45 88 $this->filepath = __FILE__;
46 89
47 - $this->setup();
48 - $this->load_requires();
90 + // Add keychecker action for scheduled use.
91 + add_action( 'ao_ccss_keychecker', array( $this, 'ao_ccss_check_key' ) );
49 92 }
50 93
51 - public function setup()
52 - {
53 - // get all options.
54 - $all_options = $this->fetch_options();
55 - foreach ( $all_options as $option => $value ) {
56 - ${$option} = $value;
57 - }
94 + public function setup() {
95 + // check if we need to upgrade.
96 + $this->check_upgrade();
58 97
59 - // make sure the 10 minutes cron schedule is added.
60 - 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' ) );
61 102
62 - // check if we need to upgrade.
63 - $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 + }
64 107
65 - // make sure ao_ccss_queue is scheduled OK if an API key is set.
66 - if ( isset( $ao_ccss_key ) && ! empty( $ao_ccss_key ) && ! wp_next_scheduled( 'ao_ccss_queue' ) ) {
67 - 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 + }
68 134 }
135 +
136 + // check/ create AO_CCSS_DIR.
137 + if ( ! file_exists( AO_CCSS_DIR ) ) {
138 + $this->create_ao_ccss_dir();
139 + }
69 140 }
70 141
71 142 public function load_requires() {
72 143 // Required libs, core is always needed.
73 - $criticalcss_core = new autoptimizeCriticalCSSCore();
144 + $this->_core = new autoptimizeCriticalCSSCore();
74 145
75 - if ( defined( 'DOING_CRON' ) || is_admin() ) {
76 - // TODO: also include if overridden somehow to force queue processing to be executed?
77 - $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();
78 149 }
79 150
80 151 if ( is_admin() ) {
81 - $criticalcss_settings = new autoptimizeCriticalCSSSettings();
82 - } else {
83 - // enqueuing only done when not wp-admin.
84 - $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();
85 156 }
86 157 }
87 158
88 - public static function fetch_options() {
89 - // Get options.
90 - $autoptimize_ccss_options['ao_css_defer'] = autoptimizeOptionWrapper::get_option( 'autoptimize_css_defer' );
91 - $autoptimize_ccss_options['ao_css_defer_inline'] = autoptimizeOptionWrapper::get_option( 'autoptimize_css_defer_inline' );
92 - $autoptimize_ccss_options['ao_ccss_rules_raw'] = get_option( 'autoptimize_ccss_rules', false );
93 - $autoptimize_ccss_options['ao_ccss_additional'] = get_option( 'autoptimize_ccss_additional' );
94 - $autoptimize_ccss_options['ao_ccss_queue_raw'] = get_option( 'autoptimize_ccss_queue', false );
95 - $autoptimize_ccss_options['ao_ccss_viewport'] = get_option( 'autoptimize_ccss_viewport', false );
96 - $autoptimize_ccss_options['ao_ccss_finclude'] = get_option( 'autoptimize_ccss_finclude', false );
97 - $autoptimize_ccss_options['ao_ccss_rlimit'] = get_option( 'autoptimize_ccss_rlimit', '5' );
98 - $autoptimize_ccss_options['ao_ccss_noptimize'] = get_option( 'autoptimize_ccss_noptimize', false );
99 - $autoptimize_ccss_options['ao_ccss_debug'] = get_option( 'autoptimize_ccss_debug', false );
100 - $autoptimize_ccss_options['ao_ccss_key'] = get_option( 'autoptimize_ccss_key' );
101 - $autoptimize_ccss_options['ao_ccss_keyst'] = get_option( 'autoptimize_ccss_keyst' );
102 - $autoptimize_ccss_options['ao_ccss_loggedin'] = get_option( 'autoptimize_ccss_loggedin', '1' );
103 - $autoptimize_ccss_options['ao_ccss_forcepath'] = get_option( 'autoptimize_ccss_forcepath', '1' );
104 - $autoptimize_ccss_options['ao_ccss_servicestatus'] = get_option( 'autoptimize_service_availablity' );
105 - $autoptimize_ccss_options['ao_ccss_deferjquery'] = get_option( 'autoptimize_ccss_deferjquery', false );
106 - $autoptimize_ccss_options['ao_ccss_domain'] = get_option( 'autoptimize_ccss_domain' );
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 + }
107 170
108 - if ( strpos( $autoptimize_ccss_options['ao_ccss_domain'], 'http' ) === false && strpos( $autoptimize_ccss_options['ao_ccss_domain'], 'uggc' ) === 0 ) {
109 - $autoptimize_ccss_options['ao_ccss_domain'] = str_rot13( $autoptimize_ccss_options['ao_ccss_domain'] );
110 - } elseif ( strpos( $autoptimize_ccss_options['ao_ccss_domain'], 'http' ) !== 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 + }
179 +
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 + }
190 +
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 + }
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 + * @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();
222 + }
223 +
224 + return $this->_enqueue->ao_ccss_enqueue( $hash, $path, $type );
225 + }
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 ) {
111 286 // not rot13'ed yet, do so now (goal; avoid migration plugins change the bound domain).
112 - update_option( 'autoptimize_ccss_domain', str_rot13( $autoptimize_ccss_options['ao_ccss_domain'] ) );
287 + update_option( 'autoptimize_ccss_domain', str_rot13( $this->_options['domain'] ) );
113 288 }
114 289
115 290 // Setup the rules array.
116 - if ( empty( $autoptimize_ccss_options['ao_ccss_rules_raw'] ) ) {
117 - $autoptimize_ccss_options['ao_ccss_rules']['paths'] = array();
118 - $autoptimize_ccss_options['ao_ccss_rules']['types'] = array();
291 + if ( empty( $this->_options['rules_raw'] ) ) {
292 + $this->_options['rules'] = array(
293 + 'paths' => array(),
294 + 'types' => array(),
295 + );
119 296 } else {
120 - $autoptimize_ccss_options['ao_ccss_rules'] = json_decode( $autoptimize_ccss_options['ao_ccss_rules_raw'], true );
297 + $this->_options['rules'] = json_decode( $this->_options['rules_raw'], true );
121 298 }
122 299
123 300 // Setup the queue array.
124 - if ( empty( $autoptimize_ccss_options['ao_ccss_queue_raw'] ) ) {
125 - $autoptimize_ccss_options['ao_ccss_queue'] = array();
301 + if ( empty( $this->_options['queue_raw'] ) ) {
302 + $this->_options['queue'] = array();
126 303 } else {
127 - $autoptimize_ccss_options['ao_ccss_queue'] = json_decode( $autoptimize_ccss_options['ao_ccss_queue_raw'], true );
304 + $this->_options['queue'] = json_decode( $this->_options['queue_raw'], true );
128 305 }
129 306
130 307 // Override API key if constant is defined.
131 308 if ( defined( 'AUTOPTIMIZE_CRITICALCSS_API_KEY' ) ) {
132 - $autoptimize_ccss_options['ao_ccss_key'] = AUTOPTIMIZE_CRITICALCSS_API_KEY;
309 + $this->_options['key'] = AUTOPTIMIZE_CRITICALCSS_API_KEY;
133 310 }
134 311
135 - return $autoptimize_ccss_options;
312 + return $this->_options;
136 313 }
137 314
138 315 public function on_upgrade() {
139 - global $ao_ccss_key;
316 + $key = $this->get_option( 'key' );
140 317
141 318 // Create the cache directory if it doesn't exist already.
142 319 if ( ! file_exists( AO_CCSS_DIR ) ) {
143 - mkdir( AO_CCSS_DIR, 0755, true );
320 + $this->create_ao_ccss_dir();
144 321 }
145 322
146 323 // Create a scheduled event for the queue.
147 - 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' ) ) {
148 325 wp_schedule_event( time(), apply_filters( 'ao_ccss_queue_schedule', 'ao_ccss' ), 'ao_ccss_queue' );
149 326 }
150 327
151 328 // Create a scheduled event for log maintenance.
152 - 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' ) ) {
153 330 wp_schedule_event( time(), 'twicedaily', 'ao_ccss_maintenance' );
154 331 }
155 332 }
156 333
@@ -167,8 +344,9 @@
167 344 public function ao_ccss_interval( $schedules ) {
168 345 // Let interval be configurable.
169 346 if ( ! defined( 'AO_CCSS_DEBUG_INTERVAL' ) ) {
170 347 $intsec = 600;
348 + $inttxt = '10 minutes';
171 349 } else {
172 350 $intsec = AO_CCSS_DEBUG_INTERVAL;
173 351 if ( $intsec >= 120 ) {
174 352 $inttxt = $intsec / 60 . ' minutes';
@@ -174,15 +352,81 @@
174 352 $inttxt = $intsec / 60 . ' minutes';
175 353 } else {
176 354 $inttxt = $intsec . ' second(s)';
177 355 }
178 - autoptimizeCriticalCSSCore::ao_ccss_log( 'Using custom WP-Cron interval of ' . $inttxt, 3 );
356 + $this->log( 'Using custom WP-Cron interval of ' . $inttxt, 3 );
179 357 }
180 358
181 359 // Attach interval to schedule.
182 360 $schedules['ao_ccss'] = array(
183 361 'interval' => $intsec,
184 - 'display' => __( 'Autoptimize CriticalCSS' ),
362 + 'display' => sprintf( __( 'Every %s (Autoptimize Crit. CSS)', 'autoptimize' ), $inttxt ),
185 363 );
186 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 );
187 431 }
188 432 }