This is a very useful module, but it use a lot of ressources, especially on a site with various menu menus.

There might be other things that can be optimized as well, might look into that, but one possible option would be to a) configure how deep it should go, most sites only need 2 or so levels for their structure and many menu blocks don't need to show active trail or hierarchy, then it would be nice to disable this logic.

CommentFileSizeAuthor
#18 interdiff-2867366-16-18.txt847 bytesmbovan
#18 allow_to_configure_max-2867366-18.patch17.14 KBmbovan
#17 interdiff-2867366-16-17.txt914 bytesjohnchque
#17 allow_to_configure_max-2867366-17.patch17.8 KBjohnchque
#16 allow_to_configure_max-2867366-16.patch17.21 KBGinovski
#16 interdiff-2867366-15-16.txt446 bytesGinovski
#15 allow_to_configure_max-2867366-15-interdiff.txt659 bytesBerdir
#15 allow_to_configure_max-2867366-15.patch17.19 KBBerdir
#14 allow_to_configure_max-2867366-14-interdiff.txt4.37 KBBerdir
#14 allow_to_configure_max-2867366-14.patch17.19 KBBerdir
#11 allow_to_configure_max-2867366-11-interdiff.txt221 bytesmbovan
#11 allow_to_configure_max-2867366-11.patch14.87 KBmbovan
#9 allow_to_configure_max-2867366-8-interdiff.txt8.5 KBmbovan
#9 allow_to_configure_max-2867366-8.patch14.85 KBmbovan
#5 allow_to_configure_max-2867366-5-interdiff.txt10.17 KBmbovan
#5 allow_to_configure_max-2867366-5.patch10 KBmbovan
#3 allow_to_configure_max-2867366-3.patch2.31 KBmbovan
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Berdir created an issue. See original summary.

davy-r’s picture

It sounds like a good idea, I'm open for patches.

mbovan’s picture

This patch implements Berdir's idea from #4 #2861225: Override behavior for unwanted menus.

You will be able to configure menu trail status per menu:

  • Off - Menu trail is disabled
  • Default behavior - The core's menu active trail logic is used
  • By Trail - Menu trail by path's module logic is used. This is also a default option in case there is no "Menu Trail Status" setting at all. Not sure if we should have a default fallback to "trail" or "off" (disabled)?
Berdir’s picture

