summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/field/field.api.php41
-rw-r--r--modules/field/field.info.inc5
-rw-r--r--modules/field/field.test41
-rw-r--r--modules/field/modules/field_sql_storage/field_sql_storage.module22
-rw-r--r--modules/field/modules/field_sql_storage/field_sql_storage.test28
-rw-r--r--modules/simpletest/tests/field_test.module43
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) {