PluginProbe
Gutenberg / 10.9.1
Gutenberg v10.9.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 10.9.1, at lib/blocks.php

507 lines 16.0 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_styles( $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_styles( $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_styles( $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 $style_path = "build/block-library/blocks/$block_name/style.css";
175 $editor_style_path = "build/block-library/blocks/$block_name/style-editor.css";
176
177 if ( file_exists( gutenberg_dir_path() . $style_path ) ) {
178 wp_deregister_style( "wp-block-{$block_name}" );
179 wp_register_style(
180 "wp-block-{$block_name}",
181 gutenberg_url( $style_path ),
182 array(),
183 filemtime( gutenberg_dir_path() . $style_path )
184 );
185 wp_style_add_data( "wp-block-{$block_name}", 'rtl', 'replace' );
186
187 // Add a reference to the stylesheet's path to allow calculations for inlining styles in `wp_head`.
188 wp_style_add_data( "wp-block-{$block_name}", 'path', gutenberg_dir_path() . $style_path );
189 } else {
190 wp_register_style( "wp-block-{$block_name}", false );
191 }
192
193 // If the current theme supports wp-block-styles, dequeue the full stylesheet
194 // and instead attach each block's theme-styles to their block styles stylesheet.
195 if ( current_theme_supports( 'wp-block-styles' ) ) {
196
197 // Dequeue the full stylesheet.
198 // Make sure this only runs once, it doesn't need to run for every block.
199 static $stylesheet_removed;
200 if ( ! $stylesheet_removed ) {
201 add_action(
202 'wp_enqueue_scripts',
203 function() {
204 wp_dequeue_style( 'wp-block-library-theme' );
205 }
206 );
207 $stylesheet_removed = true;
208 }
209
210 // Get the path to the block's stylesheet.
211 $theme_style_path = is_rtl()
212 ? "build/block-library/blocks/$block_name/theme-rtl.css"
213 : "build/block-library/blocks/$block_name/theme.css";
214
215 // If the file exists, enqueue it.
216 if ( file_exists( gutenberg_dir_path() . $theme_style_path ) ) {
217
218 if ( file_exists( gutenberg_dir_path() . $style_path ) ) {
219 // If there is a main stylesheet for this block, append the theme styles to main styles.
220 wp_add_inline_style(
221 "wp-block-{$block_name}",
222 file_get_contents( gutenberg_dir_path() . $theme_style_path )
223 );
224 } else {
225 // If there is no main stylesheet for this block, register theme style.
226 wp_register_style(
227 "wp-block-{$block_name}",
228 gutenberg_url( $theme_style_path ),
229 array(),
230 filemtime( gutenberg_dir_path() . $theme_style_path )
231 );
232 wp_style_add_data( "wp-block-{$block_name}", 'path', gutenberg_dir_path() . $theme_style_path );
233 }
234 }
235 }
236
237 if ( file_exists( gutenberg_dir_path() . $editor_style_path ) ) {
238 wp_deregister_style( "wp-block-{$block_name}-editor" );
239 wp_register_style(
240 "wp-block-{$block_name}-editor",
241 gutenberg_url( $editor_style_path ),
242 array(),
243 filemtime( gutenberg_dir_path() . $editor_style_path )
244 );
245 wp_style_add_data( "wp-block-{$block_name}-editor", 'rtl', 'replace' );
246 } else {
247 wp_register_style( "wp-block-{$block_name}-editor", false );
248 }
249 }
250
251 /**
252 * Change the way styles get loaded depending on their size.
253 *
254 * Optimizes performance and sustainability of styles by inlining smaller stylesheets.
255 *
256 * @todo Remove this function when the minimum supported version is WordPress 5.8.
257 *
258 * @return void
259 */
260 function gutenberg_maybe_inline_styles() {
261
262 // Early exit if the "wp_maybe_inline_styles" function exists.
263 if ( function_exists( 'wp_maybe_inline_styles' ) ) {
264 return;
265 }
266
267 $total_inline_limit = 20000;
268 /**
269 * The maximum size of inlined styles in bytes.
270 *
271 * @param int $total_inline_limit The file-size threshold, in bytes. Defaults to 20000.
272 * @return int The file-size threshold, in bytes.
273 */
274 $total_inline_limit = apply_filters( 'styles_inline_size_limit', $total_inline_limit );
275
276 global $wp_styles;
277 $styles = array();
278
279 // Build an array of styles that have a path defined.
280 foreach ( $wp_styles->queue as $handle ) {
281 if ( wp_styles()->get_data( $handle, 'path' ) && file_exists( $wp_styles->registered[ $handle ]->extra['path'] ) ) {
282 $styles[] = array(
283 'handle' => $handle,
284 'path' => $wp_styles->registered[ $handle ]->extra['path'],
285 'size' => filesize( $wp_styles->registered[ $handle ]->extra['path'] ),
286 );
287 }
288 }
289
290 if ( ! empty( $styles ) ) {
291 // Reorder styles array based on size.
292 usort(
293 $styles,
294 function( $a, $b ) {
295 return ( $a['size'] <= $b['size'] ) ? -1 : 1;
296 }
297 );
298
299 /**
300 * The total inlined size.
301 *
302 * On each iteration of the loop, if a style gets added inline the value of this var increases
303 * to reflect the total size of inlined styles.
304 */
305 $total_inline_size = 0;
306
307 // Loop styles.
308 foreach ( $styles as $style ) {
309
310 // Size check. Since styles are ordered by size, we can break the loop.
311 if ( $total_inline_size + $style['size'] > $total_inline_limit ) {
312 break;
313 }
314
315 // Get the styles if we don't already have them.
316 $style['css'] = file_get_contents( $style['path'] );
317
318 // Set `src` to `false` and add styles inline.
319 $wp_styles->registered[ $style['handle'] ]->src = false;
320 if ( empty( $wp_styles->registered[ $style['handle'] ]->extra['after'] ) ) {
321 $wp_styles->registered[ $style['handle'] ]->extra['after'] = array();
322 }
323 array_unshift( $wp_styles->registered[ $style['handle'] ]->extra['after'], $style['css'] );
324
325 // Add the styles size to the $total_inline_size var.
326 $total_inline_size += (int) $style['size'];
327 }
328 }
329 }
330 // Run for styles enqueued in <head>.
331 add_action( 'wp_head', 'gutenberg_maybe_inline_styles', 1 );
332 // Run for late-loaded styles in the footer.
333 add_action( 'wp_footer', 'gutenberg_maybe_inline_styles', 1 );
334
335 /**
336 * Complements the implementation of block type `core/social-icon`, whether it
337 * be provided by core or the plugin, with derived block types for each
338 * "service" (WordPress, Twitter, etc.) supported by Social Links.
339 *
340 * This ensures backwards compatibility for any users running the Gutenberg
341 * plugin who have used Social Links prior to their conversion to block
342 * variations.
343 *
344 * This shim is INTENTIONALLY left out of core, as Social Links haven't yet
345 * landed there.
346 *
347 * @see https://github.com/WordPress/gutenberg/pull/19887
348 */
349 function gutenberg_register_legacy_social_link_blocks() {
350 $services = array(
351 'amazon',
352 'bandcamp',
353 'behance',
354 'chain',
355 'codepen',
356 'deviantart',
357 'dribbble',
358 'dropbox',
359 'etsy',
360 'facebook',
361 'feed',
362 'fivehundredpx',
363 'flickr',
364 'foursquare',
365 'goodreads',
366 'google',
367 'github',
368 'instagram',
369 'lastfm',
370 'linkedin',
371 'mail',
372 'mastodon',
373 'meetup',
374 'medium',
375 'pinterest',
376 'pocket',
377 'reddit',
378 'skype',
379 'snapchat',
380 'soundcloud',
381 'spotify',
382 'tumblr',
383 'twitch',
384 'twitter',
385 'vimeo',
386 'vk',
387 'wordpress',
388 'yelp',
389 'youtube',
390 );
391
392 foreach ( $services as $service ) {
393 register_block_type(
394 'core/social-link-' . $service,
395 array(
396 'category' => 'widgets',
397 'attributes' => array(
398 'url' => array(
399 'type' => 'string',
400 ),
401 'service' => array(
402 'type' => 'string',
403 'default' => $service,
404 ),
405 'label' => array(
406 'type' => 'string',
407 ),
408 ),
409 'render_callback' => 'gutenberg_render_block_core_social_link',
410 )
411 );
412 }
413 }
414
415 add_action( 'init', 'gutenberg_register_legacy_social_link_blocks' );
416
417 /**
418 * Filters the default block categories array to add a new one for themes.
419 *
420 * This can be removed when plugin support requires WordPress 5.8.0+.
421 *
422 * @see https://core.trac.wordpress.org/ticket/52883
423 *
424 * @param array[] $categories The list of default block categories.
425 *
426 * @return array[] Filtered block categories.
427 */
428 function gutenberg_register_theme_block_category( $categories ) {
429 foreach ( $categories as $category ) {
430 // Skip when the category is already set in WordPress core.
431 if (
432 isset( $category['slug'] ) &&
433 'theme' === $category['slug']
434 ) {
435 return $categories;
436 }
437 }
438
439 $categories[] = array(
440 'slug' => 'theme',
441 'title' => _x( 'Theme', 'block category', 'gutenberg' ),
442 'icon' => null,
443 );
444 return $categories;
445 }
446 // This can be removed when plugin support requires WordPress 5.8.0+.
447 if ( ! function_exists( 'get_default_block_categories' ) ) {
448 add_filter( 'block_categories', 'gutenberg_register_theme_block_category' );
449 }
450
451 /**
452 * Checks whether the current block type supports the feature requested.
453 *
454 * @param WP_Block_Type $block_type Block type to check for support.
455 * @param array $feature Path of the feature to check support for.
456 * @param mixed $default Fallback value for feature support, defaults to false.
457 *
458 * @return boolean Whether or not the feature is supported.
459 */
460 function gutenberg_block_has_support( $block_type, $feature, $default = false ) {
461 $block_support = $default;
462 if ( $block_type && property_exists( $block_type, 'supports' ) ) {
463 $block_support = _wp_array_get( $block_type->supports, $feature, $default );
464 }
465
466 return true === $block_support || is_array( $block_support );
467 }
468
469 /**
470 * Updates the shape of supports for declaring fontSize and lineHeight.
471 *
472 * @param array $metadata Metadata for registering a block type.
473 * @return array Metadata for registering a block type with the supports shape updated.
474 */
475 function gutenberg_migrate_old_typography_shape( $metadata ) {
476 // Temporarily disable migrations from core blocks to avoid warnings on versions older than 5.8.
477 if ( isset( $metadata['supports'] ) && false === strpos( $metadata['file'], '/wp-includes/blocks/' ) ) {
478 $typography_keys = array(
479 '__experimentalFontFamily',
480 '__experimentalFontStyle',
481 '__experimentalFontWeight',
482 '__experimentalLetterSpacing',
483 '__experimentalTextDecoration',
484 '__experimentalTextTransform',
485 'fontSize',
486 'lineHeight',
487 );
488 foreach ( $typography_keys as $typography_key ) {
489 $support_for_key = _wp_array_get( $metadata['supports'], array( $typography_key ), null );
490 if ( null !== $support_for_key ) {
491 trigger_error(
492 /* translators: %1$s: Block type, %2$s: typography supports key e.g: fontSize, lineHeight etc... */
493 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 ),
494 headers_sent() || WP_DEBUG ? E_USER_WARNING : E_USER_NOTICE
495 );
496 gutenberg_experimental_set( $metadata['supports'], array( 'typography', $typography_key ), $support_for_key );
497 unset( $metadata['supports'][ $typography_key ] );
498 }
499 }
500 }
501 return $metadata;
502 }
503
504 if ( ! function_exists( 'wp_migrate_old_typography_shape' ) ) {
505 add_filter( 'block_type_metadata', 'gutenberg_migrate_old_typography_shape' );
506 }
507