it-swarm.com.de

Kann ich eine Route bedingt ausblenden (z. B. Aktion / lokale Aufgabe)?

Betrachten Sie eine Aktionsschaltfläche auf der kanonischen Seite einer benutzerdefinierten Entität:

mymodule.actions.yml:

entity.item.action:
  route_name: entity.item.action
  title: 'Do something'
  appears_on:
    - entity.item.canonical

mymodule.routing.yml:

entity.item.action:
  path: '/item/{item}/action'
  defaults:
    _controller: '\Drupal\mymodule\Controller\ItemController::action'
    _title: 'Do something'
  requirements:
    _permission: 'edit items'

Ich möchte die Aktionsschaltfläche abhängig vom Wert eines Felds der Entität ein- oder ausblenden.

Wie könnte ich das erreichen? Wäre es ratsam, hierfür eine benutzerdefinierte Zugriffsprüfung hinzuzufügen?

3
Hendrik

Sie können Ihrem Controller eine benutzerdefinierte Zugriffsmethode hinzufügen. Laut diese Seite sollten Sie Zugriff auf Ihr Argument item in der Zugriffsmethode haben, damit Sie den Zugriff basierend auf einem Wert für dieses Element einschränken können. Die Aktion sollte ausgeblendet werden, wenn der Benutzer keinen Zugriff auf die Route hat, d. H. Ihre benutzerdefinierte Zugriffsmethode den Zugriff verweigert.

2
sonfd

Ich habe eine ähnliche Aufgabe mit hook_menu_local_tasks_alter. Beachten Sie jedoch, dass Sie die aktuelle Entität (z. B. den Knoten) separat abfragen müssen, da sie nicht als Parameter an diesen Hook übergeben wird

Etwas wie das:

function XXX_menu_local_tasks_alter(&$data, $route_name) {
  $routes = ['entity.node.canonical'];

  if (in_array($route_name, $routes)) {
    foreach ($data['tabs'][0] as $task_name => &$task_array) {
      if ($task_name == 'entity.node.canonical') {

        $node = \Drupal::routeMatch()->getParameter('node');
        if ($node instanceof \Drupal\node\NodeInterface) {
2
George

Zwei nützliche Ansätze werden im Drupal 8-Handbuch/Bereitstellen moduldefinierter Aktionen beschrieben. Diese sind:

  1. Ableitungen, die dynamisch eine oder mehrere Aktionen generieren
  2. Benutzerdefinierte Klassen für die Aktionen

Ich habe das Problem mit Ansatz 1 fast gelöst. Ich habe jedoch immer noch Probleme mit dem Caching. Dies ist meine bisherige Lösung:

namespace Drupal\mymodule\Plugin\Derivative;

use Drupal\Component\Plugin\Derivative\DeriverBase;
use Drupal\mymodule\Entity\ItemInterface;
use Drupal\mymodule\Entity\Item;

/**
* Defines dynamic actions.
*/
class ItemLocalActions extends DeriverBase {

 /**
  * {@inheritdoc}
  */
 public function getDerivativeDefinitions($base_plugin_definition) {
   // Implement dynamic logic to provide values for the same keys as in example.links.task.yml.
   $id = \Drupal::routeMatch()->getRawParameter('item');
   $item = Item::load($id);

   if ($item instanceof ItemInterface) {
     switch($item->getStatus()) {
       case ItemInterface::STATUS_NEW:
         $this->derivatives['entity.item.action'] = $base_plugin_definition;
         $this->derivatives['entity.item.action']['title'] = t('Do something');
         $this->derivatives['entity.item.action']['route_name'] = 'entity.item.action';
         break;

         // add more derivative definitions here, depending on the item's state
     }
   }
   return $this->derivatives;
 }
}

und in mymodule.links.action.yml:

entity.item.state_actions:
  deriver: '\Drupal\mymodule\Plugin\Derivative\ItemLocalActions'
  cache_tags:
    - item_list
  appears_on:
    - entity.item.canonical

Wie oben erwähnt, ist das Zwischenspeichern immer noch ein Problem. Obwohl ich die entsprechenden Cache-Tags festgelegt habe, werden die Aktionen immer noch aus dem Cache gerendert.

Verwandte Fragen:

0
Hendrik