T.L.D.R.
Since this issue, the identifiers for menu links contain the link title, in addition to the link path and menu name.
This helps distinguish menu links with different menu name and link path.
Menu links which also have the same title still cause problems.

Original title: "Menu links do not support 2+ links with same menu_name/link_path"

Broken off from #860974: Menu Links will not import/revert.
Right now, features does not support two menu items in the same menu that have the same path.

It is due to the identifier for the menu items being menu-name:link_path, limiting it to only one of such a combination.

I first though of adding a parent path to distinguish, but that'd break if they have the same parent (for example, I've put two+ user/register links in a menu with different destination='s [which isn't stored with the link_path]).

So, in such a situation, when exporting the menu item, it needs to determine a unique identifier that will be able to used also when loading that menu item, and that needs to be used whenever there is 2+ of the same menu item. Now being that multiple features could be in play, ugh!

Though, that gets complicated further due to needing to be able to update the feature, for example if what was the unique identifier is changed. Well it could be seen as a new item, the old item is very unlikely to be removed if 'customized' = 1 #860974: Menu Links will not import/revert comes into play.

I have given a thought that this situation might be best by letting the user choice the identifier in some way, like by only supporting the situation by .info file addition. but that is confusing for users that only create a feature via the UI.

Status / Progress

Menu link identifiers before Oct 2013

(latest release 7.x-2.0-rc3)
In the old implementation, menu link identifiers were built as "{$link['menu_name']}:{$link['link_path']}".

Changes committed Oct 2013

(since 7.x-2.0-rc4)
In #74, @mpotter mentions that the patch from #72 has actually been committed, but it was accidentally done as part of another commit, afa91335e for unrelated issue #1597186: Do not cache included components in features_include_defaults().

With this implementation, the identifier is built as "{$link['menu_name']}_{$clean_title}:{$link['link_path']}", which means they now also contain the link title to disambiguate them from other menu links.
This makes duplicates less likely, but does not fully avoid them.

The implementation contains some BC logic to allow already-exported menu links to keep the old-style identifier.
The BC logic has some problems, see #3075693: Menu link identifier logic is confusing.

Further changes proposed since Oct 2013

Problem with parent identifier - #77:
The logic to compute the parent identifier is slightly different than for computing the identifier for the item itself. This can cause a broken hierarchy when importing the links from the feature.
Let's follow up in #2644586: Wrong parent_identifier created for menu items.

Identifiers still not unique enough - #86
Some people have use cases where even the link titles of multiple menu links are identical.
Comment #91 by @david_garcia contains a proof-of-concept patch which adds a uuid to menu links.

This should be discussed in a follow-up, if someone is still interested.

Changes from other issues since then

https://git.drupalcode.org/project/features/commits/22a216141003451e56c8...
* f260688f Issue #2353585 by mattsqd, imre.horjan, hswong3i, joseph.olstad: UUID export and import of menu items linking to nodes, terms and users
* 65b07cae Issue #2385853 by claudiu.cristea, YesCT, MustangGB, rclemings: menu link shows as overridden: options identifier showing in default, not in overrides
* 4e912791 Issue #2931464 by oadaeh, DamienMcKenna, pfrenssen, dsnopek: Features PHP 7.2 Function create_function() is deprecated
* a8b9dc5a Issue #2568161 by pfrenssen, Dane Powell: Coding standards of exported items
* 938a7c52 Issue #2509022 by eugene.ilyin: Undefined index in menu_links_features_rebuild_ordered
* 38b22da7 Issue #1231118 by arnested, tim.plunkett, nielsonm, jhedstrom, mariacha1: Generate code according to coding standards
* 09aa829b Issue #2216371: also fix the issue that this bug was about (make sure items with parents not in feature are included)
* e2a4e423 Issue #2216371: Fix regression where child weight was not being set correctly
* e417cd6e Issue #2155351: features_menu_link_load considers two different links to be the same.
* 4b6ac568 Issue #2216371 by maijs: Menu links are not being restored if their parent menu links are not stored in Features
* 8d476a85 Issue #1931512 - restore missing tag
* ffb97cc8 Issue #2155945 by idebr: Strict warning: Only variables should be passed by reference in menu_links_features_export_render
* 6fdb67b8 Issue #927576 by ipouw, jweowu, kenorb, mpotter, hefox: Fixed Menu links not set as customized, revert when menu rebuilt.

Relevant follow-ups

#2644586: Wrong parent_identifier created for menu items
#3075693: Menu link identifier logic is confusing
Yet to be created: Follow-up to further disambiguate menu links with same path, title and menu name.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

gmclelland’s picture

I am experiencing this as well. The menu item has to have a unique path for it to be able to work.
Subscribing

ericbroder’s picture

+1 for this issue. Having the same path appear multiple times in a menu is a very common feature request, but unfortunately Features does not currently support it. This would make a great addition if anyone has time to work on it!

Grayside’s picture

The combination of parent menu path + parent + menu title might do the trick for a unique identifier. That would be really unwieldy for general use, maybe the extended identifier should only be used after the first instance of a given menu path?

