changeset 22 | 8c2e4d02f4ef |
parent 21 | 48c4eec2b7e6 |
21:48c4eec2b7e6 | 22:8c2e4d02f4ef |
---|---|
239 |
239 |
240 // 'parse_blocks' includes a null block with '\n\n' as the content when |
240 // 'parse_blocks' includes a null block with '\n\n' as the content when |
241 // it encounters whitespace. This code strips it. |
241 // it encounters whitespace. This code strips it. |
242 $blocks = block_core_navigation_filter_out_empty_blocks( $parsed_blocks ); |
242 $blocks = block_core_navigation_filter_out_empty_blocks( $parsed_blocks ); |
243 |
243 |
244 if ( function_exists( 'set_ignored_hooked_blocks_metadata' ) ) { |
244 // Re-serialize, and run Block Hooks algorithm to inject hooked blocks. |
245 // Run Block Hooks algorithm to inject hooked blocks. |
245 // TODO: See if we can move the apply_block_hooks_to_content_from_post_object() call |
246 $markup = block_core_navigation_insert_hooked_blocks( $blocks, $navigation_post ); |
246 // before the parse_blocks() call further above, to avoid the extra serialization/parsing. |
247 $root_nav_block = parse_blocks( $markup )[0]; |
247 $markup = serialize_blocks( $blocks ); |
248 |
248 $markup = apply_block_hooks_to_content_from_post_object( $markup, $navigation_post ); |
249 $blocks = isset( $root_nav_block['innerBlocks'] ) ? $root_nav_block['innerBlocks'] : $blocks; |
249 $blocks = parse_blocks( $markup ); |
250 } |
|
251 |
250 |
252 // TODO - this uses the full navigation block attributes for the |
251 // TODO - this uses the full navigation block attributes for the |
253 // context which could be refined. |
252 // context which could be refined. |
254 return new WP_Block_List( $blocks, $attributes ); |
253 return new WP_Block_List( $blocks, $attributes ); |
255 } |
254 } |
344 */ |
343 */ |
345 private static function get_navigation_name( $attributes ) { |
344 private static function get_navigation_name( $attributes ) { |
346 |
345 |
347 $navigation_name = $attributes['ariaLabel'] ?? ''; |
346 $navigation_name = $attributes['ariaLabel'] ?? ''; |
348 |
347 |
348 if ( ! empty( $navigation_name ) ) { |
|
349 return $navigation_name; |
|
350 } |
|
351 |
|
349 // Load the navigation post. |
352 // Load the navigation post. |
350 if ( array_key_exists( 'ref', $attributes ) ) { |
353 if ( array_key_exists( 'ref', $attributes ) ) { |
351 $navigation_post = get_post( $attributes['ref'] ); |
354 $navigation_post = get_post( $attributes['ref'] ); |
352 if ( ! isset( $navigation_post ) ) { |
355 if ( ! isset( $navigation_post ) ) { |
353 return $navigation_name; |
356 return $navigation_name; |
481 if ( 'menu' === $attributes['icon'] ) { |
484 if ( 'menu' === $attributes['icon'] ) { |
482 $toggle_button_icon = '<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M5 5v1.5h14V5H5zm0 7.8h14v-1.5H5v1.5zM5 19h14v-1.5H5V19z" /></svg>'; |
485 $toggle_button_icon = '<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M5 5v1.5h14V5H5zm0 7.8h14v-1.5H5v1.5zM5 19h14v-1.5H5V19z" /></svg>'; |
483 } |
486 } |
484 } |
487 } |
485 $toggle_button_content = $should_display_icon_label ? $toggle_button_icon : __( 'Menu' ); |
488 $toggle_button_content = $should_display_icon_label ? $toggle_button_icon : __( 'Menu' ); |
486 $toggle_close_button_icon = '<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>'; |
489 $toggle_close_button_icon = '<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.06 12 6.47-6.47-1.06-1.06L12 10.94 5.53 4.47 4.47 5.53 10.94 12l-6.47 6.47 1.06 1.06L12 13.06l6.47 6.47 1.06-1.06L13.06 12Z"></path></svg>'; |
487 $toggle_close_button_content = $should_display_icon_label ? $toggle_close_button_icon : __( 'Close' ); |
490 $toggle_close_button_content = $should_display_icon_label ? $toggle_close_button_icon : __( 'Close' ); |
488 $toggle_aria_label_open = $should_display_icon_label ? 'aria-label="' . __( 'Open menu' ) . '"' : ''; // Open button label. |
491 $toggle_aria_label_open = $should_display_icon_label ? 'aria-label="' . __( 'Open menu' ) . '"' : ''; // Open button label. |
489 $toggle_aria_label_close = $should_display_icon_label ? 'aria-label="' . __( 'Close menu' ) . '"' : ''; // Close button label. |
492 $toggle_aria_label_close = $should_display_icon_label ? 'aria-label="' . __( 'Close menu' ) . '"' : ''; // Close button label. |
490 |
493 |
491 // Add Interactivity API directives to the markup if needed. |
494 // Add Interactivity API directives to the markup if needed. |
535 </div>', |
538 </div>', |
536 esc_attr( $modal_unique_id ), |
539 esc_attr( $modal_unique_id ), |
537 $inner_blocks_html, |
540 $inner_blocks_html, |
538 $toggle_aria_label_open, |
541 $toggle_aria_label_open, |
539 $toggle_aria_label_close, |
542 $toggle_aria_label_close, |
540 esc_attr( implode( ' ', $responsive_container_classes ) ), |
543 esc_attr( trim( implode( ' ', $responsive_container_classes ) ) ), |
541 esc_attr( implode( ' ', $open_button_classes ) ), |
544 esc_attr( trim( implode( ' ', $open_button_classes ) ) ), |
542 ( ! empty( $overlay_inline_styles ) ) ? "style=\"$overlay_inline_styles\"" : '', |
545 ( ! empty( $overlay_inline_styles ) ) ? "style=\"$overlay_inline_styles\"" : '', |
543 $toggle_button_content, |
546 $toggle_button_content, |
544 $toggle_close_button_content, |
547 $toggle_close_button_content, |
545 $open_button_directives, |
548 $open_button_directives, |
546 $responsive_container_directives, |
549 $responsive_container_directives, |
563 $nav_menu_name = static::get_unique_navigation_name( $attributes ); |
566 $nav_menu_name = static::get_unique_navigation_name( $attributes ); |
564 $is_interactive = static::is_interactive( $attributes, $inner_blocks ); |
567 $is_interactive = static::is_interactive( $attributes, $inner_blocks ); |
565 $is_responsive_menu = static::is_responsive( $attributes ); |
568 $is_responsive_menu = static::is_responsive( $attributes ); |
566 $style = static::get_styles( $attributes ); |
569 $style = static::get_styles( $attributes ); |
567 $class = static::get_classes( $attributes ); |
570 $class = static::get_classes( $attributes ); |
568 $wrapper_attributes = get_block_wrapper_attributes( |
571 $extra_attributes = array( |
569 array( |
572 'class' => $class, |
570 'class' => $class, |
573 'style' => $style, |
571 'style' => $style, |
|
572 'aria-label' => $nav_menu_name, |
|
573 ) |
|
574 ); |
574 ); |
575 if ( ! empty( $nav_menu_name ) ) { |
|
576 $extra_attributes['aria-label'] = $nav_menu_name; |
|
577 } |
|
578 $wrapper_attributes = get_block_wrapper_attributes( $extra_attributes ); |
|
575 |
579 |
576 if ( $is_responsive_menu ) { |
580 if ( $is_responsive_menu ) { |
577 $nav_element_directives = static::get_nav_element_directives( $is_interactive ); |
581 $nav_element_directives = static::get_nav_element_directives( $is_interactive ); |
578 $wrapper_attributes .= ' ' . $nav_element_directives; |
582 $wrapper_attributes .= ' ' . $nav_element_directives; |
579 } |
583 } |
622 * @param WP_Block $block The parsed block. |
626 * @param WP_Block $block The parsed block. |
623 * @param WP_Block_List $inner_blocks The list of inner blocks. |
627 * @param WP_Block_List $inner_blocks The list of inner blocks. |
624 */ |
628 */ |
625 private static function handle_view_script_module_loading( $attributes, $block, $inner_blocks ) { |
629 private static function handle_view_script_module_loading( $attributes, $block, $inner_blocks ) { |
626 if ( static::is_interactive( $attributes, $inner_blocks ) ) { |
630 if ( static::is_interactive( $attributes, $inner_blocks ) ) { |
627 $suffix = wp_scripts_get_suffix(); |
631 wp_enqueue_script_module( '@wordpress/block-library/navigation/view' ); |
628 if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) { |
|
629 $module_url = gutenberg_url( '/build/interactivity/navigation.min.js' ); |
|
630 } |
|
631 |
|
632 wp_register_script_module( |
|
633 '@wordpress/block-library/navigation', |
|
634 isset( $module_url ) ? $module_url : includes_url( "blocks/navigation/view{$suffix}.js" ), |
|
635 array( '@wordpress/interactivity' ), |
|
636 defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' ) |
|
637 ); |
|
638 wp_enqueue_script_module( '@wordpress/block-library/navigation' ); |
|
639 } |
632 } |
640 } |
633 } |
641 |
634 |
642 /** |
635 /** |
643 * Returns the markup for the navigation block. |
636 * Returns the markup for the navigation block. |
824 'class_name' => 'has-child', |
817 'class_name' => 'has-child', |
825 ) |
818 ) |
826 ) ) { |
819 ) ) { |
827 // Add directives to the parent `<li>`. |
820 // Add directives to the parent `<li>`. |
828 $tags->set_attribute( 'data-wp-interactive', 'core/navigation' ); |
821 $tags->set_attribute( 'data-wp-interactive', 'core/navigation' ); |
829 $tags->set_attribute( 'data-wp-context', '{ "submenuOpenedBy": { "click": false, "hover": false, "focus": false }, "type": "submenu" }' ); |
822 $tags->set_attribute( 'data-wp-context', '{ "submenuOpenedBy": { "click": false, "hover": false, "focus": false }, "type": "submenu", "modal": null }' ); |
830 $tags->set_attribute( 'data-wp-watch', 'callbacks.initMenu' ); |
823 $tags->set_attribute( 'data-wp-watch', 'callbacks.initMenu' ); |
831 $tags->set_attribute( 'data-wp-on--focusout', 'actions.handleMenuFocusout' ); |
824 $tags->set_attribute( 'data-wp-on--focusout', 'actions.handleMenuFocusout' ); |
832 $tags->set_attribute( 'data-wp-on--keydown', 'actions.handleMenuKeydown' ); |
825 $tags->set_attribute( 'data-wp-on--keydown', 'actions.handleMenuKeydown' ); |
833 |
826 |
834 // This is a fix for Safari. Without it, Safari doesn't change the active |
827 // This is a fix for Safari. Without it, Safari doesn't change the active |
1081 |
1074 |
1082 // Normalizing blocks may result in an empty array of blocks if they were all `null` blocks. |
1075 // Normalizing blocks may result in an empty array of blocks if they were all `null` blocks. |
1083 // In this case default to the (Page List) fallback. |
1076 // In this case default to the (Page List) fallback. |
1084 $fallback_blocks = ! empty( $maybe_fallback ) ? $maybe_fallback : $fallback_blocks; |
1077 $fallback_blocks = ! empty( $maybe_fallback ) ? $maybe_fallback : $fallback_blocks; |
1085 |
1078 |
1086 if ( function_exists( 'set_ignored_hooked_blocks_metadata' ) ) { |
1079 // Run Block Hooks algorithm to inject hooked blocks. |
1087 // Run Block Hooks algorithm to inject hooked blocks. |
1080 // We have to run it here because we need the post ID of the Navigation block to track ignored hooked blocks. |
1088 // We have to run it here because we need the post ID of the Navigation block to track ignored hooked blocks. |
1081 // TODO: See if we can move the apply_block_hooks_to_content_from_post_object() call |
1089 $markup = block_core_navigation_insert_hooked_blocks( $fallback_blocks, $navigation_post ); |
1082 // before the parse_blocks() call further above, to avoid the extra serialization/parsing. |
1090 $blocks = parse_blocks( $markup ); |
1083 $markup = serialize_blocks( $fallback_blocks ); |
1091 |
1084 $markup = apply_block_hooks_to_content_from_post_object( $markup, $navigation_post ); |
1092 if ( isset( $blocks[0]['innerBlocks'] ) ) { |
1085 $fallback_blocks = parse_blocks( $markup ); |
1093 $fallback_blocks = $blocks[0]['innerBlocks']; |
|
1094 } |
|
1095 } |
|
1096 } |
1086 } |
1097 |
1087 |
1098 /** |
1088 /** |
1099 * Filters the fallback experience for the Navigation block. |
1089 * Filters the fallback experience for the Navigation block. |
1100 * |
1090 * |
1444 return $navigation_post->posts[0]; |
1434 return $navigation_post->posts[0]; |
1445 } |
1435 } |
1446 |
1436 |
1447 return null; |
1437 return null; |
1448 } |
1438 } |
1449 |
|
1450 /** |
|
1451 * Accepts the serialized markup of a block and its inner blocks, and returns serialized markup of the inner blocks. |
|
1452 * |
|
1453 * @since 6.5.0 |
|
1454 * |
|
1455 * @param string $serialized_block The serialized markup of a block and its inner blocks. |
|
1456 * @return string |
|
1457 */ |
|
1458 function block_core_navigation_remove_serialized_parent_block( $serialized_block ) { |
|
1459 $start = strpos( $serialized_block, '-->' ) + strlen( '-->' ); |
|
1460 $end = strrpos( $serialized_block, '<!--' ); |
|
1461 return substr( $serialized_block, $start, $end - $start ); |
|
1462 } |
|
1463 |
|
1464 /** |
|
1465 * Mock a parsed block for the Navigation block given its inner blocks and the `wp_navigation` post object. |
|
1466 * The `wp_navigation` post's `_wp_ignored_hooked_blocks` meta is queried to add the `metadata.ignoredHookedBlocks` attribute. |
|
1467 * |
|
1468 * @since 6.5.0 |
|
1469 * |
|
1470 * @param array $inner_blocks Parsed inner blocks of a Navigation block. |
|
1471 * @param WP_Post $post `wp_navigation` post object corresponding to the block. |
|
1472 * |
|
1473 * @return array the normalized parsed blocks. |
|
1474 */ |
|
1475 function block_core_navigation_mock_parsed_block( $inner_blocks, $post ) { |
|
1476 $attributes = array(); |
|
1477 |
|
1478 if ( isset( $post->ID ) ) { |
|
1479 $ignored_hooked_blocks = get_post_meta( $post->ID, '_wp_ignored_hooked_blocks', true ); |
|
1480 if ( ! empty( $ignored_hooked_blocks ) ) { |
|
1481 $ignored_hooked_blocks = json_decode( $ignored_hooked_blocks, true ); |
|
1482 $attributes['metadata'] = array( |
|
1483 'ignoredHookedBlocks' => $ignored_hooked_blocks, |
|
1484 ); |
|
1485 } |
|
1486 } |
|
1487 |
|
1488 $mock_anchor_parent_block = array( |
|
1489 'blockName' => 'core/navigation', |
|
1490 'attrs' => $attributes, |
|
1491 'innerBlocks' => $inner_blocks, |
|
1492 'innerContent' => array_fill( 0, count( $inner_blocks ), null ), |
|
1493 ); |
|
1494 |
|
1495 return $mock_anchor_parent_block; |
|
1496 } |
|
1497 |
|
1498 /** |
|
1499 * Insert hooked blocks into a Navigation block. |
|
1500 * |
|
1501 * Given a Navigation block's inner blocks and its corresponding `wp_navigation` post object, |
|
1502 * this function inserts hooked blocks into it, and returns the serialized inner blocks in a |
|
1503 * mock Navigation block wrapper. |
|
1504 * |
|
1505 * If there are any hooked blocks that need to be inserted as the Navigation block's first or last |
|
1506 * children, the `wp_navigation` post's `_wp_ignored_hooked_blocks` meta is checked to see if any |
|
1507 * of those hooked blocks should be exempted from insertion. |
|
1508 * |
|
1509 * @since 6.5.0 |
|
1510 * |
|
1511 * @param array $inner_blocks Parsed inner blocks of a Navigation block. |
|
1512 * @param WP_Post $post `wp_navigation` post object corresponding to the block. |
|
1513 * @return string Serialized inner blocks in mock Navigation block wrapper, with hooked blocks inserted, if any. |
|
1514 */ |
|
1515 function block_core_navigation_insert_hooked_blocks( $inner_blocks, $post ) { |
|
1516 $mock_navigation_block = block_core_navigation_mock_parsed_block( $inner_blocks, $post ); |
|
1517 $hooked_blocks = get_hooked_blocks(); |
|
1518 $before_block_visitor = null; |
|
1519 $after_block_visitor = null; |
|
1520 |
|
1521 if ( ! empty( $hooked_blocks ) || has_filter( 'hooked_block_types' ) ) { |
|
1522 $before_block_visitor = make_before_block_visitor( $hooked_blocks, $post, 'insert_hooked_blocks' ); |
|
1523 $after_block_visitor = make_after_block_visitor( $hooked_blocks, $post, 'insert_hooked_blocks' ); |
|
1524 } |
|
1525 |
|
1526 return traverse_and_serialize_block( $mock_navigation_block, $before_block_visitor, $after_block_visitor ); |
|
1527 } |
|
1528 |
|
1529 /** |
|
1530 * Insert ignoredHookedBlocks meta into the Navigation block and its inner blocks. |
|
1531 * |
|
1532 * Given a Navigation block's inner blocks and its corresponding `wp_navigation` post object, |
|
1533 * this function inserts ignoredHookedBlocks meta into it, and returns the serialized inner blocks in a |
|
1534 * mock Navigation block wrapper. |
|
1535 * |
|
1536 * @since 6.5.0 |
|
1537 * |
|
1538 * @param array $inner_blocks Parsed inner blocks of a Navigation block. |
|
1539 * @param WP_Post $post `wp_navigation` post object corresponding to the block. |
|
1540 * @return string Serialized inner blocks in mock Navigation block wrapper, with hooked blocks inserted, if any. |
|
1541 */ |
|
1542 function block_core_navigation_set_ignored_hooked_blocks_metadata( $inner_blocks, $post ) { |
|
1543 $mock_navigation_block = block_core_navigation_mock_parsed_block( $inner_blocks, $post ); |
|
1544 $hooked_blocks = get_hooked_blocks(); |
|
1545 $before_block_visitor = null; |
|
1546 $after_block_visitor = null; |
|
1547 |
|
1548 if ( ! empty( $hooked_blocks ) || has_filter( 'hooked_block_types' ) ) { |
|
1549 $before_block_visitor = make_before_block_visitor( $hooked_blocks, $post, 'set_ignored_hooked_blocks_metadata' ); |
|
1550 $after_block_visitor = make_after_block_visitor( $hooked_blocks, $post, 'set_ignored_hooked_blocks_metadata' ); |
|
1551 } |
|
1552 |
|
1553 return traverse_and_serialize_block( $mock_navigation_block, $before_block_visitor, $after_block_visitor ); |
|
1554 } |
|
1555 |
|
1556 /** |
|
1557 * Updates the post meta with the list of ignored hooked blocks when the navigation is created or updated via the REST API. |
|
1558 * |
|
1559 * @access private |
|
1560 * @since 6.5.0 |
|
1561 * |
|
1562 * @param stdClass $post Post object. |
|
1563 * @return stdClass The updated post object. |
|
1564 */ |
|
1565 function block_core_navigation_update_ignore_hooked_blocks_meta( $post ) { |
|
1566 /* |
|
1567 * In this scenario the user has likely tried to create a navigation via the REST API. |
|
1568 * In which case we won't have a post ID to work with and store meta against. |
|
1569 */ |
|
1570 if ( empty( $post->ID ) ) { |
|
1571 return $post; |
|
1572 } |
|
1573 |
|
1574 /** |
|
1575 * Skip meta generation when consumers intentionally update specific Navigation fields |
|
1576 * and omit the content update. |
|
1577 */ |
|
1578 if ( ! isset( $post->post_content ) ) { |
|
1579 return $post; |
|
1580 } |
|
1581 |
|
1582 /* |
|
1583 * We run the Block Hooks mechanism to inject the `metadata.ignoredHookedBlocks` attribute into |
|
1584 * all anchor blocks. For the root level, we create a mock Navigation and extract them from there. |
|
1585 */ |
|
1586 $blocks = parse_blocks( $post->post_content ); |
|
1587 |
|
1588 /* |
|
1589 * Block Hooks logic requires a `WP_Post` object (rather than the `stdClass` with the updates that |
|
1590 * we're getting from the `rest_pre_insert_wp_navigation` filter) as its second argument (to be |
|
1591 * used as context for hooked blocks insertion). |
|
1592 * We thus have to look it up from the DB,based on `$post->ID`. |
|
1593 */ |
|
1594 $markup = block_core_navigation_set_ignored_hooked_blocks_metadata( $blocks, get_post( $post->ID ) ); |
|
1595 |
|
1596 $root_nav_block = parse_blocks( $markup )[0]; |
|
1597 $ignored_hooked_blocks = isset( $root_nav_block['attrs']['metadata']['ignoredHookedBlocks'] ) |
|
1598 ? $root_nav_block['attrs']['metadata']['ignoredHookedBlocks'] |
|
1599 : array(); |
|
1600 |
|
1601 if ( ! empty( $ignored_hooked_blocks ) ) { |
|
1602 $existing_ignored_hooked_blocks = get_post_meta( $post->ID, '_wp_ignored_hooked_blocks', true ); |
|
1603 if ( ! empty( $existing_ignored_hooked_blocks ) ) { |
|
1604 $existing_ignored_hooked_blocks = json_decode( $existing_ignored_hooked_blocks, true ); |
|
1605 $ignored_hooked_blocks = array_unique( array_merge( $ignored_hooked_blocks, $existing_ignored_hooked_blocks ) ); |
|
1606 } |
|
1607 update_post_meta( $post->ID, '_wp_ignored_hooked_blocks', json_encode( $ignored_hooked_blocks ) ); |
|
1608 } |
|
1609 |
|
1610 $post->post_content = block_core_navigation_remove_serialized_parent_block( $markup ); |
|
1611 return $post; |
|
1612 } |
|
1613 |
|
1614 /* |
|
1615 * Before adding our filter, we verify if it's already added in Core. |
|
1616 * However, during the build process, Gutenberg automatically prefixes our functions with "gutenberg_". |
|
1617 * Therefore, we concatenate the Core's function name to circumvent this prefix for our check. |
|
1618 */ |
|
1619 $rest_insert_wp_navigation_core_callback = 'block_core_navigation_' . 'update_ignore_hooked_blocks_meta'; // phpcs:ignore Generic.Strings.UnnecessaryStringConcat.Found |
|
1620 |
|
1621 /* |
|
1622 * Do not add the `block_core_navigation_update_ignore_hooked_blocks_meta` filter in the following cases: |
|
1623 * - If Core has added the `update_ignored_hooked_blocks_postmeta` filter already (WP >= 6.6); |
|
1624 * - or if the `set_ignored_hooked_blocks_metadata` function is unavailable (which is required for the filter to work. It was introduced by WP 6.5 but is not present in Gutenberg's WP 6.5 compatibility layer); |
|
1625 * - or if the `$rest_insert_wp_navigation_core_callback` filter has already been added. |
|
1626 */ |
|
1627 if ( |
|
1628 ! has_filter( 'rest_pre_insert_wp_navigation', 'update_ignored_hooked_blocks_postmeta' ) && |
|
1629 function_exists( 'set_ignored_hooked_blocks_metadata' ) && |
|
1630 ! has_filter( 'rest_pre_insert_wp_navigation', $rest_insert_wp_navigation_core_callback ) |
|
1631 ) { |
|
1632 add_filter( 'rest_pre_insert_wp_navigation', 'block_core_navigation_update_ignore_hooked_blocks_meta' ); |
|
1633 } |
|
1634 |
|
1635 /* |
|
1636 * Previous versions of Gutenberg were attaching the block_core_navigation_update_ignore_hooked_blocks_meta |
|
1637 * function to the `rest_insert_wp_navigation` _action_ (rather than the `rest_pre_insert_wp_navigation` _filter_). |
|
1638 * To avoid collisions, we need to remove the filter from that action if it's present. |
|
1639 */ |
|
1640 if ( has_filter( 'rest_insert_wp_navigation', $rest_insert_wp_navigation_core_callback ) ) { |
|
1641 remove_filter( 'rest_insert_wp_navigation', $rest_insert_wp_navigation_core_callback ); |
|
1642 } |
|
1643 |
|
1644 /** |
|
1645 * Hooks into the REST API response for the core/navigation block and adds the first and last inner blocks. |
|
1646 * |
|
1647 * @since 6.5.0 |
|
1648 * |
|
1649 * @param WP_REST_Response $response The response object. |
|
1650 * @param WP_Post $post Post object. |
|
1651 * @return WP_REST_Response The response object. |
|
1652 */ |
|
1653 function block_core_navigation_insert_hooked_blocks_into_rest_response( $response, $post ) { |
|
1654 if ( ! isset( $response->data['content']['raw'] ) || ! isset( $response->data['content']['rendered'] ) ) { |
|
1655 return $response; |
|
1656 } |
|
1657 $parsed_blocks = parse_blocks( $response->data['content']['raw'] ); |
|
1658 $content = block_core_navigation_insert_hooked_blocks( $parsed_blocks, $post ); |
|
1659 |
|
1660 // Remove mock Navigation block wrapper. |
|
1661 $content = block_core_navigation_remove_serialized_parent_block( $content ); |
|
1662 |
|
1663 $response->data['content']['raw'] = $content; |
|
1664 |
|
1665 /** This filter is documented in wp-includes/post-template.php */ |
|
1666 $response->data['content']['rendered'] = apply_filters( 'the_content', $content ); |
|
1667 |
|
1668 return $response; |
|
1669 } |
|
1670 |
|
1671 /* |
|
1672 * Before adding our filter, we verify if it's already added in Core. |
|
1673 * However, during the build process, Gutenberg automatically prefixes our functions with "gutenberg_". |
|
1674 * Therefore, we concatenate the Core's function name to circumvent this prefix for our check. |
|
1675 */ |
|
1676 $rest_prepare_wp_navigation_core_callback = 'block_core_navigation_' . 'insert_hooked_blocks_into_rest_response'; |
|
1677 |
|
1678 /* |
|
1679 * Do not add the `block_core_navigation_insert_hooked_blocks_into_rest_response` filter in the following cases: |
|
1680 * - If Core has added the `insert_hooked_blocks_into_rest_response` filter already (WP >= 6.6); |
|
1681 * - or if the `set_ignored_hooked_blocks_metadata` function is unavailable (which is required for the filter to work. It was introduced by WP 6.5 but is not present in Gutenberg's WP 6.5 compatibility layer); |
|
1682 * - or if the `$rest_prepare_wp_navigation_core_callback` filter has already been added. |
|
1683 */ |
|
1684 if ( |
|
1685 ! has_filter( 'rest_prepare_wp_navigation', 'insert_hooked_blocks_into_rest_response' ) && |
|
1686 function_exists( 'set_ignored_hooked_blocks_metadata' ) && |
|
1687 ! has_filter( 'rest_prepare_wp_navigation', $rest_prepare_wp_navigation_core_callback ) |
|
1688 ) { |
|
1689 add_filter( 'rest_prepare_wp_navigation', 'block_core_navigation_insert_hooked_blocks_into_rest_response', 10, 3 ); |
|
1690 } |