? .cache
? .settings
Index: modules/field/field.api.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/field.api.php,v
retrieving revision 1.51
diff -u -p -r1.51 field.api.php
--- modules/field/field.api.php	2 Dec 2009 19:26:21 -0000	1.51
+++ modules/field/field.api.php	4 Dec 2009 22:53:28 -0000
@@ -866,18 +866,48 @@ function theme_field_formatter_FORMATTER
  * @param $field
  *   The field structure for the operation.
  * @param $instances
- *   Array of instance structures for $field for each object, keyed by object id.
+ *   Array of instance structures for $field for each object, keyed by object
+ *   id.
  * @param $langcode
  *   The language the field values are to be shown in. If no language is
  *   provided the current language is used.
  * @param $items
  *   Array of field values for the objects, keyed by object id.
+ * @param $displays
+ *   Array of display settings to use for each object display, keyed by object
+ *   id.
  * @return
  *   Changes or additions to field values are done by altering the $items
  *   parameter by reference.
  */
-function hook_field_formatter_prepare_view($obj_type, $objects, $field, $instances, $langcode, &$items, $build_mode) {
+function hook_field_formatter_prepare_view($obj_type, $objects, $field, $instances, $langcode, &$items, $displays) {
+  $tids = array();
 
+  // Collect every possible term attached to any of the fieldable entities.
+  foreach ($objects as $id => $object) {
+    foreach ($items[$id] as $delta => $item) {
+      // Force the array key to prevent duplicates.
+      $tids[$item['tid']] = $item['tid'];
+    }
+  }
+  if ($tids) {
+    $terms = taxonomy_term_load_multiple($tids);
+
+    // Iterate through the fieldable entities again to attach the loaded term data.
+    foreach ($objects as $id => $object) {
+      foreach ($items[$id] as $delta => $item) {
+        // Check whether the taxonomy term field instance value could be loaded.
+        if (isset($terms[$item['tid']])) {
+          // Replace the instance value with the term data.
+          $items[$id][$delta]['taxonomy_term'] = $terms[$item['tid']];
+        }
+        // Otherwise, unset the instance value, since the term does not exist.
+        else {
+          unset($items[$id][$delta]);
+        }
+      }
+    }
+  }
 }
 
 /**
Index: modules/field/field.attach.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/field.attach.inc,v
retrieving revision 1.60
diff -u -p -r1.60 field.attach.inc
--- modules/field/field.attach.inc	4 Dec 2009 16:49:46 -0000	1.60
+++ modules/field/field.attach.inc	4 Dec 2009 22:53:28 -0000
@@ -338,7 +338,7 @@ function _field_invoke_multiple($op, $ob
     if (function_exists($function)) {
       // Iterate over all the field translations.
       foreach ($grouped_items[$field_id] as $langcode => $items) {
-        $results = $function($obj_type, $grouped_objects[$field_id], $field, $grouped_instances[$field_id], $langcode, $grouped_items[$field_id][$langcode], $options, $a, $b);
+        $results = $function($obj_type, $grouped_objects[$field_id], $field, $grouped_instances[$field_id], $langcode, $grouped_items[$field_id][$langcode], $a, $b);
         if (isset($results)) {
           // Collect results by object.
           // For hooks with array results, we merge results together.
@@ -1195,7 +1195,7 @@ function field_attach_view($obj_type, $o
   $output['#pre_render'][] = '_field_extra_weights_pre_render';
   $output['#extra_fields'] = field_extra_fields($bundle);
 
-  // Let other modules make changes after rendering the view.
+  // Let other modules alter the renderable array.
   $context = array(
     'obj_type' => $obj_type,
     'object' => $object,
Index: modules/field/field.default.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/field.default.inc,v
retrieving revision 1.23
diff -u -p -r1.23 field.default.inc
--- modules/field/field.default.inc	9 Nov 2009 18:23:41 -0000	1.23
+++ modules/field/field.default.inc	4 Dec 2009 22:53:28 -0000
@@ -55,38 +55,85 @@ function field_default_insert($obj_type,
 
 /**
  * Invoke hook_field_formatter_prepare_view() on the relavant formatters.
+ *
+ * @param $obj_type
+ *   The type of $object; e.g. 'node' or 'user'.
+ * @param $objects
+ *   An array of objects being displayed, keyed by object id.
+ * @param $field
+ *   The field structure for the operation.
+ * @param $instances
+ *   Array of instance structures for $field for each object, keyed by object
+ *   id.
+ * @param $langcode
+ *   The language associated to $items.
+ * @param $items
+ *   Array of field values already loaded for the objects, keyed by object id.
+ * @param $display
+ *   Can be either:
+ *   - the name of a build mode
+ *   - or an array of display settings to use for display, as found in the
+ *   'display' entry of $instance definitions.
  */
-function field_default_prepare_view($obj_type, $objects, $field, $instances, $langcode, &$items, $options, $build_mode) {
+function field_default_prepare_view($obj_type, $objects, $field, $instances, $langcode, &$items, $display) {
   // Group objects, instances and items by formatter module.
   $modules = array();
   foreach ($instances as $id => $instance) {
-    $module = $instance['display'][$build_mode]['module'];
-    $modules[$module] = $module;
-    $grouped_objects[$module][$id] = $objects[$id];
-    $grouped_instances[$module][$id] = $instance;
-    // hook_field_formatter_prepare_view() alters $items by reference.
-    $grouped_items[$module][$id] = &$items[$id];
+    $display = is_string($display) ? $instance['display'][$display] : $display;
+    if ($display['type'] !== 'hidden') {
+      $module = $display['module'];
+      $modules[$module] = $module;
+      $grouped_objects[$module][$id] = $objects[$id];
+      $grouped_instances[$module][$id] = $instance;
+      $grouped_displays[$module][$id] = $display;
+      // hook_field_formatter_prepare_view() alters $items by reference.
+      $grouped_items[$module][$id] = &$items[$id];
+    }
   }
 
   foreach ($modules as $module) {
     // Invoke hook_field_formatter_prepare_view().
     $function = $module . '_field_formatter_prepare_view';
     if (function_exists($function)) {
-      $function($obj_type, $grouped_objects[$module], $field, $grouped_instances[$module], $langcode, $grouped_items[$module], $build_mode);
+      $function($obj_type, $grouped_objects[$module], $field, $grouped_instances[$module], $langcode, $grouped_items[$module], $grouped_displays[$module]);
     }
   }
 }
 
 /**
- * Default field 'view' operation.
+ * Build a renderable array for field values.
  *
- * @see field_attach_view()
+ * @param $obj_type
+ *   The type of $object; e.g. 'node' or 'user'.
+ * @param $objects
+ *   An array of objects being displayed, keyed by object id.
+ * @param $field
+ *   The field structure for the operation.
+ * @param $instances
+ *   Array of instance structures for $field for each object, keyed by object id.
+ * @param $langcode
+ *   The language associated to $items.
+ * @param $items
+ *   Array of field values already loaded for the objects, keyed by object id.
+ * @param $display
+ *   Can be either:
+ *   - the name of a build mode;
+ *   - or an array of custom display settings, as found in the 'display' entry
+ *     of $instance definitions.
  */
-function field_default_view($obj_type, $object, $field, $instance, $langcode, $items, $build_mode) {
+function field_default_view($obj_type, $object, $field, $instance, $langcode, $items, $display) {
   list($id, $vid, $bundle) = entity_extract_ids($obj_type, $object);
 
   $addition = array();
-  $display = $instance['display'][$build_mode];
+
+  // Prepare incoming display specifications.
+  if (is_string($display)) {
+    $build_mode = $display;
+    $display = $instance['display'][$build_mode];
+  }
+  else {
+    $build_mode = '_custom';
+  }
 
   if ($display['type'] !== 'hidden') {
     $theme = 'field_formatter_' . $display['type'];
Index: modules/field/field.info.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/field.info.inc,v
retrieving revision 1.32
diff -u -p -r1.32 field.info.inc
--- modules/field/field.info.inc	4 Dec 2009 22:46:28 -0000	1.32
+++ modules/field/field.info.inc	4 Dec 2009 23:38:40 -0000
@@ -235,7 +235,7 @@ function _field_info_collate_fields($res
   return $info;
 }
 
-/**
+ /**
  * Prepares a field definition for the current run-time context.
  *
  * Since the field was last saved or updated, new field settings can be
@@ -278,22 +278,10 @@ function _field_info_prepare_instance($i
     $instance['default_value'] = NULL;
   }
 
-  // Fallback to default widget if widget type is not available.
-  if (!field_info_widget_types($instance['widget']['type'])) {
-    $instance['widget']['type'] = $field_type['default_widget'];
-  }
-  // Make sure all expected widget settings are present.
-  $instance['widget']['settings'] += field_info_widget_settings($instance['widget']['type']);
+  $instance['widget'] = _field_info_prepare_instance_widget($field, $instance['widget']);
 
   foreach ($instance['display'] as $build_mode => $display) {
-    if ($display['type'] != 'hidden') {
-      // Fallback to default formatter if formatter type is not available.
-      if (!field_info_formatter_types($instance['display'][$build_mode]['type'])) {
-        $instance['display'][$build_mode]['type'] = $field_type['default_formatter'];
-      }
-      // Make sure all expected formatter settings are present.
-      $instance['display'][$build_mode]['settings'] += field_info_formatter_settings($instance['display'][$build_mode]['type']);
-    }
+    $instance['display'][$build_mode] = _field_info_prepare_instance_display($field, $display);
   }
 
   // Fallback to 'full' display settings for unspecified build modes.
@@ -307,15 +295,80 @@ function _field_info_prepare_instance($i
 }
 
 /**
+ * Prepares display specifications for the current run-time context.
+ *
+ * @param $field
+ *   The field structure for the instance.
+ * @param $display
+ *   Display specifications as found in
+ *   $instance['display']['some_build_mode'].
+ */
+function _field_info_prepare_instance_display($field, $display) {
+  $field_type = field_info_field_types($field['type']);
+
+  // Fill in default values.
+  $display += array(
+    'label' => 'above',
+    'type' => $field_type['default_formatter'],
+    'settings' => array(),
+    'weight' => 0,
+  );
+  if ($display['type'] != 'hidden') {
+    $formatter_type = field_info_formatter_types($display['type']);
+    // Fallback to default formatter if formatter type is not available.
+    if (!$formatter_type) {
+      $display['type'] = $field_type['default_formatter'];
+      $formatter_type = field_info_formatter_types($display['type']);
+    }
+    $display['module'] = $formatter_type['module'];
+    // Fill in default settings for the formatter.
+    $display['settings'] += field_info_formatter_settings($display['type']);
+  }
+
+  return $display;
+}
+
+/**
+ * Prepares widget specifications for the current run-time context.
+ *
+ * @param $field
+ *   The field structure for the instance.
+ * @param $widget
+ *   Widget specifications as found in $instance['widget'].
+ */
+function _field_info_prepare_instance_widget($field, $widget) {
+  $field_type = field_info_field_types($field['type']);
+
+  // Fill in default values.
+  $widget += array(
+    'type' => $field_type['default_widget'],
+    'settings' => array(),
+    'weight' => 0,
+  );
+
+  $widget_type = field_info_widget_types($widget['type']);
+  // Fallback to default formatter if formatter type is not available.
+  if (!$widget_type) {
+    $widget['type'] = $field_type['default_widget'];
+    $widget_type = field_info_widget_types($widget['type']);
+  }
+  $widget['module'] = $widget_type['module'];
+  // Fill in default settings for the widget.
+  $widget['settings'] += field_info_widget_settings($widget['type']);
+
+  return $widget;
+}
+
+/**
  * Determines the behavior of a widget with respect to an operation.
  *
- * @param $op
+ *  @param $op
  *   The name of the operation. Currently supported: 'default value',
  *   'multiple values'.
- * @param $instance
- *   The field instance array.
+ *  @param $instance
+ *    The field instance array.
  *
- * @return
+ *  @return
  *   One of these values:
  *   - FIELD_BEHAVIOR_NONE: Do nothing for this operation.
  *   - FIELD_BEHAVIOR_CUSTOM: Use the widget's callback function.
@@ -329,12 +382,12 @@ function field_behaviors_widget($op, $in
 /**
  * Determines the behavior of a formatter with respect to an operation.
  *
- * @param $op
+ *  @param $op
  *   The name of the operation. Currently supported: 'multiple values'.
- * @param $display
- *   The $instance['display'][$build_mode] array.
+ *  @param $display
+ *    The $instance['display'][$build_mode] array.
  *
- * @return
+ *  @return
  *   One of these values:
  *   - FIELD_BEHAVIOR_NONE: Do nothing for this operation.
  *   - FIELD_BEHAVIOR_CUSTOM: Use the formatter's callback function.
Index: modules/field/field.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/field.module,v
retrieving revision 1.51
diff -u -p -r1.51 field.module
--- modules/field/field.module	4 Dec 2009 16:49:46 -0000	1.51
+++ modules/field/field.module	4 Dec 2009 22:53:28 -0000
@@ -567,45 +567,94 @@ function field_format($obj_type, $object
 }
 
 /**
- * Return a single field, fully themed with label and multiple values.
+ * Returns a renderable array for the value of a single field in an object.
  *
- * To be used by third-party code (Views, Panels...) that needs to output
- * an isolated field. Do *not* use inside node templates, use
- * render($content[FIELD_NAME]) instead.
+ * The resulting output is a fully themed field with label and multiple values.
  *
- * The field will be displayed using the display options (label display,
- * formatter settings...) specified in the $instance structure for the given
- * build mode: $instance['display'][$build_mode].
+ * This function can be used by third-party modules that needs to output an
+ * isolated field. Do *not* use inside node templates, use
+ * render($content[FIELD_NAME]) instead.
  *
+ * @param $obj_type
+ *   The type of $object; e.g. 'node' or 'user'.
  * @param $object
- *   The object containing the field to display. Must at least contain the id key,
- *   revision key (if applicable), bundle key, and the field data.
- * @param $field
- *   The field structure.
- * @param $instance
- *   The instance structure for $field on $object's bundle.
- * @param $build_mode
- *   Build mode, e.g. 'full', 'teaser'...
+ *   The object containing the field to display. Must at least contain the id
+ *   key and the field data to display.
+ * @param $field_name
+ *   The name of the field to display.
+ * @param $display
+ *   Can be either:
+ *   - The name of a build mode. The field will be displayed according to the
+ *     display settings specified for this build mode in the $instance
+ *     definition for the field in the object's bundle.
+ *     If no display settings are found for the build mode, the settings for
+ *     the 'full' build mode will be used.
+ *   - An array of display settings, as found in the 'display' entry of
+ *     $instance definitions. The following kay/value pairs are allowed:
+ *     - label: (string) Position of the label. The default 'field' theme
+ *       implementation supports the values 'inline', 'above' and 'hidden'.
+ *       Defaults to 'above'.
+ *     - type: (string) The formatter to use.
+ *       Defaults to the 'default_formatter' for the field type, specified in
+ *       hook_field_info(). The default formatter will also be used if the
+ *       requested formatter is not available.
+ *     - settings: (array) Settings specific to the formatter.
+ *       Defaults to the formatter's default settings, specified in
+ *       hook_field_formatter_info().
+ *     - weight: (float) The weight to assign to the renderable element.
+ *       Defaults to 0.
+ * @param $langcode
+ *   (Optional) The language the field values are to be shown in. The site's
+ *   current language fallback logic will be applied no values are available
+ *   for the language. If no language is provided the current language will be
+ *   used.
  * @return
- *   The themed output for the field.
+ *   A renderable array for the field value.
  */
-function field_view_field($obj_type, $object, $field, $instance, $build_mode = 'full') {
-  $output = '';
-  if (isset($object->$field['field_name'])) {
-    $items = $object->$field['field_name'];
-
-    // One-field equivalent to _field_invoke('sanitize').
-    $function = $field['module'] . '_field_sanitize';
-    if (function_exists($function)) {
-      $function($obj_type, $object, $field, $instance, $items);
-      $object->$field['field_name'] = $items;
-    }
+function field_build_field($obj_type, $object, $field_name, $display = array(), $langcode = NULL) {
+  $output = array();
 
-    $view = field_default_view($obj_type, $object, $field, $instance, $items, $build_mode);
-    // TODO : what about hook_field_attach_view ?
+  list(, , $bundle) = entity_extract_ids($obj_type, $object);
+  $field = field_info_field($field_name);
+  $instance = field_info_instance($obj_type, $field_name, $bundle);
+  if (is_string($display) && !isset($instance['display'][$display])) {
+    $display = 'full';
+  }
+
+  if ($field = field_info_field($field_name)) {
+    // Fill in default values for the display settings.
+    if (is_array($display)) {
+      $display = _field_info_prepare_instance_display($field, $display);
+    }
 
-    $output = $view[$field['field_name']];
+    // Hook invocations are done through the _field_invoke() functions in
+    // 'single field' mode, to reuse the language fallback logic.
+    $options = array('field_name' => $field_name, 'language' => field_multilingual_valid_language($langcode, FALSE));
+    $null = NULL;
+
+    // Prepare view: let the formatter load additional data.
+    list ($id) = entity_extract_ids($obj_type, $object);
+    _field_invoke_multiple_default('prepare_view', $obj_type, array($id => $object), $display, $null, $options);
+    // Sanitize the data.
+    _field_invoke('sanitize', $obj_type, $object, $null, $null, $options);
+    // Build the renderable array.
+    $result = _field_invoke_default('view', $obj_type, $object, $display, $null, $options);
+
+    // Let other modules alter the renderable array.
+    $context = array(
+      'obj_type' => $obj_type,
+      'object' => $object,
+      'build_mode' => '_custom',
+      'langcode' => $langcode,
+    );
+    drupal_alter('field_attach_view', $result, $context);
+
+    if (isset($result[$field_name])) {
+      $output = $result[$field_name];
+      $output['#attached']['css'][] = drupal_get_path('module', 'field') . '/theme/field.css';
+    }
   }
+
   return $output;
 }
 
Index: modules/field/tests/field.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/tests/field.test,v
retrieving revision 1.5
diff -u -p -r1.5 field.test
--- modules/field/tests/field.test	2 Dec 2009 19:26:22 -0000	1.5
+++ modules/field/tests/field.test	5 Dec 2009 02:03:23 -0000
@@ -1656,6 +1656,108 @@ class FieldFormTestCase extends FieldTes
   }
 }
 
+class FieldDisplayAPITestCase extends FieldTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Field Display API tests',
+      'description' => 'Test the display API.',
+      'group' => 'Field API',
+    );
+  }
+
+  function setUp() {
+    parent::setUp('field_test');
+
+    // Create a field and instance.
+    $this->field_name = 'test_field';
+    $this->label = $this->randomName();
+    $this->cardinality = 4;
+
+    $this->field = array(
+      'field_name' => $this->field_name,
+      'type' => 'test_field',
+      'cardinality' => $this->cardinality,
+    );
+    $this->instance = array(
+      'field_name' => $this->field_name,
+      'object_type' => 'test_entity',
+      'bundle' => 'test_bundle',
+      'label' => $this->label,
+      'display' => array(
+        'full' => array(
+          'type' => 'field_test_default',
+          'settings' => array(
+            'test_formatter_setting' => $this->randomName(),
+          ),
+        ),
+      ),
+    );
+    field_create_field($this->field);
+    field_create_instance($this->instance);
+
+
+    // Create an entity with values.
+    $this->values = $this->_generateTestFieldValues($this->cardinality);
+    $this->entity = field_test_create_stub_entity();
+    $this->is_new = TRUE;
+    $this->entity->{$this->field_name}[LANGUAGE_NONE] = $this->values;
+    field_test_entity_save($this->entity);
+  }
+
+  /**
+   * Test the field_build_field() function.
+   */
+  function testFieldBuildField() {
+    // No display settings: check that default display settings are used.
+    $output = field_build_field('test_entity', $this->entity, $this->field_name);
+    $this->drupalSetContent(drupal_render($output));
+    $settings = field_info_formatter_settings('field_test_default');
+    $setting = $settings['test_formatter_setting'];
+    $this->assertText($this->label, t('Label was displayed.'));
+    foreach($this->values as $delta => $value) {
+      $this->assertText($setting . '|' . $value['value'], t('Value @delta was displayed with expected setting.', array('@delta' => $delta)));
+    }
+
+    // Check that explicit display settings are used.
+    $display = array(
+      'label' => 'hidden',
+      'type' => 'field_test_multiple',
+      'settings' => array(
+        'test_formatter_setting_multiple' => $this->randomName(),
+      ),
+    );
+    $output = field_build_field('test_entity', $this->entity, $this->field_name, $display);
+    $this->drupalSetContent(drupal_render($output));
+    $setting = $display['settings']['test_formatter_setting_multiple'];
+    $this->assertNoText($this->label, t('Label was not displayed.'));
+    $array = array();
+    foreach($this->values as $delta => $value) {
+      $array[] = $delta . ':' . $value['value'];
+    }
+    $this->assertText($setting . '|' . implode('|', $array), t('Values were displayed with expected setting.'));
+
+    // Build mode: check that display settings specified in the instance are
+    // used.
+    $output = field_build_field('test_entity', $this->entity, $this->field_name, 'full');
+    $this->drupalSetContent(drupal_render($output));
+    $setting = $this->instance['display']['full']['settings']['test_formatter_setting'];
+    $this->assertText($this->label, t('Label was displayed.'));
+    foreach($this->values as $delta => $value) {
+      $this->assertText($setting . '|' . $value['value'], t('Value @delta was displayed with expected setting.', array('@delta' => $delta)));
+    }
+
+    // Unknown build mode: check that display settings for 'full' build mode
+    // are used.
+    $output = field_build_field('test_entity', $this->entity, $this->field_name, 'unknown_build_mode');
+    $this->drupalSetContent(drupal_render($output));
+    $setting = $this->instance['display']['full']['settings']['test_formatter_setting'];
+    $this->assertText($this->label, t('Label was displayed.'));
+    foreach($this->values as $delta => $value) {
+      $this->assertText($setting . '|' . $value['value'], t('Value @delta was displayed with expected setting.', array('@delta' => $delta)));
+    }
+  }
+}
+
 class FieldCrudTestCase extends FieldTestCase {
   public static function getInfo() {
     return array(
Index: modules/field/tests/field_test.field.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/tests/field_test.field.inc,v
retrieving revision 1.2
diff -u -p -r1.2 field_test.field.inc
--- modules/field/tests/field_test.field.inc	4 Dec 2009 16:49:46 -0000	1.2
+++ modules/field/tests/field_test.field.inc	4 Dec 2009 22:53:28 -0000
@@ -238,11 +238,11 @@ function field_test_field_formatter_info
 /**
  * Implements hook_field_formatter_prepare_view().
  */
-function field_test_field_formatter_prepare_view($obj_type, $objects, $field, $instances, $langcode, &$items, $build_mode) {
+function field_test_field_formatter_prepare_view($obj_type, $objects, $field, $instances, $langcode, &$items, $displays) {
   foreach ($items as $id => $item) {
     // To keep the test non-intrusive, only act on the
     // 'field_test_needs_additional_data' formatter.
-    if ($instances[$id]['display'][$build_mode]['type'] == 'field_test_needs_additional_data') {
+    if ($displays[$id]['type'] == 'field_test_needs_additional_data') {
       foreach ($item as $delta => $value) {
         // Don't add anything on empty values.
         if ($value) {
Index: modules/taxonomy/taxonomy.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.module,v
retrieving revision 1.545
diff -u -p -r1.545 taxonomy.module
--- modules/taxonomy/taxonomy.module	4 Dec 2009 16:49:47 -0000	1.545
+++ modules/taxonomy/taxonomy.module	4 Dec 2009 22:54:36 -0000
@@ -1139,12 +1139,12 @@ function taxonomy_allowed_values($field)
 }
 
 /**
- * Implements hook_field_load().
+ * Implements hook_field_formatter_prepare_view().
  *
  * This preloads all taxonomy terms for multiple loaded objects at once and
  * unsets values for invalid terms that do not exist.
  */
-function taxonomy_field_formatter_prepare_view($obj_type, $objects, $field, $instances, $langcode, &$items, $age) {
+function taxonomy_field_formatter_prepare_view($obj_type, $objects, $field, $instances, $langcode, &$items, $displays) {
   $tids = array();
 
   // Collect every possible term attached to any of the fieldable entities.
