diff --git a/src/wp-includes/block-editor.php b/src/wp-includes/block-editor.php index 4227c674c02ff..72a91ce061db5 100644 --- a/src/wp-includes/block-editor.php +++ b/src/wp-includes/block-editor.php @@ -428,6 +428,12 @@ function get_block_editor_settings( array $custom_settings, $block_editor_contex $block_classes['css'] = $actual_css; $global_styles[] = $block_classes; } + // Add the custom CSS as separate style sheet so any invalid CSS entered by users does not break other global styles. + $editor_settings['styles'][] = array( + 'css' => wp_get_global_stylesheet( array( 'custom-css' ) ), + '__unstableType' => 'user', + 'isGlobalStyles' => true, + ); } else { // If there is no `theme.json` file, ensure base layout styles are still available. $block_classes = array( diff --git a/src/wp-includes/class-wp-theme-json.php b/src/wp-includes/class-wp-theme-json.php index f9e8e371c596a..6e4b12ed64ec7 100644 --- a/src/wp-includes/class-wp-theme-json.php +++ b/src/wp-includes/class-wp-theme-json.php @@ -403,6 +403,7 @@ class WP_Theme_JSON { 'textDecoration' => null, 'textTransform' => null, ), + 'css' => null, ); /** @@ -952,6 +953,11 @@ public function get_stylesheet( $types = array( 'variables', 'styles', 'presets' $stylesheet .= $this->get_preset_classes( $setting_nodes, $origins ); } + // Load the custom CSS last so it has the highest specificity. + if ( in_array( 'custom-css', $types, true ) ) { + $stylesheet .= _wp_array_get( $this->theme_json, array( 'styles', 'css' ) ); + } + return $stylesheet; } diff --git a/src/wp-includes/global-styles-and-settings.php b/src/wp-includes/global-styles-and-settings.php index c625166524b63..fca29dd4ca021 100644 --- a/src/wp-includes/global-styles-and-settings.php +++ b/src/wp-includes/global-styles-and-settings.php @@ -75,6 +75,7 @@ function wp_get_global_styles( $path = array(), $context = array() ) { * Returns the stylesheet resulting of merging core, theme, and user data. * * @since 5.9.0 + * @since 6.2.0 Support for custom-css type added. * * @param array $types Types of styles to load. Optional. * It accepts 'variables', 'styles', 'presets' as values. @@ -106,7 +107,7 @@ function wp_get_global_stylesheet( $types = array() ) { if ( empty( $types ) && ! $supports_theme_json ) { $types = array( 'variables', 'presets', 'base-layout-styles' ); } elseif ( empty( $types ) ) { - $types = array( 'variables', 'styles', 'presets' ); + $types = array( 'variables', 'styles', 'presets', 'custom-css' ); } /* diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-global-styles-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-global-styles-controller.php index 9ce931398f383..3a476b02ff441 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-global-styles-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-global-styles-controller.php @@ -268,6 +268,10 @@ public function update_item( $request ) { } $changes = $this->prepare_item_for_database( $request ); + if ( is_wp_error( $changes ) ) { + return $changes; + } + $result = wp_update_post( wp_slash( (array) $changes ), true, false ); if ( is_wp_error( $result ) ) { return $result; @@ -290,6 +294,7 @@ public function update_item( $request ) { * Prepares a single global styles config for update. * * @since 5.9.0 + * @since 6.2.0 Added validation of styles.css property. * * @param WP_REST_Request $request Request object. * @return stdClass Changes to pass to wp_update_post. @@ -313,6 +318,10 @@ protected function prepare_item_for_database( $request ) { $config = array(); if ( isset( $request['styles'] ) ) { $config['styles'] = $request['styles']; + $validate_custom_css = $this->validate_custom_css( $request['styles']['css'] ); + if ( is_wp_error( $validate_custom_css ) ) { + return $validate_custom_css; + } } elseif ( isset( $existing_config['styles'] ) ) { $config['styles'] = $existing_config['styles']; } @@ -652,4 +661,25 @@ public function get_theme_items( $request ) { return $response; } + + /** + * Validate style.css as valid CSS. + * + * Currently just checks for invalid markup. + * + * @since 6.2.0 + * + * @param string $css CSS to validate. + * @return true|WP_Error True if the input was validated, otherwise WP_Error. + */ + private function validate_custom_css( $css ) { + if ( preg_match( '# 400 ) + ); + } + return true; + } }