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