PluginProbe
Gutenberg / 12.6.0
Gutenberg v12.6.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 7.4.0 All 402 releases
gutenberg / build / block-library / blocks / navigation.php

navigation.php in Gutenberg 12.6.0, at build/block-library/blocks/navigation.php

626 lines 23.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Server-side rendering of the `core/navigation` block.
4 *
5 * @package WordPress
6 */
7
8 // These functions are used for the __unstableLocation feature and only active
9 // when the gutenberg plugin is active.
10 if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
11 /**
12 * Returns the menu items for a WordPress menu location.
13 *
14 * @param string $location The menu location.
15 * @return array Menu items for the location.
16 */
17 function gutenberg_block_core_navigation_get_menu_items_at_location( $location ) {
18 if ( empty( $location ) ) {
19 return;
20 }
21
22 // Build menu data. The following approximates the code in
23 // `wp_nav_menu()` and `gutenberg_output_block_nav_menu`.
24
25 // Find the location in the list of locations, returning early if the
26 // location can't be found.
27 $locations = get_nav_menu_locations();
28 if ( ! isset( $locations[ $location ] ) ) {
29 return;
30 }
31
32 // Get the menu from the location, returning early if there is no
33 // menu or there was an error.
34 $menu = wp_get_nav_menu_object( $locations[ $location ] );
35 if ( ! $menu || is_wp_error( $menu ) ) {
36 return;
37 }
38
39 $menu_items = wp_get_nav_menu_items( $menu->term_id, array( 'update_post_term_cache' => false ) );
40 _wp_menu_item_classes_by_context( $menu_items );
41
42 return $menu_items;
43 }
44
45
46 /**
47 * Sorts a standard array of menu items into a nested structure keyed by the
48 * id of the parent menu.
49 *
50 * @param array $menu_items Menu items to sort.
51 * @return array An array keyed by the id of the parent menu where each element
52 * is an array of menu items that belong to that parent.
53 */
54 function gutenberg_block_core_navigation_sort_menu_items_by_parent_id( $menu_items ) {
55 $sorted_menu_items = array();
56 foreach ( (array) $menu_items as $menu_item ) {
57 $sorted_menu_items[ $menu_item->menu_order ] = $menu_item;
58 }
59 unset( $menu_items, $menu_item );
60
61 $menu_items_by_parent_id = array();
62 foreach ( $sorted_menu_items as $menu_item ) {
63 $menu_items_by_parent_id[ $menu_item->menu_item_parent ][] = $menu_item;
64 }
65
66 return $menu_items_by_parent_id;
67 }
68
69 /**
70 * Turns menu item data into a nested array of parsed blocks
71 *
72 * @param array $menu_items An array of menu items that represent
73 * an individual level of a menu.
74 * @param array $menu_items_by_parent_id An array keyed by the id of the
75 * parent menu where each element is an
76 * array of menu items that belong to
77 * that parent.
78 * @return array An array of parsed block data.
79 */
80 function gutenberg_block_core_navigation_parse_blocks_from_menu_items( $menu_items, $menu_items_by_parent_id ) {
81 if ( empty( $menu_items ) ) {
82 return array();
83 }
84
85 $blocks = array();
86
87 foreach ( $menu_items as $menu_item ) {
88 $class_name = ! empty( $menu_item->classes ) ? implode( ' ', (array) $menu_item->classes ) : null;
89 $id = ( null !== $menu_item->object_id && 'custom' !== $menu_item->object ) ? $menu_item->object_id : null;
90 $opens_in_new_tab = null !== $menu_item->target && '_blank' === $menu_item->target;
91 $rel = ( null !== $menu_item->xfn && '' !== $menu_item->xfn ) ? $menu_item->xfn : null;
92 $kind = null !== $menu_item->type ? str_replace( '_', '-', $menu_item->type ) : 'custom';
93
94 $block = array(
95 'blockName' => isset( $menu_items_by_parent_id[ $menu_item->ID ] ) ? 'core/navigation-submenu' : 'core/navigation-link',
96 'attrs' => array(
97 'className' => $class_name,
98 'description' => $menu_item->description,
99 'id' => $id,
100 'kind' => $kind,
101 'label' => $menu_item->title,
102 'opensInNewTab' => $opens_in_new_tab,
103 'rel' => $rel,
104 'title' => $menu_item->attr_title,
105 'type' => $menu_item->object,
106 'url' => $menu_item->url,
107 ),
108 );
109
110 $block['innerBlocks'] = isset( $menu_items_by_parent_id[ $menu_item->ID ] )
111 ? gutenberg_block_core_navigation_parse_blocks_from_menu_items( $menu_items_by_parent_id[ $menu_item->ID ], $menu_items_by_parent_id )
112 : array();
113 $block['innerContent'] = array_map( 'serialize_block', $block['innerBlocks'] );
114
115 $blocks[] = $block;
116 }
117
118 return $blocks;
119 }
120 }
121
122 /**
123 * Build an array with CSS classes and inline styles defining the colors
124 * which will be applied to the navigation markup in the front-end.
125 *
126 * @param array $attributes Navigation block attributes.
127 *
128 * @return array Colors CSS classes and inline styles.
129 */
130 function gutenberg_block_core_navigation_build_css_colors( $attributes ) {
131 $colors = array(
132 'css_classes' => array(),
133 'inline_styles' => '',
134 'overlay_css_classes' => array(),
135 'overlay_inline_styles' => '',
136 );
137
138 // Text color.
139 $has_named_text_color = array_key_exists( 'textColor', $attributes );
140 $has_custom_text_color = array_key_exists( 'customTextColor', $attributes );
141
142 // If has text color.
143 if ( $has_custom_text_color || $has_named_text_color ) {
144 // Add has-text-color class.
145 $colors['css_classes'][] = 'has-text-color';
146 }
147
148 if ( $has_named_text_color ) {
149 // Add the color class.
150 $colors['css_classes'][] = sprintf( 'has-%s-color', $attributes['textColor'] );
151 } elseif ( $has_custom_text_color ) {
152 // Add the custom color inline style.
153 $colors['inline_styles'] .= sprintf( 'color: %s;', $attributes['customTextColor'] );
154 }
155
156 // Background color.
157 $has_named_background_color = array_key_exists( 'backgroundColor', $attributes );
158 $has_custom_background_color = array_key_exists( 'customBackgroundColor', $attributes );
159
160 // If has background color.
161 if ( $has_custom_background_color || $has_named_background_color ) {
162 // Add has-background class.
163 $colors['css_classes'][] = 'has-background';
164 }
165
166 if ( $has_named_background_color ) {
167 // Add the background-color class.
168 $colors['css_classes'][] = sprintf( 'has-%s-background-color', $attributes['backgroundColor'] );
169 } elseif ( $has_custom_background_color ) {
170 // Add the custom background-color inline style.
171 $colors['inline_styles'] .= sprintf( 'background-color: %s;', $attributes['customBackgroundColor'] );
172 }
173
174 // Overlay text color.
175 $has_named_overlay_text_color = array_key_exists( 'overlayTextColor', $attributes );
176 $has_custom_overlay_text_color = array_key_exists( 'customOverlayTextColor', $attributes );
177
178 // If has overlay text color.
179 if ( $has_custom_overlay_text_color || $has_named_overlay_text_color ) {
180 // Add has-text-color class.
181 $colors['overlay_css_classes'][] = 'has-text-color';
182 }
183
184 if ( $has_named_overlay_text_color ) {
185 // Add the overlay color class.
186 $colors['overlay_css_classes'][] = sprintf( 'has-%s-color', $attributes['overlayTextColor'] );
187 } elseif ( $has_custom_overlay_text_color ) {
188 // Add the custom overlay color inline style.
189 $colors['overlay_inline_styles'] .= sprintf( 'color: %s;', $attributes['customOverlayTextColor'] );
190 }
191
192 // Overlay background color.
193 $has_named_overlay_background_color = array_key_exists( 'overlayBackgroundColor', $attributes );
194 $has_custom_overlay_background_color = array_key_exists( 'customOverlayBackgroundColor', $attributes );
195
196 // If has overlay background color.
197 if ( $has_custom_overlay_background_color || $has_named_overlay_background_color ) {
198 // Add has-background class.
199 $colors['overlay_css_classes'][] = 'has-background';
200 }
201
202 if ( $has_named_overlay_background_color ) {
203 // Add the overlay background-color class.
204 $colors['overlay_css_classes'][] = sprintf( 'has-%s-background-color', $attributes['overlayBackgroundColor'] );
205 } elseif ( $has_custom_overlay_background_color ) {
206 // Add the custom overlay background-color inline style.
207 $colors['overlay_inline_styles'] .= sprintf( 'background-color: %s;', $attributes['customOverlayBackgroundColor'] );
208 }
209
210 return $colors;
211 }
212
213 /**
214 * Build an array with CSS classes and inline styles defining the font sizes
215 * which will be applied to the navigation markup in the front-end.
216 *
217 * @param array $attributes Navigation block attributes.
218 *
219 * @return array Font size CSS classes and inline styles.
220 */
221 function gutenberg_block_core_navigation_build_css_font_sizes( $attributes ) {
222 // CSS classes.
223 $font_sizes = array(
224 'css_classes' => array(),
225 'inline_styles' => '',
226 );
227
228 $has_named_font_size = array_key_exists( 'fontSize', $attributes );
229 $has_custom_font_size = array_key_exists( 'customFontSize', $attributes );
230
231 if ( $has_named_font_size ) {
232 // Add the font size class.
233 $font_sizes['css_classes'][] = sprintf( 'has-%s-font-size', $attributes['fontSize'] );
234 } elseif ( $has_custom_font_size ) {
235 // Add the custom font size inline style.
236 $font_sizes['inline_styles'] = sprintf( 'font-size: %spx;', $attributes['customFontSize'] );
237 }
238
239 return $font_sizes;
240 }
241
242 /**
243 * Returns the top-level submenu SVG chevron icon.
244 *
245 * @return string
246 */
247 function gutenberg_block_core_navigation_render_submenu_icon() {
248 return '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true" focusable="false"><path d="M1.50002 4L6.00002 8L10.5 4" stroke-width="1.5"></path></svg>';
249 }
250
251
252 /**
253 * Finds the first non-empty `wp_navigation` Post.
254 *
255 * @return WP_Post|null the first non-empty Navigation or null.
256 */
257 function gutenberg_block_core_navigation_get_first_non_empty_navigation() {
258 // Order and orderby args set to mirror those in `wp_get_nav_menus`
259 // see:
260 // - https://github.com/WordPress/wordpress-develop/blob/ba943e113d3b31b121f77a2d30aebe14b047c69d/src/wp-includes/nav-menu.php#L613-L619.
261 // - https://developer.wordpress.org/reference/classes/wp_query/#order-orderby-parameters.
262 $parsed_args = array(
263 'post_type' => 'wp_navigation',
264 'no_found_rows' => true,
265 'order' => 'ASC',
266 'orderby' => 'name',
267 'post_status' => 'publish',
268 'posts_per_page' => 20, // Try the first 20 posts.
269 );
270
271 $navigation_posts = new WP_Query( $parsed_args );
272 foreach ( $navigation_posts->posts as $navigation_post ) {
273 if ( has_blocks( $navigation_post ) ) {
274 return $navigation_post;
275 }
276 }
277
278 return null;
279 }
280
281 /**
282 * Filter out empty "null" blocks from the block list.
283 * 'parse_blocks' includes a null block with '\n\n' as the content when
284 * it encounters whitespace. This is not a bug but rather how the parser
285 * is designed.
286 *
287 * @param array $parsed_blocks the parsed blocks to be normalized.
288 * @return array the normalized parsed blocks.
289 */
290 function gutenberg_block_core_navigation_filter_out_empty_blocks( $parsed_blocks ) {
291 $filtered = array_filter(
292 $parsed_blocks,
293 function( $block ) {
294 return isset( $block['blockName'] );
295 }
296 );
297
298 // Reset keys.
299 return array_values( $filtered );
300 }
301
302 /**
303 * Retrieves the appropriate fallback to be used on the front of the
304 * site when there is no menu assigned to the Nav block.
305 *
306 * This aims to mirror how the fallback mechanic for wp_nav_menu works.
307 * See https://developer.wordpress.org/reference/functions/wp_nav_menu/#more-information.
308 *
309 * @return array the array of blocks to be used as a fallback.
310 */
311 function gutenberg_block_core_navigation_get_fallback_blocks() {
312 $page_list_fallback = array(
313 array(
314 'blockName' => 'core/page-list',
315 'attrs' => array(
316 '__unstableMaxPages' => 4,
317 ),
318 ),
319 );
320
321 $registry = WP_Block_Type_Registry::get_instance();
322
323 // If `core/page-list` is not registered then return empty blocks.
324 $fallback_blocks = $registry->is_registered( 'core/page-list' ) ? $page_list_fallback : array();
325
326 // Default to a list of Pages.
327
328 $navigation_post = gutenberg_block_core_navigation_get_first_non_empty_navigation();
329
330 // Prefer using the first non-empty Navigation as fallback if available.
331 if ( $navigation_post ) {
332 $maybe_fallback = gutenberg_block_core_navigation_filter_out_empty_blocks( parse_blocks( $navigation_post->post_content ) );
333
334 // Normalizing blocks may result in an empty array of blocks if they were all `null` blocks.
335 // In this case default to the (Page List) fallback.
336 $fallback_blocks = ! empty( $maybe_fallback ) ? $maybe_fallback : $fallback_blocks;
337 }
338
339 /**
340 * Filters the fallback experience for the Navigation block.
341 *
342 * Returning a falsey value will opt out of the fallback and cause the block not to render.
343 * To customise the blocks provided return an array of blocks - these should be valid
344 * children of the `core/navigation` block.
345 *
346 * @since 5.9.0
347 *
348 * @param array[] default fallback blocks provided by the default block mechanic.
349 */
350 return apply_filters( 'block_core_navigation_render_fallback', $fallback_blocks );
351 }
352
353 /**
354 * Renders the `core/navigation` block on server.
355 *
356 * @param array $attributes The block attributes.
357 * @param string $content The saved content.
358 * @param WP_Block $block The parsed block.
359 *
360 * @return string Returns the post content with the legacy widget added.
361 */
362 function gutenberg_render_block_core_navigation( $attributes, $content, $block ) {
363
364 // Flag used to indicate whether the rendered output is considered to be
365 // a fallback (i.e. the block has no menu associated with it).
366 $is_fallback = false;
367
368 /**
369 * Deprecated:
370 * The rgbTextColor and rgbBackgroundColor attributes
371 * have been deprecated in favor of
372 * customTextColor and customBackgroundColor ones.
373 * Move the values from old attrs to the new ones.
374 */
375 if ( isset( $attributes['rgbTextColor'] ) && empty( $attributes['textColor'] ) ) {
376 $attributes['customTextColor'] = $attributes['rgbTextColor'];
377 }
378
379 if ( isset( $attributes['rgbBackgroundColor'] ) && empty( $attributes['backgroundColor'] ) ) {
380 $attributes['customBackgroundColor'] = $attributes['rgbBackgroundColor'];
381 }
382
383 unset( $attributes['rgbTextColor'], $attributes['rgbBackgroundColor'] );
384
385 /**
386 * This is for backwards compatibility after `isResponsive` attribute has been removed.
387 */
388 $has_old_responsive_attribute = ! empty( $attributes['isResponsive'] ) && $attributes['isResponsive'];
389 $is_responsive_menu = isset( $attributes['overlayMenu'] ) && 'never' !== $attributes['overlayMenu'] || $has_old_responsive_attribute;
390 $should_load_view_script = ! wp_script_is( 'wp-block-navigation-view' ) && ( $is_responsive_menu || $attributes['openSubmenusOnClick'] || $attributes['showSubmenuIcon'] );
391 if ( $should_load_view_script ) {
392 wp_enqueue_script( 'wp-block-navigation-view' );
393 }
394
395 $inner_blocks = $block->inner_blocks;
396
397 // Ensure that blocks saved with the legacy ref attribute name (navigationMenuId) continue to render.
398 if ( array_key_exists( 'navigationMenuId', $attributes ) ) {
399 $attributes['ref'] = $attributes['navigationMenuId'];
400 }
401
402 // If:
403 // - the gutenberg plugin is active
404 // - `__unstableLocation` is defined
405 // - we have menu items at the defined location
406 // - we don't have a relationship to a `wp_navigation` Post (via `ref`).
407 // ...then create inner blocks from the classic menu assigned to that location.
408 if (
409 defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN &&
410 array_key_exists( '__unstableLocation', $attributes ) &&
411 ! array_key_exists( 'ref', $attributes ) &&
412 ! empty( gutenberg_block_core_navigation_get_menu_items_at_location( $attributes['__unstableLocation'] ) )
413 ) {
414 $menu_items = gutenberg_block_core_navigation_get_menu_items_at_location( $attributes['__unstableLocation'] );
415 if ( empty( $menu_items ) ) {
416 return '';
417 }
418
419 $menu_items_by_parent_id = gutenberg_block_core_navigation_sort_menu_items_by_parent_id( $menu_items );
420 $parsed_blocks = gutenberg_block_core_navigation_parse_blocks_from_menu_items( $menu_items_by_parent_id[0], $menu_items_by_parent_id );
421 $inner_blocks = new WP_Block_List( $parsed_blocks, $attributes );
422 }
423
424 // Load inner blocks from the navigation post.
425 if ( array_key_exists( 'ref', $attributes ) ) {
426 $navigation_post = get_post( $attributes['ref'] );
427 if ( ! isset( $navigation_post ) ) {
428 return '';
429 }
430
431 $parsed_blocks = parse_blocks( $navigation_post->post_content );
432
433 // 'parse_blocks' includes a null block with '\n\n' as the content when
434 // it encounters whitespace. This code strips it.
435 $compacted_blocks = gutenberg_block_core_navigation_filter_out_empty_blocks( $parsed_blocks );
436
437 // TODO - this uses the full navigation block attributes for the
438 // context which could be refined.
439 $inner_blocks = new WP_Block_List( $compacted_blocks, $attributes );
440 }
441
442 // If there are no inner blocks then fallback to rendering an appropriate fallback.
443 if ( empty( $inner_blocks ) ) {
444 $is_fallback = true; // indicate we are rendering the fallback.
445
446 $fallback_blocks = gutenberg_block_core_navigation_get_fallback_blocks();
447
448 // Fallback my have been filtered so do basic test for validity.
449 if ( empty( $fallback_blocks ) || ! is_array( $fallback_blocks ) ) {
450 return '';
451 }
452
453 $inner_blocks = new WP_Block_List( $fallback_blocks, $attributes );
454
455 }
456
457 $layout_justification = array(
458 'left' => 'items-justified-left',
459 'right' => 'items-justified-right',
460 'center' => 'items-justified-center',
461 'space-between' => 'items-justified-space-between',
462 );
463
464 // Restore legacy classnames for submenu positioning.
465 $layout_class = '';
466 if ( isset( $attributes['layout']['justifyContent'] ) ) {
467 $layout_class .= $layout_justification[ $attributes['layout']['justifyContent'] ];
468 }
469 if ( isset( $attributes['layout']['orientation'] ) && 'vertical' === $attributes['layout']['orientation'] ) {
470 $layout_class .= ' is-vertical';
471 }
472
473 if ( isset( $attributes['layout']['flexWrap'] ) && 'nowrap' === $attributes['layout']['flexWrap'] ) {
474 $layout_class .= ' no-wrap';
475 }
476
477 $colors = gutenberg_block_core_navigation_build_css_colors( $attributes );
478 $font_sizes = gutenberg_block_core_navigation_build_css_font_sizes( $attributes );
479 $classes = array_merge(
480 $colors['css_classes'],
481 $font_sizes['css_classes'],
482 $is_responsive_menu ? array( 'is-responsive' ) : array(),
483 $layout_class ? array( $layout_class ) : array(),
484 $is_fallback ? array( 'is-fallback' ) : array()
485 );
486
487 $inner_blocks_html = '';
488 $is_list_open = false;
489 foreach ( $inner_blocks as $inner_block ) {
490 if ( ( 'core/navigation-link' === $inner_block->name || 'core/home-link' === $inner_block->name || 'core/site-title' === $inner_block->name || 'core/site-logo' === $inner_block->name || 'core/navigation-submenu' === $inner_block->name ) && ! $is_list_open ) {
491 $is_list_open = true;
492 $inner_blocks_html .= '<ul class="wp-block-navigation__container">';
493 }
494 if ( 'core/navigation-link' !== $inner_block->name && 'core/home-link' !== $inner_block->name && 'core/site-title' !== $inner_block->name && 'core/site-logo' !== $inner_block->name && 'core/navigation-submenu' !== $inner_block->name && $is_list_open ) {
495 $is_list_open = false;
496 $inner_blocks_html .= '</ul>';
497 }
498 if ( 'core/site-title' === $inner_block->name || 'core/site-logo' === $inner_block->name ) {
499 $inner_blocks_html .= '<li class="wp-block-navigation-item">' . $inner_block->render() . '</li>';
500 } else {
501 $inner_blocks_html .= $inner_block->render();
502 }
503 }
504
505 if ( $is_list_open ) {
506 $inner_blocks_html .= '</ul>';
507 }
508
509 $block_styles = isset( $attributes['styles'] ) ? $attributes['styles'] : '';
510
511 $wrapper_attributes = get_block_wrapper_attributes(
512 array(
513 'class' => implode( ' ', $classes ),
514 'style' => $block_styles . $colors['inline_styles'] . $font_sizes['inline_styles'],
515 )
516 );
517
518 $modal_unique_id = uniqid();
519
520 // Determine whether or not navigation elements should be wrapped in the markup required to make it responsive,
521 // return early if they don't.
522 if ( ! $is_responsive_menu ) {
523 return sprintf(
524 '<nav %1$s>%2$s</nav>',
525 $wrapper_attributes,
526 $inner_blocks_html
527 );
528 }
529
530 $is_hidden_by_default = isset( $attributes['overlayMenu'] ) && 'always' === $attributes['overlayMenu'];
531
532 $responsive_container_classes = array(
533 'wp-block-navigation__responsive-container',
534 $is_hidden_by_default ? 'hidden-by-default' : '',
535 implode( ' ', $colors['overlay_css_classes'] ),
536 );
537 $open_button_classes = array(
538 'wp-block-navigation__responsive-container-open',
539 $is_hidden_by_default ? 'always-shown' : '',
540 );
541
542 $toggle_button_icon = '<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><rect x="4" y="7.5" width="16" height="1.5" /><rect x="4" y="15" width="16" height="1.5" /></svg>';
543 $should_display_icon_label = isset( $attributes['hasIcon'] ) && true === $attributes['hasIcon'];
544 $toggle_button_content = $should_display_icon_label ? $toggle_button_icon : 'Menu';
545
546 $responsive_container_markup = sprintf(
547 '<button aria-haspopup="true" aria-label="%3$s" class="%6$s" data-micromodal-trigger="modal-%1$s">%9$s</button>
548 <div class="%5$s" style="%7$s" id="modal-%1$s">
549 <div class="wp-block-navigation__responsive-close" tabindex="-1" data-micromodal-close>
550 <div class="wp-block-navigation__responsive-dialog" aria-label="%8$s">
551 <button aria-label="%4$s" data-micromodal-close class="wp-block-navigation__responsive-container-close"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" focusable="false"><path d="M13 11.8l6.1-6.3-1-1-6.1 6.2-6.1-6.2-1 1 6.1 6.3-6.5 6.7 1 1 6.5-6.6 6.5 6.6 1-1z"></path></svg></button>
552 <div class="wp-block-navigation__responsive-container-content" id="modal-%1$s-content">
553 %2$s
554 </div>
555 </div>
556 </div>
557 </div>',
558 esc_attr( $modal_unique_id ),
559 $inner_blocks_html,
560 __( 'Open menu' ), // Open button label.
561 __( 'Close menu' ), // Close button label.
562 esc_attr( implode( ' ', $responsive_container_classes ) ),
563 esc_attr( implode( ' ', $open_button_classes ) ),
564 safecss_filter_attr( $colors['overlay_inline_styles'] ),
565 __( 'Menu' ),
566 $toggle_button_content
567 );
568
569 return sprintf(
570 '<nav %1$s>%2$s</nav>',
571 $wrapper_attributes,
572 $responsive_container_markup
573 );
574 }
575
576 /**
577 * Register the navigation block.
578 *
579 * @uses gutenberg_render_block_core_navigation()
580 * @throws WP_Error An WP_Error exception parsing the block definition.
581 */
582 function gutenberg_register_block_core_navigation() {
583 register_block_type_from_metadata(
584 __DIR__ . '/navigation',
585 array(
586 'render_callback' => 'gutenberg_render_block_core_navigation',
587 )
588 );
589 }
590
591 add_action( 'init', 'gutenberg_register_block_core_navigation', 20 );
592
593 /**
594 * Filter that changes the parsed attribute values of navigation blocks contain typographic presets to contain the values directly.
595 *
596 * @param array $parsed_block The block being rendered.
597 *
598 * @return array The block being rendered without typographic presets.
599 */
600 function gutenberg_block_core_navigation_typographic_presets_backcompatibility( $parsed_block ) {
601 if ( 'core/navigation' === $parsed_block['blockName'] ) {
602 $attribute_to_prefix_map = array(
603 'fontStyle' => 'var:preset|font-style|',
604 'fontWeight' => 'var:preset|font-weight|',
605 'textDecoration' => 'var:preset|text-decoration|',
606 'textTransform' => 'var:preset|text-transform|',
607 );
608 foreach ( $attribute_to_prefix_map as $style_attribute => $prefix ) {
609 if ( ! empty( $parsed_block['attrs']['style']['typography'][ $style_attribute ] ) ) {
610 $prefix_len = strlen( $prefix );
611 $attribute_value = &$parsed_block['attrs']['style']['typography'][ $style_attribute ];
612 if ( 0 === strncmp( $attribute_value, $prefix, $prefix_len ) ) {
613 $attribute_value = substr( $attribute_value, $prefix_len );
614 }
615 if ( 'textDecoration' === $style_attribute && 'strikethrough' === $attribute_value ) {
616 $attribute_value = 'line-through';
617 }
618 }
619 }
620 }
621
622 return $parsed_block;
623 }
624
625 add_filter( 'render_block_data', 'gutenberg_block_core_navigation_typographic_presets_backcompatibility' );
626