Make WordPress Core

Opened 4 weeks ago

Closed 4 weeks ago

#65079 closed defect (bug) (reported-upstream)

block_core_navigation_get_inner_blocks_from_unstable_location() calls deprecated function; deprecated docblock references non-existent replacement

Reported by: saratheonline's profile saratheonline Owned by: saratheonline's profile saratheonline
Milestone: Priority: normal
Severity: normal Version: trunk
Component: Editor Keywords: has-patch needs-testing
Focuses: docs, coding-standards Cc:

Description

There are two related issues in src/wp-includes/blocks/navigation.php that were introduced when
block_core_navigation_get_inner_blocks_from_unstable_location() was added in 6.5.0.

Issue 1 — Function added in 6.5.0 calls a function that was deprecated in 6.3.0
block_core_navigation_get_inner_blocks_from_unstable_location() (added @since 6.5.0) calls
block_core_navigation_parse_blocks_from_menu_items():

// src/wp-includes/blocks/navigation.php
  function block_core_navigation_get_inner_blocks_from_unstable_location( $attributes ) {
      $menu_items = block_core_navigation_get_menu_items_at_location( $attributes['__unstableLocation']);
      if ( empty( $menu_items ) ) {
          return new WP_Block_List( array(), $attributes );
      }

      $menu_items_by_parent_id = block_core_navigation_sort_menu_items_by_parent_id( $menu_items );
      $parsed_blocks           = block_core_navigation_parse_blocks_from_menu_items(
  $menu_items_by_parent_id[0], $menu_items_by_parent_id ); // <-- calls deprecated
      return new WP_Block_List( $parsed_blocks, $attributes );
  }

block_core_navigation_parse_blocks_from_menu_items() was deprecated in 6.3.0 and triggers a
_deprecated_function() notice:

// src/wp-includes/blocks/navigation.php
  function block_core_navigation_parse_blocks_from_menu_items( $menu_items, $menu_items_by_parent_id ) {
      _deprecated_function( __FUNCTION__, '6.3.0', 'WP_Navigation_Fallback::parse_blocks_from_menu_items');
      ...
  }

This means on any site using a Navigation block with the __unstableLocation attribute (classic menu location fallback), every page render triggers a deprecated function notice when WP_DEBUG is enabled.

Issue 2 — The deprecated function's docblock points to a non-existent replacement
The @deprecated tag on block_core_navigation_parse_blocks_from_menu_items() says:

@deprecated 6.3.0 Use WP_Navigation_Fallback::parse_blocks_from_menu_items() instead.

However, WP_Navigation_Fallback (introduced in 6.3.0, src/wp-includes/class-wp-navigation-fallback.php) has no method named parse_blocks_from_menu_items. The equivalent logic was moved to the private method WP_Classic_To_Block_Menu_Converter::to_blocks() in the same release.

The incorrect docblock would mislead any developer following the deprecation notice trying to find the correct replacement.

Issue 3 — Missing null-coalescing fallback on the same line
The call accesses $menu_items_by_parent_id[0] directly without a null coalesce:

$parsed_blocks = block_core_navigation_parse_blocks_from_menu_items( $menu_items_by_parent_id[0], ...);

Compare this with the identical pattern at (inside the already-deprecated block_core_navigation_get_classic_menu_fallback_blocks()) which correctly guards the access:

$inner_blocks = block_core_navigation_parse_blocks_from_menu_items(
      $menu_items_by_parent_id[0] ?? array(),
      $menu_items_by_parent_id
  );

block_core_navigation_sort_menu_items_by_parent_id() groups items by menu_item_parent. If (through data corruption or an unusual data source) all items carry a non-zero parent ID, the 0 key will be absent and the direct access generates an undefined array key notice on PHP 8.x.

Steps to Reproduce
1. Enable WP_DEBUG and WP_DEBUG_LOG in wp-config.php.
2. Create a Navigation block that uses a classic menu via the __unstableLocation attribute (i.e., a theme location fallback menu).
3. Load any front-end page that renders the Navigation block.
4. Check the debug log — a _deprecated_function notice for block_core_navigation_parse_blocks_from_menu_items appears on every request.

Expected Behavior
- No deprecated function notices are triggered.
- block_core_navigation_get_inner_blocks_from_unstable_location() uses the non-deprecated code path.
- The deprecated function's docblock correctly identifies its replacement.

