I have a main menu which (inter alia) has has these menu links:

Root (node/467)
  - First child (node/468)
    - First granchild (node/469)
    - Second granchild (node/470)

I need to export menu link "First child" and its' children menu links, therefore I have a following export code in my MODULE.features.menu_links.inc:

/**
 * @file
 * menu_links.features.menu_links.inc
 */

/**
 * Implements hook_menu_default_menu_links().
 */
function MODULE_menu_default_menu_links() {
  $menu_links = array();
  
  // Exported menu link: main-menu_first-child:node/468
  $menu_links['main-menu_first-child:node/468'] = array(
    'menu_name' => 'main-menu',
    'link_path' => 'node/468',
    'link_title' => 'First child',
    'options' => array(
      // ... skip irrelevant menu link meta data here and after for readability sake
      'identifier' => 'main-menu_first-child:node/468',
    ),
    'parent_identifier' => 'main-menu_root:node/467',
  );
  // Exported menu link: main-menu_first-grandchild:node/469
  $menu_links['main-menu_first-grandchild:node/469'] = array(
    'menu_name' => 'main-menu',
    'link_path' => 'node/469',
    'link_title' => 'First grandchild',
    'options' => array(
      'identifier' => 'main-menu_first-grandchild:node/469',
    ),
    'parent_identifier' => 'main-menu_first-child:node/468',
  );
  // Exported menu link: main-menu_second-grandchild:node/470
  $menu_links['main-menu_second-grandchild:node/470'] = array(
    'menu_name' => 'main-menu',
    'link_path' => 'node/470',
    'link_title' => 'Second grandchild',
    'options' => array(
      'identifier' => 'main-menu_second-grandchild:node/470',
    ),
    'parent_identifier' => 'main-menu_first-child:node/468',
  );
  return $menu_links;
}

1. Expected behaviour: Upon feature revert menu links are created or updated with data from feature settings.

2. Current behaviour: Upon feature revert menu links are neither created nor updated.

3. Problem: In MODULE.features.menu_links.inc file I don't have the root menu link exported which is the parent menu link for exported $menu_links['main-menu_first-child:node/468'] menu link.

During menu link restoration process menu_links_features_revert() calls menu_links_features_rebuild() which eventually calls menu_links_features_rebuild_ordered().

menu_links_features_rebuild_ordered() function in features.menu.inc tries to order exported menu links depending on whether they have parent menu links defined.

// Line 288
$ordered = array();
// ...
foreach ($unordered as $key => $link) {
  $identifier = menu_links_features_identifier($link);
  $parent = isset($link['parent_identifier']) ? $link['parent_identifier'] : '';
  if (empty($parent)) {
    $ordered[$identifier] = 0;
    $all_links[$identifier] = $link;
    unset($unordered[$key]);
  }
  elseif (isset($ordered[$parent])) {
    $ordered[$identifier] = $ordered[$parent] + 1;
    $all_links[$identifier] = $link;
    unset($unordered[$key]);
  }
}
// .. $ordered contains links that are restored

In this case $menu_links['main-menu_first-child:node/468'] menu does not pass neither if (empty($parent)) nor elseif (isset($ordered[$parent])) test because it has parent identified defined and parent identifier is not defined in $ordered.

4. Solution: Set the weight (to make the order) of the menu links that don't have their parents menu links exported the same as if menu link didn't have parent menu link at all:

foreach ($unordered as $key => $link) {
  $identifier = menu_links_features_identifier($link);
  $parent = isset($link['parent_identifier']) ? $link['parent_identifier'] : '';
  $weight = 0;
  if (isset($ordered[$parent])) {
    $weight = $ordered[$parent] + 1;
  }
  $ordered[$identifier] = $weight;
  $all_links[$identifier] = $link;
  unset($unordered[$key]);
}

A patch against HEAD is attached.

Comments

maijs’s picture

Issue summary: View changes
shushu’s picture

Status: Needs review » Reviewed & tested by the community

I encountered the same problem, and your patch seems to solve the problem.

jaime@gingerrobot.com’s picture

Works for me. Thankyou so much.

hefox’s picture

Status: Reviewed & tested by the community » Fixed

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

hefox’s picture

Status: Closed (fixed) » Active

This caused a regression that menu links are not actually being ordered correctly when the menu links ARE in features. Trying to fix now.

  • hefox committed e2a4e42 on 7.x-2.x
    Issue #2216371: Fix regression where child weight was not being set...

  • hefox committed 09aa829 on 7.x-2.x
    Issue #2216371: also fix the issue that this bug was about (make sure...
hefox’s picture

Status: Active » Fixed

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.