diff --git a/modules/field/field.api.php b/modules/field/field.api.php index 365fc40..38e6809 100644 --- a/modules/field/field.api.php +++ b/modules/field/field.api.php @@ -279,6 +279,32 @@ function hook_field_schema($field) { } /** + * Allow modules to alter the schema for a field. + * + * @param $schema + * The schema definition as returned by hook_field_schema(). + * @param $field + * The field definition. + * + * @see field_retrieve_schema() + */ +function hook_field_schema_alter(&$schema, $field) { + if ($field['type'] == 'image') { + // Alter the length of a field. + $schema['columns']['alt']['length'] = 2048; + // Add an additional column of data. + $schema['columns']['additional_column'] = array( + 'description' => "Additional column added to image field table.", + 'type' => 'varchar', + 'length' => 128, + 'not null' => FALSE, + ); + // Add an additional index. + $schema['indexes']['fid_additional_column'] = array('fid', 'additional_column'); + } +} + +/** * Define custom load behavior for this module's field types. * * Unlike most other field hooks, this hook operates on multiple entities. The diff --git a/modules/field/field.crud.inc b/modules/field/field.crud.inc index 83863d6..8e370c0 100644 --- a/modules/field/field.crud.inc +++ b/modules/field/field.crud.inc @@ -21,6 +21,24 @@ */ /** + * Retrieves the schema for a field. + * + * @param $field + * The field array to get the schema definition against. + * @return + * The field schema definition array. + */ +function field_retrieve_schema($field) { + module_load_install($field['module']); + $schema = (array) module_invoke($field['module'], 'field_schema', $field); + $schema += array('columns' => array(), 'indexes' => array(), 'foreign keys' => array()); + // Give other modules a chance to alter this definition. + // @see hook_field_schema_alter() + drupal_alter('field_schema', $schema, $field); + return $schema; +} + +/** * Creates a field. * * This function does not bind the field to any bundle; use @@ -130,9 +148,7 @@ function field_create_field($field) { $field['storage']['module'] = $storage_type['module']; $field['storage']['active'] = 1; // Collect storage information. - module_load_install($field['module']); - $schema = (array) module_invoke($field['module'], 'field_schema', $field); - $schema += array('columns' => array(), 'indexes' => array(), 'foreign keys' => array()); + $schema = field_retrieve_schema($field); // 'columns' are hardcoded in the field type. $field['columns'] = $schema['columns']; // 'foreign keys' are hardcoded in the field type. @@ -242,9 +258,7 @@ function field_update_field($field) { // 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()); + $schema = field_retrieve_schema($field); // 'columns' are hardcoded in the field type. $field['columns'] = $schema['columns']; // 'foreign keys' are hardcoded in the field type. @@ -388,9 +402,7 @@ function field_read_fields($params = array(), $include_additional = array()) { module_invoke_all('field_read_field', $field); // Populate storage information. - module_load_install($field['module']); - $schema = (array) module_invoke($field['module'], 'field_schema', $field); - $schema += array('columns' => array(), 'indexes' => array()); + $schema = field_retrieve_schema($field); $field['columns'] = $schema['columns']; $field_name = $field['field_name']; @@ -469,6 +481,7 @@ function field_delete_field($field_name) { * @throws FieldException * * See: @link field Field API data structures @endlink. + * @see hook_field_schema_alter() */ function field_create_instance($instance) { $field = field_read_field($instance['field_name']); diff --git a/modules/field/tests/field.test b/modules/field/tests/field.test index 1e59315..f4fdf0c 100644 --- a/modules/field/tests/field.test +++ b/modules/field/tests/field.test @@ -2760,6 +2760,49 @@ class FieldCrudTestCase extends FieldTestCase { } } +/** + * Tests that the field schema can be altered with hook_field_schema_alter(). + */ +class FieldSchemaAlterTestCase extends FieldTestCase { + public static function getInfo() { + return array( + 'name' => 'Field schema alteration tests', + 'description' => 'Alter the schema for a given type of field.', + 'group' => 'Field API', + ); + } + + function setUp() { + parent::setUp('field_test', 'field_test_schema_alter'); + } + + /** + * Tests a hook_field_schema_alter() implementation. + * + * @see field_test_schema_alter_field_schema_alter() + */ + function testImageFieldSchemaAlter() { + $test_field = array( + 'field_name' => drupal_strtolower($this->randomName()), + 'type' => 'test_field', + ); + field_create_field($test_field); + $test_field_name = $test_field['field_name']; + $test_field_instance_settings = array( + 'field_name' => $test_field_name, + 'entity_type' => 'test_entity', + 'bundle' => 'test_bundle', + 'deleted' => 0, + ); + $test_field_instance = field_create_instance($test_field_instance_settings); + + $table_name = _field_sql_storage_tablename($test_field_instance); + $schema = drupal_get_schema($table_name, TRUE); + $this->assertEqual('float', $schema['fields'][$test_field_name .'_value']['type']); + $this->assertTrue(db_field_exists($table_name, $test_field_name .'_additional_column')); + } +} + class FieldInstanceCrudTestCase extends FieldTestCase { protected $field; diff --git a/modules/field/tests/field_test_schema_alter.info b/modules/field/tests/field_test_schema_alter.info new file mode 100644 index 0000000..e955825 --- /dev/null +++ b/modules/field/tests/field_test_schema_alter.info @@ -0,0 +1,6 @@ +name = "Field API Schema Alter Test" +description = "Support module for the Field API schema alter tests." +core = 7.x +package = Testing +version = VERSION +hidden = TRUE diff --git a/modules/field/tests/field_test_schema_alter.module b/modules/field/tests/field_test_schema_alter.module new file mode 100644 index 0000000..b9dc984 --- /dev/null +++ b/modules/field/tests/field_test_schema_alter.module @@ -0,0 +1,23 @@ + "Additional column added to image field table.", + 'type' => 'varchar', + 'length' => 128, + 'not null' => FALSE, + ); + } +}