2016-10-19 14:15:31 -04:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* Customize API: WP_Customize_Custom_CSS_Setting class
|
|
|
|
*
|
|
|
|
* This handles validation, sanitization and saving of the value.
|
|
|
|
*
|
|
|
|
* @package WordPress
|
|
|
|
* @subpackage Customize
|
|
|
|
* @since 4.7.0
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Custom Setting to handle WP Custom CSS.
|
|
|
|
*
|
|
|
|
* @since 4.7.0
|
|
|
|
*
|
|
|
|
* @see WP_Customize_Setting
|
|
|
|
*/
|
|
|
|
final class WP_Customize_Custom_CSS_Setting extends WP_Customize_Setting {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The setting type.
|
|
|
|
*
|
|
|
|
* @since 4.7.0
|
2016-11-23 01:05:32 -05:00
|
|
|
* @var string
|
2016-10-19 14:15:31 -04:00
|
|
|
*/
|
|
|
|
public $type = 'custom_css';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Setting Transport
|
|
|
|
*
|
|
|
|
* @since 4.7.0
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
public $transport = 'postMessage';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Capability required to edit this setting.
|
|
|
|
*
|
|
|
|
* @since 4.7.0
|
|
|
|
* @var string
|
|
|
|
*/
|
2016-11-08 20:12:30 -05:00
|
|
|
public $capability = 'edit_css';
|
2016-10-19 14:15:31 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Stylesheet
|
|
|
|
*
|
|
|
|
* @since 4.7.0
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
public $stylesheet = '';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* WP_Customize_Custom_CSS_Setting constructor.
|
|
|
|
*
|
|
|
|
* @since 4.7.0
|
|
|
|
*
|
|
|
|
* @throws Exception If the setting ID does not match the pattern `custom_css[$stylesheet]`.
|
|
|
|
*
|
|
|
|
* @param WP_Customize_Manager $manager The Customize Manager class.
|
|
|
|
* @param string $id An specific ID of the setting. Can be a
|
|
|
|
* theme mod or option name.
|
|
|
|
* @param array $args Setting arguments.
|
|
|
|
*/
|
|
|
|
public function __construct( $manager, $id, $args = array() ) {
|
|
|
|
parent::__construct( $manager, $id, $args );
|
|
|
|
if ( 'custom_css' !== $this->id_data['base'] ) {
|
|
|
|
throw new Exception( 'Expected custom_css id_base.' );
|
|
|
|
}
|
|
|
|
if ( 1 !== count( $this->id_data['keys'] ) || empty( $this->id_data['keys'][0] ) ) {
|
|
|
|
throw new Exception( 'Expected single stylesheet key.' );
|
|
|
|
}
|
|
|
|
$this->stylesheet = $this->id_data['keys'][0];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add filter to preview post value.
|
|
|
|
*
|
|
|
|
* @since 4.7.9
|
|
|
|
*
|
|
|
|
* @return bool False when preview short-circuits due no change needing to be previewed.
|
|
|
|
*/
|
|
|
|
public function preview() {
|
|
|
|
if ( $this->is_previewed ) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
$this->is_previewed = true;
|
|
|
|
add_filter( 'wp_get_custom_css', array( $this, 'filter_previewed_wp_get_custom_css' ), 9, 2 );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2016-11-12 21:43:29 -05:00
|
|
|
* Filter `wp_get_custom_css` for applying the customized value.
|
|
|
|
*
|
|
|
|
* This is used in the preview when `wp_get_custom_css()` is called for rendering the styles.
|
2016-10-19 14:15:31 -04:00
|
|
|
*
|
|
|
|
* @since 4.7.0
|
2016-11-12 21:43:29 -05:00
|
|
|
* @see wp_get_custom_css()
|
2016-10-19 14:15:31 -04:00
|
|
|
*
|
|
|
|
* @param string $css Original CSS.
|
|
|
|
* @param string $stylesheet Current stylesheet.
|
|
|
|
* @return string CSS.
|
|
|
|
*/
|
|
|
|
public function filter_previewed_wp_get_custom_css( $css, $stylesheet ) {
|
|
|
|
if ( $stylesheet === $this->stylesheet ) {
|
|
|
|
$customized_value = $this->post_value( null );
|
|
|
|
if ( ! is_null( $customized_value ) ) {
|
|
|
|
$css = $customized_value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return $css;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2016-11-12 21:43:29 -05:00
|
|
|
* Fetch the value of the setting. Will return the previewed value when `preview()` is called.
|
2016-10-19 14:15:31 -04:00
|
|
|
*
|
|
|
|
* @since 4.7.0
|
2016-11-12 21:43:29 -05:00
|
|
|
* @see WP_Customize_Setting::value()
|
2016-10-19 14:15:31 -04:00
|
|
|
*
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public function value() {
|
2016-11-19 01:00:34 -05:00
|
|
|
if ( $this->is_previewed ) {
|
|
|
|
$post_value = $this->post_value( null );
|
|
|
|
if ( null !== $post_value ) {
|
|
|
|
return $post_value;
|
|
|
|
}
|
2016-11-12 21:43:29 -05:00
|
|
|
}
|
2016-11-19 01:00:34 -05:00
|
|
|
$id_base = $this->id_data['base'];
|
2016-11-12 21:43:29 -05:00
|
|
|
$value = '';
|
|
|
|
$post = wp_get_custom_css_post( $this->stylesheet );
|
|
|
|
if ( $post ) {
|
|
|
|
$value = $post->post_content;
|
|
|
|
}
|
2016-11-07 13:13:34 -05:00
|
|
|
if ( empty( $value ) ) {
|
|
|
|
$value = $this->default;
|
|
|
|
}
|
2016-11-12 21:43:29 -05:00
|
|
|
|
|
|
|
/** This filter is documented in wp-includes/class-wp-customize-setting.php */
|
|
|
|
$value = apply_filters( "customize_value_{$id_base}", $value, $this );
|
|
|
|
|
2016-11-07 13:13:34 -05:00
|
|
|
return $value;
|
2016-10-19 14:15:31 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Validate CSS.
|
|
|
|
*
|
|
|
|
* Checks for imbalanced braces, brackets, and comments.
|
|
|
|
* Notifications are rendered when the customizer state is saved.
|
|
|
|
*
|
|
|
|
* @since 4.7.0
|
Editor: Add CodeMirror-powered code editor with syntax highlighting, linting, and auto-completion.
* Code editor is integrated into the Theme/Plugin Editor, Additional CSS in Customizer, and Custom HTML widget. Code editor is not yet integrated into the post editor, and it may not be until accessibility concerns are addressed.
* The CodeMirror component in the Custom HTML widget is integrated in a similar way to TinyMCE being integrated into the Text widget, adopting the same approach for integrating dynamic JavaScript-initialized fields.
* Linting is performed for JS, CSS, HTML, and JSON via JSHint, CSSLint, HTMLHint, and JSONLint respectively. Linting is not yet supported for PHP.
* When user lacks `unfiltered_html` the capability, the Custom HTML widget will report any Kses-invalid elements and attributes as errors via a custom Kses rule for HTMLHint.
* When linting errors are detected, the user will be prevented from saving the code until the errors are fixed, reducing instances of broken websites.
* The placeholder value is removed from Custom CSS in favor of a fleshed-out section description which now auto-expands when the CSS field is empty. See #39892.
* The CodeMirror library is included as `wp.CodeMirror` to prevent conflicts with any existing `CodeMirror` global.
* An `wp.codeEditor.initialize()` API in JS is provided to convert a `textarea` into CodeMirror, with a `wp_enqueue_code_editor()` function in PHP to manage enqueueing the assets and settings needed to edit a given type of code.
* A user preference is added to manage whether or not "syntax highlighting" is enabled. The feature is opt-out, being enabled by default.
* Allowed file extensions in the theme and plugin editors have been updated to include formats which CodeMirror has modes for: `conf`, `css`, `diff`, `patch`, `html`, `htm`, `http`, `js`, `json`, `jsx`, `less`, `md`, `php`, `phtml`, `php3`, `php4`, `php5`, `php7`, `phps`, `scss`, `sass`, `sh`, `bash`, `sql`, `svg`, `xml`, `yml`, `yaml`, `txt`.
Props westonruter, georgestephanis, obenland, melchoyce, pixolin, mizejewski, michelleweber, afercia, grahamarmfield, samikeijonen, rianrietveld, iseulde.
See #38707.
Fixes #12423, #39892.
Built from https://develop.svn.wordpress.org/trunk@41376
git-svn-id: http://core.svn.wordpress.org/trunk@41209 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2017-09-13 02:08:47 -04:00
|
|
|
* @since 4.9.0 Checking for balanced characters has been moved client-side via linting in code editor.
|
2016-10-19 14:15:31 -04:00
|
|
|
*
|
|
|
|
* @param string $css The input string.
|
|
|
|
* @return true|WP_Error True if the input was validated, otherwise WP_Error.
|
|
|
|
*/
|
|
|
|
public function validate( $css ) {
|
|
|
|
$validity = new WP_Error();
|
|
|
|
|
|
|
|
if ( preg_match( '#</?\w+#', $css ) ) {
|
|
|
|
$validity->add( 'illegal_markup', __( 'Markup is not allowed in CSS.' ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( empty( $validity->errors ) ) {
|
|
|
|
$validity = parent::validate( $css );
|
|
|
|
}
|
|
|
|
return $validity;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Store the CSS setting value in the custom_css custom post type for the stylesheet.
|
|
|
|
*
|
|
|
|
* @since 4.7.0
|
|
|
|
*
|
|
|
|
* @param string $css The input value.
|
|
|
|
* @return int|false The post ID or false if the value could not be saved.
|
|
|
|
*/
|
|
|
|
public function update( $css ) {
|
2016-11-12 21:43:29 -05:00
|
|
|
if ( empty( $css ) ) {
|
|
|
|
$css = '';
|
|
|
|
}
|
2016-10-19 14:15:31 -04:00
|
|
|
|
2016-11-23 12:34:31 -05:00
|
|
|
$r = wp_update_custom_css_post( $css, array(
|
|
|
|
'stylesheet' => $this->stylesheet,
|
|
|
|
) );
|
2016-11-12 21:43:29 -05:00
|
|
|
|
2016-11-23 12:34:31 -05:00
|
|
|
if ( $r instanceof WP_Error ) {
|
2016-10-19 14:15:31 -04:00
|
|
|
return false;
|
|
|
|
}
|
2016-11-23 12:34:31 -05:00
|
|
|
$post_id = $r->ID;
|
2016-10-19 14:15:31 -04:00
|
|
|
|
|
|
|
// Cache post ID in theme mod for performance to avoid additional DB query.
|
|
|
|
if ( $this->manager->get_stylesheet() === $this->stylesheet ) {
|
|
|
|
set_theme_mod( 'custom_css_post_id', $post_id );
|
|
|
|
}
|
|
|
|
|
|
|
|
return $post_id;
|
|
|
|
}
|
|
|
|
}
|