Status: Needs review » Needs work
  1. +++ b/menu_trail_by_path.module
    @@ -3,3 +3,26 @@
    +  ];
    +  $form['third_party_settings']['menu_trail_by_path']['menu_trail'] = [
    +    '#type' => 'select',
    +    '#title' => t('Menu Trail Status'),
    +    '#options' => $options,
    +    '#default_value' => $menu->getThirdPartySetting('menu_trail_by_path', 'menu_trail'),
    

    we need config schema for this.

    not 100% sure about making this third party settings, makes it a bit complicated to have an overview/do initial configuration as you have to visit every menu. but ok for now I guess, we could also have a separate default setting and switch to "use default" in the future, but then we need a settings form and so on.

    Can we use a more descriptive name for this, maybe trail_source or trail_status? In case we add more options later.

  2. +++ b/src/MenuTrailByPathActiveTrail.php
    @@ -77,6 +78,22 @@ class MenuTrailByPathActiveTrail extends MenuActiveTrail {
    +        case 'off':
    

    not sure if we want to make the options constants as we refer them in a few places.

    Also seems like the switch is actually a bit overkill and weird as two of three cases return. an if/elseif would be a lot shorter in this case. And the if ($status) actually doesn't need an if, as it will simply not match the condition if it is empty. And you can even provide an explicit default as third argument if you'd want.

mbovan’s picture

Addressed #4, added global settings for the module, configuration form and the limit for path parts.

Status: Needs review » Needs work

The last submitted patch, 5: allow_to_configure_max-2867366-5.patch, failed testing.

Berdir’s picture

  1. +++ b/src/Form/MenuTrailByPathSettingsForm.php
    @@ -0,0 +1,80 @@
    +      '#size' => 30,
    +      '#title' => $this->t('Maximum path parts'),
    +      '#default_value' => $config->get('max_path_parts'),
    +      '#description' => $this->t('Configures how deep the module should go when resolving active trail links. Setting this value to zero will not limit the number of the path parts.'),
    +    ];
    +
    +    $form['trail_source'] = [
    +      '#type' => 'select',
    +      '#title' => $this->t('Trail Source'),
    +      '#description' => $this->t('Configures the default behavior for the trail source.'),
    +      '#options' => static::getTrailSourceOptions(),
    +      '#default_value' => $config->get('trail_source'),
    

    we probably need a bit more descriptions/help for this page.

    a) explain that it is recommended to configure the path parts and enabled menu to only those that require it, to avoid unnecessary performance overhead.

    b) that the trail source default can be overriden for each menu in the menu settings.

    c) that the path setting only applies when using the by path option.

    The more complicated options could be done with hook_help(), or we could use type radios, then you can put a description in [$key]['#description'] that describes each option a bit:

    off: no active trail at all. No performance overhead, useful for special/footer menus.

    default: active trail only for pages that have a menu link pointing to them, same as when not using this module.

    by path: Attempt to find a matching parent menu link based on the path structure. Slower, especially with a large amount of paths parts to consider.

    also, lets add this to the info.yml file as configure link.

  2. +++ b/src/Path/CurrentPathHelper.php
    @@ -63,7 +72,14 @@ class CurrentPathHelper implements PathHelperInterface {
    +
    +    // Limit the maximum number of path parts.
    +    if ($max_path_parts = $this->config->get('max_path_parts')) {
    +      $path_elements = explode('/', $path, $max_path_parts);
    +    }
    

    can we also respect this in the getCid() method? And cut of the parts that we don't need from the path?

mbovan’s picture

Status: Needs work » Needs review

Addressing #7.

"configure" property was added in #5, or you meant about a link in module description?

Status: Needs review » Needs work

The last submitted patch, 9: allow_to_configure_max-2867366-8.patch, failed testing.

mbovan’s picture

Moved schema/* to correct config/schema/* directory. This should fix tests...

Berdir’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests

I've been testing this a bit, both functionality and specifically also performance.

* The default is actually not considered yet, which shows nicely that we need tests. You need to pass the default config as third argument to the getThirdPartySetting() call.

* On my site, with a lot of different menu blocks, this is a nice performance improvement when configured to be active only for a single of those 9 menu. However, the config get calls for all those menus aren't free. One option to improve that would be store the per-menu settings in the global config file as well, as a list keyed by menu. third party settings are nice when the config is loaded already and makes it easier to export and put things in default config, but I think we're OK with that not working and we don't have the config loaded yet. Another advantage would be that it gets much easier to have an overview of all your menus and how you configured them if it's on a single page.

* To provide some numbers, on my site, the relative part of doGetActiveTrails() goes down from 13% to 3.3%. Obviously this will vary a lot depending on how many menu blocks you have and for how many menus you actually need trail by path.

* The getCid() override doesn't actually help because we call the parent, which adds the route + arguments. I think it would make more sense to not call the parent at all. Both this implementation and the parent are also strange as they check for $this->cid but never set it? The CID that I used for testing looked like this: "active-trail:path:langcode:{$this->languageManager->getCurrentLanguage()->getId()}:maxpathparts:$max_path_parts:pathinfo:$path_info". The problem is that this might break the parent/default implementation that works on the route, so not sure about all this. Lets not touch getCid() here, we can open a separate issue if necessary.

* The remaining time is spent on \Drupal\menu_trail_by_path\Menu\MenuTreeStorageMenuHelper::getMenuLinks() and then the toUrl() calls. I'm not really sure how to improve that further, due to various different ways of generating a url, so filtering out before seems very hard.

Berdir’s picture

Assigned: Unassigned » Berdir

Working a bit on this myself.

Berdir’s picture

Ok, those tests aren't very clean but they should assert the basic functionality here. Existing tests are a bit strange because doing a single assert like that is bad for web test performance, as we set up a new environment for them all. Instead, something like that is usually done with a testAll() which calls doTestX() methods. Would make it immediately 5x faster or so.

No tests yet for the path lengths.

Berdir’s picture

Found a problem in my patch, we currently save an empty string when menus are saved as third party setting, then this broke the default.

Fixed for now by doing the fallback differently, so it is also used when an empty string is stored. We might also want to change the entity builder to explicitly delete the key if empty instead.

Ginovski’s picture

Changed permission from 'administer menu' -> 'administer site configuration'

johnchque’s picture

I actually needed the combined patch with #2867790: Store trail URLs in a property since this issue and that one modify the same file.

mbovan’s picture

Added a safe check for the menu. Interdiff is against #16.

  • Berdir committed 1271c38 on 8.x-1.x authored by mbovan
    Issue #2867366 by mbovan, Berdir, Ginovski, yongt9412: Allow to...
Berdir’s picture

Status: Needs review » Fixed

Committing this. We've been using this for years on many sites without any issues, and the default behavior should remain unchanged.

Configured correctly, this can massively improve performance, e.g. if you have long paths and show menus where you don't need an active trail.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.