Image représentant des cordes enchainées les unes aux autres.
  • 13/05/2019
  • 0 commentaire

L'élément, selon moi, le plus important d'un site web est la qualité de ses menus. Comme il est possible d'arriver par n'importe quelle page sur un site, il est donc important que l'internaute puisse y naviguer de façon simple et fluide. Voici comment gérer une partie de vos menus dynamiquement sous Drupal 8.

L'élément de navigation majeure est le menu principal

Le réflexe que tout internaute a lorsqu'il veut naviguer sur un site internet est de repérer le menu principal et de comprendre l’architecture des rubriques. Le menu est censé représenter l'organisation de votre site, avec les rubriques principales puis les sous rubriques. Il existe différents types de menus, certains comportent un niveau unique, d'autres avec des sous niveaux et certains possèdent même du contenu dans les menus. Ils sont généralement appelés des méga-menus et sont très utilisés de nos jours.

Gestion des menus sous Drupal

Drupal propose par défaut une entité de type menu qui permet aux contributeurs d'administrer les différents liens. Une fois un menu créé, un bloc est automatiquement disponible afin de le placer dans une région du thème pour un affichage en front office.

Si vous souhaitez administrer les menus, vous les trouverez dans le menu d'administration :

Structure >> Menus

Ajouter des liens dynamiquement

Il est possible de générer des liens dynamiquement avec Drupal 8. Si vous avez une catégorie 'Actualités' et que celles ci disposent d'un type, il devient intéressant de créer une entrée de menu par type afin de pré-filtrer une liste de résultats par exemple.

Pour cela vous devez créer un fichier mymodule.links.menu.yml puis y renseigner les informations suivantes :

mymodule.menu_items.dynamically:
  class: Drupal\mymodule\Plugin\Menu\DynamicallyMenuLink
  deriver: Drupal\mymodule\Plugin\Derivative\DynamicallyMenuLink
  parent: system.admin_config
  menu_name: admin

L'option class permet de définir une classe qui s'occupera de vos liens de menus chargés. Si vous souhaitez récupérer le titre ou la description d'un lien de menu d'une autre façon que la façon standard vous pourrez surcharger ces fonctions ici.

L'option deriver définit la classe qui sera appelée pour générer les liens de menus.

Les options parent et menu_name permettent de définir un lien présent dans un menu spécifique sous lequel vos liens dynamiques se placeront.

Définition du plugin Menu :

<?php

namespace Drupal\mymodule\Plugin\Menu;

use Drupal\Core\Menu\MenuLinkDefault;

/**
 * Represents a menu link for a single dynamically menu link
 */
class DynamicallyeMenuLink extends MenuLinkDefault {

}

Comme vous pouvez le voir, ici rien de bien fou fou. Vous pouvez mettre le code métier qui gérera vos liens ici. La plupart du temps cette classe ne sera pas plus compliquée que cet exemple.

Voici maintenant la partie la plus intéressante, la définition du plugin Deriver.

<?php

namespace Drupal\mymodule\Plugin\Derivative;

use Drupal\Component\Plugin\Derivative\DeriverBase;
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Derivative class that provides the menu links
 */
class DynamicallyMenuLink extends DeriverBase implements ContainerDeriverInterface {

  use StringTranslationTrait;

  /**
   * @var EntityTypeManagerInterface $entityTypeManager.
   */
  protected $entityTypeManager;

  public function __construct($base_plugin_id, EntityTypeManagerInterface $entity_type_manager) {
    $this->entityTypeManager = $entity_type_manager;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, $base_plugin_id) {
    return new static(
      $base_plugin_id,
      $container->get('entity_type.manager')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function getDerivativeDefinitions($base_plugin_definition) {
    $links = [];

    $query = \Drupal::entityQuery('taxonomy_term');
    $query->condition('vid', 'news_type');
    $entity_ids = $query->execute();

    // We assume we don't have too many...
    $news_types = $this->entityTypeManager->getStorage('taxonomy_term')->loadMultiple($entity_ids);

    foreach ($news_types as $news_type) {
      $links[$news_type->id()] = [
          'title' => $news_type->label(),
          'route_name' => 'entity.taxonomy_term.canonical',
          'provider' => 'mymodule',
          'route_parameters' => ['taxonomy_term' => $news_type->id()],
        ] + $base_plugin_definition;
    }

    return $links;
  }
}

Ce plugin implémente un méthode getDerivativeDefinitions() qui permet de définir les liens à créer. Dans un premier temps, il faut récupérer les termes de taxonomie qui serviront à créer les liens. Complétez ensuite un tableau, qui sera retourné par la méthode, en donnant les informations nécessaires à la création des liens. Chaque entrée possède un titre, une route ainsi que les paramètres. L'option provider permet d'indiquer quel module est responsable de ce lien.

Les liens créés dynamiquement ne sont pas éditables ni supprimables dans le BO de Drupal.

Videz vos caches et contemplez le rendus de votre code.
A chaque nouveau terme de taxonomie, vous aurez un lien de menus de créé automatiquement et qui ,si il est configuré, sera tout de suite disponible dans votre sitemap.xml