1 field.crud.inc field_update_field($field)

Updates a field.

Any module may forbid any update for any reason. For example, the field's storage module might forbid an update if it would change the storage schema while data for the field exists. A field type module might forbid an update if it would change existing data's semantics, or if there are external dependencies on field settings that cannot be updated.

Parameters

$field: A field structure. $field['field_name'] must provided; it identifies the field that will be updated to match this structure. Any other properties of the field that are not specified in $field will be left unchanged, so it is not necessary to pass in a fully populated $field structure.

Return value

Throws a FieldException if the update cannot be performed.

See also

field_create_field()

Related topics

File

core/modules/field/field.crud.inc, line 151
Field CRUD API, handling field and field instance creation and deletion.

Code

function field_update_field($field) {
  // Check that the specified field exists.
  $prior_field = field_read_field($field['field_name'], array('include_inactive' => TRUE, 'include_deleted' => TRUE));
  if (empty($prior_field)) {
    throw new FieldException('Attempt to update a non-existent field.');
  }

  // Use the prior field values for anything not specifically set by the new
  // field to be sure that all values are set.
  $field += $prior_field;
  $field += field_defaults_field();
  $field['settings'] += $prior_field['settings'];
  $field['settings'] += field_info_field_settings($field['type']);

  // Validate the fully populated field.
  field_validate_field($field, TRUE);

  // Some updates are always disallowed.
  if ($field['type'] != $prior_field['type']) {
    throw new FieldException("Cannot change an existing field's type.");
  }
  if ($field['entity_types'] != $prior_field['entity_types']) {
    throw new FieldException("Cannot change an existing field's entity_types property.");
  }
  if ($field['storage']['type'] != $prior_field['storage']['type']) {
    throw new FieldException("Cannot change an existing field's storage type.");
  }

  // Fields have a large amount of data that is generated on load, so trim down
  // the entire structure to just that which is not replaced on load.
  $field_data = array_intersect_key($field, field_defaults_field());
  if (isset($field_data['storage']['details'])) {
    unset($field_data['storage']['details']);
  }

  // Store the field in config.
  $config = config('field.field.' . $field['field_name']);
  $config->setData($field_data);
  $config->save();

  // Collect the new storage information, since what is in
  // $prior_field may no longer be right.
  module_load_install($field['module']);
  $schema = (array) module_invoke($field['module'], 'field_schema', $field);
  $schema += array(
    'columns' => array(),
    'indexes' => array(),
    'foreign keys' => array(),
  );
  $field['columns'] = $schema['columns'];
  $field['foreign keys'] = $schema['foreign keys'];
  $field['indexes'] = $schema['indexes'];

  $has_data = field_has_data($field);

  // See if any module forbids the update by throwing an exception.
  foreach (module_implements('field_update_forbid') as $module) {
    $function = $module . '_field_update_forbid';
    $function($field, $prior_field, $has_data);
  }

  // Tell the storage engine to update the field. Do this before
  // saving the new definition since it still might fail.
  $storage_type = field_info_storage_types($field['storage']['type']);
  module_invoke($storage_type['module'], 'field_storage_update_field', $field, $prior_field, $has_data);

  // Clear caches
  field_cache_clear();

  // Invoke external hooks after the cache is cleared for API consistency.
  module_invoke_all('field_update_field', $field, $prior_field, $has_data);
}