Problem/Motivation

  • Back when MenuLink was an entity type, #1966298: Introduce menu link bundles per menus introduced bundles for it, where the bundle is the menu that the link is in (just like taxonomy terms have a bundle corresponding to the vocabulary they're in). This was to allow different link translation settings per menu.
  • #2301317: MenuLinkNG part4: Conversion changed MenuLink from an entity type to a plugin type, and plugins have no concept of bundles. It added a new entity type, MenuLinkContent, specifically for custom menu links, but made them have just a single bundle, not bundle = menu.
  • MenuLinkContent is now a fieldable entity type (by default although there is no interface for it), whereas the old MenuLink wasn't. Meanwhile, a link can be moved from one menu to another, and core's Field API does not have support for changing the bundle of a fieldable entity. This makes difficult to have the menu that is holding a menu item as a bundle for the entity.

This the history so far until Drupal 8.0.0 and the menu system did not add much big features. This is the situation as of Drupal 8.7.x

  • The only bundleable menu item is the content entity and it should live with other non-bundleable menu items.
  • Making the bundle the menu a item lives in introduces the problem of content entities changing bundle which introduces a lot of complexity
  • menu link content is a mono bundle entity but not like user. It has its own mechanism to force the bundle (because of the past).

Proposed resolution

Add the ability to add fields and view modes to the MenuLinkContent entity and then study the use cases that need different bundles for that entity.

Comments

dawehner’s picture

Issue tags: +MenuSystemRevamp

.

Berdir’s picture

I did write a proof of concept for file_entity to change the file type/bundle on an existing entity: https://github.com/md-systems/file_entity/blob/8.x-2.x/src/FileEntity.ph...

It's not complete yet, I need to care about changed values in $this->fields for example, and I have the advantage that that is mostly about changing from a special bundle that won't have any fields but it works.

tstoeckler’s picture

Title: Introduce MenuLinkContent bundles per menu » Introduce MenuLinkContent bundles