hefox’s picture

The issue with menu link title that is that if you change the menu link title, it will not recongize it as the same menu link so there will possible be issues with updating (changing mlid, not overriding the previous, etc.). Also, a user may want to user the same menu title (=.=), but doubt it.

Hm, a quick idea; I think extra data can be stored in options (I think purl does this), so features could form alter a machine name field easily into the menu link form, and this could easily be auto-generated, or perhaps only used for this edge case (ie machine name/extra identifier only needed when needing this and otherwise ignored). That would likely be the most full proof.

I went through a lot of thought on this originally, and the most thought about the various machine names that could be used, and I remember rejecting all of them cause someone *might* want to have them the same for whatever reason. However, with a custom field uniqueness could be enforced

Grayside’s picture

Same Path + Same Title + Same Parent + Same Weight is a possible scenario, but it strikes me as a bad idea.

I suppose the bigger problem is that anyone overriding a menu link via standard menu administration would break the correlation between the link and the export. So a machine name becomes necessary.

drupal_was_my_past’s picture

Subscribe. I'm also running into this issue.

bleen’s picture

subscribing

das-peter’s picture

subscribing - same applies to D7 port

DamienMcKenna’s picture

Ditto.

DamienMcKenna’s picture

I'm running into this with a feature that adds the Contact module's menu item ("contact") to a new menu, so rather than just showing up in the Primary Links I want it to show in the My Menu menu. I managed to add the menu item to the feature and export it, but when I clear the site cache the menu item disappears & exporting the feature again removes the item (thank webchick for revision control).

In another scenario, I'm trying to add links to local menu tasks created in a View, each time I clear the cache & export the menu items are removed.

In a third scenario I'm adding a link to a MENU_NORMAL_ITEM menu item created in another module via hook_menu(), again it disappears from the feature once the cache is cleared.

hefox’s picture

DamienMcKenna’s picture

@hefox: thanks. I've applied patches from #910604, #931782 and #927576, locally it's working fine now but on the dev server its still loosing the menu links. Gah.

DamienMcKenna’s picture

Ok, after leaving it to sit overnight, and clearing the caches again, the dev server is working. The combination of the patches mentioned above seem to have solved the problem.

ericbroder’s picture

The patches mentioned in #12 do not fix the issue for me.

hefox’s picture

The patches mentioned are for unrelated issue that DamienMckenna had mentioned in the thread earlier.

This issue is active and there has been no patches yet to address it, though there has been discussion on how to do it (above).

stovak’s picture

This fixed it for me:

/**
* Callback for generating the menu link exportable identifier.
*/
function menu_links_features_identifier($link) {
if (isset($link['options']['query'])) {
return isset($link['menu_name'], $link['link_path']) ? "{$link['menu_name']}:{$link['link_path']}?{$link['options']['query']}" : FALSE;
} else {
return isset($link['menu_name'], $link['link_path']) ? "{$link['menu_name']}:{$link['link_path']}" : FALSE;
}
}

Then add add "query" option for each menu item that's pointed to a duplicate node/URL. eg: node/11?blah=blah1

Thoughts?

Grayside’s picture

Embedding a meaningless serial identifier in the query string is pretty sloppy, but it does allow you to keep track of the menu item in a way which will be preserved even when menu items are reordered. I wouldn't want to have all exported menu items show up that way though...

hefox’s picture

The query string (or link title, etc.) is not necessarily the distinguishing factor; it'd solve somepeople's issues, but not everyone's. Considering dealing with features, which get exported, should probably not muddle it up with something that will likely need to be changed later.

Grayside’s picture

hefox: I think the idea is that the querystring is programmatically added to the actual link so it is stored as part of the object, and then manually left alone by menu administrators forevermore. Too messy to run with, IMO, but doable if you are desperate.

dkingofpa’s picture

sub

codekarate’s picture

I am experiencing this same issue.

gdl’s picture

Another use case for this involves exporting menus with multiple items with the same link_path, but with a different language set for each link. These menus are piped through i18nmenu_menu_navigation_links before they are displayed to strip out the items not in the current language.

As an example, there are six languages enabled on a site I support, and each link_path in the primary links menu can appear in from one to all of those languages. When I try to export the primary links, I'm presented with the option of saving only one of the various menu links with a given link_path. Generally, these options are in several different languages, so I can't export all of the menu links in a single language.

It would be great if Features could support multiple link_paths in an export, and even better if it could deal with i18nmenu and its menu_link_altering ways. Alternately, it would be great to just get all of the menu items for a single language, perhaps just the default, or the current language.

For even more possible implementation complexity, while the menu link titles all appear to be unique, I doubt they are guaranteed to be. The site has several Romance languages enabled, and there are link titles that are a single letter, or single accent different.

One other option would be to not support this style of multi-language menus, but only support the single-language style described in http://drupal.org/node/313302. Which has the added benefit of already being done!

Thanks for all of the hard work on Features!
-G

coderintherye’s picture

Sub in hopes that if the fix is found in 6 can create a fix in 7

