diff --git a/modules/field/field.api.php b/modules/field/field.api.php index 129a915d27..3c77b82eba 100644 --- a/modules/field/field.api.php +++ b/modules/field/field.api.php @@ -278,6 +278,32 @@ function hook_field_schema($field) { ); } +/** + * Allow modules to alter the schema for a field. + * + * @param array $schema + * The schema definition as returned by hook_field_schema(). + * @param array $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. * diff --git a/modules/field/field.crud.inc b/modules/field/field.crud.inc index 3673128d08..9b28ac5222 100644 --- a/modules/field/field.crud.inc +++ b/modules/field/field.crud.inc @@ -20,6 +20,26 @@ * the Field API. */ +/** + * Retrieves the schema for a field. + * + * @param array $field + * The field array to get the schema definition against. + * @return array + * The field schema definition array. + */ +function field_retrieve_schema($field) { + // Make sure the installation API is available. + include_once DRUPAL_ROOT . '/includes/install.inc'; + module_load_all_includes('install'); + $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. * @@ -130,9 +150,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 +260,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 +404,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 +483,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 d53d9b706b..36ef49901e 100644 --- a/modules/field/tests/field.test +++ b/modules/field/tests/field.test @@ -2874,6 +2874,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; protected $instance_definition; 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 0000000000..e955825194 --- /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.install b/modules/field/tests/field_test_schema_alter.install new file mode 100644 index 0000000000..bfb28a553d --- /dev/null +++ b/modules/field/tests/field_test_schema_alter.install @@ -0,0 +1,23 @@ + "Additional column added to image field table.", + 'type' => 'varchar', + 'length' => 128, + 'not null' => FALSE, + ); + } +} 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 0000000000..b3d9bbc7f3 --- /dev/null +++ b/modules/field/tests/field_test_schema_alter.module @@ -0,0 +1 @@ +