where the bundle is the menu that the link is in (just like taxonomy terms have a bundle corresponding to the vocabulary they're in)

This part of the issue summary is not correct.

Menu links had two separate properties: bundle and menu_name. Only if the former was empty upon saving a menu link it would default to the menu name. This was explicit as it allowed to both have menu links from different menus have the same bundle and menu links in the same menu have different bundles.

The use-case for the first (N menus : 1 bundle) is that you might have two (or more) distinct menus that are distinct because they show up in different parts of the website but they are alike in their presentation and thus you would like to share the fields with them. Of course you could also re-create the same fields on a separate bundle (if bundle == menu_name) (as the field data is shared across the entity type) so this use-case is not very pressing.

The use-case for the latter (1 menu: N bundles) is that you might have different needs for different levels of your menu. I.e. the top-level menu links should have an image field, as they constitute some mega-header on your site, but then the second-level links should not have such a field. It is superior to use distinct bundles for the different menu links over implementing checks everywhere on the display side for which level the menu link is contained in. You might also need to have a very large menu which generally is translatable but you want to exclude certain parts from the translation process as they e.g. only make sense in English. Again it is preferable to make a certain subtree of your menu belong to a different bundle than hacking your translation UI to exclude a handful of specific entities.

So while I am all for adding bundles to menu links (in order to enable the above use-cases), menu_name and bundle should stay distinct as they have been. For menu links added by core we should re-establish the default of bundle = menu_name but that should not be hardcoded. (And FWIW, I would like that to be moved into the form layer rather than the API layer.)

effulgentsia’s picture

In HEAD (until #2301319: MenuLinkNG part5: Remove dead code; and party! lands), \Drupal\menu_link\Entity\MenuLink::postLoad() has the following code:

// By default use the menu_name as type.
$menu_link->bundle = $menu_link->menu_name;

The comment says "by default", but the code does it regardless of whether bundle is already set. And MenuTest::testMenuBundles() asserts that moving a menu link to a different menu after already having a bundle changes the bundle to the new menu.

I think #3 presents good arguments for not changing the bundle once it's already set, but that doesn't appear to be the current state of HEAD.

Gábor Hojtsy’s picture

Yeah in the new situation, I'm not sure if we can even make sense of per bundle language settings given the menus may also contain stuff from configuration and static menu items, both of which have their language/translation defined elsewhere, so this setting cannot govern them. Menus, views and blocks will surely be the three most interesting combination exercises for someone to figure out how the multilingual stuff works :)

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

ozin’s picture

Couple months ago we create module Menu Item Extras which adds bundles to menus and templates, also it has integration with Views and provides couple extra features which are specific for the MenuLinkContent entity, but it has also some issues which we can't fix in our module and it require core fixes.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

rodrigoaguilera’s picture

I want to summarize a bit what I understood from reading the issue since there is a lot of concept from Drupal 8.0.0 and we are 6 minor releases from there.

- The only bundleable thing is the content entity and it should live with other non-bundleable menu items.

- Making the bundle the menu a item lives in introduces the problem of content entities changing bundle which introduces a lot of complexity.

- menu link content is a mono bundle entity but not like user. It has its own mechanism to force the bundle (because of the past).

So I think we should not introduce bundle for the menu link content entity yet and solve two situations first.

- clean the mono bundle code for menu link content so it resembles the user entity (I will open an issue)

- enable field ui for the menu link entity and view modes that can solve some use cases that bundles can also solve ( different fields for different menu levels). I plan to release a simple contrib module to showcase this.

What do you think?

andypost’s picture

Version: 8.6.x-dev » 8.8.x-dev
Category: Task » Feature request

@rodrigoaguilera nice summary, please update IS - looks a great plan!

voleger’s picture

Also during the development of https://www.drupal.org/project/menu_item_extras project, we faced with the next complications from the Drupal core:
- MenuLinkContent has no view access permission. Reason: Menu entity handles fetching the data and rendering of the child MenuLinkInterface instances (config and content entities). #2915792: MenuLinkContentAccessControlHandler does not allow "view" access without admin permission, making these entities inaccessible via REST, JSON API and GraphQL and entity reference fields
- MenuLinkContent has no own templates. Reason: Menu block template render the menu link items in a recursive manner.
- MenuLinkContent as the fieldable entity will always render in the default viewmode. User expect to handle the rendering of each menu item in the scope of rendering a menu block.
Use case: menu contains 3 menu items, each menu link item should be rendered in different view modes.
Solution: for this reason, menu_item_extras module provides a field that can override per entity which view mode should be used as a default view mode.
Another use case: we have a menu with fieldable menu items. In the header menu items of the menu block should be rendered using defined view mode by the default. In the footer, the same menu should be rendered as simple links (entity without bundle fields).
Solution: Each menu block should be able to override menu items view mode that would be used for rendering in the region.

effulgentsia’s picture

I like the idea of adding field_ui_base_route to MenuLinkContent. That would enable Field UI and creating view modes via the UI (/admin/structure/display-modes/view/add). I also like the idea of adding configuration to SystemMenuBlock for setting the view mode to use for the links rendered in that block. Those two things seem very simple and clean, yet powerful.

@voleger: would doing that in core interfere with menu_item_extras at all? Could menu_item_extras still implement bundle-per-menu and its other features if core did the above?

@rodrigoaguilera: would the above address some of your use-cases without interfering with your ability to do the rest (e.g., different view mode per link level within the same menu block) in contrib?

If there's initial agreement on the above, let's maybe open an issue in https://www.drupal.org/project/ideas to get more feedback on it?

rodrigoaguilera’s picture

Issue summary: View changes
Priority: Major » Normal
Related issues: +#2315773: Create a menu link field type/widget/formatter

@voleger Great module menu_item_extras. I even enjoyed contributing to it :)
I'll try to go point by point. (the general topic is getting some functionality into core)

- I did not experience any permission issues for rendering the menu item fields. I guess is a problem to solve for rest and jsonapi.
- Do we need new templates? Maybe altering a bit menu.html.twig can be enough. New link formatters may be needed to remove divs for the fields rendered.

- The first iteration can happen without configurable view modes by menu or per item. We can cover more use case as we move forward. Menu item extras will be there to care for those use cases ;)

Give me some time to reorganize my code a bit before publishing a module that showcases the fields for menu items. My plan is to preprocess the menu to add the rendered entity (as a render array) to the menu items.

@effulgentsia I plan to cover the use case of display mode per menu block and an override for each item but as said above let's do it slowly hardcoding 'default' at the beginning.

I don't think this is a 'major' feature to add to core so I'm lowering the priority. Updated the issue summary with the info collected.

Do we have to get an OK from the current menu system maintainers? @dawehner or @pwolanin

I didn't know about the ideas project. I will post there once I have it even more clear myself.

andypost’s picture

Is menu links delegates access to route, there's a trick with API but when menu content could have bundles granularity of entity permissions could be altered as well

rodrigoaguilera’s picture

This is my attempt at trying to render the fields in the simplest way possible with no bundles.

https://www.drupal.org/project/menu_item_fields

As I mentioned before I will try to make a case for Drupal core so we can enjoy fields on menu items.

