Duplicate a Navigation Menu
Adds a "Duplicate this menu" button to Appearance > Menus that copies the selected classic menu with all its items and nesting, handy for trying a new structure safely.
Opens WPIDE on
Code
add_action( 'admin_footer-nav-menus.php', function () {
$menu_id = isset( $_REQUEST['menu'] ) ? absint( $_REQUEST['menu'] ) : absint( get_user_option( 'nav_menu_recently_edited' ) );
if ( ! $menu_id || ! is_nav_menu( $menu_id ) ) {
return;
}
$url = wp_nonce_url( admin_url( 'admin-post.php?action=wpide_duplicate_menu&menu=' . $menu_id ), 'wpide_duplicate_menu_' . $menu_id );
?>
<script>
( function () {
var target = document.querySelector( '.major-publishing-actions .publishing-action' );
if ( ! target ) { return; }
var link = document.createElement( 'a' );
link.className = 'button';
link.style.marginRight = '6px';
link.href = <?php echo wp_json_encode( $url ); ?>;
link.textContent = 'Duplicate this menu';
target.insertBefore( link, target.firstChild );
} )();
</script>
<?php
} );
add_action( 'admin_post_wpide_duplicate_menu', function () {
$menu_id = isset( $_GET['menu'] ) ? absint( $_GET['menu'] ) : 0;
check_admin_referer( 'wpide_duplicate_menu_' . $menu_id );
if ( ! current_user_can( 'edit_theme_options' ) || ! is_nav_menu( $menu_id ) ) {
wp_die( 'Not allowed.', 403 );
}
$source = wp_get_nav_menu_object( $menu_id );
$new_id = wp_create_nav_menu( $source->name . ' (Copy)' );
if ( is_wp_error( $new_id ) ) {
wp_die( esc_html( $new_id->get_error_message() ) );
}
$map = array();
foreach ( (array) wp_get_nav_menu_items( $menu_id, array( 'post_status' => 'any' ) ) as $item ) {
$map[ $item->ID ] = wp_update_nav_menu_item( $new_id, 0, array(
'menu-item-object-id' => $item->object_id,
'menu-item-object' => $item->object,
'menu-item-type' => $item->type,
'menu-item-title' => $item->title,
'menu-item-url' => $item->url,
'menu-item-description' => $item->description,
'menu-item-attr-title' => $item->attr_title,
'menu-item-target' => $item->target,
'menu-item-classes' => implode( ' ', (array) $item->classes ),
'menu-item-xfn' => $item->xfn,
'menu-item-position' => $item->menu_order,
'menu-item-parent-id' => $item->menu_item_parent ? ( $map[ $item->menu_item_parent ] ?? 0 ) : 0,
'menu-item-status' => 'publish',
) );
}
wp_safe_redirect( admin_url( 'nav-menus.php?action=edit&menu=' . (int) $new_id ) );
exit;
} );
Notes
The copy is not assigned to any theme location until you choose one.
How to add this snippet
- Install WPIDE on your WordPress site (it is free) and open Code Snippets.
- Use snippet above adds it from the library in one click. Or copy the code into a new snippet with the same code type.
- It is added inactive: review the code and settings, then switch it on.