PluginProbe
Gutenberg / 11.2.1
Gutenberg v11.2.1
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 / blocks.php

blocks.php in Gutenberg 11.2.1, at lib/blocks.php

511 lines 16.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Block and style registration functions.
4 *
5 * @package gutenberg
6 */
7
8 /**
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 'cover',
25 'gallery',
26 'group',
27 'heading',
28 'html',
29 'home-link',
30 'image',
31 'list',
32 'media-text',
33 'missing',
34 'more',
35 'navigation-link',
36 'nextpage',
37 'paragraph',
38 'preformatted',
39 'pullquote',
40 'quote',
41 'separator',
42 'social-links',
43 'spacer',
44 'table',
45 // 'table-of-contents',
46 'text-columns',
47 'verse',
48 'video',
49 'embed',
50 ),
51 'block_names' => array(
52 'archives.php' => 'core/archives',
53 'block.php' => 'core/block',
54 'calendar.php' => 'core/calendar',
55 'categories.php' => 'core/categories',
56 'file.php' => 'core/file',
57 'latest-comments.php' => 'core/latest-comments',
58 'latest-posts.php' => 'core/latest-posts',
59 'loginout.php' => 'core/loginout',
60 'navigation.php' => 'core/navigation',
61 'navigation-link.php' => 'core/navigation-link',
62 'home-link.php' => 'core/home-link',
63 'rss.php' => 'core/rss',
64 'search.php' => 'core/search',
65 'shortcode.php' => 'core/shortcode',
66 'social-link.php' => 'core/social-link',
67 'tag-cloud.php' => 'core/tag-cloud',
68 'page-list.php' => 'core/page-list',
69 'post-author.php' => 'core/post-author',
70 'post-comment.php' => 'core/post-comment',
71 'post-comment-author.php' => 'core/post-comment-author',
72 'post-comment-content.php' => 'core/post-comment-content',
73 'post-comment-date.php' => 'core/post-comment-date',
74 'post-comments.php' => 'core/post-comments',
75 'post-comments-count.php' => 'core/post-comments-count',
76 'post-comments-form.php' => 'core/post-comments-form',
77 'post-comments-link.php' => 'core/post-comments-link',
78 'post-content.php' => 'core/post-content',
79 'post-date.php' => 'core/post-date',
80 'post-excerpt.php' => 'core/post-excerpt',
81 'post-featured-image.php' => 'core/post-featured-image',
82 'post-terms.php' => 'core/post-terms',
83 'post-navigation-link.php' => 'core/post-navigation-link',
84 'post-title.php' => 'core/post-title',
85 'query.php' => 'core/query',
86 'post-template.php' => 'core/post-template',
87 'query-title.php' => 'core/query-title',
88 'query-pagination.php' => 'core/query-pagination',
89 'query-pagination-next.php' => 'core/query-pagination-next',
90 'query-pagination-numbers.php' => 'core/query-pagination-numbers',
91 'query-pagination-previous.php' => 'core/query-pagination-previous',
92 'site-logo.php' => 'core/site-logo',
93 'site-tagline.php' => 'core/site-tagline',
94 'site-title.php' => 'core/site-title',
95 // 'table-of-contents.php' => 'core/table-of-contents',
96 'template-part.php' => 'core/template-part',
97 'term-description.php' => 'core/term-description',
98 ),
99 ),
100 __DIR__ . '/../build/edit-widgets/blocks/' => array(
101 'block_folders' => array(
102 'widget-area',
103 ),
104 'block_names' => array(),
105 ),
106 __DIR__ . '/../build/widgets/blocks/' => array(
107 'block_folders' => array(
108 'legacy-widget',
109 ),
110 'block_names' => array(
111 'legacy-widget.php' => 'core/legacy-widget',
112 ),
113 ),
114 );
115 foreach ( $blocks_dirs as $blocks_dir => $details ) {
116 $block_folders = $details['block_folders'];
117 $block_names = $details['block_names'];
118
119 $registry = WP_Block_Type_Registry::get_instance();
120
121 foreach ( $block_folders as $folder_name ) {
122 $block_json_file = $blocks_dir . $folder_name . '/block.json';
123
124 // Ideally, all paths to block metadata files should be listed in
125 // WordPress core. In this place we should rather use filter
126 // to replace paths with overrides defined by the plugin.
127 $metadata = json_decode( file_get_contents( $block_json_file ), true );
128 if ( ! is_array( $metadata ) || ! $metadata['name'] ) {
129 return false;
130 }
131
132 if ( $registry->is_registered( $metadata['name'] ) ) {
133 $registry->unregister( $metadata['name'] );
134 }
135
136 gutenberg_register_core_block_assets( $folder_name );
137 register_block_type_from_metadata( $block_json_file );
138 }
139
140 foreach ( $block_names as $file => $sub_block_names ) {
141 if ( ! file_exists( $blocks_dir . $file ) ) {
142 return;
143 }
144
145 $sub_block_names_normalized = is_string( $sub_block_names ) ? array( $sub_block_names ) : $sub_block_names;
146 foreach ( $sub_block_names_normalized as $block_name ) {
147 if ( $registry->is_registered( $block_name ) ) {
148 $registry->unregister( $block_name );
149 }
150 gutenberg_register_core_block_assets( $block_name );
151 }
152
153 require_once $blocks_dir . $file;
154 }
155 }
156 }
157
158 add_action( 'init', 'gutenberg_reregister_core_block_types' );
159
160 /**
161 * Registers block styles for a core block.
162 *
163 * @param string $block_name The block-name.
164 *
165 * @return void
166 */
167 function gutenberg_register_core_block_assets( $block_name ) {
168 if ( ! wp_should_load_separate_core_block_assets() ) {
169 return;
170 }
171
172 $block_name = str_replace( 'core/', '', $block_name );
173
174 // When in production, use the plugin's version as the default asset version;
175 // else (for development or test) default to use the current time.
176 $default_version = defined( 'GUTENBERG_VERSION' ) && ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? GUTENBERG_VERSION : time();
177
178 $style_path = "build/block-library/blocks/$block_name/style.css";
179 $editor_style_path = "build/block-library/blocks/$block_name/style-editor.css";
180
181 if ( file_exists( gutenberg_dir_path() . $style_path ) ) {
182 wp_deregister_style( "wp-block-{$block_name}" );
183 wp_register_style(
184 "wp-block-{$block_name}",
185 gutenberg_url( $style_path ),
186 array(),
187 $default_version
188 );
189 wp_style_add_data( "wp-block-{$block_name}", 'rtl', 'replace' );
190
191 // Add a reference to the stylesheet's path to allow calculations for inlining styles in `wp_head`.
192 wp_style_add_data( "wp-block-{$block_name}", 'path', gutenberg_dir_path() . $style_path );
193 } else {
194 wp_register_style( "wp-block-{$block_name}", false );
195 }
196
197 // If the current theme supports wp-block-styles, dequeue the full stylesheet
198 // and instead attach each block's theme-styles to their block styles stylesheet.
199 if ( current_theme_supports( 'wp-block-styles' ) ) {
200
201 // Dequeue the full stylesheet.
202 // Make sure this only runs once, it doesn't need to run for every block.
203 static $stylesheet_removed;
204 if ( ! $stylesheet_removed ) {
205 add_action(
206 'wp_enqueue_scripts',
207 function() {
208 wp_dequeue_style( 'wp-block-library-theme' );
209 }
210 );
211 $stylesheet_removed = true;
212 }
213
214 // Get the path to the block's stylesheet.
215 $theme_style_path = is_rtl()
216 ? "build/block-library/blocks/$block_name/theme-rtl.css"
217 : "build/block-library/blocks/$block_name/theme.css";
218
219 // If the file exists, enqueue it.
220 if ( file_exists( gutenberg_dir_path() . $theme_style_path ) ) {
221
222 if ( file_exists( gutenberg_dir_path() . $style_path ) ) {
223 // If there is a main stylesheet for this block, append the theme styles to main styles.
224 wp_add_inline_style(
225 "wp-block-{$block_name}",
226 file_get_contents( gutenberg_dir_path() . $theme_style_path )
227 );
228 } else {
229 // If there is no main stylesheet for this block, register theme style.
230 wp_register_style(
231 "wp-block-{$block_name}",
232 gutenberg_url( $theme_style_path ),
233 array(),
234 $default_version
235 );
236 wp_style_add_data( "wp-block-{$block_name}", 'path', gutenberg_dir_path() . $theme_style_path );
237 }
238 }
239 }
240
241 if ( file_exists( gutenberg_dir_path() . $editor_style_path ) ) {
242 wp_deregister_style( "wp-block-{$block_name}-editor" );
243 wp_register_style(
244 "wp-block-{$block_name}-editor",
245 gutenberg_url( $editor_style_path ),
246 array(),
247 $default_version
248 );
249 wp_style_add_data( "wp-block-{$block_name}-editor", 'rtl', 'replace' );
250 } else {
251 wp_register_style( "wp-block-{$block_name}-editor", false );
252 }
253 }
254
255 /**
256 * Change the way styles get loaded depending on their size.
257 *
258 * Optimizes performance and sustainability of styles by inlining smaller stylesheets.
259 *
260 * @todo Remove this function when the minimum supported version is WordPress 5.8.
261 *
262 * @return void
263 */
264 function gutenberg_maybe_inline_styles() {
265
266 // Early exit if the "wp_maybe_inline_styles" function exists.
267 if ( function_exists( 'wp_maybe_inline_styles' ) ) {
268 return;
269 }
270
271 $total_inline_limit = 20000;
272 /**
273 * The maximum size of inlined styles in bytes.
274 *
275 * @param int $total_inline_limit The file-size threshold, in bytes. Defaults to 20000.
276 * @return int The file-size threshold, in bytes.
277 */
278 $total_inline_limit = apply_filters( 'styles_inline_size_limit', $total_inline_limit );
279
280 global $wp_styles;
281 $styles = array();
282
283 // Build an array of styles that have a path defined.
284 foreach ( $wp_styles->queue as $handle ) {
285 if ( wp_styles()->get_data( $handle, 'path' ) && file_exists( $wp_styles->registered[ $handle ]->extra['path'] ) ) {
286 $styles[] = array(
287 'handle' => $handle,
288 'path' => $wp_styles->registered[ $handle ]->extra['path'],
289 'size' => filesize( $wp_styles->registered[ $handle ]->extra['path'] ),
290 );
291 }
292 }
293
294 if ( ! empty( $styles ) ) {
295 // Reorder styles array based on size.
296 usort(
297 $styles,
298 function( $a, $b ) {
299 return ( $a['size'] <= $b['size'] ) ? -1 : 1;
300 }
301 );
302
303 /**
304 * The total inlined size.
305 *
306 * On each iteration of the loop, if a style gets added inline the value of this var increases
307 * to reflect the total size of inlined styles.
308 */
309 $total_inline_size = 0;
310
311 // Loop styles.
312 foreach ( $styles as $style ) {
313
314 // Size check. Since styles are ordered by size, we can break the loop.
315 if ( $total_inline_size + $style['size'] > $total_inline_limit ) {
316 break;
317 }
318
319 // Get the styles if we don't already have them.
320 $style['css'] = file_get_contents( $style['path'] );
321
322 // Set `src` to `false` and add styles inline.
323 $wp_styles->registered[ $style['handle'] ]->src = false;
324 if ( empty( $wp_styles->registered[ $style['handle'] ]->extra['after'] ) ) {
325 $wp_styles->registered[ $style['handle'] ]->extra['after'] = array();
326 }
327 array_unshift( $wp_styles->registered[ $style['handle'] ]->extra['after'], $style['css'] );
328
329 // Add the styles size to the $total_inline_size var.
330 $total_inline_size += (int) $style['size'];
331 }
332 }
333 }
334 // Run for styles enqueued in <head>.
335 add_action( 'wp_head', 'gutenberg_maybe_inline_styles', 1 );
336 // Run for late-loaded styles in the footer.
337 add_action( 'wp_footer', 'gutenberg_maybe_inline_styles', 1 );
338
339 /**
340 * Complements the implementation of block type `core/social-icon`, whether it
341 * be provided by core or the plugin, with derived block types for each
342 * "service" (WordPress, Twitter, etc.) supported by Social Links.
343 *
344 * This ensures backwards compatibility for any users running the Gutenberg
345 * plugin who have used Social Links prior to their conversion to block
346 * variations.
347 *
348 * This shim is INTENTIONALLY left out of core, as Social Links haven't yet
349 * landed there.
350 *
351 * @see https://github.com/WordPress/gutenberg/pull/19887
352 */
353 function gutenberg_register_legacy_social_link_blocks() {
354 $services = array(
355 'amazon',
356 'bandcamp',
357 'behance',
358 'chain',
359 'codepen',
360 'deviantart',
361 'dribbble',
362 'dropbox',
363 'etsy',
364 'facebook',
365 'feed',
366 'fivehundredpx',
367 'flickr',
368 'foursquare',
369 'goodreads',
370 'google',
371 'github',
372 'instagram',
373 'lastfm',
374 'linkedin',
375 'mail',
376 'mastodon',
377 'meetup',
378 'medium',
379 'pinterest',
380 'pocket',
381 'reddit',
382 'skype',
383 'snapchat',
384 'soundcloud',
385 'spotify',
386 'tumblr',
387 'twitch',
388 'twitter',
389 'vimeo',
390 'vk',
391 'wordpress',
392 'yelp',
393 'youtube',
394 );
395
396 foreach ( $services as $service ) {
397 register_block_type(
398 'core/social-link-' . $service,
399 array(
400 'category' => 'widgets',
401 'attributes' => array(
402 'url' => array(
403 'type' => 'string',
404 ),
405 'service' => array(
406 'type' => 'string',
407 'default' => $service,
408 ),
409 'label' => array(
410 'type' => 'string',
411 ),
412 ),
413 'render_callback' => 'gutenberg_render_block_core_social_link',
414 )
415 );
416 }
417 }
418
419 add_action( 'init', 'gutenberg_register_legacy_social_link_blocks' );
420
421 /**
422 * Filters the default block categories array to add a new one for themes.
423 *
424 * This can be removed when plugin support requires WordPress 5.8.0+.
425 *
426 * @see https://core.trac.wordpress.org/ticket/52883
427 *
428 * @param array[] $categories The list of default block categories.
429 *
430 * @return array[] Filtered block categories.
431 */
432 function gutenberg_register_theme_block_category( $categories ) {
433 foreach ( $categories as $category ) {
434 // Skip when the category is already set in WordPress core.
435 if (
436 isset( $category['slug'] ) &&
437 'theme' === $category['slug']
438 ) {
439 return $categories;
440 }
441 }
442
443 $categories[] = array(
444 'slug' => 'theme',
445 'title' => _x( 'Theme', 'block category', 'gutenberg' ),
446 'icon' => null,
447 );
448 return $categories;
449 }
450 // This can be removed when plugin support requires WordPress 5.8.0+.
451 if ( ! function_exists( 'get_default_block_categories' ) ) {
452 add_filter( 'block_categories', 'gutenberg_register_theme_block_category' );
453 }
454
455 /**
456 * Checks whether the current block type supports the feature requested.
457 *
458 * @param WP_Block_Type $block_type Block type to check for support.
459 * @param array $feature Path of the feature to check support for.
460 * @param mixed $default Fallback value for feature support, defaults to false.
461 *
462 * @return boolean Whether or not the feature is supported.
463 */
464 function gutenberg_block_has_support( $block_type, $feature, $default = false ) {
465 $block_support = $default;
466 if ( $block_type && property_exists( $block_type, 'supports' ) ) {
467 $block_support = _wp_array_get( $block_type->supports, $feature, $default );
468 }
469
470 return true === $block_support || is_array( $block_support );
471 }
472
473 /**
474 * Updates the shape of supports for declaring fontSize and lineHeight.
475 *
476 * @param array $metadata Metadata for registering a block type.
477 * @return array Metadata for registering a block type with the supports shape updated.
478 */
479 function gutenberg_migrate_old_typography_shape( $metadata ) {
480 // Temporarily disable migrations from core blocks to avoid warnings on versions older than 5.8.
481 if ( isset( $metadata['supports'] ) && false === strpos( $metadata['file'], '/wp-includes/blocks/' ) ) {
482 $typography_keys = array(
483 '__experimentalFontFamily',
484 '__experimentalFontStyle',
485 '__experimentalFontWeight',
486 '__experimentalLetterSpacing',
487 '__experimentalTextDecoration',
488 '__experimentalTextTransform',
489 'fontSize',
490 'lineHeight',
491 );
492 foreach ( $typography_keys as $typography_key ) {
493 $support_for_key = _wp_array_get( $metadata['supports'], array( $typography_key ), null );
494 if ( null !== $support_for_key ) {
495 trigger_error(
496 /* translators: %1$s: Block type, %2$s: typography supports key e.g: fontSize, lineHeight etc... */
497 sprintf( __( 'Block %1$s is declaring %2$s support on block.json under supports.%2$s. %2$s support is now declared under supports.typography.%2$s.', 'gutenberg' ), $metadata['name'], $typography_key ),
498 headers_sent() || WP_DEBUG ? E_USER_WARNING : E_USER_NOTICE
499 );
500 gutenberg_experimental_set( $metadata['supports'], array( 'typography', $typography_key ), $support_for_key );
501 unset( $metadata['supports'][ $typography_key ] );
502 }
503 }
504 }
505 return $metadata;
506 }
507
508 if ( ! function_exists( 'wp_migrate_old_typography_shape' ) ) {
509 add_filter( 'block_type_metadata', 'gutenberg_migrate_old_typography_shape' );
510 }
511