現在の選択をエンティティブラウザーの選択ビューに渡す方法


8

私が使用していますエンティティブラウザカスタムエンティティのエンティティ参照ベースフィールドのためのフォームウィジェットとして(Drupalの8で2.xの-devのを)。エンティティブラウザが構成されている

  • モーダルディスプレイとして、
  • 単一のウィジェットで、
  • 選択表示なし、
  • エンティティブラウザーの一括選択フィールドを持つビューをウィジェットとして使用し、
  • 選択したエンティティを参照フィールドの現在の選択に追加します。

エンティティの選択は正常に機能しています。ただし、エンティティ参照フィールドには重複があってはなりません。

重複のないエンティティの選択を容易にするために、エンティティブラウザビューの結果から既に選択されているエンティティをフィルタリングします。したがって、ユーザーには選択されていないエンティティのみが表示されます。

この目的のために、エンティティIDのコンテキストデフォルト引数としてエンティティブラウザー選択ストレージを公開するカスタムビューargument_defaultプラグインを作成しました。

<?php

namespace Drupal\my_module\Plugin\views\argument_default;

use Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface;
use Drupal\views\Plugin\views\argument_default\ArgumentDefaultPluginBase;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * The entity browser selection argument default handler.
 *
 * @ViewsArgumentDefault(
 *   id = "entity_browser_selection",
 *   title = @Translation("Entity Browser Selection")
 * )
 */
class EntityBrowserSelection extends ArgumentDefaultPluginBase {

  /**
   * The selection storage.
   *
   * @var \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface
   */
  protected $selectionStorage;

  /**
   * {@inheritdoc}
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, KeyValueStoreExpirableInterface $selection_storage) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->selectionStorage = $selection_storage;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('entity_browser.selection_storage')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function access() {
    return $this->view->getDisplay()->pluginId === 'entity_browser';
  }

  /**
   * {@inheritdoc}
   */
  public function getArgument() {
    $argument = NULL;
    $current_request = $this->view->getRequest();

    // Check if the widget context is available.
    if ($current_request->query->has('uuid')) {
      $uuid = $current_request->query->get('uuid');
      if ($storage = $this->selectionStorage->get($uuid)) {
        if (!empty($storage['selected_entities'])) {
          $argument = $storage['selected_entities'];
        }
      }
    }
    return $argument;
  }

}

私が直面している問題は、エンティティ参照フィールドで選択されているエンティティの数に関係なく、選択ストレージ内の現在の選択は常に空であり、モーダル選択を完了してエンティティブラウザを再度開いた後でもです。

エンティティブラウザーの選択ストレージに現在の選択を公開するには、何をする必要がありますか?


待機していて、モーダルで選択可能なアイテムとして表示したくないアイテムをすべて選択(および保存)した場合、または、オンザフライでの重複した選択を許可しないことを意味しますか...または、選択した場合にすべてのコンテンツにわたって一意のデータが必要な場合にビューから非表示にしますか?
taggartJ 2019年

両方の場合。エンティティが新しく、モーダルが関連エンティティの選択に使用されている場合、[選択]ボタンをもう一度クリックすると(エンティティが保存される前に)、選択内容は既にエンティティブラウザからフィルタリングされます。そしてもちろん、それが保存されて再編集されようとしている後、現在の選択(#default_value)もフィルターと見なされる必要があります。
Mario Steinitz

回答:


4

エンティティブラウザーは現在、永続データの現在のデフォルト値の項目フィールドを渡しませんが、簡単に追加できます。

1)field_widget_form_alter()を使用して永続データを追加します

/**
 * Implements hook_field_widget_form_alter().
 */
function mymodule_field_widget_form_alter(&$element, FormStateInterface &$form_state, $context) {
  if (!empty($element['entity_browser'])) {
    $default_value =  $element['entity_browser']['#default_value'];
    $ids = [];
    foreach ($default_value as $entity) {
      $ids[] = $entity->id();
    }
    $element['entity_browser']['#widget_context']['current_ids'] = implode('+', $ids);
  }
}

2)選択を更新して、空白の場合にすべてが表示されるようにします。

  /**
   * {@inheritdoc}
   */
  public function getArgument() {
    $argument = NULL;
    $current_request = $this->view->getRequest();

    // Check if the widget context is available.
    if ($current_request->query->has('uuid')) {
      $uuid = $current_request->query->get('uuid');
      if ($storage = $this->selectionStorage->get($uuid)) {
        if (!empty($storage['widget_context']['current_ids'])) {
          $argument = $storage['widget_context']['current_ids'];
        }
        else {
          $argument = 'all';
        }
      }
    }
    return $argument;
  }

3)選択で「除外」と「複数許可」がチェックされていることを確認してください。

ここに画像の説明を入力してください

