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

403 lines 13.5 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 * Deregisters the existing core block type and its assets.
177 *
178 * @param string $block_name The name of the block.
179 *
180 * @return void
181 */
182 function gutenberg_deregister_core_block_and_assets( $block_name ) {
183 $registry = WP_Block_Type_Registry::get_instance();
184 if ( $registry->is_registered( $block_name ) ) {
185 $block_type = $registry->get_registered( $block_name );
186 if ( ! empty( $block_type->view_script_handles ) ) {
187 foreach ( $block_type->view_script_handles as $view_script_handle ) {
188 if ( str_starts_with( $view_script_handle, 'wp-block-' ) ) {
189 wp_deregister_script( $view_script_handle );
190 }
191 }
192 }
193 $registry->unregister( $block_name );
194 }
195 }
196
197 /**
198 * Registers block styles for a core block.
199 *
200 * @param string $block_name The block-name.
201 *
202 * @return void
203 */
204 function gutenberg_register_core_block_assets( $block_name ) {
205 if ( ! wp_should_load_separate_core_block_assets() ) {
206 return;
207 }
208
209 $block_name = str_replace( 'core/', '', $block_name );
210
211 // When in production, use the plugin's version as the default asset version;
212 // else (for development or test) default to use the current time.
213 $default_version = defined( 'GUTENBERG_VERSION' ) && ! SCRIPT_DEBUG ? GUTENBERG_VERSION : time();
214
215 $style_path = "build/block-library/blocks/$block_name/";
216 $stylesheet_url = gutenberg_url( $style_path . 'style.css' );
217 $stylesheet_path = gutenberg_dir_path() . $style_path . ( is_rtl() ? 'style-rtl.css' : 'style.css' );
218
219 if ( file_exists( $stylesheet_path ) ) {
220 wp_deregister_style( "wp-block-{$block_name}" );
221 wp_register_style(
222 "wp-block-{$block_name}",
223 $stylesheet_url,
224 array(),
225 $default_version
226 );
227 wp_style_add_data( "wp-block-{$block_name}", 'rtl', 'replace' );
228
229 // Add a reference to the stylesheet's path to allow calculations for inlining styles in `wp_head`.
230 wp_style_add_data( "wp-block-{$block_name}", 'path', $stylesheet_path );
231 } else {
232 wp_register_style( "wp-block-{$block_name}", false, array() );
233 }
234
235 // If the current theme supports wp-block-styles, dequeue the full stylesheet
236 // and instead attach each block's theme-styles to their block styles stylesheet.
237 if ( current_theme_supports( 'wp-block-styles' ) ) {
238
239 // Dequeue the full stylesheet.
240 // Make sure this only runs once, it doesn't need to run for every block.
241 static $stylesheet_removed;
242 if ( ! $stylesheet_removed ) {
243 add_action(
244 'wp_enqueue_scripts',
245 static function() {
246 wp_dequeue_style( 'wp-block-library-theme' );
247 }
248 );
249 $stylesheet_removed = true;
250 }
251
252 // Get the path to the block's stylesheet.
253 $theme_style_path = is_rtl()
254 ? "build/block-library/blocks/$block_name/theme-rtl.css"
255 : "build/block-library/blocks/$block_name/theme.css";
256
257 // If the file exists, enqueue it.
258 if ( file_exists( gutenberg_dir_path() . $theme_style_path ) ) {
259
260 if ( file_exists( $stylesheet_path ) ) {
261 // If there is a main stylesheet for this block, append the theme styles to main styles.
262 wp_add_inline_style(
263 "wp-block-{$block_name}",
264 file_get_contents( gutenberg_dir_path() . $theme_style_path )
265 );
266 } else {
267 // If there is no main stylesheet for this block, register theme style.
268 wp_register_style(
269 "wp-block-{$block_name}",
270 gutenberg_url( $theme_style_path ),
271 array(),
272 $default_version
273 );
274 wp_style_add_data( "wp-block-{$block_name}", 'path', gutenberg_dir_path() . $theme_style_path );
275 }
276 }
277 }
278
279 $editor_style_path = "build/block-library/blocks/$block_name/style-editor.css";
280 if ( file_exists( gutenberg_dir_path() . $editor_style_path ) ) {
281 wp_deregister_style( "wp-block-{$block_name}-editor" );
282 wp_register_style(
283 "wp-block-{$block_name}-editor",
284 gutenberg_url( $editor_style_path ),
285 array(),
286 $default_version
287 );
288 wp_style_add_data( "wp-block-{$block_name}-editor", 'rtl', 'replace' );
289 } else {
290 wp_register_style( "wp-block-{$block_name}-editor", false );
291 }
292 }
293
294 /**
295 * Complements the implementation of block type `core/social-icon`, whether it
296 * be provided by core or the plugin, with derived block types for each
297 * "service" (WordPress, Twitter, etc.) supported by Social Links.
298 *
299 * This ensures backwards compatibility for any users running the Gutenberg
300 * plugin who have used Social Links prior to their conversion to block
301 * variations.
302 *
303 * This shim is INTENTIONALLY left out of core, as Social Links have never
304 * landed there.
305 *
306 * @see https://github.com/WordPress/gutenberg/pull/19887
307 */
308 function gutenberg_register_legacy_social_link_blocks() {
309 $services = array(
310 'amazon',
311 'bandcamp',
312 'behance',
313 'chain',
314 'codepen',
315 'deviantart',
316 'dribbble',
317 'dropbox',
318 'etsy',
319 'facebook',
320 'feed',
321 'fivehundredpx',
322 'flickr',
323 'foursquare',
324 'goodreads',
325 'google',
326 'github',
327 'instagram',
328 'lastfm',
329 'linkedin',
330 'mail',
331 'mastodon',
332 'meetup',
333 'medium',
334 'pinterest',
335 'pocket',
336 'reddit',
337 'skype',
338 'snapchat',
339 'soundcloud',
340 'spotify',
341 'tumblr',
342 'twitch',
343 'twitter',
344 'vimeo',
345 'vk',
346 'wordpress',
347 'yelp',
348 'youtube',
349 );
350
351 foreach ( $services as $service ) {
352 register_block_type(
353 'core/social-link-' . $service,
354 array(
355 'category' => 'widgets',
356 'attributes' => array(
357 'url' => array(
358 'type' => 'string',
359 ),
360 'service' => array(
361 'type' => 'string',
362 'default' => $service,
363 ),
364 'label' => array(
365 'type' => 'string',
366 ),
367 ),
368 'render_callback' => 'gutenberg_render_block_core_social_link',
369 )
370 );
371 }
372 }
373
374 add_action( 'init', 'gutenberg_register_legacy_social_link_blocks' );
375
376 /**
377 * Migrate the legacy `sync_status` meta key (added 16.1) to the new `wp_pattern_sync_status` meta key (16.1.1).
378 *
379 * 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`.
380 * see https://github.com/WordPress/gutenberg/pull/52232
381 *
382 * @param mixed $value The value to return, either a single metadata value or an array of values depending on the value of $single.
383 * @param int $object_id ID of the object metadata is for.
384 * @param string $meta_key Metadata key.
385 * @param bool $single Whether to return only the first value of the specified $meta_key.
386 */
387 function gutenberg_legacy_wp_block_post_meta( $value, $object_id, $meta_key, $single ) {
388 if ( 'wp_pattern_sync_status' !== $meta_key ) {
389 return $value;
390 }
391
392 $sync_status = get_post_meta( $object_id, 'sync_status', $single );
393
394 if ( $single && 'unsynced' === $sync_status ) {
395 return $sync_status;
396 } elseif ( isset( $sync_status[0] ) && 'unsynced' === $sync_status[0] ) {
397 return $sync_status;
398 }
399
400 return $value;
401 }
402 add_filter( 'default_post_metadata', 'gutenberg_legacy_wp_block_post_meta', 10, 4 );
403