3 namespace Drupal\field_ui\Form;
5 use Drupal\Core\Entity\EntityForm;
6 use Drupal\Core\Field\FieldStorageDefinitionInterface;
7 use Drupal\Core\Form\FormStateInterface;
8 use Drupal\Core\Routing\RouteMatchInterface;
9 use Drupal\field\Entity\FieldConfig;
10 use Drupal\field_ui\FieldUI;
11 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
14 * Provides a form for the "field storage" edit page.
16 class FieldStorageConfigEditForm extends EntityForm {
19 * The entity being used by this form.
21 * @var \Drupal\field\FieldStorageConfigInterface
28 public function getEntityFromRouteMatch(RouteMatchInterface $route_match, $entity_type_id) {
29 // The URL of this entity form contains only the ID of the field_config
30 // but we are actually editing a field_storage_config entity.
31 $field_config = FieldConfig::load($route_match->getRawParameter('field_config'));
33 throw new NotFoundHttpException();
36 return $field_config->getFieldStorageDefinition();
42 * @param string $field_config
43 * The ID of the field config whose field storage config is being edited.
45 public function buildForm(array $form, FormStateInterface $form_state, $field_config = NULL) {
47 $field = FieldConfig::load($field_config);
48 $form_state->set('field_config', $field);
50 $form_state->set('entity_type_id', $field->getTargetEntityTypeId());
51 $form_state->set('bundle', $field->getTargetBundle());
54 return parent::buildForm($form, $form_state);
60 public function form(array $form, FormStateInterface $form_state) {
61 $form = parent::form($form, $form_state);
63 $field_label = $form_state->get('field_config')->label();
64 $form['#title'] = $field_label;
65 $form['#prefix'] = '<p>' . $this->t('These settings apply to the %field field everywhere it is used. These settings impact the way that data is stored in the database and cannot be changed once data has been created.', ['%field' => $field_label]) . '</p>';
67 // See if data already exists for this field.
68 // If so, prevent changes to the field settings.
69 if ($this->entity->hasData()) {
70 $form['#prefix'] = '<div class="messages messages--error">' . $this->t('There is data for this field in the database. The field settings can no longer be changed.') . '</div>' . $form['#prefix'];
73 // Add settings provided by the field module. The field module is
74 // responsible for not returning settings that cannot be changed if
75 // the field already has data.
80 // Create an arbitrary entity object, so that we can have an instantiated
83 'entity_type' => $form_state->get('entity_type_id'),
84 'bundle' => $form_state->get('bundle'),
87 $entity = _field_create_entity_from_ids($ids);
88 $items = $entity->get($this->entity->getName());
89 $item = $items->first() ?: $items->appendItem();
90 $form['settings'] += $item->storageSettingsForm($form, $form_state, $this->entity->hasData());
92 // Build the configurable field values.
93 $cardinality = $this->entity->getCardinality();
94 $form['cardinality_container'] = [
95 // Reset #parents so the additional container does not appear.
97 '#type' => 'fieldset',
98 '#title' => $this->t('Allowed number of values'),
99 '#attributes' => ['class' => [
105 $form['cardinality_container']['cardinality'] = [
107 '#title' => $this->t('Allowed number of values'),
108 '#title_display' => 'invisible',
110 'number' => $this->t('Limited'),
111 FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED => $this->t('Unlimited'),
113 '#default_value' => ($cardinality == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) ? FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED : 'number',
115 $form['cardinality_container']['cardinality_number'] = [
117 '#default_value' => $cardinality != FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED ? $cardinality : 1,
119 '#title' => $this->t('Limit'),
120 '#title_display' => 'invisible',
124 ':input[name="cardinality"]' => ['value' => 'number'],
127 ':input[name="cardinality"]' => ['value' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED],
138 protected function actions(array $form, FormStateInterface $form_state) {
139 $elements = parent::actions($form, $form_state);
140 $elements['submit']['#value'] = $this->t('Save field settings');
148 public function validateForm(array &$form, FormStateInterface $form_state) {
149 parent::validateForm($form, $form_state);
151 $field_storage_definitions = \Drupal::service('entity_field.manager')->getFieldStorageDefinitions($this->entity->getTargetEntityTypeId());
153 // Validate field cardinality.
154 if ($form_state->getValue('cardinality') === 'number' && !$form_state->getValue('cardinality_number')) {
155 $form_state->setErrorByName('cardinality_number', $this->t('Number of values is required.'));
157 // If a specific cardinality is used, validate that there are no entities
158 // with a higher delta.
159 elseif (!$this->entity->isNew() && isset($field_storage_definitions[$this->entity->getName()]) && $form_state->getValue('cardinality') != FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) {
161 // Get a count of entities that have a value in a delta higher than the
162 // one selected. Deltas start with 0, so the selected value does not
163 // need to be incremented.
164 $entities_with_higher_delta = \Drupal::entityQuery($this->entity->getTargetEntityTypeId())
165 ->condition($this->entity->getName() . '.%delta', $form_state->getValue('cardinality'))
168 if ($entities_with_higher_delta) {
169 $form_state->setErrorByName('cardinality_number', $this->formatPlural($entities_with_higher_delta, 'There is @count entity with @delta or more values in this field.', 'There are @count entities with @delta or more values in this field.', ['@delta' => $form_state->getValue('cardinality') + 1]));
177 public function buildEntity(array $form, FormStateInterface $form_state) {
178 // Save field cardinality.
179 if ($form_state->getValue('cardinality') === 'number' && $form_state->getValue('cardinality_number')) {
180 $form_state->setValue('cardinality', $form_state->getValue('cardinality_number'));
183 return parent::buildEntity($form, $form_state);
189 public function save(array $form, FormStateInterface $form_state) {
190 $field_label = $form_state->get('field_config')->label();
192 $this->entity->save();
193 drupal_set_message($this->t('Updated field %label field settings.', ['%label' => $field_label]));
194 $request = $this->getRequest();
195 if (($destinations = $request->query->get('destinations')) && $next_destination = FieldUI::getNextDestination($destinations)) {
196 $request->query->remove('destinations');
197 $form_state->setRedirectUrl($next_destination);
200 $form_state->setRedirectUrl(FieldUI::getOverviewRouteInfo($form_state->get('entity_type_id'), $form_state->get('bundle')));
203 catch (\Exception $e) {
204 drupal_set_message($this->t('Attempt to update field %label failed: %message.', ['%label' => $field_label, '%message' => $e->getMessage()]), 'error');