summaryrefslogtreecommitdiff
path: root/modules/field_ui
diff options
context:
space:
mode:
authorDries Buytaert <dries@buytaert.net>2010-05-23 19:10:23 +0000
committerDries Buytaert <dries@buytaert.net>2010-05-23 19:10:23 +0000
commit5ff0c0d3c7757038af8ab95f5386a9fec1aa1b10 (patch)
tree96c318263445fe4df0b3d23be923f6caaefdface /modules/field_ui
parent5d4fa6f72511d4a3948d5527f9202d6cd2aa137f (diff)
downloadbrdo-5ff0c0d3c7757038af8ab95f5386a9fec1aa1b10.tar.gz
brdo-5ff0c0d3c7757038af8ab95f5386a9fec1aa1b10.tar.bz2
- Patch #553298 by yched, te-brian, chx, sun: redesign the 'Manage Display' screen.
Diffstat (limited to 'modules/field_ui')
-rw-r--r--modules/field_ui/field_ui.admin.inc267
-rw-r--r--modules/field_ui/field_ui.css7
-rw-r--r--modules/field_ui/field_ui.js139
-rw-r--r--modules/field_ui/field_ui.module200
4 files changed, 406 insertions, 207 deletions
diff --git a/modules/field_ui/field_ui.admin.inc b/modules/field_ui/field_ui.admin.inc
index 6be92ee59..2ede71962 100644
--- a/modules/field_ui/field_ui.admin.inc
+++ b/modules/field_ui/field_ui.admin.inc
@@ -83,7 +83,7 @@ function field_ui_field_overview_form($form, &$form_state, $entity_type, $bundle
$field_types = field_info_field_types();
$widget_types = field_info_widget_types();
- $extra = field_extra_fields($entity_type, $bundle);
+ $extra_fields = field_extra_fields($entity_type, $bundle, 'form');
// Store each default weight so that we can add the 'add new' rows after them.
$weights = array();
@@ -93,7 +93,7 @@ function field_ui_field_overview_form($form, &$form_state, $entity_type, $bundle
'#entity_type' => $entity_type,
'#bundle' => $bundle,
'#fields' => array_keys($instances),
- '#extra' => array_keys($extra),
+ '#extra' => array_keys($extra_fields),
'#field_rows' => array(),
);
@@ -155,17 +155,17 @@ function field_ui_field_overview_form($form, &$form_state, $entity_type, $bundle
}
// Non-field elements.
- foreach ($extra as $name => $label) {
- $weight = $extra[$name]['weight'];
+ foreach ($extra_fields as $name => $extra_field) {
+ $weight = $extra_field['weight'];
$form[$name] = array(
'label' => array(
- '#markup' => t($extra[$name]['label']),
+ '#markup' => check_plain($extra_field['label']),
),
'name' => array(
'#markup' => $name,
),
'description' => array(
- '#markup' => isset($extra[$name]['description']) ? $extra[$name]['description'] : '',
+ '#markup' => isset($extra_field['description']) ? $extra_field['description'] : '',
),
'weight' => array(
'#type' => 'textfield',
@@ -173,10 +173,10 @@ function field_ui_field_overview_form($form, &$form_state, $entity_type, $bundle
'#size' => 3,
),
'edit' => array(
- '#markup' => isset($extra[$name]['edit']) ? $extra[$name]['edit'] : '',
+ '#markup' => isset($extra_field['edit']) ? $extra_field['edit'] : '',
),
'delete' => array(
- '#markup' => isset($extra[$name]['delete']) ? $extra[$name]['delete'] : '',
+ '#markup' => isset($extra_field['delete']) ? $extra_field['delete'] : '',
),
'hidden_name' => array(
'#type' => 'hidden',
@@ -464,8 +464,9 @@ function field_ui_field_overview_form_submit($form, &$form_state) {
$bundle = $form['#bundle'];
$admin_path = _field_ui_bundle_admin_path($entity_type, $bundle);
+ $bundle_settings = field_bundle_settings($entity_type, $bundle);
+
// Update field weights.
- $extra = array();
foreach ($form_values as $key => $values) {
if (in_array($key, $form['#fields'])) {
$instance = field_read_instance($entity_type, $key, $bundle);
@@ -476,13 +477,11 @@ function field_ui_field_overview_form_submit($form, &$form_state) {
field_update_instance($instance);
}
elseif (in_array($key, $form['#extra'])) {
- $extra[$key] = $values['weight'];
+ $bundle_settings['extra_fields']['form'][$key]['weight'] = $values['weight'];
}
}
- $extra_weights = variable_get('field_extra_weights', array());
- $extra_weights[$entity_type][$bundle] = $extra;
- variable_set('field_extra_weights', $extra_weights);
+ field_bundle_settings($entity_type, $bundle, $bundle_settings);
$destinations = array();
@@ -563,12 +562,9 @@ function field_ui_field_overview_form_submit($form, &$form_state) {
}
/**
- * Menu callback; presents a listing of fields display settings for a bundle.
- *
- * This form includes form widgets to select which fields appear in teaser and
- * full view modes, and how the field labels should be rendered.
+ * Menu callback; presents field display settings for a given view mode.
*/
-function field_ui_display_overview_form($form, &$form_state, $entity_type, $bundle, $view_modes_selector = 'basic') {
+function field_ui_display_overview_form($form, &$form_state, $entity_type, $bundle, $view_mode) {
$bundle = field_extract_bundle($entity_type, $bundle);
field_ui_inactive_message($entity_type, $bundle);
@@ -577,14 +573,14 @@ function field_ui_display_overview_form($form, &$form_state, $entity_type, $bund
// Gather type information.
$instances = field_info_instances($entity_type, $bundle);
$field_types = field_info_field_types();
- $view_modes = field_ui_view_modes_tabs($entity_type, $view_modes_selector);
+ $extra_fields = field_extra_fields($entity_type, $bundle, 'display');
$form += array(
- '#tree' => TRUE,
'#entity_type' => $entity_type,
'#bundle' => $bundle,
+ '#view_mode' => $view_mode,
'#fields' => array_keys($instances),
- '#contexts' => $view_modes_selector,
+ '#extra' => array_keys($extra_fields),
);
if (empty($instances)) {
@@ -592,85 +588,165 @@ function field_ui_display_overview_form($form, &$form_state, $entity_type, $bund
return $form;
}
- // Fields.
- $label_options = array(
+ $table = array(
+ '#theme' => 'field_ui_display_overview_table',
+ '#field_rows' => array(),
+ '#tree' => TRUE,
+ );
+
+ $field_label_options = array(
'above' => t('Above'),
'inline' => t('Inline'),
'hidden' => t('<Hidden>'),
);
+ $extra_visibility_options = array(
+ 'visible' => t('Visible'),
+ 'hidden' => t('Hidden'),
+ );
+
foreach ($instances as $name => $instance) {
- $field = field_info_field($instance['field_name']);
- $weight = $instance['widget']['weight'];
+ $display = $instance['display'][$view_mode];
- $form[$name] = array(
- 'human_name' => array('#markup' => check_plain($instance['label'])),
- 'weight' => array('#type' => 'value', '#value' => $weight),
+ $table[$name]['human_name'] = array(
+ '#markup' => check_plain($instance['label']),
);
- $defaults = $instance['display'];
+ $table[$name]['weight'] = array(
+ '#type' => 'textfield',
+ '#default_value' => $display['weight'],
+ '#size' => 3,
+ );
+ $table[$name]['hidden_name'] = array(
+ '#type' => 'hidden',
+ '#default_value' => $name,
+ );
+ $table[$name]['label'] = array(
+ '#type' => 'select',
+ '#options' => $field_label_options,
+ '#default_value' => $display['label'],
+ );
+ $field = field_info_field($instance['field_name']);
$formatter_options = field_ui_formatter_options($field['type']);
$formatter_options['hidden'] = t('<Hidden>');
- foreach ($view_modes as $view_mode) {
- $display = isset($instance['display'][$view_mode]) ? $instance['display'][$view_mode] : $instance['display']['full'];
- $form[$name][$view_mode]['label'] = array(
- '#type' => 'select',
- '#options' => $label_options,
- '#default_value' => $display['label'],
- );
- $form[$name][$view_mode]['type'] = array(
- '#type' => 'select',
- '#options' => $formatter_options,
- '#default_value' => $display['type'],
- );
+ $table[$name]['type'] = array(
+ '#type' => 'select',
+ '#options' => $formatter_options,
+ '#default_value' => $display['type'],
+ );
+ $table['#field_rows'][] = $name;
+
+ // Collect default formatters for the JS script.
+ $field_type_info = field_info_field_types($field['type']);
+ $default_formatters[$name] = $field_type_info['default_formatter'];
+ }
+
+ // Non-field elements.
+ foreach ($extra_fields as $name => $extra_field) {
+ $display = $extra_field['display'][$view_mode];
+ $table[$name]['human_name'] = array(
+ '#markup' => check_plain($extra_field['label']),
+ );
+ $table[$name]['weight'] = array(
+ '#type' => 'textfield',
+ '#default_value' => $display['weight'],
+ '#size' => 3,
+ );
+ $table[$name]['hidden_name'] = array(
+ '#type' => 'hidden',
+ '#default_value' => $name,
+ );
+ $table[$name]['type'] = array(
+ '#type' => 'select',
+ '#options' => $extra_visibility_options,
+ '#default_value' => $display['visible'] ? 'visible' : 'hidden',
+ );
+ $table['#field_rows'][] = $name;
+ }
+ $form['settings'] = $table;
+
+ // Custom display settings.
+ if ($view_mode == 'default') {
+ $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();
+ $entity_info = entity_get_info($entity_type);
+ $view_modes = $entity_info['view modes'];
+ $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 contexts'),
+ '#options' => $options,
+ '#default_value' => $default,
+ );
}
$form['actions'] = array('#type' => 'actions');
$form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save'));
+
+ $form['#attached']['js'][] = drupal_get_path('module', 'field_ui') . '/field_ui.js';
+ $form['#attached']['css'][] = drupal_get_path('module', 'field_ui') . '/field_ui.css';
+ drupal_add_js(array('fieldDefaultFormatters' => $default_formatters), 'setting');
+
return $form;
}
/**
- * Theme preprocess function for field_ui-display-overview-form.tpl.php.
+ * Theme preprocess function for field_ui-display-overview-table.tpl.php.
*/
-function template_preprocess_field_ui_display_overview_form(&$vars) {
- $form = &$vars['form'];
+function template_preprocess_field_ui_display_overview_table(&$vars) {
+ $elements = &$vars['elements'];
- $contexts_selector = $form['#contexts'];
- $view_modes = field_ui_view_modes_tabs($form['#entity_type'], $contexts_selector);
- $entity_info = entity_get_info($form['#entity_type']);
- $view_modes_info = $entity_info['view modes'];
- $vars['contexts'] = array();
- foreach ($view_modes as $view_mode) {
- $vars['contexts'][$view_mode] = $view_modes_info[$view_mode]['label'];
- }
+ $rows = array(
+ 'visible' => array(),
+ 'hidden' => array(),
+ );
- $order = _field_ui_overview_order($form, $form['#fields']);
- if (empty($order)) {
- $vars['rows'] = array();
- $vars['submit'] = '';
- return;
- }
- $rows = array();
- foreach ($order as $key) {
- $element = &$form[$key];
- $row = new stdClass();
- foreach (element_children($element) as $child) {
- if (array_key_exists('label', $element[$child])) {
- $row->{$child} = new stdClass();
- $row->{$child}->label = drupal_render($element[$child]['label']);
- $row->{$child}->type = drupal_render($element[$child]['type']);
- }
- else {
- $row->{$child} = drupal_render($element[$child]);
+ if (!empty($elements['#field_rows'])) {
+ drupal_add_tabledrag('field-display-overview', 'order', 'sibling', 'field-weight');
+
+ $order = _field_ui_overview_order($elements, $elements['#field_rows']);
+ foreach ($order as $key) {
+ $element = &$elements[$key];
+ $visibility = $element['type']['#value'] == 'hidden' ? 'hidden' : 'visible';
+
+ // Add target classes for the tabledrag behavior.
+ $element['weight']['#attributes']['class'][] = 'field-weight';
+ $element['hidden_name']['#attributes']['class'][] = 'field-name';
+ $element['type']['#attributes']['class'][] = 'field-formatter-type';
+ $element['type']['#attributes']['class'][] = "field-display-$visibility";
+ $element['type']['#attributes']['class'][] = "field-name-$key";
+
+ $row = new stdClass();
+ foreach (element_children($element) as $child) {
+ if (array_key_exists('label', $element[$child])) {
+ $row->{$child} = new stdClass();
+ $row->{$child}->label = drupal_render($element[$child]['label']);
+ $row->{$child}->type = drupal_render($element[$child]['type']);
+ }
+ else {
+ $row->{$child} = drupal_render($element[$child]);
+ }
}
+ $row->class = 'draggable';
+ $row->label_class = 'label-field';
+ $rows[$visibility][] = $row;
}
- $row->label_class = 'label-field';
- $rows[] = $row;
}
$vars['rows'] = $rows;
- $vars['submit'] = drupal_render_children($form);
}
/**
@@ -678,17 +754,46 @@ function template_preprocess_field_ui_display_overview_form(&$vars) {
*/
function field_ui_display_overview_form_submit($form, &$form_state) {
$form_values = $form_state['values'];
- foreach ($form_values as $key => $values) {
- if (in_array($key, $form['#fields'])) {
- $instance = field_info_instance($form['#entity_type'], $key, $form['#bundle']);
- foreach ($instance['display'] as $view_mode => $display) {
- if (isset($values[$view_mode])) {
- $instance['display'][$view_mode] = array_merge($instance['display'][$view_mode], $values[$view_mode]);
- }
+ $entity_type = $form['#entity_type'];
+ $bundle = $form['#bundle'];
+ $view_mode = $form['#view_mode'];
+
+ // Save data for 'regular' fields.
+ foreach ($form['#fields'] as $field_name) {
+ $instance = field_info_instance($entity_type, $field_name, $bundle);
+ $instance['display'][$view_mode] = $form_values['settings'][$field_name];
+ 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['settings'][$name]['weight'],
+ 'visible' => $form_values['settings'][$name]['type'] == 'visible',
+ );
+ }
+
+ // Save view modes data.
+ if ($view_mode == 'default') {
+ $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.
+ if (!empty($value) && empty($bundle_settings['view_modes'][$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 <a href="@url">configure them</a>.', array('%view_mode' => $view_mode_label, '@url' => url($path))));
}
- field_update_instance($instance);
+ $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.'));
}
diff --git a/modules/field_ui/field_ui.css b/modules/field_ui/field_ui.css
index 2cc52736b..43d9b78f6 100644
--- a/modules/field_ui/field_ui.css
+++ b/modules/field_ui/field_ui.css
@@ -16,3 +16,10 @@
padding-bottom: .5em;
}
+/* Manage display */
+.field-display-overview tr.region-title td {
+ font-weight: bold;
+}
+.field-display-overview tr.region-populated {
+ display: none;
+}
diff --git a/modules/field_ui/field_ui.js b/modules/field_ui/field_ui.js
index b8b8e484b..02b8b79ce 100644
--- a/modules/field_ui/field_ui.js
+++ b/modules/field_ui/field_ui.js
@@ -81,4 +81,143 @@ jQuery.fn.fieldPopulateOptions = function (options, selected) {
});
};
+/**
+ * Moves a field in the display settings table from visible to hidden.
+ *
+ * This behavior is dependent on the tableDrag behavior, since it uses the
+ * objects initialized in that behavior to update the row.
+ */
+Drupal.behaviors.fieldManageDisplayDrag = {
+ attach: function (context, settings) {
+ // tableDrag is required for this behavior.
+ if (!$('table.field-display-overview', context).length || typeof Drupal.tableDrag == 'undefined') {
+ return;
+ }
+
+ var defaultFormatters = Drupal.settings.fieldDefaultFormatters;
+ var tableDrag = Drupal.tableDrag['field-display-overview'];
+
+ // Add a handler for when a row is swapped, update empty regions.
+ tableDrag.row.prototype.onSwap = function (swappedRow) {
+ checkEmptyRegions(this.table, this);
+ };
+
+ // Add a handler to update the formatter selector when a row is dropped in
+ // or out of the 'Hidden' section.
+ tableDrag.onDrop = function () {
+ var dragObject = this;
+ var regionRow = $(dragObject.rowObject.element).prevAll('tr.region-message').get(0);
+ var visibility = regionRow.className.replace(/([^ ]+[ ]+)*region-([^ ]+)-message([ ]+[^ ]+)*/, '$2');
+
+ // Update the 'format' selector if the visibility changed.
+ var $select = $('select.field-formatter-type', dragObject.rowObject.element);
+ var oldVisibility = $select[0].className.replace(/([^ ]+[ ]+)*field-display-([^ ]+)([ ]+[^ ]+)*/, '$2');
+ if (visibility != oldVisibility) {
+ $select.removeClass('field-display-' + oldVisibility).addClass('field-display-' + visibility);
+
+ // Update the selected formatter if coming from an actual drag.
+ if (!$select.data('noUpdate')) {
+ if (visibility == 'visible') {
+ // Restore the formatter back to the previously selected one if
+ // available, or to the default formatter.
+ var value = $select.data('oldFormatter');
+ if (typeof value == 'undefined') {
+ // Extract field name from the name of the select.
+ var fieldName = $select[0].className.match(/\bfield-name-(\S+)\b/)[1].replace('-', '_');
+ // Pseudo-fields do not have an entry in the defaultFormatters
+ // array, we just return to 'visible' for those.
+ value = (fieldName in defaultFormatters) ? defaultFormatters[fieldName] : 'visible';
+ }
+ $select.data('oldFormatter', value);
+ }
+ else {
+ var value = 'hidden';
+ }
+ $select.val(value);
+ }
+ $select.removeData('noUpdate');
+ }
+ };
+
+ // Add the behavior to each formatter select list.
+ $('select.field-formatter-type', context).once('field-formatter-type', function () {
+ // Initialize 'previously selected formatter' as the incoming value.
+ if ($(this).val() != 'hidden') {
+ $(this).data('oldFormatter', $(this).val());
+ }
+
+ // Add change listener.
+ $(this).change(function (event) {
+ var $select = $(this);
+ var value = $select.val();
+
+ // Keep track of the last selected formatter.
+ if (value != 'hidden') {
+ $select.data('oldFormatter', value);
+ }
+
+ var visibility = (value == 'hidden') ? 'hidden' : 'visible';
+ var oldVisibility = $select[0].className.replace(/([^ ]+[ ]+)*field-display-([^ ]+)([ ]+[^ ]+)*/, '$2');
+ if (visibility != oldVisibility) {
+ // Prevent the onDrop handler from overriding the selected option.
+ $select.data('noUpdate', true);
+
+ // Make our new row and select field.
+ var $row = $(this).parents('tr:first');
+ var $table = $(this).parents('table');
+ var tableDrag = Drupal.tableDrag[$table.attr('id')];
+ tableDrag.rowObject = new tableDrag.row($row);
+
+ // Move the row at the bottom of the new section.
+ if (visibility == 'hidden') {
+ $('tr:last', tableDrag.table).after($row);
+ }
+ else {
+ $('tr.region-title-hidden', tableDrag.table).before($row);
+ }
+
+ // Manually update weights and restripe.
+ tableDrag.updateFields($row.get(0));
+ tableDrag.rowObject.changed = true;
+ if (tableDrag.oldRowElement) {
+ $(tableDrag.oldRowElement).removeClass('drag-previous');
+ }
+ tableDrag.oldRowElement = $row.get(0);
+ tableDrag.restripeTable();
+ tableDrag.rowObject.markChanged();
+ tableDrag.oldRowElement = $row;
+ $row.addClass('drag-previous');
+
+ // Modify empty regions with added or removed fields.
+ checkEmptyRegions($table, tableDrag.rowObject);
+ }
+
+ // Remove focus from selectbox.
+ $select.get(0).blur();
+ });
+ });
+
+ var checkEmptyRegions = function ($table, rowObject) {
+ $('tr.region-message', $table).each(function () {
+ // If the dragged row is in this region, but above the message row, swap
+ // it down one space.
+ if ($(this).prev('tr').get(0) == rowObject.element) {
+ // Prevent a recursion problem when using the keyboard to move rows up.
+ if ((rowObject.method != 'keyboard' || rowObject.direction == 'down')) {
+ rowObject.swap('after', this);
+ }
+ }
+ // This region has become empty.
+ if ($(this).next('tr').is(':not(.draggable)') || $(this).next('tr').length == 0) {
+ $(this).removeClass('region-populated').addClass('region-empty');
+ }
+ // This region has become populated.
+ else if ($(this).is('.region-empty')) {
+ $(this).removeClass('region-empty').addClass('region-populated');
+ }
+ });
+ };
+ }
+};
+
})(jQuery);
diff --git a/modules/field_ui/field_ui.module b/modules/field_ui/field_ui.module
index 3bb5cd886..470abe6d7 100644
--- a/modules/field_ui/field_ui.module
+++ b/modules/field_ui/field_ui.module
@@ -49,6 +49,24 @@ function field_ui_help($path, $arg) {
}
/**
+ * Implements hook_theme().
+ */
+function field_ui_theme() {
+ return array(
+ 'field_ui_field_overview_form' => array(
+ 'render element' => 'form',
+ 'file' => 'field_ui.admin.inc',
+ 'template' => 'field_ui-field-overview-form',
+ ),
+ 'field_ui_display_overview_table' => array(
+ 'render element' => 'elements',
+ 'file' => 'field_ui.admin.inc',
+ 'template' => 'field_ui-display-overview-table',
+ ),
+ );
+}
+
+/**
* Implements hook_menu().
*/
function field_ui_menu() {
@@ -66,10 +84,11 @@ function field_ui_menu() {
if (defined('MAINTENANCE_MODE')) {
return $items;
}
+
// Create tabs for all possible bundles.
- foreach (entity_get_info() as $entity_type => $info) {
- if ($info['fieldable']) {
- foreach ($info['bundles'] as $bundle_name => $bundle_info) {
+ foreach (entity_get_info() as $entity_type => $entity_info) {
+ if ($entity_info['fieldable']) {
+ foreach ($entity_info['bundles'] as $bundle_name => $bundle_info) {
if (isset($bundle_info['admin'])) {
// Extract path information from the bundle.
$path = $bundle_info['admin']['path'];
@@ -92,7 +111,12 @@ function field_ui_menu() {
// items below.
$field_position = count(explode('/', $path)) + 1;
+ // Extract access information, providing defaults.
$access = array_intersect_key($bundle_info['admin'], drupal_map_assoc(array('access callback', 'access arguments')));
+ $access += array(
+ 'access callback' => 'user_access',
+ 'access arguments' => array('administer site configuration'),
+ );
$items["$path/fields"] = array(
'title' => 'Manage fields',
@@ -145,24 +169,38 @@ function field_ui_menu() {
'file' => 'field_ui.admin.inc',
) + $access;
- // 'Manage display' tab and context secondary tabs.
+ // '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),
+ 'page arguments' => array('field_ui_display_overview_form', $entity_type, $bundle_arg, 'default'),
'type' => MENU_LOCAL_TASK,
'weight' => 2,
'file' => 'field_ui.admin.inc',
) + $access;
- $tabs = field_ui_view_modes_tabs($entity_type);
- foreach ($tabs as $key => $tab) {
- $items["$path/display/$key"] = array(
- 'title' => $tab['title'],
- 'page arguments' => array('field_ui_display_overview_form', $entity_type, $bundle_arg, $key),
- 'type' => $key == 'basic' ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK,
- 'weight' => $key == 'basic' ? 0 : 1,
+
+ // View modes secondary tabs.
+ // The same base $path for the menu item (with a placeholder) can be
+ // used for all bundles of a given entity type; but depending on
+ // administrator settings, each bundle has a different set of view
+ // modes available for customisation. So we define menu items for all
+ // view modes, and use an access callback to determine which ones are
+ // actually visible for a given bundle.
+ $weight = 0;
+ $view_modes = array('default' => array('label' => t('Default'))) + $entity_info['view modes'];
+ 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),
+ // 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.
+ 'access callback' => '_field_ui_view_mode_menu_access',
+ 'access arguments' => array_merge(array($entity_type, $bundle_arg, $view_mode, $access['access callback']), $access['access arguments']),
+ 'type' => ($view_mode == 'default' ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK),
+ 'weight' => ($view_mode == 'default' ? -10 : $weight++),
'file' => 'field_ui.admin.inc',
- ) + $access;
+ );
}
}
}
@@ -219,100 +257,35 @@ function field_ui_menu_title($instance) {
}
/**
- * Implements hook_theme().
+ * Menu access callback for the 'view mode display settings' pages.
*/
-function field_ui_theme() {
- return array(
- 'field_ui_field_overview_form' => array(
- 'render element' => 'form',
- 'file' => 'field_ui.admin.inc',
- 'template' => 'field_ui-field-overview-form',
- ),
- 'field_ui_display_overview_form' => array(
- 'render element' => 'form',
- 'file' => 'field_ui.admin.inc',
- 'template' => 'field_ui-display-overview-form',
- ),
- );
-}
+function _field_ui_view_mode_menu_access($entity_type, $bundle, $view_mode, $access_callback) {
+ // First, determine visibility according to the 'use custom display'
+ // setting for the view mode.
+ $bundle = field_extract_bundle($entity_type, $bundle);
+ $view_mode_settings = field_view_mode_settings($entity_type, $bundle);
+ $visibility = ($view_mode == 'default') || !empty($view_mode_settings[$view_mode]['custom_settings']);
-/**
- * Returns information about tab groups for view modes on an entity type.
- *
- * On the 'Manage display' page, an administrator can manage the display of
- * fields for each view mode for an entity type. The view modes are organized
- * into tabs. This function returns the list of entity types to display on
- * each tab, as well as the titles of the tabs.
- *
- * @param $entity_type
- * The type of entity to return tab information for.
- * @param $tab_selector
- * If not NULL, return only information for this particular tab; if NULL,
- * return all tab information.
- *
- * @return
- * Array of information about the tabs to display. The keys are internal-use
- * tab names and the values are arrays of tab information, with the following
- * elements:
- * - 'title': Human-readable title of the tab.
- * - 'view modes': Array of view modes for this entity type that should
- * be displayed on this tab.
- *
- * @see hook_field_ui_view_modes_tabs()
- *
- * @todo Remove this completely and use vertical tabs?
- */
-function field_ui_view_modes_tabs($entity_type, $tab_selector = NULL) {
- $info = &drupal_static(__FUNCTION__);
-
- if (!isset($info[$entity_type])) {
- $info[$entity_type] = module_invoke_all('field_ui_view_modes_tabs', $entity_type);
- // Filter out inactive modes.
- $entity_info = entity_get_info($entity_type);
- foreach ($info[$entity_type] as $tab => $values) {
- $modes = array();
- foreach ($info[$entity_type][$tab]['view modes'] as $mode) {
- if (isset($entity_info['view modes'][$mode])) {
- $modes[] = $mode;
- }
- }
- if ($modes) {
- $info[$entity_type][$tab]['view modes'] = $modes;
+ // Then, determine access according to the $access parameter. This duplicates
+ // part of _menu_check_access().
+ if ($visibility) {
+ // Grab the variable 'access arguments' part.
+ $args = array_slice(func_get_args(), 4);
+ $callback = empty($access_callback) ? 0 : trim($access_callback);
+ if (is_numeric($callback)) {
+ return (bool) $callback;
+ }
+ else {
+ // As call_user_func_array() is quite slow and user_access is a very
+ // common callback, it is worth making a special case for it.
+ if ($access_callback == 'user_access') {
+ return (count($args) == 1) ? user_access($args[0]) : user_access($args[0], $args[1]);
}
- else {
- unset($info[$entity_type][$tab]);
+ elseif (function_exists($access_callback)) {
+ return call_user_func_array($access_callback, $args);
}
}
}
- if ($tab_selector) {
- return isset($info[$entity_type][$tab_selector]) ? $info[$entity_type][$tab_selector]['view modes'] : array();
- }
- return $info[$entity_type];
-}
-
-/**
- * Implements hook_field_ui_view_modes_tabs() on behalf of other core modules.
- */
-function field_ui_field_ui_view_modes_tabs() {
- $modes = array(
- 'basic' => array(
- 'title' => t('Basic'),
- 'view modes' => array('teaser', 'full'),
- ),
- 'rss' => array(
- 'title' => t('RSS'),
- 'view modes' => array('rss'),
- ),
- 'print' => array(
- 'title' => t('Print'),
- 'view modes' => array('print'),
- ),
- 'search' => array(
- 'title' => t('Search'),
- 'view modes' => array('search_index', 'search_result'),
- ),
- );
- return $modes;
}
/**
@@ -325,31 +298,6 @@ function field_ui_field_attach_create_bundle($entity_type, $bundle) {
}
/**
- * Implements hook_field_attach_rename_bundle().
- */
-function field_ui_field_attach_rename_bundle($entity_type, $bundle_old, $bundle_new) {
- if ($bundle_old !== $bundle_new) {
- $extra_weights = variable_get('field_extra_weights', array());
- if (isset($info[$entity_type][$bundle_old])) {
- $extra_weights[$entity_type][$bundle_new] = $extra_weights[$entity_type][$bundle_old];
- unset($extra_weights[$entity_type][$bundle_old]);
- variable_set('field_extra_weights', $extra_weights);
- }
- }
-}
-
-/**
- * Implements hook_field_attach_delete_bundle().
- */
-function field_ui_field_attach_delete_bundle($entity_type, $bundle) {
- $extra_weights = variable_get('field_extra_weights', array());
- if (isset($extra_weights[$entity_type][$bundle])) {
- unset($extra_weights[$entity_type][$bundle]);
- variable_set('field_extra_weights', $extra_weights);
- }
-}
-
-/**
* Helper function to create the right administration path for a bundle.
*/
function _field_ui_bundle_admin_path($entity_type, $bundle_name) {