Comment créer des onglets utilisateur personnalisés?


9

J'essaie de créer un nouvel onglet personnalisé qui apparaît sur toutes les routes qui sont des descendants de l'entité. {Entity_type} .canonical. J'ai essayé d'étendre la classe DeriverBase, en remplaçant spécifiquement la méthode getDerivativeDefinitions. J'ai créé l'onglet lui-même en étendant LocalTaskDefault et en remplaçant la méthode getRouteParameters. L'onglet apparaît lorsque vous visitez un chemin utilisateur Drupal standard tel que www.mysite.com/user/1/ ou www.mysite.com/user/1/edit. Cependant, lorsque nous ajoutons nos nouveaux itinéraires utilisateur personnalisés tels que www.mysite.com/user/1/subscribe, aucun onglet n'apparaît. Existe-t-il un moyen spécial de définir des tâches de menu local sur des itinéraires personnalisés? Un exemple du code:

 $this->derivatives['recurly.subscription_tab'] = [
  'title' => $this->t('Subscription'),
  'weight' => 5,
  'route_name' => 'recurly.subscription_list',
  'base_route' => "entity.$entity_type.canonical",
];

foreach ($this->derivatives as &$entry) {
  $entry += $base_plugin_definition;
}

Merci d'avance pour toute aide.


Cela semble très proche de ce que devel fait avec sa tâche / devel route / local, je vous suggère de voir comment il implémente cela.
Berdir

@Berdir, c'était le point de départ, mais il me semble toujours manquer quelque chose.
tflanagan

Avez-vous essayé d'ajouter le fichier «yourmodule.links.task.yml» avec les paramètres de votre onglet personnalisé?
Andrew

Réponses:


7

Comme suggéré par Berdir, vous pouvez regarder le module Devel et comment il l'implémente. Le code suivant a été "extrait" de Devel

1) Créez les itinéraires

Créez le fichier mymodule.routing.yml dans et à l'intérieur définissez un rappel de route (qui est utilisé pour créer les routes dynamiques)

route_callbacks:
  - '\Drupal\mymodule\Routing\MyModuleRoutes::routes'

Créez la classe MyModuleRoutes pour générer vos routes dynamiques dans src / Routing

<?php

namespace Drupal\mymodule\Routing;

use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;

class MyModuleRoutes implements ContainerInjectionInterface {

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

  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('entity_type.manager')
    );
  }

  public function routes() {
    $collection = new RouteCollection();

    foreach ($this->entityTypeManager->getDefinitions() as $entity_type_id => $entity_type) {
      if ($entity_type->hasLinkTemplate('canonical')) {
        $route = new Route("/mymodule/$entity_type_id/{{$entity_type_id}}");
        $route
          ->addDefaults([
            '_controller' => '\Drupal\mymodule\Controller\MyModuleController::doStuff',
            '_title' => 'My module route title',
          ])
          ->addRequirements([
            '_permission' => 'access mymodule permission',
          ])
          ->setOption('_mymodule_entity_type_id', $entity_type_id)
          ->setOption('parameters', [
            $entity_type_id => ['type' => 'entity:' . $entity_type_id],
          ]);

        $collection->add("entity.$entity_type_id.mymodule", $route);
      }
    }

    return $collection;
  }

}

2) Créez les tâches locales dynamiques

Créez le fichier mymodule.links.task.yml et définissez à l'intérieur un dérivé

mymodule.tasks:
  class: \Drupal\Core\Menu\LocalTaskDefault
  deriver: \Drupal\mymodule\Plugin\Derivative\MyModuleLocalTasks

Créez la classe MyModuleLocalTasks pour générer vos routes dynamiques dans src / Plugin / Derivative

<?php

namespace Drupal\mymodule\Plugin\Derivative;

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

class MyModuleLocalTasks extends DeriverBase implements ContainerDeriverInterface {

  protected $entityTypeManager;

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

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

  public function getDerivativeDefinitions($base_plugin_definition) {
    $this->derivatives = array();

    foreach ($this->entityTypeManager->getDefinitions() as $entity_type_id => $entity_type) {
      if ($entity_type->hasLinkTemplate('canonical')) {
        $this->derivatives["$entity_type_id.mymodule_tab"] = [
          'route_name' => "entity.$entity_type_id.mymodule",
          'title' => t('Mymodule title'),
          'base_route' => "entity.$entity_type_id.canonical",
          'weight' => 100,
        ] + $base_plugin_definition;
      }
    }

    return $this->derivatives;
  }

}

3) Créez le contrôleur

Créez la classe MyModuleController dans src / Controller

namespace Drupal\mymodule\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Routing\RouteMatchInterface;

class MyModuleController extends ControllerBase {

  public function doStuff(RouteMatchInterface $route_match) {
    $output = [];

    $parameter_name = $route_match->getRouteObject()->getOption('_mymodule_entity_type_id');
    $entity = $route_match->getParameter($parameter_name);

    if ($entity && $entity instanceof EntityInterface) {
      $output = ['#markup' => $entity->label()];
    }

    return $output;
  }

}

3
C'était très similaire à ce que j'ai fini par mettre en œuvre. Passer dans RouteMatchInterface $ route_match a été la solution à mon problème. De là, mon objet entité était disponible pour mon contrôleur.
tflanagan
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.