You are here

function relation_add_field_widget_form in Relation add 7

Implements hook_field_widget_form().

File

./relation_add.module, line 625
Relation Add module file.

Code

function relation_add_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
  $item = isset($items[$delta]) ? $items[$delta] : array();
  $types = array();
  if (empty($instance['settings']['relation_type'])) {
    $relation_types = relation_get_available_types($instance['entity_type'], $instance['bundle']);
    $reverse_types = relation_get_available_types($instance['entity_type'], $instance['bundle'], 'target');
    if (empty($relation_types) && empty($reverse_types)) {
      return $element;
    }

    // Relation type selector. On change, rest of form is loaded via ajax.
    foreach ($relation_types as $relation_type) {
      $types[$relation_type->relation_type] = $relation_type->label;
    }
    foreach ($reverse_types as $relation_type) {

      // Directional n-ary relations are f@*#ing stupid.
      if ($relation_type->directional && $relation_type->max_arity == 2) {

        // Machine name doesn't have colons, so we add a suffix for reverse
        // relations, which we explode off later.
        $types[$relation_type->relation_type . ':reverse'] = $relation_type->reverse_label ? $relation_type->reverse_label : 'reverse ' . $relation_type->reverse_label;
      }
    }
  }
  elseif (count($instance['settings']['relation_type']) > 1) {
    foreach ($instance['settings']['relation_type'] as $rel_type) {
      $type_array = explode(':', $rel_type);
      $relation_type = relation_type_load($type_array[0]);
      $types[$rel_type] = !isset($type_array[1]) ? $relation_type->label : $relation_type->reverse_label;
    }
  }
  ksort($types);
  $wrapper = str_replace('_', '-', $instance['field_name']) . '-relation-add-options-' . $delta;
  $form_element = array(
    '#tree' => TRUE,
  );
  if (!empty($types)) {
    if (isset($item['relation_type'])) {
      if (isset($types[$item['relation_type'] . ':reverse']) && $item['endpoints'][LANGUAGE_NONE][0]['entity_id'] != $item['my_entity_id']) {
        $type = $item['relation_type'] . ':reverse';
        $relation_reverse = TRUE;
      }
      elseif (isset($types[$item['relation_type']])) {
        $type = $item['relation_type'];
        $relation_reverse = FALSE;
      }
    }
    elseif (isset($instance['settings']['fieldset']['default_value'])) {
      $type = $instance['settings']['fieldset']['default_value'];
      $type_array = explode(':', $type);
      $relation_reverse = isset($type_array[1]) && $type_array[1] == 'reverse';
    }
    $form_element['relation_type'] = array(
      '#type' => 'select',
      '#title' => t('Relation type'),
      '#options' => $types,
      '#default_value' => isset($type) ? $type : NULL,
      '#empty_value' => '',
      '#empty_option' => t('Select a relation type'),
      '#ajax' => array(
        'callback' => 'relation_add_widget_ajax',
        'wrapper' => $wrapper,
        'method' => 'replace',
        'effect' => 'fade',
      ),
    );
  }
  else {
    $form_element['relation_type'] = array(
      '#type' => 'value',
      '#value' => reset($instance['settings']['relation_type']),
    );
  }
  if (isset($form_state['triggering_element']['#ajax'])) {
    if (!empty($form_state['values'][$field['field_name']][$langcode][$delta]['relation_type'])) {
      $form_state_relation_type = $form_state['values'][$field['field_name']][$langcode][$delta]['relation_type'];
    }
    elseif (!empty($form_state['input'][$field['field_name']][$langcode][$delta]['relation_type'])) {
      $form_state_relation_type = $form_state['input'][$field['field_name']][$langcode][$delta]['relation_type'];
    }
    if (isset($form_state_relation_type)) {

      // Remove ':reverse' suffix if it exists, and set reverse flag.
      $type_array = explode(':', $form_state_relation_type);
      $type = $type_array[0];
      $relation_reverse = isset($type_array[1]) && $type_array[1] == 'reverse';
    }
  }
  if (empty($types)) {
    $type_array = explode(':', reset($instance['settings']['relation_type']));
    $type = $type_array[0];
    $relation_reverse = isset($type_array[1]) && $type_array[1] == 'reverse';
  }
  $field_parents = $element['#field_parents'];
  $field_name = $element['#field_name'];
  $language = $element['#language'];
  $parents = array_merge($field_parents, array(
    $field_name,
    $language,
    $delta,
  ));
  $parents[] = 'relation_options';
  $form_element['relation_options'] = array(
    '#parents' => $parents,
    '#prefix' => '<div id="' . $wrapper . '">',
    '#suffix' => '</div>',
  );
  $add_required_validation = FALSE;
  if (!empty($type)) {

    // Get all fields.
    $info_rel_instances = field_info_instances('relation', $type);

    // Remove endpoint field.
    unset($info_rel_instances['endpoins']);

    // Find required fields.
    if (!empty($info_rel_instances)) {
      foreach ($info_rel_instances as $info_rel_instance) {
        if (isset($info_rel_instance['required']) && $info_rel_instance['required']) {
          $add_required_validation = TRUE;
          break;
        }
      }
    }
    if (isset($item) && !empty($item)) {
      $relation = (object) $item;

      // $relation->relation_type can also have the :reverse suffix here so we
      // have to remove it.
      $type_array = explode(':', $relation->relation_type);
      $relation_type = relation_type_load($type_array[0]);
      $default_targets = array();
      $i = 2;
      if (!empty($item['endpoints'][LANGUAGE_NONE])) {
        foreach ($item['endpoints'][LANGUAGE_NONE] as $endpoint) {
          $entities = entity_load($endpoint['entity_type'], array(
            $endpoint['entity_id'],
          ));
          $entity = reset($entities);
          $label = entity_label($endpoint['entity_type'], $entity);
          $bundle = '';
          if (isset($instance['widget']['settings']['relation_endpoint_bundle_display'])) {
            list(, , $bundle) = entity_extract_ids($endpoint['entity_type'], $entity);
            if (!empty($bundle)) {
              $bundle = ' - (' . $bundle . ')';
            }
          }
          $entity_label = $label . $bundle . ' [' . $endpoint['entity_type'] . ':' . $endpoint['entity_id'] . ']';
          if ($endpoint['entity_id'] == $item['my_entity_id'] && $endpoint['entity_type'] == $instance['entity_type']) {
            $default_targets[1] = $entity_label;
          }
          else {
            $default_targets[$i] = $entity_label;
            $i++;
          }
        }
      }
    }
    else {

      // $type can also have the :reverse suffix here so we have to remove it.
      $type_array = explode(':', $type);
      $relation_type = relation_type_load($type_array[0]);
      $relation = (object) relation_create($type_array[0], array());
    }

    // Create one autocomplete for each endpoint beyond the first.
    $direction = $relation_reverse ? '/source' : '/target';
    $endpoint_title = '';
    switch ($instance['widget']['settings']['relation_endpoint_label']) {
      case 'endpoint':
        $relation_instance = field_info_instance('relation', 'endpoints', $relation_type->relation_type);

        // @codingStandardsIgnoreStart
        $endpoint_title = t(check_plain($relation_instance['label']));

        // @codingStandardsIgnoreEnd
        break;
      case 'custom':

        // @codingStandardsIgnoreStart
        $endpoint_title = t($instance['widget']['settings']['relation_endpoint_custom_label']);

        // @codingStandardsIgnoreEnd
        break;
    }
    $target_bundles = 'all';
    if (!empty($instance['settings']['relation_target_bundles'])) {
      $target_bundles = implode('-', $instance['settings']['relation_target_bundles']);
    }
    if ($relation_type->max_arity == 0) {
      if (isset($form_state['input'][$instance['field_name']][$element['#language']][$delta]['relation_options']['targets'])) {
        $max_arity = count($form_state['input'][$instance['field_name']][$element['#language']][$delta]['relation_options']['targets']) + 1;

        // Click "Add" button.
        if ('targets_add_' . $instance['field_name'] . '_' . $delta == $form_state['clicked_button']['#name']) {
          $max_arity += 1;
        }
      }
      elseif (isset($default_targets)) {
        $max_arity = count($default_targets) + 1;
      }
      else {
        $max_arity = 2;
      }
    }
    else {
      $max_arity = $relation_type->max_arity;
    }
    $wrapper_targets = str_replace('_', '-', $instance['field_name']) . '-relation-add-targets-' . $delta;
    $form_element['relation_options']['targets'] = array(
      '#prefix' => '<div id="' . $wrapper_targets . '">',
      '#suffix' => '</div>',
    );
    for ($i = 2; $i <= $max_arity; $i++) {
      $endpoint_title .= $instance['widget']['settings']['relation_endpoint_label_delta'] ? ' ' . ($i - 1) : '';
      $form_element['relation_options']['targets']['target_' . $i] = array(
        '#type' => 'textfield',
        '#maxlength' => 320,
        '#title' => $endpoint_title,
        '#default_value' => isset($default_targets[$i]) ? $default_targets[$i] : '',
        '#autocomplete_path' => 'relation_add/autocomplete/' . $type . $direction . '/' . $instance['entity_type'] . '-' . $instance['field_name'] . '-' . $instance['bundle'] . '/' . $target_bundles,
      );
    }
    if ($relation_type->max_arity == 0) {
      $form_element['relation_options']['targets_add'] = array(
        '#type' => 'button',
        '#value' => t('Add'),
        '#name' => 'targets_add_' . $instance['field_name'] . '_' . $delta,
        '#ajax' => array(
          'event' => 'click',
          'callback' => 'relation_add_widget_ajax',
          'wrapper' => $wrapper_targets,
          'method' => 'replace',
          'effect' => 'fade',
        ),
        '#submit' => array(
          'relation_add_widget_ajax',
        ),
        '#limit_validation_errors' => array(),
      );
    }
    if (isset($item['my_entity_id'])) {
      $form_element['relation_options']['rid'] = array(
        '#type' => 'value',
        '#value' => $item['rid'],
      );
    }
    field_attach_form('relation', $relation, $form_element['relation_options'], $form_state);
    $form_element['delete'] = array(
      '#type' => 'checkbox',
      '#title' => t('Delete'),
    );
    $form_element['relation_options']['targets']['#weight'] = $form_element['relation_options']['endpoints']['#weight'];
    if (isset($form_element['relation_options']['targets_add'])) {
      $form_element['relation_options']['targets_add']['#weight'] = $form_element['relation_options']['endpoints']['#weight'] + 1;
    }
    unset($form_element['relation_options']['endpoints']);
  }
  if ($field['cardinality'] == 1) {
    $form_element['relation_options']['#prefix'] = '<div class="relation-add-wrapper">' . $form_element['relation_options']['#prefix'];
    $form_element['delete']['#suffix'] = '</div>';
    $form_element['label'] = $element + array(
      '#type' => 'item',
    );
  }

  // Add element validate function if relation has required field.
  if ($add_required_validation) {
    $form_element['#element_validate'] = array(
      'relation_add_field_required_validate',
    );
  }
  return $element + $form_element;
}