diff --git a/core/modules/field_ui/field_ui.admin.inc b/core/modules/field_ui/field_ui.admin.inc
index bd605e54224..1c29e13fae2 100644
--- a/core/modules/field_ui/field_ui.admin.inc
+++ b/core/modules/field_ui/field_ui.admin.inc
@@ -6,6 +6,8 @@
*/
use Drupal\field\FieldInstance;
+use Drupal\field_ui\FieldOverview;
+use Drupal\field_ui\DisplayOverview;
/**
* Page callback: Lists all defined fields for quick reference.
@@ -100,18 +102,18 @@ function _field_ui_reduce_order($array, $a) {
* Returns the region to which a row in the 'Manage fields' screen belongs.
*
* This function is used as a #region_callback in
- * field_ui_field_overview_form(). It is called during
+ * Drupal\field_ui\DisplayOverview::form(). It is called during
* field_ui_table_pre_render().
*/
function field_ui_field_overview_row_region($row) {
switch ($row['#row_type']) {
case 'field':
case 'extra_field':
- return 'main';
+ return 'content';
case 'add_new_field':
// If no input in 'label', assume the row has not been dragged out of the
// 'add new' section.
- return (!empty($row['label']['#value']) ? 'main' : 'add_new');
+ return (!empty($row['label']['#value']) ? 'content' : 'hidden');
}
}
@@ -119,14 +121,14 @@ function field_ui_field_overview_row_region($row) {
* Returns the region to which a row in the 'Manage display' screen belongs.
*
* This function is used as a #region_callback in
- * field_ui_field_overview_form(), and is called during
+ * Drupal\field_ui\FieldOverview::form(), and is called during
* field_ui_table_pre_render().
*/
function field_ui_display_overview_row_region($row) {
switch ($row['#row_type']) {
case 'field':
case 'extra_field':
- return ($row['format']['type']['#value'] == 'hidden' ? 'hidden' : 'visible');
+ return ($row['format']['type']['#value'] == 'hidden' ? 'hidden' : 'content');
}
}
@@ -241,7 +243,7 @@ function theme_field_ui_table($variables) {
$region_name_class = drupal_html_class($region_name);
// Add region rows.
- if (isset($region['title'])) {
+ if (isset($region['title']) && empty($region['invisible'])) {
$table['rows'][] = array(
'class' => array('region-title', 'region-' . $region_name_class . '-title'),
'no_striping' => TRUE,
@@ -290,437 +292,34 @@ function theme_field_ui_table($variables) {
}
/**
- * Form constructor for the 'Manage fields' form of a bundle.
+ * Returns the built and processed 'Manage fields' form of a bundle.
*
* The resulting form allows fields and pseudo-fields to be re-ordered.
*
+ * @param string $entity_type
+ * The entity type for the fieldable entity.
+ * @param string $bundle
+ * The bundle for the fieldable entity.
+ *
+ * @return
+ * The processed form for the given entity type and bundle.
+ *
* @see field_ui_menu()
* @see field_ui_field_overview_form_validate()
* @see field_ui_field_overview_form_submit()
* @ingroup forms
*/
-function field_ui_field_overview_form($form, &$form_state, $entity_type, $bundle) {
+function field_ui_field_overview($entity_type, $bundle) {
$bundle = field_extract_bundle($entity_type, $bundle);
-
field_ui_inactive_message($entity_type, $bundle);
- $admin_path = _field_ui_bundle_admin_path($entity_type, $bundle);
- // When displaying the form, make sure the list of fields is up-to-date.
- if (empty($form_state['post'])) {
- field_info_cache_clear();
- }
+ $field_overview = new FieldOverview($entity_type, $bundle);
- // Gather bundle information.
- $instances = field_info_instances($entity_type, $bundle);
- $field_types = field_info_field_types();
+ $form_state = array();
+ $form_state['build_info']['callback'] = array($field_overview, 'form');
+ $form_state['build_info']['args'] = array($entity_type, $bundle);
- $extra_fields = field_info_extra_fields($entity_type, $bundle, 'form');
-
- $form += array(
- '#entity_type' => $entity_type,
- '#bundle' => $bundle,
- '#fields' => array_keys($instances),
- '#extra' => array_keys($extra_fields),
- );
-
- $table = array(
- '#type' => 'field_ui_table',
- '#tree' => TRUE,
- '#header' => array(
- t('Label'),
- t('Weight'),
- t('Parent'),
- t('Machine name'),
- t('Field type'),
- t('Widget'),
- t('Operations'),
- ),
- '#parent_options' => array(),
- '#regions' => array(
- 'main' => array('message' => t('No fields are present yet.')),
- 'add_new' => array('title' => ' '),
- ),
- '#attributes' => array(
- 'class' => array('field-ui-overview'),
- 'id' => 'field-overview',
- ),
- );
-
- // Fields.
- foreach ($instances as $name => $instance) {
- $field = field_info_field($instance['field_name']);
- $admin_field_path = $admin_path . '/fields/' . $instance['field_name'];
- $widget_definition = $instance->getWidget()->getDefinition();
-
- $table[$name] = array(
- '#attributes' => array('class' => array('draggable', 'tabledrag-leaf')),
- '#row_type' => 'field',
- '#region_callback' => 'field_ui_field_overview_row_region',
- 'label' => array(
- '#markup' => check_plain($instance['label']),
- ),
- 'weight' => array(
- '#type' => 'textfield',
- '#title' => t('Weight for @title', array('@title' => $instance['label'])),
- '#title_display' => 'invisible',
- '#default_value' => $instance['widget']['weight'],
- '#size' => 3,
- '#attributes' => array('class' => array('field-weight')),
- ),
- 'parent_wrapper' => array(
- 'parent' => array(
- '#type' => 'select',
- '#title' => t('Parent for @title', array('@title' => $instance['label'])),
- '#title_display' => 'invisible',
- '#options' => $table['#parent_options'],
- '#empty_value' => '',
- '#attributes' => array('class' => array('field-parent')),
- '#parents' => array('fields', $name, 'parent'),
- ),
- 'hidden_name' => array(
- '#type' => 'hidden',
- '#default_value' => $name,
- '#attributes' => array('class' => array('field-name')),
- ),
- ),
- 'field_name' => array(
- '#markup' => $instance['field_name'],
- ),
- 'type' => array(
- '#type' => 'link',
- '#title' => t($field_types[$field['type']]['label']),
- '#href' => $admin_field_path . '/field-settings',
- '#options' => array('attributes' => array('title' => t('Edit field settings.'))),
- ),
- 'widget_type' => array(
- '#type' => 'link',
- '#title' => $widget_definition['label'],
- '#href' => $admin_field_path . '/widget-type',
- '#options' => array('attributes' => array('title' => t('Change widget type.'))),
- ),
- );
- $links = array();
- $links['edit'] = array(
- 'title' => t('edit'),
- 'href' => $admin_field_path,
- 'attributes' => array('title' => t('Edit instance settings.')),
- );
- $links['delete'] = array(
- 'title' => t('delete'),
- 'href' => "$admin_field_path/delete",
- 'attributes' => array('title' => t('Delete instance.')),
- );
- $table[$name]['operations']['data'] = array(
- '#type' => 'operations',
- '#links' => $links,
- );
-
- if (!empty($instance['locked'])) {
- $table[$name]['operations'] = array('#value' => t('Locked'));
- $table[$name]['#attributes']['class'][] = 'menu-disabled';
- }
- }
-
- // Non-field elements.
- foreach ($extra_fields as $name => $extra_field) {
- $table[$name] = array(
- '#attributes' => array('class' => array('draggable', 'tabledrag-leaf')),
- '#row_type' => 'extra_field',
- '#region_callback' => 'field_ui_field_overview_row_region',
- 'label' => array(
- '#markup' => check_plain($extra_field['label']),
- ),
- 'weight' => array(
- '#type' => 'textfield',
- '#default_value' => $extra_field['weight'],
- '#size' => 3,
- '#attributes' => array('class' => array('field-weight')),
- '#title_display' => 'invisible',
- '#title' => t('Weight for @title', array('@title' => $extra_field['label'])),
- ),
- 'parent_wrapper' => array(
- 'parent' => array(
- '#type' => 'select',
- '#title' => t('Parent for @title', array('@title' => $extra_field['label'])),
- '#title_display' => 'invisible',
- '#options' => $table['#parent_options'],
- '#empty_value' => '',
- '#attributes' => array('class' => array('field-parent')),
- '#parents' => array('fields', $name, 'parent'),
- ),
- 'hidden_name' => array(
- '#type' => 'hidden',
- '#default_value' => $name,
- '#attributes' => array('class' => array('field-name')),
- ),
- ),
- 'field_name' => array(
- '#markup' => $name,
- ),
- 'type' => array(
- '#markup' => isset($extra_field['description']) ? $extra_field['description'] : '',
- '#cell_attributes' => array('colspan' => 2),
- ),
- 'operations' => array(
- '#markup' => '',
- ),
- );
- }
-
- // Additional row: add new field.
- $max_weight = field_info_max_weight($entity_type, $bundle, 'form');
- $field_type_options = field_ui_field_type_options();
- $widget_type_options = field_ui_widget_type_options(NULL, TRUE);
- if ($field_type_options && $widget_type_options) {
- $name = '_add_new_field';
- $table[$name] = array(
- '#attributes' => array('class' => array('draggable', 'tabledrag-leaf', 'add-new')),
- '#row_type' => 'add_new_field',
- '#region_callback' => 'field_ui_field_overview_row_region',
- 'label' => array(
- '#type' => 'textfield',
- '#title' => t('New field label'),
- '#title_display' => 'invisible',
- '#size' => 15,
- '#description' => t('Label'),
- '#prefix' => '
',
- ),
- 'weight' => array(
- '#type' => 'textfield',
- '#default_value' => $max_weight + 1,
- '#size' => 3,
- '#title_display' => 'invisible',
- '#title' => t('Weight for new field'),
- '#attributes' => array('class' => array('field-weight')),
- '#prefix' => '
',
- ),
- 'parent_wrapper' => array(
- 'parent' => array(
- '#type' => 'select',
- '#title' => t('Parent for new field'),
- '#title_display' => 'invisible',
- '#options' => $table['#parent_options'],
- '#empty_value' => '',
- '#attributes' => array('class' => array('field-parent')),
- '#prefix' => '
',
- '#parents' => array('fields', $name, 'parent'),
- ),
- 'hidden_name' => array(
- '#type' => 'hidden',
- '#default_value' => $name,
- '#attributes' => array('class' => array('field-name')),
- ),
- ),
- 'field_name' => array(
- '#type' => 'machine_name',
- '#title' => t('New field name'),
- '#title_display' => 'invisible',
- // This field should stay LTR even for RTL languages.
- '#field_prefix' => 'field_',
- '#field_suffix' => '',
- '#size' => 15,
- '#description' => t('A unique machine-readable name containing letters, numbers, and underscores.'),
- // 32 characters minus the 'field_' prefix.
- '#maxlength' => 26,
- '#prefix' => '
',
- '#machine_name' => array(
- 'source' => array('fields', $name, 'label'),
- 'exists' => '_field_ui_field_name_exists',
- 'standalone' => TRUE,
- 'label' => '',
- ),
- '#required' => FALSE,
- ),
- 'type' => array(
- '#type' => 'select',
- '#title' => t('Type of new field'),
- '#title_display' => 'invisible',
- '#options' => $field_type_options,
- '#empty_option' => t('- Select a field type -'),
- '#description' => t('Type of data to store.'),
- '#attributes' => array('class' => array('field-type-select')),
- '#prefix' => '
',
- ),
- 'widget_type' => array(
- '#type' => 'select',
- '#title' => t('Widget for new field'),
- '#title_display' => 'invisible',
- '#options' => $widget_type_options,
- '#empty_option' => t('- Select a widget -'),
- '#description' => t('Form element to edit the data.'),
- '#attributes' => array('class' => array('widget-type-select')),
- '#cell_attributes' => array('colspan' => 3),
- '#prefix' => '
',
- ),
- // Place the 'translatable' property as an explicit value so that contrib
- // modules can form_alter() the value for newly created fields.
- 'translatable' => array(
- '#type' => 'value',
- '#value' => FALSE,
- ),
- );
- }
-
- // Additional row: re-use existing field.
- $existing_fields = field_ui_existing_field_options($entity_type, $bundle);
- if ($existing_fields && $widget_type_options) {
- // Build list of options.
- $existing_field_options = array();
- foreach ($existing_fields as $field_name => $info) {
- $text = t('@type: @field (@label)', array(
- '@type' => $info['type_label'],
- '@label' => $info['label'],
- '@field' => $info['field'],
- ));
- $existing_field_options[$field_name] = truncate_utf8($text, 80, FALSE, TRUE);
- }
- asort($existing_field_options);
- $name = '_add_existing_field';
- $table[$name] = array(
- '#attributes' => array('class' => array('draggable', 'tabledrag-leaf', 'add-new')),
- '#row_type' => 'add_new_field',
- '#region_callback' => 'field_ui_field_overview_row_region',
- 'label' => array(
- '#type' => 'textfield',
- '#title' => t('Existing field label'),
- '#title_display' => 'invisible',
- '#size' => 15,
- '#description' => t('Label'),
- '#attributes' => array('class' => array('label-textfield')),
- '#prefix' => '',
- ),
- 'weight' => array(
- '#type' => 'textfield',
- '#default_value' => $max_weight + 2,
- '#size' => 3,
- '#title_display' => 'invisible',
- '#title' => t('Weight for added field'),
- '#attributes' => array('class' => array('field-weight')),
- '#prefix' => '
',
- ),
- 'parent_wrapper' => array(
- 'parent' => array(
- '#type' => 'select',
- '#title' => t('Parent for existing field'),
- '#title_display' => 'invisible',
- '#options' => $table['#parent_options'],
- '#empty_value' => '',
- '#attributes' => array('class' => array('field-parent')),
- '#prefix' => '
',
- '#parents' => array('fields', $name, 'parent'),
- ),
- 'hidden_name' => array(
- '#type' => 'hidden',
- '#default_value' => $name,
- '#attributes' => array('class' => array('field-name')),
- ),
- ),
- 'field_name' => array(
- '#type' => 'select',
- '#title' => t('Existing field to share'),
- '#title_display' => 'invisible',
- '#options' => $existing_field_options,
- '#empty_option' => t('- Select an existing field -'),
- '#description' => t('Field to share'),
- '#attributes' => array('class' => array('field-select')),
- '#cell_attributes' => array('colspan' => 2),
- '#prefix' => '
',
- ),
- 'widget_type' => array(
- '#type' => 'select',
- '#title' => t('Widget for existing field'),
- '#title_display' => 'invisible',
- '#options' => $widget_type_options,
- '#empty_option' => t('- Select a widget -'),
- '#description' => t('Form element to edit the data.'),
- '#attributes' => array('class' => array('widget-type-select')),
- '#cell_attributes' => array('colspan' => 3),
- '#prefix' => '
',
- ),
- );
- }
- $form['fields'] = $table;
-
- $form['actions'] = array('#type' => 'actions');
- $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save'));
-
- $form['#attached']['library'][] = array('field_ui', 'drupal.field_ui');
-
- // Add settings for the update selects behavior.
- $js_fields = array();
- foreach ($existing_fields as $field_name => $info) {
- $js_fields[$field_name] = array('label' => $info['label'], 'type' => $info['type'], 'widget' => $info['widget_type']);
- }
-
- $form['#attached']['js'][] = array(
- 'type' => 'setting',
- 'data' => array('fields' => $js_fields, 'fieldWidgetTypes' => field_ui_widget_type_options()),
- );
-
- // Add tabledrag behavior.
- $form['#attached']['drupal_add_tabledrag'][] = array('field-overview', 'order', 'sibling', 'field-weight');
- $form['#attached']['drupal_add_tabledrag'][] = array('field-overview', 'match', 'parent', 'field-parent', 'field-parent', 'field-name');
-
- return $form;
-}
-
-/**
- * Form validation handler for field_ui_field_overview_form().
- *
- * @see field_ui_field_overview_form_submit()
- */
-function field_ui_field_overview_form_validate($form, &$form_state) {
- _field_ui_field_overview_form_validate_add_new($form, $form_state);
- _field_ui_field_overview_form_validate_add_existing($form, $form_state);
-}
-
-/**
- * Validates the 'add new field' row of field_ui_field_overview_form().
- *
- * @see field_ui_field_overview_form_validate()
- */
-function _field_ui_field_overview_form_validate_add_new($form, &$form_state) {
- $field = $form_state['values']['fields']['_add_new_field'];
-
- // Validate if any information was provided in the 'add new field' row.
- if (array_filter(array($field['label'], $field['field_name'], $field['type'], $field['widget_type']))) {
- // Missing label.
- if (!$field['label']) {
- form_set_error('fields][_add_new_field][label', t('Add new field: you need to provide a label.'));
- }
-
- // Missing field name.
- if (!$field['field_name']) {
- form_set_error('fields][_add_new_field][field_name', t('Add new field: you need to provide a field name.'));
- }
- // Field name validation.
- else {
- $field_name = $field['field_name'];
-
- // Add the 'field_' prefix.
- $field_name = 'field_' . $field_name;
- form_set_value($form['fields']['_add_new_field']['field_name'], $field_name, $form_state);
- }
-
- // Missing field type.
- if (!$field['type']) {
- form_set_error('fields][_add_new_field][type', t('Add new field: you need to select a field type.'));
- }
-
- // Missing widget type.
- if (!$field['widget_type']) {
- form_set_error('fields][_add_new_field][widget_type', t('Add new field: you need to select a widget.'));
- }
- // Wrong widget type.
- elseif ($field['type']) {
- $widget_types = field_ui_widget_type_options($field['type']);
- if (!isset($widget_types[$field['widget_type']])) {
- form_set_error('fields][_add_new_field][widget_type', t('Add new field: invalid widget.'));
- }
- }
- }
+ return drupal_build_form('field_ui_field_overview_form', $form_state);
}
/**
@@ -742,688 +341,36 @@ function _field_ui_field_name_exists($value) {
}
/**
- * Validates the 're-use existing field' row of field_ui_field_overview_form().
+ * Returns the built and processed 'Manage display' form of a bundle.
*
- * @see field_ui_field_overview_form_validate()
- */
-function _field_ui_field_overview_form_validate_add_existing($form, &$form_state) {
- // The form element might be absent if no existing fields can be added to
- // this bundle.
- if (isset($form_state['values']['fields']['_add_existing_field'])) {
- $field = $form_state['values']['fields']['_add_existing_field'];
-
- // Validate if any information was provided in the 're-use existing field' row.
- if (array_filter(array($field['label'], $field['field_name'], $field['widget_type']))) {
- // Missing label.
- if (!$field['label']) {
- form_set_error('fields][_add_existing_field][label', t('Re-use existing field: you need to provide a label.'));
- }
-
- // Missing existing field name.
- if (!$field['field_name']) {
- form_set_error('fields][_add_existing_field][field_name', t('Re-use existing field: you need to select a field.'));
- }
-
- // Missing widget type.
- if (!$field['widget_type']) {
- form_set_error('fields][_add_existing_field][widget_type', t('Re-use existing field: you need to select a widget.'));
- }
- // Wrong widget type.
- elseif ($field['field_name'] && ($existing_field = field_info_field($field['field_name']))) {
- $widget_types = field_ui_widget_type_options($existing_field['type']);
- if (!isset($widget_types[$field['widget_type']])) {
- form_set_error('fields][_add_existing_field][widget_type', t('Re-use existing field: invalid widget.'));
- }
- }
- }
- }
-}
-
-/**
- * Form submission handler for field_ui_field_overview_form().
+ * The resulting form allows fields and pseudo-fields to be re-ordered.
*
- * @see field_ui_field_overview_form_validate()
- */
-function field_ui_field_overview_form_submit($form, &$form_state) {
- $form_values = $form_state['values']['fields'];
- $entity_type = $form['#entity_type'];
- $bundle = $form['#bundle'];
- $admin_path = _field_ui_bundle_admin_path($entity_type, $bundle);
-
- $bundle_settings = field_bundle_settings($entity_type, $bundle);
-
- // Update field weights.
- foreach ($form_values as $key => $values) {
- if (in_array($key, $form['#fields'])) {
- $instance = field_read_instance($entity_type, $key, $bundle);
- $instance['widget']['weight'] = $values['weight'];
- field_update_instance($instance);
- }
- elseif (in_array($key, $form['#extra'])) {
- $bundle_settings['extra_fields']['form'][$key]['weight'] = $values['weight'];
- }
- }
-
- field_bundle_settings($entity_type, $bundle, $bundle_settings);
-
- $destinations = array();
-
- // Create new field.
- $field = array();
- if (!empty($form_values['_add_new_field']['field_name'])) {
- $values = $form_values['_add_new_field'];
-
- $field = array(
- 'field_name' => $values['field_name'],
- 'type' => $values['type'],
- 'translatable' => $values['translatable'],
- );
- $instance = array(
- 'field_name' => $field['field_name'],
- 'entity_type' => $entity_type,
- 'bundle' => $bundle,
- 'label' => $values['label'],
- 'widget' => array(
- 'type' => $values['widget_type'],
- 'weight' => $values['weight'],
- ),
- );
-
- // Create the field and instance.
- try {
- field_create_field($field);
- field_create_instance($instance);
-
- $destinations[] = $admin_path . '/fields/' . $field['field_name'] . '/field-settings';
- $destinations[] = $admin_path . '/fields/' . $field['field_name'];
-
- // Store new field information for any additional submit handlers.
- $form_state['fields_added']['_add_new_field'] = $field['field_name'];
- }
- catch (Exception $e) {
- drupal_set_message(t('There was a problem creating field %label: !message', array('%label' => $instance['label'], '!message' => $e->getMessage())), 'error');
- }
- }
-
- // Re-use existing field.
- if (!empty($form_values['_add_existing_field']['field_name'])) {
- $values = $form_values['_add_existing_field'];
- $field = field_info_field($values['field_name']);
- if (!empty($field['locked'])) {
- drupal_set_message(t('The field %label cannot be added because it is locked.', array('%label' => $values['label'])), 'error');
- }
- else {
- $instance = array(
- 'field_name' => $field['field_name'],
- 'entity_type' => $entity_type,
- 'bundle' => $bundle,
- 'label' => $values['label'],
- 'widget' => array(
- 'type' => $values['widget_type'],
- 'weight' => $values['weight'],
- ),
- );
-
- try {
- field_create_instance($instance);
- $destinations[] = $admin_path . '/fields/' . $instance['field_name'] . '/edit';
- // Store new field information for any additional submit handlers.
- $form_state['fields_added']['_add_existing_field'] = $instance['field_name'];
- }
- catch (Exception $e) {
- drupal_set_message(t('There was a problem creating field instance %label: @message.', array('%label' => $instance['label'], '@message' => $e->getMessage())), 'error');
- }
- }
- }
-
- if ($destinations) {
- $destination = drupal_get_destination();
- $destinations[] = $destination['destination'];
- unset($_GET['destination']);
- $form_state['redirect'] = field_ui_get_destinations($destinations);
- }
- else {
- drupal_set_message(t('Your settings have been saved.'));
- }
-}
-
-/**
- * Form constructor for the field display settings for a given view mode.
+ * @param string $entity_type
+ * The entity type for the fieldable entity.
+ * @param string $bundle
+ * The bundle for the fieldable entity.
+ * @param string $view_mode
+ * The view mode for the fieldable entity.
+ *
+ * @return
+ * The processed form for the given entity type and bundle.
*
* @see field_ui_menu()
* @see field_ui_display_overview_multistep_submit()
- * @see field_ui_display_overview_form_submit()
+ * @see Drupal\field_ui\DisplayOverview::submit()
* @ingroup forms
*/
-function field_ui_display_overview_form($form, &$form_state, $entity_type, $bundle, $view_mode) {
+function field_ui_display_overview($entity_type, $bundle, $view_mode) {
$bundle = field_extract_bundle($entity_type, $bundle);
-
field_ui_inactive_message($entity_type, $bundle);
- $admin_path = _field_ui_bundle_admin_path($entity_type, $bundle);
- // Gather type information.
- $instances = field_info_instances($entity_type, $bundle);
- $field_types = field_info_field_types();
- $extra_fields = field_info_extra_fields($entity_type, $bundle, 'display');
+ $display_overview = new DisplayOverview($entity_type, $bundle, $view_mode);
- $form_state += array(
- 'formatter_settings_edit' => NULL,
- );
+ $form_state = array();
+ $form_state['build_info']['callback'] = array($display_overview, 'form');
+ $form_state['build_info']['args'] = array($entity_type, $bundle, $view_mode);
- $form += array(
- '#entity_type' => $entity_type,
- '#bundle' => $bundle,
- '#view_mode' => $view_mode,
- '#fields' => array_keys($instances),
- '#extra' => array_keys($extra_fields),
- );
-
- if (empty($instances) && empty($extra_fields)) {
- drupal_set_message(t('There are no fields yet added. You can add new fields on the Manage fields page.', array('@link' => url($admin_path . '/fields'))), 'warning');
- return $form;
- }
-
- $table = array(
- '#type' => 'field_ui_table',
- '#tree' => TRUE,
- '#header' => array(
- t('Field'),
- t('Weight'),
- t('Parent'),
- t('Label'),
- array('data' => t('Format'), 'colspan' => 3),
- ),
- '#regions' => array(
- 'visible' => array('message' => t('No field is displayed.')),
- 'hidden' => array('title' => t('Hidden'), 'message' => t('No field is hidden.')),
- ),
- '#parent_options' => array(),
- '#attributes' => array(
- 'class' => array('field-ui-overview'),
- 'id' => 'field-display-overview',
- ),
- // Add Ajax wrapper.
- '#prefix' => '',
- '#suffix' => '
',
- );
-
- $field_label_options = array(
- 'above' => t('Above'),
- 'inline' => t('Inline'),
- 'hidden' => t(''),
- );
- $extra_visibility_options = array(
- 'visible' => t('Visible'),
- 'hidden' => t('Hidden'),
- );
-
- // Field rows.
- foreach ($instances as $name => $instance) {
- $field = field_info_field($instance['field_name']);
-
- // Provide default settings if needed.
- if (isset($instance['display'][$view_mode])) {
- $display = $instance['display'][$view_mode];
- }
- else {
- $display = array(
- 'type' => 'hidden',
- 'label' => 'above',
- 'settings' => array(),
- 'weight' => 0,
- );
- }
-
- $table[$name] = array(
- '#attributes' => array('class' => array('draggable', 'tabledrag-leaf')),
- '#row_type' => 'field',
- '#region_callback' => 'field_ui_display_overview_row_region',
- '#js_settings' => array(
- 'rowHandler' => 'field',
- 'defaultFormatter' => $field_types[$field['type']]['default_formatter'],
- ),
- 'human_name' => array(
- '#markup' => check_plain($instance['label']),
- ),
- 'weight' => array(
- '#type' => 'textfield',
- '#title' => t('Weight for @title', array('@title' => $instance['label'])),
- '#title_display' => 'invisible',
- '#default_value' => $display['weight'],
- '#size' => 3,
- '#attributes' => array('class' => array('field-weight')),
- ),
- 'parent_wrapper' => array(
- 'parent' => array(
- '#type' => 'select',
- '#title' => t('Label display for @title', array('@title' => $instance['label'])),
- '#title_display' => 'invisible',
- '#options' => $table['#parent_options'],
- '#empty_value' => '',
- '#attributes' => array('class' => array('field-parent')),
- '#parents' => array('fields', $name, 'parent'),
- ),
- 'hidden_name' => array(
- '#type' => 'hidden',
- '#default_value' => $name,
- '#attributes' => array('class' => array('field-name')),
- ),
- ),
- 'label' => array(
- '#type' => 'select',
- '#title' => t('Label display for @title', array('@title' => $instance['label'])),
- '#title_display' => 'invisible',
- '#options' => $field_label_options,
- '#default_value' => $display['label'],
- ),
- );
-
- $formatter_options = field_ui_formatter_options($field['type']);
- $formatter_options['hidden'] = t('');
- $table[$name]['format'] = array(
- 'type' => array(
- '#type' => 'select',
- '#title' => t('Formatter for @title', array('@title' => $instance['label'])),
- '#title_display' => 'invisible',
- '#options' => $formatter_options,
- '#default_value' => $display['type'],
- '#parents' => array('fields', $name, 'type'),
- '#attributes' => array('class' => array('field-formatter-type')),
- ),
- 'settings_edit_form' => array(),
- );
-
- // Formatter settings.
-
- // Check the currently selected formatter, and merge persisted values for
- // formatter settings.
- if (isset($form_state['values']['fields'][$name]['type'])) {
- $display['type'] = $form_state['values']['fields'][$name]['type'];
- }
- if (isset($form_state['formatter_settings'][$name])) {
- $display['settings'] = $form_state['formatter_settings'][$name];
- }
- $formatter = $instance->getFormatter($display);
-
- // Base button element for the various formatter settings actions.
- $base_button = array(
- '#submit' => array('field_ui_display_overview_multistep_submit'),
- '#ajax' => array(
- 'callback' => 'field_ui_display_overview_multistep_js',
- 'wrapper' => 'field-display-overview-wrapper',
- 'effect' => 'fade',
- ),
- '#field_name' => $name,
- );
-
- if ($form_state['formatter_settings_edit'] == $name) {
- // We are currently editing this field's formatter settings. Display the
- // settings form and submit buttons.
- $table[$name]['format']['settings_edit_form'] = array();
-
- if ($formatter) {
- $formatter_type_info = $formatter->getDefinition();
-
- // Generate the settings form and allow other modules to alter it.
- $settings_form = $formatter->settingsForm($form, $form_state);
- $context = array(
- 'formatter' => $formatter,
- 'field' => $field,
- 'instance' => $instance,
- 'view_mode' => $view_mode,
- 'form' => $form,
- );
- drupal_alter('field_formatter_settings_form', $settings_form, $form_state, $context);
-
- if ($settings_form) {
- $table[$name]['format']['#cell_attributes'] = array('colspan' => 3);
- $table[$name]['format']['settings_edit_form'] = array(
- '#type' => 'container',
- '#attributes' => array('class' => array('field-formatter-settings-edit-form')),
- '#parents' => array('fields', $name, 'settings_edit_form'),
- 'label' => array(
- '#markup' => t('Format settings:') . ' ' . $formatter_type_info['label'] . '',
- ),
- 'settings' => $settings_form,
- 'actions' => array(
- '#type' => 'actions',
- 'save_settings' => $base_button + array(
- '#type' => 'submit',
- '#name' => $name . '_formatter_settings_update',
- '#value' => t('Update'),
- '#op' => 'update',
- ),
- 'cancel_settings' => $base_button + array(
- '#type' => 'submit',
- '#name' => $name . '_formatter_settings_cancel',
- '#value' => t('Cancel'),
- '#op' => 'cancel',
- // Do not check errors for the 'Cancel' button, but make sure we
- // get the value of the 'formatter type' select.
- '#limit_validation_errors' => array(array('fields', $name, 'type')),
- ),
- ),
- );
- $table[$name]['#attributes']['class'][] = 'field-formatter-settings-editing';
- }
- }
- }
- else {
- $table[$name]['settings_summary'] = array();
- $table[$name]['settings_edit'] = array();
-
- if ($formatter) {
- // Display a summary of the current formatter settings, and (if the
- // summary is not empty) a button to edit them.
- $summary = $formatter->settingsSummary();
-
- // Allow other modules to alter the summary.
- $context = array(
- 'formatter' => $formatter,
- 'field' => $field,
- 'instance' => $instance,
- 'view_mode' => $view_mode,
- );
- drupal_alter('field_formatter_settings_summary', $summary, $context);
-
- if ($summary) {
- $table[$name]['settings_summary'] = array(
- '#markup' => '' . $summary . '
',
- '#cell_attributes' => array('class' => array('field-formatter-summary-cell')),
- );
- $table[$name]['settings_edit'] = $base_button + array(
- '#type' => 'image_button',
- '#name' => $name . '_formatter_settings_edit',
- '#src' => 'core/misc/configure-dark.png',
- '#attributes' => array('class' => array('field-formatter-settings-edit'), 'alt' => t('Edit')),
- '#op' => 'edit',
- // Do not check errors for the 'Edit' button, but make sure we get
- // the value of the 'formatter type' select.
- '#limit_validation_errors' => array(array('fields', $name, 'type')),
- '#prefix' => '',
- '#suffix' => '
',
- );
- }
- }
- }
- }
-
- // Non-field elements.
- foreach ($extra_fields as $name => $extra_field) {
- $display = $extra_field['display'][$view_mode];
- $table[$name] = array(
- '#attributes' => array('class' => array('draggable', 'tabledrag-leaf')),
- '#row_type' => 'extra_field',
- '#region_callback' => 'field_ui_display_overview_row_region',
- '#js_settings' => array('rowHandler' => 'field'),
- 'human_name' => array(
- '#markup' => check_plain($extra_field['label']),
- ),
- 'weight' => array(
- '#type' => 'textfield',
- '#title' => t('Weight for @title', array('@title' => $extra_field['label'])),
- '#title_display' => 'invisible',
- '#default_value' => $display['weight'],
- '#size' => 3,
- '#attributes' => array('class' => array('field-weight')),
- ),
- 'parent_wrapper' => array(
- 'parent' => array(
- '#type' => 'select',
- '#title' => t('Parents for @title', array('@title' => $extra_field['label'])),
- '#title_display' => 'invisible',
- '#options' => $table['#parent_options'],
- '#empty_value' => '',
- '#attributes' => array('class' => array('field-parent')),
- '#parents' => array('fields', $name, 'parent'),
- ),
- 'hidden_name' => array(
- '#type' => 'hidden',
- '#default_value' => $name,
- '#attributes' => array('class' => array('field-name')),
- ),
- ),
- 'empty_cell' => array(
- '#markup' => ' ',
- ),
- 'format' => array(
- 'type' => array(
- '#type' => 'select',
- '#title' => t('Visibility for @title', array('@title' => $extra_field['label'])),
- '#title_display' => 'invisible',
- '#options' => $extra_visibility_options,
- '#default_value' => $display['visible'] ? 'visible' : 'hidden',
- '#parents' => array('fields', $name, 'type'),
- '#attributes' => array('class' => array('field-formatter-type')),
- ),
- ),
- 'settings_summary' => array(),
- 'settings_edit' => array(),
- );
- }
-
- $form['fields'] = $table;
-
- // Custom display settings.
- if ($view_mode == 'default') {
- $entity_info = entity_get_info($entity_type);
- $view_modes = $entity_info['view modes'];
- // Only show the settings if there is more than one view mode.
- if (count($view_modes) > 1) {
- $form['modes'] = array(
- '#type' => 'fieldset',
- '#title' => t('Custom display settings'),
- '#collapsible' => TRUE,
- '#collapsed' => TRUE,
- );
- // Collect options and default values for the 'Custom display settings'
- // checkboxes.
- $options = array();
- $default = array();
- $view_mode_settings = field_view_mode_settings($entity_type, $bundle);
- foreach ($view_modes as $view_mode_name => $view_mode_info) {
- $options[$view_mode_name] = $view_mode_info['label'];
- if (!empty($view_mode_settings[$view_mode_name]['custom_settings'])) {
- $default[] = $view_mode_name;
- }
- }
- $form['modes']['view_modes_custom'] = array(
- '#type' => 'checkboxes',
- '#title' => t('Use custom display settings for the following view modes'),
- '#options' => $options,
- '#default_value' => $default,
- );
- }
- }
-
- // In overviews involving nested rows from contributed modules (i.e
- // field_group), the 'format type' selects can trigger a series of changes in
- // child rows. The #ajax behavior is therefore not attached directly to the
- // selects, but triggered by the client-side script through a hidden #ajax
- // 'Refresh' button. A hidden 'refresh_rows' input tracks the name of
- // affected rows.
- $form['refresh_rows'] = array('#type' => 'hidden');
- $form['refresh'] = array(
- '#type' => 'submit',
- '#value' => t('Refresh'),
- '#op' => 'refresh_table',
- '#submit' => array('field_ui_display_overview_multistep_submit'),
- '#ajax' => array(
- 'callback' => 'field_ui_display_overview_multistep_js',
- 'wrapper' => 'field-display-overview-wrapper',
- 'effect' => 'fade',
- // The button stays hidden, so we hide the Ajax spinner too. Ad-hoc
- // spinners will be added manually by the client-side script.
- 'progress' => 'none',
- ),
- );
-
- $form['actions'] = array('#type' => 'actions');
- $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save'));
-
- $form['#attached']['library'][] = array('field_ui', 'drupal.field_ui');
-
- // Add tabledrag behavior.
- $form['#attached']['drupal_add_tabledrag'][] = array('field-display-overview', 'order', 'sibling', 'field-weight');
- $form['#attached']['drupal_add_tabledrag'][] = array('field-display-overview', 'match', 'parent', 'field-parent', 'field-parent', 'field-name');
-
- return $form;
-}
-
-/**
- * Form submission handler for buttons in field_ui_display_overview_form().
- */
-function field_ui_display_overview_multistep_submit($form, &$form_state) {
- $trigger = $form_state['triggering_element'];
- $op = $trigger['#op'];
-
- switch ($op) {
- case 'edit':
- // Store the field whose settings are currently being edited.
- $field_name = $trigger['#field_name'];
- $form_state['formatter_settings_edit'] = $field_name;
- break;
-
- case 'update':
- // Store the saved settings, and set the field back to 'non edit' mode.
- $field_name = $trigger['#field_name'];
- $values = $form_state['values']['fields'][$field_name]['settings_edit_form']['settings'];
- $form_state['formatter_settings'][$field_name] = $values;
- unset($form_state['formatter_settings_edit']);
- break;
-
- case 'cancel':
- // Set the field back to 'non edit' mode.
- unset($form_state['formatter_settings_edit']);
- break;
-
- case 'refresh_table':
- // If the currently edited field is one of the rows to be refreshed, set
- // it back to 'non edit' mode.
- $updated_rows = explode(' ', $form_state['values']['refresh_rows']);
- if (isset($form_state['formatter_settings_edit']) && in_array($form_state['formatter_settings_edit'], $updated_rows)) {
- unset($form_state['formatter_settings_edit']);
- }
- break;
- }
-
- $form_state['rebuild'] = TRUE;
-}
-
-/**
- * Ajax handler: Handles multistep buttons in field_ui_display_overview_form().
- */
-function field_ui_display_overview_multistep_js($form, &$form_state) {
- $trigger = $form_state['triggering_element'];
- $op = $trigger['#op'];
-
- // Pick the elements that need to receive the ajax-new-content effect.
- switch ($op) {
- case 'edit':
- $updated_rows = array($trigger['#field_name']);
- $updated_columns = array('format');
- break;
-
- case 'update':
- case 'cancel':
- $updated_rows = array($trigger['#field_name']);
- $updated_columns = array('format', 'settings_summary', 'settings_edit');
- break;
-
- case 'refresh_table':
- $updated_rows = array_values(explode(' ', $form_state['values']['refresh_rows']));
- $updated_columns = array('settings_summary', 'settings_edit');
- break;
- }
-
- foreach ($updated_rows as $name) {
- foreach ($updated_columns as $key) {
- $element = &$form['fields'][$name][$key];
- $element['#prefix'] = '' . (isset($element['#prefix']) ? $element['#prefix'] : '');
- $element['#suffix'] = (isset($element['#suffix']) ? $element['#suffix'] : '') . '
';
- }
- }
-
- // Return the whole table.
- return $form['fields'];
-}
-
-/**
- * Form submission handler for field_ui_display_overview_form().
- */
-function field_ui_display_overview_form_submit($form, &$form_state) {
- $form_values = $form_state['values'];
- $entity_type = $form['#entity_type'];
- $bundle = $form['#bundle'];
- $view_mode = $form['#view_mode'];
-
- // Save data for 'regular' fields.
- foreach ($form['#fields'] as $field_name) {
- // Retrieve the stored instance settings to merge with the incoming values.
- $instance = field_read_instance($entity_type, $field_name, $bundle);
- $values = $form_values['fields'][$field_name];
- // Get formatter settings. They lie either directly in submitted form
- // values (if the whole form was submitted while some formatter
- // settings were being edited), or have been persisted in
- // $form_state.
- $settings = array();
- if (isset($values['settings_edit_form']['settings'])) {
- $settings = $values['settings_edit_form']['settings'];
- }
- elseif (isset($form_state['formatter_settings'][$field_name])) {
- $settings = $form_state['formatter_settings'][$field_name];
- }
- elseif (isset($instance['display'][$view_mode]['settings'])) {
- $settings = $instance['display'][$view_mode]['settings'];
- }
-
- // Only save settings actually used by the selected formatter.
- $default_settings = field_info_formatter_settings($values['type']);
- $settings = array_intersect_key($settings, $default_settings);
-
- $instance['display'][$view_mode] = array(
- 'label' => $values['label'],
- 'type' => $values['type'],
- 'weight' => $values['weight'],
- 'settings' => $settings,
- );
- field_update_instance($instance);
- }
-
- // Get current bundle settings.
- $bundle_settings = field_bundle_settings($entity_type, $bundle);
-
- // Save data for 'extra' fields.
- foreach ($form['#extra'] as $name) {
- $bundle_settings['extra_fields']['display'][$name][$view_mode] = array(
- 'weight' => $form_values['fields'][$name]['weight'],
- 'visible' => $form_values['fields'][$name]['type'] == 'visible',
- );
- }
-
- // Save view modes data.
- if ($view_mode == 'default' && !empty($form_values['view_modes_custom'])) {
- $entity_info = entity_get_info($entity_type);
- foreach ($form_values['view_modes_custom'] as $view_mode_name => $value) {
- // Display a message for each view mode newly configured to use custom
- // settings.
- $view_mode_settings = field_view_mode_settings($entity_type, $bundle);
- if (!empty($value) && empty($view_mode_settings[$view_mode_name]['custom_settings'])) {
- $view_mode_label = $entity_info['view modes'][$view_mode_name]['label'];
- $path = _field_ui_bundle_admin_path($entity_type, $bundle) . "/display/$view_mode_name";
- drupal_set_message(t('The %view_mode mode now uses custom display settings. You might want to configure them.', array('%view_mode' => $view_mode_label, '@url' => url($path))));
- // Initialize the newly customized view mode with the display settings
- // from the default view mode.
- _field_ui_add_default_view_mode_settings($entity_type, $bundle, $view_mode_name, $bundle_settings);
- }
- $bundle_settings['view_modes'][$view_mode_name]['custom_settings'] = !empty($value);
- }
- }
-
- // Save updated bundle settings.
- field_bundle_settings($entity_type, $bundle, $bundle_settings);
-
- drupal_set_message(t('Your settings have been saved.'));
+ return drupal_build_form('field_ui_display_overview_form', $form_state);
}
/**
@@ -1446,7 +393,7 @@ function field_ui_display_overview_form_submit($form, &$form_state) {
* An associative array of bundle settings, as expected by
* field_bundle_settings().
*
- * @see field_ui_display_overview_form_submit().
+ * @see Drupal\field_ui\DisplayOverview::submit().
* @see field_bundle_settings()
*/
function _field_ui_add_default_view_mode_settings($entity_type, $bundle, $view_mode, &$settings) {
diff --git a/core/modules/field_ui/field_ui.js b/core/modules/field_ui/field_ui.js
index 25366acfc8c..d55f30b29ef 100644
--- a/core/modules/field_ui/field_ui.js
+++ b/core/modules/field_ui/field_ui.js
@@ -300,7 +300,7 @@ Drupal.fieldUIDisplayOverview.field.prototype = {
* Returns the region corresponding to the current form values of the row.
*/
getRegion: function () {
- return (this.$formatSelect.val() === 'hidden') ? 'hidden' : 'visible';
+ return (this.$formatSelect.val() === 'hidden') ? 'hidden' : 'content';
},
/**
@@ -326,7 +326,9 @@ Drupal.fieldUIDisplayOverview.field.prototype = {
// to the new region.
var currentValue = this.$formatSelect.val();
var value;
- if (region === 'visible') {
+ // @TODO Check if this couldn't just be like
+ // if (region !== 'hidden') {
+ if (region === 'content') {
if (currentValue === 'hidden') {
// Restore the formatter back to the default formatter. Pseudo-fields do
// not have default formatters, we just return to 'visible' for those.
diff --git a/core/modules/field_ui/field_ui.module b/core/modules/field_ui/field_ui.module
index e984b870925..b3dc6f03d4c 100644
--- a/core/modules/field_ui/field_ui.module
+++ b/core/modules/field_ui/field_ui.module
@@ -103,8 +103,8 @@ function field_ui_menu() {
$items["$path/fields"] = array(
'title' => 'Manage fields',
- 'page callback' => 'drupal_get_form',
- 'page arguments' => array('field_ui_field_overview_form', $entity_type, $bundle_arg),
+ 'page callback' => 'field_ui_field_overview',
+ 'page arguments' => array($entity_type, $bundle_arg),
'type' => MENU_LOCAL_TASK,
'weight' => 1,
'file' => 'field_ui.admin.inc',
@@ -154,8 +154,8 @@ function field_ui_menu() {
// 'Manage display' tab.
$items["$path/display"] = array(
'title' => 'Manage display',
- 'page callback' => 'drupal_get_form',
- 'page arguments' => array('field_ui_display_overview_form', $entity_type, $bundle_arg, 'default'),
+ 'page callback' => 'field_ui_display_overview',
+ 'page arguments' => array($entity_type, $bundle_arg, 'default'),
'type' => MENU_LOCAL_TASK,
'weight' => 2,
'file' => 'field_ui.admin.inc',
@@ -173,7 +173,8 @@ function field_ui_menu() {
foreach ($view_modes as $view_mode => $view_mode_info) {
$items["$path/display/$view_mode"] = array(
'title' => $view_mode_info['label'],
- 'page arguments' => array('field_ui_display_overview_form', $entity_type, $bundle_arg, $view_mode),
+ 'page callback' => 'field_ui_display_overview',
+ 'page arguments' => array($entity_type, $bundle_arg, $view_mode),
// The access callback needs to check both the current 'custom
// display' setting for the view mode, and the overall access
// rules for the bundle admin pages.
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php b/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php
new file mode 100644
index 00000000000..086f6ee8881
--- /dev/null
+++ b/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php
@@ -0,0 +1,557 @@
+ array(
+ 'title' => t('Content'),
+ 'invisible' => TRUE,
+ 'message' => t('No field is displayed.')
+ ),
+ 'hidden' => array(
+ 'title' => t('Disabled'),
+ 'message' => t('No field is hidden.')
+ ),
+ );
+ }
+
+ /**
+ * Overrides Drupal\field_ui\OverviewBase::form().
+ *
+ * @param array $form
+ * An associative array containing the structure of the form.
+ * @param array $form_state
+ * A reference to a keyed array containing the current state of the form.
+ *
+ * @return array
+ * The array containing the complete form.
+ */
+ public function form(array $form, array &$form_state) {
+ $form = parent::form($form, $form_state);
+
+ // Gather type information.
+ $instances = field_info_instances($this->entity_type, $this->bundle);
+ $field_types = field_info_field_types();
+ $extra_fields = field_info_extra_fields($this->entity_type, $this->bundle, 'display');
+
+ $form_state += array(
+ 'formatter_settings_edit' => NULL,
+ );
+
+ $form += array(
+ '#entity_type' => $this->entity_type,
+ '#bundle' => $this->bundle,
+ '#view_mode' => $this->view_mode,
+ '#fields' => array_keys($instances),
+ '#extra' => array_keys($extra_fields),
+ );
+
+ if (empty($instances) && empty($extra_fields)) {
+ drupal_set_message(t('There are no fields yet added. You can add new fields on the Manage fields page.', array('@link' => url($admin_path . '/fields'))), 'warning');
+ return $form;
+ }
+
+ $table = array(
+ '#type' => 'field_ui_table',
+ '#tree' => TRUE,
+ '#header' => array(
+ t('Field'),
+ t('Weight'),
+ t('Parent'),
+ t('Label'),
+ array('data' => t('Format'), 'colspan' => 3),
+ ),
+ '#regions' => $this->getRegions(),
+ '#parent_options' => drupal_map_assoc(array_keys($this->getRegions())),
+ '#attributes' => array(
+ 'class' => array('field-ui-overview'),
+ 'id' => 'field-display-overview',
+ ),
+ // Add Ajax wrapper.
+ '#prefix' => '',
+ '#suffix' => '
',
+ );
+
+ $field_label_options = array(
+ 'above' => t('Above'),
+ 'inline' => t('Inline'),
+ 'hidden' => t(''),
+ );
+ $extra_visibility_options = array(
+ 'content' => t('Visible'),
+ 'hidden' => t('Hidden'),
+ );
+
+ // Field rows.
+ foreach ($instances as $name => $instance) {
+ $field = field_info_field($instance['field_name']);
+ $display = $instance['display'][$this->view_mode];
+ $table[$name] = array(
+ '#attributes' => array('class' => array('draggable', 'tabledrag-leaf')),
+ '#row_type' => 'field',
+ '#region_callback' => 'field_ui_display_overview_row_region',
+ '#js_settings' => array(
+ 'rowHandler' => 'field',
+ 'defaultFormatter' => $field_types[$field['type']]['default_formatter'],
+ ),
+ 'human_name' => array(
+ '#markup' => check_plain($instance['label']),
+ ),
+ 'weight' => array(
+ '#type' => 'textfield',
+ '#title' => t('Weight for @title', array('@title' => $instance['label'])),
+ '#title_display' => 'invisible',
+ '#default_value' => $display['weight'],
+ '#size' => 3,
+ '#attributes' => array('class' => array('field-weight')),
+ ),
+ 'parent_wrapper' => array(
+ 'parent' => array(
+ '#type' => 'select',
+ '#title' => t('Label display for @title', array('@title' => $instance['label'])),
+ '#title_display' => 'invisible',
+ '#options' => $table['#parent_options'],
+ '#empty_value' => '',
+ '#attributes' => array('class' => array('field-parent')),
+ '#parents' => array('fields', $name, 'parent'),
+ ),
+ 'hidden_name' => array(
+ '#type' => 'hidden',
+ '#default_value' => $name,
+ '#attributes' => array('class' => array('field-name')),
+ ),
+ ),
+ 'label' => array(
+ '#type' => 'select',
+ '#title' => t('Label display for @title', array('@title' => $instance['label'])),
+ '#title_display' => 'invisible',
+ '#options' => $field_label_options,
+ '#default_value' => $display['label'],
+ ),
+ );
+
+ $formatter_options = field_ui_formatter_options($field['type']);
+ $formatter_options['hidden'] = t('');
+ $table[$name]['format'] = array(
+ 'type' => array(
+ '#type' => 'select',
+ '#title' => t('Formatter for @title', array('@title' => $instance['label'])),
+ '#title_display' => 'invisible',
+ '#options' => $formatter_options,
+ '#default_value' => $display['type'],
+ '#parents' => array('fields', $name, 'type'),
+ '#attributes' => array('class' => array('field-formatter-type')),
+ ),
+ 'settings_edit_form' => array(),
+ );
+
+ // Check the currently selected formatter, and merge persisted values for
+ // formatter settings.
+ if (isset($form_state['values']['fields'][$name]['type'])) {
+ $display['type'] = $form_state['values']['fields'][$name]['type'];
+ }
+ if (isset($form_state['formatter_settings'][$name])) {
+ $display['settings'] = $form_state['formatter_settings'][$name];
+ }
+ $formatter = $instance->getFormatter($display);
+
+ // Base button element for the various formatter settings actions.
+ $base_button = array(
+ '#submit' => array(array($this, 'multistepSubmit')),
+ '#ajax' => array(
+ 'callback' => array($this, 'multistepAjax'),
+ 'wrapper' => 'field-display-overview-wrapper',
+ 'effect' => 'fade',
+ ),
+ '#field_name' => $name,
+ );
+
+ if ($form_state['formatter_settings_edit'] == $name) {
+ // We are currently editing this field's formatter settings. Display the
+ // settings form and submit buttons.
+ $table[$name]['format']['settings_edit_form'] = array();
+
+ if ($formatter) {
+ $formatter_type_info = $formatter->getDefinition();
+
+ // Generate the settings form and allow other modules to alter it.
+ $settings_form = $formatter->settingsForm($form, $form_state);
+ $context = array(
+ 'formatter' => $formatter,
+ 'field' => $field,
+ 'instance' => $instance,
+ 'view_mode' => $this->view_mode,
+ 'form' => $form,
+ );
+ drupal_alter('field_formatter_settings_form', $settings_form, $form_state, $context);
+
+ if ($settings_form) {
+ $table[$name]['format']['#cell_attributes'] = array('colspan' => 3);
+ $table[$name]['format']['settings_edit_form'] = array(
+ '#type' => 'container',
+ '#attributes' => array('class' => array('field-formatter-settings-edit-form')),
+ '#parents' => array('fields', $name, 'settings_edit_form'),
+ 'label' => array(
+ '#markup' => t('Format settings:') . ' ' . $formatter_type_info['label'] . '',
+ ),
+ 'settings' => $settings_form,
+ 'actions' => array(
+ '#type' => 'actions',
+ 'save_settings' => $base_button + array(
+ '#type' => 'submit',
+ '#name' => $name . '_formatter_settings_update',
+ '#value' => t('Update'),
+ '#op' => 'update',
+ ),
+ 'cancel_settings' => $base_button + array(
+ '#type' => 'submit',
+ '#name' => $name . '_formatter_settings_cancel',
+ '#value' => t('Cancel'),
+ '#op' => 'cancel',
+ // Do not check errors for the 'Cancel' button, but make sure we
+ // get the value of the 'formatter type' select.
+ '#limit_validation_errors' => array(array('fields', $name, 'type')),
+ ),
+ ),
+ );
+ $table[$name]['#attributes']['class'][] = 'field-formatter-settings-editing';
+ }
+ }
+ }
+ else {
+ $table[$name]['settings_summary'] = array();
+ $table[$name]['settings_edit'] = array();
+
+ if ($formatter) {
+ // Display a summary of the current formatter settings, and (if the
+ // summary is not empty) a button to edit them.
+ $summary = $formatter->settingsSummary();
+
+ // Allow other modules to alter the summary.
+ $context = array(
+ 'formatter' => $formatter,
+ 'field' => $field,
+ 'instance' => $instance,
+ 'view_mode' => $this->view_mode,
+ );
+ drupal_alter('field_formatter_settings_summary', $summary, $context);
+
+ if ($summary) {
+ $table[$name]['settings_summary'] = array(
+ '#markup' => '' . $summary . '
',
+ '#cell_attributes' => array('class' => array('field-formatter-summary-cell')),
+ );
+ $table[$name]['settings_edit'] = $base_button + array(
+ '#type' => 'image_button',
+ '#name' => $name . '_formatter_settings_edit',
+ '#src' => 'core/misc/configure-dark.png',
+ '#attributes' => array('class' => array('field-formatter-settings-edit'), 'alt' => t('Edit')),
+ '#op' => 'edit',
+ // Do not check errors for the 'Edit' button, but make sure we get
+ // the value of the 'formatter type' select.
+ '#limit_validation_errors' => array(array('fields', $name, 'type')),
+ '#prefix' => '',
+ '#suffix' => '
',
+ );
+ }
+ }
+ }
+ }
+
+ // Non-field elements.
+ foreach ($extra_fields as $name => $extra_field) {
+ $display = $extra_field['display'][$this->view_mode];
+ $table[$name] = array(
+ '#attributes' => array('class' => array('draggable', 'tabledrag-leaf')),
+ '#row_type' => 'extra_field',
+ '#region_callback' => 'field_ui_display_overview_row_region',
+ '#js_settings' => array('rowHandler' => 'field'),
+ 'human_name' => array(
+ '#markup' => check_plain($extra_field['label']),
+ ),
+ 'weight' => array(
+ '#type' => 'textfield',
+ '#title' => t('Weight for @title', array('@title' => $extra_field['label'])),
+ '#title_display' => 'invisible',
+ '#default_value' => $display['weight'],
+ '#size' => 3,
+ '#attributes' => array('class' => array('field-weight')),
+ ),
+ 'parent_wrapper' => array(
+ 'parent' => array(
+ '#type' => 'select',
+ '#title' => t('Parents for @title', array('@title' => $extra_field['label'])),
+ '#title_display' => 'invisible',
+ '#options' => $table['#parent_options'],
+ '#empty_value' => '',
+ '#attributes' => array('class' => array('field-parent')),
+ '#parents' => array('fields', $name, 'parent'),
+ ),
+ 'hidden_name' => array(
+ '#type' => 'hidden',
+ '#default_value' => $name,
+ '#attributes' => array('class' => array('field-name')),
+ ),
+ ),
+ 'empty_cell' => array(
+ '#markup' => ' ',
+ ),
+ 'format' => array(
+ 'type' => array(
+ '#type' => 'select',
+ '#title' => t('Visibility for @title', array('@title' => $extra_field['label'])),
+ '#title_display' => 'invisible',
+ '#options' => $extra_visibility_options,
+ '#default_value' => $display['visible'] ? 'content' : 'hidden',
+ '#parents' => array('fields', $name, 'type'),
+ '#attributes' => array('class' => array('field-formatter-type')),
+ ),
+ ),
+ 'settings_summary' => array(),
+ 'settings_edit' => array(),
+ );
+ }
+
+ $form['fields'] = $table;
+
+ // Custom display settings.
+ if ($this->view_mode == 'default') {
+ $entity_info = entity_get_info($this->entity_type);
+ $view_modes = $entity_info['view modes'];
+ // Only show the settings if there is more than one view mode.
+ if (count($view_modes) > 1) {
+ $form['modes'] = array(
+ '#type' => 'fieldset',
+ '#title' => t('Custom display settings'),
+ '#collapsible' => TRUE,
+ '#collapsed' => TRUE,
+ );
+ // Collect options and default values for the 'Custom display settings'
+ // checkboxes.
+ $options = array();
+ $default = array();
+ $view_mode_settings = field_view_mode_settings($this->entity_type, $this->bundle);
+ foreach ($view_modes as $view_mode_name => $view_mode_info) {
+ $options[$view_mode_name] = $view_mode_info['label'];
+ if (!empty($view_mode_settings[$view_mode_name]['custom_settings'])) {
+ $default[] = $view_mode_name;
+ }
+ }
+ $form['modes']['view_modes_custom'] = array(
+ '#type' => 'checkboxes',
+ '#title' => t('Use custom display settings for the following view modes'),
+ '#options' => $options,
+ '#default_value' => $default,
+ );
+ }
+ }
+
+ // In overviews involving nested rows from contributed modules (i.e
+ // field_group), the 'format type' selects can trigger a series of changes
+ // in child rows. The #ajax behavior is therefore not attached directly to
+ // the selects, but triggered by the client-side script through a hidden
+ // #ajax 'Refresh' button. A hidden 'refresh_rows' input tracks the name of
+ // affected rows.
+ $form['refresh_rows'] = array('#type' => 'hidden');
+ $form['refresh'] = array(
+ '#type' => 'submit',
+ '#value' => t('Refresh'),
+ '#op' => 'refresh_table',
+ '#submit' => array(array($this, 'multistepSubmit')),
+ '#ajax' => array(
+ 'callback' => array($this, 'multistepAjax'),
+ 'wrapper' => 'field-display-overview-wrapper',
+ 'effect' => 'fade',
+ // The button stays hidden, so we hide the Ajax spinner too. Ad-hoc
+ // spinners will be added manually by the client-side script.
+ 'progress' => 'none',
+ ),
+ );
+
+ $form['actions'] = array('#type' => 'actions');
+ $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save'));
+
+ $form['#attached']['library'][] = array('field_ui', 'drupal.field_ui');
+
+ // Add tabledrag behavior.
+ $form['#attached']['drupal_add_tabledrag'][] = array('field-display-overview', 'order', 'sibling', 'field-weight');
+ $form['#attached']['drupal_add_tabledrag'][] = array('field-display-overview', 'match', 'parent', 'field-parent', 'field-parent', 'field-name');
+
+ return $form;
+ }
+
+ /**
+ * Overrides Drupal\field_ui\OverviewBase::submit().
+ *
+ * @param array $form
+ * An associative array containing the structure of the form.
+ * @param array $form_state
+ * A reference to a keyed array containing the current state of the form.
+ */
+ public function submit(array $form, array &$form_state) {
+ $form_values = $form_state['values'];
+
+ // Save data for 'regular' fields.
+ foreach ($form['#fields'] as $field_name) {
+ // Retrieve the stored instance settings to merge with the incoming
+ // values.
+ $instance = field_read_instance($this->entity_type, $field_name, $this->bundle);
+ $values = $form_values['fields'][$field_name];
+ // Get formatter settings. They lie either directly in submitted form
+ // values (if the whole form was submitted while some formatter
+ // settings were being edited), or have been persisted in
+ // $form_state.
+ $settings = array();
+ if (isset($values['settings_edit_form']['settings'])) {
+ $settings = $values['settings_edit_form']['settings'];
+ }
+ elseif (isset($form_state['formatter_settings'][$field_name])) {
+ $settings = $form_state['formatter_settings'][$field_name];
+ }
+ elseif (isset($instance['display'][$this->view_mode]['settings'])) {
+ $settings = $instance['display'][$this->view_mode]['settings'];
+ }
+
+ // Only save settings actually used by the selected formatter.
+ $default_settings = field_info_formatter_settings($values['type']);
+ $settings = array_intersect_key($settings, $default_settings);
+
+ $instance['display'][$this->view_mode] = array(
+ 'label' => $values['label'],
+ 'type' => $values['type'],
+ 'weight' => $values['weight'],
+ 'settings' => $settings,
+ );
+ field_update_instance($instance);
+ }
+
+ // Get current bundle settings.
+ $bundle_settings = field_bundle_settings($this->entity_type, $this->bundle);
+
+ // Save data for 'extra' fields.
+ foreach ($form['#extra'] as $name) {
+ $bundle_settings['extra_fields']['display'][$name][$this->view_mode] = array(
+ 'weight' => $form_values['fields'][$name]['weight'],
+ 'visible' => $form_values['fields'][$name]['type'] == 'content',
+ );
+ }
+
+ // Save view modes data.
+ if ($this->view_mode == 'default' && !empty($form_values['view_modes_custom'])) {
+ $entity_info = entity_get_info($this->entity_type);
+ foreach ($form_values['view_modes_custom'] as $view_mode_name => $value) {
+ // Display a message for each view mode newly configured to use custom
+ // settings.
+ $view_mode_settings = field_view_mode_settings($this->entity_type, $this->bundle);
+ if (!empty($value) && empty($view_mode_settings[$view_mode_name]['custom_settings'])) {
+ $view_mode_label = $entity_info['view modes'][$view_mode_name]['label'];
+ $path = _field_ui_bundle_admin_path($this->entity_type, $this->bundle) . "/display/$view_mode_name";
+ drupal_set_message(t('The %view_mode mode now uses custom display settings. You might want to configure them.', array('%view_mode' => $view_mode_label, '@url' => url($path))));
+ // Initialize the newly customized view mode with the display settings
+ // from the default view mode.
+ _field_ui_add_default_view_mode_settings($this->entity_type, $this->bundle, $view_mode_name, $bundle_settings);
+ }
+ $bundle_settings['view_modes'][$view_mode_name]['custom_settings'] = !empty($value);
+ }
+ }
+
+ // Save updated bundle settings.
+ field_bundle_settings($this->entity_type, $this->bundle, $bundle_settings);
+
+ drupal_set_message(t('Your settings have been saved.'));
+ }
+
+ /**
+ * Form submission handler for multistep buttons.
+ */
+ public function multistepSubmit($form, &$form_state) {
+ $trigger = $form_state['triggering_element'];
+ $op = $trigger['#op'];
+
+ switch ($op) {
+ case 'edit':
+ // Store the field whose settings are currently being edited.
+ $field_name = $trigger['#field_name'];
+ $form_state['formatter_settings_edit'] = $field_name;
+ break;
+
+ case 'update':
+ // Store the saved settings, and set the field back to 'non edit' mode.
+ $field_name = $trigger['#field_name'];
+ $values = $form_state['values']['fields'][$field_name]['settings_edit_form']['settings'];
+ $form_state['formatter_settings'][$field_name] = $values;
+ unset($form_state['formatter_settings_edit']);
+ break;
+
+ case 'cancel':
+ // Set the field back to 'non edit' mode.
+ unset($form_state['formatter_settings_edit']);
+ break;
+
+ case 'refresh_table':
+ // If the currently edited field is one of the rows to be refreshed, set
+ // it back to 'non edit' mode.
+ $updated_rows = explode(' ', $form_state['values']['refresh_rows']);
+ if (isset($form_state['formatter_settings_edit']) && in_array($form_state['formatter_settings_edit'], $updated_rows)) {
+ unset($form_state['formatter_settings_edit']);
+ }
+ break;
+ }
+
+ $form_state['rebuild'] = TRUE;
+ }
+
+ /**
+ * Ajax handler for multistep buttons.
+ */
+ public function multistepAjax($form, &$form_state) {
+ $trigger = $form_state['triggering_element'];
+ $op = $trigger['#op'];
+
+ // Pick the elements that need to receive the ajax-new-content effect.
+ switch ($op) {
+ case 'edit':
+ $updated_rows = array($trigger['#field_name']);
+ $updated_columns = array('format');
+ break;
+
+ case 'update':
+ case 'cancel':
+ $updated_rows = array($trigger['#field_name']);
+ $updated_columns = array('format', 'settings_summary', 'settings_edit');
+ break;
+
+ case 'refresh_table':
+ $updated_rows = array_values(explode(' ', $form_state['values']['refresh_rows']));
+ $updated_columns = array('settings_summary', 'settings_edit');
+ break;
+ }
+
+ foreach ($updated_rows as $name) {
+ foreach ($updated_columns as $key) {
+ $element = &$form['fields'][$name][$key];
+ $element['#prefix'] = '' . (isset($element['#prefix']) ? $element['#prefix'] : '');
+ $element['#suffix'] = (isset($element['#suffix']) ? $element['#suffix'] : '') . '
';
+ }
+ }
+
+ // Return the whole table.
+ return $form['fields'];
+ }
+}
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php b/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php
new file mode 100644
index 00000000000..5629ac9682b
--- /dev/null
+++ b/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php
@@ -0,0 +1,641 @@
+entity_type = $entity_type;
+ $this->bundle = $bundle;
+ $this->view_mode = 'form';
+ $this->adminPath = _field_ui_bundle_admin_path($this->entity_type, $this->bundle);
+ }
+
+ /**
+ * Implements Drupal\field_ui\OverviewBase::getRegions().
+ */
+ public function getRegions() {
+ return array(
+ 'content' => array(
+ 'title' => t('Content'),
+ 'invisible' => TRUE,
+ 'message' => t('No fields are present yet.'),
+ ),
+ 'hidden' => array(
+ 'title' => t('Hidden'),
+ 'invisible' => TRUE,
+ 'message' => t('No fields.'),
+ ),
+ );
+ }
+
+ /**
+ * Overrides Drupal\field_ui\OverviewBase::form().
+ *
+ * @param array $form
+ * An associative array containing the structure of the form.
+ * @param array $form_state
+ * A reference to a keyed array containing the current state of the form.
+ *
+ * @return array
+ * The array containing the complete form.
+ */
+ public function form(array $form, array &$form_state) {
+ $form = parent::form($form, $form_state);
+
+ // When displaying the form, make sure the list of fields is up-to-date.
+ if (empty($form_state['post'])) {
+ field_info_cache_clear();
+ }
+
+ // Gather bundle information.
+ $instances = field_info_instances($this->entity_type, $this->bundle);
+ $field_types = field_info_field_types();
+ $widget_types = field_info_widget_types();
+ $extra_fields = field_info_extra_fields($this->entity_type, $this->bundle, 'form');
+
+ $form += array(
+ '#entity_type' => $this->entity_type,
+ '#bundle' => $this->bundle,
+ '#fields' => array_keys($instances),
+ '#extra' => array_keys($extra_fields),
+ );
+
+ $table = array(
+ '#type' => 'field_ui_table',
+ '#tree' => TRUE,
+ '#header' => array(
+ t('Label'),
+ t('Weight'),
+ t('Parent'),
+ t('Machine name'),
+ t('Field type'),
+ t('Widget'),
+ t('Operations'),
+ ),
+ '#parent_options' => array(),
+ '#regions' => $this->getRegions(),
+ '#attributes' => array(
+ 'class' => array('field-ui-overview'),
+ 'id' => 'field-overview',
+ ),
+ );
+
+ // Fields.
+ foreach ($instances as $name => $instance) {
+ $field = field_info_field($instance['field_name']);
+ $admin_field_path = $this->adminPath . '/fields/' . $instance['field_name'];
+ $table[$name] = array(
+ '#attributes' => array('class' => array('draggable', 'tabledrag-leaf')),
+ '#row_type' => 'field',
+ '#region_callback' => 'field_ui_field_overview_row_region',
+ 'label' => array(
+ '#markup' => check_plain($instance['label']),
+ ),
+ 'weight' => array(
+ '#type' => 'textfield',
+ '#title' => t('Weight for @title', array('@title' => $instance['label'])),
+ '#title_display' => 'invisible',
+ '#default_value' => $instance['widget']['weight'],
+ '#size' => 3,
+ '#attributes' => array('class' => array('field-weight')),
+ ),
+ 'parent_wrapper' => array(
+ 'parent' => array(
+ '#type' => 'select',
+ '#title' => t('Parent for @title', array('@title' => $instance['label'])),
+ '#title_display' => 'invisible',
+ '#options' => $table['#parent_options'],
+ '#empty_value' => '',
+ '#attributes' => array('class' => array('field-parent')),
+ '#parents' => array('fields', $name, 'parent'),
+ ),
+ 'hidden_name' => array(
+ '#type' => 'hidden',
+ '#default_value' => $name,
+ '#attributes' => array('class' => array('field-name')),
+ ),
+ ),
+ 'field_name' => array(
+ '#markup' => $instance['field_name'],
+ ),
+ 'type' => array(
+ '#type' => 'link',
+ '#title' => t($field_types[$field['type']]['label']),
+ '#href' => $admin_field_path . '/field-settings',
+ '#options' => array('attributes' => array('title' => t('Edit field settings.'))),
+ ),
+ 'widget_type' => array(
+ '#type' => 'link',
+ '#title' => t($widget_types[$instance['widget']['type']]['label']),
+ '#href' => $admin_field_path . '/widget-type',
+ '#options' => array('attributes' => array('title' => t('Change widget type.'))),
+ ),
+ );
+
+ $links = array();
+ $links['edit'] = array(
+ 'title' => t('edit'),
+ 'href' => $admin_field_path,
+ 'attributes' => array('title' => t('Edit instance settings.')),
+ );
+ $links['delete'] = array(
+ 'title' => t('delete'),
+ 'href' => "$admin_field_path/delete",
+ 'attributes' => array('title' => t('Delete instance.')),
+ );
+ $table[$name]['operations']['data'] = array(
+ '#type' => 'operations',
+ '#links' => $links,
+ );
+
+ if (!empty($instance['locked'])) {
+ $table[$name]['operations'] = array('#value' => t('Locked'));
+ $table[$name]['#attributes']['class'][] = 'menu-disabled';
+ }
+ }
+
+ // Non-field elements.
+ foreach ($extra_fields as $name => $extra_field) {
+ $table[$name] = array(
+ '#attributes' => array('class' => array('draggable', 'tabledrag-leaf')),
+ '#row_type' => 'extra_field',
+ '#region_callback' => 'field_ui_field_overview_row_region',
+ 'label' => array(
+ '#markup' => check_plain($extra_field['label']),
+ ),
+ 'weight' => array(
+ '#type' => 'textfield',
+ '#default_value' => $extra_field['weight'],
+ '#size' => 3,
+ '#attributes' => array('class' => array('field-weight')),
+ '#title_display' => 'invisible',
+ '#title' => t('Weight for @title', array('@title' => $extra_field['label'])),
+ ),
+ 'parent_wrapper' => array(
+ 'parent' => array(
+ '#type' => 'select',
+ '#title' => t('Parent for @title', array('@title' => $extra_field['label'])),
+ '#title_display' => 'invisible',
+ '#options' => $table['#parent_options'],
+ '#empty_value' => '',
+ '#attributes' => array('class' => array('field-parent')),
+ '#parents' => array('fields', $name, 'parent'),
+ ),
+ 'hidden_name' => array(
+ '#type' => 'hidden',
+ '#default_value' => $name,
+ '#attributes' => array('class' => array('field-name')),
+ ),
+ ),
+ 'field_name' => array(
+ '#markup' => $name,
+ ),
+ 'type' => array(
+ '#markup' => isset($extra_field['description']) ? $extra_field['description'] : '',
+ '#cell_attributes' => array('colspan' => 2),
+ ),
+ 'operations' => array(
+ '#markup' => '',
+ ),
+ );
+ }
+
+ // Additional row: add new field.
+ $max_weight = field_info_max_weight($this->entity_type, $this->bundle, 'form');
+ $field_type_options = field_ui_field_type_options();
+ $widget_type_options = field_ui_widget_type_options(NULL, TRUE);
+ if ($field_type_options && $widget_type_options) {
+ $name = '_add_new_field';
+ $table[$name] = array(
+ '#attributes' => array('class' => array('draggable', 'tabledrag-leaf', 'add-new')),
+ '#row_type' => 'add_new_field',
+ '#region_callback' => 'field_ui_field_overview_row_region',
+ 'label' => array(
+ '#type' => 'textfield',
+ '#title' => t('New field label'),
+ '#title_display' => 'invisible',
+ '#size' => 15,
+ '#description' => t('Label'),
+ '#prefix' => '',
+ ),
+ 'weight' => array(
+ '#type' => 'textfield',
+ '#default_value' => $max_weight + 1,
+ '#size' => 3,
+ '#title_display' => 'invisible',
+ '#title' => t('Weight for new field'),
+ '#attributes' => array('class' => array('field-weight')),
+ '#prefix' => '
',
+ ),
+ 'parent_wrapper' => array(
+ 'parent' => array(
+ '#type' => 'select',
+ '#title' => t('Parent for new field'),
+ '#title_display' => 'invisible',
+ '#options' => $table['#parent_options'],
+ '#empty_value' => '',
+ '#attributes' => array('class' => array('field-parent')),
+ '#prefix' => '
',
+ '#parents' => array('fields', $name, 'parent'),
+ ),
+ 'hidden_name' => array(
+ '#type' => 'hidden',
+ '#default_value' => $name,
+ '#attributes' => array('class' => array('field-name')),
+ ),
+ ),
+ 'field_name' => array(
+ '#type' => 'machine_name',
+ '#title' => t('New field name'),
+ '#title_display' => 'invisible',
+ // This field should stay LTR even for RTL languages.
+ '#field_prefix' => 'field_',
+ '#field_suffix' => '',
+ '#size' => 15,
+ '#description' => t('A unique machine-readable name containing letters, numbers, and underscores.'),
+ // 32 characters minus the 'field_' prefix.
+ '#maxlength' => 26,
+ '#prefix' => '
',
+ '#machine_name' => array(
+ 'source' => array('fields', $name, 'label'),
+ 'exists' => '_field_ui_field_name_exists',
+ 'standalone' => TRUE,
+ 'label' => '',
+ ),
+ '#required' => FALSE,
+ ),
+ 'type' => array(
+ '#type' => 'select',
+ '#title' => t('Type of new field'),
+ '#title_display' => 'invisible',
+ '#options' => $field_type_options,
+ '#empty_option' => t('- Select a field type -'),
+ '#description' => t('Type of data to store.'),
+ '#attributes' => array('class' => array('field-type-select')),
+ '#prefix' => '
',
+ ),
+ 'widget_type' => array(
+ '#type' => 'select',
+ '#title' => t('Widget for new field'),
+ '#title_display' => 'invisible',
+ '#options' => $widget_type_options,
+ '#empty_option' => t('- Select a widget -'),
+ '#description' => t('Form element to edit the data.'),
+ '#attributes' => array('class' => array('widget-type-select')),
+ '#cell_attributes' => array('colspan' => 3),
+ '#prefix' => '
',
+ ),
+ // Place the 'translatable' property as an explicit value so that
+ // contrib modules can form_alter() the value for newly created fields.
+ 'translatable' => array(
+ '#type' => 'value',
+ '#value' => FALSE,
+ ),
+ );
+ }
+
+ // Additional row: re-use existing field.
+ $existing_fields = field_ui_existing_field_options($this->entity_type, $this->bundle);
+ if ($existing_fields && $widget_type_options) {
+ // Build list of options.
+ $existing_field_options = array();
+ foreach ($existing_fields as $field_name => $info) {
+ $text = t('@type: @field (@label)', array(
+ '@type' => $info['type_label'],
+ '@label' => $info['label'],
+ '@field' => $info['field'],
+ ));
+ $existing_field_options[$field_name] = truncate_utf8($text, 80, FALSE, TRUE);
+ }
+ asort($existing_field_options);
+ $name = '_add_existing_field';
+ $table[$name] = array(
+ '#attributes' => array('class' => array('draggable', 'tabledrag-leaf', 'add-new')),
+ '#row_type' => 'add_new_field',
+ '#region_callback' => 'field_ui_field_overview_row_region',
+ 'label' => array(
+ '#type' => 'textfield',
+ '#title' => t('Existing field label'),
+ '#title_display' => 'invisible',
+ '#size' => 15,
+ '#description' => t('Label'),
+ '#attributes' => array('class' => array('label-textfield')),
+ '#prefix' => '',
+ ),
+ 'weight' => array(
+ '#type' => 'textfield',
+ '#default_value' => $max_weight + 2,
+ '#size' => 3,
+ '#title_display' => 'invisible',
+ '#title' => t('Weight for added field'),
+ '#attributes' => array('class' => array('field-weight')),
+ '#prefix' => '
',
+ ),
+ 'parent_wrapper' => array(
+ 'parent' => array(
+ '#type' => 'select',
+ '#title' => t('Parent for existing field'),
+ '#title_display' => 'invisible',
+ '#options' => $table['#parent_options'],
+ '#empty_value' => '',
+ '#attributes' => array('class' => array('field-parent')),
+ '#prefix' => '
',
+ '#parents' => array('fields', $name, 'parent'),
+ ),
+ 'hidden_name' => array(
+ '#type' => 'hidden',
+ '#default_value' => $name,
+ '#attributes' => array('class' => array('field-name')),
+ ),
+ ),
+ 'field_name' => array(
+ '#type' => 'select',
+ '#title' => t('Existing field to share'),
+ '#title_display' => 'invisible',
+ '#options' => $existing_field_options,
+ '#empty_option' => t('- Select an existing field -'),
+ '#description' => t('Field to share'),
+ '#attributes' => array('class' => array('field-select')),
+ '#cell_attributes' => array('colspan' => 2),
+ '#prefix' => '
',
+ ),
+ 'widget_type' => array(
+ '#type' => 'select',
+ '#title' => t('Widget for existing field'),
+ '#title_display' => 'invisible',
+ '#options' => $widget_type_options,
+ '#empty_option' => t('- Select a widget -'),
+ '#description' => t('Form element to edit the data.'),
+ '#attributes' => array('class' => array('widget-type-select')),
+ '#cell_attributes' => array('colspan' => 3),
+ '#prefix' => '
',
+ ),
+ );
+ }
+ $form['fields'] = $table;
+
+ // Add AJAX wrapper.
+ $form['fields']['#prefix'] = '';
+ $form['fields']['#suffix'] = '
';
+
+ // This key is used to store the current updated field.
+ $form_state += array(
+ 'formatter_settings_edit' => NULL,
+ );
+
+ $form['actions'] = array('#type' => 'actions');
+ $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save'));
+
+ $form['#attached']['library'][] = array('field_ui', 'drupal.field_ui');
+
+ // Add settings for the update selects behavior.
+ $js_fields = array();
+ foreach ($existing_fields as $field_name => $info) {
+ $js_fields[$field_name] = array('label' => $info['label'], 'type' => $info['type'], 'widget' => $info['widget_type']);
+ }
+
+ $form['#attached']['js'][] = array(
+ 'type' => 'setting',
+ 'data' => array('fields' => $js_fields, 'fieldWidgetTypes' => field_ui_widget_type_options()),
+ );
+
+ // Add tabledrag behavior.
+ $form['#attached']['drupal_add_tabledrag'][] = array('field-overview', 'order', 'sibling', 'field-weight');
+ $form['#attached']['drupal_add_tabledrag'][] = array('field-overview', 'match', 'parent', 'field-parent', 'field-parent', 'field-name');
+
+ return $form;
+ }
+
+ /**
+ * Overrides Drupal\field_ui\OverviewBase::validate().
+ *
+ * @param array $form
+ * An associative array containing the structure of the form.
+ * @param array $form_state
+ * A reference to a keyed array containing the current state of the form.
+ */
+ public function validate(array $form, array &$form_state) {
+ $this->validateAddNew($form, $form_state);
+ $this->validateAddExisting($form, $form_state);
+ }
+
+ /**
+ * Validates the 'add new field' row.
+ *
+ * @param array $form
+ * An associative array containing the structure of the form.
+ * @param array $form_state
+ * A reference to a keyed array containing the current state of the form.
+ *
+ * @see Drupal\field_ui\FieldOverview::validate()
+ */
+ protected function validateAddNew(array $form, array &$form_state) {
+ $field = $form_state['values']['fields']['_add_new_field'];
+
+ // Validate if any information was provided in the 'add new field' row.
+ if (array_filter(array($field['label'], $field['field_name'], $field['type'], $field['widget_type']))) {
+ // Missing label.
+ if (!$field['label']) {
+ form_set_error('fields][_add_new_field][label', t('Add new field: you need to provide a label.'));
+ }
+
+ // Missing field name.
+ if (!$field['field_name']) {
+ form_set_error('fields][_add_new_field][field_name', t('Add new field: you need to provide a field name.'));
+ }
+ // Field name validation.
+ else {
+ $field_name = $field['field_name'];
+
+ // Add the 'field_' prefix.
+ $field_name = 'field_' . $field_name;
+ form_set_value($form['fields']['_add_new_field']['field_name'], $field_name, $form_state);
+ }
+
+ // Missing field type.
+ if (!$field['type']) {
+ form_set_error('fields][_add_new_field][type', t('Add new field: you need to select a field type.'));
+ }
+
+ // Missing widget type.
+ if (!$field['widget_type']) {
+ form_set_error('fields][_add_new_field][widget_type', t('Add new field: you need to select a widget.'));
+ }
+ // Wrong widget type.
+ elseif ($field['type']) {
+ $widget_types = field_ui_widget_type_options($field['type']);
+ if (!isset($widget_types[$field['widget_type']])) {
+ form_set_error('fields][_add_new_field][widget_type', t('Add new field: invalid widget.'));
+ }
+ }
+ }
+ }
+
+ /**
+ * Validates the 're-use existing field' row.
+ *
+ * @param array $form
+ * An associative array containing the structure of the form.
+ * @param array $form_state
+ * A reference to a keyed array containing the current state of the form.
+ *
+ * @see Drupal\field_ui\FieldOverview::validate()
+ */
+ protected function validateAddExisting(array $form, array &$form_state) {
+ // The form element might be absent if no existing fields can be added to
+ // this bundle.
+ if (isset($form_state['values']['fields']['_add_existing_field'])) {
+ $field = $form_state['values']['fields']['_add_existing_field'];
+
+ // Validate if any information was provided in the
+ // 're-use existing field' row.
+ if (array_filter(array($field['label'], $field['field_name'], $field['widget_type']))) {
+ // Missing label.
+ if (!$field['label']) {
+ form_set_error('fields][_add_existing_field][label', t('Re-use existing field: you need to provide a label.'));
+ }
+
+ // Missing existing field name.
+ if (!$field['field_name']) {
+ form_set_error('fields][_add_existing_field][field_name', t('Re-use existing field: you need to select a field.'));
+ }
+
+ // Missing widget type.
+ if (!$field['widget_type']) {
+ form_set_error('fields][_add_existing_field][widget_type', t('Re-use existing field: you need to select a widget.'));
+ }
+ // Wrong widget type.
+ elseif ($field['field_name'] && ($existing_field = field_info_field($field['field_name']))) {
+ $widget_types = field_ui_widget_type_options($existing_field['type']);
+ if (!isset($widget_types[$field['widget_type']])) {
+ form_set_error('fields][_add_existing_field][widget_type', t('Re-use existing field: invalid widget.'));
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Overrides Drupal\field_ui\OverviewBase::submit().
+ *
+ * @param array $form
+ * An associative array containing the structure of the form.
+ * @param array $form_state
+ * A reference to a keyed array containing the current state of the form.
+ */
+ public function submit(array $form, array &$form_state) {
+ $form_values = $form_state['values']['fields'];
+
+ $bundle_settings = field_bundle_settings($this->entity_type, $this->bundle);
+
+ // Update field weights.
+ foreach ($form_values as $key => $values) {
+ if (in_array($key, $form['#fields'])) {
+ $instance = field_read_instance($this->entity_type, $key, $this->bundle);
+ $instance['widget']['weight'] = $values['weight'];
+ field_update_instance($instance);
+ }
+ elseif (in_array($key, $form['#extra'])) {
+ $bundle_settings['extra_fields']['form'][$key]['weight'] = $values['weight'];
+ }
+ }
+
+ field_bundle_settings($this->entity_type, $this->bundle, $bundle_settings);
+
+ $destinations = array();
+
+ // Create new field.
+ $field = array();
+ if (!empty($form_values['_add_new_field']['field_name'])) {
+ $values = $form_values['_add_new_field'];
+
+ $field = array(
+ 'field_name' => $values['field_name'],
+ 'type' => $values['type'],
+ 'translatable' => $values['translatable'],
+ );
+ $instance = array(
+ 'field_name' => $field['field_name'],
+ 'entity_type' => $this->entity_type,
+ 'bundle' => $this->bundle,
+ 'label' => $values['label'],
+ 'widget' => array(
+ 'type' => $values['widget_type'],
+ 'weight' => $values['weight'],
+ ),
+ );
+
+ // Create the field and instance.
+ try {
+ field_create_field($field);
+ field_create_instance($instance);
+
+ $destinations[] = $this->adminPath. '/fields/' . $field['field_name'] . '/field-settings';
+ $destinations[] = $this->adminPath . '/fields/' . $field['field_name'];
+
+ // Store new field information for any additional submit handlers.
+ $form_state['fields_added']['_add_new_field'] = $field['field_name'];
+ }
+ catch (Exception $e) {
+ drupal_set_message(t('There was a problem creating field %label: !message', array('%label' => $instance['label'], '!message' => $e->getMessage())), 'error');
+ }
+ }
+
+ // Re-use existing field.
+ if (!empty($form_values['_add_existing_field']['field_name'])) {
+ $values = $form_values['_add_existing_field'];
+ $field = field_info_field($values['field_name']);
+ if (!empty($field['locked'])) {
+ drupal_set_message(t('The field %label cannot be added because it is locked.', array('%label' => $values['label'])), 'error');
+ }
+ else {
+ $instance = array(
+ 'field_name' => $field['field_name'],
+ 'entity_type' => $this->entity_type,
+ 'bundle' => $this->bundle,
+ 'label' => $values['label'],
+ 'widget' => array(
+ 'type' => $values['widget_type'],
+ 'weight' => $values['weight'],
+ ),
+ );
+
+ try {
+ field_create_instance($instance);
+ $destinations[] = $this->adminPath . '/fields/' . $instance['field_name'] . '/edit';
+ // Store new field information for any additional submit handlers.
+ $form_state['fields_added']['_add_existing_field'] = $instance['field_name'];
+ }
+ catch (Exception $e) {
+ drupal_set_message(t('There was a problem creating field instance %label: @message.', array('%label' => $instance['label'], '@message' => $e->getMessage())), 'error');
+ }
+ }
+ }
+
+ if ($destinations) {
+ $destination = drupal_get_destination();
+ $destinations[] = $destination['destination'];
+ unset($_GET['destination']);
+ $form_state['redirect'] = field_ui_get_destinations($destinations);
+ }
+ else {
+ drupal_set_message(t('Your settings have been saved.'));
+ }
+ }
+}
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/OverviewBase.php b/core/modules/field_ui/lib/Drupal/field_ui/OverviewBase.php
new file mode 100644
index 00000000000..c49b3ee7bf3
--- /dev/null
+++ b/core/modules/field_ui/lib/Drupal/field_ui/OverviewBase.php
@@ -0,0 +1,133 @@
+entity_type = $entity_type;
+ $this->bundle = $bundle;
+ $this->view_mode = (isset($view_mode) ? $view_mode : 'default');
+ $this->adminPath = _field_ui_bundle_admin_path($this->entity_type, $this->bundle);
+ }
+
+ /**
+ * Creates a field UI overview form.
+ *
+ * @param array $form
+ * An associative array containing the structure of the form.
+ * @param array $form_state
+ * A reference to a keyed array containing the current state of the form.
+ *
+ * @return array
+ * The array containing the complete form.
+ */
+ public function form(array $form, array &$form_state) {
+ // Add the validate and submit behavior.
+ $form['#validate'] = array(array($this, 'validate'));
+ $form['#submit'] = array(array($this, 'submit'));
+ return $form;
+ }
+
+ /**
+ * Validate handler for the field UI overview form.
+ *
+ * @param array $form
+ * The root element or form.
+ * @param array $form_state
+ * The state of the form.
+ */
+ public function validate(array $form, array &$form_state) {
+ }
+
+ /**
+ * Submit handler for the field UI overview form.
+ *
+ * @param array $form
+ * An associative array containing the structure of the form.
+ * @param array $form_state
+ * A reference to a keyed array containing the current state of the form.
+ */
+ public function submit(array $form, array &$form_state) {
+ }
+
+ /**
+ * Get the regions needed to create the overview form.
+ *
+ * @return array
+ * Example usage:
+ * @code
+ * return array(
+ * 'content' => array(
+ * // label for the region.
+ * 'title' => t('Content'),
+ * // Indicates if the region is visible in the UI.
+ * 'invisible' => TRUE,
+ * // A mesage to indicate that there is nothing to be displayed in
+ * // the region.
+ * 'message' => t('No field is displayed.'),
+ * ),
+ * );
+ * @endcode
+ */
+ abstract public function getRegions();
+
+ /**
+ * Returns an associative array of all regions.
+ */
+ public function getRegionOptions() {
+ $options = array();
+ foreach ($this->getRegions() as $region => $data) {
+ $options[$region] = $data['title'];
+ }
+ return $options;
+ }
+
+}
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeTypeInitialLanguageTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeTypeInitialLanguageTest.php
index e191ecacf2b..e079a3e6b42 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeTypeInitialLanguageTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeTypeInitialLanguageTest.php
@@ -118,11 +118,11 @@ class NodeTypeInitialLanguageTest extends NodeTestBase {
// Changes Language field visibility to true and check if it is saved.
$edit = array(
- 'fields[language][type]' => 'visible',
+ 'fields[language][type]' => 'content',
);
$this->drupalPost('admin/structure/types/manage/article/display', $edit, t('Save'));
$this->drupalGet('admin/structure/types/manage/article/display');
- $this->assertOptionSelected('edit-fields-language-type', 'visible', 'Language field has been set to visible.');
+ $this->assertOptionSelected('edit-fields-language-type', 'content', 'Language field has been set to visible.');
// Loads node page and check if Language field is shown.
$this->drupalGet('node/' . $node->nid);