'CONTAINS', 'size' => '60', 'placeholder' => '', ] + parent::defaultSettings(); } /** * {@inheritdoc} */ public function settingsForm(array $form, FormStateInterface $form_state) { $element['match_operator'] = [ '#type' => 'radios', '#title' => t('Autocomplete matching'), '#default_value' => $this->getSetting('match_operator'), '#options' => $this->getMatchOperatorOptions(), '#description' => t('Select the method used to collect autocomplete suggestions. Note that Contains can cause performance issues on sites with thousands of entities.'), ]; $element['size'] = [ '#type' => 'number', '#title' => t('Size of textfield'), '#default_value' => $this->getSetting('size'), '#min' => 1, '#required' => TRUE, ]; $element['placeholder'] = [ '#type' => 'textfield', '#title' => t('Placeholder'), '#default_value' => $this->getSetting('placeholder'), '#description' => t('Text that will be shown inside the field until a value is entered. This hint is usually a sample value or a brief description of the expected format.'), ]; return $element; } /** * {@inheritdoc} */ public function settingsSummary() { $summary = []; $operators = $this->getMatchOperatorOptions(); $summary[] = t('Autocomplete matching: @match_operator', ['@match_operator' => $operators[$this->getSetting('match_operator')]]); $summary[] = t('Textfield size: @size', ['@size' => $this->getSetting('size')]); $placeholder = $this->getSetting('placeholder'); if (!empty($placeholder)) { $summary[] = t('Placeholder: @placeholder', ['@placeholder' => $placeholder]); } else { $summary[] = t('No placeholder'); } return $summary; } /** * {@inheritdoc} */ public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) { $entity = $items->getEntity(); $referenced_entities = $items->referencedEntities(); // Append the match operation to the selection settings. $selection_settings = $this->getFieldSetting('handler_settings') + ['match_operator' => $this->getSetting('match_operator')]; $element += [ '#type' => 'entity_autocomplete', '#target_type' => $this->getFieldSetting('target_type'), '#selection_handler' => $this->getFieldSetting('handler'), '#selection_settings' => $selection_settings, // Entity reference field items are handling validation themselves via // the 'ValidReference' constraint. '#validate_reference' => FALSE, '#maxlength' => 1024, '#default_value' => isset($referenced_entities[$delta]) ? $referenced_entities[$delta] : NULL, '#size' => $this->getSetting('size'), '#placeholder' => $this->getSetting('placeholder'), ]; if ($this->getSelectionHandlerSetting('auto_create') && ($bundle = $this->getAutocreateBundle())) { $element['#autocreate'] = [ 'bundle' => $bundle, 'uid' => ($entity instanceof EntityOwnerInterface) ? $entity->getOwnerId() : \Drupal::currentUser()->id(), ]; } return ['target_id' => $element]; } /** * {@inheritdoc} */ public function errorElement(array $element, ConstraintViolationInterface $error, array $form, FormStateInterface $form_state) { return $element['target_id']; } /** * {@inheritdoc} */ public function massageFormValues(array $values, array $form, FormStateInterface $form_state) { foreach ($values as $key => $value) { // The entity_autocomplete form element returns an array when an entity // was "autocreated", so we need to move it up a level. if (is_array($value['target_id'])) { unset($values[$key]['target_id']); $values[$key] += $value['target_id']; } } return $values; } /** * Returns the name of the bundle which will be used for autocreated entities. * * @return string * The bundle name. */ protected function getAutocreateBundle() { $bundle = NULL; if ($this->getSelectionHandlerSetting('auto_create') && $target_bundles = $this->getSelectionHandlerSetting('target_bundles')) { // If there's only one target bundle, use it. if (count($target_bundles) == 1) { $bundle = reset($target_bundles); } // Otherwise use the target bundle stored in selection handler settings. elseif (!$bundle = $this->getSelectionHandlerSetting('auto_create_bundle')) { // If no bundle has been set as auto create target means that there is // an inconsistency in entity reference field settings. trigger_error(sprintf( "The 'Create referenced entities if they don't already exist' option is enabled but a specific destination bundle is not set. You should re-visit and fix the settings of the '%s' (%s) field.", $this->fieldDefinition->getLabel(), $this->fieldDefinition->getName() ), E_USER_WARNING); } } return $bundle; } /** * Returns the value of a setting for the entity reference selection handler. * * @param string $setting_name * The setting name. * * @return mixed * The setting value. */ protected function getSelectionHandlerSetting($setting_name) { $settings = $this->getFieldSetting('handler_settings'); return isset($settings[$setting_name]) ? $settings[$setting_name] : NULL; } /** * Returns the options for the match operator. * * @return array * List of options. */ protected function getMatchOperatorOptions() { return [ 'STARTS_WITH' => t('Starts with'), 'CONTAINS' => t('Contains'), ]; } }