Actual Behavior _deprecated_function( 'block_core_navigation_parse_blocks_from_menu_items', '6.3.0', 'WP_Navigation_Fallback::parse_blocks_from_menu_items' ) is triggered on every page render where the Navigation block is present with __unstableLocation.


Proposed Fix
Step 1. Make WP_Classic_To_Block_Menu_Converter::group_by_parent_id() and ::to_blocks() public (they are currently private), or add a new public static method that accepts $menu_items and returns parsed blocks — mirroring what block_core_navigation_parse_blocks_from_menu_items() does.

Step 2. Update block_core_navigation_get_inner_blocks_from_unstable_location() to call the new public method with the null-coalesce guard:

function block_core_navigation_get_inner_blocks_from_unstable_location( $attributes ) {
      $menu_items = block_core_navigation_get_menu_items_at_location( $attributes['__unstableLocation'] );
      if ( empty( $menu_items ) ) {
          return new WP_Block_List( array(), $attributes );
      }

      $menu_items_by_parent_id = block_core_navigation_sort_menu_items_by_parent_id( $menu_items );
      $parsed_blocks           = WP_Classic_To_Block_Menu_Converter::to_blocks(
          $menu_items_by_parent_id[0] ?? array(),
          $menu_items_by_parent_id
      );
      return new WP_Block_List( $parsed_blocks, $attributes );
  }


Step 3. Correct the @deprecated docblock on block_core_navigation_parse_blocks_from_menu_items() to reference the actual replacement:

- * @deprecated 6.3.0 Use `WP_Navigation_Fallback::parse_blocks_from_menu_items()` instead.
+ * @deprecated 6.3.0 Use `WP_Classic_To_Block_Menu_Converter::to_blocks()` instead.

Attachments (1)

navigation-deprecated-fix.patch (2.7 KB) - added by saratheonline 4 weeks ago.
Patch attached. Changes are limited to 2 files and 5 lines. No new logic, just redirecting the call to the already-existing WP_Classic_To_Block_Menu_Converter::to_blocks() (made public) and correcting the @deprecated docblock to point to the actual replacement.

Download all attachments as: .zip

Change History (4)

@saratheonline
4 weeks ago

Patch attached. Changes are limited to 2 files and 5 lines. No new logic, just redirecting the call to the already-existing WP_Classic_To_Block_Menu_Converter::to_blocks() (made public) and correcting the @deprecated docblock to point to the actual replacement.

#1 follow-up: @wildworks
4 weeks ago

@saratheonline Thanks for submitting a patch.

The navigation.php file cannot be directly edited in the WordPress core. This file is synced from the Gutenberg repository.

See: https://github.com/WordPress/gutenberg/blob/7563e2acf2a8bcfbe6338ca4bd5cc0d7eed74535/packages/block-library/src/navigation/index.php#L1601

Would it be possible for you to submit a new PR to the Gutenberg repository?

#2 in reply to: ↑ 1 @saratheonline
4 weeks ago

Replying to wildworks:

@saratheonline Thanks for submitting a patch.

The navigation.php file cannot be directly edited in the WordPress core. This file is synced from the Gutenberg repository.

See: https://github.com/WordPress/gutenberg/blob/7563e2acf2a8bcfbe6338ca4bd5cc0d7eed74535/packages/block-library/src/navigation/index.php#L1601

Would it be possible for you to submit a new PR to the Gutenberg repository?


Thanks for the pointer! I've confirmed the bug exists in the Gutenberg source at packages/block-library/src/navigation/index.php and have moved the fix upstream.


The PR addresses all three issues:

  1. block_core_navigation_get_inner_blocks_from_unstable_location() no longer calls the deprecated block_core_navigation_parse_blocks_from_menu_items() — a new private helper block_core_navigation_convert_menu_items_to_blocks() holds the actual logic.
  2. The missing ?? array() guard on $menu_items_by_parent_id[0] is added.
  3. The @deprecated docblock is corrected to reference WP_Classic_To_Block_Menu_Converter::to_blocks().


This ticket can be closed or marked as a duplicate/upstream once the Gutenberg PR is merged and synced to Core.

#3 @wildworks
4 weeks ago

  • Milestone Awaiting Review deleted
  • Resolution set to reported-upstream
  • Status changed from assigned to closed

@saratheonline Thanks for submitting an issue.

The ticket can be closed if an issue is reported upstream.

Note: See TracTickets for help on using tickets.