@@ -369,19 +369,28 @@ public function delete( $args, $assoc_args ) {
369369
370370 foreach ( $ args as $ arg ) {
371371
372+ $ post = get_post ($ arg );
373+ $ menu_term = get_the_terms ($ arg , 'nav_menu ' );
372374 $ parent_menu_id = (int ) get_post_meta ( $ arg , '_menu_item_menu_item_parent ' , true );
373375 $ result = wp_delete_post ( $ arg , true );
374376 if ( ! $ result ) {
375377 WP_CLI ::warning ( "Couldn't delete menu item {$ arg }. " );
376378 $ errors ++;
377- } elseif ( $ parent_menu_id ) {
378- $ children = $ wpdb ->get_results ( $ wpdb ->prepare ( "SELECT post_id FROM $ wpdb ->postmeta WHERE meta_key='_menu_item_menu_item_parent' AND meta_value=%s " , (int ) $ arg ) );
379- if ( $ children ) {
380- $ children_query = $ wpdb ->prepare ( "UPDATE $ wpdb ->postmeta SET meta_value = %d WHERE meta_key = '_menu_item_menu_item_parent' AND meta_value=%s " , $ parent_menu_id , (int ) $ arg );
381- // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- $children_query is already prepared above.
382- $ wpdb ->query ( $ children_query );
383- foreach ( $ children as $ child ) {
384- clean_post_cache ( $ child );
379+ } else {
380+
381+ if ( is_array ($ menu_term ) && !empty ($ menu_term ) && $ post ) {
382+ $ this ->reorder_menu_items ( $ menu_term [0 ]->term_id , $ post ->menu_order , -1 , 0 );
383+ }
384+
385+ if ( $ parent_menu_id ) {
386+ $ children = $ wpdb ->get_results ( $ wpdb ->prepare ( "SELECT post_id FROM $ wpdb ->postmeta WHERE meta_key='_menu_item_menu_item_parent' AND meta_value=%s " , (int ) $ arg ) );
387+ if ( $ children ) {
388+ $ children_query = $ wpdb ->prepare ( "UPDATE $ wpdb ->postmeta SET meta_value = %d WHERE meta_key = '_menu_item_menu_item_parent' AND meta_value=%s " , $ parent_menu_id , (int ) $ arg );
389+ // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- $children_query is already prepared above.
390+ $ wpdb ->query ( $ children_query );
391+ foreach ( $ children as $ child ) {
392+ clean_post_cache ( $ child );
393+ }
385394 }
386395 }
387396 }
@@ -477,6 +486,10 @@ private function add_or_update_item( $method, $type, $args, $assoc_args ) {
477486 }
478487 } else {
479488
489+ if ( 'add ' === $ method ) {
490+ $ this ->reorder_menu_items ( $ menu ->term_id , $ menu_item_args ['menu-item-position ' ], +1 , $ result );
491+ }
492+
480493 /**
481494 * Set the menu
482495 *
@@ -503,6 +516,23 @@ private function add_or_update_item( $method, $type, $args, $assoc_args ) {
503516
504517 }
505518
519+ /**
520+ * Move block of items in one nav_menu up or down by incrementing/decrementing their menu_order field.
521+ * Expects the menu items to have proper menu_orders (i.e. doesn't fix errors from previous incorrect operations).
522+ *
523+ * @param int $menu_id ID of the nav_menu
524+ * @param int $min_position minimal menu_order to touch
525+ * @param int $increment how much to change menu_order: +1 to move down, -1 to move up
526+ * @param int $ignore_item_id menu item that should be ignored by the change (e.g. newly created menu item)
527+ * @return int number of rows affected
528+ */
529+ private function reorder_menu_items ( $ menu_id , $ min_position , $ increment , $ ignore_item_id = 0 )
530+ {
531+ global $ wpdb ;
532+ $ reorder_query = $ wpdb ->prepare ( "UPDATE $ wpdb ->posts SET `menu_order`=`menu_order`+(%d) WHERE `menu_order`>=%d AND ID IN (SELECT object_id FROM $ wpdb ->term_relationships WHERE term_taxonomy_id=%d) AND ID<>%d " , (int ) $ increment , (int ) $ min_position , (int ) $ menu_id , (int ) $ ignore_item_id );
533+ return $ wpdb ->query ( $ reorder_query );
534+ }
535+
506536 protected function get_formatter ( &$ assoc_args ) {
507537 return new Formatter ( $ assoc_args , $ this ->obj_fields );
508538 }
0 commit comments