Advertising sustains the DA. Ads are hidden for members. Join today

On this page

User stories for Drupal's menu API

Last updated on
19 April 2017

Adapted from #2351379: [meta] Define, then support exact use cases for link generation and storage. Here are various user stories for the menu API and how they fare against the plan at #2407505: [meta] Finalize the menu links (and other user-entered paths) system.

Content Authors/Site Builder Use Cases (UI)

  • D7: PASS: Node paths are resolved to the system path (node/1); changing path to /content/about-us won't break the link.
  • D8 (current): PASS: It does basically the same thing, except route name/parameters rather than system path.
  • D8 (proposed): PASS: An entity reference is saved, which is resolved to route name / parameters by the menu link system.
  • D7: FAIL: This is basically the opposite of use case #1 and as such is not supported. The menu link disappears when the "Coming soon" page is deleted.
  • D8 (current): FAIL: Same.
  • D8 (proposed): PASS: In the custom menu link form, enter "content/about", and we preserve that.
  • D7: PASS: Because system path is stored, switching the underlying implementation out from underneath works fine.
  • D8 (current): FAIL: Because all paths are resolved to routes.
  • D8 (proposed): PASS: In the custom menu link form, enter "blog", and we preserve that.

As a content author, I want to build out my site navigation first, then fill it with content as I go, like I do in other CMSes.

  • D7: FAIL: Linking to non-existing content is not supported.
  • D8 (current): FAIL: Same.
  • D8 (proposed): PASS: In the custom menu link form, enter the URL aliases you want and then when building content, use those aliases. However, taking this site building approach has its drawbacks, since if you later change any of those node path aliases, you'll need to update the links manually to match.

Translator use cases

As a translator I want to use one menu and have translations for items in this same menu.

  • D7 (core): FAIL: Menu items cannot be translated in core, i18n_menu provides a solution in contrib
  • D8 (core, current): PASS: Menu items can be translated either as configuration, as content or as interface
  • D8 (core, proposed):PASS: Menu items will ALSO be translatable as a field.

As a translator, I want to use the same menu for translations but different menu items that are shown conditionally based on language.

  • D7 (core): FAIL: Menu items don't know their language so cannot be shown/hidden by their language. i18n_menu provides this feature in contrib.
  • D8 (core, current): semi-FAIL: Nodes get menu item content entities for their menu items. These know their language, but per language hiding is not implemented. That could be contrib.
  • D8 (core, proposed): semi-FAIL: Fields know their language, so per language hiding may be implement in contrib.

As a translator, I want to use different menus per language and consequently need to use different menu items for translations.

  • D7 (core): semi-PASS: Translated nodes are their own nodes if using core’s translation module and naturally have their own menu items (but not if using entity_translation). The menu selection widget cannot be limited to the specific language menu as needed, but contrib solves that.
  • D8 (core, current): FAIL: Entity translations are the same entity and neither the menu item "entity reference" is translatable nor the menu name/weight on the menu item content entity.
  • D8 (core, proposed): semi-FAIL: Menu items as fields are proposed to support weight and title/description translation but not menu name swapping. Should figure out how this may be possible in contrib at least.

Developer/Themer Use Cases (Code)

  • D7: FAIL: Because there's no concept of route machine names, your only option is linking to system paths, which can change.
  • D8 (current): PASS: This is one advantage of the new routing system.
  • D8 (proposed): PASS: Url::fromRoute() continues to work and is the recommended practice.
  • D7: PASS: System paths are stored, so whichever View gets enabled wins.
  • D8 (current): FAIL: Because paths are always resolved to route names/parameters, there's no way to support this use case.
  • D8 (proposed): PASS: During install the distro can save a menu link content entity referencing the path.
  • D7: PASS: url('admin/structure/book');
  • D8: PASS: Url::fromRoute('book.admin');
  • D7: PASS: url('blog');
  • D8 (current): semi-FAIL: Technically, you can workaround with Url::fromUri('base://blog'); but this is awkward.
  • D8 (proposed): PASS: Url::fromPath('/blog'); Note though that this use case is controversial in D8 because we do not want to encourage developers to do this, even though it is an easier/more natural progression from D7.
  • D7: PASS: url('robots.txt', array('external' => TRUE));
  • D8: PASS: Url::fromUri('base://robots.txt');

As a distribution developer, I want to change the canonical path of /admin/structure/contact and /admin/structure/contact/* to /admin/config/contact and /admin/config/contact/*. If possible, I still want to leave the site builder the freedom to create a URL alias to them.

  • D7: ? hook_url_outbound_alter(), but not sure if this completely solves the use case
  • D8 (current): PASS: the 'path' property of the routes can be altered (in code).
  • D8 (proposed): semi-FAIL: if the site builder adds a contrib module that invokes Url::fromPath('admin/structure/contact');

As a themer, I want to be able to do all the linky things a developer can do!

Available twig functions:
file_url() /// wraps file_create_url()
url_fromPath() // Basically Url::fromPath() in twig
url() // Basically Url::fromRoute() in twig

Help improve this page

Page status: No known problems

You can: