PluginProbe
Autoptimize / 2.7.3
Autoptimize v2.7.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
autoptimize / classes / autoptimizeCriticalCSSSettings.php

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

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