You are here

public function TermSelection::getReferenceableEntities in Taxonomy container 8

That actually violates parent interface. The method should return entity labels not grouped options for a select list. Technically core selection plugin also does this in a wrong way because it puts dashed in front of entity labels. The proper solution could be creating a field widget for entity_reference field. However that would be not possible to register it only for a specific entity type (Taxonomy Term).

Overrides TermSelection::getReferenceableEntities

See also

\Drupal\Core\Entity\EntityReferenceSelection\SelectionInterface::getReferenceableEntities()

File

src/Plugin/EntityReferenceSelection/TermSelection.php, line 60

Class

TermSelection
Taxonomy container implementation of the entity reference selection plugin.

Namespace

Drupal\taxonomy_container\Plugin\EntityReferenceSelection

Code

public function getReferenceableEntities($match = NULL, $match_operator = 'CONTAINS', $limit = 0) {
  if ($match || $limit) {
    return parent::getReferenceableEntities($match, $match_operator, $limit);
  }
  $bundles = $this->entityTypeBundleInfo
    ->getBundleInfo('taxonomy_term');
  $bundle_names = $this
    ->getConfiguration()['target_bundles'] ?: array_keys($bundles);

  /** @var \Drupal\taxonomy\TermStorageInterface $term_storage */
  $term_storage = $this->entityTypeManager
    ->getStorage('taxonomy_term');
  $prefix = $this->configuration['prefix'];
  $options = [];
  foreach ($bundle_names as $bundle) {

    // Use first bundle as key. This prevents turning bundle labels into
    // optgroups when more than one bundle were provided.
    // See \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem::getSettableOptions().
    // phpcs:ignore DrupalPractice.CodeAnalysis.VariableAnalysis.UndefinedVariable
    if (!isset($key)) {
      $key = $bundle;
    }

    /** @var \Drupal\taxonomy\TermInterface[] $terms */
    $terms = $term_storage
      ->loadTree($bundle, 0, NULL, TRUE);
    $protected_terms = [];

    /** @var string $parent_id */

    /** @var string $parent_label */
    foreach ($terms as $term) {
      $access = TRUE;
      if (!$term
        ->access('view') || in_array($term->parent->target_id, $protected_terms)) {
        $protected_terms[] = $term
          ->id();
        $access = FALSE;
      }

      // Check if this is a parent item. We do a loose comparison on the
      // string value of zero ('0') so that the result is correct both for
      // numeric and string IDs. If we would compare to the numeric value of
      // zero (0) PHP would cast both arguments to numbers. In the case of
      // string IDs the ID would always be casted to a 0 causing the
      // condition to always be TRUE.
      if ($term->parent->target_id == '0') {
        $parent_id = $term
          ->id();
        $parent_label = Html::escape($this->entityRepository
          ->getTranslationFromContext($term)
          ->label());
        if ($access) {
          $options[$key][$term
            ->id()] = $parent_label;
        }
      }
      else {
        if ($access) {
          $label = Html::escape($this->entityRepository
            ->getTranslationFromContext($term)
            ->label());
          $options[$key][$parent_label][$term
            ->id()] = str_repeat($prefix, $term->depth) . $label;
        }

        // If at least on child has been found, remove the top level term.
        unset($options[$key][$parent_id]);
      }
    }
  }
  return $options;
}