From edc0ccc1badc1c4af2f3bfbe66d2d78a4eba5458 Mon Sep 17 00:00:00 2001
From: Nathaniel Catchpole <catch@35733.no-reply.drupal.org>
Date: Wed, 5 Feb 2014 10:50:00 +0000
Subject: [PATCH] Issue #2160575 by agentrickard, amateescu, plopesc: Option
 widgets integration is broken for the entity reference field.

---
 .../entity_reference/entity_reference.module  | 21 ------
 .../ConfigurableEntityReferenceItem.php       | 69 ++++++++++++++++++-
 .../Tests/EntityReferenceIntegrationTest.php  | 20 +++++-
 .../selection/TermSelection.php               |  5 +-
 4 files changed, 89 insertions(+), 26 deletions(-)

diff --git a/core/modules/entity_reference/entity_reference.module b/core/modules/entity_reference/entity_reference.module
index 7f6b51c30c25..7f79580b0b01 100644
--- a/core/modules/entity_reference/entity_reference.module
+++ b/core/modules/entity_reference/entity_reference.module
@@ -167,27 +167,6 @@ function entity_reference_settings_ajax_submit($form, &$form_state) {
   $form_state['rebuild'] = TRUE;
 }
 
-/**
- * Implements hook_options_list().
- */
-function entity_reference_options_list(FieldDefinitionInterface $field_definition, EntityInterface $entity) {
-  if (!$options = \Drupal::service('plugin.manager.entity_reference.selection')->getSelectionHandler($field_definition, $entity)->getReferenceableEntities()) {
-    return array();
-  }
-
-  // Rebuild the array by changing the bundle key into the bundle label.
-  $target_type = $field_definition->getSetting('target_type');
-  $bundles = entity_get_bundles($target_type);
-
-  $return = array();
-  foreach ($options as $bundle => $entity_ids) {
-    $bundle_label = check_plain($bundles[$bundle]['label']);
-    $return[$bundle_label] = $entity_ids;
-  }
-
-  return count($return) == 1 ? reset($return) : $return;
-}
-
 /**
  * Implements hook_query_TAG_alter().
  */
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/ConfigurableEntityReferenceItem.php b/core/modules/entity_reference/lib/Drupal/entity_reference/ConfigurableEntityReferenceItem.php
index 1a2a6181e1a9..73cee86ed7b0 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/ConfigurableEntityReferenceItem.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/ConfigurableEntityReferenceItem.php
@@ -7,10 +7,14 @@
 
 namespace Drupal\entity_reference;
 
+use Drupal\Component\Utility\String;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\Core\TypedData\AllowedValuesInterface;
 use Drupal\Core\TypedData\DataDefinition;
 use Drupal\Core\Field\FieldDefinitionInterface;
 use Drupal\Core\Field\ConfigEntityReferenceItemBase;
 use Drupal\Core\Field\ConfigFieldItemInterface;
+use Drupal\Core\Validation\Plugin\Validation\Constraint\AllowedValuesConstraint;
 
 /**
  * Alternative plugin implementation of the 'entity_reference' field type.
@@ -24,7 +28,53 @@
  * @see entity_reference_field_info_alter().
  *
  */
