PluginProbe
Gutenberg / 16.5.1
Gutenberg v16.5.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 16.5.1, at lib/blocks.php

437 lines 14.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Block functions specific for the Gutenberg editor plugin.
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 'comments',
25 'details',
26 'group',
27 'footnotes',
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 'home-link.php' => 'core/home-link',
72 'image.php' => 'core/image',
73 'gallery.php' => 'core/gallery',
74 'heading.php' => 'core/heading',
75 'latest-comments.php' => 'core/latest-comments',
76 'latest-posts.php' => 'core/latest-posts',
77 'loginout.php' => 'core/loginout',
78 'navigation.php' => 'core/navigation',
79 'navigation-link.php' => 'core/navigation-link',
80 'navigation-submenu.php' => 'core/navigation-submenu',
81 'page-list.php' => 'core/page-list',
82 'page-list-item.php' => 'core/page-list-item',
83 'pattern.php' => 'core/pattern',
84 'post-author.php' => 'core/post-author',
85 'post-author-name.php' => 'core/post-author-name',
86 'post-author-biography.php' => 'core/post-author-biography',
87 'post-comment.php' => 'core/post-comment',
88 'post-comments-count.php' => 'core/post-comments-count',
89 'post-comments-form.php' => 'core/post-comments-form',
90 'post-comments-link.php' => 'core/post-comments-link',
91 'post-content.php' => 'core/post-content',
92 'post-date.php' => 'core/post-date',
93 'post-excerpt.php' => 'core/post-excerpt',
94 'post-featured-image.php' => 'core/post-featured-image',
95 'post-navigation-link.php' => 'core/post-navigation-link',
96 'post-terms.php' => 'core/post-terms',
97 'post-time-to-read.php' => 'core/post-time-to-read',
98 'post-title.php' => 'core/post-title',
99 'query.php' => 'core/query',
100 'post-template.php' => 'core/post-template',
101 'query-no-results.php' => 'core/query-no-results',
102 'query-pagination.php' => 'core/query-pagination',
103 'query-pagination-next.php' => 'core/query-pagination-next',
104 'query-pagination-numbers.php' => 'core/query-pagination-numbers',
105 'query-pagination-previous.php' => 'core/query-pagination-previous',
106 'query-title.php' => 'core/query-title',
107 'read-more.php' => 'core/read-more',
108 'rss.php' => 'core/rss',
109 'search.php' => 'core/search',
110 'shortcode.php' => 'core/shortcode',
111 'social-link.php' => 'core/social-link',
112 'site-logo.php' => 'core/site-logo',
113 'site-tagline.php' => 'core/site-tagline',
114 'site-title.php' => 'core/site-title',
115 'tag-cloud.php' => 'core/tag-cloud',
116 'template-part.php' => 'core/template-part',
117 'term-description.php' => 'core/term-description',
118 ),
119 ),
120 __DIR__ . '/../build/edit-widgets/blocks/' => array(
121 'block_folders' => array(
122 'widget-area',
123 ),
124 'block_names' => array(),
125 ),
126 __DIR__ . '/../build/widgets/blocks/' => array(
127 'block_folders' => array(
128 'legacy-widget',
129 'widget-group',
130 ),
131 'block_names' => array(
132 'legacy-widget.php' => 'core/legacy-widget',
133 'widget-group.php' => 'core/widget-group',
134 ),
135 ),
136 );
137 foreach ( $blocks_dirs as $blocks_dir => $details ) {
138 $block_folders = $details['block_folders'];
139 $block_names = $details['block_names'];
140
141 foreach ( $block_folders as $folder_name ) {
142 $block_json_file = $blocks_dir . $folder_name . '/block.json';
143
144 // Ideally, all paths to block metadata files should be listed in
145 // WordPress core. In this place we should rather use filter
146 // to replace paths with overrides defined by the plugin.
147 $metadata = json_decode( file_get_contents( $block_json_file ), true );
148 if ( ! is_array( $metadata ) || ! $metadata['name'] ) {
149 continue;
150 }
151
152 gutenberg_deregister_core_block_and_assets( $metadata['name'] );
153 gutenberg_register_core_block_assets( $folder_name );
154 register_block_type_from_metadata( $block_json_file );
155 }
156
157 foreach ( $block_names as $file => $sub_block_names ) {
158 if ( ! file_exists( $blocks_dir . $file ) ) {
159 continue;
160 }
161
162 $sub_block_names_normalized = is_string( $sub_block_names ) ? array( $sub_block_names ) : $sub_block_names;
163 foreach ( $sub_block_names_normalized as $block_name ) {
164 gutenberg_deregister_core_block_and_assets( $block_name );
165 gutenberg_register_core_block_assets( $block_name );
166 }
167
168 require_once $blocks_dir . $file;
169 }
170 }
171 }
172
173 add_action( 'init', 'gutenberg_reregister_core_block_types' );
174
175 /**
176 * Adds the defer loading strategy to all registered blocks.
177 *
178 * This function would not be part of core merge. Instead, the register_block_script_handle() function would be patched
179 * as follows.
180 *
181 * ```
182 * --- a/wp-includes/blocks.php
183 * +++ b/wp-includes/blocks.php
184 * @ @ -153,7 +153,8 @ @ function register_block_script_handle( $metadata, $field_name, $index = 0 ) {
185 * $script_handle,
186 * $script_uri,
187 * $script_dependencies,
188 * - isset( $script_asset['version'] ) ? $script_asset['version'] : false
189 * + isset( $script_asset['version'] ) ? $script_asset['version'] : false,
190 * + array( 'strategy' => 'defer' )
191 * );
192 * if ( ! $result ) {
193 * return false;
194 * ```
195 *
196 * @see register_block_script_handle()
197 */
198 function gutenberg_defer_block_view_scripts() {
199 $block_types = WP_Block_Type_Registry::get_instance()->get_all_registered();
200 foreach ( $block_types as $block_type ) {
201 foreach ( $block_type->view_script_handles as $view_script_handle ) {
202 wp_script_add_data( $view_script_handle, 'strategy', 'defer' );
203 }
204 }
205 }
206
207 add_action( 'init', 'gutenberg_defer_block_view_scripts', 100 );
208
209 /**
210 * Deregisters the existing core block type and its assets.
211 *
212 * @param string $block_name The name of the block.
213 *
214 * @return void
215 */
216 function gutenberg_deregister_core_block_and_assets( $block_name ) {
217 $registry = WP_Block_Type_Registry::get_instance();
218 if ( $registry->is_registered( $block_name ) ) {
219 $block_type = $registry->get_registered( $block_name );
220 if ( ! empty( $block_type->view_script_handles ) ) {
221 foreach ( $block_type->view_script_handles as $view_script_handle ) {
222 if ( str_starts_with( $view_script_handle, 'wp-block-' ) ) {
223 wp_deregister_script( $view_script_handle );
224 }
225 }
226 }
227 $registry->unregister( $block_name );
228 }
229 }
230
231 /**
232 * Registers block styles for a core block.
233 *
234 * @param string $block_name The block-name.
235 *
236 * @return void
237 */
238 function gutenberg_register_core_block_assets( $block_name ) {
239 if ( ! wp_should_load_separate_core_block_assets() ) {
240 return;
241 }
242
243 $block_name = str_replace( 'core/', '', $block_name );
244
245 // When in production, use the plugin's version as the default asset version;
246 // else (for development or test) default to use the current time.
247 $default_version = defined( 'GUTENBERG_VERSION' ) && ! SCRIPT_DEBUG ? GUTENBERG_VERSION : time();
248
249 $style_path = "build/block-library/blocks/$block_name/";
250 $stylesheet_url = gutenberg_url( $style_path . 'style.css' );
251 $stylesheet_path = gutenberg_dir_path() . $style_path . ( is_rtl() ? 'style-rtl.css' : 'style.css' );
252
253 if ( file_exists( $stylesheet_path ) ) {
254 wp_deregister_style( "wp-block-{$block_name}" );
255 wp_register_style(
256 "wp-block-{$block_name}",
257 $stylesheet_url,
258 array(),
259 $default_version
260 );
261 wp_style_add_data( "wp-block-{$block_name}", 'rtl', 'replace' );
262
263 // Add a reference to the stylesheet's path to allow calculations for inlining styles in `wp_head`.
264 wp_style_add_data( "wp-block-{$block_name}", 'path', $stylesheet_path );
265 } else {
266 wp_register_style( "wp-block-{$block_name}", false, array() );
267 }
268
269 // If the current theme supports wp-block-styles, dequeue the full stylesheet
270 // and instead attach each block's theme-styles to their block styles stylesheet.
271 if ( current_theme_supports( 'wp-block-styles' ) ) {
272
273 // Dequeue the full stylesheet.
274 // Make sure this only runs once, it doesn't need to run for every block.
275 static $stylesheet_removed;
276 if ( ! $stylesheet_removed ) {
277 add_action(
278 'wp_enqueue_scripts',
279 static function() {
280 wp_dequeue_style( 'wp-block-library-theme' );
281 }
282 );
283 $stylesheet_removed = true;
284 }
285
286 // Get the path to the block's stylesheet.
287 $theme_style_path = is_rtl()
288 ? "build/block-library/blocks/$block_name/theme-rtl.css"
289 : "build/block-library/blocks/$block_name/theme.css";
290
291 // If the file exists, enqueue it.
292 if ( file_exists( gutenberg_dir_path() . $theme_style_path ) ) {
293
294 if ( file_exists( $stylesheet_path ) ) {
295 // If there is a main stylesheet for this block, append the theme styles to main styles.
296 wp_add_inline_style(
297 "wp-block-{$block_name}",
298 file_get_contents( gutenberg_dir_path() . $theme_style_path )
299 );
300 } else {
301 // If there is no main stylesheet for this block, register theme style.
302 wp_register_style(
303 "wp-block-{$block_name}",
304 gutenberg_url( $theme_style_path ),
305 array(),
306 $default_version
307 );
308 wp_style_add_data( "wp-block-{$block_name}", 'path', gutenberg_dir_path() . $theme_style_path );
309 }
310 }
311 }
312
313 $editor_style_path = "build/block-library/blocks/$block_name/style-editor.css";
314 if ( file_exists( gutenberg_dir_path() . $editor_style_path ) ) {
315 wp_deregister_style( "wp-block-{$block_name}-editor" );
316 wp_register_style(
317 "wp-block-{$block_name}-editor",
318 gutenberg_url( $editor_style_path ),
319 array(),
320 $default_version
321 );
322 wp_style_add_data( "wp-block-{$block_name}-editor", 'rtl', 'replace' );
323 } else {
324 wp_register_style( "wp-block-{$block_name}-editor", false );
325 }
326 }
327
328 /**
329 * Complements the implementation of block type `core/social-icon`, whether it
330 * be provided by core or the plugin, with derived block types for each
331 * "service" (WordPress, Twitter, etc.) supported by Social Links.
332 *
333 * This ensures backwards compatibility for any users running the Gutenberg
334 * plugin who have used Social Links prior to their conversion to block
335 * variations.
336 *
337 * This shim is INTENTIONALLY left out of core, as Social Links have never
338 * landed there.
339 *
340 * @see https://github.com/WordPress/gutenberg/pull/19887
341 */
342 function gutenberg_register_legacy_social_link_blocks() {
343 $services = array(
344 'amazon',
345 'bandcamp',
346 'behance',
347 'chain',
348 'codepen',
349 'deviantart',
350 'dribbble',
351 'dropbox',
352 'etsy',
353 'facebook',
354 'feed',
355 'fivehundredpx',
356 'flickr',
357 'foursquare',
358 'goodreads',
359 'google',
360 'github',
361 'instagram',
362 'lastfm',
363 'linkedin',
364 'mail',
365 'mastodon',
366 'meetup',
367 'medium',
368 'pinterest',
369 'pocket',
370 'reddit',
371 'skype',
372 'snapchat',
373 'soundcloud',
374 'spotify',
375 'tumblr',
376 'twitch',
377 'twitter',
378 'vimeo',
379 'vk',
380 'wordpress',
381 'yelp',
382 'youtube',
383 );
384
385 foreach ( $services as $service ) {
386 register_block_type(
387 'core/social-link-' . $service,
388 array(
389 'category' => 'widgets',
390 'attributes' => array(
391 'url' => array(
392 'type' => 'string',
393 ),
394 'service' => array(
395 'type' => 'string',
396 'default' => $service,
397 ),
398 'label' => array(
399 'type' => 'string',
400 ),
401 ),
402 'render_callback' => 'gutenberg_render_block_core_social_link',
403 )
404 );
405 }
406 }
407
408 add_action( 'init', 'gutenberg_register_legacy_social_link_blocks' );
409
410 /**
411 * Migrate the legacy `sync_status` meta key (added 16.1) to the new `wp_pattern_sync_status` meta key (16.1.1).
412 *
413 * 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`.
414 * see https://github.com/WordPress/gutenberg/pull/52232
415 *
416 * @param mixed $value The value to return, either a single metadata value or an array of values depending on the value of $single.
417 * @param int $object_id ID of the object metadata is for.
418 * @param string $meta_key Metadata key.
419 * @param bool $single Whether to return only the first value of the specified $meta_key.
420 */
421 function gutenberg_legacy_wp_block_post_meta( $value, $object_id, $meta_key, $single ) {
422 if ( 'wp_pattern_sync_status' !== $meta_key ) {
423 return $value;
424 }
425
426 $sync_status = get_post_meta( $object_id, 'sync_status', $single );
427
428 if ( $single && 'unsynced' === $sync_status ) {
429 return $sync_status;
430 } elseif ( isset( $sync_status[0] ) && 'unsynced' === $sync_status[0] ) {
431 return $sync_status;
432 }
433
434 return $value;
435 }
436 add_filter( 'default_post_metadata', 'gutenberg_legacy_wp_block_post_meta', 10, 4 );
437