PluginProbe
Gutenberg / 12.1.0
Gutenberg v12.1.0
23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 12.6.0 7.4.0 All 402 releases
gutenberg / lib / global-styles.php

global-styles.php in Gutenberg 12.1.0, at lib/global-styles.php

307 lines 10.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Bootstraps Global Styles.
4 *
5 * @package gutenberg
6 */
7
8 /**
9 * Fetches the preferences for each origin (core, theme, user)
10 * and enqueues the resulting stylesheet.
11 */
12 function gutenberg_experimental_global_styles_enqueue_assets() {
13 $stylesheet = wp_get_global_stylesheet();
14 if ( empty( $stylesheet ) ) {
15 return;
16 }
17
18 if ( isset( wp_styles()->registered['global-styles'] ) ) {
19 wp_styles()->registered['global-styles']->extra['after'][0] = $stylesheet;
20 } else {
21 wp_register_style( 'global-styles', false, array(), true, true );
22 wp_add_inline_style( 'global-styles', $stylesheet );
23 wp_enqueue_style( 'global-styles' );
24 }
25 }
26
27 /**
28 * Adds the necessary settings for the Global Styles client UI.
29 *
30 * @param array $settings Existing block editor settings.
31 *
32 * @return array New block editor settings.
33 */
34 function gutenberg_experimental_global_styles_settings( $settings ) {
35 // Set what is the context for this data request.
36 $context = 'other';
37 if (
38 is_callable( 'get_current_screen' ) &&
39 function_exists( 'gutenberg_is_edit_site_page' ) &&
40 gutenberg_is_edit_site_page( get_current_screen()->id )
41 ) {
42 $context = 'site-editor';
43 }
44
45 if (
46 defined( 'REST_REQUEST' ) &&
47 REST_REQUEST &&
48 isset( $_GET['context'] ) &&
49 'mobile' === $_GET['context']
50 ) {
51 $context = 'mobile';
52 }
53
54 if ( 'mobile' === $context && WP_Theme_JSON_Resolver_Gutenberg::theme_has_support() ) {
55 $settings['__experimentalStyles'] = wp_get_global_styles();
56 }
57
58 if ( 'other' === $context ) {
59 // Make sure the styles array exists.
60 // In some contexts, like the navigation editor, it doesn't.
61 if ( ! isset( $settings['styles'] ) ) {
62 $settings['styles'] = array();
63 }
64
65 // Reset existing global styles.
66 $styles_without_existing_global_styles = array();
67 foreach ( $settings['styles'] as $style ) {
68 if ( ! isset( $style['__unstableType'] ) || 'globalStyles' !== $style['__unstableType'] ) {
69 $styles_without_existing_global_styles[] = $style;
70 }
71 }
72
73 $new_global_styles = array();
74 $new_presets = array(
75 array(
76 'css' => 'variables',
77 '__unstableType' => 'presets',
78 '__experimentalNoWrapper' => true,
79 ),
80 array(
81 'css' => 'presets',
82 '__unstableType' => 'presets',
83 ),
84 );
85 foreach ( $new_presets as $new_style ) {
86 $style_css = wp_get_global_stylesheet( array( $new_style['css'] ) );
87 if ( '' !== $style_css ) {
88 $new_style['css'] = $style_css;
89 $new_global_styles[] = $new_style;
90 }
91 }
92
93 $new_block_classes = array(
94 'css' => 'styles',
95 '__unstableType' => 'theme',
96 );
97 if ( WP_Theme_JSON_Resolver_Gutenberg::theme_has_support() ) {
98 $style_css = wp_get_global_stylesheet( array( $new_block_classes['css'] ) );
99 if ( '' !== $style_css ) {
100 $new_block_classes['css'] = $style_css;
101 $new_global_styles[] = $new_block_classes;
102 }
103 }
104
105 $settings['styles'] = array_merge( $styles_without_existing_global_styles, $new_global_styles );
106 }
107
108 // Copied from get_block_editor_settings() at wordpress-develop/block-editor.php.
109 $settings['__experimentalFeatures'] = wp_get_global_settings();
110
111 if ( isset( $settings['__experimentalFeatures']['color']['palette'] ) ) {
112 $colors_by_origin = $settings['__experimentalFeatures']['color']['palette'];
113 $settings['colors'] = isset( $colors_by_origin['custom'] ) ?
114 $colors_by_origin['custom'] : (
115 isset( $colors_by_origin['theme'] ) ?
116 $colors_by_origin['theme'] :
117 $colors_by_origin['default']
118 );
119 }
120
121 if ( isset( $settings['__experimentalFeatures']['color']['gradients'] ) ) {
122 $gradients_by_origin = $settings['__experimentalFeatures']['color']['gradients'];
123 $settings['gradients'] = isset( $gradients_by_origin['custom'] ) ?
124 $gradients_by_origin['custom'] : (
125 isset( $gradients_by_origin['theme'] ) ?
126 $gradients_by_origin['theme'] :
127 $gradients_by_origin['default']
128 );
129 }
130
131 if ( isset( $settings['__experimentalFeatures']['typography']['fontSizes'] ) ) {
132 $font_sizes_by_origin = $settings['__experimentalFeatures']['typography']['fontSizes'];
133 $settings['fontSizes'] = isset( $font_sizes_by_origin['custom'] ) ?
134 $font_sizes_by_origin['user'] : (
135 isset( $font_sizes_by_origin['theme'] ) ?
136 $font_sizes_by_origin['theme'] :
137 $font_sizes_by_origin['default']
138 );
139 }
140
141 if ( isset( $settings['__experimentalFeatures']['color']['custom'] ) ) {
142 $settings['disableCustomColors'] = ! $settings['__experimentalFeatures']['color']['custom'];
143 unset( $settings['__experimentalFeatures']['color']['custom'] );
144 }
145 if ( isset( $settings['__experimentalFeatures']['color']['customGradient'] ) ) {
146 $settings['disableCustomGradients'] = ! $settings['__experimentalFeatures']['color']['customGradient'];
147 unset( $settings['__experimentalFeatures']['color']['customGradient'] );
148 }
149 if ( isset( $settings['__experimentalFeatures']['typography']['customFontSize'] ) ) {
150 $settings['disableCustomFontSizes'] = ! $settings['__experimentalFeatures']['typography']['customFontSize'];
151 unset( $settings['__experimentalFeatures']['typography']['customFontSize'] );
152 }
153 if ( isset( $settings['__experimentalFeatures']['typography']['lineHeight'] ) ) {
154 $settings['enableCustomLineHeight'] = $settings['__experimentalFeatures']['typography']['lineHeight'];
155 unset( $settings['__experimentalFeatures']['typography']['lineHeight'] );
156 }
157 if ( isset( $settings['__experimentalFeatures']['spacing']['units'] ) ) {
158 $settings['enableCustomUnits'] = $settings['__experimentalFeatures']['spacing']['units'];
159 }
160 if ( isset( $settings['__experimentalFeatures']['spacing']['padding'] ) ) {
161 $settings['enableCustomSpacing'] = $settings['__experimentalFeatures']['spacing']['padding'];
162 unset( $settings['__experimentalFeatures']['spacing']['padding'] );
163 }
164
165 return $settings;
166 }
167
168 /**
169 * Whether or not the Site Editor is available.
170 *
171 * @return boolean
172 */
173 function gutenberg_experimental_is_site_editor_available() {
174 return gutenberg_is_fse_theme();
175 }
176
177 /**
178 * Register CPT to store/access user data.
179 *
180 * @return void
181 */
182 function gutenberg_experimental_global_styles_register_user_cpt() {
183 if ( gutenberg_experimental_is_site_editor_available() ) {
184 register_global_styles_custom_post_type();
185 }
186 }
187
188 /**
189 * Sanitizes global styles user content removing unsafe rules.
190 *
191 * @param string $content Post content to filter.
192 * @return string Filtered post content with unsafe rules removed.
193 */
194 function gutenberg_global_styles_filter_post( $content ) {
195 $decoded_data = json_decode( wp_unslash( $content ), true );
196 $json_decoding_error = json_last_error();
197 if (
198 JSON_ERROR_NONE === $json_decoding_error &&
199 is_array( $decoded_data ) &&
200 isset( $decoded_data['isGlobalStylesUserThemeJSON'] ) &&
201 $decoded_data['isGlobalStylesUserThemeJSON']
202 ) {
203 unset( $decoded_data['isGlobalStylesUserThemeJSON'] );
204
205 $data_to_encode = WP_Theme_JSON_Gutenberg::remove_insecure_properties( $decoded_data );
206
207 $data_to_encode['isGlobalStylesUserThemeJSON'] = true;
208 return wp_slash( wp_json_encode( $data_to_encode ) );
209 }
210 return $content;
211 }
212
213 /**
214 * Adds the filters to filter global styles user theme.json.
215 */
216 function gutenberg_global_styles_kses_init_filters() {
217 add_filter( 'content_save_pre', 'gutenberg_global_styles_filter_post' );
218 }
219
220 /**
221 * Removes the filters to filter global styles user theme.json.
222 */
223 function gutenberg_global_styles_kses_remove_filters() {
224 remove_filter( 'content_save_pre', 'gutenberg_global_styles_filter_post' );
225 }
226
227 /**
228 * Register global styles kses filters if the user does not have unfiltered_html capability.
229 *
230 * @uses render_block_core_navigation()
231 * @throws WP_Error An WP_Error exception parsing the block definition.
232 */
233 function gutenberg_global_styles_kses_init() {
234 gutenberg_global_styles_kses_remove_filters();
235 if ( ! current_user_can( 'unfiltered_html' ) ) {
236 gutenberg_global_styles_kses_init_filters();
237 }
238 }
239
240 /**
241 * This filter is the last being executed on force_filtered_html_on_import.
242 * If the input of the filter is true it means we are in an import situation and should
243 * enable kses, independently of the user capabilities.
244 * So in that case we call gutenberg_global_styles_kses_init_filters;
245 *
246 * @param string $arg Input argument of the filter.
247 * @return string Exactly what was passed as argument.
248 */
249 function gutenberg_global_styles_force_filtered_html_on_import_filter( $arg ) {
250 // force_filtered_html_on_import is true we need to init the global styles kses filters.
251 if ( $arg ) {
252 gutenberg_global_styles_kses_init_filters();
253 }
254 return $arg;
255 }
256
257 // TODO: Remove this filter when minimum supported version is WP 5.8
258 // As all this code is not needed anymore now core supports all variables.
259 /**
260 * This filter is the last being executed on force_filtered_html_on_import.
261 * If the input of the filter is true it means we are in an import situation and should
262 * enable kses, independently of the user capabilities.
263 * So in that case we call gutenberg_global_styles_kses_init_filters;
264 *
265 * @param bool $allow_css Whether the CSS in the test string is considered safe.
266 * @param bool $css_test_string The CSS string to test..
267 * @return bool If $allow_css is true it returns true.
268 * If $allow_css is false and the CSS rule is referencing a WordPress css variable it returns true.
269 * Otherwise the function return false.
270 */
271 function gutenberg_global_styles_include_support_for_wp_variables( $allow_css, $css_test_string ) {
272 if ( $allow_css ) {
273 return $allow_css;
274 }
275 $allowed_preset_attributes = array(
276 'background',
277 'background-color',
278 'border-color',
279 'color',
280 'font-family',
281 'font-size',
282 );
283 $parts = explode( ':', $css_test_string, 2 );
284
285 if ( ! in_array( trim( $parts[0] ), $allowed_preset_attributes, true ) ) {
286 return $allow_css;
287 }
288 return ! ! preg_match( '/^var\(--wp-[a-zA-Z0-9\-]+\)$/', trim( $parts[1] ) );
289 }
290
291 // The else clause can be removed when plugin support requires WordPress 5.8.0+.
292 if ( function_exists( 'get_block_editor_settings' ) ) {
293 add_filter( 'block_editor_settings_all', 'gutenberg_experimental_global_styles_settings', PHP_INT_MAX );
294 } else {
295 add_filter( 'block_editor_settings', 'gutenberg_experimental_global_styles_settings', PHP_INT_MAX );
296 }
297
298 add_action( 'init', 'gutenberg_experimental_global_styles_register_user_cpt' );
299 add_action( 'wp_enqueue_scripts', 'gutenberg_experimental_global_styles_enqueue_assets' );
300
301 // kses actions&filters.
302 add_action( 'init', 'gutenberg_global_styles_kses_init' );
303 add_action( 'set_current_user', 'gutenberg_global_styles_kses_init' );
304 add_filter( 'force_filtered_html_on_import', 'gutenberg_global_styles_force_filtered_html_on_import_filter', 999 );
305 add_filter( 'safecss_filter_attr_allow_css', 'gutenberg_global_styles_include_support_for_wp_variables', 10, 2 );
306 // This filter needs to be executed last.
307