alberto56’s picture

Subscribing, and confirming this is still an issue in 7.x-1.x-dev. Thanks for your work.

hefox’s picture

Version: 6.x-1.x-dev » 7.x-1.x-dev

I'm going to move this to 7 as it seems significantly big, and when fix is found there, try and backport it.

alberto56’s picture

Here is a workaround I am using: http://mediatribe.net/en/node/47

jdleonard’s picture

subscribe

nmc’s picture

subscribing

fboulais’s picture

Subscribing

Dean Reilly’s picture

subscribe

Dean Reilly’s picture

I solved this issue for the 6.x branch by generating UUIDs for each of my menu items and using those as the export keys. You can take a look at my code here #1283742: UUIDs for Menu Links.

emackn’s picture

Assigned: Unassigned » emackn

From the thread, it looks as though the two possible solutions are to :
* further specify the url path with parent, weight (which doesn't guarantee uniqueness, but would provide a work around)
* or wholesale into uuid.

I think uuid is the right answer, but it has a much longer path to becoming stable, with both uuid and feature uuid integration at an infant stage.

So I would lean toward further specifying the menu with a weight for now.

Any thoughts on these avenues?

coderintherye’s picture

I agree that UUID has a long way to go before becoming usable, though it would seem like the best long-term solution. Makes me want to go take a look at what is holding up UUID (asides the fact that alpha2 fucks over installs of alpha1, thus discouraging further testing).

Dean Reilly’s picture

The problem with using fields which the user may want to change to identify the links is that if they do change any of them the export key changes. If we follow the same implementation as is currently used of exporting individual links it means that when features is used to deploy a change to a link the original link will actually remain and the updated link with it's new key will also be added. Either additional code will need to be added to the .install by the developer to remove old links (but at that point she could just be writing code to update the link).

I think UUID is the optimum solution and would like to see it adopted more to try and drive more support to development of the UUID module.

However, there are some other alternatives. We could allow links to have machine names set as hefox suggests in #4. I actually started off with this idea so could dig my implementation out of the CVS if anyone wants to take a look at it. It worked by using the path of a menu as the key unless a machine name was set so that you wouldn't have to a machine name for each and every link. I still decided this seemed a little labour intensive though and having two different types of identifiers seemed a little unclean which is why I ended up going with UUID.

Another solution would be not to allow individual links to be exported but only export entire menus at a time. We then don't have to worry about export keys at all. I think situations where a developer wants to export only a portion of a menu are definitely in the minority but I would prefer not to lose this functionality personally. This may also make it difficult to export settings for modules which extend menu links though. Unless we came up with a way that third party modules could extend the export/import process these modules would be faced with the exact same problem of adequately targeting a menu link (although in this situation using more parameters from the link would probably cause fewer issues.)

emackn’s picture

something that struck me this morning is to use of the menuid indirectly. Couldn't we created a hashed value of title/link/menuid and use that as an identifier for export?

Dean Reilly’s picture

Hashing doesn't really help (apart from maybe giving us a string which is a bit nicer to deal with). The inclusion of the menu id would certainly avoid the uniqueness issue you flagged in #32 and the inclusion of the title and link would probably avoid any accidental collisions when moving the features to another server. The downside is that this implementation would suffer even more from orphaned links that I mentioned in the first paragraph of #34 as not only would the id change whenever you changed the link or menu title but if the menu link is rebuilt (as it gets given a new mlid). I couldn't be sure without testing it but I think the use of the mlid could lead to a lot of nasty side effects.

Unless you mean this hash is built at the beginning and is attached to the menu link and never recalculated. This is basically what the code I posted above does but uses uuid to generate the identifier rather than a hash of the link. A hash would work but given the similarity in the approaches and the fact drupal is moving towards using UUID more and more I think I would still go with UUID.

One argument you could make in favour of the hash approach is that features may be able to use the hash to identify links on a server that existed prior to the feature being built so you avoid duplicates although similar functionality could be added to the uuid generation code. I've also not thought through every scenario enough to be sure that this is a feature you would necessarily want and might not, in fact, get in the way in some situations.

Dean Reilly’s picture

Oops looked like I may have been mistaken in my first paragraph of #34. For some reason I thought the patch from #927576: Menu links not set as customized, revert when menu rebuilt had already been committed but it hasn't so any old links no longer in the feature would disappear once the menu was rebuilt.

You would still, however, get some weird behaviour from having an identifier based on fields a user may want to change though. For example if a link was edited causing it's id to change when the menu is rebuilt features would add the original link in again with the original id. This could then be disabled (although I'm not sure if this would revert as well once the menu is rebuilt a second time) but it isn't ideal behaviour.

dealancer’s picture

Solving this issue is also important for:

a) features support for Menu Token module. In menu_token-7.x-1.0-alpha3 placeholder used for path, while real tokenized is stored in the options field.

b) For multilingual websites there could be two menu items in the same menu with the same path and title.

betz’s picture

subscribing

bleen’s picture

