Problem/Motivation
Any menu link that uses the internal: URL scheme, including views, links to , and /contact, will be force-reset to the top level of its menu on cache rebuild.
Steps to reproduce:
1. Create a custom menu.
2. Create a node (or use an existing node).
3. Create a menu link, title "Parent", that points to the node from #2.
4. Create a menu link, title "Child", with parent "Parent", linked to '/contact'.
5. Confirm that Child is the child of Parent.
6. Rebuild the cache.
7. Edit your custom menu.
8. Observe that Child is now at the top level, next to Parent.
Furthermore, if you edit "Child," it still has its parent set to "Parent". If you save "Child", it will be a child of "Parent" again, until the next cache rebuild.
Screenshot - view setting specifying parent menu item:
Screenshot - main menu tree displaying all menu items at the same (top) level:
It doesn't matter what the parent menu item is. This occurs regardless of the parent item's depth -- i.e. if the parent is 3 levels deep, the view's menu item will still end up at the top level.
If you then edit the menu item directly, change nothing, and save it, it will then acquire the correct parent.
For menu links from views, the issue is compounded by the fact that views rebuilds the menus anytime any view is saved (see #941970: Only set router rebuild needed when something related to routing actually changes) so it means you're often "fixing" the menus.
This may be related to #2202493: views_menu_link_defaults() does not set a parent for links although that appears to have been fixed some time ago.
Proposed resolution
Add checks for internal/custom menu links prior to force-reset of menu items to the top.
Write tests.
Remaining tasks
Review.
User interface changes
None.
API changes
None.
Beta phase evaluation
Issue category | Bug because of the way it garbles your menus. |
---|---|
Issue priority | Critical because it results in data loss. |
Prioritized changes | The main goal of this issue is developer/site editor usability. |
Original report:
Steps to reproduce:
- Standard install.
- Create two pages and place them both in the main menu at the top level.
- Create a view with a page. Add a menu link to the view's page display, setting the parent item to the first node's menu item.
- Visit admin/structure/menu/manage/main to see the menu tree.
Expected result: The two node menu items are at the top level, with the view menu item underneath of (a secondary menu item for) the first node menu item.
Actual result: All three menu items are at the top level.
Comment | File | Size | Author |
---|---|---|---|
#43 | interdiff.txt | 3.44 KB | dawehner |
#43 | 2468713-42.patch | 7.59 KB | dawehner |
#38 | internal_custom_menu-2468713-38.patch | 6.75 KB | StryKaizer |
#38 | interdiff.txt | 3.94 KB | StryKaizer |
#30 | menu-links-rebuild-2468713-30.patch | 6.76 KB | jhedstrom |
Comments
Comment #1
dawehnerInteresting!
The problem is caused by an interested property of the menu system. It rebuilds its menu links based upon the defined menu links coming from either static menu links or views, but not from custom menu links. Given that
core/lib/Drupal/Core/Menu/MenuTreeStorage.php:164
will set the children to a link which doesn't exist,so upon save, things are totally ignored.
I think one fix would be to special case, when the parent doesn't existing in the $definitions and then somehow update the entry in the DB itself.
Moving to the menu system component, because its root problem is in the underlying menu system component.
Comment #2
rootworkYeah, I thought it might have to do with the intermixing of menu links set from nodes and menu links set from views.
Thanks for investigating this. I'll keep following this and help test patches and such if I can.
Comment #3
dawehner@rootwork
One thing we certainly will need is a test, would you be interested in writing one?
Comment #4
StryKaizerAttached you'll find a test for this issue.
Since this is only a test without a fix, the last noassert will fail until fixed.
Comment #5
StryKaizerRenamed patch to make clear this is only the test
Comment #6
rootworkThis is great, thank you. Unfortunately I probably don't have the skills to write a test, so I'm glad you have StryKaizer.
Comment #11
dawehner.
Comment #12
paulmckibbenThis problem appears to be more generic than just views. It seems to apply to any menu link that uses the internal: URL scheme, including links to <front> and /contact.
I have reproduced this issue in beta10. An easy way to reproduce this issue:
1. Create a custom menu.
2. Create a node (or use an existing node).
3. Create a menu link, title "Parent", that points to the node from #2.
4. Create a menu link, title "Child", with parent "Parent", linked to '/contact'.
5. Confirm that Child is the child of Parent.
6. Rebuild the cache.
7. Edit your custom menu.
8. Observe that Child is now at the top level, next to Parent.
Furthermore, if you edit "Child," it still has its parent set to "Parent". If you save "Child", it will be a child of "Parent" again, until the next cache rebuild.
Comment #13
rootworkInteresting, thanks for that testing. I agree that it's bizarre that the menu item still apparently has its parent item set correctly -- all it takes is re-saving the menu item and it will be correctly placed.
Comment #14
paulmckibbenWe have a patch for this issue. Please credit this patch to Nathan James (https://www.drupal.org/u/tnathanjames) in addition to myself. He did most of the work--I just provided occasional insight and testing.
Also, I'm raising the priority to major, since this issue severely corrupts menus each time the cache is rebuilt. This is untenable for anyone who uses the menu system. I'd really like to set this to Critical because D8 should not release with this bug, but I don't think it quite meets the definition for critical.
Comment #15
rootworkThis is so exciting, because this has been a MAJOR pain for me in development (and yes yes, I know, betas aren't stable and I shouldn't expect them to be).
I will test this out shortly but just wanted to say thanks so much for your work addressing this. Was this work from the sprint?
Comment #16
paulmckibbenI wish I were at the sprint. Sadly, I had to miss Drupalcon this year, though tnathanjames is there (he wrote this fix on the plane). This was to address an issue for a D8 site we're building for a client.
Comment #17
tancThank you Paul and Nathan for posting that patch. It was starting to drive me nuts and the patch seems to have fixed the issue for me. Will report back if I notice any issues.
Comment #18
rootworkConfirmed that this applies cleanly and fixes the bug. It's a beautiful thing.
Setting this to RTBC though I imagine it will have to get some reviewing by D8 component maintainers.
Comment #19
jhedstromThe patch in #14 didn't include the test from #5.
Comment #20
rootworkReroll of #14 with the test from #5 included.
Comment #21
rootworkUpdated the issue summary and title for clarity. I also added a beta evaluation, though I've never done that before so please check my work...
Comment #23
jhedstromI think this is back to RTBC now that the patch includes the test.
Comment #24
rootworkGreat!
Note @paulmckibben's request to credit the patch (from #14) to Nathan James @tnathanjames in addition to himself.
Comment #25
alexpottIt's great that we have an integration test but is it possible to test this change as part of
Drupal\system\Tests\Menu\MenuTreeStorageTest
? This is so that one test encompasses all of the functionality of the class under test?Comment #26
harings_rob CreditAttribution: harings_rob commentedStill an issue with patch.
Steps:
Comment #27
shaktikComment #28
shaktikComment #29
jhedstromI'll work on the test change.
Comment #30
jhedstromThis adds a test to
MenuTreeStorageTest
as suggested above.Comment #32
christianmgrupp CreditAttribution: christianmgrupp commentedI did not run the SimpleTest, but the patch appears to fix the problem described above on a site we are demoing Drupal 8 with.
Comment #33
bircherA related bug also exists for menu items that come from yaml files.
#2548009: Overridden menu links lose parent, expanded and enabled (are disabled) status on cache clear
The test patch from there unsurprisingly also fails with this patch, but the underlying problem is probably related.
Comment #34
paulmckibbenConfirmed that the patch at #30 fixes this issue.
(However, it does not fix the related issue linked in #33)
Comment #37
geertvd CreditAttribution: geertvd at XIO commentedThis fixes the issue but I have some small nitpicks.
"links" should go to the first line.
Can we change all these to short array notation to be more consistent with the rest of the file.
Exceeds 80 characters
Do we need t() here? This is not testing anything multilingual.
Should end with a "."
Exceeds 80 characters, should end with a "."
Comment #38
StryKaizerPatch from #30with remarks from #37 addressed in this patch
Comment #39
geertvd CreditAttribution: geertvd at XIO commentedThe changes look good, setting RTBC
Comment #40
catchThis is both views and menu so assigning to Daniel for review but tagging since pwolanin would be good on the menu bit.
Comment #41
catchAnd this is data loss every cache rebuild so bumping to critical.
Comment #42
rootworkUpdated the beta evaluation with the new priority. Thanks catch.
Comment #43
dawehnerI think the fix is the right thing to do. We still don't iterate over all stored menu links, as that would be too costly, but instead
we just care about the probably rare cases for "static" menu links, which have
The interdiff just changes some minor details + adds a bit more of documentation so the code is hopefully better to understand in the future.
Comment #44
alexpottI've tried to reproduce #26 and can't.
Committed 5cd3b68 and pushed to 8.0.x. Thanks!
Comment #48
kay_v CreditAttribution: kay_v as a volunteer commentedIssue description from #26 still occurs if you add a 2nd view:
Add a 2nd view; add it to the menu.
*Show as expanded did not appear to be an issue.
note: I have some uncertainty whether reopening this (critical) issue is the right course of action; I'm choosing to do so since from what I can tell the issue I'm seeing is in fact the same, and work on fixing it will benefit from the history logged in this issue. If someone has a strong opinion about creation of a new ticket, no problem from my perspective.
Comment #49
catch@kay_v that sounds similar, but please open a new issue linking to it from this one - can use the 'related issues' field to do so.
Comment #50
kay_v CreditAttribution: kay_v as a volunteer commentedlooking further at the issue and messing around with steps, a few things seem worth noting:
Comment #51
kay_v CreditAttribution: kay_v as a volunteer commentedthanks @catch - will open a new ticket and mark it as 'normal'
Comment #52
kay_v CreditAttribution: kay_v as a volunteer commentedclosing this issue and opening new one: #2695893: Views menu item resets position