7

What I want to do is edit what is displayed in the autocomplete/drop selects for an entity reference. Basically instead of just [title] I want to show [title] - [other_distinguishing_field]. I know that I can do this by editing getReferenceableEntities in Drupal\Core\Entity\Plugin\EntityReferenceSelection. All I want to do is override that function. I read that I need to make a plugin for this, but I find all of the tutorials a bit confusing and I don't understand how to implement what I want using a plugin. Do I need a plugin manager? Do I need to use annotations? Where do I reference Drupal\Core\Entity\Plugin\EntityReferenceSelection? Where do I override the function? Do I need to configure anything on the UI the use my plugin or will it automatically work?

**EDIT Here is what my Plugin manager looks like using the solution provided by @ya.teck

    <?php
/**
 * @file
 * Contains ExampleEntityReferenceManager
 */

namespace Drupal\example;

use Drupal\Core\Plugin\DefaultPluginManager;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;

/**
 * ExampleEntityReference plugin manager.
 */
class ExampleEntityReferenceManager extends DefaultPluginManager {

  /**
   * Constructs an ExampleEntityReferenceManager object.
   *
   * @param \Traversable $namespaces
   *   An object that implements \Traversable which contains the root paths
   *   keyed by the corresponding namespace to look for plugin implementations,
   * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
   *   Cache backend instance to use.
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
   *   The module handler to invoke the alter hook with.
   */
  public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
    parent::__construct('Plugin/EntityReferenceSelection', $namespaces, $module_handler, 'Drupal\Core\Entity\EntityManagerInterface', 'Drupal\Core\Entity\Annotation\EntityReferenceSelection');

    $this->alterInfo('example_entity_reference_manager_info');
    $this->setCacheBackend($cache_backend, 'example_entity_reference');
  }
}
1
  • 5
    Please don't implement your answer in your question. Instead it's much better to add another answer, so others can find it where they expect it to be. It's totally OK to answer you own questions.
    – leymannx
    Nov 17, 2016 at 13:58

2 Answers 2

8

Method #1 You can simply create new plugin which extends class of target Core plugin.

File: modules/example/src/Plugin/EntityReferenceSelection/ExampleSelection.php

namespace Drupal\example\Plugin\EntityReferenceSelection;

use Drupal\Component\Utility\Html;
use Drupal\Core\Entity\Plugin\EntityReferenceSelection\DefaultSelection;

/**
 * Entity Reference Selection with distinguishing field.
 *
 * @EntityReferenceSelection(
 *   id = "example",
 *   label = @Translation("Example"),
 *   group = "example",
 * )
 */
class ExampleSelection extends DefaultSelection {

  /**
   * {@inheritdoc}
   */
  public function getReferenceableEntities($match = NULL, $match_operator = 'CONTAINS', $limit = 0) {
    $target_type = $this->configuration['target_type'];

    $query = $this->buildEntityQuery($match, $match_operator);
    if ($limit > 0) {
      $query->range(0, $limit);
    }

    $result = $query->execute();

    if (empty($result)) {
      return [];
    }

    $options = array();
    $entities = $this->entityManager->getStorage($target_type)->loadMultiple($result);
    foreach ($entities as $entity_id => $entity) {
      $bundle = $entity->bundle();

      $translated_entity = $this->entityManager->getTranslationFromContext($entity);
      $label = $translated_entity->label();
      $distinguishing_field = $translated_entity->get('field_example')->get(0);
      if ($distinguishing_field) {
        $label .= ' [' . $distinguishing_field->getValue()['value'] . ']';
      }
      $options[$bundle][$entity_id] = Html::escape($label);
    }

    return $options;
  }

}

Having this done navigate to field settings page and enable your reference method.

Method #2 For select list widget you can install Entity Reference Views Select which allows to build selection options using Views fields.

Method #3 Content Browser module (not stable yet) offers more advanced way to select entities.

Method #4 You may globally override Entity::label() method for required entity type. So that the [title] - [other_distinguishing_field] pattern will be used everywhere including default entity reference selection plugin.

2
  • For method #1, what happens when 2 modules extend the same plugin class? Which "wins"?
    – Clive
    Nov 11, 2016 at 8:47
  • The one selected on field settings form wins. So it doesn't matter how many selection plugins exist until they have unique IDs (configured in annotation). I've just updated the answer.
    – ya.teck
    Nov 11, 2016 at 11:01
0

You should implement hook_entity_reference_selection_alter().

function mymodule_entity_reference_selection_alter(&$definitions) {
  // Change your class here.
} 

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.