? .cvsignore
? developer-docs
? sites/all/modules/devel
? sites/default/.cvsignore
Index: modules/field/field.api.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/field.api.php,v
retrieving revision 1.40
diff -u -p -r1.40 field.api.php
--- modules/field/field.api.php	10 Oct 2009 21:39:02 -0000	1.40
+++ modules/field/field.api.php	13 Oct 2009 20:23:34 -0000
@@ -1143,6 +1143,43 @@ function hook_field_storage_info_alter(&
 }
 
 /**
+ * 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, structure varies for different storage modules.
+ */
+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
Index: modules/field/field.info.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/field.info.inc,v
retrieving revision 1.20
diff -u -p -r1.20 field.info.inc
--- modules/field/field.info.inc	12 Oct 2009 05:22:57 -0000	1.20
+++ modules/field/field.info.inc	13 Oct 2009 20:23:34 -0000
@@ -243,6 +243,11 @@ function _field_info_collate_fields($res
       // 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;
     }
   }
 
Index: modules/field/field.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/field.test,v
retrieving revision 1.58
diff -u -p -r1.58 field.test
--- modules/field/field.test	2 Oct 2009 14:39:43 -0000	1.58
+++ modules/field/field.test	13 Oct 2009 20:23:37 -0000
@@ -274,6 +274,58 @@ class FieldAttachStorageTestCase extends
   }
 
   /**
+   * Test storage details alteration.
+   */
+  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',
+      'label' => $this->randomName() . '_label',
+      'description' => $this->randomName() . '_description',
+      'weight' => mt_rand(0, 127),
+      'settings' => array(
+        'test_instance_setting' => $this->randomName(),
+      ),
+      'widget' => array(
+        'type' => 'test_field_widget',
+        'label' => 'Test Field',
+        'settings' => array(
+          'test_widget_setting' => $this->randomName(),
+        )
+      )
+    );
+    field_create_instance($instance);
+
+    // Reset the field info static cache.
+    _field_info_collate_fields(TRUE);
+    $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.'));
+
+    // The SQL details are indexed by table name.
+    $details = $instance['storage_details']['drupal_variables'];
+    $this->assertTrue(array_key_exists('moon[current]', $details), t('Moon is available in the instance array.'));
+    $this->assertTrue(array_key_exists('mars[revisions]', $details), t('Mars is available in the instance array.'));
+
+    // There are two identical copies of the column mapping, but we only test one.
+    $columns = array_shift($details);
+    foreach ((array) $field['columns'] as $column_name => $attributes) {
+      $this->assertEqual($columns[$column_name], $column_name, t('Column name matches the definition.'));
+    }
+    
+  }
+
+  /**
    * Tests insert and update with missing or NULL fields.
    */
   function testFieldAttachSaveMissingData() {
Index: modules/field/modules/field_sql_storage/field_sql_storage.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/modules/field_sql_storage/field_sql_storage.module,v
retrieving revision 1.26
diff -u -p -r1.26 field_sql_storage.module
--- modules/field/modules/field_sql_storage/field_sql_storage.module	30 Sep 2009 12:26:36 -0000	1.26
+++ modules/field/modules/field_sql_storage/field_sql_storage.module	13 Oct 2009 20:23:37 -0000
@@ -658,3 +658,21 @@ function field_sql_storage_field_storage
   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_sql_storage_tablename($field) => $columns,
+      _field_sql_storage_revision_tablename($field) => $columns,
+    ),
+  );
+}
Index: modules/field/modules/field_sql_storage/field_sql_storage.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/modules/field_sql_storage/field_sql_storage.test,v
retrieving revision 1.10
diff -u -p -r1.10 field_sql_storage.test
--- modules/field/modules/field_sql_storage/field_sql_storage.test	30 Sep 2009 12:26:36 -0000	1.10
+++ modules/field/modules/field_sql_storage/field_sql_storage.test	13 Oct 2009 20:23:38 -0000
@@ -369,6 +369,29 @@ class FieldSqlStorageTestCase extends Dr
       $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() {
+
+    // Retrieve the instance with field_info_instance so the storage details are attached.
+    $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(_field_sql_storage_tablename($this->field), $details), t('Table name is available in the instance array.'));
+    $this->assertTrue(array_key_exists(_field_sql_storage_revision_tablename($this->field), $details), t('Revision table name is available in the instance array.'));
+
+    // There are two identical copies of the column mapping, but we only test one.
+    $columns = array_shift($details);
+    foreach ((array) $this->field['columns'] as $column_name => $attributes) {
+      $this->assertEqual($columns[$column_name], _field_sql_storage_columnname($this->field['field_name'], $column_name), t('Column name matches the definition.'));
+    }
+  }
 
   function getIndexes($table) {
     $indexes = array();
Index: modules/simpletest/tests/field_test.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/field_test.module,v
retrieving revision 1.28
diff -u -p -r1.28 field_test.module
--- modules/simpletest/tests/field_test.module	9 Oct 2009 01:00:03 -0000	1.28
+++ modules/simpletest/tests/field_test.module	13 Oct 2009 20:23:39 -0000
@@ -667,6 +667,41 @@ 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[current]' => $columns,
+      'field_test_storage_data[revisions]' => $columns,
+    ),
+  );
+}
+
+/**
+ * Implement hook_field_storage_details_alter().
+ */
+function field_test_field_storage_details_alter(&$details, $field, $instance) {
+  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(
+      'moon[current]' => $columns,
+      'mars[revisions]' => $columns,
+    );
+  }
+}
+
+/**
  * Helper function: store or retrieve data from the 'storage backend'.
  */
 function _field_test_storage_data($data = NULL) {
