public static function EntityAutocomplete::validateEntityAutocomplete in Drupal 9
Same name and namespace in other branches
- 8 core/lib/Drupal/Core/Entity/Element/EntityAutocomplete.php \Drupal\Core\Entity\Element\EntityAutocomplete::validateEntityAutocomplete()
Form element validation handler for entity_autocomplete elements.
File
- core/
lib/ Drupal/ Core/ Entity/ Element/ EntityAutocomplete.php, line 197
Class
- EntityAutocomplete
- Provides an entity autocomplete form element.
Namespace
Drupal\Core\Entity\ElementCode
public static function validateEntityAutocomplete(array &$element, FormStateInterface $form_state, array &$complete_form) {
$value = NULL;
if (!empty($element['#value'])) {
$options = $element['#selection_settings'] + [
'target_type' => $element['#target_type'],
'handler' => $element['#selection_handler'],
];
/** @var /Drupal\Core\Entity\EntityReferenceSelection\SelectionInterface $handler */
$handler = \Drupal::service('plugin.manager.entity_reference_selection')
->getInstance($options);
$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']) : [
$element['#value'],
];
foreach ($input_values as $input) {
$match = static::extractEntityIdFromAutocompleteInput($input);
if ($match === NULL) {
// Try to get a match from the input string when the user didn't use
// the autocomplete but filled in a value manually.
$match = static::matchEntityByTitle($handler, $input, $element, $form_state, !$autocreate);
}
if ($match !== NULL) {
$value[] = [
'target_id' => $match,
];
}
elseif ($autocreate) {
/** @var \Drupal\Core\Entity\EntityReferenceSelection\SelectionWithAutocreateInterface $handler */
// Auto-create item. See an example of how this is handled in
// \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem::presave().
$value[] = [
'entity' => $handler
->createNewEntity($element['#target_type'], $element['#autocreate']['bundle'], $input, $element['#autocreate']['uid']),
];
}
}
}
// Check that the referenced entities are valid, if needed.
if ($element['#validate_reference'] && !empty($value)) {
// Validate existing entities.
$ids = array_reduce($value, function ($return, $item) {
if (isset($item['target_id'])) {
$return[] = $item['target_id'];
}
return $return;
});
if ($ids) {
$valid_ids = $handler
->validateReferenceableEntities($ids);
if ($invalid_ids = array_diff($ids, $valid_ids)) {
foreach ($invalid_ids as $invalid_id) {
$form_state
->setError($element, t('The referenced entity (%type: %id) does not exist.', [
'%type' => $element['#target_type'],
'%id' => $invalid_id,
]));
}
}
}
// Validate newly created entities.
$new_entities = array_reduce($value, function ($return, $item) {
if (isset($item['entity'])) {
$return[] = $item['entity'];
}
return $return;
});
if ($new_entities) {
if ($autocreate) {
$valid_new_entities = $handler
->validateReferenceableNewEntities($new_entities);
$invalid_new_entities = array_diff_key($new_entities, $valid_new_entities);
}
else {
// If the selection handler does not support referencing newly
// created entities, all of them should be invalidated.
$invalid_new_entities = $new_entities;
}
foreach ($invalid_new_entities as $entity) {
/** @var \Drupal\Core\Entity\EntityInterface $entity */
$form_state
->setError($element, t('This entity (%type: %label) cannot be referenced.', [
'%type' => $element['#target_type'],
'%label' => $entity
->label(),
]));
}
}
}
// Use only the last value if the form element does not support multiple
// matches (tags).
if (!$element['#tags'] && !empty($value)) {
$last_value = $value[count($value) - 1];
$value = isset($last_value['target_id']) ? $last_value['target_id'] : $last_value;
}
}
$form_state
->setValueForElement($element, $value);
}