Issue #2156649 by likin, amateescu: The 'entity_reference_autocomplete' widget doesn't handle multiple values correctly.
parent
57d2604230
commit
ac9534f80f
|
@ -45,10 +45,15 @@ class AutocompleteTagsWidget extends AutocompleteWidgetBase {
|
||||||
foreach (drupal_explode_tags($element['#value']) as $input) {
|
foreach (drupal_explode_tags($element['#value']) as $input) {
|
||||||
$match = FALSE;
|
$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)) {
|
if (preg_match("/.+\((\d+)\)/", $input, $matches)) {
|
||||||
$match = $matches[1];
|
$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 {
|
else {
|
||||||
// Try to get a match from the input string when the user didn't use
|
// Try to get a match from the input string when the user didn't use
|
||||||
// the autocomplete but filled in a value manually.
|
// the autocomplete but filled in a value manually.
|
||||||
|
|
|
@ -38,17 +38,13 @@ class AutocompleteWidget extends AutocompleteWidgetBase {
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, array &$form_state) {
|
protected function getEntityIds(FieldItemListInterface $items, $delta) {
|
||||||
// We let the Field API handles multiple values for us, only take care of
|
// The autocomplete widget outputs one entity label per form element.
|
||||||
// the one matching our delta.
|
|
||||||
if (isset($items[$delta])) {
|
if (isset($items[$delta])) {
|
||||||
$items->setValue(array($items[$delta]->getValue()));
|
return array($items[$delta]->target_id);
|
||||||
}
|
|
||||||
else {
|
|
||||||
$items->setValue(array());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::formElement($items, $delta, $element, $form, $form_state);
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -88,7 +88,7 @@ abstract class AutocompleteWidgetBase extends WidgetBase {
|
||||||
$element += array(
|
$element += array(
|
||||||
'#type' => 'textfield',
|
'#type' => 'textfield',
|
||||||
'#maxlength' => 1024,
|
'#maxlength' => 1024,
|
||||||
'#default_value' => implode(', ', $this->getLabels($items)),
|
'#default_value' => implode(', ', $this->getLabels($items, $delta)),
|
||||||
'#autocomplete_route_name' => 'entity_reference.autocomplete',
|
'#autocomplete_route_name' => 'entity_reference.autocomplete',
|
||||||
'#autocomplete_route_parameters' => $autocomplete_route_parameters,
|
'#autocomplete_route_parameters' => $autocomplete_route_parameters,
|
||||||
'#size' => $this->getSetting('size'),
|
'#size' => $this->getSetting('size'),
|
||||||
|
@ -116,21 +116,15 @@ abstract class AutocompleteWidgetBase extends WidgetBase {
|
||||||
/**
|
/**
|
||||||
* Gets the entity labels.
|
* Gets the entity labels.
|
||||||
*/
|
*/
|
||||||
protected function getLabels(FieldItemListInterface $items) {
|
protected function getLabels(FieldItemListInterface $items, $delta) {
|
||||||
if ($items->isEmpty()) {
|
if ($items->isEmpty()) {
|
||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
$entity_ids = array();
|
|
||||||
$entity_labels = 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.
|
// 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) {
|
foreach ($entities as $entity_id => $entity_item) {
|
||||||
$label = $entity_item->label();
|
$label = $entity_item->label();
|
||||||
|
@ -144,6 +138,27 @@ abstract class AutocompleteWidgetBase extends WidgetBase {
|
||||||
return $entity_labels;
|
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.
|
* Creates a new entity from a label entered in the autocomplete input.
|
||||||
*
|
*
|
||||||
|
|
|
@ -33,7 +33,7 @@ class EntityReferenceIntegrationTest extends WebTestBase {
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $fieldName = 'field_test';
|
protected $fieldName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Modules to enable.
|
* Modules to enable.
|
||||||
|
@ -62,34 +62,107 @@ class EntityReferenceIntegrationTest extends WebTestBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests the autocomplete widget when targeting a config entity type.
|
* Tests the entity reference field with all its widgets.
|
||||||
*/
|
*/
|
||||||
public function testConfigAutocompleteWidget() {
|
public function testSupportedEntityTypesAndWidgets() {
|
||||||
// Create an Entity reference field targeting a config entity type.
|
foreach ($this->getTestEntities() as $referenced_entities) {
|
||||||
entity_reference_create_instance($this->entityType, $this->bundle, $this->fieldName, 'Field test', 'config_test');
|
$this->fieldName = 'field_test_' . $referenced_entities[0]->entityType();
|
||||||
|
|
||||||
// Add the field to the default form mode.
|
// 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_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();
|
$entity_name = $this->randomName();
|
||||||
$edit = array(
|
$edit = array(
|
||||||
'name' => $entity_name,
|
'name' => $entity_name,
|
||||||
'user_id' => mt_rand(0, 128),
|
'user_id' => mt_rand(0, 128),
|
||||||
$this->fieldName . '[0][target_id]' => $config_entity_label . ' (' . $config_entity_id . ')',
|
$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->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)));
|
$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->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}->target_id, $referenced_entities[0]->id());
|
||||||
$this->assertEqual($entity->{$this->fieldName}->entity->label(), $config_entity_label);
|
$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,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue