/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/EntityReferenceAutocompleteWidget.php
PHP | 195 lines | 133 code | 17 blank | 45 comment | 9 complexity | 9cf22ade35099b7efb0c52692557b83d MD5 | raw file
- <?php
- namespace Drupal\Core\Field\Plugin\Field\FieldWidget;
- use Drupal\Core\Field\FieldItemListInterface;
- use Drupal\Core\Field\WidgetBase;
- use Drupal\Core\Form\FormStateInterface;
- use Drupal\user\EntityOwnerInterface;
- use Symfony\Component\Validator\ConstraintViolationInterface;
- /**
- * Plugin implementation of the 'entity_reference_autocomplete' widget.
- *
- * @FieldWidget(
- * id = "entity_reference_autocomplete",
- * label = @Translation("Autocomplete"),
- * description = @Translation("An autocomplete text field."),
- * field_types = {
- * "entity_reference"
- * }
- * )
- */
- class EntityReferenceAutocompleteWidget extends WidgetBase {
- /**
- * {@inheritdoc}
- */
- public static function defaultSettings() {
- return array(
- 'match_operator' => 'CONTAINS',
- 'size' => '60',
- 'placeholder' => '',
- ) + parent::defaultSettings();
- }
- /**
- * {@inheritdoc}
- */
- public function settingsForm(array $form, FormStateInterface $form_state) {
- $element['match_operator'] = array(
- '#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 <em>Contains</em> can cause performance issues on sites with thousands of entities.'),
- );
- $element['size'] = array(
- '#type' => 'number',
- '#title' => t('Size of textfield'),
- '#default_value' => $this->getSetting('size'),
- '#min' => 1,
- '#required' => TRUE,
- );
- $element['placeholder'] = array(
- '#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 = array();
- $operators = $this->getMatchOperatorOptions();
- $summary[] = t('Autocomplete matching: @match_operator', array('@match_operator' => $operators[$this->getSetting('match_operator')]));
- $summary[] = t('Textfield size: @size', array('@size' => $this->getSetting('size')));
- $placeholder = $this->getSetting('placeholder');
- if (!empty($placeholder)) {
- $summary[] = t('Placeholder: @placeholder', array('@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 += array(
- '#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'] = array(
- 'bundle' => $bundle,
- 'uid' => ($entity instanceof EntityOwnerInterface) ? $entity->getOwnerId() : \Drupal::currentUser()->id()
- );
- }
- return array('target_id' => $element);
- }
- /**
- * {@inheritdoc}
- */
- public function errorElement(array $element, ConstraintViolationInterface $error, array $form, FormStateInterface $form_state) {
- return isset($element['target_id']) ? $element['target_id'] : FALSE;
- }
- /**
- * {@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'),
- ];
- }
- }