Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document how to create a view using "has member-of values"-logic #1694

Open
rosiel opened this issue Nov 17, 2020 · 2 comments
Open

Document how to create a view using "has member-of values"-logic #1694

rosiel opened this issue Nov 17, 2020 · 2 comments
Labels
help wanted Seeking a volunteer or co-worker Type: documentation provides documentation or asks for documentation.

Comments

@rosiel
Copy link
Member

rosiel commented Nov 17, 2020

@seth-shaw-unlv pointed this possibility out in the sandbox call.

@seth-shaw-unlv
Copy link
Contributor

I use a locally developed context condition plugin:

<?php

namespace Drupal\islandora_local\Plugin\Condition;

use Drupal\Core\Condition\ConditionPluginBase;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\field\Entity\FieldStorageConfig;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Condition to detect if is a node is referenced by a configured field.
 *
 * @Condition(
 *   id = "node_referenced_by_field",
 *   label = @Translation("Node referenced by field"),
 *   context = {
 *     "node" = @ContextDefinition("entity:node", required = TRUE , label = @Translation("node"))
 *   }
 * )
 */
class NodeReferencedByField extends ConditionPluginBase implements ContainerFactoryPluginInterface {

  /**
   * Node storage.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * Constructor.
   *
   * @param array $configuration
   *   The plugin configuration, i.e. an array with configuration values keyed
   *   by configuration option name. The special key 'context' may be used to
   *   initialize the defined contexts by setting it to an array of context
   *   values keyed by context names.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   Entity type manager.
   */
  public function __construct(
    array $configuration,
    $plugin_id,
    $plugin_definition,
    EntityTypeManagerInterface $entity_type_manager
  ) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->entityTypeManager = $entity_type_manager;
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return parent::defaultConfiguration() + [
      'reference_field' => 'field_member_of',
    ];
  }

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

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
    $field_map = \Drupal::service('entity_field.manager')->getFieldMapByFieldType('entity_reference');
    $node_fields = array_keys($field_map['node']);
    $options = array_combine($node_fields, $node_fields);
    $form['reference_field'] = [
      '#type' => 'select',
      '#title' => t('Field to check for reference to this node'),
      '#options' => $options,
      '#default_value' => $this->configuration['reference_field'],
      '#required' => TRUE,
      '#description' => t("Machine name of field that should be checked for references to this node."),
    ];

    return parent::buildConfigurationForm($form, $form_state);
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
    $this->configuration['reference_field'] = $form_state->getValue('reference_field');
    parent::submitConfigurationForm($form, $form_state);
  }

  /**
   * {@inheritdoc}
   */
  public function evaluate() {
    $node = $this->getContextValue('node');
    if (!$node) {
      return FALSE;
    }
    return $this->evaluateEntity($node);
  }

  /**
   * Evaluates if an entity is referenced in the configured node field.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The entity to evaluate.
   *
   * @return bool
   *   TRUE if entity is referenced..
   */
  protected function evaluateEntity(EntityInterface $entity) {
    $reference_field = $this->configuration['reference_field'];
    $config = FieldStorageConfig::loadByName('node', $reference_field);
    if ($config) {
      $id_count = \Drupal::entityQuery('node')
        ->condition($reference_field, $entity->id())
        ->count()
        ->execute();
      return ($id_count > 0);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function summary() {
    if (!empty($this->configuration['negate'])) {
      return $this->t('The node is not referenced in the field @field.', ['@field' => $this->configuration['reference_field']]);
    }
    else {
      return $this->t('The node is referenced in the field @field.', ['@field' => $this->configuration['reference_field']]);
    }
  }

}

I use the condition in a new 'complex object' context with the field_member_of and a display_mode reaction to get the appropriate view:

Complex Digital Object context configuration using the node_referenced_by_field included above and the display mode reaction.

Side note: I also add a negated service file media is PDF in case we have PDF rendition that makes more sense to display, but that isn't required for the general strategy to work.

I had forgotten it was a local condition plugin. Sometimes I forget what I've turned into PRs and what I haven't.

@dannylamb
Copy link
Contributor

We have the feature now, but this still needs documentation. Adding the 'help wanted' tag.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Seeking a volunteer or co-worker Type: documentation provides documentation or asks for documentation.
Projects
Development

No branches or pull requests

4 participants