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

Aeotrin created an issue. See original summary.

aeotrin’s picture

berdir’s picture

Status: Active » Needs review

Pretty sure this needs a reroll. Don't forget to set issues with patches to needs review.

Status: Needs review » Needs work

The last submitted patch, 2: loading-link-node-multiple-menus-2720331-2.patch, failed testing.

The last submitted patch, 2: loading-link-node-multiple-menus-2720331-2.patch, failed testing.

aeotrin’s picture

Thanks Berdir, I'll take a quick look at it, forgot about the needs review :(

aeotrin’s picture

StatusFileSize
new1.07 KB

Reroll of patch #2

Bambell’s picture

Status: Needs work » Needs review

[...] forgot about the needs review :(

Again ;).

Bambell’s picture

StatusFileSize
new1.45 KB

Here'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.

Bambell’s picture

StatusFileSize
new2.52 KB

Here's a combined. It's still failing, locally.

The last submitted patch, 9: node_menu_link_-2720331-9-test-only.patch, failed testing.

The last submitted patch, 9: node_menu_link_-2720331-9-test-only.patch, failed testing.

aeotrin’s picture

Thanks @Bambell. I always forget the needs review :(.
Is it still failing?

Bambell’s picture

Status: Needs review » Needs work

Yes, 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.

Bambell’s picture

Status: Needs work » Needs review
StatusFileSize
new3.32 KB
new2.76 KB

I 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 !

aeotrin’s picture

No problem. Glad I could help.

berdir’s picture

Status: Needs review » Needs work

The 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.

aeotrin’s picture

Status: Needs work » Needs review
StatusFileSize
new3.78 KB

Rerolled and updated comments

darrenwh’s picture

Status: Needs review » Needs work
+++ b/token.tokens.inc
@@ -1117,7 +1117,18 @@ function menu_ui_tokens($type, $tokens, array $data = array(), array $options =
-              $link = reset($links);
+              // Get the menu ui defaults so we can determine what menu was
+              // selected for this node. This ensures that if the node was added
+              // to the menu via the node UI, we use that as a default. If it
+              // was not added via the node UI then grab the first in the
+              // retrieved array.
+              $defaults = menu_ui_get_menu_link_defaults($node);
+              if (isset($defaults['id']) && isset($links[$defaults['id']])) {
+                $link = $links[$defaults['id']];
+              }
+              else {
+                $link = reset($links);
+              }

To prevent duplication create a new method to do as its repeated below.

aeotrin’s picture

StatusFileSize
new3.64 KB
new3.25 KB

Here is the change as per the review.

aeotrin’s picture

Status: Needs work » Needs review
berdir’s picture

Status: Needs review » Needs work
+++ b/token.tokens.inc
@@ -1204,6 +1204,28 @@ function menu_ui_tokens($type, $tokens, array $data = array(), array $options =
+ * Returns a default link for a given node.
+ *
+ * If the url exists in multiple menus, default to the one
+ * set on the node itself.
+ */
+function _token_get_default_menu_link($node, $links) {

Needs 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?

aeotrin’s picture

Status: Needs work » Needs review
StatusFileSize
new4.22 KB
new4.22 KB

Hopefully this does the trick. Updated the patch to be applied against most recent dev as well.

  • Berdir committed ed6cc7b on 8.x-1.x authored by aeotrin
    Issue #2720331 by aeotrin, Bambell: [node:menu-link] loading first link...
berdir’s picture

Status: Needs review » Fixed

sorry for the delay here. Finally committed now.

PS: The interdiff wasn't actually an interdiff.

Status: Fixed » Closed (fixed)

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