Skip to content

Commit 3245ddc

Browse files
Copilotswissspidy
andcommitted
Fix: reorder menu items using normalized rank-based wp_update_post instead of range SQL
Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>
1 parent d1110f1 commit 3245ddc

File tree

1 file changed

+53
-9
lines changed

1 file changed

+53
-9
lines changed

src/Menu_Item_Command.php

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)