Problem/Motivation
NavSyncManager::createChild() creates a managed child link with enabled => TRUE and saves it. It does not check the state of the link after the save.
A presave hook from another module can change that state. Publication-governance and workflow modules do this: enabled is the published key of menu_link_content, so a module that forbids the acting account from publishing can force the new link to disabled. The sync then finishes without an error and the node never appears in the menu.
updateChild() mirrors title, weight and URI only. It never looks at enabled, which is right for a link an editor disabled on purpose. It also means a link that was created disabled by a hook stays disabled on every later sync, and nothing reports it.
The same applies to renames. On a site where the acting account's saves become forward revisions, updateChild() saves a title change that does not go live, and the sync still reports nothing.
This happens when a sync runs inside a request made by a restricted account, for example an API client that updates a node while the tree is out of date.
Steps to reproduce
- Add a
hook_ENTITY_TYPE_presave()formenu_link_contentthat callssetUnpublished()for a given role. - As that role, save a published node that matches a dynamic parent's source and has no child link yet.
- The child is created disabled. Later syncs leave it disabled. No message, log entry or status shows it.
Found by reading 1.3.2. Not yet reproduced on a site.
Proposed resolution
- After
createChild()saves, reload the link. If it is not enabled, log a warning that names the parent, the node and the acting account. - Record that the link was created disabled by the save, not by an editor, in the module's own map field. A later sync by an account that may enable links can then enable it, without touching links an editor disabled.
- Show managed children that are disabled in the rebuild command output and on the parent's summary, so an operator can find them.
- Consider running the side-effect saves after the request, the way the node form already defers the sync.
Remaining tasks
- Kernel test with a test module that forces new links to disabled: warning logged, flag recorded, a later privileged sync enables the link, an editor-disabled link stays disabled.
API changes
None.
Comments
Comment #4
jmcerdaCommitted to 1.x. After a sync creates a child link the module reloads it. If another module disabled it during the save, the sync logs a warning that names the parent, the node and the acting account, and records
disabled_by_savein the link's own map. A later sync by an account that may enable links enables it once and clears the flag. A link an editor disabled is never touched, and saving the link through the form clears the flag. The rebuild command and the parent summary list managed children that are disabled. A follow-up commit covers the adoption path and skips the summary query on plain links.