<?php

/**
 * Implements image_field_update_instance().
 */
function field_default_token_field_update_instance($instance, $prior_instance) {
  $has_tokens = FALSE;
  if (!empty($instance['default_value'])) {
    foreach ($instance['default_value'] as $values) {
      foreach ($values as $value) {
        if (!is_array($value)) {
          if (strpos($value, '[') !== FALSE) {
            $has_tokens = TRUE;
          }
        }
        else {
          foreach ($value as $column_value) {
            if (strpos($column_value, '[') !== FALSE) {
              $has_tokens = TRUE;
            }
          }
        }
      }
    }
  }

  $update = FALSE;

  if (empty($instance['default_value_function'])) {
    if ($has_tokens) {
      $instance['default_value_function'] = 'field_default_token_default_value_function';
      $update = TRUE;
    }
  }
  else if ($instance['default_value_function'] == 'field_default_token_default_value_function') {
    if (!$has_tokens) {
      unset($instance['default_value_function']);
      $update = TRUE;
    }
  }

  if ($update) {
    // Resave the instance and reclear caches.
    _field_write_instance($instance, TRUE);
    field_cache_clear();
  }
}

/**
 * Function for token replacementment of default values.
 */
function field_default_token_default_value_function($entity_type, $entity, $field, $instance, $langcode) {
  $token_type = $entity_type;
  $entity_info = entity_get_info($entity_type);
  if (isset($entity_info['token type'])) {
    $token_type = $entity_info['token type'];
  }
  $data = array(
    $token_type => $entity,
  );

  $items = $instance['default_value'];
  foreach ($items as &$item) {
    if (!is_array($item)) {
      $item = token_replace($item, $data, array('clear' => TRUE));
    }
    else {
      foreach ($item as $column_name => $column_value) {
        $item[$column_name] = token_replace($column_value, $data, array('clear' => TRUE));
      }
    }
  }
  return $items;
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function field_default_token_form_field_ui_field_edit_form_alter(&$form, &$form_state, $form_id) {
  if (!isset($form['instance']['default_value_widget'])) {
    $field = $form['#field'];
    $instance = $form['#instance'];
    if ((field_behaviors_widget('default value', $instance) == FIELD_BEHAVIOR_DEFAULT)
        && (!empty($instance['default_value_function'])) && ($instance['default_value_function'] === 'field_default_token_default_value_function')) {
      //Readd default value widget hidden by core.
      $form['instance']['default_value_widget'] = field_ui_default_value_widget($field, $instance, $form, $form_state);
    }
  }

  if ((isset($form['#instance']['widget']['type'])) && ($form['#instance']['widget']['type'] == 'options_select')) {
    $default_value = '';
    if (!empty($form['#instance']['default_value'])) {
      foreach ($form['#instance']['default_value'] as $values) {
        foreach ($values as $value) {
          if (strpos($value, '[') !== FALSE) {
            $default_value = $value;
          }
        }
      }
    }
    $form['instance']['default_value_widget']['default_value_token'] = array(
      '#type' => 'textfield',
      '#title' => t('Token for default value'),
      '#description' => t('If set, this token will be used as the field default value instead.'),
      '#default_value' => $default_value,
      '#weight' => 100,
    );
  }

  // Replace validator to disable validation of strings with tokens in Field UI forms.
  foreach ($form['#validate'] as &$validator) {
    if ($validator == 'field_ui_field_edit_form_validate') {
      $validator = 'field_default_token_field_ui_field_edit_form_validate';
    }
  }
}

/**
 * Implements hook_ctools_plugin_directory().
 */
function field_default_token_ctools_plugin_directory($module, $plugin) {
  if ($module == 'entityreference') {
    return 'plugins/' . $plugin;
  }
}

/**
 * Implements hook_field_widget_form_alter().
 */
function field_default_token_field_widget_form_alter(&$element, &$form_state, $context) {
  if (!empty($element['#entity_type'])) {
    if (empty($element['#entity'])) {
      field_default_token_modify_field_ui_form($element, $form_state, $context);
    }
  }
}

/**
 * Modify Field UI form.
 */
function field_default_token_modify_field_ui_form(&$element, &$form_state, $context) {
  if (isset($element['#options'])) { // Selector, checkboxes, radio buttons.
    $element['#value_callback'] = 'field_default_token_selection_element_value';
  }
}

/**
 * Replacement for form_type_select_value() functions for selectors, checkboxes, radio buttons (Field UI forms only).
 */
function field_default_token_selection_element_value(&$element, $input, $form_state) {
  if (!empty($form_state['input']['default_value_token'])) {
    // Disable validation on Field UI forms.
    $element['#after_build'][] = 'field_default_token_remove_validation';
    $token = $form_state['input']['default_value_token'];
    if ($input !== FALSE) {
      if (isset($element['#multiple']) && $element['#multiple']) {
        $input = array($token);
      }
      else {
        $input = $token;
      }
    }
  }
  return form_type_select_value($element, $input);
}

/**
 * Disables field validation on Field UI forms for selectors, checkboxes, radio buttons.
 */
function field_default_token_remove_validation(&$element, &$form_state) {
  unset($element['#needs_validation']);
  return $element;
}

/**
 * Form validation handler for field_ui_field_edit_form, replacement for field_ui_field_edit_form_validate().
 */
function field_default_token_field_ui_field_edit_form_validate($form, &$form_state) {
  // Take the incoming values as the $instance definition, so that the 'default
  // value' gets validated using the instance settings being submitted.
  $instance = $form_state['values']['instance'];
  $field_name = $instance['field_name'];

  if (isset($form['instance']['default_value_widget'])) {
    $element = $form['instance']['default_value_widget'];

    $field_state = field_form_get_state($element['#parents'], $field_name, LANGUAGE_NONE, $form_state);
    $field = $field_state['field'];

    // Extract the 'default value'.
    $items = array();
    field_default_extract_form_values(NULL, NULL, $field, $instance, LANGUAGE_NONE, $items, $element, $form_state);

    foreach ($items as $item) {
      if (is_array($item)) {
        foreach ($item as $value) {
          if (is_scalar($value)) {
            if (strpos($value, '[') !== FALSE) {
              // Token in default value, do not validate.
              return;
            }
          }
        }
      }
    }

    // Validate the value and report errors.
    $errors = array();
    $function = $field['module'] . '_field_validate';
    if (function_exists($function)) {
      $function(NULL, NULL, $field, $instance, LANGUAGE_NONE, $items, $errors);
    }
    if (isset($errors[$field_name][LANGUAGE_NONE])) {
      // Store reported errors in $form_state.
      $field_state['errors'] = $errors[$field_name][LANGUAGE_NONE];
      field_form_set_state($element['#parents'], $field_name, LANGUAGE_NONE, $form_state, $field_state);
      // Assign reported errors to the correct form element.
      field_default_form_errors(NULL, NULL, $field, $instance, LANGUAGE_NONE, $items, $element, $form_state);
    }
  }
}
