web-dev-qa-db-ja.com

ルートを条件付きで非表示にできますか(アクション/ローカルタスクなど)

カスタムエンティティの正規ページのアクションボタンを考えてみます。

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'

エンティティのいくつかのフィールドの値に応じて、アクションボタンを表示または非表示にしたいと思います。

どうすればこれを達成できますか?これにカスタムアクセスチェックを追加するのは賢明でしょうか?

3
Hendrik

コントローラにカスタムアクセスメソッドを追加できます。 このページ によると、アクセス方法でitem引数にアクセスできる必要があるため、その項目の値に基づいてアクセスを制限できるはずです。ユーザーがルートにアクセスできない場合、つまりカスタムアクセス方法がアクセスを拒否する場合、アクションは非表示にする必要があります。

2
sonfd

私はhook_menu_local_tasks_alter。現在のエンティティ(ノードなど)はパラメーターとしてこのフックに渡されないため、個別にクエリする必要があることに注意してください。

このようなもの:

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

Drupal 8ガイド/モジュール定義のアクションの提供 には、2つの有用なアプローチの概要が示されています。これらは:

  1. 1つまたは複数のアクションを動的に生成するデリバ
  2. アクションのカスタムクラス

アプローチ1で問題をほぼ解決しました。しかし、私はまだキャッシュに苦労しています。これはこれまでの私の解決策です:

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;
 }
}

そしてmymodule.links.action.ymlで:

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

上記のように、キャッシングは依然として問題です。適切なキャッシュタグを設定しても、アクションはキャッシュからレンダリングされます。

関連する質問:

0
Hendrik