Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
[WordPress Plugin] Nav Menu Exporter and Importer / Export and Import nav menus. Requires WordPress Importer plugin.
<?php
/*
Plugin Name: Nav Menu Exporter and Importer
Description: Export and Import nav menus. Requires WordPress Importer plugin
Author: hissy, megumi themes
Version: 0.1
Text Domain: nav-menu-exporter-importer
License: GPL version 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*/
/**
* Exporter
*/
function add_mav_menu_to_export() {
$post_type = get_post_type_object('nav_menu_item');
?>
<p><label><input type="radio" name="content" value="<?php echo esc_attr( $post_type->name ); ?>" /> <?php echo esc_html( $post_type->label ); ?></label></p>
<?php
}
add_action('export_filters','add_mav_menu_to_export');
/**
* Importer
*/
if ( ! defined( 'WP_LOAD_IMPORTERS' ) )
return;
// Load Importer API
require_once ABSPATH . 'wp-admin/includes/import.php';
if ( ! class_exists( 'WP_Importer' ) ) {
$class_wp_importer = ABSPATH . 'wp-admin/includes/class-wp-importer.php';
if ( file_exists( $class_wp_importer ) )
require $class_wp_importer;
}
// include WXR file parsers
$wordpress_importer = ABSPATH . 'wp-content/plugins/wordpress-importer/wordpress-importer.php';
if ( file_exists( $wordpress_importer ) )
require_once $wordpress_importer;
/**
* Nav Menu Importer class
*/
if ( class_exists( 'WP_Import' ) ) {
class Nav_Menu_Importer extends WP_Import {
function dispatch() {
$this->header();
$step = empty( $_GET['step'] ) ? 0 : (int) $_GET['step'];
switch ( $step ) {
case 0:
$this->greet();
break;
case 1:
check_admin_referer( 'import-upload' );
if ( $this->handle_upload() ) {
$file = get_attached_file( $this->id );
set_time_limit(0);
$this->import( $file );
}
break;
}
$this->footer();
}
function greet() {
wp_import_upload_form( add_query_arg('step', 1) );
}
function import_end() {
wp_import_cleanup( $this->id );
wp_cache_flush();
echo '<p>' . __( 'All done.', 'wordpress-importer' ) . ' <a href="' . admin_url() . '">' . __( 'Have fun!', 'wordpress-importer' ) . '</a>' . '</p>';
}
function import( $file ) {
$this->import_start( $file );
wp_suspend_cache_invalidation( true );
// only processing nav menus
$this->process_menus();
wp_suspend_cache_invalidation( false );
$this->import_end();
}
function process_menus() {
$count = 0;
foreach ( $this->posts as $item ) {
$count++;
// check the item is public nav item
if ( 'nav_menu_item' == $item['post_type'] && 'draft' != $item['status'] ) {
$menu_slug = false;
if ( isset($item['terms']) ) {
// loop through terms, assume first nav_menu term is correct menu
foreach ( $item['terms'] as $term ) {
if ( 'nav_menu' == $term['domain'] ) {
$menu_slug = $term['slug'];
break;
}
}
}
// no nav_menu term associated with this menu item
if ( ! $menu_slug ) {
_e( 'Menu item skipped due to missing menu slug', 'wordpress-importer' );
echo '<br>';
continue;
}
$menu_id = term_exists( $menu_slug, 'nav_menu' );
if ( ! $menu_id ) {
printf( __( 'Menu item skipped due to invalid menu slug: %s', 'wordpress-importer' ), esc_html( $menu_slug ) );
echo '<br>';
continue;
} else {
$menu_id = is_array( $menu_id ) ? $menu_id['term_id'] : $menu_id;
}
// set postmeta
foreach ( $item['postmeta'] as $meta )
$$meta['key'] = $meta['value'];
// skip nav item when menu item object is not exists
switch ($_menu_item_type) {
case 'taxonomy':
$_menu_item_object_id = get_term($_menu_item_object_id,$_menu_item_object);
if ($_menu_item_object_id == null || is_wp_error($_menu_item_object_id)) {
printf( __( 'Menu item skipped due to %s is not exists', 'nav-menu-exporter-importer' ), esc_html( $_menu_item_object ) );
echo '<br>';
}
break;
case 'post_type':
$_menu_item_object_id = get_post($_menu_item_object_id);
if ($_menu_item_object_id instanceof WP_Post) {
$_menu_item_object_id = $_menu_item_object_id->ID;
unset($_post);
} else {
printf( __( 'Menu item skipped due to %s is not exists', 'nav-menu-exporter-importer' ), esc_html( $_menu_item_object ) );
echo '<br>';
}
break;
}
if ($_menu_item_object_id == null || is_wp_error($_menu_item_object_id))
continue;
// wp_update_nav_menu_item expects CSS classes as a space separated string
$_menu_item_classes = maybe_unserialize( $_menu_item_classes );
if ( is_array( $_menu_item_classes ) )
$_menu_item_classes = implode( ' ', $_menu_item_classes );
$args = array(
'menu-item-object-id' => $_menu_item_object_id,
'menu-item-object' => $_menu_item_object,
'menu-item-parent-id' => $_menu_item_menu_item_parent,
'menu-item-position' => intval( $item['menu_order'] ),
'menu-item-type' => $_menu_item_type,
'menu-item-title' => $item['post_title'],
'menu-item-url' => $_menu_item_url,
'menu-item-description' => $item['post_content'],
'menu-item-attr-title' => $item['post_excerpt'],
'menu-item-target' => $_menu_item_target,
'menu-item-classes' => $_menu_item_classes,
'menu-item-xfn' => $_menu_item_xfn,
'menu-item-status' => $item['status']
);
$r = wp_update_nav_menu_item( $menu_id, 0, $args );
if ( $r && is_wp_error( $r ) ) {
echo $r->get_error_message();
echo '<br>';
} else {
echo '.';
}
}
}
echo '<br>';
printf( __( '%s items processed.', 'nav-menu-exporter-importer' ), esc_html( $count ) );
}
}
// setup importer
$nav_menu_importer = new Nav_Menu_Importer();
register_importer('nav_menu', __('Nav Menu', 'nav-menu-exporter-importer'), __('Export and Import nav menus. Requires WordPress Importer plugin', 'nav-menu-exporter-importer'), array ($nav_menu_importer, 'dispatch'));
} // class_exists( 'WP_Import' )
@thednp

