it-swarm.com.de

Wie kann ich ein Menü programmgesteuert mit einem aktiven Pfad laden, der durch eine angegebene URL festgelegt wird?

Arbeiten an einer kopflosen Drupal -Site und sind auf ein Problem gestoßen. Wir haben eine REST -Ressource, die beliebige Menüs nach Menü-ID zurückgibt, jedoch immer "active-trail" wird bei jedem Menüpunkt auf false gesetzt.

Ich möchte in der Lage sein, beim Erstellen des Menüs eine URL oder Route anzugeben und den aktiven Pfad so zu gestalten, wie er wäre, wenn das Menü auf diese Route geladen würde.

Im Moment besteht unsere Lösung darin, jeden Menüpunkt zu durchlaufen, bis wir einen finden, der der angegebenen URL entspricht, und ihn und alle seine Eltern als "Active-Trail" zu markieren. Dies scheint jedoch unnötig umständlich zu sein, und ich frage mich, ob Es gibt eine vernünftigere Lösung, die wir übersehen haben.

Derzeit laden wir Menüs wie folgt:

$tree = $this->menuTree->load('menu_id', new MenuTreeParameters());

Wobei $ this-> menuTree eine Instanz von MenuLinkTree ist, die über Dependency Injection instanziiert wird:

/**
 * {@inheritdoc}
 */
public function __construct(array $configuration, $plugin_id, $plugin_definition, array $serializer_formats, LoggerInterface $logger, MenuLinkTreeInterface $menu_tree, EntityTypeManagerInterface $entity_type_manager, Request $current_request) {
  parent::__construct($configuration, $plugin_id, $plugin_definition, $serializer_formats, $logger);

  $this->menuTree = $menu_tree;
  $this->entityTypeManager = $entity_type_manager;
  $this->request = $current_request;
  $this->alias = $this->request->query->get('alias');
}

/**
 * {@inheritdoc}
 */
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
  return new static(
    $configuration,
    $plugin_id,
    $plugin_definition,
    $container->getParameter('serializer.formats'),
    $container->get('logger.factory')->get('rest'),
    $container->get('menu.link_tree'),
    $container->get('entity_type.manager'),
    $container->get('request_stack')->getCurrentRequest()
  );
}
5
Drif.io

Injizieren Sie das menu.active_trail Abhängigkeit zusammen mit menu.link_tree:

private $activeTrail;

/**
 * {@inheritdoc}
 */
public function __construct(array $configuration, $plugin_id, $plugin_definition, array $serializer_formats, LoggerInterface $logger, MenuLinkTreeInterface $menu_tree, MenuActiveTrailInterface $active_trail, EntityTypeManagerInterface $entity_type_manager, Request $current_request) {
  parent::__construct($configuration, $plugin_id, $plugin_definition, $serializer_formats, $logger);

  $this->menuTree = $menu_tree;
  $this->activeTrail = $active_trail;
  $this->entityTypeManager = $entity_type_manager;
  $this->request = $current_request;
  $this->alias = $this->request->query->get('alias');
}

/**
 * {@inheritdoc}
 */
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
  return new static(
    $configuration,
    $plugin_id,
    $plugin_definition,
    $container->getParameter('serializer.formats'),
    $container->get('logger.factory')->get('rest'),
    $container->get('menu.link_tree'),
    $container->get('menu.active_trail'),
    $container->get('entity_type.manager'),
    $container->get('request_stack')->getCurrentRequest()
  );
}

Jetzt statt:

$tree = $this->menuTree->load('menu_id', new MenuTreeParameters());

holen Sie sich die aktiven Trail-IDs kurz vor dem Erstellen Ihres Menüs und geben Sie sie als Teil der Parameter ein:

// Change this to menu machine name.
$menu_id = 'menu_id';

// This should return an array. 
// Array contains menu link uuid's, keyed by the uuid's iirc. 
// For example something like:
//   'menu_link:abcdefg_123' => 'menu_link:abcdefg_123'
$activeTrailIds = $this->activeTrail->getActiveTrailIds($menu_id); 

$params = new MenuTreeParameters();
$params->setActiveTrail($activeTrailIds);
$tree = $this->menuTree->load($menu_id, $params);

Dies sollte Ihnen einen Menübaum mit korrekten aktiven Trails zurückgeben.

5
Beebee

Ich hatte auch diesen Fall und, wie Drif.io in seinem Kommentar zu Beebees Antwort beschreibt, musste ich die MenuActiveTrail-Kernklasse erweitern.

In meinem Fall habe ich es über Patch gelöst, aber in anderen Anwendungsfällen wäre es wahrscheinlich eine bessere Idee, die Klasse zu erweitern und einen eigenen Dienst zu erstellen. Wir verwenden die Funktionalität per Patch in einem Kernmodul, in dem keine Abhängigkeit von einem benutzerdefinierten Modul erstellt werden kann.

Bisher sah die Funktion getActiveTrailIds folgendermaßen aus:

public function getActiveTrailIds($menu_name) {
  return $this->get($menu_name);
}

Ich habe die Funktion geändert, um ein optionales $route_match Parameter. Aufgrund des Parameters musste ich jedoch das Caching des aktiven Trails deaktivieren, da es ein anderes Ergebnis gibt, wenn ein regulärer Breadcrumb aus derselben (Haupt-) Navigation ohne den Parameter Route Match angezeigt wird.

public function getActiveTrailIds($menu_name,$route_match = null) {
  unset($this->storage[$menu_name]); //disable caching for this case.
  if ($route_match) {
    $this->routeMatch = $route_match;
  }
  return $this->get($menu_name);
}

Jetzt kann ich den Dienst mit anrufen

\Drupal::service('menu.active_trail')->getActiveTrailIds('main',$route_match);
1
Florian Müller