diff --git a/wp-admin/includes/nav-menu.php b/wp-admin/includes/nav-menu.php
index db49628459..7ec66664b8 100644
--- a/wp-admin/includes/nav-menu.php
+++ b/wp-admin/includes/nav-menu.php
@@ -15,7 +15,7 @@ class Walker_Nav_Menu_Edit extends Walker_Nav_Menu {
* @param string $output Passed by reference.
* @param int $depth Depth of page.
*/
- function start_lvl(&$output, $depth) {}
+ function start_lvl(&$output) {}
/**
* @see Walker_Nav_Menu::end_lvl()
@@ -24,7 +24,8 @@ class Walker_Nav_Menu_Edit extends Walker_Nav_Menu {
* @param string $output Passed by reference.
* @param int $depth Depth of page.
*/
- function end_lvl(&$output, $depth) {}
+ function end_lvl(&$output) {
+ }
/**
* @see Walker::start_el()
@@ -79,7 +80,7 @@ class Walker_Nav_Menu_Edit extends Walker_Nav_Menu {
),
remove_query_arg($removed_args, admin_url( 'nav-menus.php' ) )
),
- 'move-item'
+ 'move-menu_item'
);
?>" class="item-move-up">↑
|
@@ -92,7 +93,7 @@ class Walker_Nav_Menu_Edit extends Walker_Nav_Menu {
),
remove_query_arg($removed_args, admin_url( 'nav-menus.php' ) )
),
- 'move-item'
+ 'move-menu_item'
);
?>" class="item-move-down">↓
@@ -187,7 +188,7 @@ class Walker_Nav_Menu_Edit extends Walker_Nav_Menu {
-
+
diff --git a/wp-admin/nav-menus.php b/wp-admin/nav-menus.php
index 06459ed088..d59dee2bf2 100644
--- a/wp-admin/nav-menus.php
+++ b/wp-admin/nav-menus.php
@@ -61,99 +61,165 @@ switch ( $action ) {
case 'move-down-menu-item' :
// moving down a menu item is the same as moving up the next in order
check_admin_referer( 'move-menu_item' );
- $menu_item_id = (int) $_REQUEST['menu-item'];
- $next_item_id = 0;
+ $menu_item_id = isset( $_REQUEST['menu-item'] ) ? (int) $_REQUEST['menu-item'] : 0;
if ( is_nav_menu_item( $menu_item_id ) ) {
$menus = isset( $_REQUEST['menu'] ) ? array( (int) $_REQUEST['menu'] ) : wp_get_object_terms( $menu_item_id, 'nav_menu', array( 'fields' => 'ids' ) );
- if ( ! is_wp_error( $menus ) ) {
- foreach( (array) $menus as $menu_id ) {
- $move_down_ordered_menu_items = (array) wp_get_nav_menu_items( $menu_id );
- while ( $next = array_shift( $move_down_ordered_menu_items ) ) {
- if ( isset( $next->ID ) && $next->ID == $menu_item_id ) {
- break;
+ if ( ! is_wp_error( $menus ) && ! empty( $menus[0] ) ) {
+ $menu_id = (int) $menus[0];
+ $ordered_menu_items = wp_get_nav_menu_items( $menu_id );
+ $menu_item_data = (array) wp_setup_nav_menu_item( get_post( $menu_item_id ) );
+
+ // setup the data we need in one pass through the array of menu items
+ $dbids_to_orders = array();
+ $orders_to_dbids = array();
+ foreach( (array) $ordered_menu_items as $ordered_menu_item_object ) {
+ if ( isset( $ordered_menu_item_object->ID ) ) {
+ if ( isset( $ordered_menu_item_object->menu_order ) ) {
+ $dbids_to_orders[$ordered_menu_item_object->ID] = $ordered_menu_item_object->menu_order;
+ $orders_to_dbids[$ordered_menu_item_object->menu_order] = $ordered_menu_item_object->ID;
}
}
+ }
- if ( $following = array_shift( $move_down_ordered_menu_items ) ) {
- $next_item_id = (int) $following->ID;
+ // get next in order
+ if (
+ isset( $orders_to_dbids[$dbids_to_orders[$menu_item_id] + 1] )
+ ) {
+ $next_item_id = $orders_to_dbids[$dbids_to_orders[$menu_item_id] + 1];
+ $next_item_data = (array) wp_setup_nav_menu_item( get_post( $next_item_id ) );
+
+ // if not siblings of same parent, bubble menu item up but keep order
+ if (
+ ! empty( $menu_item_data['menu_item_parent'] ) &&
+ (
+ empty( $next_item_data['menu_item_parent'] ) ||
+ $next_item_data['menu_item_parent'] != $menu_item_data['menu_item_parent']
+ )
+ ) {
+
+ $parent_db_id = in_array( $menu_item_data['menu_item_parent'], $orders_to_dbids ) ? (int) $menu_item_data['menu_item_parent'] : 0;
+
+ $parent_object = wp_setup_nav_menu_item( get_post( $parent_db_id ) );
+
+ if ( ! is_wp_error( $parent_object ) ) {
+ $parent_data = (array) $parent_object;
+ $menu_item_data['menu_item_parent'] = $parent_data['menu_item_parent'];
+ update_post_meta( $menu_item_data['ID'], '_menu_item_menu_item_parent', (int) $menu_item_data['menu_item_parent'] );
+
+ }
+
+ // make menu item a child of its next sibling
+ } else {
+ $next_item_data['menu_order'] = $next_item_data['menu_order'] - 1;
+ $menu_item_data['menu_order'] = $menu_item_data['menu_order'] + 1;
+
+ $menu_item_data['menu_item_parent'] = $next_item_data['ID'];
+ 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);
+ wp_update_post($next_item_data);
}
+
+
+ // the item is last but still has a parent, so bubble up
+ } elseif (
+ ! empty( $menu_item_data['menu_item_parent'] ) &&
+ in_array( $menu_item_data['menu_item_parent'], $orders_to_dbids )
+ ) {
+ $menu_item_data['menu_item_parent'] = (int) get_post_meta( $menu_item_data['menu_item_parent'], '_menu_item_menu_item_parent', true);
+ update_post_meta( $menu_item_data['ID'], '_menu_item_menu_item_parent', (int) $menu_item_data['menu_item_parent'] );
}
}
}
- // fall through to next case
+
+ break;
case 'move-up-menu-item' :
check_admin_referer( 'move-menu_item' );
- $menu_item_id = empty( $next_item_id ) ? (int) $_REQUEST['menu-item'] : $next_item_id;
+ $menu_item_id = isset( $_REQUEST['menu-item'] ) ? (int) $_REQUEST['menu-item'] : 0;
if ( is_nav_menu_item( $menu_item_id ) ) {
$menus = isset( $_REQUEST['menu'] ) ? array( (int) $_REQUEST['menu'] ) : wp_get_object_terms( $menu_item_id, 'nav_menu', array( 'fields' => 'ids' ) );
- if ( ! is_wp_error( $menus ) ) {
- foreach( (array) $menus as $menu_id ) {
- $ordered_menu_items = wp_get_nav_menu_items( $menu_id );
- $menu_item_data = get_post( $menu_item_id , ARRAY_A );
+ if ( ! is_wp_error( $menus ) && ! empty( $menus[0] ) ) {
+ $menu_id = (int) $menus[0];
+ $ordered_menu_items = wp_get_nav_menu_items( $menu_id );
+ $menu_item_data = (array) wp_setup_nav_menu_item( get_post( $menu_item_id ) );
- // setup the data we need in one pass through the array of menu items
- $dbids_to_orders = array();
- $orders_to_dbids = array();
- $objectids_to_dbids = array();
- $dbids_to_objectids = array();
- foreach( (array) $ordered_menu_items as $ordered_menu_item_object ) {
- if ( isset( $ordered_menu_item_object->ID ) ) {
- if ( isset( $ordered_menu_item_object->menu_order ) ) {
- $dbids_to_orders[$ordered_menu_item_object->ID] = $ordered_menu_item_object->menu_order;
- $orders_to_dbids[$ordered_menu_item_object->menu_order] = $ordered_menu_item_object->ID;
- }
-
- $possible_object_id = (int) get_post_meta( $ordered_menu_item_object->ID, '_menu_item_object_id', true );
- if ( ! empty( $possible_object_id ) ) {
- $dbids_to_objectids[$ordered_menu_item_object->ID] = $possible_object_id;
- $objectids_to_dbids[$possible_object_id] = $ordered_menu_item_object->ID;
- }
+ // setup the data we need in one pass through the array of menu items
+ $dbids_to_orders = array();
+ $orders_to_dbids = array();
+ foreach( (array) $ordered_menu_items as $ordered_menu_item_object ) {
+ if ( isset( $ordered_menu_item_object->ID ) ) {
+ if ( isset( $ordered_menu_item_object->menu_order ) ) {
+ $dbids_to_orders[$ordered_menu_item_object->ID] = $ordered_menu_item_object->menu_order;
+ $orders_to_dbids[$ordered_menu_item_object->menu_order] = $ordered_menu_item_object->ID;
}
}
+ }
- // if this menu item is not first
- if ( ! empty( $dbids_to_orders[$menu_item_id] ) && ! empty( $orders_to_dbids[$dbids_to_orders[$menu_item_id] - 1] ) ) {
+ // if this menu item is not first
+ if ( ! empty( $dbids_to_orders[$menu_item_id] ) && ! empty( $orders_to_dbids[$dbids_to_orders[$menu_item_id] - 1] ) ) {
- // if this menu item is a child of the previous
- if (
- ! empty( $menu_item_data['post_parent'] ) &&
- isset( $objectids_to_dbids[$menu_item_data['post_parent']] ) &&
- isset( $orders_to_dbids[$dbids_to_orders[$menu_item_id] - 1] ) &&
- ( $objectids_to_dbids[$menu_item_data['post_parent']] == $orders_to_dbids[$dbids_to_orders[$menu_item_id] - 1] )
- ) {
+ // if this menu item is a child of the previous
+ if (
+ ! empty( $menu_item_data['menu_item_parent'] ) &&
+ in_array( $menu_item_data['menu_item_parent'], array_keys( $dbids_to_orders ) ) &&
+ isset( $orders_to_dbids[$dbids_to_orders[$menu_item_id] - 1] ) &&
+ ( $menu_item_data['menu_item_parent'] == $orders_to_dbids[$dbids_to_orders[$menu_item_id] - 1] )
+ ) {
+ $parent_db_id = in_array( $menu_item_data['menu_item_parent'], $orders_to_dbids ) ? (int) $menu_item_data['menu_item_parent'] : 0;
+ $parent_object = wp_setup_nav_menu_item( get_post( $parent_db_id ) );
- $parent_db_id = $objectids_to_dbids[$menu_item_data['post_parent']];
- $parent_data = get_post( $parent_db_id, ARRAY_A );
+ if ( ! is_wp_error( $parent_object ) ) {
+ $parent_data = (array) $parent_object;
- if ( ! is_wp_error( $parent_data ) ) {
+ // if there is something before the parent and parent a child of it, make menu item a child also of it
+ if (
+ ! empty( $dbids_to_orders[$parent_db_id] ) &&
+ ! empty( $orders_to_dbids[$dbids_to_orders[$parent_db_id] - 1] ) &&
+ ! empty( $parent_data['menu_item_parent'] )
+ ) {
+ $menu_item_data['menu_item_parent'] = $parent_data['menu_item_parent'];
- // if there is something before the parent, make menu item a child of the parent's parent
- if ( ! empty( $dbids_to_orders[$parent_db_id] ) && ! empty( $orders_to_dbids[$dbids_to_orders[$parent_db_id] - 1] ) ) {
- $menu_item_data['post_parent'] = $parent_data['post_parent'];
+ // else if there is something before parent and parent not a child of it, make menu item a child of that something's parent
+ } elseif (
+ ! empty( $dbids_to_orders[$parent_db_id] ) &&
+ ! empty( $orders_to_dbids[$dbids_to_orders[$parent_db_id] - 1] )
+ ) {
+ $_possible_parent_id = (int) get_post_meta( $orders_to_dbids[$dbids_to_orders[$parent_db_id] - 1], '_menu_item_menu_item_parent', true);
+ if ( in_array( $_possible_parent_id, array_keys( $dbids_to_orders ) ) )
+ $menu_item_data['menu_item_parent'] = $_possible_parent_id;
+ else
+ $menu_item_data['menu_item_parent'] = 0;
- // else there isn't something before the parent
- } else {
- $menu_item_data['post_parent'] = 0;
- }
-
- // set former parent's [menu_order] to that of menu-item's
- $parent_data['menu_order'] = $parent_data['menu_order'] + 1;
-
- // set menu-item's [menu_order] to that of former parent
- $menu_item_data['menu_order'] = $menu_item_data['menu_order'] - 1;
-
- // save changes
- wp_update_post($menu_item_data);
- wp_update_post($parent_data);
+ // else there isn't something before the parent
+ } else {
+ $menu_item_data['menu_item_parent'] = 0;
}
- // else this menu item is not a child of the previous
- } elseif ( isset($dbids_to_objectids[$orders_to_dbids[$dbids_to_orders[$menu_item_id] - 1]] ) ) {
- // just make it a child of the previous; keep the order
- $menu_item_data['post_parent'] = (int) $dbids_to_objectids[$orders_to_dbids[$dbids_to_orders[$menu_item_id] - 1]];
+ // set former parent's [menu_order] to that of menu-item's
+ $parent_data['menu_order'] = $parent_data['menu_order'] + 1;
+
+ // set menu-item's [menu_order] to that of former parent
+ $menu_item_data['menu_order'] = $menu_item_data['menu_order'] - 1;
+
+ // save changes
+ 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);
+ wp_update_post($parent_data);
}
+
+ // else this menu item is not a child of the previous
+ } elseif (
+ empty( $menu_item_data['menu_order'] ) ||
+ empty( $menu_item_data['menu_item_parent'] ) ||
+ ! in_array( $menu_item_data['menu_item_parent'], array_keys( $dbids_to_orders ) ) ||
+ empty( $orders_to_dbids[$dbids_to_orders[$menu_item_id] - 1] ) ||
+ $orders_to_dbids[$dbids_to_orders[$menu_item_id] - 1] != $menu_item_data['menu_item_parent']
+ ) {
+ // 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];
+ 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/wp-includes/nav-menu-template.php b/wp-includes/nav-menu-template.php
index 94d47a75a2..b08e66caab 100644
--- a/wp-includes/nav-menu-template.php
+++ b/wp-includes/nav-menu-template.php
@@ -28,7 +28,7 @@ class Walker_Nav_Menu extends Walker {
* @todo Decouple this.
* @var array
*/
- var $db_fields = array( 'parent' => 'post_parent', 'id' => 'object_id' );
+ var $db_fields = array( 'parent' => 'menu_item_parent', 'id' => 'db_id' );
/**
* @see Walker::start_lvl()
@@ -137,7 +137,6 @@ class Walker_Nav_Menu_Checklist extends Walker_Nav_Menu {
$_nav_menu_placeholder = ( 0 > $_nav_menu_placeholder ) ? intval($_nav_menu_placeholder) - 1 : -1;
$possible_object_id = isset( $item->post_type ) && 'nav_menu_item' == $item->post_type ? $item->object_id : $_nav_menu_placeholder;
$possible_db_id = ( ! empty( $item->ID ) ) && ( 0 < $possible_object_id ) ? (int) $item->ID : 0;
- $possible_parent_id = ( ! empty( $item->ID ) ) && ( 0 < $possible_object_id ) ? (int) $item->post_parent : 0;
$indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';
@@ -157,7 +156,7 @@ class Walker_Nav_Menu_Checklist extends Walker_Nav_Menu {
// Menu item hidden fields
$output .= '';
$output .= '';
- $output .= '';
+ $output .= '';
$output .= '';
$output .= '';
$output .= '';
diff --git a/wp-includes/nav-menu.php b/wp-includes/nav-menu.php
index a1215e8038..a2f5695961 100644
--- a/wp-includes/nav-menu.php
+++ b/wp-includes/nav-menu.php
@@ -256,6 +256,8 @@ function wp_update_nav_menu_item( $menu_id = 0, $menu_item_db_id = 0, $menu_item
}
}
+ $original_parent = 0 < $menu_item_db_id ? get_post_field( 'post_parent', $menu_item_db_id ) : 0;
+
if ( 'custom' != $args['menu-item-type'] ) {
/* if non-custom menu item, then:
* use original object's URL
@@ -266,10 +268,12 @@ function wp_update_nav_menu_item( $menu_id = 0, $menu_item_db_id = 0, $menu_item
$original_title = '';
if ( 'taxonomy' == $args['menu-item-type'] ) {
+ $original_parent = get_term_field( 'parent', $args['menu-item-object-id'], $args['menu-item-object'], 'raw' );
$original_title = get_term_field( 'name', $args['menu-item-object-id'], $args['menu-item-object'], 'raw' );
} elseif ( 'post_type' == $args['menu-item-type'] ) {
$original_object = get_post( $args['menu-item-object-id'] );
+ $original_parent = (int) $original_object->post_parent;
$original_title = $original_object->post_title;
if ( 'trash' == get_post_status( $args['menu-item-object-id'] ) ) {
@@ -297,7 +301,7 @@ function wp_update_nav_menu_item( $menu_id = 0, $menu_item_db_id = 0, $menu_item
'ping_status' => 0,
'post_content' => $args['menu-item-description'],
'post_excerpt' => $args['menu-item-attr-title'],
- 'post_parent' => $args['menu-item-parent-id'],
+ 'post_parent' => $original_parent,
'post_title' => $args['menu-item-title'],
'post_type' => 'nav_menu_item',
'tax_input' => array( 'nav_menu' => $menu->name ),
@@ -326,6 +330,7 @@ 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;
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', (int) $args['menu-item-parent-id'] );
update_post_meta( $menu_item_db_id, '_menu_item_object_id', (int) $args['menu-item-object-id'] );
update_post_meta( $menu_item_db_id, '_menu_item_object', sanitize_key($args['menu-item-object']) );
update_post_meta( $menu_item_db_id, '_menu_item_target', sanitize_key($args['menu-item-target']) );
@@ -439,12 +444,13 @@ function wp_get_nav_menu_items( $menu, $args = array() ) {
* Decorates a menu item object with the shared navigation menu item properties.
*
* Properties:
- * - db_id: The DB ID of the this item as a nav_menu_item object, if it exists (0 if it doesn't exist).
+ * - db_id: The DB ID of this item as a nav_menu_item object, if it exists (0 if it doesn't exist).
* - object_id: The DB ID of the original object this menu item represents, e.g. ID for posts and term_id for categories.
* - type: The family of objects originally represented, such as "post_type" or "taxonomy."
* - object: The type of object originally represented, such as "category," "post", or "attachment."
* - append: The singular label used to describe this type of menu item.
- * - parent: The DB ID of the original object's parent object, if any (0 otherwise).
+ * - post_parent: The DB ID of the original object's parent object, if any (0 otherwise).
+ * - menu_item_parent: The DB ID of the nav_menu_item that is this item's menu parent, if any. 0 otherwise.
* - url: The URL to which this menu item points.
* - title: The title of this menu item.
* - target: The target attribute of the link element for this menu item.
@@ -462,6 +468,7 @@ function wp_setup_nav_menu_item( $menu_item ) {
if ( isset( $menu_item->post_type ) ) {
if ( 'nav_menu_item' == $menu_item->post_type ) {
$menu_item->db_id = (int) $menu_item->ID;
+ $menu_item->menu_item_parent = get_post_meta( $menu_item->ID, '_menu_item_menu_item_parent', true );
$menu_item->object_id = get_post_meta( $menu_item->ID, '_menu_item_object_id', true );
$menu_item->object = get_post_meta( $menu_item->ID, '_menu_item_object', true );
$menu_item->type = get_post_meta( $menu_item->ID, '_menu_item_type', true );
@@ -498,6 +505,7 @@ function wp_setup_nav_menu_item( $menu_item ) {
$menu_item->xfn = get_post_meta( $menu_item->ID, '_menu_item_xfn', true );
} else {
$menu_item->db_id = 0;
+ $menu_item->menu_item_parent = 0;
$menu_item->object_id = (int) $menu_item->ID;
$menu_item->type = 'post_type';
@@ -517,6 +525,7 @@ function wp_setup_nav_menu_item( $menu_item ) {
} elseif ( isset( $menu_item->taxonomy ) ) {
$menu_item->ID = $menu_item->term_id;
$menu_item->db_id = 0;
+ $menu_item->menu_item_parent = 0;
$menu_item->object_id = (int) $menu_item->term_id;
$menu_item->post_parent = (int) $menu_item->parent;
$menu_item->type = 'taxonomy';