it-swarm.com.de

Übergeben der aktuellen Auswahl an die Auswahlansicht des Entitätsbrowsers

Ich verwende ein Entitätsbrowser (2.x-dev in Drupal 8) als Formular-Widget für das Entitätsreferenzbasisfeld einer benutzerdefinierten Entität. Der Entitätsbrowser ist konfiguriert

  • als modale Anzeige,
  • mit einem einzigen Widget,
  • und keine Auswahlanzeige,
  • verwenden einer Ansicht mit einem Massenauswahlfeld des Entitätsbrowsers als Widget und
  • um ausgewählte Entitäten an die aktuelle Auswahl des Referenzfelds anzuhängen.

Die Auswahl der Entitäten funktioniert einwandfrei. Das Entitätsreferenzfeld darf jedoch keine Duplikate enthalten.

Um die Auswahl von Entitäten ohne Duplikate zu vereinfachen, möchte ich bereits ausgewählte Entitäten aus den Ergebnissen der Entitätsbrowser-Ansicht filtern. Benutzer sehen also nur nicht ausgewählte Entitäten.

Zu diesem Zweck habe ich ein Plugin für benutzerdefinierte Ansichten argument_default erstellt, das den Auswahlspeicher des Entitätsbrowsers als Kontextstandardargument für die Entitäts-ID verfügbar macht:

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

}

Das Problem, dem ich gegenüberstehe, ist, dass die aktuelle Auswahl im Auswahlspeicher immer leer ist, unabhängig davon, wie viele Entitäten im Entitätsreferenzfeld ausgewählt wurden, und selbst nachdem ich die modale Auswahl abgeschlossen und den Entitätsbrowser erneut geöffnet habe.

Was muss ich tun, damit die aktuelle Auswahl im Auswahlspeicher des Entitätsbrowsers angezeigt wird?

8
Mario Steinitz

Der Entitätsbrowser übergibt derzeit kein aktuelles Standardwertelementfeld in persistenten Daten, aber es ist einfach, es hinzuzufügen.

1) Fügen Sie persistente Daten mit field_widget_form_alter () hinzu

/**
 * 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) Aktualisieren Sie Ihre Auswahl so, dass, wenn sie leer ist, alle angezeigt werden:

  /**
   * {@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) Stellen Sie sicher, dass bei Ihrer Auswahl die Option "Ausschließen" und "Mehrere zulassen" aktiviert ist.

enter image description here

Übrigens, wenn Sie auf die neueste Entwicklungsversion von entity_browser aktualisieren, benötigen Sie Ihr benutzerdefiniertes Plugin nicht. Es gibt ein neues Plugin für entity_browser_widget_context Standardwertansichten, das konfiguriert werden kann.

Ich habe auch ein Problem zur Entity_Browser-Warteschlange hinzugefügt , um diese Informationen im Widget-Kontext hinzuzufügen.

4
oknate

Ich habe Ihre Standardargumentklasse verwendet und ein wenig debuggt. Das ist mein Ansatz:

Das Entitätsbrowser-Widget speichert ausgewählte Werte in seiner Eigenschaft current, die gefüllt wird, wenn das Entitätsformular mit einer vorhandenen Entität/Auswahl geöffnet wird. Das Widget verwendet auch AJAX, wenn das Modal geschlossen wird und die Eigenschaft current entsprechend aktualisiert wird.

So können Sie die ausgewählten Entitäts-IDs mithilfe der folgenden Angaben in Ihrem Entitätsformular/Ihrer Formularänderung abrufen:

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

Eine weitere im Formular verfügbare Widget-Eigenschaft ist der Widget-Kontext des verwendeten Entitätsbrowsers. Sie können einfach die aktuelle Auswahl zum Widget-Kontext hinzufügen und diese Informationen mit dem Standardargument Ihrer Ansichten verwenden (der Widget-Kontext wird im Auswahlspeicher bei jedem AJAX Neuladen des Widgets/Formulars aktualisiert):

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

Ändern Sie dann Ihre 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;
  }

Mit diesen Änderungen konnte ich ausgewählte Elemente aus meiner Ansicht mit einem Kontextfilter für die Entitäts-IDs filtern und auswählen

  • Wenn der Filter nicht verfügbar ist: Geben Sie einen Standardwert ein. Geben Sie "Auswahl des Entitätsbrowsers" ein.
  • Mehr: Ausschließen

Ich hoffe es hilft!

2

Ich konnte den Standardfilter nicht zum Laufen bringen, aber ich hatte einige Erfolge mit der folgenden Unheimlichkeit:

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

Das funktioniert. Es werden jedoch einige Annahmen getroffen ... Gut, dass Sie mit dem Entity-Browser auswählen können, welche Ansicht Sie verwenden möchten.

0
Taggart Jensen