PluginProbe
Autoptimize / 2.7.7
Autoptimize v2.7.7
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.7, at classes/autoptimizeCriticalCSSSettings.php

371 lines 18.7 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 $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>' );
125 if ( ( ! $mkdirresp ) || ( ! $fileresp ) ) {
126 ?>
127 <div class="notice-error notice"><p>
128 <?php
129 _e( 'Could not create the required directory. Make sure the webserver can write to the wp-content directory.', 'autoptimize' );
130 ?>
131 </p></div>
132 <?php
133 }
134 }
135
136 // Check for Autoptimize.
137 if ( ! empty( $ao_ccss_key ) && ! $ao_css_defer ) {
138 ?>
139 <div class="notice-error notice"><p>
140 <?php
141 _e( "Oops! Please <strong>activate the \"Inline and Defer CSS\" option</strong> on Autoptimize's main settings page to use this power-up.", 'autoptimize' );
142 ?>
143 </p></div>
144 <?php
145 return;
146 }
147
148 // check if WordPress cron is disabled and warn if so.
149 if ( ! empty( $ao_ccss_key ) && defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON && PAnD::is_admin_notice_active( 'i-know-about-disable-cron-forever' ) ) {
150 ?>
151 <div data-dismissible="i-know-about-disable-cron-forever" class="notice-warning notice is-dismissible"><p>
152 <?php
153 _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' );
154 ?>
155 </p></div>
156 <?php
157 }
158
159 // warn if it looks as though the queue processing job looks isn't running
160 // but store result in transient as to not to have to go through 2 arrays each and every time.
161 $_warn_cron = get_transient( 'ao_ccss_cronwarning' );
162 if ( ! empty( $ao_ccss_key ) && false === $_warn_cron ) {
163 $_jobs_all_new = true;
164 $_oldest_job_timestamp = microtime( true ); // now.
165 $_jobs_too_old = true;
166
167 // go over queue array.
168 if ( empty( $ao_ccss_queue ) ) {
169 // no jobs, then no warning.
170 $_jobs_all_new = false;
171 } else {
172 foreach ( $ao_ccss_queue as $job ) {
173 if ( $job['jctime'] < $_oldest_job_timestamp ) {
174 // we need to catch the oldest job's timestamp.
175 $_oldest_job_timestamp = $job['jctime'];
176 }
177
178 if ( 'NEW' !== $job['jqstat'] && 'firstrun' !== $job['ljid'] ) {
179 // we have a non-"NEW" job which is not our pending firstrun job either, break the loop.
180 $_jobs_all_new = false;
181 break;
182 }
183 }
184 }
185
186 // is the oldest job too old (4h)?
187 if ( $_oldest_job_timestamp > microtime( true ) - 60 * 60 * 4 ) {
188 $_jobs_too_old = false;
189 }
190
191 if ( $_jobs_all_new && ! $this->ao_ccss_has_autorules() && $_jobs_too_old ) {
192 $_warn_cron = 'on';
193 $_transient_multiplier = 1; // store for 1 hour.
194 } else {
195 $_warn_cron = 'off';
196 $_transient_multiplier = 4; // store for 4 hours.
197 }
198 // and set transient.
199 set_transient( 'ao_ccss_cronwarning', $_warn_cron, $_transient_multiplier * HOUR_IN_SECONDS );
200 }
201
202 if ( ! empty( $ao_ccss_key ) && 'on' == $_warn_cron && PAnD::is_admin_notice_active( 'i-know-about-cron-1' ) ) {
203 ?>
204 <div data-dismissible="i-know-about-cron-1" class="notice-warning notice is-dismissible"><p>
205 <?php
206 _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' );
207 ?>
208 </p></div>
209 <?php
210 } elseif ( ! empty( $ao_ccss_key ) && '2' == $ao_ccss_keyst && 'on' != $_warn_cron && ! $this->ao_ccss_has_autorules() ) {
211 ?>
212 <div class="notice-success notice"><p>
213 <?php
214 _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' );
215 ?>
216 </p></div>
217 <?php
218 }
219
220 // warn if service is down.
221 if ( ! empty( $ao_ccss_key ) && ! empty( $ao_ccss_servicestatus ) && is_array( $ao_ccss_servicestatus ) && 'down' === $ao_ccss_servicestatus['critcss']['status'] ) {
222 ?>
223 <div class="notice-warning notice"><p>
224 <?php
225 _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' );
226 ?>
227 </p></div>
228 <?php
229 }
230
231 // Settings Form.
232 ?>
233 <form id="settings" method="post" action="options.php">
234 <?php
235 settings_fields( 'ao_ccss_options_group' );
236
237 // Get API key status.
238 $key = autoptimizeCriticalCSSCore::ao_ccss_key_status( true );
239
240 if ( $this->is_multisite_network_admin() ) {
241 ?>
242 <ul id="key-panel">
243 <li class="itemDetail">
244 <?php
245 // translators: the placesholder is for a line of code in wp-config.php.
246 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>' );
247 ?>
248 </li>
249 </ul>
250 <?php
251 } else {
252 if ( 'valid' == $key['status'] ) {
253 // If key status is valid, render other panels.
254 // Render rules section.
255 ao_ccss_render_rules();
256 // Render queue section.
257 ao_ccss_render_queue();
258 // Render advanced panel.
259 ao_ccss_render_adv();
260 } else {
261 // But if key is other than valid, add hidden fields to persist settings when submitting form
262 // Show explanation of why and how to get a API key.
263 ao_ccss_render_explain();
264
265 // Get viewport size.
266 $viewport = autoptimizeCriticalCSSCore::ao_ccss_viewport();
267
268 // Add hidden fields.
269 echo "<input class='hidden' name='autoptimize_ccss_rules' value='" . $ao_ccss_rules_raw . "'>";
270 echo "<input class='hidden' name='autoptimize_ccss_queue' value='" . $ao_ccss_queue_raw . "'>";
271 echo '<input class="hidden" name="autoptimize_ccss_viewport[w]" value="' . $viewport['w'] . '">';
272 echo '<input class="hidden" name="autoptimize_ccss_viewport[h]" value="' . $viewport['h'] . '">';
273 echo '<input class="hidden" name="autoptimize_ccss_finclude" value="' . $ao_ccss_finclude . '">';
274 echo '<input class="hidden" name="autoptimize_ccss_rlimit" value="' . $ao_ccss_rlimit . '">';
275 echo '<input class="hidden" name="autoptimize_ccss_debug" value="' . $ao_ccss_debug . '">';
276 echo '<input class="hidden" name="autoptimize_ccss_noptimize" value="' . $ao_ccss_noptimize . '">';
277 echo '<input class="hidden" name="autoptimize_css_defer_inline" value="' . esc_attr( $ao_css_defer_inline ) . '">';
278 echo '<input class="hidden" name="autoptimize_ccss_loggedin" value="' . $ao_ccss_loggedin . '">';
279 echo '<input class="hidden" name="autoptimize_ccss_forcepath" value="' . $ao_ccss_forcepath . '">';
280 }
281 // Render key panel unconditionally.
282 ao_ccss_render_key( $ao_ccss_key, $key['status'], $key['stmsg'], $key['msg'], $key['color'] );
283 ?>
284 <p class="submit left">
285 <input type="submit" class="button-primary" value="<?php _e( 'Save Changes', 'autoptimize' ); ?>" />
286 </p>
287 <?php
288 }
289 ?>
290 </form>
291 <script>
292 jQuery("form#settings").submit(function(){
293 var input = jQuery("#autoptimize_ccss_domain");
294 input.val(rot(input.val(), 13));
295 });
296 // rot JS from http://stackoverflow.com/a/617685/987044 .
297 function rot(domainstring, itype) {
298 return domainstring.toString().replace(/[a-zA-Z]/g, function (letter) {
299 return String.fromCharCode((letter <= 'Z' ? 90 : 122) >= (letter = letter.charCodeAt(0) + itype) ? letter : letter - 26);
300 });
301 }
302 </script>
303 <form id="importSettingsForm"<?php if ( $this->is_multisite_network_admin() ) { echo ' class="hidden"'; } ?>>
304 <span id="exportSettings" class="button-secondary"><?php _e( 'Export Settings', 'autoptimize' ); ?></span>
305 <input class="button-secondary" id="importSettings" type="button" value="<?php _e( 'Import Settings', 'autoptimize' ); ?>" onclick="upload();return false;" />
306 <input class="button-secondary" id="settingsfile" name="settingsfile" type="file" />
307 </form>
308 <div id="importdialog"></div>
309 </div><!-- /#autoptimize_main -->
310 </div><!-- /#wrap -->
311 <?php
312 if ( ! $this->is_multisite_network_admin() ) {
313 // Include debug panel if debug mode is enable.
314 if ( $ao_ccss_debug ) {
315 ?>
316 <div id="debug">
317 <?php
318 // Include debug panel.
319 include( 'critcss-inc/admin_settings_debug.php' );
320 ?>
321 </div><!-- /#debug -->
322 <?php
323 }
324 echo '<script>';
325 include( 'critcss-inc/admin_settings_rules.js.php' );
326 include( 'critcss-inc/admin_settings_queue.js.php' );
327 include( 'critcss-inc/admin_settings_impexp.js.php' );
328 echo '</script>';
329 }
330 }
331
332 public static function ao_ccss_has_autorules() {
333 static $_has_auto_rules = null;
334
335 if ( null === $_has_auto_rules ) {
336 global $ao_ccss_rules;
337 $_has_auto_rules = false;
338 if ( ! empty( $ao_ccss_rules ) ) {
339 foreach ( array( 'types', 'paths' ) as $_typat ) {
340 foreach ( $ao_ccss_rules[ $_typat ] as $rule ) {
341 if ( ! empty( $rule['hash'] ) ) {
342 // we have at least one AUTO job, so all is fine.
343 $_has_auto_rules = true;
344 break;
345 }
346 }
347 if ( $_has_auto_rules ) {
348 break;
349 }
350 }
351 }
352 }
353
354 return $_has_auto_rules;
355 }
356
357 public function is_multisite_network_admin() {
358 static $_multisite_network_admin = null;
359
360 if ( null === $_multisite_network_admin ) {
361 if ( is_multisite() && is_network_admin() ) {
362 $_multisite_network_admin = true;
363 } else {
364 $_multisite_network_admin = false;
365 }
366 }
367
368 return $_multisite_network_admin;
369 }
370 }
371