You are here

function field_collection_field_widget_form in Field collection 7

Implements hook_field_widget_form().

File

./field_collection.module, line 1239
Module implementing field collection field type.

Code

function field_collection_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
  static $recursion = 0;
  switch ($instance['widget']['type']) {
    case 'field_collection_hidden':
      return $element;
    case 'field_collection_embed':

      // If the field collection item form contains another field collection,
      // we might ran into a recursive loop. Prevent that.
      if ($recursion++ > 3) {
        drupal_set_message(t('The field collection item form has not been embedded to avoid recursive loops.'), 'error');
        return $element;
      }
      $field_parents = $element['#field_parents'];
      $field_name = $element['#field_name'];
      $language = $element['#language'];

      // Nest the field collection item entity form in a dedicated parent space,
      // by appending [field_name, langcode, delta] to the current parent space.
      // That way the form values of the field collection item are separated.
      $parents = array_merge($field_parents, array(
        $field_name,
        $language,
        $delta,
      ));
      $element += array(
        '#element_validate' => array(
          'field_collection_field_widget_embed_validate',
        ),
        '#parents' => $parents,
      );
      if ($field['cardinality'] == 1) {
        $element['#type'] = 'fieldset';
      }
      $field_state = field_form_get_state($field_parents, $field_name, $language, $form_state);
      if ($delta > 0 && $delta == $field_state['items_count'] && field_collection_hide_blank_items($field)) {

        // Do not add a blank item. Also see
        // field_collection_field_attach_form() for correcting #max_delta.
        $recursion--;
        return FALSE;
      }
      if ($field_state['items_count'] == 0 && field_collection_hide_blank_items($field)) {

        // We show one item, so also specify that as item count. So when the
        // add button is pressed the item count will be 2 and we show two items.
        $field_state['items_count'] = 1;
      }
      if (isset($field_state['entity'][$delta])) {
        $field_collection_item = $field_state['entity'][$delta];
      }
      else {
        if (isset($items[$delta])) {
          $field_collection_item = field_collection_field_get_entity($items[$delta], $field_name);
        }

        // Show an empty collection if we have no existing one or it does not
        // load.
        if (empty($field_collection_item)) {
          $field_collection_item = entity_create('field_collection_item', array(
            'field_name' => $field_name,
          ));
          $field_collection_item
            ->setHostEntity($element['#entity_type'], $element['#entity'], $langcode);
        }

        // Put our entity in the form state, so FAPI callbacks can access it.
        $field_state['entity'][$delta] = $field_collection_item;
      }

      // Register a child entity translation handler to properly deal with the
      // entity form language.
      if (field_collection_item_is_translatable()) {
        $element['#host_entity_type'] = $element['#entity_type'];
        $element['#host_entity'] = $element['#entity'];

        // Give each field collection item a unique entity translation handler
        // ID, otherwise an infinite loop occurs when adding values to nested
        // field collection items.
        if (!isset($field_collection_item->entity_translation_handler_id)) {
          list($id, $revision_id) = entity_extract_ids('field_collection_item', $field_collection_item);
          $revision_id = isset($revision_id) ? $revision_id : 0;
          $field_collection_item->entity_translation_handler_id = 'field_collection_item' . '-' . (!empty($id) ? 'eid-' . $id . '-' . $revision_id : 'new-' . mt_rand());
        }
        $element['#field_collection_item'] = $field_collection_item;
        field_collection_add_child_translation_handler($element);

        // Ensure this is executed even with cached forms. This is mainly useful
        // when dealing with AJAX calls.
        $element['#process'][] = 'field_collection_add_child_translation_handler';

        // Flag the field to be processed in field_collection_form_alter to
        // avoid adding incorrect translation hints.
        $address = array_slice($element['#parents'], 0, -2);
        if (empty($form['#field_collection_translation_fields']) || !in_array($address, $form['#field_collection_translation_fields'])) {
          $form['#field_collection_translation_fields'][] = $address;
        }
      }

      // Add the subform.
      field_form_set_state($field_parents, $field_name, $language, $form_state, $field_state);

      // Set the language to to parent entity language, because
      // field_content_languages() will always set $language to LANGUAGE_NONE.
      if (field_collection_item_is_translatable()) {
        field_attach_form('field_collection_item', $field_collection_item, $element, $form_state, entity_language($element['#host_entity_type'], $element['#host_entity']));
      }
      else {
        field_attach_form('field_collection_item', $field_collection_item, $element, $form_state, $language);
      }

      // Make sure subfields get translatable clues (like 'all languages')
      if (field_collection_item_is_translatable() && variable_get('entity_translation_shared_labels', TRUE)) {
        foreach (element_children($element) as $key) {
          $element[$key]['#process'][] = 'entity_translation_element_translatability_clue';
        }
      }
      if (empty($element['#required'])) {
        $element['#after_build'][] = 'field_collection_field_widget_embed_delay_required_validation';
      }
      if ($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED && empty($form_state['programmed'])) {
        $element['remove_button'] = array(
          '#delta' => $delta,
          '#name' => implode('_', $parents) . '_remove_button',
          '#type' => 'submit',
          '#value' => t('Remove'),
          '#validate' => array(),
          '#submit' => array(
            'field_collection_remove_submit',
          ),
          '#attributes' => array(
            'class' => array(
              'remove-button',
            ),
          ),
          '#limit_validation_errors' => array(),
          '#ajax' => array(
            // 'wrapper' is filled in field_collection_field_attach_form().
            'callback' => 'field_collection_remove_js',
            'effect' => 'fade',
          ),
          '#weight' => 1000,
        );
      }
      $recursion--;
      return $element;
    case 'field_collection_sorter':
      $elements = array();
      $field_name = $field['field_name'];
      $parents = $form['#parents'];
      $field_state = field_form_get_state($parents, $field_name, $langcode, $form_state);
      $count = $field_state['items_count'];
      for ($delta = 0; $delta < $count; $delta++) {
        $item_id = isset($items[$delta]['value']) ? $items[$delta]['value'] : NULL;
        $revision_id = isset($items[$delta]['revision_id']) ? $items[$delta]['revision_id'] : NULL;

        // Add a label component to visually identify this field collection item.
        $element['label'] = array();
        if ($item_id) {
          $item = field_collection_item_load($item_id);
          $element['label']['#markup'] = $item ? $item
            ->label() : $item_id;
        }

        // The field stored value (item_id) and revision_id values so we need
        // hidden fields to represent them.
        $element['value'] = array(
          '#type' => 'hidden',
          '#default_value' => $item_id,
        );
        $element['revision_id'] = array(
          '#type' => 'hidden',
          '#default_value' => $revision_id,
        );

        // Input field for the delta (drag-n-drop reordering).
        // We name the element '_weight' to avoid clashing with elements
        // defined by widget.
        $element['_weight'] = array(
          '#type' => 'weight',
          '#title' => t('Weight for row @number', array(
            '@number' => $delta + 1,
          )),
          '#title_display' => 'invisible',
          // Note: this 'delta' is the FAPI 'weight' element's property.
          '#delta' => $count,
          '#default_value' => isset($items[$delta]['_weight']) ? $items[$delta]['_weight'] : $delta,
          '#weight' => 100,
        );
        $elements[$delta] = $element;
      }
      if ($elements) {
        $elements += array(
          '#theme' => 'field_multiple_value_form',
          '#field_name' => $field['field_name'],
          '#cardinality' => $field['cardinality'],
          '#title' => check_plain($instance['label']),
          '#required' => FALSE,
          '#description' => field_filter_xss($instance['description']),
          '#max_delta' => $count - 1,
        );
      }
      return $elements;
  }
}