diff options
Diffstat (limited to 'modules')
-rw-r--r-- | modules/field/field.api.php | 41 | ||||
-rw-r--r-- | modules/field/field.info.inc | 5 | ||||
-rw-r--r-- | modules/field/field.test | 41 | ||||
-rw-r--r-- | modules/field/modules/field_sql_storage/field_sql_storage.module | 22 | ||||
-rw-r--r-- | modules/field/modules/field_sql_storage/field_sql_storage.test | 28 | ||||
-rw-r--r-- | modules/simpletest/tests/field_test.module | 43 |
6 files changed, 180 insertions, 0 deletions
diff --git a/modules/field/field.api.php b/modules/field/field.api.php index 60e54d5d8..84a9b07e9 100644 --- a/modules/field/field.api.php +++ b/modules/field/field.api.php @@ -1141,6 +1141,47 @@ function hook_field_storage_info_alter(&$info) { } /** + * Reveal the internal details about the storage for a field. + * + * For example, an SQL storage module might return the Schema API structure for + * the table. A key/value storage module might return the server name, + * authentication credentials, and bin name. + * + * Field storage modules are not obligated to implement this hook. Modules + * that rely on these details must only use them for read operations. + * + * @param $field + * A field structure. + * @param $instance + * A field instance structure. + * @return + * An array of details. + * - The first dimension is a store type (sql, solr, etc). + * - The second dimension indicates the age of the values in the store + * FIELD_LOAD_CURRENT or FIELD_LOAD_REVISION. + * - Other dimensions are specific to the field storage module. + */ +function hook_field_storage_details($field, $instance) { +} + +/** + * Perform alterations on Field API storage details. + * + * The storage details are appended to the field instance structure after this + * hook is invoked. Read and alter the $details only. + * + * @param $details + * An array of storage details for fields as exposed by + * hook_field_storage_details() implementations. + * @param $field + * A field structure. + * @param $instance + * A field instance structure. + */ +function hook_field_storage_details_alter(&$details, $field, $instance) { +} + +/** * Load field data for a set of objects. * * @param $obj_type diff --git a/modules/field/field.info.inc b/modules/field/field.info.inc index f229a1d39..68291838e 100644 --- a/modules/field/field.info.inc +++ b/modules/field/field.info.inc @@ -243,6 +243,11 @@ function _field_info_collate_fields($reset = FALSE) { // are thus not in $definitions['instances']. $info['fields'][$instance['field_name']]['bundles'][] = $instance['bundle']; $info['field_ids'][$instance['field_id']]['bundles'][] = $instance['bundle']; + + // Add storage details. + $details = (array) module_invoke($field['storage']['module'], 'field_storage_details', $field, $instance); + drupal_alter('field_storage_details', $details, $field, $instance); + $info['instances'][$instance['bundle']][$instance['field_name']]['storage_details'] = $details; } } diff --git a/modules/field/field.test b/modules/field/field.test index cfb7655ad..1fd410e78 100644 --- a/modules/field/field.test +++ b/modules/field/field.test @@ -274,6 +274,47 @@ class FieldAttachStorageTestCase extends FieldAttachTestCase { } /** + * Test storage details alteration. + * + * @see field_test_storage_details_alter() + */ + function testFieldStorageDetailsAlter() { + $field_name = 'field_test_change_my_details'; + $field = array( + 'field_name' => $field_name, + 'type' => 'test_field', + 'cardinality' => 4, + 'storage' => array('type' => 'field_test_storage'), + ); + $field = field_create_field($field); + $instance = array( + 'field_name' => $field_name, + 'bundle' => 'test_bundle', + ); + field_create_instance($instance); + + $field = field_info_field($instance['field_name']); + $instance = field_info_instance($instance['field_name'], $instance['bundle']); + + // The storage details are indexed by a storage engine type. + $this->assertTrue(array_key_exists('drupal_variables', $instance['storage_details']), t('The storage type is Drupal variables.')); + + $details = $instance['storage_details']['drupal_variables']; + + // The field_test storage details are indexed by variable name. The details + // are altered, so moon and mars are correct for this test. + $this->assertTrue(array_key_exists('moon', $details[FIELD_LOAD_CURRENT]), t('Moon is available in the instance array.')); + $this->assertTrue(array_key_exists('mars', $details[FIELD_LOAD_REVISION]), t('Mars is available in the instance array.')); + + // Test current and revision storage details together because the columns + // are the same. + foreach ((array) $field['columns'] as $column_name => $attributes) { + $this->assertEqual($details[FIELD_LOAD_CURRENT]['moon'][$column_name], $column_name, t('Column name %value matches the definition in %bin.', array('%value' => $column_name, '%bin' => 'moon[FIELD_LOAD_CURRENT]'))); + $this->assertEqual($details[FIELD_LOAD_REVISION]['mars'][$column_name], $column_name, t('Column name %value matches the definition in %bin.', array('%value' => $column_name, '%bin' => 'mars[FIELD_LOAD_REVISION]'))); + } + } + + /** * Tests insert and update with missing or NULL fields. */ function testFieldAttachSaveMissingData() { diff --git a/modules/field/modules/field_sql_storage/field_sql_storage.module b/modules/field/modules/field_sql_storage/field_sql_storage.module index 5cb49875e..81318a581 100644 --- a/modules/field/modules/field_sql_storage/field_sql_storage.module +++ b/modules/field/modules/field_sql_storage/field_sql_storage.module @@ -658,3 +658,25 @@ function field_sql_storage_field_storage_purge_field($field) { db_drop_table($revision_name); } +/** + * Implement hook_field_storage_details(). + */ +function field_sql_storage_field_storage_details($field, $instance) { + $details = array(); + + // Add field columns. + foreach ((array) $field['columns'] as $column_name => $attributes) { + $real_name = _field_sql_storage_columnname($field['field_name'], $column_name); + $columns[$column_name] = $real_name; + } + return array( + 'sql' => array( + FIELD_LOAD_CURRENT => array( + _field_sql_storage_tablename($field) => $columns, + ), + FIELD_LOAD_REVISION => array( + _field_sql_storage_revision_tablename($field) => $columns, + ), + ), + ); +} diff --git a/modules/field/modules/field_sql_storage/field_sql_storage.test b/modules/field/modules/field_sql_storage/field_sql_storage.test index f5a98cbf9..f7dc4bb62 100644 --- a/modules/field/modules/field_sql_storage/field_sql_storage.test +++ b/modules/field/modules/field_sql_storage/field_sql_storage.test @@ -369,6 +369,34 @@ class FieldSqlStorageTestCase extends DrupalWebTestCase { $this->assertEqual($entity->{$field_name}[FIELD_LANGUAGE_NONE][0]['value'], 'field data', t("Index changes performed without dropping the tables")); } } + + /** + * Test the storage details. + */ + function testFieldStorageDetails() { + $current = _field_sql_storage_tablename($this->field); + $revision = _field_sql_storage_revision_tablename($this->field); + + // Retrieve the field and instance with field_info so the storage details are attached. + $field = field_info_field($this->field['field_name']); + $instance = field_info_instance($this->instance['field_name'], $this->instance['bundle']); + + // The storage details are indexed by a storage engine type. + $this->assertTrue(array_key_exists('sql', $instance['storage_details']), t('The storage type is SQL.')); + + // The SQL details are indexed by table name. + $details = $instance['storage_details']['sql']; + $this->assertTrue(array_key_exists($current, $details[FIELD_LOAD_CURRENT]), t('Table name is available in the instance array.')); + $this->assertTrue(array_key_exists($revision, $details[FIELD_LOAD_REVISION]), t('Revision table name is available in the instance array.')); + + // Test current and revision storage details together because the columns + // are the same. + foreach ((array) $this->field['columns'] as $column_name => $attributes) { + $storage_column_name = _field_sql_storage_columnname($this->field['field_name'], $column_name); + $this->assertEqual($details[FIELD_LOAD_CURRENT][$current][$column_name], $storage_column_name, t('Column name %value matches the definition in %bin.', array('%value' => $column_name, '%bin' => $current))); + $this->assertEqual($details[FIELD_LOAD_REVISION][$revision][$column_name], $storage_column_name, t('Column name %value matches the definition in %bin.', array('%value' => $column_name, '%bin' => $revision))); + } + } function getIndexes($table) { $indexes = array(); diff --git a/modules/simpletest/tests/field_test.module b/modules/simpletest/tests/field_test.module index 6bd73c250..cbd1bc07e 100644 --- a/modules/simpletest/tests/field_test.module +++ b/modules/simpletest/tests/field_test.module @@ -667,6 +667,49 @@ function field_test_field_storage_info() { } /** + * Implement hook_field_storage_details(). + */ +function field_test_field_storage_details($field, $instance) { + $details = array(); + + // Add field columns. + $columns = array(); + foreach ((array) $field['columns'] as $column_name => $attributes) { + $columns[$column_name] = $column_name; + } + return array( + 'drupal_variables' => array( + 'field_test_storage_data[FIELD_LOAD_CURRENT]' => $columns, + 'field_test_storage_data[FIELD_LOAD_REVISION]' => $columns, + ), + ); +} + +/** + * Implement hook_field_storage_details_alter(). + * + * @see FieldAttachStorageTestCase::testFieldStorageDetailsAlter() + */ +function field_test_field_storage_details_alter(&$details, $field, $instance) { + + // For testing, storage details are changed only because of the field name. + if ($field['field_name'] == 'field_test_change_my_details') { + $columns = array(); + foreach ((array) $field['columns'] as $column_name => $attributes) { + $columns[$column_name] = $column_name; + } + $details['drupal_variables'] = array( + FIELD_LOAD_CURRENT => array( + 'moon' => $columns, + ), + FIELD_LOAD_REVISION => array( + 'mars' => $columns, + ), + ); + } +} + +/** * Helper function: store or retrieve data from the 'storage backend'. */ function _field_test_storage_data($data = NULL) { |