PluginProbe
Gutenberg / 17.0.2
Gutenberg v17.0.2
24.0.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 All 403 releases
← All changes | lib/blocks.php +534 -122 7.4.017.0.2 View file →
@@ -1,166 +1,578 @@
1 1 <?php
2 2 /**
3 - * Block and style registration functions.
3 + * Block functions specific for the Gutenberg editor plugin.
4 4 *
5 5 * @package gutenberg
6 6 */
7 7
8 8 /**
9 - * Retrieves registered social link blocks
9 + * Substitutes the implementation of a core-registered block type, if exists,
10 + * with the built result from the plugin.
11 + */
12 +function gutenberg_reregister_core_block_types() {
13 + // Blocks directory may not exist if working from a fresh clone.
14 + $blocks_dirs = array(
15 + __DIR__ . '/../build/block-library/blocks/' => array(
16 + 'block_folders' => array(
17 + 'audio',
18 + 'button',
19 + 'buttons',
20 + 'freeform',
21 + 'code',
22 + 'column',
23 + 'columns',
24 + 'details',
25 + 'form-input',
26 + 'form-submit-button',
27 + 'group',
28 + 'html',
29 + 'list',
30 + 'list-item',
31 + 'media-text',
32 + 'missing',
33 + 'more',
34 + 'nextpage',
35 + 'paragraph',
36 + 'preformatted',
37 + 'pullquote',
38 + 'quote',
39 + 'separator',
40 + 'social-links',
41 + 'spacer',
42 + 'table',
43 + 'table-of-contents',
44 + 'text-columns',
45 + 'verse',
46 + 'video',
47 + 'embed',
48 + ),
49 + 'block_names' => array(
50 + 'archives.php' => 'core/archives',
51 + 'avatar.php' => 'core/avatar',
52 + 'block.php' => 'core/block',
53 + 'calendar.php' => 'core/calendar',
54 + 'categories.php' => 'core/categories',
55 + 'cover.php' => 'core/cover',
56 + 'comment-author-avatar.php' => 'core/comment-author-avatar',
57 + 'comment-author-name.php' => 'core/comment-author-name',
58 + 'comment-content.php' => 'core/comment-content',
59 + 'comment-date.php' => 'core/comment-date',
60 + 'comment-edit-link.php' => 'core/comment-edit-link',
61 + 'comment-reply-link.php' => 'core/comment-reply-link',
62 + 'comment-template.php' => 'core/comment-template',
63 + 'comments-pagination.php' => 'core/comments-pagination',
64 + 'comments-pagination-next.php' => 'core/comments-pagination-next',
65 + 'comments-pagination-numbers.php' => 'core/comments-pagination-numbers',
66 + 'comments-pagination-previous.php' => 'core/comments-pagination-previous',
67 + 'comments-title.php' => 'core/comments-title',
68 + 'comments.php' => 'core/comments',
69 + 'footnotes.php' => 'core/footnotes',
70 + 'file.php' => 'core/file',
71 + 'form.php' => 'core/form',
72 + 'form-input.php' => 'core/form-input',
73 + 'form-submission-notification.php' => 'core/form-submission-notification',
74 + 'home-link.php' => 'core/home-link',
75 + 'image.php' => 'core/image',
76 + 'gallery.php' => 'core/gallery',
77 + 'heading.php' => 'core/heading',
78 + 'latest-comments.php' => 'core/latest-comments',
79 + 'latest-posts.php' => 'core/latest-posts',
80 + 'loginout.php' => 'core/loginout',
81 + 'navigation.php' => 'core/navigation',
82 + 'navigation-link.php' => 'core/navigation-link',
83 + 'navigation-submenu.php' => 'core/navigation-submenu',
84 + 'page-list.php' => 'core/page-list',
85 + 'page-list-item.php' => 'core/page-list-item',
86 + 'pattern.php' => 'core/pattern',
87 + 'post-author.php' => 'core/post-author',
88 + 'post-author-name.php' => 'core/post-author-name',
89 + 'post-author-biography.php' => 'core/post-author-biography',
90 + 'post-comment.php' => 'core/post-comment',
91 + 'post-comments-count.php' => 'core/post-comments-count',
92 + 'post-comments-form.php' => 'core/post-comments-form',
93 + 'post-comments-link.php' => 'core/post-comments-link',
94 + 'post-content.php' => 'core/post-content',
95 + 'post-date.php' => 'core/post-date',
96 + 'post-excerpt.php' => 'core/post-excerpt',
97 + 'post-featured-image.php' => 'core/post-featured-image',
98 + 'post-navigation-link.php' => 'core/post-navigation-link',
99 + 'post-terms.php' => 'core/post-terms',
100 + 'post-time-to-read.php' => 'core/post-time-to-read',
101 + 'post-title.php' => 'core/post-title',
102 + 'query.php' => 'core/query',
103 + 'post-template.php' => 'core/post-template',
104 + 'query-no-results.php' => 'core/query-no-results',
105 + 'query-pagination.php' => 'core/query-pagination',
106 + 'query-pagination-next.php' => 'core/query-pagination-next',
107 + 'query-pagination-numbers.php' => 'core/query-pagination-numbers',
108 + 'query-pagination-previous.php' => 'core/query-pagination-previous',
109 + 'query-title.php' => 'core/query-title',
110 + 'read-more.php' => 'core/read-more',
111 + 'rss.php' => 'core/rss',
112 + 'search.php' => 'core/search',
113 + 'shortcode.php' => 'core/shortcode',
114 + 'social-link.php' => 'core/social-link',
115 + 'site-logo.php' => 'core/site-logo',
116 + 'site-tagline.php' => 'core/site-tagline',
117 + 'site-title.php' => 'core/site-title',
118 + 'tag-cloud.php' => 'core/tag-cloud',
119 + 'template-part.php' => 'core/template-part',
120 + 'term-description.php' => 'core/term-description',
121 + ),
122 + ),
123 + __DIR__ . '/../build/edit-widgets/blocks/' => array(
124 + 'block_folders' => array(
125 + 'widget-area',
126 + ),
127 + 'block_names' => array(),
128 + ),
129 + __DIR__ . '/../build/widgets/blocks/' => array(
130 + 'block_folders' => array(
131 + 'legacy-widget',
132 + 'widget-group',
133 + ),
134 + 'block_names' => array(
135 + 'legacy-widget.php' => 'core/legacy-widget',
136 + 'widget-group.php' => 'core/widget-group',
137 + ),
138 + ),
139 + );
140 + foreach ( $blocks_dirs as $blocks_dir => $details ) {
141 + $block_folders = $details['block_folders'];
142 + $block_names = $details['block_names'];
143 +
144 + foreach ( $block_folders as $folder_name ) {
145 + $block_json_file = $blocks_dir . $folder_name . '/block.json';
146 +
147 + // Ideally, all paths to block metadata files should be listed in
148 + // WordPress core. In this place we should rather use filter
149 + // to replace paths with overrides defined by the plugin.
150 + $metadata = json_decode( file_get_contents( $block_json_file ), true );
151 + if ( ! is_array( $metadata ) || ! $metadata['name'] ) {
152 + continue;
153 + }
154 +
155 + gutenberg_deregister_core_block_and_assets( $metadata['name'] );
156 + gutenberg_register_core_block_assets( $folder_name );
157 + register_block_type_from_metadata( $block_json_file );
158 + }
159 +
160 + foreach ( $block_names as $file => $sub_block_names ) {
161 + if ( ! file_exists( $blocks_dir . $file ) ) {
162 + continue;
163 + }
164 +
165 + $sub_block_names_normalized = is_string( $sub_block_names ) ? array( $sub_block_names ) : $sub_block_names;
166 + foreach ( $sub_block_names_normalized as $block_name ) {
167 + gutenberg_deregister_core_block_and_assets( $block_name );
168 + gutenberg_register_core_block_assets( $block_name );
169 + }
170 +
171 + require_once $blocks_dir . $file;
172 + }
173 + }
174 +}
175 +
176 +add_action( 'init', 'gutenberg_reregister_core_block_types' );
177 +
178 +/**
179 + * Adds the defer loading strategy to all registered blocks.
10 180 *
11 - * @return array Array of strings containing the registered social link block names.
181 + * This function would not be part of core merge. Instead, the register_block_script_handle() function would be patched
182 + * as follows.
183 + *
184 + * ```
185 + * --- a/wp-includes/blocks.php
186 + * +++ b/wp-includes/blocks.php
187 + * @ @ -153,7 +153,8 @ @ function register_block_script_handle( $metadata, $field_name, $index = 0 ) {
188 + * $script_handle,
189 + * $script_uri,
190 + * $script_dependencies,
191 + * - isset( $script_asset['version'] ) ? $script_asset['version'] : false
192 + * + isset( $script_asset['version'] ) ? $script_asset['version'] : false,
193 + * + array( 'strategy' => 'defer' )
194 + * );
195 + * if ( ! $result ) {
196 + * return false;
197 + * ```
198 + *
199 + * @see register_block_script_handle()
12 200 */
13 -function gutenberg_get_registered_social_link_blocks() {
14 - $social_link_prefix = 'core/social-link';
15 - $social_link_prefix_length = strlen( $social_link_prefix );
201 +function gutenberg_defer_block_view_scripts() {
202 + $block_types = WP_Block_Type_Registry::get_instance()->get_all_registered();
203 + foreach ( $block_types as $block_type ) {
204 + foreach ( $block_type->view_script_handles as $view_script_handle ) {
205 + wp_script_add_data( $view_script_handle, 'strategy', 'defer' );
206 + }
207 + }
208 +}
16 209
17 - $registry = WP_Block_Type_Registry::get_instance();
18 - $block_types = $registry->get_all_registered();
210 +add_action( 'init', 'gutenberg_defer_block_view_scripts', 100 );
19 211
20 - $registered_social_link_blocks = array();
21 - foreach ( $block_types as $block_type ) {
22 - // Block type name starts with $social_link_prefix.
23 - if ( strncmp( $block_type->name, $social_link_prefix, $social_link_prefix_length ) === 0 ) {
24 - $registered_social_link_blocks[] = $block_type->name;
212 +/**
213 + * Deregisters the existing core block type and its assets.
214 + *
215 + * @param string $block_name The name of the block.
216 + *
217 + * @return void
218 + */
219 +function gutenberg_deregister_core_block_and_assets( $block_name ) {
220 + $registry = WP_Block_Type_Registry::get_instance();
221 + if ( $registry->is_registered( $block_name ) ) {
222 + $block_type = $registry->get_registered( $block_name );
223 + if ( ! empty( $block_type->view_script_handles ) ) {
224 + foreach ( $block_type->view_script_handles as $view_script_handle ) {
225 + if ( str_starts_with( $view_script_handle, 'wp-block-' ) ) {
226 + wp_deregister_script( $view_script_handle );
227 + }
228 + }
25 229 }
230 + $registry->unregister( $block_name );
26 231 }
27 - return $registered_social_link_blocks;
28 232 }
29 233
30 234 /**
31 - * Substitutes the implementation of a core-registered block type, if exists,
32 - * with the built result from the plugin.
235 + * Registers block styles for a core block.
236 + *
237 + * @param string $block_name The block-name.
238 + *
239 + * @return void
33 240 */
34 -function gutenberg_reregister_core_block_types() {
35 - // Blocks directory may not exist if working from a fresh clone.
36 - $blocks_dir = dirname( __FILE__ ) . '/../build/block-library/blocks/';
37 - if ( ! file_exists( $blocks_dir ) ) {
241 +function gutenberg_register_core_block_assets( $block_name ) {
242 + if ( ! wp_should_load_separate_core_block_assets() ) {
38 243 return;
39 244 }
40 245
41 - $block_names = array(
42 - 'archives.php' => 'core/archives',
43 - 'block.php' => 'core/block',
44 - 'calendar.php' => 'core/calendar',
45 - 'categories.php' => 'core/categories',
46 - 'latest-comments.php' => 'core/latest-comments',
47 - 'latest-posts.php' => 'core/latest-posts',
48 - 'legacy-widget.php' => 'core/legacy-widget',
49 - 'navigation.php' => 'core/navigation',
50 - 'rss.php' => 'core/rss',
51 - 'shortcode.php' => 'core/shortcode',
52 - 'search.php' => 'core/search',
53 - 'social-link.php' => gutenberg_get_registered_social_link_blocks(),
54 - 'tag-cloud.php' => 'core/tag-cloud',
55 - 'site-title.php' => 'core/site-title',
56 - 'template-part.php' => 'core/template-part',
57 - 'post-title.php' => 'core/post-title',
58 - 'post-content.php' => 'core/post-content',
59 - 'post-author.php' => 'core/post-author',
60 - 'post-date.php' => 'core/post-date',
61 - 'post-excerpt.php' => 'core/post-excerpt',
62 - );
246 + $block_name = str_replace( 'core/', '', $block_name );
63 247
64 - $registry = WP_Block_Type_Registry::get_instance();
248 + // When in production, use the plugin's version as the default asset version;
249 + // else (for development or test) default to use the current time.
250 + $default_version = defined( 'GUTENBERG_VERSION' ) && ! SCRIPT_DEBUG ? GUTENBERG_VERSION : time();
65 251
66 - foreach ( $block_names as $file => $block_names ) {
67 - if ( ! file_exists( $blocks_dir . $file ) ) {
68 - return;
252 + $style_path = "build/block-library/blocks/$block_name/";
253 + $stylesheet_url = gutenberg_url( $style_path . 'style.css' );
254 + $stylesheet_path = gutenberg_dir_path() . $style_path . ( is_rtl() ? 'style-rtl.css' : 'style.css' );
255 +
256 + if ( file_exists( $stylesheet_path ) ) {
257 + wp_deregister_style( "wp-block-{$block_name}" );
258 + wp_register_style(
259 + "wp-block-{$block_name}",
260 + $stylesheet_url,
261 + array(),
262 + $default_version
263 + );
264 + wp_style_add_data( "wp-block-{$block_name}", 'rtl', 'replace' );
265 +
266 + // Add a reference to the stylesheet's path to allow calculations for inlining styles in `wp_head`.
267 + wp_style_add_data( "wp-block-{$block_name}", 'path', $stylesheet_path );
268 + } else {
269 + wp_register_style( "wp-block-{$block_name}", false, array() );
270 + }
271 +
272 + // If the current theme supports wp-block-styles, dequeue the full stylesheet
273 + // and instead attach each block's theme-styles to their block styles stylesheet.
274 + if ( current_theme_supports( 'wp-block-styles' ) ) {
275 +
276 + // Dequeue the full stylesheet.
277 + // Make sure this only runs once, it doesn't need to run for every block.
278 + static $stylesheet_removed;
279 + if ( ! $stylesheet_removed ) {
280 + add_action(
281 + 'wp_enqueue_scripts',
282 + static function () {
283 + wp_dequeue_style( 'wp-block-library-theme' );
284 + }
285 + );
286 + $stylesheet_removed = true;
69 287 }
70 288
71 - if ( is_string( $block_names ) ) {
72 - if ( $registry->is_registered( $block_names ) ) {
73 - $registry->unregister( $block_names );
289 + // Get the path to the block's stylesheet.
290 + $theme_style_path = is_rtl()
291 + ? "build/block-library/blocks/$block_name/theme-rtl.css"
292 + : "build/block-library/blocks/$block_name/theme.css";
293 +
294 + // If the file exists, enqueue it.
295 + if ( file_exists( gutenberg_dir_path() . $theme_style_path ) ) {
296 +
297 + if ( file_exists( $stylesheet_path ) ) {
298 + // If there is a main stylesheet for this block, append the theme styles to main styles.
299 + wp_add_inline_style(
300 + "wp-block-{$block_name}",
301 + file_get_contents( gutenberg_dir_path() . $theme_style_path )
302 + );
303 + } else {
304 + // If there is no main stylesheet for this block, register theme style.
305 + wp_register_style(
306 + "wp-block-{$block_name}",
307 + gutenberg_url( $theme_style_path ),
308 + array(),
309 + $default_version
310 + );
311 + wp_style_add_data( "wp-block-{$block_name}", 'path', gutenberg_dir_path() . $theme_style_path );
74 312 }
75 - } elseif ( is_array( $block_names ) ) {
76 - foreach ( $block_names as $block_name ) {
77 - if ( $registry->is_registered( $block_name ) ) {
78 - $registry->unregister( $block_name );
79 - }
80 - }
81 313 }
314 + }
82 315
83 - require $blocks_dir . $file;
316 + $editor_style_path = "build/block-library/blocks/$block_name/style-editor.css";
317 + if ( file_exists( gutenberg_dir_path() . $editor_style_path ) ) {
318 + wp_deregister_style( "wp-block-{$block_name}-editor" );
319 + wp_register_style(
320 + "wp-block-{$block_name}-editor",
321 + gutenberg_url( $editor_style_path ),
322 + array(),
323 + $default_version
324 + );
325 + wp_style_add_data( "wp-block-{$block_name}-editor", 'rtl', 'replace' );
326 + } else {
327 + wp_register_style( "wp-block-{$block_name}-editor", false );
84 328 }
85 329 }
86 -add_action( 'init', 'gutenberg_reregister_core_block_types' );
87 330
88 -if ( ! function_exists( 'register_block_style' ) ) {
89 - /**
90 - * Registers a new block style.
91 - *
92 - * @param string $block_name Block type name including namespace.
93 - * @param array $style_properties Array containing the properties of the style name, label, style (name of the stylesheet to be enqueued), inline_style (string containing the CSS to be added).
94 - *
95 - * @return boolean True if the block style was registered with success and false otherwise.
96 - */
97 - function register_block_style( $block_name, $style_properties ) {
98 - return WP_Block_Styles_Registry::get_instance()->register( $block_name, $style_properties );
331 +/**
332 + * Complements the implementation of block type `core/social-icon`, whether it
333 + * be provided by core or the plugin, with derived block types for each
334 + * "service" (WordPress, Twitter, etc.) supported by Social Links.
335 + *
336 + * This ensures backwards compatibility for any users running the Gutenberg
337 + * plugin who have used Social Links prior to their conversion to block
338 + * variations.
339 + *
340 + * This shim is INTENTIONALLY left out of core, as Social Links have never
341 + * landed there.
342 + *
343 + * @see https://github.com/WordPress/gutenberg/pull/19887
344 + */
345 +function gutenberg_register_legacy_social_link_blocks() {
346 + $services = array(
347 + 'amazon',
348 + 'bandcamp',
349 + 'behance',
350 + 'chain',
351 + 'codepen',
352 + 'deviantart',
353 + 'dribbble',
354 + 'dropbox',
355 + 'etsy',
356 + 'facebook',
357 + 'feed',
358 + 'fivehundredpx',
359 + 'flickr',
360 + 'foursquare',
361 + 'goodreads',
362 + 'google',
363 + 'github',
364 + 'instagram',
365 + 'lastfm',
366 + 'linkedin',
367 + 'mail',
368 + 'mastodon',
369 + 'meetup',
370 + 'medium',
371 + 'pinterest',
372 + 'pocket',
373 + 'reddit',
374 + 'skype',
375 + 'snapchat',
376 + 'soundcloud',
377 + 'spotify',
378 + 'tumblr',
379 + 'twitch',
380 + 'twitter',
381 + 'vimeo',
382 + 'vk',
383 + 'wordpress',
384 + 'yelp',
385 + 'youtube',
386 + );
387 +
388 + foreach ( $services as $service ) {
389 + register_block_type(
390 + 'core/social-link-' . $service,
391 + array(
392 + 'category' => 'widgets',
393 + 'attributes' => array(
394 + 'url' => array(
395 + 'type' => 'string',
396 + ),
397 + 'service' => array(
398 + 'type' => 'string',
399 + 'default' => $service,
400 + ),
401 + 'label' => array(
402 + 'type' => 'string',
403 + ),
404 + ),
405 + 'render_callback' => 'gutenberg_render_block_core_social_link',
406 + )
407 + );
99 408 }
100 409 }
101 410
102 -if ( ! function_exists( 'unregister_block_style' ) ) {
103 - /**
104 - * Unregisters a block style.
105 - *
106 - * @param string $block_name Block type name including namespace.
107 - * @param array $block_style_name Block style name.
108 - *
109 - * @return boolean True if the block style was unregistered with success and false otherwise.
110 - */
111 - function unregister_block_style( $block_name, $block_style_name ) {
112 - return WP_Block_Styles_Registry::get_instance()->unregister( $block_name, $block_style_name );
411 +add_action( 'init', 'gutenberg_register_legacy_social_link_blocks' );
412 +
413 +/**
414 + * Migrate the legacy `sync_status` meta key (added 16.1) to the new `wp_pattern_sync_status` meta key (16.1.1).
415 + *
416 + * This filter is INTENTIONALLY left out of core as the meta key was fist introduced to core in 6.3 as `wp_pattern_sync_status`.
417 + * see https://github.com/WordPress/gutenberg/pull/52232
418 + *
419 + * @param mixed $value The value to return, either a single metadata value or an array of values depending on the value of $single.
420 + * @param int $object_id ID of the object metadata is for.
421 + * @param string $meta_key Metadata key.
422 + * @param bool $single Whether to return only the first value of the specified $meta_key.
423 + */
424 +function gutenberg_legacy_wp_block_post_meta( $value, $object_id, $meta_key, $single ) {
425 + if ( 'wp_pattern_sync_status' !== $meta_key ) {
426 + return $value;
113 427 }
428 +
429 + $sync_status = get_post_meta( $object_id, 'sync_status', $single );
430 +
431 + if ( $single && 'unsynced' === $sync_status ) {
432 + return $sync_status;
433 + } elseif ( isset( $sync_status[0] ) && 'unsynced' === $sync_status[0] ) {
434 + return $sync_status;
435 + }
436 +
437 + return $value;
114 438 }
115 439
116 -if ( ! has_action( 'enqueue_block_assets', 'enqueue_block_styles_assets' ) ) {
117 - /**
118 - * Function responsible for enqueuing the styles required for block styles functionality on the editor and on the frontend.
119 - */
120 - function gutenberg_enqueue_block_styles_assets() {
121 - $block_styles = WP_Block_Styles_Registry::get_instance()->get_all_registered();
440 +add_filter( 'default_post_metadata', 'gutenberg_legacy_wp_block_post_meta', 10, 4 );
122 441
123 - foreach ( $block_styles as $styles ) {
124 - foreach ( $styles as $style_properties ) {
125 - if ( isset( $style_properties['style_handle'] ) ) {
126 - wp_enqueue_style( $style_properties['style_handle'] );
127 - }
128 - if ( isset( $style_properties['inline_style'] ) ) {
129 - wp_add_inline_style( 'wp-block-library', $style_properties['inline_style'] );
130 - }
131 - }
442 +/**
443 + * Complements the lightbox implementation for the 'core/image' block.
444 + *
445 + * This function is INTENTIONALLY left out of core as it only provides
446 + * backwards compatibility for the legacy lightbox syntax that was only
447 + * introduced in Gutenberg. The legacy syntax was using the `behaviors` key in
448 + * the block attrbutes and the `theme.json` file.
449 + *
450 + * @since 16.7.0
451 + *
452 + * @param array $block The block to check.
453 + * @return array The block with the legacyLightboxSettings set if available.
454 + */
455 +function gutenberg_should_render_lightbox( $block ) {
456 +
457 + if ( 'core/image' !== $block['blockName'] ) {
458 + return $block;
459 + }
460 +
461 + if ( isset( $block['attrs']['behaviors']['lightbox'] ) ) {
462 + $block['legacyLightboxSettings'] = $block['attrs']['behaviors']['lightbox'];
463 + }
464 +
465 + return $block;
466 +}
467 +
468 +add_filter( 'render_block_data', 'gutenberg_should_render_lightbox', 15, 1 );
469 +
470 +/**
471 + * Registers the metadata block attribute for all block types.
472 + *
473 + * @param array $args Array of arguments for registering a block type.
474 + * @return array $args
475 + */
476 +function gutenberg_register_metadata_attribute( $args ) {
477 + // Setup attributes if needed.
478 + if ( ! isset( $args['attributes'] ) || ! is_array( $args['attributes'] ) ) {
479 + $args['attributes'] = array();
480 + }
481 +
482 + if ( ! array_key_exists( 'metadata', $args['attributes'] ) ) {
483 + $args['attributes']['metadata'] = array(
484 + 'type' => 'object',
485 + );
486 + }
487 +
488 + return $args;
489 +}
490 +add_filter( 'register_block_type_args', 'gutenberg_register_metadata_attribute' );
491 +
492 +/**
493 + * Strips all HTML from the content of footnotes, and sanitizes the ID.
494 + *
495 + * This function expects slashed data on the footnotes content.
496 + *
497 + * @access private
498 + *
499 + * @param string $footnotes JSON encoded string of an array containing the content and ID of each footnote.
500 + * @return string Filtered content without any HTML on the footnote content and with the sanitized id.
501 + */
502 +function _gutenberg_filter_post_meta_footnotes( $footnotes ) {
503 + $footnotes_decoded = json_decode( $footnotes, true );
504 + if ( ! is_array( $footnotes_decoded ) ) {
505 + return '';
506 + }
507 + $footnotes_sanitized = array();
508 + foreach ( $footnotes_decoded as $footnote ) {
509 + if ( ! empty( $footnote['content'] ) && ! empty( $footnote['id'] ) ) {
510 + $footnotes_sanitized[] = array(
511 + 'id' => sanitize_key( $footnote['id'] ),
512 + 'content' => wp_unslash( wp_filter_post_kses( wp_slash( $footnote['content'] ) ) ),
513 + );
132 514 }
133 515 }
134 - add_action( 'enqueue_block_assets', 'gutenberg_enqueue_block_styles_assets', 30 );
516 + return wp_json_encode( $footnotes_sanitized );
135 517 }
136 -if ( ! has_action( 'enqueue_block_editor_assets', 'enqueue_editor_block_styles_assets' ) ) {
137 - /**
138 - * Function responsible for enqueuing the assets required for block styles functionality on the editor.
139 - */
140 - function gutenberg_enqueue_editor_block_styles_assets() {
141 - $block_styles = WP_Block_Styles_Registry::get_instance()->get_all_registered();
142 518
143 - $register_script_lines = array( '( function() {' );
144 - foreach ( $block_styles as $block_name => $styles ) {
145 - foreach ( $styles as $style_properties ) {
146 - $register_script_lines[] = sprintf(
147 - ' wp.blocks.registerBlockStyle( \'%s\', %s );',
148 - $block_name,
149 - wp_json_encode(
150 - array(
151 - 'name' => $style_properties['name'],
152 - 'label' => $style_properties['label'],
153 - )
154 - )
155 - );
156 - }
157 - }
158 - $register_script_lines[] = '} )();';
159 - $inline_script = implode( "\n", $register_script_lines );
519 +/**
520 + * Adds the filters to filter footnotes meta field.
521 + *
522 + * @access private
523 + */
524 +function _gutenberg_footnotes_kses_init_filters() {
525 + add_filter( 'sanitize_post_meta_footnotes', '_gutenberg_filter_post_meta_footnotes' );
526 +}
160 527
161 - wp_register_script( 'wp-block-styles', false, array( 'wp-blocks' ), true, true );
162 - wp_add_inline_script( 'wp-block-styles', $inline_script );
163 - wp_enqueue_script( 'wp-block-styles' );
528 +/**
529 + * Removes the filters that filter footnotes meta field.
530 + *
531 + * @access private
532 + */
533 +function _gutenberg_footnotes_remove_filters() {
534 + remove_filter( 'sanitize_post_meta_footnotes', '_gutenberg_filter_post_meta_footnotes' );
535 +}
536 +
537 +/**
538 + * Registers the filter of footnotes meta field if the user does not have unfiltered_html capability.
539 + *
540 + * @access private
541 + */
542 +function _gutenberg_footnotes_kses_init() {
543 + if ( function_exists( '_wp_filter_post_meta_footnotes' ) ) {
544 + return;
164 545 }
165 - add_action( 'enqueue_block_editor_assets', 'gutenberg_enqueue_editor_block_styles_assets' );
546 + _gutenberg_footnotes_remove_filters();
547 + if ( ! current_user_can( 'unfiltered_html' ) ) {
548 + _gutenberg_footnotes_kses_init_filters();
549 + }
166 550 }
551 +
552 +/**
553 + * Initializes footnotes meta field filters when imported data should be filtered.
554 + *
555 + * This filter is the last being executed on force_filtered_html_on_import.
556 + * If the input of the filter is true it means we are in an import situation and should
557 + * enable kses, independently of the user capabilities.
558 + * So in that case we call _gutenberg_footnotes_kses_init_filters;
559 + *
560 + * @access private
561 + *
562 + * @param string $arg Input argument of the filter.
563 + * @return string Input argument of the filter.
564 + */
565 +function _gutenberg_footnotes_force_filtered_html_on_import_filter( $arg ) {
566 + if ( function_exists( '_wp_filter_post_meta_footnotes' ) ) {
567 + return;
568 + }
569 + // force_filtered_html_on_import is true we need to init the global styles kses filters.
570 + if ( $arg ) {
571 + _gutenberg_footnotes_kses_init_filters();
572 + }
573 + return $arg;
574 +}
575 +
576 +add_action( 'init', '_gutenberg_footnotes_kses_init' );
577 +add_action( 'set_current_user', '_gutenberg_footnotes_kses_init' );
578 +add_filter( 'force_filtered_html_on_import', '_gutenberg_footnotes_force_filtered_html_on_import_filter', 999 );