-class ConfigurableEntityReferenceItem extends ConfigEntityReferenceItemBase implements ConfigFieldItemInterface {
+class ConfigurableEntityReferenceItem extends ConfigEntityReferenceItemBase implements ConfigFieldItemInterface, AllowedValuesInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getPossibleValues(AccountInterface $account = NULL) {
+    return $this->getSettableValues($account);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getPossibleOptions(AccountInterface $account = NULL) {
+    return $this->getSettableOptions($account);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getSettableValues(AccountInterface $account = NULL) {
+    // Flatten options firstly, because Settable Options may contain group
+    // arrays.
+    $flatten_options = \Drupal::formBuilder()->flattenOptions($this->getSettableOptions($account));
+    return array_keys($flatten_options);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getSettableOptions(AccountInterface $account = NULL) {
+    $field_definition = $this->getFieldDefinition();
+    if (!$options = \Drupal::service('plugin.manager.entity_reference.selection')->getSelectionHandler($field_definition, $this->getEntity())->getReferenceableEntities()) {
+      return array();
+    }
+
+    // Rebuild the array by changing the bundle key into the bundle label.
+    $target_type = $field_definition->getSetting('target_type');
+    $bundles = \Drupal::entityManager()->getBundleInfo($target_type);
+
+    $return = array();
+    foreach ($options as $bundle => $entity_ids) {
+      $bundle_label = String::checkPlain($bundles[$bundle]['label']);
+      $return[$bundle_label] = $entity_ids;
+    }
+
+    return count($return) == 1 ? reset($return) : $return;
+  }
 
   /**
    * Definitions of the contained properties.
@@ -63,6 +113,23 @@ public function getPropertyDefinitions() {
     return static::$propertyDefinitions[$key];
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getConstraints() {
+    $constraints = parent::getConstraints();
+
+    // Remove the 'AllowedValuesConstraint' validation constraint because entity
+    // reference fields already use the 'ValidReference' constraint.
+    foreach ($constraints as $key => $constraint) {
+      if ($constraint instanceof AllowedValuesConstraint) {
+        unset($constraints[$key]);
+      }
+    }
+
+    return $constraints;
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceIntegrationTest.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceIntegrationTest.php
index 76efe3d4c8a0..3a892b2652f7 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceIntegrationTest.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceIntegrationTest.php
@@ -40,7 +40,7 @@ class EntityReferenceIntegrationTest extends WebTestBase {
    *
    * @var array
    */
-  public static $modules = array('config_test', 'entity_test', 'entity_reference');
+  public static $modules = array('config_test', 'entity_test', 'entity_reference', 'options');
 
   public static function getInfo() {
     return array(
@@ -62,7 +62,7 @@ public function setUp() {
   }
 
   /**
-   * Tests the entity reference field with all its widgets.
+   * Tests the entity reference field with all its supported field widgets.
    */
   public function testSupportedEntityTypesAndWidgets() {
     foreach ($this->getTestEntities() as $referenced_entities) {
@@ -111,6 +111,22 @@ public function testSupportedEntityTypesAndWidgets() {
       $entity = current(entity_load_multiple_by_properties($this->entityType, array('name' => $entity_name)));
       $this->drupalPostForm($this->entityType . '/manage/' . $entity->id(), array(), t('Save'));
       $this->assertFieldValues($entity_name, $referenced_entities);
+
+      // Test all the other widgets supported by the entity reference field.
+      // Since we don't know the form structure for these widgets, just test
+      // that editing and saving an already created entity works.
+      $entity = current(entity_load_multiple_by_properties($this->entityType, array('name' => $entity_name)));
+      $supported_widgets = \Drupal::service('plugin.manager.field.widget')->getOptions('entity_reference');
+      $supported_widget_types = array_diff(array_keys($supported_widgets), array('entity_reference_autocomplete', 'entity_reference_autocomplete_tags'));
+
+      foreach ($supported_widget_types as $widget_type) {
+        entity_get_form_display($this->entityType, $this->bundle, 'default')->setComponent($this->fieldName, array(
+          'type' => $widget_type,
+        ))->save();
+
+        $this->drupalPostForm($this->entityType . '/manage/' . $entity->id(), array(), t('Save'));
+        $this->assertFieldValues($entity_name, $referenced_entities);
+      }
     }
   }
 
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/entity_reference/selection/TermSelection.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/entity_reference/selection/TermSelection.php
index 7894242fc521..436484522745 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/entity_reference/selection/TermSelection.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/entity_reference/selection/TermSelection.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\taxonomy\Plugin\entity_reference\selection;
 
+use Drupal\Component\Utility\String;
 use Drupal\Core\Database\Query\SelectInterface;
 use Drupal\Core\Field\FieldDefinitionInterface;
 use Drupal\entity_reference\Plugin\entity_reference\selection\SelectionBase;
@@ -63,9 +64,9 @@ public function getReferenceableEntities($match = NULL, $match_operator = 'CONTA
 
     foreach ($bundle_names as $bundle) {
       if ($vocabulary = entity_load('taxonomy_vocabulary', $bundle)) {
-        if ($terms = taxonomy_get_tree($vocabulary->id(), 0)) {
+        if ($terms = taxonomy_get_tree($vocabulary->id(), 0, NULL, TRUE)) {
           foreach ($terms as $term) {
-            $options[$vocabulary->id()][$term->id()] = str_repeat('-', $term->depth) . check_plain($term->name);
+            $options[$vocabulary->id()][$term->id()] = str_repeat('-', $term->depth) . String::checkPlain($term->label());
           }
         }
       }
-- 
GitLab