Problem/Motivation

Issues such as

#1905268: Disabled menu items
#1693074: Change menu translation approach (i18n_menu_translated_menu_link_alter() skips item subtree processing)
#1230034: Menu link disappears when publishing a node by the moderation dropdown or by the moderation view link
#1451336: Reverting a node revision deletes menu item
#1534356: Data loss - menu items unintentionally delete themselves if a node is updated via code (not via form UI) . Test case attached.
#1947340: Expire menus incompatible with Panelizer
#1247506: menu link deleted on programmatically updated nodes
#1245094: Node menu link deleted on update

are appearing because third party modules implementing this hook seem to expect it only to run upon menu link display, whereas it also runs upon saving a menu link through the node edit form. The documentation says this hook should only affect display and not loading/saving, and upon reviewing several contrib modules which use this hook, none of them seem to expect this behavior: http://drupalcontrib.org/api/drupal/drupal!modules!system!system.api.php...

This means the menu item is being altered in unpredictable ways (such as being set to "hidden"/disabled when the menu item had been explicitly enabled/"not hidden" before).

When loading the node edit form, in menu_node_prepare, menu_link_load is being called to load the existing menu link into the node object to be saved in $form_state. From there, in _menu_link_translate, hook_translated_menu_link_alter() is invoked for the existing menu link for the node, meaning the link can be unpredictably altered while it is being saved into $node->menu.

This same (altered) menu item is later saved in menu_link_save() (called from menu_node_save() when the form with the altered menu link in the $form_state is submitted).

Proposed resolution

1. Documenting the current behavior and reviewing contrib modules invoking this hook, submitting fixes to the separate modules.

or

2. Not running hook_translated_menu_link_alter() if it's being invoked from the node edit page.

Remaining tasks

User interface changes

API changes

Comments

stefan.r’s picture

Issue summary: View changes
stefan.r’s picture

Issue summary: View changes
stefan.r’s picture

Status: Active » Needs review
StatusFileSize
new621 bytes

The attached patch would be an API change but on the other hand it seems like the current behavior upon node edit is unexpected and undocumented.

stefan.r’s picture

Issue summary: View changes
stefan.r’s picture

This should skip the menu link being edited...

stefan.r’s picture

Title: hook_translated_menu_link_alter also runs upon saving nodes with menu links, not just upon menu link display » hook_translated_menu_link_alter also runs upon editing nodes with menu links, not just upon menu link display
Issue summary: View changes
stefan.r’s picture

kopeboy’s picture

Please review this, I'm tired of wasting days on duplicate translated or not translating menu links!

develcuy’s picture

Priority: Normal » Major

I'm the maintainer of Menu Token module, this patch will help 16k sites using Menu Token to prevent duplicated menu items or just broken translations. Thanks in advance!

develcuy’s picture

Status: Needs review » Reviewed & tested by the community

Status: Reviewed & tested by the community » Needs work
David_Rothstein’s picture

Version: 7.23 » 7.x-dev

Checking for the node/X/edit URL seems a little iffy to me... What if there's a link to the node being displayed somewhere else on that page, but not being edited?

Also, aren't there other ways to reproduce this => basically any time you call menu_link_load() followed by menu_link_save()?

Perhaps we need a new function, something named along the lines of menu_link_load_untranslated(), and the idea is you would call that function instead of menu_link_load() if your code is loading a menu link for the purpose of editing it rather than displaying it?

stefan.r’s picture

Status: Needs work » Needs review
StatusFileSize
new6.02 KB

@David_Rothstein yes I like that idea.

This is not only a problem on menu link save, it's also a problem in the menu parent selector (and likely all other widgets that display menu links). See #2529360: i18n_menu erroneously marks some menu links as disabled on parent link selector in node edit page. This patch passes along a parameter for those cases as well.

If we think this is the right way to go I can build a test using a test module with a hook_translated_menu_link_alter() invocation to confirm this fixes the issue.

Status: Needs review » Needs work

The last submitted patch, 13: 2136815-13.patch, failed testing.

stefan.r’s picture

Anyone willing to have a look at those test failures?

manuel garcia’s picture

Status: Needs work » Needs review
StatusFileSize
new6.43 KB

Reroll, small conflict on includes/menu.inc

Status: Needs review » Needs work

The last submitted patch, 16: 2136815-16.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

Status: Needs work » Closed (outdated)

Automatically closed because Drupal 7 security and bugfix support has ended as of 5 January 2025. If the issue verifiably applies to later versions, please reopen with details and update the version.