@@ -636,17 +636,61 @@ private function add_or_update_item( $method, $type, $args, $assoc_args ) {
636636
637637 $ menu_item_args ['menu-item-type ' ] = $ type ;
638638
639- // Reorder other menu items before updating the current one.
640- // The item being moved is at $old_position, which is never inside the affected
641- // range ([new, old-1] for moving up or [old+1, new] for moving down), so no
642- // exclusion of the item itself is necessary.
639+ // Reorder other menu items when the position changes on update.
643640 if ( 'update ' === $ method ) {
644641 $ new_position = (int ) $ menu_item_args ['menu-item-position ' ];
645- if ( $ new_position > 0 && $ new_position !== $ old_position ) {
646- if ( $ new_position < $ old_position ) {
647- $ this ->reorder_menu_items_in_range ( $ menu ->term_id , $ new_position , $ old_position - 1 , +1 );
648- } else {
649- $ this ->reorder_menu_items_in_range ( $ menu ->term_id , $ old_position + 1 , $ new_position , -1 );
642+ if ( $ new_position > 0 ) {
643+ // Fetch all menu items sorted by their raw menu_order to determine
644+ // normalized (1-indexed) ranks, since wp_get_nav_menu_items(ARRAY_A)
645+ // normalises menu_order to 1,2,3… which may differ from the raw DB values.
646+ $ sorted_items = get_posts (
647+ [
648+ 'post_type ' => 'nav_menu_item ' ,
649+ 'numberposts ' => -1 ,
650+ 'orderby ' => 'menu_order ' ,
651+ 'order ' => 'ASC ' ,
652+ 'post_status ' => 'any ' ,
653+ 'tax_query ' => [
654+ [
655+ 'taxonomy ' => 'nav_menu ' ,
656+ 'field ' => 'term_taxonomy_id ' ,
657+ 'terms ' => $ menu ->term_taxonomy_id ,
658+ ],
659+ ],
660+ ]
661+ );
662+
663+ // Find the 1-indexed normalized rank of the item being moved.
664+ $ old_position_normalized = 0 ;
665+ foreach ( $ sorted_items as $ idx => $ sorted_item ) {
666+ if ( (int ) $ sorted_item ->ID === (int ) $ menu_item_db_id ) {
667+ $ old_position_normalized = $ idx + 1 ;
668+ break ;
669+ }
670+ }
671+
672+ if ( $ old_position_normalized > 0 && $ new_position !== $ old_position_normalized ) {
673+ if ( $ new_position < $ old_position_normalized ) {
674+ // Moving up: items at 0-indexed [new_pos-1, old_pos-2] shift down by +1.
675+ for ( $ i = $ new_position - 1 ; $ i <= $ old_position_normalized - 2 ; $ i ++ ) {
676+ wp_update_post (
677+ [
678+ 'ID ' => $ sorted_items [ $ i ]->ID ,
679+ 'menu_order ' => $ i + 2 ,
680+ ]
681+ );
682+ }
683+ } else {
684+ // Moving down: items at 0-indexed [old_pos, new_pos-1] shift up by -1.
685+ for ( $ i = $ old_position_normalized ; $ i <= $ new_position - 1 ; $ i ++ ) {
686+ wp_update_post (
687+ [
688+ 'ID ' => $ sorted_items [ $ i ]->ID ,
689+ 'menu_order ' => $ i ,
690+ ]
691+ );
692+ }
693+ }
650694 }
651695 }
652696 }
0 commit comments