diff --git a/src/wp-admin/nav-menus.php b/src/wp-admin/nav-menus.php index 28dbc8219f..b14a20fce1 100644 --- a/src/wp-admin/nav-menus.php +++ b/src/wp-admin/nav-menus.php @@ -117,6 +117,10 @@ switch ( $action ) { if ( ! is_wp_error( $parent_object ) ) { $parent_data = (array) $parent_object; $menu_item_data['menu_item_parent'] = $parent_data['menu_item_parent']; + + // Reset invalid `menu_item_parent`. + $menu_item_data = _wp_reset_invalid_menu_item_parent( $menu_item_data ); + update_post_meta( $menu_item_data['ID'], '_menu_item_menu_item_parent', (int) $menu_item_data['menu_item_parent'] ); } @@ -126,6 +130,10 @@ switch ( $action ) { $menu_item_data['menu_order'] = $menu_item_data['menu_order'] + 1; $menu_item_data['menu_item_parent'] = $next_item_data['ID']; + + // Reset invalid `menu_item_parent`. + $menu_item_data = _wp_reset_invalid_menu_item_parent( $menu_item_data ); + update_post_meta( $menu_item_data['ID'], '_menu_item_menu_item_parent', (int) $menu_item_data['menu_item_parent'] ); wp_update_post( $menu_item_data ); @@ -137,6 +145,10 @@ switch ( $action ) { && in_array( (int) $menu_item_data['menu_item_parent'], $orders_to_dbids, true ) ) { $menu_item_data['menu_item_parent'] = (int) get_post_meta( $menu_item_data['menu_item_parent'], '_menu_item_menu_item_parent', true ); + + // Reset invalid `menu_item_parent`. + $menu_item_data = _wp_reset_invalid_menu_item_parent( $menu_item_data ); + update_post_meta( $menu_item_data['ID'], '_menu_item_menu_item_parent', (int) $menu_item_data['menu_item_parent'] ); } } @@ -247,6 +259,10 @@ switch ( $action ) { ) { // Just make it a child of the previous; keep the order. $menu_item_data['menu_item_parent'] = (int) $orders_to_dbids[ $dbids_to_orders[ $menu_item_id ] - 1 ]; + + // Reset invalid `menu_item_parent`. + $menu_item_data = _wp_reset_invalid_menu_item_parent( $menu_item_data ); + update_post_meta( $menu_item_data['ID'], '_menu_item_menu_item_parent', (int) $menu_item_data['menu_item_parent'] ); wp_update_post( $menu_item_data ); } diff --git a/src/wp-includes/nav-menu-template.php b/src/wp-includes/nav-menu-template.php index 893727c44c..b92cc0c7a8 100644 --- a/src/wp-includes/nav-menu-template.php +++ b/src/wp-includes/nav-menu-template.php @@ -199,6 +199,11 @@ function wp_nav_menu( $args = array() ) { $menu_items_tree = array(); $menu_items_with_children = array(); foreach ( (array) $menu_items as $menu_item ) { + // Fix invalid `menu_item_parent`. See: https://core.trac.wordpress.org/ticket/56926. + if ( (int) $menu_item->ID === (int) $menu_item->menu_item_parent ) { + $menu_item->menu_item_parent = 0; + } + $sorted_menu_items[ $menu_item->menu_order ] = $menu_item; $menu_items_tree[ $menu_item->ID ] = $menu_item->menu_item_parent; if ( $menu_item->menu_item_parent ) { diff --git a/src/wp-includes/nav-menu.php b/src/wp-includes/nav-menu.php index 87b51182e3..c3750f9e9a 100644 --- a/src/wp-includes/nav-menu.php +++ b/src/wp-includes/nav-menu.php @@ -563,6 +563,11 @@ function wp_update_nav_menu_item( $menu_id = 0, $menu_item_db_id = 0, $menu_item $menu_item_db_id = (int) $menu_item_db_id; + // Reset invalid `menu_item_parent`. + if ( (int) $args['menu-item-parent-id'] === $menu_item_db_id ) { + $args['menu-item-parent-id'] = 0; + } + update_post_meta( $menu_item_db_id, '_menu_item_type', sanitize_key( $args['menu-item-type'] ) ); update_post_meta( $menu_item_db_id, '_menu_item_menu_item_parent', (string) ( (int) $args['menu-item-parent-id'] ) ); update_post_meta( $menu_item_db_id, '_menu_item_object_id', (string) ( (int) $args['menu-item-object-id'] ) ); @@ -1273,3 +1278,31 @@ function wp_map_nav_menu_locations( $new_nav_menu_locations, $old_nav_menu_locat return $new_nav_menu_locations; } + +/** + * Prevents menu items from being their own parent. + * + * Resets menu_item_parent to 0 when the parent is set to the item itself. + * For use before saving `_menu_item_menu_item_parent` in nav-menus.php. + * + * @since 6.1.2 + * @access private + * + * @param array $menu_item_data The menu item data array. + * @return array The menu item data with reset menu_item_parent. + */ +function _wp_reset_invalid_menu_item_parent( $menu_item_data ) { + if ( ! is_array( $menu_item_data ) ) { + return $menu_item_data; + } + + if ( + ! empty( $menu_item_data['ID'] ) && + ! empty( $menu_item_data['menu_item_parent'] ) && + (int) $menu_item_data['ID'] === (int) $menu_item_data['menu_item_parent'] + ) { + $menu_item_data['menu_item_parent'] = 0; + } + + return $menu_item_data; +}