betz: there is no longer a need to leave a "subscribe" comment. Instead, please use the green "follow" button at the top of the issue queue

timbrandin’s picture

Status: Active » Needs review
FileSize
5.58 KB

Could someone verify this patch as a solution, whilst we wait for UUID to get crackin.

timbrandin’s picture

FileSize
709 bytes

SORRY, staging all other files is something one might consider. :S

wjaspers’s picture

Interesting approach, although I don't know how it would behave if that mlid already exists. Would features overwrite the current one in the existing menu?

timbrandin’s picture

Status: Needs review » Active

Going to work on this today.

The idea is to store the first mlid the menu item had somewhere on each item.
So I can get recognize it again when rebuilding.

timbrandin’s picture

I propose we use these identifiers instead:

"{$link['menu_name']}_{$cleantitle}:{$link['link_path']}"

And let $cleantitle only contains lowercase letters, numbers and dashes.

Output in the UI would then be:
navigation_add-content:node/add
navigation_compose-tips:filter/tips
toolbar_create:<nolink>
toolbar_clear:<nolink>
toolbar_remove:<nolink>

Instead of:
navigation:node/add
navigation:filter/tips
toolbar:<nolink>

This will make links in the UI more helpful to understand which link is which, and also add some uniqueness to the links; allowing for multiple links with same path but different link-title, which is used for example in a toolbar menu that only does javascript actions (using as a path on all these links). Another use case of multiples is when using or as a path to either separate or group the links.

I'm working on a patch, and I will post it here later.
// T

timbrandin’s picture

Status: Active » Needs review
FileSize
21.76 KB

Here's a possible solution.

Not sure if I created the patch in the correct way you should do it. Tell me otherwise if something is missing.
And if anyone could test if it works, would be great.

Anyway here's the problems I've solved in the patch:

  • Multiple links with same path is working.
  • link_path-change is tracked, now only do a rebuild and the new path is updated to code.
  • link_title-change works as expected, do a rebuild to capture the new title to code.
  • Backward compatibility with links of old style identifier: menu_name:link_path.
  • Reverting works as expected.

How I solved this:
First I've re-done the identifier to be a little bit smarter and unique, using the title.
- This will also make it easier knowing which link is which for users using the UI; i.e. when the title is visible in the added components to the right.
Secondly to find the link again after the link_title or link_path have changed; I had to make the links remember it's previous identifier using the options array in each link.

Notice: I've also corrected some documentation spelling in features.api.php

I hope this solves the issue.
// T

timbrandin’s picture

Removed some old unnecessary $_SESSION, which I thought I had to use it, but solved it in another way.
Here's the new patch, cleaned up and tested on multiple setups.

Dublin Drupaller’s picture

thanks Tim. that patch wouldn't work for me I'm afraid.

pianomansam’s picture

Patch seems to be working for me.

acouch’s picture

Great work TimBrandin. #47 worked for listing but not exporting (at least with drush) so I rerolled and made a few fixes. I had to manually add the patch since it failed against the latest dev version so I couldn't provide a good interdiff but the main change I made was to change how the variables for the new identifier format are parsed in the features_menu_link_load() function.

I didn't grok this, just re-applied and got it working for me so this should get some testing before it is RTBC.

paulmckibben’s picture

Status: Needs review » Needs work

I applied the patch from #50 above. It did not work quite correctly for me. I defined two nodes and a 3-item menu as follows:

-- First (Node 1)
---- Child (Node 2)
------ Grandchild (also Node 2)

Grandchild is a child of Child, but both links point to the same node.

When I installed the feature, it did create the two nodes and three menu links. However, the hierarchy was not preserved. I got:

-- First (Node 1)
---- Child (Node 2)
-- Grandchild (Node 2)

First and Grandchild were at the same level upon installation.

richsky’s picture

Hmm #50 still not working here, but I'm also trying to export "special_menu_items" in two different languages that uses the path <nolink>.

chris.smith’s picture

Having difficulty applying patch 50 to 7.x-1.x-dev. Patch is failing.

chris.smith’s picture

Spoke too soon. Ignore this:

Probably not the most elegant solution, but #42 worked in our simple use case.

kmonty’s picture

Assigned: emackn » Unassigned
timaholt’s picture

Patch on #50 worked for me on 7.x-2.0-beta1

pixelula’s picture

Thanks for the Patch. I applied the patch on #50 in 7.x-2.0-beta1 and worked, but the items was created with parent item to the menu's root. The menu item doesn't was created with correct parent item configuration.

JvE’s picture

I created a sandbox here for the module I use to export and import menu links with Features.
It uses a UUID but does not depend on or integrate with the UUID module.
It adds an independent component that becomes available as alternative to menu_links so exisiting features are not affected and manual action is required to move links from menu_links to exportmenuitems.

snipebin’s picture

Just tested JvE's sandbox module provided on #58 on my local machine.

my use case was the following (Features version 7.x-2.0-beta1):

- Team members and I had the same menu in our installations, already exported through a feature
- I updated two menu items which were previously pointing to distinct paths to point to the same <nolink>
- I followed the instructions provided on the sandbox module :