rodrigoaguilera’s picture

Turns out there was already an issue to remove the bundle from the entity

#2987537: Custom menu link entity type should not declare "bundle" entity key

Please continue the discussion there. I'm postponing this until a decision is taken there.

voleger’s picture

@effulgentsia We develop this module with thoughts in mind how the core menu system can be enhanced with menu items fields.
So the first complication was solved in the core. #2903161: Fix incorrect FieldFormatter id for "weight" field in base field definition in display options Our module has a fallback for that case if using an older version of the core.
Another one is allowed to alter the bundle in the form controller #2923429: Remove 'bundle' key from menu link create method in 'Drupal\menu_link_content\Controller\MenuController'. This allows defining which bundle will be used during link creation.
> would doing that in core interfere with menu_item_extras at all?
So in case if core will introduce bundled MenuLinkContent entity, our module should deprecate implementation in favor of the core functionality.
> Could menu_item_extras still implement bundle-per-menu and its other features if core did the above?
No, module alters MenuLinkContent entity type definition.

voleger’s picture

Here more notices about changes:
- We will have a break in BC for allowing to set entity to the different menus in case if Menu entity type will be a bundle for MenuLinkContent entity type. In Menu Item Extras module we set a limit to allow move menu item within the current menu.
- Node create/edit form will require a refactoring in Menu Link configuration form.
- Regarding template of the MenuLinkContent. We provide more theme suggestion for each menu item because of specific cases related to 'below' (child items) field. We faced a few use cases:

  1. The default one. This is how https://www.drupal.org/project/menu_item_fields currently handles the rendering of the menu item content:
    <ul>
      <li>
        <div><!-- menu item template --></div>
        <ul><!-- child items (field 'below' in the current core template)  --></ul>
      </li>
    </ul>
    
  2. Case when child items are rendered somewere between menu item fields:
    <ul>
      <li>
        <div>
          <!-- menu item template -->
          <ul><!-- child items (field 'below' in the current core template)  --></ul>
          <!-- menu item template -->
        </div>
      </li>
    </ul>
    

    For example, menu item consist of:
    - title only field;
    - list of child menu items as just links;
    - image.

So we provide additional field for child items. If that field is hidden in the view mode, child items will be rendered below the menu item (default behavior). If that field showed in the view mode, below shouldn't render anything in respect of rendered child items by the field configured by the view mode.

voleger’s picture

Also introducing Field UI for the MenuLinkContent entity type allow us to use Layout builder. Take a look for a great article Creating a Mega Menu using Layout Builder in Drupal 8 by Phaze2
And Get a Fieldable Drupal Menu: Menu Item Extras Overview by Lemberg (thanks @ozin)

rodrigoaguilera’s picture

Here is the idea proposed for Drupal core
#3047131: Enable the field interface for creating fields and view modes on content menu items

I don't think it will impact much the menu_item_extras module. It just the first baby steps to bring more functionality to Drupal core so the use case for bundles is even stronger when people experience the possibility to add fields to menu items.

effulgentsia’s picture

Status: Postponed » Closed (won't fix)

> would doing that in core interfere with menu_item_extras at all?
So in case if core will introduce bundled MenuLinkContent entity, our module should deprecate implementation in favor of the core functionality.
> Could menu_item_extras still implement bundle-per-menu and its other features if core did the above?
No, module alters MenuLinkContent entity type definition.

Sorry, I think I wasn't clear in #16. In that comment I'm not proposing that core introduce bundles for MenuLinkContent. However, given that that is still this issue's title, I see that that's confusing, so I'm closing this as "won't fix". If anyone wants to re-open it, go for it, but given that this issue has already been open 5 years, and that we're not really any closer to allowing entities to change their bundle (e.g., when a menu link is moved from one menu to another), I think "won't fix" most closely reflects current reality.

What I was trying to ask in #16 is if core enabled Field UI for the existing situation of all menu links being in the same bundle, whether that would interfere with menu_item_extras, or if it would be straightforward for menu_item_extras to still do its job. For example, suppose someone used core to add fields to menu links that are in their default "menu_link_content" bundle. And then someone enables menu_item_extras. Would menu_item_extras reassign existing menu links to the bundle that corresponds to the menu they're in? And if so, what would happen to the existing fields that are only on the "menu_link_content" bundle? Please comment in #3047131: Enable the field interface for creating fields and view modes on content menu items with any thoughts about that or other impacts that you foresee on menu_item_extras. Thanks!

arnaud-brugnon’s picture

If anyone wants bundle for menu link content, take a look to menu_item_extras module.