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

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

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