PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 4.3.5
Jetpack – WP Security, Backup, Speed, & Growth v4.3.5
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 4.3.5, at modules/custom-css/custom-css.php

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