0

An alias supplied to the [Path] attribute of a Menu Link is converted to node/nid when saved, (along with a nice message: "The menu system stores system paths only, but will use the URL alias for display".) This is implemented in core: function menu_edit_item_validate of menu.admin.inc. (Drupal 7.22)

When moving nodes around between instances of the same site with node-export and uuid, node/nid is no longer valid, and results in menu links being dropped, or pointing to the wrong node.

A similar question was raised earlier:

How do I use URL aliases in menus?

But the solutions I think are for different use cases. The suggestion of adding the alias and menu item together on node creation does not seem to work. Our concern has nothing to do with how the node url is displayed.

UUID_path or maybe UUID_features seem to imply a solution, but if there is a resolution there, I don't understand it, and will appreciate any insight into how to handle this.

In the end, we need to have exportable menu links with path attributes that, one way or another stay, linked to an alias, regardless of nid.

1

Both nid and aliases are not guaranteed to be stable and unchanged, nid being a bit less prone to mutation. What you seem to really need, are UUID Links. It should allow you to store links by the unchangeable UUID, not localised nid.

There was also a sandbox project UUID Menu for just the case, but it seems it was never properly initiated.

The other approach is to export both content and menu as a Feature. This problem is in Features' issue queue and in UUIDs for Menu Links issue queue, unresolved yet. But in the second one patches exists.

  • project/uuid_Links covers a different use case, does not handle with menu_links. We're pretty well committed to content export with node_export, not features. – August1914 Jun 13 '13 at 21:58
  • project/uuid_Links is a different use case: does not handle menu_links. We're committed to using node_export, not features, for content export. Workaround so far: exporting the affected menu with features (not content), then editing the feature, replacing the nids with aliases. Still, the menu_link parent is not respected when the feature is enabled, so we're having to specifically lookup and set the parent (menu_link_save) after the menu feature is enabled, despite setting plid. In our case, our menu can be expected to be stable, can survive kludging, but wondering, what would you do? – August1914 Jun 13 '13 at 22:07
  • I would find a way to store uuid links in menu. Write a module or hack for it if I have to. Portability is the very reason of uuid existence and there is no better approach at the moment. – Mołot Jun 13 '13 at 22:14
0

This turned out to be pretty easy, once I finally understood what's going on. We implemented our menu in an install hook, where we resolve uuid to normal path (node/nid):

function _get_normal_path_for_uuid($uuid) {
  $nid = db_select('node', 'n') 
    ->fields('n', array('nid'))
    ->condition('n.uuid', $uuid, '=')
    ->execute()
    ->fetchField();
  return 'node/' . $nid;
}    

and here, and example of a single menu_link,

$normal_path = _get_normal_path_for_uuid('8674c2c0-9ee4-4628-8666-e7eee4167250');
$menu_link = array(
  'menu_name' => 'products-menu',
  'link_path' => $normal_path,
  'router_path' => 'node/%',
  'link_title' => 'Resources',
  'options' => array(
    'attributes' => array(
      'title' => '',
    ),
  ),
  'module' => 'menu',
  'hidden' => 0,
  'external' => 0,
  'has_children' => 0,
  'expanded' => 0,
  'weight' => -48,
  'plid' => $some_plid,
);
menu_link_save($menu_link);

Now our menu links are pinned to specific nodes via uuid, in code, and content is fully portable between various site instances. Whenever we import node_export content from one site instance to another (which results in the "normal path" changing), we simply reinstall this menu module.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.