PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 8.6
Jetpack – WP Security, Backup, Speed, & Growth v8.6
16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 13.9.2 14.0.1 14.1.1 14.2.2 14.3.1 All 501 releases
jetpack / modules / custom-css / custom-css.php

custom-css.php in Jetpack – WP Security, Backup, Speed, & Growth 8.6, at modules/custom-css/custom-css.php

1,872 lines 59.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 use Automattic\Jetpack\Assets;
4 use Automattic\Jetpack\Redirect;
5
6 class Jetpack_Custom_CSS {
7 static function init() {
8 add_action( 'switch_theme', array( __CLASS__, 'reset' ) );
9 add_action( 'wp_restore_post_revision', array( __CLASS__, 'restore_revision' ), 10, 2 );
10
11 // Save revisions for posts of type safecss.
12 add_action( 'load-revision.php', array( __CLASS__, 'add_revision_redirect' ) );
13
14 // Override the edit link, the default link causes a redirect loop
15 add_filter( 'get_edit_post_link', array( __CLASS__, 'revision_post_link' ), 10, 3 );
16
17 // Overwrite the content width global variable if one is set in the custom css
18 add_action( 'template_redirect', array( __CLASS__, 'set_content_width' ) );
19 add_action( 'admin_init', array( __CLASS__, 'set_content_width' ) );
20
21 if ( ! is_admin() )
22 add_filter( 'stylesheet_uri', array( __CLASS__, 'style_filter' ) );
23
24 define(
25 'SAFECSS_USE_ACE',
26 ! jetpack_is_mobile() &&
27 ! Jetpack_User_Agent_Info::is_ipad() &&
28 /**
29 * Should the Custom CSS module use ACE to process CSS.
30 * @see https://ace.c9.io/
31 *
32 * @module custom-css
33 *
34 * @since 1.7.0
35 *
36 * @param bool true Use ACE to process the Custom CSS. Default to true.
37 */
38 apply_filters( 'safecss_use_ace', true )
39 );
40
41 // Register safecss as a custom post_type
42 // Explicit capability definitions are largely unnecessary because the posts are manipulated in code via an options page, managing CSS revisions does check the capabilities, so let's ensure that the proper caps are checked.
43 register_post_type( 'safecss', array(
44 // These are the defaults
45 // 'exclude_from_search' => true,
46 // 'public' => false,
47 // 'publicly_queryable' => false,
48 // 'show_ui' => false,
49 'supports' => array( 'revisions' ),
50 'label' => 'Custom CSS',
51 'can_export' => false,
52 'rewrite' => false,
53 'capabilities' => array(
54 'edit_post' => 'edit_theme_options',
55 'read_post' => 'read',
56 'delete_post' => 'edit_theme_options',
57 'edit_posts' => 'edit_theme_options',
58 'edit_others_posts' => 'edit_theme_options',
59 'publish_posts' => 'edit_theme_options',
60 'read_private_posts' => 'read'
61 )
62 ) );
63
64 // Short-circuit WP if this is a CSS stylesheet request
65 if ( isset( $_GET['custom-css'] ) ) {
66 header( 'Content-Type: text/css', true, 200 );
67 header( 'Expires: ' . gmdate( 'D, d M Y H:i:s', time() + 31536000) . ' GMT' ); // 1 year
68 Jetpack_Custom_CSS::print_css();
69 exit;
70 }
71
72 add_action( 'admin_enqueue_scripts', array( 'Jetpack_Custom_CSS', 'enqueue_scripts' ) );
73
74 if ( isset( $_GET['page'] ) && 'editcss' == $_GET['page'] && is_admin() ) {
75 // Do migration routine if necessary
76 Jetpack_Custom_CSS::upgrade();
77
78 /**
79 * Allows additional work when migrating safecss from wp_options to wp_post.
80 *
81 * @module custom-css
82 *
83 * @since 1.7.0
84 */
85 do_action( 'safecss_migrate_post' );
86 }
87
88 /**
89 * Never embed the style in the head on wpcom.
90 * Yes, this filter should be added to an unsynced file on wpcom, but
91 * there is no good syntactically-correct location to put it yet.
92 * @link https://github.com/Automattic/jetpack/commit/a1be114e9179f64d147124727a58e2cf76c7e5a1#commitcomment-7763921
93 */
94 if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
95 add_filter( 'safecss_embed_style', '__return_false' );
96 } else {
97 add_filter( 'safecss_embed_style', array( 'Jetpack_Custom_CSS', 'should_we_inline_custom_css' ), 10, 2 );
98 }
99
100 add_action( 'wp_head', array( 'Jetpack_Custom_CSS', 'link_tag' ), 101 );
101
102 add_filter( 'jetpack_content_width', array( 'Jetpack_Custom_CSS', 'jetpack_content_width' ) );
103 add_filter( 'editor_max_image_size', array( 'Jetpack_Custom_CSS', 'editor_max_image_size' ), 10, 3 );
104
105 if ( !current_user_can( 'switch_themes' ) && !is_super_admin() )
106 return;
107
108 add_action( 'admin_menu', array( 'Jetpack_Custom_CSS', 'menu' ) );
109
110 if ( isset( $_POST['safecss'] ) && false == strstr( $_SERVER[ 'REQUEST_URI' ], 'options.php' ) ) {
111 check_admin_referer( 'safecss' );
112
113 $save_result = self::save( array(
114 'css' => stripslashes( $_POST['safecss'] ),
115 'is_preview' => isset( $_POST['action'] ) && $_POST['action'] == 'preview',
116 'preprocessor' => isset( $_POST['custom_css_preprocessor'] ) ? $_POST['custom_css_preprocessor'] : '',
117 'add_to_existing' => isset( $_POST['add_to_existing'] ) ? $_POST['add_to_existing'] == 'true' : true,
118 'content_width' => isset( $_POST['custom_content_width'] ) ? $_POST['custom_content_width'] : false,
119 ) );
120
121 if ( $_POST['action'] == 'preview' ) {
122 wp_safe_redirect( add_query_arg( 'csspreview', 'true', get_option( 'home' ) ) );
123 exit;
124 }
125
126 if ( $save_result )
127 add_action( 'admin_notices', array( 'Jetpack_Custom_CSS', 'saved_message' ) );
128 }
129
130 // Prevent content filters running on CSS when restoring revisions
131 if ( isset( $_REQUEST[ 'action' ] ) && 'restore' === $_REQUEST[ 'action' ] && false !== strstr( $_SERVER[ 'REQUEST_URI' ], 'revision.php' ) ) {
132 $parent_post = get_post( wp_get_post_parent_id( intval( $_REQUEST[ 'revision' ] ) ) );
133 if ( $parent_post && ! is_wp_error( $parent_post ) && 'safecss' === $parent_post->post_type ) {
134 // Remove wp_filter_post_kses, this causes CSS escaping issues
135 remove_filter( 'content_save_pre', 'wp_filter_post_kses' );
136 remove_filter( 'content_filtered_save_pre', 'wp_filter_post_kses' );
137 remove_all_filters( 'content_save_pre' );
138 }
139 }
140
141 // Modify all internal links so that preview state persists
142 if ( Jetpack_Custom_CSS::is_preview() )
143 ob_start( array( 'Jetpack_Custom_CSS', 'buffer' ) );
144 }
145
146 /**
147 * Save new custom CSS. This should be the entry point for any third-party code using Jetpack_Custom_CSS
148 * to save CSS.
149 *
150 * @param array $args Array of arguments:
151 * string $css The CSS (or LESS or Sass)
152 * bool $is_preview Whether this CSS is preview or published
153 * string preprocessor Which CSS preprocessor to use
154 * bool $add_to_existing Whether this CSS replaces the theme's CSS or supplements it.
155 * int $content_width A custom $content_width to go along with this CSS.
156 * @return int The post ID of the saved Custom CSS post.
157 */
158 public static function save( $args = array() ) {
159 $defaults = array(
160 'css' => '',
161 'is_preview' => false,
162 'preprocessor' => '',
163 'add_to_existing' => true,
164 'content_width' => false,
165 );
166
167 $args = wp_parse_args( $args, $defaults );
168
169 if ( $args['content_width'] && intval( $args['content_width']) > 0 && ( ! isset( $GLOBALS['content_width'] ) || $args['content_width'] != $GLOBALS['content_width'] ) )
170 $args['content_width'] = intval( $args['content_width'] );
171 else
172 $args['content_width'] = false;
173
174 // Remove wp_filter_post_kses, this causes CSS escaping issues
175 remove_filter( 'content_save_pre', 'wp_filter_post_kses' );
176 remove_filter( 'content_filtered_save_pre', 'wp_filter_post_kses' );
177 remove_all_filters( 'content_save_pre' );
178
179 /**
180 * Fires prior to saving custom css values. Necessitated because the
181 * core WordPress save_pre filters were removed:
182 * - content_save_pre
183 * - content_filtered_save_pre
184 *
185 * @module custom-css
186 *
187 * @since 1.7.0
188 *
189 * @param array $args {
190 * Array of custom CSS arguments.
191 * @type string $css The CSS (or LESS or Sass).
192 * @type bool $is_preview Whether this CSS is preview or published.
193 * @type string preprocessor Which CSS preprocessor to use.
194 * @type bool $add_to_existing Whether this CSS replaces the theme's CSS or supplements it.
195 * @type int $content_width A custom $content_width to go along with this CSS.
196 * }
197 */
198 do_action( 'safecss_save_pre', $args );
199
200 $warnings = array();
201
202 safecss_class();
203 $csstidy = new csstidy();
204 $csstidy->optimise = new safecss( $csstidy );
205
206 $csstidy->set_cfg( 'remove_bslash', false );
207 $csstidy->set_cfg( 'compress_colors', false );
208 $csstidy->set_cfg( 'compress_font-weight', false );
209 $csstidy->set_cfg( 'optimise_shorthands', 0 );
210 $csstidy->set_cfg( 'remove_last_;', false );
211 $csstidy->set_cfg( 'case_properties', false );
212 $csstidy->set_cfg( 'discard_invalid_properties', true );
213 $csstidy->set_cfg( 'css_level', 'CSS3.0' );
214 $csstidy->set_cfg( 'preserve_css', true );
215 $csstidy->set_cfg( 'template', dirname( __FILE__ ) . '/csstidy/wordpress-standard.tpl' );
216
217 $css = $orig = $args['css'];
218
219 $css = preg_replace( '/\\\\([0-9a-fA-F]{4})/', '\\\\\\\\$1', $prev = $css );
220 // prevent content: '\3434' from turning into '\\3434'
221 $css = str_replace( array( '\'\\\\', '"\\\\' ), array( '\'\\', '"\\' ), $css );
222
223 if ( $css != $prev )
224 $warnings[] = 'preg_replace found stuff';
225
226 // Some people put weird stuff in their CSS, KSES tends to be greedy
227 $css = str_replace( '<=', '&lt;=', $css );
228 // Why KSES instead of strip_tags? Who knows?
229 $css = wp_kses_split( $prev = $css, array(), array() );
230 $css = str_replace( '&gt;', '>', $css ); // kses replaces lone '>' with &gt;
231 // Why both KSES and strip_tags? Because we just added some '>'.
232 $css = strip_tags( $css );
233
234 if ( $css != $prev )
235 $warnings[] = 'kses found stuff';
236
237 // if we're not using a preprocessor
238 if ( ! $args['preprocessor'] ) {
239
240 /**
241 * Fires before parsing the css with CSSTidy, but only if
242 * the preprocessor is not configured for use.
243 *
244 * @module custom-css
245 *
246 * @since 1.7.0
247 *
248 * @param obj $csstidy The csstidy object.
249 * @param string $css Custom CSS.
250 * @param array $args Array of custom CSS arguments.
251 */
252 do_action( 'safecss_parse_pre', $csstidy, $css, $args );
253
254 $csstidy->parse( $css );
255
256 /**
257 * Fires after parsing the css with CSSTidy, but only if
258 * the preprocessor is not cinfigured for use.
259 *
260 * @module custom-css
261 *
262 * @since 1.7.0
263 *
264 * @param obj $csstidy The csstidy object.
265 * @param array $warnings Array of warnings.
266 * @param array $args Array of custom CSS arguments.
267 */
268 do_action( 'safecss_parse_post', $csstidy, $warnings, $args );
269
270 $css = $csstidy->print->plain();
271 }
272
273 if ( $args['add_to_existing'] )
274 $add_to_existing = 'yes';
275 else
276 $add_to_existing = 'no';
277
278 if ( $args['is_preview'] || Jetpack_Custom_CSS::is_freetrial() ) {
279 // Save the CSS
280 $safecss_revision_id = Jetpack_Custom_CSS::save_revision( $css, true, $args['preprocessor'] );
281
282 // Cache Buster
283 update_option( 'safecss_preview_rev', intval( get_option( 'safecss_preview_rev' ) ) + 1);
284
285 update_metadata( 'post', $safecss_revision_id, 'custom_css_add', $add_to_existing );
286 update_metadata( 'post', $safecss_revision_id, 'content_width', $args['content_width'] );
287 update_metadata( 'post', $safecss_revision_id, 'custom_css_preprocessor', $args['preprocessor'] );
288
289 delete_option( 'safecss_add' );
290 delete_option( 'safecss_content_width' );
291
292 if ( $args['is_preview'] ) {
293 return $safecss_revision_id;
294 }
295
296 /**
297 * Fires after saving Custom CSS.
298 *
299 * @module custom-css
300 *
301 * @since 1.7.0
302 */
303 do_action( 'safecss_save_preview_post' );
304 }
305
306 // Save the CSS
307 $safecss_post_id = Jetpack_Custom_CSS::save_revision( $css, false, $args['preprocessor'] );
308
309 $safecss_post_revision = Jetpack_Custom_CSS::get_current_revision();
310
311 update_option( 'safecss_rev', intval( get_option( 'safecss_rev' ) ) + 1 );
312
313 update_post_meta( $safecss_post_id, 'custom_css_add', $add_to_existing );
314 update_post_meta( $safecss_post_id, 'content_width', $args['content_width'] );
315 update_post_meta( $safecss_post_id, 'custom_css_preprocessor', $args['preprocessor'] );
316
317 delete_option( 'safecss_add' );
318 delete_option( 'safecss_content_width' );
319
320 update_metadata( 'post', $safecss_post_revision['ID'], 'custom_css_add', $add_to_existing );
321 update_metadata( 'post', $safecss_post_revision['ID'], 'content_width', $args['content_width'] );
322 update_metadata( 'post', $safecss_post_revision['ID'], 'custom_css_preprocessor', $args['preprocessor'] );
323
324 delete_option( 'safecss_preview_add' );
325
326 return $safecss_post_id;
327 }
328
329 /**
330 * Get the published custom CSS post.
331 *
332 * @return array
333 */
334 static function get_post() {
335 $custom_css_post_id = Jetpack_Custom_CSS::post_id();
336
337 if ( $custom_css_post_id )
338 return get_post( $custom_css_post_id, ARRAY_A );
339
340 return array();
341 }
342
343 /**
344 * Get the post ID of the published custom CSS post.
345 *
346 * @return int|bool The post ID if it exists; false otherwise.
347 */
348 static function post_id() {
349 /**
350 * Filter the ID of the post where Custom CSS is stored, before the ID is retrieved.
351 *
352 * If the callback function returns a non-null value, then post_id() will immediately
353 * return that value, instead of retrieving the normal post ID.
354 *
355 * @module custom-css
356 *
357 * @since 3.8.1
358 *
359 * @param null null The ID to return instead of the normal ID.
360 */
361 $custom_css_post_id = apply_filters( 'jetpack_custom_css_pre_post_id', null );
362 if ( ! is_null( $custom_css_post_id ) ) {
363 return $custom_css_post_id;
364 }
365
366 $custom_css_post_id = wp_cache_get( 'custom_css_post_id' );
367
368 if ( false === $custom_css_post_id ) {
369 $custom_css_posts = get_posts( array(
370 'posts_per_page' => 1,
371 'post_type' => 'safecss',
372 'post_status' => 'publish',
373 'orderby' => 'date',
374 'order' => 'DESC'
375 ) );
376
377 if ( count( $custom_css_posts ) > 0 )
378 $custom_css_post_id = $custom_css_posts[0]->ID;
379 else
380 $custom_css_post_id = 0;
381
382 // Save post_id=0 to note that no safecss post exists.
383 wp_cache_set( 'custom_css_post_id', $custom_css_post_id );
384 }
385
386 if ( ! $custom_css_post_id )
387 return false;
388
389 return $custom_css_post_id;
390 }
391
392 /**
393 * Get the current revision of the original safecss record
394 *
395 * @return object
396 */
397 static function get_current_revision() {
398 $safecss_post = Jetpack_Custom_CSS::get_post();
399
400 if ( empty( $safecss_post ) ) {
401 return false;
402 }
403
404 $revisions = wp_get_post_revisions( $safecss_post['ID'], array( 'posts_per_page' => 1, 'orderby' => 'date', 'order' => 'DESC' ) );
405
406 // Empty array if no revisions exist
407 if ( empty( $revisions ) ) {
408 // Return original post
409 return $safecss_post;
410 } else {
411 // Return the first entry in $revisions, this will be the current revision
412 $current_revision = get_object_vars( array_shift( $revisions ) );
413 return $current_revision;
414 }
415 }
416
417 /**
418 * Save new revision of CSS
419 * Checks to see if content was modified before really saving
420 *
421 * @param string $css
422 * @param bool $is_preview
423 * @return bool|int If nothing was saved, returns false. If a post
424 * or revision was saved, returns the post ID.
425 */
426 static function save_revision( $css, $is_preview = false, $preprocessor = '' ) {
427 $safecss_post = Jetpack_Custom_CSS::get_post();
428
429 $compressed_css = Jetpack_Custom_CSS::minify( $css, $preprocessor );
430
431 // If null, there was no original safecss record, so create one
432 if ( null == $safecss_post ) {
433 if ( ! $css )
434 return false;
435
436 $post = array();
437 $post['post_content'] = wp_slash( $css );
438 $post['post_title'] = 'safecss';
439 $post['post_status'] = 'publish';
440 $post['post_type'] = 'safecss';
441 $post['post_content_filtered'] = wp_slash( $compressed_css );
442
443 // Set excerpt to current theme, for display in revisions list
444 $current_theme = wp_get_theme();
445 $post['post_excerpt'] = $current_theme->Name;
446
447 // Insert the CSS into wp_posts
448 $post_id = wp_insert_post( $post );
449 wp_cache_set( 'custom_css_post_id', $post_id );
450 return $post_id;
451 }
452
453 // Update CSS in post array with new value passed to this function
454 $safecss_post['post_content'] = $css;
455 $safecss_post['post_content_filtered'] = $compressed_css;
456
457 // Set excerpt to current theme, for display in revisions list
458 $current_theme = wp_get_theme();
459 $safecss_post['post_excerpt'] = $current_theme->Name;
460
461 // Don't carry over last revision's timestamps, otherwise revisions all have matching timestamps
462 unset( $safecss_post['post_date'] );
463 unset( $safecss_post['post_date_gmt'] );
464 unset( $safecss_post['post_modified'] );
465 unset( $safecss_post['post_modified_gmt'] );
466
467 // Do not update post if we are only saving a preview
468 if ( false === $is_preview ) {
469 $safecss_post['post_content'] = wp_slash( $safecss_post['post_content'] );
470 $safecss_post['post_content_filtered'] = wp_slash( $safecss_post['post_content_filtered'] );
471 $post_id = wp_update_post( $safecss_post );
472 wp_cache_set( 'custom_css_post_id', $post_id );
473 return $post_id;
474 }
475 else if ( ! defined( 'DOING_MIGRATE' ) ) {
476 return _wp_put_post_revision( $safecss_post );
477 }
478 }
479
480 static function skip_stylesheet() {
481 /**
482 * Prevent the Custom CSS stylesheet from being enqueued.
483 *
484 * @module custom-css
485 *
486 * @since 2.2.1
487 *
488 * @param null Should the stylesheet be skipped. Default to null. Anything else will force the stylesheet to be skipped.
489 */
490 $skip_stylesheet = apply_filters( 'safecss_skip_stylesheet', null );
491
492 if ( null !== $skip_stylesheet ) {
493 return $skip_stylesheet;
494 } elseif ( Jetpack_Custom_CSS::is_customizer_preview() ) {
495 return false;
496 } else {
497 if ( Jetpack_Custom_CSS::is_preview() ) {
498 $safecss_post = Jetpack_Custom_CSS::get_current_revision();
499
500 if ( $safecss_post )
501 return (bool) ( get_post_meta( $safecss_post['ID'], 'custom_css_add', true ) == 'no' );
502 else
503 return (bool) ( get_option( 'safecss_preview_add' ) == 'no' );
504 }
505 else {
506 $custom_css_post_id = Jetpack_Custom_CSS::post_id();
507
508 if ( $custom_css_post_id ) {
509 $custom_css_add = get_post_meta( $custom_css_post_id, 'custom_css_add', true );
510
511 // It is possible for the CSS to be stored in a post but for the safecss_add option
512 // to have not been upgraded yet if the user hasn't opened their Custom CSS editor
513 // since October 2012.
514 if ( ! empty( $custom_css_add ) )
515 return (bool) ( $custom_css_add === 'no' );
516 }
517
518 return (bool) ( Jetpack_Options::get_option_and_ensure_autoload( 'safecss_add', '' ) == 'no' );
519 }
520 }
521 }
522
523 static function is_preview() {
524 return isset( $_GET['csspreview'] ) && $_GET['csspreview'] === 'true';
525 }
526
527 /**
528 * Currently this filter function gets called on
529 * 'template_redirect' action and
530 * 'admin_init' action
531 */
532 static function set_content_width(){
533 // Don't apply this filter on the Edit CSS page
534 if ( isset( $_GET ) && isset( $_GET['page'] ) && 'editcss' == $_GET['page'] && is_admin() ) {
535 return;
536 }
537
538 $GLOBALS['content_width'] = Jetpack::get_content_width();
539 }
540
541 /*
542 * False when the site has the Custom Design upgrade.
543 * Used only on WordPress.com.
544 */
545 static function is_freetrial() {
546 /**
547 * Determine if a WordPress.com site uses a Free trial of the Custom Design Upgrade.
548 * Used only on WordPress.com.
549 *
550 * @module custom-css
551 *
552 * @since 1.7.0
553 *
554 * @param bool false Does the site use a Free trial of the Custom Design Upgrade. Default to false.
555 */
556 return apply_filters( 'safecss_is_freetrial', false );
557 }
558
559 static function get_preprocessor_key() {
560 $safecss_post = Jetpack_Custom_CSS::get_current_revision();
561 return get_post_meta( $safecss_post['ID'], 'custom_css_preprocessor', true );
562 }
563
564 static function get_preprocessor() {
565 /** This filter is documented in modules/custom-css/custom-css.php */
566 $preprocessors = apply_filters( 'jetpack_custom_css_preprocessors', array() );
567 $selected_preprocessor_key = self::get_preprocessor_key();
568 $selected_preprocessor = isset( $preprocessors[ $selected_preprocessor_key ] ) ? $preprocessors[ $selected_preprocessor_key ] : null;
569 return $selected_preprocessor;
570 }
571
572 static function get_css( $compressed = false ) {
573 /**
574 * Filter the Custom CSS returned.
575 * Can be used to return an error, or no CSS at all.
576 *
577 * @module custom-css
578 *
579 * @since 1.7.0
580 *
581 * @param bool false Should we return an error instead of the Custom CSS. Default to false.
582 */
583 $default_css = apply_filters( 'safecss_get_css_error', false );
584
585 if ( $default_css !== false )
586 return $default_css;
587
588 $option = ( Jetpack_Custom_CSS::is_preview() || Jetpack_Custom_CSS::is_freetrial() ) ? 'safecss_preview' : 'safecss';
589 $css = '';
590
591 if ( 'safecss' == $option ) {
592 // Don't bother checking for a migrated 'safecss' option if it never existed.
593 if ( false === get_option( 'safecss' ) || get_option( 'safecss_revision_migrated' ) ) {
594 $safecss_post = Jetpack_Custom_CSS::get_post();
595 if ( ! empty( $safecss_post ) ) {
596 $css = ( $compressed && $safecss_post['post_content_filtered'] ) ? $safecss_post['post_content_filtered'] : $safecss_post['post_content'];
597 }
598 } else {
599 $current_revision = Jetpack_Custom_CSS::get_current_revision();
600 if ( false === $current_revision ) {
601 $css = '';
602 } else {
603 $css = ( $compressed && $current_revision['post_content_filtered'] ) ? $current_revision['post_content_filtered'] : $current_revision['post_content'];
604 }
605 }
606
607 // Fix for un-migrated Custom CSS
608 if ( empty( $safecss_post ) ) {
609 $_css = get_option( 'safecss' );
610 if ( !empty( $_css ) ) {
611 $css = $_css;
612 }
613 }
614 }
615 else if ( 'safecss_preview' == $option ) {
616 $safecss_post = Jetpack_Custom_CSS::get_current_revision();
617 $css = $safecss_post['post_content'];
618 $css = Jetpack_Custom_CSS::minify( $css, get_post_meta( $safecss_post['ID'], 'custom_css_preprocessor', true ) );
619 }
620
621 $css = str_replace( array( '\\\00BB \\\0020', '\0BB \020', '0BB 020' ), '\00BB \0020', $css );
622
623 if ( empty( $css ) ) {
624 $css = "/*\n"
625 . wordwrap(
626 /**
627 * Filter the default message displayed in the Custom CSS editor.
628 *
629 * @module custom-css
630 *
631 * @since 1.7.0
632 *
633 * @param string $str Default Custom CSS editor content.
634 */
635 apply_filters(
636 'safecss_default_css',
637 __(
638 "Welcome to Custom CSS!\n\nTo learn how this works, see https://wp.me/PEmnE-Bt",
639 'jetpack'
640 )
641 )
642 )
643 . "\n*/";
644 }
645
646 /**
647 * Filter the Custom CSS returned from the editor.
648 *
649 * @module custom-css
650 *
651 * @since 1.7.0
652 *
653 * @param string $css Custom CSS.
654 */
655 $css = apply_filters( 'safecss_css', $css );
656
657 return $css;
658 }
659
660 static function replace_insecure_urls( $css ) {
661 if ( ! function_exists( '_sa_get_frontend_https_url_replacement_map' ) ) {
662 return $css;
663 }
664 list( $http_urls, $secure_urls ) = _sa_get_frontend_https_url_replacement_map();
665
666 return str_replace( $http_urls, $secure_urls, $css );
667 }
668
669 static function print_css() {
670
671 /**
672 * Fires right before printing the custom CSS inside the <head> element.
673 *
674 * @module custom-css
675 *
676 * @since 1.7.0
677 */
678 do_action( 'safecss_print_pre' );
679 $css = Jetpack_Custom_CSS::get_css( true );
680 echo self::replace_insecure_urls( $css );
681 }
682
683 static function should_we_inline_custom_css( $should_we, $css ) {
684 // If the CSS is less than 2,000 characters, inline it! otherwise return what was passed in.
685 return ( strlen( $css ) < 2000 ) ? true : $should_we;
686 }
687
688 static function link_tag() {
689 global $blog_id, $current_blog;
690
691 if (
692 /**
693 * Do not include any CSS on the page if the CSS includes an error.
694 * Setting this filter to true stops any Custom CSS from being enqueued.
695 *
696 * @module custom-css
697 *
698 * @since 1.7.0
699 *
700 * @param bool false Does the CSS include an error. Default to false.
701 */
702 apply_filters( 'safecss_style_error', false )
703 ) {
704 return;
705 }
706
707 if ( ! is_super_admin() && isset( $current_blog ) && ( 1 == $current_blog->spam || 1 == $current_blog->deleted ) )
708 return;
709
710 if ( Jetpack_Custom_CSS::is_customizer_preview() )
711 return;
712
713 $css = '';
714 $option = Jetpack_Custom_CSS::is_preview() ? 'safecss_preview' : 'safecss';
715
716 if ( 'safecss' == $option ) {
717 if ( Jetpack_Options::get_option_and_ensure_autoload( 'safecss_revision_migrated', '0' ) ) {
718 $safecss_post = Jetpack_Custom_CSS::get_post();
719
720 if ( ! empty( $safecss_post['post_content'] ) ) {
721 $css = $safecss_post['post_content'];
722 }
723 } else {
724 $current_revision = Jetpack_Custom_CSS::get_current_revision();
725
726 if ( ! empty( $current_revision['post_content'] ) ) {
727 $css = $current_revision['post_content'];
728 }
729 }
730
731 // Fix for un-migrated Custom CSS
732 if ( empty( $safecss_post ) ) {
733 $_css = Jetpack_Options::get_option_and_ensure_autoload( 'safecss', '' );
734 if ( !empty( $_css ) ) {
735 $css = $_css;
736 }
737 }
738 }
739
740 if ( 'safecss_preview' == $option ) {
741 $safecss_post = Jetpack_Custom_CSS::get_current_revision();
742
743 if ( !empty( $safecss_post['post_content'] ) ) {
744 $css = $safecss_post['post_content'];
745 }
746 }
747
748 $css = str_replace( array( '\\\00BB \\\0020', '\0BB \020', '0BB 020' ), '\00BB \0020', $css );
749
750 if ( $css == '' )
751 return;
752
753 if (
754 /**
755 * Allow inserting CSS inline instead of through a separate file.
756 *
757 * @module custom-css
758 *
759 * @since 3.4.0
760 *
761 * @param bool false Should the CSS be added inline instead of through a separate file. Default to false.
762 * @param string $css Custom CSS.
763 */
764 apply_filters( 'safecss_embed_style', false, $css )
765 ) {
766
767 echo "\r\n" . '<style id="custom-css-css">' . Jetpack_Custom_CSS::get_css( true ) . "</style>\r\n";
768
769 } else {
770
771 $href = home_url( '/' );
772 $href = add_query_arg( 'custom-css', 1, $href );
773 $href = add_query_arg( 'csblog', $blog_id, $href );
774 $href = add_query_arg( 'cscache', 6, $href );
775 $href = add_query_arg( 'csrev', (int) get_option( $option . '_rev' ), $href );
776
777 /**
778 * Filter the Custom CSS link enqueued in the head.
779 *
780 * @module custom-css
781 *
782 * @since 1.7.0
783 *
784 * @param string $href Custom CSS link enqueued in the head.
785 * @param string $blog_id Blog ID.
786 */
787 $href = apply_filters( 'safecss_href', $href, $blog_id );
788
789 if ( Jetpack_Custom_CSS::is_preview() )
790 $href = add_query_arg( 'csspreview', 'true', $href );
791
792 ?>
793 <link rel="stylesheet" id="custom-css-css" type="text/css" href="<?php echo esc_url( $href ); ?>" />
794 <?php
795
796 }
797
798 /**
799 * Fires after creating the <link> in the <head> element for the custom css stylesheet.
800 *
801 * @module custom-css
802 *
803 * @since 2.2.2
804 */
805 do_action( 'safecss_link_tag_post' );
806 }
807
808 static function style_filter( $current ) {
809 if ( Jetpack_Custom_CSS::is_freetrial() && ( ! Jetpack_Custom_CSS::is_preview() || ! current_user_can( 'switch_themes' ) ) )
810 return $current;
811 else if ( Jetpack_Custom_CSS::skip_stylesheet() )
812 /**
813 * Filter the default blank Custom CSS URL.
814 *
815 * @module custom-css
816 *
817 * @since 2.2.1
818 *
819 * @param string $url Default blank Custom CSS URL.
820 */
821 return apply_filters( 'safecss_style_filter_url', plugins_url( 'custom-css/css/blank.css', __FILE__ ) );
822
823 return $current;
824 }
825
826 static function buffer( $html ) {
827 $html = str_replace( '</body>', Jetpack_Custom_CSS::preview_flag(), $html );
828 return preg_replace_callback( '!href=([\'"])(.*?)\\1!', array( 'Jetpack_Custom_CSS', 'preview_links' ), $html );
829 }
830
831 static function preview_links( $matches ) {
832 if ( 0 !== strpos( $matches[2], get_option( 'home' ) ) )
833 return $matches[0];
834
835 $link = wp_specialchars_decode( $matches[2] );
836 $link = add_query_arg( 'csspreview', 'true', $link );
837 $link = esc_url( $link );
838 return "href={$matches[1]}$link{$matches[1]}";
839 }
840
841 /**
842 * Places a black bar above every preview page
843 */
844 static function preview_flag() {
845 if ( is_admin() )
846 return;
847
848 $message = esc_html__( 'Preview: changes must be saved or they will be lost', 'jetpack' );
849 /**
850 * Filter the Preview message displayed on the site when previewing custom CSS, before to save it.
851 *
852 * @module custom-css
853 *
854 * @since 1.7.0
855 *
856 * @param string $message Custom CSS preview message.
857 */
858 $message = apply_filters( 'safecss_preview_message', $message );
859
860 $preview_flag_js = "var flag = document.createElement('div');
861 flag.innerHTML = " . json_encode( $message ) . ";
862 flag.style.background = '#FF6600';
863 flag.style.color = 'white';
864 flag.style.textAlign = 'center';
865 flag.style.fontSize = '15px';
866 flag.style.padding = '2px';
867 flag.style.fontFamily = 'sans-serif';
868 document.body.style.paddingTop = '0px';
869 document.body.insertBefore(flag, document.body.childNodes[0]);
870 ";
871
872 /**
873 * Filter the Custom CSS preview message JS styling.
874 *
875 * @module custom-css
876 *
877 * @since 1.7.0
878 *
879 * @param string $preview_flag_js Custom CSS preview message JS styling.
880 */
881 $preview_flag_js = apply_filters( 'safecss_preview_flag_js', $preview_flag_js );
882 if ( $preview_flag_js ) {
883 $preview_flag_js = '<script type="text/javascript">
884 // <![CDATA[
885 ' . $preview_flag_js . '
886 // ]]>
887 </script>';
888 }
889
890 return $preview_flag_js;
891 }
892
893 static function menu() {
894 $parent = 'themes.php';
895 $title = __( 'Edit CSS', 'jetpack' );
896 $hook = add_theme_page( $title, $title, 'edit_theme_options', 'editcss', array( 'Jetpack_Custom_CSS', 'admin' ) );
897
898 add_action( "load-revision.php", array( 'Jetpack_Custom_CSS', 'prettify_post_revisions' ) );
899 add_action( "load-$hook", array( 'Jetpack_Custom_CSS', 'update_title' ) );
900 }
901
902 /**
903 * Adds a menu item in the appearance section for this plugin's administration
904 * page. Also adds hooks to enqueue the CSS and JS for the admin page.
905 */
906 static function update_title() {
907 global $title;
908 $title = __( 'CSS', 'jetpack' );
909 }
910
911 static function prettify_post_revisions() {
912 add_filter( 'the_title', array( 'Jetpack_Custom_CSS', 'post_title' ), 10, 2 );
913 }
914
915 static function post_title( $title, $post_id ) {
916 if ( !$post_id = (int) $post_id ) {
917 return $title;
918 }
919
920 if ( !$post = get_post( $post_id ) ) {
921 return $title;
922 }
923
924 if ( 'safecss' != $post->post_type ) {
925 return $title;
926 }
927
928 return __( 'Custom CSS Stylesheet', 'jetpack' );
929 }
930
931 static function enqueue_scripts( $hook ) {
932 if ( 'appearance_page_editcss' != $hook )
933 return;
934
935 wp_enqueue_script( 'postbox' );
936 wp_enqueue_script(
937 'custom-css-editor',
938 Assets::get_file_url_for_environment(
939 '_inc/build/custom-css/custom-css/js/css-editor.min.js',
940 'modules/custom-css/custom-css/js/css-editor.js'
941 ),
942 'jquery',
943 '20130325',
944 true
945 );
946 wp_enqueue_style( 'custom-css-editor', plugins_url( 'custom-css/css/css-editor.css', __FILE__ ) );
947
948 if ( defined( 'SAFECSS_USE_ACE' ) && SAFECSS_USE_ACE ) {
949 wp_register_style( 'jetpack-css-codemirror', plugins_url( 'custom-css/css/codemirror.css', __FILE__ ), array(), '20120905' );
950 wp_enqueue_style( 'jetpack-css-use-codemirror', plugins_url( 'custom-css/css/use-codemirror.css', __FILE__ ), array( 'jetpack-css-codemirror' ), '20120905' );
951
952 wp_register_script( 'jetpack-css-codemirror', plugins_url( 'custom-css/js/codemirror.min.js', __FILE__ ), array(), '3.16', true );
953 wp_enqueue_script(
954 'jetpack-css-use-codemirror',
955 Assets::get_file_url_for_environment(
956 '_inc/build/custom-css/custom-css/js/use-codemirror.min.js',
957 'modules/custom-css/custom-css/js/use-codemirror.js'
958 ),
959 array( 'jquery', 'underscore', 'jetpack-css-codemirror' ),
960 '20131009',
961 true
962 );
963 }
964 }
965
966 static function saved_message() {
967 echo '<div id="message" class="updated fade"><p><strong>' . __( 'Stylesheet saved.', 'jetpack' ) . '</strong></p></div>';
968 }
969
970 static function admin() {
971 add_meta_box( 'submitdiv', __( 'Publish', 'jetpack' ), array( __CLASS__, 'publish_box' ), 'editcss', 'side' );
972 add_action( 'custom_css_submitbox_misc_actions', array( __CLASS__, 'content_width_settings' ) );
973
974 $safecss_post = Jetpack_Custom_CSS::get_post();
975
976 if ( ! empty( $safecss_post ) && 0 < $safecss_post['ID'] && wp_get_post_revisions( $safecss_post['ID'], array( 'posts_per_page' => 1 ) ) )
977 add_meta_box( 'revisionsdiv', __( 'CSS Revisions', 'jetpack' ), array( __CLASS__, 'revisions_meta_box' ), 'editcss', 'side' );
978 ?>
979 <div class="wrap">
980 <?php
981
982 /**
983 * Fires right before the custom css page begins.
984 *
985 * @module custom-css
986 *
987 * @since 1.7.0
988 */
989 do_action( 'custom_design_header' );
990
991 ?>
992 <h1><?php _e( 'CSS Stylesheet Editor', 'jetpack' ); ?></h1>
993 <form id="safecssform" action="" method="post">
994 <?php wp_nonce_field( 'safecss' ) ?>
995 <?php wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false ); ?>
996 <?php wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false ); ?>
997 <input type="hidden" name="action" value="save" />
998 <div id="poststuff">
999 <p class="css-support">
1000 <?php
1001 /**
1002 * Filter the intro text appearing above the Custom CSS Editor.
1003 *
1004 * @module custom-css
1005 *
1006 * @since 1.7.0
1007 *
1008 * @param string $str Intro text appearing above the Custom CSS editor.
1009 */
1010 echo apply_filters( 'safecss_intro_text', __( 'New to CSS? Start with a <a href="https://www.htmldog.com/guides/css/beginner/" rel="noopener noreferrer" target="_blank">beginner tutorial</a>. Questions?
1011 Ask in the <a href="https://wordpress.org/support/forum/themes-and-templates" rel="noopener noreferrer" target="_blank">Themes and Templates forum</a>.', 'jetpack' ) );
1012 ?></p>
1013 <p class="css-support"><?php echo __( 'Note: Custom CSS will be reset when changing themes.', 'jetpack' ); ?></p>
1014
1015 <div id="post-body" class="metabox-holder columns-2">
1016 <div id="post-body-content">
1017 <div class="postarea">
1018 <textarea id="safecss" name="safecss"<?php if ( SAFECSS_USE_ACE ) echo ' class="hide-if-js"'; ?>><?php echo esc_textarea( Jetpack_Custom_CSS::get_css() ); ?></textarea>
1019 <div class="clear"></div>
1020 </div>
1021 </div>
1022 <div id="postbox-container-1" class="postbox-container">
1023 <?php do_meta_boxes( 'editcss', 'side', $safecss_post ); ?>
1024 </div>
1025 </div>
1026 <br class="clear" />
1027 </div>
1028 </form>
1029 </div>
1030 <?php
1031 }
1032
1033 /**
1034 * Content width setting callback
1035 */
1036 static function content_width_settings() {
1037 $safecss_post = Jetpack_Custom_CSS::get_current_revision();
1038
1039 $custom_content_width = get_post_meta( $safecss_post['ID'], 'content_width', true );
1040
1041 // If custom content width hasn't been overridden and the theme has a content_width value, use that as a default.
1042 if ( $custom_content_width <= 0 && ! empty( $GLOBALS['content_width'] ) )
1043 $custom_content_width = $GLOBALS['content_width'];
1044
1045 if ( ! $custom_content_width || ( isset( $GLOBALS['content_width'] ) && $custom_content_width == $GLOBALS['content_width'] ) )
1046 $custom_content_width = '';
1047
1048 ?>
1049 <div class="misc-pub-section">
1050 <label><?php esc_html_e( 'Media Width:', 'jetpack' ); ?></label>
1051 <span id="content-width-display" data-default-text="<?php esc_attr_e( 'Default', 'jetpack' ); ?>" data-custom-text="<?php esc_attr_e( '%s px', 'jetpack' ); ?>"><?php echo $custom_content_width ? sprintf( esc_html__( '%s px', 'jetpack' ), $custom_content_width ) : esc_html_e( 'Default', 'jetpack' ); ?></span>
1052 <a class="edit-content-width hide-if-no-js" href="#content-width"><?php echo esc_html_e( 'Edit', 'jetpack' ); ?></a>
1053 <div id="content-width-select" class="hide-if-js">
1054 <input type="hidden" name="custom_content_width" id="custom_content_width" value="<?php echo esc_attr( $custom_content_width ); ?>" />
1055 <p>
1056 <?php
1057
1058 printf( /* translators: %1$s is replaced with an input field for numbers. */
1059 __( 'Limit width to %1$s pixels for full size images. (<a href="%2$s" rel="noopener noreferrer" target="_blank">More info</a>.)', 'jetpack' ),
1060 '<input type="text" id="custom_content_width_visible" value="' . esc_attr( $custom_content_width ) . '" size="4" />',
1061 /**
1062 * Filter the Custom CSS limited width's support doc URL.
1063 *
1064 * @module custom-css
1065 *
1066 * @since 2.2.3
1067 *
1068 * @param string $url Custom CSS limited width's support doc URL.
1069 */
1070 esc_url(
1071 apply_filters( 'safecss_limit_width_link', Redirect::get_url( 'jetpack-support-custom-css', array( 'anchor' => 'limited-width' ) ) )
1072 )
1073 );
1074
1075 ?>
1076 </p>
1077 <?php
1078
1079 if (
1080 ! empty( $GLOBALS['content_width'] )
1081 && $custom_content_width != $GLOBALS['content_width']
1082 ) {
1083 $current_theme = wp_get_theme()->Name;
1084
1085 ?>
1086 <p><?php printf( _n( 'The default content width for the %s theme is %d pixel.', 'The default content width for the %s theme is %d pixels.', intval( $GLOBALS['content_width'] ), 'jetpack' ), $current_theme, intval( $GLOBALS['content_width'] ) ); ?></p>
1087 <?php
1088 }
1089
1090 ?>
1091 <a class="save-content-width hide-if-no-js button" href="#content-width"><?php esc_html_e( 'OK', 'jetpack' ); ?></a>
1092 <a class="cancel-content-width hide-if-no-js" href="#content-width"><?php esc_html_e( 'Cancel', 'jetpack' ); ?></a>
1093 </div>
1094 <script type="text/javascript">
1095 jQuery( function ( $ ) {
1096 var defaultContentWidth = <?php echo isset( $GLOBALS['content_width'] ) ? json_encode( intval( $GLOBALS['content_width'] ) ) : 0; ?>;
1097
1098 $( '.edit-content-width' ).bind( 'click', function ( e ) {
1099 e.preventDefault();
1100
1101 $( '#content-width-select' ).slideDown();
1102 $( this ).hide();
1103 } );
1104
1105 $( '.cancel-content-width' ).bind( 'click', function ( e ) {
1106 e.preventDefault();
1107
1108 $( '#content-width-select' ).slideUp( function () {
1109 $( '.edit-content-width' ).show();
1110 $( '#custom_content_width_visible' ).val( $( '#custom_content_width' ).val() );
1111 } );
1112 } );
1113
1114 $( '.save-content-width' ).bind( 'click', function ( e ) {
1115 e.preventDefault();
1116
1117 $( '#content-width-select' ).slideUp();
1118
1119 var newContentWidth = parseInt( $( '#custom_content_width_visible' ).val(), 10 );
1120
1121 if ( newContentWidth && newContentWidth != defaultContentWidth ) {
1122 $( '#content-width-display' ).text(
1123 $( '#content-width-display' )
1124 .data( 'custom-text' )
1125 .replace( '%s', $( '#custom_content_width_visible' ).val() )
1126 );
1127 }
1128 else {
1129 $( '#content-width-display' ).text( $( '#content-width-display' ).data( 'default-text' ) );
1130 }
1131
1132 $( '#custom_content_width' ).val( $( '#custom_content_width_visible' ).val() );
1133 $( '.edit-content-width' ).show();
1134 } );
1135 } );
1136 </script>
1137 </div>
1138 <?php
1139 }
1140
1141 static function publish_box() {
1142 ?>
1143 <div id="minor-publishing">
1144 <div id="misc-publishing-actions">
1145 <?php
1146
1147 /**
1148 * Filter the array of available Custom CSS preprocessors.
1149 *
1150 * @module custom-css
1151 *
1152 * @since 2.0.3
1153 *
1154 * @param array array() Empty by default.
1155 */
1156 $preprocessors = apply_filters( 'jetpack_custom_css_preprocessors', array() );
1157
1158 if ( ! empty( $preprocessors ) ) {
1159 $safecss_post = Jetpack_Custom_CSS::get_current_revision();
1160 $selected_preprocessor_key = get_post_meta( $safecss_post['ID'], 'custom_css_preprocessor', true );
1161 $selected_preprocessor = isset( $preprocessors[$selected_preprocessor_key] ) ? $preprocessors[$selected_preprocessor_key] : null;
1162
1163 ?>
1164 <div class="misc-pub-section">
1165 <label><?php esc_html_e( 'Preprocessor:', 'jetpack' ); ?></label>
1166 <span id="preprocessor-display"><?php echo esc_html( $selected_preprocessor ? $selected_preprocessor['name'] : __( 'None', 'jetpack' ) ); ?></span>
1167 <a class="edit-preprocessor hide-if-no-js" href="#preprocessor"><?php echo esc_html_e( 'Edit', 'jetpack' ); ?></a>
1168 <div id="preprocessor-select" class="hide-if-js">
1169 <input type="hidden" name="custom_css_preprocessor" id="custom_css_preprocessor" value="<?php echo esc_attr( $selected_preprocessor_key ); ?>" />
1170 <select id="preprocessor_choices">
1171 <option value=""><?php esc_html_e( 'None', 'jetpack' ); ?></option>
1172 <?php
1173
1174 foreach ( $preprocessors as $preprocessor_key => $preprocessor ) {
1175 ?>
1176 <option value="<?php echo esc_attr( $preprocessor_key ); ?>" <?php selected( $selected_preprocessor_key, $preprocessor_key ); ?>><?php echo esc_html( $preprocessor['name'] ); ?></option>
1177 <?php
1178 }
1179
1180 ?>
1181 </select>
1182 <a class="save-preprocessor hide-if-no-js button" href="#preprocessor"><?php esc_html_e( 'OK', 'jetpack' ); ?></a>
1183 <a class="cancel-preprocessor hide-if-no-js" href="#preprocessor"><?php esc_html_e( 'Cancel', 'jetpack' ); ?></a>
1184 </div>
1185 </div>
1186 <?php
1187 }
1188
1189 $safecss_post = Jetpack_Custom_CSS::get_current_revision();
1190
1191 $add_css = ( get_post_meta( $safecss_post['ID'], 'custom_css_add', true ) != 'no' );
1192
1193 ?>
1194 <div class="misc-pub-section">
1195 <label><?php esc_html_e( 'Mode:', 'jetpack' ); ?></label>
1196 <span id="css-mode-display"><?php echo esc_html( $add_css ? __( 'Add-on', 'jetpack' ) : __( 'Replacement', 'jetpack' ) ); ?></span>
1197 <a class="edit-css-mode hide-if-no-js" href="#css-mode"><?php echo esc_html_e( 'Edit', 'jetpack' ); ?></a>
1198 <div id="css-mode-select" class="hide-if-js">
1199 <input type="hidden" name="add_to_existing" id="add_to_existing" value="<?php echo $add_css ? 'true' : 'false'; ?>" />
1200 <p>
1201 <label>
1202 <input type="radio" name="add_to_existing_display" value="true" <?php checked( $add_css ); ?>/>
1203 <?php _e( 'Add-on CSS <b>(Recommended)</b>', 'jetpack' ); ?>
1204 </label>
1205 <br />
1206 <label>
1207 <input type="radio" name="add_to_existing_display" value="false" <?php checked( ! $add_css ); ?>/>
1208 <?php printf(
1209 __( 'Replace <a href="%s">theme\'s CSS</a> <b>(Advanced)</b>', 'jetpack' ),
1210 /**
1211 * Filter the theme's stylesheet URL.
1212 *
1213 * @module custom-css
1214 *
1215 * @since 1.7.0
1216 *
1217 * @param string $url Active theme's stylesheet URL. Default to get_stylesheet_uri().
1218 */
1219 apply_filters( 'safecss_theme_stylesheet_url', get_stylesheet_uri() )
1220 ); ?>
1221 </label>
1222 </p>
1223 <a class="save-css-mode hide-if-no-js button" href="#css-mode"><?php esc_html_e( 'OK', 'jetpack' ); ?></a>
1224 <a class="cancel-css-mode hide-if-no-js" href="#css-mode"><?php esc_html_e( 'Cancel', 'jetpack' ); ?></a>
1225 </div>
1226 </div>
1227 <?php
1228
1229 /**
1230 * Allows addition of elements to the submit box for custom css on the wp-admin side.
1231 *
1232 * @module custom-css
1233 *
1234 * @since 2.0.3
1235 */
1236 do_action( 'custom_css_submitbox_misc_actions' );
1237
1238 ?>
1239 </div>
1240 </div>
1241 <div id="major-publishing-actions">
1242 <input type="button" class="button" id="preview" name="preview" value="<?php esc_attr_e( 'Preview', 'jetpack' ) ?>" />
1243 <div id="publishing-action">
1244 <input type="submit" class="button-primary" id="save" name="save" value="<?php ( Jetpack_Custom_CSS::is_freetrial() ) ? esc_attr_e( 'Save &amp; Buy Upgrade', 'jetpack' ) : esc_attr_e( 'Save Stylesheet', 'jetpack' ); ?>" />
1245 </div>
1246 </div>
1247 <?php
1248 }
1249
1250 /**
1251 * Render metabox listing CSS revisions and the themes that correspond to the revisions.
1252 * Called by safecss_admin
1253 *
1254 * @global $post
1255 * @param array $safecss_post
1256 * @uses wp_revisions_to_keep
1257 * @uses WP_Query
1258 * @uses wp_post_revision_title
1259 * @uses esc_html
1260 * @uses add_query_arg
1261 * @uses menu_page_url
1262 * @uses wp_reset_query
1263 * @return string
1264 */
1265 static function revisions_meta_box( $safecss_post ) {
1266
1267 $show_all_revisions = isset( $_GET['show_all_rev'] );
1268
1269 if ( function_exists( 'wp_revisions_to_keep' ) ) {
1270 $max_revisions = wp_revisions_to_keep( (object) $safecss_post );
1271 } else {
1272 $max_revisions = defined( 'WP_POST_REVISIONS' ) && is_numeric( WP_POST_REVISIONS ) ? (int) WP_POST_REVISIONS : 25;
1273 }
1274
1275 $posts_per_page = $show_all_revisions ? $max_revisions : 6;
1276
1277 $revisions = new WP_Query( array(
1278 'posts_per_page' => $posts_per_page,
1279 'post_type' => 'revision',
1280 'post_status' => 'inherit',
1281 'post_parent' => $safecss_post['ID'],
1282 'orderby' => 'date',
1283 'order' => 'DESC'
1284 ) );
1285
1286 if ( $revisions->have_posts() ) { ?>
1287 <ul class="post-revisions"><?php
1288
1289 global $post;
1290
1291 while ( $revisions->have_posts() ) :
1292 $revisions->the_post();
1293
1294 ?><li>
1295 <?php
1296 echo wp_post_revision_title( $post );
1297
1298 if ( ! empty( $post->post_excerpt ) )
1299 echo ' (' . esc_html( $post->post_excerpt ) . ')';
1300 ?>
1301 </li><?php
1302
1303 endwhile;
1304
1305 ?></ul><?php
1306
1307 if ( $revisions->found_posts > 6 && !$show_all_revisions ) {
1308 ?>
1309 <br>
1310 <a href="<?php echo add_query_arg( 'show_all_rev', 'true', menu_page_url( 'editcss', false ) ); ?>"><?php esc_html_e( 'Show all', 'jetpack' ); ?></a>
1311 <?php
1312 }
1313 }
1314
1315 wp_reset_query();
1316 }
1317
1318 /**
1319 * Hook in init at priority 11 to disable custom CSS.
1320 */
1321 static function disable() {
1322 remove_action( 'wp_head', array( 'Jetpack_Custom_CSS', 'link_tag' ), 101 );
1323 remove_filter( 'stylesheet_uri', array( 'Jetpack_Custom_CSS', 'style_filter' ) );
1324 }
1325
1326 /**
1327 * Reset all aspects of Custom CSS on a theme switch so that changing
1328 * themes is a sure-fire way to get a clean start.
1329 */
1330 static function reset() {
1331 $safecss_post_id = Jetpack_Custom_CSS::save_revision( '' );
1332 $safecss_revision = Jetpack_Custom_CSS::get_current_revision();
1333
1334 update_option( 'safecss_rev', intval( get_option( 'safecss_rev' ) ) + 1 );
1335
1336 update_post_meta( $safecss_post_id, 'custom_css_add', 'yes' );
1337 update_post_meta( $safecss_post_id, 'content_width', false );
1338 update_post_meta( $safecss_post_id, 'custom_css_preprocessor', '' );
1339
1340 delete_option( 'safecss_add' );
1341 delete_option( 'safecss_content_width' );
1342
1343 update_metadata( 'post', $safecss_revision['ID'], 'custom_css_add', 'yes' );
1344 update_metadata( 'post', $safecss_revision['ID'], 'content_width', false );
1345 update_metadata( 'post', $safecss_revision['ID'], 'custom_css_preprocessor', '' );
1346
1347 delete_option( 'safecss_preview_add' );
1348 }
1349
1350 static function is_customizer_preview() {
1351 if ( isset ( $GLOBALS['wp_customize'] ) )
1352 return ! $GLOBALS['wp_customize']->is_theme_active();
1353
1354 return false;
1355 }
1356
1357 static function minify( $css, $preprocessor = '' ) {
1358 if ( ! $css )
1359 return '';
1360
1361 if ( $preprocessor ) {
1362 /** This filter is documented in modules/custom-css/custom-css.php */
1363 $preprocessors = apply_filters( 'jetpack_custom_css_preprocessors', array() );
1364
1365 if ( isset( $preprocessors[$preprocessor] ) ) {
1366 $css = call_user_func( $preprocessors[$preprocessor]['callback'], $css );
1367 }
1368 }
1369
1370 safecss_class();
1371 $csstidy = new csstidy();
1372 $csstidy->optimise = new safecss( $csstidy );
1373
1374 $csstidy->set_cfg( 'remove_bslash', false );
1375 $csstidy->set_cfg( 'compress_colors', true );
1376 $csstidy->set_cfg( 'compress_font-weight', true );
1377 $csstidy->set_cfg( 'remove_last_;', true );
1378 $csstidy->set_cfg( 'case_properties', true );
1379 $csstidy->set_cfg( 'discard_invalid_properties', true );
1380 $csstidy->set_cfg( 'css_level', 'CSS3.0' );
1381 $csstidy->set_cfg( 'template', 'highest');
1382 $csstidy->parse( $css );
1383
1384 return $csstidy->print->plain();
1385 }
1386
1387 /**
1388 * When restoring a SafeCSS post revision, also copy over the
1389 * content_width and custom_css_add post metadata.
1390 */
1391 static function restore_revision( $_post_id, $_revision_id ) {
1392 $_post = get_post( $_post_id );
1393
1394 if ( 'safecss' != $_post->post_type )
1395 return;
1396
1397 $safecss_revision = Jetpack_Custom_CSS::get_current_revision();
1398
1399 $content_width = get_post_meta( $_revision_id, 'content_width', true );
1400 $custom_css_add = get_post_meta( $_revision_id, 'custom_css_add', true );
1401 $preprocessor = get_post_meta( $_revision_id, 'custom_css_preprocessor', true );
1402
1403 update_metadata( 'post', $safecss_revision['ID'], 'content_width', $content_width );
1404 update_metadata( 'post', $safecss_revision['ID'], 'custom_css_add', $custom_css_add );
1405 update_metadata( 'post', $safecss_revision['ID'], 'custom_css_preprocessor', $preprocessor );
1406
1407 delete_option( 'safecss_add' );
1408 delete_option( 'safecss_content_width' );
1409
1410 update_post_meta( $_post->ID, 'content_width', $content_width );
1411 update_post_meta( $_post->ID, 'custom_css_add', $custom_css_add );
1412 update_post_meta( $_post->ID, 'custom_css_preprocessor', $preprocessor );
1413
1414 delete_option( 'safecss_preview_add' );
1415 }
1416
1417 /**
1418 * Migration routine for moving safecss from wp_options to wp_posts to support revisions
1419 *
1420 * @return void
1421 */
1422 static function upgrade() {
1423 $css = get_option( 'safecss' );
1424
1425 if ( get_option( 'safecss_revision_migrated' ) ) {
1426 return false;
1427 }
1428
1429 // Check if CSS is stored in wp_options
1430 if ( $css ) {
1431 // Remove the async actions from publish_post
1432 remove_action( 'publish_post', 'queue_publish_post' );
1433
1434 $post = array();
1435 $post['post_content'] = $css;
1436 $post['post_title'] = 'safecss';
1437 $post['post_status'] = 'publish';
1438 $post['post_type'] = 'safecss';
1439
1440 // Insert the CSS into wp_posts
1441 $post_id = wp_insert_post( $post );
1442 // Check for errors
1443 if ( !$post_id or is_wp_error( $post_id ) )
1444 die( $post_id->get_error_message() );
1445
1446 // Delete safecss option
1447 delete_option( 'safecss' );
1448 }
1449
1450 unset( $css );
1451
1452 // Check if we have already done this
1453 if ( !get_option( 'safecss_revision_migrated' ) ) {
1454 define( 'DOING_MIGRATE', true );
1455
1456 // Get hashes of safecss post and current revision
1457 $safecss_post = Jetpack_Custom_CSS::get_post();
1458
1459 if ( empty( $safecss_post ) )
1460 return;
1461
1462 $safecss_post_hash = md5( $safecss_post['post_content'] );
1463 $current_revision = Jetpack_Custom_CSS::get_current_revision();
1464
1465 if ( null == $current_revision )
1466 return;
1467
1468 $current_revision_hash = md5( $current_revision['post_content'] );
1469
1470 // If hashes are not equal, set safecss post with content from current revision
1471 if ( $safecss_post_hash !== $current_revision_hash ) {
1472 Jetpack_Custom_CSS::save_revision( $current_revision['post_content'] );
1473 // Reset post_content to display the migrated revsion
1474 $safecss_post['post_content'] = $current_revision['post_content'];
1475 }
1476
1477 // Set option so that we dont keep doing this
1478 update_option( 'safecss_revision_migrated', time() );
1479 }
1480
1481 $newest_safecss_post = Jetpack_Custom_CSS::get_current_revision();
1482
1483 if ( $newest_safecss_post ) {
1484 if ( get_option( 'safecss_content_width' ) ) {
1485 // Add the meta to the post and the latest revision.
1486 update_post_meta( $newest_safecss_post['ID'], 'content_width', get_option( 'safecss_content_width' ) );
1487 update_metadata( 'post', $newest_safecss_post['ID'], 'content_width', get_option( 'safecss_content_width' ) );
1488
1489 delete_option( 'safecss_content_width' );
1490 }
1491
1492 if ( get_option( 'safecss_add' ) ) {
1493 update_post_meta( $newest_safecss_post['ID'], 'custom_css_add', get_option( 'safecss_add' ) );
1494 update_metadata( 'post', $newest_safecss_post['ID'], 'custom_css_add', get_option( 'safecss_add' ) );
1495
1496 delete_option( 'safecss_add' );
1497 }
1498 }
1499 }
1500
1501 /**
1502 * Adds a filter to the redirect location in `wp-admin/revisions.php`.
1503 */
1504 static function add_revision_redirect() {
1505 add_filter( 'wp_redirect', array( __CLASS__, 'revision_redirect' ) );
1506 }
1507
1508 /**
1509 * Filters the redirect location in `wp-admin/revisions.php`.
1510 *
1511 * @param string $location The path to redirect to.
1512 * @return string
1513 */
1514 static function revision_redirect( $location ) {
1515 $post = get_post();
1516
1517 if ( ! empty( $post->post_type ) && 'safecss' == $post->post_type ) {
1518 $location = 'themes.php?page=editcss';
1519
1520 if ( 'edit.php' == $location ) {
1521 $location = '';
1522 }
1523 }
1524
1525 return $location;
1526 }
1527
1528 static function revision_post_link( $post_link, $post_id, $context ) {
1529 if ( !$post_id = (int) $post_id ) {
1530 return $post_link;
1531 }
1532
1533 if ( !$post = get_post( $post_id ) ) {
1534 return $post_link;
1535 }
1536
1537 if ( 'safecss' != $post->post_type ) {
1538 return $post_link;
1539 }
1540
1541 $post_link = admin_url( 'themes.php?page=editcss' );
1542
1543 if ( 'display' == $context ) {
1544 return esc_url( $post_link );
1545 }
1546
1547 return esc_url_raw( $post_link );
1548 }
1549
1550 /**
1551 * When on the edit screen, make sure the custom content width
1552 * setting is applied to the large image size.
1553 */
1554 static function editor_max_image_size( $dims, $size = 'medium', $context = null ) {
1555 list( $width, $height ) = $dims;
1556
1557 if ( 'large' == $size && 'edit' == $context )
1558 $width = Jetpack::get_content_width();
1559
1560 return array( $width, $height );
1561 }
1562
1563 /**
1564 * Override the content_width with a custom value if one is set.
1565 */
1566 static function jetpack_content_width( $content_width ) {
1567 $custom_content_width = 0;
1568
1569 if ( Jetpack_Custom_CSS::is_preview() ) {
1570 $safecss_post = Jetpack_Custom_CSS::get_current_revision();
1571 $custom_content_width = intval( get_post_meta( $safecss_post['ID'], 'content_width', true ) );
1572 } else if ( ! Jetpack_Custom_CSS::is_freetrial() ) {
1573 $custom_css_post_id = Jetpack_Custom_CSS::post_id();
1574 if ( $custom_css_post_id )
1575 $custom_content_width = intval( get_post_meta( $custom_css_post_id, 'content_width', true ) );
1576 }
1577
1578 if ( $custom_content_width > 0 )
1579 $content_width = $custom_content_width;
1580
1581 return $content_width;
1582 }
1583 }
1584
1585 class Jetpack_Safe_CSS {
1586 static function filter_attr( $css, $element = 'div' ) {
1587 safecss_class();
1588
1589 $css = $element . ' {' . $css . '}';
1590
1591 $csstidy = new csstidy();
1592 $csstidy->optimise = new safecss( $csstidy );
1593 $csstidy->set_cfg( 'remove_bslash', false );
1594 $csstidy->set_cfg( 'compress_colors', false );
1595 $csstidy->set_cfg( 'compress_font-weight', false );
1596 $csstidy->set_cfg( 'discard_invalid_properties', true );
1597 $csstidy->set_cfg( 'merge_selectors', false );
1598 $csstidy->set_cfg( 'remove_last_;', false );
1599 $csstidy->set_cfg( 'css_level', 'CSS3.0' );
1600
1601 $css = preg_replace( '/\\\\([0-9a-fA-F]{4})/', '\\\\\\\\$1', $css );
1602 $css = wp_kses_split( $css, array(), array() );
1603 $csstidy->parse( $css );
1604
1605 $css = $csstidy->print->plain();
1606
1607 $css = str_replace( array( "\n","\r","\t" ), '', $css );
1608
1609 preg_match( "/^{$element}\s*{(.*)}\s*$/", $css, $matches );
1610
1611 if ( empty( $matches[1] ) )
1612 return '';
1613
1614 return $matches[1];
1615 }
1616 }
1617
1618 function migrate() {
1619 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::upgrade()' );
1620
1621 return Jetpack_Custom_CSS::upgrade();
1622 }
1623
1624 function safecss_revision_redirect( $redirect ) {
1625 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::revision_redirect()' );
1626
1627 return Jetpack_Custom_CSS::revision_redirect( $redirect );
1628 }
1629
1630 function safecss_revision_post_link( $post_link, $post_id, $context ) {
1631 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::revision_post_link()' );
1632
1633 return Jetpack_Custom_CSS::revision_post_link( $post_link, $post_id, $context );
1634 }
1635
1636 function get_safecss_post() {
1637 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::get_post()' );
1638
1639 return Jetpack_Custom_CSS::get_post();
1640 }
1641
1642 function custom_css_post_id() {
1643 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::post_id()' );
1644
1645 return Jetpack_Custom_CSS::post_id();
1646 }
1647
1648 function get_current_revision() {
1649 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::get_current_revision()' );
1650
1651 return Jetpack_Custom_CSS::get_current_revision();
1652 }
1653
1654 function save_revision( $css, $is_preview = false, $preprocessor = '' ) {
1655 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::save_revision()' );
1656
1657 return Jetpack_Custom_CSS::save_revision( $css, $is_preview, $preprocessor );
1658 }
1659
1660 function safecss_skip_stylesheet() {
1661 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::skip_stylesheet()' );
1662
1663 return Jetpack_Custom_CSS::skip_stylesheet();
1664 }
1665
1666 function safecss_init() {
1667 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::init()' );
1668
1669 return Jetpack_Custom_CSS::init();
1670 }
1671
1672 function safecss_is_preview() {
1673 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::is_preview()' );
1674
1675 return Jetpack_Custom_CSS::is_preview();
1676 }
1677
1678 function safecss_is_freetrial() {
1679 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::is_freetrial()' );
1680
1681 return Jetpack_Custom_CSS::is_freetrial();
1682 }
1683
1684 function safecss( $compressed = false ) {
1685 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::get_css()' );
1686
1687 return Jetpack_Custom_CSS::get_css( $compressed );
1688 }
1689
1690 function safecss_print() {
1691 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::print_css()' );
1692
1693 return Jetpack_Custom_CSS::print_css();
1694 }
1695
1696 function safecss_style() {
1697 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::link_tag()' );
1698
1699 return Jetpack_Custom_CSS::link_tag();
1700 }
1701
1702 function safecss_style_filter( $current ) {
1703 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::style_filter()' );
1704
1705 return Jetpack_Custom_CSS::style_filter( $current );
1706 }
1707
1708 function safecss_buffer( $html ) {
1709 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::buffer()' );
1710
1711 return Jetpack_Custom_CSS::buffer( $html );
1712 }
1713
1714 function safecss_preview_links( $matches ) {
1715 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::preview_links()' );
1716
1717 return Jetpack_Custom_CSS::preview_links( $matches );
1718 }
1719
1720 function safecss_preview_flag() {
1721 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::preview_flag()' );
1722
1723 return Jetpack_Custom_CSS::preview_flag();
1724 }
1725
1726 function safecss_menu() {
1727 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::menu()' );
1728
1729 return Jetpack_Custom_CSS::menu();
1730 }
1731
1732 function update_title() {
1733 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::update_title()' );
1734
1735 return Jetpack_Custom_CSS::update_title();
1736 }
1737
1738 function safecss_prettify_post_revisions() {
1739 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::prettify_post_revisions()' );
1740
1741 return Jetpack_Custom_CSS::prettify_post_revisions();
1742 }
1743
1744 function safecss_remove_title_excerpt_from_revisions() {
1745 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::remove_title_excerpt_from_revisions()' );
1746
1747 return Jetpack_Custom_CSS::remove_title_excerpt_from_revisions();
1748 }
1749
1750 function safecss_post_title( $title, $post_id ) {
1751 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::post_title()' );
1752
1753 return Jetpack_Custom_CSS::post_title( $title, $post_id );
1754 }
1755
1756 function safe_css_enqueue_scripts() {
1757 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::enqueue_scripts()' );
1758
1759 return Jetpack_Custom_CSS::enqueue_scripts( null );
1760 }
1761
1762 function safecss_admin_head() {
1763 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::admin_head()' );
1764
1765 return Jetpack_Custom_CSS::admin_head();
1766 }
1767
1768 function safecss_saved() {
1769 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::saved_message()' );
1770
1771 return Jetpack_Custom_CSS::saved_message();
1772 }
1773
1774 function safecss_admin() {
1775 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::admin()' );
1776
1777 return Jetpack_Custom_CSS::admin();
1778 }
1779
1780 function custom_css_meta_box() {
1781 _deprecated_function( __FUNCTION__, '2.1', 'add_meta_box( $id, $title, $callback, \'editcss\', \'side\' )' );
1782 }
1783
1784 function custom_css_post_revisions_meta_box( $safecss_post ) {
1785 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::revisions_meta_box()' );
1786
1787 return Jetpack_Custom_CSS::revisions_meta_box( $safecss_post );
1788 }
1789
1790 function disable_safecss_style() {
1791 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::disable()' );
1792
1793 return Jetpack_Custom_CSS::disable();
1794 }
1795
1796 function custom_css_reset() {
1797 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::reset()' );
1798
1799 return Jetpack_Custom_CSS::reset();
1800 }
1801
1802 function custom_css_is_customizer_preview() {
1803 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::is_customizer_preview()' );
1804
1805 return Jetpack_Custom_CSS::is_customizer_preview();
1806 }
1807
1808 function custom_css_minify( $css, $preprocessor = '' ) {
1809 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::minify()' );
1810
1811 return Jetpack_Custom_CSS::minify( $css, $preprocessor );
1812 }
1813
1814 function custom_css_restore_revision( $_post_id, $_revision_id ) {
1815 _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::restore_revision()' );
1816
1817 return Jetpack_Custom_CSS::restore_revision( $_post_id, $_revision_id );
1818 }
1819
1820 if ( ! function_exists( 'safecss_class' ) ) :
1821 function safecss_class() {
1822 // Wrapped so we don't need the parent class just to load the plugin
1823 if ( class_exists('safecss') )
1824 return;
1825
1826 require_once( dirname( __FILE__ ) . '/csstidy/class.csstidy.php' );
1827
1828 class safecss extends csstidy_optimise {
1829
1830 function postparse() {
1831
1832 /**
1833 * Fires after parsing the css.
1834 *
1835 * @module custom-css
1836 *
1837 * @since 1.8.0
1838 *
1839 * @param obj $this CSSTidy object.
1840 */
1841 do_action( 'csstidy_optimize_postparse', $this );
1842
1843 return parent::postparse();
1844 }
1845
1846 function subvalue() {
1847
1848 /**
1849 * Fires before optimizing the Custom CSS subvalue.
1850 *
1851 * @module custom-css
1852 *
1853 * @since 1.8.0
1854 *
1855 * @param obj $this CSSTidy object.
1856 **/
1857 do_action( 'csstidy_optimize_subvalue', $this );
1858
1859 return parent::subvalue();
1860 }
1861 }
1862 }
1863 endif;
1864
1865 if ( ! function_exists( 'safecss_filter_attr' ) ) {
1866 function safecss_filter_attr( $css, $element = 'div' ) {
1867 return Jetpack_Safe_CSS::filter_attr( $css, $element );
1868 }
1869 }
1870
1871 include_once dirname( __FILE__ ) . '/custom-css/preprocessors.php';
1872