summaryrefslogtreecommitdiff
path: root/modules/field/field.crud.inc
diff options
context:
space:
mode:
authorDries Buytaert <dries@buytaert.net>2009-09-26 15:57:39 +0000
committerDries Buytaert <dries@buytaert.net>2009-09-26 15:57:39 +0000
commitdb09a6178ba423fe2ce85317afaca5c58a5b6887 (patch)
tree7a23bc57bfb65197a9ac1416d8c989b506e5e05d /modules/field/field.crud.inc
parentdba2ebb118a25ff6ed9bcc6a59cc42c20d55ad66 (diff)
downloadbrdo-db09a6178ba423fe2ce85317afaca5c58a5b6887.tar.gz
brdo-db09a6178ba423fe2ce85317afaca5c58a5b6887.tar.bz2
- Patch #367013 by bjaspan, KarenS | yched, Dries: add support for field updates.
Diffstat (limited to 'modules/field/field.crud.inc')
-rw-r--r--modules/field/field.crud.inc83
1 files changed, 83 insertions, 0 deletions
diff --git a/modules/field/field.crud.inc b/modules/field/field.crud.inc
index 7f316c4db..210dad136 100644
--- a/modules/field/field.crud.inc
+++ b/modules/field/field.crud.inc
@@ -312,6 +312,89 @@ function field_create_field($field) {
return $field;
}
+/*
+ * Update 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.
+ *
+ * @param $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
+ * Throws a FieldException if the update cannot be performed.
+ * @see field_create_field()
+ */
+function field_update_field($field) {
+ // Check that the specified field exists.
+ $prior_field = field_read_field($field['field_name']);
+ 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['settings'] += $prior_field['settings'];
+
+ // Field type cannot be changed.
+ if ($field['type'] != $prior_field['type']) {
+ throw new FieldException("Cannot change an existing field's type.");
+ }
+
+ // Collect the new storage information, since what is in
+ // $prior_field may no longer be right.
+ $schema = (array) module_invoke($field['module'], 'field_schema', $field);
+ $schema += array('columns' => array(), 'indexes' => array());
+ // 'columns' are hardcoded in the field type.
+ $field['columns'] = $schema['columns'];
+ // 'indexes' can be both hardcoded in the field type, and specified in the
+ // incoming $field definition.
+ $field += array(
+ 'indexes' => array(),
+ );
+ $field['indexes'] += $schema['indexes'];
+
+ $has_data = field_attach_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.
+ module_invoke(variable_get('field_storage_module', 'field_sql_storage'), 'field_storage_update_field', $field, $prior_field, $has_data);
+
+ // Save the new field definition. @todo: refactor with
+ // field_create_field.
+
+ // The serialized 'data' column contains everything from $field that does not
+ // have its own column and is not automatically populated when the field is
+ // read.
+ $data = $field;
+ unset($data['columns'], $data['field_name'], $data['type'], $data['locked'], $data['module'], $data['cardinality'], $data['active'], $data['deleted']);
+ $field['data'] = $data;
+
+ // Store the field and create the id.
+ $primary_key = array('id');
+ drupal_write_record('field_config', $field, $primary_key);
+
+ // Clear caches
+ field_cache_clear(TRUE);
+
+ // Invoke external hooks after the cache is cleared for API consistency.
+ module_invoke_all('field_update_field', $field, $prior_field, $has_data);
+}
+
/**
* Read a single field record directly from the database. Generally,
* you should use the field_info_field() instead.