The code in token.tokens.inc where it looks up the link and generates the tokens using that link defaults to the first link in the array.
if ($menu_tokens = \Drupal::token()->findWithPrefix($tokens, 'menu-link')) {
$url = $node->urlInfo();
if ($links = $menu_link_manager->loadLinksByRoute($url->getRouteName(), $url->getRouteParameters())) {
$link = reset($links);
$replacements += \Drupal::token()->generate('menu-link', $menu_tokens, array('menu-link' => $link), $options, $bubbleable_metadata);
}
}
This poses a problem in the following scenario.
We have 2 menu's and a node is linked in each. This does not take into account what menu the node was added to on the node-edit screen. Should the priority not be on what was selected there and the manually entered link on the second menu should be used as the backup?
I propose the following fix:
- Looking up the default selected menu item for the node
- Using that link if it was returned by loadLinksByRoute()
- Fallback to reset($links) if the default was not found for some reason.
Comments
Comment #2
aeotrinComment #3
berdirPretty sure this needs a reroll. Don't forget to set issues with patches to needs review.
Comment #6
aeotrinThanks Berdir, I'll take a quick look at it, forgot about the needs review :(
Comment #7
aeotrinReroll of patch #2
Comment #8
Bambell commentedAgain ;).
Comment #9
Bambell commentedHere's a test only patch. It creates a node providing a menu link and then creates two menu links from the menu ui linking to this node. The failing test should show that the tokens are replaced with those of one of the manually created menu links.
Comment #10
Bambell commentedHere's a combined. It's still failing, locally.
Comment #13
aeotrinThanks @Bambell. I always forget the needs review :(.
Is it still failing?
Comment #14
Bambell commentedYes, it's currently randomly failing for me, but that is because your code is only called for chained tokens and I'm testing for [node:menu-link], if I test for [node:menu-link:title], for instance, it's consistently green. Well, I'm not sure why it's randomly failing, but it explains why it should fail. So it's all good, except for (non-chained) menu-link token. I'm currently working on a fix.
Comment #15
Bambell commentedI refactored / compacted the code and duplicated it in the logic for [node:menu-link]. I ran the test a couple times and it looks all good to me now. Thanks for reporting this issue @aeotrin and for working on it !
Comment #16
aeotrinNo problem. Glad I could help.
Comment #17
berdirThe problem is that the fix assumes that the expected link is the one in the default menu, but there is no gurantee that this is correct. I guess respecting it is more correct than not doing that and we follow the same logic as the UI now.
Given that, I'm fine with this change, but lets document it a bit better. Basically something along the lines of ensuring that we pick the same menu link as the UI would, to be consistent with that.
Comment #18
aeotrinRerolled and updated comments
Comment #19
darrenwh commentedTo prevent duplication create a new method to do as its repeated below.
Comment #20
aeotrinHere is the change as per the review.
Comment #21
aeotrinComment #22
berdirNeeds proper @return and @param documentation as well as NodeInterface and array type hints.
Still not sure about the use of "default" menu link, maybe we should go with something like "_token_menu_link_best_match()" or so?
Comment #23
aeotrinHopefully this does the trick. Updated the patch to be applied against most recent dev as well.
Comment #25
berdirsorry for the delay here. Finally committed now.
PS: The interdiff wasn't actually an interdiff.