diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Field/FieldWidget/AutocompleteTagsWidget.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Field/FieldWidget/AutocompleteTagsWidget.php index abcbde47a5ceb8a7cd7b7cec8fc4d5999d3b6424..9c41b2ae9738c6893e5b4c9458a040b83cf51719 100644 --- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Field/FieldWidget/AutocompleteTagsWidget.php +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Field/FieldWidget/AutocompleteTagsWidget.php @@ -45,10 +45,15 @@ public function elementValidate($element, &$form_state, $form) { foreach (drupal_explode_tags($element['#value']) as $input) { $match = FALSE; - // Take "label (entity id)', match the id from parenthesis. + // Take "label (entity id)', match the ID from parenthesis when it's a + // number. if (preg_match("/.+\((\d+)\)/", $input, $matches)) { $match = $matches[1]; } + // Match the ID when it's a string (e.g. for config entity types). + elseif (preg_match("/.+\(([\w.]+)\)/", $input, $matches)) { + $match = $matches[1]; + } else { // Try to get a match from the input string when the user didn't use // the autocomplete but filled in a value manually. diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Field/FieldWidget/AutocompleteWidget.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Field/FieldWidget/AutocompleteWidget.php index bcaafaff0540434b5413413dd0ea654c020c1e09..f0719fec3797adba5dc98f110116dc30815cb411 100644 --- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Field/FieldWidget/AutocompleteWidget.php +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Field/FieldWidget/AutocompleteWidget.php @@ -38,17 +38,13 @@ class AutocompleteWidget extends AutocompleteWidgetBase { /** * {@inheritdoc} */ - public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, array &$form_state) { - // We let the Field API handles multiple values for us, only take care of - // the one matching our delta. + protected function getEntityIds(FieldItemListInterface $items, $delta) { + // The autocomplete widget outputs one entity label per form element. if (isset($items[$delta])) { - $items->setValue(array($items[$delta]->getValue())); - } - else { - $items->setValue(array()); + return array($items[$delta]->target_id); } - return parent::formElement($items, $delta, $element, $form, $form_state); + return array(); } /** diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Field/FieldWidget/AutocompleteWidgetBase.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Field/FieldWidget/AutocompleteWidgetBase.php index e660056083c1a7fe56f1ab40ce1700584d5a5134..fd88603c6c25862d674baf5a06dfe4f3d0968b23 100644 --- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Field/FieldWidget/AutocompleteWidgetBase.php +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Field/FieldWidget/AutocompleteWidgetBase.php @@ -88,7 +88,7 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen $element += array( '#type' => 'textfield', '#maxlength' => 1024, - '#default_value' => implode(', ', $this->getLabels($items)), + '#default_value' => implode(', ', $this->getLabels($items, $delta)), '#autocomplete_route_name' => 'entity_reference.autocomplete', '#autocomplete_route_parameters' => $autocomplete_route_parameters, '#size' => $this->getSetting('size'), @@ -116,21 +116,15 @@ public function elementValidate($element, &$form_state, $form) { } /** * Gets the entity labels. */ - protected function getLabels(FieldItemListInterface $items) { + protected function getLabels(FieldItemListInterface $items, $delta) { if ($items->isEmpty()) { return array(); } - $entity_ids = array(); $entity_labels = array(); - // Build an array of entity IDs. - foreach ($items as $item) { - $entity_ids[] = $item->target_id; - } - // Load those entities and loop through them to extract their labels. - $entities = entity_load_multiple($this->getFieldSetting('target_type'), $entity_ids); + $entities = entity_load_multiple($this->getFieldSetting('target_type'), $this->getEntityIds($items, $delta)); foreach ($entities as $entity_id => $entity_item) { $label = $entity_item->label(); @@ -144,6 +138,27 @@ protected function getLabels(FieldItemListInterface $items) { return $entity_labels; } + /** + * Builds an array of entity IDs for which to get the entity labels. + * + * @param \Drupal\Core\Field\FieldItemListInterface $items + * Array of default values for this field. + * @param int $delta + * The order of a field item in the array of subelements (0, 1, 2, etc). + * + * @return array + * An array of entity IDs. + */ + protected function getEntityIds(FieldItemListInterface $items, $delta) { + $entity_ids = array(); + + foreach ($items as $item) { + $entity_ids[] = $item->target_id; + } + + return $entity_ids; + } + /** * Creates a new entity from a label entered in the autocomplete input. * 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 2d17a780c2cfc3d6a26e51453a408d2110788967..97acd3d1fcbea596d120584c824aa8ea41b6ebef 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 @@ -33,7 +33,7 @@ class EntityReferenceIntegrationTest extends WebTestBase { * * @var string */ - protected $fieldName = 'field_test'; + protected $fieldName; /** * Modules to enable. @@ -62,34 +62,107 @@ public function setUp() { } /** - * Tests the autocomplete widget when targeting a config entity type. + * Tests the entity reference field with all its widgets. */ - public function testConfigAutocompleteWidget() { - // Create an Entity reference field targeting a config entity type. - entity_reference_create_instance($this->entityType, $this->bundle, $this->fieldName, 'Field test', 'config_test'); - - // Add the field to the default form mode. - entity_get_form_display($this->entityType, $this->bundle, 'default')->setComponent($this->fieldName)->save(); - - // Create a test config entity. - $config_entity_id = $this->randomName(); - $config_entity_label = $this->randomString(); - $config_entity = entity_create('config_test', array('id' => $config_entity_id, 'label' => $config_entity_label)); - $config_entity->save(); - - $entity_name = $this->randomName(); - $edit = array( - 'name' => $entity_name, - 'user_id' => mt_rand(0, 128), - $this->fieldName . '[0][target_id]' => $config_entity_label . ' (' . $config_entity_id . ')', - ); - $this->drupalPostForm($this->entityType . '/add', $edit, t('Save')); + public function testSupportedEntityTypesAndWidgets() { + foreach ($this->getTestEntities() as $referenced_entities) { + $this->fieldName = 'field_test_' . $referenced_entities[0]->entityType(); + + // Create an Entity reference field. + entity_reference_create_instance($this->entityType, $this->bundle, $this->fieldName, $this->fieldName, $referenced_entities[0]->entityType(), 'default', array(), 2); + + // Test the default 'entity_reference_autocomplete' widget. + entity_get_form_display($this->entityType, $this->bundle, 'default')->setComponent($this->fieldName)->save(); + + $entity_name = $this->randomName(); + $edit = array( + 'name' => $entity_name, + 'user_id' => mt_rand(0, 128), + $this->fieldName . '[0][target_id]' => $referenced_entities[0]->label() . ' (' . $referenced_entities[0]->id() . ')', + $this->fieldName . '[1][target_id]' => $referenced_entities[1]->label() . ' (' . $referenced_entities[1]->id() . ')', + ); + $this->drupalPostForm($this->entityType . '/add', $edit, t('Save')); + $this->assertFieldValues($entity_name, $referenced_entities); + + // Try to post the form again with no modification and check if the field + // values remain the same. + $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 the 'entity_reference_autocomplete_tags' widget. + entity_get_form_display($this->entityType, $this->bundle, 'default')->setComponent($this->fieldName, array( + 'type' => 'entity_reference_autocomplete_tags', + ))->save(); + + $entity_name = $this->randomName(); + $target_id = $referenced_entities[0]->label() . ' (' . $referenced_entities[0]->id() . ')'; + $target_id .= ', ' . $referenced_entities[1]->label() . ' (' . $referenced_entities[1]->id() . ')'; + $edit = array( + 'name' => $entity_name, + 'user_id' => mt_rand(0, 128), + $this->fieldName . '[target_id]' => $target_id, + ); + $this->drupalPostForm($this->entityType . '/add', $edit, t('Save')); + $this->assertFieldValues($entity_name, $referenced_entities); + + // Try to post the form again with no modification and check if the field + // values remain the same. + $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); + } + } + + /** + * Asserts that the reference field values are correct. + * + * @param string $entity_name + * The name of the test entity. + * @param \Drupal\Core\Entity\EntityInterface[] $referenced_entities + * An array of referenced entities. + */ + protected function assertFieldValues($entity_name, $referenced_entities) { $entity = current(entity_load_multiple_by_properties($this->entityType, array('name' => $entity_name))); $this->assertTrue($entity, format_string('%entity_type: Entity found in the database.', array('%entity_type' => $this->entityType))); - $this->assertEqual($entity->{$this->fieldName}->target_id, $config_entity_id); - $this->assertEqual($entity->{$this->fieldName}->entity->id(), $config_entity_id); - $this->assertEqual($entity->{$this->fieldName}->entity->label(), $config_entity_label); + + $this->assertEqual($entity->{$this->fieldName}->target_id, $referenced_entities[0]->id()); + $this->assertEqual($entity->{$this->fieldName}->entity->id(), $referenced_entities[0]->id()); + $this->assertEqual($entity->{$this->fieldName}->entity->label(), $referenced_entities[0]->label()); + + $this->assertEqual($entity->{$this->fieldName}[1]->target_id, $referenced_entities[1]->id()); + $this->assertEqual($entity->{$this->fieldName}[1]->entity->id(), $referenced_entities[1]->id()); + $this->assertEqual($entity->{$this->fieldName}[1]->entity->label(), $referenced_entities[1]->label()); + } + + /** + * Creates two content and two config test entities. + * + * @return array + * An array of entity objects. + */ + protected function getTestEntities() { + $config_entity_1 = entity_create('config_test', array('id' => $this->randomName(), 'label' => $this->randomName())); + $config_entity_1->save(); + $config_entity_2 = entity_create('config_test', array('id' => $this->randomName(), 'label' => $this->randomName())); + $config_entity_2->save(); + + $content_entity_1 = entity_create('entity_test', array('name' => $this->randomName())); + $content_entity_1->save(); + $content_entity_2 = entity_create('entity_test', array('name' => $this->randomName())); + $content_entity_2->save(); + + return array( + 'config' => array( + $config_entity_1, + $config_entity_2, + ), + 'content' => array( + $content_entity_1, + $content_entity_2, + ), + ); } }