Install module
Go to rebuild your feature
Select all menu links you need under "Menu items (exportmenuitems)"
Remove those menu links from "Menu links (menu_links)"
Download/generate your feature

- Team member got the updated feature code and reverted the feature, resulting in the creation of two new menu items for those that changed.

So we just had to delete the older menu items and everything has been fine after that. We've actually chosen to counter duplication propagation by deleting all menu links in the relevant menu with a hook_update_N:

/**
 * Enables the exportmenuitems sandbox module (http://drupal.org/sandbox/Kender/1935964),
 * deletes all links on outerbanks menu to then be rebuilt by feature reversion, now using uuid system given by exportmenuitems 
 * 
 */
function vrre_utils_update_7008(&$sandbox) {
  module_enable(array("exportmenuitems"));
  menu_delete_links("menu-outer-banks-area");
}

- Changed a path on another random link in the menu, updated feature with drush
- Team member reverts the updated feature, menu link is updated correctly, without duplication

So far so good, thanks JvE!

UPDATE: We've been using this process with the exportmenuitems module in a distributed development environment with several devs and it has worked great. We're using http://drupal.org/project/menu_attributes, and all configuration is exported as expected.

patcon’s picture

Just looking at JvE's sandbox module, and wondering if there's any plan for it to become a full project or be pulled into a full project. Looks cool though :)

JvE’s picture

Thanks.
No, no plans for making it a full project. I feel this should be correctly handled by the Features module.
Unfortunately due to the way menu items exist in drupal it's going to be nigh impossible to get a definition of "correctly" that everyone agrees on.

Of course the Features maintainers are most welcome to use my implementation in their project, but I'm sure there are drawbacks to my approach as well.
Some edge cases may not work well and I find it difficult to create full test coverage.

AlfTheCat’s picture

On a fresh install the sandbox module from #58 didn't work for me.
After the feature installed, all the menu links were marked as "overridden".
I also couldn't revert the menu items component, they remained overridden.

Also, menu links included as a single link (so not the same link twice in the same feature) didn't work for me.

This issue is about to celebrate it's third birthday, btw :(

Edit: -- cried too soon, was using 1.x version of features. Will post back after I test 2.x

Edit 2: -- almost the same result with feature 2.x. On clean install, feature containing the same link twice fails to install the second link, ends up overridden and I'm unable to revert it. Only difference now is that the feature containing just one link does succeed in placing that one in the main menu.

JvE’s picture

@AlfTheCat: Make sure you have removed the links from "Menu links (menu_links)" and added them to "Menu items (exportmenuitems)" in your feature. The module does not change the existing menu links functionality, but adds an alternative.
If you still have issues with that sandbox module, you can report them in the issue queue for it.

andrewsuth’s picture

The logic of how Features associates menu items to their parent to me seems flawed.

Rather than using the node path of the parent, shouldn't it use the menu item id of the parent?

AlfTheCat’s picture

Hi JvE,

Sorry for my late reply, and yes, I had moved the exports from menu_links to exportmenuitems. I will have to revisit it later, for I've been with this issue for a long time and already designed my current project with the thought of 2+ menu item exports not working so I have to give priority to other tasks. However, I do hope it will one day work and after finishing up some stuff I'll definitely be back with this issue.

In my case however, what I tried to do was add menu items from the drupal admin menu to another sub tree of the admin menu, where they were included in the same feature that installed the admin_menu module. Perhaps that is a bit too much to hope for and I'd better separate those links in a different feature.
The reason I'm doing it by the way, is because I use the module contextual_admin, which basically allows you to extend the admin menu and have admin pages easily included in your feature. Next to those (content, taxonomy and users) admin pages, I wanted to have a few links pointing to settings too. But again, I know already from the past years that that won't really work.

Thanks anyway!

acouch’s picture

I re-rolled #50 as well as made a few changes. I've tested this in several scenarios and it worked both for newly exported links and is also backwards compatible with the previous way of identifying menu_links. It maintains 'parent_path' for menu_link features exported before this patch and uses identifier and parent_identifier for newly exported menu_links.

acouch’s picture

Status: Needs work » Needs review

Updating status.

mpotter’s picture

Status: Needs review » Needs work

andrewsuth: it cannot use the menu_id because that is not a unique value. On a different site it might conflict with an existing id. That's the whole problem with anything that uses sequential ids rather than uuids (like menu items). That is why it uses the link url instead.

In any case, trying to bounce the automated tester to get this patch tested. Something this major needs to pass testing and also have some backwards compatibility tests in order to get into an rc-release. Otherwise this will need to wait till the next beta cycle.

acouch’s picture

mpotter, let me know if / how I can help out with the testing.

mpotter’s picture

Version: 7.x-1.x-dev » 7.x-2.x-dev
Status: Needs work » Needs review

re-queue the test on 2.x-dev

spotzero’s picture

Patch #66 applied cleanly to the 2.x branch and worked for me.

mpotter’s picture

Not sure why the automated tester keeps ignoring this, so let's post a new patch and try it.

jemond’s picture

The patch in #66 applied cleanly and fixed the issue for me.

mpotter’s picture

Status: Needs review » Fixed

This patch was applied in commit afa91335e. Sorry for combining two patches in one commit, but seems to be working fine.

ThomasH’s picture

Status: Fixed » Active

This is not solved. I am still having issues after applying this patch/upgrading to latest development environment.

Setup 1

Structure in feature:
Property /property
> Oakland /property/oakland
>> Current developments /property/oakland/current
> Oklahoma /property/oklahoma
>> Current developments /property/oklahoma/current

Feature enabled structure:
Property /property
> Oakland /property/oakland
> Oklahoma /property/oklahoma
>> Current developments /property/oklahoma/current

Setup 2

Structure in feature:
Corporate /corporate
> Business /corporate/business
>> Property /corporate/business/property
Property /property
> Oakland /property/oakland
>> Current developments /property/oakland/current
> Oklahoma /property/oklahoma
>> Current developments /property/oklahoma/current

Feature enabled structure:
Corporate /corporate
> Business /corporate/business
>> Property /corporate/business/property
>>> Oakland /property/oakland
>>>> Current developments /property/oakland/current

mpotter’s picture

Status: Active » Postponed (maintainer needs more info)

The code fix had some backwards compatibility in it, so it's not going to affect/change previously exported menu link features. You need to create a new feature export for these links. The new code should use keys that include both the Link and the Title.

Also, rather than trying to explain the issue in text, it's better to post the actual exported code so we can see it.

I need steps on reproducing this on a clean site before we can go back to working on this issue.

FreekVR’s picture

Issue summary: View changes
Status: Postponed (maintainer needs more info) » Needs review
FileSize
605 bytes

I am not sure the problem is the same as reported above, but I have succesfully replicated an issue with the parent identifier. The problem is that when recreating, the parent_identifier is created using the 'title' in the menu_router table. When reverting, the identifier is checked against the 'link_title' in the menu table. It is possible for these two to differ.

In my case, adding a link under the "/user" link in the user menu did not work.
User menu export:

// Exported menu link: user-menu_to-homepage:<front>
  $menu_links['user-menu_to-homepage:<front>'] = array(
    'menu_name' => 'user-menu',
    'link_path' => '<front>',
    'router_path' => '',
    'link_title' => 'To homepage',
    'options' => array(
      'attributes' => array(
        'title' => '',
      ),
      'identifier' => 'user-menu_to-homepage:<front>',
    ),
    'module' => 'menu',
    'hidden' => 0,
    'external' => 1,
    'has_children' => 0,
    'expanded' => 0,
    'weight' => -50,
    'customized' => 1,
    'parent_identifier' => 'user-menu_my-account:user',
  );
  // Translatables
  // Included for use with string extractors like potx.
  t('To homepage');

Notice how the parent_identifier is set to "user-menu_my-account:user".

The menu item "/user" has the link_title 'User account'. The title (in the menu router table) is 'My account'. Since the two differ, no match is made when reverting the feature and my link is not being added, despite the parent being present.

Attached is a patch which uses the 'link_title' from the menu_links table on recreate / render. Which results in this parent identifier:
"user-menu_user-account:user". A match on revert is made and I correctly get a menu link listed under the /user link in the right menu. It also seems correct seeing as how in "menu_links_features_identifier()" this same 'link_title' is being used for the identifier.

Status: Needs review » Needs work

The last submitted patch, 77: features-parent_identifier-927566-77.diff, failed testing.

FreekVR’s picture

Status: Needs work » Needs review
FileSize
613 bytes

Should apply now.

sherakama’s picture

Status: Needs review » Reviewed & tested by the community

Patch in #79 applies and works for me. Marking as RTBC.

Thank you very much.

FreekVR’s picture

Priority: Normal » Major

Any chance to get this commited? Running features 7.x-2.2 we're now getting a ton of errors for links which do not have a correctly defined identifier:

Undefined index: main-menu_news:news in                 [notice]
menu_links_features_rebuild_ordered() (line 325 of
/var/www/xxx/sites/all/modules/contrib/features/includes/features.menu.inc).
php: Notice: Undefined index: link_path in user_menu_link_alter()    [notice]
(line 1889 of
/var/www/xxx/htdocs/modules/user/user.module).
php: Notice: Undefined index: link_path in user_menu_link_alter()    [notice]
(line 1895 of
/var/www/xxx/htdocs/modules/user/user.module).
[drush] PDOException: SQLSTATE[23000]: Integrity constraint violation: 1048 Column &#039;link_path&#039; cannot be null: INSERT INTO {menu_links} (menu_name, plid, link_path, hidden, external, has_children, expanded, weight, module, link_title, options, customized, updated) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5, :db_insert_placeholder_6, :db_insert_placeholder_7, :db_insert_placeholder_8, :db_insert_placeholder_9, :db_insert_placeholder_10, :db_insert_placeholder_11, :db_insert_placeholder_12); Array
    [drush] (
    [drush]     [:db_insert_placeholder_0] => navigation
    [drush]     [:db_insert_placeholder_1] => 0
    [drush]     [:db_insert_placeholder_2] =>
    [drush]     [:db_insert_placeholder_3] => 0
    [drush]     [:db_insert_placeholder_4] => 0
    [drush]     [:db_insert_placeholder_5] => 0
    [drush]     [:db_insert_placeholder_6] => 0
    [drush]     [:db_insert_placeholder_7] => 0
    [drush]     [:db_insert_placeholder_8] => menu
    [drush]     [:db_insert_placeholder_9] =>
    [drush]     [:db_insert_placeholder_10] => a:0:{}
    [drush]     [:db_insert_placeholder_11] => 0
    [drush]     [:db_insert_placeholder_12] => 0
    [drush] )
    [drush]  in menu_link_save() (line 3134 of /var/www/xxx/htdocs/includes/menu.inc).
    [drush] Drush reported an error.