This comment has been minimized.

Copy link

commented Apr 20, 2014

Hi. Thanks for your code. I was wondering if we can implement your code and merge with this one here
http://wordpress.org/support/topic/failure-to-import-post-meta-for-nav-menu-item?replies=6#post-3926917

This one should include the menu items meta data, something that's missing as well from WP Importer.

Thanks for any reply.

@thatryan

This comment has been minimized.

Copy link

commented Feb 26, 2016

Super helpful, thank you for sharing! Just saved me a few hours :)

@cubalibre

This comment has been minimized.

Copy link

commented Apr 12, 2016

Hi, can I export only a specific menu name and not all definited menus?

Thanks for any reply.

@robinpecha

This comment has been minimized.

Copy link

commented Jun 25, 2016

Hi,
plugin like this is really important. It last (probalby) working one in the world.
But it didnt work in my case.
After importing wp shows error:
Menu item skipped due to invalid menu slug: default
Menu item skipped due to invalid menu slug: default
Menu item skipped due to invalid menu slug: default
....

@chrslcy

This comment has been minimized.

Copy link

commented Jul 30, 2016

I am getting the same error as reported by robinpecha.

@chrslcy

This comment has been minimized.

Copy link

commented Jul 30, 2016

The above error reported by robinpecha is overcome by creating empty menus with the same name as the source website menus before importing. However, once imported, the menus are flat, having lost all submenu structure.

@bobettekyle

This comment has been minimized.

Copy link

commented Aug 10, 2016

Great job. This just saved me from setting up over 100 menu items. FYI, the one quirk: menu hierarchy is lost on the imported menu. The new menu has all top-level items. They looked to be ordered by original menu level. i.e. all the top-level items first, followed by their children, etc.

As chrslcy suggested, I first made empty menus in the site I was importing to, identical in name to the originals.

I got two import errors. These make sense because I had two pages on the old site that were not on the new site. Can't find what is not there.

@yelnyaface

This comment has been minimized.

Copy link

commented Sep 28, 2016

how to use this 'plugin'?

there is no guide or instructions about how to 'install' this

@raynov

This comment has been minimized.

Copy link

commented Oct 20, 2016

@elzix

This comment has been minimized.

Copy link

commented Nov 16, 2016

I have tried this plugin and raynov's patched plugin. I cannot seem to get a plugin that works for custom menus. I have a single page solution with anchor links (#something) for the menu. Having no menu gives errors described above. Creating an empty menu solves the error problem. However the menu items are not created at all.

@overclokk

This comment has been minimized.

Copy link

commented Dec 30, 2016

I made some fix and modification, with WordPress 4.7 in my dev enviroments it works fine with tax, post_type and custom nav menu items and now if the menu doesn't exist it will be created during the import.
Here the link https://gist.github.com/overclokk/bad83a7cb3db4263192aa52db0a60fc0

@renegithub

This comment has been minimized.

Copy link

commented Jan 30, 2017

Hello,

can I use this Tool to migrate from one Domain www.123.com to another Domain www.abc.de
How can I do this?

The pages are the same on both Domains.

I´ve renamed in domains inside the export file to the new domain, but I got this error:

Menu item skipped due to invalid menu slug: primary

Best regards,

Rene

@Mr-Alexander

This comment has been minimized.

Copy link

commented Nov 29, 2017

It is unfortunate but this tool does not work in multisite.

@duchuy

This comment has been minimized.

Copy link

commented Jun 20, 2019

how to use this 'plugin'?

there is no guide or instructions about how to 'install' this

save the file as nav-menu-exporter-importer.php and put into wp-content/plugins/wordpress-importer directory. then go into Plugins in Admin Dashboard to activate

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.