ちなみに、entity_browserの最新の開発リリースに更新する場合は、カスタムプラグインは必要ありません。構成可能な新しいentity_browser_widget_contextデフォルト値ビュープラグインがあります。

また、widget_contextにあるときにこの情報を追加するために、entity_browserキュー問題を追加しまし


2

デフォルトの引数クラスを使用して、少しデバッグしました。これは私のアプローチです:

エンティティブラウザーウィジェットcurrentは、エンティティフォームが既存のエンティティ/選択で開かれたときに、選択された値をそのプロパティに格納します。ウィジェットは、モーダルが閉じ、currentそれに応じてプロパティが更新されるときにもAJAXを使用します。

したがって、エンティティフォーム/フォームの変更で次のようなものを使用して、選択したエンティティIDを取得できます。

use Drupal\Core\Render\Element;

// Current selection. Replace 'field_references' with the actual
// name of your field.
$selection = [];
if (isset($form['field_references']['widget']['current'])) {
  $current = $form['time_records']['widget']['current'];
  foreach (Element::children($current) as $key) {
    if (isset($current[$key]['target_id']['#value'])) {
      $selection[] = $current[$key]['target_id']['#value'];
    }
  }
}

フォームで使用できるもう1つのウィジェットプロパティは、使用されるエンティティブラウザーのウィジェットコンテキストです。現在の選択をウィジェットコンテキストに追加し、この情報をビューのデフォルト引数で使用できます(ウィジェットコンテキストは、ウィジェット/フォームの各AJAXリロードの選択ストレージで更新されます)。

$form['field_references']['widget']['entity_browser']['#widget_context']['current_selection'] = $selection;

次にあなたを変更しますEntityBrowserSelection::getArgument()

  /**
   * {@inheritdoc}
   */
  public function getArgument() {
    $argument = NULL;
    $current_request = $this->view->getRequest();

    // Check if the widget context is available.
    if ($current_request->query->has('uuid')) {
      $uuid = $current_request->query->get('uuid');
      if ($storage = $this->selectionStorage->get($uuid)) {
        if (!empty($storage['widget_context']['current_selection'])) {
          $selection = $storage['widget_context']['current_selection'];
          if (is_string($selection)) {
            $argument = $selection;
          }
          elseif (is_array($selection)) {
            $non_scalar = array_filter($selection, function ($item) {
              return !is_scalar($item);
            });
            if (empty($non_scalar)) {
              // Replace the ',' with '+', if you like to have an
              // OR filter rather than an AND filter.
              $argument = implode(',', $selection);
            }
          }
        }
      }
    }
    return $argument;
  }

これらの変更により、エンティティIDのコンテキストフィルターを使用して、ビューから選択したアイテムをフィルターすることができました。

  • フィルターが使用できない場合:デフォルト値を入力し、「エンティティブラウザーの選択」と入力します。
  • 詳細:除外

それが役に立てば幸い!


0

デフォルトのフィルターを機能させることはできませんでしたが、次の恐ろしさを実行することにある程度成功しました。

function mymodule_views_pre_render(\Drupal\views\ViewExecutable $view) {
  if ($view->id() == "media_entity_browser" && $view->current_display ==
    'entity_browser_1') {
    $request = \Drupal::request();
    $prams = $request->query->all();
    $is_edit = FALSE;
    if (!empty($prams['original_path'])) {
      // testing with "/node/1/edit"
      $check_explode = explode('/', $prams['original_path']);
      if (in_array('edit', $check_explode)) {
        $edit_key = array_search ( 'edit', $check_explode);
        $entity_id_key = $edit_key - 1;
        $entity_id = $check_explode[$entity_id_key];
        $entity_type_key = $edit_key - 2;
        $entity_type = $check_explode[$entity_type_key];
        $selected_ids = [];
        try {
          $entity = \Drupal::entityTypeManager()->getStorage($entity_type)->load($entity_id);
          // This sucks bacause field name is hardcoded.
          $media_entities = $entity->field_image->referencedEntities();
          if (!empty($media_entities)) {
            foreach ($media_entities as $media_entity) {
              $selected_ids[] = (int) $media_entity->id();
            }
          }
        }
        catch (\Exception $e) {
          // log this.
        }

        $my_results = [];
        // Now need to remove from view.
        if (!empty($selected_ids)) {
          $i = 0;
          foreach ($view->result as $key =>  $item) {
            $id = (int) $item->_entity->id();
            if (!in_array($id, $selected_ids)) {
              $my_results[] = new ResultRow([
                '_entity' => $item->_entity,
                'index' => $i,
                'mid' => $item->_entity->id(),
              ]);
              $i++;
            }
          }
          $view->result = $my_results;
        }
      }
    }
  }
}

これは機能します。ただし、かなりの数の前提条件があります...良いことエンティティブラウザーでは、どのビューを選択できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.