FieldEditForm.php 7.45 KB
Newer Older
1 2 3 4
<?php

/**
 * @file
5
 * Contains \Drupal\field_ui\Form\FieldEditForm.
6 7 8 9
 */

namespace Drupal\field_ui\Form;

10
use Drupal\Core\Entity\EntityManagerInterface;
11 12 13
use Drupal\Core\Form\FormBase;
use Drupal\Core\TypedData\TypedDataManager;
use Drupal\field\FieldInfo;
14 15 16
use Drupal\field\FieldInstanceInterface;
use Drupal\field_ui\FieldUI;
use Symfony\Component\DependencyInjection\ContainerInterface;
17 18 19 20

/**
 * Provides a form for the field settings edit page.
 */
21
class FieldEditForm extends FormBase {
22 23 24 25

  /**
   * The field instance being edited.
   *
26
   * @var \Drupal\field\FieldInstanceInterface
27 28 29
   */
  protected $instance;

30 31 32
  /**
   * The entity manager.
   *
33
   * @var \Drupal\Core\Entity\EntityManagerInterface
34 35 36
   */
  protected $entityManager;

37 38 39 40 41 42 43 44 45 46 47 48 49 50
  /**
   * The field info service.
   *
   * @var \Drupal\field\FieldInfo
   */
  protected $fieldInfo;

  /**
   * The typed data manager.
   *
   * @var \Drupal\Core\TypedData\TypedDataManager
   */
  protected $typedData;

51 52 53
  /**
   * {@inheritdoc}
   */
54
  public function getFormId() {
55
    return 'field_ui_field_edit_form';
56 57
  }

58 59 60
  /**
   * Constructs a new FieldEditForm object.
   *
61
   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
62
   *   The entity manager.
63 64 65 66
   * @param \Drupal\field\FieldInfo $field_info
   *   The field info service.
   * @param \Drupal\Core\TypedData\TypedDataManager $typed_data
   *   The typed data manager.
67
   */
68
  public function __construct(EntityManagerInterface $entity_manager, FieldInfo $field_info, TypedDataManager $typed_data) {
69
    $this->entityManager = $entity_manager;
70 71
    $this->fieldInfo = $field_info;
    $this->typedData = $typed_data;
72 73
  }

74 75 76
  /**
   * {@inheritdoc}
   */
77 78
  public static function create(ContainerInterface $container) {
    return new static(
79
      $container->get('entity.manager'),
80 81
      $container->get('field.info'),
      $container->get('typed_data')
82 83 84 85 86 87 88
    );
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, array &$form_state, FieldInstanceInterface $field_instance = NULL) {
89
    $this->instance = $form_state['instance'] = $field_instance;
90

91 92 93
    $field = $this->instance->getField();
    $form['#field'] = $field;

94
    $description = '<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.', array('%field' => $this->instance->label())) . '</p>';
95 96 97 98 99 100 101 102 103

    // Create a form structure for the field values.
    $form['field'] = array(
      '#prefix' => $description,
      '#tree' => TRUE,
    );

