diff --git a/core/modules/field/config/schema/field.schema.yml b/core/modules/field/config/schema/field.schema.yml
index 26b156c..55760a7 100644
--- a/core/modules/field/config/schema/field.schema.yml
+++ b/core/modules/field/config/schema/field.schema.yml
@@ -24,9 +24,6 @@ field.storage.*.*:
type:
type: string
label: 'Type'
- label:
- type: label
- label: 'Label'
settings:
type: field.storage_settings.[%parent.type]
module:
diff --git a/core/modules/field/src/Entity/FieldStorageConfig.php b/core/modules/field/src/Entity/FieldStorageConfig.php
index b07ef69..db6505f 100644
--- a/core/modules/field/src/Entity/FieldStorageConfig.php
+++ b/core/modules/field/src/Entity/FieldStorageConfig.php
@@ -28,14 +28,13 @@
* config_prefix = "storage",
* entity_keys = {
* "id" = "id",
- * "label" = "label"
+ * "label" = "id"
* },
* config_export = {
* "id",
* "field_name",
* "entity_type",
* "type",
- * "label",
* "settings",
* "module",
* "locked",
@@ -96,16 +95,6 @@ class FieldStorageConfig extends ConfigEntityBase implements FieldStorageConfigI
protected $type;
/**
- * The human-readable label for the field storage.
- *
- * This will be used as the default title for new fields using this field
- * storage.
- *
- * @var string
- */
- protected $label;
-
- /**
* The name of the module that provides the field type.
*
* @var string
diff --git a/core/modules/field_ui/src/Form/FieldStorageAddForm.php b/core/modules/field_ui/src/Form/FieldStorageAddForm.php
index 9ef499a..46ef63b 100644
--- a/core/modules/field_ui/src/Form/FieldStorageAddForm.php
+++ b/core/modules/field_ui/src/Form/FieldStorageAddForm.php
@@ -15,6 +15,7 @@
use Drupal\Core\Form\FormState;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
+use Drupal\field\Entity\FieldStorageConfig;
use Drupal\field\FieldStorageConfigInterface;
use Drupal\field_ui\FieldUI;
use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -155,7 +156,7 @@ public function buildForm(array $form, FormStateInterface $form_state, $entity_t
'#empty_option' => $this->t('- Select an existing field -'),
);
- $form['#attached']['drupalSettings']['existingFieldLabels'] = $this->getExistingFieldStorageLabels(array_keys($existing_field_storage_options));
+ $form['#attached']['drupalSettings']['existingFieldLabels'] = $this->getExistingFieldLabels(array_keys($existing_field_storage_options));
}
else {
// Provide a placeholder form element to simplify the validation code.
@@ -194,6 +195,32 @@ public function buildForm(array $form, FormStateInterface $form_state, $entity_t
unset($field_storage_form['#process'], $field_storage_form['#after_build']);
$field_storage_form['cardinality_container']['#parents'] = ['new_storage_wrapper'];
+ $form['new_storage_wrapper']['label'] = array(
+ '#type' => 'textfield',
+ '#title' => $this->t('Label'),
+ '#size' => 15,
+ '#weight' => -15,
+ );
+
+ $field_prefix = $this->config('field_ui.settings')->get('field_prefix');
+ $form['new_storage_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('label'),
+ 'exists' => array($this, 'fieldNameExists'),
+ ),
+ '#required' => FALSE,
+ '#weight' => -14,
+ );
+
$form['new_storage_wrapper'] += $field_storage_form;
}
@@ -273,6 +300,25 @@ public function validateForm(array &$form, FormStateInterface $form_state) {
protected function validateAddNew(array $form, FormStateInterface $form_state) {
// Validate if any information was provided in the 'add new field' case.
if ($form_state->isRebuilding() && $form_state->getValue('new_storage_type')) {
+ // Missing label.
+ if (!$form_state->getValue('label')) {
+ $form_state->setErrorByName('label', $this->t('Add new field: you need to provide a label.'));
+ }
+
+ // Missing field name.
+ if (!$form_state->getValue('field_name')) {
+ $form_state->setErrorByName('field_name', $this->t('Add new field: you need to provide a machine name for the field.'));
+ }
+ // Field name validation.
+ else {
+ $field_name = $form_state->getValue('field_name');
+
+ // Add the field prefix.
+ $field_name = $this->configFactory->get('field_ui.settings')->get('field_prefix') . $field_name;
+ $form_state->setValueForElement($form['new_storage_wrapper']['field_name'], $field_name);
+ }
+
+ // Also run the field storage config form validation.
$form_object = $this->entityManager->getFormObject('field_storage_config', 'edit');
$form_object->validateForm($form['new_storage_wrapper'], $form_state);
}
@@ -531,25 +577,64 @@ protected function getExistingFieldStorageOptions() {
/**
* Gets the human-readable labels for the given field storage names.
*
+ * Since not all field storages are required to have a field, we can only
+ * provide the field labels on a best-effort basis (e.g. the label of a field
+ * storage without any field attached to a bundle will be the field name).
+ *
* @param array $field_names
* An array of field names.
*
* @return array
* An array of field labels keyed by field name.
*/
- protected function getExistingFieldStorageLabels(array $field_names) {
- $field_ids = [];
- foreach ($field_names as $field_name) {
- $field_ids[] = $this->entityTypeId . '.' . $field_name;
- }
- $field_storages = $this->entityManager->getStorage('field_storage_config')->loadMultiple($field_ids);
-
+ protected function getExistingFieldLabels(array $field_names) {
+ // Get all the fields corresponding to the given field storage names and
+ // this entity type.
+ $field_ids = $this->queryFactory->get('field_config')
+ ->condition('entity_type', $this->entityTypeId)
+ ->condition('field_name', $field_names)
+ ->execute();
+ $fields = $this->entityManager->getStorage('field_config')->loadMultiple($field_ids);
+
+ // Go through all the fields and use the label of the first encounter.
$labels = array();
- foreach ($field_storages as $field_storage) {
- $labels[$field_storage->getName()] = $field_storage->label();
+ foreach ($fields as $field) {
+ if (!isset($labels[$field->getName()])) {
+ $labels[$field->getName()] = $field->label();
+ }
}
+ // For field storages without any fields attached to a bundle, the default
+ // label is the field name.
+ $labels += array_combine($field_names, $field_names);
+
return $labels;
}
+ /**
+ * Checks if a field machine name is taken.
+ *
+ * @param string $value
+ * The machine name, not prefixed.
+ * @param array $element
+ * An array containing the structure of the 'field_name' element.
+ * @param \Drupal\Core\Form\FormStateInterface $form_state
+ * The current state of the form.
+ *
+ * @return bool
+ * Whether or not the field machine name is taken.
+ */
+ public function fieldNameExists($value, $element, FormStateInterface $form_state) {
+ // Don't validate the case when an existing field has been selected.
+ if ($form_state->getValue('existing_storage_name')) {
+ return FALSE;
+ }
+
+ // Add the field prefix.
+ $field_name = $this->configFactory->get('field_ui.settings')->get('field_prefix') . $value;
+
+ $field_storage_definitions = $this->entityManager->getFieldStorageDefinitions($this->entityTypeId);
+ return isset($field_storage_definitions[$field_name]);
+ }
+
}
diff --git a/core/modules/field_ui/src/Form/FieldStorageConfigEditForm.php b/core/modules/field_ui/src/Form/FieldStorageConfigEditForm.php
index 473bfab..c651b0a 100644
--- a/core/modules/field_ui/src/Form/FieldStorageConfigEditForm.php
+++ b/core/modules/field_ui/src/Form/FieldStorageConfigEditForm.php
@@ -11,13 +11,10 @@
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Field\FieldItemList;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
-use Drupal\Core\Field\FieldTypePluginManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\field\Entity\FieldConfig;
-use Drupal\field\Entity\FieldStorageConfig;
use Drupal\field_ui\FieldUI;
-use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides a form for the "field storage" edit page.
@@ -32,32 +29,6 @@ class FieldStorageConfigEditForm extends EntityForm {
protected $entity;
/**
- * The field type plugin manager.
- *
- * @var \Drupal\Core\Field\FieldTypePluginManagerInterface
- */
- protected $fieldTypePluginManager;
-
- /**
- * Constructs a new FieldStorageConfigEditForm.
- *
- * @param \Drupal\Core\Field\FieldTypePluginManagerInterface $field_type_manager
- * The field type manager.
- */
- public function __construct(FieldTypePluginManagerInterface $field_type_manager) {
- $this->fieldTypePluginManager = $field_type_manager;
- }
-
- /**
- * {@inheritdoc}
- */
- public static function create(ContainerInterface $container) {
- return new static(
- $container->get('plugin.manager.field.field_type')
- );
- }
-
- /**
* {@inheritdoc}
*/
public function getEntityFromRouteMatch(RouteMatchInterface $route_match, $entity_type_id) {
@@ -106,36 +77,6 @@ public function form(array $form, FormStateInterface $form_state) {
}
}
- $form['label'] = array(
- '#type' => 'textfield',
- '#title' => $this->t('Label'),
- '#default_value' => $this->entity->label(),
- '#size' => 15,
- '#required' => TRUE,
- '#weight' => -15,
- );
-
- $field_prefix = $this->config('field_ui.settings')->get('field_prefix');
- $form['field_name'] = array(
- '#type' => 'machine_name',
- '#default_value' => $this->entity->getName(),
- // 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' => TRUE,
- '#access' => $this->entity->isNew(),
- '#weight' => -14,
- );
-
// Add settings provided by the field module. The field module is
// responsible for not returning settings that cannot be changed if
// the field already has data.
@@ -224,12 +165,6 @@ public function validateForm(array &$form, FormStateInterface $form_state) {
if ($form_state->getValue('cardinality') === 'number' && !$form_state->getValue('cardinality_number')) {
$form_state->setErrorByName('cardinality_number', $this->t('Number of values is required.'));
}
-
- // Add the field prefix.
- if (isset($form['field_name'])) {
- $field_name = $this->config('field_ui.settings')->get('field_prefix') . $form_state->getValue('field_name');
- $form_state->setValueForElement($form['field_name'], $field_name);
- }
}
/**
@@ -266,25 +201,4 @@ public function save(array $form, FormStateInterface $form_state) {
}
}
- /**
- * Checks if a field machine name is taken.
- *
- * @param string $value
- * The machine name, not prefixed.
- * @param array $element
- * An array containing the structure of the 'field_name' element.
- * @param \Drupal\Core\Form\FormStateInterface $form_state
- * The current state of the form.
- *
- * @return bool
- * Whether or not the field machine name is taken.
- */
- public function fieldNameExists($value, $element, FormStateInterface $form_state) {
- // Add the field prefix.
- $field_name = $this->config('field_ui.settings')->get('field_prefix') . $value;
-
- $field_storage_definitions = $this->entityManager->getFieldStorageDefinitions($form_state->get('entity_type_id'));
- return isset($field_storage_definitions[$field_name]);
- }
-
}