As per the title, this module currently makes a mess of menus with nested items.

CommentFileSizeAuthor
#9 old.png440.28 KBkenny83
#9 new.png439.08 KBkenny83
#5 After.png421.53 KBbrooke_heaton
#5 Before.png435.46 KBbrooke_heaton

Comments

danbohea created an issue. See original summary.

sandeepguntaka’s picture

Status: Active » Postponed (maintainer needs more info)

When i tried i didn't face any such one. Could you post a screenshot which would be very helpful. I know it is too late to ask but if any chance please do.

dddbbb’s picture

Sorry, way too late. No longer using the module.

brooke_heaton’s picture

This is true. Menus with a structured hierarchy two or three levels deep will be exported/imported completely scrambled. Use with caution!

brooke_heaton’s picture

StatusFileSize
new435.46 KB
new421.53 KB

Before
Before
After
After

ivnish’s picture

I try today export-import menu with 3-level deep. No problem.

komlenic’s picture

I can confirm that exporting a 2-level menu and importing results in a completely jumbled menu.

ivnish’s picture

Status: Postponed (maintainer needs more info) » Active
kenny83’s picture

StatusFileSize
new439.08 KB
new440.28 KB

I know this issue is nearly 2 years old now, but I am still facing it on a Drupal 8 site with version 8.x-1.2 of the module. This is incredibly frustrating as I can't find any other modules that get so close to importing a complex menu structure correctly.

To make the matter even worse, I have stepped through the import form's submitForm() function with XDebug and everything seems to be working properly. I have also investigated the created/edited rows of the menu_link_content and menu_link_content_data tables, which also seem to be as they should be! Looking at the corresponding rows in my old and new DBs, the weight and parent values are exactly the same!

So what else could be causing the weird behaviour demonstrated in the attached screenshots?

ivnish’s picture

@all I use https://drupal.org/project/default_content + https://drupal.org/project/default_content_deploy to deploy menu items from dev to prod. Try it too.

kenny83’s picture

Thanks @ivnish for the suggestion, but I ended up solving the problem with this module by editing the submitForm() function of /src/Form/MenuImportForm.php like so:

public function submitForm(array &$form, FormStateInterface $form_state) {
    $invalidMenus = [];
    $menus = $this->config('menu_export.export_data')->get();
    $keys = array_keys($menus);
    foreach ($menus as $key => $menu) {
      $menu_name = $menu['menu_name']['value'];
      if (!Menu::load($menu_name)) {
        $invalidMenus[] = $menu_name;
        continue;
      }
      unset($menu['id']);
      $menuLinkEntity = \Drupal::entityQuery('menu_link_content')
        ->condition('uuid', $menu['uuid'])
        ->execute();
      if (!$menuLinkEntity) {
        $menuLinkEntity = MenuLinkContent::create();
      } else{
        $menuLinkEntity = MenuLinkContent::load(reset($menuLinkEntity));
      }
      foreach ($menu as $kkey => $items) {
        $menuLinkEntity->set($kkey, $items);
      }
      $menuLinkEntity->save();
      unset($menuLinkEntity);

      $keys[array_search($key, $keys)] = $menu['uuid']['value'];
      unset($menus[$key]['uuid']);
      $menus = array_combine($keys, $menus);
    }
    if (count($invalidMenus)){
      drupal_set_message($this->t('Menu(s) @menus not found',['@menus'=>implode(',',$invalidMenus)]), 'error');
      return;
    }

    foreach ($menus as $key => $menu) {
      $parentUuid = $menu['parent']['value'];
      if (!isset($parentUuid)) {
        continue;
      }

      $db = \Drupal::database();
      $query = $db->select('menu_tree', 'mt');
      $query->condition('mt.id', 'menu_link_content:' . $key);
      $query->addField('mt', 'mlid');
      $menuId = $query->execute()->fetchField();

      $parentIds = [ $menuId ];
      $fields = [ 'parent' => $parentUuid ];

      do {
        $query = $db->select('menu_tree', 'mt');
        $query->condition('mt.id', $parentUuid);
        $query->addField('mt', 'mlid');
        $parentId = $query->execute()->fetchField();

        array_unshift($parentIds, $parentId);
        $menu = $menus[str_replace('menu_link_content:', '', $parentUuid)];
        $parentUuid = $menu['parent']['value'];
      } while (!empty($parentUuid));

      foreach ($parentIds as $i => $parentId) {
        $fieldName = 'p' . ($i + 1);
        $fields[$fieldName] = $parentId;
      }

      $fields['depth'] = count($parentIds);
      $result = $db->update('menu_tree')
        ->condition('mlid', $menuId, '=')
        ->fields($fields)
        ->execute();

      if ($result != 1) {
        drupal_set_message($this->t('Failed to correctly link menu items to their parents!'), 'error');
        return;
      }
    }
    drupal_set_message($this->t('Menu(s) imported successfully'), 'success');
  }

The problem was that there is a menu_tree table in the Drupal DB that was not being correctly updated by the previous code. The rows that are automatically generated in this table by the first foreach loop do not always contain the correct values for the parent, depth or pX columns. My fix is not the prettiest, but it seems to do the job nicely.

Hopefully this helps some other poor shlub who may struggle with this in the future! ;-)

ressa’s picture

I just tried Menu migration (Import & Export) and the menu hierarchy is preserved.