    // See if data already exists for this field.
    // If so, prevent changes to the field settings.
104
    if ($field->hasData()) {
105
      $form['field']['#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['field']['#prefix'];
106 107 108
    }

    // Build the configurable field values.
109
    $cardinality = $field->getFieldCardinality();
110
    $form['field']['cardinality_container'] = array(
111 112 113
      // We can't use the container element because it doesn't support the title
      // or description properties.
      '#type' => 'item',
114 115
      // Reset #parents to 'field', so the additional container does not appear.
      '#parents' => array('field'),
116 117
      '#field_prefix' => '<div class="container-inline">',
      '#field_suffix' => '</div>',
118
      '#title' => $this->t('Allowed number of values'),
119
    );
120
    $form['field']['cardinality_container']['cardinality'] = array(
121
      '#type' => 'select',
122
      '#title' => $this->t('Allowed number of values'),
123 124
      '#title_display' => 'invisible',
      '#options' => array(
125
        'number' => $this->t('Limited'),
126
        FieldInstanceInterface::CARDINALITY_UNLIMITED => $this->t('Unlimited'),
127
      ),
128
      '#default_value' => ($cardinality == FieldInstanceInterface::CARDINALITY_UNLIMITED) ? FieldInstanceInterface::CARDINALITY_UNLIMITED : 'number',
129
    );
130
    $form['field']['cardinality_container']['cardinality_number'] = array(
131
      '#type' => 'number',
132
      '#default_value' => $cardinality != FieldInstanceInterface::CARDINALITY_UNLIMITED ? $cardinality : 1,
133
      '#min' => 1,
134
      '#title' => $this->t('Limit'),
135
      '#title_display' => 'invisible',
136
      '#size' => 2,
137 138
      '#states' => array(
        'visible' => array(
139
         ':input[name="field[cardinality]"]' => array('value' => 'number'),
140 141 142 143 144
        ),
      ),
    );

    // Build the non-configurable field values.
145 146 147 148
    $form['field']['field_name'] = array('#type' => 'value', '#value' => $field->getFieldName());
    $form['field']['type'] = array('#type' => 'value', '#value' => $field->getFieldType());
    $form['field']['module'] = array('#type' => 'value', '#value' => $field->module);
    $form['field']['active'] = array('#type' => 'value', '#value' => $field->active);
149 150 151 152 153 154 155

    // 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.
    $form['field']['settings'] = array(
      '#weight' => 10,
    );
156 157
    // Create an arbitrary entity object, so that we can have an instantiated
    // FieldItem.
158
    $ids = (object) array('entity_type' => $this->instance->entity_type, 'bundle' => $this->instance->bundle, 'entity_id' => NULL);
159
    $entity = _field_create_entity_from_ids($ids);
160
    $form['field']['settings'] += $entity->get($field->getFieldName())->offsetGet(0)->settingsForm($form, $form_state, $field->hasData());
161 162

    $form['actions'] = array('#type' => 'actions');
163
    $form['actions']['submit'] = array('#type' => 'submit', '#value' => $this->t('Save field settings'));
164 165 166 167 168 169 170 171
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, array &$form_state) {
    // Validate field cardinality.
172 173 174
    $cardinality = $form_state['values']['field']['cardinality'];
    $cardinality_number = $form_state['values']['field']['cardinality_number'];
    if ($cardinality === 'number' && empty($cardinality_number)) {
175
      form_error($form['field']['cardinality_container']['cardinality_number'], $this->t('Number of values is required.'));
176 177 178 179 180 181 182 183 184 185 186
    }
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, array &$form_state) {
    $form_values = $form_state['values'];
    $field_values = $form_values['field'];

    // Save field cardinality.
187 188 189 190
    $cardinality = $field_values['cardinality'];
    $cardinality_number = $field_values['cardinality_number'];
    if ($cardinality === 'number') {
      $cardinality = $cardinality_number;
191 192 193 194 195
    }
    $field_values['cardinality'] = $cardinality;
    unset($field_values['container']);

    // Merge incoming form values into the existing field.
196
    $field = $this->instance->getField();
197
    foreach ($field_values as $key => $value) {
198
      $field->{$key} = $value;
199 200 201 202 203
    }

    // Update the field.
    try {
      $field->save();
204
      drupal_set_message($this->t('Updated field %label field settings.', array('%label' => $this->instance->label())));
205 206 207 208
      if ($next_destination = FieldUI::getNextDestination($this->getRequest())) {
        $form_state['redirect'] = $next_destination;
      }
      else {
209
        $form_state['redirect_route'] = $this->entityManager->getAdminRouteInfo($this->instance->entity_type, $this->instance->bundle);
210
      }
211
    }
212
    catch (\Exception $e) {
213
      drupal_set_message($this->t('Attempt to update field %label failed: %message.', array('%label' => $this->instance->label(), '%message' => $e->getMessage())), 'error');
214 215 216 217
    }
  }

}