Issue #2718697 by damiankloip, dawehner: EntityAutocomplete element cannot handle GET input values
parent
853202a000
commit
677116e149
|
@ -57,13 +57,14 @@ class EntityAutocomplete extends Textfield {
|
||||||
if (is_array($element['#default_value']) && $element['#tags'] !== TRUE) {
|
if (is_array($element['#default_value']) && $element['#tags'] !== TRUE) {
|
||||||
throw new \InvalidArgumentException('The #default_value property is an array but the form element does not allow multiple values.');
|
throw new \InvalidArgumentException('The #default_value property is an array but the form element does not allow multiple values.');
|
||||||
}
|
}
|
||||||
elseif (!is_array($element['#default_value'])) {
|
elseif (!empty($element['#default_value']) && !is_array($element['#default_value'])) {
|
||||||
// Convert the default value into an array for easier processing in
|
// Convert the default value into an array for easier processing in
|
||||||
// static::getEntityLabels().
|
// static::getEntityLabels().
|
||||||
$element['#default_value'] = array($element['#default_value']);
|
$element['#default_value'] = array($element['#default_value']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($element['#default_value'] && !(reset($element['#default_value']) instanceof EntityInterface)) {
|
if ($element['#default_value']) {
|
||||||
|
if (!(reset($element['#default_value']) instanceof EntityInterface)) {
|
||||||
throw new \InvalidArgumentException('The #default_value property has to be an entity object or an array of entity objects.');
|
throw new \InvalidArgumentException('The #default_value property has to be an entity object or an array of entity objects.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,6 +74,19 @@ class EntityAutocomplete extends Textfield {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Potentially the #value is set directly, so it contains the 'target_id'
|
||||||
|
// array structure instead of a string.
|
||||||
|
if ($input !== FALSE && is_array($input)) {
|
||||||
|
$entity_ids = array_map(function(array $item) {
|
||||||
|
return $item['target_id'];
|
||||||
|
}, $input);
|
||||||
|
|
||||||
|
$entities = \Drupal::entityTypeManager()->getStorage($element['#target_type'])->loadMultiple($entity_ids);
|
||||||
|
|
||||||
|
return static::getEntityLabels($entities);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds entity autocomplete functionality to a form element.
|
* Adds entity autocomplete functionality to a form element.
|
||||||
*
|
*
|
||||||
|
@ -136,6 +150,7 @@ class EntityAutocomplete extends Textfield {
|
||||||
*/
|
*/
|
||||||
public static function validateEntityAutocomplete(array &$element, FormStateInterface $form_state, array &$complete_form) {
|
public static function validateEntityAutocomplete(array &$element, FormStateInterface $form_state, array &$complete_form) {
|
||||||
$value = NULL;
|
$value = NULL;
|
||||||
|
|
||||||
if (!empty($element['#value'])) {
|
if (!empty($element['#value'])) {
|
||||||
$options = array(
|
$options = array(
|
||||||
'target_type' => $element['#target_type'],
|
'target_type' => $element['#target_type'],
|
||||||
|
@ -146,7 +161,14 @@ class EntityAutocomplete extends Textfield {
|
||||||
$handler = \Drupal::service('plugin.manager.entity_reference_selection')->getInstance($options);
|
$handler = \Drupal::service('plugin.manager.entity_reference_selection')->getInstance($options);
|
||||||
$autocreate = (bool) $element['#autocreate'] && $handler instanceof SelectionWithAutocreateInterface;
|
$autocreate = (bool) $element['#autocreate'] && $handler instanceof SelectionWithAutocreateInterface;
|
||||||
|
|
||||||
|
// GET forms might pass the validated data around on the next request, in
|
||||||
|
// which case it will already be in the expected format.
|
||||||
|
if (is_array($element['#value'])) {
|
||||||
|
$value = $element['#value'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
$input_values = $element['#tags'] ? Tags::explode($element['#value']) : array($element['#value']);
|
$input_values = $element['#tags'] ? Tags::explode($element['#value']) : array($element['#value']);
|
||||||
|
|
||||||
foreach ($input_values as $input) {
|
foreach ($input_values as $input) {
|
||||||
$match = static::extractEntityIdFromAutocompleteInput($input);
|
$match = static::extractEntityIdFromAutocompleteInput($input);
|
||||||
if ($match === NULL) {
|
if ($match === NULL) {
|
||||||
|
@ -169,6 +191,7 @@ class EntityAutocomplete extends Textfield {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check that the referenced entities are valid, if needed.
|
// Check that the referenced entities are valid, if needed.
|
||||||
if ($element['#validate_reference'] && !empty($value)) {
|
if ($element['#validate_reference'] && !empty($value)) {
|
||||||
|
|
|
@ -28,7 +28,7 @@ class Name extends InOperator {
|
||||||
'#target_type' => 'user',
|
'#target_type' => 'user',
|
||||||
'#tags' => TRUE,
|
'#tags' => TRUE,
|
||||||
'#default_value' => $default_value,
|
'#default_value' => $default_value,
|
||||||
'#process_default_value' => FALSE,
|
'#process_default_value' => $this->isExposed(),
|
||||||
);
|
);
|
||||||
|
|
||||||
$user_input = $form_state->getUserInput();
|
$user_input = $form_state->getUserInput();
|
||||||
|
|
|
@ -137,6 +137,17 @@ class HandlerFilterUserNameTest extends ViewTestBase {
|
||||||
$this->drupalGet($path, $options);
|
$this->drupalGet($path, $options);
|
||||||
$this->assertRaw(t('There are no entities matching "%value".', array('%value' => implode(', ', $users))));
|
$this->assertRaw(t('There are no entities matching "%value".', array('%value' => implode(', ', $users))));
|
||||||
|
|
||||||
|
// Pass in an invalid target_id in for the entity_autocomplete value format.
|
||||||
|
// There should be no errors, but all results should be returned as the
|
||||||
|
// default value for the autocomplete will not match any users so should
|
||||||
|
// be empty.
|
||||||
|
$options['query']['uid'] = [['target_id' => 9999]];
|
||||||
|
$this->drupalGet($path, $options);
|
||||||
|
// The actual result should contain all of the user ids.
|
||||||
|
foreach ($this->accounts as $account) {
|
||||||
|
$this->assertRaw($account->id());
|
||||||
|
}
|
||||||
|
|
||||||
// Pass in an invalid username and a valid username.
|
// Pass in an invalid username and a valid username.
|
||||||
$users = array($this->randomMachineName(), $this->names[0]);
|
$users = array($this->randomMachineName(), $this->names[0]);
|
||||||
$users = array_map('strtolower', $users);
|
$users = array_map('strtolower', $users);
|
||||||
|
@ -156,6 +167,18 @@ class HandlerFilterUserNameTest extends ViewTestBase {
|
||||||
foreach ($this->accounts as $account) {
|
foreach ($this->accounts as $account) {
|
||||||
$this->assertRaw($account->id());
|
$this->assertRaw($account->id());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pass in just valid user IDs in the entity_autocomplete target_id format.
|
||||||
|
$options['query']['uid'] = array_map(function($account) {
|
||||||
|
return ['target_id' => $account->id()];
|
||||||
|
}, $this->accounts);
|
||||||
|
|
||||||
|
$this->drupalGet($path, $options);
|
||||||
|
$this->assertNoRaw('Unable to find user');
|
||||||
|
// The actual result should contain all of the user ids.
|
||||||
|
foreach ($this->accounts as $account) {
|
||||||
|
$this->assertRaw($account->id());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -310,6 +310,31 @@ class EntityAutocompleteElementFormTest extends EntityKernelTestBase implements
|
||||||
$this->assertEqual($form['tags_access']['#value'], $expected);
|
$this->assertEqual($form['tags_access']['#value'], $expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests ID input is handled correctly.
|
||||||
|
*
|
||||||
|
* E.g. This can happen with GET form parameters.
|
||||||
|
*/
|
||||||
|
public function testEntityAutocompleteIdInput() {
|
||||||
|
/** @var \Drupal\Core\Form\FormBuilderInterface $form_builder */
|
||||||
|
$form_builder = $this->container->get('form_builder');
|
||||||
|
//$form = $form_builder->getForm($this);
|
||||||
|
$form_state = (new FormState())
|
||||||
|
->setMethod('GET')
|
||||||
|
->setValues([
|
||||||
|
'single' => [['target_id' => $this->referencedEntities[0]->id()]],
|
||||||
|
'single_no_validate' => [['target_id' => $this->referencedEntities[0]->id()]],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$form_builder->submitForm($this, $form_state);
|
||||||
|
|
||||||
|
$form = $form_state->getCompleteForm();
|
||||||
|
|
||||||
|
$expected_label = $this->getAutocompleteInput($this->referencedEntities[0]);
|
||||||
|
$this->assertSame($expected_label, $form['single']['#value']);
|
||||||
|
$this->assertSame($expected_label, $form['single_no_validate']['#value']);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an entity label in the format needed by the EntityAutocomplete
|
* Returns an entity label in the format needed by the EntityAutocomplete
|
||||||
* element.
|
* element.
|
||||||
|
|
Loading…
Reference in New Issue