Rob C’s picture

Reroll for drush make. (fix 'patch unexpectedly ends in middle of line')

joelpittet’s picture

Thanks @Rob C, still RTBC.

eMuse_be’s picture

Same issue as FreekVR

ron_s’s picture

Thank you for everyone's efforts on this patch. @hefox originally said:

Also, a user may want to user the same menu title (=.=), but doubt it.

Yes, the patch works really well if the titles are unique. However we have a situation where a client wants a "Donate" link on the top level of the main menu, and also wants a second "Donate" link to be shown as a child of a separate menu item.

Same menu, same path, and same link title... but different menu items. If we try to add all menu items to the feature, it rejects the second "Donate" menu link. The same problem also exists with the Special Menu Items module (https://www.drupal.org/project/special_menu_items), as discussed in this issue: https://www.drupal.org/node/1355088. Special Menu Items causes sites to have <nolink> and <separator> menu items with the same identifiers (for example, main-menu_hr:<separator>).

It really seems as though the identifier needs to be more unique than it currently is if it's going to work in these other use cases.

Just tossing out an idea... would it be possible to run all menu links in the feature through features_clean_title, store the results, check for matches when processing the link in the menu_links_features_identifier function, and then add "--1", "--2", etc. as a suffix if it finds matches? Not sure if this type of approach might have other conflicts.

ron_s’s picture

Status: Reviewed & tested by the community » Needs work
FileSize
28.5 KB

Looking at this a bit further... #82 resolves the unidentified index errors for custom menu items. However, it creates a problem for navigation menu items generated by Drupal.

As an example, we have a custom content type called "event," and we want to include the "node/add/event" navigation menu item in our feature. If we do not include patch #82, everything works as expected. If we do include patch #82, the feature is always shown as overridden. Even if we attempt to recreate the feature, it is still shown as overridden.

The diff when #82 is applied is shown in the attached image. If we remove the patch and recreate the feature, it no longer displays as overridden.

ron_s’s picture

After additional review, it seems as though #82 is not causing the problem. However, there is certainly an issue with the menu_name/link_path generated for navigation menu items.

It's very odd behavior -- this is what happens:

  1. Menu link "navigation: ---- Event" is selected in the feature, corresponding to "node/add/event."
  2. Feature is regenerated.
  3. Once regeneration is complete, Event feature page is reloaded. Menu link "navigation: ---- Event" is still selected.
  4. Reload Manage Features page, and Event feature has a state of "Default."
  5. After some time passes, return to the Manage Features page, and event feature is now shown as "Overridden" (even though no changes have been made to the site or features).
  6. Open the Event feature, and "navigation: ---- Event" menu link has disappeared; it is no longer selected.
  7. Diff displays information shown in picture attached to #87.

Maybe it makes sense to post these as separate issues?

david_garcia’s picture

Same thing if there are two or more menu links with the same combination of PATH+NAME+LANGUAGE.

Language key should be included in the item's identifier.

david_garcia’s picture

Adding support for language means adding another "layer" of backwards compatiblity, it is already a complete mess, and it will get messier.

david_garcia’s picture

I just uploaded a proof-of-concept patch.

Backwards compatiblity is not implemented yet (but everything in place to do it).

The big difference between old and new behaviour is that now it truly generates unique identifiers for menu items, so once exported from a system there is a 1-1 match without any confussion. And no matter what combination of path, language, title or whatever the menu link has this will work.

mpotter’s picture

Priority: Major » Normal
Status: Needs work » Needs review

Would be good for somebody to summarize this old and long issue. The patch in #82 seemed simple and clean but potentially had issues (although in #88 it was said that the issue wasn't from this patch).

So is the patch in #82 still something we want?

How did it go from simple to so complex in #91. Definitely will need a *lot* more review of that. Marking this as "needs review" to trigger the testbot.

Status: Needs review » Needs work

The last submitted patch, 91: 927566-features-inconsitent-menu-import-export.patch, failed testing.

david_garcia’s picture

@mpotter The refactor in #91 was to put some sanity in something that has been patch over patch to cover new cases - while still preserving backwards compatiblity.

#91 is not finished, there's like 7 TODO's in the file, all backwards compatibility related, it's just a starting point (we are using it for everyday work regarding that we have got nothing old to maintain backwards compatibility with).

mpotter’s picture

Was wondering though if the simple patch in #82 works for most cases and is worth committing while a more comprehensive solution is found. #72 was already committed, and #82 seems like a minor fix/tweak to that patch. I hate to lose the work people here did on that and wonder if your #91 needs to be a separate issue?

claudiu.cristea’s picture

#82 is not fixing the problem for me.

scorchio’s picture

#82 is not working for me either.

MustangGB’s picture

Status: Needs work » Reviewed & tested by the community

Just thought I'd say that I've been using #82 for more than 6 months, I can't recall exactly the problem I was hitting, but it definitely solved it for me, so whilst it may not be the endgame for all circumstances perhaps these should be dealt with in follow-up issues anyway, at least it still seems like a step in the right direction to be going on with.

mpotter’s picture

Status: Reviewed & tested by the community » Needs work

I don't think we can mark this RTBC when people in #96 and #97 say it's not working for them.

Can people who say "its not working" please provide more details on their specific problems?

brunodbo’s picture

Confirming #98: patch in #82 fixes this issue for me.

ibuildit’s picture

#82 does not work for me, I don't experience any additional error apart from the original one - links missing in features create

Ronino’s picture

I think #82 is unrelated to the original issue as it "only" creates a parent_identifier from the correct title. I found the same fix in #2644586: Wrong parent_identifier created for menu items to make an extra "admin" link in the main menu work for me (the wrong title "Administration" from the original item in the management menu was used for the parent_identifier). The same scenario was described in #77.

I'm running features 7.x-2.7 and I can export multiple menu items with the same path and different titles in the same menu without any patches. What does not work is exporting multiple menu items in the same menu with the same path and title. Only one is possible as the identifier is currently based on menu name, title and path.

dobe’s picture

#82 seemed to resolve the issue so far for me. Since we are updating the hook_features_export_render, when testing, make sure to recreate your feature then the changes should take place.

I agree with #95. The refactoring from #91 should really be in a separate issue queue. Specially since it was incomplete to begin with.

MustangGB’s picture

Status: Needs work » Reviewed & tested by the community

As claudiu.cristea and scorchio haven't responded with more details, the re-factoring should be a separate issue, this is just a tweak to the original fix, and several other people have reported it solves the issue, I think it's time to get this committed and create some new issues for these special cases and/or re-factoring.

So going to try RTBC again.

dobe’s picture

RTBC #82

weynhamz’s picture

#82 is not working for me, same path, same title, different language, really need a unique identifier for every menu path.

kalidasan’s picture

Subscribe.

Darren Oh’s picture

Darren Oh’s picture

Darren Oh’s picture

Status: Reviewed & tested by the community » Needs work

We tested the patch in #82 with Features 7.x-2.10. Menu links with the same path in multiple menus only showed in one menu in the menu links section of the feature creation form.

Maffoo’s picture

None of the patches help at all. The one in #82 seems like it *should* work, but also seems incomplete. It generates the rows correctly in the features.info file, but otherwise doesn't actually export the data properly. I feel it could work if it were hooked up a bit more elsewhere in the module.

Maffoo’s picture

Embarrassingly, the only way I could get the links upstream is to put some bogus link path in and then change it later, like so:

foreach ($menu as $link) {
  $link['link_path'] = 'http://www.google.com/' . substr(uniqid(), -6);
  unset($link['options']);
  menu_link_save($link);
}

But it is definitely a kludge just to get the structure of the menu committed in, and is in no way a fix.

suchdavid’s picture

For a me only a dirty hack worked. Put a space at the end of one duplicated menu link, so it won't really be the same. Hopefully it won't affect the appearence of the item, but in features the identifier will be created with an extra "-" and so they won't coincide. ¯\_(ツ)_/¯

Chipie’s picture

I was able to export multiple menu links with the same path by enabling the Use tokens in title and in path. option.

tanasi’s picture

@chipie where is this setting? D7?

Chipie’s picture

@tansai, you can enable this setting when editing or adding a menu item, if the menu_token module is installed.

donquixote’s picture

Some observations:
- The menu_links component is a mess. Bugs and complexity have accumulated over time.
- This issue is a mess. Something was already committed in #72 / #74, since then we are discussing distinct follow-up problems.

I am closing this, we should continue in follow-ups where we focus on specific isolated problems.
#2644586: Wrong parent_identifier created for menu items
#3075693: Menu link identifier logic is confusing

I am not sure which type of "Closed" would be applicable here.
I think "Fixed" makes the most sense, even though there are some flaws in the solution that was committed in #72 / #74.

donquixote’s picture

Title: Menu links do not support 2+ links with same menu_name/link_path » Add link title to menu link identifiers to make them more unique.
Issue summary: View changes

Changing the title to clarify the scope of what was done in this issue.

Status: Fixed » Closed (fixed)

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