I have a site with a menu structure like so:
- a
- b
- 1
- 2
- c
- 1
- 2
Now lets say that I have a node that both b2 and c2 point to (I'll call it node/4). When the user clicks either link, I want the site to display as a click on c2. That is to say that the main menu item for c should be highlighted, and the secondary menu for c should be displayed. And of course, the content of node/4 should be visible.
What actually happens is that the node/4 content is displayed, but both b & c main menu items are highlighted and the secondary menu for b is displayed.
I've investigated, and found the menu_link_get_preferred
function in core/includes/menu.inc. This function builds a list of candidates that can match the current path, and places them into an array keyed like this:
$candidates[MENU_ITEM_LINK_PATH][MENU_NAME]
My problem is that I have two link candidates that match the same exact criteria:
$candidates['node/4']['main']
and so I cannot control which one ends up in the candidates array. Ideally I would like to have a way of flagging the c2 link so that it was not treated as a candidate. I had thought that this would make a good module, but I cannot see a way of interrupting the execution of the function.
The bit of code I would like to alter is (D7 version, D8 is very similar):
// Sort candidates by link path and menu name.
$candidates = array();
foreach ($query->execute() as $candidate) {
$candidate['weight'] = $candidate['link_weight'];
$candidates[$candidate['link_path']][$candidate['menu_name']] = $candidate;
// Add any menus not already in the menu name search list.
if (!in_array($candidate['menu_name'], $menu_names)) {
$menu_names[] = $candidate['menu_name'];
}
}
In an ideal world I would have added an extra field to the database, so that a $candidate would be discarded on a certain flag. Any ideas how I could achieve this?
menu_link_get_preferred
does not sort it's results. If two items match the same paths, it will just return the first result returned by the database (so you can workaround this by ensuring the menu you want was added first in the database, but that's not a sustainable way of addressing this). There is an ongoing issue about this: drupal.org/node/1649062