/modules/custom-css/custom-css.php

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