diff options
Diffstat (limited to 'modules/field_ui')
-rw-r--r-- | modules/field_ui/field_ui.admin.inc | 102 | ||||
-rw-r--r-- | modules/field_ui/field_ui.api.php | 4 | ||||
-rw-r--r-- | modules/field_ui/field_ui.css | 8 | ||||
-rw-r--r-- | modules/field_ui/field_ui.js | 19 | ||||
-rw-r--r-- | modules/field_ui/field_ui.module | 2 | ||||
-rw-r--r-- | modules/field_ui/field_ui.test | 27 |
6 files changed, 107 insertions, 55 deletions
diff --git a/modules/field_ui/field_ui.admin.inc b/modules/field_ui/field_ui.admin.inc index 36c58f60c..33ce2f05c 100644 --- a/modules/field_ui/field_ui.admin.inc +++ b/modules/field_ui/field_ui.admin.inc @@ -280,8 +280,8 @@ function theme_field_ui_table($variables) { * * Allows fields and pseudo-fields to be re-ordered. * - * @see field_ui_overview_form_validate(). - * @see field_ui_overview_form_submit(). + * @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) { @@ -316,7 +316,7 @@ function field_ui_field_overview_form($form, &$form_state, $entity_type, $bundle t('Label'), t('Weight'), t('Parent'), - t('Name'), + t('Machine name'), t('Field'), t('Widget'), array('data' => t('Operations'), 'colspan' => 2), @@ -498,16 +498,24 @@ function field_ui_field_overview_form($form, &$form_state, $entity_type, $bundle ), ), 'field_name' => array( - '#type' => 'textfield', + '#type' => 'machine_name', '#title' => t('New field name'), '#title_display' => 'invisible', // This field should stay LTR even for RTL languages. '#field_prefix' => '<span dir="ltr">field_', '#field_suffix' => '</span>‎', - '#attributes' => array('dir'=>'ltr'), - '#size' => 10, - '#description' => t('Field name (a-z, 0-9, _)'), + '#size' => 15, + '#description' => t('A unique machine-readable name containing letters, numbers, and underscores.'), + // 32 characters minus the 'field_' prefix. + '#maxlength' => 26, '#prefix' => '<div class="add-new-placeholder"> </div>', + '#machine_name' => array( + 'source' => array('fields', $name, 'label'), + 'exists' => '_field_ui_field_name_exists', + 'standalone' => TRUE, + 'label' => '', + ), + '#required' => FALSE, ), 'type' => array( '#type' => 'select', @@ -540,8 +548,19 @@ function field_ui_field_overview_form($form, &$form_state, $entity_type, $bundle } // Additional row: add existing field. - $existing_field_options = field_ui_existing_field_options($entity_type, $bundle); - if ($existing_field_options && $widget_type_options) { + $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')), @@ -617,10 +636,8 @@ function field_ui_field_overview_form($form, &$form_state, $entity_type, $bundle // Add settings for the update selects behavior. $js_fields = array(); - foreach ($existing_field_options as $field_name => $fields) { - $field = field_info_field($field_name); - $instance = field_info_instance($form['#entity_type'], $field_name, $form['#bundle']); - $js_fields[$field_name] = array('label' => $instance['label'], 'type' => $field['type'], 'widget' => $instance['widget']['type']); + 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( @@ -669,25 +686,8 @@ function _field_ui_field_overview_form_validate_add_new($form, &$form_state) { $field_name = $field['field_name']; // Add the 'field_' prefix. - if (substr($field_name, 0, 6) != 'field_') { - $field_name = 'field_' . $field_name; - form_set_value($form['fields']['_add_new_field']['field_name'], $field_name, $form_state); - } - - // Invalid field name. - if (!preg_match('!^field_[a-z0-9_]+$!', $field_name)) { - form_set_error('fields][_add_new_field][field_name', t('Add new field: the field name %field_name is invalid. The name must include only lowercase unaccentuated letters, numbers, and underscores.', array('%field_name' => $field_name))); - } - if (strlen($field_name) > 32) { - form_set_error('fields][_add_new_field][field_name', t("Add new field: the field name %field_name is too long. The name is limited to 32 characters, including the 'field_' prefix.", array('%field_name' => $field_name))); - } - - // Field name already exists. We need to check inactive fields as well, so - // we can't use field_info_fields(). - $fields = field_read_fields(array('field_name' => $field_name), array('include_inactive' => TRUE)); - if ($fields) { - form_set_error('fields][_add_new_field][field_name', t('Add new field: the field name %field_name already exists.', array('%field_name' => $field_name))); - } + $field_name = 'field_' . $field_name; + form_set_value($form['fields']['_add_new_field']['field_name'], $field_name, $form_state); } // Missing field type. @@ -710,6 +710,24 @@ function _field_ui_field_overview_form_validate_add_new($form, &$form_state) { } /** + * Render API callback: Checks if a field machine name is taken. + * + * @param $value + * The machine name, not prefixed with 'field_'. + * + * @return + * Whether or not the field machine name is taken. + */ +function _field_ui_field_name_exists($value) { + // Prefix with 'field_'. + $field_name = 'field_' . $value; + + // We need to check inactive fields as well, so we can't use + // field_info_fields(). + return (bool) field_read_fields(array('field_name' => $field_name), array('include_inactive' => TRUE)); +} + +/** * Validates the 'add existing field' row of field_ui_field_overview_form(). * * @see field_ui_field_overview_form_validate() @@ -1502,7 +1520,7 @@ function field_ui_formatter_options($field_type = NULL) { * Returns an array of existing fields to be added to a bundle. */ function field_ui_existing_field_options($entity_type, $bundle) { - $options = array(); + $info = array(); $field_types = field_info_field_types(); foreach (field_info_instances() as $existing_entity_type => $bundles) { @@ -1521,19 +1539,19 @@ function field_ui_existing_field_options($entity_type, $bundle) { && !field_info_instance($entity_type, $field['field_name'], $bundle) && (empty($field['entity_types']) || in_array($entity_type, $field['entity_types'])) && empty($field_types[$field['type']]['no_ui'])) { - $text = t('@type: @field (@label)', array( - '@type' => $field_types[$field['type']]['label'], - '@label' => t($instance['label']), '@field' => $instance['field_name'], - )); - $options[$instance['field_name']] = (drupal_strlen($text) > 80 ? truncate_utf8($text, 77) . '...' : $text); + $info[$instance['field_name']] = array( + 'type' => $field['type'], + 'type_label' => $field_types[$field['type']]['label'], + 'field' => $field['field_name'], + 'label' => t($instance['label']), + 'widget_type' => $instance['widget']['type'], + ); } } } } } - // Sort the list by field name. - asort($options); - return $options; + return $info; } /** @@ -1705,7 +1723,7 @@ function field_ui_widget_type_form_submit($form, &$form_state) { /** * Form constructor for removing a field instance from a bundle. * - * @see field_ui_delete_form_submit() + * @see field_ui_field_delete_form_submit() * @ingroup forms */ function field_ui_field_delete_form($form, &$form_state, $instance) { diff --git a/modules/field_ui/field_ui.api.php b/modules/field_ui/field_ui.api.php index f903e12f3..882f467a6 100644 --- a/modules/field_ui/field_ui.api.php +++ b/modules/field_ui/field_ui.api.php @@ -6,7 +6,7 @@ */ /** - * @ingroup field_ui_field_type + * @addtogroup field_types * @{ */ @@ -200,5 +200,5 @@ function hook_field_formatter_settings_summary($field, $instance, $view_mode) { } /** - * @} End of "ingroup field_ui_field_type" + * @} End of "addtogroup field_types" */ diff --git a/modules/field_ui/field_ui.css b/modules/field_ui/field_ui.css index ae469e207..2184023b7 100644 --- a/modules/field_ui/field_ui.css +++ b/modules/field_ui/field_ui.css @@ -12,6 +12,10 @@ table.field-ui-overview tr.add-new .tabledrag-changed { } table.field-ui-overview tr.add-new .description { margin-bottom: 0; + max-width: 250px; +} +table.field-ui-overview tr.add-new .form-type-machine-name .description { + white-space: normal; } table.field-ui-overview tr.add-new .add-new-placeholder { font-weight: bold; @@ -29,6 +33,10 @@ table.field-ui-overview tr.region-populated { table.field-ui-overview tr.region-add-new-title { display: none; } +table.field-ui-overview tr.add-new td { + vertical-align: top; + white-space: nowrap; +} /* 'Manage display' overview */ #field-display-overview .field-formatter-summary-cell { diff --git a/modules/field_ui/field_ui.js b/modules/field_ui/field_ui.js index 0a41c4c6f..1017937b6 100644 --- a/modules/field_ui/field_ui.js +++ b/modules/field_ui/field_ui.js @@ -28,7 +28,7 @@ Drupal.fieldUIFieldOverview = { // 'Field type' select updates its 'Widget' select. $('.field-type-select', table).each(function () { - this.targetSelect = $('.widget-type-select', $(this).parents('tr').eq(0)); + this.targetSelect = $('.widget-type-select', $(this).closest('tr')); $(this).bind('change keyup', function () { var selectedFieldType = this.options[this.selectedIndex].value; @@ -43,8 +43,13 @@ Drupal.fieldUIFieldOverview = { // 'Existing field' select updates its 'Widget' select and 'Label' textfield. $('.field-select', table).each(function () { - this.targetSelect = $('.widget-type-select', $(this).parents('tr').eq(0)); - this.targetTextfield = $('.label-textfield', $(this).parents('tr').eq(0)); + this.targetSelect = $('.widget-type-select', $(this).closest('tr')); + this.targetTextfield = $('.label-textfield', $(this).closest('tr')); + this.targetTextfield + .data('field_ui_edited', false) + .bind('keyup', function (e) { + $(this).data('field_ui_edited', $(this).val() != ''); + }); $(this).bind('change keyup', function (e, updateText) { var updateText = (typeof updateText == 'undefined' ? true : updateText); @@ -54,8 +59,10 @@ Drupal.fieldUIFieldOverview = { var options = (selectedFieldType && (selectedFieldType in widgetTypes) ? widgetTypes[selectedFieldType] : []); this.targetSelect.fieldUIPopulateOptions(options, selectedFieldWidget); - if (updateText) { - $(this.targetTextfield).attr('value', (selectedField in fields ? fields[selectedField].label : '')); + // Only overwrite the "Label" input if it has not been manually + // changed, or if it is empty. + if (updateText && !this.targetTextfield.data('field_ui_edited')) { + this.targetTextfield.val(selectedField in fields ? fields[selectedField].label : ''); } }); @@ -133,7 +140,7 @@ Drupal.fieldUIOverview = { */ onChange: function () { var $trigger = $(this); - var row = $trigger.parents('tr:first').get(0); + var row = $trigger.closest('tr').get(0); var rowHandler = $(row).data('fieldUIRowHandler'); var refreshRows = {}; diff --git a/modules/field_ui/field_ui.module b/modules/field_ui/field_ui.module index 7bfb4faa7..93cbcccc7 100644 --- a/modules/field_ui/field_ui.module +++ b/modules/field_ui/field_ui.module @@ -12,7 +12,7 @@ function field_ui_help($path, $arg) { case 'admin/help#field_ui': $output = ''; $output .= '<h3>' . t('About') . '</h3>'; - $output .= '<p>' . t('The Field UI module provides an administrative user interface (UI) for attaching and managing fields. Fields can be defined at the content-type level for content items and comments, at the vocabulary level for taxonomy terms, and at the site level for user accounts. Other modules may also enable fields to be defined for their data. Field types (text, image, number, etc.) are defined by modules, and collected and managed by the <a href="@field">Field module</a>. For more information, see the online handbook entry for <a href="@field_ui" target="_blank">Field UI module</a>.', array('@field' => url('admin/help/field'), '@field_ui' => 'http://drupal.org/handbook/modules/field-ui')) . '</p>'; + $output .= '<p>' . t('The Field UI module provides an administrative user interface (UI) for attaching and managing fields. Fields can be defined at the content-type level for content items and comments, at the vocabulary level for taxonomy terms, and at the site level for user accounts. Other modules may also enable fields to be defined for their data. Field types (text, image, number, etc.) are defined by modules, and collected and managed by the <a href="@field">Field module</a>. For more information, see the online handbook entry for <a href="@field_ui" target="_blank">Field UI module</a>.', array('@field' => url('admin/help/field'), '@field_ui' => 'http://drupal.org/documentation/modules/field-ui')) . '</p>'; $output .= '<h3>' . t('Uses') . '</h3>'; $output .= '<dl>'; $output .= '<dt>' . t('Planning fields') . '</dt>'; diff --git a/modules/field_ui/field_ui.test b/modules/field_ui/field_ui.test index f1e770baa..75a70846f 100644 --- a/modules/field_ui/field_ui.test +++ b/modules/field_ui/field_ui.test @@ -172,7 +172,7 @@ class FieldUIManageFieldsTestCase extends FieldUITestCase { // Check all table columns. $table_headers = array( t('Label'), - t('Name'), + t('Machine name'), t('Field'), t('Widget'), t('Operations'), @@ -338,7 +338,7 @@ class FieldUIManageFieldsTestCase extends FieldUITestCase { $bundle_path1 = 'admin/structure/types/manage/' . $this->hyphen_type; $edit1 = array( 'fields[_add_new_field][label]' => $this->field_label, - 'fields[_add_new_field][field_name]' => $this->field_name, + 'fields[_add_new_field][field_name]' => $this->field_name_input, ); $this->fieldUIAddNewField($bundle_path1, $edit1); @@ -426,6 +426,25 @@ class FieldUIManageFieldsTestCase extends FieldUITestCase { $this->drupalGet('admin/structure/types/manage/' . $hyphen_type2 . '/fields'); } + + /** + * Tests that a duplicate field name is caught by validation. + */ + function testDuplicateFieldName() { + // field_tags already exists, so we're expecting an error when trying to + // create a new field with the same name. + $edit = array( + 'fields[_add_new_field][field_name]' => 'tags', + 'fields[_add_new_field][label]' => $this->randomName(), + 'fields[_add_new_field][type]' => 'taxonomy_term_reference', + 'fields[_add_new_field][widget_type]' => 'options_select', + ); + $url = 'admin/structure/types/manage/' . $this->hyphen_type . '/fields'; + $this->drupalPost($url, $edit, t('Save')); + + $this->assertText(t('The machine-readable name is already in use. It must be unique.')); + $this->assertUrl($url, array(), 'Stayed on the same page.'); + } } /** @@ -454,7 +473,7 @@ class FieldUIManageDisplayTestCase extends FieldUITestCase { // Create a field, and a node with some data for the field. $edit = array( 'fields[_add_new_field][label]' => 'Test field', - 'fields[_add_new_field][field_name]' => 'field_test', + 'fields[_add_new_field][field_name]' => 'test', ); $this->fieldUIAddNewField($manage_fields, $edit); @@ -499,7 +518,7 @@ class FieldUIManageDisplayTestCase extends FieldUITestCase { // Create a field, and a node with some data for the field. $edit = array( 'fields[_add_new_field][label]' => 'Test field', - 'fields[_add_new_field][field_name]' => 'field_test', + 'fields[_add_new_field][field_name]' => 'test', ); $this->fieldUIAddNewField('admin/structure/types/manage/' . $this->hyphen_type, $edit); // For this test, use a formatter setting value that is an integer unlikely |