• Hi, I’m the author of the Nav menu roles plugin and I think I have finally tracked down an error one of my users is having when importing/exporting data. My plugin saves each menu item’s custom visibility permissions as post meta for nav menu item, _nav_menu_roles.

    I am digging through the process_menu_item() method of your WP_Import() class and you seem to limit the menu data to the defaults. Would it be possible to adjust so that nav menu item’s meta is imported?

    function process_menu_item( $item ) {
    		// skip draft, orphaned menu items
    		if ( 'draft' == $item['status'] )
    			return;
    
    		$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 />';
    			return;
    		}
    
    		$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 />';
    			return;
    		} else {
    			$menu_id = is_array( $menu_id ) ? $menu_id['term_id'] : $menu_id;
    		}
    
    		foreach ( $item['postmeta'] as $meta )
    			$$meta['key'] = $meta['value'];
    
    		if ( 'taxonomy' == $_menu_item_type && isset( $this->processed_terms[intval($_menu_item_object_id)] ) ) {
    			$_menu_item_object_id = $this->processed_terms[intval($_menu_item_object_id)];
    		} else if ( 'post_type' == $_menu_item_type && isset( $this->processed_posts[intval($_menu_item_object_id)] ) ) {
    			$_menu_item_object_id = $this->processed_posts[intval($_menu_item_object_id)];
    		} else if ( 'custom' != $_menu_item_type ) {
    			// associated object is missing or not imported yet, we'll retry later
    			$this->missing_menu_items[] = $item;
    			return;
    		}
    
    		if ( isset( $this->processed_menu_items[intval($_menu_item_menu_item_parent)] ) ) {
    			$_menu_item_menu_item_parent = $this->processed_menu_items[intval($_menu_item_menu_item_parent)];
    		} else if ( $_menu_item_menu_item_parent ) {
    			$this->menu_item_orphans[intval($item['post_id'])] = (int) $_menu_item_menu_item_parent;
    			$_menu_item_menu_item_parent = 0;
    		}
    
    		// 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']
    		);
    
    		$id = wp_update_nav_menu_item( $menu_id, 0, $args );
    		if ( $id && ! is_wp_error( $id ) )
    			$this->processed_menu_items[intval($item['post_id'])] = (int) $id;
    	}

    http://wordpress.org/extend/plugins/wordpress-importer/

Viewing 5 replies - 1 through 5 (of 5 total)
  • Thread Starter HelgaTheViking

    (@helgatheviking)

    I took a stab at updating the process_menu_item() method so that it would also import post meta. My results are as below:

    /**
    	 * Attempt to create a new menu item from import data
    	 *
    	 * Fails for draft, orphaned menu items and those without an associated nav_menu
    	 * or an invalid nav_menu term. If the post type or term object which the menu item
    	 * represents doesn't exist then the menu item will not be imported (waits until the
    	 * end of the import to retry again before discarding).
    	 *
    	 * @param array $item Menu item details from WXR file
    	 */
    	function process_menu_item( $item ) {
    		// skip draft, orphaned menu items
    		if ( 'draft' == $item['status'] )
    			return;
    
    		$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 />';
    			return;
    		}
    
    		$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 />';
    			return;
    		} else {
    			$menu_id = is_array( $menu_id ) ? $menu_id['term_id'] : $menu_id;
    		}
    
    		// Create an array to store all the post meta in
    		$menu_item_meta = array();
    
    		foreach ( $item['postmeta'] as $meta ){
    			$$meta['key'] = $meta['value'];
    			$menu_item_meta[$meta['key']] = $meta['value'];
    		}
    
    		if ( 'taxonomy' == $_menu_item_type && isset( $this->processed_terms[intval($_menu_item_object_id)] ) ) {
    			$_menu_item_object_id = $this->processed_terms[intval($_menu_item_object_id)];
    		} else if ( 'post_type' == $_menu_item_type && isset( $this->processed_posts[intval($_menu_item_object_id)] ) ) {
    			$_menu_item_object_id = $this->processed_posts[intval($_menu_item_object_id)];
    		} else if ( 'custom' != $_menu_item_type ) {
    			// associated object is missing or not imported yet, we'll retry later
    			$this->missing_menu_items[] = $item;
    			return;
    		}
    
    		if ( isset( $this->processed_menu_items[intval($_menu_item_menu_item_parent)] ) ) {
    			$_menu_item_menu_item_parent = $this->processed_menu_items[intval($_menu_item_menu_item_parent)];
    		} else if ( $_menu_item_menu_item_parent ) {
    			$this->menu_item_orphans[intval($item['post_id'])] = (int) $_menu_item_menu_item_parent;
    			$_menu_item_menu_item_parent = 0;
    		}
    
    		// 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']
    		);
    
    		$id = wp_update_nav_menu_item( $menu_id, 0, $args );
    
    		if ( $id && ! is_wp_error( $id ) ) {
    			$this->processed_menu_items[intval($item['post_id'])] = (int) $id;
    
    			// Add Custom Meta not already covered by $args
    
    			// Remove all default $args from $menu_item_meta array
    			foreach ( $args as $a => $arg ) {
    				unset( $menu_item_meta[ '_' . str_replace('-', '_', $a) ]);
    			}
    			// For some reason this doesn't follow the same naming convention so manually unset
    			unset ( $menu_item_meta['_menu_item_menu_item_parent'] );
    
    			$menu_item_meta = array_diff_assoc( $menu_item_meta, $args );
    
    			// update any other post meta
    			if ( ! empty ( $menu_item_meta ) ) foreach( $menu_item_meta as $key => $value ) {
    				update_post_meta( (int) $id, $key, maybe_unserialize( $value ) );
    			}
    
    		}
    	}

    Good idea. Have you tried posting this to trac?

    Thread Starter HelgaTheViking

    (@helgatheviking)

    No I haven’t. I thought it was principally a plugin problem so I posted here.

    Yeah, understandable; but trac is where the developers have visibility. There’s so much happening in the forums, it’s unlikely anyone would see it and create a patch/use your patch.

    john

    Thread Starter HelgaTheViking

    (@helgatheviking)

    I guess? But if my plugins are getting issues in trac I would have no idea. I hate trac and think the UI is terrible, but submitted there too:

    http://plugins.trac.wordpress.org/ticket/1678

    In the mean time I’ve developed a beta version of my own importer that pretty much duplicates the WordPress Importer and re-imports all post meta for menu items.

Viewing 5 replies - 1 through 5 (of 5 total)
  • The topic ‘Failure to import post meta for Nav Menu item’ is closed to new replies.