$field, 'instance' => $instance, ); // Populate widgets with default values when creating a new object. if (empty($items) && empty($id)) { $items = field_get_default_value($obj_type, $object, $field, $instance, $langcode); } $field_elements = array(); if (field_access('edit', $field, $obj_type, $object)) { // If field module handles multiple values for this form element, and we // are displaying an individual element, process the multiple value form. if (!isset($get_delta) && field_behaviors_widget('multiple values', $instance) == FIELD_BEHAVIOR_DEFAULT) { $field_elements = field_multiple_value_form($field, $instance, $langcode, $items, $form, $form_state); } // If the widget is handling multiple values (e.g Options), or if we are // displaying an individual element, just get a single form element and // make it the $delta value. else { $delta = isset($get_delta) ? $get_delta : 0; $function = $instance['widget']['module'] . '_field_widget'; if (function_exists($function)) { $element = array( '#object_type' => $instance['object_type'], '#bundle' => $instance['bundle'], '#field_name' => $field_name, '#columns' => array_keys($field['columns']), '#title' => check_plain(t($instance['label'])), '#description' => field_filter_xss($instance['description']), // Only the first widget should be required. '#required' => $delta == 0 && $instance['required'], '#delta' => $delta, ); if ($element = $function($form, $form_state, $field, $instance, $langcode, $items, $delta, $element)) { // If we're processing a specific delta value for a field where the // field module handles multiples, set the delta in the result. // For fields that handle their own processing, we can't make // assumptions about how the field is structured, just merge in the // returned element. if (field_behaviors_widget('multiple values', $instance) == FIELD_BEHAVIOR_DEFAULT) { $field_elements[$delta] = $element; } else { $field_elements = $element; } } } } } if ($field_elements) { // Add the field form element as a child keyed by language code to match // the field data structure: // $object->{$field_name}[$langcode][$delta][$column]. // The '#language' key can be used to access the field's form element // when $langcode is unknown. The #weight property is inherited from the // field's form element. // Also aid in theming of field widgets by rendering a classified // container. $addition[$field_name] = array( '#type' => 'container', '#attributes' => array( 'class' => array( 'field-type-' . drupal_html_class($field['type']), 'field-name-' . drupal_html_class($field_name), 'field-widget-' . drupal_html_class($instance['widget']['type']), ), ), '#tree' => TRUE, '#weight' => $instance['widget']['weight'], '#language' => $langcode, $langcode => $field_elements, ); } else { // The field is not accessible, or the widget did not return anything. Make // sure the items are available in the submitted form values. foreach ($items as $delta => $item) { $field_elements[$delta] = array( '#type' => 'value', '#value' => $item, ); } $addition[$field_name] = array( '#tree' => TRUE, '#language' => $langcode, $langcode => $field_elements, ); } $form['#fields'][$field_name]['form_path'] = array($field_name); return $addition; } /** * Special handling to create form elements for multiple values. * * Handles generic features for multiple fields: * - number of widgets * - AHAH-'add more' button * - drag-n-drop value reordering */ function field_multiple_value_form($field, $instance, $langcode, $items, &$form, &$form_state) { // This form has its own multistep persistance. if ($form_state['rebuild']) { $form_state['input'] = array(); } $field_name = $field['field_name']; // Determine the number of widgets to display. switch ($field['cardinality']) { case FIELD_CARDINALITY_UNLIMITED: $filled_items = field_set_empty($field, $items); $current_item_count = isset($form_state['field_item_count'][$field_name]) ? $form_state['field_item_count'][$field_name] : count($items); // We always want at least one empty icon for the user to fill in. $max = ($current_item_count > count($filled_items)) ? $current_item_count - 1 : $current_item_count; break; default: $max = $field['cardinality'] - 1; break; } $title = check_plain(t($instance['label'])); $description = field_filter_xss(t($instance['description'])); $wrapper_id = drupal_html_class($field_name) . '-wrapper'; $field_elements = array(); $function = $instance['widget']['module'] . '_field_widget'; if (function_exists($function)) { for ($delta = 0; $delta <= $max; $delta++) { $multiple = $field['cardinality'] > 1 || $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED; $element = array( '#object_type' => $instance['object_type'], '#bundle' => $instance['bundle'], '#field_name' => $field_name, '#columns' => array_keys($field['columns']), // For multiple fields, title and description are handled by the wrapping table. '#title' => $multiple ? '' : $title, '#description' => $multiple ? '' : $description, // Only the first widget should be required. '#required' => $delta == 0 && $instance['required'], '#delta' => $delta, '#weight' => $delta, ); if ($element = $function($form, $form_state, $field, $instance, $langcode, $items, $delta, $element)) { // Input field for the delta (drag-n-drop reordering). if ($multiple) { // We name the element '_weight' to avoid clashing with elements // defined by widget. $element['_weight'] = array( '#type' => 'weight', // Note: this 'delta' is the FAPI 'weight' element's property. '#delta' => $max, '#default_value' => isset($items[$delta]['_weight']) ? $items[$delta]['_weight'] : $delta, '#weight' => 100, ); } $field_elements[$delta] = $element; } } if ($field_elements) { $field_elements += array( '#theme' => 'field_multiple_value_form', '#field_name' => $field['field_name'], '#cardinality' => $field['cardinality'], '#title' => $title, '#required' => $instance['required'], '#description' => $description, '#prefix' => '