Currently, hook_menu_link_defaults()
has the following documentation:
/**
* Alter links for menus.
*
* @param array $links
* The link definitions to be altered.
*
* @return array
* An array of default menu links. Each link has a key that is the machine
* name, which must be unique. By default, use the route name as the
* machine name. In cases where multiple links use the same route name, such
* as two links to the same page in different menus, or two links using the
* same route name but different route parameters, the suggested machine name
* patten is the route name followed by a dot and a unique suffix. For
* example, an additional logout link might have a machine name of
* user.logout.navigation, and default links provided to edit the article and
* page content types could use machine names node.type_edit.article and
* node.type_edit.page. Since the machine name may be arbitrary, you should
* never write code that assumes it is identical to the route name.
*
* The value corresponding to each machine name key is an associative array
* that may contain the following key-value pairs:
* - title: (required) The untranslated title of the menu link.
* - description: The untranslated description of the link.
* - route_name: (optional) The route name to be used to build the path.
* Either a route_name or a link_path must be provided.
* - route_parameters: (optional) The route parameters to build the path.
* - link_path: (optional) If you have an external link use link_path instead
* of providing a route_name.
* - parent: (optional) The machine name of the link that is this link's menu
* parent.
* - weight: (optional) An integer that determines the relative position of
* items in the menu; higher-weighted items sink. Defaults to 0. Menu items
* with the same weight are ordered alphabetically.
* - menu_name: (optional) The machine name of a menu to put the link in, if
* not the default Tools menu.
* - expanded: (optional) If set to TRUE, and if a menu link is provided for
* this menu item (as a result of other properties), then the menu link is
* always expanded, equivalent to its 'always expanded' checkbox being set
* in the UI.
* - options: (optional) An array of options to be passed to l() when
* generating a link from this menu item.
*/
function hook_menu_link_defaults_alter(&$links) {
// Change the weight and title of the user.logout link.
$links['user.logout']['weight'] = -10;
$links['user.logout']['title'] = 'Logout';
}
And dblog module adds a new item at the following code:
/**
* Implements hook_menu_link_defaults_alter().
*/
function dblog_menu_link_defaults_alter(&$links) {
if (\Drupal::moduleHandler()->moduleExists('search')) {
$links['dblog.search'] = array(
'title' => 'Top search phrases',
'route_name' => 'dblog.search',
'description' => 'View most popular search phrases.',
'parent' => 'system.admin_reports',
);
}
return $links;
}
Problem is, since the above array does not define $links['dblog.search']['machine_name'], the menu link is saved like the following:
*************************** 2. row ***************************
menu_name: admin
mlid: 62
uuid: 03c5fb18-290e-4c50-9c04-4a14903bc478
machine_name: NULL
plid: 45
link_path: admin/reports/search
langcode:
link_title: Top search phrases
options: a:1:{s:10:"attributes";a:1:{s:5:"title";s:33:"View most popular search phrases.";}}
module: menu_ui
hidden: 0
external: 0
has_children: 0
expanded: 0
weight: 0
depth: 3
customized: 0
p1: 4
p2: 45
p3: 62
p4: 0
p5: 0
p6: 0
p7: 0
p8: 0
p9: 0
updated: 0
route_name: dblog.search
route_parameters: a:0:{}
Since, machine_name = NULL
, the following code at menu.inc does not find the link definition while rebuilding:
function menu_link_rebuild_defaults() {
...
if ($all_links) {
foreach ($all_links as $machine_name => $link) {
// For performance reasons, do a straight query now and convert to a menu
// link entity later.
// @todo revisit before release.
$existing_item = db_select('menu_links')
->fields('menu_links')
->condition('machine_name', $machine_name)
->execute()->fetchObject();
if ($existing_item) {
...
This causes that the menu link gets listed several times (as many as you clear caches), as you can see in the following screenshot:
Possible solutions
a) Specify at hook_menu_link_defaults()
that new links must define machine_name.
b) Add logic at _menu_link_save_recursive() to make sure that 'machine_name' is set before calling drupal_save_record().
Comment | File | Size | Author |
---|---|---|---|
#16 | drupal-menu-links-machine-name-2258299-16-just-test.patch | 3.69 KB | juampynr |
#16 | drupal-menu-links-machine-name-2258299-16.patch | 4.61 KB | juampynr |
#16 | interdiff.txt | 1.3 KB | juampynr |
#11 | interdiff.txt | 3.18 KB | juampynr |
#11 | drupal-menu-links-machine-name-2258299-11.patch | 4.14 KB | juampynr |
Comments
Comment #1
juampynr CreditAttribution: juampynr commentedHere is a patch that fixes the issue by adding machine_name to dblog_menu_links_defaults_alter().
Comment #2
juampynr CreditAttribution: juampynr commentedHere is a perhaps cleaner way to solve it in which we set the machine_name index in case it is not present after loading all the links.
Comment #3
dawehnerThis seems fine, but we are gonna remove this file anyway.
Comment #4
juampynr CreditAttribution: juampynr commented@dawehner, what's the plan? Is there any post where I can read about it and help?
Comment #5
dawehner#2227441: New plan, Phase 1:Review the architecture and overall implementation proposal for menu links as plugins is probably what you look for.
Comment #6
dawehneror maybe #2256497: [meta] Menu Links - New Plan for the Homestretch
Comment #7
juampynr CreditAttribution: juampynr commentedNo point then in committing this until those issues are fixed? This issue is affecting Devel module too #2244523: Fix devel after all the menu system changes.
Comment #8
dawehnerWell yeah ... rebase that branch won't be funny anyway :P
Comment #9
dawehnerNot sure whether we though need some test coverage
Comment #10
webchickAgreed, I think test coverage would be a good idea. We don't want to ever accidentally re-introduce this bug.
Comment #11
juampynr CreditAttribution: juampynr commentedHere it is. Added a patch with just the test to make it fail and a patch with the test and the fix.
Comment #13
juampynr CreditAttribution: juampynr commentedBumping up as critical since it meets "Render a system unusable and have no workaround.".
If caches are rebuild 100 times (very common on a production site), the admin/reports page would show 100 links to Top Search Phrases. Devel module is also waiting for this to get committed before fixing #2244523: Fix devel after all the menu system changes.
Comment #14
dawehnerTbh. issue priorities are more or less random these days.
It would be great to also have something which tries to test the actual regression: you execute the rebuild multiple times and end up with more than one entry. This should not be that hard to test.
Comment #15
pwolanin CreditAttribution: pwolanin commentedThis should also be resolved by: #2256497: [meta] Menu Links - New Plan for the Homestretch
Comment #16
juampynr CreditAttribution: juampynr commentedAdded an assertion that rebuilds the menu tree and checks that links added at hook_menu_link_defaults() do not duplicate.
Comment #18
juampynr CreditAttribution: juampynr commentedSetting to needs review. Tests worked as expected.
Comment #19
dawehnerIt is great to see some test coverage, this would be yet another critical which would be also covered by the menu rewrite. So sad.
Comment #21
alexpottCommitted 50197bc and pushed to 8.x. Thanks!
Nice to have test coverage.
Fixed comment style during commit.