PluginProbe
Autoptimize / 2.7.8
Autoptimize v2.7.8
2.2.2 2.3.0 2.3.1 2.3.2 2.3.3 2.3.4 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.5.0 2.5.1 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 2.7.8 All 107 releases
autoptimize / classes / autoptimizeCriticalCSSSettings.php

autoptimizeCriticalCSSSettings.php in Autoptimize 2.7.8, at classes/autoptimizeCriticalCSSSettings.php

381 lines 18.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Critical CSS Options page.
4 */
5
6 if ( ! defined( 'ABSPATH' ) ) {
7 exit;
8 }
9
10 class autoptimizeCriticalCSSSettings {
11 /**
12 * Options.
13 *
14 * @var bool
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 }
23
24 protected function enabled()
25 {
26 return apply_filters( 'autoptimize_filter_show_criticalcss_tabs', true );
27 }
28
29 public function run()
30 {
31 if ( $this->enabled() ) {
32 add_filter( 'autoptimize_filter_settingsscreen_tabs', array( $this, 'add_critcss_tabs' ), 10, 1 );
33 add_action( 'admin_enqueue_scripts', array( $this, 'admin_assets' ) );
34
35 if ( $this->is_multisite_network_admin() && autoptimizeOptionWrapper::is_ao_active_for_network() ) {
36 add_action( 'network_admin_menu', array( $this, 'add_critcss_admin_menu' ) );
37 } else {
38 add_action( 'admin_menu', array( $this, 'add_critcss_admin_menu' ) );
39 }
40
41 $criticalcss_ajax = new autoptimizeCriticalCSSSettingsAjax();
42 }
43 }
44
45 public function add_critcss_tabs( $in )
46 {
47 $in = array_merge( $in, array( 'ao_critcss' => 'âš¡ ' . __( 'Critical CSS', 'autoptimize' ) ) );
48
49 return $in;
50 }
51
52 public function add_critcss_admin_menu()
53 {
54 // Register settings.
55 register_setting( 'ao_ccss_options_group', 'autoptimize_css_defer_inline' );
56 register_setting( 'ao_ccss_options_group', 'autoptimize_ccss_rules' );
57 register_setting( 'ao_ccss_options_group', 'autoptimize_ccss_additional' );
58 register_setting( 'ao_ccss_options_group', 'autoptimize_ccss_queue' );
59 register_setting( 'ao_ccss_options_group', 'autoptimize_ccss_viewport' );
60 register_setting( 'ao_ccss_options_group', 'autoptimize_ccss_finclude' );
61 register_setting( 'ao_ccss_options_group', 'autoptimize_ccss_rlimit' );
62 register_setting( 'ao_ccss_options_group', 'autoptimize_ccss_noptimize' );
63 register_setting( 'ao_ccss_options_group', 'autoptimize_ccss_debug' );
64 register_setting( 'ao_ccss_options_group', 'autoptimize_ccss_key' );
65 register_setting( 'ao_ccss_options_group', 'autoptimize_ccss_keyst' );
66 register_setting( 'ao_ccss_options_group', 'autoptimize_ccss_loggedin' );
67 register_setting( 'ao_ccss_options_group', 'autoptimize_ccss_forcepath' );
68 register_setting( 'ao_ccss_options_group', 'autoptimize_ccss_deferjquery' );
69 register_setting( 'ao_ccss_options_group', 'autoptimize_ccss_domain' );
70 register_setting( 'ao_ccss_options_group', 'autoptimize_ccss_unloadccss' );
71
72 // And add submenu-page.
73 add_submenu_page( null, 'Critical CSS', 'Critical CSS', 'manage_options', 'ao_critcss', array( $this, 'ao_criticalcsssettings_page' ) );
74 }
75
76 public function admin_assets( $hook ) {
77 // Return if plugin is not hooked.
78 if ( 'settings_page_ao_critcss' != $hook && 'admin_page_ao_critcss' != $hook ) {
79 return;
80 }
81
82 // Stylesheets to add.
83 wp_enqueue_style( 'wp-jquery-ui-dialog' );
84 wp_enqueue_style( 'ao-tablesorter', plugins_url( 'critcss-inc/css/ao-tablesorter/style.css', __FILE__ ) );
85 wp_enqueue_style( 'ao-ccss-admin-css', plugins_url( 'critcss-inc/css/admin_styles.css', __FILE__ ) );
86
87 // Scripts to add.
88 wp_enqueue_script( 'jquery-ui-dialog', array( 'jquery' ) );
89 wp_enqueue_script( 'md5', plugins_url( 'critcss-inc/js/md5.min.js', __FILE__ ), null, null, true );
90 wp_enqueue_script( 'tablesorter', plugins_url( 'critcss-inc/js/jquery.tablesorter.min.js', __FILE__ ), array( 'jquery' ), null, true );
91 wp_enqueue_script( 'ao-ccss-admin-license', plugins_url( 'critcss-inc/js/admin_settings.js', __FILE__ ), array( 'jquery' ), null, true );
92 }
93
94 public function ao_criticalcsssettings_page()
95 {
96 // these are not OO yet, simply require for now.
97 require_once( 'critcss-inc/admin_settings_rules.php' );
98 require_once( 'critcss-inc/admin_settings_queue.php' );
99 require_once( 'critcss-inc/admin_settings_key.php' );
100 require_once( 'critcss-inc/admin_settings_adv.php' );
101 require_once( 'critcss-inc/admin_settings_explain.php' );
102
103 // fetch all options at once and populate them individually explicitely as globals.
104 $all_options = autoptimizeCriticalCSSBase::fetch_options();
105 foreach ( $all_options as $_option => $_value ) {
106 global ${$_option};
107 ${$_option} = $_value;
108 }
109 ?>
110 <script>document.title = "Autoptimize: <?php _e( 'Critical CSS', 'autoptimize' ); ?> " + document.title;</script>
111 <div class="wrap">
112 <div id="autoptimize_main">
113 <div id="ao_title_and_button">
114 <h1><?php _e( 'Autoptimize Settings', 'autoptimize' ); ?></h1>
115 </div>
116
117 <?php
118 // Print AO settings tabs.
119 echo autoptimizeConfig::ao_admin_tabs();
120
121 // Make sure dir to write ao_ccss exists and is writable.
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 ( ( ! $mkdirresp ) || ( ! $fileresp ) ) {
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
144 }
145
146 // Check for Autoptimize.
147 if ( ! empty( $ao_ccss_key ) && ! $ao_css_defer ) {
148 ?>
149 <div class="notice-error notice"><p>
150 <?php
151 _e( "Oops! Please <strong>activate the \"Inline and Defer CSS\" option</strong> on Autoptimize's main settings page to use this power-up.", 'autoptimize' );
152 ?>
153 </p></div>
154 <?php
155 return;
156 }
157
158 // check if WordPress cron is disabled and warn if so.
159 if ( ! empty( $ao_ccss_key ) && defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON && PAnD::is_admin_notice_active( 'i-know-about-disable-cron-forever' ) ) {
160 ?>
161 <div data-dismissible="i-know-about-disable-cron-forever" class="notice-warning notice is-dismissible"><p>
162 <?php
163 _e( 'WordPress cron (for task scheduling) seems to be disabled. Have a look at <a href="https://wordpress.org/plugins/autoptimize-criticalcss/faq/" target="_blank">the FAQ</a> or the info in the Job Queue instructions if all jobs remain in "N" status and no rules are created.', 'autoptimize' );
164 ?>
165 </p></div>
166 <?php
167 }
168
169 // warn if it looks as though the queue processing job looks isn't running
170 // but store result in transient as to not to have to go through 2 arrays each and every time.
171 $_warn_cron = get_transient( 'ao_ccss_cronwarning' );
172 if ( ! empty( $ao_ccss_key ) && false === $_warn_cron ) {
173 $_jobs_all_new = true;
174 $_oldest_job_timestamp = microtime( true ); // now.
175 $_jobs_too_old = true;
176
177 // go over queue array.
178 if ( empty( $ao_ccss_queue ) ) {
179 // no jobs, then no warning.
180 $_jobs_all_new = false;
181 } else {
182 foreach ( $ao_ccss_queue as $job ) {
183 if ( $job['jctime'] < $_oldest_job_timestamp ) {
184 // we need to catch the oldest job's timestamp.
185 $_oldest_job_timestamp = $job['jctime'];
186 }
187
188 if ( 'NEW' !== $job['jqstat'] && 'firstrun' !== $job['ljid'] ) {
189 // we have a non-"NEW" job which is not our pending firstrun job either, break the loop.
190 $_jobs_all_new = false;
191 break;
192 }
193 }
194 }
195
196 // is the oldest job too old (4h)?
197 if ( $_oldest_job_timestamp > microtime( true ) - 60 * 60 * 4 ) {
198 $_jobs_too_old = false;
199 }
200
201 if ( $_jobs_all_new && ! $this->ao_ccss_has_autorules() && $_jobs_too_old ) {
202 $_warn_cron = 'on';
203 $_transient_multiplier = 1; // store for 1 hour.
204 } else {
205 $_warn_cron = 'off';
206 $_transient_multiplier = 4; // store for 4 hours.
207 }
208 // and set transient.
209 set_transient( 'ao_ccss_cronwarning', $_warn_cron, $_transient_multiplier * HOUR_IN_SECONDS );
210 }
211
212 if ( ! empty( $ao_ccss_key ) && 'on' == $_warn_cron && PAnD::is_admin_notice_active( 'i-know-about-cron-1' ) ) {
213 ?>
214 <div data-dismissible="i-know-about-cron-1" class="notice-warning notice is-dismissible"><p>
215 <?php
216 _e( 'It looks like there might be a problem with WordPress cron (task scheduling). Have a look at <a href="https://wordpress.org/plugins/autoptimize-criticalcss/faq/" target="_blank">the FAQ</a> or the info in the Job Queue instructions if all jobs remain in "N" status and no rules are created.', 'autoptimize' );
217 ?>
218 </p></div>
219 <?php
220 } elseif ( ! empty( $ao_ccss_key ) && '2' == $ao_ccss_keyst && 'on' != $_warn_cron && ! $this->ao_ccss_has_autorules() ) {
221 ?>
222 <div class="notice-success notice"><p>
223 <?php
224 _e( 'Great, Autoptimize will now automatically start creating new critical CSS rules, you should see those appearing below in the next couple of hours.', 'autoptimize' );
225 ?>
226 </p></div>
227 <?php
228 }
229
230 // warn if service is down.
231 if ( ! empty( $ao_ccss_key ) && ! empty( $ao_ccss_servicestatus ) && is_array( $ao_ccss_servicestatus ) && 'down' === $ao_ccss_servicestatus['critcss']['status'] ) {
232 ?>
233 <div class="notice-warning notice"><p>
234 <?php
235 _e( 'The critical CSS service has been reported to be down. Although no new rules will be created for now, this does not prevent existing rules from being applied.', 'autoptimize' );
236 ?>
237 </p></div>
238 <?php
239 }
240
241 // Settings Form.
242 ?>
243 <form id="settings" method="post" action="options.php">
244 <?php
245 settings_fields( 'ao_ccss_options_group' );
246
247 // Get API key status.
248 $key = autoptimizeCriticalCSSCore::ao_ccss_key_status( true );
249
250 if ( $this->is_multisite_network_admin() ) {
251 ?>
252 <ul id="key-panel">
253 <li class="itemDetail">
254 <?php
255 // translators: the placesholder is for a line of code in wp-config.php.
256 echo sprintf( __( '<p>Critical CSS settings cannot be set at network level as critical CSS is specific to each sub-site.</p><p>You can however provide the critical CSS API key for use by all sites by adding this your wp-config.php as %s</p>', 'autoptimize' ), '<br/><code>define(\'AUTOPTIMIZE_CRITICALCSS_API_KEY\', \'eyJhbGmorestringsherexHa7MkOQFtDFkZgLmBLe-LpcHx4\');</code>' );
257 ?>
258 </li>
259 </ul>
260 <?php
261 } else {
262 if ( 'valid' == $key['status'] ) {
263 // If key status is valid, render other panels.
264 // Render rules section.
265 ao_ccss_render_rules();
266 // Render queue section.
267 ao_ccss_render_queue();
268 // Render advanced panel.
269 ao_ccss_render_adv();
270 } else {
271 // But if key is other than valid, add hidden fields to persist settings when submitting form
272 // Show explanation of why and how to get a API key.
273 ao_ccss_render_explain();
274
275 // Get viewport size.
276 $viewport = autoptimizeCriticalCSSCore::ao_ccss_viewport();
277
278 // Add hidden fields.
279 echo "<input class='hidden' name='autoptimize_ccss_rules' value='" . $ao_ccss_rules_raw . "'>";
280 echo "<input class='hidden' name='autoptimize_ccss_queue' value='" . $ao_ccss_queue_raw . "'>";
281 echo '<input class="hidden" name="autoptimize_ccss_viewport[w]" value="' . $viewport['w'] . '">';
282 echo '<input class="hidden" name="autoptimize_ccss_viewport[h]" value="' . $viewport['h'] . '">';
283 echo '<input class="hidden" name="autoptimize_ccss_finclude" value="' . $ao_ccss_finclude . '">';
284 echo '<input class="hidden" name="autoptimize_ccss_rlimit" value="' . $ao_ccss_rlimit . '">';
285 echo '<input class="hidden" name="autoptimize_ccss_debug" value="' . $ao_ccss_debug . '">';
286 echo '<input class="hidden" name="autoptimize_ccss_noptimize" value="' . $ao_ccss_noptimize . '">';
287 echo '<input class="hidden" name="autoptimize_css_defer_inline" value="' . esc_attr( $ao_css_defer_inline ) . '">';
288 echo '<input class="hidden" name="autoptimize_ccss_loggedin" value="' . $ao_ccss_loggedin . '">';
289 echo '<input class="hidden" name="autoptimize_ccss_forcepath" value="' . $ao_ccss_forcepath . '">';
290 }
291 // Render key panel unconditionally.
292 ao_ccss_render_key( $ao_ccss_key, $key['status'], $key['stmsg'], $key['msg'], $key['color'] );
293 ?>
294 <p class="submit left">
295 <input type="submit" class="button-primary" value="<?php _e( 'Save Changes', 'autoptimize' ); ?>" />
296 </p>
297 <?php
298 }
299 ?>
300 </form>
301 <script>
302 jQuery("form#settings").submit(function(){
303 var input = jQuery("#autoptimize_ccss_domain");
304 input.val(rot(input.val(), 13));
305 });
306 // rot JS from http://stackoverflow.com/a/617685/987044 .
307 function rot(domainstring, itype) {
308 return domainstring.toString().replace(/[a-zA-Z]/g, function (letter) {
309 return String.fromCharCode((letter <= 'Z' ? 90 : 122) >= (letter = letter.charCodeAt(0) + itype) ? letter : letter - 26);
310 });
311 }
312 </script>
313 <form id="importSettingsForm"<?php if ( $this->is_multisite_network_admin() ) { echo ' class="hidden"'; } ?>>
314 <span id="exportSettings" class="button-secondary"><?php _e( 'Export Settings', 'autoptimize' ); ?></span>
315 <input class="button-secondary" id="importSettings" type="button" value="<?php _e( 'Import Settings', 'autoptimize' ); ?>" onclick="upload();return false;" />
316 <input class="button-secondary" id="settingsfile" name="settingsfile" type="file" />
317 </form>
318 <div id="importdialog"></div>
319 </div><!-- /#autoptimize_main -->
320 </div><!-- /#wrap -->
321 <?php
322 if ( ! $this->is_multisite_network_admin() ) {
323 // Include debug panel if debug mode is enable.
324 if ( $ao_ccss_debug ) {
325 ?>
326 <div id="debug">
327 <?php
328 // Include debug panel.
329 include( 'critcss-inc/admin_settings_debug.php' );
330 ?>
331 </div><!-- /#debug -->
332 <?php
333 }
334 echo '<script>';
335 include( 'critcss-inc/admin_settings_rules.js.php' );
336 include( 'critcss-inc/admin_settings_queue.js.php' );
337 include( 'critcss-inc/admin_settings_impexp.js.php' );
338 echo '</script>';
339 }
340 }
341
342 public static function ao_ccss_has_autorules() {
343 static $_has_auto_rules = null;
344
345 if ( null === $_has_auto_rules ) {
346 global $ao_ccss_rules;
347 $_has_auto_rules = false;
348 if ( ! empty( $ao_ccss_rules ) ) {
349 foreach ( array( 'types', 'paths' ) as $_typat ) {
350 foreach ( $ao_ccss_rules[ $_typat ] as $rule ) {
351 if ( ! empty( $rule['hash'] ) ) {
352 // we have at least one AUTO job, so all is fine.
353 $_has_auto_rules = true;
354 break;
355 }
356 }
357 if ( $_has_auto_rules ) {
358 break;
359 }
360 }
361 }
362 }
363
364 return $_has_auto_rules;
365 }
366
367 public function is_multisite_network_admin() {
368 static $_multisite_network_admin = null;
369
370 if ( null === $_multisite_network_admin ) {
371 if ( is_multisite() && is_network_admin() ) {
372 $_multisite_network_admin = true;
373 } else {
374 $_multisite_network_admin = false;
375 }
376 }
377
378 return $_multisite_network_admin;
379 }
380 }
381