#675116: stop duplicating code in the field documentation.

From: Damien Tournoud <damien@commerceguys.com>


---
 field/field.api.php |  376 ++-------------------------------------------------
 1 files changed, 14 insertions(+), 362 deletions(-)

diff --git modules/field/field.api.php modules/field/field.api.php
index 21cc979..cc07f80 100644
--- modules/field/field.api.php
+++ modules/field/field.api.php
@@ -530,23 +530,7 @@ function hook_field_update($entity_type, $entity, $field, $instance, $langcode,
  *   TRUE if the field has data in storage currently.
  */
 function hook_field_storage_update_field($field, $prior_field, $has_data) {
-  if (!$has_data) {
-    // There is no data. Re-create the tables completely.
-    $prior_schema = _field_sql_storage_schema($prior_field);
-    foreach ($prior_schema as $name => $table) {
-      db_drop_table($name, $table);
-    }
-    $schema = _field_sql_storage_schema($field);
-    foreach ($schema as $name => $table) {
-      db_create_table($name, $table);
-    }
-  }
-  else {
-    // There is data. See field_sql_storage_field_storage_update_field() for
-    // an example of what to do to modify the schema in place, preserving the
-    // old data as much as possible.
-  }
-  drupal_get_schema(NULL, TRUE);
+  // See field_sql_storage_field_storage_update_field() for an example.
 }
 
 /**
@@ -1402,13 +1386,7 @@ function hook_field_attach_delete_bundle($entity_type, $bundle, $instances) {
  *     those settings.
  */
 function hook_field_storage_info() {
-  return array(
-    'field_sql_storage' => array(
-      'label' => t('Default SQL storage'),
-      'description' => t('Stores fields in the local SQL database, using per-field tables.'),
-      'settings' => array(),
-    ),
-  );
+  // See field_sql_storage_field_storage_info() for an example.
 }
 
 /**
@@ -1448,23 +1426,7 @@ function hook_field_storage_info_alter(&$info) {
  * @see hook_field_storage_details_alter()
  */
 function hook_field_storage_details($field) {
-  $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,
-      ),
-    ),
-  );
+  // See field_sql_storage_field_storage_details() for an example.
 }
 
 /**
@@ -1523,49 +1485,7 @@ function hook_field_storage_details_alter(&$details, $field) {
  *     loaded.
  */
 function hook_field_storage_load($entity_type, &$entities, $age, $fields, $options) {
-  $field_info = field_info_field_by_ids();
-  $etid = _field_sql_storage_etid($entity_type);
-  $load_current = $age == FIELD_LOAD_CURRENT;
-
-  foreach ($fields as $field_id => $ids) {
-    $field = $field_info[$field_id];
-    $field_name = $field['field_name'];
-    $table = $load_current ? _field_sql_storage_tablename($field) : _field_sql_storage_revision_tablename($field);
-
-    $query = db_select($table, 't')
-      ->fields('t')
-      ->condition('etid', $etid)
-      ->condition($load_current ? 'entity_id' : 'revision_id', $ids, 'IN')
-      ->condition('language', field_available_languages($entity_type, $field), 'IN')
-      ->orderBy('delta');
-
-    if (empty($options['deleted'])) {
-      $query->condition('deleted', 0);
-    }
-
-    $results = $query->execute();
-
-    $delta_count = array();
-    foreach ($results as $row) {
-      if (!isset($delta_count[$row->entity_id][$row->language])) {
-        $delta_count[$row->entity_id][$row->language] = 0;
-      }
-
-      if ($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED || $delta_count[$row->entity_id][$row->language] < $field['cardinality']) {
-        $item = array();
-        // For each column declared by the field, populate the item
-        // from the prefixed database column.
-        foreach ($field['columns'] as $column => $attributes) {
-          $column_name = _field_sql_storage_columnname($field_name, $column);
-          $item[$column] = $row->$column_name;
-        }
-
-        // Add the item to the field values for the entity.
-        $entities[$row->entity_id]->{$field_name}[$row->language][] = $item;
-        $delta_count[$row->entity_id][$row->language]++;
-      }
-    }
-  }
+  // See field_sql_storage_field_storage_load() for an example.
 }
 
 /**
@@ -1586,87 +1506,7 @@ function hook_field_storage_load($entity_type, &$entities, $age, $fields, $optio
  *   array are field IDs.
  */
 function hook_field_storage_write($entity_type, $entity, $op, $fields) {
-  list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
-  $etid = _field_sql_storage_etid($entity_type);
-
-  foreach ($fields as $field_id) {
-    $field = field_info_field_by_id($field_id);
-    $field_name = $field['field_name'];
-    $table_name = _field_sql_storage_tablename($field);
-    $revision_name = _field_sql_storage_revision_tablename($field);
-
-    $all_languages = field_available_languages($entity_type, $field);
-    $field_languages = array_intersect($all_languages, array_keys((array) $entity->$field_name));
-
-    // Delete and insert, rather than update, in case a value was added.
-    if ($op == FIELD_STORAGE_UPDATE) {
-      // Delete languages present in the incoming $entity->$field_name.
-      // Delete all languages if $entity->$field_name is empty.
-      $languages = !empty($entity->$field_name) ? $field_languages : $all_languages;
-      if ($languages) {
-        db_delete($table_name)
-          ->condition('etid', $etid)
-          ->condition('entity_id', $id)
-          ->condition('language', $languages, 'IN')
-          ->execute();
-        if (isset($vid)) {
-          db_delete($revision_name)
-            ->condition('etid', $etid)
-            ->condition('entity_id', $id)
-            ->condition('revision_id', $vid)
-            ->condition('language', $languages, 'IN')
-            ->execute();
-        }
-      }
-    }
-
-    // Prepare the multi-insert query.
-    $do_insert = FALSE;
-    $columns = array('etid', 'entity_id', 'revision_id', 'bundle', 'delta', 'language');
-    foreach ($field['columns'] as $column => $attributes) {
-      $columns[] = _field_sql_storage_columnname($field_name, $column);
-    }
-    $query = db_insert($table_name)->fields($columns);
-    if (isset($vid)) {
-      $revision_query = db_insert($revision_name)->fields($columns);
-    }
-
-    foreach ($field_languages as $langcode) {
-      $items = (array) $entity->{$field_name}[$langcode];
-      $delta_count = 0;
-      foreach ($items as $delta => $item) {
-        // We now know we have someting to insert.
-        $do_insert = TRUE;
-        $record = array(
-          'etid' => $etid,
-          'entity_id' => $id,
-          'revision_id' => $vid,
-          'bundle' => $bundle,
-          'delta' => $delta,
-          'language' => $langcode,
-        );
-        foreach ($field['columns'] as $column => $attributes) {
-          $record[_field_sql_storage_columnname($field_name, $column)] = isset($item[$column]) ? $item[$column] : NULL;
-        }
-        $query->values($record);
-        if (isset($vid)) {
-          $revision_query->values($record);
-        }
-
-        if ($field['cardinality'] != FIELD_CARDINALITY_UNLIMITED && ++$delta_count == $field['cardinality']) {
-          break;
-        }
-      }
-    }
-
-    // Execute the query if we have values to insert.
-    if ($do_insert) {
-      $query->execute();
-      if (isset($vid)) {
-        $revision_query->execute();
-      }
-    }
-  }
+  // See field_sql_storage_field_storage_write() for an example.
 }
 
 /**
@@ -1684,15 +1524,7 @@ function hook_field_storage_write($entity_type, $entity, $op, $fields) {
  *   array are field IDs.
  */
 function hook_field_storage_delete($entity_type, $entity, $fields) {
-  list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
-  $etid = _field_sql_storage_etid($entity_type);
-
-  foreach (field_info_instances($entity_type, $bundle) as $instance) {
-    if (isset($fields[$instance['field_id']])) {
-      $field = field_info_field_by_id($instance['field_id']);
-      field_sql_storage_field_storage_purge($entity_type, $entity, $field, $instance);
-    }
-  }
+  // See field_sql_storage_field_storage_delete() for an example.
 }
 
 /**
@@ -1715,20 +1547,7 @@ function hook_field_storage_delete($entity_type, $entity, $fields) {
  *   array are field IDs.
  */
 function hook_field_storage_delete_revision($entity_type, $entity, $fields) {
-  list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
-  $etid = _field_sql_storage_etid($entity_type);
-
-  if (isset($vid)) {
-    foreach ($fields as $field_id) {
-      $field = field_info_field_by_id($field_id);
-      $revision_name = _field_sql_storage_revision_tablename($field);
-      db_delete($revision_name)
-        ->condition('etid', $etid)
-        ->condition('entity_id', $id)
-        ->condition('revision_id', $vid)
-        ->execute();
-    }
-  }
+  // See field_sql_storage_field_storage_delete_revision() for an example.
 }
 
 /**
@@ -1746,126 +1565,7 @@ function hook_field_storage_delete_revision($entity_type, $entity, $fields) {
  *   See EntityFieldQuery::execute() for the return values.
  */
 function hook_field_storage_query($query) {
-  $load_current = $options['age'] == FIELD_LOAD_CURRENT;
-
-  $field = field_info_field_by_id($field_id);
-  $field_name = $field['field_name'];
-  $table = $load_current ? _field_sql_storage_tablename($field) : _field_sql_storage_revision_tablename($field);
-  $field_columns = array_keys($field['columns']);
-
-  // Build the query.
-  $query = db_select($table, 't');
-  $query->join('field_config_entity_type', 'e', 't.etid = e.etid');
-
-  // Add conditions.
-  foreach ($conditions as $condition) {
-    // A condition is either a (column, value, operator) triple, or a
-    // (column, value) pair with implied operator.
-    @list($column, $value, $operator) = $condition;
-    // Translate operator and value if needed.
-    switch ($operator) {
-      case 'STARTS_WITH':
-        $operator = 'LIKE';
-        $value = db_like($value) . '%';
-        break;
-
-      case 'ENDS_WITH':
-        $operator = 'LIKE';
-        $value = '%' . db_like($value);
-        break;
-
-      case 'CONTAINS':
-        $operator = 'LIKE';
-        $value = '%' . db_like($value) . '%';
-        break;
-    }
-    // Translate field columns into prefixed db columns.
-    if (in_array($column, $field_columns)) {
-      $column = _field_sql_storage_columnname($field_name, $column);
-    }
-    // Translate entity types into numeric ids. Expressing the condition on the
-    // local 'etid' column rather than the JOINed 'type' column avoids a
-    // filesort.
-    if ($column == 'type') {
-      $column = 't.etid';
-      if (is_array($value)) {
-        foreach (array_keys($value) as $key) {
-          $value[$key] = _field_sql_storage_etid($value[$key]);
-        }
-      }
-      else {
-        $value = _field_sql_storage_etid($value);
-      }
-    }
-    // Track condition on 'deleted'.
-    if ($column == 'deleted') {
-      $condition_deleted = TRUE;
-    }
-
-    $query->condition($column, $value, $operator);
-  }
-
-  // Exclude deleted data unless we have a condition on it.
-  if (!isset($condition_deleted)) {
-    $query->condition('deleted', 0);
-  }
-
-  // For a count query, return the count now.
-  if ($options['count']) {
-    return $query
-      ->fields('t', array('etid', 'entity_id', 'revision_id'))
-      ->distinct()
-      ->countQuery()
-      ->execute()
-      ->fetchField();
-  }
-
-  // For a data query, add fields.
-  $query
-    ->fields('t', array('bundle', 'entity_id', 'revision_id'))
-    ->fields('e', array('type'))
-    // We need to ensure entities arrive in a consistent order for the
-    // range() operation to work.
-    ->orderBy('t.etid')
-    ->orderBy('t.entity_id');
-
-  // Initialize results array
-  $return = array();
-
-  // Getting $count entities possibly requires reading more than $count rows
-  // since fields with multiple values span over several rows. We query for
-  // batches of $count rows until we've either read $count entities or received
-  // less rows than asked for.
-  $entity_count = 0;
-  do {
-    if ($options['limit'] != FIELD_QUERY_NO_LIMIT) {
-      $query->range($options['cursor'], $options['limit']);
-    }
-    $results = $query->execute();
-
-    $row_count = 0;
-    foreach ($results as $row) {
-      $row_count++;
-      $options['cursor']++;
-      // If querying all revisions and the entity type has revisions, we need
-      // to key the results by revision_ids.
-      $entity_type = entity_get_info($row->type);
-      $id = ($load_current || empty($entity_type['entity keys']['revision'])) ? $row->entity_id : $row->revision_id;
-
-      if (!isset($return[$row->type][$id])) {
-        $return[$row->type][$id] = entity_create_stub_entity($row->type, array($row->entity_id, $row->revision_id, $row->bundle));
-        $entity_count++;
-      }
-    }
-  } while ($options['limit'] != FIELD_QUERY_NO_LIMIT && $row_count == $options['limit'] && $entity_count < $options['limit']);
-
-  // The query is complete when the last batch returns less rows than asked
-  // for.
-  if ($row_count < $options['limit']) {
-    $options['cursor'] = FIELD_QUERY_COMPLETE;
-  }
-
-  return $return;
+  // See field_sql_storage_field_storage_query() for an example.
 }
 
 /**
@@ -1879,11 +1579,7 @@ function hook_field_storage_query($query) {
  *   The field structure being created.
  */
 function hook_field_storage_create_field($field) {
-  $schema = _field_sql_storage_schema($field);
-  foreach ($schema as $name => $table) {
-    db_create_table($name, $table);
-  }
-  drupal_get_schema(NULL, TRUE);
+  // See field_sql_storage_field_storage_create_field() for an example.
 }
 
 /**
@@ -1896,21 +1592,7 @@ function hook_field_storage_create_field($field) {
  *   The field being deleted.
  */
 function hook_field_storage_delete_field($field) {
-  // Mark all data associated with the field for deletion.
-  $field['deleted'] = 0;
-  $table = _field_sql_storage_tablename($field);
-  $revision_table = _field_sql_storage_revision_tablename($field);
-  db_update($table)
-    ->fields(array('deleted' => 1))
-    ->execute();
-
-  // Move the table to a unique name while the table contents are being deleted.
-  $field['deleted'] = 1;
-  $new_table = _field_sql_storage_tablename($field);
-  $revision_new_table = _field_sql_storage_revision_tablename($field);
-  db_rename_table($table, $new_table);
-  db_rename_table($revision_table, $revision_new_table);
-  drupal_get_schema(NULL, TRUE);
+  // See field_sql_storage_field_storage_delete_field() for an example.
 }
 
 /**
@@ -1923,20 +1605,7 @@ function hook_field_storage_delete_field($field) {
  *   The instance being deleted.
  */
 function hook_field_storage_delete_instance($instance) {
-  $etid = _field_sql_storage_etid($instance['entity_type']);
-  $field = field_info_field($instance['field_name']);
-  $table_name = _field_sql_storage_tablename($field);
-  $revision_name = _field_sql_storage_revision_tablename($field);
-  db_update($table_name)
-    ->fields(array('deleted' => 1))
-    ->condition('etid', $etid)
-    ->condition('bundle', $instance['bundle'])
-    ->execute();
-  db_update($revision_name)
-    ->fields(array('deleted' => 1))
-    ->condition('etid', $etid)
-    ->condition('bundle', $instance['bundle'])
-    ->execute();
+  // See field_sql_storage_field_storage_delete_instance() for an example.
 }
 
 /**
@@ -2355,10 +2024,7 @@ function hook_field_purge_field_instance($instance) {
  *   The field being purged.
  */
 function hook_field_storage_purge_field($field) {
-  $table_name = _field_sql_storage_tablename($field);
-  $revision_name = _field_sql_storage_revision_tablename($field);
-  db_drop_table($table_name);
-  db_drop_table($revision_name);
+  // See field_sql_storage_field_storage_purge_field() for an example.
 }
 
 /**
@@ -2372,9 +2038,7 @@ function hook_field_storage_purge_field($field) {
  *   The instance being purged.
  */
 function hook_field_storage_purge_field_instance($instance) {
-  db_delete('my_module_field_instance_info')
-    ->condition('id', $instance['id'])
-    ->execute();
+  // See field_sql_storage_field_storage_purge_field_instance() for an example.
 }
 
 /**
@@ -2393,19 +2057,7 @@ function hook_field_storage_purge_field_instance($instance) {
  *   The deleted field instance whose data is being purged.
  */
 function hook_field_storage_purge($entity_type, $entity, $field, $instance) {
-  list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
-  $etid = _field_sql_storage_etid($entity_type);
-
-  $table_name = _field_sql_storage_tablename($field);
-  $revision_name = _field_sql_storage_revision_tablename($field);
-  db_delete($table_name)
-    ->condition('etid', $etid)
-    ->condition('entity_id', $id)
-    ->execute();
-  db_delete($revision_name)
-    ->condition('etid', $etid)
-    ->condition('entity_id', $id)
-    ->execute();
+  // See field_sql_storage_field_storage_purge() for an example.
 }
 
 /**
