You are here

function og_field_widget_form in Organic groups 7.2

Same name and namespace in other branches
  1. 7 og.field.inc \og_field_widget_form()

Implements hook_field_widget_form().

File

includes/og.field.inc, line 25
Field widget related code for Organic groups.

Code

function og_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
  $entity_type = $instance['entity_type'];
  $entity = isset($element['#entity']) ? $element['#entity'] : NULL;
  if (!$entity) {
    return;
  }
  if ($field['settings']['handler'] != 'og' && strpos($field['settings']['handler'], 'og_') !== 0) {
    $params = array(
      '%label' => $instance['label'],
    );
    form_error($form, t('Field %label is a group-audience but its Entity selection mode is not defined as "Organic groups" in the field settings page.', $params));
    return;
  }

  // Cache the processed entity, to make sure we call the widget only once.
  $cache =& drupal_static(__FUNCTION__, array());
  list($id, , $bundle) = entity_extract_ids($entity_type, $entity);
  $field_name = $field['field_name'];
  $identifier = $field_name . ':' . $entity_type . ':' . $bundle . ':' . $id;
  if (isset($cache[$identifier])) {
    return array();
  }
  $cache[$identifier] = TRUE;
  ctools_include('fields');
  $field_modes = array(
    'default',
  );
  $has_admin = FALSE;

  // The group IDs that might not be accessible by the user, but we need
  // to keep even after saving.
  $element['#other_groups_ids'] = array();
  $element['#element_validate'][] = 'og_complex_widget_element_validate';
  if (user_access('administer group')) {
    $has_admin = TRUE;
    $field_modes[] = 'admin';
  }

  // Build an array of entity IDs. Field's $items are loaded
  // in OgBehaviorHandler::load().
  $entity_gids = array();
  foreach ($items as $item) {
    $entity_gids[] = $item['target_id'];
  }
  $target_type = $field['settings']['target_type'];
  $user_gids = og_get_entity_groups('user', NULL, array(
    OG_STATE_ACTIVE,
    OG_STATE_PENDING,
  ));
  $user_gids = !empty($user_gids[$target_type]) ? $user_gids[$target_type] : array();

  // Get the "Other group" group IDs.
  $other_groups_ids = array_diff($entity_gids, $user_gids);
  foreach ($field_modes as $field_mode) {
    $mocked_instance = og_get_mocked_instance($instance, $field_mode);
    $dummy_entity = clone $entity;
    if ($has_admin) {
      $mocked_instance['required'] = FALSE;
      if ($field_mode == 'default') {
        $mocked_instance['label'] = t('Your groups');
        if ($entity_type == 'user') {
          $mocked_instance['description'] = t('Associate this user with groups you belong to.');
        }
        else {
          $mocked_instance['description'] = t('Associate this content with groups you belong to.');
        }
      }
      else {
        $mocked_instance['label'] = t('Other groups');
        if ($entity_type == 'user') {
          $mocked_instance['description'] = t('As groups administrator, associate this user with groups you do <em>not</em> belong to.');
        }
        else {
          $mocked_instance['description'] = t('As groups administrator, associate this content with groups you do <em>not</em> belong to.');
        }
      }

      // The field might be required, and it will throw an exception
      // when we try to set an empty value, so change the wrapper's
      // info.
      $wrapper = entity_metadata_wrapper($entity_type, $dummy_entity, array(
        'property info alter' => 'og_property_info_alter',
        'field name' => $field_name,
      ));
      if ($field_mode == 'admin') {

        // Keep only the hidden group IDs on the entity, so they won't
        // appear again on the "admin" field, for example on an autocomplete
        // widget type.
        $valid_ids = $other_groups_ids ? entityreference_get_selection_handler($field, $mocked_instance, $entity_type, $dummy_entity)
          ->validateReferencableEntities($other_groups_ids) : array();
        $valid_ids = $field['cardinality'] == 1 ? reset($valid_ids) : $valid_ids;
        $wrapper->{$field_name}
          ->set($valid_ids ? $valid_ids : NULL);
      }
      else {

        // Keep only the groups that belong to the user and to the entity.
        $my_group_ids = array_values(array_intersect($user_gids, $entity_gids));
        $valid_ids = $my_group_ids ? entityreference_get_selection_handler($field, $mocked_instance, $entity_type, $dummy_entity)
          ->validateReferencableEntities($my_group_ids) : array();
        $valid_ids = $field['cardinality'] == 1 ? reset($valid_ids) : $valid_ids;
        $wrapper->{$field_name}
          ->set($valid_ids ? $valid_ids : NULL);
      }
    }
    elseif ($other_groups_ids) {
      foreach ($other_groups_ids as $id) {
        $element['#other_groups_ids'][] = array(
          'target_id' => $id,
          'field_mode' => 'admin',
        );
      }
      if (!empty($dummy_entity->{$field_name}[$langcode])) {

        // Non-admin user.
        $ids = array();
        foreach ($dummy_entity->{$field_name}[$langcode] as $delta => $value) {
          $id = $value['target_id'];
          if (!in_array($id, $other_groups_ids)) {
            $ids[] = $id;
          }
        }

        // Rekey the field items.
        $dummy_entity->{$field_name}[$langcode] = array();
        foreach ($ids as $id) {
          $dummy_entity->{$field_name}[$langcode][] = array(
            'target_id' => $id,
          );
        }
      }
    }
    $dummy_form_state = $form_state;
    if (empty($form_state['rebuild'])) {

      // Form is "fresh" (i.e. not call from field_add_more_submit()), so
      // re-set the items-count, to show the correct amount for the mocked
      // instance.
      $dummy_form_state['field'][$field_name][$langcode]['items_count'] = !empty($dummy_entity->{$field_name}[$langcode]) ? count($dummy_entity->{$field_name}[$langcode]) : 0;
    }
    $new_element = ctools_field_invoke_field($mocked_instance, 'form', $entity_type, $dummy_entity, $form, $dummy_form_state, array(
      'default' => TRUE,
    ));
    $element[$field_mode] = $new_element[$field_name][LANGUAGE_NONE];
    if (in_array($mocked_instance['widget']['type'], array(
      'entityreference_autocomplete',
      'entityreference_autocomplete_tags',
    ))) {

      // Change the "Add more" button name so it adds only the needed
      // element.
      if (!empty($element[$field_mode]['add_more']['#name'])) {
        $element[$field_mode]['add_more']['#name'] .= '__' . $field_mode;
      }
      if ($mocked_instance['widget']['type'] == 'entityreference_autocomplete') {
        foreach (array_keys($element[$field_mode]) as $delta) {
          if (!is_numeric($delta)) {
            continue;
          }
          $sub_element =& $element[$field_mode][$delta]['target_id'];
          _og_field_widget_replace_autocomplete_path($sub_element, $field_mode);
        }
      }
      else {

        // Tags widget, there's no delta, we can pass the element itself.
        _og_field_widget_replace_autocomplete_path($element[$field_mode], $field_mode);
      }
    }
  }
  $form['#after_build']['og'] = 'og_complex_widget_after_build';
  $form['#validate'][] = 'og_validate_widgets';
  return $element;
}