diff --git a/core/modules/field_ui/css/field_ui.admin.css b/core/modules/field_ui/css/field_ui.admin.css index 95c0033..ede3d06 100644 --- a/core/modules/field_ui/css/field_ui.admin.css +++ b/core/modules/field_ui/css/field_ui.admin.css @@ -4,12 +4,12 @@ */ /* Add new field page. */ -.field-ui-add-field .field-type-wrapper .form-item { +.field-ui-field-storage-add-form .field-type-wrapper .form-item { float: left; margin-right: 1em; vertical-align: text-bottom; } -.field-ui-add-field .field-type-wrapper .form-type-item { +.field-ui-field-storage-add-form .field-type-wrapper .form-type-item { margin-top: 2.3em; } diff --git a/core/modules/field_ui/field_ui.js b/core/modules/field_ui/field_ui.js index 3fed9ef..ffbe499 100644 --- a/core/modules/field_ui/field_ui.js +++ b/core/modules/field_ui/field_ui.js @@ -7,6 +7,29 @@ "use strict"; + Drupal.behaviors.fieldUIFieldStorageAddForm = { + attach: function (context) { + var $fieldType = $(context).find('select[name="type"]'); + var $existingField = $(context).find('select[name="existing_field_name"]'); + + // When the user selects a new field type, clear the "existing field" + // selection. + $fieldType.change(function () { + if ($(this).val() != '') { + $existingField.val(''); + } + }); + + // When the user selects an existing field, clear the "new field type" + // selection. + $existingField.change(function () { + if ($(this).val() != '') { + $fieldType.val('').change(); + } + }); + } + }; + Drupal.behaviors.fieldUIDisplayOverview = { attach: function (context, settings) { $(context).find('table#field-display-overview').once('field-display-overview', function () { diff --git a/core/modules/field_ui/src/Form/FieldStorageAddForm.php b/core/modules/field_ui/src/Form/FieldStorageAddForm.php index 6b318cb..98a5fcc 100644 --- a/core/modules/field_ui/src/Form/FieldStorageAddForm.php +++ b/core/modules/field_ui/src/Form/FieldStorageAddForm.php @@ -103,37 +103,9 @@ public function buildForm(array $form, FormStateInterface $form_state, $entity_t $this->entityTypeId = $entity_type_id; $this->bundle = $form_state->getValue('bundle'); - $form = array( - '#entity_type_id' => $entity_type_id, + $form += array( + '#entity_type_id' => $this->entityTypeId, '#bundle' => $this->bundle, - '#attributes' => array( - 'id' => 'field-add-wrapper', - 'class' => array('field-ui-add-field'), - ), - ); - - $form['label'] = array( - '#type' => 'textfield', - '#title' => $this->t('Label'), - '#size' => 15, - ); - - $field_prefix = $this->config('field_ui.settings')->get('field_prefix'); - $form['field_name'] = array( - '#type' => 'machine_name', - // This field should stay LTR even for RTL languages. - '#field_prefix' => '' . $field_prefix, - '#field_suffix' => '‎', - '#size' => 15, - '#description' => $this->t('A unique machine-readable name containing letters, numbers, and underscores.'), - // Calculate characters depending on the length of the field prefix - // setting. Maximum length is 32. - '#maxlength' => FieldStorageConfig::NAME_MAX_LENGTH - strlen($field_prefix), - '#machine_name' => array( - 'source' => array('label'), - 'exists' => array($this, 'fieldNameExists'), - ), - '#required' => FALSE, ); // Gather valid field types. @@ -190,6 +162,38 @@ public function buildForm(array $form, FormStateInterface $form_state, $entity_t ); } + $form['new_field_wrapper'] = array( + '#type' => 'container', + '#states' => array( + '!visible' => array( + ':input[name="type"]' => array('value' => ''), + ), + ), + ); + $form['new_field_wrapper']['label'] = array( + '#type' => 'textfield', + '#title' => $this->t('Label'), + '#size' => 15, + ); + + $field_prefix = $this->config('field_ui.settings')->get('field_prefix'); + $form['new_field_wrapper']['field_name'] = array( + '#type' => 'machine_name', + // This field should stay LTR even for RTL languages. + '#field_prefix' => '' . $field_prefix, + '#field_suffix' => '‎', + '#size' => 15, + '#description' => $this->t('A unique machine-readable name containing letters, numbers, and underscores.'), + // Calculate characters depending on the length of the field prefix + // setting. Maximum length is 32. + '#maxlength' => FieldStorageConfig::NAME_MAX_LENGTH - strlen($field_prefix), + '#machine_name' => array( + 'source' => array('new_field_wrapper', 'label'), + 'exists' => array($this, 'fieldNameExists'), + ), + '#required' => FALSE, + ); + // Place the 'translatable' property as an explicit value so that // contrib modules can form_alter() the value for newly created fields. $form['translatable'] = array( @@ -217,8 +221,10 @@ public function validateForm(array &$form, FormStateInterface $form_state) { if (!$form_state->getValue('type') && !$form_state->getValue('existing_field_name')) { $form_state->setErrorByName('type', $this->t('You need to select a field type.')); } + // Both field type and existing field option selected. This is prevented in + // the UI with JavaScript but we also need a proper server-side validation. elseif ($form_state->getValue('type') && $form_state->getValue('existing_field_name')) { - $form_state->setErrorByName('type', $this->t('So.. you want to add a new field *and* re-use an existing one? Not cool!')); + $form_state->setErrorByName('type', $this->t('Adding a new field and re-using an existing field at the same time is not allowed.')); return; } @@ -275,13 +281,10 @@ protected function validateAddExisting(array $form, FormStateInterface $form_sta // The form element might be absent if no existing fields can be added to // this bundle. $field = $form_state->getValues(); - if ($field['existing_field_name']) { - // Missing label. - if (!$field['label']) { - $form_state->setErrorByName('label', $this->t('Re-use existing field: you need to provide a label.')); - } - - // Discard the value for the 'field_name' form element. + if (isset($field['existing_field_name'])) { + // Discard any values that might be set for the 'label' and 'field_name' + // form elements. + $form_state->setValueForElement($form['label'], ''); $form_state->setValueForElement($form['field_name'], ''); } } @@ -343,14 +346,16 @@ public function submitForm(array &$form, FormStateInterface $form_state) { $field_name = $values['existing_field_name']; $field_storage = FieldStorageConfig::loadByName($this->entityTypeId, $field_name); if ($field_storage->isLocked()) { - drupal_set_message($this->t('The field %label cannot be added because it is locked.', array('%label' => $values['label'])), 'error'); + drupal_set_message($this->t('The field %field_name cannot be added because it is locked.', array('%field_name' => $field_storage->getName())), 'error'); } else { $field = array( 'field_name' => $field_name, 'entity_type' => $this->entityTypeId, 'bundle' => $this->bundle, - 'label' => $values['label'], + // @todo Should we try to populate this value on a best-effort basis? + // (i.e. use the label of the first instance of this field storage) + 'label' => '', ); try { @@ -371,7 +376,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) { } catch (\Exception $e) { $error = TRUE; - drupal_set_message($this->t('There was a problem creating field %label: @message.', array('%label' => $field['label'], '@message' => $e->getMessage())), 'error'); + drupal_set_message($this->t('There was a problem creating field %field_name: @message.', array('%field_name' => $field_storage->getName(), '@message' => $e->getMessage())), 'error'); } } }