class-wp-customize-custom-css-setting.php 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. <?php
  2. /**
  3. * Customize API: WP_Customize_Custom_CSS_Setting class
  4. *
  5. * This handles validation, sanitization and saving of the value.
  6. *
  7. * @package WordPress
  8. * @subpackage Customize
  9. * @since 4.7.0
  10. */
  11. /**
  12. * Custom Setting to handle WP Custom CSS.
  13. *
  14. * @since 4.7.0
  15. *
  16. * @see WP_Customize_Setting
  17. */
  18. final class WP_Customize_Custom_CSS_Setting extends WP_Customize_Setting {
  19. /**
  20. * The setting type.
  21. *
  22. * @since 4.7.0
  23. * @var string
  24. */
  25. public $type = 'custom_css';
  26. /**
  27. * Setting Transport
  28. *
  29. * @since 4.7.0
  30. * @var string
  31. */
  32. public $transport = 'postMessage';
  33. /**
  34. * Capability required to edit this setting.
  35. *
  36. * @since 4.7.0
  37. * @var string
  38. */
  39. public $capability = 'edit_css';
  40. /**
  41. * Stylesheet
  42. *
  43. * @since 4.7.0
  44. * @var string
  45. */
  46. public $stylesheet = '';
  47. /**
  48. * WP_Customize_Custom_CSS_Setting constructor.
  49. *
  50. * @since 4.7.0
  51. *
  52. * @throws Exception If the setting ID does not match the pattern `custom_css[$stylesheet]`.
  53. *
  54. * @param WP_Customize_Manager $manager The Customize Manager class.
  55. * @param string $id An specific ID of the setting. Can be a
  56. * theme mod or option name.
  57. * @param array $args Setting arguments.
  58. */
  59. public function __construct( $manager, $id, $args = array() ) {
  60. parent::__construct( $manager, $id, $args );
  61. if ( 'custom_css' !== $this->id_data['base'] ) {
  62. throw new Exception( 'Expected custom_css id_base.' );
  63. }
  64. if ( 1 !== count( $this->id_data['keys'] ) || empty( $this->id_data['keys'][0] ) ) {
  65. throw new Exception( 'Expected single stylesheet key.' );
  66. }
  67. $this->stylesheet = $this->id_data['keys'][0];
  68. }
  69. /**
  70. * Add filter to preview post value.
  71. *
  72. * @since 4.7.9
  73. *
  74. * @return bool False when preview short-circuits due no change needing to be previewed.
  75. */
  76. public function preview() {
  77. if ( $this->is_previewed ) {
  78. return false;
  79. }
  80. $this->is_previewed = true;
  81. add_filter( 'wp_get_custom_css', array( $this, 'filter_previewed_wp_get_custom_css' ), 9, 2 );
  82. return true;
  83. }
  84. /**
  85. * Filter `wp_get_custom_css` for applying the customized value.
  86. *
  87. * This is used in the preview when `wp_get_custom_css()` is called for rendering the styles.
  88. *
  89. * @since 4.7.0
  90. * @see wp_get_custom_css()
  91. *
  92. * @param string $css Original CSS.
  93. * @param string $stylesheet Current stylesheet.
  94. * @return string CSS.
  95. */
  96. public function filter_previewed_wp_get_custom_css( $css, $stylesheet ) {
  97. if ( $stylesheet === $this->stylesheet ) {
  98. $customized_value = $this->post_value( null );
  99. if ( ! is_null( $customized_value ) ) {
  100. $css = $customized_value;
  101. }
  102. }
  103. return $css;
  104. }
  105. /**
  106. * Fetch the value of the setting. Will return the previewed value when `preview()` is called.
  107. *
  108. * @since 4.7.0
  109. * @see WP_Customize_Setting::value()
  110. *
  111. * @return string
  112. */
  113. public function value() {
  114. if ( $this->is_previewed ) {
  115. $post_value = $this->post_value( null );
  116. if ( null !== $post_value ) {
  117. return $post_value;
  118. }
  119. }
  120. $id_base = $this->id_data['base'];
  121. $value = '';
  122. $post = wp_get_custom_css_post( $this->stylesheet );
  123. if ( $post ) {
  124. $value = $post->post_content;
  125. }
  126. if ( empty( $value ) ) {
  127. $value = $this->default;
  128. }
  129. /** This filter is documented in wp-includes/class-wp-customize-setting.php */
  130. $value = apply_filters( "customize_value_{$id_base}", $value, $this );
  131. return $value;
  132. }
  133. /**
  134. * Validate CSS.
  135. *
  136. * Checks for imbalanced braces, brackets, and comments.
  137. * Notifications are rendered when the customizer state is saved.
  138. *
  139. * @since 4.7.0
  140. * @since 4.9.0 Checking for balanced characters has been moved client-side via linting in code editor.
  141. *
  142. * @param string $css The input string.
  143. * @return true|WP_Error True if the input was validated, otherwise WP_Error.
  144. */
  145. public function validate( $css ) {
  146. $validity = new WP_Error();
  147. if ( preg_match( '#</?\w+#', $css ) ) {
  148. $validity->add( 'illegal_markup', __( 'Markup is not allowed in CSS.' ) );
  149. }
  150. if ( ! $validity->has_errors() ) {
  151. $validity = parent::validate( $css );
  152. }
  153. return $validity;
  154. }
  155. /**
  156. * Store the CSS setting value in the custom_css custom post type for the stylesheet.
  157. *
  158. * @since 4.7.0
  159. *
  160. * @param string $css The input value.
  161. * @return int|false The post ID or false if the value could not be saved.
  162. */
  163. public function update( $css ) {
  164. if ( empty( $css ) ) {
  165. $css = '';
  166. }
  167. $r = wp_update_custom_css_post(
  168. $css,
  169. array(
  170. 'stylesheet' => $this->stylesheet,
  171. )
  172. );
  173. if ( $r instanceof WP_Error ) {
  174. return false;
  175. }
  176. $post_id = $r->ID;
  177. // Cache post ID in theme mod for performance to avoid additional DB query.
  178. if ( $this->manager->get_stylesheet() === $this->stylesheet ) {
  179. set_theme_mod( 'custom_css_post_id', $post_id );
  180. }
  181. return $post_id;
  182. }
  183. }