Cara meneruskan seleksi saat ini ke tampilan pemilihan browser entitas

8

Saya menggunakan Browser Entity (2.x-dev di Drupal 8) sebagai widget bentuk untuk bidang basis referensi entitas entitas kustom. Browser entitas dikonfigurasi

  • sebagai tampilan modal,
  • dengan satu widget,
  • dan tidak ada tampilan pilihan,
  • menggunakan tampilan dengan bidang pilih massal peramban entitas sebagai widget, dan
  • untuk menambahkan entitas yang dipilih ke pemilihan bidang referensi saat ini.

Memilih entitas berfungsi dengan baik. Tetapi bidang referensi entitas tidak boleh memiliki duplikat.

Untuk mempermudah pemilihan entitas tanpa duplikat, saya ingin memfilter entitas yang sudah dipilih dari hasil tampilan browser entitas. Jadi pengguna akan melihat entitas yang tidak dipilih saja.

Untuk tujuan ini, saya membuat plugin custom views argument_default yang memperlihatkan penyimpanan pemilihan browser entitas sebagai argumen default konteks untuk ID entitas:

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

}

Masalah yang saya hadapi, adalah bahwa pemilihan saat ini dalam penyimpanan pemilihan selalu kosong, tidak peduli berapa banyak entitas yang telah dipilih di bidang referensi entitas, dan bahkan setelah saya menyelesaikan pemilihan modal dan membuka browser entitas lagi.

Apa yang harus saya lakukan untuk membuka seleksi saat ini di penyimpanan pilihan browser entitas?

Mario Steinitz
sumber
tunggu jadi maksud Anda jika Anda telah memilih semua (dan menyimpan) item yang tidak Anda inginkan ditampilkan dalam modal sebagai item yang dapat dipilih? atau apakah Anda maksudnya tidak mengizinkan duplikat memilih dengan cepat ... atau apakah Anda maksudnya Anda ingin data unik melintasi semua konten Anda jika dipilih lalu sembunyikan dari tampilan?
taggart
Kedua kasus. Jika entitas baru dan modal digunakan untuk memilih entitas terkait, maka pilihan yang dibuat harus sudah disaring dari browser entitas, setelah mengklik tombol "pilih" lagi (sebelum entitas telah disimpan). Dan tentu saja, setelah disimpan dan akan diedit ulang, pemilihan saat ini ( #default_value) perlu dipertimbangkan juga sebagai filter.
Mario Steinitz

Jawaban:

4

Entity Browser saat ini tidak meneruskan bidang item nilai default saat ini dalam data yang persisten, tetapi mudah untuk menambahkannya.

1) Tambahkan data persisten menggunakan 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) Perbarui pilihan Anda sehingga jika kosong itu menunjukkan semua:

  /**
   * {@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) Pastikan Anda telah "mengecualikan" dan "mengizinkan beberapa" dicentang pada pilihan Anda.

masukkan deskripsi gambar di sini

Omong-omong, jika Anda memperbarui ke rilis dev terbaru dari entity_browser, Anda tidak memerlukan plugin khusus Anda. Ada plugin views nilai entitas entitas_browser_widget_context baru yang dapat dikonfigurasi.

Saya juga menambahkan masalah ke antrian entitas_browser untuk menambahkan informasi ini ketika di widget_context.

oknate
sumber
2

Saya menggunakan kelas argumen default Anda dan sedikit berselisih. Ini pendekatan saya:

Widget peramban entitas menyimpan nilai yang dipilih di currentpropertinya, yang diisi, ketika formulir entitas dibuka dengan entitas / pilihan yang ada. Widget juga menggunakan AJAX ketika modal ditutup dan currentproperti diperbarui sesuai.

Jadi Anda bisa mendapatkan ID entitas yang dipilih menggunakan sesuatu seperti yang berikut di formulir entitas Anda / ubah form:

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

Properti widget lain yang tersedia dalam formulir adalah konteks widget dari browser entitas yang digunakan. Anda cukup menambahkan pilihan saat ini ke konteks widget dan menggunakan informasi ini dengan argumen default tampilan Anda (konteks widget diperbarui dalam penyimpanan pilihan pada setiap isi ulang AJAX dari widget / form):

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

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

Dengan perubahan ini saya dapat memfilter item yang dipilih dari tampilan saya dengan filter kontekstual untuk ID entitas, memilih

  • Ketika filter tidak tersedia: Berikan nilai default, ketik "Entity Browser Selection"
  • Lebih lanjut: Kecualikan

Semoga ini bisa membantu!

Andreas W. Wylach
sumber
0

Saya tidak bisa mendapatkan filter default untuk bekerja tetapi saya berhasil melakukan menakutkan berikut:

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

Ini berhasil. Namun, ada beberapa asumsi yang dibuat ... Browser entitas yang bagus memungkinkan Anda untuk memilih tampilan mana.

taggartJ
sumber