You are here

public static function FieldChangeHelper::changeType in Helper 7

Change a field's type, even if it has data.

Parameters

$field_name: The name of the field to change.

$type: The type of field to change it to.

array $column_renames: An array of existing field schema columns to rename. For example, if the old field type has a column 'value' which maps to the new field type's 'data' column, use array('value' => 'data') to ensure the old column is just renamed instead of dropped. To ensure an old field column is dropped, for example, if the same column name is used in the new field type, but is used to store different data, use array('old_column' => FALSE).

array $field_overrides: An optional array that overrides any of the values in the $field definition array prior to saving.

array $field_instance_overrides: An optional array that overrides any of the values in any of the field's instance definition array prior to saving.

Return value

array The change field if everything was successful.

Throws

Exception

File

lib/FieldChangeHelper.php, line 32

Class

FieldChangeHelper

Code

public static function changeType($field_name, $type, array $column_renames = array(), array $field_overrides = array(), array $field_instance_overrides = array()) {
  $field = $prior_field = field_read_field($field_name);
  if (empty($field)) {
    throw new Exception("Field {$field_name} does not exist or is inactive or deleted.");
  }
  if ($field['type'] === $type) {
    throw new Exception("Field {$field_name} is already type {$type}.");
  }
  if ($field['storage']['type'] !== 'field_sql_storage') {
    throw new Exception("Unable to change field type for field {$field_name} using storage {$field['storage']['type']}.");
  }
  $type_info = field_info_field_types($type);
  if (empty($type_info)) {
    throw new Exception("Invalid field type {$type}.");
  }
  $transaction = db_transaction();
  try {

    // Serialize properties back into the data property so it can be saved
    // to the database.
    $field['data'] = array();
    foreach ($field as $key => $value) {
      switch ($key) {
        case 'id':
        case 'field_name':
        case 'type':
        case 'module':
        case 'active':
        case 'locked':
        case 'cardinality':
        case 'deleted':
        case 'data':
          break;
        default:
          $field['data'][$key] =& $field[$key];
      }
    }

    // Update basic information on the field config.
    $field['type'] = $type;
    $field['module'] = $type_info['module'];
    $field['settings'] = array_intersect_key($field['settings'], $type_info['settings']);
    $field['settings'] += $type_info['settings'];

    // @todo Check if $field['translatable'] needs to be changed.
    // Make any final field overrides before updating the schema and saving
    // the field config record back to the database.
    $field = drupal_array_merge_deep($field, $field_overrides);
    static::changeSchema($field, $column_renames);
    drupal_write_record('field_config', $field, array(
      'id',
    ));

    // Now update the instances for this field.
    static::changeInstances($field, $field_instance_overrides);

    // Clear caches
    field_cache_clear();

    // Invoke external hooks after the cache is cleared for API consistency.
    $has_data = field_has_data($field);
    module_invoke_all('field_update_field', $field, $prior_field, $has_data);
    watchdog('helper', "Converted field {$field_name} from {$prior_field['type']} to {$type}.");
    return $field;
  } catch (Exception $e) {
    $transaction
      ->rollback();
    watchdog_exception('helper', $e);
    throw $e;
  }
}